Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: Add ARM64_HAS_LPA2 CPU capability

Expose FEAT_LPA2 as a capability so that we can take advantage of
alternatives patching in the hypervisor.

Although FEAT_LPA2 presence is advertised separately for stage1 and
stage2, the expectation is that in practice both stages will either
support or not support it. Therefore, we combine both into a single
capability, allowing us to simplify the implementation. KVM requires
support in both stages in order to use LPA2 since the same library is
used for hyp stage 1 and guest stage 2 pgtables.

Reviewed-by: Oliver Upton <oliver.upton@linux.dev>
Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20231127111737.1897081-6-ryan.roberts@arm.com

authored by

Ryan Roberts and committed by
Marc Zyngier
b1366d21 e477c8c4

+45
+5
arch/arm64/include/asm/cpufeature.h
··· 819 819 return alternative_has_cap_unlikely(ARM64_HAS_TLB_RANGE); 820 820 } 821 821 822 + static inline bool system_supports_lpa2(void) 823 + { 824 + return cpus_have_final_cap(ARM64_HAS_LPA2); 825 + } 826 + 822 827 int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt); 823 828 bool try_emulate_mrs(struct pt_regs *regs, u32 isn); 824 829
+39
arch/arm64/kernel/cpufeature.c
··· 1768 1768 return !meltdown_safe; 1769 1769 } 1770 1770 1771 + #if defined(ID_AA64MMFR0_EL1_TGRAN_LPA2) && defined(ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2) 1772 + static bool has_lpa2_at_stage1(u64 mmfr0) 1773 + { 1774 + unsigned int tgran; 1775 + 1776 + tgran = cpuid_feature_extract_unsigned_field(mmfr0, 1777 + ID_AA64MMFR0_EL1_TGRAN_SHIFT); 1778 + return tgran == ID_AA64MMFR0_EL1_TGRAN_LPA2; 1779 + } 1780 + 1781 + static bool has_lpa2_at_stage2(u64 mmfr0) 1782 + { 1783 + unsigned int tgran; 1784 + 1785 + tgran = cpuid_feature_extract_unsigned_field(mmfr0, 1786 + ID_AA64MMFR0_EL1_TGRAN_2_SHIFT); 1787 + return tgran == ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2; 1788 + } 1789 + 1790 + static bool has_lpa2(const struct arm64_cpu_capabilities *entry, int scope) 1791 + { 1792 + u64 mmfr0; 1793 + 1794 + mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1); 1795 + return has_lpa2_at_stage1(mmfr0) && has_lpa2_at_stage2(mmfr0); 1796 + } 1797 + #else 1798 + static bool has_lpa2(const struct arm64_cpu_capabilities *entry, int scope) 1799 + { 1800 + return false; 1801 + } 1802 + #endif 1803 + 1771 1804 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 1772 1805 #define KPTI_NG_TEMP_VA (-(1UL << PMD_SHIFT)) 1773 1806 ··· 2763 2730 .type = ARM64_CPUCAP_SYSTEM_FEATURE, 2764 2731 .matches = has_cpuid_feature, 2765 2732 ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP) 2733 + }, 2734 + { 2735 + .desc = "52-bit Virtual Addressing for KVM (LPA2)", 2736 + .capability = ARM64_HAS_LPA2, 2737 + .type = ARM64_CPUCAP_SYSTEM_FEATURE, 2738 + .matches = has_lpa2, 2766 2739 }, 2767 2740 {}, 2768 2741 };
+1
arch/arm64/tools/cpucaps
··· 37 37 HAS_GIC_PRIO_RELAXED_SYNC 38 38 HAS_HCX 39 39 HAS_LDAPR 40 + HAS_LPA2 40 41 HAS_LSE_ATOMICS 41 42 HAS_MOPS 42 43 HAS_NESTED_VIRT