From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 29C8C3EE1E9; Thu, 25 Jun 2026 17:35:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=13.77.154.182 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782408909; cv=none; b=l6sEWY/vlunDPDoJPxAQH7zLU98erndS+WBycN40h0zAYthxpfP8iqr93ZfX1tJ0D6e/5uhdxJFf/1y+BSDe1SfSXYPUQ1B2nh7J8LIDm+qmbS9eDskyBtVXehgCV7DzVwxKLBNnWZ/wTYaiQPhZkg+DEfYqviHaeHkWN+V/zoI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782408909; c=relaxed/simple; bh=wpjck5Ya2DsDfCGJPG4vm+8bcScyNpEpMLWvHxca/Bc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CQQI8xvTdxrDEGdzSZxdyscla7FhnNnTjSLaG+8gW2JFqqzi2c9vwYUHzdutcij0Kw0OOo37f0Oyz9l712ugm5gtDIJDxZ/unDeSGK2ehNVv8cFULtOEgI46P8LCg0irhRA4ZOYi/Rb7149Rk8NNa01iean50wutoBsZK7ORBT8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com; spf=pass smtp.mailfrom=linux.microsoft.com; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b=q1S4WC1A; arc=none smtp.client-ip=13.77.154.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="q1S4WC1A" Received: from linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net (linux.microsoft.com [13.77.154.182]) by linux.microsoft.com (Postfix) with ESMTPSA id C1D8D20B716D; Thu, 25 Jun 2026 10:35:02 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com C1D8D20B716D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1782408902; bh=WinnC+elao/6KfT3ISKBQMmx/JrCmROo1EZBJFHsDq8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=q1S4WC1AbV0TSqHXOD6/xAOue6FCvkujvh+Jy9U71pgqrrWcQoKZatIZkAsIhuSFw mymGmy8NSvxhdPX3qP7u/8OhcVtVyY4AjxH6HyHwBqu/RTapeW6b/aTk1ATmBz3d8i Y8X6RXM1ghE+I2ZxpqwVVR+Mb7jTG0B9Z5T4jP4U= From: Kameron Carr To: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org, decui@microsoft.com, longli@microsoft.com Cc: catalin.marinas@arm.com, will@kernel.org, mark.rutland@arm.com, lpieralisi@kernel.org, sudeep.holla@kernel.org, arnd@arndb.de, thuth@redhat.com, linux-hyperv@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org, mhklinux@outlook.com Subject: [PATCH v2 5/6] arm64: hyperv: Route hypercalls through RSI host call in CCA Realms Date: Thu, 25 Jun 2026 10:34:59 -0700 Message-ID: <20260625173500.1995481-6-kameroncarr@linux.microsoft.com> X-Mailer: git-send-email 2.43.7 In-Reply-To: <20260625173500.1995481-1-kameroncarr@linux.microsoft.com> References: <20260625173500.1995481-1-kameroncarr@linux.microsoft.com> Precedence: bulk X-Mailing-List: linux-hyperv@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Modify the five hypercall wrapper functions to check is_realm_world() and use the per-CPU rsi_host_call structure when inside a Realm. Signed-off-by: Kameron Carr --- arch/arm64/hyperv/hv_core.c | 155 ++++++++++++++++++++++++++++-------- 1 file changed, 121 insertions(+), 34 deletions(-) diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c index e33a9e3c366a1..77cba08fca132 100644 --- a/arch/arm64/hyperv/hv_core.c +++ b/arch/arm64/hyperv/hv_core.c @@ -13,9 +13,41 @@ #include #include #include +#include #include #include #include +#include + +/* + * hv_do_rsi_hypercall - Helper function to invoke a hypercall from a + * Realm world using the RSI interface. + */ +static u64 hv_do_rsi_hypercall(u64 control, u64 input1, u64 input2) +{ + struct rsi_host_call *hostcall; + unsigned long flags; + u64 ret; + + if (!hv_hostcall_array) + return HV_STATUS_INVALID_HYPERCALL_INPUT; + + local_irq_save(flags); + hostcall = &hv_hostcall_array[smp_processor_id()]; + memset(hostcall, 0, sizeof(*hostcall)); + hostcall->gprs[0] = HV_FUNC_ID; + hostcall->gprs[1] = control; + hostcall->gprs[2] = input1; + hostcall->gprs[3] = input2; + + if (rsi_host_call(virt_to_phys(hostcall)) == RSI_SUCCESS) + ret = hostcall->gprs[0]; + else + ret = HV_STATUS_INVALID_HYPERCALL_INPUT; + + local_irq_restore(flags); + return ret; +} /* * hv_do_hypercall- Invoke the specified hypercall @@ -29,8 +61,11 @@ u64 hv_do_hypercall(u64 control, void *input, void *output) input_address = input ? virt_to_phys(input) : 0; output_address = output ? virt_to_phys(output) : 0; - arm_smccc_1_1_hvc(HV_FUNC_ID, control, - input_address, output_address, &res); + if (is_realm_world()) + return hv_do_rsi_hypercall(control, input_address, output_address); + + arm_smccc_1_1_hvc(HV_FUNC_ID, control, input_address, + output_address, &res); return res.a0; } EXPORT_SYMBOL_GPL(hv_do_hypercall); @@ -48,6 +83,9 @@ u64 hv_do_fast_hypercall8(u16 code, u64 input) control = (u64)code | HV_HYPERCALL_FAST_BIT; + if (is_realm_world()) + return hv_do_rsi_hypercall(control, input, 0); + arm_smccc_1_1_hvc(HV_FUNC_ID, control, input, &res); return res.a0; } @@ -65,6 +103,9 @@ u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2) control = (u64)code | HV_HYPERCALL_FAST_BIT; + if (is_realm_world()) + return hv_do_rsi_hypercall(control, input1, input2); + arm_smccc_1_1_hvc(HV_FUNC_ID, control, input1, input2, &res); return res.a0; } @@ -76,24 +117,44 @@ EXPORT_SYMBOL_GPL(hv_do_fast_hypercall16); void hv_set_vpreg(u32 msr, u64 value) { struct arm_smccc_res res; + struct rsi_host_call *hostcall; + unsigned long flags; + u64 status; - arm_smccc_1_1_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); + if (is_realm_world()) { + local_irq_save(flags); + hostcall = &hv_hostcall_array[smp_processor_id()]; + memset(hostcall, 0, sizeof(*hostcall)); + hostcall->gprs[0] = HV_FUNC_ID; + hostcall->gprs[1] = HVCALL_SET_VP_REGISTERS | + HV_HYPERCALL_FAST_BIT | + HV_HYPERCALL_REP_COMP_1; + hostcall->gprs[2] = HV_PARTITION_ID_SELF; + hostcall->gprs[3] = HV_VP_INDEX_SELF; + hostcall->gprs[4] = msr; + hostcall->gprs[6] = value; + + if (rsi_host_call(virt_to_phys(hostcall)) == RSI_SUCCESS) + status = hostcall->gprs[0]; + else + status = HV_STATUS_INVALID_HYPERCALL_INPUT; + local_irq_restore(flags); + } else { + arm_smccc_1_1_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); + status = res.a0; + } /* - * Something is fundamentally broken in the hypervisor if - * setting a VP register fails. There's really no way to - * continue as a guest VM, so panic. + * Something is fundamentally broken in the hypervisor (or, in a + * Realm, the RMM denied the host call) if setting a VP register + * fails. There's really no way to continue as a guest VM, so panic. */ - BUG_ON(!hv_result_success(res.a0)); + BUG_ON(!hv_result_success(status)); } EXPORT_SYMBOL_GPL(hv_set_vpreg); @@ -108,29 +169,55 @@ 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; + struct rsi_host_call *hostcall; + unsigned long flags; + u64 status; - 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; + if (is_realm_world()) { + local_irq_save(flags); + hostcall = &hv_hostcall_array[smp_processor_id()]; + memset(hostcall, 0, sizeof(*hostcall)); - /* - * Use the SMCCC 1.2 interface because the results are in registers - * beyond X0-X3. - */ - arm_smccc_1_2_hvc(&args, &res); + hostcall->gprs[0] = HV_FUNC_ID; + hostcall->gprs[1] = HVCALL_GET_VP_REGISTERS | + HV_HYPERCALL_FAST_BIT | + HV_HYPERCALL_REP_COMP_1; + hostcall->gprs[2] = HV_PARTITION_ID_SELF; + hostcall->gprs[3] = HV_VP_INDEX_SELF; + hostcall->gprs[4] = msr; + + if (rsi_host_call(virt_to_phys(hostcall)) == RSI_SUCCESS) { + status = hostcall->gprs[0]; + result->as64.low = hostcall->gprs[6]; + result->as64.high = hostcall->gprs[7]; + } else { + status = HV_STATUS_INVALID_HYPERCALL_INPUT; + } + local_irq_restore(flags); + } else { + 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); + status = res.a0; + result->as64.low = res.a6; + result->as64.high = res.a7; + } /* - * Something is fundamentally broken in the hypervisor if - * getting a VP register fails. There's really no way to - * continue as a guest VM, so panic. + * Something is fundamentally broken in the hypervisor (or, in a + * Realm, the RMM denied the host call) if getting a VP register + * fails. There's really no way to continue as a guest VM, so panic. */ - BUG_ON(!hv_result_success(res.a0)); - - result->as64.low = res.a6; - result->as64.high = res.a7; + BUG_ON(!hv_result_success(status)); } EXPORT_SYMBOL_GPL(hv_get_vpreg_128); -- 2.45.4