Skip to content

Commit

Permalink
KVM: PPC: e500: Add emulation helper for getting instruction ea
Browse files Browse the repository at this point in the history
Add emulation helper for getting instruction ea and refactor tlb instruction
emulation to use it.

Signed-off-by: Mihai Caraman <mihai.caraman@freescale.com>
[agraf: keep rt variable around]
Signed-off-by: Alexander Graf <agraf@suse.de>
  • Loading branch information
Mihai Caraman authored and Alexander Graf committed Dec 6, 2012
1 parent e51f8f3 commit 7cdd7a9
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 29 deletions.
11 changes: 11 additions & 0 deletions arch/powerpc/include/asm/kvm_ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,15 @@ static inline void kvmppc_lazy_ee_enable(void)
#endif
}

static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
{
ulong ea;

ea = kvmppc_get_gpr(vcpu, rb);
if (ra)
ea += kvmppc_get_gpr(vcpu, ra);

return ea;
}

#endif /* __POWERPC_KVM_PPC_H__ */
6 changes: 3 additions & 3 deletions arch/powerpc/kvm/e500.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
ulong value);
int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu);
int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb);
int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb);
int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb);
int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea);
int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea);
int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea);
int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);

Expand Down
14 changes: 10 additions & 4 deletions arch/powerpc/kvm/e500_emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
int ra = get_ra(inst);
int rb = get_rb(inst);
int rt = get_rt(inst);
gva_t ea;

switch (get_op(inst)) {
case 31:
Expand All @@ -113,15 +114,20 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;

case XOP_TLBSX:
emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
break;

case XOP_TLBILX:
emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
case XOP_TLBILX: {
int type = rt & 0x3;
ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
emulated = kvmppc_e500_emul_tlbilx(vcpu, type, ea);
break;
}

case XOP_TLBIVAX:
emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
break;

default:
Expand Down
33 changes: 11 additions & 22 deletions arch/powerpc/kvm/e500_tlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,14 +689,11 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
return EMULATE_DONE;
}

int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
unsigned int ia;
int esel, tlbsel;
gva_t ea;

ea = ((ra) ? kvmppc_get_gpr(vcpu, ra) : 0) + kvmppc_get_gpr(vcpu, rb);

ia = (ea >> 2) & 0x1;

Expand All @@ -723,7 +720,7 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
}

static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
int pid, int rt)
int pid, int type)
{
struct kvm_book3e_206_tlb_entry *tlbe;
int tid, esel;
Expand All @@ -732,22 +729,17 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries; esel++) {
tlbe = get_entry(vcpu_e500, tlbsel, esel);
tid = get_tlb_tid(tlbe);
if (rt == 0 || tid == pid) {
if (type == 0 || tid == pid) {
inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
}
}
}

static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
int ra, int rb)
gva_t ea)
{
int tlbsel, esel;
gva_t ea;

ea = kvmppc_get_gpr(&vcpu_e500->vcpu, rb);
if (ra)
ea += kvmppc_get_gpr(&vcpu_e500->vcpu, ra);

for (tlbsel = 0; tlbsel < 2; tlbsel++) {
esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1);
Expand All @@ -759,16 +751,16 @@ static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
}
}

int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb)
int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
int pid = get_cur_spid(vcpu);

if (rt == 0 || rt == 1) {
tlbilx_all(vcpu_e500, 0, pid, rt);
tlbilx_all(vcpu_e500, 1, pid, rt);
} else if (rt == 3) {
tlbilx_one(vcpu_e500, pid, ra, rb);
if (type == 0 || type == 1) {
tlbilx_all(vcpu_e500, 0, pid, type);
tlbilx_all(vcpu_e500, 1, pid, type);
} else if (type == 3) {
tlbilx_one(vcpu_e500, pid, ea);
}

return EMULATE_DONE;
Expand All @@ -793,16 +785,13 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
return EMULATE_DONE;
}

int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb)
int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
int as = !!get_cur_sas(vcpu);
unsigned int pid = get_cur_spid(vcpu);
int esel, tlbsel;
struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
gva_t ea;

ea = kvmppc_get_gpr(vcpu, rb);

for (tlbsel = 0; tlbsel < 2; tlbsel++) {
esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
Expand Down

0 comments on commit 7cdd7a9

Please sign in to comment.