Linux-HyperV List
 help / color / mirror / Atom feed
* [PATCH v3 0/6] arm64: hyperv: Add Realm support for Hyper-V
@ 2026-07-21 20:11 Kameron Carr
  2026-07-21 20:11 ` [PATCH v3 1/6] arm64: rsi: Add RSI host call structure and helper function Kameron Carr
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Kameron Carr @ 2026-07-21 20:11 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, mhklinux
  Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
	arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
	linux-arch

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.

This patch series was tested by booting a Realm on Cobalt 200 running
Windows. I tested 4KB and 64KB page size. I replaced vzalloc() in
netvsc_init_buf() with alloc_pages_node() -> set_memory_decrypted() ->
vmap() in my testing as a workaround for the issue mentioned above [1].

Changes since v1 [2]:
  Patch 1: Add explicit padding to the RSI host call structure
  Patch 3: Change from a per-cpu pointer lazily allocated to an array
             of host call structs indexed by cpu id
  Patch 4: Align input_page + output_page allocation to PAGE_SIZE since
             that is the smallest unit of memory that can be decrypted
           ~Remove KASAN tags before passing address to
             set_memory_decrypted() since __is_lm_address() does pointer
             arithmetic.~
  Patch 5: Add a helper function to reduce repetition
           Check for NULL before indexing into host call array

Changes since v2 [3]:
  Patch 3: Remove hv_hostcall_free() and inline the logic for simplicity
           Reorder edits to keep #include line at the end of the file
  Patch 4: Remove kasan_reset_tag()

[1] https://lore.kernel.org/all/20260721195633.1438361-1-kameroncarr@linux.microsoft.com/
[2] https://lore.kernel.org/all/20260609181030.2378391-1-kameroncarr@linux.microsoft.com/
[3] https://lore.kernel.org/all/20260625173500.1995481-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       | 155 +++++++++++++++++++++++-------
 arch/arm64/hyperv/mshyperv.c      |  38 +++++++-
 arch/arm64/include/asm/mshyperv.h |   4 +
 arch/arm64/include/asm/rsi_cmds.h |  22 +++++
 arch/arm64/include/asm/rsi_smc.h  |   7 ++
 drivers/firmware/smccc/smccc.c    |  41 +++++++-
 drivers/hv/hv_common.c            |  17 +++-
 include/asm-generic/mshyperv.h    |   1 +
 8 files changed, 244 insertions(+), 41 deletions(-)


base-commit: a4ffc59238be84dd1c26bf1c001543e832674fc6
-- 
2.45.4


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 1/6] arm64: rsi: Add RSI host call structure and helper function
  2026-07-21 20:11 [PATCH v3 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
@ 2026-07-21 20:11 ` Kameron Carr
  2026-07-21 20:22   ` sashiko-bot
  2026-07-21 20:11 ` [PATCH v3 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms Kameron Carr
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Kameron Carr @ 2026-07-21 20:11 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, mhklinux
  Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
	arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
	linux-arch

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 | 22 ++++++++++++++++++++++
 arch/arm64/include/asm/rsi_smc.h  |  7 +++++++
 2 files changed, 29 insertions(+)

diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi_cmds.h
index 2c8763876dfb7..9daf8008e5da2 100644
--- a/arch/arm64/include/asm/rsi_cmds.h
+++ b/arch/arm64/include/asm/rsi_cmds.h
@@ -88,6 +88,28 @@ static inline long rsi_set_addr_range_state(phys_addr_t start,
 	return res.a0;
 }
 
+/**
+ * rsi_host_call - Make a Host call.
+ * @host_call_struct: IPA of host call structure
+ *
+ * This call will fail if the IPA of the host call structure:
+ * * is not aligned to 256 bytes,
+ * * is not protected / encrypted,
+ * * is RIPAS_EMPTY
+ *
+ * Returns:
+ *  On success, returns RSI_SUCCESS.
+ *  Otherwise, returns an error code.
+ */
+static inline unsigned 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;
+}
+
 /**
  * rsi_attestation_token_init - Initialise the operation to retrieve an
  * attestation token.
diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_smc.h
index e19253f96c940..9cc57b5be0c02 100644
--- a/arch/arm64/include/asm/rsi_smc.h
+++ b/arch/arm64/include/asm/rsi_smc.h
@@ -142,6 +142,13 @@ struct realm_config {
 	 */
 } __aligned(0x1000);
 
+struct rsi_host_call {
+	u16 immediate;
+	u8 _padding[6];
+	u64 gprs[31];
+} __aligned(256);
+static_assert(sizeof(struct rsi_host_call) == 256);
+
 #endif /* __ASSEMBLER__ */
 
 /*
-- 
2.45.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v3 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms
  2026-07-21 20:11 [PATCH v3 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
  2026-07-21 20:11 ` [PATCH v3 1/6] arm64: rsi: Add RSI host call structure and helper function Kameron Carr
@ 2026-07-21 20:11 ` Kameron Carr
  2026-07-21 20:24   ` sashiko-bot
  2026-07-21 20:11 ` [PATCH v3 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for " Kameron Carr
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Kameron Carr @ 2026-07-21 20:11 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, mhklinux
  Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
	arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
	linux-arch

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..a876b7aa2dc99 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 void 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) {
+		res->a0 = SMCCC_RET_NOT_SUPPORTED;
+		return;
+	}
+
+	res->a0 = uuid_hc.gprs[0];
+	res->a1 = uuid_hc.gprs[1];
+	res->a2 = uuid_hc.gprs[2];
+	res->a3 = uuid_hc.gprs[3];
+}
+#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())
+		arm_smccc_realm_get_hypervisor_uuid(&res);
+	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] 12+ messages in thread

* [PATCH v3 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for CCA Realms
  2026-07-21 20:11 [PATCH v3 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
  2026-07-21 20:11 ` [PATCH v3 1/6] arm64: rsi: Add RSI host call structure and helper function Kameron Carr
  2026-07-21 20:11 ` [PATCH v3 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms Kameron Carr
@ 2026-07-21 20:11 ` Kameron Carr
  2026-07-21 20:25   ` sashiko-bot
  2026-07-21 20:11 ` [PATCH v3 4/6] Drivers: hv: Mark shared memory as decrypted " Kameron Carr
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Kameron Carr @ 2026-07-21 20:11 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, mhklinux
  Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
	arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
	linux-arch

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 hv_hostcall_array as a per-CPU struct array and allocate it during
hyperv_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      | 28 ++++++++++++++++++++++++++--
 arch/arm64/include/asm/mshyperv.h |  4 ++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index 4fdc26ade1d74..d9010e64ddd7c 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -15,10 +15,15 @@
 #include <linux/errno.h>
 #include <linux/version.h>
 #include <linux/cpuhotplug.h>
+#include <linux/slab.h>
 #include <asm/mshyperv.h>
+#include <asm/rsi.h>
 
 static bool hyperv_initialized;
 
+struct rsi_host_call *hv_hostcall_array;
+EXPORT_SYMBOL_GPL(hv_hostcall_array);
+
 int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
 {
 	hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION,
@@ -85,6 +90,20 @@ static int __init hyperv_init(void)
 	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
 		return 0;
 
+	/*
+	 * The RSI host-call buffers are only ever used when
+	 * is_realm_world() is true. Skip the allocation on non-Realm
+	 * guests. A single contiguous array of nr_cpu_ids entries is
+	 * allocated; each CPU indexes into it by its processor ID.
+	 */
+	if (is_realm_world()) {
+		hv_hostcall_array = kcalloc(nr_cpu_ids,
+					    sizeof(struct rsi_host_call),
+					    GFP_KERNEL);
+		if (!hv_hostcall_array)
+			return -ENOMEM;
+	}
+
 	/* Setup the guest ID */
 	guest_id = hv_generate_guest_id(LINUX_VERSION_CODE);
 	hv_set_vpreg(HV_REGISTER_GUEST_OS_ID, guest_id);
@@ -106,13 +125,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);
 	if (ret < 0) {
 		hv_common_free();
-		return ret;
+		goto free_hostcall_mem;
 	}
 
 	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
@@ -125,6 +144,11 @@ static int __init hyperv_init(void)
 
 	hyperv_initialized = true;
 	return 0;
+
+free_hostcall_mem:
+	kfree(hv_hostcall_array);
+	hv_hostcall_array = NULL;
+	return ret;
 }
 
 early_initcall(hyperv_init);
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
index b721d3134ab66..aed0aa526c8b4 100644
--- a/arch/arm64/include/asm/mshyperv.h
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -61,6 +61,10 @@ static inline u64 hv_get_non_nested_msr(unsigned int reg)
 				ARM_SMCCC_OWNER_VENDOR_HYP,	\
 				HV_SMCCC_FUNC_NUMBER)
 
+/* Per-CPU-indexed RSI host call structures for CCA Realms */
+struct rsi_host_call;
+extern struct rsi_host_call *hv_hostcall_array;
+
 #include <asm-generic/mshyperv.h>
 
 #endif
-- 
2.45.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v3 4/6] Drivers: hv: Mark shared memory as decrypted for CCA Realms
  2026-07-21 20:11 [PATCH v3 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
                   ` (2 preceding siblings ...)
  2026-07-21 20:11 ` [PATCH v3 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for " Kameron Carr
@ 2026-07-21 20:11 ` Kameron Carr
  2026-07-21 20:24   ` sashiko-bot
  2026-07-21 20:11 ` [PATCH v3 5/6] arm64: hyperv: Route hypercalls through RSI host call in " Kameron Carr
  2026-07-21 20:11 ` [PATCH v3 6/6] arm64: hyperv: Implement hv_is_isolation_supported() for " Kameron Carr
  5 siblings, 1 reply; 12+ messages in thread
From: Kameron Carr @ 2026-07-21 20:11 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, mhklinux
  Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
	arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
	linux-arch

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         | 17 +++++++++++++----
 include/asm-generic/mshyperv.h |  1 +
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index d9010e64ddd7c..8519f694f2897 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -158,3 +158,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..0f9412fcb9571 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -476,6 +476,7 @@ int hv_common_cpu_init(unsigned int cpu)
 	u64 msr_vp_index;
 	gfp_t flags;
 	const int pgcount = hv_output_page_exists() ? 2 : 1;
+	const size_t alloc_size = ALIGN((size_t)pgcount * HV_HYP_PAGE_SIZE, PAGE_SIZE);
 	void *mem;
 	int ret = 0;
 
@@ -489,7 +490,7 @@ int hv_common_cpu_init(unsigned int cpu)
 	 * online and then taken offline
 	 */
 	if (!*inputarg) {
-		mem = kmalloc_array(pgcount, HV_HYP_PAGE_SIZE, flags);
+		mem = kmalloc(alloc_size, flags);
 		if (!mem)
 			return -ENOMEM;
 
@@ -499,14 +500,16 @@ int hv_common_cpu_init(unsigned int cpu)
 		}
 
 		if (!ms_hyperv.paravisor_present &&
-		    (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
-			ret = set_memory_decrypted((unsigned long)mem, pgcount);
+		    (hv_isolation_type_snp() || hv_isolation_type_tdx() ||
+		     hv_isolation_type_cca())) {
+			ret = set_memory_decrypted((unsigned long)mem,
+						   alloc_size >> PAGE_SHIFT);
 			if (ret) {
 				/* It may be unsafe to free 'mem' */
 				return ret;
 			}
 
-			memset(mem, 0x00, pgcount * HV_HYP_PAGE_SIZE);
+			memset(mem, 0x00, alloc_size);
 		}
 
 		/*
@@ -666,6 +669,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] 12+ messages in thread

* [PATCH v3 5/6] arm64: hyperv: Route hypercalls through RSI host call in CCA Realms
  2026-07-21 20:11 [PATCH v3 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
                   ` (3 preceding siblings ...)
  2026-07-21 20:11 ` [PATCH v3 4/6] Drivers: hv: Mark shared memory as decrypted " Kameron Carr
@ 2026-07-21 20:11 ` Kameron Carr
  2026-07-21 20:27   ` sashiko-bot
  2026-07-21 20:11 ` [PATCH v3 6/6] arm64: hyperv: Implement hv_is_isolation_supported() for " Kameron Carr
  5 siblings, 1 reply; 12+ messages in thread
From: Kameron Carr @ 2026-07-21 20:11 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, mhklinux
  Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
	arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
	linux-arch

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 | 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 <linux/mm.h>
 #include <linux/arm-smccc.h>
 #include <linux/module.h>
+#include <linux/smp.h>
 #include <asm-generic/bug.h>
 #include <hyperv/hvhdk.h>
 #include <asm/mshyperv.h>
+#include <asm/rsi.h>
+
+/*
+ * 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


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v3 6/6] arm64: hyperv: Implement hv_is_isolation_supported() for CCA Realms
  2026-07-21 20:11 [PATCH v3 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
                   ` (4 preceding siblings ...)
  2026-07-21 20:11 ` [PATCH v3 5/6] arm64: hyperv: Route hypercalls through RSI host call in " Kameron Carr
@ 2026-07-21 20:11 ` Kameron Carr
  5 siblings, 0 replies; 12+ messages in thread
From: Kameron Carr @ 2026-07-21 20:11 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, mhklinux
  Cc: catalin.marinas, will, mark.rutland, lpieralisi, sudeep.holla,
	arnd, thuth, linux-hyperv, linux-arm-kernel, linux-kernel,
	linux-arch

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 8519f694f2897..e28612255a970 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -163,3 +163,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] 12+ messages in thread

* Re: [PATCH v3 1/6] arm64: rsi: Add RSI host call structure and helper function
  2026-07-21 20:11 ` [PATCH v3 1/6] arm64: rsi: Add RSI host call structure and helper function Kameron Carr
@ 2026-07-21 20:22   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-07-21 20:22 UTC (permalink / raw)
  To: Kameron Carr; +Cc: linux-hyperv

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The `rsi_host_call` structure uses native integer types instead of explicit little-endian types, which can cause an ABI mismatch on big-endian kernels.
--

--- Patch [1]: [PATCH v3 1/6] arm64: rsi: Add RSI host call structure and helper function ---
commit 47a2fc3b0f72dc993f44827b221ab5eb02bbcb36
Author: Kameron Carr <kameroncarr@linux.microsoft.com>

arm64: rsi: Add RSI host call structure and helper function

This commit introduces the rsi_host_call structure and a helper function to
invoke SMC_RSI_HOST_CALL. This allows Hyper-V guest code to route hypercalls
through the RSI interface when running inside an Arm CCA Realm.

[ ... ]

> diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_smc.h
> index e19253f96c940..9cc57b5be0c02 100644
> --- a/arch/arm64/include/asm/rsi_smc.h
> +++ b/arch/arm64/include/asm/rsi_smc.h
> @@ -142,6 +142,13 @@ struct realm_config {
>  	 */
>  } __aligned(0x1000);
>  
> +struct rsi_host_call {
> +	u16 immediate;
> +	u8 _padding[6];
> +	u64 gprs[31];
> +} __aligned(256);

[Severity: Medium]
Should this structure use explicit little-endian types (__le16, __le64)
instead of native integer types?

If a big-endian kernel constructs this structure in memory and issues the
SMC, won't the Realm Management Monitor read byte-swapped values? The CCA
RMM specification dictates that memory structures shared between the Realm
and the RMM must be little-endian, so using native types could cause an ABI
mismatch.

> +static_assert(sizeof(struct rsi_host_call) == 256);
> +
>  #endif /* __ASSEMBLER__ */
>  
>  /*

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260721201148.1441143-1-kameroncarr@linux.microsoft.com?part=1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 4/6] Drivers: hv: Mark shared memory as decrypted for CCA Realms
  2026-07-21 20:11 ` [PATCH v3 4/6] Drivers: hv: Mark shared memory as decrypted " Kameron Carr
@ 2026-07-21 20:24   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-07-21 20:24 UTC (permalink / raw)
  To: Kameron Carr; +Cc: linux-hyperv

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Using `kmalloc()` for memory passed to `set_memory_decrypted()` causes silent memory corruption on x86 and initialization failures on ARM64 due to a lack of strict page alignment and KASAN/MTE pointer tagging.
--

--- Patch [4]: [PATCH v3 4/6] Drivers: hv: Mark shared memory as decrypted for CCA Realms ---
commit 21b5c4cec77eb56971c17ededee7133820fad287
Author: Kameron Carr <kameroncarr@linux.microsoft.com>

Drivers: hv: Mark shared memory as decrypted for CCA Realms

This patch extends confidential VM isolation memory decryption to Arm CCA Realm
guests during hypercall memory initialization. It introduces a helper for CCA
isolation and updates the hypercall buffer allocation path to use it.

> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> index 6b67ac6167891..0f9412fcb9571 100644
> --- a/drivers/hv/hv_common.c
> +++ b/drivers/hv/hv_common.c
[ ... ]
> @@ -489,7 +490,7 @@ int hv_common_cpu_init(unsigned int cpu)
>  	 * online and then taken offline
>  	 */
>  	if (!*inputarg) {
> -		mem = kmalloc_array(pgcount, HV_HYP_PAGE_SIZE, flags);
> +		mem = kmalloc(alloc_size, flags);
>  		if (!mem)
>  			return -ENOMEM;
>  
> @@ -499,14 +500,16 @@ int hv_common_cpu_init(unsigned int cpu)
>  		}
>  
>  		if (!ms_hyperv.paravisor_present &&
> -		    (hv_isolation_type_snp() || hv_isolation_type_tdx())) {
> -			ret = set_memory_decrypted((unsigned long)mem, pgcount);
> +		    (hv_isolation_type_snp() || hv_isolation_type_tdx() ||
> +		     hv_isolation_type_cca())) {
> +			ret = set_memory_decrypted((unsigned long)mem,
> +						   alloc_size >> PAGE_SHIFT);

[Severity: High]
This isn't a bug introduced by this patch, but is it safe to pass memory 
allocated by kmalloc to set_memory_decrypted() in hv_common_cpu_init()?

When kmalloc is used with SLUB_DEBUG, the returned pointer is not strictly 
page-aligned. Because set_memory_decrypted() operates on page frames and
rounds down to the page boundary, this could silently decrypt adjacent slab
objects or metadata on x86 architectures.

Additionally, on arm64 systems with MTE enabled, kmalloc returns a tagged 
pointer. Passing a tagged pointer to set_memory_decrypted() causes its
internal __is_lm_address() check to fail, leading to initialization failures
during boot or CPU hotplug for CCA guests.

Would it be better to allocate this memory using the page allocator, such as 
with __get_free_pages(), to ensure the address is strictly page-aligned and 
untagged?

>  			if (ret) {
>  				/* It may be unsafe to free 'mem' */
>  				return ret;
>  			}
>  
> -			memset(mem, 0x00, pgcount * HV_HYP_PAGE_SIZE);
> +			memset(mem, 0x00, alloc_size);
>  		}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260721201148.1441143-1-kameroncarr@linux.microsoft.com?part=4

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms
  2026-07-21 20:11 ` [PATCH v3 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms Kameron Carr
@ 2026-07-21 20:24   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-07-21 20:24 UTC (permalink / raw)
  To: Kameron Carr; +Cc: linux-hyperv

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Missing compiler memory barrier causes dead-store elimination and constant-folding of the RSI host call buffer.
--

--- Patch [2]: [PATCH v3 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms ---
commit 5f8398cb1bc3327a58d70463ef37d994ffacca02
Author: Kameron Carr <kameroncarr@linux.microsoft.com>

firmware: smccc: Detect hypervisor via RSI host call in CCA Realms

This commit modifies arm_smccc_hypervisor_has_uuid() to use rsi_host_call()
when operating in a Realm. It introduces arm_smccc_realm_get_hypervisor_uuid()
which uses a spinlock-protected file-static buffer to make the call.

> diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
> index bdee057db2fd3..a876b7aa2dc99 100644
> --- a/drivers/firmware/smccc/smccc.c
> +++ b/drivers/firmware/smccc/smccc.c
[ ... ]
> @@ -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 void 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) {
> +		res->a0 = SMCCC_RET_NOT_SUPPORTED;
> +		return;
> +	}
> +
> +	res->a0 = uuid_hc.gprs[0];

[Severity: High]
Does this code need a compiler memory barrier before reading back the results?

Because __pa_symbol() uses RELOC_HIDE() to explicitly hide the pointer's
provenance from the compiler's alias analysis, the compiler may not realize
that rsi_host_call() modifies uuid_hc.

Without a barrier(), could the compiler constant-fold the reads to their
statically-known previous values? If so, this could result in res->a0 being
optimized to ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID instead of the value
returned by the hypervisor, and potentially allow the stores during
initialization to be dead-store eliminated.

> +	res->a1 = uuid_hc.gprs[1];
> +	res->a2 = uuid_hc.gprs[2];
> +	res->a3 = uuid_hc.gprs[3];
> +}
> +#endif

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260721201148.1441143-1-kameroncarr@linux.microsoft.com?part=2

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for CCA Realms
  2026-07-21 20:11 ` [PATCH v3 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for " Kameron Carr
@ 2026-07-21 20:25   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-07-21 20:25 UTC (permalink / raw)
  To: Kameron Carr; +Cc: linux-hyperv

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] kcalloc does not guarantee the 256-byte alignment required by the RSI host call structure, leading to RSI hypercall failures and boot crashes.
- [Low] Unnecessary complex error handling and cleanup logic for an early boot memory allocation failure.
--

--- Patch [3]: [PATCH v3 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for CCA Realms ---
commit d6de874ec14c2f54fe70b4639d2b20bb51fd11c9
Author: Kameron Carr <kameroncarr@linux.microsoft.com>

arm64: hyperv: Add per-CPU RSI host call infrastructure for CCA Realms

This patch introduces a per-CPU array of rsi_host_call structures to
support Hyper-V hypercalls in Arm CCA Realm guests. The array is
allocated dynamically during hyperv_init() so that non-Realm guests pay
no memory overhead.

> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> index 4fdc26ade1d74..d9010e64ddd7c 100644
> --- a/arch/arm64/hyperv/mshyperv.c
> +++ b/arch/arm64/hyperv/mshyperv.c
[ ... ]
> @@ -85,6 +90,20 @@ static int __init hyperv_init(void)
>  	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
>  		return 0;
>  
> +	/*
> +	 * The RSI host-call buffers are only ever used when
> +	 * is_realm_world() is true. Skip the allocation on non-Realm
> +	 * guests. A single contiguous array of nr_cpu_ids entries is
> +	 * allocated; each CPU indexes into it by its processor ID.
> +	 */
> +	if (is_realm_world()) {
> +		hv_hostcall_array = kcalloc(nr_cpu_ids,
> +					    sizeof(struct rsi_host_call),
> +					    GFP_KERNEL);

[Severity: Critical]
Does using kcalloc() violate the __aligned(256) constraint on struct
rsi_host_call?

If slab debugging (e.g., redzoning) or KASAN is enabled, the allocator
offsets the returned pointer, breaking natural power-of-two alignment.

When the unaligned IPA is passed to the RMM via SMC, it gets rejected,
causing the guest to trigger a BUG_ON() inside hv_set_vpreg() during early
boot.

Would it be safer to use alloc_percpu() here to guarantee the required
alignment natively?

> +		if (!hv_hostcall_array)
> +			return -ENOMEM;

[Severity: Low]
This isn't a bug, but since hyperv_init() runs early in the boot process, is
it necessary to handle this memory allocation failure gracefully?

At this stage, physical memory should be available, and an allocation failure
typically means the system cannot boot anyway. It seems the explicit error
handling and cleanup logic add unnecessary complexity.

> +	}
> +
>  	/* Setup the guest ID */
>  	guest_id = hv_generate_guest_id(LINUX_VERSION_CODE);
>  	hv_set_vpreg(HV_REGISTER_GUEST_OS_ID, guest_id);
[ ... ]
> @@ -106,13 +125,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);
>  	if (ret < 0) {
>  		hv_common_free();
> -		return ret;
> +		goto free_hostcall_mem;
>  	}
>  
>  	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
> @@ -125,6 +144,11 @@ static int __init hyperv_init(void)
>  
>  	hyperv_initialized = true;
>  	return 0;
> +
> +free_hostcall_mem:
> +	kfree(hv_hostcall_array);
> +	hv_hostcall_array = NULL;
> +	return ret;

[Severity: Low]
This isn't a bug, but following up on the previous question, could we avoid
adding this entire cleanup block since this is early boot code?

>  }
>  
>  early_initcall(hyperv_init);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260721201148.1441143-1-kameroncarr@linux.microsoft.com?part=3

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 5/6] arm64: hyperv: Route hypercalls through RSI host call in CCA Realms
  2026-07-21 20:11 ` [PATCH v3 5/6] arm64: hyperv: Route hypercalls through RSI host call in " Kameron Carr
@ 2026-07-21 20:27   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-07-21 20:27 UTC (permalink / raw)
  To: Kameron Carr; +Cc: linux-hyperv

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] The globally allocated `hv_hostcall_array` is used for RSI host calls, but it is not guaranteed to be 256-byte aligned, which is strictly required by the RMM.
- [High] Using a single shared per-CPU buffer for hypercalls without masking NMIs/FIQs destroys re-entrancy, risking data corruption.
- [High] Hypercalls passing memory buffers will fail because the guest passes Protected IPAs to the host instead of Shared IPAs.
--

--- Patch [5]: [PATCH v3 5/6] arm64: hyperv: Route hypercalls through RSI host call in CCA Realms ---
commit a89ea311002c08edfbe0b6f9d1e3ca3c6d94b198
Author: Kameron Carr <kameroncarr@linux.microsoft.com>

arm64: hyperv: Route hypercalls through RSI host call in CCA Realms

This patch modifies the hypercall wrapper functions to check for
is_realm_world(). When running inside a Realm, it routes the hypercalls
through the RSI interface using a per-CPU rsi_host_call structure.

> 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

[ ... ]

> +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()];

[Severity: High]
Since local_irq_save() doesn't mask FIQs or pseudo-NMIs on ARM64, is this 
shared per-CPU buffer safe from re-entrancy?

If a pseudo-NMI like a perf interrupt or hardware watchdog interrupts an 
ongoing hypercall and issues a hypercall itself (e.g., hyperv_report_panic 
calling hv_set_vpreg), wouldn't it overwrite this same hostcall buffer and 
corrupt the state?

> +	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)

[Severity: High]
Does the allocation of hv_hostcall_array guarantee the 256-byte alignment 
required by the RMM ABI?

If it is allocated using kcalloc() during init, that only guarantees 
alignment up to ARCH_KMALLOC_MINALIGN. When slab debugging like SLUB_DEBUG 
redzoning is enabled, the objects can be shifted by redzone padding, 
completely breaking the 256-byte alignment and causing the RMM to reject the 
call.

> +		ret = hostcall->gprs[0];
> +	else
> +		ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
> +
> +	local_irq_restore(flags);
> +	return ret;
> +}

[ ... ]

> @@ -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);

[Severity: High]
Will the Hyper-V host be able to access these input and output buffers?

In a CCA Realm, the physical address space is divided by the prot_ns_shared 
bit, and virt_to_phys() returns a Protected IPA without this bit set.

If the host requires access to these buffers, does this need to pass a 
Shared IPA instead of the base Protected IPA?

> +
> +	arm_smccc_1_1_hvc(HV_FUNC_ID, control, input_address,
> +			  output_address, &res);
>  	return res.a0;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260721201148.1441143-1-kameroncarr@linux.microsoft.com?part=5

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-07-21 20:27 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-21 20:11 [PATCH v3 0/6] arm64: hyperv: Add Realm support for Hyper-V Kameron Carr
2026-07-21 20:11 ` [PATCH v3 1/6] arm64: rsi: Add RSI host call structure and helper function Kameron Carr
2026-07-21 20:22   ` sashiko-bot
2026-07-21 20:11 ` [PATCH v3 2/6] firmware: smccc: Detect hypervisor via RSI host call in CCA Realms Kameron Carr
2026-07-21 20:24   ` sashiko-bot
2026-07-21 20:11 ` [PATCH v3 3/6] arm64: hyperv: Add per-CPU RSI host call infrastructure for " Kameron Carr
2026-07-21 20:25   ` sashiko-bot
2026-07-21 20:11 ` [PATCH v3 4/6] Drivers: hv: Mark shared memory as decrypted " Kameron Carr
2026-07-21 20:24   ` sashiko-bot
2026-07-21 20:11 ` [PATCH v3 5/6] arm64: hyperv: Route hypercalls through RSI host call in " Kameron Carr
2026-07-21 20:27   ` sashiko-bot
2026-07-21 20:11 ` [PATCH v3 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