diff options
author | Alexander Graf <agraf@suse.de> | 2012-01-16 13:12:11 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2012-03-05 07:57:28 -0500 |
commit | d2a1b483a4a3f4bbb5fec1877f716c15ac7fa405 (patch) | |
tree | 3c1e6162250afb6c79f846749d91d71d2ccc0712 /arch/powerpc | |
parent | b7f5d0114c708d6efd264a2c5e5a31cf292a9cec (diff) |
KVM: PPC: Add HPT preallocator
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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_hv.c | 19 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_builtin.c | 39 |
4 files changed, 57 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 8221e717bbce..1843d5d2a3be 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -235,6 +235,7 @@ struct kvm_arch { | |||
235 | int slot_npages[KVM_MEM_SLOTS_NUM]; | 235 | int slot_npages[KVM_MEM_SLOTS_NUM]; |
236 | unsigned short last_vcpu[NR_CPUS]; | 236 | unsigned short last_vcpu[NR_CPUS]; |
237 | struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; | 237 | struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; |
238 | struct kvmppc_linear_info *hpt_li; | ||
238 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 239 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ |
239 | }; | 240 | }; |
240 | 241 | ||
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 1c37a2f8d0f4..9d6dee0f7d48 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, | |||
130 | struct kvm_allocate_rma *rma); | 130 | struct kvm_allocate_rma *rma); |
131 | extern struct kvmppc_linear_info *kvm_alloc_rma(void); | 131 | extern struct kvmppc_linear_info *kvm_alloc_rma(void); |
132 | extern void kvm_release_rma(struct kvmppc_linear_info *ri); | 132 | extern void kvm_release_rma(struct kvmppc_linear_info *ri); |
133 | extern struct kvmppc_linear_info *kvm_alloc_hpt(void); | ||
134 | extern void kvm_release_hpt(struct kvmppc_linear_info *li); | ||
133 | extern int kvmppc_core_init_vm(struct kvm *kvm); | 135 | extern int kvmppc_core_init_vm(struct kvm *kvm); |
134 | extern void kvmppc_core_destroy_vm(struct kvm *kvm); | 136 | extern void kvmppc_core_destroy_vm(struct kvm *kvm); |
135 | extern int kvmppc_core_prepare_memory_region(struct kvm *kvm, | 137 | 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 783cd3510c93..ddc485a529f2 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c | |||
@@ -44,10 +44,20 @@ long kvmppc_alloc_hpt(struct kvm *kvm) | |||
44 | unsigned long hpt; | 44 | unsigned long hpt; |
45 | unsigned long lpid; | 45 | unsigned long lpid; |
46 | struct revmap_entry *rev; | 46 | struct revmap_entry *rev; |
47 | struct kvmppc_linear_info *li; | ||
47 | 48 | ||
48 | /* Allocate guest's hashed page table */ | 49 | /* Allocate guest's hashed page table */ |
49 | hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT|__GFP_NOWARN, | 50 | li = kvm_alloc_hpt(); |
50 | HPT_ORDER - PAGE_SHIFT); | 51 | if (li) { |
52 | /* using preallocated memory */ | ||
53 | hpt = (ulong)li->base_virt; | ||
54 | kvm->arch.hpt_li = li; | ||
55 | } else { | ||
56 | /* using dynamic memory */ | ||
57 | hpt = __get_free_pages(GFP_KERNEL|__GFP_ZERO|__GFP_REPEAT| | ||
58 | __GFP_NOWARN, HPT_ORDER - PAGE_SHIFT); | ||
59 | } | ||
60 | |||
51 | if (!hpt) { | 61 | if (!hpt) { |
52 | pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n"); | 62 | pr_err("kvm_alloc_hpt: Couldn't alloc HPT\n"); |
53 | return -ENOMEM; | 63 | return -ENOMEM; |
@@ -88,7 +98,10 @@ void kvmppc_free_hpt(struct kvm *kvm) | |||
88 | { | 98 | { |
89 | clear_bit(kvm->arch.lpid, lpid_inuse); | 99 | clear_bit(kvm->arch.lpid, lpid_inuse); |
90 | vfree(kvm->arch.revmap); | 100 | vfree(kvm->arch.revmap); |
91 | free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT); | 101 | if (kvm->arch.hpt_li) |
102 | kvm_release_hpt(kvm->arch.hpt_li); | ||
103 | else | ||
104 | free_pages(kvm->arch.hpt_virt, HPT_ORDER - PAGE_SHIFT); | ||
92 | } | 105 | } |
93 | 106 | ||
94 | /* Bits in first HPTE dword for pagesize 4k, 64k or 16M */ | 107 | /* 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 7caed1dfd7a4..bed1279aa6a8 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/kvm_book3s.h> | 19 | #include <asm/kvm_book3s.h> |
20 | 20 | ||
21 | #define KVM_LINEAR_RMA 0 | 21 | #define KVM_LINEAR_RMA 0 |
22 | #define KVM_LINEAR_HPT 1 | ||
22 | 23 | ||
23 | static void __init kvm_linear_init_one(ulong size, int count, int type); | 24 | static void __init kvm_linear_init_one(ulong size, int count, int type); |
24 | static struct kvmppc_linear_info *kvm_alloc_linear(int type); | 25 | static struct kvmppc_linear_info *kvm_alloc_linear(int type); |
@@ -97,6 +98,39 @@ void kvm_release_rma(struct kvmppc_linear_info *ri) | |||
97 | } | 98 | } |
98 | EXPORT_SYMBOL_GPL(kvm_release_rma); | 99 | EXPORT_SYMBOL_GPL(kvm_release_rma); |
99 | 100 | ||
101 | /*************** HPT *************/ | ||
102 | |||
103 | /* | ||
104 | * This maintains a list of big linear HPT tables that contain the GVA->HPA | ||
105 | * memory mappings. If we don't reserve those early on, we might not be able | ||
106 | * to get a big (usually 16MB) linear memory region from the kernel anymore. | ||
107 | */ | ||
108 | |||
109 | static unsigned long kvm_hpt_count; | ||
110 | |||
111 | static int __init early_parse_hpt_count(char *p) | ||
112 | { | ||
113 | if (!p) | ||
114 | return 1; | ||
115 | |||
116 | kvm_hpt_count = simple_strtoul(p, NULL, 0); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | early_param("kvm_hpt_count", early_parse_hpt_count); | ||
121 | |||
122 | struct kvmppc_linear_info *kvm_alloc_hpt(void) | ||
123 | { | ||
124 | return kvm_alloc_linear(KVM_LINEAR_HPT); | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(kvm_alloc_hpt); | ||
127 | |||
128 | void kvm_release_hpt(struct kvmppc_linear_info *li) | ||
129 | { | ||
130 | kvm_release_linear(li); | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(kvm_release_hpt); | ||
133 | |||
100 | /*************** generic *************/ | 134 | /*************** generic *************/ |
101 | 135 | ||
102 | static LIST_HEAD(free_linears); | 136 | static LIST_HEAD(free_linears); |
@@ -114,7 +148,7 @@ static void __init kvm_linear_init_one(ulong size, int count, int type) | |||
114 | if (!count) | 148 | if (!count) |
115 | return; | 149 | return; |
116 | 150 | ||
117 | typestr = (type == KVM_LINEAR_RMA) ? "RMA" : ""; | 151 | typestr = (type == KVM_LINEAR_RMA) ? "RMA" : "HPT"; |
118 | 152 | ||
119 | npages = size >> PAGE_SHIFT; | 153 | npages = size >> PAGE_SHIFT; |
120 | linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info)); | 154 | linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info)); |
@@ -173,6 +207,9 @@ static void kvm_release_linear(struct kvmppc_linear_info *ri) | |||
173 | */ | 207 | */ |
174 | void __init kvm_linear_init(void) | 208 | void __init kvm_linear_init(void) |
175 | { | 209 | { |
210 | /* HPT */ | ||
211 | kvm_linear_init_one(1 << HPT_ORDER, kvm_hpt_count, KVM_LINEAR_HPT); | ||
212 | |||
176 | /* RMA */ | 213 | /* RMA */ |
177 | /* Only do this on PPC970 in HV mode */ | 214 | /* Only do this on PPC970 in HV mode */ |
178 | if (!cpu_has_feature(CPU_FTR_HVMODE) || | 215 | if (!cpu_has_feature(CPU_FTR_HVMODE) || |