Skip to content

Commit 091258a

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/fpmr into kvmarm-master/next
* kvm-arm64/fpmr: : . : Add FP8 support to the KVM/arm64 floating point handling. : : This includes new ID registers (ID_AA64PFR2_EL1 ID_AA64FPFR0_EL1) : being made visible to guests, as well as a new confrol register : (FPMR) which gets context-switched. : . KVM: arm64: Expose ID_AA64PFR2_EL1 to userspace and guests KVM: arm64: Enable FP8 support when available and configured KVM: arm64: Expose ID_AA64FPFR0_EL1 as a writable ID reg KVM: arm64: Honor trap routing for FPMR KVM: arm64: Add save/restore support for FPMR KVM: arm64: Move FPMR into the sysreg array KVM: arm64: Add predicate for FPMR support in a VM KVM: arm64: Move SVCR into the sysreg array Signed-off-by: Marc Zyngier <[email protected]>
2 parents 8884fd1 + 13c7a51 commit 091258a

File tree

8 files changed

+82
-7
lines changed

8 files changed

+82
-7
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,10 @@ enum vcpu_sysreg {
446446
GCR_EL1, /* Tag Control Register */
447447
TFSRE0_EL1, /* Tag Fault Status Register (EL0) */
448448

449+
/* FP/SIMD/SVE */
450+
SVCR,
451+
FPMR,
452+
449453
/* 32bit specific registers. */
450454
DACR32_EL2, /* Domain Access Control Register */
451455
IFSR32_EL2, /* Instruction Fault Status Register */
@@ -595,6 +599,16 @@ struct kvm_host_data {
595599
struct cpu_sve_state *sve_state;
596600
};
597601

602+
union {
603+
/* HYP VA pointer to the host storage for FPMR */
604+
u64 *fpmr_ptr;
605+
/*
606+
* Used by pKVM only, as it needs to provide storage
607+
* for the host
608+
*/
609+
u64 fpmr;
610+
};
611+
598612
/* Ownership of the FP regs */
599613
enum {
600614
FP_STATE_FREE,
@@ -664,8 +678,6 @@ struct kvm_vcpu_arch {
664678
void *sve_state;
665679
enum fp_type fp_type;
666680
unsigned int sve_max_vl;
667-
u64 svcr;
668-
u64 fpmr;
669681

670682
/* Stage 2 paging state used by the hardware on next switch */
671683
struct kvm_s2_mmu *hw_mmu;
@@ -1473,4 +1485,8 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val);
14731485
(pa + pi + pa3) == 1; \
14741486
})
14751487

1488+
#define kvm_has_fpmr(k) \
1489+
(system_supports_fpmr() && \
1490+
kvm_has_feat((k), ID_AA64PFR2_EL1, FPMR, IMP))
1491+
14761492
#endif /* __ARM64_KVM_HOST_H__ */

arch/arm64/kvm/emulate-nested.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ enum cgt_group_id {
8383
CGT_CPTR_TAM,
8484
CGT_CPTR_TCPAC,
8585

86+
CGT_HCRX_EnFPM,
8687
CGT_HCRX_TCR2En,
8788

8889
/*
@@ -372,6 +373,12 @@ static const struct trap_bits coarse_trap_bits[] = {
372373
.mask = CPTR_EL2_TCPAC,
373374
.behaviour = BEHAVE_FORWARD_ANY,
374375
},
376+
[CGT_HCRX_EnFPM] = {
377+
.index = HCRX_EL2,
378+
.value = 0,
379+
.mask = HCRX_EL2_EnFPM,
380+
.behaviour = BEHAVE_FORWARD_ANY,
381+
},
375382
[CGT_HCRX_TCR2En] = {
376383
.index = HCRX_EL2,
377384
.value = 0,
@@ -1108,6 +1115,7 @@ static const struct encoding_to_trap_config encoding_to_cgt[] __initconst = {
11081115
SR_TRAP(SYS_CNTP_CTL_EL0, CGT_CNTHCTL_EL1PTEN),
11091116
SR_TRAP(SYS_CNTPCT_EL0, CGT_CNTHCTL_EL1PCTEN),
11101117
SR_TRAP(SYS_CNTPCTSS_EL0, CGT_CNTHCTL_EL1PCTEN),
1118+
SR_TRAP(SYS_FPMR, CGT_HCRX_EnFPM),
11111119
};
11121120

11131121
static DEFINE_XARRAY(sr_forward_xa);

arch/arm64/kvm/fpsimd.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
6363
*/
6464
*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
6565
*host_data_ptr(fpsimd_state) = kern_hyp_va(&current->thread.uw.fpsimd_state);
66+
*host_data_ptr(fpmr_ptr) = kern_hyp_va(&current->thread.uw.fpmr);
6667

6768
vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
6869
if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
@@ -134,8 +135,8 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
134135
fp_state.sve_state = vcpu->arch.sve_state;
135136
fp_state.sve_vl = vcpu->arch.sve_max_vl;
136137
fp_state.sme_state = NULL;
137-
fp_state.svcr = &vcpu->arch.svcr;
138-
fp_state.fpmr = &vcpu->arch.fpmr;
138+
fp_state.svcr = &__vcpu_sys_reg(vcpu, SVCR);
139+
fp_state.fpmr = &__vcpu_sys_reg(vcpu, FPMR);
139140
fp_state.fp_type = &vcpu->arch.fp_type;
140141

141142
if (vcpu_has_sve(vcpu))

arch/arm64/kvm/hyp/include/hyp/switch.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,9 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
403403
else
404404
__fpsimd_restore_state(&vcpu->arch.ctxt.fp_regs);
405405

406+
if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm)))
407+
write_sysreg_s(__vcpu_sys_reg(vcpu, FPMR), SYS_FPMR);
408+
406409
/* Skip restoring fpexc32 for AArch64 guests */
407410
if (!(read_sysreg(hcr_el2) & HCR_RW))
408411
write_sysreg(__vcpu_sys_reg(vcpu, FPEXC32_EL2), fpexc32_el2);

arch/arm64/kvm/hyp/nvhe/hyp-main.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ static void fpsimd_sve_flush(void)
6262

6363
static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
6464
{
65+
bool has_fpmr;
66+
6567
if (!guest_owns_fp_regs())
6668
return;
6769

@@ -73,11 +75,18 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu)
7375
else
7476
__fpsimd_save_state(&vcpu->arch.ctxt.fp_regs);
7577

78+
has_fpmr = kvm_has_fpmr(kern_hyp_va(vcpu->kvm));
79+
if (has_fpmr)
80+
__vcpu_sys_reg(vcpu, FPMR) = read_sysreg_s(SYS_FPMR);
81+
7682
if (system_supports_sve())
7783
__hyp_sve_restore_host();
7884
else
7985
__fpsimd_restore_state(*host_data_ptr(fpsimd_state));
8086

87+
if (has_fpmr)
88+
write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR);
89+
8190
*host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED;
8291
}
8392

arch/arm64/kvm/hyp/nvhe/switch.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
197197
} else {
198198
__fpsimd_save_state(*host_data_ptr(fpsimd_state));
199199
}
200+
201+
if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) {
202+
u64 val = read_sysreg_s(SYS_FPMR);
203+
204+
if (unlikely(is_protected_kvm_enabled()))
205+
*host_data_ptr(fpmr) = val;
206+
else
207+
**host_data_ptr(fpmr_ptr) = val;
208+
}
200209
}
201210

202211
static const exit_handler_fn hyp_exit_handlers[] = {

arch/arm64/kvm/hyp/vhe/switch.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,9 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code)
312312
static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
313313
{
314314
__fpsimd_save_state(*host_data_ptr(fpsimd_state));
315+
316+
if (kvm_has_fpmr(vcpu->kvm))
317+
**host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR);
315318
}
316319

317320
static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code)

arch/arm64/kvm/sys_regs.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,10 @@ static u64 __kvm_read_sanitised_id_reg(const struct kvm_vcpu *vcpu,
15451545

15461546
val &= ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME);
15471547
break;
1548+
case SYS_ID_AA64PFR2_EL1:
1549+
/* We only expose FPMR */
1550+
val &= ID_AA64PFR2_EL1_FPMR;
1551+
break;
15481552
case SYS_ID_AA64ISAR1_EL1:
15491553
if (!vcpu_has_ptrauth(vcpu))
15501554
val &= ~(ARM64_FEATURE_MASK(ID_AA64ISAR1_EL1_APA) |
@@ -1675,6 +1679,24 @@ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu,
16751679
return REG_HIDDEN;
16761680
}
16771681

1682+
static unsigned int sme_visibility(const struct kvm_vcpu *vcpu,
1683+
const struct sys_reg_desc *rd)
1684+
{
1685+
if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SME, IMP))
1686+
return 0;
1687+
1688+
return REG_HIDDEN;
1689+
}
1690+
1691+
static unsigned int fp8_visibility(const struct kvm_vcpu *vcpu,
1692+
const struct sys_reg_desc *rd)
1693+
{
1694+
if (kvm_has_fpmr(vcpu->kvm))
1695+
return 0;
1696+
1697+
return REG_HIDDEN;
1698+
}
1699+
16781700
static u64 read_sanitised_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
16791701
const struct sys_reg_desc *rd)
16801702
{
@@ -2369,12 +2391,12 @@ static const struct sys_reg_desc sys_reg_descs[] = {
23692391
ID_AA64PFR0_EL1_AdvSIMD |
23702392
ID_AA64PFR0_EL1_FP), },
23712393
ID_SANITISED(ID_AA64PFR1_EL1),
2372-
ID_UNALLOCATED(4,2),
2394+
ID_WRITABLE(ID_AA64PFR2_EL1, ID_AA64PFR2_EL1_FPMR),
23732395
ID_UNALLOCATED(4,3),
23742396
ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0),
23752397
ID_HIDDEN(ID_AA64SMFR0_EL1),
23762398
ID_UNALLOCATED(4,6),
2377-
ID_UNALLOCATED(4,7),
2399+
ID_WRITABLE(ID_AA64FPFR0_EL1, ~ID_AA64FPFR0_EL1_RES0),
23782400

23792401
/* CRm=5 */
23802402
{ SYS_DESC(SYS_ID_AA64DFR0_EL1),
@@ -2541,7 +2563,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
25412563
CTR_EL0_IDC_MASK |
25422564
CTR_EL0_DminLine_MASK |
25432565
CTR_EL0_IminLine_MASK),
2544-
{ SYS_DESC(SYS_SVCR), undef_access },
2566+
{ SYS_DESC(SYS_SVCR), undef_access, reset_val, SVCR, 0, .visibility = sme_visibility },
2567+
{ SYS_DESC(SYS_FPMR), undef_access, reset_val, FPMR, 0, .visibility = fp8_visibility },
25452568

25462569
{ PMU_SYS_REG(PMCR_EL0), .access = access_pmcr, .reset = reset_pmcr,
25472570
.reg = PMCR_EL0, .get_user = get_pmcr, .set_user = set_pmcr },
@@ -4566,6 +4589,9 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
45664589

45674590
if (kvm_has_feat(kvm, ID_AA64MMFR3_EL1, TCRX, IMP))
45684591
vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En;
4592+
4593+
if (kvm_has_fpmr(kvm))
4594+
vcpu->arch.hcrx_el2 |= HCRX_EL2_EnFPM;
45694595
}
45704596

45714597
if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags))

0 commit comments

Comments
 (0)