aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kvm/e500.h1
-rw-r--r--arch/powerpc/kvm/e500_emulate.c9
-rw-r--r--arch/powerpc/kvm/e500_tlb.c52
3 files changed, 62 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index f4dee55ae6c7..ce3f163f702e 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -124,6 +124,7 @@ int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500,
124int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu); 124int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu);
125int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu); 125int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu);
126int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb); 126int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb);
127int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb);
127int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb); 128int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb);
128int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500); 129int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500);
129void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500); 130void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500);
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index c80794d097d3..af02c18fc798 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -22,6 +22,7 @@
22#define XOP_TLBSX 914 22#define XOP_TLBSX 914
23#define XOP_TLBRE 946 23#define XOP_TLBRE 946
24#define XOP_TLBWE 978 24#define XOP_TLBWE 978
25#define XOP_TLBILX 18
25 26
26int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, 27int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
27 unsigned int inst, int *advance) 28 unsigned int inst, int *advance)
@@ -29,6 +30,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
29 int emulated = EMULATE_DONE; 30 int emulated = EMULATE_DONE;
30 int ra; 31 int ra;
31 int rb; 32 int rb;
33 int rt;
32 34
33 switch (get_op(inst)) { 35 switch (get_op(inst)) {
34 case 31: 36 case 31:
@@ -47,6 +49,13 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
47 emulated = kvmppc_e500_emul_tlbsx(vcpu,rb); 49 emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
48 break; 50 break;
49 51
52 case XOP_TLBILX:
53 ra = get_ra(inst);
54 rb = get_rb(inst);
55 rt = get_rt(inst);
56 emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb);
57 break;
58
50 case XOP_TLBIVAX: 59 case XOP_TLBIVAX:
51 ra = get_ra(inst); 60 ra = get_ra(inst);
52 rb = get_rb(inst); 61 rb = get_rb(inst);
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index c8ce51d03a2f..6eb5d655bdb4 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -631,6 +631,58 @@ int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb)
631 return EMULATE_DONE; 631 return EMULATE_DONE;
632} 632}
633 633
634static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
635 int pid, int rt)
636{
637 struct kvm_book3e_206_tlb_entry *tlbe;
638 int tid, esel;
639
640 /* invalidate all entries */
641 for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries; esel++) {
642 tlbe = get_entry(vcpu_e500, tlbsel, esel);
643 tid = get_tlb_tid(tlbe);
644 if (rt == 0 || tid == pid) {
645 inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
646 kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
647 }
648 }
649}
650
651static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
652 int ra, int rb)
653{
654 int tlbsel, esel;
655 gva_t ea;
656
657 ea = kvmppc_get_gpr(&vcpu_e500->vcpu, rb);
658 if (ra)
659 ea += kvmppc_get_gpr(&vcpu_e500->vcpu, ra);
660
661 for (tlbsel = 0; tlbsel < 2; tlbsel++) {
662 esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1);
663 if (esel >= 0) {
664 inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
665 kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
666 break;
667 }
668 }
669}
670
671int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb)
672{
673 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
674 int pid = get_cur_spid(vcpu);
675
676 if (rt == 0 || rt == 1) {
677 tlbilx_all(vcpu_e500, 0, pid, rt);
678 tlbilx_all(vcpu_e500, 1, pid, rt);
679 } else if (rt == 3) {
680 tlbilx_one(vcpu_e500, pid, ra, rb);
681 }
682
683 return EMULATE_DONE;
684}
685
634int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu) 686int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
635{ 687{
636 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); 688 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);