Skip to content

Commit

Permalink
KVM: PPC: factor out lpid allocator from book3s_64_mmu_hv
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Scott Wood authored and Avi Kivity committed Apr 8, 2012
1 parent 06aae86 commit 043cc4d
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 16 deletions.
3 changes: 3 additions & 0 deletions arch/powerpc/include/asm/kvm_book3s.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 3 additions & 0 deletions arch/powerpc/include/asm/kvm_booke.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions arch/powerpc/include/asm/kvm_ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
26 changes: 10 additions & 16 deletions arch/powerpc/kvm/book3s_64_mmu_hv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down
34 changes: 34 additions & 0 deletions arch/powerpc/kvm/powerpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 043cc4d

Please sign in to comment.