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:
Родитель
06aae86799
Коммит
043cc4d724
|
@ -452,4 +452,7 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
|
|||
|
||||
#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__ */
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include <linux/types.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)
|
||||
{
|
||||
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,
|
||||
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__ */
|
||||
|
|
|
@ -36,13 +36,11 @@
|
|||
|
||||
/* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */
|
||||
#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)
|
||||
{
|
||||
unsigned long hpt;
|
||||
unsigned long lpid;
|
||||
long lpid;
|
||||
struct revmap_entry *rev;
|
||||
struct kvmppc_linear_info *li;
|
||||
|
||||
|
@ -72,14 +70,9 @@ long kvmppc_alloc_hpt(struct kvm *kvm)
|
|||
}
|
||||
kvm->arch.revmap = rev;
|
||||
|
||||
/* Allocate the guest's logical partition ID */
|
||||
do {
|
||||
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;
|
||||
}
|
||||
} while (test_and_set_bit(lpid, lpid_inuse));
|
||||
lpid = kvmppc_alloc_lpid();
|
||||
if (lpid < 0)
|
||||
goto out_freeboth;
|
||||
|
||||
kvm->arch.sdr1 = __pa(hpt) | (HPT_ORDER - 18);
|
||||
kvm->arch.lpid = lpid;
|
||||
|
@ -96,7 +89,7 @@ long kvmppc_alloc_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);
|
||||
if (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))
|
||||
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)) {
|
||||
host_lpid = mfspr(SPRN_LPID); /* POWER7 */
|
||||
rsvd_lpid = LPID_RSVD;
|
||||
|
@ -181,9 +173,11 @@ int kvmppc_mmu_hv_init(void)
|
|||
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 */
|
||||
set_bit(rsvd_lpid, lpid_inuse);
|
||||
kvmppc_claim_lpid(rsvd_lpid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -799,6 +799,40 @@ out:
|
|||
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)
|
||||
{
|
||||
return 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче