svn commit: r302167 - in stable/10/sys: conf dev/hyperv/vmbus dev/hyperv/vmbus/amd64 dev/hyperv/vmbus/i386 modules/hyperv/vmbus
Sepherosa Ziehau
sephe at FreeBSD.org
Fri Jun 24 02:06:15 UTC 2016
Author: sephe
Date: Fri Jun 24 02:06:13 2016
New Revision: 302167
URL: https://svnweb.freebsd.org/changeset/base/302167
Log:
MFC 301113
hyperv: Rename some cleaned up/almost cleaned up files
MFC after: 1 week
Sponsored by: Microsoft OSTC
Added:
stable/10/sys/dev/hyperv/vmbus/amd64/vmbus_vector.S
- copied unchanged from r302166, stable/10/sys/dev/hyperv/vmbus/amd64/hv_vector.S
stable/10/sys/dev/hyperv/vmbus/hyperv.c
- copied unchanged from r302166, stable/10/sys/dev/hyperv/vmbus/hv_hv.c
stable/10/sys/dev/hyperv/vmbus/i386/vmbus_vector.S
- copied unchanged from r302166, stable/10/sys/dev/hyperv/vmbus/i386/hv_vector.S
stable/10/sys/dev/hyperv/vmbus/vmbus.c
- copied unchanged from r302166, stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
stable/10/sys/dev/hyperv/vmbus/vmbus_et.c
- copied unchanged from r302166, stable/10/sys/dev/hyperv/vmbus/hv_et.c
Deleted:
stable/10/sys/dev/hyperv/vmbus/amd64/hv_vector.S
stable/10/sys/dev/hyperv/vmbus/hv_et.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/i386/hv_vector.S
Modified:
stable/10/sys/conf/files.amd64
stable/10/sys/conf/files.i386
stable/10/sys/modules/hyperv/vmbus/Makefile
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/conf/files.amd64
==============================================================================
--- stable/10/sys/conf/files.amd64 Fri Jun 24 01:49:59 2016 (r302166)
+++ stable/10/sys/conf/files.amd64 Fri Jun 24 02:06:13 2016 (r302167)
@@ -274,12 +274,12 @@ dev/hyperv/utilities/hv_util.c option
dev/hyperv/vmbus/hv_channel.c optional hyperv
dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv
dev/hyperv/vmbus/hv_connection.c optional hyperv
-dev/hyperv/vmbus/hv_hv.c optional hyperv
-dev/hyperv/vmbus/hv_et.c optional hyperv
dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv
-dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
+dev/hyperv/vmbus/hyperv.c optional hyperv
dev/hyperv/vmbus/hyperv_busdma.c optional hyperv
-dev/hyperv/vmbus/amd64/hv_vector.S optional hyperv
+dev/hyperv/vmbus/vmbus.c optional hyperv
+dev/hyperv/vmbus/vmbus_et.c optional hyperv
+dev/hyperv/vmbus/amd64/vmbus_vector.S optional hyperv
dev/kbd/kbd.c optional atkbd | sc | ukbd | vt
dev/lindev/full.c optional lindev
dev/lindev/lindev.c optional lindev
Modified: stable/10/sys/conf/files.i386
==============================================================================
--- stable/10/sys/conf/files.i386 Fri Jun 24 01:49:59 2016 (r302166)
+++ stable/10/sys/conf/files.i386 Fri Jun 24 02:06:13 2016 (r302167)
@@ -250,12 +250,12 @@ dev/hyperv/utilities/hv_util.c option
dev/hyperv/vmbus/hv_channel.c optional hyperv
dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv
dev/hyperv/vmbus/hv_connection.c optional hyperv
-dev/hyperv/vmbus/hv_hv.c optional hyperv
-dev/hyperv/vmbus/hv_et.c optional hyperv
dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv
-dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
+dev/hyperv/vmbus/hyperv.c optional hyperv
dev/hyperv/vmbus/hyperv_busdma.c optional hyperv
-dev/hyperv/vmbus/i386/hv_vector.S optional hyperv
+dev/hyperv/vmbus/vmbus.c optional hyperv
+dev/hyperv/vmbus/vmbus_et.c optional hyperv
+dev/hyperv/vmbus/i386/vmbus_vector.S optional hyperv
dev/ichwd/ichwd.c optional ichwd
dev/if_ndis/if_ndis.c optional ndis
dev/if_ndis/if_ndis_pccard.c optional ndis pccard
Copied: stable/10/sys/dev/hyperv/vmbus/amd64/vmbus_vector.S (from r302166, stable/10/sys/dev/hyperv/vmbus/amd64/hv_vector.S)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/10/sys/dev/hyperv/vmbus/amd64/vmbus_vector.S Fri Jun 24 02:06:13 2016 (r302167, copy of r302166, stable/10/sys/dev/hyperv/vmbus/amd64/hv_vector.S)
@@ -0,0 +1,46 @@
+/*-
+ * 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$
+ */
+
+#include <machine/asmacros.h>
+#include <machine/specialreg.h>
+
+#include "assym.s"
+
+/*
+ * This is the Hyper-V vmbus channel direct callback interrupt.
+ * Only used when it is running on Hyper-V.
+ */
+ .text
+ SUPERALIGN_TEXT
+IDTVEC(vmbus_isr)
+ PUSH_FRAME
+ FAKE_MCOUNT(TF_RIP(%rsp))
+ movq %rsp, %rdi
+ call vmbus_handle_intr
+ MEXITCOUNT
+ jmp doreti
Copied: stable/10/sys/dev/hyperv/vmbus/hyperv.c (from r302166, stable/10/sys/dev/hyperv/vmbus/hv_hv.c)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/10/sys/dev/hyperv/vmbus/hyperv.c Fri Jun 24 02:06:13 2016 (r302167, copy of r302166, stable/10/sys/dev/hyperv/vmbus/hv_hv.c)
@@ -0,0 +1,404 @@
+/*-
+ * Copyright (c) 2009-2012,2016 Microsoft Corp.
+ * Copyright (c) 2012 NetApp Inc.
+ * Copyright (c) 2012 Citrix Inc.
+ * 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.
+ */
+
+/**
+ * Implements low-level interactions with Hypver-V/Azure
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/pcpu.h>
+#include <sys/timetc.h>
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
+#include <dev/hyperv/vmbus/hyperv_reg.h>
+#include <dev/hyperv/vmbus/hyperv_var.h>
+#include <dev/hyperv/vmbus/vmbus_var.h>
+
+#define HYPERV_FREEBSD_BUILD 0ULL
+#define HYPERV_FREEBSD_VERSION ((uint64_t)__FreeBSD_version)
+#define HYPERV_FREEBSD_OSID 0ULL
+
+#define MSR_HV_GUESTID_BUILD_FREEBSD \
+ (HYPERV_FREEBSD_BUILD & MSR_HV_GUESTID_BUILD_MASK)
+#define MSR_HV_GUESTID_VERSION_FREEBSD \
+ ((HYPERV_FREEBSD_VERSION << MSR_HV_GUESTID_VERSION_SHIFT) & \
+ MSR_HV_GUESTID_VERSION_MASK)
+#define MSR_HV_GUESTID_OSID_FREEBSD \
+ ((HYPERV_FREEBSD_OSID << MSR_HV_GUESTID_OSID_SHIFT) & \
+ MSR_HV_GUESTID_OSID_MASK)
+
+#define MSR_HV_GUESTID_FREEBSD \
+ (MSR_HV_GUESTID_BUILD_FREEBSD | \
+ MSR_HV_GUESTID_VERSION_FREEBSD | \
+ MSR_HV_GUESTID_OSID_FREEBSD | \
+ MSR_HV_GUESTID_OSTYPE_FREEBSD)
+
+struct hypercall_ctx {
+ void *hc_addr;
+ struct hyperv_dma hc_dma;
+};
+
+static u_int hyperv_get_timecount(struct timecounter *tc);
+
+u_int hyperv_features;
+u_int hyperv_recommends;
+
+static u_int hyperv_pm_features;
+static u_int hyperv_features3;
+
+static struct timecounter hyperv_timecounter = {
+ .tc_get_timecount = hyperv_get_timecount,
+ .tc_poll_pps = NULL,
+ .tc_counter_mask = 0xffffffff,
+ .tc_frequency = HYPERV_TIMER_FREQ,
+ .tc_name = "Hyper-V",
+ .tc_quality = 2000,
+ .tc_flags = 0,
+ .tc_priv = NULL
+};
+
+static struct hypercall_ctx hypercall_context;
+
+static u_int
+hyperv_get_timecount(struct timecounter *tc __unused)
+{
+ return rdmsr(MSR_HV_TIME_REF_COUNT);
+}
+
+/**
+ * @brief Invoke the specified hypercall
+ */
+static uint64_t
+hv_vmbus_do_hypercall(uint64_t control, void* input, void* output)
+{
+#ifdef __x86_64__
+ 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 = hypercall_context.hc_addr;
+
+ __asm__ __volatile__ ("mov %0, %%r8" : : "r" (output_address): "r8");
+ __asm__ __volatile__ ("call *%3" : "=a"(hv_status):
+ "c" (control), "d" (input_address),
+ "m" (hypercall_page));
+ return (hv_status);
+#else
+ uint32_t control_high = control >> 32;
+ uint32_t control_low = control & 0xFFFFFFFF;
+ uint32_t hv_status_high = 1;
+ uint32_t hv_status_low = 1;
+ uint64_t input_address = (input) ? hv_get_phys_addr(input) : 0;
+ uint32_t input_address_high = input_address >> 32;
+ uint32_t input_address_low = input_address & 0xFFFFFFFF;
+ 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 = hypercall_context.hc_addr;
+
+ __asm__ __volatile__ ("call *%8" : "=d"(hv_status_high),
+ "=a"(hv_status_low) : "d" (control_high),
+ "a" (control_low), "b" (input_address_high),
+ "c" (input_address_low),
+ "D"(output_address_high),
+ "S"(output_address_low), "m" (hypercall_page));
+ return (hv_status_low | ((uint64_t)hv_status_high << 32));
+#endif /* __x86_64__ */
+}
+
+/**
+ * @brief Post a message using the hypervisor message IPC.
+ * (This involves a hypercall.)
+ */
+hv_vmbus_status
+hv_vmbus_post_msg_via_msg_ipc(
+ hv_vmbus_connection_id connection_id,
+ hv_vmbus_msg_type message_type,
+ void* payload,
+ size_t payload_size)
+{
+ struct alignedinput {
+ uint64_t alignment8;
+ hv_vmbus_input_post_message msg;
+ };
+
+ hv_vmbus_input_post_message* aligned_msg;
+ hv_vmbus_status status;
+ size_t addr;
+
+ if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
+ return (EMSGSIZE);
+
+ addr = (size_t) malloc(sizeof(struct alignedinput), M_DEVBUF,
+ M_ZERO | M_NOWAIT);
+ KASSERT(addr != 0,
+ ("Error VMBUS: malloc failed to allocate message buffer!"));
+ if (addr == 0)
+ return (ENOMEM);
+
+ aligned_msg = (hv_vmbus_input_post_message*)
+ (HV_ALIGN_UP(addr, HV_HYPERCALL_PARAM_ALIGN));
+
+ aligned_msg->connection_id = connection_id;
+ aligned_msg->message_type = message_type;
+ aligned_msg->payload_size = payload_size;
+ memcpy((void*) aligned_msg->payload, payload, payload_size);
+
+ status = hv_vmbus_do_hypercall(
+ HV_CALL_POST_MESSAGE, aligned_msg, 0) & 0xFFFF;
+
+ free((void *) addr, M_DEVBUF);
+ return (status);
+}
+
+/**
+ * @brief Signal an event on the specified connection using the hypervisor
+ * event IPC. (This involves a hypercall.)
+ */
+hv_vmbus_status
+hv_vmbus_signal_event(void *con_id)
+{
+ hv_vmbus_status status;
+
+ status = hv_vmbus_do_hypercall(
+ HV_CALL_SIGNAL_EVENT,
+ con_id,
+ 0) & 0xFFFF;
+
+ return (status);
+}
+
+int
+hyperv_guid2str(const struct hv_guid *guid, char *buf, size_t sz)
+{
+ const uint8_t *d = guid->data;
+
+ return snprintf(buf, sz, "%02x%02x%02x%02x-"
+ "%02x%02x-%02x%02x-%02x%02x-"
+ "%02x%02x%02x%02x%02x%02x",
+ d[3], d[2], d[1], d[0],
+ d[5], d[4], d[7], d[6], d[8], d[9],
+ d[10], d[11], d[12], d[13], d[14], d[15]);
+}
+
+static bool
+hyperv_identify(void)
+{
+ u_int regs[4];
+ unsigned int maxleaf;
+
+ if (vm_guest != VM_GUEST_HV)
+ return (false);
+
+ do_cpuid(CPUID_LEAF_HV_MAXLEAF, regs);
+ maxleaf = regs[0];
+ if (maxleaf < CPUID_LEAF_HV_LIMITS)
+ return (false);
+
+ do_cpuid(CPUID_LEAF_HV_INTERFACE, regs);
+ if (regs[0] != CPUID_HV_IFACE_HYPERV)
+ return (false);
+
+ do_cpuid(CPUID_LEAF_HV_FEATURES, regs);
+ if ((regs[0] & CPUID_HV_MSR_HYPERCALL) == 0) {
+ /*
+ * Hyper-V w/o Hypercall is impossible; someone
+ * is faking Hyper-V.
+ */
+ return (false);
+ }
+ hyperv_features = regs[0];
+ hyperv_pm_features = regs[2];
+ hyperv_features3 = regs[3];
+
+ do_cpuid(CPUID_LEAF_HV_IDENTITY, regs);
+ printf("Hyper-V Version: %d.%d.%d [SP%d]\n",
+ regs[1] >> 16, regs[1] & 0xffff, regs[0], regs[2]);
+
+ printf(" Features=0x%b\n", hyperv_features,
+ "\020"
+ "\001VPRUNTIME" /* MSR_HV_VP_RUNTIME */
+ "\002TMREFCNT" /* MSR_HV_TIME_REF_COUNT */
+ "\003SYNIC" /* MSRs for SynIC */
+ "\004SYNTM" /* MSRs for SynTimer */
+ "\005APIC" /* MSR_HV_{EOI,ICR,TPR} */
+ "\006HYPERCALL" /* MSR_HV_{GUEST_OS_ID,HYPERCALL} */
+ "\007VPINDEX" /* MSR_HV_VP_INDEX */
+ "\010RESET" /* MSR_HV_RESET */
+ "\011STATS" /* MSR_HV_STATS_ */
+ "\012REFTSC" /* MSR_HV_REFERENCE_TSC */
+ "\013IDLE" /* MSR_HV_GUEST_IDLE */
+ "\014TMFREQ" /* MSR_HV_{TSC,APIC}_FREQUENCY */
+ "\015DEBUG"); /* MSR_HV_SYNTH_DEBUG_ */
+ printf(" PM Features=0x%b [C%u]\n",
+ (hyperv_pm_features & ~CPUPM_HV_CSTATE_MASK),
+ "\020"
+ "\005C3HPET", /* HPET is required for C3 state */
+ CPUPM_HV_CSTATE(hyperv_pm_features));
+ printf(" Features3=0x%b\n", hyperv_features3,
+ "\020"
+ "\001MWAIT" /* MWAIT */
+ "\002DEBUG" /* guest debug support */
+ "\003PERFMON" /* performance monitor */
+ "\004PCPUDPE" /* physical CPU dynamic partition event */
+ "\005XMMHC" /* hypercall input through XMM regs */
+ "\006IDLE" /* guest idle support */
+ "\007SLEEP" /* hypervisor sleep support */
+ "\010NUMA" /* NUMA distance query support */
+ "\011TMFREQ" /* timer frequency query (TSC, LAPIC) */
+ "\012SYNCMC" /* inject synthetic machine checks */
+ "\013CRASH" /* MSRs for guest crash */
+ "\014DEBUGMSR" /* MSRs for guest debug */
+ "\015NPIEP" /* NPIEP */
+ "\016HVDIS"); /* disabling hypervisor */
+
+ do_cpuid(CPUID_LEAF_HV_RECOMMENDS, regs);
+ hyperv_recommends = regs[0];
+ if (bootverbose)
+ printf(" Recommends: %08x %08x\n", regs[0], regs[1]);
+
+ do_cpuid(CPUID_LEAF_HV_LIMITS, regs);
+ if (bootverbose) {
+ printf(" Limits: Vcpu:%d Lcpu:%d Int:%d\n",
+ regs[0], regs[1], regs[2]);
+ }
+
+ if (maxleaf >= CPUID_LEAF_HV_HWFEATURES) {
+ do_cpuid(CPUID_LEAF_HV_HWFEATURES, regs);
+ if (bootverbose) {
+ printf(" HW Features: %08x, AMD: %08x\n",
+ regs[0], regs[3]);
+ }
+ }
+
+ return (true);
+}
+
+static void
+hyperv_init(void *dummy __unused)
+{
+ if (!hyperv_identify()) {
+ /* Not Hyper-V; reset guest id to the generic one. */
+ if (vm_guest == VM_GUEST_HV)
+ vm_guest = VM_GUEST_VM;
+ return;
+ }
+
+ /* Set guest id */
+ wrmsr(MSR_HV_GUEST_OS_ID, MSR_HV_GUESTID_FREEBSD);
+
+ if (hyperv_features & CPUID_HV_MSR_TIME_REFCNT) {
+ /* Register Hyper-V timecounter */
+ tc_init(&hyperv_timecounter);
+ }
+}
+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)
+{
+ uint64_t hc;
+
+ if (hypercall_context.hc_addr == NULL)
+ return;
+
+ /* Disable Hypercall */
+ hc = rdmsr(MSR_HV_HYPERCALL);
+ wrmsr(MSR_HV_HYPERCALL, (hc & MSR_HV_HYPERCALL_RSVD_MASK));
+ hypercall_memfree();
+
+ if (bootverbose)
+ printf("hyperv: Hypercall destroyed\n");
+}
+SYSUNINIT(hypercall_dtor, SI_SUB_DRIVERS, SI_ORDER_FIRST, hypercall_destroy,
+ NULL);
Copied: stable/10/sys/dev/hyperv/vmbus/i386/vmbus_vector.S (from r302166, stable/10/sys/dev/hyperv/vmbus/i386/hv_vector.S)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/10/sys/dev/hyperv/vmbus/i386/vmbus_vector.S Fri Jun 24 02:06:13 2016 (r302167, copy of r302166, stable/10/sys/dev/hyperv/vmbus/i386/hv_vector.S)
@@ -0,0 +1,49 @@
+/*-
+ * 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$
+ */
+
+#include <machine/asmacros.h>
+#include <machine/specialreg.h>
+
+#include "assym.s"
+
+/*
+ * This is the Hyper-V vmbus channel direct callback interrupt.
+ * Only used when it is running on Hyper-V.
+ */
+ .text
+ SUPERALIGN_TEXT
+IDTVEC(vmbus_isr)
+ PUSH_FRAME
+ SET_KERNEL_SREGS
+ cld
+ FAKE_MCOUNT(TF_EIP(%esp))
+ pushl %esp
+ call vmbus_handle_intr
+ add $4, %esp
+ MEXITCOUNT
+ jmp doreti
Copied: stable/10/sys/dev/hyperv/vmbus/vmbus.c (from r302166, stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/10/sys/dev/hyperv/vmbus/vmbus.c Fri Jun 24 02:06:13 2016 (r302167, copy of r302166, stable/10/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c)
@@ -0,0 +1,833 @@
+/*-
+ * Copyright (c) 2009-2012,2016 Microsoft Corp.
+ * Copyright (c) 2012 NetApp Inc.
+ * Copyright (c) 2012 Citrix Inc.
+ * 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.
+ */
+
+/*
+ * VM Bus Driver Implementation
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+#include <sys/rtprio.h>
+#include <sys/interrupt.h>
+#include <sys/sx.h>
+#include <sys/taskqueue.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <machine/stdarg.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/segments.h>
+#include <sys/pcpu.h>
+#include <machine/apicvar.h>
+
+#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
+#include <dev/hyperv/vmbus/hyperv_reg.h>
+#include <dev/hyperv/vmbus/hyperv_var.h>
+#include <dev/hyperv/vmbus/vmbus_reg.h>
+#include <dev/hyperv/vmbus/vmbus_var.h>
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include "acpi_if.h"
+
+struct vmbus_softc *vmbus_sc;
+
+extern inthand_t IDTVEC(rsvd), IDTVEC(vmbus_isr);
+
+static void
+vmbus_msg_task(void *xsc, int pending __unused)
+{
+ struct vmbus_softc *sc = xsc;
+ volatile struct vmbus_message *msg;
+
+ msg = VMBUS_PCPU_GET(sc, message, curcpu) + VMBUS_SINT_MESSAGE;
+ for (;;) {
+ const hv_vmbus_channel_msg_table_entry *entry;
+ hv_vmbus_channel_msg_header *hdr;
+ hv_vmbus_channel_msg_type msg_type;
+
+ if (msg->msg_type == VMBUS_MSGTYPE_NONE)
+ break; /* no message */
+
+ /* XXX: update messageHandler interface */
+ hdr = __DEVOLATILE(hv_vmbus_channel_msg_header *,
+ msg->msg_data);
+ msg_type = hdr->message_type;
+
+ if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) {
+ printf("VMBUS: unknown message type = %d\n", msg_type);
+ goto handled;
+ }
+
+ entry = &g_channel_message_table[msg_type];
+ if (entry->messageHandler)
+ entry->messageHandler(hdr);
+handled:
+ msg->msg_type = VMBUS_MSGTYPE_NONE;
+ /*
+ * Make sure the write to msg_type (i.e. set to
+ * VMBUS_MSGTYPE_NONE) happens before we read the
+ * msg_flags and EOMing. Otherwise, the EOMing will
+ * not deliver any more messages since there is no
+ * empty slot
+ *
+ * NOTE:
+ * mb() is used here, since atomic_thread_fence_seq_cst()
+ * will become compiler fence on UP kernel.
+ */
+ mb();
+ if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) {
+ /*
+ * This will cause message queue rescan to possibly
+ * deliver another msg from the hypervisor
+ */
+ wrmsr(MSR_HV_EOM, 0);
+ }
+ }
+}
+
+static __inline int
+vmbus_handle_intr1(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
+{
+ volatile struct vmbus_message *msg;
+ struct vmbus_message *msg_base;
+
+ msg_base = VMBUS_PCPU_GET(sc, message, cpu);
+
+ /*
+ * Check event timer.
+ *
+ * TODO: move this to independent IDT vector.
+ */
+ msg = msg_base + VMBUS_SINT_TIMER;
+ if (msg->msg_type == VMBUS_MSGTYPE_TIMER_EXPIRED) {
+ msg->msg_type = VMBUS_MSGTYPE_NONE;
+
+ vmbus_et_intr(frame);
+
+ /*
+ * Make sure the write to msg_type (i.e. set to
+ * VMBUS_MSGTYPE_NONE) happens before we read the
+ * msg_flags and EOMing. Otherwise, the EOMing will
+ * not deliver any more messages since there is no
+ * empty slot
+ *
+ * NOTE:
+ * mb() is used here, since atomic_thread_fence_seq_cst()
+ * will become compiler fence on UP kernel.
+ */
+ mb();
+ if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) {
+ /*
+ * This will cause message queue rescan to possibly
+ * deliver another msg from the hypervisor
+ */
+ wrmsr(MSR_HV_EOM, 0);
+ }
+ }
+
+ /*
+ * Check events. Hot path for network and storage I/O data; high rate.
+ *
+ * NOTE:
+ * As recommended by the Windows guest fellows, we check events before
+ * checking messages.
+ */
+ sc->vmbus_event_proc(sc, cpu);
+
+ /*
+ * Check messages. Mainly management stuffs; ultra low rate.
+ */
+ msg = msg_base + VMBUS_SINT_MESSAGE;
+ if (__predict_false(msg->msg_type != VMBUS_MSGTYPE_NONE)) {
+ taskqueue_enqueue(VMBUS_PCPU_GET(sc, message_tq, cpu),
+ VMBUS_PCPU_PTR(sc, message_task, cpu));
+ }
+
+ return (FILTER_HANDLED);
+}
+
+void
+vmbus_handle_intr(struct trapframe *trap_frame)
+{
+ struct vmbus_softc *sc = vmbus_get_softc();
+ int cpu = curcpu;
+
+ /*
+ * Disable preemption.
+ */
+ critical_enter();
+
+ /*
+ * Do a little interrupt counting.
+ */
+ (*VMBUS_PCPU_GET(sc, intr_cnt, cpu))++;
+
+ vmbus_handle_intr1(sc, trap_frame, cpu);
+
+ /*
+ * Enable preemption.
+ */
+ critical_exit();
+}
+
+static void
+vmbus_synic_setup(void *xsc)
+{
+ struct vmbus_softc *sc = xsc;
+ int cpu = curcpu;
+ uint64_t val, orig;
+ uint32_t sint;
+
+ if (hyperv_features & CPUID_HV_MSR_VP_INDEX) {
+ /*
+ * Save virtual processor id.
+ */
+ VMBUS_PCPU_GET(sc, vcpuid, cpu) = rdmsr(MSR_HV_VP_INDEX);
+ } else {
+ /*
+ * XXX
+ * Virtual processoor id is only used by a pretty broken
+ * channel selection code from storvsc. It's nothing
+ * critical even if CPUID_HV_MSR_VP_INDEX is not set; keep
+ * moving on.
+ */
+ VMBUS_PCPU_GET(sc, vcpuid, cpu) = cpu;
+ }
+
+ /*
+ * Setup the SynIC message.
+ */
+ orig = rdmsr(MSR_HV_SIMP);
+ val = MSR_HV_SIMP_ENABLE | (orig & MSR_HV_SIMP_RSVD_MASK) |
+ ((VMBUS_PCPU_GET(sc, message_dma.hv_paddr, cpu) >> PAGE_SHIFT) <<
+ MSR_HV_SIMP_PGSHIFT);
+ wrmsr(MSR_HV_SIMP, val);
+
+ /*
+ * Setup the SynIC event flags.
+ */
+ orig = rdmsr(MSR_HV_SIEFP);
+ val = MSR_HV_SIEFP_ENABLE | (orig & MSR_HV_SIEFP_RSVD_MASK) |
+ ((VMBUS_PCPU_GET(sc, event_flags_dma.hv_paddr, cpu)
+ >> PAGE_SHIFT) << MSR_HV_SIEFP_PGSHIFT);
+ wrmsr(MSR_HV_SIEFP, val);
+
+
+ /*
+ * Configure and unmask SINT for message and event flags.
+ */
+ sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
+ orig = rdmsr(sint);
+ val = sc->vmbus_idtvec | MSR_HV_SINT_AUTOEOI |
+ (orig & MSR_HV_SINT_RSVD_MASK);
+ wrmsr(sint, val);
+
+ /*
+ * Configure and unmask SINT for timer.
+ */
+ sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
+ orig = rdmsr(sint);
+ val = sc->vmbus_idtvec | MSR_HV_SINT_AUTOEOI |
+ (orig & MSR_HV_SINT_RSVD_MASK);
+ wrmsr(sint, val);
+
+ /*
+ * All done; enable SynIC.
+ */
+ orig = rdmsr(MSR_HV_SCONTROL);
+ val = MSR_HV_SCTRL_ENABLE | (orig & MSR_HV_SCTRL_RSVD_MASK);
+ wrmsr(MSR_HV_SCONTROL, val);
+}
+
+static void
+vmbus_synic_teardown(void *arg)
+{
+ uint64_t orig;
+ uint32_t sint;
+
+ /*
+ * Disable SynIC.
+ */
+ orig = rdmsr(MSR_HV_SCONTROL);
+ wrmsr(MSR_HV_SCONTROL, (orig & MSR_HV_SCTRL_RSVD_MASK));
+
+ /*
+ * Mask message and event flags SINT.
+ */
+ sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
+ orig = rdmsr(sint);
+ wrmsr(sint, orig | MSR_HV_SINT_MASKED);
+
+ /*
+ * Mask timer SINT.
+ */
+ sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
+ orig = rdmsr(sint);
+ wrmsr(sint, orig | MSR_HV_SINT_MASKED);
+
+ /*
+ * Teardown SynIC message.
+ */
+ orig = rdmsr(MSR_HV_SIMP);
+ wrmsr(MSR_HV_SIMP, (orig & MSR_HV_SIMP_RSVD_MASK));
+
+ /*
+ * Teardown SynIC event flags.
+ */
+ orig = rdmsr(MSR_HV_SIEFP);
+ wrmsr(MSR_HV_SIEFP, (orig & MSR_HV_SIEFP_RSVD_MASK));
+}
+
+static int
+vmbus_dma_alloc(struct vmbus_softc *sc)
+{
+ int cpu;
+
+ CPU_FOREACH(cpu) {
+ void *ptr;
+
+ /*
+ * Per-cpu messages and event flags.
+ */
+ ptr = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
+ PAGE_SIZE, 0, PAGE_SIZE,
+ VMBUS_PCPU_PTR(sc, message_dma, cpu),
+ BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ if (ptr == NULL)
+ return ENOMEM;
+ VMBUS_PCPU_GET(sc, message, cpu) = ptr;
+
+ ptr = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev),
+ PAGE_SIZE, 0, PAGE_SIZE,
+ VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
+ BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ if (ptr == NULL)
+ return ENOMEM;
+ VMBUS_PCPU_GET(sc, event_flags, cpu) = ptr;
+ }
+ return 0;
+}
+
+static void
+vmbus_dma_free(struct vmbus_softc *sc)
+{
+ int cpu;
+
+ CPU_FOREACH(cpu) {
+ if (VMBUS_PCPU_GET(sc, message, cpu) != NULL) {
+ hyperv_dmamem_free(
+ VMBUS_PCPU_PTR(sc, message_dma, cpu),
+ VMBUS_PCPU_GET(sc, message, cpu));
+ VMBUS_PCPU_GET(sc, message, cpu) = NULL;
+ }
+ if (VMBUS_PCPU_GET(sc, event_flags, cpu) != NULL) {
+ hyperv_dmamem_free(
+ VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
+ VMBUS_PCPU_GET(sc, event_flags, cpu));
+ VMBUS_PCPU_GET(sc, event_flags, cpu) = NULL;
+ }
+ }
+}
+
+/**
+ * @brief Find a free IDT slot and setup the interrupt handler.
+ */
+static int
+vmbus_vector_alloc(void)
+{
+ int vector;
+ uintptr_t func;
+ struct gate_descriptor *ip;
+
+ /*
+ * Search backwards form the highest IDT vector available for use
+ * as vmbus channel callback vector. We install 'hv_vmbus_callback'
+ * handler at that vector and use it to interrupt vcpus.
+ */
+ vector = APIC_SPURIOUS_INT;
+ while (--vector >= APIC_IPI_INTS) {
+ ip = &idt[vector];
+ func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
+ if (func == (uintptr_t)&IDTVEC(rsvd)) {
+#ifdef __i386__
+ setidt(vector , IDTVEC(vmbus_isr), SDT_SYS386IGT,
+ SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+#else
+ setidt(vector , IDTVEC(vmbus_isr), SDT_SYSIGT,
+ SEL_KPL, 0);
+#endif
+
+ return (vector);
+ }
+ }
+ return (0);
+}
+
+/**
+ * @brief Restore the IDT slot to rsvd.
+ */
+static void
+vmbus_vector_free(int vector)
+{
+ uintptr_t func;
+ struct gate_descriptor *ip;
+
+ if (vector == 0)
+ return;
+
+ KASSERT(vector >= APIC_IPI_INTS && vector < APIC_SPURIOUS_INT,
+ ("invalid vector %d", vector));
+
+ ip = &idt[vector];
+ func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
+ KASSERT(func == (uintptr_t)&IDTVEC(hv_vmbus_callback),
+ ("invalid vector %d", vector));
+
+ setidt(vector, IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
+}
+
+static void
+vmbus_cpuset_setthread_task(void *xmask, int pending __unused)
+{
+ cpuset_t *mask = xmask;
+ int error;
+
+ error = cpuset_setthread(curthread->td_tid, mask);
+ if (error) {
+ panic("curthread=%ju: can't pin; error=%d",
+ (uintmax_t)curthread->td_tid, error);
+ }
+}
+
+static int
+vmbus_intr_setup(struct vmbus_softc *sc)
+{
+ int cpu;
+
+ CPU_FOREACH(cpu) {
+ struct task cpuset_task;
+ char buf[MAXCOMLEN + 1];
+ cpuset_t cpu_mask;
+
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-10
mailing list