From da5b69f202331ca38f2905657dca5f00adb01102 Mon Sep 17 00:00:00 2001 From: Ian May Date: Fri, 6 Feb 2026 06:18:15 +0000 Subject: [PATCH] NVIDIA: SAUCE: target/arm: Add sysfs detection for KVM CCA capability Add runtime detection of the KVM CCA capability number by reading from the kernel's sysfs module parameter. This allows QEMU to automatically discover the correct capability number without needing version-specific hardcoded values that may become stale. The ARM CCA host patches underwent a naming change from RME to RMI in v11: - v10 (Linux 6.17): KVM_CAP_ARM_RME, sysfs param kvm_cap_arm_rme - v11 (Linux 6.18+): KVM_CAP_ARM_RMI, sysfs param kvm_cap_arm_rmi Detection order: 1. Try v11 sysfs path (/sys/module/kvm/parameters/kvm_cap_arm_rmi) 2. Try v10 sysfs path (/sys/module/kvm/parameters/kvm_cap_arm_rme) 3. Fall back to uname detection for 6.16 dev kernel (capability == 243) 4. Use compile-time KVM_CAP_ARM_RME as last resort This allows the same QEMU binary to work with linux-nvidia-6.16 (dev), linux-nvidia-6.17 (v10 host patches), and linux-nvidia-6.18+ (v11 host patches). Signed-off-by: Ian May --- target/arm/aarch64-qmp-cmds.c | 5 +-- target/arm/kvm-rme.c | 59 ++++++++++++++++++++++++++++------- target/arm/kvm_arm.h | 13 ++++++-- 3 files changed, 61 insertions(+), 16 deletions(-) diff --git a/target/arm/aarch64-qmp-cmds.c b/target/arm/aarch64-qmp-cmds.c index 241a6662f1..f2b331aa52 100644 --- a/target/arm/aarch64-qmp-cmds.c +++ b/target/arm/aarch64-qmp-cmds.c @@ -37,8 +37,9 @@ CcaCapability *qmp_query_cca_capabilities(Error **errp) } /* - * Use the runtime-detected KVM_CAP_ARM_RME value to handle - * the ABI change between kernel versions (243 on 6.16, 244 on later). + * Use kvm_arm_rme_get_cap() to get the KVM CCA capability value + * from the kernel's sysfs module parameter, handling ABI changes + * between kernel versions gracefully. */ if (!kvm_check_extension(kvm_state, kvm_arm_rme_get_cap())) { error_setg(errp, "RME is not enabled in KVM"); diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c index 5b6de24539..0b98b169b3 100644 --- a/target/arm/kvm-rme.c +++ b/target/arm/kvm-rme.c @@ -24,10 +24,30 @@ #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 + * Sysfs paths for KVM CCA capability detection. + * v11+ host patches (6.18+) use RMI naming, v10 (6.17) uses RME naming. + */ +#define KVM_CAP_ARM_RMI_SYSFS_PATH "/sys/module/kvm/parameters/kvm_cap_arm_rmi" +#define KVM_CAP_ARM_RME_SYSFS_PATH "/sys/module/kvm/parameters/kvm_cap_arm_rme" + +/* + * Returns the correct KVM CCA capability value for the running kernel. + * + * The ARM CCA host patches underwent a naming change from RME to RMI in v11: + * - v10 (Linux 6.17): KVM_CAP_ARM_RME, sysfs param kvm_cap_arm_rme + * - v11 (Linux 6.18+): KVM_CAP_ARM_RMI, sysfs param kvm_cap_arm_rmi + * + * Detection order: + * 1. Try reading from the v11 sysfs module parameter (RMI naming): + * /sys/module/kvm/parameters/kvm_cap_arm_rmi + * + * 2. Try reading from the v10 sysfs module parameter (RME naming): + * /sys/module/kvm/parameters/kvm_cap_arm_rme + * + * 3. Fall back to uname-based detection for Linux 6.16 dev kernel + * (which does not have the sysfs parameter): capability == 243 + * + * 4. Otherwise use the compile-time KVM_CAP_ARM_RME value. */ unsigned int kvm_arm_rme_get_cap(void) { @@ -35,16 +55,33 @@ unsigned int kvm_arm_rme_get_cap(void) static bool detected = false; if (!detected) { - struct utsname buf; - int major, minor; + FILE *f = NULL; + int cap; 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; + /* First try v11 sysfs path (RMI naming, 6.18+ kernels) */ + f = fopen(KVM_CAP_ARM_RMI_SYSFS_PATH, "r"); + if (!f) { + /* Then try v10 sysfs path (RME naming, 6.17 kernels) */ + f = fopen(KVM_CAP_ARM_RME_SYSFS_PATH, "r"); + } + + if (f) { + if (fscanf(f, "%d", &cap) == 1 && cap > 0) { + rme_cap = cap; + } + fclose(f); + } else { + /* Fallback for 6.16 dev kernel (no sysfs parameter) */ + struct utsname buf; + int major, minor; + + if (uname(&buf) == 0) { + if (sscanf(buf.release, "%d.%d", &major, &minor) == 2) { + if (major == 6 && minor == 16) { + rme_cap = 243; + } } } } diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 1eab906d0a..07d1b0cecb 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -277,9 +277,16 @@ 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). + * Returns the correct KVM CCA capability value for the running kernel. + * Supports both v10 (RME naming, 6.17) and v11+ (RMI naming, 6.18+) host patches. + * + * First tries to read from the sysfs module parameters: + * /sys/module/kvm/parameters/kvm_cap_arm_rmi (v11+, 6.18+) + * /sys/module/kvm/parameters/kvm_cap_arm_rme (v10, 6.17) + * + * Falls back to uname-based kernel version detection (6.16=243, 6.17=244, + * 6.18=246) if sysfs is not available, or uses the compile-time + * KVM_CAP_ARM_RME value as a last resort. */ unsigned int kvm_arm_rme_get_cap(void);