| .. | .. |
|---|
| 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; |
|---|