arm64: Honor limits set by bootloader

Introduce a varible to save bootloader enforced memory limits and
restricts adding beyond this boundary during a memory hotplug.

Change-Id: I28c100644b7287ec4625c4c018b5fffc865e2e72
Signed-off-by: Arun KS <arunks@codeaurora.org>
This commit is contained in:
Arun KS 2017-09-15 13:52:00 +05:30
parent 2247011a9c
commit ea4e70e7d6
3 changed files with 35 additions and 5 deletions

View file

@ -152,6 +152,7 @@ static void __init arm64_memory_present(void)
#endif
static phys_addr_t memory_limit = (phys_addr_t)ULLONG_MAX;
static phys_addr_t bootloader_memory_limit;
/*
* Limit the memory size that was specified via FDT.
@ -205,6 +206,11 @@ void __init arm64_memblock_init(void)
* via the linear mapping.
*/
if (memory_limit != (phys_addr_t)ULLONG_MAX) {
/*
* Save bootloader imposed memory limit before we overwirte
* memblock.
*/
bootloader_memory_limit = memblock_end_of_DRAM();
memblock_enforce_memory_limit(memory_limit);
memblock_add(__pa(_text), (u64)(_end - _text));
}
@ -607,4 +613,25 @@ int arch_remove_memory(u64 start, u64 size)
}
#endif /* CONFIG_MEMORY_HOTREMOVE */
static int arm64_online_page(struct page *page)
{
unsigned long target_pfn = page_to_pfn(page);
unsigned long limit = __phys_to_pfn(bootloader_memory_limit);
if (target_pfn >= limit)
return -EINVAL;
__online_page_set_limits(page);
__online_page_increment_counters(page);
__online_page_free(page);
return 0;
}
static int __init arm64_memory_hotplug_init(void)
{
set_online_page_callback(&arm64_online_page);
return 0;
}
subsys_initcall(arm64_memory_hotplug_init);
#endif /* CONFIG_MEMORY_HOTPLUG */

View file

@ -89,7 +89,7 @@ extern int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
unsigned long *valid_start, unsigned long *valid_end);
extern void __offline_isolated_pages(unsigned long, unsigned long);
typedef void (*online_page_callback_t)(struct page *page);
typedef int (*online_page_callback_t)(struct page *page);
extern int set_online_page_callback(online_page_callback_t callback);
extern int restore_online_page_callback(online_page_callback_t callback);

View file

@ -45,7 +45,7 @@
* and restore_online_page_callback() for generic callback restore.
*/
static void generic_online_page(struct page *page);
static int generic_online_page(struct page *page);
static online_page_callback_t online_page_callback = generic_online_page;
static DEFINE_MUTEX(online_page_callback_lock);
@ -857,11 +857,12 @@ void __online_page_free(struct page *page)
}
EXPORT_SYMBOL_GPL(__online_page_free);
static void generic_online_page(struct page *page)
static int generic_online_page(struct page *page)
{
__online_page_set_limits(page);
__online_page_increment_counters(page);
__online_page_free(page);
return 0;
}
static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
@ -870,11 +871,13 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages,
unsigned long i;
unsigned long onlined_pages = *(unsigned long *)arg;
struct page *page;
int ret;
if (PageReserved(pfn_to_page(start_pfn)))
for (i = 0; i < nr_pages; i++) {
page = pfn_to_page(start_pfn + i);
(*online_page_callback)(page);
onlined_pages++;
ret = (*online_page_callback)(page);
if (!ret)
onlined_pages++;
}
*(unsigned long *)arg = onlined_pages;
return 0;