Skip to content

Commit

Permalink
Add desktop PowerPC specific emulation
Browse files Browse the repository at this point in the history
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: Alexander Graf <agraf@suse.de>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Alexander Graf authored and Benjamin Herrenschmidt committed Nov 5, 2009
1 parent 9a7a9b0 commit 513579e
Showing 1 changed file with 39 additions and 10 deletions.
49 changes: 39 additions & 10 deletions arch/powerpc/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "trace.h"

#define OP_TRAP 3
#define OP_TRAP_64 2

#define OP_31_XOP_LWZX 23
#define OP_31_XOP_LBZX 87
Expand Down Expand Up @@ -64,16 +65,36 @@
#define OP_STH 44
#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)
{
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
* that's how we convert the guest DEC value to the number of
* host ticks. */

vcpu->arch.dec_jiffies = mftb();
vcpu->arch.dec_jiffies = get_tb();
nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy;
mod_timer(&vcpu->arch.dec_timer,
get_jiffies_64() + nr_jiffies);
Expand Down Expand Up @@ -113,9 +134,15 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
/* this default type might be overwritten by subcategories */
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)) {
case OP_TRAP:
#ifdef CONFIG_PPC64
case OP_TRAP_64:
#else
vcpu->arch.esr |= ESR_PTR;
#endif
kvmppc_core_queue_program(vcpu);
advance = 0;
break;
Expand Down Expand Up @@ -190,17 +217,19 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
case SPRN_SRR1:
vcpu->arch.gpr[rt] = vcpu->arch.srr1; break;
case SPRN_PVR:
vcpu->arch.gpr[rt] = mfspr(SPRN_PVR); break;
vcpu->arch.gpr[rt] = vcpu->arch.pvr; break;
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
* the guest can always access the real TB anyways.
* In fact, we probably will never see these traps. */
case SPRN_TBWL:
vcpu->arch.gpr[rt] = mftbl(); break;
vcpu->arch.gpr[rt] = get_tb() >> 32; break;
case SPRN_TBWU:
vcpu->arch.gpr[rt] = mftbu(); break;
vcpu->arch.gpr[rt] = get_tb(); break;

case SPRN_SPRG0:
vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break;
Expand All @@ -215,11 +244,9 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)

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;
#ifdef DEBUG_EMUL
printk(KERN_INFO "mfDEC: %x - %llx = %lx\n", vcpu->arch.dec, jd, vcpu->arch.gpr[rt]);
#endif
pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n", vcpu->arch.dec, jd, vcpu->arch.gpr[rt]);
break;
}
default:
Expand Down Expand Up @@ -271,6 +298,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
case SPRN_TBWL: break;
case SPRN_TBWU: break;

case SPRN_MSSSR0: break;

case SPRN_DEC:
vcpu->arch.dec = vcpu->arch.gpr[rs];
kvmppc_emulate_dec(vcpu);
Expand Down

0 comments on commit 513579e

Please sign in to comment.