I tried this workaround and there're no failure in booting Fedora 26 and Windows
server 2016 now. If no objection, I'll merge it into new version of this patch.

> -----Original Message-----
> From: Wang, Jian J
> Sent: Wednesday, November 15, 2017 3:37 PM
> To: Zeng, Star <star.z...@intel.com>; Laszlo Ersek <ler...@redhat.com>
> Cc: Matt Fleming <m...@codeblueprint.co.uk>; edk2-devel@lists.01.org; Yao,
> Jiewen <jiewen....@intel.com>; Dong, Eric <eric.d...@intel.com>; Ard
> Biesheuvel <ard.biesheu...@linaro.org>
> Subject: RE: [PATCH v5] UefiCpuPkg/CpuDxe: Fix multiple entries of RT_CODE in
> memory map
> 
> Since OS never had chance to use the those capabilities before, I think it's
> feasible.
> But it's just a workaround not solution because there's real gap between UEFI
> and
> OS on how to interpret the memory capabilities.
> 
> > -----Original Message-----
> > From: Zeng, Star
> > Sent: Wednesday, November 15, 2017 2:53 PM
> > To: Wang, Jian J <jian.j.w...@intel.com>; Laszlo Ersek <ler...@redhat.com>
> > Cc: Matt Fleming <m...@codeblueprint.co.uk>; edk2-devel@lists.01.org; Yao,
> > Jiewen <jiewen....@intel.com>; Dong, Eric <eric.d...@intel.com>; Ard
> > Biesheuvel <ard.biesheu...@linaro.org>; Zeng, Star <star.z...@intel.com>
> > Subject: RE: [PATCH v5] UefiCpuPkg/CpuDxe: Fix multiple entries of RT_CODE
> in
> > memory map
> >
> > How about the code to filter out paging capabilities from UEFI memory map in
> > Page.c CoreGetMemoryMap(), then with maximum compatibility, the UEFI
> > memory map could be same with before
> > 14dde9e903bb9a719ebb8f3381da72b19509bc36 [MdeModulePkg/Core: Fix
> out-
> > of-sync issue in GCD].
> >
> > Thanks,
> > Star
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of
> Wang,
> > Jian J
> > Sent: Tuesday, November 14, 2017 10:36 PM
> > To: Laszlo Ersek <ler...@redhat.com>
> > Cc: Matt Fleming <m...@codeblueprint.co.uk>; edk2-devel@lists.01.org; Yao,
> > Jiewen <jiewen....@intel.com>; Dong, Eric <eric.d...@intel.com>; Ard
> > Biesheuvel <ard.biesheu...@linaro.org>
> > Subject: Re: [edk2] [PATCH v5] UefiCpuPkg/CpuDxe: Fix multiple entries of
> > RT_CODE in memory map
> >
> > Hi Laszlo,
> >
> > I did some investigation works on this issue. I think I found the root 
> > cause and
> > tend to believe this is a Fedora kernel issue. Here're proves:
> >
> > memmap output patterns in which Fedora 26 failed to boot:
> > 1) BS_Data    00000000AE200000-00000000AE20EFFF 000000000000000F
> > 000000000002600F
> >     RT_Data    00000000AE20F000-00000000AE38EFFF 0000000000000180
> > 800000000002600F
> >     RT_Code    00000000AE38F000-00000000AE48EFFF 0000000000000100
> > 800000000002600F
> >     Reserved   00000000AE48F000-00000000AE58EFFF 0000000000000100
> > 000000000002600F
> >
> > 2) BS_Data    00000000AE200000-00000000AE20EFFF 000000000000000F
> > 000000000000000F
> >     RT_Data    00000000AE20F000-00000000AE38EFFF 0000000000000180
> > 800000000000000F
> >     RT_Code    00000000AE38F000-00000000AE467FFF 00000000000000D9
> > 800000000000000F
> >     RT_Code    00000000AE468000-00000000AE469FFF 0000000000000002
> > 800000000002600F
> >     RT_Code    00000000AE46A000-00000000AE46EFFF 0000000000000005
> > 800000000000000F
> >     RT_Code    00000000AE46F000-00000000AE470FFF 0000000000000002
> > 800000000002600F
> >     RT_Code    00000000AE471000-00000000AE475FFF 0000000000000005
> > 800000000000000F
> >     RT_Code    00000000AE476000-00000000AE479FFF 0000000000000004
> > 800000000002600F
> >     RT_Code    00000000AE47A000-00000000AE47FFFF 0000000000000006
> > 800000000000000F
> >     RT_Code    00000000AE480000-00000000AE481FFF 0000000000000002
> > 800000000002600F
> >     RT_Code    00000000AE482000-00000000AE487FFF 0000000000000006
> > 800000000000000F
> >     RT_Code    00000000AE488000-00000000AE489FFF 0000000000000002
> > 800000000002600F
> >     RT_Code    00000000AE48A000-00000000AE48EFFF 0000000000000005
> > 800000000000000F
> >     Reserved   00000000AE48F000-00000000AE58EFFF 0000000000000100
> > 000000000000000F
> >
> > 3) RT_Data    00000000AE20F000-00000000AE38EFFF 0000000000000180
> > 800000000000000F
> >     RT_Code    00000000AE38F000-00000000AE418FFF 000000000000008A
> > 800000000000000F
> >     RT_Code    00000000AE419000-00000000AE48EFFF 0000000000000076
> > 800000000002600F
> >     Reserved   00000000AE48F000-00000000AE58EFFF 0000000000000100
> > 000000000000000F
> >
> > 4) BS_Data    00000000AE200000-00000000AE20EFFF 000000000000000F
> > 000000000002400F
> >     RT_Data    00000000AE20F000-00000000AE38EFFF 0000000000000180
> > 800000000002400F
> >     RT_Code    00000000AE38F000-00000000AE48EFFF 0000000000000100
> > 800000000002400F
> >     Reserved   00000000AE48F000-00000000AE58EFFF 0000000000000100
> > 000000000002400F
> >
> >
> > memmap output pattern in which Fedora 26 booted successfully
> > 5) BS_Data    00000000AE200000-00000000AE20EFFF 000000000000000F
> > 000000000000000F
> >     RT_Data    00000000AE20F000-00000000AE38EFFF 0000000000000180
> > 800000000000000F
> >     RT_Code    00000000AE38F000-00000000AE48EFFF 0000000000000100
> > 800000000000000F
> >     Reserved   00000000AE48F000-00000000AE58EFFF 0000000000000100
> > 000000000000000F
> >
> > 6) BS_Data    00000000AE200000-00000000AE20EFFF 000000000000000F
> > 000000000000000F
> >     RT_Data    00000000AE20F000-00000000AE38EFFF 0000000000000180
> > 800000000000000F
> >     RT_Code    00000000AE38F000-00000000AE418FFF 000000000000008A
> > 800000000000000F
> >     RT_Code    00000000AE419000-00000000AE419FFF 0000000000000001
> > 800000000000400F
> >     RT_Code    00000000AE41A000-00000000AE41BFFF 0000000000000002
> > 800000000002000F
> >     RT_Code    00000000AE41C000-00000000AE420FFF 0000000000000005
> > 800000000000400F
> >     RT_Code    00000000AE421000-00000000AE422FFF 0000000000000002
> > 800000000002000F
> >     RT_Code    00000000AE423000-00000000AE427FFF 0000000000000005
> > 800000000000400F
> >     RT_Code    00000000AE428000-00000000AE42AFFF 0000000000000003
> > 800000000002000F
> >     RT_Code    00000000AE42B000-00000000AE42FFFF 0000000000000005
> > 800000000000400F
> >     RT_Code    00000000AE430000-00000000AE432FFF 0000000000000003
> > 800000000002000F
> >     RT_Code    00000000AE433000-00000000AE439FFF 0000000000000007
> > 800000000000400F
> >     RT_Code    00000000AE43A000-00000000AE43DFFF 0000000000000004
> > 800000000002000F
> >     RT_Code    00000000AE43E000-00000000AE444FFF 0000000000000007
> > 800000000000400F
> >     RT_Code    00000000AE445000-00000000AE448FFF 0000000000000004
> > 800000000002000F
> >     RT_Code    00000000AE449000-00000000AE44EFFF 0000000000000006
> > 800000000000400F
> >     RT_Code    00000000AE44F000-00000000AE450FFF 0000000000000002
> > 800000000002000F
> >     RT_Code    00000000AE451000-00000000AE455FFF 0000000000000005
> > 800000000000400F
> >     RT_Code    00000000AE456000-00000000AE458FFF 0000000000000003
> > 800000000002000F
> >     RT_Code    00000000AE459000-00000000AE45FFFF 0000000000000007
> > 800000000000400F
> >     RT_Code    00000000AE460000-00000000AE461FFF 0000000000000002
> > 800000000002000F
> >     RT_Code    00000000AE462000-00000000AE467FFF 0000000000000006
> > 800000000000400F
> >     RT_Code    00000000AE468000-00000000AE469FFF 0000000000000002
> > 800000000002000F
> >     RT_Code    00000000AE46A000-00000000AE46EFFF 0000000000000005
> > 800000000000400F
> >     RT_Code    00000000AE46F000-00000000AE470FFF 0000000000000002
> > 800000000002000F
> >     RT_Code    00000000AE471000-00000000AE475FFF 0000000000000005
> > 800000000000400F
> >     RT_Code    00000000AE476000-00000000AE479FFF 0000000000000004
> > 800000000002000F
> >     RT_Code    00000000AE47A000-00000000AE47FFFF 0000000000000006
> > 800000000000400F
> >     RT_Code    00000000AE480000-00000000AE481FFF 0000000000000002
> > 800000000002000F
> >     RT_Code    00000000AE482000-00000000AE487FFF 0000000000000006
> > 800000000000400F
> >     RT_Code    00000000AE488000-00000000AE489FFF 0000000000000002
> > 800000000002000F
> >     RT_Code    00000000AE48A000-00000000AE48EFFF 0000000000000005
> > 800000000000400F
> >     Reserved   00000000AE48F000-00000000AE58EFFF 0000000000000100
> > 000000000000000F
> >
> > You may notice that 4) will fail but 6) will succeed. Taking into account 
> > the fact
> > that failure always happened in the runtime service api (set_variable), I 
> > think it
> > must be that the kernel will mark the memory block to be RO/XP/RP memory
> > according to its capabilities but not its current attributes.
> >
> > This can explain why 4) will fail but 6) will succeed. Although memmap shows
> all
> > runtime driver image memory as RT_Code, but they're not all code segment.
> > Instead some of them are actually data segment.
> >
> > It's normal to mark code segment to be RO and data segment to be XP. But
> mark
> > data segment to be RO will cause runtime services failure. 4) shows all
> RT_Code
> > to be XXX24XXX, which means Fedora kernel will mark all code segment and
> data
> > segment to be RO and XP mistakenly, based on my previous hypothesis. This
> can
> > also explain why 1), 2), 3) will fail the boot because XXX26XXX will let 
> > Fedora
> > kernel to mark RT_Code memory block to be not-present.
> >
> > I haven't got time to look into the Linux kernel source so I can't confirm 
> > above
> > analysis yet.
> > I think you're more familiar with kernel source than us. Maybe you could 
> > help
> to
> > take a look.
> >
> > Thanks,
> > Jian
> >
> > > -----Original Message-----
> > > From: Laszlo Ersek [mailto:ler...@redhat.com]
> > > Sent: Friday, November 10, 2017 8:24 PM
> > > To: Wang, Jian J <jian.j.w...@intel.com>
> > > Cc: edk2-devel@lists.01.org; Dong, Eric <eric.d...@intel.com>; Yao,
> > > Jiewen <jiewen....@intel.com>; Ard Biesheuvel
> > > <ard.biesheu...@linaro.org>; Matt Fleming <m...@codeblueprint.co.uk>
> > > Subject: Re: [PATCH v5] UefiCpuPkg/CpuDxe: Fix multiple entries of
> > > RT_CODE in memory map
> > >
> > > Hi Jian,
> > >
> > > I'm CC'ing Ard and Matt, and commenting at the bottom.
> > >
> > > On 11/10/17 02:02, Jian J Wang wrote:
> > > >> v5:
> > > >>    Coding style clean-up
> > > >
> > > >> v4:
> > > >> a. Remove DoUpdate and check attributes mismatch all the time to avoid
> > > >>    a logic hole
> > > >> b. Add warning message if failed to update capability c. Add local
> > > >> variable to hold new attributes to make code cleaner
> > > >
> > > >> v3:
> > > >> a. Add comment to explain more on updating memory capabilities b.
> > > >> Fix logic hole in updating attributes c. Instead of checking
> > > >> illegal memory space address and size, use return
> > > >>    status of gDS->SetMemorySpaceCapabilities() to skip memory block
> which
> > > >>    cannot be updated with new capabilities.
> > > >
> > > >> v2
> > > >> a. Fix an issue which will cause setting capability failure if size is 
> > > >> smaller
> > > >>    than a page.
> > > >
> > > > More than one entry of RT_CODE memory might cause boot problem for
> > > some
> > > > old OSs. This patch will fix this issue to keep OS compatibility as
> > > > much as possible.
> > > >
> > > > More detailed information, please refer to
> > > >     https://bugzilla.tianocore.org/show_bug.cgi?id=753
> > > >
> > > > Cc: Eric Dong <eric.d...@intel.com>
> > > > Cc: Jiewen Yao <jiewen....@intel.com>
> > > > Cc: Laszlo Ersek <ler...@redhat.com>
> > > > Contributed-under: TianoCore Contribution Agreement 1.1
> > > > Signed-off-by: Jian J Wang <jian.j.w...@intel.com>
> > > > ---
> > > >  UefiCpuPkg/CpuDxe/CpuPageTable.c | 69
> > > +++++++++++++++++++++++++++++-----------
> > > >  1 file changed, 50 insertions(+), 19 deletions(-)
> > > >
> > > > diff --git a/UefiCpuPkg/CpuDxe/CpuPageTable.c
> > > b/UefiCpuPkg/CpuDxe/CpuPageTable.c
> > > > index d312eb66f8..61537838b7 100644
> > > > --- a/UefiCpuPkg/CpuDxe/CpuPageTable.c
> > > > +++ b/UefiCpuPkg/CpuDxe/CpuPageTable.c
> > > > @@ -789,8 +789,7 @@ RefreshGcdMemoryAttributesFromPaging (
> > > >    UINT64                              BaseAddress;
> > > >    UINT64                              PageStartAddress;
> > > >    UINT64                              Attributes;
> > > > -  UINT64                              Capabilities;
> > > > -  BOOLEAN                             DoUpdate;
> > > > +  UINT64                              NewAttributes;
> > > >    UINTN                               Index;
> > > >
> > > >    //
> > > > @@ -802,9 +801,8 @@ RefreshGcdMemoryAttributesFromPaging (
> > > >
> > > >    GetCurrentPagingContext (&PagingContext);
> > > >
> > > > -  DoUpdate      = FALSE;
> > > > -  Capabilities  = 0;
> > > >    Attributes    = 0;
> > > > +  NewAttributes = 0;
> > > >    BaseAddress   = 0;
> > > >    PageLength    = 0;
> > > >
> > > > @@ -813,6 +811,34 @@ RefreshGcdMemoryAttributesFromPaging (
> > > >        continue;
> > > >      }
> > > >
> > > > +    //
> > > > +    // Sync the actual paging related capabilities back to GCD service 
> > > > first.
> > > > +    // As a side effect (good one), this can also help to avoid 
> > > > unnecessary
> > > > +    // memory map entries due to the different capabilities of the same
> type
> > > > +    // memory, such as multiple RT_CODE and RT_DATA entries in
> > > > + memory
> > > map,
> > > > +    // which could cause boot failure of some old Linux distro (before 
> > > > v4.3).
> > > > +    //
> > > > +    Status = gDS->SetMemorySpaceCapabilities (
> > > > +                    MemorySpaceMap[Index].BaseAddress,
> > > > +                    MemorySpaceMap[Index].Length,
> > > > +                    MemorySpaceMap[Index].Capabilities |
> > > > +                    EFI_MEMORY_PAGETYPE_MASK
> > > > +                    );
> > > > +    if (EFI_ERROR (Status)) {
> > > > +      //
> > > > +      // If we cannot udpate the capabilities, we cannot update its
> > > > +      // attributes either. So just simply skip current block of 
> > > > memory.
> > > > +      //
> > > > +      DEBUG ((
> > > > +        DEBUG_WARN,
> > > > +        "Failed to update capability: [%lu] %016lx - %016lx (%016lx
> > > > + -
> > > > %016lx)\r\n",
> > > > +        (UINT64)Index, BaseAddress, BaseAddress + Length - 1,
> > > > +        MemorySpaceMap[Index].Capabilities,
> > > > +        MemorySpaceMap[Index].Capabilities |
> > EFI_MEMORY_PAGETYPE_MASK
> > > > +        ));
> > > > +      continue;
> > > > +    }
> > > > +
> > > >      if (MemorySpaceMap[Index].BaseAddress >= (BaseAddress +
> PageLength))
> > {
> > > >        //
> > > >        // Current memory space starts at a new page. Resetting
> > > > PageLength will @@ -826,7 +852,9 @@
> > RefreshGcdMemoryAttributesFromPaging (
> > > >        PageLength -= (MemorySpaceMap[Index].BaseAddress - BaseAddress);
> > > >      }
> > > >
> > > > -    // Sync real page attributes to GCD
> > > > +    //
> > > > +    // Sync actual page attributes to GCD
> > > > +    //
> > > >      BaseAddress       = MemorySpaceMap[Index].BaseAddress;
> > > >      MemorySpaceLength = MemorySpaceMap[Index].Length;
> > > >      while (MemorySpaceLength > 0) { @@ -842,23 +870,26 @@
> > > > RefreshGcdMemoryAttributesFromPaging (
> > > >          PageStartAddress  = (*PageEntry) &
> > > (UINT64)PageAttributeToMask(PageAttribute);
> > > >          PageLength        = PageAttributeToLength (PageAttribute) -
> > (BaseAddress -
> > > PageStartAddress);
> > > >          Attributes        = GetAttributesFromPageEntry (PageEntry);
> > > > -
> > > > -        if (Attributes != (MemorySpaceMap[Index].Attributes &
> > > EFI_MEMORY_PAGETYPE_MASK)) {
> > > > -          DoUpdate = TRUE;
> > > > -          Attributes |= (MemorySpaceMap[Index].Attributes &
> > > ~EFI_MEMORY_PAGETYPE_MASK);
> > > > -          Capabilities = Attributes | 
> > > > MemorySpaceMap[Index].Capabilities;
> > > > -        } else {
> > > > -          DoUpdate = FALSE;
> > > > -        }
> > > >        }
> > > >
> > > >        Length = MIN (PageLength, MemorySpaceLength);
> > > > -      if (DoUpdate) {
> > > > -        gDS->SetMemorySpaceCapabilities (BaseAddress, Length,
> Capabilities);
> > > > -        gDS->SetMemorySpaceAttributes (BaseAddress, Length, 
> > > > Attributes);
> > > > -        DEBUG ((DEBUG_INFO, "Update memory space attribute:
> > [%02d] %016lx
> > > - %016lx (%08lx -> %08lx)\r\n",
> > > > -                             Index, BaseAddress, BaseAddress + Length 
> > > > - 1,
> > > > -                             MemorySpaceMap[Index].Attributes, 
> > > > Attributes));
> > > > +      if (Attributes != (MemorySpaceMap[Index].Attributes &
> > > > +                         EFI_MEMORY_PAGETYPE_MASK)) {
> > > > +        NewAttributes = (MemorySpaceMap[Index].Attributes &
> > > > +                         ~EFI_MEMORY_PAGETYPE_MASK) | Attributes;
> > > > +        Status = gDS->SetMemorySpaceAttributes (
> > > > +                        BaseAddress,
> > > > +                        Length,
> > > > +                        NewAttributes
> > > > +                        );
> > > > +        ASSERT_EFI_ERROR (Status);
> > > > +        DEBUG ((
> > > > +          DEBUG_INFO,
> > > > +          "Updated memory space attribute: [%lu] %016lx - %016lx
> > > > + (%016lx -
> > > > %016lx)\r\n",
> > > > +          (UINT64)Index, BaseAddress, BaseAddress + Length - 1,
> > > > +          MemorySpaceMap[Index].Attributes,
> > > > +          NewAttributes
> > > > +          ));
> > > >        }
> > > >
> > > >        PageLength        -= Length;
> > > >
> > >
> > > So, I was ready to give my R-b for this patch, but then I also wanted
> > > to test it. I applied the patch on current edk2 master (7e2a8dfe8a9a,
> > > "ArmPlatformPkg/PrePeiCore: seed temporary stack before entering PEI
> > > core", 2017-10-20), and built OVMF like this:
> > >
> > > $ build \
> > >   -a IA32 \
> > >   -a X64 \
> > >   -p OvmfPkg/OvmfPkgIa32X64.dsc \
> > >   -t GCC48 \
> > >   -b NOOPT \
> > >   -D SMM_REQUIRE \
> > >   -D SECURE_BOOT_ENABLE \
> > >   -D E1000_ENABLE \
> > >   -D HTTP_BOOT_ENABLE
> > >
> > > For testing I used a recent-ish upstream QEMU development build
> > > (ae49fbbcd8e4, "Merge remote-tracking branch
> > > 'remotes/rth/tags/pull-tcg-20171025' into staging", 2017-10-25), with
> > > the Q35 machine type (which is required by SMM anyway).
> > >
> > > The results vary across guest OSes:
> > >
> > > (1) Up-to-date Fedora 26 guest crashes during boot, with the following
> > > call stack:
> > >
> > > BUG: unable to handle kernel paging request at fffffffefe893018 Call
> > > Trace:
> > >  ? __change_page_attr_set_clr+0xaa6/0xd70
> > >  ? kernel_map_pages_in_pgd+0xbc/0xd0
> > >  ? efi_call+0x58/0x90
> > >  ? virt_efi_set_variable.part.7+0x66/0x120
> > >  ? virt_efi_set_variable+0x4f/0x60
> > >  ? efi_delete_dummy_variable+0x62/0x90
> > >  ? efi_enter_virtual_mode+0x4d4/0x4e8
> > >  ? efi_enter_virtual_mode+0x4d4/0x4e8
> > >  ? start_kernel+0x442/0x4e6
> > >  ? early_idt_handler_array+0x120/0x120
> > >  ? x86_64_start_reservations+0x24/0x26
> > >  ? x86_64_start_kernel+0x13e/0x161
> > >  ? secondary_startup_64+0x9f/0x9f
> > >
> > > (2) The following Windows OSes all boot successfully:
> > >
> > > - Windows 7
> > > - Windows Server 2008 R2
> > > - Windows 8.1
> > > - Windows Server 2012 R2
> > > - Windows 10
> > >
> > > (3) Windows Server 2016 crashes with a BSOD; reporting "ATTEMPTED
> > > WRITE TO READONLY MEMORY".
> > >
> > > (Without the patch, all OSes boot OK.)
> > >
> > >
> > > I'm attaching a ZIP file with the following contents (note that I'll
> > > attach the same file to TianoCore BZ#753 as well, because the mailing
> > > list archive(s) don't seem to preserve attachments):
> > >
> > > - "ovmf.pre.txt", "shell.memmap.pre.txt", "kernel.pre.txt": OVMF log,
> > > MEMMAP command output in the UEFI shell, and Fedora 26 kernel boot log
> > > (successful) *before* applying your patch. The kernel log is detailed
> > > (the cmdline had "ignore_loglevel" and "efi=debug").
> > >
> > > - "ovmf.post.txt", "shell.memmap.post.txt", "kernel.post.txt": same
> > > files as above, but saved *after* applying your patch. This is when
> > > the
> > > F26 kernel crashes.
> > >
> > > - "win2016.post.png": screenshot of the Windows Server 2016 boot
> > > failure (after the patch was applied).
> > >
> > > Thanks,
> > > Laszlo
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to