diff mbox

[3/3] KVM: PPC: Add HPT preallocator

Message ID 1326928658-10791-4-git-send-email-agraf@suse.de
State New, archived
Headers show

Commit Message

Alexander Graf Jan. 18, 2012, 11:17 p.m. UTC
We're currently allocating 16MB of linear memory on demand when creating
a guest. That does work some times, but finding 16MB of linear memory
available in the system at runtime is definitely not a given.

So let's add another command line option similar to the RMA preallocator,
that we can use to keep a pool of page tables around. Now, when a guest
gets created it has a pretty low chance of receiving an OOM.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/include/asm/kvm_host.h  |    1 +
 arch/powerpc/include/asm/kvm_ppc.h   |    2 +
 arch/powerpc/kvm/book3s_64_mmu_hv.c  |   18 ++++++++++++++-
 arch/powerpc/kvm/book3s_hv_builtin.c |   39 +++++++++++++++++++++++++++++++++-
 4 files changed, 58 insertions(+), 2 deletions(-)

Comments

Paul Mackerras Jan. 19, 2012, 9:31 a.m. UTC | #1
On Thu, Jan 19, 2012 at 12:17:38AM +0100, Alexander Graf wrote:

>  	/* Allocate guest's hashed page table */
> +
> +	/* using preallocated memory */
> +	li = kvm_alloc_hpt();
> +	if (li) {
> +		hpt = (ulong)li->base_virt;
> +		kvm->arch.hpt_li = li;
> +		goto has_hpt;
> +	}
> +
> +	/* using dynamic memory */
>  	hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|__GFP_NOWARN,
>  			       HPT_ORDER - PAGE_SHIFT);
> +
> +has_hpt:

This would look cleaner and be easier to follow if you used the "else"
keyword. :)

Paul.
--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexander Graf Jan. 19, 2012, 3:58 p.m. UTC | #2
On 19.01.2012, at 10:31, Paul Mackerras wrote:

> On Thu, Jan 19, 2012 at 12:17:38AM +0100, Alexander Graf wrote:
> 
>> 	/* Allocate guest's hashed page table */
>> +
>> +	/* using preallocated memory */
>> +	li = kvm_alloc_hpt();
>> +	if (li) {
>> +		hpt = (ulong)li->base_virt;
>> +		kvm->arch.hpt_li = li;
>> +		goto has_hpt;
>> +	}
>> +
>> +	/* using dynamic memory */
>> 	hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|__GFP_NOWARN,
>> 			       HPT_ORDER - PAGE_SHIFT);
>> +
>> +has_hpt:
> 
> This would look cleaner and be easier to follow if you used the "else"
> keyword. :)

Yeah, I just figured we might want to extend the "else" path by quite a bit. But I'll change it for now :). It certainly does look better when done that way in its current form.


Alex

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 8221e71..1843d5d 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -235,6 +235,7 @@  struct kvm_arch {
 	int slot_npages[KVM_MEM_SLOTS_NUM];
 	unsigned short last_vcpu[NR_CPUS];
 	struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
+	struct kvmppc_linear_info *hpt_li;
 #endif /* CONFIG_KVM_BOOK3S_64_HV */
 };
 
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 1c37a2f..9d6dee0 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -130,6 +130,8 @@  extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm,
 				struct kvm_allocate_rma *rma);
 extern struct kvmppc_linear_info *kvm_alloc_rma(void);
 extern void kvm_release_rma(struct kvmppc_linear_info *ri);
+extern struct kvmppc_linear_info *kvm_alloc_hpt(void);
+extern void kvm_release_hpt(struct kvmppc_linear_info *li);
 extern int kvmppc_core_init_vm(struct kvm *kvm);
 extern void kvmppc_core_destroy_vm(struct kvm *kvm);
 extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 783cd35..b3207c7 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -44,10 +44,23 @@  long kvmppc_alloc_hpt(struct kvm *kvm)
 	unsigned long hpt;
 	unsigned long lpid;
 	struct revmap_entry *rev;
+	struct kvmppc_linear_info *li;
 
 	/* Allocate guest's hashed page table */
+
+	/* using preallocated memory */
+	li = kvm_alloc_hpt();
+	if (li) {
+		hpt = (ulong)li->base_virt;
+		kvm->arch.hpt_li = li;
+		goto has_hpt;
+	}
+
+	/* using dynamic memory */
 	hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|__GFP_NOWARN,
 			       HPT_ORDER - PAGE_SHIFT);
+
+has_hpt:
 	if (!hpt) {
 		pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n");
 		return -ENOMEM;
@@ -88,7 +101,10 @@  void kvmppc_free_hpt(struct kvm *kvm)
 {
 	clear_bit(kvm->arch.lpid, lpid_inuse);
 	vfree(kvm->arch.revmap);
-	free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT);
+	if (kvm->arch.hpt_li)
+		kvm_release_hpt(kvm->arch.hpt_li);
+	else
+		free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT);
 }
 
 /* Bits in first HPTE dword for pagesize 4k, 64k or 16M */
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 7caed1d..bed1279 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -19,6 +19,7 @@ 
 #include <asm/kvm_book3s.h>
 
 #define KVM_LINEAR_RMA		0
+#define KVM_LINEAR_HPT		1
 
 static void __init kvm_linear_init_one(ulong size, int count, int type);
 static struct kvmppc_linear_info *kvm_alloc_linear(int type);
@@ -97,6 +98,39 @@  void kvm_release_rma(struct kvmppc_linear_info *ri)
 }
 EXPORT_SYMBOL_GPL(kvm_release_rma);
 
+/*************** HPT *************/
+
+/*
+ * This maintains a list of big linear HPT tables that contain the GVA->HPA
+ * memory mappings. If we don't reserve those early on, we might not be able
+ * to get a big (usually 16MB) linear memory region from the kernel anymore.
+ */
+
+static unsigned long kvm_hpt_count;
+
+static int __init early_parse_hpt_count(char *p)
+{
+	if (!p)
+		return 1;
+
+	kvm_hpt_count = simple_strtoul(p, NULL, 0);
+
+	return 0;
+}
+early_param("kvm_hpt_count", early_parse_hpt_count);
+
+struct kvmppc_linear_info *kvm_alloc_hpt(void)
+{
+	return kvm_alloc_linear(KVM_LINEAR_HPT);
+}
+EXPORT_SYMBOL_GPL(kvm_alloc_hpt);
+
+void kvm_release_hpt(struct kvmppc_linear_info *li)
+{
+	kvm_release_linear(li);
+}
+EXPORT_SYMBOL_GPL(kvm_release_hpt);
+
 /*************** generic *************/
 
 static LIST_HEAD(free_linears);
@@ -114,7 +148,7 @@  static void __init kvm_linear_init_one(ulong size, int count, int type)
 	if (!count)
 		return;
 
-	typestr = (type == KVM_LINEAR_RMA) ? "RMA" : "";
+	typestr = (type == KVM_LINEAR_RMA) ? "RMA" : "HPT";
 
 	npages = size >> PAGE_SHIFT;
 	linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info));
@@ -173,6 +207,9 @@  static void kvm_release_linear(struct kvmppc_linear_info *ri)
  */
 void __init kvm_linear_init(void)
 {
+	/* HPT */
+	kvm_linear_init_one(1 << HPT_ORDER, kvm_hpt_count, KVM_LINEAR_HPT);
+
 	/* RMA */
 	/* Only do this on PPC970 in HV mode */
 	if (!cpu_has_feature(CPU_FTR_HVMODE) ||