Commit 7cdd7a95 authored by Mihai Caraman's avatar Mihai Caraman Committed by Alexander Graf

KVM: PPC: e500: Add emulation helper for getting instruction ea

Add emulation helper for getting instruction ea and refactor tlb instruction
emulation to use it.
Signed-off-by: default avatarMihai Caraman <mihai.caraman@freescale.com>
[agraf: keep rt variable around]
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent e51f8f32
...@@ -295,4 +295,15 @@ static inline void kvmppc_lazy_ee_enable(void) ...@@ -295,4 +295,15 @@ static inline void kvmppc_lazy_ee_enable(void)
#endif #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__ */ #endif /* __POWERPC_KVM_PPC_H__ */
...@@ -129,9 +129,9 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ...@@ -129,9 +129,9 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
ulong value); ulong value);
int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu); int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
int kvmppc_e500_emul_tlbre(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_tlbivax(struct kvm_vcpu *vcpu, gva_t ea);
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);
int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb); int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea);
int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500); int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500); void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
......
...@@ -89,6 +89,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -89,6 +89,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
int ra = get_ra(inst); int ra = get_ra(inst);
int rb = get_rb(inst); int rb = get_rb(inst);
int rt = get_rt(inst); int rt = get_rt(inst);
gva_t ea;
switch (get_op(inst)) { switch (get_op(inst)) {
case 31: case 31:
...@@ -113,15 +114,20 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -113,15 +114,20 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
break; break;
case XOP_TLBSX: 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; break;
case XOP_TLBILX: case XOP_TLBILX: {
emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb); int type = rt & 0x3;
ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
emulated = kvmppc_e500_emul_tlbilx(vcpu, type, ea);
break; break;
}
case XOP_TLBIVAX: 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; break;
default: default:
......
...@@ -689,14 +689,11 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value) ...@@ -689,14 +689,11 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
return EMULATE_DONE; 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); struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
unsigned int ia; unsigned int ia;
int esel, tlbsel; int esel, tlbsel;
gva_t ea;
ea = ((ra) ? kvmppc_get_gpr(vcpu, ra) : 0) + kvmppc_get_gpr(vcpu, rb);
ia = (ea >> 2) & 0x1; ia = (ea >> 2) & 0x1;
...@@ -723,7 +720,7 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb) ...@@ -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, 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; struct kvm_book3e_206_tlb_entry *tlbe;
int tid, esel; int tid, esel;
...@@ -732,7 +729,7 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel, ...@@ -732,7 +729,7 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries; esel++) { for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries; esel++) {
tlbe = get_entry(vcpu_e500, tlbsel, esel); tlbe = get_entry(vcpu_e500, tlbsel, esel);
tid = get_tlb_tid(tlbe); tid = get_tlb_tid(tlbe);
if (rt == 0 || tid == pid) { if (type == 0 || tid == pid) {
inval_gtlbe_on_host(vcpu_e500, tlbsel, esel); inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel); kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
} }
...@@ -740,14 +737,9 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel, ...@@ -740,14 +737,9 @@ static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
} }
static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid, static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
int ra, int rb) gva_t ea)
{ {
int tlbsel, esel; 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++) { for (tlbsel = 0; tlbsel < 2; tlbsel++) {
esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1); esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1);
...@@ -759,16 +751,16 @@ static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid, ...@@ -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); struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
int pid = get_cur_spid(vcpu); int pid = get_cur_spid(vcpu);
if (rt == 0 || rt == 1) { if (type == 0 || type == 1) {
tlbilx_all(vcpu_e500, 0, pid, rt); tlbilx_all(vcpu_e500, 0, pid, type);
tlbilx_all(vcpu_e500, 1, pid, rt); tlbilx_all(vcpu_e500, 1, pid, type);
} else if (rt == 3) { } else if (type == 3) {
tlbilx_one(vcpu_e500, pid, ra, rb); tlbilx_one(vcpu_e500, pid, ea);
} }
return EMULATE_DONE; return EMULATE_DONE;
...@@ -793,16 +785,13 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu) ...@@ -793,16 +785,13 @@ int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
return EMULATE_DONE; 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); struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
int as = !!get_cur_sas(vcpu); int as = !!get_cur_sas(vcpu);
unsigned int pid = get_cur_spid(vcpu); unsigned int pid = get_cur_spid(vcpu);
int esel, tlbsel; int esel, tlbsel;
struct kvm_book3e_206_tlb_entry *gtlbe = NULL; struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
gva_t ea;
ea = kvmppc_get_gpr(vcpu, rb);
for (tlbsel = 0; tlbsel < 2; tlbsel++) { for (tlbsel = 0; tlbsel < 2; tlbsel++) {
esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as); esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment