mirror of
https://github.com/torvalds/linux.git
synced 2024-12-03 17:41:22 +00:00
arm64: cpufeature: Add helper to test for CPU feature overrides
Add some helpers to extract and apply feature overrides to the bare idreg values. This involves inspecting the value and mask of the specific field that we are interested in, given that an override value/mask pair might be invalid for one field but valid for another. Then, wire up the new helper for the hVHE test - note that we can drop the sysreg test here, as the override will be invalid when trying to enable hVHE on non-VHE capable hardware. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Link: https://lore.kernel.org/r/20240214122845.2033971-55-ardb+git@google.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
parent
8a6e40e1f6
commit
35876f35f4
@ -915,6 +915,45 @@ extern struct arm64_ftr_override id_aa64isar2_override;
|
||||
|
||||
extern struct arm64_ftr_override arm64_sw_feature_override;
|
||||
|
||||
static inline
|
||||
u64 arm64_apply_feature_override(u64 val, int feat, int width,
|
||||
const struct arm64_ftr_override *override)
|
||||
{
|
||||
u64 oval = override->val;
|
||||
|
||||
/*
|
||||
* When it encounters an invalid override (e.g., an override that
|
||||
* cannot be honoured due to a missing CPU feature), the early idreg
|
||||
* override code will set the mask to 0x0 and the value to non-zero for
|
||||
* the field in question. In order to determine whether the override is
|
||||
* valid or not for the field we are interested in, we first need to
|
||||
* disregard bits belonging to other fields.
|
||||
*/
|
||||
oval &= GENMASK_ULL(feat + width - 1, feat);
|
||||
|
||||
/*
|
||||
* The override is valid if all value bits are accounted for in the
|
||||
* mask. If so, replace the masked bits with the override value.
|
||||
*/
|
||||
if (oval == (oval & override->mask)) {
|
||||
val &= ~override->mask;
|
||||
val |= oval;
|
||||
}
|
||||
|
||||
/* Extract the field from the updated value */
|
||||
return cpuid_feature_extract_unsigned_field(val, feat);
|
||||
}
|
||||
|
||||
static inline bool arm64_test_sw_feature_override(int feat)
|
||||
{
|
||||
/*
|
||||
* Software features are pseudo CPU features that have no underlying
|
||||
* CPUID system register value to apply the override to.
|
||||
*/
|
||||
return arm64_apply_feature_override(0, feat, 4,
|
||||
&arm64_sw_feature_override);
|
||||
}
|
||||
|
||||
u32 get_kvm_ipa_limit(void);
|
||||
void dump_cpu_features(void);
|
||||
|
||||
|
@ -2042,14 +2042,7 @@ static bool has_nested_virt_support(const struct arm64_cpu_capabilities *cap,
|
||||
static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
|
||||
int __unused)
|
||||
{
|
||||
u64 val;
|
||||
|
||||
val = read_sysreg(id_aa64mmfr1_el1);
|
||||
if (!cpuid_feature_extract_unsigned_field(val, ID_AA64MMFR1_EL1_VH_SHIFT))
|
||||
return false;
|
||||
|
||||
val = arm64_sw_feature_override.val & arm64_sw_feature_override.mask;
|
||||
return cpuid_feature_extract_unsigned_field(val, ARM64_SW_FEATURE_OVERRIDE_HVHE);
|
||||
return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_PAN
|
||||
|
Loading…
Reference in New Issue
Block a user