On 02/07/13 17:50, David Woodhouse wrote:
> I've been doing some testing of SMP booting with CSM, and the only
> problem I've found is one that *doesn't* seem to be CSM-specific. Even
> when I boot Linux in EFI mode under OVMF with more than one CPU, it
> complains that the MTRRs are inconsistent:
> 
> [    0.059069] mtrr: your CPUs had inconsistent fixed MTRR settings
> [    0.060002] mtrr: your CPUs had inconsistent variable MTRR settings
> [    0.060667] mtrr: your CPUs had inconsistent MTRRdefType settings
> [    0.061002] mtrr: probably your BIOS does not setup all CPUs.
> [    0.061611] mtrr: corrected configuration.
> 
> Presumably we should be bringing up the secondary CPUs to set the MTRRs
> on them.... do we currently bring them up at all, or is all that
> infrastructure code absent? I still haven't really found my way around
> the code base to find this for myself...

When I began to tinker with OVMF, it supported one CPU only.

After a while QemuInstallAcpiMadtTable() was added
[AcpiPlatformDxe/Qemu.c] which grabs the number of CPUs via fw_cfg and
installs an according MADT. This seemed to be enough to get several
VCPUs recognized & working in a Linux guest.

When discussing related stuff internally @ RH, Gleb (CC'd) replied to me
with the following (I hope you won't mind me quoting you here, Gleb;
msgid <[email protected]>):

On 05/15/12 11:50, Gleb Natapov wrote:
> On Tue, May 15, 2012 at 11:34:43AM +0200, Laszlo Ersek wrote:

>> (I think SeaBIOS counts the VCPUs (for ACPI table building) with a
>> mixture of fw_cfg client code and actually booting the AP's and making
>> them increment a counter. If possible I too think we should avoid
>> booting the AP's in OVMF.)
>>
> Firmware has to boot APs because certain configuration has to be made
> to each CPU before starting an OS. SeaBIOS configures MTRRs, on real
> HW firmware may need to disable VMX for instance. Counting cpus at
> this stage is done to make sure that all CPUs completed running before
> continuing. There are two numbers concerning vcpu count. First is how
> much vcpus are actually present during boot (this number is in RTC CMOS)
> and second is max number of vcpus we want to support (this one is in
> fw_cfg). Missing vcpus can be hotplugged latter, so appropriate ACPI
> entries should be created for them.

I obviously chose to ignore ^W postpone the bits about VCPU hotplug, but
more importantly for this discussion, after seeing that the MADT was
sufficient to get multiple VCPUs working, I also turned my eyes away, in
terror, from the MTRR parts.

Chapter 13 in Volume 2 of the Platform Initialization Specification
("Driver Execution Environment Core Interface") speaks about
EFI_MP_SERVICES_PROTOCOL, and there's a reference to MTRR programming:

    MP Services Protocol may also be used to program and configure
    processors, such as MTRR synchronization for memory space attributes
    setting in DXE Services.

>From a cursory look, this is a protocol that OvmfPkg should produce. I
have no idea what would consume it. (The spec names the "ACPI module" as
an example.) An actual implementation appears to be in
"EmulatorPkg/CpuRuntimeDxe/MpService.c"; in accordance with the spec,
it's a DXE_DRIVER.

Also, OvmfPkg already seems to use UefiCpuPkg/Library/MtrrLib: function
MemDetect() in "OvmfPkg/PlatformPei/MemDetect.c" calls
MtrrSetMemoryAttribute().

Earlier I had a RHEL-5 Xen bug
<https://bugzilla.redhat.com/show_bug.cgi?id=713123> that required me to
educate myself, to a minimal extent, about MTRRs. As far as I remember,
one must configure the same caching attributes for the same memory
ranges across all processors.

What's more, I vaguely recall some Intel CPU model from which onwards
one has to do this MTRR configuration all at once on all CPUs. (Boot all
CPUs, line them up at a barrier, then have all of them enter the code
configuring the same MTRRs. Line them up again at the exit barrier, once
each one is done, they're free to go independent.)

... Intel SDM vol 3A, 11.11.8 MTRR Considerations in MP Systems

I *guess* this is something we could do in
EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(), by calling
MtrrSetMemoryAttribute() from the callback function that we pass as
EFI_AP_PROCEDURE to StartupAllAPs().

EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
  our callback function
    MtrrSetMemoryAttribute()

The memory map might have to be passed in via "This"
(EFI_MP_SERVICES_PROTOCOL embedded in our own struct type as usual), or
maybe we could get it from gBS->GetMemoryMap().

Laszlo

------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to