Index: sys/dev/hyperv/vmbus/aarch64/hyperv_machdep.h =================================================================== --- /dev/null +++ sys/dev/hyperv/vmbus/aarch64/hyperv_machdep.h @@ -0,0 +1,59 @@ +/*- SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Microsoft Corp. + * + * 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 + +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; + }; +}; + +uint64_t hypercall_md(volatile void *hc_addr, u64 in_val, + u64 in_paddr, u64 out_paddr); +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,105 @@ +/*- SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2016-2017,2022 Microsoft Corp. + * + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#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 msr, u64 value) +{ + struct arm_smccc_res res; + + 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; + + arm_smccc_hvc(HV_FUNC_ID, in_val, in_paddr, out_paddr, 0, 0, 0, 0, + &res); + + return (res.a0); +} Index: sys/dev/psci/smccc.h =================================================================== --- sys/dev/psci/smccc.h +++ sys/dev/psci/smccc.h @@ -91,4 +91,27 @@ int arm_smccc_hvc(register_t, register_t, register_t, register_t, register_t, register_t, register_t, register_t, struct arm_smccc_res *res); +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 /* _PSCI_SMCCC_H_ */ Index: sys/dev/psci/smccc_arm64.S =================================================================== --- sys/dev/psci/smccc_arm64.S +++ sys/dev/psci/smccc_arm64.S @@ -51,3 +51,39 @@ */ arm_smccc_1_0 hvc arm_smccc_1_0 smc +/* arm_smccc_1_2_hvc(const struct arm_smccc_1_2_regs *args, + struct arm_smccc_1_2_regs *res) */ +.macro arm_smccc_1_2 insn +ENTRY(arm_smccc_1_2_\insn) + 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\insn) +.endm +/* int arm_smccc_1_2_*(const struct arm_smccc_1_2_regs *args, + * struct arm_smccc_1_2_regs *res) + */ +arm_smccc_1_2 hvc +arm_smccc_1_2 smc