Commit d98db29f authored by James Morse's avatar James Morse Committed by Wupeng Ma
Browse files

KVM: arm64: Detect and enable PBHA for stage2

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I7ZC0H

Reference: https://lore.kernel.org/all/20211015161416.2196-1-james.morse@arm.com/t/#u



--------------------------------

Page Based Hardware Attributes (PBHA, aka HPDS2) allow a page table entry
to specify up to four bits that can be used by the hardware for some
implementation defined purpose.

This is a problem for KVM guests as the host may swap guest memory using
a different combination of PBHA bits than the guest used when writing the
data. Without knowing what the PBHA bits do, its not possible to know if
this will corrupt the guest's data.

The arm-arm doesn't describe how the PBHA bits are combined between stage1
and stage2. Arm's Cortex CPUs appear to all do the same thing: stage2 wins.

Enable PBHA for stage2, where the configured value is zero. This has no
effect if PBHA isn't in use. On Cortex cores that have the 'stage2 wins'
behaviour, this disables whatever the guest may be doing. For any other
core with a sensible combination policy, it should be harmless.

Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarMa Wupeng <mawupeng1@huawei.com>
parent eee0ebf4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@
#define ARM64_HAS_WFXT				68
#define ARM64_WORKAROUND_HISILICON_ERRATUM_162100125	69
#define ARM64_HAS_LDAPR                         70
#define ARM64_HAS_PBHA				71

#define ARM64_NCAPS				80

+1 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@
#define VTCR_EL2_VS_SHIFT	19
#define VTCR_EL2_VS_8BIT	(0 << VTCR_EL2_VS_SHIFT)
#define VTCR_EL2_VS_16BIT	(1 << VTCR_EL2_VS_SHIFT)
#define VTCR_EL2_PBHA_MASK	GENMASK(28, 25)

#define VTCR_EL2_T0SZ(x)	TCR_T0SZ(x)

+9 −0
Original line number Diff line number Diff line
@@ -35,6 +35,10 @@ struct kvm_pgtable {
 * @KVM_PGTABLE_PROT_W:		Write permission.
 * @KVM_PGTABLE_PROT_R:		Read permission.
 * @KVM_PGTABLE_PROT_DEVICE:	Device attributes.
 * @KVM_PGTABLE_PROT_PBHA0:	Page-Based Hardware Attribute 0.
 * @KVM_PGTABLE_PROT_PBHA1:	Page-Based Hardware Attribute 1.
 * @KVM_PGTABLE_PROT_PBHA2:	Page-Based Hardware Attribute 2.
 * @KVM_PGTABLE_PROT_PBHA3:	Page-Based Hardware Attribute 3.
 */
enum kvm_pgtable_prot {
	KVM_PGTABLE_PROT_X			= BIT(0),
@@ -42,6 +46,11 @@ enum kvm_pgtable_prot {
	KVM_PGTABLE_PROT_R			= BIT(2),

	KVM_PGTABLE_PROT_DEVICE			= BIT(3),

	KVM_PGTABLE_PROT_PBHA0			= BIT(59),
	KVM_PGTABLE_PROT_PBHA1			= BIT(60),
	KVM_PGTABLE_PROT_PBHA2			= BIT(61),
	KVM_PGTABLE_PROT_PBHA3			= BIT(62),
};

#define PAGE_HYP		(KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W)
+9 −0
Original line number Diff line number Diff line
@@ -2295,6 +2295,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
		.matches = has_cpuid_feature,
		.min_field_value = 1,
	},
	{
		.capability = ARM64_HAS_PBHA,
		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
		.sys_reg = SYS_ID_AA64MMFR1_EL1,
		.sign = FTR_UNSIGNED,
		.field_pos = ID_AA64MMFR1_HPD_SHIFT,
		.matches = has_cpuid_feature,
		.min_field_value = 2,
	},
	{},
};

+9 −0
Original line number Diff line number Diff line
@@ -474,6 +474,15 @@ int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type)
	 */
	vtcr |= VTCR_EL2_HA;

	/*
	 * Enable PBHA for stage2 on systems that support it. The configured
	 * value will always be 0, which is defined as the safe default
	 * setting. On Cortex cores, enabling PBHA for stage2 effectively
	 * disables it for stage1.
	 */
	if (cpus_have_final_cap(ARM64_HAS_PBHA))
		vtcr |= FIELD_PREP(VTCR_EL2_PBHA_MASK, 0xf);

	/* Set the vmid bits */
	vtcr |= (kvm_get_vmid_bits() == 16) ?
		VTCR_EL2_VS_16BIT :