Re: [PATCH v2] memblock: add no-map alloc functions
From: Wei Yang
Date: Tue Apr 16 2024 - 22:24:09 EST
On Tue, Apr 16, 2024 at 09:06:35PM +0900, skseofh@xxxxxxxxx wrote:
>From: Daero Lee <daero_le.lee@xxxxxxxxxxx>
>
>Like reserved-memory with the 'no-map' property and only 'size' property
>(w/o 'reg' property), there are memory regions need to be allocated in
>memblock.memory marked with the MEMBLOCK_NOMAP flag, but should not be
>allocated in memblock.reserved.
We don't "allocate" memory from memblock.memory directly.
We present memory in memblock.memory and "allocate" a memory by marking it in
memblock.reserved.
>
>example : arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
> reserved-memory {
> #address-cells = <2>;
> #size-cells = <2>;
> ranges;
>
> bman_fbpr: bman-fbpr {
> compatible = "shared-dma-pool";
> size = <0 0x1000000>;
> alignment = <0 0x1000000>;
> no-map;
> };
>
> qman_fqd: qman-fqd {
> compatible = "shared-dma-pool";
> size = <0 0x400000>;
> alignment = <0 0x400000>;
> no-map;
> };
>
> qman_pfdr: qman-pfdr {
> compatible = "shared-dma-pool";
> size = <0 0x2000000>;
> alignment = <0 0x2000000>;
> no-map;
> };
> };
>
>So, functions were added that find the required memory area in
>memblock.memory, but do not allocate it to memblock.reserved.
>
>In previous patch(a7259df), early_init_dt_alloc_reserved_memory was
You want to say this patch introduced a regression?
>modified to use memblock_phys_alloc_range allocating memory in
>memblock.reserved, instead of memblock_find_in_range that just find the
>available region. But if there is a 'no-map' property, memory region
>should not be allocated to memblock.reserved.
If my understanding is correct, memblock_phys_free() is called if 'no-map'
property is set. This would release the "allocation" in memblock.reserved.
>
>So, the early_init_dt_alloc_reserved_memory_arch function was modified
>using the no-map alloc function.
>
>Signed-off-by: Daero Lee <daero_le.lee@xxxxxxxxxxx>
>---
> drivers/of/of_reserved_mem.c | 9 +++--
> mm/memblock.c | 78 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 84 insertions(+), 3 deletions(-)
>
>diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
>index 8236ecae2953..504f2f60689c 100644
>--- a/drivers/of/of_reserved_mem.c
>+++ b/drivers/of/of_reserved_mem.c
>@@ -40,15 +40,18 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
>
> end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end;
> align = !align ? SMP_CACHE_BYTES : align;
>- base = memblock_phys_alloc_range(size, align, start, end);
>+ if (nomap) {
>+ base = memblock_phys_alloc_range_nomap(size, align, start, end);
>+ } else {
>+ base = memblock_phys_alloc_range(size, align, start, end);
>+ }
>+
> if (!base)
> return -ENOMEM;
>
> *res_base = base;
> if (nomap) {
> err = memblock_mark_nomap(base, size);
>- if (err)
>- memblock_phys_free(base, size);
I see you removed it here, seems does the same as before.
> }
>
> kmemleak_ignore_phys(base);
>diff --git a/mm/memblock.c b/mm/memblock.c
>index d09136e040d3..f103f1ecbfad 100644
>--- a/mm/memblock.c
>+++ b/mm/memblock.c
>@@ -1506,6 +1506,72 @@ phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
> return found;
> }
>
>+phys_addr_t __init memblock_alloc_range_nid_nomap(phys_addr_t size,
>+ phys_addr_t align, phys_addr_t start,
>+ phys_addr_t end, int nid,
>+ bool exact_nid)
>+{
>+ enum memblock_flags flags = choose_memblock_flags();
>+ phys_addr_t found;
>+
>+ if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
>+ nid = NUMA_NO_NODE;
>+
>+ if (!align) {
>+ /* Can't use WARNs this early in boot on powerpc */
>+ dump_stack();
>+ align = SMP_CACHE_BYTES;
>+ }
>+
>+again:
>+ found = memblock_find_in_range_node(size, align, start, end, nid,
>+ flags);
>+ if (found)
>+ goto done;
>+
>+ if (nid != NUMA_NO_NODE && !exact_nid) {
>+ found = memblock_find_in_range_node(size, align, start,
>+ end, NUMA_NO_NODE,
>+ flags);
>+ if (found)
>+ goto done;
>+ }
>+
>+ if (flags & MEMBLOCK_MIRROR) {
>+ flags &= ~MEMBLOCK_MIRROR;
>+ pr_warn_ratelimited("Could not allocate %pap bytes of mirrored memory\n",
>+ &size);
>+ goto again;
>+ }
>+
>+ return 0;
>+
>+done:
>+ /*
>+ * Skip kmemleak for those places like kasan_init() and
>+ * early_pgtable_alloc() due to high volume.
>+ */
>+ if (end != MEMBLOCK_ALLOC_NOLEAKTRACE)
>+ /*
>+ * Memblock allocated blocks are never reported as
>+ * leaks. This is because many of these blocks are
>+ * only referred via the physical address which is
>+ * not looked up by kmemleak.
>+ */
>+ kmemleak_alloc_phys(found, size, 0);
>+
>+ /*
>+ * Some Virtual Machine platforms, such as Intel TDX or AMD SEV-SNP,
>+ * require memory to be accepted before it can be used by the
>+ * guest.
>+ *
>+ * Accept the memory of the allocated buffer.
>+ */
>+ accept_memory(found, found + size);
>+
>+ return found;
>+}
>+
> /**
> * memblock_phys_alloc_range - allocate a memory block inside specified range
> * @size: size of memory block to be allocated in bytes
>@@ -1530,6 +1596,18 @@ phys_addr_t __init memblock_phys_alloc_range(phys_addr_t size,
> false);
> }
>
>+phys_addr_t __init memblock_phys_alloc_range_nomap(phys_addr_t size,
>+ phys_addr_t align,
>+ phys_addr_t start,
>+ phys_addr_t end)
>+{
>+ memblock_dbg("%s: %llu bytes align=0x%llx from=%pa max_addr=%pa %pS\n",
>+ __func__, (u64)size, (u64)align, &start, &end,
>+ (void *)_RET_IP_);
>+ return memblock_alloc_range_nid_nomap(size, align, start, end,
>+ NUMA_NO_NODE, false);
>+}
>+
> /**
> * memblock_phys_alloc_try_nid - allocate a memory block from specified NUMA node
> * @size: size of memory block to be allocated in bytes
>--
>2.25.1
>
--
Wei Yang
Help you, Help me