Commit 2b33cb58 authored by Simon Guo's avatar Simon Guo Committed by Paul Mackerras

KVM: PPC: Reimplement LOAD_FP/STORE_FP instruction mmio emulation with analyse_instr() input

This patch reimplements LOAD_FP/STORE_FP instruction MMIO emulation with
analyse_instr() input. It utilizes the FPCONV/UPDATE properties exported by
analyse_instr() and invokes kvmppc_handle_load(s)/kvmppc_handle_store()
accordingly.

For FP store MMIO emulation, the FP regs need to be flushed firstly so
that the right FP reg vals can be read from vcpu->arch.fpr, which will
be stored into MMIO data.
Suggested-by: default avatarPaul Mackerras <paulus@ozlabs.org>
Signed-off-by: default avatarSimon Guo <wei.guo.simon@gmail.com>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parent 2e6baa46
...@@ -138,6 +138,26 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) ...@@ -138,6 +138,26 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
break; break;
} }
#ifdef CONFIG_PPC_FPU
case LOAD_FP:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
if (op.type & FPCONV)
vcpu->arch.mmio_sp64_extend = 1;
if (op.type & SIGNEXT)
emulated = kvmppc_handle_loads(run, vcpu,
KVM_MMIO_REG_FPR|op.reg, size, 1);
else
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|op.reg, size, 1);
if ((op.type & UPDATE) && (emulated != EMULATE_FAIL))
kvmppc_set_gpr(vcpu, op.update_reg, op.ea);
break;
#endif
case STORE: case STORE:
/* if need byte reverse, op.val has been reversed by /* if need byte reverse, op.val has been reversed by
* analyse_instr(). * analyse_instr().
...@@ -149,6 +169,30 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) ...@@ -149,6 +169,30 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
kvmppc_set_gpr(vcpu, op.update_reg, op.ea); kvmppc_set_gpr(vcpu, op.update_reg, op.ea);
break; break;
#ifdef CONFIG_PPC_FPU
case STORE_FP:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
/* The FP registers need to be flushed so that
* kvmppc_handle_store() can read actual FP vals
* from vcpu->arch.
*/
if (vcpu->kvm->arch.kvm_ops->giveup_ext)
vcpu->kvm->arch.kvm_ops->giveup_ext(vcpu,
MSR_FP);
if (op.type & FPCONV)
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, op.reg), size, 1);
if ((op.type & UPDATE) && (emulated != EMULATE_FAIL))
kvmppc_set_gpr(vcpu, op.update_reg, op.ea);
break;
#endif
case CACHEOP: case CACHEOP:
/* Do nothing. The guest is performing dcbi because /* Do nothing. The guest is performing dcbi because
* hardware DMA is not snooped by the dcache, but * hardware DMA is not snooped by the dcache, but
...@@ -170,93 +214,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) ...@@ -170,93 +214,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
switch (get_op(inst)) { switch (get_op(inst)) {
case 31: case 31:
switch (get_xop(inst)) { switch (get_xop(inst)) {
#ifdef CONFIG_PPC_FPU
case OP_31_XOP_LFSX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|rt, 4, 1);
break;
case OP_31_XOP_LFSUX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|rt, 4, 1);
kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
break;
case OP_31_XOP_LFDX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|rt, 8, 1);
break;
case OP_31_XOP_LFDUX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|rt, 8, 1);
kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
break;
case OP_31_XOP_LFIWAX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_loads(run, vcpu,
KVM_MMIO_REG_FPR|rt, 4, 1);
break;
case OP_31_XOP_LFIWZX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|rt, 4, 1);
break;
case OP_31_XOP_STFSX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, rs), 4, 1);
break;
case OP_31_XOP_STFSUX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, rs), 4, 1);
kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
break;
case OP_31_XOP_STFDX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, rs), 8, 1);
break;
case OP_31_XOP_STFDUX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, rs), 8, 1);
kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
break;
case OP_31_XOP_STFIWX:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, rs), 4, 1);
break;
#endif
#ifdef CONFIG_VSX #ifdef CONFIG_VSX
case OP_31_XOP_LXSDX: case OP_31_XOP_LXSDX:
if (kvmppc_check_vsx_disabled(vcpu)) if (kvmppc_check_vsx_disabled(vcpu))
...@@ -421,76 +378,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) ...@@ -421,76 +378,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
} }
break; break;
#ifdef CONFIG_PPC_FPU
case OP_STFS:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, rs),
4, 1);
break;
case OP_STFSU:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, rs),
4, 1);
kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
break;
case OP_STFD:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, rs),
8, 1);
break;
case OP_STFDU:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_store(run, vcpu,
VCPU_FPR(vcpu, rs),
8, 1);
kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
break;
case OP_LFS:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|rt, 4, 1);
break;
case OP_LFSU:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
vcpu->arch.mmio_sp64_extend = 1;
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|rt, 4, 1);
kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
break;
case OP_LFD:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|rt, 8, 1);
break;
case OP_LFDU:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
emulated = kvmppc_handle_load(run, vcpu,
KVM_MMIO_REG_FPR|rt, 8, 1);
kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
break;
#endif
default: default:
emulated = EMULATE_FAIL; emulated = EMULATE_FAIL;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment