Commit 513579e3 authored by Alexander Graf's avatar Alexander Graf Committed by Benjamin Herrenschmidt

Add desktop PowerPC specific emulation

Little opcodes behave differently on desktop and embedded PowerPC cores.
In order to reflect those differences, let's add some #ifdef code to emulate.c.

We could probably also handle them in the core specific emulation files, but I
would prefer to reuse as much code as possible.
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 9a7a9b09
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "trace.h" #include "trace.h"
#define OP_TRAP 3 #define OP_TRAP 3
#define OP_TRAP_64 2
#define OP_31_XOP_LWZX 23 #define OP_31_XOP_LWZX 23
#define OP_31_XOP_LBZX 87 #define OP_31_XOP_LBZX 87
...@@ -64,16 +65,36 @@ ...@@ -64,16 +65,36 @@
#define OP_STH 44 #define OP_STH 44
#define OP_STHU 45 #define OP_STHU 45
#ifdef CONFIG_PPC64
static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
{
return 1;
}
#else
static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
{
return vcpu->arch.tcr & TCR_DIE;
}
#endif
void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
{ {
unsigned long nr_jiffies; unsigned long nr_jiffies;
if (vcpu->arch.tcr & TCR_DIE) { #ifdef CONFIG_PPC64
/* POWER4+ triggers a dec interrupt if the value is < 0 */
if (vcpu->arch.dec & 0x80000000) {
del_timer(&vcpu->arch.dec_timer);
kvmppc_core_queue_dec(vcpu);
return;
}
#endif
if (kvmppc_dec_enabled(vcpu)) {
/* The decrementer ticks at the same rate as the timebase, so /* The decrementer ticks at the same rate as the timebase, so
* that's how we convert the guest DEC value to the number of * that's how we convert the guest DEC value to the number of
* host ticks. */ * host ticks. */
vcpu->arch.dec_jiffies = mftb(); vcpu->arch.dec_jiffies = get_tb();
nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy; nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy;
mod_timer(&vcpu->arch.dec_timer, mod_timer(&vcpu->arch.dec_timer,
get_jiffies_64() + nr_jiffies); get_jiffies_64() + nr_jiffies);
...@@ -113,9 +134,15 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) ...@@ -113,9 +134,15 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
/* this default type might be overwritten by subcategories */ /* this default type might be overwritten by subcategories */
kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
switch (get_op(inst)) { switch (get_op(inst)) {
case OP_TRAP: case OP_TRAP:
#ifdef CONFIG_PPC64
case OP_TRAP_64:
#else
vcpu->arch.esr |= ESR_PTR; vcpu->arch.esr |= ESR_PTR;
#endif
kvmppc_core_queue_program(vcpu); kvmppc_core_queue_program(vcpu);
advance = 0; advance = 0;
break; break;
...@@ -190,17 +217,19 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) ...@@ -190,17 +217,19 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
case SPRN_SRR1: case SPRN_SRR1:
vcpu->arch.gpr[rt] = vcpu->arch.srr1; break; vcpu->arch.gpr[rt] = vcpu->arch.srr1; break;
case SPRN_PVR: case SPRN_PVR:
vcpu->arch.gpr[rt] = mfspr(SPRN_PVR); break; vcpu->arch.gpr[rt] = vcpu->arch.pvr; break;
case SPRN_PIR: case SPRN_PIR:
vcpu->arch.gpr[rt] = mfspr(SPRN_PIR); break; vcpu->arch.gpr[rt] = vcpu->vcpu_id; break;
case SPRN_MSSSR0:
vcpu->arch.gpr[rt] = 0; break;
/* Note: mftb and TBRL/TBWL are user-accessible, so /* Note: mftb and TBRL/TBWL are user-accessible, so
* the guest can always access the real TB anyways. * the guest can always access the real TB anyways.
* In fact, we probably will never see these traps. */ * In fact, we probably will never see these traps. */
case SPRN_TBWL: case SPRN_TBWL:
vcpu->arch.gpr[rt] = mftbl(); break; vcpu->arch.gpr[rt] = get_tb() >> 32; break;
case SPRN_TBWU: case SPRN_TBWU:
vcpu->arch.gpr[rt] = mftbu(); break; vcpu->arch.gpr[rt] = get_tb(); break;
case SPRN_SPRG0: case SPRN_SPRG0:
vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break; vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break;
...@@ -215,11 +244,9 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) ...@@ -215,11 +244,9 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
case SPRN_DEC: case SPRN_DEC:
{ {
u64 jd = mftb() - vcpu->arch.dec_jiffies; u64 jd = get_tb() - vcpu->arch.dec_jiffies;
vcpu->arch.gpr[rt] = vcpu->arch.dec - jd; vcpu->arch.gpr[rt] = vcpu->arch.dec - jd;
#ifdef DEBUG_EMUL pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n", vcpu->arch.dec, jd, vcpu->arch.gpr[rt]);
printk(KERN_INFO "mfDEC: %x - %llx = %lx\n", vcpu->arch.dec, jd, vcpu->arch.gpr[rt]);
#endif
break; break;
} }
default: default:
...@@ -271,6 +298,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) ...@@ -271,6 +298,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
case SPRN_TBWL: break; case SPRN_TBWL: break;
case SPRN_TBWU: break; case SPRN_TBWU: break;
case SPRN_MSSSR0: break;
case SPRN_DEC: case SPRN_DEC:
vcpu->arch.dec = vcpu->arch.gpr[rs]; vcpu->arch.dec = vcpu->arch.gpr[rs];
kvmppc_emulate_dec(vcpu); kvmppc_emulate_dec(vcpu);
......
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