[linux] 01/01: [x86] efi-bgrt: Fix kernel panic when mapping BGRT data (Closes: #815125)

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Sun Feb 21 03:31:31 UTC 2016


This is an automated email from the git hooks/post-receive script.

benh pushed a commit to branch sid
in repository linux.

commit 88d259a75c05e46ce19dd31cf037627d6fb572d4
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Sat Feb 20 23:24:53 2016 +0000

    [x86] efi-bgrt: Fix kernel panic when mapping BGRT data (Closes: #815125)
    
    Plus the following fix-up.
---
 debian/changelog                                   |   7 +
 ...t-fix-kernel-panic-when-mapping-bgrt-data.patch | 180 +++++++++++++++++++++
 ...bgrt-replace-early_memremap-with-memremap.patch |  92 +++++++++++
 debian/patches/series                              |   2 +
 4 files changed, 281 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 9628e6f..79499b6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+linux (4.4.2-3) UNRELEASED; urgency=medium
+
+  * [x86] efi-bgrt: Fix kernel panic when mapping BGRT data (Closes: #815125)
+  * [x86] efi-bgrt: Replace early_memremap() with memremap()
+
+ -- Ben Hutchings <ben at decadent.org.uk>  Sat, 20 Feb 2016 23:24:00 +0000
+
 linux (4.4.2-2) unstable; urgency=medium
 
   [ Ben Hutchings ]
diff --git a/debian/patches/bugfix/x86/x86-efi-bgrt-fix-kernel-panic-when-mapping-bgrt-data.patch b/debian/patches/bugfix/x86/x86-efi-bgrt-fix-kernel-panic-when-mapping-bgrt-data.patch
new file mode 100644
index 0000000..bcba95b
--- /dev/null
+++ b/debian/patches/bugfix/x86/x86-efi-bgrt-fix-kernel-panic-when-mapping-bgrt-data.patch
@@ -0,0 +1,180 @@
+From: Sai Praneeth <sai.praneeth.prakhya at intel.com>
+Date: Wed, 9 Dec 2015 15:41:08 -0800
+Subject: x86/efi-bgrt: Fix kernel panic when mapping BGRT data
+Origin: https://git.kernel.org/cgit/linux/kernel/git/mfleming/efi.git/commit?id=50a0cb565246f20d59cdb161778531e4b19d35ac
+Bug-Debian: https://bugs.debian.org/815125
+
+Starting with this commit 35eb8b81edd4 ("x86/efi: Build our own page
+table structures") efi regions have a separate page directory called
+"efi_pgd". In order to access any efi region we have to first shift %cr3
+to this page table. In the bgrt code we are trying to copy bgrt_header
+and image, but these regions fall under "EFI_BOOT_SERVICES_DATA"
+and to access these regions we have to shift %cr3 to efi_pgd and not
+doing so will cause page fault as shown below.
+
+[    0.251599] Last level dTLB entries: 4KB 64, 2MB 0, 4MB 0, 1GB 4
+[    0.259126] Freeing SMP alternatives memory: 32K (ffffffff8230e000 - ffffffff82316000)
+[    0.271803] BUG: unable to handle kernel paging request at fffffffefce35002
+[    0.279740] IP: [<ffffffff821bca49>] efi_bgrt_init+0x144/0x1fd
+[    0.286383] PGD 300f067 PUD 0
+[    0.289879] Oops: 0000 [#1] SMP
+[    0.293566] Modules linked in:
+[    0.297039] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.4.0-rc1-eywa-eywa-built-in-47041+ #2
+[    0.306619] Hardware name: Intel Corporation Skylake Client platform/Skylake Y LPDDR3 RVP3, BIOS SKLSE2R1.R00.B104.B01.1511110114 11/11/2015
+[    0.320925] task: ffffffff820134c0 ti: ffffffff82000000 task.ti: ffffffff82000000
+[    0.329420] RIP: 0010:[<ffffffff821bca49>]  [<ffffffff821bca49>] efi_bgrt_init+0x144/0x1fd
+[    0.338821] RSP: 0000:ffffffff82003f18  EFLAGS: 00010246
+[    0.344852] RAX: fffffffefce35000 RBX: fffffffefce35000 RCX: fffffffefce2b000
+[    0.352952] RDX: 000000008a82b000 RSI: ffffffff8235bb80 RDI: 000000008a835000
+[    0.361050] RBP: ffffffff82003f30 R08: 000000008a865000 R09: ffffffffff202850
+[    0.369149] R10: ffffffff811ad62f R11: 0000000000000000 R12: 0000000000000000
+[    0.377248] R13: ffff88016dbaea40 R14: ffffffff822622c0 R15: ffffffff82003fb0
+[    0.385348] FS:  0000000000000000(0000) GS:ffff88016d800000(0000) knlGS:0000000000000000
+[    0.394533] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[    0.401054] CR2: fffffffefce35002 CR3: 000000000300c000 CR4: 00000000003406f0
+[    0.409153] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[    0.417252] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[    0.425350] Stack:
+[    0.427638]  ffffffffffffffff ffffffff82256900 ffff88016dbaea40 ffffffff82003f40
+[    0.436086]  ffffffff821bbce0 ffffffff82003f88 ffffffff8219c0c2 0000000000000000
+[    0.444533]  ffffffff8219ba4a ffffffff822622c0 0000000000083000 00000000ffffffff
+[    0.452978] Call Trace:
+[    0.455763]  [<ffffffff821bbce0>] efi_late_init+0x9/0xb
+[    0.461697]  [<ffffffff8219c0c2>] start_kernel+0x463/0x47f
+[    0.467928]  [<ffffffff8219ba4a>] ? set_init_arg+0x55/0x55
+[    0.474159]  [<ffffffff8219b120>] ? early_idt_handler_array+0x120/0x120
+[    0.481669]  [<ffffffff8219b5ee>] x86_64_start_reservations+0x2a/0x2c
+[    0.488982]  [<ffffffff8219b72d>] x86_64_start_kernel+0x13d/0x14c
+[    0.495897] Code: 00 41 b4 01 48 8b 78 28 e8 09 36 01 00 48 85 c0 48 89 c3 75 13 48 c7 c7 f8 ac d3 81 31 c0 e8 d7 3b fb fe e9 b5 00 00 00 45 84 e4 <44> 8b 6b 02 74 0d be 06 00 00 00 48 89 df e8 ae 34 0$
+[    0.518151] RIP  [<ffffffff821bca49>] efi_bgrt_init+0x144/0x1fd
+[    0.524888]  RSP <ffffffff82003f18>
+[    0.528851] CR2: fffffffefce35002
+[    0.532615] ---[ end trace 7b06521e6ebf2aea ]---
+[    0.537852] Kernel panic - not syncing: Attempted to kill the idle task!
+
+As said above one way to fix this bug is to shift %cr3 to efi_pgd but we
+are not doing that way because it leaks inner details of how we switch
+to EFI page tables into a new call site and it also adds duplicate code.
+Instead, we remove the call to efi_lookup_mapped_addr() and always
+perform early_mem*() instead of early_io*() because we want to remap RAM
+regions and not I/O regions. We also delete efi_lookup_mapped_addr()
+because we are no longer using it.
+
+Signed-off-by: Sai Praneeth Prakhya <sai.praneeth.prakhya at intel.com>
+Reported-by: Wendy Wang <wendy.wang at intel.com>
+Cc: Borislav Petkov <bp at suse.de>
+Cc: Josh Triplett <josh at joshtriplett.org>
+Cc: Ricardo Neri <ricardo.neri at intel.com>
+Cc: Ravi Shankar <ravi.v.shankar at intel.com>
+Signed-off-by: Matt Fleming <matt at codeblueprint.co.uk>
+---
+ arch/x86/platform/efi/efi-bgrt.c | 39 ++++++++++++++-------------------------
+ drivers/firmware/efi/efi.c       | 32 --------------------------------
+ 2 files changed, 14 insertions(+), 57 deletions(-)
+
+--- a/arch/x86/platform/efi/efi-bgrt.c
++++ b/arch/x86/platform/efi/efi-bgrt.c
+@@ -28,8 +28,7 @@ struct bmp_header {
+ void __init efi_bgrt_init(void)
+ {
+ 	acpi_status status;
+-	void __iomem *image;
+-	bool ioremapped = false;
++	void *image;
+ 	struct bmp_header bmp_header;
+ 
+ 	if (acpi_disabled)
+@@ -70,20 +69,14 @@ void __init efi_bgrt_init(void)
+ 		return;
+ 	}
+ 
+-	image = efi_lookup_mapped_addr(bgrt_tab->image_address);
++	image = early_memremap(bgrt_tab->image_address, sizeof(bmp_header));
+ 	if (!image) {
+-		image = early_ioremap(bgrt_tab->image_address,
+-				       sizeof(bmp_header));
+-		ioremapped = true;
+-		if (!image) {
+-			pr_err("Ignoring BGRT: failed to map image header memory\n");
+-			return;
+-		}
++		pr_err("Ignoring BGRT: failed to map image header memory\n");
++		return;
+ 	}
+ 
+-	memcpy_fromio(&bmp_header, image, sizeof(bmp_header));
+-	if (ioremapped)
+-		early_iounmap(image, sizeof(bmp_header));
++	memcpy(&bmp_header, image, sizeof(bmp_header));
++	early_memunmap(image, sizeof(bmp_header));
+ 	bgrt_image_size = bmp_header.size;
+ 
+ 	bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN);
+@@ -93,18 +86,14 @@ void __init efi_bgrt_init(void)
+ 		return;
+ 	}
+ 
+-	if (ioremapped) {
+-		image = early_ioremap(bgrt_tab->image_address,
+-				       bmp_header.size);
+-		if (!image) {
+-			pr_err("Ignoring BGRT: failed to map image memory\n");
+-			kfree(bgrt_image);
+-			bgrt_image = NULL;
+-			return;
+-		}
++	image = early_memremap(bgrt_tab->image_address, bmp_header.size);
++	if (!image) {
++		pr_err("Ignoring BGRT: failed to map image memory\n");
++		kfree(bgrt_image);
++		bgrt_image = NULL;
++		return;
+ 	}
+ 
+-	memcpy_fromio(bgrt_image, image, bgrt_image_size);
+-	if (ioremapped)
+-		early_iounmap(image, bmp_header.size);
++	memcpy(bgrt_image, image, bgrt_image_size);
++	early_memunmap(image, bmp_header.size);
+ }
+--- a/drivers/firmware/efi/efi.c
++++ b/drivers/firmware/efi/efi.c
+@@ -324,38 +324,6 @@ u64 __init efi_mem_desc_end(efi_memory_d
+ 	return end;
+ }
+ 
+-/*
+- * We can't ioremap data in EFI boot services RAM, because we've already mapped
+- * it as RAM.  So, look it up in the existing EFI memory map instead.  Only
+- * callable after efi_enter_virtual_mode and before efi_free_boot_services.
+- */
+-void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
+-{
+-	struct efi_memory_map *map;
+-	void *p;
+-	map = efi.memmap;
+-	if (!map)
+-		return NULL;
+-	if (WARN_ON(!map->map))
+-		return NULL;
+-	for (p = map->map; p < map->map_end; p += map->desc_size) {
+-		efi_memory_desc_t *md = p;
+-		u64 size = md->num_pages << EFI_PAGE_SHIFT;
+-		u64 end = md->phys_addr + size;
+-		if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
+-		    md->type != EFI_BOOT_SERVICES_CODE &&
+-		    md->type != EFI_BOOT_SERVICES_DATA)
+-			continue;
+-		if (!md->virt_addr)
+-			continue;
+-		if (phys_addr >= md->phys_addr && phys_addr < end) {
+-			phys_addr += md->virt_addr - md->phys_addr;
+-			return (__force void __iomem *)(unsigned long)phys_addr;
+-		}
+-	}
+-	return NULL;
+-}
+-
+ static __initdata efi_config_table_type_t common_tables[] = {
+ 	{ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
+ 	{ACPI_TABLE_GUID, "ACPI", &efi.acpi},
diff --git a/debian/patches/bugfix/x86/x86-efi-bgrt-replace-early_memremap-with-memremap.patch b/debian/patches/bugfix/x86/x86-efi-bgrt-replace-early_memremap-with-memremap.patch
new file mode 100644
index 0000000..e695fd9
--- /dev/null
+++ b/debian/patches/bugfix/x86/x86-efi-bgrt-replace-early_memremap-with-memremap.patch
@@ -0,0 +1,92 @@
+From: Matt Fleming <matt at codeblueprint.co.uk>
+Date: Mon, 21 Dec 2015 14:12:52 +0000
+Subject: x86/efi-bgrt: Replace early_memremap() with memremap()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://git.kernel.org/cgit/linux/kernel/git/mfleming/efi.git/commit?id=e2c90dd7e11e3025b46719a79fb4bb1e7a5cef9f
+Bug-Debian: https://bugs.debian.org/815125
+
+Môshe reported the following warning triggered on his machine since
+commit 50a0cb565246 ("x86/efi-bgrt: Fix kernel panic when mapping BGRT
+data"),
+
+  [    0.026936] ------------[ cut here ]------------
+  [    0.026941] WARNING: CPU: 0 PID: 0 at mm/early_ioremap.c:137 __early_ioremap+0x102/0x1bb()
+  [    0.026941] Modules linked in:
+  [    0.026944] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.4.0-rc1 #2
+  [    0.026945] Hardware name: Dell Inc. XPS 13 9343/09K8G1, BIOS A05 07/14/2015
+  [    0.026946]  0000000000000000 900f03d5a116524d ffffffff81c03e60 ffffffff813a3fff
+  [    0.026948]  0000000000000000 ffffffff81c03e98 ffffffff810a0852 00000000d7b76000
+  [    0.026949]  0000000000000000 0000000000000001 0000000000000001 000000000000017c
+  [    0.026951] Call Trace:
+  [    0.026955]  [<ffffffff813a3fff>] dump_stack+0x44/0x55
+  [    0.026958]  [<ffffffff810a0852>] warn_slowpath_common+0x82/0xc0
+  [    0.026959]  [<ffffffff810a099a>] warn_slowpath_null+0x1a/0x20
+  [    0.026961]  [<ffffffff81d8c395>] __early_ioremap+0x102/0x1bb
+  [    0.026962]  [<ffffffff81d8c602>] early_memremap+0x13/0x15
+  [    0.026964]  [<ffffffff81d78361>] efi_bgrt_init+0x162/0x1ad
+  [    0.026966]  [<ffffffff81d778ec>] efi_late_init+0x9/0xb
+  [    0.026968]  [<ffffffff81d58ff5>] start_kernel+0x46f/0x49f
+  [    0.026970]  [<ffffffff81d58120>] ? early_idt_handler_array+0x120/0x120
+  [    0.026972]  [<ffffffff81d58339>] x86_64_start_reservations+0x2a/0x2c
+  [    0.026974]  [<ffffffff81d58485>] x86_64_start_kernel+0x14a/0x16d
+  [    0.026977] ---[ end trace f9b3812eb8e24c58 ]---
+  [    0.026978] efi_bgrt: Ignoring BGRT: failed to map image memory
+
+early_memremap() has an upper limit on the size of mapping it can
+handle which is ~200KB. Clearly the BGRT image on Môshe's machine is
+much larger than that.
+
+There's actually no reason to restrict ourselves to using the early_*
+version of memremap() - the ACPI BGRT driver is invoked late enough in
+boot that we can use the standard version, with the benefit that the
+late version allows mappings of arbitrary size.
+
+Reported-by: Môshe van der Sterre <me at moshe.nl>
+Tested-by: Môshe van der Sterre <me at moshe.nl>
+Signed-off-by: Matt Fleming <matt at codeblueprint.co.uk>
+Cc: Josh Triplett <josh at joshtriplett.org>
+Cc: Sai Praneeth Prakhya <sai.praneeth.prakhya at intel.com>
+Cc: Borislav Petkov <bp at suse.de>
+Link: http://lkml.kernel.org/r/1450707172-12561-1-git-send-email-matt@codeblueprint.co.uk
+Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
+---
+ arch/x86/platform/efi/efi-bgrt.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/x86/platform/efi/efi-bgrt.c
++++ b/arch/x86/platform/efi/efi-bgrt.c
+@@ -69,14 +69,14 @@ void __init efi_bgrt_init(void)
+ 		return;
+ 	}
+ 
+-	image = early_memremap(bgrt_tab->image_address, sizeof(bmp_header));
++	image = memremap(bgrt_tab->image_address, sizeof(bmp_header), MEMREMAP_WB);
+ 	if (!image) {
+ 		pr_err("Ignoring BGRT: failed to map image header memory\n");
+ 		return;
+ 	}
+ 
+ 	memcpy(&bmp_header, image, sizeof(bmp_header));
+-	early_memunmap(image, sizeof(bmp_header));
++	memunmap(image);
+ 	bgrt_image_size = bmp_header.size;
+ 
+ 	bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN);
+@@ -86,7 +86,7 @@ void __init efi_bgrt_init(void)
+ 		return;
+ 	}
+ 
+-	image = early_memremap(bgrt_tab->image_address, bmp_header.size);
++	image = memremap(bgrt_tab->image_address, bmp_header.size, MEMREMAP_WB);
+ 	if (!image) {
+ 		pr_err("Ignoring BGRT: failed to map image memory\n");
+ 		kfree(bgrt_image);
+@@ -95,5 +95,5 @@ void __init efi_bgrt_init(void)
+ 	}
+ 
+ 	memcpy(bgrt_image, image, bgrt_image_size);
+-	early_memunmap(image, bmp_header.size);
++	memunmap(image);
+ }
diff --git a/debian/patches/series b/debian/patches/series
index ec1bad3..971ac10 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -130,3 +130,5 @@ bugfix/x86/x86-mm-fix-types-used-in-pgprot-cacheability-flags-t.patch
 debian/i386-686-pae-pci-set-pci-nobios-by-default.patch
 bugfix/all/iff_no_queue-fix-for-drivers-not-calling-ether_setup.patch
 bugfix/arm/net-mv643xx_eth-fix-packet-corruption-with-tso-and-t.patch
+bugfix/x86/x86-efi-bgrt-fix-kernel-panic-when-mapping-bgrt-data.patch
+bugfix/x86/x86-efi-bgrt-replace-early_memremap-with-memremap.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list