aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h3
-rw-r--r--arch/powerpc/include/asm/kvm_booke.h3
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h5
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c26
-rw-r--r--arch/powerpc/kvm/powerpc.c34
5 files changed, 55 insertions, 16 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index aa795ccef294..046041ff847f 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -452,4 +452,7 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
452 452
453#define INS_DCBZ 0x7c0007ec 453#define INS_DCBZ 0x7c0007ec
454 454
455/* LPIDs we support with this build -- runtime limit may be lower */
456#define KVMPPC_NR_LPIDS (LPID_RSVD + 1)
457
455#endif /* __ASM_KVM_BOOK3S_H__ */ 458#endif /* __ASM_KVM_BOOK3S_H__ */
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h
index a90e09188777..b7cd3356a532 100644
--- a/arch/powerpc/include/asm/kvm_booke.h
+++ b/arch/powerpc/include/asm/kvm_booke.h
@@ -23,6 +23,9 @@
23#include <linux/types.h> 23#include <linux/types.h>
24#include <linux/kvm_host.h> 24#include <linux/kvm_host.h>
25 25
26/* LPIDs we support with this build -- runtime limit may be lower */
27#define KVMPPC_NR_LPIDS 64
28
26static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) 29static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
27{ 30{
28 vcpu->arch.gpr[num] = val; 31 vcpu->arch.gpr[num] = val;
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 9d6dee0f7d48..731e920eda1e 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -204,4 +204,9 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
204int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu, 204int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
205 struct kvm_dirty_tlb *cfg); 205 struct kvm_dirty_tlb *cfg);
206 206
207long kvmppc_alloc_lpid(void);
208void kvmppc_claim_lpid(long lpid);
209void kvmppc_free_lpid(long lpid);
210void kvmppc_init_lpid(unsigned long nr_lpids);
211
207#endif /* __POWERPC_KVM_PPC_H__ */ 212#endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index ddc485a529f2..d031ce1d83f5 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -36,13 +36,11 @@
36 36
37/* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */ 37/* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
38#define MAX_LPID_970 63 38#define MAX_LPID_970 63
39#define NR_LPIDS (LPID_RSVD + 1)
40unsigned long lpid_inuse[BITS_TO_LONGS(NR_LPIDS)];
41 39
42long kvmppc_alloc_hpt(struct kvm *kvm) 40long kvmppc_alloc_hpt(struct kvm *kvm)
43{ 41{
44 unsigned long hpt; 42 unsigned long hpt;
45 unsigned long lpid; 43 long lpid;
46 struct revmap_entry *rev; 44 struct revmap_entry *rev;
47 struct kvmppc_linear_info *li; 45 struct kvmppc_linear_info *li;
48 46
@@ -72,14 +70,9 @@ long kvmppc_alloc_hpt(struct kvm *kvm)
72 } 70 }
73 kvm->arch.revmap = rev; 71 kvm->arch.revmap = rev;
74 72
75 /* Allocate the guest's logical partition ID */ 73 lpid = kvmppc_alloc_lpid();
76 do { 74 if (lpid < 0)
77 lpid = find_first_zero_bit(lpid_inuse, NR_LPIDS); 75 goto out_freeboth;
78 if (lpid >= NR_LPIDS) {
79 pr_err("kvm_alloc_hpt: No LPIDs free\n");
80 goto out_freeboth;
81 }
82 } while (test_and_set_bit(lpid, lpid_inuse));
83 76
84 kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18); 77 kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18);
85 kvm->arch.lpid = lpid; 78 kvm->arch.lpid = lpid;
@@ -96,7 +89,7 @@ long kvmppc_alloc_hpt(struct kvm *kvm)
96 89
97void kvmppc_free_hpt(struct kvm *kvm) 90void kvmppc_free_hpt(struct kvm *kvm)
98{ 91{
99 clear_bit(kvm->arch.lpid, lpid_inuse); 92 kvmppc_free_lpid(kvm->arch.lpid);
100 vfree(kvm->arch.revmap); 93 vfree(kvm->arch.revmap);
101 if (kvm->arch.hpt_li) 94 if (kvm->arch.hpt_li)
102 kvm_release_hpt(kvm->arch.hpt_li); 95 kvm_release_hpt(kvm->arch.hpt_li);
@@ -171,8 +164,7 @@ int kvmppc_mmu_hv_init(void)
171 if (!cpu_has_feature(CPU_FTR_HVMODE)) 164 if (!cpu_has_feature(CPU_FTR_HVMODE))
172 return -EINVAL; 165 return -EINVAL;
173 166
174 memset(lpid_inuse, 0, sizeof(lpid_inuse)); 167 /* POWER7 has 10-bit LPIDs, PPC970 and e500mc have 6-bit LPIDs */
175
176 if (cpu_has_feature(CPU_FTR_ARCH_206)) { 168 if (cpu_has_feature(CPU_FTR_ARCH_206)) {
177 host_lpid = mfspr(SPRN_LPID); /* POWER7 */ 169 host_lpid = mfspr(SPRN_LPID); /* POWER7 */
178 rsvd_lpid = LPID_RSVD; 170 rsvd_lpid = LPID_RSVD;
@@ -181,9 +173,11 @@ int kvmppc_mmu_hv_init(void)
181 rsvd_lpid = MAX_LPID_970; 173 rsvd_lpid = MAX_LPID_970;
182 } 174 }
183 175
184 set_bit(host_lpid, lpid_inuse); 176 kvmppc_init_lpid(rsvd_lpid + 1);
177
178 kvmppc_claim_lpid(host_lpid);
185 /* rsvd_lpid is reserved for use in partition switching */ 179 /* rsvd_lpid is reserved for use in partition switching */
186 set_bit(rsvd_lpid, lpid_inuse); 180 kvmppc_claim_lpid(rsvd_lpid);
187 181
188 return 0; 182 return 0;
189} 183}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index b5e9046462fd..cd53e08403b3 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -799,6 +799,40 @@ out:
799 return r; 799 return r;
800} 800}
801 801
802static unsigned long lpid_inuse[BITS_TO_LONGS(KVMPPC_NR_LPIDS)];
803static unsigned long nr_lpids;
804
805long kvmppc_alloc_lpid(void)
806{
807 long lpid;
808
809 do {
810 lpid = find_first_zero_bit(lpid_inuse, KVMPPC_NR_LPIDS);
811 if (lpid >= nr_lpids) {
812 pr_err("%s: No LPIDs free\n", __func__);
813 return -ENOMEM;
814 }
815 } while (test_and_set_bit(lpid, lpid_inuse));
816
817 return lpid;
818}
819
820void kvmppc_claim_lpid(long lpid)
821{
822 set_bit(lpid, lpid_inuse);
823}
824
825void kvmppc_free_lpid(long lpid)
826{
827 clear_bit(lpid, lpid_inuse);
828}
829
830void kvmppc_init_lpid(unsigned long nr_lpids_param)
831{
832 nr_lpids = min_t(unsigned long, KVMPPC_NR_LPIDS, nr_lpids_param);
833 memset(lpid_inuse, 0, sizeof(lpid_inuse));
834}
835
802int kvm_arch_init(void *opaque) 836int kvm_arch_init(void *opaque)
803{ 837{
804 return 0; 838 return 0;