Skip to content

Commit c1c8a66

Browse files
farosasmpe
authored andcommitted
KVM: PPC: Book3s: mmio: Deliver DSI after emulation failure
MMIO emulation can fail if the guest uses an instruction that we are not prepared to emulate. Since these instructions can be and most likely are valid ones, this is (slightly) closer to an access fault than to an illegal instruction, so deliver a Data Storage interrupt instead of a Program interrupt. BookE ignores bad faults, so it will keep using a Program interrupt because a DSI would cause a fault loop in the guest. Suggested-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com> Reviewed-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20220125215655.1026224-6-farosas@linux.ibm.com
1 parent 349fbfe commit c1c8a66

2 files changed

Lines changed: 25 additions & 7 deletions

File tree

arch/powerpc/kvm/emulate_loadstore.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
7373
{
7474
u32 inst;
7575
enum emulation_result emulated = EMULATE_FAIL;
76-
int advance = 1;
7776
struct instruction_op op;
7877

7978
/* this default type might be overwritten by subcategories */
@@ -98,6 +97,8 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
9897
int type = op.type & INSTR_TYPE_MASK;
9998
int size = GETSIZE(op.type);
10099

100+
vcpu->mmio_is_write = OP_IS_STORE(type);
101+
101102
switch (type) {
102103
case LOAD: {
103104
int instr_byte_swap = op.type & BYTEREV;
@@ -355,15 +356,10 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
355356
}
356357
}
357358

358-
if (emulated == EMULATE_FAIL) {
359-
advance = 0;
360-
kvmppc_core_queue_program(vcpu, 0);
361-
}
362-
363359
trace_kvm_ppc_instr(inst, kvmppc_get_pc(vcpu), emulated);
364360

365361
/* Advance past emulated instruction. */
366-
if (advance)
362+
if (emulated != EMULATE_FAIL)
367363
kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4);
368364

369365
return emulated;

arch/powerpc/kvm/powerpc.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,28 @@ int kvmppc_emulate_mmio(struct kvm_vcpu *vcpu)
309309
kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst);
310310
kvm_debug_ratelimited("Guest access to device memory using unsupported instruction (opcode: %#08x)\n",
311311
last_inst);
312+
313+
/*
314+
* Injecting a Data Storage here is a bit more
315+
* accurate since the instruction that caused the
316+
* access could still be a valid one.
317+
*/
318+
if (!IS_ENABLED(CONFIG_BOOKE)) {
319+
ulong dsisr = DSISR_BADACCESS;
320+
321+
if (vcpu->mmio_is_write)
322+
dsisr |= DSISR_ISSTORE;
323+
324+
kvmppc_core_queue_data_storage(vcpu, vcpu->arch.vaddr_accessed, dsisr);
325+
} else {
326+
/*
327+
* BookE does not send a SIGBUS on a bad
328+
* fault, so use a Program interrupt instead
329+
* to avoid a fault loop.
330+
*/
331+
kvmppc_core_queue_program(vcpu, 0);
332+
}
333+
312334
r = RESUME_GUEST;
313335
break;
314336
}

0 commit comments

Comments
 (0)