Skip to content

Commit

Permalink
hyperv/vmbus Add features and recommendation work
Browse files Browse the repository at this point in the history
  • Loading branch information
howard0su committed Apr 8, 2016
1 parent 3330e5a commit d1d031e
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 25 deletions.
6 changes: 6 additions & 0 deletions sys/dev/hyperv/vmbus/hv_et.c
Expand Up @@ -102,6 +102,12 @@ hv_et_intr(struct trapframe *frame)
static void
hv_et_identify (driver_t *driver, device_t parent)
{
if (vm_guest != VM_GUEST_HV)
return;

if (!(hv_features & HV_MSR_FEATURE_STIMER))
return;

if (device_find_child(parent, "hv_et", -1) != NULL)
return;

Expand Down
82 changes: 58 additions & 24 deletions sys/dev/hyperv/vmbus/hv_hv.c
Expand Up @@ -47,6 +47,8 @@ __FBSDID("$FreeBSD$");

#define HV_NANOSECONDS_PER_SEC 1000000000L

uint32_t hv_features;
uint32_t hv_recommendation;

static u_int hv_get_timecount(struct timecounter *tc);

Expand Down Expand Up @@ -76,32 +78,67 @@ hv_vmbus_query_hypervisor_presence(void)
}

/**
* @brief Get version of the windows hypervisor
* @brief Get information of the hypervisor
* @return 0 if hyperisor info is not present.
*/
static int
hv_vmbus_get_hypervisor_version(void)
hv_vmbus_get_hypervisor_info(void)
{
u_int regs[4];
unsigned int maxLeaf;
unsigned int op;

/*
* Its assumed that this is called after confirming that
* Viridian is present
* Query id and revision.
*/
op = HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION;
do_cpuid(op, regs);

maxLeaf = regs[0];
op = HV_CPU_ID_FUNCTION_HV_INTERFACE;
do_cpuid(op, regs);
if (regs[0] != 0x31237648 /* HV#1 */
|| maxLeaf < HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS)
return (0);

if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_VERSION) {
op = HV_CPU_ID_FUNCTION_MS_HV_VERSION;
do_cpuid(op, regs);
op = HV_CPU_ID_FUNCTION_MS_HV_VERSION;
do_cpuid(op, regs);
printf("Hyper-V Version: %d.%d.%d [SP%d]\n",
regs[1] >> 16, regs[1] & 0xffff, regs[0], regs[2]);
}

if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_FEATURES) {
op = HV_CPU_ID_FUNCTION_MS_HV_FEATURES;
do_cpuid(op, regs);
hv_features = regs[0];
if (bootverbose)
printf("Hyper-V Features: %08X %08X %08X %08X\n",
regs[0], regs[1], regs[2], regs[3]);
}

if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION) {
op = HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION;
do_cpuid(op, regs);
hv_recommendation = regs[0];
if (bootverbose)
printf("Hyper-V Recommendations: %08X %08X\n", regs[0], regs[1]);
}

if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS) {
op = HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS;
do_cpuid(op, regs);
if (bootverbose)
printf("Hyper-V Limits: Vcpu:%d Lcpu:%d Int:%d\n",
regs[0], regs[1], regs[2]);
}
return (maxLeaf);

if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE) {
op = HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE;
do_cpuid(op, regs);
if (bootverbose)
printf("Hyper-V HW Features: %08x AMD: %08x\n",
regs[0], regs[3]);
}

return (1);
}

/**
Expand Down Expand Up @@ -151,14 +188,17 @@ hv_vmbus_do_hypercall(uint64_t control, void* input, void* output)
static int
hv_vmbus_init(void* context)
{
int max_leaf;
hv_vmbus_x64_msr_hypercall_contents hypercall_msr;
void* virt_addr;

if (vm_guest != VM_GUEST_HV)
return (ENOTSUP);

max_leaf = hv_vmbus_get_hypervisor_version();
if (!hv_vmbus_get_hypervisor_info())
return (ENOTSUP);

if (!(hv_features & HV_MSR_FEATURE_HYPERCALL))
return (ENOTSUP);

/*
* Write our OS info
Expand Down Expand Up @@ -188,6 +228,11 @@ hv_vmbus_init(void* context)

hypercall_page = virt_addr;

if (hv_features & HV_MSR_FEATURE_REF_COUNT) {
/* register virtual timecounter */
tc_init(&hv_timecounter);
}

return (0);

cleanup:
Expand Down Expand Up @@ -279,16 +324,5 @@ hv_vmbus_signal_event(void *con_id)
return (status);
}

static void
hv_tc_init(void)
{
if (vm_guest != VM_GUEST_HV)
return;

/* register virtual timecounter */
tc_init(&hv_timecounter);
}

SYSINIT(hv_tc_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hv_tc_init, NULL);
SYSINIT(hv_init, SI_SUB_HYPERVISOR, SI_ORDER_ANY, hv_vmbus_init, NULL);
SYSINIT(hv_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hv_vmbus_init, NULL);
SYSUNINIT(hv_cleanup, SI_SUB_HYPERVISOR, SI_ORDER_ANY, hv_vmbus_cleanup, NULL);
11 changes: 10 additions & 1 deletion sys/dev/hyperv/vmbus/hv_vmbus_priv.h
Expand Up @@ -469,10 +469,17 @@ typedef enum {
HV_CPU_ID_FUNCTION_MS_HV_VERSION = 0x40000002,
HV_CPU_ID_FUNCTION_MS_HV_FEATURES = 0x40000003,
HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION = 0x40000004,
HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005
HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005,
HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE = 0x40000006

} hv_vmbus_cpuid_function;

#define HV_MSR_FEATURE_REF_COUNT (1 << 1)
#define HV_MSR_FEATURE_SYNCIC (1 << 2)
#define HV_MSR_FEATURE_STIMER (1 << 3)
#define HV_MSR_FEATURE_APIC (1 << 4)
#define HV_MSR_FEATURE_HYPERCALL (1 << 5)

/*
* Define the format of the SIMP register
*/
Expand Down Expand Up @@ -623,6 +630,8 @@ typedef enum {
/**
* Global variables
*/
extern uint32_t hv_features;
extern uint32_t hv_recommendation;

extern hv_vmbus_context hv_vmbus_g_context;
extern hv_vmbus_connection hv_vmbus_g_connection;
Expand Down

0 comments on commit d1d031e

Please sign in to comment.