]>
Commit | Line | Data |
---|---|---|
08dbd0f8 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
2d3cbc78 RK |
2 | /* |
3 | * Cache management functions for Hexagon | |
4 | * | |
e1858b2a | 5 | * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. |
2d3cbc78 RK |
6 | */ |
7 | ||
8 | #include <linux/mm.h> | |
9 | #include <asm/cacheflush.h> | |
10 | #include <asm/hexagon_vm.h> | |
11 | ||
12 | #define spanlines(start, end) \ | |
13 | (((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1) | |
14 | ||
15 | void flush_dcache_range(unsigned long start, unsigned long end) | |
16 | { | |
17 | unsigned long lines = spanlines(start, end-1); | |
18 | unsigned long i, flags; | |
19 | ||
20 | start &= ~(LINESIZE - 1); | |
21 | ||
22 | local_irq_save(flags); | |
23 | ||
24 | for (i = 0; i < lines; i++) { | |
25 | __asm__ __volatile__ ( | |
26 | " dccleaninva(%0); " | |
27 | : | |
28 | : "r" (start) | |
29 | ); | |
30 | start += LINESIZE; | |
31 | } | |
32 | local_irq_restore(flags); | |
33 | } | |
34 | ||
35 | void flush_icache_range(unsigned long start, unsigned long end) | |
36 | { | |
37 | unsigned long lines = spanlines(start, end-1); | |
38 | unsigned long i, flags; | |
39 | ||
40 | start &= ~(LINESIZE - 1); | |
41 | ||
42 | local_irq_save(flags); | |
43 | ||
44 | for (i = 0; i < lines; i++) { | |
45 | __asm__ __volatile__ ( | |
46 | " dccleana(%0); " | |
47 | " icinva(%0); " | |
48 | : | |
49 | : "r" (start) | |
50 | ); | |
51 | start += LINESIZE; | |
52 | } | |
53 | __asm__ __volatile__ ( | |
54 | "isync" | |
55 | ); | |
56 | local_irq_restore(flags); | |
57 | } | |
e3560305 | 58 | EXPORT_SYMBOL(flush_icache_range); |
2d3cbc78 RK |
59 | |
60 | void hexagon_clean_dcache_range(unsigned long start, unsigned long end) | |
61 | { | |
62 | unsigned long lines = spanlines(start, end-1); | |
63 | unsigned long i, flags; | |
64 | ||
65 | start &= ~(LINESIZE - 1); | |
66 | ||
67 | local_irq_save(flags); | |
68 | ||
69 | for (i = 0; i < lines; i++) { | |
70 | __asm__ __volatile__ ( | |
71 | " dccleana(%0); " | |
72 | : | |
73 | : "r" (start) | |
74 | ); | |
75 | start += LINESIZE; | |
76 | } | |
77 | local_irq_restore(flags); | |
78 | } | |
79 | ||
80 | void hexagon_inv_dcache_range(unsigned long start, unsigned long end) | |
81 | { | |
82 | unsigned long lines = spanlines(start, end-1); | |
83 | unsigned long i, flags; | |
84 | ||
85 | start &= ~(LINESIZE - 1); | |
86 | ||
87 | local_irq_save(flags); | |
88 | ||
89 | for (i = 0; i < lines; i++) { | |
90 | __asm__ __volatile__ ( | |
91 | " dcinva(%0); " | |
92 | : | |
93 | : "r" (start) | |
94 | ); | |
95 | start += LINESIZE; | |
96 | } | |
97 | local_irq_restore(flags); | |
98 | } | |
99 | ||
100 | ||
101 | ||
102 | ||
103 | /* | |
104 | * This is just really brutal and shouldn't be used anyways, | |
105 | * especially on V2. Left here just in case. | |
106 | */ | |
107 | void flush_cache_all_hexagon(void) | |
108 | { | |
109 | unsigned long flags; | |
110 | local_irq_save(flags); | |
111 | __vmcache_ickill(); | |
112 | __vmcache_dckill(); | |
113 | __vmcache_l2kill(); | |
114 | local_irq_restore(flags); | |
115 | mb(); | |
116 | } | |
cb84c2b4 GR |
117 | |
118 | void copy_to_user_page(struct vm_area_struct *vma, struct page *page, | |
119 | unsigned long vaddr, void *dst, void *src, int len) | |
120 | { | |
121 | memcpy(dst, src, len); | |
122 | if (vma->vm_flags & VM_EXEC) { | |
123 | flush_icache_range((unsigned long) dst, | |
124 | (unsigned long) dst + len); | |
125 | } | |
126 | } |