|
22 | 22 | #include <asm/cputype.h>
|
23 | 23 | #include <asm/sections.h>
|
24 | 24 | #include <asm/cachetype.h>
|
| 25 | +#include <asm/fixmap.h> |
25 | 26 | #include <asm/sections.h>
|
26 | 27 | #include <asm/setup.h>
|
27 | 28 | #include <asm/smp_plat.h>
|
@@ -392,6 +393,29 @@ SET_MEMORY_FN(rw, pte_set_rw)
|
392 | 393 | SET_MEMORY_FN(x, pte_set_x)
|
393 | 394 | SET_MEMORY_FN(nx, pte_set_nx)
|
394 | 395 |
|
| 396 | +/* |
| 397 | + * To avoid TLB flush broadcasts, this uses local_flush_tlb_kernel_range(). |
| 398 | + * As a result, this can only be called with preemption disabled, as under |
| 399 | + * stop_machine(). |
| 400 | + */ |
| 401 | +void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) |
| 402 | +{ |
| 403 | + unsigned long vaddr = __fix_to_virt(idx); |
| 404 | + pte_t *pte = pte_offset_kernel(pmd_off_k(vaddr), vaddr); |
| 405 | + |
| 406 | + /* Make sure fixmap region does not exceed available allocation. */ |
| 407 | + BUILD_BUG_ON(FIXADDR_START + (__end_of_fixed_addresses * PAGE_SIZE) > |
| 408 | + FIXADDR_END); |
| 409 | + BUG_ON(idx >= __end_of_fixed_addresses); |
| 410 | + |
| 411 | + if (pgprot_val(prot)) |
| 412 | + set_pte_at(NULL, vaddr, pte, |
| 413 | + pfn_pte(phys >> PAGE_SHIFT, prot)); |
| 414 | + else |
| 415 | + pte_clear(NULL, vaddr, pte); |
| 416 | + local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); |
| 417 | +} |
| 418 | + |
395 | 419 | /*
|
396 | 420 | * Adjust the PMD section entries according to the CPU in use.
|
397 | 421 | */
|
|
0 commit comments