diff options
author | Kees Cook <keescook@chromium.org> | 2014-04-04 17:27:49 -0400 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2014-10-16 17:38:52 -0400 |
commit | 99b4ac9afce4129323b5b4c7002a942a9489914c (patch) | |
tree | e3e5a3a562883eac4999f72e940fa5261c518b46 | |
parent | 836a24183273e9db1c092246bd8e306b297d9917 (diff) |
arm: fixmap: implement __set_fixmap()
This is used from set_fixmap() and clear_fixmap() via asm-generic/fixmap.h.
Also makes sure that the fixmap allocation fits into the expected range.
Based on patch by Rabin Vincent.
Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Rabin Vincent <rabin@rab.in>
Acked-by: Nicolas Pitre <nico@linaro.org>
-rw-r--r-- | arch/arm/include/asm/fixmap.h | 2 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 24 |
2 files changed, 26 insertions, 0 deletions
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index d984ca69ce19..714606f70425 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h | |||
@@ -14,6 +14,8 @@ enum fixed_addresses { | |||
14 | __end_of_fixed_addresses | 14 | __end_of_fixed_addresses |
15 | }; | 15 | }; |
16 | 16 | ||
17 | void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot); | ||
18 | |||
17 | #include <asm-generic/fixmap.h> | 19 | #include <asm-generic/fixmap.h> |
18 | 20 | ||
19 | #endif | 21 | #endif |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 7fa0966cd15f..bdf5c94f7c36 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/cputype.h> | 22 | #include <asm/cputype.h> |
23 | #include <asm/sections.h> | 23 | #include <asm/sections.h> |
24 | #include <asm/cachetype.h> | 24 | #include <asm/cachetype.h> |
25 | #include <asm/fixmap.h> | ||
25 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
26 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
27 | #include <asm/smp_plat.h> | 28 | #include <asm/smp_plat.h> |
@@ -393,6 +394,29 @@ SET_MEMORY_FN(x, pte_set_x) | |||
393 | SET_MEMORY_FN(nx, pte_set_nx) | 394 | SET_MEMORY_FN(nx, pte_set_nx) |
394 | 395 | ||
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 | |||
419 | /* | ||
396 | * Adjust the PMD section entries according to the CPU in use. | 420 | * Adjust the PMD section entries according to the CPU in use. |
397 | */ | 421 | */ |
398 | static void __init build_mem_type_table(void) | 422 | static void __init build_mem_type_table(void) |