diff options
Diffstat (limited to 'arch/x86/platform/efi/efi_64.c')
-rw-r--r-- | arch/x86/platform/efi/efi_64.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 17e80d829df0..a0ac0f9c307f 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
@@ -41,9 +41,6 @@ | |||
41 | #include <asm/realmode.h> | 41 | #include <asm/realmode.h> |
42 | #include <asm/time.h> | 42 | #include <asm/time.h> |
43 | 43 | ||
44 | static pgd_t *save_pgd __initdata; | ||
45 | static unsigned long efi_flags __initdata; | ||
46 | |||
47 | /* | 44 | /* |
48 | * We allocate runtime services regions bottom-up, starting from -4G, i.e. | 45 | * We allocate runtime services regions bottom-up, starting from -4G, i.e. |
49 | * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G. | 46 | * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G. |
@@ -78,17 +75,18 @@ static void __init early_code_mapping_set_exec(int executable) | |||
78 | } | 75 | } |
79 | } | 76 | } |
80 | 77 | ||
81 | void __init efi_call_phys_prolog(void) | 78 | pgd_t * __init efi_call_phys_prolog(void) |
82 | { | 79 | { |
83 | unsigned long vaddress; | 80 | unsigned long vaddress; |
81 | pgd_t *save_pgd; | ||
82 | |||
84 | int pgd; | 83 | int pgd; |
85 | int n_pgds; | 84 | int n_pgds; |
86 | 85 | ||
87 | if (!efi_enabled(EFI_OLD_MEMMAP)) | 86 | if (!efi_enabled(EFI_OLD_MEMMAP)) |
88 | return; | 87 | return NULL; |
89 | 88 | ||
90 | early_code_mapping_set_exec(1); | 89 | early_code_mapping_set_exec(1); |
91 | local_irq_save(efi_flags); | ||
92 | 90 | ||
93 | n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); | 91 | n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); |
94 | save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); | 92 | save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); |
@@ -99,24 +97,29 @@ void __init efi_call_phys_prolog(void) | |||
99 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); | 97 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); |
100 | } | 98 | } |
101 | __flush_tlb_all(); | 99 | __flush_tlb_all(); |
100 | |||
101 | return save_pgd; | ||
102 | } | 102 | } |
103 | 103 | ||
104 | void __init efi_call_phys_epilog(void) | 104 | void __init efi_call_phys_epilog(pgd_t *save_pgd) |
105 | { | 105 | { |
106 | /* | 106 | /* |
107 | * After the lock is released, the original page table is restored. | 107 | * After the lock is released, the original page table is restored. |
108 | */ | 108 | */ |
109 | int pgd; | 109 | int pgd_idx; |
110 | int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); | 110 | int nr_pgds; |
111 | 111 | ||
112 | if (!efi_enabled(EFI_OLD_MEMMAP)) | 112 | if (!save_pgd) |
113 | return; | 113 | return; |
114 | 114 | ||
115 | for (pgd = 0; pgd < n_pgds; pgd++) | 115 | nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); |
116 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); | 116 | |
117 | for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++) | ||
118 | set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]); | ||
119 | |||
117 | kfree(save_pgd); | 120 | kfree(save_pgd); |
121 | |||
118 | __flush_tlb_all(); | 122 | __flush_tlb_all(); |
119 | local_irq_restore(efi_flags); | ||
120 | early_code_mapping_set_exec(0); | 123 | early_code_mapping_set_exec(0); |
121 | } | 124 | } |
122 | 125 | ||