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 | ||
