Skip to content

Commit e794049

Browse files
author
Marc Zyngier
committed
KVM: arm64: nv: Add basic emulation of AT S1E2{R,W}
Similar to our AT S1E{0,1} emulation, we implement the AT S1E2 handling. This emulation of course suffers from the same problems, but is somehow simpler due to the lack of PAN2 and the fact that we are guaranteed to execute it from the correct context. Co-developed-by: Jintack Lim <jintack.lim@linaro.org> Signed-off-by: Jintack Lim <jintack.lim@linaro.org> Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent be0135b commit e794049

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

arch/arm64/include/asm/kvm_asm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ extern int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding);
237237

238238
extern void __kvm_timer_set_cntvoff(u64 cntvoff);
239239
extern void __kvm_at_s1e01(struct kvm_vcpu *vcpu, u32 op, u64 vaddr);
240+
extern void __kvm_at_s1e2(struct kvm_vcpu *vcpu, u32 op, u64 vaddr);
240241

241242
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
242243

arch/arm64/kvm/at.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,54 @@ void __kvm_at_s1e01(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
164164

165165
vcpu_write_sys_reg(vcpu, par, PAR_EL1);
166166
}
167+
168+
void __kvm_at_s1e2(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
169+
{
170+
u64 par;
171+
172+
/*
173+
* We've trapped, so everything is live on the CPU. As we will be
174+
* switching context behind everybody's back, disable interrupts...
175+
*/
176+
scoped_guard(write_lock_irqsave, &vcpu->kvm->mmu_lock) {
177+
struct kvm_s2_mmu *mmu;
178+
u64 val, hcr;
179+
bool fail;
180+
181+
mmu = &vcpu->kvm->arch.mmu;
182+
183+
val = hcr = read_sysreg(hcr_el2);
184+
val &= ~HCR_TGE;
185+
val |= HCR_VM;
186+
187+
if (!vcpu_el2_e2h_is_set(vcpu))
188+
val |= HCR_NV | HCR_NV1;
189+
190+
write_sysreg(val, hcr_el2);
191+
isb();
192+
193+
par = SYS_PAR_EL1_F;
194+
195+
switch (op) {
196+
case OP_AT_S1E2R:
197+
fail = __kvm_at(OP_AT_S1E1R, vaddr);
198+
break;
199+
case OP_AT_S1E2W:
200+
fail = __kvm_at(OP_AT_S1E1W, vaddr);
201+
break;
202+
default:
203+
WARN_ON_ONCE(1);
204+
fail = true;
205+
}
206+
207+
isb();
208+
209+
if (!fail)
210+
par = read_sysreg_par();
211+
212+
write_sysreg(hcr, hcr_el2);
213+
isb();
214+
}
215+
216+
vcpu_write_sys_reg(vcpu, par, PAR_EL1);
217+
}

0 commit comments

Comments
 (0)