Loading Documentation/devicetree/bindings/arm/msm/memory-offline.txt 0 → 100644 +31 −0 Original line number Diff line number Diff line Memory offline driver ===================== The memory offline driver supports the onlining and offlining of DDR memory. Through the mem-offline node you can configure how much of the DDR will support being offlined/onlined. By default all memory is onlined when the device has booted up. Note that offlinable memory can only support 'movable' memory allocations so designating too much memory as offlinable can result in system performance and stability issues. For more information on how to request the onlining and offlining of memory see the memory hotplug documentation (Documentation/memory-hotplug.txt). Required properties: - compatible: "qcom,mem-offline" - granule: The minimum granule size in mega-bytes for memory onlining/offlining. - mem-percent: Percentage of the DDR which will support being onlined/offlined. The system will round down the value to align with the minimum offlinable granule size supported by DDR. - mboxes: Reference to the mailbox used by the driver to make requests to online/offline memory. Example: mem-offline { compatible = "qcom,mem-offline"; granule = <512>; mem-percent = "35"; mboxes = <&qmp_aop 0>; }; arch/arm64/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,18 @@ config HAVE_GENERIC_GUP config SMP def_bool y config HOTPLUG_SIZE_BITS int "Memory hotplug block size(29 => 512MB 30 => 1GB)" depends on SPARSEMEM depends on MEMORY_HOTPLUG depends on QCOM_MEM_OFFLINE default 30 help Selects granularity of hotplug memory. Block size for memory hotplug is represent as a power of 2. If unsure, stick with default value. config KERNEL_MODE_NEON def_bool y Loading arch/arm64/include/asm/sparsemem.h +4 −0 Original line number Diff line number Diff line Loading @@ -18,7 +18,11 @@ #ifdef CONFIG_SPARSEMEM #define MAX_PHYSMEM_BITS CONFIG_ARM64_PA_BITS #ifndef CONFIG_MEMORY_HOTPLUG #define SECTION_SIZE_BITS 30 #else #define SECTION_SIZE_BITS CONFIG_HOTPLUG_SIZE_BITS #endif #endif #endif arch/arm64/mm/init.c +48 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ #include <linux/mm.h> #include <linux/kexec.h> #include <linux/crash_dump.h> #include <linux/memory.h> #include <linux/libfdt.h> #include <asm/boot.h> #include <asm/fixmap.h> Loading Loading @@ -317,6 +319,51 @@ static void __init arm64_memory_present(void) static phys_addr_t memory_limit = PHYS_ADDR_MAX; phys_addr_t bootloader_memory_limit; #ifdef CONFIG_OVERRIDE_MEMORY_LIMIT static void __init update_memory_limit(void) { unsigned long dt_root = of_get_flat_dt_root(); unsigned long node, mp; const char *p; unsigned long long ram_sz, sz; int ret; ram_sz = memblock_end_of_DRAM() - memblock_start_of_DRAM(); node = of_get_flat_dt_subnode_by_name(dt_root, "mem-offline"); if (node == -FDT_ERR_NOTFOUND) { pr_err("mem-offine node not found in FDT\n"); return; } p = of_get_flat_dt_prop(node, "mem-percent", NULL); if (!p) { pr_err("mem-offine: mem-percent property not found in FDT\n"); return; } ret = kstrtoul(p, 10, &mp); if (ret) { pr_err("mem-offine: kstrtoul failed\n"); return; } if (mp > 100) { pr_err("mem-offine: Invalid mem-percent DT property\n"); return; } sz = ram_sz - ((ram_sz * mp) / 100); memory_limit = (phys_addr_t)sz; memory_limit = ALIGN(memory_limit, MIN_MEMORY_BLOCK_SIZE); pr_notice("Memory limit set/overridden to %lldMB\n", memory_limit >> 20); } #else static void __init update_memory_limit(void) { } #endif /* * Limit the memory size that was specified via FDT. */ Loading Loading @@ -401,6 +448,7 @@ void __init arm64_memblock_init(void) memblock_remove(0, memstart_addr); } update_memory_limit(); /* * Save bootloader imposed memory limit before we overwirte * memblock. Loading arch/arm64/mm/mmu.c +3 −1 Original line number Diff line number Diff line Loading @@ -708,11 +708,13 @@ void hotplug_paging(phys_addr_t start, phys_addr_t size) struct page *pg; phys_addr_t pgd_phys = pgd_pgtable_alloc(); pgd_t *pgd = pgd_set_fixmap(pgd_phys); int flags; memcpy(pgd, swapper_pg_dir, PAGE_SIZE); flags = debug_pagealloc_enabled() ? NO_BLOCK_MAPPINGS : 0; __create_pgd_mapping(pgd, start, __phys_to_virt(start), size, PAGE_KERNEL, pgd_pgtable_alloc, !debug_pagealloc_enabled()); PAGE_KERNEL, pgd_pgtable_alloc, flags); cpu_replace_ttbr1(__va(pgd_phys)); memcpy(swapper_pg_dir, pgd, PAGE_SIZE); Loading Loading
Documentation/devicetree/bindings/arm/msm/memory-offline.txt 0 → 100644 +31 −0 Original line number Diff line number Diff line Memory offline driver ===================== The memory offline driver supports the onlining and offlining of DDR memory. Through the mem-offline node you can configure how much of the DDR will support being offlined/onlined. By default all memory is onlined when the device has booted up. Note that offlinable memory can only support 'movable' memory allocations so designating too much memory as offlinable can result in system performance and stability issues. For more information on how to request the onlining and offlining of memory see the memory hotplug documentation (Documentation/memory-hotplug.txt). Required properties: - compatible: "qcom,mem-offline" - granule: The minimum granule size in mega-bytes for memory onlining/offlining. - mem-percent: Percentage of the DDR which will support being onlined/offlined. The system will round down the value to align with the minimum offlinable granule size supported by DDR. - mboxes: Reference to the mailbox used by the driver to make requests to online/offline memory. Example: mem-offline { compatible = "qcom,mem-offline"; granule = <512>; mem-percent = "35"; mboxes = <&qmp_aop 0>; };
arch/arm64/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,18 @@ config HAVE_GENERIC_GUP config SMP def_bool y config HOTPLUG_SIZE_BITS int "Memory hotplug block size(29 => 512MB 30 => 1GB)" depends on SPARSEMEM depends on MEMORY_HOTPLUG depends on QCOM_MEM_OFFLINE default 30 help Selects granularity of hotplug memory. Block size for memory hotplug is represent as a power of 2. If unsure, stick with default value. config KERNEL_MODE_NEON def_bool y Loading
arch/arm64/include/asm/sparsemem.h +4 −0 Original line number Diff line number Diff line Loading @@ -18,7 +18,11 @@ #ifdef CONFIG_SPARSEMEM #define MAX_PHYSMEM_BITS CONFIG_ARM64_PA_BITS #ifndef CONFIG_MEMORY_HOTPLUG #define SECTION_SIZE_BITS 30 #else #define SECTION_SIZE_BITS CONFIG_HOTPLUG_SIZE_BITS #endif #endif #endif
arch/arm64/mm/init.c +48 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ #include <linux/mm.h> #include <linux/kexec.h> #include <linux/crash_dump.h> #include <linux/memory.h> #include <linux/libfdt.h> #include <asm/boot.h> #include <asm/fixmap.h> Loading Loading @@ -317,6 +319,51 @@ static void __init arm64_memory_present(void) static phys_addr_t memory_limit = PHYS_ADDR_MAX; phys_addr_t bootloader_memory_limit; #ifdef CONFIG_OVERRIDE_MEMORY_LIMIT static void __init update_memory_limit(void) { unsigned long dt_root = of_get_flat_dt_root(); unsigned long node, mp; const char *p; unsigned long long ram_sz, sz; int ret; ram_sz = memblock_end_of_DRAM() - memblock_start_of_DRAM(); node = of_get_flat_dt_subnode_by_name(dt_root, "mem-offline"); if (node == -FDT_ERR_NOTFOUND) { pr_err("mem-offine node not found in FDT\n"); return; } p = of_get_flat_dt_prop(node, "mem-percent", NULL); if (!p) { pr_err("mem-offine: mem-percent property not found in FDT\n"); return; } ret = kstrtoul(p, 10, &mp); if (ret) { pr_err("mem-offine: kstrtoul failed\n"); return; } if (mp > 100) { pr_err("mem-offine: Invalid mem-percent DT property\n"); return; } sz = ram_sz - ((ram_sz * mp) / 100); memory_limit = (phys_addr_t)sz; memory_limit = ALIGN(memory_limit, MIN_MEMORY_BLOCK_SIZE); pr_notice("Memory limit set/overridden to %lldMB\n", memory_limit >> 20); } #else static void __init update_memory_limit(void) { } #endif /* * Limit the memory size that was specified via FDT. */ Loading Loading @@ -401,6 +448,7 @@ void __init arm64_memblock_init(void) memblock_remove(0, memstart_addr); } update_memory_limit(); /* * Save bootloader imposed memory limit before we overwirte * memblock. Loading
arch/arm64/mm/mmu.c +3 −1 Original line number Diff line number Diff line Loading @@ -708,11 +708,13 @@ void hotplug_paging(phys_addr_t start, phys_addr_t size) struct page *pg; phys_addr_t pgd_phys = pgd_pgtable_alloc(); pgd_t *pgd = pgd_set_fixmap(pgd_phys); int flags; memcpy(pgd, swapper_pg_dir, PAGE_SIZE); flags = debug_pagealloc_enabled() ? NO_BLOCK_MAPPINGS : 0; __create_pgd_mapping(pgd, start, __phys_to_virt(start), size, PAGE_KERNEL, pgd_pgtable_alloc, !debug_pagealloc_enabled()); PAGE_KERNEL, pgd_pgtable_alloc, flags); cpu_replace_ttbr1(__va(pgd_phys)); memcpy(swapper_pg_dir, pgd, PAGE_SIZE); Loading