diff options
author | Huang, Ying <ying.huang@intel.com> | 2008-02-13 04:22:41 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-02-13 10:20:35 -0500 |
commit | 4de0d4a6d173351b023ab2855c3d331146a418e5 (patch) | |
tree | 59fd58a74fc693e8b7c2b769180abc8bcbd2df61 /arch | |
parent | e85f20518bb928667508c22090c85d458e25a4f7 (diff) |
x86: EFI runtime code mapping enhancement
This patch enhances EFI runtime code memory mapping as following:
- Move __supported_pte_mask & _PAGE_NX checking before invoking
runtime_code_page_mkexec(). This makes it possible for compiler to
eliminate runtime_code_page_mkexec() on machine without NX support.
- Use set_memory_x/nx in early_mapping_set_exec(). This eliminates the
duplicated implementation.
This patch has been tested on Intel x86_64 platform with EFI64/32
firmware.
Signed-off-by: Huang Ying <ying.huang@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/efi.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/efi_64.c | 32 |
2 files changed, 15 insertions, 23 deletions
diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index b4d523276f40..cbdf9bacc575 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c | |||
@@ -384,9 +384,6 @@ static void __init runtime_code_page_mkexec(void) | |||
384 | efi_memory_desc_t *md; | 384 | efi_memory_desc_t *md; |
385 | void *p; | 385 | void *p; |
386 | 386 | ||
387 | if (!(__supported_pte_mask & _PAGE_NX)) | ||
388 | return; | ||
389 | |||
390 | /* Make EFI runtime service code area executable */ | 387 | /* Make EFI runtime service code area executable */ |
391 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 388 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
392 | md = p; | 389 | md = p; |
@@ -476,7 +473,8 @@ void __init efi_enter_virtual_mode(void) | |||
476 | efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; | 473 | efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; |
477 | efi.reset_system = virt_efi_reset_system; | 474 | efi.reset_system = virt_efi_reset_system; |
478 | efi.set_virtual_address_map = virt_efi_set_virtual_address_map; | 475 | efi.set_virtual_address_map = virt_efi_set_virtual_address_map; |
479 | runtime_code_page_mkexec(); | 476 | if (__supported_pte_mask & _PAGE_NX) |
477 | runtime_code_page_mkexec(); | ||
480 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); | 478 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); |
481 | memmap.map = NULL; | 479 | memmap.map = NULL; |
482 | } | 480 | } |
diff --git a/arch/x86/kernel/efi_64.c b/arch/x86/kernel/efi_64.c index 09d5c2330934..d143a1e76b30 100644 --- a/arch/x86/kernel/efi_64.c +++ b/arch/x86/kernel/efi_64.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <asm/tlbflush.h> | 35 | #include <asm/tlbflush.h> |
36 | #include <asm/proto.h> | 36 | #include <asm/proto.h> |
37 | #include <asm/efi.h> | 37 | #include <asm/efi.h> |
38 | #include <asm/cacheflush.h> | ||
38 | 39 | ||
39 | static pgd_t save_pgd __initdata; | 40 | static pgd_t save_pgd __initdata; |
40 | static unsigned long efi_flags __initdata; | 41 | static unsigned long efi_flags __initdata; |
@@ -43,22 +44,15 @@ static void __init early_mapping_set_exec(unsigned long start, | |||
43 | unsigned long end, | 44 | unsigned long end, |
44 | int executable) | 45 | int executable) |
45 | { | 46 | { |
46 | pte_t *kpte; | 47 | unsigned long num_pages; |
47 | unsigned int level; | 48 | |
48 | 49 | start &= PMD_MASK; | |
49 | while (start < end) { | 50 | end = (end + PMD_SIZE - 1) & PMD_MASK; |
50 | kpte = lookup_address((unsigned long)__va(start), &level); | 51 | num_pages = (end - start) >> PAGE_SHIFT; |
51 | BUG_ON(!kpte); | 52 | if (executable) |
52 | if (executable) | 53 | set_memory_x((unsigned long)__va(start), num_pages); |
53 | set_pte(kpte, pte_mkexec(*kpte)); | 54 | else |
54 | else | 55 | set_memory_nx((unsigned long)__va(start), num_pages); |
55 | set_pte(kpte, __pte((pte_val(*kpte) | _PAGE_NX) & \ | ||
56 | __supported_pte_mask)); | ||
57 | if (level == PG_LEVEL_4K) | ||
58 | start = (start + PAGE_SIZE) & PAGE_MASK; | ||
59 | else | ||
60 | start = (start + PMD_SIZE) & PMD_MASK; | ||
61 | } | ||
62 | } | 56 | } |
63 | 57 | ||
64 | static void __init early_runtime_code_mapping_set_exec(int executable) | 58 | static void __init early_runtime_code_mapping_set_exec(int executable) |
@@ -74,7 +68,7 @@ static void __init early_runtime_code_mapping_set_exec(int executable) | |||
74 | md = p; | 68 | md = p; |
75 | if (md->type == EFI_RUNTIME_SERVICES_CODE) { | 69 | if (md->type == EFI_RUNTIME_SERVICES_CODE) { |
76 | unsigned long end; | 70 | unsigned long end; |
77 | end = md->phys_addr + (md->num_pages << PAGE_SHIFT); | 71 | end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); |
78 | early_mapping_set_exec(md->phys_addr, end, executable); | 72 | early_mapping_set_exec(md->phys_addr, end, executable); |
79 | } | 73 | } |
80 | } | 74 | } |
@@ -84,8 +78,8 @@ void __init efi_call_phys_prelog(void) | |||
84 | { | 78 | { |
85 | unsigned long vaddress; | 79 | unsigned long vaddress; |
86 | 80 | ||
87 | local_irq_save(efi_flags); | ||
88 | early_runtime_code_mapping_set_exec(1); | 81 | early_runtime_code_mapping_set_exec(1); |
82 | local_irq_save(efi_flags); | ||
89 | vaddress = (unsigned long)__va(0x0UL); | 83 | vaddress = (unsigned long)__va(0x0UL); |
90 | save_pgd = *pgd_offset_k(0x0UL); | 84 | save_pgd = *pgd_offset_k(0x0UL); |
91 | set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); | 85 | set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); |
@@ -98,9 +92,9 @@ void __init efi_call_phys_epilog(void) | |||
98 | * After the lock is released, the original page table is restored. | 92 | * After the lock is released, the original page table is restored. |
99 | */ | 93 | */ |
100 | set_pgd(pgd_offset_k(0x0UL), save_pgd); | 94 | set_pgd(pgd_offset_k(0x0UL), save_pgd); |
101 | early_runtime_code_mapping_set_exec(0); | ||
102 | __flush_tlb_all(); | 95 | __flush_tlb_all(); |
103 | local_irq_restore(efi_flags); | 96 | local_irq_restore(efi_flags); |
97 | early_runtime_code_mapping_set_exec(0); | ||
104 | } | 98 | } |
105 | 99 | ||
106 | void __init efi_reserve_bootmem(void) | 100 | void __init efi_reserve_bootmem(void) |