aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/xen/balloon.c73
1 files changed, 53 insertions, 20 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index c79329fcfa78..095bb6789731 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -54,6 +54,7 @@
54#include <linux/memory.h> 54#include <linux/memory.h>
55#include <linux/memory_hotplug.h> 55#include <linux/memory_hotplug.h>
56#include <linux/percpu-defs.h> 56#include <linux/percpu-defs.h>
57#include <linux/slab.h>
57 58
58#include <asm/page.h> 59#include <asm/page.h>
59#include <asm/pgalloc.h> 60#include <asm/pgalloc.h>
@@ -208,26 +209,56 @@ static bool balloon_is_inflated(void)
208 return false; 209 return false;
209} 210}
210 211
211/* 212static struct resource *additional_memory_resource(phys_addr_t size)
212 * reserve_additional_memory() adds memory region of size >= credit above 213{
213 * max_pfn. New region is section aligned and size is modified to be multiple 214 struct resource *res;
214 * of section size. Those features allow optimal use of address space and 215 int ret;
215 * establish proper alignment when this function is called first time after 216
216 * boot (last section not fully populated at boot time contains unused memory 217 res = kzalloc(sizeof(*res), GFP_KERNEL);
217 * pages with PG_reserved bit not set; online_pages_range() does not allow page 218 if (!res)
218 * onlining in whole range if first onlined page does not have PG_reserved 219 return NULL;
219 * bit set). Real size of added memory is established at page onlining stage. 220
220 */ 221 res->name = "System RAM";
222 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
223
224 ret = allocate_resource(&iomem_resource, res,
225 size, 0, -1,
226 PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
227 if (ret < 0) {
228 pr_err("Cannot allocate new System RAM resource\n");
229 kfree(res);
230 return NULL;
231 }
232
233 return res;
234}
235
236static void release_memory_resource(struct resource *resource)
237{
238 if (!resource)
239 return;
240
241 /*
242 * No need to reset region to identity mapped since we now
243 * know that no I/O can be in this region
244 */
245 release_resource(resource);
246 kfree(resource);
247}
221 248
222static enum bp_state reserve_additional_memory(long credit) 249static enum bp_state reserve_additional_memory(long credit)
223{ 250{
251 struct resource *resource;
224 int nid, rc; 252 int nid, rc;
225 u64 hotplug_start_paddr; 253 unsigned long balloon_hotplug;
226 unsigned long balloon_hotplug = credit; 254
255 balloon_hotplug = round_up(credit, PAGES_PER_SECTION);
256
257 resource = additional_memory_resource(balloon_hotplug * PAGE_SIZE);
258 if (!resource)
259 goto err;
227 260
228 hotplug_start_paddr = PFN_PHYS(SECTION_ALIGN_UP(max_pfn)); 261 nid = memory_add_physaddr_to_nid(resource->start);
229 balloon_hotplug = round_up(balloon_hotplug, PAGES_PER_SECTION);
230 nid = memory_add_physaddr_to_nid(hotplug_start_paddr);
231 262
232#ifdef CONFIG_XEN_HAVE_PVMMU 263#ifdef CONFIG_XEN_HAVE_PVMMU
233 /* 264 /*
@@ -242,21 +273,20 @@ static enum bp_state reserve_additional_memory(long credit)
242 if (!xen_feature(XENFEAT_auto_translated_physmap)) { 273 if (!xen_feature(XENFEAT_auto_translated_physmap)) {
243 unsigned long pfn, i; 274 unsigned long pfn, i;
244 275
245 pfn = PFN_DOWN(hotplug_start_paddr); 276 pfn = PFN_DOWN(resource->start);
246 for (i = 0; i < balloon_hotplug; i++) { 277 for (i = 0; i < balloon_hotplug; i++) {
247 if (!set_phys_to_machine(pfn + i, INVALID_P2M_ENTRY)) { 278 if (!set_phys_to_machine(pfn + i, INVALID_P2M_ENTRY)) {
248 pr_warn("set_phys_to_machine() failed, no memory added\n"); 279 pr_warn("set_phys_to_machine() failed, no memory added\n");
249 return BP_ECANCELED; 280 goto err;
250 } 281 }
251 } 282 }
252 } 283 }
253#endif 284#endif
254 285
255 rc = add_memory(nid, hotplug_start_paddr, balloon_hotplug << PAGE_SHIFT); 286 rc = add_memory_resource(nid, resource);
256
257 if (rc) { 287 if (rc) {
258 pr_warn("Cannot add additional memory (%i)\n", rc); 288 pr_warn("Cannot add additional memory (%i)\n", rc);
259 return BP_ECANCELED; 289 goto err;
260 } 290 }
261 291
262 balloon_hotplug -= credit; 292 balloon_hotplug -= credit;
@@ -265,6 +295,9 @@ static enum bp_state reserve_additional_memory(long credit)
265 balloon_stats.balloon_hotplug = balloon_hotplug; 295 balloon_stats.balloon_hotplug = balloon_hotplug;
266 296
267 return BP_DONE; 297 return BP_DONE;
298 err:
299 release_memory_resource(resource);
300 return BP_ECANCELED;
268} 301}
269 302
270static void xen_online_page(struct page *page) 303static void xen_online_page(struct page *page)