mirror of
https://github.com/torvalds/linux.git
synced 2024-12-19 17:41:29 +00:00
KVM: PPC: 440: Implement mfdcrx
We need mfdcrx to execute properly on 460 cores. Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
e4dcfe88fb
commit
ceb985f9d1
@ -27,6 +27,7 @@
|
|||||||
#include "booke.h"
|
#include "booke.h"
|
||||||
#include "44x_tlb.h"
|
#include "44x_tlb.h"
|
||||||
|
|
||||||
|
#define XOP_MFDCRX 259
|
||||||
#define XOP_MFDCR 323
|
#define XOP_MFDCR 323
|
||||||
#define XOP_MTDCRX 387
|
#define XOP_MTDCRX 387
|
||||||
#define XOP_MTDCR 451
|
#define XOP_MTDCR 451
|
||||||
@ -51,6 +52,43 @@ static int emulate_mtdcr(struct kvm_vcpu *vcpu, int rs, int dcrn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn)
|
||||||
|
{
|
||||||
|
/* The guest may access CPR0 registers to determine the timebase
|
||||||
|
* frequency, and it must know the real host frequency because it
|
||||||
|
* can directly access the timebase registers.
|
||||||
|
*
|
||||||
|
* It would be possible to emulate those accesses in userspace,
|
||||||
|
* but userspace can really only figure out the end frequency.
|
||||||
|
* We could decompose that into the factors that compute it, but
|
||||||
|
* that's tricky math, and it's easier to just report the real
|
||||||
|
* CPR0 values.
|
||||||
|
*/
|
||||||
|
switch (dcrn) {
|
||||||
|
case DCRN_CPR0_CONFIG_ADDR:
|
||||||
|
kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
|
||||||
|
break;
|
||||||
|
case DCRN_CPR0_CONFIG_DATA:
|
||||||
|
local_irq_disable();
|
||||||
|
mtdcr(DCRN_CPR0_CONFIG_ADDR,
|
||||||
|
vcpu->arch.cpr0_cfgaddr);
|
||||||
|
kvmppc_set_gpr(vcpu, rt,
|
||||||
|
mfdcr(DCRN_CPR0_CONFIG_DATA));
|
||||||
|
local_irq_enable();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vcpu->run->dcr.dcrn = dcrn;
|
||||||
|
vcpu->run->dcr.data = 0;
|
||||||
|
vcpu->run->dcr.is_write = 0;
|
||||||
|
vcpu->arch.io_gpr = rt;
|
||||||
|
vcpu->arch.dcr_needed = 1;
|
||||||
|
kvmppc_account_exit(vcpu, DCR_EXITS);
|
||||||
|
return EMULATE_DO_DCR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EMULATE_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
||||||
unsigned int inst, int *advance)
|
unsigned int inst, int *advance)
|
||||||
{
|
{
|
||||||
@ -68,38 +106,12 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|||||||
switch (get_xop(inst)) {
|
switch (get_xop(inst)) {
|
||||||
|
|
||||||
case XOP_MFDCR:
|
case XOP_MFDCR:
|
||||||
/* The guest may access CPR0 registers to determine the timebase
|
emulated = emulate_mfdcr(vcpu, rt, dcrn);
|
||||||
* frequency, and it must know the real host frequency because it
|
break;
|
||||||
* can directly access the timebase registers.
|
|
||||||
*
|
|
||||||
* It would be possible to emulate those accesses in userspace,
|
|
||||||
* but userspace can really only figure out the end frequency.
|
|
||||||
* We could decompose that into the factors that compute it, but
|
|
||||||
* that's tricky math, and it's easier to just report the real
|
|
||||||
* CPR0 values.
|
|
||||||
*/
|
|
||||||
switch (dcrn) {
|
|
||||||
case DCRN_CPR0_CONFIG_ADDR:
|
|
||||||
kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
|
|
||||||
break;
|
|
||||||
case DCRN_CPR0_CONFIG_DATA:
|
|
||||||
local_irq_disable();
|
|
||||||
mtdcr(DCRN_CPR0_CONFIG_ADDR,
|
|
||||||
vcpu->arch.cpr0_cfgaddr);
|
|
||||||
kvmppc_set_gpr(vcpu, rt,
|
|
||||||
mfdcr(DCRN_CPR0_CONFIG_DATA));
|
|
||||||
local_irq_enable();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
run->dcr.dcrn = dcrn;
|
|
||||||
run->dcr.data = 0;
|
|
||||||
run->dcr.is_write = 0;
|
|
||||||
vcpu->arch.io_gpr = rt;
|
|
||||||
vcpu->arch.dcr_needed = 1;
|
|
||||||
kvmppc_account_exit(vcpu, DCR_EXITS);
|
|
||||||
emulated = EMULATE_DO_DCR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
case XOP_MFDCRX:
|
||||||
|
emulated = emulate_mfdcr(vcpu, rt,
|
||||||
|
kvmppc_get_gpr(vcpu, ra));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XOP_MTDCR:
|
case XOP_MTDCR:
|
||||||
|
Loading…
Reference in New Issue
Block a user