54
54
#include <linux/memory.h>
55
55
#include <linux/memory_hotplug.h>
56
56
#include <linux/percpu-defs.h>
57
+ #include <linux/slab.h>
57
58
58
59
#include <asm/page.h>
59
60
#include <asm/pgalloc.h>
@@ -208,26 +209,56 @@ static bool balloon_is_inflated(void)
208
209
return false;
209
210
}
210
211
211
- /*
212
- * reserve_additional_memory() adds memory region of size >= credit above
213
- * max_pfn. New region is section aligned and size is modified to be multiple
214
- * of section size. Those features allow optimal use of address space and
215
- * establish proper alignment when this function is called first time after
216
- * boot (last section not fully populated at boot time contains unused memory
217
- * pages with PG_reserved bit not set; online_pages_range() does not allow page
218
- * onlining in whole range if first onlined page does not have PG_reserved
219
- * bit set). Real size of added memory is established at page onlining stage.
220
- */
212
+ static struct resource * additional_memory_resource (phys_addr_t size )
213
+ {
214
+ struct resource * res ;
215
+ int ret ;
216
+
217
+ res = kzalloc (sizeof (* res ), GFP_KERNEL );
218
+ if (!res )
219
+ return NULL ;
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
+
236
+ static 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
222
249
static enum bp_state reserve_additional_memory (long credit )
223
250
{
251
+ struct resource * resource ;
224
252
int nid , rc ;
225
- u64 hotplug_start_paddr ;
226
- unsigned long balloon_hotplug = credit ;
253
+ unsigned long balloon_hotplug ;
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 ));
229
- balloon_hotplug = round_up (balloon_hotplug , PAGES_PER_SECTION );
230
- nid = memory_add_physaddr_to_nid (hotplug_start_paddr );
261
+ nid = memory_add_physaddr_to_nid (resource -> start );
231
262
232
263
#ifdef CONFIG_XEN_HAVE_PVMMU
233
264
/*
@@ -242,21 +273,20 @@ static enum bp_state reserve_additional_memory(long credit)
242
273
if (!xen_feature (XENFEAT_auto_translated_physmap )) {
243
274
unsigned long pfn , i ;
244
275
245
- pfn = PFN_DOWN (hotplug_start_paddr );
276
+ pfn = PFN_DOWN (resource -> start );
246
277
for (i = 0 ; i < balloon_hotplug ; i ++ ) {
247
278
if (!set_phys_to_machine (pfn + i , INVALID_P2M_ENTRY )) {
248
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
284
#endif
254
285
255
- rc = add_memory (nid , hotplug_start_paddr , balloon_hotplug << PAGE_SHIFT );
256
-
286
+ rc = add_memory_resource (nid , resource );
257
287
if (rc ) {
258
288
pr_warn ("Cannot add additional memory (%i)\n" , rc );
259
- return BP_ECANCELED ;
289
+ goto err ;
260
290
}
261
291
262
292
balloon_hotplug -= credit ;
@@ -265,6 +295,9 @@ static enum bp_state reserve_additional_memory(long credit)
265
295
balloon_stats .balloon_hotplug = balloon_hotplug ;
266
296
267
297
return BP_DONE ;
298
+ err :
299
+ release_memory_resource (resource );
300
+ return BP_ECANCELED ;
268
301
}
269
302
270
303
static void xen_online_page (struct page * page )
0 commit comments