mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-02 15:43:35 -04:00
KVM: arm64: nv: Honor guest hypervisor's FP/SVE traps in CPTR_EL2
Start folding the guest hypervisor's FP/SVE traps into the value programmed in hardware. Note that as of writing this is dead code, since KVM does a full put() / load() for every nested exception boundary which saves + flushes the FP/SVE state. However, this will become useful when we can keep the guest's FP/SVE state alive across a nested exception boundary and the host no longer needs to conservatively program traps. Reviewed-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20240620164653.1130714-12-oliver.upton@linux.dev Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
@@ -67,6 +67,8 @@ static u64 __compute_hcr(struct kvm_vcpu *vcpu)
|
||||
|
||||
static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u64 cptr;
|
||||
|
||||
/*
|
||||
* With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to
|
||||
* CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2,
|
||||
@@ -85,6 +87,35 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
|
||||
__activate_traps_fpsimd32(vcpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Layer the guest hypervisor's trap configuration on top of our own if
|
||||
* we're in a nested context.
|
||||
*/
|
||||
if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu))
|
||||
goto write;
|
||||
|
||||
cptr = vcpu_sanitised_cptr_el2(vcpu);
|
||||
|
||||
/*
|
||||
* Pay attention, there's some interesting detail here.
|
||||
*
|
||||
* The CPTR_EL2.xEN fields are 2 bits wide, although there are only two
|
||||
* meaningful trap states when HCR_EL2.TGE = 0 (running a nested guest):
|
||||
*
|
||||
* - CPTR_EL2.xEN = x0, traps are enabled
|
||||
* - CPTR_EL2.xEN = x1, traps are disabled
|
||||
*
|
||||
* In other words, bit[0] determines if guest accesses trap or not. In
|
||||
* the interest of simplicity, clear the entire field if the guest
|
||||
* hypervisor has traps enabled to dispel any illusion of something more
|
||||
* complicated taking place.
|
||||
*/
|
||||
if (!(SYS_FIELD_GET(CPACR_ELx, FPEN, cptr) & BIT(0)))
|
||||
val &= ~CPACR_ELx_FPEN;
|
||||
if (!(SYS_FIELD_GET(CPACR_ELx, ZEN, cptr) & BIT(0)))
|
||||
val &= ~CPACR_ELx_ZEN;
|
||||
|
||||
write:
|
||||
write_sysreg(val, cpacr_el1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user