mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 12:35:52 +02:00
memblock, treewide: make memblock_free() handle late freeing
It shouldn't be responsibility of memblock users to detect if they free memory allocated from memblock late and should use memblock_free_late(). Make memblock_free() and memblock_phys_free() take care of late memory freeing and drop memblock_free_late(). Link: https://patch.msgid.link/20260323074836.3653702-9-rppt@kernel.org Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
This commit is contained in:
parent
b2129a3951
commit
87ce9e83ab
|
|
@ -183,14 +183,12 @@ static struct mdesc_handle * __init mdesc_memblock_alloc(unsigned int mdesc_size
|
||||||
static void __init mdesc_memblock_free(struct mdesc_handle *hp)
|
static void __init mdesc_memblock_free(struct mdesc_handle *hp)
|
||||||
{
|
{
|
||||||
unsigned int alloc_size;
|
unsigned int alloc_size;
|
||||||
unsigned long start;
|
|
||||||
|
|
||||||
BUG_ON(refcount_read(&hp->refcnt) != 0);
|
BUG_ON(refcount_read(&hp->refcnt) != 0);
|
||||||
BUG_ON(!list_empty(&hp->list));
|
BUG_ON(!list_empty(&hp->list));
|
||||||
|
|
||||||
alloc_size = PAGE_ALIGN(hp->handle_size);
|
alloc_size = PAGE_ALIGN(hp->handle_size);
|
||||||
start = __pa(hp);
|
memblock_free(hp, alloc_size);
|
||||||
memblock_free_late(start, alloc_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mdesc_mem_ops memblock_mdesc_ops = {
|
static struct mdesc_mem_ops memblock_mdesc_ops = {
|
||||||
|
|
|
||||||
|
|
@ -426,7 +426,7 @@ int __init ima_free_kexec_buffer(void)
|
||||||
if (!ima_kexec_buffer_size)
|
if (!ima_kexec_buffer_size)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
memblock_free_late(ima_kexec_buffer_phys,
|
memblock_phys_free(ima_kexec_buffer_phys,
|
||||||
ima_kexec_buffer_size);
|
ima_kexec_buffer_size);
|
||||||
|
|
||||||
ima_kexec_buffer_phys = 0;
|
ima_kexec_buffer_phys = 0;
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,6 @@ static
|
||||||
void __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags)
|
void __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags)
|
||||||
{
|
{
|
||||||
if (flags & EFI_MEMMAP_MEMBLOCK) {
|
if (flags & EFI_MEMMAP_MEMBLOCK) {
|
||||||
if (slab_is_available())
|
|
||||||
memblock_free_late(phys, size);
|
|
||||||
else
|
|
||||||
memblock_phys_free(phys, size);
|
memblock_phys_free(phys, size);
|
||||||
} else if (flags & EFI_MEMMAP_SLAB) {
|
} else if (flags & EFI_MEMMAP_SLAB) {
|
||||||
struct page *p = pfn_to_page(PHYS_PFN(phys));
|
struct page *p = pfn_to_page(PHYS_PFN(phys));
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ void __init efi_reserve_boot_services(void)
|
||||||
* doesn't make sense as far as the firmware is
|
* doesn't make sense as far as the firmware is
|
||||||
* concerned, but it does provide us with a way to tag
|
* concerned, but it does provide us with a way to tag
|
||||||
* those regions that must not be paired with
|
* those regions that must not be paired with
|
||||||
* memblock_free_late().
|
* memblock_phys_free().
|
||||||
*/
|
*/
|
||||||
md->attribute |= EFI_MEMORY_RUNTIME;
|
md->attribute |= EFI_MEMORY_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ static int __init map_properties(void)
|
||||||
*/
|
*/
|
||||||
data->len = 0;
|
data->len = 0;
|
||||||
memunmap(data);
|
memunmap(data);
|
||||||
memblock_free_late(pa_data + sizeof(*data), data_len);
|
memblock_phys_free(pa_data + sizeof(*data), data_len);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ int __init ima_free_kexec_buffer(void)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
memblock_free_late(addr, size);
|
memblock_phys_free(addr, size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -172,8 +172,6 @@ void __next_mem_range_rev(u64 *idx, int nid, enum memblock_flags flags,
|
||||||
struct memblock_type *type_b, phys_addr_t *out_start,
|
struct memblock_type *type_b, phys_addr_t *out_start,
|
||||||
phys_addr_t *out_end, int *out_nid);
|
phys_addr_t *out_end, int *out_nid);
|
||||||
|
|
||||||
void memblock_free_late(phys_addr_t base, phys_addr_t size);
|
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
|
#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
|
||||||
static inline void __next_physmem_range(u64 *idx, struct memblock_type *type,
|
static inline void __next_physmem_range(u64 *idx, struct memblock_type *type,
|
||||||
phys_addr_t *out_start,
|
phys_addr_t *out_start,
|
||||||
|
|
|
||||||
|
|
@ -546,10 +546,10 @@ void __init swiotlb_exit(void)
|
||||||
free_pages(tbl_vaddr, get_order(tbl_size));
|
free_pages(tbl_vaddr, get_order(tbl_size));
|
||||||
free_pages((unsigned long)mem->slots, get_order(slots_size));
|
free_pages((unsigned long)mem->slots, get_order(slots_size));
|
||||||
} else {
|
} else {
|
||||||
memblock_free_late(__pa(mem->areas),
|
memblock_free(mem->areas,
|
||||||
array_size(sizeof(*mem->areas), mem->nareas));
|
array_size(sizeof(*mem->areas), mem->nareas));
|
||||||
memblock_free_late(mem->start, tbl_size);
|
memblock_phys_free(mem->start, tbl_size);
|
||||||
memblock_free_late(__pa(mem->slots), slots_size);
|
memblock_free(mem->slots, slots_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(mem, 0, sizeof(*mem));
|
memset(mem, 0, sizeof(*mem));
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ static inline void __init xbc_free_mem(void *addr, size_t size, bool early)
|
||||||
if (early)
|
if (early)
|
||||||
memblock_free(addr, size);
|
memblock_free(addr, size);
|
||||||
else if (addr)
|
else if (addr)
|
||||||
memblock_free_late(__pa(addr), size);
|
memblock_free(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !__KERNEL__ */
|
#else /* !__KERNEL__ */
|
||||||
|
|
|
||||||
|
|
@ -731,10 +731,10 @@ static bool __init kfence_init_pool_early(void)
|
||||||
* fails for the first page, and therefore expect addr==__kfence_pool in
|
* fails for the first page, and therefore expect addr==__kfence_pool in
|
||||||
* most failure cases.
|
* most failure cases.
|
||||||
*/
|
*/
|
||||||
memblock_free_late(__pa(addr), KFENCE_POOL_SIZE - (addr - (unsigned long)__kfence_pool));
|
memblock_free((void *)addr, KFENCE_POOL_SIZE - (addr - (unsigned long)__kfence_pool));
|
||||||
__kfence_pool = NULL;
|
__kfence_pool = NULL;
|
||||||
|
|
||||||
memblock_free_late(__pa(kfence_metadata_init), KFENCE_METADATA_SIZE);
|
memblock_free(kfence_metadata_init, KFENCE_METADATA_SIZE);
|
||||||
kfence_metadata_init = NULL;
|
kfence_metadata_init = NULL;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -385,26 +385,27 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u
|
||||||
*/
|
*/
|
||||||
void __init memblock_discard(void)
|
void __init memblock_discard(void)
|
||||||
{
|
{
|
||||||
phys_addr_t addr, size;
|
phys_addr_t size;
|
||||||
|
void *addr;
|
||||||
|
|
||||||
if (memblock.reserved.regions != memblock_reserved_init_regions) {
|
if (memblock.reserved.regions != memblock_reserved_init_regions) {
|
||||||
addr = __pa(memblock.reserved.regions);
|
addr = memblock.reserved.regions;
|
||||||
size = PAGE_ALIGN(sizeof(struct memblock_region) *
|
size = PAGE_ALIGN(sizeof(struct memblock_region) *
|
||||||
memblock.reserved.max);
|
memblock.reserved.max);
|
||||||
if (memblock_reserved_in_slab)
|
if (memblock_reserved_in_slab)
|
||||||
kfree(memblock.reserved.regions);
|
kfree(addr);
|
||||||
else
|
else
|
||||||
memblock_free_late(addr, size);
|
memblock_free(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memblock.memory.regions != memblock_memory_init_regions) {
|
if (memblock.memory.regions != memblock_memory_init_regions) {
|
||||||
addr = __pa(memblock.memory.regions);
|
addr = memblock.memory.regions;
|
||||||
size = PAGE_ALIGN(sizeof(struct memblock_region) *
|
size = PAGE_ALIGN(sizeof(struct memblock_region) *
|
||||||
memblock.memory.max);
|
memblock.memory.max);
|
||||||
if (memblock_memory_in_slab)
|
if (memblock_memory_in_slab)
|
||||||
kfree(memblock.memory.regions);
|
kfree(addr);
|
||||||
else
|
else
|
||||||
memblock_free_late(addr, size);
|
memblock_free(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
memblock_memory = NULL;
|
memblock_memory = NULL;
|
||||||
|
|
@ -962,7 +963,8 @@ unsigned long free_reserved_area(void *start, void *end, int poison, const char
|
||||||
* @size: size of the boot memory block in bytes
|
* @size: size of the boot memory block in bytes
|
||||||
*
|
*
|
||||||
* Free boot memory block previously allocated by memblock_alloc_xx() API.
|
* Free boot memory block previously allocated by memblock_alloc_xx() API.
|
||||||
* The freeing memory will not be released to the buddy allocator.
|
* If called after the buddy allocator is available, the memory is released to
|
||||||
|
* the buddy allocator.
|
||||||
*/
|
*/
|
||||||
void __init_memblock memblock_free(void *ptr, size_t size)
|
void __init_memblock memblock_free(void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
|
|
@ -976,17 +978,24 @@ void __init_memblock memblock_free(void *ptr, size_t size)
|
||||||
* @size: size of the boot memory block in bytes
|
* @size: size of the boot memory block in bytes
|
||||||
*
|
*
|
||||||
* Free boot memory block previously allocated by memblock_phys_alloc_xx() API.
|
* Free boot memory block previously allocated by memblock_phys_alloc_xx() API.
|
||||||
* The freeing memory will not be released to the buddy allocator.
|
* If called after the buddy allocator is available, the memory is released to
|
||||||
|
* the buddy allocator.
|
||||||
*/
|
*/
|
||||||
int __init_memblock memblock_phys_free(phys_addr_t base, phys_addr_t size)
|
int __init_memblock memblock_phys_free(phys_addr_t base, phys_addr_t size)
|
||||||
{
|
{
|
||||||
phys_addr_t end = base + size - 1;
|
phys_addr_t end = base + size - 1;
|
||||||
|
int ret;
|
||||||
|
|
||||||
memblock_dbg("%s: [%pa-%pa] %pS\n", __func__,
|
memblock_dbg("%s: [%pa-%pa] %pS\n", __func__,
|
||||||
&base, &end, (void *)_RET_IP_);
|
&base, &end, (void *)_RET_IP_);
|
||||||
|
|
||||||
kmemleak_free_part_phys(base, size);
|
kmemleak_free_part_phys(base, size);
|
||||||
return memblock_remove_range(&memblock.reserved, base, size);
|
ret = memblock_remove_range(&memblock.reserved, base, size);
|
||||||
|
|
||||||
|
if (slab_is_available())
|
||||||
|
__free_reserved_area(base, base + size, -1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init_memblock __memblock_reserve(phys_addr_t base, phys_addr_t size,
|
int __init_memblock __memblock_reserve(phys_addr_t base, phys_addr_t size,
|
||||||
|
|
@ -1814,26 +1823,6 @@ void *__init __memblock_alloc_or_panic(phys_addr_t size, phys_addr_t align,
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* memblock_free_late - free pages directly to buddy allocator
|
|
||||||
* @base: phys starting address of the boot memory block
|
|
||||||
* @size: size of the boot memory block in bytes
|
|
||||||
*
|
|
||||||
* This is only useful when the memblock allocator has already been torn
|
|
||||||
* down, but we are still initializing the system. Pages are released directly
|
|
||||||
* to the buddy allocator.
|
|
||||||
*/
|
|
||||||
void __init memblock_free_late(phys_addr_t base, phys_addr_t size)
|
|
||||||
{
|
|
||||||
phys_addr_t end = base + size - 1;
|
|
||||||
|
|
||||||
memblock_dbg("%s: [%pa-%pa] %pS\n",
|
|
||||||
__func__, &base, &end, (void *)_RET_IP_);
|
|
||||||
|
|
||||||
kmemleak_free_part_phys(base, size);
|
|
||||||
__free_reserved_area(base, base + size, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remaining API functions
|
* Remaining API functions
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user