soc: qcom: mem-offline: online only valid memory blocks

mem-offline driver onlines blocks between memory_limit to end of DDR,
but for some cases when using large ram size, the range may not be
contiguous. We online un-existed memory blocks in this case. Example
-
RAM Entry 0 : Base 0x0080000000  Size 0x0033E00000
RAM Entry 1 : Base 0x0200000000  Size 0x0200000000
RAM Entry 2 : Base 0x0800000000  Size 0x0100000000
RAM Entry 3 : Base 0x00C0000000  Size 0x0140000000
if offline-size is 5GB and total memory size is 18GB, we onlined
also un-existed range [0x400000000,0x800000000] in
mem_online_remaining_blocks(). To fix this, Do parsing the DT tree
again and updated bitmap accordingly. Use this bitmap to online memory
blocks.

Change-Id: I5ea94a0ea9dca10e3a3311d6ea53a14302a41ae5
Signed-off-by: Zhenhua Huang <zhenhuah@codeaurora.org>
This commit is contained in:
Zhenhua Huang 2021-05-27 16:07:00 +08:00 • committed by Gerrit - the friendly Code Review server
commit df12e38f23

View file

@ -49,6 +49,7 @@ static bool is_rpm_controller;
static bool has_pend_offline_req;
static atomic_long_t totalram_pages_with_offline = ATOMIC_INIT(0);
static struct workqueue_struct *migrate_wq;
static unsigned long movable_bitmap;
#define MODULE_CLASS_NAME "mem-offline"
#define MIGRATE_TIMEOUT_SEC (20)
@ -752,6 +753,63 @@ static int mem_event_callback(struct notifier_block *self,
return NOTIFY_OK;
}
static int update_movable_bitmap(void)
{
struct device_node *node;
struct property *prop;
int len, num_cells, num_entries;
u64 base, size, end, section_size;
u64 movable_start, movable_end;
int nr_address_cells, nr_size_cells;
const __be32 *pos;
node = of_find_node_by_name(of_root, "memory");
if (!node) {
pr_err("mem-offine: memory node not found in DT\n");
return -EINVAL;
}
nr_address_cells = of_n_addr_cells(of_root);
nr_size_cells = of_n_size_cells(of_root);
prop = of_find_property(node, "reg", &len);
num_cells = len / sizeof(__be32);
num_entries = num_cells / (nr_address_cells + nr_size_cells);
pos = prop->value;
section_size = MIN_MEMORY_BLOCK_SIZE;
movable_start = memblock_end_of_DRAM();
movable_end = bootloader_memory_limit - 1;
while (num_entries--) {
u64 new_base, new_end;
u64 new_start_bitmap, bitmap_size;
base = of_read_number(pos, nr_address_cells);
size = of_read_number(pos + nr_address_cells, nr_size_cells);
pos += nr_address_cells + nr_size_cells;
end = base + size;
if (end <= movable_start)
continue;
if (base < movable_start)
new_base = movable_start;
else
new_base = base;
new_end = end;
new_start_bitmap = (new_base - movable_start) / section_size;
bitmap_size = (new_end - new_base) / section_size;
bitmap_set(&movable_bitmap, new_start_bitmap, bitmap_size);
}
pr_debug("mem-offline: movable_bitmap is %lx\n", movable_bitmap);
return 0;
}
static int mem_online_remaining_blocks(void)
{
unsigned long memblock_end_pfn = __phys_to_pfn(memblock_end_of_DRAM());
@ -760,6 +818,7 @@ static int mem_online_remaining_blocks(void)
unsigned int nid;
phys_addr_t phys_addr;
int fail = 0;
int ret;
block_size = memory_block_size_bytes();
sections_per_block = block_size / MIN_MEMORY_BLOCK_SIZE;
@ -771,8 +830,17 @@ static int mem_online_remaining_blocks(void)
pr_info("mem-offline: System booted with no zone movable memory blocks. Cannot perform memory offlining\n");
return -EINVAL;
}
ret = update_movable_bitmap();
if (ret < 0)
return -ENODEV;
for (memblock = start_section_nr; memblock <= end_section_nr;
memblock += sections_per_block) {
if (!test_bit(memblock - start_section_nr, &movable_bitmap))
continue;
pfn = section_nr_to_pfn(memblock);
phys_addr = __pfn_to_phys(pfn);