Skip to content

Commit 9b7c3dd

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/idregs-6.12 into kvmarm/fixes
* kvm-arm64/idregs-6.12: : . : Make some fields of ID_AA64DFR0_EL1 and ID_AA64PFR1_EL1 : writable from userspace, so that a VMM can influence the : set of guest-visible features. : : - for ID_AA64DFR0_EL1: DoubleLock, WRPs, PMUVer and DebugVer : are writable (courtesy of Shameer Kolothum) : : - for ID_AA64PFR1_EL1: BT, SSBS, CVS2_frac are writable : (courtesy of Shaoqin Huang) : . KVM: selftests: aarch64: Add writable test for ID_AA64PFR1_EL1 KVM: arm64: Allow userspace to change ID_AA64PFR1_EL1 KVM: arm64: Use kvm_has_feat() to check if FEAT_SSBS is advertised to the guest KVM: arm64: Disable fields that KVM doesn't know how to handle in ID_AA64PFR1_EL1 KVM: arm64: Make the exposed feature bits in AA64DFR0_EL1 writable from userspace Signed-off-by: Marc Zyngier <[email protected]>
2 parents a1d402a + dc9b5d7 commit 9b7c3dd

File tree

3 files changed

+55
-11
lines changed

3 files changed

+55
-11
lines changed

arch/arm64/kvm/hypercalls.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
317317
* to the guest, and hide SSBS so that the
318318
* guest stays protected.
319319
*/
320-
if (cpus_have_final_cap(ARM64_SSBS))
320+
if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SSBS, IMP))
321321
break;
322322
fallthrough;
323323
case SPECTRE_UNAFFECTED:
@@ -428,7 +428,7 @@ int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
428428
* Convert the workaround level into an easy-to-compare number, where higher
429429
* values mean better protection.
430430
*/
431-
static int get_kernel_wa_level(u64 regid)
431+
static int get_kernel_wa_level(struct kvm_vcpu *vcpu, u64 regid)
432432
{
433433
switch (regid) {
434434
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
@@ -449,7 +449,7 @@ static int get_kernel_wa_level(u64 regid)
449449
* don't have any FW mitigation if SSBS is there at
450450
* all times.
451451
*/
452-
if (cpus_have_final_cap(ARM64_SSBS))
452+
if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SSBS, IMP))
453453
return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
454454
fallthrough;
455455
case SPECTRE_UNAFFECTED:
@@ -486,7 +486,7 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
486486
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
487487
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
488488
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
489-
val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
489+
val = get_kernel_wa_level(vcpu, reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
490490
break;
491491
case KVM_REG_ARM_STD_BMAP:
492492
val = READ_ONCE(smccc_feat->std_bmap);
@@ -588,7 +588,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
588588
if (val & ~KVM_REG_FEATURE_LEVEL_MASK)
589589
return -EINVAL;
590590

591-
if (get_kernel_wa_level(reg->id) < val)
591+
if (get_kernel_wa_level(vcpu, reg->id) < val)
592592
return -EINVAL;
593593

594594
return 0;
@@ -624,7 +624,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
624624
* We can deal with NOT_AVAIL on NOT_REQUIRED, but not the
625625
* other way around.
626626
*/
627-
if (get_kernel_wa_level(reg->id) < wa_level)
627+
if (get_kernel_wa_level(vcpu, reg->id) < wa_level)
628628
return -EINVAL;
629629

630630
return 0;

arch/arm64/kvm/sys_regs.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,6 +1527,14 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
15271527
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE);
15281528

15291529
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME);
1530+
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_RNDR_trap);
1531+
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_NMI);
1532+
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac);
1533+
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_GCS);
1534+
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_THE);
1535+
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTEX);
1536+
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_DF2);
1537+
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_PFAR);
15301538
break;
15311539
case SYS_ID_AA64PFR2_EL1:
15321540
/* We only expose FPMR */
@@ -2376,7 +2384,19 @@ static const struct sys_reg_desc sys_reg_descs[] = {
23762384
ID_AA64PFR0_EL1_RAS |
23772385
ID_AA64PFR0_EL1_AdvSIMD |
23782386
ID_AA64PFR0_EL1_FP), },
2379-
ID_SANITISED(ID_AA64PFR1_EL1),
2387+
ID_WRITABLE(ID_AA64PFR1_EL1, ~(ID_AA64PFR1_EL1_PFAR |
2388+
ID_AA64PFR1_EL1_DF2 |
2389+
ID_AA64PFR1_EL1_MTEX |
2390+
ID_AA64PFR1_EL1_THE |
2391+
ID_AA64PFR1_EL1_GCS |
2392+
ID_AA64PFR1_EL1_MTE_frac |
2393+
ID_AA64PFR1_EL1_NMI |
2394+
ID_AA64PFR1_EL1_RNDR_trap |
2395+
ID_AA64PFR1_EL1_SME |
2396+
ID_AA64PFR1_EL1_RES0 |
2397+
ID_AA64PFR1_EL1_MPAM_frac |
2398+
ID_AA64PFR1_EL1_RAS_frac |
2399+
ID_AA64PFR1_EL1_MTE)),
23802400
ID_WRITABLE(ID_AA64PFR2_EL1, ID_AA64PFR2_EL1_FPMR),
23812401
ID_UNALLOCATED(4,3),
23822402
ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0),
@@ -2390,7 +2410,21 @@ static const struct sys_reg_desc sys_reg_descs[] = {
23902410
.get_user = get_id_reg,
23912411
.set_user = set_id_aa64dfr0_el1,
23922412
.reset = read_sanitised_id_aa64dfr0_el1,
2393-
.val = ID_AA64DFR0_EL1_PMUVer_MASK |
2413+
/*
2414+
* Prior to FEAT_Debugv8.9, the architecture defines context-aware
2415+
* breakpoints (CTX_CMPs) as the highest numbered breakpoints (BRPs).
2416+
* KVM does not trap + emulate the breakpoint registers, and as such
2417+
* cannot support a layout that misaligns with the underlying hardware.
2418+
* While it may be possible to describe a subset that aligns with
2419+
* hardware, just prevent changes to BRPs and CTX_CMPs altogether for
2420+
* simplicity.
2421+
*
2422+
* See DDI0487K.a, section D2.8.3 Breakpoint types and linking
2423+
* of breakpoints for more details.
2424+
*/
2425+
.val = ID_AA64DFR0_EL1_DoubleLock_MASK |
2426+
ID_AA64DFR0_EL1_WRPs_MASK |
2427+
ID_AA64DFR0_EL1_PMUVer_MASK |
23942428
ID_AA64DFR0_EL1_DebugVer_MASK, },
23952429
ID_SANITISED(ID_AA64DFR1_EL1),
23962430
ID_UNALLOCATED(5,2),

tools/testing/selftests/kvm/aarch64/set_id_regs.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ struct test_feature_reg {
6868
}
6969

7070
static const struct reg_ftr_bits ftr_id_aa64dfr0_el1[] = {
71+
S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64DFR0_EL1, DoubleLock, 0),
72+
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64DFR0_EL1, WRPs, 0),
7173
S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64DFR0_EL1, PMUVer, 0),
7274
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64DFR0_EL1, DebugVer, ID_AA64DFR0_EL1_DebugVer_IMP),
7375
REG_FTR_END,
@@ -134,6 +136,13 @@ static const struct reg_ftr_bits ftr_id_aa64pfr0_el1[] = {
134136
REG_FTR_END,
135137
};
136138

139+
static const struct reg_ftr_bits ftr_id_aa64pfr1_el1[] = {
140+
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, CSV2_frac, 0),
141+
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, SSBS, ID_AA64PFR1_EL1_SSBS_NI),
142+
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, BT, 0),
143+
REG_FTR_END,
144+
};
145+
137146
static const struct reg_ftr_bits ftr_id_aa64mmfr0_el1[] = {
138147
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, ECV, 0),
139148
REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64MMFR0_EL1, EXS, 0),
@@ -200,6 +209,7 @@ static struct test_feature_reg test_regs[] = {
200209
TEST_REG(SYS_ID_AA64ISAR1_EL1, ftr_id_aa64isar1_el1),
201210
TEST_REG(SYS_ID_AA64ISAR2_EL1, ftr_id_aa64isar2_el1),
202211
TEST_REG(SYS_ID_AA64PFR0_EL1, ftr_id_aa64pfr0_el1),
212+
TEST_REG(SYS_ID_AA64PFR1_EL1, ftr_id_aa64pfr1_el1),
203213
TEST_REG(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0_el1),
204214
TEST_REG(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1_el1),
205215
TEST_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2_el1),
@@ -569,9 +579,9 @@ int main(void)
569579
test_cnt = ARRAY_SIZE(ftr_id_aa64dfr0_el1) + ARRAY_SIZE(ftr_id_dfr0_el1) +
570580
ARRAY_SIZE(ftr_id_aa64isar0_el1) + ARRAY_SIZE(ftr_id_aa64isar1_el1) +
571581
ARRAY_SIZE(ftr_id_aa64isar2_el1) + ARRAY_SIZE(ftr_id_aa64pfr0_el1) +
572-
ARRAY_SIZE(ftr_id_aa64mmfr0_el1) + ARRAY_SIZE(ftr_id_aa64mmfr1_el1) +
573-
ARRAY_SIZE(ftr_id_aa64mmfr2_el1) + ARRAY_SIZE(ftr_id_aa64zfr0_el1) -
574-
ARRAY_SIZE(test_regs) + 2;
582+
ARRAY_SIZE(ftr_id_aa64pfr1_el1) + ARRAY_SIZE(ftr_id_aa64mmfr0_el1) +
583+
ARRAY_SIZE(ftr_id_aa64mmfr1_el1) + ARRAY_SIZE(ftr_id_aa64mmfr2_el1) +
584+
ARRAY_SIZE(ftr_id_aa64zfr0_el1) - ARRAY_SIZE(test_regs) + 2;
575585

576586
ksft_set_plan(test_cnt);
577587

0 commit comments

Comments
 (0)