diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kvm/e500.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kvm/e500_emulate.c | 9 | ||||
-rw-r--r-- | arch/powerpc/kvm/e500_tlb.c | 52 |
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, | |||
124 | int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu); | 124 | int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu); |
125 | int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu); | 125 | int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu); |
126 | int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb); | 126 | int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, int ra, int rb); |
127 | int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int rt, int ra, int rb); | ||
127 | int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb); | 128 | int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, int rb); |
128 | int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500); | 129 | int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500); |
129 | void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500); | 130 | void 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 | ||
26 | int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | 27 | int 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 | ||
634 | static 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 | |||
651 | static 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 | |||
671 | int 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 | |||
634 | int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu) | 686 | int 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); |