diff options
| -rw-r--r-- | arch/x86/platform/efi/efi_64.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 95fd505dfeb6..2b2003860615 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | #include <asm/cacheflush.h> | 38 | #include <asm/cacheflush.h> |
| 39 | #include <asm/fixmap.h> | 39 | #include <asm/fixmap.h> |
| 40 | 40 | ||
| 41 | static pgd_t save_pgd __initdata; | 41 | static pgd_t *save_pgd __initdata; |
| 42 | static unsigned long efi_flags __initdata; | 42 | static unsigned long efi_flags __initdata; |
| 43 | 43 | ||
| 44 | static void __init early_code_mapping_set_exec(int executable) | 44 | static void __init early_code_mapping_set_exec(int executable) |
| @@ -61,12 +61,20 @@ static void __init early_code_mapping_set_exec(int executable) | |||
| 61 | void __init efi_call_phys_prelog(void) | 61 | void __init efi_call_phys_prelog(void) |
| 62 | { | 62 | { |
| 63 | unsigned long vaddress; | 63 | unsigned long vaddress; |
| 64 | int pgd; | ||
| 65 | int n_pgds; | ||
| 64 | 66 | ||
| 65 | early_code_mapping_set_exec(1); | 67 | early_code_mapping_set_exec(1); |
| 66 | local_irq_save(efi_flags); | 68 | local_irq_save(efi_flags); |
| 67 | vaddress = (unsigned long)__va(0x0UL); | 69 | |
| 68 | save_pgd = *pgd_offset_k(0x0UL); | 70 | n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); |
| 69 | set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); | 71 | save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); |
| 72 | |||
| 73 | for (pgd = 0; pgd < n_pgds; pgd++) { | ||
| 74 | save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); | ||
| 75 | vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); | ||
| 76 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); | ||
| 77 | } | ||
| 70 | __flush_tlb_all(); | 78 | __flush_tlb_all(); |
| 71 | } | 79 | } |
| 72 | 80 | ||
| @@ -75,7 +83,11 @@ void __init efi_call_phys_epilog(void) | |||
| 75 | /* | 83 | /* |
| 76 | * After the lock is released, the original page table is restored. | 84 | * After the lock is released, the original page table is restored. |
| 77 | */ | 85 | */ |
| 78 | set_pgd(pgd_offset_k(0x0UL), save_pgd); | 86 | int pgd; |
| 87 | int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); | ||
| 88 | for (pgd = 0; pgd < n_pgds; pgd++) | ||
| 89 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); | ||
| 90 | kfree(save_pgd); | ||
| 79 | __flush_tlb_all(); | 91 | __flush_tlb_all(); |
| 80 | local_irq_restore(efi_flags); | 92 | local_irq_restore(efi_flags); |
| 81 | early_code_mapping_set_exec(0); | 93 | early_code_mapping_set_exec(0); |
