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

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 <maz@kernel.org>

+55 -11
+6 -6
arch/arm64/kvm/hypercalls.c
··· 317 317 * to the guest, and hide SSBS so that the 318 318 * guest stays protected. 319 319 */ 320 - if (cpus_have_final_cap(ARM64_SSBS)) 320 + if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SSBS, IMP)) 321 321 break; 322 322 fallthrough; 323 323 case SPECTRE_UNAFFECTED: ··· 428 428 * Convert the workaround level into an easy-to-compare number, where higher 429 429 * values mean better protection. 430 430 */ 431 - static int get_kernel_wa_level(u64 regid) 431 + static int get_kernel_wa_level(struct kvm_vcpu *vcpu, u64 regid) 432 432 { 433 433 switch (regid) { 434 434 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: ··· 449 449 * don't have any FW mitigation if SSBS is there at 450 450 * all times. 451 451 */ 452 - if (cpus_have_final_cap(ARM64_SSBS)) 452 + if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SSBS, IMP)) 453 453 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; 454 454 fallthrough; 455 455 case SPECTRE_UNAFFECTED: ··· 486 486 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: 487 487 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: 488 488 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; 490 490 break; 491 491 case KVM_REG_ARM_STD_BMAP: 492 492 val = READ_ONCE(smccc_feat->std_bmap); ··· 588 588 if (val & ~KVM_REG_FEATURE_LEVEL_MASK) 589 589 return -EINVAL; 590 590 591 - if (get_kernel_wa_level(reg->id) < val) 591 + if (get_kernel_wa_level(vcpu, reg->id) < val) 592 592 return -EINVAL; 593 593 594 594 return 0; ··· 624 624 * We can deal with NOT_AVAIL on NOT_REQUIRED, but not the 625 625 * other way around. 626 626 */ 627 - if (get_kernel_wa_level(reg->id) < wa_level) 627 + if (get_kernel_wa_level(vcpu, reg->id) < wa_level) 628 628 return -EINVAL; 629 629 630 630 return 0;
+36 -2
arch/arm64/kvm/sys_regs.c
··· 1527 1527 val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE); 1528 1528 1529 1529 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); 1530 1538 break; 1531 1539 case SYS_ID_AA64PFR2_EL1: 1532 1540 /* We only expose FPMR */ ··· 2384 2376 ID_AA64PFR0_EL1_RAS | 2385 2377 ID_AA64PFR0_EL1_AdvSIMD | 2386 2378 ID_AA64PFR0_EL1_FP), }, 2387 - ID_SANITISED(ID_AA64PFR1_EL1), 2379 + ID_WRITABLE(ID_AA64PFR1_EL1, ~(ID_AA64PFR1_EL1_PFAR | 2380 + ID_AA64PFR1_EL1_DF2 | 2381 + ID_AA64PFR1_EL1_MTEX | 2382 + ID_AA64PFR1_EL1_THE | 2383 + ID_AA64PFR1_EL1_GCS | 2384 + ID_AA64PFR1_EL1_MTE_frac | 2385 + ID_AA64PFR1_EL1_NMI | 2386 + ID_AA64PFR1_EL1_RNDR_trap | 2387 + ID_AA64PFR1_EL1_SME | 2388 + ID_AA64PFR1_EL1_RES0 | 2389 + ID_AA64PFR1_EL1_MPAM_frac | 2390 + ID_AA64PFR1_EL1_RAS_frac | 2391 + ID_AA64PFR1_EL1_MTE)), 2388 2392 ID_WRITABLE(ID_AA64PFR2_EL1, ID_AA64PFR2_EL1_FPMR), 2389 2393 ID_UNALLOCATED(4,3), 2390 2394 ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0), ··· 2410 2390 .get_user = get_id_reg, 2411 2391 .set_user = set_id_aa64dfr0_el1, 2412 2392 .reset = read_sanitised_id_aa64dfr0_el1, 2413 - .val = ID_AA64DFR0_EL1_PMUVer_MASK | 2393 + /* 2394 + * Prior to FEAT_Debugv8.9, the architecture defines context-aware 2395 + * breakpoints (CTX_CMPs) as the highest numbered breakpoints (BRPs). 2396 + * KVM does not trap + emulate the breakpoint registers, and as such 2397 + * cannot support a layout that misaligns with the underlying hardware. 2398 + * While it may be possible to describe a subset that aligns with 2399 + * hardware, just prevent changes to BRPs and CTX_CMPs altogether for 2400 + * simplicity. 2401 + * 2402 + * See DDI0487K.a, section D2.8.3 Breakpoint types and linking 2403 + * of breakpoints for more details. 2404 + */ 2405 + .val = ID_AA64DFR0_EL1_DoubleLock_MASK | 2406 + ID_AA64DFR0_EL1_WRPs_MASK | 2407 + ID_AA64DFR0_EL1_PMUVer_MASK | 2414 2408 ID_AA64DFR0_EL1_DebugVer_MASK, }, 2415 2409 ID_SANITISED(ID_AA64DFR1_EL1), 2416 2410 ID_UNALLOCATED(5,2),
+13 -3
tools/testing/selftests/kvm/aarch64/set_id_regs.c
··· 68 68 } 69 69 70 70 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), 71 73 S_REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64DFR0_EL1, PMUVer, 0), 72 74 REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64DFR0_EL1, DebugVer, ID_AA64DFR0_EL1_DebugVer_IMP), 73 75 REG_FTR_END, ··· 133 131 REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR0_EL1, EL2, 0), 134 132 REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR0_EL1, EL1, 0), 135 133 REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR0_EL1, EL0, 0), 134 + REG_FTR_END, 135 + }; 136 + 137 + static const struct reg_ftr_bits ftr_id_aa64pfr1_el1[] = { 138 + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, CSV2_frac, 0), 139 + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, SSBS, ID_AA64PFR1_EL1_SSBS_NI), 140 + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, BT, 0), 136 141 REG_FTR_END, 137 142 }; 138 143 ··· 209 200 TEST_REG(SYS_ID_AA64ISAR1_EL1, ftr_id_aa64isar1_el1), 210 201 TEST_REG(SYS_ID_AA64ISAR2_EL1, ftr_id_aa64isar2_el1), 211 202 TEST_REG(SYS_ID_AA64PFR0_EL1, ftr_id_aa64pfr0_el1), 203 + TEST_REG(SYS_ID_AA64PFR1_EL1, ftr_id_aa64pfr1_el1), 212 204 TEST_REG(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0_el1), 213 205 TEST_REG(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1_el1), 214 206 TEST_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2_el1), ··· 579 569 test_cnt = ARRAY_SIZE(ftr_id_aa64dfr0_el1) + ARRAY_SIZE(ftr_id_dfr0_el1) + 580 570 ARRAY_SIZE(ftr_id_aa64isar0_el1) + ARRAY_SIZE(ftr_id_aa64isar1_el1) + 581 571 ARRAY_SIZE(ftr_id_aa64isar2_el1) + ARRAY_SIZE(ftr_id_aa64pfr0_el1) + 582 - ARRAY_SIZE(ftr_id_aa64mmfr0_el1) + ARRAY_SIZE(ftr_id_aa64mmfr1_el1) + 583 - ARRAY_SIZE(ftr_id_aa64mmfr2_el1) + ARRAY_SIZE(ftr_id_aa64zfr0_el1) - 584 - ARRAY_SIZE(test_regs) + 2; 572 + ARRAY_SIZE(ftr_id_aa64pfr1_el1) + ARRAY_SIZE(ftr_id_aa64mmfr0_el1) + 573 + ARRAY_SIZE(ftr_id_aa64mmfr1_el1) + ARRAY_SIZE(ftr_id_aa64mmfr2_el1) + 574 + ARRAY_SIZE(ftr_id_aa64zfr0_el1) - ARRAY_SIZE(test_regs) + 2; 585 575 586 576 ksft_set_plan(test_cnt); 587 577