aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile')
-rw-r--r--arch/tile/include/asm/cache.h12
-rw-r--r--arch/tile/include/asm/fixmap.h14
-rw-r--r--arch/tile/include/asm/homecache.h19
-rw-r--r--arch/tile/include/asm/page.h7
-rw-r--r--arch/tile/kernel/pci-dma.c182
-rw-r--r--arch/tile/mm/homecache.c156
-rw-r--r--arch/tile/mm/init.c59
7 files changed, 278 insertions, 171 deletions
diff --git a/arch/tile/include/asm/cache.h b/arch/tile/include/asm/cache.h
index 392e5333dd8b..a9a529964e07 100644
--- a/arch/tile/include/asm/cache.h
+++ b/arch/tile/include/asm/cache.h
@@ -27,11 +27,17 @@
27#define L2_CACHE_ALIGN(x) (((x)+(L2_CACHE_BYTES-1)) & -L2_CACHE_BYTES) 27#define L2_CACHE_ALIGN(x) (((x)+(L2_CACHE_BYTES-1)) & -L2_CACHE_BYTES)
28 28
29/* 29/*
30 * TILE-Gx is fully coherent so we don't need to define ARCH_DMA_MINALIGN. 30 * TILEPro I/O is not always coherent (networking typically uses coherent
31 * I/O, but PCI traffic does not) and setting ARCH_DMA_MINALIGN to the
32 * L2 cacheline size helps ensure that kernel heap allocations are aligned.
33 * TILE-Gx I/O is always coherent when used on hash-for-home pages.
34 *
35 * However, it's possible at runtime to request not to use hash-for-home
36 * for the kernel heap, in which case the kernel will use flush-and-inval
37 * to manage coherence. As a result, we use L2_CACHE_BYTES for the
38 * DMA minimum alignment to avoid false sharing in the kernel heap.
31 */ 39 */
32#ifndef __tilegx__
33#define ARCH_DMA_MINALIGN L2_CACHE_BYTES 40#define ARCH_DMA_MINALIGN L2_CACHE_BYTES
34#endif
35 41
36/* use the cache line size for the L2, which is where it counts */ 42/* use the cache line size for the L2, which is where it counts */
37#define SMP_CACHE_BYTES_SHIFT L2_CACHE_SHIFT 43#define SMP_CACHE_BYTES_SHIFT L2_CACHE_SHIFT
diff --git a/arch/tile/include/asm/fixmap.h b/arch/tile/include/asm/fixmap.h
index c66f7933beaa..e16dbf929cb5 100644
--- a/arch/tile/include/asm/fixmap.h
+++ b/arch/tile/include/asm/fixmap.h
@@ -45,15 +45,23 @@
45 * 45 *
46 * TLB entries of such buffers will not be flushed across 46 * TLB entries of such buffers will not be flushed across
47 * task switches. 47 * task switches.
48 *
49 * We don't bother with a FIX_HOLE since above the fixmaps
50 * is unmapped memory in any case.
51 */ 48 */
52enum fixed_addresses { 49enum fixed_addresses {
50#ifdef __tilegx__
51 /*
52 * TILEPro has unmapped memory above so the hole isn't needed,
53 * and in any case the hole pushes us over a single 16MB pmd.
54 */
55 FIX_HOLE,
56#endif
53#ifdef CONFIG_HIGHMEM 57#ifdef CONFIG_HIGHMEM
54 FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ 58 FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
55 FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, 59 FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
56#endif 60#endif
61#ifdef __tilegx__ /* see homecache.c */
62 FIX_HOMECACHE_BEGIN,
63 FIX_HOMECACHE_END = FIX_HOMECACHE_BEGIN+(NR_CPUS)-1,
64#endif
57 __end_of_permanent_fixed_addresses, 65 __end_of_permanent_fixed_addresses,
58 66
59 /* 67 /*
diff --git a/arch/tile/include/asm/homecache.h b/arch/tile/include/asm/homecache.h
index a8243865d49e..7b7771328642 100644
--- a/arch/tile/include/asm/homecache.h
+++ b/arch/tile/include/asm/homecache.h
@@ -79,10 +79,17 @@ extern void homecache_change_page_home(struct page *, int order, int home);
79/* 79/*
80 * Flush a page out of whatever cache(s) it is in. 80 * Flush a page out of whatever cache(s) it is in.
81 * This is more than just finv, since it properly handles waiting 81 * This is more than just finv, since it properly handles waiting
82 * for the data to reach memory on tilepro, but it can be quite 82 * for the data to reach memory, but it can be quite
83 * heavyweight, particularly on hash-for-home memory. 83 * heavyweight, particularly on incoherent or immutable memory.
84 */ 84 */
85extern void homecache_flush_cache(struct page *, int order); 85extern void homecache_finv_page(struct page *);
86
87/*
88 * Flush a page out of the specified home cache.
89 * Note that the specified home need not be the actual home of the page,
90 * as for example might be the case when coordinating with I/O devices.
91 */
92extern void homecache_finv_map_page(struct page *, int home);
86 93
87/* 94/*
88 * Allocate a page with the given GFP flags, home, and optionally 95 * Allocate a page with the given GFP flags, home, and optionally
@@ -104,10 +111,10 @@ extern struct page *homecache_alloc_pages_node(int nid, gfp_t gfp_mask,
104 * routines use homecache_change_page_home() to reset the home 111 * routines use homecache_change_page_home() to reset the home
105 * back to the default before returning the page to the allocator. 112 * back to the default before returning the page to the allocator.
106 */ 113 */
114void __homecache_free_pages(struct page *, unsigned int order);
107void homecache_free_pages(unsigned long addr, unsigned int order); 115void homecache_free_pages(unsigned long addr, unsigned int order);
108#define homecache_free_page(page) \ 116#define __homecache_free_page(page) __homecache_free_pages((page), 0)
109 homecache_free_pages((page), 0) 117#define homecache_free_page(page) homecache_free_pages((page), 0)
110
111 118
112 119
113/* 120/*
diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h
index 9d9131e5c552..dd033a4fd627 100644
--- a/arch/tile/include/asm/page.h
+++ b/arch/tile/include/asm/page.h
@@ -174,7 +174,9 @@ static inline __attribute_const__ int get_order(unsigned long size)
174#define MEM_LOW_END (HALF_VA_SPACE - 1) /* low half */ 174#define MEM_LOW_END (HALF_VA_SPACE - 1) /* low half */
175#define MEM_HIGH_START (-HALF_VA_SPACE) /* high half */ 175#define MEM_HIGH_START (-HALF_VA_SPACE) /* high half */
176#define PAGE_OFFSET MEM_HIGH_START 176#define PAGE_OFFSET MEM_HIGH_START
177#define _VMALLOC_START _AC(0xfffffff500000000, UL) /* 4 GB */ 177#define FIXADDR_BASE _AC(0xfffffff400000000, UL) /* 4 GB */
178#define FIXADDR_TOP _AC(0xfffffff500000000, UL) /* 4 GB */
179#define _VMALLOC_START FIXADDR_TOP
178#define HUGE_VMAP_BASE _AC(0xfffffff600000000, UL) /* 4 GB */ 180#define HUGE_VMAP_BASE _AC(0xfffffff600000000, UL) /* 4 GB */
179#define MEM_SV_START _AC(0xfffffff700000000, UL) /* 256 MB */ 181#define MEM_SV_START _AC(0xfffffff700000000, UL) /* 256 MB */
180#define MEM_SV_INTRPT MEM_SV_START 182#define MEM_SV_INTRPT MEM_SV_START
@@ -185,9 +187,6 @@ static inline __attribute_const__ int get_order(unsigned long size)
185/* Highest DTLB address we will use */ 187/* Highest DTLB address we will use */
186#define KERNEL_HIGH_VADDR MEM_SV_START 188#define KERNEL_HIGH_VADDR MEM_SV_START
187 189
188/* Since we don't currently provide any fixmaps, we use an impossible VA. */
189#define FIXADDR_TOP MEM_HV_START
190
191#else /* !__tilegx__ */ 190#else /* !__tilegx__ */
192 191
193/* 192/*
diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c
index b3ed19f8779c..9814d7082f24 100644
--- a/arch/tile/kernel/pci-dma.c
+++ b/arch/tile/kernel/pci-dma.c
@@ -22,9 +22,15 @@
22/* Generic DMA mapping functions: */ 22/* Generic DMA mapping functions: */
23 23
24/* 24/*
25 * Allocate what Linux calls "coherent" memory, which for us just 25 * Allocate what Linux calls "coherent" memory. On TILEPro this is
26 * means uncached. 26 * uncached memory; on TILE-Gx it is hash-for-home memory.
27 */ 27 */
28#ifdef __tilepro__
29#define PAGE_HOME_DMA PAGE_HOME_UNCACHED
30#else
31#define PAGE_HOME_DMA PAGE_HOME_HASH
32#endif
33
28void *dma_alloc_coherent(struct device *dev, 34void *dma_alloc_coherent(struct device *dev,
29 size_t size, 35 size_t size,
30 dma_addr_t *dma_handle, 36 dma_addr_t *dma_handle,
@@ -48,13 +54,13 @@ void *dma_alloc_coherent(struct device *dev,
48 if (dma_mask <= DMA_BIT_MASK(32)) 54 if (dma_mask <= DMA_BIT_MASK(32))
49 node = 0; 55 node = 0;
50 56
51 pg = homecache_alloc_pages_node(node, gfp, order, PAGE_HOME_UNCACHED); 57 pg = homecache_alloc_pages_node(node, gfp, order, PAGE_HOME_DMA);
52 if (pg == NULL) 58 if (pg == NULL)
53 return NULL; 59 return NULL;
54 60
55 addr = page_to_phys(pg); 61 addr = page_to_phys(pg);
56 if (addr + size > dma_mask) { 62 if (addr + size > dma_mask) {
57 homecache_free_pages(addr, order); 63 __homecache_free_pages(pg, order);
58 return NULL; 64 return NULL;
59 } 65 }
60 66
@@ -87,22 +93,110 @@ EXPORT_SYMBOL(dma_free_coherent);
87 * can count on nothing having been touched. 93 * can count on nothing having been touched.
88 */ 94 */
89 95
90/* Flush a PA range from cache page by page. */ 96/* Set up a single page for DMA access. */
91static void __dma_map_pa_range(dma_addr_t dma_addr, size_t size) 97static void __dma_prep_page(struct page *page, unsigned long offset,
98 size_t size, enum dma_data_direction direction)
92{ 99{
93 struct page *page = pfn_to_page(PFN_DOWN(dma_addr)); 100 /*
94 size_t bytesleft = PAGE_SIZE - (dma_addr & (PAGE_SIZE - 1)); 101 * Flush the page from cache if necessary.
102 * On tilegx, data is delivered to hash-for-home L3; on tilepro,
103 * data is delivered direct to memory.
104 *
105 * NOTE: If we were just doing DMA_TO_DEVICE we could optimize
106 * this to be a "flush" not a "finv" and keep some of the
107 * state in cache across the DMA operation, but it doesn't seem
108 * worth creating the necessary flush_buffer_xxx() infrastructure.
109 */
110 int home = page_home(page);
111 switch (home) {
112 case PAGE_HOME_HASH:
113#ifdef __tilegx__
114 return;
115#endif
116 break;
117 case PAGE_HOME_UNCACHED:
118#ifdef __tilepro__
119 return;
120#endif
121 break;
122 case PAGE_HOME_IMMUTABLE:
123 /* Should be going to the device only. */
124 BUG_ON(direction == DMA_FROM_DEVICE ||
125 direction == DMA_BIDIRECTIONAL);
126 return;
127 case PAGE_HOME_INCOHERENT:
128 /* Incoherent anyway, so no need to work hard here. */
129 return;
130 default:
131 BUG_ON(home < 0 || home >= NR_CPUS);
132 break;
133 }
134 homecache_finv_page(page);
135
136#ifdef DEBUG_ALIGNMENT
137 /* Warn if the region isn't cacheline aligned. */
138 if (offset & (L2_CACHE_BYTES - 1) || (size & (L2_CACHE_BYTES - 1)))
139 pr_warn("Unaligned DMA to non-hfh memory: PA %#llx/%#lx\n",
140 PFN_PHYS(page_to_pfn(page)) + offset, size);
141#endif
142}
95 143
96 while ((ssize_t)size > 0) { 144/* Make the page ready to be read by the core. */
97 /* Flush the page. */ 145static void __dma_complete_page(struct page *page, unsigned long offset,
98 homecache_flush_cache(page++, 0); 146 size_t size, enum dma_data_direction direction)
147{
148#ifdef __tilegx__
149 switch (page_home(page)) {
150 case PAGE_HOME_HASH:
151 /* I/O device delivered data the way the cpu wanted it. */
152 break;
153 case PAGE_HOME_INCOHERENT:
154 /* Incoherent anyway, so no need to work hard here. */
155 break;
156 case PAGE_HOME_IMMUTABLE:
157 /* Extra read-only copies are not a problem. */
158 break;
159 default:
160 /* Flush the bogus hash-for-home I/O entries to memory. */
161 homecache_finv_map_page(page, PAGE_HOME_HASH);
162 break;
163 }
164#endif
165}
99 166
100 /* Figure out if we need to continue on the next page. */ 167static void __dma_prep_pa_range(dma_addr_t dma_addr, size_t size,
101 size -= bytesleft; 168 enum dma_data_direction direction)
102 bytesleft = PAGE_SIZE; 169{
170 struct page *page = pfn_to_page(PFN_DOWN(dma_addr));
171 unsigned long offset = dma_addr & (PAGE_SIZE - 1);
172 size_t bytes = min(size, (size_t)(PAGE_SIZE - offset));
173
174 while (size != 0) {
175 __dma_prep_page(page, offset, bytes, direction);
176 size -= bytes;
177 ++page;
178 offset = 0;
179 bytes = min((size_t)PAGE_SIZE, size);
180 }
181}
182
183static void __dma_complete_pa_range(dma_addr_t dma_addr, size_t size,
184 enum dma_data_direction direction)
185{
186 struct page *page = pfn_to_page(PFN_DOWN(dma_addr));
187 unsigned long offset = dma_addr & (PAGE_SIZE - 1);
188 size_t bytes = min(size, (size_t)(PAGE_SIZE - offset));
189
190 while (size != 0) {
191 __dma_complete_page(page, offset, bytes, direction);
192 size -= bytes;
193 ++page;
194 offset = 0;
195 bytes = min((size_t)PAGE_SIZE, size);
103 } 196 }
104} 197}
105 198
199
106/* 200/*
107 * dma_map_single can be passed any memory address, and there appear 201 * dma_map_single can be passed any memory address, and there appear
108 * to be no alignment constraints. 202 * to be no alignment constraints.
@@ -111,28 +205,29 @@ static void __dma_map_pa_range(dma_addr_t dma_addr, size_t size)
111 * line with some other data that has been touched in the meantime. 205 * line with some other data that has been touched in the meantime.
112 */ 206 */
113dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, 207dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
114 enum dma_data_direction direction) 208 enum dma_data_direction direction)
115{ 209{
116 dma_addr_t dma_addr = __pa(ptr); 210 dma_addr_t dma_addr = __pa(ptr);
117 211
118 BUG_ON(!valid_dma_direction(direction)); 212 BUG_ON(!valid_dma_direction(direction));
119 WARN_ON(size == 0); 213 WARN_ON(size == 0);
120 214
121 __dma_map_pa_range(dma_addr, size); 215 __dma_prep_pa_range(dma_addr, size, direction);
122 216
123 return dma_addr; 217 return dma_addr;
124} 218}
125EXPORT_SYMBOL(dma_map_single); 219EXPORT_SYMBOL(dma_map_single);
126 220
127void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, 221void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
128 enum dma_data_direction direction) 222 enum dma_data_direction direction)
129{ 223{
130 BUG_ON(!valid_dma_direction(direction)); 224 BUG_ON(!valid_dma_direction(direction));
225 __dma_complete_pa_range(dma_addr, size, direction);
131} 226}
132EXPORT_SYMBOL(dma_unmap_single); 227EXPORT_SYMBOL(dma_unmap_single);
133 228
134int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, 229int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
135 enum dma_data_direction direction) 230 enum dma_data_direction direction)
136{ 231{
137 struct scatterlist *sg; 232 struct scatterlist *sg;
138 int i; 233 int i;
@@ -143,17 +238,25 @@ int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
143 238
144 for_each_sg(sglist, sg, nents, i) { 239 for_each_sg(sglist, sg, nents, i) {
145 sg->dma_address = sg_phys(sg); 240 sg->dma_address = sg_phys(sg);
146 __dma_map_pa_range(sg->dma_address, sg->length); 241 __dma_prep_pa_range(sg->dma_address, sg->length, direction);
147 } 242 }
148 243
149 return nents; 244 return nents;
150} 245}
151EXPORT_SYMBOL(dma_map_sg); 246EXPORT_SYMBOL(dma_map_sg);
152 247
153void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, 248void dma_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
154 enum dma_data_direction direction) 249 enum dma_data_direction direction)
155{ 250{
251 struct scatterlist *sg;
252 int i;
253
156 BUG_ON(!valid_dma_direction(direction)); 254 BUG_ON(!valid_dma_direction(direction));
255 for_each_sg(sglist, sg, nents, i) {
256 sg->dma_address = sg_phys(sg);
257 __dma_complete_pa_range(sg->dma_address, sg->length,
258 direction);
259 }
157} 260}
158EXPORT_SYMBOL(dma_unmap_sg); 261EXPORT_SYMBOL(dma_unmap_sg);
159 262
@@ -164,16 +267,17 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
164 BUG_ON(!valid_dma_direction(direction)); 267 BUG_ON(!valid_dma_direction(direction));
165 268
166 BUG_ON(offset + size > PAGE_SIZE); 269 BUG_ON(offset + size > PAGE_SIZE);
167 homecache_flush_cache(page, 0); 270 __dma_prep_page(page, offset, size, direction);
168
169 return page_to_pa(page) + offset; 271 return page_to_pa(page) + offset;
170} 272}
171EXPORT_SYMBOL(dma_map_page); 273EXPORT_SYMBOL(dma_map_page);
172 274
173void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, 275void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
174 enum dma_data_direction direction) 276 enum dma_data_direction direction)
175{ 277{
176 BUG_ON(!valid_dma_direction(direction)); 278 BUG_ON(!valid_dma_direction(direction));
279 __dma_complete_page(pfn_to_page(PFN_DOWN(dma_address)),
280 dma_address & PAGE_OFFSET, size, direction);
177} 281}
178EXPORT_SYMBOL(dma_unmap_page); 282EXPORT_SYMBOL(dma_unmap_page);
179 283
@@ -181,33 +285,33 @@ void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
181 size_t size, enum dma_data_direction direction) 285 size_t size, enum dma_data_direction direction)
182{ 286{
183 BUG_ON(!valid_dma_direction(direction)); 287 BUG_ON(!valid_dma_direction(direction));
288 __dma_complete_pa_range(dma_handle, size, direction);
184} 289}
185EXPORT_SYMBOL(dma_sync_single_for_cpu); 290EXPORT_SYMBOL(dma_sync_single_for_cpu);
186 291
187void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, 292void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
188 size_t size, enum dma_data_direction direction) 293 size_t size, enum dma_data_direction direction)
189{ 294{
190 unsigned long start = PFN_DOWN(dma_handle); 295 __dma_prep_pa_range(dma_handle, size, direction);
191 unsigned long end = PFN_DOWN(dma_handle + size - 1);
192 unsigned long i;
193
194 BUG_ON(!valid_dma_direction(direction));
195 for (i = start; i <= end; ++i)
196 homecache_flush_cache(pfn_to_page(i), 0);
197} 296}
198EXPORT_SYMBOL(dma_sync_single_for_device); 297EXPORT_SYMBOL(dma_sync_single_for_device);
199 298
200void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, 299void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist,
201 enum dma_data_direction direction) 300 int nelems, enum dma_data_direction direction)
202{ 301{
302 struct scatterlist *sg;
303 int i;
304
203 BUG_ON(!valid_dma_direction(direction)); 305 BUG_ON(!valid_dma_direction(direction));
204 WARN_ON(nelems == 0 || sg[0].length == 0); 306 WARN_ON(nelems == 0 || sglist->length == 0);
307
308 for_each_sg(sglist, sg, nelems, i) {
309 dma_sync_single_for_cpu(dev, sg->dma_address,
310 sg_dma_len(sg), direction);
311 }
205} 312}
206EXPORT_SYMBOL(dma_sync_sg_for_cpu); 313EXPORT_SYMBOL(dma_sync_sg_for_cpu);
207 314
208/*
209 * Flush and invalidate cache for scatterlist.
210 */
211void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, 315void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
212 int nelems, enum dma_data_direction direction) 316 int nelems, enum dma_data_direction direction)
213{ 317{
@@ -242,8 +346,8 @@ void dma_sync_single_range_for_device(struct device *dev,
242EXPORT_SYMBOL(dma_sync_single_range_for_device); 346EXPORT_SYMBOL(dma_sync_single_range_for_device);
243 347
244/* 348/*
245 * dma_alloc_noncoherent() returns non-cacheable memory, so there's no 349 * dma_alloc_noncoherent() is #defined to return coherent memory,
246 * need to do any flushing here. 350 * so there's no need to do any flushing here.
247 */ 351 */
248void dma_cache_sync(struct device *dev, void *vaddr, size_t size, 352void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
249 enum dma_data_direction direction) 353 enum dma_data_direction direction)
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c
index dbcbdf7b8aa8..5f7868dcd6d4 100644
--- a/arch/tile/mm/homecache.c
+++ b/arch/tile/mm/homecache.c
@@ -64,10 +64,6 @@ early_param("noallocl2", set_noallocl2);
64 64
65#endif 65#endif
66 66
67/* Provide no-op versions of these routines to keep flush_remote() cleaner. */
68#define mark_caches_evicted_start() 0
69#define mark_caches_evicted_finish(mask, timestamp) do {} while (0)
70
71 67
72/* 68/*
73 * Update the irq_stat for cpus that we are going to interrupt 69 * Update the irq_stat for cpus that we are going to interrupt
@@ -107,7 +103,6 @@ static void hv_flush_update(const struct cpumask *cache_cpumask,
107 * there's never any good reason for hv_flush_remote() to fail. 103 * there's never any good reason for hv_flush_remote() to fail.
108 * - Accepts a 32-bit PFN rather than a 64-bit PA, which generally 104 * - Accepts a 32-bit PFN rather than a 64-bit PA, which generally
109 * is the type that Linux wants to pass around anyway. 105 * is the type that Linux wants to pass around anyway.
110 * - Centralizes the mark_caches_evicted() handling.
111 * - Canonicalizes that lengths of zero make cpumasks NULL. 106 * - Canonicalizes that lengths of zero make cpumasks NULL.
112 * - Handles deferring TLB flushes for dataplane tiles. 107 * - Handles deferring TLB flushes for dataplane tiles.
113 * - Tracks remote interrupts in the per-cpu irq_cpustat_t. 108 * - Tracks remote interrupts in the per-cpu irq_cpustat_t.
@@ -126,7 +121,6 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
126 HV_Remote_ASID *asids, int asidcount) 121 HV_Remote_ASID *asids, int asidcount)
127{ 122{
128 int rc; 123 int rc;
129 int timestamp = 0; /* happy compiler */
130 struct cpumask cache_cpumask_copy, tlb_cpumask_copy; 124 struct cpumask cache_cpumask_copy, tlb_cpumask_copy;
131 struct cpumask *cache_cpumask, *tlb_cpumask; 125 struct cpumask *cache_cpumask, *tlb_cpumask;
132 HV_PhysAddr cache_pa; 126 HV_PhysAddr cache_pa;
@@ -157,15 +151,11 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
157 hv_flush_update(cache_cpumask, tlb_cpumask, tlb_va, tlb_length, 151 hv_flush_update(cache_cpumask, tlb_cpumask, tlb_va, tlb_length,
158 asids, asidcount); 152 asids, asidcount);
159 cache_pa = (HV_PhysAddr)cache_pfn << PAGE_SHIFT; 153 cache_pa = (HV_PhysAddr)cache_pfn << PAGE_SHIFT;
160 if (cache_control & HV_FLUSH_EVICT_L2)
161 timestamp = mark_caches_evicted_start();
162 rc = hv_flush_remote(cache_pa, cache_control, 154 rc = hv_flush_remote(cache_pa, cache_control,
163 cpumask_bits(cache_cpumask), 155 cpumask_bits(cache_cpumask),
164 tlb_va, tlb_length, tlb_pgsize, 156 tlb_va, tlb_length, tlb_pgsize,
165 cpumask_bits(tlb_cpumask), 157 cpumask_bits(tlb_cpumask),
166 asids, asidcount); 158 asids, asidcount);
167 if (cache_control & HV_FLUSH_EVICT_L2)
168 mark_caches_evicted_finish(cache_cpumask, timestamp);
169 if (rc == 0) 159 if (rc == 0)
170 return; 160 return;
171 cpumask_scnprintf(cache_buf, sizeof(cache_buf), &cache_cpumask_copy); 161 cpumask_scnprintf(cache_buf, sizeof(cache_buf), &cache_cpumask_copy);
@@ -180,85 +170,86 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
180 panic("Unsafe to continue."); 170 panic("Unsafe to continue.");
181} 171}
182 172
183void flush_remote_page(struct page *page, int order) 173static void homecache_finv_page_va(void* va, int home)
184{ 174{
185 int i, pages = (1 << order); 175 if (home == smp_processor_id()) {
186 for (i = 0; i < pages; ++i, ++page) { 176 finv_buffer_local(va, PAGE_SIZE);
187 void *p = kmap_atomic(page); 177 } else if (home == PAGE_HOME_HASH) {
188 int hfh = 0; 178 finv_buffer_remote(va, PAGE_SIZE, 1);
189 int home = page_home(page); 179 } else {
190#if CHIP_HAS_CBOX_HOME_MAP() 180 BUG_ON(home < 0 || home >= NR_CPUS);
191 if (home == PAGE_HOME_HASH) 181 finv_buffer_remote(va, PAGE_SIZE, 0);
192 hfh = 1;
193 else
194#endif
195 BUG_ON(home < 0 || home >= NR_CPUS);
196 finv_buffer_remote(p, PAGE_SIZE, hfh);
197 kunmap_atomic(p);
198 } 182 }
199} 183}
200 184
201void homecache_evict(const struct cpumask *mask) 185void homecache_finv_map_page(struct page *page, int home)
202{ 186{
203 flush_remote(0, HV_FLUSH_EVICT_L2, mask, 0, 0, 0, NULL, NULL, 0); 187 unsigned long flags;
188 unsigned long va;
189 pte_t *ptep;
190 pte_t pte;
191
192 if (home == PAGE_HOME_UNCACHED)
193 return;
194 local_irq_save(flags);
195#ifdef CONFIG_HIGHMEM
196 va = __fix_to_virt(FIX_KMAP_BEGIN + kmap_atomic_idx_push() +
197 (KM_TYPE_NR * smp_processor_id()));
198#else
199 va = __fix_to_virt(FIX_HOMECACHE_BEGIN + smp_processor_id());
200#endif
201 ptep = virt_to_pte(NULL, (unsigned long)va);
202 pte = pfn_pte(page_to_pfn(page), PAGE_KERNEL);
203 __set_pte(ptep, pte_set_home(pte, home));
204 homecache_finv_page_va((void *)va, home);
205 __pte_clear(ptep);
206 hv_flush_page(va, PAGE_SIZE);
207#ifdef CONFIG_HIGHMEM
208 kmap_atomic_idx_pop();
209#endif
210 local_irq_restore(flags);
204} 211}
205 212
206/* 213static void homecache_finv_page_home(struct page *page, int home)
207 * Return a mask of the cpus whose caches currently own these pages.
208 * The return value is whether the pages are all coherently cached
209 * (i.e. none are immutable, incoherent, or uncached).
210 */
211static int homecache_mask(struct page *page, int pages,
212 struct cpumask *home_mask)
213{ 214{
214 int i; 215 if (!PageHighMem(page) && home == page_home(page))
215 int cached_coherently = 1; 216 homecache_finv_page_va(page_address(page), home);
216 cpumask_clear(home_mask); 217 else
217 for (i = 0; i < pages; ++i) { 218 homecache_finv_map_page(page, home);
218 int home = page_home(&page[i]);
219 if (home == PAGE_HOME_IMMUTABLE ||
220 home == PAGE_HOME_INCOHERENT) {
221 cpumask_copy(home_mask, cpu_possible_mask);
222 return 0;
223 }
224#if CHIP_HAS_CBOX_HOME_MAP()
225 if (home == PAGE_HOME_HASH) {
226 cpumask_or(home_mask, home_mask, &hash_for_home_map);
227 continue;
228 }
229#endif
230 if (home == PAGE_HOME_UNCACHED) {
231 cached_coherently = 0;
232 continue;
233 }
234 BUG_ON(home < 0 || home >= NR_CPUS);
235 cpumask_set_cpu(home, home_mask);
236 }
237 return cached_coherently;
238} 219}
239 220
240/* 221static inline bool incoherent_home(int home)
241 * Return the passed length, or zero if it's long enough that we
242 * believe we should evict the whole L2 cache.
243 */
244static unsigned long cache_flush_length(unsigned long length)
245{ 222{
246 return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length; 223 return home == PAGE_HOME_IMMUTABLE || home == PAGE_HOME_INCOHERENT;
247} 224}
248 225
249/* Flush a page out of whatever cache(s) it is in. */ 226static void homecache_finv_page_internal(struct page *page, int force_map)
250void homecache_flush_cache(struct page *page, int order)
251{ 227{
252 int pages = 1 << order; 228 int home = page_home(page);
253 int length = cache_flush_length(pages * PAGE_SIZE); 229 if (home == PAGE_HOME_UNCACHED)
254 unsigned long pfn = page_to_pfn(page); 230 return;
255 struct cpumask home_mask; 231 if (incoherent_home(home)) {
256 232 int cpu;
257 homecache_mask(page, pages, &home_mask); 233 for_each_cpu(cpu, &cpu_cacheable_map)
258 flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0); 234 homecache_finv_map_page(page, cpu);
259 sim_validate_lines_evicted(PFN_PHYS(pfn), pages * PAGE_SIZE); 235 } else if (force_map) {
236 /* Force if, e.g., the normal mapping is migrating. */
237 homecache_finv_map_page(page, home);
238 } else {
239 homecache_finv_page_home(page, home);
240 }
241 sim_validate_lines_evicted(PFN_PHYS(page_to_pfn(page)), PAGE_SIZE);
260} 242}
261 243
244void homecache_finv_page(struct page *page)
245{
246 homecache_finv_page_internal(page, 0);
247}
248
249void homecache_evict(const struct cpumask *mask)
250{
251 flush_remote(0, HV_FLUSH_EVICT_L2, mask, 0, 0, 0, NULL, NULL, 0);
252}
262 253
263/* Report the home corresponding to a given PTE. */ 254/* Report the home corresponding to a given PTE. */
264static int pte_to_home(pte_t pte) 255static int pte_to_home(pte_t pte)
@@ -441,15 +432,8 @@ struct page *homecache_alloc_pages_node(int nid, gfp_t gfp_mask,
441 return page; 432 return page;
442} 433}
443 434
444void homecache_free_pages(unsigned long addr, unsigned int order) 435void __homecache_free_pages(struct page *page, unsigned int order)
445{ 436{
446 struct page *page;
447
448 if (addr == 0)
449 return;
450
451 VM_BUG_ON(!virt_addr_valid((void *)addr));
452 page = virt_to_page((void *)addr);
453 if (put_page_testzero(page)) { 437 if (put_page_testzero(page)) {
454 homecache_change_page_home(page, order, initial_page_home()); 438 homecache_change_page_home(page, order, initial_page_home());
455 if (order == 0) { 439 if (order == 0) {
@@ -460,3 +444,13 @@ void homecache_free_pages(unsigned long addr, unsigned int order)
460 } 444 }
461 } 445 }
462} 446}
447EXPORT_SYMBOL(__homecache_free_pages);
448
449void homecache_free_pages(unsigned long addr, unsigned int order)
450{
451 if (addr != 0) {
452 VM_BUG_ON(!virt_addr_valid((void *)addr));
453 __homecache_free_pages(virt_to_page((void *)addr), order);
454 }
455}
456EXPORT_SYMBOL(homecache_free_pages);
diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c
index 630dd2ce2afe..a2417a0a8222 100644
--- a/arch/tile/mm/init.c
+++ b/arch/tile/mm/init.c
@@ -150,7 +150,21 @@ void __init shatter_pmd(pmd_t *pmd)
150 assign_pte(pmd, pte); 150 assign_pte(pmd, pte);
151} 151}
152 152
153#ifdef CONFIG_HIGHMEM 153#ifdef __tilegx__
154static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va)
155{
156 pud_t *pud = pud_offset(&pgtables[pgd_index(va)], va);
157 if (pud_none(*pud))
158 assign_pmd(pud, alloc_pmd());
159 return pmd_offset(pud, va);
160}
161#else
162static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va)
163{
164 return pmd_offset(pud_offset(&pgtables[pgd_index(va)], va), va);
165}
166#endif
167
154/* 168/*
155 * This function initializes a certain range of kernel virtual memory 169 * This function initializes a certain range of kernel virtual memory
156 * with new bootmem page tables, everywhere page tables are missing in 170 * with new bootmem page tables, everywhere page tables are missing in
@@ -163,24 +177,17 @@ void __init shatter_pmd(pmd_t *pmd)
163 * checking the pgd every time. 177 * checking the pgd every time.
164 */ 178 */
165static void __init page_table_range_init(unsigned long start, 179static void __init page_table_range_init(unsigned long start,
166 unsigned long end, pgd_t *pgd_base) 180 unsigned long end, pgd_t *pgd)
167{ 181{
168 pgd_t *pgd;
169 int pgd_idx;
170 unsigned long vaddr; 182 unsigned long vaddr;
171 183 start = round_down(start, PMD_SIZE);
172 vaddr = start; 184 end = round_up(end, PMD_SIZE);
173 pgd_idx = pgd_index(vaddr); 185 for (vaddr = start; vaddr < end; vaddr += PMD_SIZE) {
174 pgd = pgd_base + pgd_idx; 186 pmd_t *pmd = get_pmd(pgd, vaddr);
175
176 for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
177 pmd_t *pmd = pmd_offset(pud_offset(pgd, vaddr), vaddr);
178 if (pmd_none(*pmd)) 187 if (pmd_none(*pmd))
179 assign_pte(pmd, alloc_pte()); 188 assign_pte(pmd, alloc_pte());
180 vaddr += PMD_SIZE;
181 } 189 }
182} 190}
183#endif /* CONFIG_HIGHMEM */
184 191
185 192
186#if CHIP_HAS_CBOX_HOME_MAP() 193#if CHIP_HAS_CBOX_HOME_MAP()
@@ -404,21 +411,6 @@ static inline pgprot_t ktext_set_nocache(pgprot_t prot)
404 return prot; 411 return prot;
405} 412}
406 413
407#ifndef __tilegx__
408static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va)
409{
410 return pmd_offset(pud_offset(&pgtables[pgd_index(va)], va), va);
411}
412#else
413static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va)
414{
415 pud_t *pud = pud_offset(&pgtables[pgd_index(va)], va);
416 if (pud_none(*pud))
417 assign_pmd(pud, alloc_pmd());
418 return pmd_offset(pud, va);
419}
420#endif
421
422/* Temporary page table we use for staging. */ 414/* Temporary page table we use for staging. */
423static pgd_t pgtables[PTRS_PER_PGD] 415static pgd_t pgtables[PTRS_PER_PGD]
424 __attribute__((aligned(HV_PAGE_TABLE_ALIGN))); 416 __attribute__((aligned(HV_PAGE_TABLE_ALIGN)));
@@ -779,9 +771,6 @@ static void __init set_non_bootmem_pages_init(void)
779 */ 771 */
780void __init paging_init(void) 772void __init paging_init(void)
781{ 773{
782#ifdef CONFIG_HIGHMEM
783 unsigned long vaddr, end;
784#endif
785#ifdef __tilegx__ 774#ifdef __tilegx__
786 pud_t *pud; 775 pud_t *pud;
787#endif 776#endif
@@ -789,14 +778,14 @@ void __init paging_init(void)
789 778
790 kernel_physical_mapping_init(pgd_base); 779 kernel_physical_mapping_init(pgd_base);
791 780
792#ifdef CONFIG_HIGHMEM
793 /* 781 /*
794 * Fixed mappings, only the page table structure has to be 782 * Fixed mappings, only the page table structure has to be
795 * created - mappings will be set by set_fixmap(): 783 * created - mappings will be set by set_fixmap():
796 */ 784 */
797 vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; 785 page_table_range_init(fix_to_virt(__end_of_fixed_addresses - 1),
798 end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK; 786 FIXADDR_TOP, pgd_base);
799 page_table_range_init(vaddr, end, pgd_base); 787
788#ifdef CONFIG_HIGHMEM
800 permanent_kmaps_init(pgd_base); 789 permanent_kmaps_init(pgd_base);
801#endif 790#endif
802 791