diff options
author | grehan <grehan@FreeBSD.org> | 2013-09-09 08:07:46 +0000 |
---|---|---|
committer | grehan <grehan@FreeBSD.org> | 2013-09-09 08:07:46 +0000 |
commit | 182a56e295b4378df6a37e1b8422fb6eec08613a (patch) | |
tree | f5547d3cd15ee1a4dc5d59529652353928079365 /sys/dev/hyperv/vmbus | |
parent | 9394ef331eb7d0ba7f22583970cc84b62ad9f19a (diff) | |
download | FreeBSD-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.c | 79 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c | 33 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 56 |
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__ */ |