[tip:efi/core] x86/efi: Clean up the EFI CR3 save/restore logic

2017-04-05 Thread tip-bot for Andy Lutomirski
Commit-ID:  05dd61fa7ff73678c33d252aa9f989634349c791
Gitweb: http://git.kernel.org/tip/05dd61fa7ff73678c33d252aa9f989634349c791
Author: Andy Lutomirski 
AuthorDate: Tue, 4 Apr 2017 17:02:36 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:48 +0200

x86/efi: Clean up the EFI CR3 save/restore logic

efi_call_phys_prolog() used to return a "pgd_t *" that meant one of
three different things depending on kernel and system configuration.

Clean it up so it uses a union and is more explicit about what's
going on.

Signed-off-by: Andy Lutomirski 
Signed-off-by: Matt Fleming 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Lutomirski 
Cc: Borislav Petkov 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/include/asm/efi.h | 17 +++--
 arch/x86/platform/efi/efi.c|  6 +++---
 arch/x86/platform/efi/efi_32.c | 12 ++--
 arch/x86/platform/efi/efi_64.c | 22 --
 4 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 2f77bce..0859ed7 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -111,11 +111,24 @@ extern void __iomem *__init efi_ioremap(unsigned long 
addr, unsigned long size,
 
 #endif /* CONFIG_X86_32 */
 
+union efi_saved_pgd {
+   /*
+* If !EFI_OLD_MEMMAP or we're 32-bit, this is a verbatim saved CR3
+* value:
+*/
+   unsigned long cr3;
+
+#ifdef CONFIG_X86_64
+   /* If EFI_OLD_MEMMAP, this is a kmalloc()ed copy of the pgd: */
+   pgd_t *pgd;
+#endif
+};
+
 extern struct efi_scratch efi_scratch;
 extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int __init efi_memblock_x86_reserve_range(void);
-extern pgd_t * __init efi_call_phys_prolog(void);
-extern void __init efi_call_phys_epilog(pgd_t *save_pgd);
+extern union efi_saved_pgd __init efi_call_phys_prolog(void);
+extern void __init efi_call_phys_epilog(union efi_saved_pgd saved_pgd);
 extern void __init efi_print_memmap(void);
 extern void __init efi_memory_uc(u64 addr, unsigned long size);
 extern void __init efi_map_region(efi_memory_desc_t *md);
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 565dff3..217dc16 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -81,9 +81,9 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
 {
efi_status_t status;
unsigned long flags;
-   pgd_t *save_pgd;
+   union efi_saved_pgd saved_pgd;
 
-   save_pgd = efi_call_phys_prolog();
+   saved_pgd = efi_call_phys_prolog();
 
/* Disable interrupts around EFI calls: */
local_irq_save(flags);
@@ -92,7 +92,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
   descriptor_version, virtual_map);
local_irq_restore(flags);
 
-   efi_call_phys_epilog(save_pgd);
+   efi_call_phys_epilog(saved_pgd);
 
return status;
 }
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c
index cef39b0..9b1abcf 100644
--- a/arch/x86/platform/efi/efi_32.c
+++ b/arch/x86/platform/efi/efi_32.c
@@ -58,13 +58,13 @@ void __init efi_map_region(efi_memory_desc_t *md)
 void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
 void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
 
-pgd_t * __init efi_call_phys_prolog(void)
+union efi_saved_pgd __init efi_call_phys_prolog(void)
 {
struct desc_ptr gdt_descr;
-   pgd_t *save_pgd;
+   union efi_saved_pgd saved_pgd;
 
/* Current pgd is swapper_pg_dir, we'll restore it later: */
-   save_pgd = swapper_pg_dir;
+   saved_pgd.cr3 = __pa(swapper_pg_dir);
load_cr3(initial_page_table);
__flush_tlb_all();
 
@@ -72,10 +72,10 @@ pgd_t * __init efi_call_phys_prolog(void)
gdt_descr.size = GDT_SIZE - 1;
load_gdt(_descr);
 
-   return save_pgd;
+   return saved_pgd;
 }
 
-void __init efi_call_phys_epilog(pgd_t *save_pgd)
+void __init efi_call_phys_epilog(union efi_saved_pgd saved_pgd)
 {
struct desc_ptr gdt_descr;
 
@@ -83,7 +83,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
gdt_descr.size = GDT_SIZE - 1;
load_gdt(_descr);
 
-   load_cr3(save_pgd);
+   write_cr3(saved_pgd.cr3);
__flush_tlb_all();
 }
 
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index a4695da..d56dd864 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -69,16 +69,16 @@ static void __init 

[tip:efi/core] x86/efi: Clean up the EFI CR3 save/restore logic

2017-04-05 Thread tip-bot for Andy Lutomirski
Commit-ID:  05dd61fa7ff73678c33d252aa9f989634349c791
Gitweb: http://git.kernel.org/tip/05dd61fa7ff73678c33d252aa9f989634349c791
Author: Andy Lutomirski 
AuthorDate: Tue, 4 Apr 2017 17:02:36 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:48 +0200

x86/efi: Clean up the EFI CR3 save/restore logic

efi_call_phys_prolog() used to return a "pgd_t *" that meant one of
three different things depending on kernel and system configuration.

Clean it up so it uses a union and is more explicit about what's
going on.

Signed-off-by: Andy Lutomirski 
Signed-off-by: Matt Fleming 
Signed-off-by: Ard Biesheuvel 
Cc: Andy Lutomirski 
Cc: Borislav Petkov 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-3-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 arch/x86/include/asm/efi.h | 17 +++--
 arch/x86/platform/efi/efi.c|  6 +++---
 arch/x86/platform/efi/efi_32.c | 12 ++--
 arch/x86/platform/efi/efi_64.c | 22 --
 4 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 2f77bce..0859ed7 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -111,11 +111,24 @@ extern void __iomem *__init efi_ioremap(unsigned long 
addr, unsigned long size,
 
 #endif /* CONFIG_X86_32 */
 
+union efi_saved_pgd {
+   /*
+* If !EFI_OLD_MEMMAP or we're 32-bit, this is a verbatim saved CR3
+* value:
+*/
+   unsigned long cr3;
+
+#ifdef CONFIG_X86_64
+   /* If EFI_OLD_MEMMAP, this is a kmalloc()ed copy of the pgd: */
+   pgd_t *pgd;
+#endif
+};
+
 extern struct efi_scratch efi_scratch;
 extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int __init efi_memblock_x86_reserve_range(void);
-extern pgd_t * __init efi_call_phys_prolog(void);
-extern void __init efi_call_phys_epilog(pgd_t *save_pgd);
+extern union efi_saved_pgd __init efi_call_phys_prolog(void);
+extern void __init efi_call_phys_epilog(union efi_saved_pgd saved_pgd);
 extern void __init efi_print_memmap(void);
 extern void __init efi_memory_uc(u64 addr, unsigned long size);
 extern void __init efi_map_region(efi_memory_desc_t *md);
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 565dff3..217dc16 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -81,9 +81,9 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
 {
efi_status_t status;
unsigned long flags;
-   pgd_t *save_pgd;
+   union efi_saved_pgd saved_pgd;
 
-   save_pgd = efi_call_phys_prolog();
+   saved_pgd = efi_call_phys_prolog();
 
/* Disable interrupts around EFI calls: */
local_irq_save(flags);
@@ -92,7 +92,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
   descriptor_version, virtual_map);
local_irq_restore(flags);
 
-   efi_call_phys_epilog(save_pgd);
+   efi_call_phys_epilog(saved_pgd);
 
return status;
 }
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c
index cef39b0..9b1abcf 100644
--- a/arch/x86/platform/efi/efi_32.c
+++ b/arch/x86/platform/efi/efi_32.c
@@ -58,13 +58,13 @@ void __init efi_map_region(efi_memory_desc_t *md)
 void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
 void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
 
-pgd_t * __init efi_call_phys_prolog(void)
+union efi_saved_pgd __init efi_call_phys_prolog(void)
 {
struct desc_ptr gdt_descr;
-   pgd_t *save_pgd;
+   union efi_saved_pgd saved_pgd;
 
/* Current pgd is swapper_pg_dir, we'll restore it later: */
-   save_pgd = swapper_pg_dir;
+   saved_pgd.cr3 = __pa(swapper_pg_dir);
load_cr3(initial_page_table);
__flush_tlb_all();
 
@@ -72,10 +72,10 @@ pgd_t * __init efi_call_phys_prolog(void)
gdt_descr.size = GDT_SIZE - 1;
load_gdt(_descr);
 
-   return save_pgd;
+   return saved_pgd;
 }
 
-void __init efi_call_phys_epilog(pgd_t *save_pgd)
+void __init efi_call_phys_epilog(union efi_saved_pgd saved_pgd)
 {
struct desc_ptr gdt_descr;
 
@@ -83,7 +83,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
gdt_descr.size = GDT_SIZE - 1;
load_gdt(_descr);
 
-   load_cr3(save_pgd);
+   write_cr3(saved_pgd.cr3);
__flush_tlb_all();
 }
 
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index a4695da..d56dd864 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -69,16 +69,16 @@ static void __init early_code_mapping_set_exec(int 
executable)
}
 }
 
-pgd_t * __init efi_call_phys_prolog(void)
+union efi_saved_pgd __init efi_call_phys_prolog(void)
 {
unsigned long vaddress;
-   pgd_t *save_pgd;
+   union efi_saved_pgd