aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/44x_emulate.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2012-08-15 18:34:58 -0400
committerAlexander Graf <agraf@suse.de>2012-10-05 17:38:49 -0400
commitceb985f9d18cba2efdef08b8d31751c2c2b20d77 (patch)
treee01a89642eb8137dbf16c4b131bd7faf63c66271 /arch/powerpc/kvm/44x_emulate.c
parente4dcfe88fb30bcedda80c151018086fffb8280e6 (diff)
KVM: PPC: 440: Implement mfdcrx
We need mfdcrx to execute properly on 460 cores. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm/44x_emulate.c')
-rw-r--r--arch/powerpc/kvm/44x_emulate.c74
1 files changed, 43 insertions, 31 deletions
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c
index 3843a75e3e98..1a793c4c4a67 100644
--- a/arch/powerpc/kvm/44x_emulate.c
+++ b/arch/powerpc/kvm/44x_emulate.c
@@ -27,6 +27,7 @@
27#include "booke.h" 27#include "booke.h"
28#include "44x_tlb.h" 28#include "44x_tlb.h"
29 29
30#define XOP_MFDCRX 259
30#define XOP_MFDCR 323 31#define XOP_MFDCR 323
31#define XOP_MTDCRX 387 32#define XOP_MTDCRX 387
32#define XOP_MTDCR 451 33#define XOP_MTDCR 451
@@ -51,6 +52,43 @@ static int emulate_mtdcr(struct kvm_vcpu *vcpu, int rs, int dcrn)
51 } 52 }
52} 53}
53 54
55static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn)
56{
57 /* The guest may access CPR0 registers to determine the timebase
58 * frequency, and it must know the real host frequency because it
59 * can directly access the timebase registers.
60 *
61 * It would be possible to emulate those accesses in userspace,
62 * but userspace can really only figure out the end frequency.
63 * We could decompose that into the factors that compute it, but
64 * that's tricky math, and it's easier to just report the real
65 * CPR0 values.
66 */
67 switch (dcrn) {
68 case DCRN_CPR0_CONFIG_ADDR:
69 kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
70 break;
71 case DCRN_CPR0_CONFIG_DATA:
72 local_irq_disable();
73 mtdcr(DCRN_CPR0_CONFIG_ADDR,
74 vcpu->arch.cpr0_cfgaddr);
75 kvmppc_set_gpr(vcpu, rt,
76 mfdcr(DCRN_CPR0_CONFIG_DATA));
77 local_irq_enable();
78 break;
79 default:
80 vcpu->run->dcr.dcrn = dcrn;
81 vcpu->run->dcr.data = 0;
82 vcpu->run->dcr.is_write = 0;
83 vcpu->arch.io_gpr = rt;
84 vcpu->arch.dcr_needed = 1;
85 kvmppc_account_exit(vcpu, DCR_EXITS);
86 return EMULATE_DO_DCR;
87 }
88
89 return EMULATE_DONE;
90}
91
54int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, 92int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
55 unsigned int inst, int *advance) 93 unsigned int inst, int *advance)
56{ 94{
@@ -68,38 +106,12 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
68 switch (get_xop(inst)) { 106 switch (get_xop(inst)) {
69 107
70 case XOP_MFDCR: 108 case XOP_MFDCR:
71 /* The guest may access CPR0 registers to determine the timebase 109 emulated = emulate_mfdcr(vcpu, rt, dcrn);
72 * frequency, and it must know the real host frequency because it 110 break;
73 * can directly access the timebase registers.
74 *
75 * It would be possible to emulate those accesses in userspace,
76 * but userspace can really only figure out the end frequency.
77 * We could decompose that into the factors that compute it, but
78 * that's tricky math, and it's easier to just report the real
79 * CPR0 values.
80 */
81 switch (dcrn) {
82 case DCRN_CPR0_CONFIG_ADDR:
83 kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
84 break;
85 case DCRN_CPR0_CONFIG_DATA:
86 local_irq_disable();
87 mtdcr(DCRN_CPR0_CONFIG_ADDR,
88 vcpu->arch.cpr0_cfgaddr);
89 kvmppc_set_gpr(vcpu, rt,
90 mfdcr(DCRN_CPR0_CONFIG_DATA));
91 local_irq_enable();
92 break;
93 default:
94 run->dcr.dcrn = dcrn;
95 run->dcr.data = 0;
96 run->dcr.is_write = 0;
97 vcpu->arch.io_gpr = rt;
98 vcpu->arch.dcr_needed = 1;
99 kvmppc_account_exit(vcpu, DCR_EXITS);
100 emulated = EMULATE_DO_DCR;
101 }
102 111
112 case XOP_MFDCRX:
113 emulated = emulate_mfdcr(vcpu, rt,
114 kvmppc_get_gpr(vcpu, ra));
103 break; 115 break;
104 116
105 case XOP_MTDCR: 117 case XOP_MTDCR: