Author: sephe
Date: Wed Jun  1 09:20:52 2016
New Revision: 301113
URL: https://svnweb.freebsd.org/changeset/base/301113

Log:
  hyperv: Rename some cleaned up/almost cleaned up files
  
  MFC after:    1 week
  Sponsored by: Microsoft OSTC

Added:
  head/sys/dev/hyperv/vmbus/amd64/vmbus_vector.S
     - copied unchanged from r301112, 
head/sys/dev/hyperv/vmbus/amd64/hv_vector.S
  head/sys/dev/hyperv/vmbus/hyperv.c
     - copied unchanged from r301112, head/sys/dev/hyperv/vmbus/hv_hv.c
  head/sys/dev/hyperv/vmbus/i386/vmbus_vector.S
     - copied unchanged from r301112, head/sys/dev/hyperv/vmbus/i386/hv_vector.S
  head/sys/dev/hyperv/vmbus/vmbus.c
     - copied unchanged from r301112, 
head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
  head/sys/dev/hyperv/vmbus/vmbus_et.c
     - copied unchanged from r301112, head/sys/dev/hyperv/vmbus/hv_et.c
Deleted:
  head/sys/dev/hyperv/vmbus/amd64/hv_vector.S
  head/sys/dev/hyperv/vmbus/hv_et.c
  head/sys/dev/hyperv/vmbus/hv_hv.c
  head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
  head/sys/dev/hyperv/vmbus/i386/hv_vector.S
Modified:
  head/sys/conf/files.amd64
  head/sys/conf/files.i386
  head/sys/modules/hyperv/vmbus/Makefile

Modified: head/sys/conf/files.amd64
==============================================================================
--- head/sys/conf/files.amd64   Wed Jun  1 08:20:10 2016        (r301112)
+++ head/sys/conf/files.amd64   Wed Jun  1 09:20:52 2016        (r301113)
@@ -273,12 +273,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/nfe/if_nfe.c               optional        nfe pci
 dev/ntb/if_ntb/if_ntb.c                optional        if_ntb
 dev/ntb/ntb_hw/ntb_hw.c                optional        if_ntb | ntb_hw

Modified: head/sys/conf/files.i386
==============================================================================
--- head/sys/conf/files.i386    Wed Jun  1 08:20:10 2016        (r301112)
+++ head/sys/conf/files.i386    Wed Jun  1 09:20:52 2016        (r301113)
@@ -248,12 +248,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: head/sys/dev/hyperv/vmbus/amd64/vmbus_vector.S (from r301112, 
head/sys/dev/hyperv/vmbus/amd64/hv_vector.S)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/hyperv/vmbus/amd64/vmbus_vector.S      Wed Jun  1 09:20:52 
2016        (r301113, copy of r301112, 
head/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: head/sys/dev/hyperv/vmbus/hyperv.c (from r301112, 
head/sys/dev/hyperv/vmbus/hv_hv.c)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/hyperv/vmbus/hyperv.c  Wed Jun  1 09:20:52 2016        
(r301113, copy of r301112, head/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: head/sys/dev/hyperv/vmbus/i386/vmbus_vector.S (from r301112, 
head/sys/dev/hyperv/vmbus/i386/hv_vector.S)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/hyperv/vmbus/i386/vmbus_vector.S       Wed Jun  1 09:20:52 
2016        (r301113, copy of r301112, 
head/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: head/sys/dev/hyperv/vmbus/vmbus.c (from r301112, 
head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/hyperv/vmbus/vmbus.c   Wed Jun  1 09:20:52 2016        
(r301113, copy of r301112, head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c)
@@ -0,0 +1,759 @@
+/*-
+ * 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 <x86/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(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;
+               }
+       }
+}
+
+static int
+vmbus_intr_setup(struct vmbus_softc *sc)
+{
+       int cpu;
+
+       CPU_FOREACH(cpu) {
+               char buf[MAXCOMLEN + 1];
+               cpuset_t cpu_mask;
+
+               /* Allocate an interrupt counter for Hyper-V interrupt */
+               snprintf(buf, sizeof(buf), "cpu%d:hyperv", cpu);
+               intrcnt_add(buf, VMBUS_PCPU_PTR(sc, intr_cnt, cpu));
+
+               /*
+                * Setup taskqueue to handle events.  Task will be per-
+                * channel.
+                */
+               VMBUS_PCPU_GET(sc, event_tq, cpu) = taskqueue_create_fast(
+                   "hyperv event", M_WAITOK, taskqueue_thread_enqueue,
+                   VMBUS_PCPU_PTR(sc, event_tq, cpu));
+               CPU_SETOF(cpu, &cpu_mask);
+               taskqueue_start_threads_cpuset(
+                   VMBUS_PCPU_PTR(sc, event_tq, cpu), 1, PI_NET, &cpu_mask,
+                   "hvevent%d", cpu);
+
+               /*
+                * Setup tasks and taskqueues to handle messages.
+                */
+               VMBUS_PCPU_GET(sc, message_tq, cpu) = taskqueue_create_fast(
+                   "hyperv msg", M_WAITOK, taskqueue_thread_enqueue,
+                   VMBUS_PCPU_PTR(sc, message_tq, cpu));
+               CPU_SETOF(cpu, &cpu_mask);
+               taskqueue_start_threads_cpuset(
+                   VMBUS_PCPU_PTR(sc, message_tq, cpu), 1, PI_NET, &cpu_mask,
+                   "hvmsg%d", cpu);
+               TASK_INIT(VMBUS_PCPU_PTR(sc, message_task, cpu), 0,
+                   vmbus_msg_task, sc);
+       }
+
+       /*
+        * All Hyper-V ISR required resources are setup, now let's find a
+        * free IDT vector for Hyper-V ISR and set it up.
+        */
+       sc->vmbus_idtvec = lapic_ipi_alloc(IDTVEC(vmbus_isr));
+       if (sc->vmbus_idtvec < 0) {
+               device_printf(sc->vmbus_dev, "cannot find free IDT vector\n");
+               return ENXIO;
+       }
+       if(bootverbose) {
+               device_printf(sc->vmbus_dev, "vmbus IDT vector %d\n",
+                   sc->vmbus_idtvec);
+       }
+       return 0;
+}
+
+static void
+vmbus_intr_teardown(struct vmbus_softc *sc)
+{
+       int cpu;
+
+       if (sc->vmbus_idtvec >= 0) {
+               lapic_ipi_free(sc->vmbus_idtvec);
+               sc->vmbus_idtvec = -1;
+       }
+
+       CPU_FOREACH(cpu) {
+               if (VMBUS_PCPU_GET(sc, event_tq, cpu) != NULL) {
+                       taskqueue_free(VMBUS_PCPU_GET(sc, event_tq, cpu));
+                       VMBUS_PCPU_GET(sc, event_tq, cpu) = NULL;
+               }
+               if (VMBUS_PCPU_GET(sc, message_tq, cpu) != NULL) {
+                       taskqueue_drain(VMBUS_PCPU_GET(sc, message_tq, cpu),
+                           VMBUS_PCPU_PTR(sc, message_task, cpu));
+                       taskqueue_free(VMBUS_PCPU_GET(sc, message_tq, cpu));
+                       VMBUS_PCPU_GET(sc, message_tq, cpu) = NULL;
+               }
+       }
+}
+
+static int

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to