Skip to content

Commit 77e02cf

Browse files
committed
memblock: introduce saner 'memblock_free_ptr()' interface
The boot-time allocation interface for memblock is a mess, with 'memblock_alloc()' returning a virtual pointer, but then you are supposed to free it with 'memblock_free()' that takes a _physical_ address. Not only is that all kinds of strange and illogical, but it actually causes bugs, when people then use it like a normal allocation function, and it fails spectacularly on a NULL pointer: https://lore.kernel.org/all/20210912140820.GD25450@xsang-OptiPlex-9020/ or just random memory corruption if the debug checks don't catch it: https://lore.kernel.org/all/61ab2d0c-3313-aaab-514c-e15b7aa054a0@suse.cz/ I really don't want to apply patches that treat the symptoms, when the fundamental cause is this horribly confusing interface. I started out looking at just automating a sane replacement sequence, but because of this mix or virtual and physical addresses, and because people have used the "__pa()" macro that can take either a regular kernel pointer, or just the raw "unsigned long" address, it's all quite messy. So this just introduces a new saner interface for freeing a virtual address that was allocated using 'memblock_alloc()', and that was kept as a regular kernel pointer. And then it converts a couple of users that are obvious and easy to test, including the 'xbc_nodes' case in lib/bootconfig.c that caused problems. Reported-by: kernel test robot <oliver.sang@intel.com> Fixes: 40caa12 ("init: bootconfig: Remove all bootconfig data when the init memory is removed") Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Mike Rapoport <rppt@kernel.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 6a4746b commit 77e02cf

File tree

11 files changed

+27
-15
lines changed

11 files changed

+27
-15
lines changed

arch/x86/kernel/setup_percpu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
135135

136136
static void __init pcpu_fc_free(void *ptr, size_t size)
137137
{
138-
memblock_free(__pa(ptr), size);
138+
memblock_free_ptr(ptr, size);
139139
}
140140

141141
static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)

arch/x86/mm/kasan_init_64.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ static void __init kasan_populate_pmd(pmd_t *pmd, unsigned long addr,
4949
p = early_alloc(PMD_SIZE, nid, false);
5050
if (p && pmd_set_huge(pmd, __pa(p), PAGE_KERNEL))
5151
return;
52-
else if (p)
53-
memblock_free(__pa(p), PMD_SIZE);
52+
memblock_free_ptr(p, PMD_SIZE);
5453
}
5554

5655
p = early_alloc(PAGE_SIZE, nid, true);
@@ -86,8 +85,7 @@ static void __init kasan_populate_pud(pud_t *pud, unsigned long addr,
8685
p = early_alloc(PUD_SIZE, nid, false);
8786
if (p && pud_set_huge(pud, __pa(p), PAGE_KERNEL))
8887
return;
89-
else if (p)
90-
memblock_free(__pa(p), PUD_SIZE);
88+
memblock_free_ptr(p, PUD_SIZE);
9189
}
9290

9391
p = early_alloc(PAGE_SIZE, nid, true);

arch/x86/mm/numa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ void __init numa_reset_distance(void)
355355

356356
/* numa_distance could be 1LU marking allocation failure, test cnt */
357357
if (numa_distance_cnt)
358-
memblock_free(__pa(numa_distance), size);
358+
memblock_free_ptr(numa_distance, size);
359359
numa_distance_cnt = 0;
360360
numa_distance = NULL; /* enable table creation */
361361
}

arch/x86/mm/numa_emulation.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
517517
}
518518

519519
/* free the copied physical distance table */
520-
if (phys_dist)
521-
memblock_free(__pa(phys_dist), phys_size);
520+
memblock_free_ptr(phys_dist, phys_size);
522521
return;
523522

524523
no_emu:

drivers/base/arch_numa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ void __init numa_free_distance(void)
264264
size = numa_distance_cnt * numa_distance_cnt *
265265
sizeof(numa_distance[0]);
266266

267-
memblock_free(__pa(numa_distance), size);
267+
memblock_free_ptr(numa_distance, size);
268268
numa_distance_cnt = 0;
269269
numa_distance = NULL;
270270
}

drivers/macintosh/smu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ int __init smu_init (void)
570570
fail_db_node:
571571
of_node_put(smu->db_node);
572572
fail_bootmem:
573-
memblock_free(__pa(smu), sizeof(struct smu_device));
573+
memblock_free_ptr(smu, sizeof(struct smu_device));
574574
smu = NULL;
575575
fail_np:
576576
of_node_put(np);

include/linux/memblock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
118118
int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
119119

120120
void memblock_free_all(void);
121+
void memblock_free_ptr(void *ptr, size_t size);
121122
void reset_node_managed_pages(pg_data_t *pgdat);
122123
void reset_all_zones_managed_pages(void);
123124

init/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ static void __init print_unknown_bootoptions(void)
924924
end += sprintf(end, " %s", *p);
925925

926926
pr_notice("Unknown command line parameters:%s\n", unknown_options);
927-
memblock_free(__pa(unknown_options), len);
927+
memblock_free_ptr(unknown_options, len);
928928
}
929929

930930
asmlinkage __visible void __init __no_sanitize_address start_kernel(void)

kernel/printk/printk.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,9 +1166,9 @@ void __init setup_log_buf(int early)
11661166
return;
11671167

11681168
err_free_descs:
1169-
memblock_free(__pa(new_descs), new_descs_size);
1169+
memblock_free_ptr(new_descs, new_descs_size);
11701170
err_free_log_buf:
1171-
memblock_free(__pa(new_log_buf), new_log_buf_len);
1171+
memblock_free_ptr(new_log_buf, new_log_buf_len);
11721172
}
11731173

11741174
static bool __read_mostly ignore_loglevel;

lib/bootconfig.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ void __init xbc_destroy_all(void)
792792
xbc_data = NULL;
793793
xbc_data_size = 0;
794794
xbc_node_num = 0;
795-
memblock_free(__pa(xbc_nodes), sizeof(struct xbc_node) * XBC_NODE_MAX);
795+
memblock_free_ptr(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX);
796796
xbc_nodes = NULL;
797797
brace_index = 0;
798798
}

mm/memblock.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
472472
kfree(old_array);
473473
else if (old_array != memblock_memory_init_regions &&
474474
old_array != memblock_reserved_init_regions)
475-
memblock_free(__pa(old_array), old_alloc_size);
475+
memblock_free_ptr(old_array, old_alloc_size);
476476

477477
/*
478478
* Reserve the new array if that comes from the memblock. Otherwise, we
@@ -795,6 +795,20 @@ int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
795795
return memblock_remove_range(&memblock.memory, base, size);
796796
}
797797

798+
/**
799+
* memblock_free_ptr - free boot memory allocation
800+
* @ptr: starting address of the boot memory allocation
801+
* @size: size of the boot memory block in bytes
802+
*
803+
* Free boot memory block previously allocated by memblock_alloc_xx() API.
804+
* The freeing memory will not be released to the buddy allocator.
805+
*/
806+
void __init_memblock memblock_free_ptr(void *ptr, size_t size)
807+
{
808+
if (ptr)
809+
memblock_free(__pa(ptr), size);
810+
}
811+
798812
/**
799813
* memblock_free - free boot memory block
800814
* @base: phys starting address of the boot memory block

0 commit comments

Comments
 (0)