From: Laszlo Ersek <lersek@redhat.com> To: Borislav Petkov <bp@alien8.de> Cc: edk2-devel@lists.sourceforge.net, David Woodhouse <dwmw2@infradead.org>, linux-efi@vger.kernel.org, lkml <linux-kernel@vger.kernel.org>, Gleb Natapov <gleb@redhat.com>, Matthew Garrett <mjg59@srcf.ucam.org>, Matt Fleming <matt@console-pimps.org>, "Jordan Justen (Intel address)" <jordan.l.justen@intel.com> Subject: Re: [edk2] Corrupted EFI region Date: Wed, 07 Aug 2013 19:49:16 +0200 [thread overview] Message-ID: <5202889C.2080608@redhat.com> (raw) In-Reply-To: <20130807151935.GJ17920@pd.tnic> [-- Attachment #1: Type: text/plain, Size: 4476 bytes --] On 08/07/13 17:19, Borislav Petkov wrote: > On Tue, Aug 06, 2013 at 05:31:29PM +0200, Laszlo Ersek wrote: >> Can you capture the OVMF debug output? Do you see >> >> ConvertPages: Incompatible memory types >> >> there? >> >> Can you set the following bits too in the debug mask? >> >> #define DEBUG_POOL 0x00000010 // Alloc & Free's >> #define DEBUG_PAGE 0x00000020 // Alloc & Free's > > Ok, I got debug output; I have to be careful now of not missing > anything. Ok, so here we go: > > First of all, I changed debugging mask to: > > gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8010007F > > (I just set all three bits you requested). > > Using the new OVMF.id changed the addresses, of course, so we're looking > at 0x7dc59XXX ones now. > > [ 0.000000] memblock_reserve: [0x0000007dc59018-0x0000007dc59618] efi_memblock_x86_reserve_range+0x70/0x75 > > So, I've attached an archive of the debug logs. The initial observations > I could do is that the region still gets "squashed" to: > > [ 0.014041] efi: mem11: type=4, attr=0xf, range=[0x000000007dc59000-0x000000007dc59000) (0MB) > > from > > [ 0.000000] efi: mem11: type=4, attr=0xf, range=[0x000000007dc59000-0x000000007e146000) (4MB) > > And the interesting stuff in the OVMF output is right at the end: > > ConvertRange: 7DC59000-7DC5AFFF to 4 > AddRange: 7DC59000-7DC5AFFF to 4 > AllocatePoolI: Type 4, Addr 7DC59018 (len 16F0) 26,735,072 > Jumping to kernel > > We get that same output no matter if I boot it with "-enable-kvm" or > not. > > If the order of the debug messages is the same as the calls actually > happen, we AllocatePoolI to address 7DC59018 which we already have added > as a range. But I'm not going to pretend I even know the code so I'll > let you comment instead :). I think this allows us to solve the bug :) First, forget everything I said :) I was completely lost. Remember this? 01 efi_main() 02 exit_boot() 03 low_alloc() 04 GetMemoryMap() 05 ExitBootServices() 06 07 start_kernel() 08 setup_arch() 09 efi_memblock_x86_reserve_range() 10 efi_reserve_boot_services() 11 efi_enter_virtual_mode() 12 SetVirtualAddressMap() Now, lines 01 to 05 *do not happen*. More precisely, they don't happen in the kernel. They happen in the firmware. Specifically, "OvmfPkg/Library/LoadLinuxLib/Linux.c". You're booting the kernel from the qemu command line. The kernel you run is also an "[o]ld kernel[] without EFI handover protocol". So what happens is, OVMF downloads the kernel image from qemu over fw_cfg, figures it's an old kernel... PlatformBdsPolicyBehavior() [OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c] // Process QEMU's -kernel command line option: TryRunningQemuKernel() [OvmfPkg/Library/PlatformBdsLib/QemuKernel.c] LoadLinux() [OvmfPkg/Library/LoadLinuxLib/Linux.c] // Old kernels without EFI handover protocol SetupLinuxBootParams() SetupLinuxMemmap() AllocatePool() <-------------- !!! gBS->GetMemoryMap() gBS->ExitBootServices() prints "Jumping to kernel" JumpToKernel() Now pull up efi_memblock_x86_reserve_range(). It reserves "boot_params.efi_info->efi_memmap". I assumed this field would come from the exit_boot() kernel function. It doesn't. It comes from SetupLinuxMemmap(). The former allocates the backing store as EFI_LOADER_DATA. The latter, alas, marked with !!! above, as boot services data. :) So, what you're seeing in the OVMF debug log: > ConvertRange: 7DC59000-7DC5AFFF to 4 > AddRange: 7DC59000-7DC5AFFF to 4 > AllocatePoolI: Type 4, Addr 7DC59018 (len 16F0) 26,735,072 This is self-consistent. It just documents that the AllocatePool() call marked with !!! needs to grab two full pages first (two first lines), carve them up into pool chunks, and then serve the request from them (third line). The address displayed here shows up in the linux dmesg later on because the storage for the memory map itself is allocated, and populated, by OVMF, not the EFI stub in the kernel. In one sentence, efi_memblock_x86_reserve_range() expects that "boot_params.efi_info->efi_memmap" has been allocated as "loader data" (by whomever), but SetupLinuxMemmap() violates this by allocating the storage as "boot services data". This leads to double reservation attempts between efi_memblock_x86_reserve_range(), and efi_reserve_boot_services(). The attached edk2 patch should fix it. Please confirm. Thanks, Laszlo [-- Attachment #2: 0001-OvmfPkg-allocate-the-EFI-memory-map-for-Linux-as-Loa.patch --] [-- Type: text/plain, Size: 1729 bytes --] From 4a9e1f10fa2d06496f1983c25c47c6a1373d2f42 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek <lersek@redhat.com> Date: Wed, 7 Aug 2013 19:39:30 +0200 Subject: [PATCH] OvmfPkg: allocate the EFI memory map for Linux as Loader Data In Linux, efi_memblock_x86_reserve_range() and efi_reserve_boot_services() expect that whoever allocates the EFI memmap allocates it in Loader Data type memory. Linux's own exit_boot()-->low_alloc() complies, but SetupLinuxMemmap() in LoadLinuxLib doesn't. The memory type discrepancy leads to efi_memblock_x86_reserve_range() and efi_reserve_boot_services() both trying to reserve the range backing the memmap, resulting in memmap entry truncation in efi_reserve_boot_services(). This fix also makes this allocation consistent with all other persistent allocations in "OvmfPkg/Library/LoadLinuxLib/Linux.c". Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> --- OvmfPkg/Library/LoadLinuxLib/Linux.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/Library/LoadLinuxLib/Linux.c b/OvmfPkg/Library/LoadLinuxLib/Linux.c index cd673aa..4a3e2c1 100644 --- a/OvmfPkg/Library/LoadLinuxLib/Linux.c +++ b/OvmfPkg/Library/LoadLinuxLib/Linux.c @@ -280,8 +280,12 @@ SetupLinuxMemmap ( // Enlarge space here, because we will allocate pool now. // MemoryMapSize += EFI_PAGE_SIZE; - MemoryMap = AllocatePool (MemoryMapSize); - ASSERT (MemoryMap != NULL); + Status = gBS->AllocatePool ( + EfiLoaderData, + MemoryMapSize, + (VOID **) &MemoryMap + ); + ASSERT_EFI_ERROR (Status); // // Get System MemoryMap -- 1.7.1
WARNING: multiple messages have this Message-ID (diff)
From: Laszlo Ersek <lersek-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> To: Borislav Petkov <bp-Gina5bIWoIWzQB+pC5nmwQ@public.gmane.org> Cc: edk2-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org, David Woodhouse <dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>, linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, lkml <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>, Gleb Natapov <gleb-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>, Matthew Garrett <mjg59-1xO5oi07KQx4cg9Nei1l7Q@public.gmane.org>, Matt Fleming <matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>, "Jordan Justen (Intel address)" <jordan.l.justen-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> Subject: Re: [edk2] Corrupted EFI region Date: Wed, 07 Aug 2013 19:49:16 +0200 [thread overview] Message-ID: <5202889C.2080608@redhat.com> (raw) In-Reply-To: <20130807151935.GJ17920-fF5Pk5pvG8Y@public.gmane.org> [-- Attachment #1: Type: text/plain, Size: 4476 bytes --] On 08/07/13 17:19, Borislav Petkov wrote: > On Tue, Aug 06, 2013 at 05:31:29PM +0200, Laszlo Ersek wrote: >> Can you capture the OVMF debug output? Do you see >> >> ConvertPages: Incompatible memory types >> >> there? >> >> Can you set the following bits too in the debug mask? >> >> #define DEBUG_POOL 0x00000010 // Alloc & Free's >> #define DEBUG_PAGE 0x00000020 // Alloc & Free's > > Ok, I got debug output; I have to be careful now of not missing > anything. Ok, so here we go: > > First of all, I changed debugging mask to: > > gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8010007F > > (I just set all three bits you requested). > > Using the new OVMF.id changed the addresses, of course, so we're looking > at 0x7dc59XXX ones now. > > [ 0.000000] memblock_reserve: [0x0000007dc59018-0x0000007dc59618] efi_memblock_x86_reserve_range+0x70/0x75 > > So, I've attached an archive of the debug logs. The initial observations > I could do is that the region still gets "squashed" to: > > [ 0.014041] efi: mem11: type=4, attr=0xf, range=[0x000000007dc59000-0x000000007dc59000) (0MB) > > from > > [ 0.000000] efi: mem11: type=4, attr=0xf, range=[0x000000007dc59000-0x000000007e146000) (4MB) > > And the interesting stuff in the OVMF output is right at the end: > > ConvertRange: 7DC59000-7DC5AFFF to 4 > AddRange: 7DC59000-7DC5AFFF to 4 > AllocatePoolI: Type 4, Addr 7DC59018 (len 16F0) 26,735,072 > Jumping to kernel > > We get that same output no matter if I boot it with "-enable-kvm" or > not. > > If the order of the debug messages is the same as the calls actually > happen, we AllocatePoolI to address 7DC59018 which we already have added > as a range. But I'm not going to pretend I even know the code so I'll > let you comment instead :). I think this allows us to solve the bug :) First, forget everything I said :) I was completely lost. Remember this? 01 efi_main() 02 exit_boot() 03 low_alloc() 04 GetMemoryMap() 05 ExitBootServices() 06 07 start_kernel() 08 setup_arch() 09 efi_memblock_x86_reserve_range() 10 efi_reserve_boot_services() 11 efi_enter_virtual_mode() 12 SetVirtualAddressMap() Now, lines 01 to 05 *do not happen*. More precisely, they don't happen in the kernel. They happen in the firmware. Specifically, "OvmfPkg/Library/LoadLinuxLib/Linux.c". You're booting the kernel from the qemu command line. The kernel you run is also an "[o]ld kernel[] without EFI handover protocol". So what happens is, OVMF downloads the kernel image from qemu over fw_cfg, figures it's an old kernel... PlatformBdsPolicyBehavior() [OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c] // Process QEMU's -kernel command line option: TryRunningQemuKernel() [OvmfPkg/Library/PlatformBdsLib/QemuKernel.c] LoadLinux() [OvmfPkg/Library/LoadLinuxLib/Linux.c] // Old kernels without EFI handover protocol SetupLinuxBootParams() SetupLinuxMemmap() AllocatePool() <-------------- !!! gBS->GetMemoryMap() gBS->ExitBootServices() prints "Jumping to kernel" JumpToKernel() Now pull up efi_memblock_x86_reserve_range(). It reserves "boot_params.efi_info->efi_memmap". I assumed this field would come from the exit_boot() kernel function. It doesn't. It comes from SetupLinuxMemmap(). The former allocates the backing store as EFI_LOADER_DATA. The latter, alas, marked with !!! above, as boot services data. :) So, what you're seeing in the OVMF debug log: > ConvertRange: 7DC59000-7DC5AFFF to 4 > AddRange: 7DC59000-7DC5AFFF to 4 > AllocatePoolI: Type 4, Addr 7DC59018 (len 16F0) 26,735,072 This is self-consistent. It just documents that the AllocatePool() call marked with !!! needs to grab two full pages first (two first lines), carve them up into pool chunks, and then serve the request from them (third line). The address displayed here shows up in the linux dmesg later on because the storage for the memory map itself is allocated, and populated, by OVMF, not the EFI stub in the kernel. In one sentence, efi_memblock_x86_reserve_range() expects that "boot_params.efi_info->efi_memmap" has been allocated as "loader data" (by whomever), but SetupLinuxMemmap() violates this by allocating the storage as "boot services data". This leads to double reservation attempts between efi_memblock_x86_reserve_range(), and efi_reserve_boot_services(). The attached edk2 patch should fix it. Please confirm. Thanks, Laszlo [-- Attachment #2: 0001-OvmfPkg-allocate-the-EFI-memory-map-for-Linux-as-Loa.patch --] [-- Type: text/plain, Size: 1729 bytes --] From 4a9e1f10fa2d06496f1983c25c47c6a1373d2f42 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek <lersek@redhat.com> Date: Wed, 7 Aug 2013 19:39:30 +0200 Subject: [PATCH] OvmfPkg: allocate the EFI memory map for Linux as Loader Data In Linux, efi_memblock_x86_reserve_range() and efi_reserve_boot_services() expect that whoever allocates the EFI memmap allocates it in Loader Data type memory. Linux's own exit_boot()-->low_alloc() complies, but SetupLinuxMemmap() in LoadLinuxLib doesn't. The memory type discrepancy leads to efi_memblock_x86_reserve_range() and efi_reserve_boot_services() both trying to reserve the range backing the memmap, resulting in memmap entry truncation in efi_reserve_boot_services(). This fix also makes this allocation consistent with all other persistent allocations in "OvmfPkg/Library/LoadLinuxLib/Linux.c". Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> --- OvmfPkg/Library/LoadLinuxLib/Linux.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/Library/LoadLinuxLib/Linux.c b/OvmfPkg/Library/LoadLinuxLib/Linux.c index cd673aa..4a3e2c1 100644 --- a/OvmfPkg/Library/LoadLinuxLib/Linux.c +++ b/OvmfPkg/Library/LoadLinuxLib/Linux.c @@ -280,8 +280,12 @@ SetupLinuxMemmap ( // Enlarge space here, because we will allocate pool now. // MemoryMapSize += EFI_PAGE_SIZE; - MemoryMap = AllocatePool (MemoryMapSize); - ASSERT (MemoryMap != NULL); + Status = gBS->AllocatePool ( + EfiLoaderData, + MemoryMapSize, + (VOID **) &MemoryMap + ); + ASSERT_EFI_ERROR (Status); // // Get System MemoryMap -- 1.7.1
next prev parent reply other threads:[~2013-08-07 17:47 UTC|newest] Thread overview: 108+ messages / expand[flat|nested] mbox.gz Atom feed top 2013-07-31 20:54 Corrupted EFI region Borislav Petkov 2013-07-31 20:54 ` Borislav Petkov 2013-07-31 20:58 ` Matthew Garrett 2013-07-31 20:58 ` Matthew Garrett 2013-07-31 21:51 ` Borislav Petkov 2013-07-31 21:51 ` Borislav Petkov 2013-07-31 21:54 ` Matthew Garrett 2013-07-31 21:54 ` Matthew Garrett 2013-08-01 16:51 ` Borislav Petkov 2013-08-01 16:51 ` Borislav Petkov 2013-07-31 21:55 ` David Woodhouse 2013-07-31 21:55 ` David Woodhouse 2013-08-01 16:49 ` Borislav Petkov 2013-08-01 16:49 ` Borislav Petkov 2013-08-05 11:27 ` [edk2] " Laszlo Ersek 2013-08-05 11:27 ` Laszlo Ersek 2013-08-05 13:02 ` Borislav Petkov 2013-08-05 13:02 ` Borislav Petkov 2013-08-05 13:39 ` Laszlo Ersek 2013-08-05 13:39 ` Laszlo Ersek 2013-08-05 14:03 ` Borislav Petkov 2013-08-05 14:03 ` Borislav Petkov 2013-08-05 14:27 ` Laszlo Ersek 2013-08-05 14:27 ` Laszlo Ersek 2013-08-05 14:40 ` Borislav Petkov 2013-08-05 14:40 ` Borislav Petkov 2013-08-05 15:15 ` Laszlo Ersek 2013-08-05 15:15 ` Laszlo Ersek 2013-08-05 15:34 ` James Bottomley 2013-08-05 15:34 ` James Bottomley 2013-08-05 16:27 ` Laszlo Ersek 2013-08-05 16:27 ` Laszlo Ersek 2013-08-05 16:12 ` Borislav Petkov 2013-08-05 16:12 ` Borislav Petkov 2013-08-05 16:41 ` Laszlo Ersek 2013-08-05 16:41 ` Laszlo Ersek 2013-08-05 16:47 ` Borislav Petkov 2013-08-05 16:47 ` Borislav Petkov 2013-08-05 17:00 ` Kinney, Michael D 2013-08-05 17:00 ` Kinney, Michael D 2013-08-05 17:09 ` Laszlo Ersek 2013-08-05 17:09 ` Laszlo Ersek 2013-08-05 21:26 ` Laszlo Ersek 2013-08-05 21:26 ` Laszlo Ersek 2013-08-05 22:08 ` Borislav Petkov 2013-08-05 22:08 ` Borislav Petkov 2013-08-06 14:10 ` Borislav Petkov 2013-08-06 14:10 ` Borislav Petkov 2013-08-06 15:31 ` Laszlo Ersek 2013-08-06 15:31 ` Laszlo Ersek 2013-08-07 15:19 ` Borislav Petkov 2013-08-07 17:23 ` Andrew Fish 2013-08-07 17:23 ` Andrew Fish 2013-08-07 20:19 ` Matt Fleming 2013-08-07 20:19 ` Matt Fleming 2013-08-07 20:24 ` Matt Fleming 2013-08-07 20:24 ` Matt Fleming 2013-08-07 21:10 ` Andrew Fish 2013-08-07 21:10 ` Andrew Fish 2013-08-07 21:23 ` Matthew Garrett 2013-08-08 10:17 ` Matt Fleming 2013-08-08 10:17 ` Matt Fleming 2013-08-08 13:46 ` Andrew Fish 2013-08-08 13:46 ` Andrew Fish 2013-09-02 8:19 ` Matt Fleming 2013-09-02 8:19 ` Matt Fleming 2013-09-13 20:38 ` jerry.hoemann 2013-09-13 20:38 ` jerry.hoemann-VXdhtT5mjnY 2013-09-16 10:59 ` Matt Fleming 2013-09-16 10:59 ` Matt Fleming 2013-09-16 11:50 ` Laszlo Ersek 2013-09-16 11:50 ` Laszlo Ersek 2013-09-16 15:57 ` Josh Triplett 2013-09-16 15:57 ` Josh Triplett 2013-09-16 16:25 ` Laszlo Ersek 2013-09-16 16:25 ` Laszlo Ersek 2013-09-16 16:27 ` Matthew Garrett 2013-09-16 16:27 ` Matthew Garrett 2013-09-16 16:29 ` Josh Triplett 2013-09-16 16:29 ` Josh Triplett 2013-09-18 19:24 ` jerry.hoemann 2013-09-18 19:24 ` jerry.hoemann-VXdhtT5mjnY 2013-09-20 9:06 ` Matt Fleming 2013-09-20 9:06 ` Matt Fleming 2013-08-07 17:49 ` Laszlo Ersek [this message] 2013-08-07 17:49 ` Laszlo Ersek 2013-08-08 15:02 ` Borislav Petkov 2013-08-08 15:02 ` Borislav Petkov 2013-08-08 21:45 ` Brian J. Johnson 2013-08-08 21:45 ` Brian J. Johnson 2013-08-18 7:33 ` Jordan Justen 2013-08-18 7:33 ` Jordan Justen 2013-08-05 15:50 ` Andrew Fish 2013-08-05 15:50 ` Andrew Fish 2013-08-05 18:12 ` Borislav Petkov 2013-08-05 18:12 ` Borislav Petkov 2013-08-05 21:37 ` H. Peter Anvin 2013-08-05 21:37 ` H. Peter Anvin 2013-08-05 21:41 ` Borislav Petkov 2013-08-05 21:41 ` Borislav Petkov 2013-08-05 21:49 ` H. Peter Anvin 2013-08-05 21:49 ` H. Peter Anvin 2013-08-05 21:55 ` Laszlo Ersek 2013-08-05 21:55 ` Laszlo Ersek 2013-08-05 22:52 ` James Bottomley 2013-08-05 22:52 ` James Bottomley 2013-08-06 7:26 ` Laszlo Ersek 2013-08-06 7:26 ` Laszlo Ersek
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=5202889C.2080608@redhat.com \ --to=lersek@redhat.com \ --cc=bp@alien8.de \ --cc=dwmw2@infradead.org \ --cc=edk2-devel@lists.sourceforge.net \ --cc=gleb@redhat.com \ --cc=jordan.l.justen@intel.com \ --cc=linux-efi@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=matt@console-pimps.org \ --cc=mjg59@srcf.ucam.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.