Skip to content

Commit 6d3e32e

Browse files
Matt FlemingH. Peter Anvin
authored andcommitted
x86, efi: Make efi_call_phys_{prelog,epilog} CONFIG_RELOCATABLE-aware
efi_call_phys_prelog() sets up a 1:1 mapping of the physical address range in swapper_pg_dir. Instead of replacing then restoring entries in swapper_pg_dir we should be using initial_page_table which already contains the 1:1 mapping. It's safe to blindly switch back to swapper_pg_dir in the epilog because the physical EFI routines are only called before efi_enter_virtual_mode(), e.g. before any user processes have been forked. Therefore, we don't need to track which pgd was in %cr3 when we entered the prelog. The previous code actually contained a bug because it assumed that the kernel was loaded at a physical address within the first 8MB of ram, usually at 0x100000. However, this isn't the case with a CONFIG_RELOCATABLE=y kernel which could have been loaded anywhere in the physical address space. Also delete the ancient (and bogus) comments about the page table being restored after the lock is released. There is no locking. Cc: Matthew Garrett <mjg@redhat.com> Cc: Darrent Hart <dvhart@linux.intel.com> Signed-off-by: Matt Fleming <matt.fleming@intel.com> Link: http://lkml.kernel.org/r/1323346250.3894.74.camel@mfleming-mobl1.ger.corp.intel.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
1 parent dc47ce9 commit 6d3e32e

1 file changed

Lines changed: 2 additions & 46 deletions

File tree

arch/x86/platform/efi/efi_32.c

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -39,43 +39,14 @@
3939
*/
4040

4141
static unsigned long efi_rt_eflags;
42-
static pgd_t efi_bak_pg_dir_pointer[2];
4342

4443
void efi_call_phys_prelog(void)
4544
{
46-
unsigned long cr4;
47-
unsigned long temp;
4845
struct desc_ptr gdt_descr;
4946

5047
local_irq_save(efi_rt_eflags);
5148

52-
/*
53-
* If I don't have PAE, I should just duplicate two entries in page
54-
* directory. If I have PAE, I just need to duplicate one entry in
55-
* page directory.
56-
*/
57-
cr4 = read_cr4_safe();
58-
59-
if (cr4 & X86_CR4_PAE) {
60-
efi_bak_pg_dir_pointer[0].pgd =
61-
swapper_pg_dir[pgd_index(0)].pgd;
62-
swapper_pg_dir[0].pgd =
63-
swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
64-
} else {
65-
efi_bak_pg_dir_pointer[0].pgd =
66-
swapper_pg_dir[pgd_index(0)].pgd;
67-
efi_bak_pg_dir_pointer[1].pgd =
68-
swapper_pg_dir[pgd_index(0x400000)].pgd;
69-
swapper_pg_dir[pgd_index(0)].pgd =
70-
swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
71-
temp = PAGE_OFFSET + 0x400000;
72-
swapper_pg_dir[pgd_index(0x400000)].pgd =
73-
swapper_pg_dir[pgd_index(temp)].pgd;
74-
}
75-
76-
/*
77-
* After the lock is released, the original page table is restored.
78-
*/
49+
load_cr3(initial_page_table);
7950
__flush_tlb_all();
8051

8152
gdt_descr.address = __pa(get_cpu_gdt_table(0));
@@ -85,28 +56,13 @@ void efi_call_phys_prelog(void)
8556

8657
void efi_call_phys_epilog(void)
8758
{
88-
unsigned long cr4;
8959
struct desc_ptr gdt_descr;
9060

9161
gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
9262
gdt_descr.size = GDT_SIZE - 1;
9363
load_gdt(&gdt_descr);
9464

95-
cr4 = read_cr4_safe();
96-
97-
if (cr4 & X86_CR4_PAE) {
98-
swapper_pg_dir[pgd_index(0)].pgd =
99-
efi_bak_pg_dir_pointer[0].pgd;
100-
} else {
101-
swapper_pg_dir[pgd_index(0)].pgd =
102-
efi_bak_pg_dir_pointer[0].pgd;
103-
swapper_pg_dir[pgd_index(0x400000)].pgd =
104-
efi_bak_pg_dir_pointer[1].pgd;
105-
}
106-
107-
/*
108-
* After the lock is released, the original page table is restored.
109-
*/
65+
load_cr3(swapper_pg_dir);
11066
__flush_tlb_all();
11167

11268
local_irq_restore(efi_rt_eflags);

0 commit comments

Comments
 (0)