Skip to content

Commit aae0777

Browse files
dgibsonpaulusmack
authored andcommitted
KVM: PPC: Book3S HV: Split HPT allocation from activation
Currently, kvmppc_alloc_hpt() both allocates a new hashed page table (HPT) and sets it up as the active page table for a VM. For the upcoming HPT resize implementation we're going to want to allocate HPTs separately from activating them. So, split the allocation itself out into kvmppc_allocate_hpt() and perform the activation with a new kvmppc_set_hpt() function. Likewise we split kvmppc_free_hpt(), which just frees the HPT, from kvmppc_release_hpt() which unsets it as an active HPT, then frees it. We also move the logic to fall back to smaller HPT sizes if the first try fails into the single caller which used that behaviour, kvmppc_hv_setup_htab_rma(). This introduces a slight semantic change, in that previously if the initial attempt at CMA allocation failed, we would fall back to attempting smaller sizes with the page allocator. Now, we try first CMA, then the page allocator at each size. As far as I can tell this change should be harmless. To match, we make kvmppc_free_hpt() just free the actual HPT itself. The call to kvmppc_free_lpid() that was there, we move to the single caller. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 parent 3d089f8 commit aae0777

File tree

4 files changed

+68
-55
lines changed

4 files changed

+68
-55
lines changed

arch/powerpc/include/asm/kvm_book3s_64.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222

2323
#include <asm/book3s/64/mmu-hash.h>
2424

25+
/* Power architecture requires HPT is at least 256kiB, at most 64TiB */
26+
#define PPC_MIN_HPT_ORDER 18
27+
#define PPC_MAX_HPT_ORDER 46
28+
2529
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
2630
static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu)
2731
{

arch/powerpc/include/asm/kvm_ppc.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,10 @@ extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
155155
extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu);
156156
extern void kvmppc_map_magic(struct kvm_vcpu *vcpu);
157157

158-
extern long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp);
158+
extern int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order);
159+
extern void kvmppc_set_hpt(struct kvm *kvm, struct kvm_hpt_info *info);
159160
extern long kvmppc_alloc_reset_hpt(struct kvm *kvm, u32 *htab_orderp);
160-
extern void kvmppc_free_hpt(struct kvm *kvm);
161+
extern void kvmppc_free_hpt(struct kvm_hpt_info *info);
161162
extern long kvmppc_prepare_vrma(struct kvm *kvm,
162163
struct kvm_userspace_memory_region *mem);
163164
extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu,

arch/powerpc/kvm/book3s_64_mmu_hv.c

Lines changed: 47 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -40,74 +40,66 @@
4040

4141
#include "trace_hv.h"
4242

43-
/* Power architecture requires HPT is at least 256kB */
44-
#define PPC_MIN_HPT_ORDER 18
45-
4643
static long kvmppc_virtmode_do_h_enter(struct kvm *kvm, unsigned long flags,
4744
long pte_index, unsigned long pteh,
4845
unsigned long ptel, unsigned long *pte_idx_ret);
4946
static void kvmppc_rmap_reset(struct kvm *kvm);
5047

51-
long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
48+
int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order)
5249
{
5350
unsigned long hpt = 0;
54-
struct revmap_entry *rev;
51+
int cma = 0;
5552
struct page *page = NULL;
56-
long order = KVM_DEFAULT_HPT_ORDER;
53+
struct revmap_entry *rev;
54+
unsigned long npte;
5755

58-
if (htab_orderp) {
59-
order = *htab_orderp;
60-
if (order < PPC_MIN_HPT_ORDER)
61-
order = PPC_MIN_HPT_ORDER;
62-
}
56+
if ((order < PPC_MIN_HPT_ORDER) || (order > PPC_MAX_HPT_ORDER))
57+
return -EINVAL;
6358

64-
kvm->arch.hpt.cma = 0;
6559
page = kvm_alloc_hpt_cma(1ul << (order - PAGE_SHIFT));
6660
if (page) {
6761
hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
6862
memset((void *)hpt, 0, (1ul << order));
69-
kvm->arch.hpt.cma = 1;
63+
cma = 1;
7064
}
7165

72-
/* Lastly try successively smaller sizes from the page allocator */
73-
/* Only do this if userspace didn't specify a size via ioctl */
74-
while (!hpt && order > PPC_MIN_HPT_ORDER && !htab_orderp) {
75-
hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|
76-
__GFP_NOWARN, order - PAGE_SHIFT);
77-
if (!hpt)
78-
--order;
79-
}
66+
if (!hpt)
67+
hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT
68+
|__GFP_NOWARN, order - PAGE_SHIFT);
8069

8170
if (!hpt)
8271
return -ENOMEM;
8372

84-
kvm->arch.hpt.virt = hpt;
85-
kvm->arch.hpt.order = order;
86-
87-
atomic64_set(&kvm->arch.mmio_update, 0);
73+
/* HPTEs are 2**4 bytes long */
74+
npte = 1ul << (order - 4);
8875

8976
/* Allocate reverse map array */
90-
rev = vmalloc(sizeof(struct revmap_entry) * kvmppc_hpt_npte(&kvm->arch.hpt));
77+
rev = vmalloc(sizeof(struct revmap_entry) * npte);
9178
if (!rev) {
92-
pr_err("kvmppc_alloc_hpt: Couldn't alloc reverse map array\n");
93-
goto out_freehpt;
79+
pr_err("kvmppc_allocate_hpt: Couldn't alloc reverse map array\n");
80+
if (cma)
81+
kvm_free_hpt_cma(page, 1 << (order - PAGE_SHIFT));
82+
else
83+
free_pages(hpt, order - PAGE_SHIFT);
84+
return -ENOMEM;
9485
}
95-
kvm->arch.hpt.rev = rev;
96-
kvm->arch.sdr1 = __pa(hpt) | (order - 18);
9786

98-
pr_info("KVM guest htab at %lx (order %ld), LPID %x\n",
99-
hpt, order, kvm->arch.lpid);
87+
info->order = order;
88+
info->virt = hpt;
89+
info->cma = cma;
90+
info->rev = rev;
10091

101-
if (htab_orderp)
102-
*htab_orderp = order;
10392
return 0;
93+
}
10494

105-
out_freehpt:
106-
if (kvm->arch.hpt.cma)
107-
kvm_free_hpt_cma(page, 1 << (order - PAGE_SHIFT));
108-
else
109-
free_pages(hpt, order - PAGE_SHIFT);
110-
return -ENOMEM;
95+
void kvmppc_set_hpt(struct kvm *kvm, struct kvm_hpt_info *info)
96+
{
97+
atomic64_set(&kvm->arch.mmio_update, 0);
98+
kvm->arch.hpt = *info;
99+
kvm->arch.sdr1 = __pa(info->virt) | (info->order - 18);
100+
101+
pr_info("KVM guest htab at %lx (order %ld), LPID %x\n",
102+
info->virt, (long)info->order, kvm->arch.lpid);
111103
}
112104

113105
long kvmppc_alloc_reset_hpt(struct kvm *kvm, u32 *htab_orderp)
@@ -141,23 +133,28 @@ long kvmppc_alloc_reset_hpt(struct kvm *kvm, u32 *htab_orderp)
141133
*htab_orderp = order;
142134
err = 0;
143135
} else {
144-
err = kvmppc_alloc_hpt(kvm, htab_orderp);
145-
order = *htab_orderp;
136+
struct kvm_hpt_info info;
137+
138+
err = kvmppc_allocate_hpt(&info, *htab_orderp);
139+
if (err < 0)
140+
goto out;
141+
kvmppc_set_hpt(kvm, &info);
146142
}
147143
out:
148144
mutex_unlock(&kvm->lock);
149145
return err;
150146
}
151147

152-
void kvmppc_free_hpt(struct kvm *kvm)
148+
void kvmppc_free_hpt(struct kvm_hpt_info *info)
153149
{
154-
vfree(kvm->arch.hpt.rev);
155-
if (kvm->arch.hpt.cma)
156-
kvm_free_hpt_cma(virt_to_page(kvm->arch.hpt.virt),
157-
1 << (kvm->arch.hpt.order - PAGE_SHIFT));
158-
else if (kvm->arch.hpt.virt)
159-
free_pages(kvm->arch.hpt.virt,
160-
kvm->arch.hpt.order - PAGE_SHIFT);
150+
vfree(info->rev);
151+
if (info->cma)
152+
kvm_free_hpt_cma(virt_to_page(info->virt),
153+
1 << (info->order - PAGE_SHIFT));
154+
else if (info->virt)
155+
free_pages(info->virt, info->order - PAGE_SHIFT);
156+
info->virt = 0;
157+
info->order = 0;
161158
}
162159

163160
/* Bits in first HPTE dword for pagesize 4k, 64k or 16M */

arch/powerpc/kvm/book3s_hv.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3198,11 +3198,22 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
31983198

31993199
/* Allocate hashed page table (if not done already) and reset it */
32003200
if (!kvm->arch.hpt.virt) {
3201-
err = kvmppc_alloc_hpt(kvm, NULL);
3202-
if (err) {
3201+
int order = KVM_DEFAULT_HPT_ORDER;
3202+
struct kvm_hpt_info info;
3203+
3204+
err = kvmppc_allocate_hpt(&info, order);
3205+
/* If we get here, it means userspace didn't specify a
3206+
* size explicitly. So, try successively smaller
3207+
* sizes if the default failed. */
3208+
while ((err == -ENOMEM) && --order >= PPC_MIN_HPT_ORDER)
3209+
err = kvmppc_allocate_hpt(&info, order);
3210+
3211+
if (err < 0) {
32033212
pr_err("KVM: Couldn't alloc HPT\n");
32043213
goto out;
32053214
}
3215+
3216+
kvmppc_set_hpt(kvm, &info);
32063217
}
32073218

32083219
/* Look up the memslot for guest physical address 0 */
@@ -3467,7 +3478,7 @@ static void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
34673478
if (kvm_is_radix(kvm))
34683479
kvmppc_free_radix(kvm);
34693480
else
3470-
kvmppc_free_hpt(kvm);
3481+
kvmppc_free_hpt(&kvm->arch.hpt);
34713482

34723483
kvmppc_free_pimap(kvm);
34733484
}

0 commit comments

Comments
 (0)