]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
KVM: PPC: Add HPT preallocator
authorAlexander Graf <agraf@suse.de>
Mon, 16 Jan 2012 18:12:11 +0000 (19:12 +0100)
committerAvi Kivity <avi@redhat.com>
Mon, 5 Mar 2012 12:57:28 +0000 (14:57 +0200)
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>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_hv_builtin.c

index 8221e717bbce869538fd958a61d547191bc27e9f..1843d5d2a3be3c8b3b324efa293af96e20435b44 100644 (file)
@@ -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 */
 };
 
index 1c37a2f8d0f41fdb466120746a3a47f720872567..9d6dee0f7d48ecc442b3d1e8062583c033434e69 100644 (file)
@@ -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,
index 783cd3510c93963deb03ff1a8e3ec91bebd6def4..ddc485a529f2d7f7c59e22729fd55372eac9be03 100644 (file)
@@ -44,10 +44,20 @@ 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 */
-       hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|__GFP_NOWARN,
-                              HPT_ORDER - PAGE_SHIFT);
+       li = kvm_alloc_hpt();
+       if (li) {
+               /* using preallocated memory */
+               hpt = (ulong)li->base_virt;
+               kvm->arch.hpt_li = li;
+       } else {
+               /* using dynamic memory */
+               hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|
+                                      __GFP_NOWARN, HPT_ORDER - PAGE_SHIFT);
+       }
+
        if (!hpt) {
                pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n");
                return -ENOMEM;
@@ -88,7 +98,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 */
index 7caed1dfd7a415ed5ea9fb36920bd413f9d3e82e..bed1279aa6a8788a8308b8966ef4c970f8aafd36 100644 (file)
@@ -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) ||