diff --git a/MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf index 02ee5827d4..e10f9c542d 100644 --- a/MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf +++ b/MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -95,6 +95,7 @@ gMsvmPkgTokenSpaceGuid.PcdHmatSize ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdTpmEnabled ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdVirtualBatteryEnabled ## CONSUMES + gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdWatchdogEnabled ## CONSUMES [Pcd.X64] diff --git a/MsvmPkg/AcpiPlatformDxe/Dsdt.c b/MsvmPkg/AcpiPlatformDxe/Dsdt.c index 224537c1c6..1d62bac3ab 100644 --- a/MsvmPkg/AcpiPlatformDxe/Dsdt.c +++ b/MsvmPkg/AcpiPlatformDxe/Dsdt.c @@ -33,6 +33,7 @@ typedef struct _DSDT_AML_DATA UINT8 ProcIdleEnabled; UINT8 CxlMemoryEnabled; UINT16 NvdimmCount; + UINT8 VmbusEnabled; } DSDT_AML_DATA; typedef struct _DSDT_AML_DESCRIPTOR @@ -138,6 +139,7 @@ Return Value: data->ProcIdleEnabled = PcdGetBool(PcdProcIdleEnabled); data->CxlMemoryEnabled = PcdGetBool(PcdCxlMemoryEnabled); data->NvdimmCount = PcdGet16(PcdNvdimmCount); + data->VmbusEnabled = PcdGetBool(PcdVmbusEnabled); DEBUG((DEBUG_VERBOSE, "--- %a: Mmio1Start 0x%lx\n", __func__, data->Mmio1Start)); DEBUG((DEBUG_VERBOSE, "--- %a: Mmio1Length 0x%lx\n", __func__, data->Mmio1Length)); diff --git a/MsvmPkg/AcpiTables/Dsdt.asl b/MsvmPkg/AcpiTables/Dsdt.asl index abd5c3a0ba..12a6822e50 100644 --- a/MsvmPkg/AcpiTables/Dsdt.asl +++ b/MsvmPkg/AcpiTables/Dsdt.asl @@ -63,6 +63,7 @@ DefinitionBlock ( PADE,8, // Processor Aggregator Device enabled/disabled CCFG,8, // CXL memory support enabled/disabled NCNT,16, // NVDIMM count + VCFG,8, // VMBus enabled/disabled } // Supported machine sleep states ========================================= @@ -140,6 +141,7 @@ DefinitionBlock ( { Name(_HID, "ACPI0004") Name(_UID, 0) + Name(_CRS, ResourceTemplate() { @@ -166,19 +168,27 @@ DefinitionBlock ( Method(_INI, 0) { - // Update the DWORDMemory resource descriptor with the low MMIO region. - Store(MG2B, MIN6) - Store(MG2L, LEN6) - Store(MG2L, Local0) - Add(MIN6, Decrement(Local0), MAX6) + // Update the DWORDMemory descriptor with the low MMIO region + // only if the region has nonzero size. + If(LGreater(MG2L, 0)) + { + Store(MG2B, MIN6) + Store(MG2L, LEN6) + Store(MG2L, Local0) + Add(MIN6, Decrement(Local0), MAX6) + } - // Update the QWORDMemory resource descriptor with the high MMIO region. - ShiftLeft (HMIB, 20, Local1) - ShiftLeft (HMIL, 20, Local2) - Store(Local1, MIN7) - Store(Local2, LEN7) - Store(Local2, Local0) - Add(MIN7, Decrement(Local0), MAX7) + // Update the QWORDMemory descriptor with the high MMIO region + // only if the region has nonzero size. + If(LGreater(HMIL, 0)) + { + ShiftLeft (HMIB, 20, Local1) + ShiftLeft (HMIL, 20, Local2) + Store(Local1, MIN7) + Store(Local2, LEN7) + Store(Local2, Local0) + Add(MIN7, Decrement(Local0), MAX7) + } } } @@ -306,74 +316,77 @@ DefinitionBlock ( // VMBus ================================================================== - Device(\_SB.VMOD.VMBS) + If(LGreater(VCFG, 0)) { - Name(STA, 0xF) - Name(_ADR, 0x00) + Device(\_SB.VMOD.VMBS) + { + Name(STA, 0xF) + Name(_ADR, 0x00) #if defined(_DSDT_ARM_) - Name(_CCA, One) + Name(_CCA, One) #endif - Name(_DDN, "VMBUS") - Name(_HID, "MSFT1000") - Name(_CID, "VMBus") - Name(_UID, 0) - Method(_DIS, 0) { And(STA, 0xD, STA) } - Method(_PS0, 0) { Or(STA, 0xF, STA) } - Method(_STA, 0) - { - return(STA) - } - - // Older versions of this DSDT implemented _PS3 improperly, as: - // Name(_PS3, 0) - // This is intentionally a do-nothing method in case any version of Windows requires _PS3 to be implemented - - Method(_PS3, 0) { return(STA) } - - // TODO: SPIs are not available to the guest on AARCH64, which is what - // PcdVmbusVector is currently defined as. Supposedly it should use a PPI, - // but those are strange because they're reserved for hypervisor devices. - // - // Windows doesn't boot when VmBus is given an SPI, since it's unable to - // allocate any since none exist in guests. Thus, leave it out on AARCH64 - // for now. - // - // Linux may need this field if it's not hardcoded, unsure. - // - // Additionally, no Interrupt-Signaled event devices currently work either, - // due to SPIs not being available to guests. - Name(_CRS, + Name(_DDN, "VMBUS") + Name(_HID, "MSFT1000") + Name(_CID, "VMBus") + Name(_UID, 0) + Method(_DIS, 0) { And(STA, 0xD, STA) } + Method(_PS0, 0) { Or(STA, 0xF, STA) } + Method(_STA, 0) + { + return(STA) + } - // Include an interrupt resource so that Linux VMs can get IDT - // entries. - // - // N.B. All Windows VMs that support UEFI also support - // getting IDT entries via other mechanisms, so this is not - // necessary for Windows. + // Older versions of this DSDT implemented _PS3 improperly, as: + // Name(_PS3, 0) + // This is intentionally a do-nothing method in case any version of Windows requires _PS3 to be implemented - ResourceTemplate() - { + Method(_PS3, 0) { return(STA) } + + // TODO: SPIs are not available to the guest on AARCH64, which is what + // PcdVmbusVector is currently defined as. Supposedly it should use a PPI, + // but those are strange because they're reserved for hypervisor devices. + // + // Windows doesn't boot when VmBus is given an SPI, since it's unable to + // allocate any since none exist in guests. Thus, leave it out on AARCH64 + // for now. + // + // Linux may need this field if it's not hardcoded, unsure. + // + // Additionally, no Interrupt-Signaled event devices currently work either, + // due to SPIs not being available to guests. + Name(_CRS, + + // Include an interrupt resource so that Linux VMs can get IDT + // entries. + // + // N.B. All Windows VMs that support UEFI also support + // getting IDT entries via other mechanisms, so this is not + // necessary for Windows. + + ResourceTemplate() + { #if defined(_DSDT_INTEL_) - // Older Linux kernels like RHEL/CentOS don't seem to be able to - // parse the new Extended Interrupt Descriptor resource type (see ACPI Section 6.4.3.6), - // so we instead use the old legacy IRQ description which - // becomes the short form of Interrupt Descriptor (ACPI Section 5.4.2.1) - // which only supports legacy PIC devices to describe up to 15 - // interrupts. VMBUS is interrupt 5 on X64, so this is okay. - IRQ(Edge,ActiveHigh,Exclusive) - {FixedPcdGet8(PcdVmbusVector)} + // Older Linux kernels like RHEL/CentOS don't seem to be able to + // parse the new Extended Interrupt Descriptor resource type (see ACPI Section 6.4.3.6), + // so we instead use the old legacy IRQ description which + // becomes the short form of Interrupt Descriptor (ACPI Section 5.4.2.1) + // which only supports legacy PIC devices to describe up to 15 + // interrupts. VMBUS is interrupt 5 on X64, so this is okay. + IRQ(Edge,ActiveHigh,Exclusive) + {FixedPcdGet8(PcdVmbusVector)} #else - // On AArch64, we select a PPI (16) because Linux expects it to - // be available to all CPUs. - Interrupt(ResourceConsumer, Edge, ActiveHigh, Exclusive) - {FixedPcdGet8(PcdVmbusVector)} + // On AArch64, we select a PPI (16) because Linux expects it to + // be available to all CPUs. + Interrupt(ResourceConsumer, Edge, ActiveHigh, Exclusive) + {FixedPcdGet8(PcdVmbusVector)} #endif - } - ) + } + ) + } } // TPM ==================================================================== diff --git a/MsvmPkg/Include/BiosInterface.h b/MsvmPkg/Include/BiosInterface.h index 72e6d6f9ec..42951361b4 100644 --- a/MsvmPkg/Include/BiosInterface.h +++ b/MsvmPkg/Include/BiosInterface.h @@ -789,7 +789,9 @@ typedef struct _UEFI_CONFIG_FLAGS UINT64 Dhcp6DuidTypeLlt : 1; UINT64 CxlMemoryEnabled : 1; UINT64 MtrrsInitializedAtLoad : 1; - UINT64 Reserved:35; + UINT64 HvSintEnabled : 1; // Reserved; used by other codebase. + UINT64 VmbusDisabled : 1; + UINT64 Reserved:33; } Flags; } UEFI_CONFIG_FLAGS; diff --git a/MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.c b/MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.c index 470c4388b5..ca787830d9 100644 --- a/MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.c +++ b/MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.c @@ -425,6 +425,10 @@ DeviceBootManagerBeforeConsole ( *DevicePath = NULL; *PlatformConsoles = NULL; + if (!PcdGetBool(PcdVmbusEnabled)) { + goto Exit; + } + Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiVmbusProtocolGuid, diff --git a/MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.inf b/MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.inf index 40d7a5e73b..f52f9c937d 100644 --- a/MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.inf +++ b/MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.inf @@ -69,6 +69,7 @@ CONSTRUCTOR = DeviceBootManagerConstructor gMsvmPkgTokenSpaceGuid.PcdIsVmbfsBoot gMsvmPkgTokenSpaceGuid.PcdLogoFile gMsvmPkgTokenSpaceGuid.PcdPxeIpV6 + gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled gMsvmPkgTokenSpaceGuid.PcdVpciBootEnabled [Depex] diff --git a/MsvmPkg/MsvmPkg.dec b/MsvmPkg/MsvmPkg.dec index b326956e97..8ec8f9b7a4 100644 --- a/MsvmPkg/MsvmPkg.dec +++ b/MsvmPkg/MsvmPkg.dec @@ -298,6 +298,7 @@ gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated|FALSE|BOOLEAN|0x6064 gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled|FALSE|BOOLEAN|0x6065 gMsvmPkgTokenSpaceGuid.PcdMtrrsInitializedAtLoad|FALSE|BOOLEAN|0x6067 + gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled|TRUE|BOOLEAN|0x6068 # UEFI_CONFIG_PROCESSOR_INFORMATION gMsvmPkgTokenSpaceGuid.PcdProcessorCount|0x0|UINT32|0x6032 diff --git a/MsvmPkg/MsvmPkgAARCH64.dsc b/MsvmPkg/MsvmPkgAARCH64.dsc index 48dccb27c1..5d3d598193 100644 --- a/MsvmPkg/MsvmPkgAARCH64.dsc +++ b/MsvmPkg/MsvmPkgAARCH64.dsc @@ -697,6 +697,7 @@ gMsvmPkgTokenSpaceGuid.PcdWatchdogEnabled|FALSE gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated|FALSE gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled|TRUE # UEFI_CONFIG_PROCESSOR_INFORMATION gMsvmPkgTokenSpaceGuid.PcdProcessorCount|0x0 diff --git a/MsvmPkg/MsvmPkgX64.dsc b/MsvmPkg/MsvmPkgX64.dsc index a62c04c226..2523eb8be1 100644 --- a/MsvmPkg/MsvmPkgX64.dsc +++ b/MsvmPkg/MsvmPkgX64.dsc @@ -715,6 +715,7 @@ gMsvmPkgTokenSpaceGuid.PcdWatchdogEnabled|FALSE gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated|FALSE gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled|TRUE # UEFI_CONFIG_PROCESSOR_INFORMATION gMsvmPkgTokenSpaceGuid.PcdProcessorCount|0x0 diff --git a/MsvmPkg/PlatformPei/AArch64/Mmu.c b/MsvmPkg/PlatformPei/AArch64/Mmu.c index 093beaf4cc..898adafb02 100644 --- a/MsvmPkg/PlatformPei/AArch64/Mmu.c +++ b/MsvmPkg/PlatformPei/AArch64/Mmu.c @@ -404,6 +404,7 @@ ConfigureMmu( UINT64 highMmioSize; #define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 6 ARM_MEMORY_REGION_DESCRIPTOR virtualMemoryTable[MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS]; + UINTN index = 0; // // Convert PCD page counts to byte addresses/sizes using safe @@ -423,10 +424,8 @@ ConfigureMmu( // // Validate that MMIO regions fit within the physical address space. - // The host may provide MMIO ranges that extend beyond the CPU's - // physical address width, which would cause page table entries for - // unmappable addresses. // + if (highMmioSize > 0) { UINT64 highMmioEnd; if (RETURN_ERROR(SafeUint64Add(highMmioBaseAddress, highMmioSize, &highMmioEnd))) @@ -447,62 +446,71 @@ ConfigureMmu( } // - // Fill table that drives the mmu setup functions. + // Build the memory map based on which MMIO gaps are present. // - // From zero to beginning of low MMIO gap. - virtualMemoryTable[0].PhysicalBase = 0; - virtualMemoryTable[0].VirtualBase = virtualMemoryTable[0].PhysicalBase; - virtualMemoryTable[0].Length = (SIZE_4GB - lowMmioSize); - virtualMemoryTable[0].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK; - - // First MMIO gap. - virtualMemoryTable[1].PhysicalBase = virtualMemoryTable[0].PhysicalBase + virtualMemoryTable[0].Length; - virtualMemoryTable[1].VirtualBase = virtualMemoryTable[1].PhysicalBase; - virtualMemoryTable[1].Length = lowMmioSize; - virtualMemoryTable[1].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; - - // From 4GB to beginning of high MMIO gap. - virtualMemoryTable[2].PhysicalBase = virtualMemoryTable[1].PhysicalBase + virtualMemoryTable[1].Length; - virtualMemoryTable[2].VirtualBase = virtualMemoryTable[2].PhysicalBase; - - if (RETURN_ERROR(SafeUint64Sub(highMmioBaseAddress, virtualMemoryTable[2].PhysicalBase, &virtualMemoryTable[2].Length))) + + // From zero to beginning of low MMIO gap (or to 4GB if no low gap). + virtualMemoryTable[index].PhysicalBase = 0; + virtualMemoryTable[index].VirtualBase = 0; + virtualMemoryTable[index].Length = (SIZE_4GB - lowMmioSize); + virtualMemoryTable[index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK; + index++; + + // Low MMIO gap (only if nonzero size). + if (lowMmioSize > 0) { - DEBUG((DEBUG_ERROR, "ConfigureMmu: highMmioBaseAddress (0x%lx) < PhysicalBase (0x%lx)\n", - highMmioBaseAddress, virtualMemoryTable[2].PhysicalBase)); - ASSERT(FALSE); - return EFI_INVALID_PARAMETER; + virtualMemoryTable[index].PhysicalBase = virtualMemoryTable[index - 1].PhysicalBase + virtualMemoryTable[index - 1].Length; + virtualMemoryTable[index].VirtualBase = virtualMemoryTable[index].PhysicalBase; + virtualMemoryTable[index].Length = lowMmioSize; + virtualMemoryTable[index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; + index++; } - virtualMemoryTable[2].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK; + if (highMmioSize > 0) + { + // From end of low gap (or 4GB) to beginning of high MMIO gap. + virtualMemoryTable[index].PhysicalBase = virtualMemoryTable[index - 1].PhysicalBase + virtualMemoryTable[index - 1].Length; + virtualMemoryTable[index].VirtualBase = virtualMemoryTable[index].PhysicalBase; + + if (RETURN_ERROR(SafeUint64Sub(highMmioBaseAddress, virtualMemoryTable[index].PhysicalBase, &virtualMemoryTable[index].Length))) + { + DEBUG((DEBUG_ERROR, "ConfigureMmu: highMmioBaseAddress (0x%lx) < PhysicalBase (0x%lx)\n", + highMmioBaseAddress, virtualMemoryTable[index].PhysicalBase)); + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + + virtualMemoryTable[index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK; + index++; - // Second MMIO gap. - virtualMemoryTable[3].PhysicalBase = virtualMemoryTable[2].PhysicalBase + virtualMemoryTable[2].Length; - virtualMemoryTable[3].VirtualBase = virtualMemoryTable[3].PhysicalBase; - virtualMemoryTable[3].Length = highMmioSize; - virtualMemoryTable[3].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; + // High MMIO gap. + virtualMemoryTable[index].PhysicalBase = virtualMemoryTable[index - 1].PhysicalBase + virtualMemoryTable[index - 1].Length; + virtualMemoryTable[index].VirtualBase = virtualMemoryTable[index].PhysicalBase; + virtualMemoryTable[index].Length = highMmioSize; + virtualMemoryTable[index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; + index++; + } // To top of address space. - virtualMemoryTable[4].PhysicalBase = virtualMemoryTable[3].PhysicalBase + virtualMemoryTable[3].Length; - virtualMemoryTable[4].VirtualBase = virtualMemoryTable[4].PhysicalBase; + virtualMemoryTable[index].PhysicalBase = virtualMemoryTable[index - 1].PhysicalBase + virtualMemoryTable[index - 1].Length; + virtualMemoryTable[index].VirtualBase = virtualMemoryTable[index].PhysicalBase; - // - // Validate that the final region does not underflow. This should - // not happen given the MMIO validation above, but check defensively. - // - if (virtualMemoryTable[4].PhysicalBase > MaxAddress) + if (virtualMemoryTable[index].PhysicalBase > MaxAddress) { DEBUG((DEBUG_ERROR, "ConfigureMmu: PhysicalBase (0x%lx) > MaxAddress (0x%lx)\n", - virtualMemoryTable[4].PhysicalBase, MaxAddress)); + virtualMemoryTable[index].PhysicalBase, MaxAddress)); FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); } - virtualMemoryTable[4].Length = (MaxAddress - virtualMemoryTable[4].PhysicalBase) + 1; - virtualMemoryTable[4].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK; + virtualMemoryTable[index].Length = (MaxAddress - virtualMemoryTable[index].PhysicalBase) + 1; + virtualMemoryTable[index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK; + index++; - virtualMemoryTable[5].PhysicalBase = 0; - virtualMemoryTable[5].VirtualBase = 0; - virtualMemoryTable[5].Length = 0; - virtualMemoryTable[5].Attributes = 0; + // End-of-table sentinel. + virtualMemoryTable[index].PhysicalBase = 0; + virtualMemoryTable[index].VirtualBase = 0; + virtualMemoryTable[index].Length = 0; + virtualMemoryTable[index].Attributes = 0; // Lookup the Table Level to get the information LookupAddresstoRootTable(MaxAddress, &T0SZ, &RootTableEntryCount); diff --git a/MsvmPkg/PlatformPei/Config.c b/MsvmPkg/PlatformPei/Config.c index 6532196828..2bb05c554c 100644 --- a/MsvmPkg/PlatformPei/Config.c +++ b/MsvmPkg/PlatformPei/Config.c @@ -762,6 +762,7 @@ DebugDumpUefiConfigStruct( DEBUG((DEBUG_VERBOSE, "\tWatchdogEnabled: %u\n", flags->Flags.WatchdogEnabled)); DEBUG((DEBUG_VERBOSE, "\tTpmLocalityRegsEnabled: %u\n", flags->Flags.TpmLocalityRegsEnabled)); DEBUG((DEBUG_VERBOSE, "\tMtrrsInitializedAtLoad: %u\n", flags->Flags.MtrrsInitializedAtLoad)); + DEBUG((DEBUG_VERBOSE, "\tVmbusDisabled: %u\n", flags->Flags.VmbusDisabled)); break; } case UefiConfigProcessorInformation: @@ -941,6 +942,7 @@ ConfigSetUefiConfigFlags( PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdWatchdogEnabled, (UINT8) ConfigFlags->Flags.WatchdogEnabled)); PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdTpmLocalityRegsEnabled, (UINT8) ConfigFlags->Flags.TpmLocalityRegsEnabled)); PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdMtrrsInitializedAtLoad, (UINT8) ConfigFlags->Flags.MtrrsInitializedAtLoad)); + PEI_FAIL_FAST_IF_FAILED(PcdSetBoolS(PcdVmbusEnabled, !ConfigFlags->Flags.VmbusDisabled)); // // If memory protections are enabled, configure the value into the HOB. @@ -1558,16 +1560,20 @@ Return Value: // // Figure out which entry is the low gap, and which is the high. + // Use base >= 4GB as the indicator for the high gap. When an + // entry is empty (size=0) its base is typically 0, so it will + // naturally fall into the "low" bucket and be skipped downstream. // - if (mmioRanges->Ranges[0].MmioPageNumberStart < mmioRanges->Ranges[1].MmioPageNumberStart) + if (mmioRanges->Ranges[0].MmioPageNumberStart >= (SIZE_4GB / SIZE_4KB) && + mmioRanges->Ranges[0].MmioSizeInPages > 0) { - lowGap = 0; - highGap = 1; + highGap = 0; + lowGap = 1; } else { - lowGap = 1; - highGap = 0; + lowGap = 0; + highGap = 1; } // @@ -1585,35 +1591,37 @@ Return Value: UINT64 highGapEnd; // - // Low gap size (in pages) must not exceed 4GB worth of pages, - // and the low gap must end at or before the 4GB boundary. + // Low gap: if size is nonzero, it must not exceed 4GB worth + // of pages, and must end at or before the 4GB boundary. // - if ((lowGapSize > (SIZE_4GB / SIZE_4KB)) || - RETURN_ERROR(SafeUint64Add(lowGapBase, lowGapSize, &lowGapEnd)) || - (lowGapEnd > (SIZE_4GB / SIZE_4KB))) + if (lowGapSize > 0) { - DEBUG((DEBUG_ERROR, "***Invalid low MMIO gap range\n")); - FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); + if ((lowGapSize > (SIZE_4GB / SIZE_4KB)) || + RETURN_ERROR(SafeUint64Add(lowGapBase, lowGapSize, &lowGapEnd)) || + (lowGapEnd > (SIZE_4GB / SIZE_4KB))) + { + DEBUG((DEBUG_ERROR, "***Invalid low MMIO gap range\n")); + FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); + } } // - // High gap must start at or above the 4GB boundary (in pages) - // to avoid unsigned underflow when computing memory region - // lengths in ConfigureMmu(). + // High gap: if size is nonzero, it must start at or above + // the 4GB boundary and must not overflow the address space. // - if (highGapBase < (SIZE_4GB / SIZE_4KB)) + if (highGapSize > 0) { - DEBUG((DEBUG_ERROR, "***Invalid high MMIO gap base below 4GB\n")); - FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); - } + if (highGapBase < (SIZE_4GB / SIZE_4KB)) + { + DEBUG((DEBUG_ERROR, "***Invalid high MMIO gap base below 4GB\n")); + FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); + } - // - // High gap must not overflow the address space. - // - if (RETURN_ERROR(SafeUint64Add(highGapBase, highGapSize, &highGapEnd))) - { - DEBUG((DEBUG_ERROR, "***High MMIO gap range overflow\n")); - FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); + if (RETURN_ERROR(SafeUint64Add(highGapBase, highGapSize, &highGapEnd))) + { + DEBUG((DEBUG_ERROR, "***High MMIO gap range overflow\n")); + FAIL_FAST_UNEXPECTED_HOST_BEHAVIOR(); + } } } @@ -1794,6 +1802,8 @@ Return Value: header = (UEFI_CONFIG_HEADER*) ((UINT64) header + header->Length); } + + if (requiredStructures.AsUINT64 != AllStructuresFound) { DEBUG((DEBUG_ERROR, "Missing required structures, found structures: 0x%x\n", requiredStructures.AsUINT64)); diff --git a/MsvmPkg/PlatformPei/Platform.c b/MsvmPkg/PlatformPei/Platform.c index e513a8be37..fcdd8c78c7 100644 --- a/MsvmPkg/PlatformPei/Platform.c +++ b/MsvmPkg/PlatformPei/Platform.c @@ -701,45 +701,54 @@ Return Value: #endif // - // Low and high MMIO range + // Low and high MMIO ranges. Declared based on nonzero size rather than + // VMBus state, since chipset devices (e.g. TPM) may need low MMIO even + // without VMBus. // + if (PcdGet64(PcdLowMmioGapSizeInPages) > 0) + { #if defined (MDE_CPU_X64) - HobAddMmioRange( - PcdGet64(PcdLowMmioGapBasePageNumber) * SIZE_4KB, - PcdGet64(PcdLowMmioGapSizeInPages) * SIZE_4KB - ); + HobAddMmioRange( + PcdGet64(PcdLowMmioGapBasePageNumber) * SIZE_4KB, + PcdGet64(PcdLowMmioGapSizeInPages) * SIZE_4KB + ); #elif defined(MDE_CPU_AARCH64) - // - // For ARM64 we are still using the BiosDevice for runtime services. - // However the registers are now in MMIO space instead of IO space. Therefore the - // addresses need to be translated after the guest calls SetVirtualAddressMap. - // To have the address range included with the guest's call to SetVirtualAddressMap - // the range has to be declared as DXE runtime memory. That has to be done in DXE phase - // by a driver so the range can't be declared as MMIO here. Therefore leave that page - // out of this early general platform declaration. - // - UINT64 GapBase = PcdGet32(PcdBiosBaseAddress); - UINT64 GapSize = SIZE_4KB; - UINT64 FirstRangeBase = PcdGet64(PcdLowMmioGapBasePageNumber) * SIZE_4KB; - UINT64 FirstRangeSize = GapBase - FirstRangeBase; - UINT64 SecondRangeBase = FirstRangeBase + FirstRangeSize + GapSize; - UINT64 SecondRangeSize = (PcdGet64(PcdLowMmioGapSizeInPages) * SIZE_4KB) - - (FirstRangeSize + GapSize); - - HobAddMmioRange( - FirstRangeBase, - FirstRangeSize - ); + // + // For ARM64 we are still using the BiosDevice for runtime services. + // However the registers are now in MMIO space instead of IO space. Therefore the + // addresses need to be translated after the guest calls SetVirtualAddressMap. + // To have the address range included with the guest's call to SetVirtualAddressMap + // the range has to be declared as DXE runtime memory. That has to be done in DXE phase + // by a driver so the range can't be declared as MMIO here. Therefore leave that page + // out of this early general platform declaration. + // + UINT64 GapBase = PcdGet32(PcdBiosBaseAddress); + UINT64 GapSize = SIZE_4KB; + UINT64 FirstRangeBase = PcdGet64(PcdLowMmioGapBasePageNumber) * SIZE_4KB; + UINT64 FirstRangeSize = GapBase - FirstRangeBase; + UINT64 SecondRangeBase = FirstRangeBase + FirstRangeSize + GapSize; + UINT64 SecondRangeSize = (PcdGet64(PcdLowMmioGapSizeInPages) * SIZE_4KB) - + (FirstRangeSize + GapSize); + + HobAddMmioRange( + FirstRangeBase, + FirstRangeSize + ); - HobAddMmioRange( - SecondRangeBase, - SecondRangeSize - ); + HobAddMmioRange( + SecondRangeBase, + SecondRangeSize + ); #endif - HobAddMmioRange( - PcdGet64(PcdHighMmioGapBasePageNumber) * SIZE_4KB, - PcdGet64(PcdHighMmioGapSizeInPages) * SIZE_4KB - ); + } + + if (PcdGet64(PcdHighMmioGapSizeInPages) > 0) + { + HobAddMmioRange( + PcdGet64(PcdHighMmioGapBasePageNumber) * SIZE_4KB, + PcdGet64(PcdHighMmioGapSizeInPages) * SIZE_4KB + ); + } // // Read PcieBarApertures first -- these determine which bridges UEFI diff --git a/MsvmPkg/PlatformPei/PlatformPei.inf b/MsvmPkg/PlatformPei/PlatformPei.inf index 3fd7c92cc0..7eb5b21818 100644 --- a/MsvmPkg/PlatformPei/PlatformPei.inf +++ b/MsvmPkg/PlatformPei/PlatformPei.inf @@ -196,6 +196,7 @@ gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled gMsvmPkgTokenSpaceGuid.PcdMtrrsInitializedAtLoad + gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled gMsvmPkgTokenSpaceGuid.PcdPcieBarAperturesPtr gMsvmPkgTokenSpaceGuid.PcdPcieBarAperturesSize diff --git a/MsvmPkg/VmbusDxe/VmbusDxe.inf b/MsvmPkg/VmbusDxe/VmbusDxe.inf index 0e09956d11..ffa71195fa 100644 --- a/MsvmPkg/VmbusDxe/VmbusDxe.inf +++ b/MsvmPkg/VmbusDxe/VmbusDxe.inf @@ -56,6 +56,7 @@ gInternalEventServicesProtocolGuid ## CONSUMES [Pcd] + gMsvmPkgTokenSpaceGuid.PcdVmbusEnabled ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdVmbusSintVector ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdVmbusSintIndex ## CONSUMES gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaBoundary ## CONSUMES diff --git a/MsvmPkg/VmbusDxe/VmbusRoot.c b/MsvmPkg/VmbusDxe/VmbusRoot.c index 9aa1662b37..86522fcc47 100644 --- a/MsvmPkg/VmbusDxe/VmbusRoot.c +++ b/MsvmPkg/VmbusDxe/VmbusRoot.c @@ -2282,6 +2282,12 @@ VmbusDriverInitialize ( DEBUG((DEBUG_VERBOSE, ">>> %a\n", __func__)); + if (!PcdGetBool(PcdVmbusEnabled)) + { + DEBUG((DEBUG_INFO, "VMBus is disabled by configuration, not starting VMBus driver.\n")); + return EFI_UNSUPPORTED; + } + mVmbusImageHandle = ImageHandle; //