aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHuang, Ying <ying.huang@intel.com>2008-02-13 04:22:41 -0500
committerIngo Molnar <mingo@elte.hu>2008-02-13 10:20:35 -0500
commit4de0d4a6d173351b023ab2855c3d331146a418e5 (patch)
tree59fd58a74fc693e8b7c2b769180abc8bcbd2df61
parente85f20518bb928667508c22090c85d458e25a4f7 (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>
-rw-r--r--arch/x86/kernel/efi.c6
-rw-r--r--arch/x86/kernel/efi_64.c32
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
39static pgd_t save_pgd __initdata; 40static pgd_t save_pgd __initdata;
40static unsigned long efi_flags __initdata; 41static 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
64static void __init early_runtime_code_mapping_set_exec(int executable) 58static 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
106void __init efi_reserve_bootmem(void) 100void __init efi_reserve_bootmem(void)