From e2dc41c48f42bc10f517fd4348e857c3292e2cda Mon Sep 17 00:00:00 2001 From: Ian May Date: Wed, 17 Dec 2025 18:32:05 +0000 Subject: [PATCH] target/arm: Use shared helper for KVM_CAP_ARM_RME detection The query-cca-capabilities QMP command was using the hardcoded KVM_CAP_ARM_RME value (244), but on kernel 6.16 the capability number is 243. This caused the command to incorrectly report 'RME is not enabled in KVM' even when RME was available. Extract the kernel version detection logic from rme_guest_init() into a shared kvm_arm_rme_get_cap() helper function and use it in both places to ensure consistent behavior. Fixes: b5ae241e19b ('target/arm: Handle KVM_CAP_ARM_RME ABI change') Signed-off-by: Ian May --- target/arm/aarch64-qmp-cmds.c | 6 ++++- target/arm/kvm-rme.c | 45 +++++++++++++++++++++++++---------- target/arm/kvm_arm.h | 9 +++++++ 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/target/arm/aarch64-qmp-cmds.c b/target/arm/aarch64-qmp-cmds.c index 10e35e163d..241a6662f1 100644 --- a/target/arm/aarch64-qmp-cmds.c +++ b/target/arm/aarch64-qmp-cmds.c @@ -36,7 +36,11 @@ CcaCapability *qmp_query_cca_capabilities(Error **errp) return NULL; } - if (!kvm_check_extension(kvm_state, KVM_CAP_ARM_RME)) { + /* + * Use the runtime-detected KVM_CAP_ARM_RME value to handle + * the ABI change between kernel versions (243 on 6.16, 244 on later). + */ + if (!kvm_check_extension(kvm_state, kvm_arm_rme_get_cap())) { error_setg(errp, "RME is not enabled in KVM"); return NULL; } diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c index cf4f1ed1d7..5b6de24539 100644 --- a/target/arm/kvm-rme.c +++ b/target/arm/kvm-rme.c @@ -23,6 +23,37 @@ #include "system/runstate.h" #include +/* + * Returns the correct KVM_CAP_ARM_RME capability value for the running kernel. + * This handles the ABI change between kernel versions: + * - Linux 6.16: KVM_CAP_ARM_RME == 243 + * - Linux 6.17+: KVM_CAP_ARM_RME == 244 + */ +unsigned int kvm_arm_rme_get_cap(void) +{ + static unsigned int rme_cap = 0; + static bool detected = false; + + if (!detected) { + struct utsname buf; + int major, minor; + + rme_cap = KVM_CAP_ARM_RME; + + if (uname(&buf) == 0) { + if (sscanf(buf.release, "%d.%d", &major, &minor) == 2) { + /* For Linux kernel v6.16, KVM_CAP_ARM_RME == 243 */ + if ((major == 6) && (minor == 16)) { + rme_cap = 243; + } + } + } + detected = true; + } + + return rme_cap; +} + #define TYPE_RME_GUEST "rme-guest" OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST) @@ -788,9 +819,6 @@ static void rme_guest_class_init(ObjectClass *oc, const void *data) static void rme_guest_init(Object *obj) { - struct utsname buf; - int major, minor; - if (rme_guest) { error_report("a single instance of RmeGuest is supported"); exit(1); @@ -800,16 +828,7 @@ static void rme_guest_init(Object *obj) rme_guest->measurement_algo = RME_GUEST_MEASUREMENT_ALGORITHM_SHA512; rme_guest->mec_specified = false; - rme_guest->rme_capable = KVM_CAP_ARM_RME; - - if (uname(&buf) == 0) { - if (sscanf(buf.release, "%d.%d", &major, &minor) == 2) { - /* For Linux kernel v6.16, KVM_CAP_ARM_RME == 243 */ - if ((major == 6) && (minor == 16)) { - rme_guest->rme_capable = 243; - } - } - } + rme_guest->rme_capable = kvm_arm_rme_get_cap(); } static void rme_guest_finalize(Object *obj) diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 7c737fd35a..1eab906d0a 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -274,6 +274,15 @@ void kvm_arm_enable_mte(Object *cpuobj, Error **errp); void arm_cpu_kvm_set_irq(void *arm_cpu, int irq, int level); +/** + * kvm_arm_rme_get_cap: + * + * Returns the correct KVM_CAP_ARM_RME capability value for the running + * kernel. This handles the ABI change between kernel versions where the + * capability number differs (e.g., 243 on kernel 6.16, 244 on later kernels). + */ +unsigned int kvm_arm_rme_get_cap(void); + /** * kvm_arm_rme_init * @ms: the machine state