* [RFC PATCH 0/6] arm64: hyperv: Add Realm support for Hyper-V
@ 2026-06-09 18:10 Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 1/6] arm64: rsi: Add RSI host call structure and helper function Kameron Carr
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Kameron Carr @ 2026-06-09 18:10 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli
Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
linux-arch, mhklinux
From: Kameron Carr <kameroncarr@microsoft.com>
Realms (CoCo VMs on ARM) require host calls to be routed through the RMM
(Realm Management Monitor) via the RSI (Realm Service Interface). This
series implements most of the necessary changes to support Realms on
Hyper-V.
One required change is not included in this series. The two buffers
allocated via vzalloc() in netvsc_init_buf() cannot be decrypted in
vmbus_establish_gpadl(). Currently only linearly mapped memory can be
decrypted. See my RFC patch [1]. I will implement the accompanying netvsc
changes based on the feedback I receive on that patch.
This patch series was tested by booting a Realm on Cobalt 200 running
Windows. I decreased the buffer size and used kzalloc() in
netvsc_init_buf() in my testing as a workaround for the issue mentioned
above.
[1] https://lore.kernel.org/all/20260521205834.1012925-1-kameroncarr@linux.microsoft.com/
Kameron Carr (6):
arm64: rsi: Add RSI host call structure and helper function
firmware: smccc: Detect hypervisor via RSI host call in CCA Realms
arm64: hyperv: Add per-CPU RSI host call infrastructure for CCA Realms
Drivers: hv: Mark shared memory as decrypted for CCA Realms
arm64: hyperv: Route hypercalls through RSI host call in CCA Realms
arm64: hyperv: Implement hv_is_isolation_supported() for CCA Realms
arch/arm64/hyperv/hv_core.c | 175 ++++++++++++++++++++++++------
arch/arm64/hyperv/mshyperv.c | 88 ++++++++++++++-
arch/arm64/include/asm/mshyperv.h | 3 +
arch/arm64/include/asm/rsi_cmds.h | 9 ++
arch/arm64/include/asm/rsi_smc.h | 6 +
drivers/firmware/smccc/smccc.c | 41 ++++++-
drivers/hv/hv_common.c | 9 +-
include/asm-generic/mshyperv.h | 1 +
8 files changed, 294 insertions(+), 38 deletions(-)
base-commit: 7a035678fc2bdee81881170764ef08a91a076147
--
2.45.4
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC PATCH 1/6] arm64: rsi: Add RSI host call structure and helper function
2026-06-09 18:10 [RFC PATCH 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
@ 2026-06-09 18:10 ` Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms Kameron Carr
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Kameron Carr @ 2026-06-09 18:10 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli
Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
linux-arch, mhklinux
Add struct rsi_host_call to rsi_smc.h, which represents the host call
data structure used by the Realm Management Monitor (RMM) for the
RSI_HOST_CALL interface. The structure contains a 16-bit immediate field
and 31 general-purpose register values, aligned to 256 bytes as required
by the CCA RMM specification.
Add rsi_host_call() static inline wrapper in rsi_cmds.h that invokes
SMC_RSI_HOST_CALL with the physical address of the host call structure.
This will be used by Hyper-V guest code to route hypercalls through the
RSI interface when running inside an Arm CCA Realm.
Signed-off-by: Kameron Carr <kameroncarr@linux.microsoft.com>
---
arch/arm64/include/asm/rsi_cmds.h | 9 +++++++++
arch/arm64/include/asm/rsi_smc.h | 6 ++++++
2 files changed, 15 insertions(+)
diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi_cmds.h
index 2c8763876dfb7..83b4b1f598454 100644
--- a/arch/arm64/include/asm/rsi_cmds.h
+++ b/arch/arm64/include/asm/rsi_cmds.h
@@ -159,4 +159,13 @@ static inline unsigned long rsi_attestation_token_continue(phys_addr_t granule,
return res.a0;
}
+static inline long rsi_host_call(phys_addr_t host_call_struct)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(SMC_RSI_HOST_CALL, host_call_struct, 0, 0, 0, 0, 0, 0,
+ &res);
+ return res.a0;
+}
+
#endif /* __ASM_RSI_CMDS_H */
diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_smc.h
index e19253f96c940..ffea93340ed7f 100644
--- a/arch/arm64/include/asm/rsi_smc.h
+++ b/arch/arm64/include/asm/rsi_smc.h
@@ -142,6 +142,12 @@ struct realm_config {
*/
} __aligned(0x1000);
+struct rsi_host_call {
+ u16 immediate;
+ u64 gprs[31];
+} __aligned(256);
+static_assert(sizeof(struct rsi_host_call) == 256);
+
#endif /* __ASSEMBLER__ */
/*
--
2.45.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms
2026-06-09 18:10 [RFC PATCH 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 1/6] arm64: rsi: Add RSI host call structure and helper function Kameron Carr
@ 2026-06-09 18:10 ` Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for " Kameron Carr
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Kameron Carr @ 2026-06-09 18:10 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli
Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
linux-arch, mhklinux
Modify arm_smccc_hypervisor_has_uuid() to check is_realm_world() and
use rsi_host_call() to query the hypervisor vendor UUID when inside a
Realm. The realm path is factored into a helper,
arm_smccc_realm_get_hypervisor_uuid(), that owns a file-static
rsi_host_call buffer (uuid_hc) serialized by a spinlock.
The RSI-specific includes, file-static state and helper are guarded
with CONFIG_ARM64 because <asm/rsi.h> does not exist on 32-bit ARM.
For non-Realm environments, the existing arm_smccc_1_1_invoke() path
is unchanged.
Signed-off-by: Kameron Carr <kameroncarr@linux.microsoft.com>
---
drivers/firmware/smccc/smccc.c | 41 +++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
index bdee057db2fd3..6b465e65472b0 100644
--- a/drivers/firmware/smccc/smccc.c
+++ b/drivers/firmware/smccc/smccc.c
@@ -12,6 +12,12 @@
#include <linux/platform_device.h>
#include <asm/archrandom.h>
+#ifdef CONFIG_ARM64
+#include <linux/cleanup.h>
+#include <linux/spinlock.h>
+#include <asm/rsi.h>
+#endif
+
static u32 smccc_version = ARM_SMCCC_VERSION_1_0;
static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
@@ -67,12 +73,45 @@ s32 arm_smccc_get_soc_id_revision(void)
}
EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
+#ifdef CONFIG_ARM64
+static struct rsi_host_call uuid_hc;
+static DEFINE_SPINLOCK(uuid_hc_lock);
+
+/*
+ * Helper function to get the hypervisor UUID via an RsiHostCall.
+ */
+static bool arm_smccc_realm_get_hypervisor_uuid(struct arm_smccc_res *res)
+{
+ guard(spinlock_irqsave)(&uuid_hc_lock);
+
+ memset(&uuid_hc, 0, sizeof(uuid_hc));
+ uuid_hc.gprs[0] = ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID;
+
+ if (rsi_host_call(__pa_symbol(&uuid_hc)) != RSI_SUCCESS)
+ return false;
+
+ res->a0 = uuid_hc.gprs[0];
+ res->a1 = uuid_hc.gprs[1];
+ res->a2 = uuid_hc.gprs[2];
+ res->a3 = uuid_hc.gprs[3];
+ return true;
+}
+#endif
+
bool arm_smccc_hypervisor_has_uuid(const uuid_t *hyp_uuid)
{
struct arm_smccc_res res = {};
uuid_t uuid;
- arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
+#ifdef CONFIG_ARM64
+ if (is_realm_world()) {
+ if (!arm_smccc_realm_get_hypervisor_uuid(&res))
+ return false;
+ } else
+#endif
+ arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID,
+ &res);
+
if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
return false;
--
2.45.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for CCA Realms
2026-06-09 18:10 [RFC PATCH 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 1/6] arm64: rsi: Add RSI host call structure and helper function Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms Kameron Carr
@ 2026-06-09 18:10 ` Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 4/6] Drivers: hv: Mark shared memory as decrypted " Kameron Carr
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Kameron Carr @ 2026-06-09 18:10 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli
Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
linux-arch, mhklinux
Arm CCA Realms cannot issue Hyper-V hypercalls via HVC; the guest must
route them through the RSI_HOST_CALL interface, which takes the IPA of a
per-CPU rsi_host_call structure as its argument.
Add hyperv_pcpu_hostcall_struct as a per-CPU pointer to that buffer and
allocate it for the boot CPU during hyperv_init() and for each secondary
CPU in hv_cpu_init(). The allocation is gated on is_realm_world() so
non-Realm arm64 Hyper-V guests pay no memory cost.
Signed-off-by: Kameron Carr <kameroncarr@linux.microsoft.com>
---
arch/arm64/hyperv/mshyperv.c | 78 ++++++++++++++++++++++++++++++-
arch/arm64/include/asm/mshyperv.h | 3 ++
2 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index 4fdc26ade1d74..08fec82691683 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -15,10 +15,16 @@
#include <linux/errno.h>
#include <linux/version.h>
#include <linux/cpuhotplug.h>
+#include <linux/slab.h>
+#include <linux/percpu.h>
#include <asm/mshyperv.h>
+#include <asm/rsi.h>
static bool hyperv_initialized;
+void * __percpu *hyperv_pcpu_hostcall_struct;
+EXPORT_SYMBOL_GPL(hyperv_pcpu_hostcall_struct);
+
int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
{
hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION,
@@ -60,6 +66,46 @@ static bool __init hyperv_detect_via_acpi(void)
#endif
+static void hv_hostcall_free(void)
+{
+ int cpu;
+
+ if (!hyperv_pcpu_hostcall_struct)
+ return;
+
+ for_each_possible_cpu(cpu)
+ kfree(*per_cpu_ptr(hyperv_pcpu_hostcall_struct, cpu));
+ free_percpu(hyperv_pcpu_hostcall_struct);
+ hyperv_pcpu_hostcall_struct = NULL;
+}
+
+static int hv_cpu_init(unsigned int cpu)
+{
+ void **hostcall_struct;
+ gfp_t flags;
+ void *mem;
+
+ if (hyperv_pcpu_hostcall_struct) {
+ /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
+ flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL;
+
+ hostcall_struct = (void **)this_cpu_ptr(hyperv_pcpu_hostcall_struct);
+ /*
+ * The hostcall_struct memory is not freed when the CPU
+ * goes offline. If a previously offlined CPU is brought
+ * back online, the memory is reused here.
+ */
+ if (!*hostcall_struct) {
+ mem = kzalloc_obj(struct rsi_host_call, flags);
+ if (!mem)
+ return -ENOMEM;
+ *hostcall_struct = mem;
+ }
+ }
+
+ return hv_common_cpu_init(cpu);
+}
+
static bool __init hyperv_detect_via_smccc(void)
{
uuid_t hyperv_uuid = UUID_INIT(
@@ -73,6 +119,8 @@ static bool __init hyperv_detect_via_smccc(void)
static int __init hyperv_init(void)
{
struct hv_get_vp_registers_output result;
+ void **hostcall_struct;
+ void *mem;
u64 guest_id;
int ret;
@@ -85,6 +133,27 @@ static int __init hyperv_init(void)
if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
return 0;
+ /*
+ * The RSI host-call buffer is only ever used when
+ * is_realm_world() is true. Skip the per-CPU allocation on
+ * non-Realm guests.
+ */
+ if (is_realm_world()) {
+ hyperv_pcpu_hostcall_struct = alloc_percpu(void *);
+ if (!hyperv_pcpu_hostcall_struct)
+ return -ENOMEM;
+
+ hostcall_struct = (void **)this_cpu_ptr(hyperv_pcpu_hostcall_struct);
+ if (!*hostcall_struct) {
+ mem = kzalloc_obj(struct rsi_host_call);
+ if (!mem) {
+ ret = -ENOMEM;
+ goto free_hostcall_mem;
+ }
+ *hostcall_struct = mem;
+ }
+ }
+
/* Setup the guest ID */
guest_id = hv_generate_guest_id(LINUX_VERSION_CODE);
hv_set_vpreg(HV_REGISTER_GUEST_OS_ID, guest_id);
@@ -106,12 +175,13 @@ static int __init hyperv_init(void)
ret = hv_common_init();
if (ret)
- return ret;
+ goto free_hostcall_mem;
ret = cpuhp_setup_state(CPUHP_AP_HYPERV_ONLINE, "arm64/hyperv_init:online",
- hv_common_cpu_init, hv_common_cpu_die);
+ hv_cpu_init, hv_common_cpu_die);
if (ret < 0) {
hv_common_free();
+ hv_hostcall_free();
return ret;
}
@@ -125,6 +195,10 @@ static int __init hyperv_init(void)
hyperv_initialized = true;
return 0;
+
+free_hostcall_mem:
+ hv_hostcall_free();
+ return ret;
}
early_initcall(hyperv_init);
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
index b721d3134ab66..65a00bd14c6cb 100644
--- a/arch/arm64/include/asm/mshyperv.h
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -63,4 +63,7 @@ static inline u64 hv_get_non_nested_msr(unsigned int reg)
#include <asm-generic/mshyperv.h>
+/* Per-CPU RSI host call structure for CCA Realms */
+extern void *__percpu *hyperv_pcpu_hostcall_struct;
+
#endif
--
2.45.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH 4/6] Drivers: hv: Mark shared memory as decrypted for CCA Realms
2026-06-09 18:10 [RFC PATCH 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
` (2 preceding siblings ...)
2026-06-09 18:10 ` [RFC PATCH 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for " Kameron Carr
@ 2026-06-09 18:10 ` Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 5/6] arm64: hyperv: Route hypercalls through RSI host call in " Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 6/6] arm64: hyperv: Implement hv_is_isolation_supported() for " Kameron Carr
5 siblings, 0 replies; 7+ messages in thread
From: Kameron Carr @ 2026-06-09 18:10 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli
Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
linux-arch, mhklinux
In hv_common_cpu_init(), the per-CPU hypercall input/output pages need
to be marked as decrypted (shared) for confidential VM isolation types.
This is already done for SNP and TDX isolation; extend the same handling
to Arm CCA Realm guests so that the host hypervisor can access the
shared hypercall buffers.
is_realm_world() is only declared in arch/arm64/include/asm/rsi.h, so
using it directly in the arch-neutral drivers/hv/hv_common.c would
break the x86 build. Introduce a Hyper-V-specific helper following the
established hv_isolation_type_snp() / hv_isolation_type_tdx() pattern.
On architectures other than arm64 the weak default keeps the existing
behaviour.
Signed-off-by: Kameron Carr <kameroncarr@linux.microsoft.com>
---
arch/arm64/hyperv/mshyperv.c | 5 +++++
drivers/hv/hv_common.c | 9 ++++++++-
include/asm-generic/mshyperv.h | 1 +
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index 08fec82691683..b595b2b9bdbbb 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -208,3 +208,8 @@ bool hv_is_hyperv_initialized(void)
return hyperv_initialized;
}
EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);
+
+bool hv_isolation_type_cca(void)
+{
+ return is_realm_world();
+}
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 6b67ac6167891..010c7d98b5de1 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -499,7 +499,8 @@ int hv_common_cpu_init(unsigned int cpu)
}
if (!ms_hyperv.paravisor_present &&
- (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
+ (hv_isolation_type_snp() || hv_isolation_type_tdx() ||
+ hv_isolation_type_cca())) {
ret = set_memory_decrypted((unsigned long)mem, pgcount);
if (ret) {
/* It may be unsafe to free 'mem' */
@@ -666,6 +667,12 @@ bool __weak hv_isolation_type_tdx(void)
}
EXPORT_SYMBOL_GPL(hv_isolation_type_tdx);
+bool __weak hv_isolation_type_cca(void)
+{
+ return false;
+}
+EXPORT_SYMBOL_GPL(hv_isolation_type_cca);
+
void __weak hv_setup_vmbus_handler(void (*handler)(void))
{
}
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index bf601d67cecb9..1fa79abce743c 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -79,6 +79,7 @@ u64 hv_do_fast_hypercall16(u16 control, u64 input1, u64 input2);
bool hv_isolation_type_snp(void);
bool hv_isolation_type_tdx(void);
+bool hv_isolation_type_cca(void);
/*
* On architectures where Hyper-V doesn't support AEOI (e.g., ARM64),
--
2.45.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH 5/6] arm64: hyperv: Route hypercalls through RSI host call in CCA Realms
2026-06-09 18:10 [RFC PATCH 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
` (3 preceding siblings ...)
2026-06-09 18:10 ` [RFC PATCH 4/6] Drivers: hv: Mark shared memory as decrypted " Kameron Carr
@ 2026-06-09 18:10 ` Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 6/6] arm64: hyperv: Implement hv_is_isolation_supported() for " Kameron Carr
5 siblings, 0 replies; 7+ messages in thread
From: Kameron Carr @ 2026-06-09 18:10 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli
Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
linux-arch, mhklinux
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 <kameroncarr@linux.microsoft.com>
---
arch/arm64/hyperv/hv_core.c | 175 +++++++++++++++++++++++++++++-------
1 file changed, 141 insertions(+), 34 deletions(-)
diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index e33a9e3c366a1..1759998ef2667 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -16,6 +16,7 @@
#include <asm-generic/bug.h>
#include <hyperv/hvhdk.h>
#include <asm/mshyperv.h>
+#include <asm/rsi.h>
/*
* hv_do_hypercall- Invoke the specified hypercall
@@ -25,12 +26,32 @@ u64 hv_do_hypercall(u64 control, void *input, void *output)
struct arm_smccc_res res;
u64 input_address;
u64 output_address;
+ struct rsi_host_call *hostcall;
+ unsigned long flags;
+ u64 ret;
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()) {
+ local_irq_save(flags);
+ hostcall = *this_cpu_ptr(hyperv_pcpu_hostcall_struct);
+ memset(hostcall, 0, sizeof(*hostcall));
+ hostcall->gprs[0] = HV_FUNC_ID;
+ hostcall->gprs[1] = control;
+ hostcall->gprs[2] = input_address;
+ hostcall->gprs[3] = output_address;
+
+ 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;
+ }
+
+ arm_smccc_1_1_hvc(HV_FUNC_ID, control, input_address,
+ output_address, &res);
return res.a0;
}
EXPORT_SYMBOL_GPL(hv_do_hypercall);
@@ -45,9 +66,28 @@ u64 hv_do_fast_hypercall8(u16 code, u64 input)
{
struct arm_smccc_res res;
u64 control;
+ struct rsi_host_call *hostcall;
+ unsigned long flags;
+ u64 ret;
control = (u64)code | HV_HYPERCALL_FAST_BIT;
+ if (is_realm_world()) {
+ local_irq_save(flags);
+ hostcall = *this_cpu_ptr(hyperv_pcpu_hostcall_struct);
+ memset(hostcall, 0, sizeof(*hostcall));
+ hostcall->gprs[0] = HV_FUNC_ID;
+ hostcall->gprs[1] = control;
+ hostcall->gprs[2] = input;
+
+ 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;
+ }
+
arm_smccc_1_1_hvc(HV_FUNC_ID, control, input, &res);
return res.a0;
}
@@ -62,9 +102,29 @@ u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
{
struct arm_smccc_res res;
u64 control;
+ struct rsi_host_call *hostcall;
+ unsigned long flags;
+ u64 ret;
control = (u64)code | HV_HYPERCALL_FAST_BIT;
+ if (is_realm_world()) {
+ local_irq_save(flags);
+ hostcall = *this_cpu_ptr(hyperv_pcpu_hostcall_struct);
+ 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;
+ }
+
arm_smccc_1_1_hvc(HV_FUNC_ID, control, input1, input2, &res);
return res.a0;
}
@@ -76,24 +136,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;
+
+ if (is_realm_world()) {
+ local_irq_save(flags);
+ hostcall = *this_cpu_ptr(hyperv_pcpu_hostcall_struct);
+ 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;
- 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 (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 +188,56 @@ 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;
+ 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()) {
+ unsigned long flags;
- /*
- * Use the SMCCC 1.2 interface because the results are in registers
- * beyond X0-X3.
- */
- arm_smccc_1_2_hvc(&args, &res);
+ local_irq_save(flags);
+ hostcall = *this_cpu_ptr(hyperv_pcpu_hostcall_struct);
+ memset(hostcall, 0, sizeof(*hostcall));
+
+ 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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH 6/6] arm64: hyperv: Implement hv_is_isolation_supported() for CCA Realms
2026-06-09 18:10 [RFC PATCH 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
` (4 preceding siblings ...)
2026-06-09 18:10 ` [RFC PATCH 5/6] arm64: hyperv: Route hypercalls through RSI host call in " Kameron Carr
@ 2026-06-09 18:10 ` Kameron Carr
5 siblings, 0 replies; 7+ messages in thread
From: Kameron Carr @ 2026-06-09 18:10 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli
Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
linux-arch, mhklinux
Provide an arm64 implementation of hv_is_isolation_supported() that
overrides the __weak default in drivers/hv/hv_common.c.
The implementation deliberately does not depend on
hv_is_hyperv_initialized() because hv_common_init() consults
hv_is_isolation_supported() before hyperv_initialized is set.
Signed-off-by: Kameron Carr <kameroncarr@linux.microsoft.com>
---
arch/arm64/hyperv/mshyperv.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index b595b2b9bdbbb..b9b1c2f8e3ec7 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -213,3 +213,8 @@ bool hv_isolation_type_cca(void)
{
return is_realm_world();
}
+
+bool hv_is_isolation_supported(void)
+{
+ return is_realm_world();
+}
--
2.45.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-09 18:11 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-09 18:10 [RFC PATCH 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 1/6] arm64: rsi: Add RSI host call structure and helper function Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for " Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 4/6] Drivers: hv: Mark shared memory as decrypted " Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 5/6] arm64: hyperv: Route hypercalls through RSI host call in " Kameron Carr
2026-06-09 18:10 ` [RFC PATCH 6/6] arm64: hyperv: Implement hv_is_isolation_supported() for " Kameron Carr
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox