diff options
-rw-r--r-- | arch/powerpc/include/asm/kvm.h | 18 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_asm.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s.c | 49 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_emulate.c | 38 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 3 | ||||
-rw-r--r-- | include/linux/kvm.h | 3 |
8 files changed, 101 insertions, 16 deletions
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index c9ca97f43bc1..81f3b0b5601e 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h | |||
@@ -47,7 +47,23 @@ struct kvm_regs { | |||
47 | 47 | ||
48 | struct kvm_sregs { | 48 | struct kvm_sregs { |
49 | __u32 pvr; | 49 | __u32 pvr; |
50 | char pad[1020]; | 50 | union { |
51 | struct { | ||
52 | __u64 sdr1; | ||
53 | struct { | ||
54 | struct { | ||
55 | __u64 slbe; | ||
56 | __u64 slbv; | ||
57 | } slb[64]; | ||
58 | } ppc64; | ||
59 | struct { | ||
60 | __u32 sr[16]; | ||
61 | __u64 ibat[8]; | ||
62 | __u64 dbat[8]; | ||
63 | } ppc32; | ||
64 | } s; | ||
65 | __u8 pad[1020]; | ||
66 | } u; | ||
51 | }; | 67 | }; |
52 | 68 | ||
53 | struct kvm_fpu { | 69 | struct kvm_fpu { |
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 19ddb352fd0f..af2abe74f544 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h | |||
@@ -87,6 +87,7 @@ | |||
87 | #define BOOK3S_IRQPRIO_MAX 16 | 87 | #define BOOK3S_IRQPRIO_MAX 16 |
88 | 88 | ||
89 | #define BOOK3S_HFLAG_DCBZ32 0x1 | 89 | #define BOOK3S_HFLAG_DCBZ32 0x1 |
90 | #define BOOK3S_HFLAG_SLB 0x2 | ||
90 | 91 | ||
91 | #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ | 92 | #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ |
92 | #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ | 93 | #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ |
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index c6011336371e..74b7369770d0 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h | |||
@@ -46,6 +46,7 @@ struct kvmppc_sr { | |||
46 | }; | 46 | }; |
47 | 47 | ||
48 | struct kvmppc_bat { | 48 | struct kvmppc_bat { |
49 | u64 raw; | ||
49 | u32 bepi; | 50 | u32 bepi; |
50 | u32 bepi_mask; | 51 | u32 bepi_mask; |
51 | bool vs; | 52 | bool vs; |
@@ -113,6 +114,8 @@ extern struct kvmppc_pte *kvmppc_mmu_find_pte(struct kvm_vcpu *vcpu, u64 ea, boo | |||
113 | extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr, bool data); | 114 | extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr, bool data); |
114 | extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr); | 115 | extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr); |
115 | extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec); | 116 | extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec); |
117 | extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, | ||
118 | bool upper, u32 val); | ||
116 | 119 | ||
117 | extern u32 kvmppc_trampoline_lowmem; | 120 | extern u32 kvmppc_trampoline_lowmem; |
118 | extern u32 kvmppc_trampoline_enter; | 121 | extern u32 kvmppc_trampoline_enter; |
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 42037d46a416..3e294bd9b8c6 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c | |||
@@ -281,6 +281,7 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | |||
281 | 281 | ||
282 | void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) | 282 | void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) |
283 | { | 283 | { |
284 | vcpu->arch.hflags &= ~BOOK3S_HFLAG_SLB; | ||
284 | vcpu->arch.pvr = pvr; | 285 | vcpu->arch.pvr = pvr; |
285 | if ((pvr >= 0x330000) && (pvr < 0x70330000)) { | 286 | if ((pvr >= 0x330000) && (pvr < 0x70330000)) { |
286 | kvmppc_mmu_book3s_64_init(vcpu); | 287 | kvmppc_mmu_book3s_64_init(vcpu); |
@@ -762,14 +763,62 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
762 | int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | 763 | int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, |
763 | struct kvm_sregs *sregs) | 764 | struct kvm_sregs *sregs) |
764 | { | 765 | { |
766 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); | ||
767 | int i; | ||
768 | |||
765 | sregs->pvr = vcpu->arch.pvr; | 769 | sregs->pvr = vcpu->arch.pvr; |
770 | |||
771 | sregs->u.s.sdr1 = to_book3s(vcpu)->sdr1; | ||
772 | if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) { | ||
773 | for (i = 0; i < 64; i++) { | ||
774 | sregs->u.s.ppc64.slb[i].slbe = vcpu3s->slb[i].orige | i; | ||
775 | sregs->u.s.ppc64.slb[i].slbv = vcpu3s->slb[i].origv; | ||
776 | } | ||
777 | } else { | ||
778 | for (i = 0; i < 16; i++) { | ||
779 | sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw; | ||
780 | sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw; | ||
781 | } | ||
782 | for (i = 0; i < 8; i++) { | ||
783 | sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw; | ||
784 | sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw; | ||
785 | } | ||
786 | } | ||
766 | return 0; | 787 | return 0; |
767 | } | 788 | } |
768 | 789 | ||
769 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | 790 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, |
770 | struct kvm_sregs *sregs) | 791 | struct kvm_sregs *sregs) |
771 | { | 792 | { |
793 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); | ||
794 | int i; | ||
795 | |||
772 | kvmppc_set_pvr(vcpu, sregs->pvr); | 796 | kvmppc_set_pvr(vcpu, sregs->pvr); |
797 | |||
798 | vcpu3s->sdr1 = sregs->u.s.sdr1; | ||
799 | if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) { | ||
800 | for (i = 0; i < 64; i++) { | ||
801 | vcpu->arch.mmu.slbmte(vcpu, sregs->u.s.ppc64.slb[i].slbv, | ||
802 | sregs->u.s.ppc64.slb[i].slbe); | ||
803 | } | ||
804 | } else { | ||
805 | for (i = 0; i < 16; i++) { | ||
806 | vcpu->arch.mmu.mtsrin(vcpu, i, sregs->u.s.ppc32.sr[i]); | ||
807 | } | ||
808 | for (i = 0; i < 8; i++) { | ||
809 | kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), false, | ||
810 | (u32)sregs->u.s.ppc32.ibat[i]); | ||
811 | kvmppc_set_bat(vcpu, &(vcpu3s->ibat[i]), true, | ||
812 | (u32)(sregs->u.s.ppc32.ibat[i] >> 32)); | ||
813 | kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), false, | ||
814 | (u32)sregs->u.s.ppc32.dbat[i]); | ||
815 | kvmppc_set_bat(vcpu, &(vcpu3s->dbat[i]), true, | ||
816 | (u32)(sregs->u.s.ppc32.dbat[i] >> 32)); | ||
817 | } | ||
818 | } | ||
819 | |||
820 | /* Flush the MMU after messing with the segments */ | ||
821 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | ||
773 | return 0; | 822 | return 0; |
774 | } | 823 | } |
775 | 824 | ||
diff --git a/arch/powerpc/kvm/book3s_64_emulate.c b/arch/powerpc/kvm/book3s_64_emulate.c index c343e67306e0..1027eac6d474 100644 --- a/arch/powerpc/kvm/book3s_64_emulate.c +++ b/arch/powerpc/kvm/book3s_64_emulate.c | |||
@@ -185,7 +185,27 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
185 | return emulated; | 185 | return emulated; |
186 | } | 186 | } |
187 | 187 | ||
188 | static void kvmppc_write_bat(struct kvm_vcpu *vcpu, int sprn, u64 val) | 188 | void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, bool upper, |
189 | u32 val) | ||
190 | { | ||
191 | if (upper) { | ||
192 | /* Upper BAT */ | ||
193 | u32 bl = (val >> 2) & 0x7ff; | ||
194 | bat->bepi_mask = (~bl << 17); | ||
195 | bat->bepi = val & 0xfffe0000; | ||
196 | bat->vs = (val & 2) ? 1 : 0; | ||
197 | bat->vp = (val & 1) ? 1 : 0; | ||
198 | bat->raw = (bat->raw & 0xffffffff00000000ULL) | val; | ||
199 | } else { | ||
200 | /* Lower BAT */ | ||
201 | bat->brpn = val & 0xfffe0000; | ||
202 | bat->wimg = (val >> 3) & 0xf; | ||
203 | bat->pp = val & 3; | ||
204 | bat->raw = (bat->raw & 0x00000000ffffffffULL) | ((u64)val << 32); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | static void kvmppc_write_bat(struct kvm_vcpu *vcpu, int sprn, u32 val) | ||
189 | { | 209 | { |
190 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | 210 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); |
191 | struct kvmppc_bat *bat; | 211 | struct kvmppc_bat *bat; |
@@ -207,19 +227,7 @@ static void kvmppc_write_bat(struct kvm_vcpu *vcpu, int sprn, u64 val) | |||
207 | BUG(); | 227 | BUG(); |
208 | } | 228 | } |
209 | 229 | ||
210 | if (!(sprn % 2)) { | 230 | kvmppc_set_bat(vcpu, bat, !(sprn % 2), val); |
211 | /* Upper BAT */ | ||
212 | u32 bl = (val >> 2) & 0x7ff; | ||
213 | bat->bepi_mask = (~bl << 17); | ||
214 | bat->bepi = val & 0xfffe0000; | ||
215 | bat->vs = (val & 2) ? 1 : 0; | ||
216 | bat->vp = (val & 1) ? 1 : 0; | ||
217 | } else { | ||
218 | /* Lower BAT */ | ||
219 | bat->brpn = val & 0xfffe0000; | ||
220 | bat->wimg = (val >> 3) & 0xf; | ||
221 | bat->pp = val & 3; | ||
222 | } | ||
223 | } | 231 | } |
224 | 232 | ||
225 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | 233 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) |
@@ -243,7 +251,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | |||
243 | case SPRN_IBAT4U ... SPRN_IBAT7L: | 251 | case SPRN_IBAT4U ... SPRN_IBAT7L: |
244 | case SPRN_DBAT0U ... SPRN_DBAT3L: | 252 | case SPRN_DBAT0U ... SPRN_DBAT3L: |
245 | case SPRN_DBAT4U ... SPRN_DBAT7L: | 253 | case SPRN_DBAT4U ... SPRN_DBAT7L: |
246 | kvmppc_write_bat(vcpu, sprn, vcpu->arch.gpr[rs]); | 254 | kvmppc_write_bat(vcpu, sprn, (u32)vcpu->arch.gpr[rs]); |
247 | /* BAT writes happen so rarely that we're ok to flush | 255 | /* BAT writes happen so rarely that we're ok to flush |
248 | * everything here */ | 256 | * everything here */ |
249 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | 257 | kvmppc_mmu_pte_flush(vcpu, 0, 0); |
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c index a31f9c677d23..5598f88f142e 100644 --- a/arch/powerpc/kvm/book3s_64_mmu.c +++ b/arch/powerpc/kvm/book3s_64_mmu.c | |||
@@ -473,4 +473,6 @@ void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu) | |||
473 | mmu->esid_to_vsid = kvmppc_mmu_book3s_64_esid_to_vsid; | 473 | mmu->esid_to_vsid = kvmppc_mmu_book3s_64_esid_to_vsid; |
474 | mmu->ea_to_vp = kvmppc_mmu_book3s_64_ea_to_vp; | 474 | mmu->ea_to_vp = kvmppc_mmu_book3s_64_ea_to_vp; |
475 | mmu->is_dcbz32 = kvmppc_mmu_book3s_64_is_dcbz32; | 475 | mmu->is_dcbz32 = kvmppc_mmu_book3s_64_is_dcbz32; |
476 | |||
477 | vcpu->arch.hflags |= BOOK3S_HFLAG_SLB; | ||
476 | } | 478 | } |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 692c3709011e..d82551efbfbf 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -144,6 +144,9 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
144 | int r; | 144 | int r; |
145 | 145 | ||
146 | switch (ext) { | 146 | switch (ext) { |
147 | case KVM_CAP_PPC_SEGSTATE: | ||
148 | r = 1; | ||
149 | break; | ||
147 | case KVM_CAP_COALESCED_MMIO: | 150 | case KVM_CAP_COALESCED_MMIO: |
148 | r = KVM_COALESCED_MMIO_PAGE_OFFSET; | 151 | r = KVM_COALESCED_MMIO_PAGE_OFFSET; |
149 | break; | 152 | break; |
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index f8f8900fc5ec..caf6173bd2e8 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -436,6 +436,9 @@ struct kvm_ioeventfd { | |||
436 | #endif | 436 | #endif |
437 | #define KVM_CAP_IOEVENTFD 36 | 437 | #define KVM_CAP_IOEVENTFD 36 |
438 | #define KVM_CAP_SET_IDENTITY_MAP_ADDR 37 | 438 | #define KVM_CAP_SET_IDENTITY_MAP_ADDR 37 |
439 | /* KVM upstream has more features, but we synched this number. | ||
440 | Linux, please remove this comment on rebase. */ | ||
441 | #define KVM_CAP_PPC_SEGSTATE 43 | ||
439 | 442 | ||
440 | #ifdef KVM_CAP_IRQ_ROUTING | 443 | #ifdef KVM_CAP_IRQ_ROUTING |
441 | 444 | ||