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.
next prev 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