From: "Laszlo Ersek" <lersek@redhat.com>
To: Gerd Hoffmann <kraxel@redhat.com>
Cc: devel@edk2.groups.io, Oliver Steffen <osteffen@redhat.com>,
Jiewen Yao <jiewen.yao@intel.com>,
Ard Biesheuvel <ardb+tianocore@kernel.org>
Subject: Re: [edk2-devel] [PATCH 1/3] OvmfPkg/PlatformPei: consider AP stacks for pei memory cap
Date: Wed, 31 Jan 2024 20:29:34 +0100 [thread overview]
Message-ID: <54eae7c0-0bfd-f464-1190-1d89d634884a@redhat.com> (raw)
In-Reply-To: <xhvhdo5czxfiulfxkjog25vvwhpk3lolnml3qhw6sdzpamtf7i@qqkahqirqach>
On 1/31/24 15:55, Gerd Hoffmann wrote:
> Hi,
>
>>> + if (MemoryCap > MAX_UINT32) {
>>> + MemoryCap = MAX_UINT32;
>>> + }
>>> +
>>
>> (2) This doesn't look good, for two reasons.
>>
>> First, if UINTN is UINT32, then we're too late to check. (If it's
>> intentional that the code be dead on IA32, then that should be
>> documented.)
>
> IA32 has an early exit in this function.
>
> Looking again I see this applies to 32-bit DXE only, so with mixed
> 32-bit PEI / 64-bit DXE we can still land here. Hmm, so yes, you
> have a point here.
>
> In practice we don't come even close to MAX_UINT32. With 4096 vcpus
> the amount of memory needed for the AP stacks sums up to 128 MB. The
> page table memory wouldn't grow that big too because OVMF will use at
> most 1 TB of address space if gigabyte pages are not available (to
> limit page table memory and boot time needed to set them all up).
>
>> Second, while returning MAX_UINT32 from this function is safe, it's
>> also obscure. After the call site, we've got
>>
>> MemoryBase = PlatformInfoHob->S3Supported && PlatformInfoHob->SmmSmramRequire ?
>> PcdGet32 (PcdOvmfDecompressionScratchEnd) :
>> PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize);
>> MemorySize = LowerMemorySize - MemoryBase;
>> if (MemorySize > PeiMemoryCap) {
>> MemoryBase = LowerMemorySize - PeiMemoryCap;
>> MemorySize = PeiMemoryCap;
>> }
>
> MemorySize is UINT64. So I guess the easiest would be to just switch
> MemoryCap variable and GetPeiMemoryCap() return value to UINT64 too.
> Avoids all the thinking and arguing whenever UINT32 is safe or not.
I consider that a cop-out; I'd want to see evidence (or deduce the
evidence myself) that UINT64 was safe, too. UINT64 is not "unlimited"
either.
In general, I don't want to do integer arithmetic without knowing the
potential value ranges at all times.
(1) It's great that we're discussing this, BTW -- an integer overflow is
already possible (at least in theory) after the second patch in the
series.
Before the series, TotalPages is at most 0x40201, so
EFI_PAGES_TO_SIZE(TotalPages) is at most ~1GB. We add SIZE_64MB to it;
that still fits in the UINT32 return value.
After the first patch in the series, a new increment is ApStacks; you
mention it never exceeds 128 MB in practice. So that's safe (in
practice).
However, after the second patch in the series, that no longer suffices
(in theory). As I calculated under patch#2, TotalPages can grow up to
and including 0x8040201, which means EFI_PAGES_TO_SIZE(TotalPages) is
~513 GB.
Meaning that,
(1.1) on IA32X64, the following
MemoryCap = EFI_PAGES_TO_SIZE (TotalPages) + ApStacks + SIZE_64MB;
already truncates (because EFI_PAGES_TO_SIZE takes a UINTN and produces
a UINTN, but UINTN is just UINT32); and that
(1.2) on X64, while "MemoryCap" itself is fine, the final
return (UINT32)(MemoryCap);
will truncate.
(2) Now, if we consider the 1TB address space limitation from
PlatformAddressWidthFromCpuid()
[OvmfPkg/Library/PlatformInitLib/MemDetect.c] that you highlight:
if (!Page1GSupport && (PhysBits > 40)) {
DEBUG ((DEBUG_INFO, "%a: limit PhysBits to 40 (no 1G pages available)\n", __func__));
PhysBits = 40;
}
then we get (from the exact calculation):
Level2Pages = BIT10;
Level3Pages = BIT1;
Level4Pages = 1;
Level5Pages = 1;
TotalPages = 1024 + 2 + 1 + 1;
and then EFI_PAGES_TO_SIZE(1028) is just ~ 4 MB. So the UINT32 retval is
safe, with the 1TB address space limitation in place -- but then we
should ASSERT the predicate here that PlatformAddressWidthFromCpuid()
ensures: ((PhysBits <= 40) || Page1GSupport)!
(3) Finally, if Page1GSupport is TRUE, and PhysMemAddressWidth is 57, we
get:
Level2Pages = 0;
Level3Pages = BIT18;
Level4Pages = BIT9;
Level5Pages = BIT0;
which produces the pre-series value 0x40201 for TotalPages -- so that
again will be safe for the UINT32 retval (the memory allocated for page
tables will be again ~1GB).
OK, summary:
- before calculating "End" and "Level2Pages" in patch#2, we should
ASSERT ((PhysBits <= 40) || Page1GSupport).
- I guess it is fine to assume that
(PcdCpuMaxLogicalProcessorNumber*PcdCpuApStackSize) will never
exceed a few hundred MB. Maybe add a comment?
- I suggest keeping the retval UINT32; there is no reason for widening
it to UINT64 (thanks to the 1TB address space limitation, without 1G
pages!)
- The pre-series assertion that (TotalPages <= 0x40201) remains correct,
after all, using the exact calculation (again due to the 1TB address
space limitation, without 1G pages).
>
> And maybe add an else branch to log a warning in case
> MemorySize < PeiMemoryCap.
That is a good idea even with the unchanged UINT32 retval type!
Laszlo
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114917): https://edk2.groups.io/g/devel/message/114917
Mute This Topic: https://groups.io/mt/104073297/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-01-31 19:29 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-31 11:59 [edk2-devel] [PATCH 0/3] OvmfPkg/PlatformPei: scaleability fixes for GetPeiMemoryCap() Gerd Hoffmann
2024-01-31 11:59 ` [edk2-devel] [PATCH 1/3] OvmfPkg/PlatformPei: consider AP stacks for pei memory cap Gerd Hoffmann
2024-01-31 14:08 ` Laszlo Ersek
2024-01-31 14:55 ` Gerd Hoffmann
2024-01-31 19:29 ` Laszlo Ersek [this message]
2024-01-31 11:59 ` [edk2-devel] [PATCH 2/3] OvmfPkg/PlatformPei: rewrite page table calculation Gerd Hoffmann
2024-01-31 15:13 ` Laszlo Ersek
2024-01-31 15:21 ` Laszlo Ersek
2024-01-31 16:28 ` Gerd Hoffmann
2024-02-01 21:04 ` Laszlo Ersek
2024-01-31 12:00 ` [edk2-devel] [PATCH 3/3] OvmfPkg/PlatformPei: log pei memory cap details Gerd Hoffmann
2024-01-31 15:38 ` 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=54eae7c0-0bfd-f464-1190-1d89d634884a@redhat.com \
--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