Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 043cc4d7 authored by Scott Wood's avatar Scott Wood Committed by Avi Kivity
Browse files

KVM: PPC: factor out lpid allocator from book3s_64_mmu_hv



We'll use it on e500mc as well.

Signed-off-by: default avatarScott Wood <scottwood@freescale.com>
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 06aae867
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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__ */
+3 −0
Original line number Diff line number Diff line
@@ -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;
+5 −0
Original line number Diff line number Diff line
@@ -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__ */
+10 −16
Original line number Diff line number Diff line
@@ -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");
	lpid = kvmppc_alloc_lpid();
	if (lpid < 0)
		goto out_freeboth;
		}
	} while (test_and_set_bit(lpid, lpid_inuse));

	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;
}
+34 −0
Original line number Diff line number Diff line
@@ -799,6 +799,40 @@ long kvm_arch_vm_ioctl(struct file *filp,
	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;