summaryrefslogtreecommitdiffstats
path: root/sys/dev/hyperv/vmbus
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2013-09-09 08:07:46 +0000
committergrehan <grehan@FreeBSD.org>2013-09-09 08:07:46 +0000
commit182a56e295b4378df6a37e1b8422fb6eec08613a (patch)
treef5547d3cd15ee1a4dc5d59529652353928079365 /sys/dev/hyperv/vmbus
parent9394ef331eb7d0ba7f22583970cc84b62ad9f19a (diff)
downloadFreeBSD-src-182a56e295b4378df6a37e1b8422fb6eec08613a.zip
FreeBSD-src-182a56e295b4378df6a37e1b8422fb6eec08613a.tar.gz
Latest update from Microsoft.
Obtained from: Microsoft Hyper-v dev team
Diffstat (limited to 'sys/dev/hyperv/vmbus')
-rw-r--r--sys/dev/hyperv/vmbus/hv_hv.c79
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c33
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h56
3 files changed, 59 insertions, 109 deletions
diff --git a/sys/dev/hyperv/vmbus/hv_hv.c b/sys/dev/hyperv/vmbus/hv_hv.c
index 0e73bdc..e3f3ae0 100644
--- a/sys/dev/hyperv/vmbus/hv_hv.c
+++ b/sys/dev/hyperv/vmbus/hv_hv.c
@@ -43,6 +43,7 @@
#include "hv_vmbus_priv.h"
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
+
#define HV_X64_CPUID_MIN 0x40000005
#define HV_X64_CPUID_MAX 0x4000ffff
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
@@ -51,7 +52,6 @@
static u_int hv_get_timecount(struct timecounter *tc);
-static u_int hv_get_timecount(struct timecounter *tc);
static inline void do_cpuid_inline(unsigned int op, unsigned int *eax,
unsigned int *ebx, unsigned int *ecx, unsigned int *edx) {
@@ -76,7 +76,7 @@ static struct timecounter hv_timecounter = {
static u_int
hv_get_timecount(struct timecounter *tc)
{
- u_int now = hv_vmbus_read_msr(HV_X64_MSR_TIME_REF_COUNT);
+ u_int now = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
return (now);
}
@@ -217,13 +217,13 @@ hv_vmbus_init(void)
* Write our OS info
*/
uint64_t os_guest_info = HV_FREEBSD_GUEST_ID;
- hv_vmbus_write_msr(HV_X64_MSR_GUEST_OS_ID, os_guest_info);
+ wrmsr(HV_X64_MSR_GUEST_OS_ID, os_guest_info);
hv_vmbus_g_context.guest_id = os_guest_info;
/*
* See if the hypercall page is already set
*/
- hypercall_msr.as_uint64_t = hv_vmbus_read_msr(HV_X64_MSR_HYPERCALL);
+ hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL);
virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
KASSERT(virt_addr != NULL,
("Error VMBUS: malloc failed to allocate page during init!"));
@@ -233,13 +233,13 @@ hv_vmbus_init(void)
hypercall_msr.enable = 1;
hypercall_msr.guest_physical_address =
(hv_get_phys_addr(virt_addr) >> PAGE_SHIFT);
- hv_vmbus_write_msr(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64_t);
+ wrmsr(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64_t);
/*
* Confirm that hypercall page did get set up
*/
hypercall_msr.as_uint64_t = 0;
- hypercall_msr.as_uint64_t = hv_vmbus_read_msr(HV_X64_MSR_HYPERCALL);
+ hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL);
if (!hypercall_msr.enable)
goto cleanup;
@@ -276,7 +276,7 @@ hv_vmbus_init(void)
if (virt_addr != NULL) {
if (hypercall_msr.enable) {
hypercall_msr.as_uint64_t = 0;
- hv_vmbus_write_msr(HV_X64_MSR_HYPERCALL,
+ wrmsr(HV_X64_MSR_HYPERCALL,
hypercall_msr.as_uint64_t);
}
@@ -302,7 +302,7 @@ hv_vmbus_cleanup(void)
if (hv_vmbus_g_context.guest_id == HV_FREEBSD_GUEST_ID) {
if (hv_vmbus_g_context.hypercall_page != NULL) {
hypercall_msr.as_uint64_t = 0;
- hv_vmbus_write_msr(HV_X64_MSR_HYPERCALL,
+ wrmsr(HV_X64_MSR_HYPERCALL,
hypercall_msr.as_uint64_t);
free(hv_vmbus_g_context.hypercall_page, M_DEVBUF);
hv_vmbus_g_context.hypercall_page = NULL;
@@ -376,18 +376,17 @@ hv_vmbus_signal_event()
* @brief hv_vmbus_synic_init
*/
void
-hv_vmbus_synic_init(void *irq_arg)
+hv_vmbus_synic_init(void *arg)
{
int cpu;
- uint32_t irq_vector;
hv_vmbus_synic_simp simp;
hv_vmbus_synic_siefp siefp;
hv_vmbus_synic_scontrol sctrl;
hv_vmbus_synic_sint shared_sint;
uint64_t version;
+ hv_setup_args* setup_args = (hv_setup_args *)arg;
- irq_vector = *((uint32_t *) (irq_arg));
cpu = PCPU_GET(cpuid);
if (hv_vmbus_g_context.hypercall_page == NULL)
@@ -406,65 +405,50 @@ hv_vmbus_synic_init(void *irq_arg)
/*
* TODO: Check the version
*/
- version = hv_vmbus_read_msr(HV_X64_MSR_SVERSION);
-
- hv_vmbus_g_context.syn_ic_msg_page[cpu] =
- malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
- KASSERT(hv_vmbus_g_context.syn_ic_msg_page[cpu] != NULL,
- ("Error VMBUS: malloc failed for allocating page!"));
- if (hv_vmbus_g_context.syn_ic_msg_page[cpu] == NULL)
- goto cleanup;
+ version = rdmsr(HV_X64_MSR_SVERSION);
- hv_vmbus_g_context.syn_ic_event_page[cpu] =
- malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
- KASSERT(hv_vmbus_g_context.syn_ic_event_page[cpu] != NULL,
- ("Error VMBUS: malloc failed to allocate page!"));
- if (hv_vmbus_g_context.syn_ic_event_page[cpu] == NULL)
- goto cleanup;
+
+ hv_vmbus_g_context.syn_ic_msg_page[cpu] = setup_args->page_buffers[0];
+ hv_vmbus_g_context.syn_ic_event_page[cpu] = setup_args->page_buffers[1];
/*
* Setup the Synic's message page
*/
- simp.as_uint64_t = hv_vmbus_read_msr(HV_X64_MSR_SIMP);
+ simp.as_uint64_t = rdmsr(HV_X64_MSR_SIMP);
simp.simp_enabled = 1;
simp.base_simp_gpa = ((hv_get_phys_addr(
hv_vmbus_g_context.syn_ic_msg_page[cpu])) >> PAGE_SHIFT);
- hv_vmbus_write_msr(HV_X64_MSR_SIMP, simp.as_uint64_t);
+ wrmsr(HV_X64_MSR_SIMP, simp.as_uint64_t);
/*
* Setup the Synic's event page
*/
- siefp.as_uint64_t = hv_vmbus_read_msr(HV_X64_MSR_SIEFP);
+ siefp.as_uint64_t = rdmsr(HV_X64_MSR_SIEFP);
siefp.siefp_enabled = 1;
siefp.base_siefp_gpa = ((hv_get_phys_addr(
hv_vmbus_g_context.syn_ic_event_page[cpu])) >> PAGE_SHIFT);
- hv_vmbus_write_msr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
+ wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
- shared_sint.vector = irq_vector; /*HV_SHARED_SINT_IDT_VECTOR + 0x20; */
+ /*HV_SHARED_SINT_IDT_VECTOR + 0x20; */
+ shared_sint.vector = setup_args->vector;
shared_sint.masked = FALSE;
shared_sint.auto_eoi = FALSE;
- hv_vmbus_write_msr(
- HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT,
+ wrmsr(HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT,
shared_sint.as_uint64_t);
/* Enable the global synic bit */
- sctrl.as_uint64_t = hv_vmbus_read_msr(HV_X64_MSR_SCONTROL);
+ sctrl.as_uint64_t = rdmsr(HV_X64_MSR_SCONTROL);
sctrl.enable = 1;
- hv_vmbus_write_msr(HV_X64_MSR_SCONTROL, sctrl.as_uint64_t);
+ wrmsr(HV_X64_MSR_SCONTROL, sctrl.as_uint64_t);
hv_vmbus_g_context.syn_ic_initialized = TRUE;
return;
-
- cleanup:
-
- free(hv_vmbus_g_context.syn_ic_msg_page[cpu], M_DEVBUF);
- free(hv_vmbus_g_context.syn_ic_msg_page[cpu], M_DEVBUF);
}
/**
@@ -483,7 +467,7 @@ void hv_vmbus_synic_cleanup(void *arg)
if (cpu != 0)
return; /* TODO: XXXKYS: SMP? */
- shared_sint.as_uint64_t = hv_vmbus_read_msr(
+ shared_sint.as_uint64_t = rdmsr(
HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT);
shared_sint.masked = 1;
@@ -491,25 +475,20 @@ void hv_vmbus_synic_cleanup(void *arg)
/*
* Disable the interrupt
*/
- hv_vmbus_write_msr(
+ wrmsr(
HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT,
shared_sint.as_uint64_t);
- simp.as_uint64_t = hv_vmbus_read_msr(HV_X64_MSR_SIMP);
+ simp.as_uint64_t = rdmsr(HV_X64_MSR_SIMP);
simp.simp_enabled = 0;
simp.base_simp_gpa = 0;
- hv_vmbus_write_msr(HV_X64_MSR_SIMP, simp.as_uint64_t);
+ wrmsr(HV_X64_MSR_SIMP, simp.as_uint64_t);
- siefp.as_uint64_t = hv_vmbus_read_msr(HV_X64_MSR_SIEFP);
+ siefp.as_uint64_t = rdmsr(HV_X64_MSR_SIEFP);
siefp.siefp_enabled = 0;
siefp.base_siefp_gpa = 0;
- hv_vmbus_write_msr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
-
- contigfree(hv_vmbus_g_context.syn_ic_msg_page[cpu],
- PAGE_SIZE, M_DEVBUF);
- contigfree(hv_vmbus_g_context.syn_ic_event_page[cpu],
- PAGE_SIZE, M_DEVBUF);
+ wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
}
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
index e010308..08c6112 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
@@ -68,6 +68,7 @@ static int vmbus_rid;
struct resource *intr_res;
static int vmbus_irq = VMBUS_IRQ;
static int vmbus_inited;
+static hv_setup_args setup_args; /* only CPU 0 supported at this time */
/**
* @brief Software interrupt thread routine to handle channel messages from
@@ -117,7 +118,7 @@ vmbus_msg_swintr(void *dummy)
* This will cause message queue rescan to possibly
* deliver another msg from the hypervisor
*/
- hv_vmbus_write_msr(HV_X64_MSR_EOM, 0);
+ wrmsr(HV_X64_MSR_EOM, 0);
}
}
}
@@ -339,8 +340,7 @@ vmbus_bus_init(void)
int io_bus:4;
uint32_t io_lowreg;
};
-
- int ret;
+ int i, ret;
unsigned int vector = 0;
struct intsrc *isrc;
struct ioapic_intsrc *intpin;
@@ -418,15 +418,28 @@ vmbus_bus_init(void)
/**
* Notify the hypervisor of our irq.
*/
+ setup_args.vector = vector;
+ for(i = 0; i < 2; i++) {
+ setup_args.page_buffers[i] =
+ malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (setup_args.page_buffers[i] == NULL) {
+ KASSERT(setup_args.page_buffers[i] != NULL,
+ ("Error VMBUS: malloc failed!"));
+ if (i > 0)
+ free(setup_args.page_buffers[0], M_DEVBUF);
+ goto cleanup4;
+ }
+ }
- smp_rendezvous(NULL, hv_vmbus_synic_init, NULL, &vector);
+ /* only CPU #0 supported at this time */
+ smp_rendezvous(NULL, hv_vmbus_synic_init, NULL, &setup_args);
- /**
+ /*
* Connect to VMBus in the root partition
*/
ret = hv_vmbus_connect();
- if (ret)
+ if (ret != 0)
goto cleanup4;
hv_vmbus_request_channel_offers();
@@ -440,7 +453,6 @@ vmbus_bus_init(void)
bus_teardown_intr(vmbus_devp, intr_res, vmbus_cookiep);
cleanup3:
-
bus_release_resource(vmbus_devp, SYS_RES_IRQ, vmbus_rid, intr_res);
cleanup2:
@@ -490,11 +502,18 @@ vmbus_init(void)
static void
vmbus_bus_exit(void)
{
+ int i;
+
hv_vmbus_release_unattached_channels();
hv_vmbus_disconnect();
smp_rendezvous(NULL, hv_vmbus_synic_cleanup, NULL, NULL);
+ for(i = 0; i < 2; i++) {
+ if (setup_args.page_buffers[i] != 0)
+ free(setup_args.page_buffers[i], M_DEVBUF);
+ }
+
hv_vmbus_cleanup();
/* remove swi, bus and intr resource */
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index 739acb1..4607d50 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -675,58 +675,6 @@ int hv_vmbus_post_message(void *buffer, size_t buf_size);
int hv_vmbus_set_event(uint32_t child_rel_id);
void hv_vmbus_on_events(void *);
-/*
- * static inline functions
- * (with some helper macros for reading/writing to model specific registers)
- */
-
-#ifdef __x86_64__
-
-#define HV_VMBUS_READ_MSR(reg, v) { \
- uint32_t h, l; \
- __asm__ __volatile__("rdmsr" \
- : "=a" (l), "=d" (h) \
- : "c" (reg)); \
- v = (((uint64_t)h) << 32) | l; \
-}
-
-#define HV_VMBUS_WRITE_MSR(reg, v) { \
- uint32_t h, l; \
- l = (uint32_t)(((uint64_t)(v)) & 0xFFFFFFFF); \
- h = (uint32_t)((((uint64_t)(v)) >> 32) & 0xFFFFFFFF); \
- __asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (reg), "a" (l), "d" (h)); \
-}
-
-#else
-
-#define HV_VMBUS_READ_MSR(reg, v) \
- __asm__ __volatile__("rdmsr" \
- : "=A" (v) \
- : "c" (reg))
-
-#define HV_VMBUS_WRITE_MSR(reg, v) \
- __asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (reg), "A" ((uint64_t)v))
-
-#endif
-
-static inline unsigned long long
-hv_vmbus_read_msr(int msr)
-{
- unsigned long long val;
- HV_VMBUS_READ_MSR(msr, val);
- return (val);
-}
-
-static inline
-void hv_vmbus_write_msr(int msr, uint64_t val)
-{
- HV_VMBUS_WRITE_MSR(msr, val);
- return;
-}
/*
* The guest OS needs to register the guest ID with the hypervisor.
@@ -766,5 +714,9 @@ static inline uint64_t hv_generate_guest_id(
return guest_id;
}
+typedef struct {
+ unsigned int vector;
+ void *page_buffers[2];
+} hv_setup_args;
#endif /* __HYPERV_PRIV_H__ */
OpenPOWER on IntegriCloud