Message ID | 1524657284-16706-8-git-send-email-wei.guo.simon@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Apr 25, 2018 at 07:54:40PM +0800, wei.guo.simon@gmail.com wrote: > From: Simon Guo <wei.guo.simon@gmail.com> > > This patch reconstructs non-SIMD LOAD/STORE instruction MMIO emulation > with analyse_intr() input. It utilizes the BYTEREV/UPDATE/SIGNEXT > properties exported by analyse_instr() and invokes > kvmppc_handle_load(s)/kvmppc_handle_store() accordingly. > > It also move CACHEOP type handling into the skeleton. > > instruction_type within sstep.h is renamed to avoid conflict with > kvm_ppc.h. I'd prefer to change the one in kvm_ppc.h, especially since that one isn't exactly about the type of instruction, but more about the type of interrupt led to us trying to fetch the instruction. > Suggested-by: Paul Mackerras <paulus@ozlabs.org> > Signed-off-by: Simon Guo <wei.guo.simon@gmail.com> > --- > arch/powerpc/include/asm/sstep.h | 2 +- > arch/powerpc/kvm/emulate_loadstore.c | 282 +++++++---------------------------- > 2 files changed, 51 insertions(+), 233 deletions(-) > > diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h > index ab9d849..0a1a312 100644 > --- a/arch/powerpc/include/asm/sstep.h > +++ b/arch/powerpc/include/asm/sstep.h > @@ -23,7 +23,7 @@ > #define IS_RFID(instr) (((instr) & 0xfc0007fe) == 0x4c000024) > #define IS_RFI(instr) (((instr) & 0xfc0007fe) == 0x4c000064) > > -enum instruction_type { > +enum analyse_instruction_type { > COMPUTE, /* arith/logical/CR op, etc. */ > LOAD, /* load and store types need to be contiguous */ > LOAD_MULTI, > diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c > index 90b9692..aaaf872 100644 > --- a/arch/powerpc/kvm/emulate_loadstore.c > +++ b/arch/powerpc/kvm/emulate_loadstore.c > @@ -31,9 +31,12 @@ > #include <asm/kvm_ppc.h> > #include <asm/disassemble.h> > #include <asm/ppc-opcode.h> > +#include <asm/sstep.h> > #include "timing.h" > #include "trace.h" > > +int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, > + unsigned int instr); You shouldn't need this prototype here, since there's one in sstep.h. > #ifdef CONFIG_PPC_FPU > static bool kvmppc_check_fp_disabled(struct kvm_vcpu *vcpu) > { > @@ -84,8 +87,9 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) > struct kvm_run *run = vcpu->run; > u32 inst; > int ra, rs, rt; > - enum emulation_result emulated; > + enum emulation_result emulated = EMULATE_FAIL; > int advance = 1; > + struct instruction_op op; > > /* this default type might be overwritten by subcategories */ > kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); > @@ -114,144 +118,64 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) > vcpu->arch.mmio_update_ra = 0; > vcpu->arch.mmio_host_swabbed = 0; > > - switch (get_op(inst)) { > - case 31: > - switch (get_xop(inst)) { > - case OP_31_XOP_LWZX: > - emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); > - break; > - > - case OP_31_XOP_LWZUX: > - emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > - break; > - > - case OP_31_XOP_LBZX: > - emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); > - break; > + emulated = EMULATE_FAIL; > + vcpu->arch.regs.msr = vcpu->arch.shared->msr; > + vcpu->arch.regs.ccr = vcpu->arch.cr; > + if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) { > + int type = op.type & INSTR_TYPE_MASK; > + int size = GETSIZE(op.type); > > - case OP_31_XOP_LBZUX: > - emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > - break; > + switch (type) { > + case LOAD: { > + int instr_byte_swap = op.type & BYTEREV; > > - case OP_31_XOP_STDX: > - emulated = kvmppc_handle_store(run, vcpu, > - kvmppc_get_gpr(vcpu, rs), 8, 1); > - break; > + if (op.type & UPDATE) { > + vcpu->arch.mmio_ra = op.update_reg; > + vcpu->arch.mmio_update_ra = 1; > + } Any reason we can't just update RA here immediately? > > - case OP_31_XOP_STDUX: > - emulated = kvmppc_handle_store(run, vcpu, > - kvmppc_get_gpr(vcpu, rs), 8, 1); > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > - break; > - > - case OP_31_XOP_STWX: > - emulated = kvmppc_handle_store(run, vcpu, > - kvmppc_get_gpr(vcpu, rs), 4, 1); > - break; > - > - case OP_31_XOP_STWUX: > - emulated = kvmppc_handle_store(run, vcpu, > - kvmppc_get_gpr(vcpu, rs), 4, 1); > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > - break; > - > - case OP_31_XOP_STBX: > - emulated = kvmppc_handle_store(run, vcpu, > - kvmppc_get_gpr(vcpu, rs), 1, 1); > - break; > - > - case OP_31_XOP_STBUX: > - emulated = kvmppc_handle_store(run, vcpu, > - kvmppc_get_gpr(vcpu, rs), 1, 1); > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > - break; > - > - case OP_31_XOP_LHAX: > - emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); > - break; > - > - case OP_31_XOP_LHAUX: > - emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > - break; > + if (op.type & SIGNEXT) > + emulated = kvmppc_handle_loads(run, vcpu, > + op.reg, size, !instr_byte_swap); > + else > + emulated = kvmppc_handle_load(run, vcpu, > + op.reg, size, !instr_byte_swap); > > - case OP_31_XOP_LHZX: > - emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); > break; > - > - case OP_31_XOP_LHZUX: > - emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > - break; > - > - case OP_31_XOP_STHX: > - emulated = kvmppc_handle_store(run, vcpu, > - kvmppc_get_gpr(vcpu, rs), 2, 1); > - break; > - > - case OP_31_XOP_STHUX: > - emulated = kvmppc_handle_store(run, vcpu, > - kvmppc_get_gpr(vcpu, rs), 2, 1); > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > - break; > - > - case OP_31_XOP_DCBST: > - case OP_31_XOP_DCBF: > - case OP_31_XOP_DCBI: > + } > + case STORE: > + if (op.type & UPDATE) { > + vcpu->arch.mmio_ra = op.update_reg; > + vcpu->arch.mmio_update_ra = 1; > + } Same comment again about updating RA. > + > + /* if need byte reverse, op.val has been reverted by "reversed" rather than "reverted". "Reverted" means put back to a former state. Paul.
On Thu, May 03, 2018 at 04:03:46PM +1000, Paul Mackerras wrote: > On Wed, Apr 25, 2018 at 07:54:40PM +0800, wei.guo.simon@gmail.com wrote: > > From: Simon Guo <wei.guo.simon@gmail.com> > > > > This patch reconstructs non-SIMD LOAD/STORE instruction MMIO emulation > > with analyse_intr() input. It utilizes the BYTEREV/UPDATE/SIGNEXT > > properties exported by analyse_instr() and invokes > > kvmppc_handle_load(s)/kvmppc_handle_store() accordingly. > > > > It also move CACHEOP type handling into the skeleton. > > > > instruction_type within sstep.h is renamed to avoid conflict with > > kvm_ppc.h. > > I'd prefer to change the one in kvm_ppc.h, especially since that one > isn't exactly about the type of instruction, but more about the type > of interrupt led to us trying to fetch the instruction. > Agreed. > > Suggested-by: Paul Mackerras <paulus@ozlabs.org> > > Signed-off-by: Simon Guo <wei.guo.simon@gmail.com> > > --- > > arch/powerpc/include/asm/sstep.h | 2 +- > > arch/powerpc/kvm/emulate_loadstore.c | 282 +++++++---------------------------- > > 2 files changed, 51 insertions(+), 233 deletions(-) > > > > diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h > > index ab9d849..0a1a312 100644 > > --- a/arch/powerpc/include/asm/sstep.h > > +++ b/arch/powerpc/include/asm/sstep.h > > @@ -23,7 +23,7 @@ > > #define IS_RFID(instr) (((instr) & 0xfc0007fe) == 0x4c000024) > > #define IS_RFI(instr) (((instr) & 0xfc0007fe) == 0x4c000064) > > > > -enum instruction_type { > > +enum analyse_instruction_type { > > COMPUTE, /* arith/logical/CR op, etc. */ > > LOAD, /* load and store types need to be contiguous */ > > LOAD_MULTI, > > diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c > > index 90b9692..aaaf872 100644 > > --- a/arch/powerpc/kvm/emulate_loadstore.c > > +++ b/arch/powerpc/kvm/emulate_loadstore.c > > @@ -31,9 +31,12 @@ > > #include <asm/kvm_ppc.h> > > #include <asm/disassemble.h> > > #include <asm/ppc-opcode.h> > > +#include <asm/sstep.h> > > #include "timing.h" > > #include "trace.h" > > > > +int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, > > + unsigned int instr); > > You shouldn't need this prototype here, since there's one in sstep.h. > Yes. > > #ifdef CONFIG_PPC_FPU > > static bool kvmppc_check_fp_disabled(struct kvm_vcpu *vcpu) > > { > > @@ -84,8 +87,9 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) > > struct kvm_run *run = vcpu->run; > > u32 inst; > > int ra, rs, rt; > > - enum emulation_result emulated; > > + enum emulation_result emulated = EMULATE_FAIL; > > int advance = 1; > > + struct instruction_op op; > > > > /* this default type might be overwritten by subcategories */ > > kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); > > @@ -114,144 +118,64 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) > > vcpu->arch.mmio_update_ra = 0; > > vcpu->arch.mmio_host_swabbed = 0; > > > > - switch (get_op(inst)) { > > - case 31: > > - switch (get_xop(inst)) { > > - case OP_31_XOP_LWZX: > > - emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); > > - break; > > - > > - case OP_31_XOP_LWZUX: > > - emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); > > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > > - break; > > - > > - case OP_31_XOP_LBZX: > > - emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); > > - break; > > + emulated = EMULATE_FAIL; > > + vcpu->arch.regs.msr = vcpu->arch.shared->msr; > > + vcpu->arch.regs.ccr = vcpu->arch.cr; > > + if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) { > > + int type = op.type & INSTR_TYPE_MASK; > > + int size = GETSIZE(op.type); > > > > - case OP_31_XOP_LBZUX: > > - emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); > > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > > - break; > > + switch (type) { > > + case LOAD: { > > + int instr_byte_swap = op.type & BYTEREV; > > > > - case OP_31_XOP_STDX: > > - emulated = kvmppc_handle_store(run, vcpu, > > - kvmppc_get_gpr(vcpu, rs), 8, 1); > > - break; > > + if (op.type & UPDATE) { > > + vcpu->arch.mmio_ra = op.update_reg; > > + vcpu->arch.mmio_update_ra = 1; > > + } > > Any reason we can't just update RA here immediately? > > > > > - case OP_31_XOP_STDUX: > > - emulated = kvmppc_handle_store(run, vcpu, > > - kvmppc_get_gpr(vcpu, rs), 8, 1); > > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > > - break; > > - > > - case OP_31_XOP_STWX: > > - emulated = kvmppc_handle_store(run, vcpu, > > - kvmppc_get_gpr(vcpu, rs), 4, 1); > > - break; > > - > > - case OP_31_XOP_STWUX: > > - emulated = kvmppc_handle_store(run, vcpu, > > - kvmppc_get_gpr(vcpu, rs), 4, 1); > > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > > - break; > > - > > - case OP_31_XOP_STBX: > > - emulated = kvmppc_handle_store(run, vcpu, > > - kvmppc_get_gpr(vcpu, rs), 1, 1); > > - break; > > - > > - case OP_31_XOP_STBUX: > > - emulated = kvmppc_handle_store(run, vcpu, > > - kvmppc_get_gpr(vcpu, rs), 1, 1); > > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > > - break; > > - > > - case OP_31_XOP_LHAX: > > - emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); > > - break; > > - > > - case OP_31_XOP_LHAUX: > > - emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); > > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > > - break; > > + if (op.type & SIGNEXT) > > + emulated = kvmppc_handle_loads(run, vcpu, > > + op.reg, size, !instr_byte_swap); > > + else > > + emulated = kvmppc_handle_load(run, vcpu, > > + op.reg, size, !instr_byte_swap); > > > > - case OP_31_XOP_LHZX: > > - emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); > > break; > > - > > - case OP_31_XOP_LHZUX: > > - emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); > > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > > - break; > > - > > - case OP_31_XOP_STHX: > > - emulated = kvmppc_handle_store(run, vcpu, > > - kvmppc_get_gpr(vcpu, rs), 2, 1); > > - break; > > - > > - case OP_31_XOP_STHUX: > > - emulated = kvmppc_handle_store(run, vcpu, > > - kvmppc_get_gpr(vcpu, rs), 2, 1); > > - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); > > - break; > > - > > - case OP_31_XOP_DCBST: > > - case OP_31_XOP_DCBF: > > - case OP_31_XOP_DCBI: > > + } > > + case STORE: > > + if (op.type & UPDATE) { > > + vcpu->arch.mmio_ra = op.update_reg; > > + vcpu->arch.mmio_update_ra = 1; > > + } > > Same comment again about updating RA. > > > + > > + /* if need byte reverse, op.val has been reverted by > > "reversed" rather than "reverted". "Reverted" means put back to a > former state. I will correct that. > > Paul. Thanks, - Simon
diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h index ab9d849..0a1a312 100644 --- a/arch/powerpc/include/asm/sstep.h +++ b/arch/powerpc/include/asm/sstep.h @@ -23,7 +23,7 @@ #define IS_RFID(instr) (((instr) & 0xfc0007fe) == 0x4c000024) #define IS_RFI(instr) (((instr) & 0xfc0007fe) == 0x4c000064) -enum instruction_type { +enum analyse_instruction_type { COMPUTE, /* arith/logical/CR op, etc. */ LOAD, /* load and store types need to be contiguous */ LOAD_MULTI, diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c index 90b9692..aaaf872 100644 --- a/arch/powerpc/kvm/emulate_loadstore.c +++ b/arch/powerpc/kvm/emulate_loadstore.c @@ -31,9 +31,12 @@ #include <asm/kvm_ppc.h> #include <asm/disassemble.h> #include <asm/ppc-opcode.h> +#include <asm/sstep.h> #include "timing.h" #include "trace.h" +int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, + unsigned int instr); #ifdef CONFIG_PPC_FPU static bool kvmppc_check_fp_disabled(struct kvm_vcpu *vcpu) { @@ -84,8 +87,9 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) struct kvm_run *run = vcpu->run; u32 inst; int ra, rs, rt; - enum emulation_result emulated; + enum emulation_result emulated = EMULATE_FAIL; int advance = 1; + struct instruction_op op; /* this default type might be overwritten by subcategories */ kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); @@ -114,144 +118,64 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) vcpu->arch.mmio_update_ra = 0; vcpu->arch.mmio_host_swabbed = 0; - switch (get_op(inst)) { - case 31: - switch (get_xop(inst)) { - case OP_31_XOP_LWZX: - emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); - break; - - case OP_31_XOP_LWZUX: - emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_31_XOP_LBZX: - emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); - break; + emulated = EMULATE_FAIL; + vcpu->arch.regs.msr = vcpu->arch.shared->msr; + vcpu->arch.regs.ccr = vcpu->arch.cr; + if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) { + int type = op.type & INSTR_TYPE_MASK; + int size = GETSIZE(op.type); - case OP_31_XOP_LBZUX: - emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; + switch (type) { + case LOAD: { + int instr_byte_swap = op.type & BYTEREV; - case OP_31_XOP_STDX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 8, 1); - break; + if (op.type & UPDATE) { + vcpu->arch.mmio_ra = op.update_reg; + vcpu->arch.mmio_update_ra = 1; + } - case OP_31_XOP_STDUX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 8, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_31_XOP_STWX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 4, 1); - break; - - case OP_31_XOP_STWUX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 4, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_31_XOP_STBX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 1, 1); - break; - - case OP_31_XOP_STBUX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 1, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_31_XOP_LHAX: - emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); - break; - - case OP_31_XOP_LHAUX: - emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; + if (op.type & SIGNEXT) + emulated = kvmppc_handle_loads(run, vcpu, + op.reg, size, !instr_byte_swap); + else + emulated = kvmppc_handle_load(run, vcpu, + op.reg, size, !instr_byte_swap); - case OP_31_XOP_LHZX: - emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); break; - - case OP_31_XOP_LHZUX: - emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_31_XOP_STHX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 2, 1); - break; - - case OP_31_XOP_STHUX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 2, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_31_XOP_DCBST: - case OP_31_XOP_DCBF: - case OP_31_XOP_DCBI: + } + case STORE: + if (op.type & UPDATE) { + vcpu->arch.mmio_ra = op.update_reg; + vcpu->arch.mmio_update_ra = 1; + } + + /* if need byte reverse, op.val has been reverted by + * analyse_instr(). + */ + emulated = kvmppc_handle_store(run, vcpu, op.val, + size, 1); + break; + case CACHEOP: /* Do nothing. The guest is performing dcbi because * hardware DMA is not snooped by the dcache, but * emulated DMA either goes through the dcache as * normal writes, or the host kernel has handled dcache - * coherence. */ - break; - - case OP_31_XOP_LWBRX: - emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0); - break; - - case OP_31_XOP_STWBRX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 4, 0); + * coherence. + */ + emulated = EMULATE_DONE; break; - - case OP_31_XOP_LHBRX: - emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0); - break; - - case OP_31_XOP_STHBRX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 2, 0); - break; - - case OP_31_XOP_LDBRX: - emulated = kvmppc_handle_load(run, vcpu, rt, 8, 0); - break; - - case OP_31_XOP_STDBRX: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 8, 0); - break; - - case OP_31_XOP_LDX: - emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1); + default: break; + } + } - case OP_31_XOP_LDUX: - emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - case OP_31_XOP_LWAX: - emulated = kvmppc_handle_loads(run, vcpu, rt, 4, 1); - break; - - case OP_31_XOP_LWAUX: - emulated = kvmppc_handle_loads(run, vcpu, rt, 4, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; + if (emulated == EMULATE_DONE) + goto out; + switch (get_op(inst)) { + case 31: + switch (get_xop(inst)) { #ifdef CONFIG_PPC_FPU case OP_31_XOP_LFSX: if (kvmppc_check_fp_disabled(vcpu)) @@ -503,10 +427,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) } break; - case OP_LWZ: - emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); - break; - #ifdef CONFIG_PPC_FPU case OP_STFS: if (kvmppc_check_fp_disabled(vcpu)) @@ -543,110 +463,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) 8, 1); kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); break; -#endif - - case OP_LD: - rt = get_rt(inst); - switch (inst & 3) { - case 0: /* ld */ - emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1); - break; - case 1: /* ldu */ - emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - case 2: /* lwa */ - emulated = kvmppc_handle_loads(run, vcpu, rt, 4, 1); - break; - default: - emulated = EMULATE_FAIL; - } - break; - - case OP_LWZU: - emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_LBZ: - emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); - break; - - case OP_LBZU: - emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_STW: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), - 4, 1); - break; - - case OP_STD: - rs = get_rs(inst); - switch (inst & 3) { - case 0: /* std */ - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 8, 1); - break; - case 1: /* stdu */ - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 8, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - default: - emulated = EMULATE_FAIL; - } - break; - - case OP_STWU: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 4, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_STB: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 1, 1); - break; - - case OP_STBU: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 1, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_LHZ: - emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); - break; - - case OP_LHZU: - emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - - case OP_LHA: - emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); - break; - - case OP_LHAU: - emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - case OP_STH: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 2, 1); - break; - - case OP_STHU: - emulated = kvmppc_handle_store(run, vcpu, - kvmppc_get_gpr(vcpu, rs), 2, 1); - kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); - break; - -#ifdef CONFIG_PPC_FPU case OP_LFS: if (kvmppc_check_fp_disabled(vcpu)) return EMULATE_DONE; @@ -685,6 +502,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) break; } +out: if (emulated == EMULATE_FAIL) { advance = 0; kvmppc_core_queue_program(vcpu, 0);