hyperv: Add reference counter support

Adds support for the Hyper-V partition reference counter.

Change-Id: Ie74b4d3af1b320b7b724776bdb6a22f643873f80
Reviewed-on: https://review.haiku-os.org/c/haiku/+/10500
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
John Davis
2026-03-17 06:25:53 +00:00
committed by Jérôme Duval
parent d5a5f22579
commit 4f6e4b41ba
6 changed files with 49 additions and 0 deletions
+1
View File
@@ -51,6 +51,7 @@ typedef struct hyperv_device_interface {
driver_module_info info; driver_module_info info;
uint32 (*get_bus_version)(hyperv_device cookie); uint32 (*get_bus_version)(hyperv_device cookie);
status_t (*get_reference_counter)(hyperv_device cookie, uint64* _count);
status_t (*open)(hyperv_device cookie, uint32 txLength, uint32 rxLength, status_t (*open)(hyperv_device cookie, uint32 txLength, uint32 rxLength,
hyperv_device_callback callback, void* callbackData); hyperv_device_callback callback, void* callbackData);
void (*close)(hyperv_device cookie); void (*close)(hyperv_device cookie);
@@ -12,6 +12,7 @@ VMBusDevice::VMBusDevice(device_node* node)
fNode(node), fNode(node),
fStatus(B_NO_INIT), fStatus(B_NO_INIT),
fChannelID(0), fChannelID(0),
fReferenceCounterSupported(false),
fDPCHandle(NULL), fDPCHandle(NULL),
fIsOpen(false), fIsOpen(false),
fRingGPADL(0), fRingGPADL(0),
@@ -41,6 +42,9 @@ VMBusDevice::VMBusDevice(device_node* node)
mutex_init(&fLock, "vmbus device lock"); mutex_init(&fLock, "vmbus device lock");
B_INITIALIZE_SPINLOCK(&fTXLock); B_INITIALIZE_SPINLOCK(&fTXLock);
B_INITIALIZE_SPINLOCK(&fRXLock); B_INITIALIZE_SPINLOCK(&fRXLock);
fReferenceCounterSupported = _IsReferenceCounterSupported();
TRACE("Reference counter: %s\n", fReferenceCounterSupported ? "yes" : "no");
} }
@@ -56,6 +56,15 @@ vmbus_device_get_bus_version(hyperv_device cookie)
} }
static status_t
vmbus_device_get_reference_counter(hyperv_device cookie, uint64* _count)
{
CALLED();
VMBusDevice* device = reinterpret_cast<VMBusDevice*>(cookie);
return device->GetReferenceCounter(_count);
}
static status_t static status_t
vmbus_device_open(hyperv_device cookie, uint32 txLength, uint32 rxLength, vmbus_device_open(hyperv_device cookie, uint32 txLength, uint32 rxLength,
hyperv_device_callback callback, void* callbackData) hyperv_device_callback callback, void* callbackData)
@@ -153,6 +162,7 @@ hyperv_device_interface gVMBusDeviceModule = {
}, },
vmbus_device_get_bus_version, vmbus_device_get_bus_version,
vmbus_device_get_reference_counter,
vmbus_device_open, vmbus_device_open,
vmbus_device_close, vmbus_device_close,
vmbus_device_read_packet, vmbus_device_read_packet,
@@ -47,6 +47,7 @@ public:
status_t InitCheck() const { return fStatus; } status_t InitCheck() const { return fStatus; }
uint32 GetBusVersion(); uint32 GetBusVersion();
status_t GetReferenceCounter(uint64* _count);
status_t Open(uint32 txLength, uint32 rxLength, status_t Open(uint32 txLength, uint32 rxLength,
hyperv_device_callback callback, void* callbackData); hyperv_device_callback callback, void* callbackData);
void Close(); void Close();
@@ -64,6 +65,7 @@ public:
status_t FreeGPADL(uint32 gpadl); status_t FreeGPADL(uint32 gpadl);
private: private:
bool _IsReferenceCounterSupported();
static void _CallbackHandler(void* arg); static void _CallbackHandler(void* arg);
static void _DPCHandler(void* arg); static void _DPCHandler(void* arg);
@@ -78,6 +80,7 @@ private:
device_node* fNode; device_node* fNode;
status_t fStatus; status_t fStatus;
uint32 fChannelID; uint32 fChannelID;
bool fReferenceCounterSupported;
mutex fLock; mutex fLock;
void* fDPCHandle; void* fDPCHandle;
bool fIsOpen; bool fIsOpen;
@@ -11,4 +11,5 @@ SubDirHdrs $(HAIKU_TOP) src add-ons kernel bus_managers acpi acpica include plat
KernelStaticLibrary hyperv_arch_bus_manager : KernelStaticLibrary hyperv_arch_bus_manager :
VMBus_x86.cpp VMBus_x86.cpp
VMBusDevice_x86.cpp
; ;
@@ -0,0 +1,30 @@
/*
* Copyright 2026 John Davis
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include <arch_cpu.h>
#include "hyperv_cpu.h"
#include "VMBusDevicePrivate.h"
status_t
VMBusDevice::GetReferenceCounter(uint64* _counter)
{
if (!fReferenceCounterSupported)
return B_NOT_SUPPORTED;
*_counter = x86_read_msr(IA32_MSR_HV_TIME_REF_COUNT);
return B_OK;
}
bool
VMBusDevice::_IsReferenceCounterSupported()
{
cpuid_info cpuInfo;
get_cpuid(&cpuInfo, IA32_CPUID_LEAF_HV_FEAT_ID, 0);
return (cpuInfo.regs.eax & HV_CPUID_FEATURE_TIME_REF_COUNTER) != 0;
}