The branch main has been updated by whu:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=9729f076e4d93c5a37e78d427bfe0f1ab99bbcc6

commit 9729f076e4d93c5a37e78d427bfe0f1ab99bbcc6
Author:     Souradeep Chakrabarti <schakraba...@microsoft.com>
AuthorDate: 2022-10-27 13:46:08 +0000
Commit:     Wei Hu <w...@freebsd.org>
CommitDate: 2022-10-27 13:53:22 +0000

    arm64: Hyper-V: enablement for ARM64 in Hyper-V (Part 3, final)
    
    This is the last part for ARM64 Hyper-V enablement. This includes
    commone files and make file changes to enable the ARM64 FreeBSD
    guest on Hyper-V. With this patch, it should be able to build
    the ARM64 image and install it on Hyper-V.
    
    Reviewed by:    emaste, andrew, whu
    Tested by:      Souradeep Chakrabarti <schakraba...@microsoft.com>
    Sponsored by:   Microsoft
    Differential Revision:  https://reviews.freebsd.org/D36744
---
 share/mk/src.opts.mk                        |   3 +-
 sys/arm64/conf/GENERIC                      |   1 +
 sys/arm64/conf/std.dev                      |   3 +
 sys/arm64/conf/std.hyperv                   |   6 +
 sys/conf/files.arm64                        |  22 ++++
 sys/conf/files.x86                          |   2 +
 sys/dev/hyperv/include/hyperv.h             |   5 +
 sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c |   5 +-
 sys/dev/hyperv/vmbus/hyperv.c               | 194 +++------------------------
 sys/dev/hyperv/vmbus/hyperv_machdep.h       |  37 ------
 sys/dev/hyperv/vmbus/hyperv_reg.h           | 193 ---------------------------
 sys/dev/hyperv/vmbus/hyperv_var.h           |   4 +
 sys/dev/hyperv/vmbus/i386/hyperv_machdep.c  |   2 +-
 sys/dev/hyperv/vmbus/vmbus.c                | 197 +++++++++-------------------
 sys/dev/hyperv/vmbus/vmbus_et.c             |   7 +-
 sys/dev/hyperv/vmbus/vmbus_reg.h            |   7 +-
 sys/dev/hyperv/vmbus/vmbus_var.h            |  15 +++
 sys/modules/Makefile                        |   1 +
 sys/modules/hyperv/utilities/Makefile       |   1 -
 sys/modules/hyperv/vmbus/Makefile           |  11 +-
 20 files changed, 164 insertions(+), 552 deletions(-)

diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
index a03b8147ecbb..4c0913474ef7 100644
--- a/share/mk/src.opts.mk
+++ b/share/mk/src.opts.mk
@@ -332,8 +332,7 @@ BROKEN_OPTIONS+=CXGBETOOL
 BROKEN_OPTIONS+=MLX5TOOL
 .endif
 
-# HyperV is currently x86-only
-.if ${__T} != "amd64" && ${__T} != "i386"
+.if ${__T} != "amd64" && ${__T} != "i386" && ${__T} != "aarch64"
 BROKEN_OPTIONS+=HYPERV
 .endif
 
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
index c716183aae61..60772893cdbb 100644
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -31,6 +31,7 @@ include               "std.amd"
 include                "std.arm"
 include                "std.broadcom"
 include                "std.cavium"
+include                "std.hyperv"
 include                "std.hisilicon"
 include                "std.imx"
 include                "std.marvell"
diff --git a/sys/arm64/conf/std.dev b/sys/arm64/conf/std.dev
index 6ef7358e5e85..8cdd35e2fd21 100644
--- a/sys/arm64/conf/std.dev
+++ b/sys/arm64/conf/std.dev
@@ -107,3 +107,6 @@ device              mmcsd                   # mmc/sd flash 
cards
 # HID support
 options        HID_DEBUG               # enable debug msgs
 device         hid                     # Generic HID support
+
+#hyper-v support
+device         hyperv
diff --git a/sys/arm64/conf/std.hyperv b/sys/arm64/conf/std.hyperv
new file mode 100644
index 000000000000..f87082f15c96
--- /dev/null
+++ b/sys/arm64/conf/std.hyperv
@@ -0,0 +1,6 @@
+#
+# Hyper-V support (Hyper-v Gen 2)
+#
+
+#hyper-v support
+device      hyperv
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 5178048cb0af..8b6ba43d2a3d 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -624,3 +624,25 @@ arm64/rockchip/clk/rk3399_pmucru.c         optional fdt 
soc_rockchip_rk3399
 
 # Xilinx
 arm/xilinx/uart_dev_cdnc.c                     optional uart soc_xilinx_zynq
+
+# Microsoft Hyper-V
+dev/hyperv/vmbus/hyperv.c              optional        hyperv
+dev/hyperv/vmbus/aarch64/hyperv_aarch64.c              optional    hyperv
+dev/hyperv/vmbus/vmbus.c                               optional        hyperv 
pci
+dev/hyperv/vmbus/aarch64/vmbus_aarch64.c               optional    hyperv
+dev/hyperv/vmbus/vmbus_if.m                            optional        hyperv
+dev/hyperv/vmbus/vmbus_res.c                           optional        hyperv
+dev/hyperv/vmbus/vmbus_xact.c                          optional        hyperv
+dev/hyperv/vmbus/aarch64/hyperv_machdep.c                              
optional    hyperv
+dev/hyperv/vmbus/vmbus_chan.c                          optional                
hyperv
+dev/hyperv/vmbus/hyperv_busdma.c                               optional hyperv
+dev/hyperv/vmbus/vmbus_br.c                            optional        hyperv
+dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c                            
optional hyperv
+dev/hyperv/utilities/vmbus_timesync.c                          optional        
hyperv
+dev/hyperv/utilities/vmbus_heartbeat.c                         optional    
hyperv
+dev/hyperv/utilities/vmbus_ic.c                                optional    
hyperv
+dev/hyperv/utilities/vmbus_shutdown.c                          optional    
hyperv
+dev/hyperv/utilities/hv_kvp.c                  optional   hyperv
+dev/hyperv/netvsc/hn_nvs.c                             optional        hyperv
+dev/hyperv/netvsc/hn_rndis.c                   optional        hyperv
+dev/hyperv/netvsc/if_hn.c                              optional        hyperv
diff --git a/sys/conf/files.x86 b/sys/conf/files.x86
index e8f65628c5c1..4547adcda8bb 100644
--- a/sys/conf/files.x86
+++ b/sys/conf/files.x86
@@ -132,6 +132,8 @@ dev/hyperv/utilities/vmbus_ic.c                             
optional        hyperv
 dev/hyperv/utilities/vmbus_shutdown.c                  optional        hyperv
 dev/hyperv/utilities/vmbus_timesync.c                  optional        hyperv
 dev/hyperv/vmbus/hyperv.c                              optional        hyperv
+dev/hyperv/vmbus/x86/hyperv_x86.c              optional    hyperv
+dev/hyperv/vmbus/x86/vmbus_x86.c               optional    hyperv
 dev/hyperv/vmbus/hyperv_busdma.c                       optional        hyperv
 dev/hyperv/vmbus/vmbus.c                               optional        hyperv 
pci
 dev/hyperv/vmbus/vmbus_br.c                            optional        hyperv
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h
index 8b985b2f31a7..2e46a092a16e 100644
--- a/sys/dev/hyperv/include/hyperv.h
+++ b/sys/dev/hyperv/include/hyperv.h
@@ -86,6 +86,11 @@ typedef uint64_t                     (*hyperv_tc64_t)(void);
 int                    hyperv_guid2str(const struct hyperv_guid *, char *,
                            size_t);
 
+void   hyperv_init_tc(void);
+int            hypercall_page_setup(vm_paddr_t);
+void   hypercall_disable(void);
+bool   hyperv_identify_features(void);
+
 /*
  * hyperv_tc64 could be NULL, if there were no suitable Hyper-V
  * specific timecounter.
diff --git a/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c 
b/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
index f3f5308fa6dc..c158f72eb9e7 100644
--- a/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
+++ b/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
@@ -44,9 +44,10 @@ __FBSDID("$FreeBSD$");
 
 #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/x86/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/x86/hyperv_reg.h>
 #include <dev/hyperv/vmbus/hyperv_var.h>
+#include <dev/hyperv/vmbus/hyperv_common_reg.h>
 
 struct hyperv_reftsc_ctx {
        struct hyperv_reftsc    *tsc_ref;
diff --git a/sys/dev/hyperv/vmbus/hyperv.c b/sys/dev/hyperv/vmbus/hyperv.c
index b2a74036f6c3..38217d1f0b67 100644
--- a/sys/dev/hyperv/vmbus/hyperv.c
+++ b/sys/dev/hyperv/vmbus/hyperv.c
@@ -45,8 +45,14 @@ __FBSDID("$FreeBSD$");
 
 #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>
+#if defined(__aarch64__)
+#include <dev/hyperv/vmbus/aarch64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/aarch64/hyperv_reg.h>
+#else
+#include <dev/hyperv/vmbus/x86/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/x86/hyperv_reg.h>
+#endif
+#include <dev/hyperv/vmbus/hyperv_common_reg.h>
 #include <dev/hyperv/vmbus/hyperv_var.h>
 
 #define HYPERV_FREEBSD_BUILD           0ULL
@@ -68,51 +74,10 @@ __FBSDID("$FreeBSD$");
         MSR_HV_GUESTID_OSID_FREEBSD |  \
         MSR_HV_GUESTID_OSTYPE_FREEBSD)
 
-struct hypercall_ctx {
-       void                    *hc_addr;
-       vm_paddr_t              hc_paddr;
-};
-
-static u_int                   hyperv_get_timecount(struct timecounter *);
 static bool                    hyperv_identify(void);
 static void                    hypercall_memfree(void);
 
-u_int                          hyperv_ver_major;
-
-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)
 {
@@ -143,97 +108,8 @@ hyperv_guid2str(const struct hyperv_guid *guid, char *buf, 
size_t sz)
 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);
-       hyperv_ver_major = regs[1] >> 16;
-       printf("Hyper-V Version: %d.%d.%d [SP%d]\n",
-           hyperv_ver_major, 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);
+       return(hyperv_identify_features());
 }
-
 static void
 hyperv_init(void *dummy __unused)
 {
@@ -245,22 +121,8 @@ hyperv_init(void *dummy __unused)
        }
 
        /* 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.  This should be done as early
-                * as possible to let DELAY() work, since the 8254 PIT is not
-                * reliably emulated or even available.
-                */
-               tc_init(&hyperv_timecounter);
-
-               /*
-                * Install 64 bits timecounter method for other modules
-                * to use.
-                */
-               hyperv_tc64 = hyperv_tc64_rdmsr;
-       }
+       WRMSR(MSR_HV_GUEST_OS_ID, MSR_HV_GUESTID_FREEBSD);
+       hyperv_init_tc();       
 }
 SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init,
     NULL);
@@ -275,8 +137,8 @@ hypercall_memfree(void)
 static void
 hypercall_create(void *arg __unused)
 {
-       uint64_t hc, hc_orig;
 
+       int ret;
        if (vm_guest != VM_GUEST_HV)
                return;
 
@@ -288,30 +150,9 @@ hypercall_create(void *arg __unused)
         */
        hypercall_context.hc_addr = kmem_malloc(PAGE_SIZE, M_EXEC | M_WAITOK);
        hypercall_context.hc_paddr = vtophys(hypercall_context.hc_addr);
-
-       /* 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_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");
+       ret = hypercall_page_setup(hypercall_context.hc_paddr);
+       if (ret) {
                hypercall_memfree();
-               /* Can't perform any Hyper-V specific actions */
-               vm_guest = VM_GUEST_VM;
                return;
        }
        if (bootverbose)
@@ -322,16 +163,11 @@ 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_disable();
        hypercall_memfree();
-
        if (bootverbose)
                printf("hyperv: Hypercall destroyed\n");
 }
diff --git a/sys/dev/hyperv/vmbus/hyperv_machdep.h 
b/sys/dev/hyperv/vmbus/hyperv_machdep.h
deleted file mode 100644
index 48cf5b78dc3b..000000000000
--- a/sys/dev/hyperv/vmbus/hyperv_machdep.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-
- * 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_MACHDEP_H_
-#define _HYPERV_MACHDEP_H_
-
-#include <sys/param.h>
-
-uint64_t       hypercall_md(volatile void *hc_addr, uint64_t in_val,
-                   uint64_t in_paddr, uint64_t out_paddr);
-
-#endif /* !_HYPERV_MACHDEP_H_ */
diff --git a/sys/dev/hyperv/vmbus/hyperv_reg.h 
b/sys/dev/hyperv/vmbus/hyperv_reg.h
deleted file mode 100644
index b3b133c84881..000000000000
--- a/sys/dev/hyperv/vmbus/hyperv_reg.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*-
- * Copyright (c) 2016 Microsoft Corp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice unmodified, this list of conditions, and the following
- *    disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _HYPERV_REG_H_
-#define _HYPERV_REG_H_
-
-#include <sys/param.h>
-#include <sys/systm.h>
-
-/*
- * Hyper-V Synthetic MSRs
- */
-
-#define MSR_HV_GUEST_OS_ID             0x40000000
-#define MSR_HV_GUESTID_BUILD_MASK      0xffffULL
-#define MSR_HV_GUESTID_VERSION_MASK    0x0000ffffffff0000ULL
-#define MSR_HV_GUESTID_VERSION_SHIFT   16
-#define MSR_HV_GUESTID_OSID_MASK       0x00ff000000000000ULL
-#define MSR_HV_GUESTID_OSID_SHIFT      48
-#define MSR_HV_GUESTID_OSTYPE_MASK     0x7f00000000000000ULL
-#define MSR_HV_GUESTID_OSTYPE_SHIFT    56
-#define MSR_HV_GUESTID_OPENSRC         0x8000000000000000ULL
-#define MSR_HV_GUESTID_OSTYPE_LINUX    \
-       ((0x01ULL << MSR_HV_GUESTID_OSTYPE_SHIFT) | MSR_HV_GUESTID_OPENSRC)
-#define MSR_HV_GUESTID_OSTYPE_FREEBSD  \
-       ((0x02ULL << MSR_HV_GUESTID_OSTYPE_SHIFT) | MSR_HV_GUESTID_OPENSRC)
-
-#define MSR_HV_HYPERCALL               0x40000001
-#define MSR_HV_HYPERCALL_ENABLE                0x0001ULL
-#define MSR_HV_HYPERCALL_RSVD_MASK     0x0ffeULL
-#define MSR_HV_HYPERCALL_PGSHIFT       12
-
-#define MSR_HV_VP_INDEX                        0x40000002
-
-#define MSR_HV_REFERENCE_TSC           0x40000021
-#define MSR_HV_REFTSC_ENABLE           0x0001ULL
-#define MSR_HV_REFTSC_RSVD_MASK                0x0ffeULL
-#define MSR_HV_REFTSC_PGSHIFT          12
-
-#define MSR_HV_SCONTROL                        0x40000080
-#define MSR_HV_SCTRL_ENABLE            0x0001ULL
-#define MSR_HV_SCTRL_RSVD_MASK         0xfffffffffffffffeULL
-
-#define MSR_HV_SIEFP                   0x40000082
-#define MSR_HV_SIEFP_ENABLE            0x0001ULL
-#define MSR_HV_SIEFP_RSVD_MASK         0x0ffeULL
-#define MSR_HV_SIEFP_PGSHIFT           12
-
-#define MSR_HV_SIMP                    0x40000083
-#define MSR_HV_SIMP_ENABLE             0x0001ULL
-#define MSR_HV_SIMP_RSVD_MASK          0x0ffeULL
-#define MSR_HV_SIMP_PGSHIFT            12
-
-#define MSR_HV_EOM                     0x40000084
-
-#define MSR_HV_SINT0                   0x40000090
-#define MSR_HV_SINT_VECTOR_MASK                0x00ffULL
-#define MSR_HV_SINT_RSVD1_MASK         0xff00ULL
-#define MSR_HV_SINT_MASKED             0x00010000ULL
-#define MSR_HV_SINT_AUTOEOI            0x00020000ULL
-#define MSR_HV_SINT_RSVD2_MASK         0xfffffffffffc0000ULL
-#define MSR_HV_SINT_RSVD_MASK          (MSR_HV_SINT_RSVD1_MASK |       \
-                                        MSR_HV_SINT_RSVD2_MASK)
-
-#define MSR_HV_STIMER0_CONFIG          0x400000b0
-#define MSR_HV_STIMER_CFG_ENABLE       0x0001ULL
-#define MSR_HV_STIMER_CFG_PERIODIC     0x0002ULL
-#define MSR_HV_STIMER_CFG_LAZY         0x0004ULL
-#define MSR_HV_STIMER_CFG_AUTOEN       0x0008ULL
-#define MSR_HV_STIMER_CFG_SINT_MASK    0x000f0000ULL
-#define MSR_HV_STIMER_CFG_SINT_SHIFT   16
-
-#define MSR_HV_STIMER0_COUNT           0x400000b1
-
-/*
- * CPUID leaves
- */
-
-#define CPUID_LEAF_HV_MAXLEAF          0x40000000
-
-#define CPUID_LEAF_HV_INTERFACE                0x40000001
-#define CPUID_HV_IFACE_HYPERV          0x31237648      /* HV#1 */
-
-#define CPUID_LEAF_HV_IDENTITY         0x40000002
-
-#define CPUID_LEAF_HV_FEATURES         0x40000003
-/* EAX: features include/hyperv.h CPUID_HV_MSR */
-/* ECX: power management features */
-#define CPUPM_HV_CSTATE_MASK           0x000f  /* deepest C-state */
-#define CPUPM_HV_C3_HPET               0x0010  /* C3 requires HPET */
-#define CPUPM_HV_CSTATE(f)             ((f) & CPUPM_HV_CSTATE_MASK)
-/* EDX: features3 */
-#define CPUID3_HV_MWAIT                        0x0001  /* MWAIT */
-#define CPUID3_HV_XMM_HYPERCALL                0x0010  /* Hypercall input 
through
-                                                * XMM regs */
-#define CPUID3_HV_GUEST_IDLE           0x0020  /* guest idle */
-#define CPUID3_HV_NUMA                 0x0080  /* NUMA distance query */
-#define CPUID3_HV_TIME_FREQ            0x0100  /* timer frequency query
-                                                * (TSC, LAPIC) */
-#define CPUID3_HV_MSR_CRASH            0x0400  /* MSRs for guest crash */
-
-#define CPUID_LEAF_HV_RECOMMENDS       0x40000004
-#define CPUID_LEAF_HV_LIMITS           0x40000005
-#define CPUID_LEAF_HV_HWFEATURES       0x40000006
-
-/*
- * Hyper-V Monitor Notification Facility
- */
-struct hyperv_mon_param {
-       uint32_t        mp_connid;
-       uint16_t        mp_evtflag_ofs;
-       uint16_t        mp_rsvd;
-} __packed;
-
-/*
- * Hyper-V message types
- */
-#define HYPERV_MSGTYPE_NONE            0
-#define HYPERV_MSGTYPE_CHANNEL         1
-#define HYPERV_MSGTYPE_TIMER_EXPIRED   0x80000010
-
-/*
- * Hypercall status codes
- */
-#define HYPERCALL_STATUS_SUCCESS       0x0000
-
-/*
- * Hypercall input values
- */
-#define HYPERCALL_POST_MESSAGE         0x005c
-#define HYPERCALL_SIGNAL_EVENT         0x005d
-
-/*
- * Hypercall input parameters
- */
-#define HYPERCALL_PARAM_ALIGN          8
-#if 0
-/*
- * XXX
- * <<Hypervisor Top Level Functional Specification 4.0b>> requires
- * input parameters size to be multiple of 8, however, many post
- * message input parameters do _not_ meet this requirement.
- */
-#define HYPERCALL_PARAM_SIZE_ALIGN     8
-#endif
-
-/*
- * HYPERCALL_POST_MESSAGE
- */
-#define HYPERCALL_POSTMSGIN_DSIZE_MAX  240
-#define HYPERCALL_POSTMSGIN_SIZE       256
-
-struct hypercall_postmsg_in {
-       uint32_t        hc_connid;
-       uint32_t        hc_rsvd;
-       uint32_t        hc_msgtype;     /* HYPERV_MSGTYPE_ */
-       uint32_t        hc_dsize;
-       uint8_t         hc_data[HYPERCALL_POSTMSGIN_DSIZE_MAX];
-} __packed;
-CTASSERT(sizeof(struct hypercall_postmsg_in) == HYPERCALL_POSTMSGIN_SIZE);
-
-/*
- * HYPERCALL_SIGNAL_EVENT
- *
- * struct hyperv_mon_param.
- */
-
-#endif /* !_HYPERV_REG_H_ */
diff --git a/sys/dev/hyperv/vmbus/hyperv_var.h 
b/sys/dev/hyperv/vmbus/hyperv_var.h
index f620e4fd64ae..3272569893e9 100644
--- a/sys/dev/hyperv/vmbus/hyperv_var.h
+++ b/sys/dev/hyperv/vmbus/hyperv_var.h
@@ -31,6 +31,10 @@
 
 extern u_int   hyperv_recommends;
 
+struct hypercall_ctx {
+    void            *hc_addr;
+    vm_paddr_t      hc_paddr;
+};
 uint64_t       hypercall_post_message(bus_addr_t msg_paddr);
 uint64_t       hypercall_signal_event(bus_addr_t monprm_paddr);
 
diff --git a/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c 
b/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c
index b12bff855f63..f0dcf3ba1004 100644
--- a/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c
+++ b/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c
@@ -28,7 +28,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
-#include <dev/hyperv/vmbus/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/x86/hyperv_machdep.h>
 
 uint64_t
 hypercall_md(volatile void *hc_addr, uint64_t in_val,
diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c
index b0cd750b26c8..f370f2a75b99 100644
--- a/sys/dev/hyperv/vmbus/vmbus.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -51,23 +51,29 @@ __FBSDID("$FreeBSD$");
 #include <vm/pmap.h>
 
 #include <machine/bus.h>
+#if defined(__aarch64__)
+#include <dev/psci/smccc.h>
+#include <dev/hyperv/vmbus/aarch64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/aarch64/hyperv_reg.h>
+#else
+#include <dev/hyperv/vmbus/x86/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/x86/hyperv_reg.h>
 #include <machine/intr_machdep.h>
+#include <x86/include/apicvar.h>
+#endif
 #include <machine/metadata.h>
 #include <machine/md_var.h>
 #include <machine/resource.h>
-#include <x86/include/apicvar.h>
-
 #include <contrib/dev/acpica/include/acpi.h>
 #include <dev/acpica/acpivar.h>
 
 #include <dev/hyperv/include/hyperv.h>
 #include <dev/hyperv/include/vmbus_xact.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 <dev/hyperv/vmbus/vmbus_chanvar.h>
-
+#include <dev/hyperv/vmbus/hyperv_common_reg.h>
 #include "acpi_if.h"
 #include "pcib_if.h"
 #include "vmbus_if.h"
@@ -107,7 +113,7 @@ static uint32_t                     
vmbus_get_vcpu_id_method(device_t bus,
                                    device_t dev, int cpu);
 static struct taskqueue                *vmbus_get_eventtq_method(device_t, 
device_t,
                                    int);
-#ifdef EARLY_AP_STARTUP
+#if defined(EARLY_AP_STARTUP) || defined(__aarch64__)
 static void                    vmbus_intrhook(void *);
 #endif
 
@@ -132,7 +138,6 @@ static void                 vmbus_intr_teardown(struct 
vmbus_softc *);
 static int                     vmbus_doattach(struct vmbus_softc *);
 static void                    vmbus_event_proc_dummy(struct vmbus_softc *,
                                    int);
-
 static struct vmbus_softc      *vmbus_sc;
 
 SYSCTL_NODE(_hw, OID_AUTO, vmbus, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
@@ -141,10 +146,6 @@ SYSCTL_NODE(_hw, OID_AUTO, vmbus, CTLFLAG_RD | 
CTLFLAG_MPSAFE, NULL,
 static int                     vmbus_pin_evttask = 1;
 SYSCTL_INT(_hw_vmbus, OID_AUTO, pin_evttask, CTLFLAG_RDTUN,
     &vmbus_pin_evttask, 0, "Pin event tasks to their respective CPU");
-
-extern inthand_t IDTVEC(vmbus_isr), IDTVEC(vmbus_isr_pti);
-#define VMBUS_ISR_ADDR trunc_page((uintptr_t)IDTVEC(vmbus_isr_pti))
-
 uint32_t                       vmbus_current_version;
 
 static const uint32_t          vmbus_version[] = {
@@ -660,11 +661,10 @@ vmbus_msg_task(void *xsc, int pending __unused)
                         * This will cause message queue rescan to possibly
                         * deliver another msg from the hypervisor
                         */
-                       wrmsr(MSR_HV_EOM, 0);
+                       WRMSR(MSR_HV_EOM, 0);
                }
        }
 }
-
 static __inline int
 vmbus_handle_intr1(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
 {
@@ -678,33 +678,7 @@ vmbus_handle_intr1(struct vmbus_softc *sc, struct 
trapframe *frame, int cpu)
         *
         * TODO: move this to independent IDT vector.
         */
-       msg = msg_base + VMBUS_SINT_TIMER;
-       if (msg->msg_type == HYPERV_MSGTYPE_TIMER_EXPIRED) {
-               msg->msg_type = HYPERV_MSGTYPE_NONE;
-
-               vmbus_et_intr(frame);
-
-               /*
-                * Make sure the write to msg_type (i.e. set to
-                * HYPERV_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);
-               }
-       }
-
+       vmbus_handle_timer_intr1(msg_base, frame);
        /*
         * Check events.  Hot path for network and storage I/O data; high rate.
         *
@@ -738,10 +712,12 @@ vmbus_handle_intr(struct trapframe *trap_frame)
        critical_enter();
 
        /*
-        * Do a little interrupt counting.
+        * Do a little interrupt counting. This used x86 specific
+        * intrcnt_add function
         */
+#if !defined(__aarch64__)
        (*VMBUS_PCPU_GET(sc, intr_cnt, cpu))++;
-
+#endif /* not for aarch64 */
        vmbus_handle_intr1(sc, trap_frame, cpu);
 
        /*
@@ -760,7 +736,7 @@ vmbus_synic_setup(void *xsc)
 
        if (hyperv_features & CPUID_HV_MSR_VP_INDEX) {
                /* Save virtual processor id. */
-               VMBUS_PCPU_GET(sc, vcpuid, cpu) = rdmsr(MSR_HV_VP_INDEX);
+               VMBUS_PCPU_GET(sc, vcpuid, cpu) = RDMSR(MSR_HV_VP_INDEX);
        } else {
                /* Set virtual processor id to 0 for compatibility. */
                VMBUS_PCPU_GET(sc, vcpuid, cpu) = 0;
@@ -769,46 +745,39 @@ vmbus_synic_setup(void *xsc)
        /*
         * Setup the SynIC message.
         */
-       orig = rdmsr(MSR_HV_SIMP);
+       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);
-
+           ((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);
+       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);
-
+           ((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);
+       orig = RDMSR(sint);
        val = sc->vmbus_idtvec | MSR_HV_SINT_AUTOEOI |
            (orig & MSR_HV_SINT_RSVD_MASK);
-       wrmsr(sint, val);
+       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);
-
+       vmbus_synic_setup1(sc);
        /*
         * All done; enable SynIC.
         */
-       orig = rdmsr(MSR_HV_SCONTROL);
+       orig = RDMSR(MSR_HV_SCONTROL);
        val = MSR_HV_SCTRL_ENABLE | (orig & MSR_HV_SCTRL_RSVD_MASK);
-       wrmsr(MSR_HV_SCONTROL, val);
+       WRMSR(MSR_HV_SCONTROL, val);
 }
 
 static void
@@ -820,34 +789,31 @@ vmbus_synic_teardown(void *arg)
        /*
         * Disable SynIC.
         */
-       orig = rdmsr(MSR_HV_SCONTROL);
-       wrmsr(MSR_HV_SCONTROL, (orig & MSR_HV_SCTRL_RSVD_MASK));
+       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);
+       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);
-
+       vmbus_synic_teardown1();
        /*
         * Teardown SynIC message.
         */
-       orig = rdmsr(MSR_HV_SIMP);
-       wrmsr(MSR_HV_SIMP, (orig & MSR_HV_SIMP_RSVD_MASK));
+       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));
+       orig = RDMSR(MSR_HV_SIEFP);
+       WRMSR(MSR_HV_SIEFP, (orig & MSR_HV_SIEFP_RSVD_MASK));
 }
 
 static int
@@ -948,8 +914,9 @@ vmbus_intr_setup(struct vmbus_softc *sc)
 
                /* Allocate an interrupt counter for Hyper-V interrupt */
                snprintf(buf, sizeof(buf), "cpu%d:hyperv", cpu);
+#if !defined(__aarch64__)
                intrcnt_add(buf, VMBUS_PCPU_PTR(sc, intr_cnt, cpu));
-
+#endif /* not for aarch64 */
                /*
                 * Setup taskqueue to handle events.  Task will be per-
                 * channel.
@@ -981,57 +948,12 @@ vmbus_intr_setup(struct vmbus_softc *sc)
                TASK_INIT(VMBUS_PCPU_PTR(sc, message_task, cpu), 0,
                    vmbus_msg_task, sc);
        }
-
-#if defined(__amd64__) && defined(KLD_MODULE)
-       pmap_pti_add_kva(VMBUS_ISR_ADDR, VMBUS_ISR_ADDR + PAGE_SIZE, true);
-#endif
-
-       /*
-        * 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(pti ? IDTVEC(vmbus_isr_pti) :
-           IDTVEC(vmbus_isr));
-       if (sc->vmbus_idtvec < 0) {
-#if defined(__amd64__) && defined(KLD_MODULE)
-               pmap_pti_remove_kva(VMBUS_ISR_ADDR, VMBUS_ISR_ADDR + PAGE_SIZE);
-#endif
-               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;
+       return (vmbus_setup_intr1(sc));
 }
-
 static void
 vmbus_intr_teardown(struct vmbus_softc *sc)
 {
-       int cpu;
-
-       if (sc->vmbus_idtvec >= 0) {
-               lapic_ipi_free(sc->vmbus_idtvec);
*** 274 LINES SKIPPED ***


Reply via email to