Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145220970
D6445.id16549.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D6445.id16549.diff
View Options
Index: sys/dev/hyperv/vmbus/hv_hv.c
===================================================================
--- sys/dev/hyperv/vmbus/hv_hv.c
+++ sys/dev/hyperv/vmbus/hv_hv.c
@@ -43,8 +43,9 @@
#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 @@
(((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 @@
*/
hv_vmbus_context hv_vmbus_g_context = {
.syn_ic_initialized = FALSE,
- .hypercall_page = NULL,
};
static struct timecounter hv_timecounter = {
@@ -116,7 +123,7 @@
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 @@
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 @@
}
/**
- * @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 @@
cpu = PCPU_GET(cpuid);
- if (hv_vmbus_g_context.hypercall_page == NULL)
- return;
-
/*
* TODO: Check the version
*/
@@ -537,3 +463,74 @@
}
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);
Index: sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
===================================================================
--- sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
+++ sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
@@ -349,7 +349,7 @@
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");
@@ -385,14 +385,6 @@
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.
*/
@@ -401,6 +393,7 @@
if(bootverbose)
printf("Error VMBUS: Cannot find free IDT slot for "
"vmbus callback!\n");
+ ret = ENXIO;
goto cleanup;
}
@@ -504,8 +497,6 @@
lapic_ipi_free(hv_vmbus_g_context.hv_cb_vector);
cleanup:
- hv_vmbus_cleanup();
-
return (ret);
}
@@ -574,8 +565,6 @@
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) {
Index: sys/dev/hyperv/vmbus/hv_vmbus_priv.h
===================================================================
--- sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -198,7 +198,6 @@
#define HV_HYPERCALL_PARAM_ALIGN sizeof(uint64_t)
typedef struct {
- void* hypercall_page;
hv_bool_uint8_t syn_ic_initialized;
hv_vmbus_handle syn_ic_msg_page[MAXCPU];
@@ -722,8 +721,6 @@
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,
Index: sys/dev/hyperv/vmbus/hyperv_reg.h
===================================================================
--- /dev/null
+++ 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_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Feb 18, 6:19 AM (10 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28839795
Default Alt Text
D6445.id16549.diff (9 KB)
Attached To
Mode
D6445: hyperv: Move Hypercall setup to an early place.
Attached
Detach File
Event Timeline
Log In to Comment