- added subset of original FreeBSD driver code for Hyper/V
 
(https://github.com/freebsd/freebsd/tree/4f55a572a1ac518b3e4f5a856ec0b403fe23ed5e)
 for now limited to VMBus driver basic functionality and common header files.
- renamed all *.c files to *.cc.
- replaced tabs with spaces.

Most of this code is not necessary to make OSv boot on Hyper/V however it is 
included in anticipation of the network/disk support later.

Signed-off-by: Waldemar Kozaczuk <[email protected]>
---
 bsd/sys/dev/hyperv/include/hyperv.h        |  96 +++++++++
 bsd/sys/dev/hyperv/include/hyperv_busdma.h |  49 +++++
 bsd/sys/dev/hyperv/include/vmbus.h         | 230 ++++++++++++++++++++
 bsd/sys/dev/hyperv/include/vmbus_xact.h    |  65 ++++++
 bsd/sys/dev/hyperv/vmbus/hyperv.cc         | 327 +++++++++++++++++++++++++++++
 5 files changed, 767 insertions(+)
 create mode 100644 bsd/sys/dev/hyperv/include/hyperv.h
 create mode 100644 bsd/sys/dev/hyperv/include/hyperv_busdma.h
 create mode 100644 bsd/sys/dev/hyperv/include/vmbus.h
 create mode 100644 bsd/sys/dev/hyperv/include/vmbus_xact.h
 create mode 100644 bsd/sys/dev/hyperv/vmbus/hyperv.cc

diff --git a/bsd/sys/dev/hyperv/include/hyperv.h 
b/bsd/sys/dev/hyperv/include/hyperv.h
new file mode 100644
index 0000000..4d0f5b7
--- /dev/null
+++ b/bsd/sys/dev/hyperv/include/hyperv.h
@@ -0,0 +1,96 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _HYPERV_H_
+#define _HYPERV_H_
+
+#ifdef _KERNEL
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#define MSR_HV_TIME_REF_COUNT           0x40000020
+
+#define CPUID_HV_MSR_TIME_REFCNT        0x0002  /* MSR_HV_TIME_REF_COUNT */
+#define CPUID_HV_MSR_SYNIC              0x0004  /* MSRs for SynIC */
+#define CPUID_HV_MSR_SYNTIMER           0x0008  /* MSRs for SynTimer */
+#define CPUID_HV_MSR_APIC               0x0010  /* MSR_HV_{EOI,ICR,TPR} */
+#define CPUID_HV_MSR_HYPERCALL          0x0020  /* MSR_HV_GUEST_OS_ID
+                         * MSR_HV_HYPERCALL */
+#define CPUID_HV_MSR_VP_INDEX           0x0040  /* MSR_HV_VP_INDEX */
+#define CPUID_HV_MSR_REFERENCE_TSC      0x0200  /* MSR_HV_REFERENCE_TSC */
+#define CPUID_HV_MSR_GUEST_IDLE         0x0400  /* MSR_HV_GUEST_IDLE */
+
+#ifndef NANOSEC
+#define NANOSEC                         1000000000ULL
+#endif
+#define HYPERV_TIMER_NS_FACTOR          100ULL
+#define HYPERV_TIMER_FREQ               (NANOSEC / HYPERV_TIMER_NS_FACTOR)
+
+#endif  /* _KERNEL */
+
+#define HYPERV_REFTSC_DEVNAME           "hv_tsc"
+
+/*
+ * Hyper-V Reference TSC
+ */
+struct hyperv_reftsc {
+    volatile uint32_t           tsc_seq;
+    volatile uint32_t           tsc_rsvd1;
+    volatile uint64_t           tsc_scale;
+    volatile int64_t            tsc_ofs;
+} __packed __aligned(PAGE_SIZE);
+#ifdef CTASSERT
+CTASSERT(sizeof(struct hyperv_reftsc) == PAGE_SIZE);
+#endif
+
+#ifdef _KERNEL
+
+struct hyperv_guid {
+    uint8_t                             hv_guid[16];
+} __packed;
+
+#define HYPERV_GUID_STRLEN              40
+
+typedef uint64_t                        (*hyperv_tc64_t)(void);
+
+int                     hyperv_guid2str(const struct hyperv_guid *, char *,
+                size_t);
+
+/*
+ * hyperv_tc64 could be NULL, if there were no suitable Hyper-V
+ * specific timecounter.
+ */
+extern hyperv_tc64_t    hyperv_tc64;
+extern u_int            hyperv_features;        /* CPUID_HV_MSR_ */
+
+#endif  /* _KERNEL */
+
+#endif  /* _HYPERV_H_ */
diff --git a/bsd/sys/dev/hyperv/include/hyperv_busdma.h 
b/bsd/sys/dev/hyperv/include/hyperv_busdma.h
new file mode 100644
index 0000000..e978827
--- /dev/null
+++ b/bsd/sys/dev/hyperv/include/hyperv_busdma.h
@@ -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$
+ */
+
+#ifndef _HYPERV_BUSDMA_H_
+#define _HYPERV_BUSDMA_H_
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+
+struct hyperv_dma {
+    bus_addr_t  hv_paddr;
+    bus_dma_tag_t       hv_dtag;
+    bus_dmamap_t        hv_dmap;
+};
+
+void            hyperv_dma_map_paddr(void *arg, bus_dma_segment_t *segs,
+                    int nseg, int error);
+void            *hyperv_dmamem_alloc(bus_dma_tag_t parent_dtag,
+                    bus_size_t alignment, bus_addr_t boundary, bus_size_t size,
+                    struct hyperv_dma *dma, int flags);
+void            hyperv_dmamem_free(struct hyperv_dma *dma, void *ptr);
+
+#endif  /* !_HYPERV_BUSDMA_H_ */
diff --git a/bsd/sys/dev/hyperv/include/vmbus.h 
b/bsd/sys/dev/hyperv/include/vmbus.h
new file mode 100644
index 0000000..73c4561
--- /dev/null
+++ b/bsd/sys/dev/hyperv/include/vmbus.h
@@ -0,0 +1,230 @@
+/*-
+ * 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 _VMBUS_H_
+#define _VMBUS_H_
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+/*
+ * VMBUS version is 32 bit, upper 16 bit for major_number and lower
+ * 16 bit for minor_number.
+ *
+ * 0.13  --  Windows Server 2008
+ * 1.1   --  Windows 7
+ * 2.4   --  Windows 8
+ * 3.0   --  Windows 8.1
+ */
+#define VMBUS_VERSION_WS2008            ((0 << 16) | (13))
+#define VMBUS_VERSION_WIN7              ((1 << 16) | (1))
+#define VMBUS_VERSION_WIN8              ((2 << 16) | (4))
+#define VMBUS_VERSION_WIN8_1            ((3 << 16) | (0))
+
+#define VMBUS_VERSION_MAJOR(ver)        (((uint32_t)(ver)) >> 16)
+#define VMBUS_VERSION_MINOR(ver)        (((uint32_t)(ver)) & 0xffff)
+
+#define VMBUS_CHAN_POLLHZ_MIN           100     /* 10ms interval */
+#define VMBUS_CHAN_POLLHZ_MAX           1000000 /* 1us interval */
+
+/*
+ * GPA stuffs.
+ */
+struct vmbus_gpa_range {
+    uint32_t    gpa_len;
+    uint32_t    gpa_ofs;
+    uint64_t    gpa_page[0];
+} __packed;
+
+/* This is actually vmbus_gpa_range.gpa_page[1] */
+struct vmbus_gpa {
+    uint32_t    gpa_len;
+    uint32_t    gpa_ofs;
+    uint64_t    gpa_page;
+} __packed;
+
+#define VMBUS_CHANPKT_SIZE_SHIFT        3
+
+#define VMBUS_CHANPKT_GETLEN(pktlen)    \
+    (((int)(pktlen)) << VMBUS_CHANPKT_SIZE_SHIFT)
+
+struct vmbus_chanpkt_hdr {
+    uint16_t    cph_type;       /* VMBUS_CHANPKT_TYPE_ */
+    uint16_t    cph_hlen;       /* header len, in 8 bytes */
+    uint16_t    cph_tlen;       /* total len, in 8 bytes */
+    uint16_t    cph_flags;      /* VMBUS_CHANPKT_FLAG_ */
+    uint64_t    cph_xactid;
+} __packed;
+
+#define VMBUS_CHANPKT_TYPE_INBAND       0x0006
+#define VMBUS_CHANPKT_TYPE_RXBUF        0x0007
+#define VMBUS_CHANPKT_TYPE_GPA          0x0009
+#define VMBUS_CHANPKT_TYPE_COMP         0x000b
+
+#define VMBUS_CHANPKT_FLAG_NONE         0
+#define VMBUS_CHANPKT_FLAG_RC           0x0001  /* report completion */
+
+#define VMBUS_CHANPKT_CONST_DATA(pkt)           \
+    (const void *)((const uint8_t *)(pkt) +     \
+    VMBUS_CHANPKT_GETLEN((pkt)->cph_hlen))
+
+/* Include padding */
+#define VMBUS_CHANPKT_DATALEN(pkt)              \
+    (VMBUS_CHANPKT_GETLEN((pkt)->cph_tlen) -\
+     VMBUS_CHANPKT_GETLEN((pkt)->cph_hlen))
+
+struct vmbus_rxbuf_desc {
+    uint32_t    rb_len;
+    uint32_t    rb_ofs;
+} __packed;
+
+struct vmbus_chanpkt_rxbuf {
+    struct vmbus_chanpkt_hdr cp_hdr;
+    uint16_t    cp_rxbuf_id;
+    uint16_t    cp_rsvd;
+    uint32_t    cp_rxbuf_cnt;
+    struct vmbus_rxbuf_desc cp_rxbuf[];
+} __packed;
+
+struct vmbus_chan_br {
+    void                *cbr;
+    bus_addr_t  cbr_paddr;
+    int         cbr_txsz;
+    int         cbr_rxsz;
+};
+
+struct vmbus_channel;
+struct vmbus_xact;
+struct vmbus_xact_ctx;
+struct hyperv_guid;
+struct task;
+struct taskqueue;
+
+typedef void    (*vmbus_chan_callback_t)(struct vmbus_channel *, void *);
+
+static __inline struct vmbus_channel *
+vmbus_get_channel(device_t dev)
+{
+    return device_get_ivars(dev);
+}
+
+/*
+ * vmbus_chan_open_br()
+ *
+ * Return values:
+ * 0                    Succeeded.
+ * EISCONN              Failed, and the memory passed through 'br' is still
+ *                      connected.  Callers must _not_ free the the memory
+ *                      passed through 'br', if this error happens.
+ * other values         Failed.  The memory passed through 'br' is no longer
+ *                      connected.  Callers are free to do anything with the
+ *                      memory passed through 'br'.
+ *
+ *
+ *
+ * vmbus_chan_close_direct()
+ *
+ * NOTE:
+ * Callers of this function _must_ make sure to close all sub-channels before
+ * closing the primary channel.
+ *
+ * Return values:
+ * 0                    Succeeded.
+ * EISCONN              Failed, and the memory associated with the bufring
+ *                      is still connected.  Callers must _not_ free the the
+ *                      memory associated with the bufring, if this error
+ *                      happens.
+ * other values         Failed.  The memory associated with the bufring is
+ *                      no longer connected.  Callers are free to do anything
+ *                      with the memory associated with the bufring.
+ */
+int             vmbus_chan_open(struct vmbus_channel *chan,
+                    int txbr_size, int rxbr_size, const void *udata, int udlen,
+                    vmbus_chan_callback_t cb, void *cbarg);
+int             vmbus_chan_open_br(struct vmbus_channel *chan,
+                    const struct vmbus_chan_br *cbr, const void *udata,
+                    int udlen, vmbus_chan_callback_t cb, void *cbarg);
+void            vmbus_chan_close(struct vmbus_channel *chan);
+int             vmbus_chan_close_direct(struct vmbus_channel *chan);
+void            vmbus_chan_intr_drain(struct vmbus_channel *chan);
+void            vmbus_chan_run_task(struct vmbus_channel *chan,
+                    struct task *task);
+void            vmbus_chan_set_orphan(struct vmbus_channel *chan,
+                    struct vmbus_xact_ctx *);
+void            vmbus_chan_unset_orphan(struct vmbus_channel *chan);
+const void      *vmbus_chan_xact_wait(const struct vmbus_channel *chan,
+                    struct vmbus_xact *xact, size_t *resp_len, bool can_sleep);
+
+int             vmbus_chan_gpadl_connect(struct vmbus_channel *chan,
+                    bus_addr_t paddr, int size, uint32_t *gpadl);
+int             vmbus_chan_gpadl_disconnect(struct vmbus_channel *chan,
+                    uint32_t gpadl);
+
+void            vmbus_chan_cpu_set(struct vmbus_channel *chan, int cpu);
+void            vmbus_chan_cpu_rr(struct vmbus_channel *chan);
+void            vmbus_chan_set_readbatch(struct vmbus_channel *chan, bool on);
+
+struct vmbus_channel **
+                vmbus_subchan_get(struct vmbus_channel *pri_chan,
+                    int subchan_cnt);
+void            vmbus_subchan_rel(struct vmbus_channel **subchan,
+                    int subchan_cnt);
+void            vmbus_subchan_drain(struct vmbus_channel *pri_chan);
+
+int             vmbus_chan_recv(struct vmbus_channel *chan, void *data, int 
*dlen,
+                    uint64_t *xactid);
+int             vmbus_chan_recv_pkt(struct vmbus_channel *chan,
+                    struct vmbus_chanpkt_hdr *pkt, int *pktlen);
+
+int             vmbus_chan_send(struct vmbus_channel *chan, uint16_t type,
+                    uint16_t flags, void *data, int dlen, uint64_t xactid);
+int             vmbus_chan_send_sglist(struct vmbus_channel *chan,
+                    struct vmbus_gpa sg[], int sglen, void *data, int dlen,
+                    uint64_t xactid);
+int             vmbus_chan_send_prplist(struct vmbus_channel *chan,
+                    struct vmbus_gpa_range *prp, int prp_cnt, void *data,
+                    int dlen, uint64_t xactid);
+
+uint32_t        vmbus_chan_id(const struct vmbus_channel *chan);
+uint32_t        vmbus_chan_subidx(const struct vmbus_channel *chan);
+bool            vmbus_chan_is_primary(const struct vmbus_channel *chan);
+bool            vmbus_chan_is_revoked(const struct vmbus_channel *chan);
+const struct hyperv_guid *
+                vmbus_chan_guid_inst(const struct vmbus_channel *chan);
+int             vmbus_chan_prplist_nelem(int br_size, int prpcnt_max,
+                    int dlen_max);
+bool            vmbus_chan_rx_empty(const struct vmbus_channel *chan);
+bool            vmbus_chan_tx_empty(const struct vmbus_channel *chan);
+struct taskqueue *
+                vmbus_chan_mgmt_tq(const struct vmbus_channel *chan);
+
+void            vmbus_chan_poll_enable(struct vmbus_channel *chan,
+                    u_int pollhz);
+void            vmbus_chan_poll_disable(struct vmbus_channel *chan);
+
+#endif  /* !_VMBUS_H_ */
diff --git a/bsd/sys/dev/hyperv/include/vmbus_xact.h 
b/bsd/sys/dev/hyperv/include/vmbus_xact.h
new file mode 100644
index 0000000..f529945
--- /dev/null
+++ b/bsd/sys/dev/hyperv/include/vmbus_xact.h
@@ -0,0 +1,65 @@
+/*-
+ * 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 _VMBUS_XACT_H_
+#define _VMBUS_XACT_H_
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+struct vmbus_xact;
+struct vmbus_xact_ctx;
+
+struct vmbus_xact_ctx   *vmbus_xact_ctx_create(bus_dma_tag_t dtag,
+                            size_t req_size, size_t resp_size,
+                            size_t priv_size);
+void                    vmbus_xact_ctx_destroy(struct vmbus_xact_ctx *ctx);
+bool                    vmbus_xact_ctx_orphan(struct vmbus_xact_ctx *ctx);
+
+struct vmbus_xact       *vmbus_xact_get(struct vmbus_xact_ctx *ctx,
+                            size_t req_len);
+void                    vmbus_xact_put(struct vmbus_xact *xact);
+
+void                    *vmbus_xact_req_data(const struct vmbus_xact *xact);
+bus_addr_t              vmbus_xact_req_paddr(const struct vmbus_xact *xact);
+void                    *vmbus_xact_priv(const struct vmbus_xact *xact,
+                            size_t priv_len);
+void                    vmbus_xact_activate(struct vmbus_xact *xact);
+void                    vmbus_xact_deactivate(struct vmbus_xact *xact);
+const void              *vmbus_xact_wait(struct vmbus_xact *xact,
+                            size_t *resp_len);
+const void              *vmbus_xact_busywait(struct vmbus_xact *xact,
+                            size_t *resp_len);
+const void              *vmbus_xact_poll(struct vmbus_xact *xact,
+                            size_t *resp_len);
+void                    vmbus_xact_wakeup(struct vmbus_xact *xact,
+                            const void *data, size_t dlen);
+void                    vmbus_xact_ctx_wakeup(struct vmbus_xact_ctx *ctx,
+                            const void *data, size_t dlen);
+
+#endif  /* !_VMBUS_XACT_H_ */
diff --git a/bsd/sys/dev/hyperv/vmbus/hyperv.cc 
b/bsd/sys/dev/hyperv/vmbus/hyperv.cc
new file mode 100644
index 0000000..757672a
--- /dev/null
+++ b/bsd/sys/dev/hyperv/vmbus/hyperv.cc
@@ -0,0 +1,327 @@
+/*-
+ * 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/systm.h>
+#include <sys/timetc.h>
+
+#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/hyperv/vmbus/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/hyperv_reg.h>
+#include <dev/hyperv/vmbus/hyperv_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 *);
+static bool                     hyperv_identify(void);
+static void                     hypercall_memfree(void);
+
+u_int                           hyperv_features;
+u_int                           hyperv_recommends;
+
+static u_int                    hyperv_pm_features;
+static u_int                    hyperv_features3;
+
+hyperv_tc64_t                   hyperv_tc64;
+
+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);
+}
+
+static uint64_t
+hyperv_tc64_rdmsr(void)
+{
+
+    return (rdmsr(MSR_HV_TIME_REF_COUNT));
+}
+
+uint64_t
+hypercall_post_message(bus_addr_t msg_paddr)
+{
+    return hypercall_md(hypercall_context.hc_addr,
+        HYPERCALL_POST_MESSAGE, msg_paddr, 0);
+}
+
+uint64_t
+hypercall_signal_event(bus_addr_t monprm_paddr)
+{
+    return hypercall_md(hypercall_context.hc_addr,
+        HYPERCALL_SIGNAL_EVENT, monprm_paddr, 0);
+}
+
+int
+hyperv_guid2str(const struct hyperv_guid *guid, char *buf, size_t sz)
+{
+    const uint8_t *d = guid->hv_guid;
+
+    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);
+
+        /*
+         * Install 64 bits timecounter method for other modules
+         * to use.
+         */
+        hyperv_tc64 = hyperv_tc64_rdmsr;
+    }
+}
+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);
-- 
2.7.4

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to