diff options
author | Scott Wood <scottwood@freescale.com> | 2011-12-20 10:34:20 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2012-04-08 05:51:02 -0400 |
commit | 043cc4d724da6bb9e4f417c735accec58dfa40bf (patch) | |
tree | fa2d40741f8dcd636bb0c74f98f87cb88e6a2be4 /arch | |
parent | 06aae86799c1b37f216371e05a1eacb2188bee9d (diff) |
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s.h | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_booke.h | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 5 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_hv.c | 26 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 34 |
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 | |||
26 | static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) | 29 | static 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, | |||
204 | int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu, | 204 | int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu, |
205 | struct kvm_dirty_tlb *cfg); | 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 | #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) | ||
40 | unsigned long lpid_inuse[BITS_TO_LONGS(NR_LPIDS)]; | ||
41 | 39 | ||
42 | long kvmppc_alloc_hpt(struct kvm *kvm) | 40 | long 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 | ||
97 | void kvmppc_free_hpt(struct kvm *kvm) | 90 | void 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 | ||
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 | int kvm_arch_init(void *opaque) | 836 | int kvm_arch_init(void *opaque) |
803 | { | 837 | { |
804 | return 0; | 838 | return 0; |