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
