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>
This commit is contained in:
parent
06aae86799
commit
043cc4d724
5 changed files with 55 additions and 16 deletions
|
@ -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 @@
|
||||||
#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,
|
||||||
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 @@
|
||||||
|
|
||||||
/* 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)
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
if (lpid >= NR_LPIDS) {
|
|
||||||
pr_err("kvm_alloc_hpt: No LPIDs free\n");
|
|
||||||
goto out_freeboth;
|
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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 @@ out:
|
||||||
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue