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:
parent
2247011a9c
commit
ea4e70e7d6
3 changed files with 35 additions and 5 deletions
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,10 +871,12 @@ 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);
|
||||
ret = (*online_page_callback)(page);
|
||||
if (!ret)
|
||||
onlined_pages++;
|
||||
}
|
||||
*(unsigned long *)arg = onlined_pages;
|
||||
|
|
Loading…
Add table
Reference in a new issue