Files
linux/arch/m68k/include/asm/mcf_pgalloc.h
Will Deacon fd1aa6303c m68k: mm: Fix ColdFire pgd_alloc()
I also notice that building for m5475evb_defconfig with vanilla v5.5
triggers this scary looking warning due to a mismatch between the pgd
size and the (8k!) page size:

 | In function 'pgd_alloc.isra.111',
 |     inlined from 'mm_alloc_pgd' at kernel/fork.c:634:12,
 |     inlined from 'mm_init.isra.112' at kernel/fork.c:1043:6:
 | ./arch/m68k/include/asm/string.h:72:25: warning: '__builtin_memcpy' forming offset [4097, 8192] is out of the bounds [0, 4096] of object 'kernel_pg_dir' with type 'pgd_t[1024]' {aka 'struct <anonymous>[1024]'} [-Warray-bounds]
 |  #define memcpy(d, s, n) __builtin_memcpy(d, s, n)
 |                          ^~~~~~~~~~~~~~~~~~~~~~~~~
 | ./arch/m68k/include/asm/mcf_pgalloc.h:93:2: note: in expansion of macro 'memcpy'
 |   memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE);
 |   ^~~~~~

Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Greg Ungerer <gerg@linux-m68k.org>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Tested-by: Greg Ungerer <gerg@linux-m68k.org>
Link: https://lore.kernel.org/r/20200131125403.540057688@infradead.org
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
2020-02-10 10:57:48 +01:00

95 lines
2.0 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
#ifndef M68K_MCF_PGALLOC_H
#define M68K_MCF_PGALLOC_H
#include <asm/tlb.h>
#include <asm/tlbflush.h>
extern inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
free_page((unsigned long) pte);
}
extern const char bad_pmd_string[];
extern inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
{
unsigned long page = __get_free_page(GFP_DMA);
if (!page)
return NULL;
memset((void *)page, 0, PAGE_SIZE);
return (pte_t *) (page);
}
extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
{
return (pmd_t *) pgd;
}
#define pmd_populate(mm, pmd, page) (pmd_val(*pmd) = \
(unsigned long)(page_address(page)))
#define pmd_populate_kernel(mm, pmd, pte) (pmd_val(*pmd) = (unsigned long)(pte))
#define pmd_pgtable(pmd) pmd_page(pmd)
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
unsigned long address)
{
pgtable_pte_page_dtor(page);
__free_page(page);
}
static inline struct page *pte_alloc_one(struct mm_struct *mm)
{
struct page *page = alloc_pages(GFP_DMA, 0);
pte_t *pte;
if (!page)
return NULL;
if (!pgtable_pte_page_ctor(page)) {
__free_page(page);
return NULL;
}
pte = kmap(page);
if (pte)
clear_page(pte);
kunmap(page);
return page;
}
static inline void pte_free(struct mm_struct *mm, struct page *page)
{
pgtable_pte_page_dtor(page);
__free_page(page);
}
/*
* In our implementation, each pgd entry contains 1 pmd that is never allocated
* or freed. pgd_present is always 1, so this should never be called. -NL
*/
#define pmd_free(mm, pmd) BUG()
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_page((unsigned long) pgd);
}
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *new_pgd;
new_pgd = (pgd_t *)__get_free_page(GFP_DMA | __GFP_NOWARN);
if (!new_pgd)
return NULL;
memcpy(new_pgd, swapper_pg_dir, PTRS_PER_PGD * sizeof(pgd_t));
memset(new_pgd, 0, PAGE_OFFSET >> PGDIR_SHIFT);
return new_pgd;
}
#endif /* M68K_MCF_PGALLOC_H */