On Wed, Apr 25, 2018 at 07:54:40PM +0800, wei.guo.si...@gmail.com wrote:
> From: Simon Guo <wei.guo.si...@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 <pau...@ozlabs.org>
> Signed-off-by: Simon Guo <wei.guo.si...@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.

Reply via email to