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: Paul Mackerras <paulus@ozlabs.org> Signed-off-by: Simon Guo <wei.guo.simon@gmail.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
2e6baa46b4
commit
2b33cb585f
|
@ -138,6 +138,26 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
|
|||
|
||||
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:
|
||||
/* if need byte reverse, op.val has been reversed by
|
||||
* analyse_instr().
|
||||
|
@ -149,6 +169,30 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
|
|||
kvmppc_set_gpr(vcpu, op.update_reg, op.ea);
|
||||
|
||||
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:
|
||||
/* Do nothing. The guest is performing dcbi because
|
||||
* hardware DMA is not snooped by the dcache, but
|
||||
|
@ -170,93 +214,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
|
|||
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))
|
||||
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
|
||||
case OP_31_XOP_LXSDX:
|
||||
if (kvmppc_check_vsx_disabled(vcpu))
|
||||
|
@ -421,76 +378,6 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
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:
|
||||
emulated = EMULATE_FAIL;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue