[PATCH 07/11] KVM: PPC: reconstruct non-SIMD LOAD/STORE instruction mmio emulation with analyse_intr() input
Simon Guo
wei.guo.simon at gmail.com
Thu May 3 19:07:16 AEST 2018
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 at gmail.com wrote:
> > From: Simon Guo <wei.guo.simon at 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 at ozlabs.org>
> > Signed-off-by: Simon Guo <wei.guo.simon at 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
More information about the Linuxppc-dev
mailing list