Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: PPC: factor out lpid allocator from book3s_64_mmu_hv

We'll use it on e500mc as well.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>

authored by

Scott Wood and committed by
Avi Kivity
043cc4d7 06aae867

+55 -16
+3
arch/powerpc/include/asm/kvm_book3s.h
··· 452 452 453 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 458 #endif /* __ASM_KVM_BOOK3S_H__ */
+3
arch/powerpc/include/asm/kvm_booke.h
··· 23 23 #include <linux/types.h> 24 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 + 26 29 static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) 27 30 { 28 31 vcpu->arch.gpr[num] = val;
+5
arch/powerpc/include/asm/kvm_ppc.h
··· 204 204 int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu, 205 205 struct kvm_dirty_tlb *cfg); 206 206 207 + long kvmppc_alloc_lpid(void); 208 + void kvmppc_claim_lpid(long lpid); 209 + void kvmppc_free_lpid(long lpid); 210 + void kvmppc_init_lpid(unsigned long nr_lpids); 211 + 207 212 #endif /* __POWERPC_KVM_PPC_H__ */
+10 -16
arch/powerpc/kvm/book3s_64_mmu_hv.c
··· 36 36 37 37 /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */ 38 38 #define MAX_LPID_970 63 39 - #define NR_LPIDS (LPID_RSVD + 1) 40 - unsigned long lpid_inuse[BITS_TO_LONGS(NR_LPIDS)]; 41 39 42 40 long kvmppc_alloc_hpt(struct kvm *kvm) 43 41 { 44 42 unsigned long hpt; 45 - unsigned long lpid; 43 + long lpid; 46 44 struct revmap_entry *rev; 47 45 struct kvmppc_linear_info *li; 48 46 ··· 70 72 } 71 73 kvm->arch.revmap = rev; 72 74 73 - /* Allocate the guest's logical partition ID */ 74 - do { 75 - lpid = find_first_zero_bit(lpid_inuse, NR_LPIDS); 76 - if (lpid >= NR_LPIDS) { 77 - pr_err("kvm_alloc_hpt: No LPIDs free\n"); 78 - goto out_freeboth; 79 - } 80 - } while (test_and_set_bit(lpid, lpid_inuse)); 75 + lpid = kvmppc_alloc_lpid(); 76 + if (lpid < 0) 77 + goto out_freeboth; 81 78 82 79 kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18); 83 80 kvm->arch.lpid = lpid; ··· 89 96 90 97 void kvmppc_free_hpt(struct kvm *kvm) 91 98 { 92 - clear_bit(kvm->arch.lpid, lpid_inuse); 99 + kvmppc_free_lpid(kvm->arch.lpid); 93 100 vfree(kvm->arch.revmap); 94 101 if (kvm->arch.hpt_li) 95 102 kvm_release_hpt(kvm->arch.hpt_li); ··· 164 171 if (!cpu_has_feature(CPU_FTR_HVMODE)) 165 172 return -EINVAL; 166 173 167 - memset(lpid_inuse, 0, sizeof(lpid_inuse)); 168 - 174 + /* POWER7 has 10-bit LPIDs, PPC970 and e500mc have 6-bit LPIDs */ 169 175 if (cpu_has_feature(CPU_FTR_ARCH_206)) { 170 176 host_lpid = mfspr(SPRN_LPID); /* POWER7 */ 171 177 rsvd_lpid = LPID_RSVD; ··· 173 181 rsvd_lpid = MAX_LPID_970; 174 182 } 175 183 176 - set_bit(host_lpid, lpid_inuse); 184 + kvmppc_init_lpid(rsvd_lpid + 1); 185 + 186 + kvmppc_claim_lpid(host_lpid); 177 187 /* rsvd_lpid is reserved for use in partition switching */ 178 - set_bit(rsvd_lpid, lpid_inuse); 188 + kvmppc_claim_lpid(rsvd_lpid); 179 189 180 190 return 0; 181 191 }
+34
arch/powerpc/kvm/powerpc.c
··· 799 799 return r; 800 800 } 801 801 802 + static unsigned long lpid_inuse[BITS_TO_LONGS(KVMPPC_NR_LPIDS)]; 803 + static unsigned long nr_lpids; 804 + 805 + long 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 + 820 + void kvmppc_claim_lpid(long lpid) 821 + { 822 + set_bit(lpid, lpid_inuse); 823 + } 824 + 825 + void kvmppc_free_lpid(long lpid) 826 + { 827 + clear_bit(lpid, lpid_inuse); 828 + } 829 + 830 + void 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 + 802 836 int kvm_arch_init(void *opaque) 803 837 { 804 838 return 0;