mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-12-16 15:49:12 +01:00
Patch series "Add and use memdesc_flags_t". At some point struct page will be separated from struct slab and struct folio. This is a step towards that by introducing a type for the 'flags' word of all three structures. This gives us a certain amount of type safety by establishing that some of these unsigned longs are different from other unsigned longs in that they contain things like node ID, section number and zone number in the upper bits. That lets us have functions that can be easily called by anyone who has a slab, folio or page (but not easily by anyone else) to get the node or zone. There's going to be some unusual merge problems with this as some odd bits of the kernel decide they want to print out the flags value or something similar by writing page->flags and now they'll need to write page->flags.f instead. That's most of the churn here. Maybe we should be removing these things from the debug output? This patch (of 11): Wrap the unsigned long flags in a typedef. In upcoming patches, this will provide a strong hint that you can't just pass a random unsigned long to functions which take this as an argument. [willy@infradead.org: s/flags/flags.f/ in several architectures] Link: https://lkml.kernel.org/r/aKMgPRLD-WnkPxYm@casper.infradead.org [nicola.vetrini@gmail.com: mips: fix compilation error] Link: https://lore.kernel.org/lkml/CA+G9fYvkpmqGr6wjBNHY=dRp71PLCoi2341JxOudi60yqaeUdg@mail.gmail.com/ Link: https://lkml.kernel.org/r/20250825214245.1838158-1-nicola.vetrini@gmail.com Link: https://lkml.kernel.org/r/20250805172307.1302730-1-willy@infradead.org Link: https://lkml.kernel.org/r/20250805172307.1302730-2-willy@infradead.org Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Acked-by: Zi Yan <ziy@nvidia.com> Cc: Shakeel Butt <shakeel.butt@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
139 lines
3.3 KiB
C
139 lines
3.3 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* linux/arch/arm/mm/copypage-v6.c
|
|
*
|
|
* Copyright (C) 2002 Deep Blue Solutions Ltd, All Rights Reserved.
|
|
*/
|
|
#include <linux/init.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/highmem.h>
|
|
#include <linux/pagemap.h>
|
|
|
|
#include <asm/shmparam.h>
|
|
#include <asm/tlbflush.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/cachetype.h>
|
|
|
|
#include "mm.h"
|
|
|
|
#if SHMLBA > 16384
|
|
#error FIX ME
|
|
#endif
|
|
|
|
static DEFINE_RAW_SPINLOCK(v6_lock);
|
|
|
|
/*
|
|
* Copy the user page. No aliasing to deal with so we can just
|
|
* attack the kernel's existing mapping of these pages.
|
|
*/
|
|
static void v6_copy_user_highpage_nonaliasing(struct page *to,
|
|
struct page *from, unsigned long vaddr, struct vm_area_struct *vma)
|
|
{
|
|
void *kto, *kfrom;
|
|
|
|
kfrom = kmap_atomic(from);
|
|
kto = kmap_atomic(to);
|
|
copy_page(kto, kfrom);
|
|
kunmap_atomic(kto);
|
|
kunmap_atomic(kfrom);
|
|
}
|
|
|
|
/*
|
|
* Clear the user page. No aliasing to deal with so we can just
|
|
* attack the kernel's existing mapping of this page.
|
|
*/
|
|
static void v6_clear_user_highpage_nonaliasing(struct page *page, unsigned long vaddr)
|
|
{
|
|
void *kaddr = kmap_atomic(page);
|
|
clear_page(kaddr);
|
|
kunmap_atomic(kaddr);
|
|
}
|
|
|
|
/*
|
|
* Discard data in the kernel mapping for the new page.
|
|
* FIXME: needs this MCRR to be supported.
|
|
*/
|
|
static void discard_old_kernel_data(void *kto)
|
|
{
|
|
__asm__("mcrr p15, 0, %1, %0, c6 @ 0xec401f06"
|
|
:
|
|
: "r" (kto),
|
|
"r" ((unsigned long)kto + PAGE_SIZE - 1)
|
|
: "cc");
|
|
}
|
|
|
|
/*
|
|
* Copy the page, taking account of the cache colour.
|
|
*/
|
|
static void v6_copy_user_highpage_aliasing(struct page *to,
|
|
struct page *from, unsigned long vaddr, struct vm_area_struct *vma)
|
|
{
|
|
struct folio *src = page_folio(from);
|
|
unsigned int offset = CACHE_COLOUR(vaddr);
|
|
unsigned long kfrom, kto;
|
|
|
|
if (!test_and_set_bit(PG_dcache_clean, &src->flags.f))
|
|
__flush_dcache_folio(folio_flush_mapping(src), src);
|
|
|
|
/* FIXME: not highmem safe */
|
|
discard_old_kernel_data(page_address(to));
|
|
|
|
/*
|
|
* Now copy the page using the same cache colour as the
|
|
* pages ultimate destination.
|
|
*/
|
|
raw_spin_lock(&v6_lock);
|
|
|
|
kfrom = COPYPAGE_V6_FROM + (offset << PAGE_SHIFT);
|
|
kto = COPYPAGE_V6_TO + (offset << PAGE_SHIFT);
|
|
|
|
set_top_pte(kfrom, mk_pte(from, PAGE_KERNEL));
|
|
set_top_pte(kto, mk_pte(to, PAGE_KERNEL));
|
|
|
|
copy_page((void *)kto, (void *)kfrom);
|
|
|
|
raw_spin_unlock(&v6_lock);
|
|
}
|
|
|
|
/*
|
|
* Clear the user page. We need to deal with the aliasing issues,
|
|
* so remap the kernel page into the same cache colour as the user
|
|
* page.
|
|
*/
|
|
static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vaddr)
|
|
{
|
|
unsigned long to = COPYPAGE_V6_TO + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
|
|
|
|
/* FIXME: not highmem safe */
|
|
discard_old_kernel_data(page_address(page));
|
|
|
|
/*
|
|
* Now clear the page using the same cache colour as
|
|
* the pages ultimate destination.
|
|
*/
|
|
raw_spin_lock(&v6_lock);
|
|
|
|
set_top_pte(to, mk_pte(page, PAGE_KERNEL));
|
|
clear_page((void *)to);
|
|
|
|
raw_spin_unlock(&v6_lock);
|
|
}
|
|
|
|
struct cpu_user_fns v6_user_fns __initdata = {
|
|
.cpu_clear_user_highpage = v6_clear_user_highpage_nonaliasing,
|
|
.cpu_copy_user_highpage = v6_copy_user_highpage_nonaliasing,
|
|
};
|
|
|
|
static int __init v6_userpage_init(void)
|
|
{
|
|
if (cache_is_vipt_aliasing()) {
|
|
cpu_user.cpu_clear_user_highpage = v6_clear_user_highpage_aliasing;
|
|
cpu_user.cpu_copy_user_highpage = v6_copy_user_highpage_aliasing;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
core_initcall(v6_userpage_init);
|