arm64: Add ARM64_HAS_NESTED_VIRT cpufeature
authorJintack Lim <jintack.lim@linaro.org>
Thu, 9 Feb 2023 17:58:03 +0000 (17:58 +0000)
committerOliver Upton <oliver.upton@linux.dev>
Sat, 11 Feb 2023 09:16:11 +0000 (09:16 +0000)
Add a new ARM64_HAS_NESTED_VIRT feature to indicate that the
CPU has the ARMv8.3 nested virtualization capability, together
with the 'kvm-arm.mode=nested' command line option.

This will be used to support nested virtualization in KVM.

Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Jintack Lim <jintack.lim@linaro.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
[maz: moved the command-line option to kvm-arm.mode]
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230209175820.1939006-2-maz@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Documentation/admin-guide/kernel-parameters.txt
arch/arm64/include/asm/kvm_host.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kvm/arm.c
arch/arm64/tools/cpucaps

index 6cfa6e3..b7b0704 100644 (file)
                        protected: nVHE-based mode with support for guests whose
                                   state is kept private from the host.
 
+                       nested: VHE-based mode with support for nested
+                               virtualization. Requires at least ARMv8.3
+                               hardware.
+
                        Defaults to VHE/nVHE based on hardware support. Setting
                        mode to "protected" will disable kexec and hibernation
-                       for the host.
+                       for the host. "nested" is experimental and should be
+                       used with extreme caution.
 
        kvm-arm.vgic_v3_group0_trap=
                        [KVM,ARM] Trap guest accesses to GICv3 group-0
index 35a159d..8919e97 100644 (file)
 enum kvm_mode {
        KVM_MODE_DEFAULT,
        KVM_MODE_PROTECTED,
+       KVM_MODE_NV,
        KVM_MODE_NONE,
 };
+#ifdef CONFIG_KVM
 enum kvm_mode kvm_get_mode(void);
+#else
+static inline enum kvm_mode kvm_get_mode(void) { return KVM_MODE_NONE; };
+#endif
 
 DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
index a77315b..3fc14ee 100644 (file)
@@ -1956,6 +1956,20 @@ static void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
                write_sysreg(read_sysreg(tpidr_el1), tpidr_el2);
 }
 
+static bool has_nested_virt_support(const struct arm64_cpu_capabilities *cap,
+                                   int scope)
+{
+       if (kvm_get_mode() != KVM_MODE_NV)
+               return false;
+
+       if (!has_cpuid_feature(cap, scope)) {
+               pr_warn("unavailable: %s\n", cap->desc);
+               return false;
+       }
+
+       return true;
+}
+
 #ifdef CONFIG_ARM64_PAN
 static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
 {
@@ -2216,6 +2230,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
                .cpu_enable = cpu_copy_el2regs,
        },
        {
+               .desc = "Nested Virtualization Support",
+               .capability = ARM64_HAS_NESTED_VIRT,
+               .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+               .matches = has_nested_virt_support,
+               .sys_reg = SYS_ID_AA64MMFR2_EL1,
+               .sign = FTR_UNSIGNED,
+               .field_pos = ID_AA64MMFR2_EL1_NV_SHIFT,
+               .field_width = 4,
+               .min_field_value = ID_AA64MMFR2_EL1_NV_IMP,
+       },
+       {
                .capability = ARM64_HAS_32BIT_EL0_DO_NOT_USE,
                .type = ARM64_CPUCAP_SYSTEM_FEATURE,
                .matches = has_32bit_el0,
index 9c5573b..3fd8f37 100644 (file)
@@ -2310,6 +2310,11 @@ static int __init early_kvm_mode_cfg(char *arg)
                return 0;
        }
 
+       if (strcmp(arg, "nested") == 0 && !WARN_ON(!is_kernel_in_hyp_mode())) {
+               kvm_mode = KVM_MODE_NV;
+               return 0;
+       }
+
        return -EINVAL;
 }
 early_param("kvm-arm.mode", early_kvm_mode_cfg);
index dfeb2c5..1af77a3 100644 (file)
@@ -31,6 +31,7 @@ HAS_GENERIC_AUTH_IMP_DEF
 HAS_IRQ_PRIO_MASKING
 HAS_LDAPR
 HAS_LSE_ATOMICS
+HAS_NESTED_VIRT
 HAS_NO_FPSIMD
 HAS_NO_HW_PREFETCH
 HAS_PAN