2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-21 03:33:59 +08:00

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: Alexander Graf <agraf@suse.de>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
Alexander Graf 2009-10-30 05:47:16 +00:00 committed by Benjamin Herrenschmidt
parent 9a7a9b09fe
commit 513579e3a3

View File

@ -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 @@
#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)
/* 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)
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)
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)
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);