Skip to content

Commit

Permalink
PCIBridge: Add support for device property injection
Browse files Browse the repository at this point in the history
  • Loading branch information
Goldfish64 committed Oct 15, 2023
1 parent c0344f9 commit a3740c8
Show file tree
Hide file tree
Showing 10 changed files with 373 additions and 20 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ MacHyperVSupport Changelog
#### v0.9.7
- Fixed disks on a passed-in PCI device not being usable
- Improved PCI interrupt handling to support both MSI and MSI-X
- Added support for device property injection on PCI devices

#### v0.9.6
- Fixed extended registers not being correctly read/written
Expand Down
8 changes: 8 additions & 0 deletions MacHyperVSupport.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@
41BF4621288CDF1200813670 /* HyperVNetwork.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41B41BDB26C74B4C00926A0D /* HyperVNetwork.cpp */; };
41BF4622288CDF1200813670 /* HyperVNetworkRNDIS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41B41BE626CDC42D00926A0D /* HyperVNetworkRNDIS.cpp */; };
41BF4623288CDF1200813670 /* HyperVPCIBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41F9B8EE2849792200E0DCB2 /* HyperVPCIBridge.cpp */; };
41CF8A6F2ADB89A9002AC7A4 /* HyperVPCIBridgeDevProps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41CF8A6E2ADB89A9002AC7A4 /* HyperVPCIBridgeDevProps.cpp */; };
41CF8A702ADB89A9002AC7A4 /* HyperVPCIBridgeDevProps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41CF8A6E2ADB89A9002AC7A4 /* HyperVPCIBridgeDevProps.cpp */; };
41E2EC78263F894300BBE18F /* HyperVControllerInterrupts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41E2EC77263F894300BBE18F /* HyperVControllerInterrupts.cpp */; };
41E5E20C28C5766700E6E84F /* HyperVController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41E5E20A28C5766700E6E84F /* HyperVController.cpp */; };
41E5E20D28C5766700E6E84F /* HyperVController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41E5E20A28C5766700E6E84F /* HyperVController.cpp */; };
Expand Down Expand Up @@ -349,6 +351,8 @@
41BE4113263EDEA10018C52B /* libkmod.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libkmod.a; path = MacKernelSDK/Library/x86_64/libkmod.a; sourceTree = "<group>"; };
41BF462A288CDF1200813670 /* MacHyperVSupportMonterey.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MacHyperVSupportMonterey.kext; sourceTree = BUILT_PRODUCTS_DIR; };
41C604AB28B2F87600FB77ED /* HyperV-versions.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "HyperV-versions.md"; sourceTree = "<group>"; };
41CF8A6E2ADB89A9002AC7A4 /* HyperVPCIBridgeDevProps.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HyperVPCIBridgeDevProps.cpp; sourceTree = "<group>"; };
41CF8A712ADB8DD2002AC7A4 /* DevicePathPropertyDatabase.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DevicePathPropertyDatabase.hpp; sourceTree = "<group>"; };
41E2EC77263F894300BBE18F /* HyperVControllerInterrupts.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HyperVControllerInterrupts.cpp; sourceTree = "<group>"; };
41E5E20A28C5766700E6E84F /* HyperVController.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HyperVController.cpp; sourceTree = "<group>"; };
41E5E20B28C5766700E6E84F /* HyperVController.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = HyperVController.hpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -822,8 +826,10 @@
41F9B8ED284978EF00E0DCB2 /* PCIBridge */ = {
isa = PBXGroup;
children = (
41CF8A712ADB8DD2002AC7A4 /* DevicePathPropertyDatabase.hpp */,
41F9B8EE2849792200E0DCB2 /* HyperVPCIBridge.cpp */,
41F9B8EF2849792200E0DCB2 /* HyperVPCIBridge.hpp */,
41CF8A6E2ADB89A9002AC7A4 /* HyperVPCIBridgeDevProps.cpp */,
41F9B8F7284983FF00E0DCB2 /* HyperVPCIBridgePrivate.cpp */,
41F9B8FA2849846700E0DCB2 /* HyperVPCIBridgeRegs.hpp */,
);
Expand Down Expand Up @@ -1234,6 +1240,7 @@
416E429D265751CC006DED6D /* HyperVVMBusDevicePrivate.cpp in Sources */,
41F2E44B2666F37B00CE26CE /* HyperVPCIProvider.cpp in Sources */,
41F9B8FF284BA20700E0DCB2 /* HyperVModuleDevice.cpp in Sources */,
41CF8A6F2ADB89A9002AC7A4 /* HyperVPCIBridgeDevProps.cpp in Sources */,
4191F6F528F4E71A00809232 /* HyperVTimeSyncUserClient.cpp in Sources */,
418F843D2648BA38003F8520 /* HyperVStorage.cpp in Sources */,
41F2E42D2665B64D00CE26CE /* HyperVPlatformProvider.cpp in Sources */,
Expand Down Expand Up @@ -1279,6 +1286,7 @@
41BF461A288CDF1200813670 /* HyperVVMBusDevicePrivate.cpp in Sources */,
41BF461B288CDF1200813670 /* HyperVPCIProvider.cpp in Sources */,
41BF461C288CDF1200813670 /* HyperVModuleDevice.cpp in Sources */,
41CF8A702ADB89A9002AC7A4 /* HyperVPCIBridgeDevProps.cpp in Sources */,
4191F6F628F4E71A00809232 /* HyperVTimeSyncUserClient.cpp in Sources */,
41BF461D288CDF1200813670 /* HyperVStorage.cpp in Sources */,
41BF461E288CDF1200813670 /* HyperVPlatformProvider.cpp in Sources */,
Expand Down
16 changes: 16 additions & 0 deletions MacHyperVSupport/Controller/HyperV.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ typedef enum : UInt32 {

#define kHyperVHypercallRetryCount 100

inline void
guid_unparse(const uuid_t uu, uuid_string_t out) {
snprintf(out,
sizeof(uuid_string_t),
"%02x%02x%02x%02x-"
"%02x%02x-"
"%02x%02x-"
"%02x%02x-"
"%02x%02x%02x%02x%02x%02x",
uu[3], uu[2], uu[1], uu[0],
uu[5], uu[4],
uu[7], uu[6],
uu[8], uu[9],
uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
}

#if DEBUG
//
// Debug logging function.
Expand Down
85 changes: 85 additions & 0 deletions MacHyperVSupport/PCIBridge/DevicePathPropertyDatabase.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//
// DevicePathPropertyDatabase.hpp
// Device Path Property Database definitions
//
// Copyright © 2023 Goldfish64. All rights reserved.
//

#ifndef DevicePathPropertyDatabase_h
#define DevicePathPropertyDatabase_h

#define EFI_DEVICE_PATH_PROPERTY_DATABASE_VERSION 1

/**
This protocol can be used on any device handle to obtain generic path/location
information concerning the physical device or logical device. If the handle does
not logically map to a physical device, the handle may not necessarily support
the device path protocol. The device path describes the location of the device
the handle is for. The size of the Device Path can be determined from the structures
that make up the Device Path.
**/
#define HARDWARE_DEVICE_PATH 0x01
#define HW_VENDOR_DP 0x04

#define END_DEVICE_PATH 0x7F
#define END_DEVICE_PATH_SUBTYPE 0xFF

//
// Generic EFI device path node.
//
typedef struct {
UInt8 type;
UInt8 subType;
UInt8 length[2];
} EfiDevicePathProtocol;

//
// Hyper-V vendor-specific EFI device path node.
//
typedef struct {
EfiDevicePathProtocol header;

uuid_t vendorGuid;
uuid_t deviceTypeGuid;
uuid_t instanceGuid;
} HyperVDevPropEfiDevicePathProtocol;

//
// Device path property data set.
// There should be a pair of these for each property present,
// one for the property name (in unicode) and one for the data.
//
typedef struct {
UInt32 Size;
UInt8 Data[];
} EfiDevicePathPropertyData;

//
// Device path property node header.
//
typedef struct {
UInt32 Size;
UInt32 NumberOfProperties;
} EfiDevicePathPropertyBufferNodeHeader;

//
// Device path property node.
//
typedef struct {
EfiDevicePathPropertyBufferNodeHeader Hdr;
HyperVDevPropEfiDevicePathProtocol DevicePath; // Variable length
//EfiDevicePathPropertyData Data; // Variable length
} EfiDevicePathPropertyBufferNode;

//
// Device path property buffer.
//
typedef struct {
UInt32 Size;
UInt32 Version;
UInt32 NumberOfNodes;

EfiDevicePathPropertyBufferNode Nodes[]; // Each node is variable in length.
} EfiDevicePathPropertyBuffer;

#endif
11 changes: 11 additions & 0 deletions MacHyperVSupport/PCIBridge/HyperVPCIBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,14 @@ void HyperVPCIBridge::configWrite8(IOPCIAddressSpace space, UInt8 offset, UInt8
//
writePCIConfig(offset32, sizeof (UInt8), data);
}

bool HyperVPCIBridge::initializeNub(IOPCIDevice *nub, OSDictionary *from) {
//
// Merge any injected properties into device tree.
//
IOReturn status = mergePropertiesFromDT(nub->getFunctionNumber(), from);
if (status != kIOReturnSuccess) {
return false;
}
return super::initializeNub(nub, from);
}
24 changes: 20 additions & 4 deletions MacHyperVSupport/PCIBridge/HyperVPCIBridge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,28 +45,42 @@ class HyperVPCIBridge : public HV_PCIBRIDGE_CLASS {
UInt32 _pciFunctionsCount = 0;
HyperVPCIFunctionDescription *_pciFunctions = nullptr;

//
// Packet handling.
//
bool wakePacketHandler(VMBusPacketHeader *pktHeader, UInt32 pktHeaderLength, UInt8 *pktData, UInt32 pktDataLength);
void handlePacket(VMBusPacketHeader *pktHeader, UInt32 pktHeaderLength, UInt8 *pktData, UInt32 pktDataLength);
void handleIncomingPCIMessage(HyperVPCIBridgeIncomingMessageHeader *pciMsgHeader, UInt32 msgSize);

//
// PCI bus setup.
//
IOReturn connectPCIBus();
IOReturn negotiateProtocolVersion();
IOReturn allocatePCIConfigWindow();
IOReturn queryBusRelations();
IOReturn enterPCID0();
IOReturn queryResourceRequirements();
IOReturn sendResourcesAssigned(UInt32 slot);

inline UInt64 getBarSize(UInt64 barValue) {
if (barValue < UINT32_MAX) {
barValue |= 0xFFFFFFFF00000000;
}
return roundup((1 + ~(barValue & kHyperVPCIBarMemoryMask)), PAGE_SIZE);
}


//
// Device properties handling.
//
IOReturn mergePropertiesFromDT(UInt32 slot, OSDictionary *dict);

//
// PCI config space read/write.
//
UInt32 readPCIConfig(UInt32 offset, UInt8 size);
void writePCIConfig(UInt32 offset, UInt8 size, UInt32 value);

public:
//
// IOService overrides.
Expand Down Expand Up @@ -97,11 +111,13 @@ class HyperVPCIBridge : public HV_PCIBRIDGE_CLASS {
HVDBGLOG("start");
return _pciBusNumber;
}

UInt8 lastBusNum() APPLE_KEXT_OVERRIDE {
HVDBGLOG("start");
return _pciBusNumber;
}

bool initializeNub(IOPCIDevice *nub, OSDictionary *from) APPLE_KEXT_OVERRIDE;
};

#endif
Loading

0 comments on commit a3740c8

Please sign in to comment.