root/src/add-ons/kernel/bus_managers/hyperv/arch/x86/hyperv_cpu.h
/*
 * Copyright 2026 John Davis. All rights reserved.
 * Distributed under the terms of the MIT License.
 */
#ifndef _HYPERV_x86_CPU_H_
#define _HYPERV_x86_CPU_H_


// CPUID leaves
#define IA32_CPUID_LEAF_HYPERVISOR                              0x40000000
#define IA32_CPUID_LEAF_HV_INT_ID                               0x40000001
#define IA32_CPUID_LEAF_HV_SYS_ID                               0x40000002
#define IA32_CPUID_LEAF_HV_FEAT_ID                              0x40000003
#define IA32_CPUID_LEAF_HV_IMP_RECOMMENDS               0x40000004
#define IA32_CPUID_LEAF_HV_IMP_LIMITS                   0x40000005
#define IA32_CPUID_LEAF_HV_IMP_FEATURES                 0x40000006

// Hyper-V signature "Hv#1"
#define HV_CPUID_INTERFACE_ID                                   0x31237648

// Hyper-V x86 features from feature CPUID leaf, eax register
// https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/datatypes/hv_partition_privilege_mask
#define HV_CPUID_FEATURE_VP_RUNTIME                             (1 << 0)
#define HV_CPUID_FEATURE_TIME_REF_COUNTER               (1 << 1)
#define HV_CPUID_FEATURE_SYNIC                                  (1 << 2)
#define HV_CPUID_FEATURE_SYNTIMER                               (1 << 3)
#define HV_CPUID_FEATURE_APIC                                   (1 << 4)
#define HV_CPUID_FEATURE_HYPERCALL                              (1 << 5)
#define HV_CPUID_FEATURE_VP_INDEX                               (1 << 6)
#define HV_CPUID_FEATURE_RESET                                  (1 << 7)
#define HV_CPUID_FEATURE_STATS                                  (1 << 8)
#define HV_CPUID_FEATURE_REFERENCE_TSC                  (1 << 9)
#define HV_CPUID_FEATURE_GUEST_IDLE                             (1 << 10)
#define HV_CPUID_FEATURE_FREQUENCY                              (1 << 11)
#define HV_CPUID_FEATURE_REENLIGHTMENT                  (1 << 13)

// Hyper-V x86 features from feature CPUID leaf, ebx register
#define HV_CPUID_FEATURE_HYPERCALL_POST_MESSAGE         (1 << 4)
#define HV_CPUID_FEATURE_HYPERCALL_SIGNAL_EVENT         (1 << 5)

// Required feature bits for VMBus operation
#define HV_CPUID_EAX_REQUIRED_FEATURES  (HV_CPUID_FEATURE_SYNIC | HV_CPUID_FEATURE_SYNTIMER \
        | HV_CPUID_FEATURE_HYPERCALL)
#define HV_CPUID_EBX_REQUIRED_FEATURES  (HV_CPUID_FEATURE_HYPERCALL_POST_MESSAGE \
        | HV_CPUID_FEATURE_HYPERCALL_SIGNAL_EVENT)

// MSR registers
#define IA32_MSR_HV_GUEST_OS_ID                                 0x40000000
#define IA32_MSR_HV_HYPERCALL                                   0x40000001
#define IA32_MSR_HV_VP_INDEX                                    0x40000002
#define IA32_MSR_HV_RESET                                               0x40000003
#define IA32_MSR_HV_VP_RUNTIME                                  0x40000010

#define IA32_MSR_HV_TIME_REF_COUNT                              0x40000020
#define IA32_MSR_HV_REFERENCE_TSC                               0x40000021
#define IA32_MSR_HV_TSC_FREQUENCY                               0x40000022
#define IA32_MSR_HV_APIC_FREQUENCY                              0x40000023

#define IA32_MSR_HV_EOI                                                 0x40000070
#define IA32_MSR_HV_ICR                                                 0x40000071
#define IA32_MSR_HV_TPR                                                 0x40000072
#define IA32_MSR_HV_APIC_ASSIST_PAGE                    0x40000073

#define IA32_MSR_HV_SCONTROL                                    0x40000080
#define IA32_MSR_HV_SVERSION                                    0x40000081
#define IA32_MSR_HV_SIEFP                                               0x40000082
#define IA32_MSR_HV_SIMP                                                0x40000083
#define IA32_MSR_HV_EOM                                                 0x40000084

#define IA32_MSR_HV_SINT0                                               0x40000090
#define IA32_MSR_HV_STIMER0_CONFIG                              0x400000B0
#define IA32_MSR_HV_STIMER0_COUNT                               0x400000B1

#define IA32_MSR_HV_GUEST_IDLE                                  0x400000f0

// MSR guest ID bits
#define IA32_MSR_HV_GUEST_OS_ID_BUILD_MASK              0x000000000000FFFFULL
#define IA32_MSR_HV_GUEST_OS_ID_VERSION_MASK    0x0000FFFFFFFF0000ULL
#define IA32_MSR_HV_GUEST_OS_ID_VERSION_SHIFT   16
#define IA32_MSR_HV_GUEST_OS_ID_OSID_MASK               0x00FF000000000000ULL
#define IA32_MSR_HV_GUEST_OS_ID_OSID_SHIFT              48
#define IA32_MSR_HV_GUEST_OS_ID_OSTYPE_MASK             0x7F00000000000000ULL
#define IA32_MSR_HV_GUEST_OS_ID_OSTYPE_SHIFT    56
#define IA32_MSR_HV_GUEST_OS_ID_OPEN_SOURCE             (1ULL << 63)

// MSR hypercall bits
#define IA32_MSR_HV_HYPERCALL_ENABLE                    (1ULL << 0)
#define IA32_MSR_HV_HYPERCALL_RSVD_MASK                 0x0FFEULL
#define IA32_MSR_HV_HYPERCALL_PAGE_SHIFT                12

// MSR SynIC control bits
#define IA32_MSR_HV_SCONTROL_ENABLE                             (1ULL << 0)
#define IA32_MSR_HV_SCONTROL_RSVD_MASK                  0xFFFFFFFFFFFFFFFEULL

// MSR SIEFP bits
#define IA32_MSR_HV_SIEFP_ENABLE                                (1ULL << 0)
#define IA32_MSR_HV_SIEFP_RSVD_MASK                             0x0FFEULL
#define IA32_MSR_HV_SIEFP_PAGE_SHIFT                    12
#define IA32_MSR_HV_SIEFP_PAGE_MASK                             (~0ULL << IA32_MSR_HV_SIEFP_PAGE_SHIFT)

// MSR SIMP bits
#define IA32_MSR_HV_SIMP_ENABLE                                 (1ULL << 0)
#define IA32_MSR_HV_SIMP_RSVD_MASK                              0x0FFEULL
#define IA32_MSR_HV_SIMP_PAGE_SHIFT                             12
#define IA32_MSR_HV_SIMP_PAGE_MASK                              (~0ULL << IA32_MSR_HV_SIMP_PAGE_SHIFT)

// MSR SINT bits
#define IA32_MSR_HV_SINT_VECTOR_MASK                    0x00000000000000FFULL
#define IA32_MSR_HV_SINT_RSVD1_MASK                             0x000000000000FF00ULL
#define IA32_MSR_HV_SINT_MASKED                                 (1ULL << 16)
#define IA32_MSR_HV_SINT_AUTOEOI                                (1ULL << 17)
#define IA32_MSR_HV_SINT_POLLING                                (1ULL << 18)
#define IA32_MSR_HV_SINT_RSVD2_MASK                             0xFFFFFFFFFFFC0000ULL
#define IA32_MSR_HV_SINT_RSVD_MASK \
        (IA32_MSR_HV_SINT_RSVD1_MASK | IA32_MSR_HV_SINT_RSVD2_MASK)


// Version info reported to Hyper-V for hypercall purposes
// Report as FreeBSD 16.0, can optionally request a new OS type for Haiku
// https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/hypercall-interface#guest-os-identity-msr-for-open-source-operating-systems
#define HYPERV_FREEBSD_BUILD    0ULL
#define HYPERV_FREEBSD_VERSION  1600000ULL
#define HYPERV_FREEBSD_OSID             0ULL
#define HYPERV_FREEBSD_OSTYPE   0x2ULL

#define IA32_MSR_HV_GUEST_OS_ID_BUILD_FREEBSD \
        (HYPERV_FREEBSD_BUILD & IA32_MSR_HV_GUEST_OS_ID_BUILD_MASK)
#define IA32_MSR_HV_GUEST_OS_ID_VERSION_FREEBSD \
        ((HYPERV_FREEBSD_VERSION << IA32_MSR_HV_GUEST_OS_ID_VERSION_SHIFT) \
                & IA32_MSR_HV_GUEST_OS_ID_VERSION_MASK)
#define IA32_MSR_HV_GUEST_OS_ID_OSID_FREEBSD \
        ((HYPERV_FREEBSD_OSID << IA32_MSR_HV_GUEST_OS_ID_OSID_SHIFT) \
                & IA32_MSR_HV_GUEST_OS_ID_OSID_MASK)
#define IA32_MSR_HV_GUEST_OS_ID_OSTYPE_FREEBSD \
        ((HYPERV_FREEBSD_OSTYPE << IA32_MSR_HV_GUEST_OS_ID_OSTYPE_SHIFT) \
                & IA32_MSR_HV_GUEST_OS_ID_OSTYPE_MASK)

#define IA32_MSR_HV_GUEST_OS_ID_FREEBSD \
        (IA32_MSR_HV_GUEST_OS_ID_BUILD_FREEBSD \
        | IA32_MSR_HV_GUEST_OS_ID_VERSION_FREEBSD \
        | IA32_MSR_HV_GUEST_OS_ID_OSID_FREEBSD \
        | IA32_MSR_HV_GUEST_OS_ID_OSTYPE_FREEBSD \
        | IA32_MSR_HV_GUEST_OS_ID_OPEN_SOURCE)


#endif // _HYPERV_x86_CPU_H_