public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Roger Pau Monné" <roger.pau@citrix.com>
To: Anthony PERARD <anthony.perard@citrix.com>
Cc: <devel@edk2.groups.io>, <xen-devel@lists.xenproject.org>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Jordan Justen <jordan.l.justen@intel.com>,
	Laszlo Ersek <lersek@redhat.com>,
	Julien Grall <julien.grall@arm.com>,
	"Andrew Cooper" <andrew.cooper3@citrix.com>
Subject: Re: [PATCH v3 24/35] OvmfPkg/XenPlatformPei: Rework memory detection
Date: Tue, 23 Jul 2019 11:42:07 +0200	[thread overview]
Message-ID: <20190723094207.ccnzyzuma4ydpugi@Air-de-Roger> (raw)
In-Reply-To: <20190722145319.GG1208@perard.uk.xensource.com>

On Mon, Jul 22, 2019 at 03:53:19PM +0100, Anthony PERARD wrote:
> On Mon, Jul 15, 2019 at 04:15:21PM +0200, Roger Pau Monné wrote:
> > On Thu, Jul 04, 2019 at 03:42:22PM +0100, Anthony PERARD wrote:
> > > When running as a Xen PVH guest, there is no CMOS to read the memory
> > > size from.  Rework GetSystemMemorySize(Below|Above)4gb() so they can
> > > works without CMOS by reading the e820 table.
> > > 
> > > Rework XenPublishRamRegions for PVH, handle the Reserve type and explain
> > > about the ACPI type. MTRR settings aren't modified anymore, on HVM, it's
> > > already done by hvmloader, on PVH it is supposed to have sane default.
> > > 
> > > Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1689
> > > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> > > Acked-by: Laszlo Ersek <lersek@redhat.com>
> > > ---
> > > 
> > > Notes:
> > >     Comment for Xen people:
> > >     About MTRR, should we redo the setting in OVMF? Even if in both case of
> > >     PVH and HVM, something would have setup the default type to write back
> > >     and handle a few other ranges like PCI hole, hvmloader for HVM or and
> > >     libxc I think for PVH.
> > 
> > That's a tricky question. Ideally we would like the firmware (OVMF) to
> > take care of that, because it already has code to do so. Problem here
> > is that PVH can also be booted without firmware, in which case it
> > needs the hypervisor to have setup some sane initial MTRR state.
> > 
> > The statement in the PVH document about initial MTRR state is vague
> > enough that allows Xen to boot into the guest with a minimal MTRR
> > state, that can for example not contain UC regions for the MMIO
> > regions of passed through devices, hence I think OVMF should be in
> > charge of creating a more complete MTRR state if possible.
> > 
> > Is this something OVMF already has logic for?
> 
> Well, there are some logic but it's for QEMU (and uses an interface that
> isn't available when running on Xen, fwcfg).
> 
> The logic that was there for Xen HVM was very simple, a single set
> cache-write-back for the RAM, that's why I remove it (and because I'm
> not sure yet I figured out how to run the mtrr functions correctly in
> OVMF).
> 
> I probably going to have to write a new logic which would rewrite the
> MTRR from scratch instead of relying on the existing setup.
> 
> > Also accounting for the MMIO regions of devices?
> 
> I'll have to dig deeper into OVMF codes, and PCI device handling. On
> HVM, we have a different logic than the one for QEMU, OVMF only scan
> what hvmloader have done instead of re-setup the pci devices. I'm
> probably missing other stuff.

MTRR setup it's always a PITA, I was hoping OVMF could manage to do
that based on the memory map plus scanning for devices and positioning
BARs, but if it gets the information from other side-channels it's
going to be more complicated.

Anyway, something to improve in the future in order to get rid of
hvmloader.

> > > diff --git a/OvmfPkg/XenPlatformPei/MemDetect.c b/OvmfPkg/XenPlatformPei/MemDetect.c
> > > index cb7dd93ad6..3e33e7f414 100644
> > > --- a/OvmfPkg/XenPlatformPei/MemDetect.c
> > > +++ b/OvmfPkg/XenPlatformPei/MemDetect.c
> > > @@ -96,6 +96,47 @@ Q35TsegMbytesInitialization (
> > >    mQ35TsegMbytes = ExtendedTsegMbytes;
> > >  }
> > >  
> > > +STATIC
> > > +UINT64
> > > +GetHighestSystemMemoryAddress (
> > > +  BOOLEAN       Below4gb
> > > +  )
> > > +{
> > > +  EFI_E820_ENTRY64    *E820Map;
> > > +  UINT32              E820EntriesCount;
> > > +  EFI_E820_ENTRY64    *Entry;
> > > +  EFI_STATUS          Status;
> > > +  UINT32              Loop;
> > > +  UINT64              HighestAddress;
> > > +  UINT64              EntryEnd;
> > > +
> > > +  HighestAddress = 0;
> > > +
> > > +  Status = XenGetE820Map (&E820Map, &E820EntriesCount);
> > 
> > You could maybe initialize this as a global to avoid having to issue
> > a hypercall each time you need to get something from the memory map.
> 
> That function does that, it only make the hypercall once. (The hypercall
> can only be made once anyway, the second time Xen doesn't return the
> map.)

Why? I'm looking at the implementation in Xen of XENMEM_memory_map and
I'm not sure I see how/why the hypercall can only be made once. AFAICT
you should be able to call XENMEM_memory_map multiple times without
issues, or else it's a bug somewhere.

> > > +  ASSERT_EFI_ERROR (Status);
> > > +
> > > +  for (Loop = 0; Loop < E820EntriesCount; Loop++) {
> > > +    Entry = E820Map + Loop;
> > > +    EntryEnd = Entry->BaseAddr + Entry->Length;
> > > +
> > > +    if (Entry->Type == EfiAcpiAddressRangeMemory &&
> > > +        EntryEnd > HighestAddress) {
> > > +
> > > +      if (Below4gb && (EntryEnd <= BASE_4GB)) {
> > > +        HighestAddress = EntryEnd;
> > > +      } else if (!Below4gb && (EntryEnd >= BASE_4GB)) {
> > > +        HighestAddress = EntryEnd;
> > > +      }
> > > +    }
> > > +  }
> > > +
> > > +  //
> > > +  // Round down the end address.
> > > +  //
> > > +  HighestAddress &= ~(UINT64)EFI_PAGE_MASK;
> > > +
> > > +  return HighestAddress;
> > 
> > You could do the rounding on the return statement.
> 
> Yes, I think that can be done.
> 
> > > +}
> > >  
> > >  UINT32
> > >  GetSystemMemorySizeBelow4gb (
> > > @@ -105,6 +146,19 @@ GetSystemMemorySizeBelow4gb (
> > >    UINT8 Cmos0x34;
> > >    UINT8 Cmos0x35;
> > >  
> > > +  //
> > > +  // In PVH case, there is no CMOS, we have to calculate the memory size
> > > +  // from parsing the E820
> > > +  //
> > > +  if (XenPvhDetected ()) {
> > 
> > IIRC on HVM you can also get the memory map from the hypercall, in
> > which case you could use the same code path for both HVM and PVH.
> 
> I think that wouldn't work because in my experiment, the hypercall would
> only return the map the first time (at least on PVH). hvmloader already
> make the hypercall so OVMF can't.

OK, I'm not sure the reason for this, as I said above I think this is
a bug somewhere. You should be able to call XENMEM_memory_map multiple
times.

> On the other hand, XenGetE820Map() return an E820 map, it doesn't matter
> if it's the one passed by hvmloader, or the one we've got directly from
> Xen. So I guess we could ignore what hvmloader have written in the CMOS

Hm, I'm not sure hvmloader uploads a new memory map to Xen (using
XENMEM_set_memory_map) if it does any modifications to it. It should
certainly do it, so that the guest OS gets the same memory map from
the hypercall or from the firmware.

> and use the information in the e820 directly. But I think I let this
> change for future patch.
> 
> > > +    UINT64  HighestAddress;
> > > +
> > > +    HighestAddress = GetHighestSystemMemoryAddress (TRUE);
> > > +    ASSERT (HighestAddress > 0 && HighestAddress <= BASE_4GB);
> > > +
> > > +    return HighestAddress;
> > 
> > The name of the function here is GetSystemMemorySizeBelow4gb, but you
> > are returning the highest memory address in the range, is this
> > expected?
> > 
> > ie: highest address != memory size
> > 
> > On HVM there are quite some holes in the memory map, and nothing
> > guarantees there are no memory regions after the holes or non-RAM
> > regions.
> 
> I think that's what is expected by caller of the function.

OK, the naming is slightly misleading, just wanted to make sure this
was the expected value.

> > > +  }
> > > +
> > >    //
> > >    // CMOS 0x34/0x35 specifies the system memory above 16 MB.
> > >    // * CMOS(0x35) is the high byte
> > > diff --git a/OvmfPkg/XenPlatformPei/Xen.c b/OvmfPkg/XenPlatformPei/Xen.c
> > > index cbfd8058fc..62a2c3ed93 100644
> > > --- a/OvmfPkg/XenPlatformPei/Xen.c
> > > +++ b/OvmfPkg/XenPlatformPei/Xen.c
> > > @@ -279,6 +279,8 @@ XenPublishRamRegions (
> > >    EFI_E820_ENTRY64  *E820Map;
> > >    UINT32            E820EntriesCount;
> > >    EFI_STATUS        Status;
> > > +  EFI_E820_ENTRY64 *Entry;
> > > +  UINTN Index;
> > >  
> > >    DEBUG ((EFI_D_INFO, "Using memory map provided by Xen\n"));
> > >  
> > > @@ -287,26 +289,45 @@ XenPublishRamRegions (
> > >    //
> > >    E820EntriesCount = 0;
> > >    Status = XenGetE820Map (&E820Map, &E820EntriesCount);
> > > -
> > >    ASSERT_EFI_ERROR (Status);
> > >  
> > > -  if (E820EntriesCount > 0) {
> > > -    EFI_E820_ENTRY64 *Entry;
> > > -    UINT32 Loop;
> > > +  for (Index = 0; Index < E820EntriesCount; Index++) {
> > > +    UINT64 Base;
> > > +    UINT64 End;
> > >  
> > > -    for (Loop = 0; Loop < E820EntriesCount; Loop++) {
> > > -      Entry = E820Map + Loop;
> > > +    Entry = &E820Map[Index];
> > >  
> > > +
> > > +    //
> > > +    // Round up the start address, and round down the end address.
> > > +    //
> > > +    Base = ALIGN_VALUE (Entry->BaseAddr, (UINT64)EFI_PAGE_SIZE);
> > > +    End = (Entry->BaseAddr + Entry->Length) & ~(UINT64)EFI_PAGE_MASK;
> > > +
> > > +    switch (Entry->Type) {
> > > +    case EfiAcpiAddressRangeMemory:
> > > +      AddMemoryRangeHob (Base, End);
> > > +      break;
> > > +    case EfiAcpiAddressRangeACPI:
> > > +      //
> > > +      // Ignore, OVMF should read the ACPI tables and provide them to linux
> > > +      // from a different location.
> > 
> > Will OVMF also parse dynamic tables to check for references there?
> 
> I haven't looked at what OVMF does with the ACPI tables, but Linux seems
> fine. I've compared the boot output of linux running as PVH vs booted
> via OVMF. Beside the location of the table been different, the number of
> table where the same, I don't remember other difference.

OK, what I find weird is that you seem to discard quite a lot of stuff
from the original memory map, and then reconstruct it afterwards I
assume?

It would seem safer to not discard regions from the memory map
provided to OVMF, and instead just build on top of it. I would expect
for example that OVMF will use some of the RAM regions on the memory
map, and it should likely turn those areas from RAM into reserved
regions.

> > > +      // error message: CpuDxe: IntersectMemoryDescriptor:
> > > +      //        desc [FC000000, 100000000) type 1 cap 8700000000026001
> > > +      //        conflicts with aperture [FEE00000, FEE01000) cap 1
> > >        //
> > > -      if (Entry->Type != EfiAcpiAddressRangeMemory) {
> > > -        continue;
> > > +      if (!XenHvmloaderDetected ()) {
> > > +        AddReservedMemoryBaseSizeHob (Base, End - Base, FALSE);
> > 
> > This special casing for PVH looks weird, ideally we would like to use
> > the same code path, or else it should be explicitly mentioned why PVH
> > has diverging behaviour.
> 
> I think hvmloader is the issue rather than PVH. Here is part of the
> "memory map" as found in hvmloader/config.h:
> 
>   /* Special BIOS mappings, etc. are allocated from here upwards... */
>   #define RESERVED_MEMBASE              0xFC000000
>   /* NB. ACPI_INFO_PHYSICAL_ADDRESS *MUST* match definition in acpi/dsdt.asl! */
>   #define ACPI_INFO_PHYSICAL_ADDRESS    0xFC000000
>   #define RESERVED_MEMORY_DYNAMIC_START 0xFC001000
>   #define RESERVED_MEMORY_DYNAMIC_END   0xFE000000
> 
> and hvmloader simply creates a single e820 reserved entry, from
> RESERVED_MEMBASE to the top of 4GB. It's probably too much.

But isn't this kind of dangerous? How can you assure future versions
of hvmloader won't use this space?

> If hvmloader only reserved
> ACPI_INFO_PHYSICAL_ADDRESS-RESERVED_MEMORY_DYNAMIC_END, I might not have
> to special case hvmloader.

Could we look into getting this fixed in hvmloader then?

I think it's dangerous for OVMF to play such tricks with the memory
map.

> As far as I know 0xfee00000 isn't a special
> bios mapping, but something the hardware provides.

Yes, that's used by the lapic, so it's not specific to hvmloader.

> Anyway, thanks for the feedback, there's probably quite a bit to do to
> cleanup the memory stuff. I do think about one day running OVMF without
> running hvmloader first :-), but there's a bit more to do.

Sorry if some of my comments are out of place, I certainly know very
little about OVMF code base, or the Xen bits in it.

Running OVMF without hvmloader would be my end goal also if possible
:).

Thanks, Roger.

  parent reply	other threads:[~2019-07-23  9:42 UTC|newest]

Thread overview: 90+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-04 14:41 [PATCH v3 00/35] Specific platform to run OVMF in Xen PVH and HVM guests Anthony PERARD
2019-07-04 14:41 ` [PATCH v3 01/35] OvmfPkg/ResetSystemLib: Add missing dependency on PciLib Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 02/35] OvmfPkg: Create platform OvmfXen Anthony PERARD
2019-07-05 13:29   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 03/35] OvmfPkg: Introduce XenResetVector Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 04/35] OvmfPkg: Introduce XenPlatformPei Anthony PERARD
2019-07-05 13:53   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 05/35] OvmfPkg/OvmfXen: Creating an ELF header Anthony PERARD
2019-07-05 14:09   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 06/35] OvmfPkg/XenResetVector: Add new entry point for Xen PVH Anthony PERARD
2019-07-05 13:57   ` Andrew Cooper
2019-07-19 10:20     ` Anthony PERARD
2019-07-19 14:33       ` Laszlo Ersek
2019-07-19 14:41         ` Andrew Cooper
2019-07-19 15:51           ` Anthony PERARD
2019-07-05 14:14   ` Laszlo Ersek
2019-07-15 11:46   ` Roger Pau Monné
2019-07-15 11:50     ` Andrew Cooper
2019-07-15 14:25       ` Roger Pau Monné
2019-07-19 14:00     ` Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 07/35] OvmfPkg/XenResetVector: Saving start of day pointer for PVH guests Anthony PERARD
2019-07-05 14:24   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 08/35] OvmfPkg/XenResetVector: Allow jumpstart from either hvmloader or PVH Anthony PERARD
2019-07-05 14:54   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 09/35] OvmfPkg/OvmfXen: use a TimerLib instance that depends only on the CPU Anthony PERARD
2019-07-05 15:01   ` Laszlo Ersek
2019-07-15 14:22   ` Roger Pau Monné
2019-07-22 13:49     ` Anthony PERARD
2019-07-22 19:28       ` Laszlo Ersek
2019-07-23  9:02         ` Roger Pau Monné
2019-07-04 14:42 ` [PATCH v3 10/35] OvmfPkg/XenPlatformPei: Detect OVMF_INFO from hvmloader Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 11/35] OvmfPkg/XenPlatformPei: Use mXenHvmloaderInfo to get E820 Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 12/35] OvmfPkg/XenPlatformPei: Grab RSDP from PVH guest start of day struct Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 13/35] OvmfPkg/Library/XenPlatformLib: New library Anthony PERARD
2019-07-08 14:34   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 14/35] OvmfPkg/AcpiPlatformDxe: Use XenPlatformLib Anthony PERARD
2019-07-08 14:38   ` Laszlo Ersek
2019-07-10  9:42     ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 15/35] OvmfPkg/AcpiPlatformDxe: Use Xen PVH RSDP if it exist Anthony PERARD
2019-07-08 14:42   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 16/35] OvmfPkg/XenHypercallLib: Enable it in PEIM Anthony PERARD
2019-07-08 14:51   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 17/35] OvmfPkg/XenPlatformPei: Reinit XenHypercallLib Anthony PERARD
2019-07-08 15:07   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 18/35] OvmfPkg/XenPlatformPei: Introduce XenHvmloaderDetected Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 19/35] OvmfPkg/XenPlatformPei: Reserve hvmloader's memory only when it has run Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 20/35] OvmfPkg/XenPlatformPei: Setup HyperPages earlier Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 21/35] OvmfPkg/XenPlatformPei: Introduce XenPvhDetected Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 22/35] OvmfPkg: Import XENMEM_memory_map hypercall to Xen/memory.h Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 23/35] OvmfPkg/XenPlatformPei: no hvmloader: get the E820 table via hypercall Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 24/35] OvmfPkg/XenPlatformPei: Rework memory detection Anthony PERARD
2019-07-15 14:15   ` roger.pau
2019-07-22 14:53     ` Anthony PERARD
2019-07-22 19:45       ` Laszlo Ersek
2019-07-22 23:08         ` Laszlo Ersek
2019-07-23  9:42       ` Roger Pau Monné [this message]
2019-07-23 16:06         ` Anthony PERARD
2019-07-24 16:17         ` Anthony PERARD
2019-07-25  9:08           ` Roger Pau Monné
2019-07-25 10:05             ` Anthony PERARD
2019-07-25 11:03               ` Roger Pau Monné
2019-07-04 14:42 ` [PATCH v3 25/35] OvmfPkg/XenPlatformPei: Reserve VGA memory region, to boot Linux Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 26/35] OvmfPkg/XenPlatformPei: Ignore missing PCI Host Bridge on Xen PVH Anthony PERARD
2019-07-08 15:31   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 27/35] OvmfPkg/XenPlatformLib: Cache result for XenDetected Anthony PERARD
2019-07-10  9:31   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 28/35] OvmfPkg/PlatformBootManagerLib: Use XenDetected from XenPlatformLib Anthony PERARD
2019-07-10  9:45   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 29/35] OvmfPkg/PlatformBootManagerLib: Handle the absence of PCI bus on Xen PVH Anthony PERARD
2019-07-10  9:50   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 30/35] OvmfPkg/OvmfXen: Override PcdFSBClock to Xen vLAPIC timer frequency Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 31/35] OvmfPkg/OvmfXen: Introduce XenTimerDxe Anthony PERARD
2019-07-10 10:12   ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 32/35] OvmfPkg/PlatformBootManagerLib: Use a Xen console for ConOut/ConIn Anthony PERARD
2019-07-10 10:48   ` Laszlo Ersek
2019-07-22 17:06     ` Anthony PERARD
2019-07-23  7:31       ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 33/35] OvmfPkg: Introduce XenIoPvhDxe to initialize Grant Tables Anthony PERARD
2019-07-10 14:05   ` Laszlo Ersek
2019-07-26 16:06     ` Anthony PERARD
2019-07-26 17:19       ` Laszlo Ersek
2019-07-04 14:42 ` [PATCH v3 34/35] OvmfPkg: Move XenRealTimeClockLib from ArmVirtPkg Anthony PERARD
2019-07-04 14:42 ` [PATCH v3 35/35] OvmfPkg/OvmfXen: use RealTimeClockRuntimeDxe from EmbeddedPkg Anthony PERARD
2019-07-05 12:21 ` [edk2-devel] [PATCH v3 00/35] Specific platform to run OVMF in Xen PVH and HVM guests Laszlo Ersek
2019-07-19 16:42   ` Anthony PERARD
2019-07-22 19:09     ` Laszlo Ersek
2019-07-23 11:37       ` Anthony PERARD
2019-07-30  9:03         ` Laszlo Ersek
2019-07-05 15:06 ` Laszlo Ersek
2019-07-10 14:12 ` 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-list 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=20190723094207.ccnzyzuma4ydpugi@Air-de-Roger \
    --to=devel@edk2.groups.io \
    /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: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox