mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-01 18:24:23 +08:00
f806714f70
Patch series "memblock: simplify several early memory allocation", v4. These patches simplify some of the early memory allocations by replacing usage of older memblock APIs with newer and shinier ones. Quite a few places in the arch/ code allocated memory using a memblock API that returns a physical address of the allocated area, then converted this physical address to a virtual one and then used memset(0) to clear the allocated range. More recent memblock APIs do all the three steps in one call and their usage simplifies the code. It's important to note that regardless of API used, the core allocation is nearly identical for any set of memblock allocators: first it tries to find a free memory with all the constraints specified by the caller and then falls back to the allocation with some or all constraints disabled. The first three patches perform the conversion of call sites that have exact requirements for the node and the possible memory range. The fourth patch is a bit one-off as it simplifies openrisc's implementation of pte_alloc_one_kernel(), and not only the memblock usage. The fifth patch takes care of simpler cases when the allocation can be satisfied with a simple call to memblock_alloc(). The sixth patch removes one-liner wrappers for memblock_alloc on arm and unicore32, as suggested by Christoph. This patch (of 6): There are a several places that allocate memory using memblock APIs that return a physical address, convert the returned address to the virtual address and frequently also memset(0) the allocated range. Update these places to use memblock allocators already returning a virtual address. Use memblock functions that clear the allocated memory instead of calling memset(0) where appropriate. The calls to memblock_alloc_base() that were not followed by memset(0) are replaced with memblock_alloc_try_nid_raw(). Since the latter does not panic() when the allocation fails, the appropriate panic() calls are added to the call sites. Link: http://lkml.kernel.org/r/1546248566-14910-2-git-send-email-rppt@linux.ibm.com Signed-off-by: Mike Rapoport <rppt@linux.ibm.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Guan Xuetao <gxt@pku.edu.cn> Cc: Greentime Hu <green.hu@gmail.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Jonas Bonn <jonas@southpole.se> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Michal Hocko <mhocko@suse.com> Cc: Michal Simek <monstr@monstr.eu> Cc: Mark Salter <msalter@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Rich Felker <dalias@libc.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> Cc: Stafford Horne <shorne@gmail.com> Cc: Vincent Chen <deanbo422@gmail.com> Cc: Yoshinori Sato <ysato@users.sourceforge.jp> Cc: Christoph Hellwig <hch@infradead.org> Cc: Michal Simek <michal.simek@xilinx.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
116 lines
3.1 KiB
C
116 lines
3.1 KiB
C
/*
|
|
* Copyright 2005, Paul Mackerras, IBM Corporation.
|
|
* Copyright 2009, Benjamin Herrenschmidt, IBM Corporation.
|
|
* Copyright 2015-2016, Aneesh Kumar K.V, IBM Corporation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
|
|
#include <linux/sched.h>
|
|
#include <linux/memblock.h>
|
|
#include <asm/pgalloc.h>
|
|
#include <asm/tlb.h>
|
|
#include <asm/dma.h>
|
|
|
|
#include "mmu_decl.h"
|
|
|
|
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
|
/*
|
|
* On Book3E CPUs, the vmemmap is currently mapped in the top half of
|
|
* the vmalloc space using normal page tables, though the size of
|
|
* pages encoded in the PTEs can be different
|
|
*/
|
|
int __meminit vmemmap_create_mapping(unsigned long start,
|
|
unsigned long page_size,
|
|
unsigned long phys)
|
|
{
|
|
/* Create a PTE encoding without page size */
|
|
unsigned long i, flags = _PAGE_PRESENT | _PAGE_ACCESSED |
|
|
_PAGE_KERNEL_RW;
|
|
|
|
/* PTEs only contain page size encodings up to 32M */
|
|
BUG_ON(mmu_psize_defs[mmu_vmemmap_psize].enc > 0xf);
|
|
|
|
/* Encode the size in the PTE */
|
|
flags |= mmu_psize_defs[mmu_vmemmap_psize].enc << 8;
|
|
|
|
/* For each PTE for that area, map things. Note that we don't
|
|
* increment phys because all PTEs are of the large size and
|
|
* thus must have the low bits clear
|
|
*/
|
|
for (i = 0; i < page_size; i += PAGE_SIZE)
|
|
BUG_ON(map_kernel_page(start + i, phys, __pgprot(flags)));
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_MEMORY_HOTPLUG
|
|
void vmemmap_remove_mapping(unsigned long start,
|
|
unsigned long page_size)
|
|
{
|
|
}
|
|
#endif
|
|
#endif /* CONFIG_SPARSEMEM_VMEMMAP */
|
|
|
|
static __ref void *early_alloc_pgtable(unsigned long size)
|
|
{
|
|
return memblock_alloc_try_nid(size, size, MEMBLOCK_LOW_LIMIT,
|
|
__pa(MAX_DMA_ADDRESS), NUMA_NO_NODE);
|
|
}
|
|
|
|
/*
|
|
* map_kernel_page currently only called by __ioremap
|
|
* map_kernel_page adds an entry to the ioremap page table
|
|
* and adds an entry to the HPT, possibly bolting it
|
|
*/
|
|
int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
|
|
{
|
|
pgd_t *pgdp;
|
|
pud_t *pudp;
|
|
pmd_t *pmdp;
|
|
pte_t *ptep;
|
|
|
|
BUILD_BUG_ON(TASK_SIZE_USER64 > PGTABLE_RANGE);
|
|
if (slab_is_available()) {
|
|
pgdp = pgd_offset_k(ea);
|
|
pudp = pud_alloc(&init_mm, pgdp, ea);
|
|
if (!pudp)
|
|
return -ENOMEM;
|
|
pmdp = pmd_alloc(&init_mm, pudp, ea);
|
|
if (!pmdp)
|
|
return -ENOMEM;
|
|
ptep = pte_alloc_kernel(pmdp, ea);
|
|
if (!ptep)
|
|
return -ENOMEM;
|
|
} else {
|
|
pgdp = pgd_offset_k(ea);
|
|
#ifndef __PAGETABLE_PUD_FOLDED
|
|
if (pgd_none(*pgdp)) {
|
|
pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
|
|
BUG_ON(pudp == NULL);
|
|
pgd_populate(&init_mm, pgdp, pudp);
|
|
}
|
|
#endif /* !__PAGETABLE_PUD_FOLDED */
|
|
pudp = pud_offset(pgdp, ea);
|
|
if (pud_none(*pudp)) {
|
|
pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
|
|
BUG_ON(pmdp == NULL);
|
|
pud_populate(&init_mm, pudp, pmdp);
|
|
}
|
|
pmdp = pmd_offset(pudp, ea);
|
|
if (!pmd_present(*pmdp)) {
|
|
ptep = early_alloc_pgtable(PAGE_SIZE);
|
|
BUG_ON(ptep == NULL);
|
|
pmd_populate_kernel(&init_mm, pmdp, ptep);
|
|
}
|
|
ptep = pte_offset_kernel(pmdp, ea);
|
|
}
|
|
set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, prot));
|
|
|
|
smp_wmb();
|
|
return 0;
|
|
}
|