Commit 157efa29 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Andrew Morton
Browse files

sh: implement the new page table range API

Add PFN_PTE_SHIFT, update_mmu_cache_range(), flush_dcache_folio() and
flush_icache_pages().  Change the PG_dcache_clean flag from being per-page
to per-folio.  Flush the entire folio containing the pages in
flush_icache_pages() for ease of implementation.

Link: https://lkml.kernel.org/r/20230802151406.3735276-25-willy@infradead.org


Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: default avatarMike Rapoport (IBM) <rppt@kernel.org>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Rich Felker <dalias@libc.org>
Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 843f9310
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -13,9 +13,9 @@
 *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
 *  - flush_cache_range(vma, start, end) flushes a range of pages
 *
 *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
 *  - flush_dcache_folio(folio) flushes(wback&invalidates) a folio for dcache
 *  - flush_icache_range(start, end) flushes(invalidates) a range for icache
 *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
 *  - flush_icache_pages(vma, pg, nr) flushes(invalidates) pages for icache
 *  - flush_cache_sigtramp(vaddr) flushes the signal trampoline
 */
extern void (*local_flush_cache_all)(void *args);
@@ -23,9 +23,9 @@ extern void (*local_flush_cache_mm)(void *args);
extern void (*local_flush_cache_dup_mm)(void *args);
extern void (*local_flush_cache_page)(void *args);
extern void (*local_flush_cache_range)(void *args);
extern void (*local_flush_dcache_page)(void *args);
extern void (*local_flush_dcache_folio)(void *args);
extern void (*local_flush_icache_range)(void *args);
extern void (*local_flush_icache_page)(void *args);
extern void (*local_flush_icache_folio)(void *args);
extern void (*local_flush_cache_sigtramp)(void *args);

static inline void cache_noop(void *args) { }
@@ -42,11 +42,18 @@ extern void flush_cache_page(struct vm_area_struct *vma,
extern void flush_cache_range(struct vm_area_struct *vma,
				 unsigned long start, unsigned long end);
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
void flush_dcache_page(struct page *page);
void flush_dcache_folio(struct folio *folio);
#define flush_dcache_folio flush_dcache_folio
static inline void flush_dcache_page(struct page *page)
{
	flush_dcache_folio(page_folio(page));
}

extern void flush_icache_range(unsigned long start, unsigned long end);
#define flush_icache_user_range flush_icache_range
extern void flush_icache_page(struct vm_area_struct *vma,
				 struct page *page);
void flush_icache_pages(struct vm_area_struct *vma, struct page *page,
		unsigned int nr);
#define flush_icache_page(vma, page) flush_icache_pages(vma, page, 1)
extern void flush_cache_sigtramp(unsigned long address);

struct flusher_data {
+5 −2
Original line number Diff line number Diff line
@@ -102,13 +102,16 @@ extern void __update_cache(struct vm_area_struct *vma,
extern void __update_tlb(struct vm_area_struct *vma,
			 unsigned long address, pte_t pte);

static inline void
update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
static inline void update_mmu_cache_range(struct vm_fault *vmf,
		struct vm_area_struct *vma, unsigned long address,
		pte_t *ptep, unsigned int nr)
{
	pte_t pte = *ptep;
	__update_cache(vma, address, pte);
	__update_tlb(vma, address, pte);
}
#define update_mmu_cache(vma, addr, ptep) \
	update_mmu_cache_range(NULL, vma, addr, ptep, 1)

extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern void paging_init(void);
+2 −3
Original line number Diff line number Diff line
@@ -307,14 +307,13 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
#endif

#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)

/*
 * (pmds are folded into pgds so this doesn't get actually called,
 * but the define is needed for a generic inline function.)
 */
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)

#define PFN_PTE_SHIFT	PAGE_SHIFT
#define pfn_pte(pfn, prot) \
	__pte(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
#define pfn_pmd(pfn, prot) \
@@ -323,7 +322,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
#define pte_none(x)		(!pte_val(x))
#define pte_present(x)		((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))

#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
#define pte_clear(mm, addr, ptep) set_pte(ptep, __pte(0))

#define pmd_none(x)	(!pmd_val(x))
#define pmd_present(x)	(pmd_val(x))
+2 −2
Original line number Diff line number Diff line
@@ -55,9 +55,9 @@ void __init j2_cache_init(void)
	local_flush_cache_dup_mm = j2_flush_both;
	local_flush_cache_page = j2_flush_both;
	local_flush_cache_range = j2_flush_both;
	local_flush_dcache_page = j2_flush_dcache;
	local_flush_dcache_folio = j2_flush_dcache;
	local_flush_icache_range = j2_flush_icache;
	local_flush_icache_page = j2_flush_icache;
	local_flush_icache_folio = j2_flush_icache;
	local_flush_cache_sigtramp = j2_flush_icache;

	pr_info("Initial J2 CCR is %.8x\n", __raw_readl(j2_ccr_base));
+18 −8
Original line number Diff line number Diff line
@@ -107,19 +107,29 @@ static inline void flush_cache_one(unsigned long start, unsigned long phys)
 * Write back & invalidate the D-cache of the page.
 * (To avoid "alias" issues)
 */
static void sh4_flush_dcache_page(void *arg)
static void sh4_flush_dcache_folio(void *arg)
{
	struct page *page = arg;
	unsigned long addr = (unsigned long)page_address(page);
	struct folio *folio = arg;
#ifndef CONFIG_SMP
	struct address_space *mapping = page_mapping_file(page);
	struct address_space *mapping = folio_flush_mapping(folio);

	if (mapping && !mapping_mapped(mapping))
		clear_bit(PG_dcache_clean, &page->flags);
		clear_bit(PG_dcache_clean, &folio->flags);
	else
#endif
	{
		unsigned long pfn = folio_pfn(folio);
		unsigned long addr = (unsigned long)folio_address(folio);
		unsigned int i, nr = folio_nr_pages(folio);

		for (i = 0; i < nr; i++) {
			flush_cache_one(CACHE_OC_ADDRESS_ARRAY |
				(addr & shm_align_mask), page_to_phys(page));
						(addr & shm_align_mask),
					pfn * PAGE_SIZE);
			addr += PAGE_SIZE;
			pfn++;
		}
	}

	wmb();
}
@@ -379,7 +389,7 @@ void __init sh4_cache_init(void)
		__raw_readl(CCN_PRR));

	local_flush_icache_range	= sh4_flush_icache_range;
	local_flush_dcache_page		= sh4_flush_dcache_page;
	local_flush_dcache_folio	= sh4_flush_dcache_folio;
	local_flush_cache_all		= sh4_flush_cache_all;
	local_flush_cache_mm		= sh4_flush_cache_mm;
	local_flush_cache_dup_mm	= sh4_flush_cache_mm;
Loading