提交 043cc4d7 编写于 作者: S Scott Wood 提交者: Avi Kivity

KVM: PPC: factor out lpid allocator from book3s_64_mmu_hv

We'll use it on e500mc as well.
Signed-off-by: NScott Wood <scottwood@freescale.com>
Signed-off-by: NAlexander Graf <agraf@suse.de>
Signed-off-by: NAvi Kivity <avi@redhat.com>
上级 06aae867
...@@ -452,4 +452,7 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu) ...@@ -452,4 +452,7 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
#define INS_DCBZ 0x7c0007ec #define INS_DCBZ 0x7c0007ec
/* LPIDs we support with this build -- runtime limit may be lower */
#define KVMPPC_NR_LPIDS (LPID_RSVD + 1)
#endif /* __ASM_KVM_BOOK3S_H__ */ #endif /* __ASM_KVM_BOOK3S_H__ */
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/kvm_host.h> #include <linux/kvm_host.h>
/* LPIDs we support with this build -- runtime limit may be lower */
#define KVMPPC_NR_LPIDS 64
static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
{ {
vcpu->arch.gpr[num] = val; vcpu->arch.gpr[num] = val;
......
...@@ -204,4 +204,9 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu, ...@@ -204,4 +204,9 @@ int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu, int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
struct kvm_dirty_tlb *cfg); struct kvm_dirty_tlb *cfg);
long kvmppc_alloc_lpid(void);
void kvmppc_claim_lpid(long lpid);
void kvmppc_free_lpid(long lpid);
void kvmppc_init_lpid(unsigned long nr_lpids);
#endif /* __POWERPC_KVM_PPC_H__ */ #endif /* __POWERPC_KVM_PPC_H__ */
...@@ -36,13 +36,11 @@ ...@@ -36,13 +36,11 @@
/* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */ /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
#define MAX_LPID_970 63 #define MAX_LPID_970 63
#define NR_LPIDS (LPID_RSVD + 1)
unsigned long lpid_inuse[BITS_TO_LONGS(NR_LPIDS)];
long kvmppc_alloc_hpt(struct kvm *kvm) long kvmppc_alloc_hpt(struct kvm *kvm)
{ {
unsigned long hpt; unsigned long hpt;
unsigned long lpid; long lpid;
struct revmap_entry *rev; struct revmap_entry *rev;
struct kvmppc_linear_info *li; struct kvmppc_linear_info *li;
...@@ -72,14 +70,9 @@ long kvmppc_alloc_hpt(struct kvm *kvm) ...@@ -72,14 +70,9 @@ long kvmppc_alloc_hpt(struct kvm *kvm)
} }
kvm->arch.revmap = rev; kvm->arch.revmap = rev;
/* Allocate the guest's logical partition ID */ lpid = kvmppc_alloc_lpid();
do { if (lpid < 0)
lpid = find_first_zero_bit(lpid_inuse, NR_LPIDS); goto out_freeboth;
if (lpid >= NR_LPIDS) {
pr_err("kvm_alloc_hpt: No LPIDs free\n");
goto out_freeboth;
}
} while (test_and_set_bit(lpid, lpid_inuse));
kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18); kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18);
kvm->arch.lpid = lpid; kvm->arch.lpid = lpid;
...@@ -96,7 +89,7 @@ long kvmppc_alloc_hpt(struct kvm *kvm) ...@@ -96,7 +89,7 @@ long kvmppc_alloc_hpt(struct kvm *kvm)
void kvmppc_free_hpt(struct kvm *kvm) void kvmppc_free_hpt(struct kvm *kvm)
{ {
clear_bit(kvm->arch.lpid, lpid_inuse); kvmppc_free_lpid(kvm->arch.lpid);
vfree(kvm->arch.revmap); vfree(kvm->arch.revmap);
if (kvm->arch.hpt_li) if (kvm->arch.hpt_li)
kvm_release_hpt(kvm->arch.hpt_li); kvm_release_hpt(kvm->arch.hpt_li);
...@@ -171,8 +164,7 @@ int kvmppc_mmu_hv_init(void) ...@@ -171,8 +164,7 @@ int kvmppc_mmu_hv_init(void)
if (!cpu_has_feature(CPU_FTR_HVMODE)) if (!cpu_has_feature(CPU_FTR_HVMODE))
return -EINVAL; return -EINVAL;
memset(lpid_inuse, 0, sizeof(lpid_inuse)); /* POWER7 has 10-bit LPIDs, PPC970 and e500mc have 6-bit LPIDs */
if (cpu_has_feature(CPU_FTR_ARCH_206)) { if (cpu_has_feature(CPU_FTR_ARCH_206)) {
host_lpid = mfspr(SPRN_LPID); /* POWER7 */ host_lpid = mfspr(SPRN_LPID); /* POWER7 */
rsvd_lpid = LPID_RSVD; rsvd_lpid = LPID_RSVD;
...@@ -181,9 +173,11 @@ int kvmppc_mmu_hv_init(void) ...@@ -181,9 +173,11 @@ int kvmppc_mmu_hv_init(void)
rsvd_lpid = MAX_LPID_970; rsvd_lpid = MAX_LPID_970;
} }
set_bit(host_lpid, lpid_inuse); kvmppc_init_lpid(rsvd_lpid + 1);
kvmppc_claim_lpid(host_lpid);
/* rsvd_lpid is reserved for use in partition switching */ /* rsvd_lpid is reserved for use in partition switching */
set_bit(rsvd_lpid, lpid_inuse); kvmppc_claim_lpid(rsvd_lpid);
return 0; return 0;
} }
......
...@@ -799,6 +799,40 @@ long kvm_arch_vm_ioctl(struct file *filp, ...@@ -799,6 +799,40 @@ long kvm_arch_vm_ioctl(struct file *filp,
return r; return r;
} }
static unsigned long lpid_inuse[BITS_TO_LONGS(KVMPPC_NR_LPIDS)];
static unsigned long nr_lpids;
long kvmppc_alloc_lpid(void)
{
long lpid;
do {
lpid = find_first_zero_bit(lpid_inuse, KVMPPC_NR_LPIDS);
if (lpid >= nr_lpids) {
pr_err("%s: No LPIDs free\n", __func__);
return -ENOMEM;
}
} while (test_and_set_bit(lpid, lpid_inuse));
return lpid;
}
void kvmppc_claim_lpid(long lpid)
{
set_bit(lpid, lpid_inuse);
}
void kvmppc_free_lpid(long lpid)
{
clear_bit(lpid, lpid_inuse);
}
void kvmppc_init_lpid(unsigned long nr_lpids_param)
{
nr_lpids = min_t(unsigned long, KVMPPC_NR_LPIDS, nr_lpids_param);
memset(lpid_inuse, 0, sizeof(lpid_inuse));
}
int kvm_arch_init(void *opaque) int kvm_arch_init(void *opaque)
{ {
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册