Commit 675cabc8 authored by Jintack Lim's avatar Jintack Lim Committed by Oliver Upton
Browse files

arm64: Add ARM64_HAS_NESTED_VIRT cpufeature



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: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Acked-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarJintack Lim <jintack.lim@linaro.org>
Signed-off-by: default avatarAndre Przywara <andre.przywara@arm.com>
Signed-off-by: default avatarChristoffer Dall <christoffer.dall@arm.com>
[maz: moved the command-line option to kvm-arm.mode]
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230209175820.1939006-2-maz@kernel.org


Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parent 5dc4c995
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -2553,9 +2553,14 @@
			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
+5 −0
Original line number Diff line number Diff line
@@ -60,9 +60,14 @@
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);

+25 −0
Original line number Diff line number Diff line
@@ -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)
{
@@ -2215,6 +2229,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
		.matches = runs_at_el2,
		.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,
+5 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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