2018-06-30 14:59:26

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 00/11] docs/mm: add boot time memory management docs

Hi,

Both bootmem and memblock have pretty good documentation coverage. With
some fixups and additions we get a nice overall description.

v2 changes:
* address Randy's comments

Mike Rapoport (11):
mm/bootmem: drop duplicated kernel-doc comments
docs/mm: nobootmem: fixup kernel-doc comments
docs/mm: bootmem: fix kernel-doc warnings
docs/mm: bootmem: add kernel-doc description of 'struct bootmem_data'
docs/mm: bootmem: add overview documentation
mm/memblock: add a name for memblock flags enumeration
docs/mm: memblock: update kernel-doc comments
docs/mm: memblock: add kernel-doc comments for memblock_add[_node]
docs/mm: memblock: add kernel-doc description for memblock types
docs/mm: memblock: add overview documentation
docs/mm: add description of boot time memory management

Documentation/core-api/boot-time-mm.rst | 92 +++++++++++++++
Documentation/core-api/index.rst | 1 +
include/linux/bootmem.h | 17 ++-
include/linux/memblock.h | 76 ++++++++----
mm/bootmem.c | 159 +++++++++----------------
mm/memblock.c | 203 +++++++++++++++++++++++---------
mm/nobootmem.c | 20 +++-
7 files changed, 380 insertions(+), 188 deletions(-)
create mode 100644 Documentation/core-api/boot-time-mm.rst

--
2.7.4



2018-06-30 14:57:35

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 03/11] docs/mm: bootmem: fix kernel-doc warnings

Add descriptions of the return value where they were missing and fixup the
syntax for present ones.

Signed-off-by: Mike Rapoport <[email protected]>
---
mm/bootmem.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/mm/bootmem.c b/mm/bootmem.c
index 42ab0da..76fc17e 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -62,6 +62,8 @@ static unsigned long __init bootmap_bytes(unsigned long pages)
/**
* bootmem_bootmap_pages - calculate bitmap size in pages
* @pages: number of pages the bitmap has to represent
+ *
+ * Return: the number of pages needed to hold the bitmap.
*/
unsigned long __init bootmem_bootmap_pages(unsigned long pages)
{
@@ -121,7 +123,7 @@ static unsigned long __init init_bootmem_core(bootmem_data_t *bdata,
* @startpfn: first pfn on the node
* @endpfn: first pfn after the node
*
- * Returns the number of bytes needed to hold the bitmap for this node.
+ * Return: the number of bytes needed to hold the bitmap for this node.
*/
unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn,
unsigned long startpfn, unsigned long endpfn)
@@ -134,7 +136,7 @@ unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn,
* @start: pfn where the bitmap is to be placed
* @pages: number of available physical pages
*
- * Returns the number of bytes needed to hold the bitmap.
+ * Return: the number of bytes needed to hold the bitmap.
*/
unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
{
@@ -406,6 +408,8 @@ void __init free_bootmem(unsigned long physaddr, unsigned long size)
* Partial pages will be reserved.
*
* The range must reside completely on the specified node.
+ *
+ * Return: 0 on success, -errno on failure.
*/
int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
unsigned long size, int flags)
@@ -427,6 +431,8 @@ int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
* Partial pages will be reserved.
*
* The range must be contiguous but may span node boundaries.
+ *
+ * Return: 0 on success, -errno on failure.
*/
int __init reserve_bootmem(unsigned long addr, unsigned long size,
int flags)
--
2.7.4


2018-06-30 14:57:35

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 10/11] docs/mm: memblock: add overview documentation

Signed-off-by: Mike Rapoport <[email protected]>
---
mm/memblock.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)

diff --git a/mm/memblock.c b/mm/memblock.c
index 3e6be01..084f5f5 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -27,6 +27,61 @@

#include "internal.h"

+/**
+ * DOC: memblock overview
+ *
+ * Memblock is a method of managing memory regions during the early
+ * boot period when the usual kernel memory allocators are not up and
+ * running.
+ *
+ * Memblock views the system memory as collections of contiguous
+ * regions. There are several types of these collections:
+ *
+ * * ``memory`` - describes the physical memory available to the
+ * kernel; this may differ from the actual physical memory installed
+ * in the system, for instance when the memory is restricted with
+ * ``mem=`` command line parameter
+ * * ``reserved`` - describes the regions that were allocated
+ * * ``physmap`` - describes the actual physical memory regardless of
+ * the possible restrictions; the ``physmap`` type is only available
+ * on some architectures.
+ *
+ * Each region is represented by :c:type:`struct memblock_region` that
+ * defines the region extents, its attributes and NUMA node id on NUMA
+ * systems. Every memory type is described by the :c:type:`struct
+ * memblock_type` which contains an array of memory regions along with
+ * the allocator metadata. The memory types are nicely wrapped with
+ * :c:type:`struct memblock`. This structure is statically initialzed
+ * at build time. The region arrays for the "memory" and "reserved"
+ * types are initially sized to %INIT_MEMBLOCK_REGIONS and for the
+ * "physmap" type to %INIT_PHYSMEM_REGIONS.
+ * The :c:func:`memblock_allow_resize` enables automatic resizing of
+ * the region arrays during addition of new regions. This feature
+ * should be used with care so that memory allocated for the region
+ * array will not overlap with areas that should be reserved, for
+ * example initrd.
+ *
+ * The early architecture setup should tell memblock what the physical
+ * memory layout is by using :c:func:`memblock_add` or
+ * :c:func:`memblock_add_node` functions. The first function does not
+ * assign the region to a NUMA node and it is appropriate for UMA
+ * systems. Yet, it is possible to use it on NUMA systems as well and
+ * assign the region to a NUMA node later in the setup process using
+ * :c:func:`memblock_set_node`. The :c:func:`memblock_add_node`
+ * performs such an assignment directly.
+ *
+ * Once memblock is setup the memory can be allocated using either
+ * memblock or bootmem APIs.
+ *
+ * As the system boot progresses, the architecture specific
+ * :c:func:`mem_init` function frees all the memory to the buddy page
+ * allocator.
+ *
+ * If an architecure enables %CONFIG_ARCH_DISCARD_MEMBLOCK, the
+ * memblock data structures will be discarded after the system
+ * initialization compltes.
+ */
+
static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
--
2.7.4


2018-06-30 14:57:35

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 06/11] mm/memblock: add a name for memblock flags enumeration

Since kernel-doc does not like anonymous enums the name is required for
adding documentation. While on it, I've also updated all the function
declarations to use 'enum memblock_flags' instead of unsigned long.

Signed-off-by: Mike Rapoport <[email protected]>
---
include/linux/memblock.h | 22 +++++++++++-----------
mm/memblock.c | 37 +++++++++++++++++++++----------------
mm/nobootmem.c | 2 +-
3 files changed, 33 insertions(+), 28 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index ca59883..8b8fbce 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -21,7 +21,7 @@
#define INIT_PHYSMEM_REGIONS 4

/* Definition of memblock flags. */
-enum {
+enum memblock_flags {
MEMBLOCK_NONE = 0x0, /* No special request */
MEMBLOCK_HOTPLUG = 0x1, /* hotpluggable region */
MEMBLOCK_MIRROR = 0x2, /* mirrored region */
@@ -31,7 +31,7 @@ enum {
struct memblock_region {
phys_addr_t base;
phys_addr_t size;
- unsigned long flags;
+ enum memblock_flags flags;
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
int nid;
#endif
@@ -72,7 +72,7 @@ void memblock_discard(void);

phys_addr_t memblock_find_in_range_node(phys_addr_t size, phys_addr_t align,
phys_addr_t start, phys_addr_t end,
- int nid, ulong flags);
+ int nid, enum memblock_flags flags);
phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,
phys_addr_t size, phys_addr_t align);
void memblock_allow_resize(void);
@@ -89,19 +89,19 @@ int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
-ulong choose_memblock_flags(void);
+enum memblock_flags choose_memblock_flags(void);

/* Low level functions */
int memblock_add_range(struct memblock_type *type,
phys_addr_t base, phys_addr_t size,
- int nid, unsigned long flags);
+ int nid, enum memblock_flags flags);

-void __next_mem_range(u64 *idx, int nid, ulong flags,
+void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags,
struct memblock_type *type_a,
struct memblock_type *type_b, phys_addr_t *out_start,
phys_addr_t *out_end, int *out_nid);

-void __next_mem_range_rev(u64 *idx, int nid, ulong flags,
+void __next_mem_range_rev(u64 *idx, int nid, enum memblock_flags flags,
struct memblock_type *type_a,
struct memblock_type *type_b, phys_addr_t *out_start,
phys_addr_t *out_end, int *out_nid);
@@ -253,13 +253,13 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
NUMA_NO_NODE, MEMBLOCK_NONE, p_start, p_end, NULL)

static inline void memblock_set_region_flags(struct memblock_region *r,
- unsigned long flags)
+ enum memblock_flags flags)
{
r->flags |= flags;
}

static inline void memblock_clear_region_flags(struct memblock_region *r,
- unsigned long flags)
+ enum memblock_flags flags)
{
r->flags &= ~flags;
}
@@ -317,10 +317,10 @@ static inline bool memblock_bottom_up(void)

phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
phys_addr_t start, phys_addr_t end,
- ulong flags);
+ enum memblock_flags flags);
phys_addr_t memblock_alloc_base_nid(phys_addr_t size,
phys_addr_t align, phys_addr_t max_addr,
- int nid, ulong flags);
+ int nid, enum memblock_flags flags);
phys_addr_t memblock_alloc_base(phys_addr_t size, phys_addr_t align,
phys_addr_t max_addr);
phys_addr_t __memblock_alloc_base(phys_addr_t size, phys_addr_t align,
diff --git a/mm/memblock.c b/mm/memblock.c
index cc16d70..4f5aecb 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -61,7 +61,7 @@ static int memblock_can_resize __initdata_memblock;
static int memblock_memory_in_slab __initdata_memblock = 0;
static int memblock_reserved_in_slab __initdata_memblock = 0;

-ulong __init_memblock choose_memblock_flags(void)
+enum memblock_flags __init_memblock choose_memblock_flags(void)
{
return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE;
}
@@ -110,7 +110,7 @@ bool __init_memblock memblock_overlaps_region(struct memblock_type *type,
static phys_addr_t __init_memblock
__memblock_find_range_bottom_up(phys_addr_t start, phys_addr_t end,
phys_addr_t size, phys_addr_t align, int nid,
- ulong flags)
+ enum memblock_flags flags)
{
phys_addr_t this_start, this_end, cand;
u64 i;
@@ -144,7 +144,7 @@ __memblock_find_range_bottom_up(phys_addr_t start, phys_addr_t end,
static phys_addr_t __init_memblock
__memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
phys_addr_t size, phys_addr_t align, int nid,
- ulong flags)
+ enum memblock_flags flags)
{
phys_addr_t this_start, this_end, cand;
u64 i;
@@ -189,7 +189,8 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
*/
phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
phys_addr_t align, phys_addr_t start,
- phys_addr_t end, int nid, ulong flags)
+ phys_addr_t end, int nid,
+ enum memblock_flags flags)
{
phys_addr_t kernel_end, ret;

@@ -252,7 +253,7 @@ phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
phys_addr_t align)
{
phys_addr_t ret;
- ulong flags = choose_memblock_flags();
+ enum memblock_flags flags = choose_memblock_flags();

again:
ret = memblock_find_in_range_node(size, align, start, end,
@@ -473,7 +474,8 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type)
static void __init_memblock memblock_insert_region(struct memblock_type *type,
int idx, phys_addr_t base,
phys_addr_t size,
- int nid, unsigned long flags)
+ int nid,
+ enum memblock_flags flags)
{
struct memblock_region *rgn = &type->regions[idx];

@@ -505,7 +507,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,
*/
int __init_memblock memblock_add_range(struct memblock_type *type,
phys_addr_t base, phys_addr_t size,
- int nid, unsigned long flags)
+ int nid, enum memblock_flags flags)
{
bool insert = false;
phys_addr_t obase = base;
@@ -874,7 +876,8 @@ void __init_memblock __next_reserved_mem_region(u64 *idx,
* As both region arrays are sorted, the function advances the two indices
* in lockstep and returns each intersection.
*/
-void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
+void __init_memblock __next_mem_range(u64 *idx, int nid,
+ enum memblock_flags flags,
struct memblock_type *type_a,
struct memblock_type *type_b,
phys_addr_t *out_start,
@@ -983,7 +986,8 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
*
* Reverse of __next_mem_range().
*/
-void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
+void __init_memblock __next_mem_range_rev(u64 *idx, int nid,
+ enum memblock_flags flags,
struct memblock_type *type_a,
struct memblock_type *type_b,
phys_addr_t *out_start,
@@ -1141,7 +1145,8 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,

static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
phys_addr_t align, phys_addr_t start,
- phys_addr_t end, int nid, ulong flags)
+ phys_addr_t end, int nid,
+ enum memblock_flags flags)
{
phys_addr_t found;

@@ -1163,7 +1168,7 @@ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,

phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
phys_addr_t start, phys_addr_t end,
- ulong flags)
+ enum memblock_flags flags)
{
return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE,
flags);
@@ -1171,14 +1176,14 @@ phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,

phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
phys_addr_t align, phys_addr_t max_addr,
- int nid, ulong flags)
+ int nid, enum memblock_flags flags)
{
return memblock_alloc_range_nid(size, align, 0, max_addr, nid, flags);
}

phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
{
- ulong flags = choose_memblock_flags();
+ enum memblock_flags flags = choose_memblock_flags();
phys_addr_t ret;

again:
@@ -1259,7 +1264,7 @@ static void * __init memblock_virt_alloc_internal(
{
phys_addr_t alloc;
void *ptr;
- ulong flags = choose_memblock_flags();
+ enum memblock_flags flags = choose_memblock_flags();

if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
nid = NUMA_NO_NODE;
@@ -1734,7 +1739,7 @@ phys_addr_t __init_memblock memblock_get_current_limit(void)
static void __init_memblock memblock_dump(struct memblock_type *type)
{
phys_addr_t base, end, size;
- unsigned long flags;
+ enum memblock_flags flags;
int idx;
struct memblock_region *rgn;

@@ -1752,7 +1757,7 @@ static void __init_memblock memblock_dump(struct memblock_type *type)
snprintf(nid_buf, sizeof(nid_buf), " on node %d",
memblock_get_region_node(rgn));
#endif
- pr_info(" %s[%#x]\t[%pa-%pa], %pa bytes%s flags: %#lx\n",
+ pr_info(" %s[%#x]\t[%pa-%pa], %pa bytes%s flags: %#x\n",
type->name, idx, &base, &end, &size, nid_buf, flags);
}
}
diff --git a/mm/nobootmem.c b/mm/nobootmem.c
index c2cfa04..439af3b 100644
--- a/mm/nobootmem.c
+++ b/mm/nobootmem.c
@@ -42,7 +42,7 @@ static void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
{
void *ptr;
u64 addr;
- ulong flags = choose_memblock_flags();
+ enum memblock_flags flags = choose_memblock_flags();

if (limit > memblock.current_limit)
limit = memblock.current_limit;
--
2.7.4


2018-06-30 14:57:41

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 08/11] docs/mm: memblock: add kernel-doc comments for memblock_add[_node]

Signed-off-by: Mike Rapoport <[email protected]>
---
mm/memblock.c | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/mm/memblock.c b/mm/memblock.c
index 8159869..3e6be01 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -595,12 +595,35 @@ int __init_memblock memblock_add_range(struct memblock_type *type,
}
}

+/**
+ * memblock_add_node - add new memblock region within a NUMA node
+ * @base: base address of the new region
+ * @size: size of the new region
+ * @nid: nid of the new region
+ *
+ * Add new memblock region [@base, @base + @size) to the "memory"
+ * type. See memblock_add_range() description for mode details
+ *
+ * Return:
+ * 0 on success, -errno on failure.
+ */
int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size,
int nid)
{
return memblock_add_range(&memblock.memory, base, size, nid, 0);
}

+/**
+ * memblock_add - add new memblock region
+ * @base: base address of the new region
+ * @size: size of the new region
+ *
+ * Add new memblock region [@base, @base + @size) to the "memory"
+ * type. See memblock_add_range() description for mode details
+ *
+ * Return:
+ * 0 on success, -errno on failure.
+ */
int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
{
phys_addr_t end = base + size - 1;
@@ -1464,9 +1487,9 @@ void __init __memblock_free_early(phys_addr_t base, phys_addr_t size)
memblock_remove_range(&memblock.reserved, base, size);
}

-/*
+/**
* __memblock_free_late - free bootmem block pages directly to buddy allocator
- * @addr: phys starting address of the boot memory block
+ * @base: phys starting address of the boot memory block
* @size: size of the boot memory block in bytes
*
* This is only useful when the bootmem allocator has already been torn
--
2.7.4


2018-06-30 14:58:10

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 04/11] docs/mm: bootmem: add kernel-doc description of 'struct bootmem_data'

Signed-off-by: Mike Rapoport <[email protected]>
---
include/linux/bootmem.h | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 7942a96..4251519 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -27,9 +27,20 @@ extern unsigned long max_pfn;
extern unsigned long long max_possible_pfn;

#ifndef CONFIG_NO_BOOTMEM
-/*
- * node_bootmem_map is a map pointer - the bits represent all physical
- * memory pages (including holes) on the node.
+/**
+ * struct bootmem_data - per-node information used by the bootmem allocator
+ * @node_min_pfn: the starting physical address of the node's memory
+ * @node_low_pfn: the end physical address of the directly addressable memory
+ * @node_bootmem_map: is a bitmap pointer - the bits represent all physical
+ * memory pages (including holes) on the node.
+ * @last_end_off: the offset within the page of the end of the last allocation;
+ * if 0, the page used is full
+ * @hint_idx: the PFN of the page used with the last allocation;
+ * together with using this with the @last_end_offset field,
+ * a test can be made to see if allocations can be merged
+ * with the page used for the last allocation rather than
+ * using up a full new page.
+ * @list: list entry in the linked list ordered by the memory addresses
*/
typedef struct bootmem_data {
unsigned long node_min_pfn;
--
2.7.4


2018-06-30 14:58:17

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 09/11] docs/mm: memblock: add kernel-doc description for memblock types

Signed-off-by: Mike Rapoport <[email protected]>
---
include/linux/memblock.h | 37 +++++++++++++++++++++++++++++++++----
1 file changed, 33 insertions(+), 4 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 63704c6..5169205 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -20,7 +20,13 @@
#define INIT_MEMBLOCK_REGIONS 128
#define INIT_PHYSMEM_REGIONS 4

-/* Definition of memblock flags. */
+/**
+ * enum memblock_flags - definition of memory region attributes
+ * @MEMBLOCK_NONE: no special request
+ * @MEMBLOCK_HOTPLUG: hotpluggable region
+ * @MEMBLOCK_MIRROR: mirrored region
+ * @MEMBLOCK_NOMAP: don't add to kernel direct mapping
+ */
enum memblock_flags {
MEMBLOCK_NONE = 0x0, /* No special request */
MEMBLOCK_HOTPLUG = 0x1, /* hotpluggable region */
@@ -28,6 +34,13 @@ enum memblock_flags {
MEMBLOCK_NOMAP = 0x4, /* don't add to kernel direct mapping */
};

+/**
+ * struct memblock_region - represents a memory region
+ * @base: physical address of the region
+ * @size: size of the region
+ * @flags: memory region attributes
+ * @nid: NUMA node id
+ */
struct memblock_region {
phys_addr_t base;
phys_addr_t size;
@@ -37,14 +50,30 @@ struct memblock_region {
#endif
};

+/**
+ * struct memblock_type - collection of memory regions of certain type
+ * @cnt: number of regions
+ * @max: size of the allocated array
+ * @total_size: size of all regions
+ * @regions: array of regions
+ * @name: the memory type symbolic name
+ */
struct memblock_type {
- unsigned long cnt; /* number of regions */
- unsigned long max; /* size of the allocated array */
- phys_addr_t total_size; /* size of all regions */
+ unsigned long cnt;
+ unsigned long max;
+ phys_addr_t total_size;
struct memblock_region *regions;
char *name;
};

+/**
+ * struct memblock - memblock allocator metadata
+ * @bottom_up: is bottom up direction?
+ * @current_limit: physical address of the current allocation limit
+ * @memory: usabe memory regions
+ * @reserved: reserved memory regions
+ * @physmem: all physical memory
+ */
struct memblock {
bool bottom_up; /* is bottom up direction? */
phys_addr_t current_limit;
--
2.7.4


2018-06-30 14:58:24

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 11/11] docs/mm: add description of boot time memory management

Both bootmem and memblock are have pretty good internal documentation
coverage. With addition of some overview we get a nice description of the
early memory management.

Signed-off-by: Mike Rapoport <[email protected]>
---
Documentation/core-api/boot-time-mm.rst | 92 +++++++++++++++++++++++++++++++++
Documentation/core-api/index.rst | 1 +
2 files changed, 93 insertions(+)
create mode 100644 Documentation/core-api/boot-time-mm.rst

diff --git a/Documentation/core-api/boot-time-mm.rst b/Documentation/core-api/boot-time-mm.rst
new file mode 100644
index 0000000..03cb164
--- /dev/null
+++ b/Documentation/core-api/boot-time-mm.rst
@@ -0,0 +1,92 @@
+===========================
+Boot time memory management
+===========================
+
+Early system initialization cannot use "normal" memory management
+simply because it is not set up yet. But there is still need to
+allocate memory for various data structures, for instance for the
+physical page allocator. To address this, a specialized allocator
+called the :ref:`Boot Memory Allocator <bootmem>`, or bootmem, was
+introduced. Several years later PowerPC developers added a "Logical
+Memory Blocks" allocator, which was later adopted by other
+architectures and renamed to :ref:`memblock <memblock>`. There is also
+a compatibility layer called `nobootmem` that translates bootmem
+allocation interfaces to memblock calls.
+
+The selection of the early allocator is done using
+``CONFIG_NO_BOOTMEM`` and ``CONFIG_HAVE_MEMBLOCK`` kernel
+configuration options. These options are enabled or disabled
+statically by the architectures' Kconfig files.
+
+* Architectures that rely only on bootmem select
+ ``CONFIG_NO_BOOTMEM=n && CONFIG_HAVE_MEMBLOCK=n``.
+* The users of memblock with the nobootmem compatibility layer set
+ ``CONFIG_NO_BOOTMEM=y && CONFIG_HAVE_MEMBLOCK=y``.
+* And for those that use both memblock and bootmem the configuration
+ includes ``CONFIG_NO_BOOTMEM=n && CONFIG_HAVE_MEMBLOCK=y``.
+
+Whichever allocator is used, it is the responsibility of the
+architecture specific initialization to set it up in
+:c:func:`setup_arch` and tear it down in :c:func:`mem_init` functions.
+
+Once the early memory management is available it offers a variety of
+functions and macros for memory allocations. The allocation request
+may be directed to the first (and probably the only) node or to a
+particular node in a NUMA system. There are API variants that panic
+when an allocation fails and those that don't. And more recent and
+advanced memblock even allows controlling its own behaviour.
+
+.. _bootmem:
+
+Bootmem
+=======
+
+(mostly stolen from Mel Gorman's "Understanding the Linux Virtual
+Memory Manager" `book`_)
+
+.. _book: https://www.kernel.org/doc/gorman/
+
+.. kernel-doc:: mm/bootmem.c
+ :doc: bootmem overview
+
+.. _memblock:
+
+Memblock
+========
+
+.. kernel-doc:: mm/memblock.c
+ :doc: memblock overview
+
+
+Functions and structures
+========================
+
+Common API
+----------
+
+The functions that are described in this section are available
+regardless of what early memory manager is enabled.
+
+.. kernel-doc:: mm/nobootmem.c
+
+Bootmem specific API
+--------------------
+
+These interfaces available only with bootmem, i.e when ``CONFIG_NO_BOOTMEM=n``
+
+.. kernel-doc:: include/linux/bootmem.h
+.. kernel-doc:: mm/bootmem.c
+ :nodocs:
+
+Memblock specific API
+---------------------
+
+Here is the description of memblock data structures, functions and
+macros. Some of them are actually internal, but since they are
+documented it would be silly to omit them. Besides, reading the
+descriptions for the internal functions can help to understand what
+really happens under the hood.
+
+.. kernel-doc:: include/linux/memblock.h
+.. kernel-doc:: mm/memblock.c
+ :nodocs:
diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
index f5a66b7..93d5a46 100644
--- a/Documentation/core-api/index.rst
+++ b/Documentation/core-api/index.rst
@@ -28,6 +28,7 @@ Core utilities
printk-formats
circular-buffers
gfp_mask-from-fs-io
+ boot-time-mm

Interfaces for kernel debugging
===============================
--
2.7.4


2018-06-30 14:58:34

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 02/11] docs/mm: nobootmem: fixup kernel-doc comments

* add kernel-doc marking to free_bootmem_late() description
* add return value descriptions
* mention that address parameter of free_bootmem{_node} is a physical address

Signed-off-by: Mike Rapoport <[email protected]>
---
mm/nobootmem.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/mm/nobootmem.c b/mm/nobootmem.c
index 9b02fda..c2cfa04 100644
--- a/mm/nobootmem.c
+++ b/mm/nobootmem.c
@@ -72,7 +72,7 @@ static void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
return ptr;
}

-/*
+/**
* free_bootmem_late - free bootmem pages directly to page allocator
* @addr: starting address of the range
* @size: size of the range in bytes
@@ -176,7 +176,7 @@ void __init reset_all_zones_managed_pages(void)
/**
* free_all_bootmem - release free pages to the buddy allocator
*
- * Returns the number of pages actually released.
+ * Return: the number of pages actually released.
*/
unsigned long __init free_all_bootmem(void)
{
@@ -193,7 +193,7 @@ unsigned long __init free_all_bootmem(void)
/**
* free_bootmem_node - mark a page range as usable
* @pgdat: node the range resides on
- * @physaddr: starting address of the range
+ * @physaddr: starting physical address of the range
* @size: size of the range in bytes
*
* Partial pages will be considered reserved and left as they are.
@@ -208,7 +208,7 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,

/**
* free_bootmem - mark a page range as usable
- * @addr: starting address of the range
+ * @addr: starting physical address of the range
* @size: size of the range in bytes
*
* Partial pages will be considered reserved and left as they are.
@@ -256,7 +256,7 @@ static void * __init ___alloc_bootmem_nopanic(unsigned long size,
*
* Allocation may happen on any node in the system.
*
- * Returns NULL on failure.
+ * Return: address of the allocated region or %NULL on failure.
*/
void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
unsigned long goal)
@@ -293,6 +293,8 @@ static void * __init ___alloc_bootmem(unsigned long size, unsigned long align,
* Allocation may happen on any node in the system.
*
* The function panics if the request can not be satisfied.
+ *
+ * Return: address of the allocated region.
*/
void * __init __alloc_bootmem(unsigned long size, unsigned long align,
unsigned long goal)
@@ -367,6 +369,8 @@ static void * __init ___alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
* can not hold the requested memory.
*
* The function panics if the request can not be satisfied.
+ *
+ * Return: address of the allocated region.
*/
void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
unsigned long align, unsigned long goal)
@@ -396,6 +400,8 @@ void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
* Allocation may happen on any node in the system.
*
* The function panics if the request can not be satisfied.
+ *
+ * Return: address of the allocated region.
*/
void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
unsigned long goal)
@@ -425,6 +431,8 @@ void * __init __alloc_bootmem_low_nopanic(unsigned long size,
* can not hold the requested memory.
*
* The function panics if the request can not be satisfied.
+ *
+ * Return: address of the allocated region.
*/
void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size,
unsigned long align, unsigned long goal)
--
2.7.4


2018-06-30 14:58:42

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 07/11] docs/mm: memblock: update kernel-doc comments

* make memblock_discard description kernel-doc compatible
* add brief description for memblock_setclr_flag and describe its
parameters
* fixup return value descriptions

Signed-off-by: Mike Rapoport <[email protected]>
---
include/linux/memblock.h | 17 +++++++---
mm/memblock.c | 84 +++++++++++++++++++++++++++---------------------
2 files changed, 59 insertions(+), 42 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 8b8fbce..63704c6 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -239,7 +239,6 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
/**
* for_each_resv_unavail_range - iterate through reserved and unavailable memory
* @i: u64 used as loop variable
- * @flags: pick from blocks based on memory attributes
* @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
* @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
*
@@ -367,8 +366,10 @@ phys_addr_t memblock_get_current_limit(void);
*/

/**
- * memblock_region_memory_base_pfn - Return the lowest pfn intersecting with the memory region
+ * memblock_region_memory_base_pfn - get the lowest pfn of the memory region
* @reg: memblock_region structure
+ *
+ * Return: the lowest pfn intersecting with the memory region
*/
static inline unsigned long memblock_region_memory_base_pfn(const struct memblock_region *reg)
{
@@ -376,8 +377,10 @@ static inline unsigned long memblock_region_memory_base_pfn(const struct membloc
}

/**
- * memblock_region_memory_end_pfn - Return the end_pfn this region
+ * memblock_region_memory_end_pfn - get the end pfn of the memory region
* @reg: memblock_region structure
+ *
+ * Return: the end_pfn of the reserved region
*/
static inline unsigned long memblock_region_memory_end_pfn(const struct memblock_region *reg)
{
@@ -385,8 +388,10 @@ static inline unsigned long memblock_region_memory_end_pfn(const struct memblock
}

/**
- * memblock_region_reserved_base_pfn - Return the lowest pfn intersecting with the reserved region
+ * memblock_region_reserved_base_pfn - get the lowest pfn of the reserved region
* @reg: memblock_region structure
+ *
+ * Return: the lowest pfn intersecting with the reserved region
*/
static inline unsigned long memblock_region_reserved_base_pfn(const struct memblock_region *reg)
{
@@ -394,8 +399,10 @@ static inline unsigned long memblock_region_reserved_base_pfn(const struct membl
}

/**
- * memblock_region_reserved_end_pfn - Return the end_pfn this region
+ * memblock_region_reserved_end_pfn - get the end pfn of the reserved region
* @reg: memblock_region structure
+ *
+ * Return: the end_pfn of the reserved region
*/
static inline unsigned long memblock_region_reserved_end_pfn(const struct memblock_region *reg)
{
diff --git a/mm/memblock.c b/mm/memblock.c
index 4f5aecb..8159869 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -93,10 +93,11 @@ bool __init_memblock memblock_overlaps_region(struct memblock_type *type,
return i < type->cnt;
}

-/*
+/**
* __memblock_find_range_bottom_up - find free area utility in bottom-up
* @start: start of candidate range
- * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
+ * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
+ * %MEMBLOCK_ALLOC_ACCESSIBLE
* @size: size of free area to find
* @align: alignment of free area to find
* @nid: nid of the free area to find, %NUMA_NO_NODE for any node
@@ -104,7 +105,7 @@ bool __init_memblock memblock_overlaps_region(struct memblock_type *type,
*
* Utility called from memblock_find_in_range_node(), find free area bottom-up.
*
- * RETURNS:
+ * Return:
* Found address on success, 0 on failure.
*/
static phys_addr_t __init_memblock
@@ -130,7 +131,8 @@ __memblock_find_range_bottom_up(phys_addr_t start, phys_addr_t end,
/**
* __memblock_find_range_top_down - find free area utility, in top-down
* @start: start of candidate range
- * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
+ * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
+ * %MEMBLOCK_ALLOC_ACCESSIBLE
* @size: size of free area to find
* @align: alignment of free area to find
* @nid: nid of the free area to find, %NUMA_NO_NODE for any node
@@ -138,7 +140,7 @@ __memblock_find_range_bottom_up(phys_addr_t start, phys_addr_t end,
*
* Utility called from memblock_find_in_range_node(), find free area top-down.
*
- * RETURNS:
+ * Return:
* Found address on success, 0 on failure.
*/
static phys_addr_t __init_memblock
@@ -170,7 +172,8 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
* @size: size of free area to find
* @align: alignment of free area to find
* @start: start of candidate range
- * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
+ * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
+ * %MEMBLOCK_ALLOC_ACCESSIBLE
* @nid: nid of the free area to find, %NUMA_NO_NODE for any node
* @flags: pick from blocks based on memory attributes
*
@@ -184,7 +187,7 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
*
* If bottom-up allocation failed, will try to allocate memory top-down.
*
- * RETURNS:
+ * Return:
* Found address on success, 0 on failure.
*/
phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
@@ -239,13 +242,14 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
/**
* memblock_find_in_range - find free area in given range
* @start: start of candidate range
- * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
+ * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
+ * %MEMBLOCK_ALLOC_ACCESSIBLE
* @size: size of free area to find
* @align: alignment of free area to find
*
* Find @size free area aligned to @align in the specified range.
*
- * RETURNS:
+ * Return:
* Found address on success, 0 on failure.
*/
phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
@@ -289,7 +293,7 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u

#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
/**
- * Discard memory and reserved arrays if they were allocated
+ * memblock_discard - discard memory and reserved arrays if they were allocated
*/
void __init memblock_discard(void)
{
@@ -319,11 +323,11 @@ void __init memblock_discard(void)
*
* Double the size of the @type regions array. If memblock is being used to
* allocate memory for a new reserved regions array and there is a previously
- * allocated memory range [@new_area_start,@new_area_start+@new_area_size]
+ * allocated memory range [@new_area_start, @new_area_start + @new_area_size]
* waiting to be reserved, ensure the memory used by the new array does
* not overlap.
*
- * RETURNS:
+ * Return:
* 0 on success, -1 on failure.
*/
static int __init_memblock memblock_double_array(struct memblock_type *type,
@@ -468,7 +472,7 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type)
* @nid: node id of the new region
* @flags: flags of the new region
*
- * Insert new memblock region [@base,@base+@size) into @type at @idx.
+ * Insert new memblock region [@base, @base + @size) into @type at @idx.
* @type must already have extra room to accommodate the new region.
*/
static void __init_memblock memblock_insert_region(struct memblock_type *type,
@@ -497,12 +501,12 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,
* @nid: nid of the new region
* @flags: flags of the new region
*
- * Add new memblock region [@base,@base+@size) into @type. The new region
+ * Add new memblock region [@base, @base + @size) into @type. The new region
* is allowed to overlap with existing ones - overlaps don't affect already
* existing regions. @type is guaranteed to be minimal (all neighbouring
* compatible regions are merged) after the addition.
*
- * RETURNS:
+ * Return:
* 0 on success, -errno on failure.
*/
int __init_memblock memblock_add_range(struct memblock_type *type,
@@ -616,11 +620,11 @@ int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
* @end_rgn: out parameter for the end of isolated region
*
* Walk @type and ensure that regions don't cross the boundaries defined by
- * [@base,@base+@size). Crossing regions are split at the boundaries,
+ * [@base, @base + @size). Crossing regions are split at the boundaries,
* which may create at most two more regions. The index of the first
* region inside the range is returned in *@start_rgn and end in *@end_rgn.
*
- * RETURNS:
+ * Return:
* 0 on success, -errno on failure.
*/
static int __init_memblock memblock_isolate_range(struct memblock_type *type,
@@ -731,10 +735,15 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
}

/**
+ * memblock_setclr_flag - set or clear flag for a memory region
+ * @base: base address of the region
+ * @size: size of the region
+ * @set: set or clear the flag
+ * @flag: the flag to udpate
*
* This function isolates region [@base, @base + @size), and sets/clears flag
*
- * Return 0 on success, -errno on failure.
+ * Return: 0 on success, -errno on failure.
*/
static int __init_memblock memblock_setclr_flag(phys_addr_t base,
phys_addr_t size, int set, int flag)
@@ -761,7 +770,7 @@ static int __init_memblock memblock_setclr_flag(phys_addr_t base,
* @base: the base phys addr of the region
* @size: the size of the region
*
- * Return 0 on success, -errno on failure.
+ * Return: 0 on success, -errno on failure.
*/
int __init_memblock memblock_mark_hotplug(phys_addr_t base, phys_addr_t size)
{
@@ -773,7 +782,7 @@ int __init_memblock memblock_mark_hotplug(phys_addr_t base, phys_addr_t size)
* @base: the base phys addr of the region
* @size: the size of the region
*
- * Return 0 on success, -errno on failure.
+ * Return: 0 on success, -errno on failure.
*/
int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size)
{
@@ -785,7 +794,7 @@ int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size)
* @base: the base phys addr of the region
* @size: the size of the region
*
- * Return 0 on success, -errno on failure.
+ * Return: 0 on success, -errno on failure.
*/
int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
{
@@ -799,7 +808,7 @@ int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
* @base: the base phys addr of the region
* @size: the size of the region
*
- * Return 0 on success, -errno on failure.
+ * Return: 0 on success, -errno on failure.
*/
int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
{
@@ -811,7 +820,7 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
* @base: the base phys addr of the region
* @size: the size of the region
*
- * Return 0 on success, -errno on failure.
+ * Return: 0 on success, -errno on failure.
*/
int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
{
@@ -972,9 +981,6 @@ void __init_memblock __next_mem_range(u64 *idx, int nid,
/**
* __next_mem_range_rev - generic next function for for_each_*_range_rev()
*
- * Finds the next range from type_a which is not marked as unsuitable
- * in type_b.
- *
* @idx: pointer to u64 loop variable
* @nid: node selector, %NUMA_NO_NODE for all nodes
* @flags: pick from blocks based on memory attributes
@@ -984,6 +990,9 @@ void __init_memblock __next_mem_range(u64 *idx, int nid,
* @out_end: ptr to phys_addr_t for end address of the range, can be %NULL
* @out_nid: ptr to int for nid of the range, can be %NULL
*
+ * Finds the next range from type_a which is not marked as unsuitable
+ * in type_b.
+ *
* Reverse of __next_mem_range().
*/
void __init_memblock __next_mem_range_rev(u64 *idx, int nid,
@@ -1119,10 +1128,10 @@ void __init_memblock __next_mem_pfn_range(int *idx, int nid,
* @type: memblock type to set node ID for
* @nid: node ID to set
*
- * Set the nid of memblock @type regions in [@base,@base+@size) to @nid.
+ * Set the nid of memblock @type regions in [@base, @base + @size) to @nid.
* Regions which cross the area boundaries are split as necessary.
*
- * RETURNS:
+ * Return:
* 0 on success, -errno on failure.
*/
int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
@@ -1246,7 +1255,7 @@ phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, i
* The allocation is performed from memory region limited by
* memblock.current_limit if @max_addr == %BOOTMEM_ALLOC_ACCESSIBLE.
*
- * The memory block is aligned on SMP_CACHE_BYTES if @align == 0.
+ * The memory block is aligned on %SMP_CACHE_BYTES if @align == 0.
*
* The phys address of allocated boot memory block is converted to virtual and
* allocated memory is reset to 0.
@@ -1254,7 +1263,7 @@ phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, i
* In addition, function sets the min_count to 0 using kmemleak_alloc for
* allocated boot memory block, so that it is never reported as leaks.
*
- * RETURNS:
+ * Return:
* Virtual address of allocated memory block on success, NULL on failure.
*/
static void * __init memblock_virt_alloc_internal(
@@ -1339,7 +1348,7 @@ static void * __init memblock_virt_alloc_internal(
* info), if enabled. Does not zero allocated memory, does not panic if request
* cannot be satisfied.
*
- * RETURNS:
+ * Return:
* Virtual address of allocated memory block on success, NULL on failure.
*/
void * __init memblock_virt_alloc_try_nid_raw(
@@ -1376,7 +1385,7 @@ void * __init memblock_virt_alloc_try_nid_raw(
* Public function, provides additional debug information (including caller
* info), if enabled. This function zeroes the allocated memory.
*
- * RETURNS:
+ * Return:
* Virtual address of allocated memory block on success, NULL on failure.
*/
void * __init memblock_virt_alloc_try_nid_nopanic(
@@ -1412,7 +1421,7 @@ void * __init memblock_virt_alloc_try_nid_nopanic(
* which provides debug information (including caller info), if enabled,
* and panics if the request can not be satisfied.
*
- * RETURNS:
+ * Return:
* Virtual address of allocated memory block on success, NULL on failure.
*/
void * __init memblock_virt_alloc_try_nid(
@@ -1669,9 +1678,9 @@ int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
* @base: base of region to check
* @size: size of region to check
*
- * Check if the region [@base, @base+@size) is a subset of a memory block.
+ * Check if the region [@base, @base + @size) is a subset of a memory block.
*
- * RETURNS:
+ * Return:
* 0 if false, non-zero if true
*/
bool __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
@@ -1690,9 +1699,10 @@ bool __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t siz
* @base: base of region to check
* @size: size of region to check
*
- * Check if the region [@base, @base+@size) intersects a reserved memory block.
+ * Check if the region [@base, @base + @size) intersects a reserved
+ * memory block.
*
- * RETURNS:
+ * Return:
* True if they intersect, false if not.
*/
bool __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size)
--
2.7.4


2018-06-30 14:59:56

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 05/11] docs/mm: bootmem: add overview documentation

Signed-off-by: Mike Rapoport <[email protected]>
---
mm/bootmem.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)

diff --git a/mm/bootmem.c b/mm/bootmem.c
index 76fc17e..97db0e8 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -21,6 +21,53 @@

#include "internal.h"

+/**
+ * DOC: bootmem overview
+ *
+ * Bootmem is a boot-time physical memory allocator and configurator.
+ *
+ * It is used early in the boot process before the page allocator is
+ * set up.
+ *
+ * Bootmem is based on the most basic of allocators, a First Fit
+ * allocator which uses a bitmap to represent memory. If a bit is 1,
+ * the page is allocated and 0 if unallocated. To satisfy allocations
+ * of sizes smaller than a page, the allocator records the Page Frame
+ * Number (PFN) of the last allocation and the offset the allocation
+ * ended at. Subsequent small allocations are merged together and
+ * stored on the same page.
+ *
+ * The information used by the bootmem allocator is represented by
+ * :c:type:`struct bootmem_data`. An array to hold up to %MAX_NUMNODES
+ * such structures is statically allocated and then it is discarded
+ * when the system initialization completes. Each entry in this array
+ * corresponds to a node with memory. For UMA systems only entry 0 is
+ * used.
+ *
+ * The bootmem allocator is initialized during early architecture
+ * specific setup. Each architecture is required to supply a
+ * :c:func:`setup_arch` function which, among other tasks, is
+ * responsible for acquiring the necessary parameters to initialise
+ * the boot memory allocator. These parameters define limits of usable
+ * physical memory:
+ *
+ * * @min_low_pfn - the lowest PFN that is available in the system
+ * * @max_low_pfn - the highest PFN that may be addressed by low
+ * memory (%ZONE_NORMAL)
+ * * @max_pfn - the last PFN available to the system.
+ *
+ * After those limits are determined, the :c:func:`init_bootmem` or
+ * :c:func:`init_bootmem_node` function should be called to initialize
+ * the bootmem allocator. The UMA case should use the `init_bootmem`
+ * function. It will initialize ``contig_page_data`` structure that
+ * represents the only memory node in the system. In the NUMA case the
+ * `init_bootmem_node` function should be called to initialize the
+ * bootmem allocator for each node.
+ *
+ * Once the allocator is set up, it is possible to use either single
+ * node or NUMA variant of the allocation APIs.
+ */
+
#ifndef CONFIG_NEED_MULTIPLE_NODES
struct pglist_data __refdata contig_page_data = {
.bdata = &bootmem_node_data[0]
--
2.7.4


2018-06-30 15:00:23

by Mike Rapoport

[permalink] [raw]
Subject: [PATCH v2 01/11] mm/bootmem: drop duplicated kernel-doc comments

Parts of the bootmem interfaces are duplicated in nobootmem.c along with
the kernel-doc comments. There is no point to keep two copies of the
comments, so let's drop the bootmem.c copy.

Signed-off-by: Mike Rapoport <[email protected]>
---
mm/bootmem.c | 102 -----------------------------------------------------------
1 file changed, 102 deletions(-)

diff --git a/mm/bootmem.c b/mm/bootmem.c
index 9e19798..42ab0da 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -143,15 +143,6 @@ unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages);
}

-/*
- * free_bootmem_late - free bootmem pages directly to page allocator
- * @addr: starting physical address of the range
- * @size: size of the range in bytes
- *
- * This is only useful when the bootmem allocator has already been torn
- * down, but we are still initializing the system. Pages are given directly
- * to the page allocator, no bootmem metadata is updated because it is gone.
- */
void __init free_bootmem_late(unsigned long physaddr, unsigned long size)
{
unsigned long cursor, end;
@@ -264,11 +255,6 @@ void __init reset_all_zones_managed_pages(void)
reset_managed_pages_done = 1;
}

-/**
- * free_all_bootmem - release free pages to the buddy allocator
- *
- * Returns the number of pages actually released.
- */
unsigned long __init free_all_bootmem(void)
{
unsigned long total_pages = 0;
@@ -385,16 +371,6 @@ static int __init mark_bootmem(unsigned long start, unsigned long end,
BUG();
}

-/**
- * free_bootmem_node - mark a page range as usable
- * @pgdat: node the range resides on
- * @physaddr: starting address of the range
- * @size: size of the range in bytes
- *
- * Partial pages will be considered reserved and left as they are.
- *
- * The range must reside completely on the specified node.
- */
void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
unsigned long size)
{
@@ -408,15 +384,6 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
mark_bootmem_node(pgdat->bdata, start, end, 0, 0);
}

-/**
- * free_bootmem - mark a page range as usable
- * @physaddr: starting physical address of the range
- * @size: size of the range in bytes
- *
- * Partial pages will be considered reserved and left as they are.
- *
- * The range must be contiguous but may span node boundaries.
- */
void __init free_bootmem(unsigned long physaddr, unsigned long size)
{
unsigned long start, end;
@@ -646,19 +613,6 @@ static void * __init ___alloc_bootmem_nopanic(unsigned long size,
return NULL;
}

-/**
- * __alloc_bootmem_nopanic - allocate boot memory without panicking
- * @size: size of the request in bytes
- * @align: alignment of the region
- * @goal: preferred starting address of the region
- *
- * The goal is dropped if it can not be satisfied and the allocation will
- * fall back to memory below @goal.
- *
- * Allocation may happen on any node in the system.
- *
- * Returns NULL on failure.
- */
void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
unsigned long goal)
{
@@ -682,19 +636,6 @@ static void * __init ___alloc_bootmem(unsigned long size, unsigned long align,
return NULL;
}

-/**
- * __alloc_bootmem - allocate boot memory
- * @size: size of the request in bytes
- * @align: alignment of the region
- * @goal: preferred starting address of the region
- *
- * The goal is dropped if it can not be satisfied and the allocation will
- * fall back to memory below @goal.
- *
- * Allocation may happen on any node in the system.
- *
- * The function panics if the request can not be satisfied.
- */
void * __init __alloc_bootmem(unsigned long size, unsigned long align,
unsigned long goal)
{
@@ -754,21 +695,6 @@ void * __init ___alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
return NULL;
}

-/**
- * __alloc_bootmem_node - allocate boot memory from a specific node
- * @pgdat: node to allocate from
- * @size: size of the request in bytes
- * @align: alignment of the region
- * @goal: preferred starting address of the region
- *
- * The goal is dropped if it can not be satisfied and the allocation will
- * fall back to memory below @goal.
- *
- * Allocation may fall back to any node in the system if the specified node
- * can not hold the requested memory.
- *
- * The function panics if the request can not be satisfied.
- */
void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
unsigned long align, unsigned long goal)
{
@@ -807,19 +733,6 @@ void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,

}

-/**
- * __alloc_bootmem_low - allocate low boot memory
- * @size: size of the request in bytes
- * @align: alignment of the region
- * @goal: preferred starting address of the region
- *
- * The goal is dropped if it can not be satisfied and the allocation will
- * fall back to memory below @goal.
- *
- * Allocation may happen on any node in the system.
- *
- * The function panics if the request can not be satisfied.
- */
void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
unsigned long goal)
{
@@ -834,21 +747,6 @@ void * __init __alloc_bootmem_low_nopanic(unsigned long size,
ARCH_LOW_ADDRESS_LIMIT);
}

-/**
- * __alloc_bootmem_low_node - allocate low boot memory from a specific node
- * @pgdat: node to allocate from
- * @size: size of the request in bytes
- * @align: alignment of the region
- * @goal: preferred starting address of the region
- *
- * The goal is dropped if it can not be satisfied and the allocation will
- * fall back to memory below @goal.
- *
- * Allocation may fall back to any node in the system if the specified node
- * can not hold the requested memory.
- *
- * The function panics if the request can not be satisfied.
- */
void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size,
unsigned long align, unsigned long goal)
{
--
2.7.4


2018-07-01 15:29:15

by Randy Dunlap

[permalink] [raw]
Subject: Re: [PATCH v2 00/11] docs/mm: add boot time memory management docs

On 06/30/18 07:54, Mike Rapoport wrote:
> Hi,
>
> Both bootmem and memblock have pretty good documentation coverage. With
> some fixups and additions we get a nice overall description.
>
> v2 changes:
> * address Randy's comments

For the series:
Acked-by: Randy Dunlap <[email protected]>

Thanks.


> Mike Rapoport (11):
> mm/bootmem: drop duplicated kernel-doc comments
> docs/mm: nobootmem: fixup kernel-doc comments
> docs/mm: bootmem: fix kernel-doc warnings
> docs/mm: bootmem: add kernel-doc description of 'struct bootmem_data'
> docs/mm: bootmem: add overview documentation
> mm/memblock: add a name for memblock flags enumeration
> docs/mm: memblock: update kernel-doc comments
> docs/mm: memblock: add kernel-doc comments for memblock_add[_node]
> docs/mm: memblock: add kernel-doc description for memblock types
> docs/mm: memblock: add overview documentation
> docs/mm: add description of boot time memory management
>
> Documentation/core-api/boot-time-mm.rst | 92 +++++++++++++++
> Documentation/core-api/index.rst | 1 +
> include/linux/bootmem.h | 17 ++-
> include/linux/memblock.h | 76 ++++++++----
> mm/bootmem.c | 159 +++++++++----------------
> mm/memblock.c | 203 +++++++++++++++++++++++---------
> mm/nobootmem.c | 20 +++-
> 7 files changed, 380 insertions(+), 188 deletions(-)
> create mode 100644 Documentation/core-api/boot-time-mm.rst
>


--
~Randy

2018-07-02 17:34:05

by Jonathan Corbet

[permalink] [raw]
Subject: Re: [PATCH v2 00/11] docs/mm: add boot time memory management docs

On Sat, 30 Jun 2018 17:54:55 +0300
Mike Rapoport <[email protected]> wrote:

> Both bootmem and memblock have pretty good documentation coverage. With
> some fixups and additions we get a nice overall description.
>
> v2 changes:
> * address Randy's comments
>
> Mike Rapoport (11):
> mm/bootmem: drop duplicated kernel-doc comments
> docs/mm: nobootmem: fixup kernel-doc comments
> docs/mm: bootmem: fix kernel-doc warnings
> docs/mm: bootmem: add kernel-doc description of 'struct bootmem_data'
> docs/mm: bootmem: add overview documentation
> mm/memblock: add a name for memblock flags enumeration
> docs/mm: memblock: update kernel-doc comments
> docs/mm: memblock: add kernel-doc comments for memblock_add[_node]
> docs/mm: memblock: add kernel-doc description for memblock types
> docs/mm: memblock: add overview documentation
> docs/mm: add description of boot time memory management

So this seems like good stuff overall. It digs pretty deeply into the mm
code, though, so I'm a little reluctant to apply it without an ack from an
mm developer. Alternatively, I'm happy to step back if Andrew wants to
pick the set up.

Thanks,

jon

2018-07-03 12:24:23

by Michal Hocko

[permalink] [raw]
Subject: Re: [PATCH v2 11/11] docs/mm: add description of boot time memory management

On Sat 30-06-18 17:55:06, Mike Rapoport wrote:
> Both bootmem and memblock are have pretty good internal documentation
> coverage. With addition of some overview we get a nice description of the
> early memory management.
>
> Signed-off-by: Mike Rapoport <[email protected]>

Yes this looks reasonable. I would just mention the available debugging
options and CONFIG_ARCH_DISCARD_MEMBLOCK.

Other than that looks goot to get a rough idea. Improvements can be done
on top of course.

Acked-by: Michal Hocko <[email protected]>

> ---
> Documentation/core-api/boot-time-mm.rst | 92 +++++++++++++++++++++++++++++++++
> Documentation/core-api/index.rst | 1 +
> 2 files changed, 93 insertions(+)
> create mode 100644 Documentation/core-api/boot-time-mm.rst
>
> diff --git a/Documentation/core-api/boot-time-mm.rst b/Documentation/core-api/boot-time-mm.rst
> new file mode 100644
> index 0000000..03cb164
> --- /dev/null
> +++ b/Documentation/core-api/boot-time-mm.rst
> @@ -0,0 +1,92 @@
> +===========================
> +Boot time memory management
> +===========================
> +
> +Early system initialization cannot use "normal" memory management
> +simply because it is not set up yet. But there is still need to
> +allocate memory for various data structures, for instance for the
> +physical page allocator. To address this, a specialized allocator
> +called the :ref:`Boot Memory Allocator <bootmem>`, or bootmem, was
> +introduced. Several years later PowerPC developers added a "Logical
> +Memory Blocks" allocator, which was later adopted by other
> +architectures and renamed to :ref:`memblock <memblock>`. There is also
> +a compatibility layer called `nobootmem` that translates bootmem
> +allocation interfaces to memblock calls.
> +
> +The selection of the early allocator is done using
> +``CONFIG_NO_BOOTMEM`` and ``CONFIG_HAVE_MEMBLOCK`` kernel
> +configuration options. These options are enabled or disabled
> +statically by the architectures' Kconfig files.
> +
> +* Architectures that rely only on bootmem select
> + ``CONFIG_NO_BOOTMEM=n && CONFIG_HAVE_MEMBLOCK=n``.
> +* The users of memblock with the nobootmem compatibility layer set
> + ``CONFIG_NO_BOOTMEM=y && CONFIG_HAVE_MEMBLOCK=y``.
> +* And for those that use both memblock and bootmem the configuration
> + includes ``CONFIG_NO_BOOTMEM=n && CONFIG_HAVE_MEMBLOCK=y``.
> +
> +Whichever allocator is used, it is the responsibility of the
> +architecture specific initialization to set it up in
> +:c:func:`setup_arch` and tear it down in :c:func:`mem_init` functions.
> +
> +Once the early memory management is available it offers a variety of
> +functions and macros for memory allocations. The allocation request
> +may be directed to the first (and probably the only) node or to a
> +particular node in a NUMA system. There are API variants that panic
> +when an allocation fails and those that don't. And more recent and
> +advanced memblock even allows controlling its own behaviour.
> +
> +.. _bootmem:
> +
> +Bootmem
> +=======
> +
> +(mostly stolen from Mel Gorman's "Understanding the Linux Virtual
> +Memory Manager" `book`_)
> +
> +.. _book: https://www.kernel.org/doc/gorman/
> +
> +.. kernel-doc:: mm/bootmem.c
> + :doc: bootmem overview
> +
> +.. _memblock:
> +
> +Memblock
> +========
> +
> +.. kernel-doc:: mm/memblock.c
> + :doc: memblock overview
> +
> +
> +Functions and structures
> +========================
> +
> +Common API
> +----------
> +
> +The functions that are described in this section are available
> +regardless of what early memory manager is enabled.
> +
> +.. kernel-doc:: mm/nobootmem.c
> +
> +Bootmem specific API
> +--------------------
> +
> +These interfaces available only with bootmem, i.e when ``CONFIG_NO_BOOTMEM=n``
> +
> +.. kernel-doc:: include/linux/bootmem.h
> +.. kernel-doc:: mm/bootmem.c
> + :nodocs:
> +
> +Memblock specific API
> +---------------------
> +
> +Here is the description of memblock data structures, functions and
> +macros. Some of them are actually internal, but since they are
> +documented it would be silly to omit them. Besides, reading the
> +descriptions for the internal functions can help to understand what
> +really happens under the hood.
> +
> +.. kernel-doc:: include/linux/memblock.h
> +.. kernel-doc:: mm/memblock.c
> + :nodocs:
> diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
> index f5a66b7..93d5a46 100644
> --- a/Documentation/core-api/index.rst
> +++ b/Documentation/core-api/index.rst
> @@ -28,6 +28,7 @@ Core utilities
> printk-formats
> circular-buffers
> gfp_mask-from-fs-io
> + boot-time-mm
>
> Interfaces for kernel debugging
> ===============================
> --
> 2.7.4

--
Michal Hocko
SUSE Labs

2018-07-12 07:27:13

by Mike Rapoport

[permalink] [raw]
Subject: Re: [PATCH v2 11/11] docs/mm: add description of boot time memory management

Hi,

On Tue, Jul 03, 2018 at 02:23:24PM +0200, Michal Hocko wrote:
> On Sat 30-06-18 17:55:06, Mike Rapoport wrote:
> > Both bootmem and memblock are have pretty good internal documentation
> > coverage. With addition of some overview we get a nice description of the
> > early memory management.
> >
> > Signed-off-by: Mike Rapoport <[email protected]>
>
> Yes this looks reasonable. I would just mention the available debugging
> options and CONFIG_ARCH_DISCARD_MEMBLOCK.

I'd really prefer to add it as a separate patch rather then resending the
whole series.

> Other than that looks goot to get a rough idea. Improvements can be done
> on top of course.
>
> Acked-by: Michal Hocko <[email protected]>

Thanks for the review. I think Jon was mostly concerned about the patch
"mm/memblock: add a name for memblock flags enumeration" [1]. Could you
please review it as well?

[1] https://lore.kernel.org/lkml/[email protected]/

> > ---
> > Documentation/core-api/boot-time-mm.rst | 92 +++++++++++++++++++++++++++++++++
> > Documentation/core-api/index.rst | 1 +
> > 2 files changed, 93 insertions(+)
> > create mode 100644 Documentation/core-api/boot-time-mm.rst
> >
> > diff --git a/Documentation/core-api/boot-time-mm.rst b/Documentation/core-api/boot-time-mm.rst
> > new file mode 100644
> > index 0000000..03cb164
> > --- /dev/null
> > +++ b/Documentation/core-api/boot-time-mm.rst
> > @@ -0,0 +1,92 @@
> > +===========================
> > +Boot time memory management
> > +===========================
> > +
> > +Early system initialization cannot use "normal" memory management
> > +simply because it is not set up yet. But there is still need to
> > +allocate memory for various data structures, for instance for the
> > +physical page allocator. To address this, a specialized allocator
> > +called the :ref:`Boot Memory Allocator <bootmem>`, or bootmem, was
> > +introduced. Several years later PowerPC developers added a "Logical
> > +Memory Blocks" allocator, which was later adopted by other
> > +architectures and renamed to :ref:`memblock <memblock>`. There is also
> > +a compatibility layer called `nobootmem` that translates bootmem
> > +allocation interfaces to memblock calls.
> > +
> > +The selection of the early allocator is done using
> > +``CONFIG_NO_BOOTMEM`` and ``CONFIG_HAVE_MEMBLOCK`` kernel
> > +configuration options. These options are enabled or disabled
> > +statically by the architectures' Kconfig files.
> > +
> > +* Architectures that rely only on bootmem select
> > + ``CONFIG_NO_BOOTMEM=n && CONFIG_HAVE_MEMBLOCK=n``.
> > +* The users of memblock with the nobootmem compatibility layer set
> > + ``CONFIG_NO_BOOTMEM=y && CONFIG_HAVE_MEMBLOCK=y``.
> > +* And for those that use both memblock and bootmem the configuration
> > + includes ``CONFIG_NO_BOOTMEM=n && CONFIG_HAVE_MEMBLOCK=y``.
> > +
> > +Whichever allocator is used, it is the responsibility of the
> > +architecture specific initialization to set it up in
> > +:c:func:`setup_arch` and tear it down in :c:func:`mem_init` functions.
> > +
> > +Once the early memory management is available it offers a variety of
> > +functions and macros for memory allocations. The allocation request
> > +may be directed to the first (and probably the only) node or to a
> > +particular node in a NUMA system. There are API variants that panic
> > +when an allocation fails and those that don't. And more recent and
> > +advanced memblock even allows controlling its own behaviour.
> > +
> > +.. _bootmem:
> > +
> > +Bootmem
> > +=======
> > +
> > +(mostly stolen from Mel Gorman's "Understanding the Linux Virtual
> > +Memory Manager" `book`_)
> > +
> > +.. _book: https://www.kernel.org/doc/gorman/
> > +
> > +.. kernel-doc:: mm/bootmem.c
> > + :doc: bootmem overview
> > +
> > +.. _memblock:
> > +
> > +Memblock
> > +========
> > +
> > +.. kernel-doc:: mm/memblock.c
> > + :doc: memblock overview
> > +
> > +
> > +Functions and structures
> > +========================
> > +
> > +Common API
> > +----------
> > +
> > +The functions that are described in this section are available
> > +regardless of what early memory manager is enabled.
> > +
> > +.. kernel-doc:: mm/nobootmem.c
> > +
> > +Bootmem specific API
> > +--------------------
> > +
> > +These interfaces available only with bootmem, i.e when ``CONFIG_NO_BOOTMEM=n``
> > +
> > +.. kernel-doc:: include/linux/bootmem.h
> > +.. kernel-doc:: mm/bootmem.c
> > + :nodocs:
> > +
> > +Memblock specific API
> > +---------------------
> > +
> > +Here is the description of memblock data structures, functions and
> > +macros. Some of them are actually internal, but since they are
> > +documented it would be silly to omit them. Besides, reading the
> > +descriptions for the internal functions can help to understand what
> > +really happens under the hood.
> > +
> > +.. kernel-doc:: include/linux/memblock.h
> > +.. kernel-doc:: mm/memblock.c
> > + :nodocs:
> > diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
> > index f5a66b7..93d5a46 100644
> > --- a/Documentation/core-api/index.rst
> > +++ b/Documentation/core-api/index.rst
> > @@ -28,6 +28,7 @@ Core utilities
> > printk-formats
> > circular-buffers
> > gfp_mask-from-fs-io
> > + boot-time-mm
> >
> > Interfaces for kernel debugging
> > ===============================
> > --
> > 2.7.4
>
> --
> Michal Hocko
> SUSE Labs
>

--
Sincerely yours,
Mike.


2018-07-12 08:01:02

by Michal Hocko

[permalink] [raw]
Subject: Re: [PATCH v2 06/11] mm/memblock: add a name for memblock flags enumeration

On Sat 30-06-18 17:55:01, Mike Rapoport wrote:
> Since kernel-doc does not like anonymous enums the name is required for
> adding documentation. While on it, I've also updated all the function
> declarations to use 'enum memblock_flags' instead of unsigned long.

memblock_flags doesn't tell me much about the purpose of these flags. We
could bikeshed about the name but let's keep it this way. I do not have
good tip for nice name either.

I haven't checked whether all places have been updated (the memblock api
is quite large) but this changes makes perfect sense to me. Unsigned
long is just improper type for something like this.

> Signed-off-by: Mike Rapoport <[email protected]>
> ---
> include/linux/memblock.h | 22 +++++++++++-----------
> mm/memblock.c | 37 +++++++++++++++++++++----------------
> mm/nobootmem.c | 2 +-
> 3 files changed, 33 insertions(+), 28 deletions(-)
>
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index ca59883..8b8fbce 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -21,7 +21,7 @@
> #define INIT_PHYSMEM_REGIONS 4
>
> /* Definition of memblock flags. */
> -enum {
> +enum memblock_flags {
> MEMBLOCK_NONE = 0x0, /* No special request */
> MEMBLOCK_HOTPLUG = 0x1, /* hotpluggable region */
> MEMBLOCK_MIRROR = 0x2, /* mirrored region */
> @@ -31,7 +31,7 @@ enum {
> struct memblock_region {
> phys_addr_t base;
> phys_addr_t size;
> - unsigned long flags;
> + enum memblock_flags flags;
> #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
> int nid;
> #endif
> @@ -72,7 +72,7 @@ void memblock_discard(void);
>
> phys_addr_t memblock_find_in_range_node(phys_addr_t size, phys_addr_t align,
> phys_addr_t start, phys_addr_t end,
> - int nid, ulong flags);
> + int nid, enum memblock_flags flags);
> phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,
> phys_addr_t size, phys_addr_t align);
> void memblock_allow_resize(void);
> @@ -89,19 +89,19 @@ int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
> int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
> int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
> int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
> -ulong choose_memblock_flags(void);
> +enum memblock_flags choose_memblock_flags(void);
>
> /* Low level functions */
> int memblock_add_range(struct memblock_type *type,
> phys_addr_t base, phys_addr_t size,
> - int nid, unsigned long flags);
> + int nid, enum memblock_flags flags);
>
> -void __next_mem_range(u64 *idx, int nid, ulong flags,
> +void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags,
> struct memblock_type *type_a,
> struct memblock_type *type_b, phys_addr_t *out_start,
> phys_addr_t *out_end, int *out_nid);
>
> -void __next_mem_range_rev(u64 *idx, int nid, ulong flags,
> +void __next_mem_range_rev(u64 *idx, int nid, enum memblock_flags flags,
> struct memblock_type *type_a,
> struct memblock_type *type_b, phys_addr_t *out_start,
> phys_addr_t *out_end, int *out_nid);
> @@ -253,13 +253,13 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
> NUMA_NO_NODE, MEMBLOCK_NONE, p_start, p_end, NULL)
>
> static inline void memblock_set_region_flags(struct memblock_region *r,
> - unsigned long flags)
> + enum memblock_flags flags)
> {
> r->flags |= flags;
> }
>
> static inline void memblock_clear_region_flags(struct memblock_region *r,
> - unsigned long flags)
> + enum memblock_flags flags)
> {
> r->flags &= ~flags;
> }
> @@ -317,10 +317,10 @@ static inline bool memblock_bottom_up(void)
>
> phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
> phys_addr_t start, phys_addr_t end,
> - ulong flags);
> + enum memblock_flags flags);
> phys_addr_t memblock_alloc_base_nid(phys_addr_t size,
> phys_addr_t align, phys_addr_t max_addr,
> - int nid, ulong flags);
> + int nid, enum memblock_flags flags);
> phys_addr_t memblock_alloc_base(phys_addr_t size, phys_addr_t align,
> phys_addr_t max_addr);
> phys_addr_t __memblock_alloc_base(phys_addr_t size, phys_addr_t align,
> diff --git a/mm/memblock.c b/mm/memblock.c
> index cc16d70..4f5aecb 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -61,7 +61,7 @@ static int memblock_can_resize __initdata_memblock;
> static int memblock_memory_in_slab __initdata_memblock = 0;
> static int memblock_reserved_in_slab __initdata_memblock = 0;
>
> -ulong __init_memblock choose_memblock_flags(void)
> +enum memblock_flags __init_memblock choose_memblock_flags(void)
> {
> return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE;
> }
> @@ -110,7 +110,7 @@ bool __init_memblock memblock_overlaps_region(struct memblock_type *type,
> static phys_addr_t __init_memblock
> __memblock_find_range_bottom_up(phys_addr_t start, phys_addr_t end,
> phys_addr_t size, phys_addr_t align, int nid,
> - ulong flags)
> + enum memblock_flags flags)
> {
> phys_addr_t this_start, this_end, cand;
> u64 i;
> @@ -144,7 +144,7 @@ __memblock_find_range_bottom_up(phys_addr_t start, phys_addr_t end,
> static phys_addr_t __init_memblock
> __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
> phys_addr_t size, phys_addr_t align, int nid,
> - ulong flags)
> + enum memblock_flags flags)
> {
> phys_addr_t this_start, this_end, cand;
> u64 i;
> @@ -189,7 +189,8 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
> */
> phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
> phys_addr_t align, phys_addr_t start,
> - phys_addr_t end, int nid, ulong flags)
> + phys_addr_t end, int nid,
> + enum memblock_flags flags)
> {
> phys_addr_t kernel_end, ret;
>
> @@ -252,7 +253,7 @@ phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
> phys_addr_t align)
> {
> phys_addr_t ret;
> - ulong flags = choose_memblock_flags();
> + enum memblock_flags flags = choose_memblock_flags();
>
> again:
> ret = memblock_find_in_range_node(size, align, start, end,
> @@ -473,7 +474,8 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type)
> static void __init_memblock memblock_insert_region(struct memblock_type *type,
> int idx, phys_addr_t base,
> phys_addr_t size,
> - int nid, unsigned long flags)
> + int nid,
> + enum memblock_flags flags)
> {
> struct memblock_region *rgn = &type->regions[idx];
>
> @@ -505,7 +507,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type,
> */
> int __init_memblock memblock_add_range(struct memblock_type *type,
> phys_addr_t base, phys_addr_t size,
> - int nid, unsigned long flags)
> + int nid, enum memblock_flags flags)
> {
> bool insert = false;
> phys_addr_t obase = base;
> @@ -874,7 +876,8 @@ void __init_memblock __next_reserved_mem_region(u64 *idx,
> * As both region arrays are sorted, the function advances the two indices
> * in lockstep and returns each intersection.
> */
> -void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
> +void __init_memblock __next_mem_range(u64 *idx, int nid,
> + enum memblock_flags flags,
> struct memblock_type *type_a,
> struct memblock_type *type_b,
> phys_addr_t *out_start,
> @@ -983,7 +986,8 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
> *
> * Reverse of __next_mem_range().
> */
> -void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
> +void __init_memblock __next_mem_range_rev(u64 *idx, int nid,
> + enum memblock_flags flags,
> struct memblock_type *type_a,
> struct memblock_type *type_b,
> phys_addr_t *out_start,
> @@ -1141,7 +1145,8 @@ int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
>
> static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
> phys_addr_t align, phys_addr_t start,
> - phys_addr_t end, int nid, ulong flags)
> + phys_addr_t end, int nid,
> + enum memblock_flags flags)
> {
> phys_addr_t found;
>
> @@ -1163,7 +1168,7 @@ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
>
> phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
> phys_addr_t start, phys_addr_t end,
> - ulong flags)
> + enum memblock_flags flags)
> {
> return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE,
> flags);
> @@ -1171,14 +1176,14 @@ phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
>
> phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
> phys_addr_t align, phys_addr_t max_addr,
> - int nid, ulong flags)
> + int nid, enum memblock_flags flags)
> {
> return memblock_alloc_range_nid(size, align, 0, max_addr, nid, flags);
> }
>
> phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
> {
> - ulong flags = choose_memblock_flags();
> + enum memblock_flags flags = choose_memblock_flags();
> phys_addr_t ret;
>
> again:
> @@ -1259,7 +1264,7 @@ static void * __init memblock_virt_alloc_internal(
> {
> phys_addr_t alloc;
> void *ptr;
> - ulong flags = choose_memblock_flags();
> + enum memblock_flags flags = choose_memblock_flags();
>
> if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead\n"))
> nid = NUMA_NO_NODE;
> @@ -1734,7 +1739,7 @@ phys_addr_t __init_memblock memblock_get_current_limit(void)
> static void __init_memblock memblock_dump(struct memblock_type *type)
> {
> phys_addr_t base, end, size;
> - unsigned long flags;
> + enum memblock_flags flags;
> int idx;
> struct memblock_region *rgn;
>
> @@ -1752,7 +1757,7 @@ static void __init_memblock memblock_dump(struct memblock_type *type)
> snprintf(nid_buf, sizeof(nid_buf), " on node %d",
> memblock_get_region_node(rgn));
> #endif
> - pr_info(" %s[%#x]\t[%pa-%pa], %pa bytes%s flags: %#lx\n",
> + pr_info(" %s[%#x]\t[%pa-%pa], %pa bytes%s flags: %#x\n",
> type->name, idx, &base, &end, &size, nid_buf, flags);
> }
> }
> diff --git a/mm/nobootmem.c b/mm/nobootmem.c
> index c2cfa04..439af3b 100644
> --- a/mm/nobootmem.c
> +++ b/mm/nobootmem.c
> @@ -42,7 +42,7 @@ static void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
> {
> void *ptr;
> u64 addr;
> - ulong flags = choose_memblock_flags();
> + enum memblock_flags flags = choose_memblock_flags();
>
> if (limit > memblock.current_limit)
> limit = memblock.current_limit;
> --
> 2.7.4

--
Michal Hocko
SUSE Labs

2018-07-18 11:48:58

by Mike Rapoport

[permalink] [raw]
Subject: Re: [PATCH v2 00/11] docs/mm: add boot time memory management docs

Hi,

On Mon, Jul 02, 2018 at 11:32:55AM -0600, Jonathan Corbet wrote:
> On Sat, 30 Jun 2018 17:54:55 +0300
> Mike Rapoport <[email protected]> wrote:
>
> > Both bootmem and memblock have pretty good documentation coverage. With
> > some fixups and additions we get a nice overall description.
> >
> > v2 changes:
> > * address Randy's comments
> >
> > Mike Rapoport (11):
> > mm/bootmem: drop duplicated kernel-doc comments
> > docs/mm: nobootmem: fixup kernel-doc comments
> > docs/mm: bootmem: fix kernel-doc warnings
> > docs/mm: bootmem: add kernel-doc description of 'struct bootmem_data'
> > docs/mm: bootmem: add overview documentation
> > mm/memblock: add a name for memblock flags enumeration
> > docs/mm: memblock: update kernel-doc comments
> > docs/mm: memblock: add kernel-doc comments for memblock_add[_node]
> > docs/mm: memblock: add kernel-doc description for memblock types
> > docs/mm: memblock: add overview documentation
> > docs/mm: add description of boot time memory management
>
> So this seems like good stuff overall. It digs pretty deeply into the mm
> code, though, so I'm a little reluctant to apply it without an ack from an
> mm developer. Alternatively, I'm happy to step back if Andrew wants to
> pick the set up.

Jon, does Michal's reply [1] address your concerns?
Or should I respin and ask Andrew to pick it up?

[1] https://lore.kernel.org/lkml/[email protected]/
> Thanks,
>
> jon
>

--
Sincerely yours,
Mike.


2018-07-18 12:03:46

by Jonathan Corbet

[permalink] [raw]
Subject: Re: [PATCH v2 00/11] docs/mm: add boot time memory management docs

On Wed, 18 Jul 2018 14:47:30 +0300
Mike Rapoport <[email protected]> wrote:

> > So this seems like good stuff overall. It digs pretty deeply into the mm
> > code, though, so I'm a little reluctant to apply it without an ack from an
> > mm developer. Alternatively, I'm happy to step back if Andrew wants to
> > pick the set up.
>
> Jon, does Michal's reply [1] address your concerns?
> Or should I respin and ask Andrew to pick it up?
>
> [1] https://lore.kernel.org/lkml/[email protected]/

Michal acked #11 (the docs patch) in particular but not the series as a
whole. But it's the rest of the series that I was most worried about :)
I'm happy for the patches to take either path, but I'd really like an
explicit ack before I apply that many changes directly to the MM code...

Thanks,

jon

2018-07-18 17:02:05

by Mike Rapoport

[permalink] [raw]
Subject: Re: [PATCH v2 00/11] docs/mm: add boot time memory management docs

(added Andrew)

On Wed, Jul 18, 2018 at 06:02:49AM -0600, Jonathan Corbet wrote:
> On Wed, 18 Jul 2018 14:47:30 +0300
> Mike Rapoport <[email protected]> wrote:
>
> > > So this seems like good stuff overall. It digs pretty deeply into the mm
> > > code, though, so I'm a little reluctant to apply it without an ack from an
> > > mm developer. Alternatively, I'm happy to step back if Andrew wants to
> > > pick the set up.
> >
> > Jon, does Michal's reply [1] address your concerns?
> > Or should I respin and ask Andrew to pick it up?
> >
> > [1] https://lore.kernel.org/lkml/[email protected]/
>
> Michal acked #11 (the docs patch) in particular but not the series as a
> whole. But it's the rest of the series that I was most worried about :)
> I'm happy for the patches to take either path, but I'd really like an
> explicit ack before I apply that many changes directly to the MM code...

Andrew,

Can you please take a look at this series? The thread starts at [1] and if
it'd be more convenient to you I can respin the whole set.

[1] https://lore.kernel.org/lkml/[email protected]/

> Thanks,
>
> jon
>

--
Sincerely yours,
Mike.


2018-07-26 21:47:09

by Jonathan Corbet

[permalink] [raw]
Subject: Re: [PATCH v2 00/11] docs/mm: add boot time memory management docs

On Wed, 18 Jul 2018 20:00:43 +0300
Mike Rapoport <[email protected]> wrote:

> > Michal acked #11 (the docs patch) in particular but not the series as a
> > whole. But it's the rest of the series that I was most worried about :)
> > I'm happy for the patches to take either path, but I'd really like an
> > explicit ack before I apply that many changes directly to the MM code...
>
> Andrew,
>
> Can you please take a look at this series? The thread starts at [1] and if
> it'd be more convenient to you I can respin the whole set.

It seems this hasn't happened - at least, I don't see the patches in
linux-next. Unless somebody says something I think I'll just go ahead and
merge the set. It all still applies cleanly enough, no conflicts against
-next, and I'd hate to see this work fall through the cracks.

jon

2018-08-02 18:49:30

by Jonathan Corbet

[permalink] [raw]
Subject: Re: [PATCH v2 00/11] docs/mm: add boot time memory management docs

On Thu, 26 Jul 2018 15:45:57 -0600
Jonathan Corbet <[email protected]> wrote:

> It seems this hasn't happened - at least, I don't see the patches in
> linux-next. Unless somebody says something I think I'll just go ahead and
> merge the set. It all still applies cleanly enough, no conflicts against
> -next, and I'd hate to see this work fall through the cracks.

So I have now merged this set, thanks.

jon