Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105571751
D36052.id108915.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
72 KB
Referenced Files
None
Subscribers
None
D36052.id108915.diff
View Options
Index: share/mk/src.opts.mk
===================================================================
--- share/mk/src.opts.mk
+++ share/mk/src.opts.mk
@@ -332,7 +332,7 @@
.endif
# HyperV is currently x86-only
-.if ${__T} != "amd64" && ${__T} != "i386"
+.if ${__T} != "amd64" && ${__T} != "i386" && ${__T} != "aarch64"
BROKEN_OPTIONS+=HYPERV
.endif
Index: stand/efi/loader/conf.c
===================================================================
--- stand/efi/loader/conf.c
+++ stand/efi/loader/conf.c
@@ -88,7 +88,9 @@
struct console *consoles[] = {
&efi_console,
+#if defined(__aarch64_hyperv__)
&comconsole,
+#endif
#if defined(__amd64__) || defined(__i386__)
&nullconsole,
&spinconsole,
Index: sys/Makefile
===================================================================
--- sys/Makefile
+++ sys/Makefile
@@ -19,6 +19,7 @@
.endif
.endif
.endif
+CSCOPE_ARCHDIR += arm arm64
HTAGSFLAGS+= -at `awk -F= '/^RELEASE *=/{release=$2}; END {print "FreeBSD", release, "kernel"}' < conf/newvers.sh`
Index: sys/arm/conf/GENERIC
===================================================================
--- sys/arm/conf/GENERIC
+++ sys/arm/conf/GENERIC
@@ -282,6 +282,8 @@
# HID support
device hid # Generic HID support
+options HYPERV
+device hyperv
# Flattened Device Tree
options FDT # Configure using FDT/DTB data
Index: sys/arm64/conf/std.dev
===================================================================
--- sys/arm64/conf/std.dev
+++ sys/arm64/conf/std.dev
@@ -107,3 +107,6 @@
# HID support
options HID_DEBUG # enable debug msgs
device hid # Generic HID support
+
+#hyper-v support
+device hyperv
Index: sys/conf/files.arm64
===================================================================
--- sys/conf/files.arm64
+++ sys/conf/files.arm64
@@ -606,3 +606,27 @@
# 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
+dev/hyperv/vmbus/aarch64/smccc_1_2_arm64.S optional hyperv
+#dev/hyperv/pcib/vmbus_pcib.c optional hyperv pci
Index: sys/conf/files.x86
===================================================================
--- sys/conf/files.x86
+++ sys/conf/files.x86
@@ -132,6 +132,8 @@
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
Index: sys/dev/hyperv/include/hyperv.h
===================================================================
--- sys/dev/hyperv/include/hyperv.h
+++ sys/dev/hyperv/include/hyperv.h
@@ -86,6 +86,11 @@
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.
Index: sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
===================================================================
--- sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
+++ sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
@@ -1832,11 +1832,15 @@
#ifdef INVARIANTS
if (nsegs > 1) {
if (i == 0) {
+#if !defined(__aarch64__)
KASSERT((segs[i].ds_addr & PAGE_MASK) +
segs[i].ds_len == PAGE_SIZE,
("invalid 1st page, ofs 0x%jx, len %zu",
(uintmax_t)segs[i].ds_addr,
segs[i].ds_len));
+#else
+ /* do nothing for arm64 */
+#endif
} else if (i == nsegs - 1) {
KASSERT((segs[i].ds_addr & PAGE_MASK) == 0,
("invalid last page, ofs 0x%jx",
@@ -1853,6 +1857,19 @@
prplist->gpa_page[i] = atop(segs[i].ds_addr);
}
reqp->prp_cnt = nsegs;
+
+#if defined(__aarch64__)
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+ bus_dmasync_op_t op;
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ op = BUS_DMASYNC_PREREAD;
+ } else {
+ op = BUS_DMASYNC_PREWRITE;
+ }
+ bus_dmamap_sync(reqp->softc->storvsc_req_dtag,
+ reqp->data_dmap, op);
+ }
+#endif
}
/**
@@ -2113,6 +2130,19 @@
int ori_sg_count = 0;
const struct scsi_generic *cmd;
+#if defined(__aarch64__)
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+ bus_dmasync_op_t op;
+
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
+ op = BUS_DMASYNC_POSTREAD;
+ else
+ op = BUS_DMASYNC_POSTWRITE;
+
+ bus_dmamap_sync(sc->storvsc_req_dtag, reqp->data_dmap, op);
+ bus_dmamap_unload(sc->storvsc_req_dtag, reqp->data_dmap);
+ }
+#endif /* aarch64 */
/* destroy bounce buffer if it is used */
if (reqp->bounce_sgl_count) {
ori_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr;
Index: sys/dev/hyperv/vmbus/aarch64/hyperv_aarch64.c
===================================================================
--- /dev/null
+++ sys/dev/hyperv/vmbus/aarch64/hyperv_aarch64.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2009-2012,2016-2017 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 Hyper-V/Azure
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/timetc.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+
+#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/hyperv/vmbus/aarch64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/aarch64/hyperv_reg.h>
+#include <dev/hyperv/vmbus/hyperv_var.h>
+
+
+void hyperv_init_tc(void);
+int hypercall_page_setup(vm_paddr_t);
+void hypercall_disable(void);
+bool hyperv_identify_features(void);
+
+u_int hyperv_ver_major;
+
+u_int hyperv_features;
+u_int hyperv_recommends;
+
+hyperv_tc64_t hyperv_tc64;
+
+void
+hyperv_init_tc(void)
+{
+ hyperv_tc64 = NULL;
+
+}
+
+int
+hypercall_page_setup(vm_paddr_t hc)
+{
+ return (0);
+}
+
+
+void
+hypercall_disable(void)
+{
+ //do nothing for aarch64, it is just a stub
+ return;
+}
+
+bool
+hyperv_identify_features(void)
+{
+ struct hv_get_vp_registers_output result;
+ printf("Hyper-V identify for arm64\n");
+ vm_guest = VM_GUEST_HV;
+
+ hv_get_vpreg_128(CPUID_LEAF_HV_FEATURES, &result);
+ hyperv_features = result.as32.a;
+ hv_get_vpreg_128(CPUID_LEAF_HV_IDENTITY, &result);
+ hyperv_ver_major = result.as32.b >> 16;
+ hv_get_vpreg_128(CPUID_LEAF_HV_RECOMMENDS, &result);
+ hyperv_recommends = result.as32.a;
+ return (true);
+}
Index: sys/dev/hyperv/vmbus/aarch64/hyperv_machdep.h
===================================================================
--- /dev/null
+++ sys/dev/hyperv/vmbus/aarch64/hyperv_machdep.h
@@ -0,0 +1,58 @@
+/*-
+ * 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);
+typedef uint32_t u32;
+typedef uint64_t u64;
+struct hv_get_vp_registers_output {
+ union {
+ struct {
+ u32 a;
+ u32 b;
+ u32 c;
+ u32 d;
+ } as32 __packed;
+ struct {
+ u64 low;
+ u64 high;
+ } as64 __packed;
+ };
+};
+
+void hv_get_vpreg_128(u32 , struct hv_get_vp_registers_output *);
+void arm_hv_set_vreg(u32 msr, u64 val);
+#define WRMSR(msr, val) arm_hv_set_vreg(msr, val)
+u64 arm_hv_get_vreg(u32 msr);
+#define RDMSR(msr) arm_hv_get_vreg(msr)
+#endif /* !_HYPERV_MACHDEP_H_ */
Index: sys/dev/hyperv/vmbus/aarch64/hyperv_machdep.c
===================================================================
--- /dev/null
+++ sys/dev/hyperv/vmbus/aarch64/hyperv_machdep.c
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (c) 2016-2017 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/timetc.h>
+#include <sys/vdso.h>
+
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+
+#include <vm/vm.h>
+
+#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/hyperv/vmbus/aarch64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/aarch64/hyperv_reg.h>
+#include <dev/hyperv/vmbus/aarch64/smccc_1_2.h>
+#include <dev/psci/smccc.h>
+#include <dev/hyperv/vmbus/hyperv_var.h>
+
+#define HVCALL_SET_VP_REGISTERS 0x0051
+#define HVCALL_GET_VP_REGISTERS 0x0050
+#define BIT(A) (1 << (A))
+#define HV_HYPERCALL_FAST_BIT BIT(16)
+#define BIT_ULL(a) (1ULL << (a))
+#define HV_HYPERCALL_REP_COMP_1 BIT_ULL(32)
+#define HV_PARTITION_ID_SELF ((u64)-1)
+#define HV_VP_INDEX_SELF ((u32)-2)
+#define HV_SMCCC_FUNC_NUMBER 1
+
+#define HV_FUNC_ID SMCCC_FUNC_ID(SMCCC_YIELDING_CALL, SMCCC_64BIT_CALL, \
+ SMCCC_VENDOR_HYP_SERVICE_CALLS, (HV_SMCCC_FUNC_NUMBER))
+
+
+void arm_hv_set_vreg(u32, u64);
+void hv_get_vpreg_128(u32 , struct hv_get_vp_registers_output *);
+u64 arm_hv_get_vreg(u32 msr);
+void arm_hv_set_vreg(u32 msr, u64 value)
+{
+ struct arm_smccc_res res;
+ printf("inside arm_hv_set_vreg\n");
+ int64_t hv_func_id;
+ hv_func_id = SMCCC_FUNC_ID(SMCCC_YIELDING_CALL, SMCCC_64BIT_CALL,
+ SMCCC_VENDOR_HYP_SERVICE_CALLS, (HV_SMCCC_FUNC_NUMBER));
+ printf("inside arm_hv_set_vreg hv_func_id set hv_func_id %lu \n",hv_func_id);
+ arm_smccc_hvc (hv_func_id,
+ HVCALL_SET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
+ HV_HYPERCALL_REP_COMP_1,
+ HV_PARTITION_ID_SELF,
+ HV_VP_INDEX_SELF,
+ msr,
+ 0,
+ value,
+ 0,
+ &res);
+}
+
+
+
+void hv_get_vpreg_128(u32 msr, struct hv_get_vp_registers_output *result)
+{
+ struct arm_smccc_1_2_regs args;
+ struct arm_smccc_1_2_regs res;
+
+ args.a0 = HV_FUNC_ID;
+ args.a1 = HVCALL_GET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
+ HV_HYPERCALL_REP_COMP_1;
+ args.a2 = HV_PARTITION_ID_SELF;
+ args.a3 = HV_VP_INDEX_SELF;
+ args.a4 = msr;
+
+ /*
+ * Use the SMCCC 1.2 interface because the results are in registers
+ * beyond X0-X3.
+ */
+ arm_smccc_1_2_hvc(&args, &res);
+
+ result->as64.low = res.a6;
+ result->as64.high = res.a7;
+}
+
+u64 arm_hv_get_vreg(u32 msr)
+{
+ struct hv_get_vp_registers_output output;
+
+ hv_get_vpreg_128(msr, &output);
+
+ return output.as64.low;
+}
+
+uint64_t
+hypercall_md(volatile void *hc_addr, uint64_t in_val,
+ uint64_t in_paddr, uint64_t out_paddr)
+{
+ struct arm_smccc_res res;
+ int64_t hv_func_id;
+ hv_func_id = SMCCC_FUNC_ID(SMCCC_YIELDING_CALL, SMCCC_64BIT_CALL,
+ SMCCC_VENDOR_HYP_SERVICE_CALLS, (HV_SMCCC_FUNC_NUMBER));
+ arm_smccc_hvc (hv_func_id,
+ in_val,
+ in_paddr,
+ out_paddr,
+ 0,
+ 0,
+ 0,
+ 0,
+ &res);
+
+ return (res.a0);
+}
Index: sys/dev/hyperv/vmbus/aarch64/hyperv_reg.h
===================================================================
--- /dev/null
+++ sys/dev/hyperv/vmbus/aarch64/hyperv_reg.h
@@ -0,0 +1,193 @@
+/*-
+ * 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 0x00090002
+#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 0x00090003
+
+#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 0x000A0010
+#define MSR_HV_SCTRL_ENABLE 0x0001ULL
+#define MSR_HV_SCTRL_RSVD_MASK 0xfffffffffffffffeULL
+
+#define MSR_HV_SIEFP 0x000A0012
+#define MSR_HV_SIEFP_ENABLE 0x0001ULL
+#define MSR_HV_SIEFP_RSVD_MASK 0x0ffeULL
+#define MSR_HV_SIEFP_PGSHIFT 12
+
+#define MSR_HV_SIMP 0x000A0013
+#define MSR_HV_SIMP_ENABLE 0x0001ULL
+#define MSR_HV_SIMP_RSVD_MASK 0x0ffeULL
+#define MSR_HV_SIMP_PGSHIFT 12
+
+#define MSR_HV_EOM 0x000A0014
+
+#define MSR_HV_SINT0 0x000A0000
+#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 0x00000000ULL
+#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 0x00000100
+
+#define CPUID_LEAF_HV_FEATURES 0x00000200
+/* 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 0x00000201
+#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_ */
Index: sys/dev/hyperv/vmbus/aarch64/smccc_1_2.h
===================================================================
--- /dev/null
+++ sys/dev/hyperv/vmbus/aarch64/smccc_1_2.h
@@ -0,0 +1,61 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2018 Andrew Turner
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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_SMCCC_H_
+#define _HYPERV_SMCCC_H_
+
+
+struct arm_smccc_1_2_regs {
+ register_t a0;
+ register_t a1;
+ register_t a2;
+ register_t a3;
+ register_t a4;
+ register_t a5;
+ register_t a6;
+ register_t a7;
+ register_t a8;
+ register_t a9;
+ register_t a10;
+ register_t a11;
+ register_t a12;
+ register_t a13;
+ register_t a14;
+ register_t a15;
+ register_t a16;
+ register_t a17;
+};
+int arm_smccc_1_2_hvc(const struct arm_smccc_1_2_regs *args,
+ struct arm_smccc_1_2_regs *res);
+
+#endif /* _HYPERV_SMCCC_H_ */
Index: sys/dev/hyperv/vmbus/aarch64/smccc_1_2_arm64.S
===================================================================
--- /dev/null
+++ sys/dev/hyperv/vmbus/aarch64/smccc_1_2_arm64.S
@@ -0,0 +1,68 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Ruslan Bukin <br@bsdpad.com>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/* arm_smccc_1_2_hvc(const struct arm_smccc_1_2_regs *args,
+ struct arm_smccc_1_2_regs *res) */
+ENTRY(arm_smccc_1_2_hvc)
+ stp x1, x19, [sp, #-16]!
+ mov x19, x0
+
+ ldp x0, x1, [x19, #16 * 0]
+ ldp x2, x3, [x19, #16 * 1]
+ ldp x4, x5, [x19, #16 * 2]
+ ldp x6, x7, [x19, #16 * 3]
+ ldp x8, x9, [x19, #16 * 4]
+ ldp x10, x11, [x19, #16 * 5]
+ ldp x12, x13, [x19, #16 * 6]
+ ldp x14, x15, [x19, #16 * 7]
+ ldp x16, x17, [x19, #16 * 8]
+
+ hvc #0
+ ldr x19, [sp]
+ cbz x19, 1f
+
+ stp x0, x1, [x19, #16 * 0]
+ stp x2, x3, [x19, #16 * 1]
+ stp x4, x5, [x19, #16 * 2]
+ stp x6, x7, [x19, #16 * 3]
+ stp x8, x9, [x19, #16 * 4]
+ stp x10, x11, [x19, #16 * 5]
+ stp x12, x13, [x19, #16 * 6]
+ stp x14, x15, [x19, #16 * 7]
+ stp x16, x17, [x19, #16 * 8]
+
+ ldp xzr, x19, [sp], #16
+1: ret
+END(arm_smccc_1_2_hvc)
Index: sys/dev/hyperv/vmbus/aarch64/vmbus_aarch64.c
===================================================================
--- /dev/null
+++ sys/dev/hyperv/vmbus/aarch64/vmbus_aarch64.c
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 2009-2012,2016-2017 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/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/sbuf.h>
+#include <sys/smp.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/metadata.h>
+#include <machine/md_var.h>
+#include <machine/resource.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_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/aarch64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/aarch64/hyperv_reg.h>
+#include "acpi_if.h"
+#include "pcib_if.h"
+#include "vmbus_if.h"
+
+
+static int vmbus_handle_intr_new(void *);
+
+
+void vmbus_handle_timer_intr1(struct vmbus_message *msg_base,
+ struct trapframe *frame);
+void vmbus_synic_setup1(void *xsc);
+void vmbus_synic_teardown1(void);
+int vmbus_setup_intr1(struct vmbus_softc *sc);
+void vmbus_intr_teardown1(struct vmbus_softc *sc);
+
+void
+vmbus_handle_timer_intr1(struct vmbus_message *msg_base, struct trapframe *frame)
+{
+ // do nothing for arm64, as we are using generic timer
+ return;
+}
+static int
+vmbus_handle_intr_new(void *arg)
+{
+ vmbus_handle_intr(NULL);
+ return(FILTER_HANDLED);
+}
+
+
+void
+vmbus_synic_setup1(void *xsc)
+{
+ return;
+}
+
+void
+vmbus_synic_teardown1(void)
+{
+ return;
+}
+
+
+int
+vmbus_setup_intr1(struct vmbus_softc *sc)
+{
+ int err;
+ struct intr_map_data_acpi *irq_data;
+
+ sc->ires = bus_alloc_resource_any(device_get_parent(sc->vmbus_dev),
+ SYS_RES_IRQ, &sc->vector, RF_ACTIVE | RF_SHAREABLE);
+ if (sc->ires == NULL) {
+ device_printf(sc->vmbus_dev,
+ "bus_alloc_resouce_any failed\n");
+ return (ENXIO);
+ } else {
+ device_printf(sc->vmbus_dev,
+ "irq 0x%lx, vector %d end 0x%lx\n",
+ (uint64_t)rman_get_start(sc->ires), sc->vector, (uint64_t)rman_get_end(sc->ires));
+ }
+ err = bus_setup_intr(sc->vmbus_dev, sc->ires, INTR_TYPE_MISC ,
+ vmbus_handle_intr_new, NULL, sc, &sc->icookie);
+ if (err) {
+ device_printf(sc->vmbus_dev, "failed to setup IRQ %d\n",err);
+ return (err);
+ }
+ device_printf(sc->vmbus_dev, "vmbus IRQ is set\n");
+ irq_data = (struct intr_map_data_acpi *) rman_get_virtual(sc->ires);
+ device_printf(sc->vmbus_dev,"the irq %u\n",irq_data->irq);
+ sc->vmbus_idtvec = irq_data->irq;
+ return 0;
+}
+
+void
+vmbus_intr_teardown1(struct vmbus_softc *sc)
+{
+ int cpu;
+
+ sc->vmbus_idtvec = -1;
+ bus_teardown_intr(sc->vmbus_dev, sc->ires, sc->icookie);
+
+ 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;
+ }
+ }
+}
Index: sys/dev/hyperv/vmbus/amd64/hyperv_machdep.h
===================================================================
--- sys/dev/hyperv/vmbus/amd64/hyperv_machdep.h
+++ sys/dev/hyperv/vmbus/amd64/hyperv_machdep.h
@@ -34,4 +34,6 @@
uint64_t hypercall_md(volatile void *hc_addr, uint64_t in_val,
uint64_t in_paddr, uint64_t out_paddr);
+#define WRMSR(msr, val) wrmsr(msr, val)
+#define RDMSR(msr) rdmsr(msr)
#endif /* !_HYPERV_MACHDEP_H_ */
Index: sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
===================================================================
--- sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
+++ sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
@@ -44,8 +44,8 @@
#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/amd64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/amd64/hyperv_reg.h>
#include <dev/hyperv/vmbus/hyperv_var.h>
struct hyperv_reftsc_ctx {
Index: sys/dev/hyperv/vmbus/hyperv.c
===================================================================
--- sys/dev/hyperv/vmbus/hyperv.c
+++ sys/dev/hyperv/vmbus/hyperv.c
@@ -45,8 +45,13 @@
#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/amd64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/amd64/hyperv_reg.h>
+#endif
#include <dev/hyperv/vmbus/hyperv_var.h>
#define HYPERV_FREEBSD_BUILD 0ULL
@@ -68,51 +73,10 @@
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 +107,8 @@
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 +120,8 @@
}
/* 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 +136,8 @@
static void
hypercall_create(void *arg __unused)
{
- uint64_t hc, hc_orig;
+ int ret;
if (vm_guest != VM_GUEST_HV)
return;
@@ -289,30 +150,9 @@
hypercall_context.hc_addr = (void *)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)
@@ -323,16 +163,11 @@
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");
}
Index: sys/dev/hyperv/vmbus/hyperv_var.h
===================================================================
--- sys/dev/hyperv/vmbus/hyperv_var.h
+++ 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);
Index: sys/dev/hyperv/vmbus/i386/hyperv_machdep.c
===================================================================
--- sys/dev/hyperv/vmbus/i386/hyperv_machdep.c
+++ 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/amd64/hyperv_machdep.h>
uint64_t
hypercall_md(volatile void *hc_addr, uint64_t in_val,
Index: sys/dev/hyperv/vmbus/vmbus.c
===================================================================
--- sys/dev/hyperv/vmbus/vmbus.c
+++ sys/dev/hyperv/vmbus/vmbus.c
@@ -51,23 +51,28 @@
#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/amd64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/amd64/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 "acpi_if.h"
#include "pcib_if.h"
#include "vmbus_if.h"
@@ -107,7 +112,7 @@
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 +137,9 @@
static int vmbus_doattach(struct vmbus_softc *);
static void vmbus_event_proc_dummy(struct vmbus_softc *,
int);
-
+#if defined(__aarch64__)
+static int vmbus_handle_intr_new(void *);
+#endif /* for aarch64 */
static struct vmbus_softc *vmbus_sc;
SYSCTL_NODE(_hw, OID_AUTO, vmbus, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
@@ -141,10 +148,6 @@
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[] = {
@@ -209,7 +212,12 @@
};
DRIVER_MODULE(vmbus, pcib, vmbus_driver, NULL, NULL);
+#if !defined(__aarch64__)
DRIVER_MODULE(vmbus, acpi_syscontainer, vmbus_driver, NULL, NULL);
+#else
+DRIVER_MODULE(vmbus, vmbus_res, vmbus_driver,
+ NULL,NULL);
+#endif
MODULE_DEPEND(vmbus, acpi, 1, 1, 1);
MODULE_DEPEND(vmbus, pci, 1, 1, 1);
@@ -660,11 +668,10 @@
* 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 +685,7 @@
*
* 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 +719,12 @@
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);
/*
@@ -750,6 +733,7 @@
critical_exit();
}
+
static void
vmbus_synic_setup(void *xsc)
{
@@ -760,7 +744,7 @@
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 +753,40 @@
/*
* 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);
-
+ 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);
+ 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 +798,31 @@
/*
* 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 +923,9 @@
/* 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 +957,13 @@
TASK_INIT(VMBUS_PCPU_PTR(sc, message_task, cpu), 0,
vmbus_msg_task, sc);
}
+ return(vmbus_setup_intr1(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;
}
-
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;
- }
-
-#if defined(__amd64__) && defined(KLD_MODULE)
- pmap_pti_remove_kva(VMBUS_ISR_ADDR, VMBUS_ISR_ADDR + PAGE_SIZE);
-#endif
-
- 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;
- }
- }
+ vmbus_intr_teardown1(sc);
}
static int
@@ -1358,7 +1290,9 @@
vmbus_fb_mmio_res(device_t dev)
{
struct efi_fb *efifb;
+#if !defined(__aarch64__)
struct vbe_fb *vbefb;
+#endif /* aarch64 */
rman_res_t fb_start, fb_end, fb_count;
int fb_height, fb_width;
caddr_t kmdp;
@@ -1371,21 +1305,27 @@
kmdp = preload_search_by_type("elf64 kernel");
efifb = (struct efi_fb *)preload_search_info(kmdp,
MODINFO_METADATA | MODINFOMD_EFI_FB);
+#if !defined(__aarch64__)
vbefb = (struct vbe_fb *)preload_search_info(kmdp,
MODINFO_METADATA | MODINFOMD_VBE_FB);
+#endif /* aarch64 */
if (efifb != NULL) {
fb_start = efifb->fb_addr;
fb_end = efifb->fb_addr + efifb->fb_size;
fb_count = efifb->fb_size;
fb_height = efifb->fb_height;
fb_width = efifb->fb_width;
- } else if (vbefb != NULL) {
+ }
+#if !defined(__aarch64__)
+ else if (vbefb != NULL) {
fb_start = vbefb->fb_addr;
fb_end = vbefb->fb_addr + vbefb->fb_size;
fb_count = vbefb->fb_size;
fb_height = vbefb->fb_height;
fb_width = vbefb->fb_width;
- } else {
+ }
+#endif /* aarch64 */
+ else {
if (bootverbose)
device_printf(dev,
"no preloaded kernel fb information\n");
@@ -1560,7 +1500,7 @@
{
}
-#ifdef EARLY_AP_STARTUP
+#if defined(EARLY_AP_STARTUP) || defined(__aarch64__)
static void
vmbus_intrhook(void *xsc)
@@ -1573,7 +1513,7 @@
config_intrhook_disestablish(&sc->vmbus_intrhook);
}
-#endif /* EARLY_AP_STARTUP */
+#endif /* EARLY_AP_STARTUP aarch64 */
static int
vmbus_attach(device_t dev)
@@ -1589,7 +1529,7 @@
*/
vmbus_sc->vmbus_event_proc = vmbus_event_proc_dummy;
-#ifdef EARLY_AP_STARTUP
+#if defined(EARLY_AP_STARTUP) || defined(__aarch64__)
/*
* Defer the real attach until the pause(9) works as expected.
*/
@@ -1605,7 +1545,7 @@
*/
if (!cold)
vmbus_doattach(vmbus_sc);
-#endif /* EARLY_AP_STARTUP */
+#endif /* EARLY_AP_STARTUP and aarch64 */
return (0);
}
@@ -1643,10 +1583,14 @@
vmbus_free_mmio_res(dev);
#endif
+#if defined(__aarch64__)
+ bus_release_resource(device_get_parent(dev), SYS_RES_IRQ, sc->vector,
+ sc->ires);
+#endif
return (0);
}
-#ifndef EARLY_AP_STARTUP
+#if !defined(EARLY_AP_STARTUP) && !defined(__aarch64__)
static void
vmbus_sysinit(void *arg __unused)
@@ -1671,5 +1615,4 @@
* initialized.
*/
SYSINIT(vmbus_initialize, SI_SUB_SMP, SI_ORDER_ANY, vmbus_sysinit, NULL);
-
#endif /* !EARLY_AP_STARTUP */
Index: sys/dev/hyperv/vmbus/vmbus_et.c
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_et.c
+++ sys/dev/hyperv/vmbus/vmbus_et.c
@@ -37,7 +37,11 @@
#include <sys/timeet.h>
#include <dev/hyperv/include/hyperv.h>
-#include <dev/hyperv/vmbus/hyperv_reg.h>
+#if defined(__aarch64__)
+#include <dev/hyperv/vmbus/aarch64/hyperv_reg.h>
+#else
+#include <dev/hyperv/vmbus/amd64/hyperv_reg.h>
+#endif
#include <dev/hyperv/vmbus/hyperv_var.h>
#include <dev/hyperv/vmbus/vmbus_var.h>
Index: sys/dev/hyperv/vmbus/vmbus_reg.h
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_reg.h
+++ sys/dev/hyperv/vmbus/vmbus_reg.h
@@ -32,7 +32,11 @@
#include <sys/param.h>
#include <dev/hyperv/include/hyperv.h> /* XXX for hyperv_guid */
#include <dev/hyperv/include/vmbus.h>
-#include <dev/hyperv/vmbus/hyperv_reg.h>
+#if defined(__aarch64__)
+#include <dev/hyperv/vmbus/aarch64/hyperv_reg.h>
+#else
+#include <dev/hyperv/vmbus/amd64/hyperv_reg.h>
+#endif
/*
* Hyper-V SynIC message format.
Index: sys/dev/hyperv/vmbus/vmbus_res.c
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_res.c
+++ sys/dev/hyperv/vmbus/vmbus_res.c
@@ -39,10 +39,23 @@
#include "acpi_if.h"
#include "bus_if.h"
+#include "pcib_if.h"
static int vmbus_res_probe(device_t);
static int vmbus_res_attach(device_t);
static int vmbus_res_detach(device_t);
+#if defined(__aarch64__)
+static int acpi_syscont_alloc_msi(device_t, device_t,
+ int count, int maxcount, int *irqs);
+static int acpi_syscont_release_msi(device_t bus, device_t dev,
+ int count, int *irqs);
+static int acpi_syscont_alloc_msix(device_t bus, device_t dev,
+ int *irq);
+static int acpi_syscont_release_msix(device_t bus, device_t dev,
+ int irq);
+static int acpi_syscont_map_msi(device_t bus, device_t dev,
+ int irq, uint64_t *addr, uint32_t *data);
+#endif /* aarch64 */
static device_method_t vmbus_res_methods[] = {
/* Device interface */
@@ -52,7 +65,18 @@
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
-
+#if defined(__aarch64__)
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ /* pcib interface */
+ DEVMETHOD(pcib_alloc_msi, acpi_syscont_alloc_msi),
+ DEVMETHOD(pcib_release_msi, acpi_syscont_release_msi),
+ DEVMETHOD(pcib_alloc_msix, acpi_syscont_alloc_msix),
+ DEVMETHOD(pcib_release_msix, acpi_syscont_release_msix),
+ DEVMETHOD(pcib_map_msi, acpi_syscont_map_msi),
+#endif /* aarch64 */
DEVMETHOD_END
};
@@ -84,13 +108,65 @@
static int
vmbus_res_attach(device_t dev __unused)
{
-
+#if defined(__aarch64__)
+ bus_generic_probe(dev);
+ return(bus_generic_attach(dev));
+#endif /* aarch64 */
return (0);
}
static int
vmbus_res_detach(device_t dev __unused)
{
-
+#if defined(__aarch64__)
+ int error;
+ error = bus_generic_detach(dev);
+ if (error)
+ return (error);
+#endif
return (0);
}
+#if defined(__aarch64__)
+static int
+acpi_syscont_alloc_msi(device_t bus, device_t dev, int count, int maxcount,
+ int *irqs)
+{
+ device_t parent = device_get_parent(bus);
+
+ return (PCIB_ALLOC_MSI(device_get_parent(parent), dev, count, maxcount,
+ irqs));
+}
+
+static int
+acpi_syscont_release_msi(device_t bus, device_t dev, int count, int *irqs)
+{
+ device_t parent = device_get_parent(bus);
+
+ return (PCIB_RELEASE_MSI(device_get_parent(parent), dev, count, irqs));
+}
+
+static int
+acpi_syscont_alloc_msix(device_t bus, device_t dev, int *irq)
+{
+ device_t parent = device_get_parent(bus);
+
+ return (PCIB_ALLOC_MSIX(device_get_parent(parent), dev, irq));
+}
+
+static int
+acpi_syscont_release_msix(device_t bus, device_t dev, int irq)
+{
+ device_t parent = device_get_parent(bus);
+
+ return (PCIB_RELEASE_MSIX(device_get_parent(parent), dev, irq));
+}
+
+static int
+acpi_syscont_map_msi(device_t bus, device_t dev, int irq, uint64_t *addr,
+ uint32_t *data)
+{
+ device_t parent = device_get_parent(bus);
+
+ return (PCIB_MAP_MSI(device_get_parent(parent), dev, irq, addr, data));
+}
+#endif /* aarch64 */
Index: sys/dev/hyperv/vmbus/vmbus_var.h
===================================================================
--- sys/dev/hyperv/vmbus/vmbus_var.h
+++ sys/dev/hyperv/vmbus/vmbus_var.h
@@ -135,6 +135,12 @@
/* The list of usable MMIO ranges for PCIe pass-through */
struct pcib_host_resources vmbus_mmio_res;
#endif
+
+#if defined(__aarch64__)
+ struct resource *ires;
+ void *icookie;
+ int vector;
+#endif
};
#define VMBUS_FLAG_ATTACHED 0x0001 /* vmbus was attached */
@@ -151,7 +157,9 @@
void vmbus_handle_intr(struct trapframe *);
int vmbus_add_child(struct vmbus_channel *);
int vmbus_delete_child(struct vmbus_channel *);
+#if !defined(__aarch64__)
void vmbus_et_intr(struct trapframe *);
+#endif
uint32_t vmbus_gpadl_alloc(struct vmbus_softc *);
struct vmbus_msghc *
@@ -172,4 +180,11 @@
const struct vmbus_message *);
void vmbus_msghc_reset(struct vmbus_msghc *, size_t);
+void vmbus_handle_timer_intr1(struct vmbus_message *msg_base,
+ struct trapframe *frame);
+
+void vmbus_synic_setup1(void *xsc);
+void vmbus_synic_teardown1(void);
+int vmbus_setup_intr1(struct vmbus_softc *sc);
+void vmbus_intr_teardown1(struct vmbus_softc *sc);
#endif /* !_VMBUS_VAR_H_ */
Index: sys/dev/hyperv/vmbus/x86/hyperv_x86.c
===================================================================
--- /dev/null
+++ sys/dev/hyperv/vmbus/x86/hyperv_x86.c
@@ -0,0 +1,245 @@
+/*-
+ * Copyright (c) 2009-2012,2016-2017 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 Hyper-V/Azure
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/timetc.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+
+#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/hyperv_busdma.h>
+#include <dev/hyperv/vmbus/amd64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/amd64/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
+
+void hyperv_init_tc(void);
+int hypercall_page_setup(vm_paddr_t);
+void hypercall_disable(void);
+bool hyperv_identify_features(void);
+
+u_int hyperv_ver_major;
+
+u_int hyperv_features;
+u_int hyperv_recommends;
+
+hyperv_tc64_t hyperv_tc64;
+
+static u_int hyperv_pm_features;
+static u_int hyperv_features3;
+static u_int hyperv_get_timecount(struct timecounter *);
+
+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 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));
+}
+
+void
+hyperv_init_tc(void)
+{
+ 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;
+ }
+}
+
+int
+hypercall_page_setup(vm_paddr_t paddr)
+{
+ uint64_t hc, hc_orig;
+ hc_orig = rdmsr(MSR_HV_HYPERCALL);
+
+ /*
+ * Setup the Hypercall page.
+ *
+ * NOTE: 'reserved' bits MUST be preserved.
+ */
+ 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");
+ /* Can't perform any Hyper-V specific actions */
+ vm_guest = VM_GUEST_VM;
+ return(-1);
+ }
+ return (0);
+}
+
+
+void
+hypercall_disable(void)
+{
+ uint64_t hc;
+ /* Disable Hypercall */
+ hc = rdmsr(MSR_HV_HYPERCALL);
+ wrmsr(MSR_HV_HYPERCALL, (hc & MSR_HV_HYPERCALL_RSVD_MASK));
+}
+
+bool
+hyperv_identify_features(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);
+}
Index: sys/dev/hyperv/vmbus/x86/vmbus_x86.c
===================================================================
--- /dev/null
+++ sys/dev/hyperv/vmbus/x86/vmbus_x86.c
@@ -0,0 +1,208 @@
+/*-
+ * Copyright (c) 2009-2012,2016-2017 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/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/sbuf.h>
+#include <sys/smp.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/metadata.h>
+#include <machine/md_var.h>
+#include <machine/resource.h>
+#include <machine/intr_machdep.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_var.h>
+#include <dev/hyperv/vmbus/vmbus_reg.h>
+#include <dev/hyperv/vmbus/vmbus_var.h>
+#include <dev/hyperv/vmbus/vmbus_chanvar.h>
+#include <x86/include/apicvar.h>
+#include <dev/hyperv/vmbus/amd64/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/amd64/hyperv_reg.h>
+#include "acpi_if.h"
+#include "pcib_if.h"
+#include "vmbus_if.h"
+
+extern inthand_t IDTVEC(vmbus_isr), IDTVEC(vmbus_isr_pti);
+#define VMBUS_ISR_ADDR trunc_page((uintptr_t)IDTVEC(vmbus_isr_pti))
+
+static int vmbus_handle_intr_new(void *);
+
+
+void vmbus_handle_timer_intr1(struct vmbus_message *msg_base,
+ struct trapframe *frame);
+void vmbus_synic_setup1(void *xsc);
+void vmbus_synic_teardown1(void);
+int vmbus_setup_intr1(struct vmbus_softc *sc);
+void vmbus_intr_teardown1(struct vmbus_softc *sc);
+
+void
+vmbus_handle_timer_intr1(struct vmbus_message *msg_base, struct trapframe *frame)
+{
+ volatile struct vmbus_message *msg;
+ 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);
+ }
+ }
+ return;
+}
+static int
+vmbus_handle_intr_new(void *arg)
+{
+ // no operation in x86, just a stub
+ return(0);
+}
+
+
+void
+vmbus_synic_setup1(void *xsc)
+{
+ struct vmbus_softc *sc = xsc;
+ uint32_t sint;
+ uint64_t val, orig;
+
+ 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);
+ return;
+}
+
+void
+vmbus_synic_teardown1(void)
+{
+ uint64_t orig;
+ uint32_t sint;
+
+ sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
+ orig = RDMSR(sint);
+ WRMSR(sint, orig | MSR_HV_SINT_MASKED);
+ return;
+}
+
+
+int
+vmbus_setup_intr1(struct vmbus_softc *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;
+}
+
+void
+vmbus_intr_teardown1(struct vmbus_softc *sc)
+{
+ int cpu;
+
+ if (sc->vmbus_idtvec >= 0) {
+ lapic_ipi_free(sc->vmbus_idtvec);
+ sc->vmbus_idtvec = -1;
+ }
+
+#if defined(__amd64__) && defined(KLD_MODULE)
+ pmap_pti_remove_kva(VMBUS_ISR_ADDR, VMBUS_ISR_ADDR + PAGE_SIZE);
+#endif
+
+ 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;
+ }
+ }
+}
Index: sys/modules/Makefile
===================================================================
--- sys/modules/Makefile
+++ sys/modules/Makefile
@@ -649,6 +649,7 @@
_sdhci_fdt= sdhci_fdt
_e6000sw= e6000sw
_neta= neta
+_hyperv= hyperv
.endif
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
Index: sys/modules/hyperv/utilities/Makefile
===================================================================
--- sys/modules/hyperv/utilities/Makefile
+++ sys/modules/hyperv/utilities/Makefile
@@ -5,7 +5,6 @@
KMOD= hv_utils
SRCS= vmbus_ic.c
SRCS+= hv_kvp.c
-SRCS+= hv_snapshot.c
SRCS+= vmbus_heartbeat.c
SRCS+= vmbus_shutdown.c
SRCS+= vmbus_timesync.c
Index: sys/modules/hyperv/vmbus/Makefile
===================================================================
--- sys/modules/hyperv/vmbus/Makefile
+++ sys/modules/hyperv/vmbus/Makefile
@@ -1,7 +1,8 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/dev/hyperv/vmbus \
- ${SRCTOP}/sys/dev/hyperv/vmbus/${MACHINE_CPUARCH}
+ ${SRCTOP}/sys/dev/hyperv/vmbus/${MACHINE_CPUARCH} \
+ ${SRCTOP}/sys/dev/hyperv/vmbus/x86
KMOD= hv_vmbus
SRCS= hyperv.c \
@@ -10,14 +11,18 @@
vmbus.c \
vmbus_br.c \
vmbus_chan.c \
- vmbus_et.c \
vmbus_if.c \
vmbus_res.c \
vmbus_xact.c
-.if ${MACHINE_CPUARCH} != "i386"
+.if ${MACHINE_CPUARCH} != "i386" && ${MACHINE_CPUARCH} != "aarch64"
SRCS+= vmbus_vector.S
.endif
+.if ${MACHINE_CPUARCH} != "aarch64"
+SRCS+= vmbus_et.c hyperv_x86.c vmbus_x86.c
+.else
+SRC+= hyperv_aarch64.c vmbus_aarch64.c smccc_1_2_arm64.S
+.endif
SRCS+= acpi_if.h bus_if.h device_if.h opt_acpi.h pci_if.h pcib_if.h vmbus_if.h
# XXX: for assym.inc
@@ -31,6 +36,9 @@
vmbus_vector.o:
${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
${.IMPSRC} -o ${.TARGET}
+smccc_1_2_arm64.o:
+ ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
+ ${.IMPSRC} -o ${.TARGET}
CFLAGS+= -I${SRCTOP}/sys/dev/hyperv/include \
-I${SRCTOP}/sys/dev/hyperv/vmbus
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Dec 18, 7:34 PM (20 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15494002
Default Alt Text
D36052.id108915.diff (72 KB)
Attached To
Mode
D36052: Enabling FreeBSD on ARM64 Hyper-V
Attached
Detach File
Event Timeline
Log In to Comment