.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * TLB support routines. |
---|
3 | 4 | * |
---|
.. | .. |
---|
21 | 22 | #include <linux/sched.h> |
---|
22 | 23 | #include <linux/smp.h> |
---|
23 | 24 | #include <linux/mm.h> |
---|
24 | | -#include <linux/bootmem.h> |
---|
| 25 | +#include <linux/memblock.h> |
---|
25 | 26 | #include <linux/slab.h> |
---|
26 | 27 | |
---|
27 | 28 | #include <asm/delay.h> |
---|
28 | 29 | #include <asm/mmu_context.h> |
---|
29 | | -#include <asm/pgalloc.h> |
---|
30 | 30 | #include <asm/pal.h> |
---|
31 | 31 | #include <asm/tlbflush.h> |
---|
32 | 32 | #include <asm/dma.h> |
---|
.. | .. |
---|
59 | 59 | void __init |
---|
60 | 60 | mmu_context_init (void) |
---|
61 | 61 | { |
---|
62 | | - ia64_ctx.bitmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3); |
---|
63 | | - ia64_ctx.flushmap = alloc_bootmem((ia64_ctx.max_ctx+1)>>3); |
---|
| 62 | + ia64_ctx.bitmap = memblock_alloc((ia64_ctx.max_ctx + 1) >> 3, |
---|
| 63 | + SMP_CACHE_BYTES); |
---|
| 64 | + if (!ia64_ctx.bitmap) |
---|
| 65 | + panic("%s: Failed to allocate %u bytes\n", __func__, |
---|
| 66 | + (ia64_ctx.max_ctx + 1) >> 3); |
---|
| 67 | + ia64_ctx.flushmap = memblock_alloc((ia64_ctx.max_ctx + 1) >> 3, |
---|
| 68 | + SMP_CACHE_BYTES); |
---|
| 69 | + if (!ia64_ctx.flushmap) |
---|
| 70 | + panic("%s: Failed to allocate %u bytes\n", __func__, |
---|
| 71 | + (ia64_ctx.max_ctx + 1) >> 3); |
---|
64 | 72 | } |
---|
65 | 73 | |
---|
66 | 74 | /* |
---|
.. | .. |
---|
236 | 244 | spinaphore_init(&ptcg_sem, max_purges); |
---|
237 | 245 | } |
---|
238 | 246 | |
---|
239 | | -void |
---|
| 247 | +#ifdef CONFIG_SMP |
---|
| 248 | +static void |
---|
240 | 249 | ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, |
---|
241 | 250 | unsigned long end, unsigned long nbits) |
---|
242 | 251 | { |
---|
.. | .. |
---|
273 | 282 | activate_context(active_mm); |
---|
274 | 283 | } |
---|
275 | 284 | } |
---|
| 285 | +#endif /* CONFIG_SMP */ |
---|
276 | 286 | |
---|
277 | 287 | void |
---|
278 | 288 | local_flush_tlb_all (void) |
---|
.. | .. |
---|
297 | 307 | ia64_srlz_i(); /* srlz.i implies srlz.d */ |
---|
298 | 308 | } |
---|
299 | 309 | |
---|
300 | | -void |
---|
301 | | -flush_tlb_range (struct vm_area_struct *vma, unsigned long start, |
---|
| 310 | +static void |
---|
| 311 | +__flush_tlb_range (struct vm_area_struct *vma, unsigned long start, |
---|
302 | 312 | unsigned long end) |
---|
303 | 313 | { |
---|
304 | 314 | struct mm_struct *mm = vma->vm_mm; |
---|
.. | .. |
---|
323 | 333 | preempt_disable(); |
---|
324 | 334 | #ifdef CONFIG_SMP |
---|
325 | 335 | if (mm != current->active_mm || cpumask_weight(mm_cpumask(mm)) != 1) { |
---|
326 | | - platform_global_tlb_purge(mm, start, end, nbits); |
---|
| 336 | + ia64_global_tlb_purge(mm, start, end, nbits); |
---|
327 | 337 | preempt_enable(); |
---|
328 | 338 | return; |
---|
329 | 339 | } |
---|
.. | .. |
---|
335 | 345 | preempt_enable(); |
---|
336 | 346 | ia64_srlz_i(); /* srlz.i implies srlz.d */ |
---|
337 | 347 | } |
---|
| 348 | + |
---|
| 349 | +void flush_tlb_range(struct vm_area_struct *vma, |
---|
| 350 | + unsigned long start, unsigned long end) |
---|
| 351 | +{ |
---|
| 352 | + if (unlikely(end - start >= 1024*1024*1024*1024UL |
---|
| 353 | + || REGION_NUMBER(start) != REGION_NUMBER(end - 1))) { |
---|
| 354 | + /* |
---|
| 355 | + * If we flush more than a tera-byte or across regions, we're |
---|
| 356 | + * probably better off just flushing the entire TLB(s). This |
---|
| 357 | + * should be very rare and is not worth optimizing for. |
---|
| 358 | + */ |
---|
| 359 | + flush_tlb_all(); |
---|
| 360 | + } else { |
---|
| 361 | + /* flush the address range from the tlb */ |
---|
| 362 | + __flush_tlb_range(vma, start, end); |
---|
| 363 | + /* flush the virt. page-table area mapping the addr range */ |
---|
| 364 | + __flush_tlb_range(vma, ia64_thash(start), ia64_thash(end)); |
---|
| 365 | + } |
---|
| 366 | +} |
---|
338 | 367 | EXPORT_SYMBOL(flush_tlb_range); |
---|
339 | 368 | |
---|
340 | 369 | void ia64_tlb_init(void) |
---|
341 | 370 | { |
---|
342 | | - ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */ |
---|
| 371 | + ia64_ptce_info_t ptce_info; |
---|
343 | 372 | u64 tr_pgbits; |
---|
344 | 373 | long status; |
---|
345 | 374 | pal_vm_info_1_u_t vm_info_1; |
---|