svn commit: r302114 - stable/10/sys/dev/hyperv/vmbus
Sepherosa Ziehau
sephe at FreeBSD.org
Thu Jun 23 04:40:15 UTC 2016
Author: sephe
Date: Thu Jun 23 04:40:13 2016
New Revision: 302114
URL: https://svnweb.freebsd.org/changeset/base/302114
Log:
MFC 300480,300481,300486
300480
hyperv: Move Hypercall setup to an early place.
It does not belong to the vmbus.
While I'm here rework the Hypercall setup, e.g. use busdma(9)
and avoid bit fields.
Discussed with: Jun Su <junsu microsoft com>
MFC after: 1 week
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6445
300481
hyperv/vmbus: Declare Synic message and event w/ proper types
Avoid ugly casts.
MFC after: 1 week
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6446
300486
hyperv/vmbus: Get rid of vmbus_devp
While I'm here, nuke useless print in vmbus_attach().
MFC after: 1 week
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D6447
Added:
stable/10/sys/dev/hyperv/vmbus/hyperv_reg.h
- copied unchanged from r300480, head/sys/dev/hyperv/vmbus/hyperv_reg.h
Modified:
stable/10/sys/dev/hyperv/vmbus/hv_connection.c
stable/10/sys/dev/hyperv/vmbus/hv_hv.c
stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
stable/10/sys/dev/hyperv/vmbus/vmbus_var.h
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_connection.c Thu Jun 23 03:25:18 2016 (r302113)
+++ stable/10/sys/dev/hyperv/vmbus/hv_connection.c Thu Jun 23 04:40:13 2016 (r302114)
@@ -336,8 +336,8 @@ vmbus_event_proc(struct vmbus_softc *sc,
{
hv_vmbus_synic_event_flags *event;
- event = ((hv_vmbus_synic_event_flags *)
- hv_vmbus_g_context.syn_ic_event_page[cpu]) + HV_VMBUS_MESSAGE_SINT;
+ event = hv_vmbus_g_context.syn_ic_event_page[cpu] +
+ HV_VMBUS_MESSAGE_SINT;
/*
* On Host with Win8 or above, the event page can be checked directly
@@ -352,8 +352,8 @@ vmbus_event_proc_compat(struct vmbus_sof
{
hv_vmbus_synic_event_flags *event;
- event = ((hv_vmbus_synic_event_flags *)
- hv_vmbus_g_context.syn_ic_event_page[cpu]) + HV_VMBUS_MESSAGE_SINT;
+ event = hv_vmbus_g_context.syn_ic_event_page[cpu] +
+ HV_VMBUS_MESSAGE_SINT;
if (atomic_testandclear_int(&event->flags32[0], 0)) {
vmbus_event_flags_proc(
Modified: stable/10/sys/dev/hyperv/vmbus/hv_hv.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_hv.c Thu Jun 23 03:25:18 2016 (r302113)
+++ stable/10/sys/dev/hyperv/vmbus/hv_hv.c Thu Jun 23 04:40:13 2016 (r302114)
@@ -43,8 +43,9 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_param.h>
#include <vm/pmap.h>
-
-#include "hv_vmbus_priv.h"
+#include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
+#include <dev/hyperv/vmbus/hyperv_reg.h>
#define HV_NANOSECONDS_PER_SEC 1000000000L
@@ -79,6 +80,13 @@ __FBSDID("$FreeBSD$");
(((uint64_t)__FreeBSD_version) << 16) | \
((uint64_t)((id) & 0x00ffff)))
+struct hypercall_ctx {
+ void *hc_addr;
+ struct hyperv_dma hc_dma;
+};
+
+static struct hypercall_ctx hypercall_context;
+
static u_int hv_get_timecount(struct timecounter *tc);
u_int hyperv_features;
@@ -92,7 +100,6 @@ static u_int hyperv_features3;
*/
hv_vmbus_context hv_vmbus_g_context = {
.syn_ic_initialized = FALSE,
- .hypercall_page = NULL,
};
static struct timecounter hv_timecounter = {
@@ -116,7 +123,7 @@ hv_vmbus_do_hypercall(uint64_t control,
uint64_t hv_status = 0;
uint64_t input_address = (input) ? hv_get_phys_addr(input) : 0;
uint64_t output_address = (output) ? hv_get_phys_addr(output) : 0;
- volatile void* hypercall_page = hv_vmbus_g_context.hypercall_page;
+ volatile void *hypercall_page = hypercall_context.hc_addr;
__asm__ __volatile__ ("mov %0, %%r8" : : "r" (output_address): "r8");
__asm__ __volatile__ ("call *%3" : "=a"(hv_status):
@@ -134,7 +141,7 @@ hv_vmbus_do_hypercall(uint64_t control,
uint64_t output_address = (output) ? hv_get_phys_addr(output) : 0;
uint32_t output_address_high = output_address >> 32;
uint32_t output_address_low = output_address & 0xFFFFFFFF;
- volatile void* hypercall_page = hv_vmbus_g_context.hypercall_page;
+ volatile void *hypercall_page = hypercall_context.hc_addr;
__asm__ __volatile__ ("call *%8" : "=d"(hv_status_high),
"=a"(hv_status_low) : "d" (control_high),
@@ -147,84 +154,6 @@ hv_vmbus_do_hypercall(uint64_t control,
}
/**
- * @brief Main initialization routine.
- *
- * This routine must be called
- * before any other routines in here are called
- */
-int
-hv_vmbus_init(void)
-{
- hv_vmbus_x64_msr_hypercall_contents hypercall_msr;
- void* virt_addr = NULL;
-
- memset(
- hv_vmbus_g_context.syn_ic_event_page,
- 0,
- sizeof(hv_vmbus_handle) * MAXCPU);
-
- memset(
- hv_vmbus_g_context.syn_ic_msg_page,
- 0,
- sizeof(hv_vmbus_handle) * MAXCPU);
-
- if (vm_guest != VM_GUEST_HV)
- goto cleanup;
-
- /*
- * See if the hypercall page is already set
- */
- hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL);
- virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
-
- hypercall_msr.u.enable = 1;
- hypercall_msr.u.guest_physical_address =
- (hv_get_phys_addr(virt_addr) >> PAGE_SHIFT);
- 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 = rdmsr(HV_X64_MSR_HYPERCALL);
-
- if (!hypercall_msr.u.enable)
- goto cleanup;
-
- hv_vmbus_g_context.hypercall_page = virt_addr;
-
- return (0);
-
- cleanup:
- if (virt_addr != NULL) {
- if (hypercall_msr.u.enable) {
- hypercall_msr.as_uint64_t = 0;
- wrmsr(HV_X64_MSR_HYPERCALL,
- hypercall_msr.as_uint64_t);
- }
-
- free(virt_addr, M_DEVBUF);
- }
- return (ENOTSUP);
-}
-
-/**
- * @brief Cleanup routine, called normally during driver unloading or exiting
- */
-void
-hv_vmbus_cleanup(void)
-{
- if (hv_vmbus_g_context.hypercall_page != NULL) {
- hv_vmbus_x64_msr_hypercall_contents hypercall_msr;
-
- hypercall_msr.as_uint64_t = 0;
- 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;
- }
-}
-
-/**
* @brief Post a message using the hypervisor message IPC.
* (This involves a hypercall.)
*/
@@ -304,9 +233,6 @@ hv_vmbus_synic_init(void *arg)
cpu = PCPU_GET(cpuid);
- if (hv_vmbus_g_context.hypercall_page == NULL)
- return;
-
/*
* TODO: Check the version
*/
@@ -537,3 +463,74 @@ hyperv_init(void *dummy __unused)
}
SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init,
NULL);
+
+static void
+hypercall_memfree(void)
+{
+ hyperv_dmamem_free(&hypercall_context.hc_dma,
+ hypercall_context.hc_addr);
+ hypercall_context.hc_addr = NULL;
+}
+
+static void
+hypercall_create(void *arg __unused)
+{
+ uint64_t hc, hc_orig;
+
+ if (vm_guest != VM_GUEST_HV)
+ return;
+
+ hypercall_context.hc_addr = hyperv_dmamem_alloc(NULL, PAGE_SIZE, 0,
+ PAGE_SIZE, &hypercall_context.hc_dma, BUS_DMA_WAITOK);
+ if (hypercall_context.hc_addr == NULL) {
+ printf("hyperv: Hypercall page allocation failed\n");
+ /* Can't perform any Hyper-V specific actions */
+ vm_guest = VM_GUEST_VM;
+ return;
+ }
+
+ /* Get the 'reserved' bits, which requires preservation. */
+ hc_orig = rdmsr(MSR_HV_HYPERCALL);
+
+ /*
+ * Setup the Hypercall page.
+ *
+ * NOTE: 'reserved' bits MUST be preserved.
+ */
+ hc = ((hypercall_context.hc_dma.hv_paddr >> PAGE_SHIFT) <<
+ MSR_HV_HYPERCALL_PGSHIFT) |
+ (hc_orig & MSR_HV_HYPERCALL_RSVD_MASK) |
+ MSR_HV_HYPERCALL_ENABLE;
+ wrmsr(MSR_HV_HYPERCALL, hc);
+
+ /*
+ * Confirm that Hypercall page did get setup.
+ */
+ hc = rdmsr(MSR_HV_HYPERCALL);
+ if ((hc & MSR_HV_HYPERCALL_ENABLE) == 0) {
+ printf("hyperv: Hypercall setup failed\n");
+ hypercall_memfree();
+ /* Can't perform any Hyper-V specific actions */
+ vm_guest = VM_GUEST_VM;
+ return;
+ }
+ if (bootverbose)
+ printf("hyperv: Hypercall created\n");
+}
+SYSINIT(hypercall_ctor, SI_SUB_DRIVERS, SI_ORDER_FIRST, hypercall_create, NULL);
+
+static void
+hypercall_destroy(void *arg __unused)
+{
+ if (hypercall_context.hc_addr == NULL)
+ return;
+
+ /* Disable Hypercall */
+ wrmsr(MSR_HV_HYPERCALL, 0);
+ hypercall_memfree();
+
+ if (bootverbose)
+ printf("hyperv: Hypercall destroyed\n");
+}
+SYSUNINIT(hypercall_dtor, SI_SUB_DRIVERS, SI_ORDER_FIRST, hypercall_destroy,
+ NULL);
Modified: stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c Thu Jun 23 03:25:18 2016 (r302113)
+++ stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c Thu Jun 23 04:40:13 2016 (r302114)
@@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$");
struct vmbus_softc *vmbus_sc;
-static device_t vmbus_devp;
static int vmbus_inited;
static hv_setup_args setup_args; /* only CPU 0 supported at this time */
@@ -79,8 +78,9 @@ vmbus_msg_task(void *arg __unused, int p
{
hv_vmbus_message *msg;
- msg = ((hv_vmbus_message *)hv_vmbus_g_context.syn_ic_msg_page[curcpu]) +
+ msg = hv_vmbus_g_context.syn_ic_msg_page[curcpu] +
HV_VMBUS_MESSAGE_SINT;
+
for (;;) {
const hv_vmbus_channel_msg_table_entry *entry;
hv_vmbus_channel_msg_header *hdr;
@@ -134,9 +134,8 @@ static inline int
hv_vmbus_isr(struct trapframe *frame)
{
struct vmbus_softc *sc = vmbus_get_softc();
+ hv_vmbus_message *msg, *msg_base;
int cpu = curcpu;
- hv_vmbus_message *msg;
- void *page_addr;
/*
* The Windows team has advised that we check for events
@@ -146,8 +145,8 @@ hv_vmbus_isr(struct trapframe *frame)
sc->vmbus_event_proc(sc, cpu);
/* Check if there are actual msgs to be process */
- page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu];
- msg = ((hv_vmbus_message *)page_addr) + HV_VMBUS_TIMER_SINT;
+ msg_base = hv_vmbus_g_context.syn_ic_msg_page[cpu];
+ msg = msg_base + HV_VMBUS_TIMER_SINT;
/* we call eventtimer process the message */
if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) {
@@ -178,7 +177,7 @@ hv_vmbus_isr(struct trapframe *frame)
}
}
- msg = ((hv_vmbus_message *)page_addr) + HV_VMBUS_MESSAGE_SINT;
+ msg = msg_base + HV_VMBUS_MESSAGE_SINT;
if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) {
taskqueue_enqueue(hv_vmbus_g_context.hv_msg_tq[cpu],
&hv_vmbus_g_context.hv_msg_task[cpu]);
@@ -324,7 +323,7 @@ hv_vmbus_child_device_register(struct hv
printf("VMBUS: Class ID: %s\n", name);
}
- child = device_add_child(vmbus_devp, NULL, -1);
+ child = device_add_child(vmbus_get_device(), NULL, -1);
child_dev->device = child;
device_set_ivars(child, child_dev);
@@ -340,7 +339,7 @@ hv_vmbus_child_device_unregister(struct
* device_add_child()
*/
mtx_lock(&Giant);
- ret = device_delete_child(vmbus_devp, child_dev->device);
+ ret = device_delete_child(vmbus_get_device(), child_dev->device);
mtx_unlock(&Giant);
return(ret);
}
@@ -349,7 +348,7 @@ static int
vmbus_probe(device_t dev)
{
if (ACPI_ID_PROBE(device_get_parent(dev), dev, vmbus_ids) == NULL ||
- device_get_unit(dev) != 0)
+ device_get_unit(dev) != 0 || vm_guest != VM_GUEST_HV)
return (ENXIO);
device_set_desc(dev, "Hyper-V Vmbus");
@@ -455,14 +454,6 @@ vmbus_bus_init(void)
vmbus_inited = 1;
sc = vmbus_get_softc();
- ret = hv_vmbus_init();
-
- if (ret) {
- if(bootverbose)
- printf("Error VMBUS: Hypervisor Initialization Failed!\n");
- return (ret);
- }
-
/*
* Find a free IDT slot for vmbus callback.
*/
@@ -472,6 +463,7 @@ vmbus_bus_init(void)
if(bootverbose)
printf("Error VMBUS: Cannot find free IDT slot for "
"vmbus callback!\n");
+ ret = ENXIO;
goto cleanup;
}
@@ -559,8 +551,8 @@ vmbus_bus_init(void)
hv_vmbus_request_channel_offers();
vmbus_scan();
- bus_generic_attach(vmbus_devp);
- device_printf(vmbus_devp, "device scan, probe and attach done\n");
+ bus_generic_attach(sc->vmbus_dev);
+ device_printf(sc->vmbus_dev, "device scan, probe and attach done\n");
return (ret);
@@ -585,8 +577,6 @@ vmbus_bus_init(void)
vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector);
cleanup:
- hv_vmbus_cleanup();
-
return (ret);
}
@@ -598,11 +588,8 @@ vmbus_event_proc_dummy(struct vmbus_soft
static int
vmbus_attach(device_t dev)
{
- if(bootverbose)
- device_printf(dev, "VMBUS: attach dev: %p\n", dev);
-
- vmbus_devp = dev;
vmbus_sc = device_get_softc(dev);
+ vmbus_sc->vmbus_dev = dev;
/*
* Event processing logic will be configured:
@@ -655,8 +642,6 @@ vmbus_detach(device_t dev)
free(setup_args.page_buffers[i], M_DEVBUF);
}
- hv_vmbus_cleanup();
-
/* remove swi */
CPU_FOREACH(i) {
if (hv_vmbus_g_context.hv_event_queue[i] != NULL) {
Modified: stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Thu Jun 23 03:25:18 2016 (r302113)
+++ stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Thu Jun 23 04:40:13 2016 (r302114)
@@ -197,12 +197,14 @@ enum {
#define HV_HYPERCALL_PARAM_ALIGN sizeof(uint64_t)
+struct vmbus_message;
+union vmbus_event_flags;
+
typedef struct {
- void* hypercall_page;
hv_bool_uint8_t syn_ic_initialized;
- hv_vmbus_handle syn_ic_msg_page[MAXCPU];
- hv_vmbus_handle syn_ic_event_page[MAXCPU];
+ struct vmbus_message *syn_ic_msg_page[MAXCPU];
+ union vmbus_event_flags *syn_ic_event_page[MAXCPU];
/*
* For FreeBSD cpuid to Hyper-V vcpuid mapping.
*/
@@ -304,7 +306,7 @@ typedef struct {
/*
* Define synthetic interrupt controller message format
*/
-typedef struct {
+typedef struct vmbus_message {
hv_vmbus_msg_header header;
union {
uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
@@ -579,7 +581,7 @@ typedef struct {
/*
* Define the synthetic interrupt controller event flags format
*/
-typedef union {
+typedef union vmbus_event_flags {
uint8_t flags8[HV_EVENT_FLAGS_BYTE_COUNT];
uint32_t flags32[HV_EVENT_FLAGS_DWORD_COUNT];
unsigned long flagsul[HV_EVENT_FLAGS_ULONG_COUNT];
@@ -722,8 +724,6 @@ hv_vmbus_channel* hv_vmbus_allocate_chan
void hv_vmbus_free_vmbus_channel(hv_vmbus_channel *channel);
int hv_vmbus_request_channel_offers(void);
void hv_vmbus_release_unattached_channels(void);
-int hv_vmbus_init(void);
-void hv_vmbus_cleanup(void);
uint16_t hv_vmbus_post_msg_via_msg_ipc(
hv_vmbus_connection_id connection_id,
Copied: stable/10/sys/dev/hyperv/vmbus/hyperv_reg.h (from r300480, head/sys/dev/hyperv/vmbus/hyperv_reg.h)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/10/sys/dev/hyperv/vmbus/hyperv_reg.h Thu Jun 23 04:40:13 2016 (r302114, copy of r300480, head/sys/dev/hyperv/vmbus/hyperv_reg.h)
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2016 Microsoft Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _HYPERV_REG_H_
+#define _HYPERV_REG_H_
+
+#define MSR_HV_HYPERCALL 0x40000001
+#define MSR_HV_HYPERCALL_ENABLE 0x0001ULL
+#define MSR_HV_HYPERCALL_RSVD_MASK 0x0ffeULL
+#define MSR_HV_HYPERCALL_PGSHIFT 12
+
+#endif /* !_HYPERV_REG_H_ */
Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_var.h
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/vmbus_var.h Thu Jun 23 03:25:18 2016 (r302113)
+++ stable/10/sys/dev/hyperv/vmbus/vmbus_var.h Thu Jun 23 04:40:13 2016 (r302114)
@@ -38,6 +38,7 @@ struct vmbus_pcpu_data {
struct vmbus_softc {
void (*vmbus_event_proc)(struct vmbus_softc *, int);
struct vmbus_pcpu_data vmbus_pcpu[MAXCPU];
+ device_t vmbus_dev;
};
extern struct vmbus_softc *vmbus_sc;
@@ -48,6 +49,12 @@ vmbus_get_softc(void)
return vmbus_sc;
}
+static __inline device_t
+vmbus_get_device(void)
+{
+ return vmbus_sc->vmbus_dev;
+}
+
#define VMBUS_SC_PCPU_GET(sc, field, cpu) (sc)->vmbus_pcpu[(cpu)].field
#define VMBUS_SC_PCPU_PTR(sc, field, cpu) &(sc)->vmbus_pcpu[(cpu)].field
#define VMBUS_PCPU_GET(field, cpu) \
More information about the svn-src-stable-10
mailing list