Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 343514
b: refs/heads/master
c: 388cf9e
h: refs/heads/master
v: v3
  • Loading branch information
Alexander Graf committed Oct 30, 2012
1 parent 42df2ad commit d030ea5
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 101 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 686de182a217d315e50fef74ba5e7bcd7ea6c246
refs/heads/master: 388cf9ee3c751c3a4cf8776987143354d6d8c797
221 changes: 121 additions & 100 deletions trunk/arch/powerpc/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,125 @@ u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
return vcpu->arch.dec - jd;
}

static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
{
enum emulation_result emulated = EMULATE_DONE;
ulong spr_val = kvmppc_get_gpr(vcpu, rs);

switch (sprn) {
case SPRN_SRR0:
vcpu->arch.shared->srr0 = spr_val;
break;
case SPRN_SRR1:
vcpu->arch.shared->srr1 = spr_val;
break;

/* XXX We need to context-switch the timebase for
* watchdog and FIT. */
case SPRN_TBWL: break;
case SPRN_TBWU: break;

case SPRN_MSSSR0: break;

case SPRN_DEC:
vcpu->arch.dec = spr_val;
kvmppc_emulate_dec(vcpu);
break;

case SPRN_SPRG0:
vcpu->arch.shared->sprg0 = spr_val;
break;
case SPRN_SPRG1:
vcpu->arch.shared->sprg1 = spr_val;
break;
case SPRN_SPRG2:
vcpu->arch.shared->sprg2 = spr_val;
break;
case SPRN_SPRG3:
vcpu->arch.shared->sprg3 = spr_val;
break;

default:
emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
spr_val);
if (emulated == EMULATE_FAIL)
printk(KERN_INFO "mtspr: unknown spr "
"0x%x\n", sprn);
break;
}

kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);

return emulated;
}

static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
{
enum emulation_result emulated = EMULATE_DONE;
ulong spr_val = 0;

switch (sprn) {
case SPRN_SRR0:
spr_val = vcpu->arch.shared->srr0;
break;
case SPRN_SRR1:
spr_val = vcpu->arch.shared->srr1;
break;
case SPRN_PVR:
spr_val = vcpu->arch.pvr;
break;
case SPRN_PIR:
spr_val = vcpu->vcpu_id;
break;
case SPRN_MSSSR0:
spr_val = 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:
spr_val = get_tb() >> 32;
break;
case SPRN_TBWU:
spr_val = get_tb();
break;

case SPRN_SPRG0:
spr_val = vcpu->arch.shared->sprg0;
break;
case SPRN_SPRG1:
spr_val = vcpu->arch.shared->sprg1;
break;
case SPRN_SPRG2:
spr_val = vcpu->arch.shared->sprg2;
break;
case SPRN_SPRG3:
spr_val = vcpu->arch.shared->sprg3;
break;
/* Note: SPRG4-7 are user-readable, so we don't get
* a trap. */

case SPRN_DEC:
spr_val = kvmppc_get_dec(vcpu, get_tb());
break;
default:
emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
&spr_val);
if (unlikely(emulated == EMULATE_FAIL)) {
printk(KERN_INFO "mfspr: unknown spr "
"0x%x\n", sprn);
}
break;
}

if (emulated == EMULATE_DONE)
kvmppc_set_gpr(vcpu, rt, spr_val);
kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);

return emulated;
}

/* XXX to do:
* lhax
* lhaux
Expand All @@ -156,7 +275,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
int sprn = get_sprn(inst);
enum emulation_result emulated = EMULATE_DONE;
int advance = 1;
ulong spr_val = 0;

/* this default type might be overwritten by subcategories */
kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
Expand Down Expand Up @@ -236,62 +354,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
break;

case OP_31_XOP_MFSPR:
switch (sprn) {
case SPRN_SRR0:
spr_val = vcpu->arch.shared->srr0;
break;
case SPRN_SRR1:
spr_val = vcpu->arch.shared->srr1;
break;
case SPRN_PVR:
spr_val = vcpu->arch.pvr;
break;
case SPRN_PIR:
spr_val = vcpu->vcpu_id;
break;
case SPRN_MSSSR0:
spr_val = 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:
spr_val = get_tb() >> 32;
break;
case SPRN_TBWU:
spr_val = get_tb();
break;

case SPRN_SPRG0:
spr_val = vcpu->arch.shared->sprg0;
break;
case SPRN_SPRG1:
spr_val = vcpu->arch.shared->sprg1;
break;
case SPRN_SPRG2:
spr_val = vcpu->arch.shared->sprg2;
break;
case SPRN_SPRG3:
spr_val = vcpu->arch.shared->sprg3;
break;
/* Note: SPRG4-7 are user-readable, so we don't get
* a trap. */

case SPRN_DEC:
spr_val = kvmppc_get_dec(vcpu, get_tb());
break;
default:
emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
&spr_val);
if (unlikely(emulated == EMULATE_FAIL)) {
printk(KERN_INFO "mfspr: unknown spr "
"0x%x\n", sprn);
}
break;
}
kvmppc_set_gpr(vcpu, rt, spr_val);
kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
break;

case OP_31_XOP_STHX:
Expand All @@ -308,49 +371,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
break;

case OP_31_XOP_MTSPR:
spr_val = kvmppc_get_gpr(vcpu, rs);
switch (sprn) {
case SPRN_SRR0:
vcpu->arch.shared->srr0 = spr_val;
break;
case SPRN_SRR1:
vcpu->arch.shared->srr1 = spr_val;
break;

/* XXX We need to context-switch the timebase for
* watchdog and FIT. */
case SPRN_TBWL: break;
case SPRN_TBWU: break;

case SPRN_MSSSR0: break;

case SPRN_DEC:
vcpu->arch.dec = spr_val;
kvmppc_emulate_dec(vcpu);
break;

case SPRN_SPRG0:
vcpu->arch.shared->sprg0 = spr_val;
break;
case SPRN_SPRG1:
vcpu->arch.shared->sprg1 = spr_val;
break;
case SPRN_SPRG2:
vcpu->arch.shared->sprg2 = spr_val;
break;
case SPRN_SPRG3:
vcpu->arch.shared->sprg3 = spr_val;
break;

default:
emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
spr_val);
if (emulated == EMULATE_FAIL)
printk(KERN_INFO "mtspr: unknown spr "
"0x%x\n", sprn);
break;
}
kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
break;

case OP_31_XOP_DCBI:
Expand Down

0 comments on commit d030ea5

Please sign in to comment.