Skip to content

Commit fff97df

Browse files
committed
KVM: arm64: Route SEAs to the SError vector when EASE is set
One of the finest additions of FEAT_DoubleFault2 is the ability for software to request *synchronous* external aborts be taken to the SError vector, which of coure are *asynchronous* in nature. Opinions be damned, implement the architecture and send SEAs to the SError vector if EASE is set for the target context. Reviewed-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 178ec0a commit fff97df

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

arch/arm64/kvm/emulate-nested.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2834,6 +2834,10 @@ int kvm_inject_nested_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr)
28342834
esr |= ESR_ELx_FSC_EXTABT | ESR_ELx_IL;
28352835

28362836
vcpu_write_sys_reg(vcpu, FAR_EL2, addr);
2837+
2838+
if (__vcpu_sys_reg(vcpu, SCTLR2_EL2) & SCTLR2_EL1_EASE)
2839+
return kvm_inject_nested(vcpu, esr, except_type_serror);
2840+
28372841
return kvm_inject_nested_sync(vcpu, esr);
28382842
}
28392843

arch/arm64/kvm/hyp/exception.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ static void kvm_inject_exception(struct kvm_vcpu *vcpu)
339339
enter_exception64(vcpu, PSR_MODE_EL1h, except_type_sync);
340340
break;
341341

342+
case unpack_vcpu_flag(EXCEPT_AA64_EL1_SERR):
343+
enter_exception64(vcpu, PSR_MODE_EL1h, except_type_serror);
344+
break;
345+
342346
case unpack_vcpu_flag(EXCEPT_AA64_EL2_SYNC):
343347
enter_exception64(vcpu, PSR_MODE_EL2h, except_type_sync);
344348
break;
@@ -353,7 +357,7 @@ static void kvm_inject_exception(struct kvm_vcpu *vcpu)
353357

354358
default:
355359
/*
356-
* Only EL1_SYNC and EL2_{SYNC,IRQ,SERR} makes
360+
* Only EL1_{SYNC,SERR} and EL2_{SYNC,IRQ,SERR} makes
357361
* sense so far. Everything else gets silently
358362
* ignored.
359363
*/

arch/arm64/kvm/inject_fault.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,49 @@ static void pend_sync_exception(struct kvm_vcpu *vcpu)
6565
kvm_pend_exception(vcpu, EXCEPT_AA64_EL2_SYNC);
6666
}
6767

68+
static void pend_serror_exception(struct kvm_vcpu *vcpu)
69+
{
70+
if (exception_target_el(vcpu) == PSR_MODE_EL1h)
71+
kvm_pend_exception(vcpu, EXCEPT_AA64_EL1_SERR);
72+
else
73+
kvm_pend_exception(vcpu, EXCEPT_AA64_EL2_SERR);
74+
}
75+
76+
static bool __effective_sctlr2_bit(struct kvm_vcpu *vcpu, unsigned int idx)
77+
{
78+
u64 sctlr2;
79+
80+
if (!kvm_has_sctlr2(vcpu->kvm))
81+
return false;
82+
83+
if (is_nested_ctxt(vcpu) &&
84+
!(__vcpu_sys_reg(vcpu, HCRX_EL2) & HCRX_EL2_SCTLR2En))
85+
return false;
86+
87+
if (exception_target_el(vcpu) == PSR_MODE_EL1h)
88+
sctlr2 = vcpu_read_sys_reg(vcpu, SCTLR2_EL1);
89+
else
90+
sctlr2 = vcpu_read_sys_reg(vcpu, SCTLR2_EL2);
91+
92+
return sctlr2 & BIT(idx);
93+
}
94+
95+
static bool effective_sctlr2_ease(struct kvm_vcpu *vcpu)
96+
{
97+
return __effective_sctlr2_bit(vcpu, SCTLR2_EL1_EASE_SHIFT);
98+
}
99+
68100
static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
69101
{
70102
unsigned long cpsr = *vcpu_cpsr(vcpu);
71103
bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
72104
u64 esr = 0;
73105

74-
pend_sync_exception(vcpu);
106+
/* This delight is brought to you by FEAT_DoubleFault2. */
107+
if (effective_sctlr2_ease(vcpu))
108+
pend_serror_exception(vcpu);
109+
else
110+
pend_sync_exception(vcpu);
75111

76112
/*
77113
* Build an {i,d}abort, depending on the level and the

0 commit comments

Comments
 (0)