aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2013-07-23 17:32:04 -0400
committerChris Metcalf <cmetcalf@tilera.com>2013-07-31 11:51:19 -0400
commitdd78bc11fb2050b6a3990d0421feca4c68ca4335 (patch)
tree7147fe5e0b3815443eea608d3dd0950ba53bb47d
parent7d937719e3c5c6c9ad00584f6b62230d2ef7f9f1 (diff)
tile: convert uses of "inv" to "finv"
The "inv" (invalidate) instruction is generally less safe than "finv" (flush and invalidate), as it will drop dirty data from the cache. It turns out we have almost no need for "inv" (other than for the older 32-bit architecture in some limited cases), so convert to "finv" where possible and delete the extra "inv" infrastructure. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
-rw-r--r--arch/tile/include/asm/cacheflush.h44
-rw-r--r--arch/tile/include/asm/uaccess.h31
-rw-r--r--arch/tile/include/uapi/asm/cachectl.h4
-rw-r--r--arch/tile/kernel/head_32.S2
-rw-r--r--arch/tile/kernel/head_64.S2
-rw-r--r--arch/tile/lib/cacheflush.c13
-rw-r--r--arch/tile/lib/exports.c1
-rw-r--r--arch/tile/lib/usercopy_32.S19
-rw-r--r--arch/tile/lib/usercopy_64.S19
9 files changed, 32 insertions, 103 deletions
diff --git a/arch/tile/include/asm/cacheflush.h b/arch/tile/include/asm/cacheflush.h
index 0fc63c488edf..92ee4c8a4f76 100644
--- a/arch/tile/include/asm/cacheflush.h
+++ b/arch/tile/include/asm/cacheflush.h
@@ -75,23 +75,6 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
75#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ 75#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
76 memcpy((dst), (src), (len)) 76 memcpy((dst), (src), (len))
77 77
78/*
79 * Invalidate a VA range; pads to L2 cacheline boundaries.
80 *
81 * Note that on TILE64, __inv_buffer() actually flushes modified
82 * cache lines in addition to invalidating them, i.e., it's the
83 * same as __finv_buffer().
84 */
85static inline void __inv_buffer(void *buffer, size_t size)
86{
87 char *next = (char *)((long)buffer & -L2_CACHE_BYTES);
88 char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size);
89 while (next < finish) {
90 __insn_inv(next);
91 next += CHIP_INV_STRIDE();
92 }
93}
94
95/* Flush a VA range; pads to L2 cacheline boundaries. */ 78/* Flush a VA range; pads to L2 cacheline boundaries. */
96static inline void __flush_buffer(void *buffer, size_t size) 79static inline void __flush_buffer(void *buffer, size_t size)
97{ 80{
@@ -115,13 +98,6 @@ static inline void __finv_buffer(void *buffer, size_t size)
115} 98}
116 99
117 100
118/* Invalidate a VA range and wait for it to be complete. */
119static inline void inv_buffer(void *buffer, size_t size)
120{
121 __inv_buffer(buffer, size);
122 mb();
123}
124
125/* 101/*
126 * Flush a locally-homecached VA range and wait for the evicted 102 * Flush a locally-homecached VA range and wait for the evicted
127 * cachelines to hit memory. 103 * cachelines to hit memory.
@@ -142,6 +118,26 @@ static inline void finv_buffer_local(void *buffer, size_t size)
142 mb_incoherent(); 118 mb_incoherent();
143} 119}
144 120
121#ifdef __tilepro__
122/* Invalidate a VA range; pads to L2 cacheline boundaries. */
123static inline void __inv_buffer(void *buffer, size_t size)
124{
125 char *next = (char *)((long)buffer & -L2_CACHE_BYTES);
126 char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size);
127 while (next < finish) {
128 __insn_inv(next);
129 next += CHIP_INV_STRIDE();
130 }
131}
132
133/* Invalidate a VA range and wait for it to be complete. */
134static inline void inv_buffer(void *buffer, size_t size)
135{
136 __inv_buffer(buffer, size);
137 mb();
138}
139#endif
140
145/* 141/*
146 * Flush and invalidate a VA range that is homed remotely, waiting 142 * Flush and invalidate a VA range that is homed remotely, waiting
147 * until the memory controller holds the flushed values. If "hfh" is 143 * until the memory controller holds the flushed values. If "hfh" is
diff --git a/arch/tile/include/asm/uaccess.h b/arch/tile/include/asm/uaccess.h
index e4d44bd7df27..f68503f8e0aa 100644
--- a/arch/tile/include/asm/uaccess.h
+++ b/arch/tile/include/asm/uaccess.h
@@ -567,37 +567,6 @@ static inline unsigned long __must_check flush_user(
567} 567}
568 568
569/** 569/**
570 * inv_user: - Invalidate a block of memory in user space from cache.
571 * @mem: Destination address, in user space.
572 * @len: Number of bytes to invalidate.
573 *
574 * Returns number of bytes that could not be invalidated.
575 * On success, this will be zero.
576 *
577 * Note that on Tile64, the "inv" operation is in fact a
578 * "flush and invalidate", so cache write-backs will occur prior
579 * to the cache being marked invalid.
580 */
581extern unsigned long inv_user_asm(void __user *mem, unsigned long len);
582static inline unsigned long __must_check __inv_user(
583 void __user *mem, unsigned long len)
584{
585 int retval;
586
587 might_fault();
588 retval = inv_user_asm(mem, len);
589 mb_incoherent();
590 return retval;
591}
592static inline unsigned long __must_check inv_user(
593 void __user *mem, unsigned long len)
594{
595 if (access_ok(VERIFY_WRITE, mem, len))
596 return __inv_user(mem, len);
597 return len;
598}
599
600/**
601 * finv_user: - Flush-inval a block of memory in user space from cache. 570 * finv_user: - Flush-inval a block of memory in user space from cache.
602 * @mem: Destination address, in user space. 571 * @mem: Destination address, in user space.
603 * @len: Number of bytes to invalidate. 572 * @len: Number of bytes to invalidate.
diff --git a/arch/tile/include/uapi/asm/cachectl.h b/arch/tile/include/uapi/asm/cachectl.h
index af4c9f9154d1..572ddcad2090 100644
--- a/arch/tile/include/uapi/asm/cachectl.h
+++ b/arch/tile/include/uapi/asm/cachectl.h
@@ -29,8 +29,8 @@
29 * to honor the arguments at some point.) 29 * to honor the arguments at some point.)
30 * 30 *
31 * Flush and invalidation of memory can normally be performed with the 31 * Flush and invalidation of memory can normally be performed with the
32 * __insn_flush(), __insn_inv(), and __insn_finv() instructions from 32 * __insn_flush() and __insn_finv() instructions from userspace.
33 * userspace. The DCACHE option to the system call allows userspace 33 * The DCACHE option to the system call allows userspace
34 * to flush the entire L1+L2 data cache from the core. In this case, 34 * to flush the entire L1+L2 data cache from the core. In this case,
35 * the address and length arguments are not used. The DCACHE flush is 35 * the address and length arguments are not used. The DCACHE flush is
36 * restricted to the current core, not all cores in the address space. 36 * restricted to the current core, not all cores in the address space.
diff --git a/arch/tile/kernel/head_32.S b/arch/tile/kernel/head_32.S
index ac115307e5e4..80cd407925cd 100644
--- a/arch/tile/kernel/head_32.S
+++ b/arch/tile/kernel/head_32.S
@@ -64,7 +64,7 @@ ENTRY(_start)
64 auli r0, r0, ha16(swapper_pg_dir - PAGE_OFFSET) 64 auli r0, r0, ha16(swapper_pg_dir - PAGE_OFFSET)
65 } 65 }
66 { 66 {
67 inv r6 67 finv r6
68 move r1, zero /* high 32 bits of CPA is zero */ 68 move r1, zero /* high 32 bits of CPA is zero */
69 } 69 }
70 { 70 {
diff --git a/arch/tile/kernel/head_64.S b/arch/tile/kernel/head_64.S
index 6093964fa5c7..e23e5f7b91d9 100644
--- a/arch/tile/kernel/head_64.S
+++ b/arch/tile/kernel/head_64.S
@@ -77,7 +77,7 @@ ENTRY(_start)
77 { 77 {
78 /* After initializing swapper_pgprot, HV_PTE_GLOBAL is set. */ 78 /* After initializing swapper_pgprot, HV_PTE_GLOBAL is set. */
79 bfextu r7, r1, HV_PTE_INDEX_GLOBAL, HV_PTE_INDEX_GLOBAL 79 bfextu r7, r1, HV_PTE_INDEX_GLOBAL, HV_PTE_INDEX_GLOBAL
80 inv r4 80 finv r4
81 } 81 }
82 bnez r7, .Lno_write 82 bnez r7, .Lno_write
83 { 83 {
diff --git a/arch/tile/lib/cacheflush.c b/arch/tile/lib/cacheflush.c
index 8f8ad814b139..2238b40abf3c 100644
--- a/arch/tile/lib/cacheflush.c
+++ b/arch/tile/lib/cacheflush.c
@@ -147,18 +147,21 @@ void finv_buffer_remote(void *buffer, size_t size, int hfh)
147 force_load(p); 147 force_load(p);
148 148
149 /* 149 /*
150 * Repeat, but with inv's instead of loads, to get rid of the 150 * Repeat, but with finv's instead of loads, to get rid of the
151 * data we just loaded into our own cache and the old home L3. 151 * data we just loaded into our own cache and the old home L3.
152 * No need to unroll since inv's don't target a register. 152 * No need to unroll since finv's don't target a register.
153 * The finv's are guaranteed not to actually flush the data in
154 * the buffer back to their home, since we just read it, so the
155 * lines are clean in cache; we will only invalidate those lines.
153 */ 156 */
154 p = (char *)buffer + size - 1; 157 p = (char *)buffer + size - 1;
155 __insn_inv(p); 158 __insn_finv(p);
156 p -= step_size; 159 p -= step_size;
157 p = (char *)((unsigned long)p | (step_size - 1)); 160 p = (char *)((unsigned long)p | (step_size - 1));
158 for (; p >= base; p -= step_size) 161 for (; p >= base; p -= step_size)
159 __insn_inv(p); 162 __insn_finv(p);
160 163
161 /* Wait for the load+inv's (and thus finvs) to have completed. */ 164 /* Wait for these finv's (and thus the first finvs) to be done. */
162 __insn_mf(); 165 __insn_mf();
163 166
164#ifdef __tilegx__ 167#ifdef __tilegx__
diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c
index a93b02a25222..359b1bc52d84 100644
--- a/arch/tile/lib/exports.c
+++ b/arch/tile/lib/exports.c
@@ -22,7 +22,6 @@ EXPORT_SYMBOL(strnlen_user_asm);
22EXPORT_SYMBOL(strncpy_from_user_asm); 22EXPORT_SYMBOL(strncpy_from_user_asm);
23EXPORT_SYMBOL(clear_user_asm); 23EXPORT_SYMBOL(clear_user_asm);
24EXPORT_SYMBOL(flush_user_asm); 24EXPORT_SYMBOL(flush_user_asm);
25EXPORT_SYMBOL(inv_user_asm);
26EXPORT_SYMBOL(finv_user_asm); 25EXPORT_SYMBOL(finv_user_asm);
27 26
28/* arch/tile/kernel/entry.S */ 27/* arch/tile/kernel/entry.S */
diff --git a/arch/tile/lib/usercopy_32.S b/arch/tile/lib/usercopy_32.S
index b62d002af009..21ffa88ffe5f 100644
--- a/arch/tile/lib/usercopy_32.S
+++ b/arch/tile/lib/usercopy_32.S
@@ -109,25 +109,6 @@ STD_ENTRY(flush_user_asm)
109 .popsection 109 .popsection
110 110
111/* 111/*
112 * inv_user_asm takes the user target address in r0 and the
113 * number of bytes to invalidate in r1.
114 * It returns the number of not inv'able bytes (hopefully zero) in r0.
115 */
116STD_ENTRY(inv_user_asm)
117 bz r1, 2f
118 { movei r2, L2_CACHE_BYTES; add r1, r0, r1 }
119 { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 }
120 { and r0, r0, r2; and r1, r1, r2 }
121 { sub r1, r1, r0 }
1221: { inv r0; addi r1, r1, -CHIP_INV_STRIDE() }
123 { addi r0, r0, CHIP_INV_STRIDE(); bnzt r1, 1b }
1242: { move r0, r1; jrp lr }
125 STD_ENDPROC(inv_user_asm)
126 .pushsection __ex_table,"a"
127 .word 1b, 2b
128 .popsection
129
130/*
131 * finv_user_asm takes the user target address in r0 and the 112 * finv_user_asm takes the user target address in r0 and the
132 * number of bytes to flush-invalidate in r1. 113 * number of bytes to flush-invalidate in r1.
133 * It returns the number of not finv'able bytes (hopefully zero) in r0. 114 * It returns the number of not finv'able bytes (hopefully zero) in r0.
diff --git a/arch/tile/lib/usercopy_64.S b/arch/tile/lib/usercopy_64.S
index adb2dbbc70cd..f248d3196e5c 100644
--- a/arch/tile/lib/usercopy_64.S
+++ b/arch/tile/lib/usercopy_64.S
@@ -109,25 +109,6 @@ STD_ENTRY(flush_user_asm)
109 .popsection 109 .popsection
110 110
111/* 111/*
112 * inv_user_asm takes the user target address in r0 and the
113 * number of bytes to invalidate in r1.
114 * It returns the number of not inv'able bytes (hopefully zero) in r0.
115 */
116STD_ENTRY(inv_user_asm)
117 beqz r1, 2f
118 { movei r2, L2_CACHE_BYTES; add r1, r0, r1 }
119 { sub r2, zero, r2; addi r1, r1, L2_CACHE_BYTES-1 }
120 { and r0, r0, r2; and r1, r1, r2 }
121 { sub r1, r1, r0 }
1221: { inv r0; addi r1, r1, -CHIP_INV_STRIDE() }
123 { addi r0, r0, CHIP_INV_STRIDE(); bnezt r1, 1b }
1242: { move r0, r1; jrp lr }
125 STD_ENDPROC(inv_user_asm)
126 .pushsection __ex_table,"a"
127 .quad 1b, 2b
128 .popsection
129
130/*
131 * finv_user_asm takes the user target address in r0 and the 112 * finv_user_asm takes the user target address in r0 and the
132 * number of bytes to flush-invalidate in r1. 113 * number of bytes to flush-invalidate in r1.
133 * It returns the number of not finv'able bytes (hopefully zero) in r0. 114 * It returns the number of not finv'able bytes (hopefully zero) in r0.