Skip to content

Commit e70bbca

Browse files
Matthew Wilcox (Oracle)akpm00
Matthew Wilcox (Oracle)
authored andcommitted
parisc: implement the new page table range API
Add set_ptes(), update_mmu_cache_range(), flush_dcache_folio() and flush_icache_pages(). Change the PG_arch_1 (aka PG_dcache_dirty) flag from being per-page to per-folio. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Acked-by: Mike Rapoport (IBM) <[email protected]> Cc: "James E.J. Bottomley" <[email protected]> Cc: Helge Deller <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 063e409 commit e70bbca

File tree

3 files changed

+105
-53
lines changed

3 files changed

+105
-53
lines changed

arch/parisc/include/asm/cacheflush.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,13 @@ void invalidate_kernel_vmap_range(void *vaddr, int size);
4343
#define flush_cache_vmap(start, end) flush_cache_all()
4444
#define flush_cache_vunmap(start, end) flush_cache_all()
4545

46+
void flush_dcache_folio(struct folio *folio);
47+
#define flush_dcache_folio flush_dcache_folio
4648
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
47-
void flush_dcache_page(struct page *page);
49+
static inline void flush_dcache_page(struct page *page)
50+
{
51+
flush_dcache_folio(page_folio(page));
52+
}
4853

4954
#define flush_dcache_mmap_lock(mapping) xa_lock_irq(&mapping->i_pages)
5055
#define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages)
@@ -53,10 +58,9 @@ void flush_dcache_page(struct page *page);
5358
#define flush_dcache_mmap_unlock_irqrestore(mapping, flags) \
5459
xa_unlock_irqrestore(&mapping->i_pages, flags)
5560

56-
#define flush_icache_page(vma,page) do { \
57-
flush_kernel_dcache_page_addr(page_address(page)); \
58-
flush_kernel_icache_page(page_address(page)); \
59-
} while (0)
61+
void flush_icache_pages(struct vm_area_struct *vma, struct page *page,
62+
unsigned int nr);
63+
#define flush_icache_page(vma, page) flush_icache_pages(vma, page, 1)
6064

6165
#define flush_icache_range(s,e) do { \
6266
flush_kernel_dcache_range_asm(s,e); \

arch/parisc/include/asm/pgtable.h

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,6 @@ extern void __update_cache(pte_t pte);
7373
mb(); \
7474
} while(0)
7575

76-
#define set_pte_at(mm, addr, pteptr, pteval) \
77-
do { \
78-
if (pte_present(pteval) && \
79-
pte_user(pteval)) \
80-
__update_cache(pteval); \
81-
*(pteptr) = (pteval); \
82-
purge_tlb_entries(mm, addr); \
83-
} while (0)
84-
8576
#endif /* !__ASSEMBLY__ */
8677

8778
#define pte_ERROR(e) \
@@ -285,7 +276,7 @@ extern unsigned long *empty_zero_page;
285276
#define pte_none(x) (pte_val(x) == 0)
286277
#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
287278
#define pte_user(x) (pte_val(x) & _PAGE_USER)
288-
#define pte_clear(mm, addr, xp) set_pte_at(mm, addr, xp, __pte(0))
279+
#define pte_clear(mm, addr, xp) set_pte(xp, __pte(0))
289280

290281
#define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK)
291282
#define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT)
@@ -391,11 +382,29 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
391382

392383
extern void paging_init (void);
393384

385+
static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
386+
pte_t *ptep, pte_t pte, unsigned int nr)
387+
{
388+
if (pte_present(pte) && pte_user(pte))
389+
__update_cache(pte);
390+
for (;;) {
391+
*ptep = pte;
392+
purge_tlb_entries(mm, addr);
393+
if (--nr == 0)
394+
break;
395+
ptep++;
396+
pte_val(pte) += 1 << PFN_PTE_SHIFT;
397+
addr += PAGE_SIZE;
398+
}
399+
}
400+
#define set_ptes set_ptes
401+
394402
/* Used for deferring calls to flush_dcache_page() */
395403

396404
#define PG_dcache_dirty PG_arch_1
397405

398-
#define update_mmu_cache(vms,addr,ptep) __update_cache(*ptep)
406+
#define update_mmu_cache_range(vmf, vma, addr, ptep, nr) __update_cache(*ptep)
407+
#define update_mmu_cache(vma, addr, ptep) __update_cache(*ptep)
399408

400409
/*
401410
* Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
@@ -450,7 +459,7 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned
450459
if (!pte_young(pte)) {
451460
return 0;
452461
}
453-
set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
462+
set_pte(ptep, pte_mkold(pte));
454463
return 1;
455464
}
456465

@@ -460,14 +469,14 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
460469
pte_t old_pte;
461470

462471
old_pte = *ptep;
463-
set_pte_at(mm, addr, ptep, __pte(0));
472+
set_pte(ptep, __pte(0));
464473

465474
return old_pte;
466475
}
467476

468477
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
469478
{
470-
set_pte_at(mm, addr, ptep, pte_wrprotect(*ptep));
479+
set_pte(ptep, pte_wrprotect(*ptep));
471480
}
472481

473482
#define pte_same(A,B) (pte_val(A) == pte_val(B))

arch/parisc/kernel/cache.c

Lines changed: 73 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -94,25 +94,29 @@ static inline void flush_data_cache(void)
9494
/* Kernel virtual address of pfn. */
9595
#define pfn_va(pfn) __va(PFN_PHYS(pfn))
9696

97-
void
98-
__update_cache(pte_t pte)
97+
void __update_cache(pte_t pte)
9998
{
10099
unsigned long pfn = pte_pfn(pte);
101-
struct page *page;
100+
struct folio *folio;
101+
unsigned int nr;
102102

103103
/* We don't have pte special. As a result, we can be called with
104104
an invalid pfn and we don't need to flush the kernel dcache page.
105105
This occurs with FireGL card in C8000. */
106106
if (!pfn_valid(pfn))
107107
return;
108108

109-
page = pfn_to_page(pfn);
110-
if (page_mapping_file(page) &&
111-
test_bit(PG_dcache_dirty, &page->flags)) {
112-
flush_kernel_dcache_page_addr(pfn_va(pfn));
113-
clear_bit(PG_dcache_dirty, &page->flags);
109+
folio = page_folio(pfn_to_page(pfn));
110+
pfn = folio_pfn(folio);
111+
nr = folio_nr_pages(folio);
112+
if (folio_flush_mapping(folio) &&
113+
test_bit(PG_dcache_dirty, &folio->flags)) {
114+
while (nr--)
115+
flush_kernel_dcache_page_addr(pfn_va(pfn + nr));
116+
clear_bit(PG_dcache_dirty, &folio->flags);
114117
} else if (parisc_requires_coherency())
115-
flush_kernel_dcache_page_addr(pfn_va(pfn));
118+
while (nr--)
119+
flush_kernel_dcache_page_addr(pfn_va(pfn + nr));
116120
}
117121

118122
void
@@ -366,6 +370,20 @@ static void flush_user_cache_page(struct vm_area_struct *vma, unsigned long vmad
366370
preempt_enable();
367371
}
368372

373+
void flush_icache_pages(struct vm_area_struct *vma, struct page *page,
374+
unsigned int nr)
375+
{
376+
void *kaddr = page_address(page);
377+
378+
for (;;) {
379+
flush_kernel_dcache_page_addr(kaddr);
380+
flush_kernel_icache_page(kaddr);
381+
if (--nr == 0)
382+
break;
383+
kaddr += PAGE_SIZE;
384+
}
385+
}
386+
369387
static inline pte_t *get_ptep(struct mm_struct *mm, unsigned long addr)
370388
{
371389
pte_t *ptep = NULL;
@@ -394,27 +412,30 @@ static inline bool pte_needs_flush(pte_t pte)
394412
== (_PAGE_PRESENT | _PAGE_ACCESSED);
395413
}
396414

397-
void flush_dcache_page(struct page *page)
415+
void flush_dcache_folio(struct folio *folio)
398416
{
399-
struct address_space *mapping = page_mapping_file(page);
400-
struct vm_area_struct *mpnt;
401-
unsigned long offset;
417+
struct address_space *mapping = folio_flush_mapping(folio);
418+
struct vm_area_struct *vma;
402419
unsigned long addr, old_addr = 0;
420+
void *kaddr;
403421
unsigned long count = 0;
404-
unsigned long flags;
422+
unsigned long i, nr, flags;
405423
pgoff_t pgoff;
406424

407425
if (mapping && !mapping_mapped(mapping)) {
408-
set_bit(PG_dcache_dirty, &page->flags);
426+
set_bit(PG_dcache_dirty, &folio->flags);
409427
return;
410428
}
411429

412-
flush_kernel_dcache_page_addr(page_address(page));
430+
nr = folio_nr_pages(folio);
431+
kaddr = folio_address(folio);
432+
for (i = 0; i < nr; i++)
433+
flush_kernel_dcache_page_addr(kaddr + i * PAGE_SIZE);
413434

414435
if (!mapping)
415436
return;
416437

417-
pgoff = page->index;
438+
pgoff = folio->index;
418439

419440
/*
420441
* We have carefully arranged in arch_get_unmapped_area() that
@@ -424,20 +445,33 @@ void flush_dcache_page(struct page *page)
424445
* on machines that support equivalent aliasing
425446
*/
426447
flush_dcache_mmap_lock_irqsave(mapping, flags);
427-
vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
428-
offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
429-
addr = mpnt->vm_start + offset;
430-
if (parisc_requires_coherency()) {
431-
bool needs_flush = false;
432-
pte_t *ptep;
448+
vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff + nr - 1) {
449+
unsigned long offset = pgoff - vma->vm_pgoff;
450+
unsigned long pfn = folio_pfn(folio);
451+
452+
addr = vma->vm_start;
453+
nr = folio_nr_pages(folio);
454+
if (offset > -nr) {
455+
pfn -= offset;
456+
nr += offset;
457+
} else {
458+
addr += offset * PAGE_SIZE;
459+
}
460+
if (addr + nr * PAGE_SIZE > vma->vm_end)
461+
nr = (vma->vm_end - addr) / PAGE_SIZE;
433462

434-
ptep = get_ptep(mpnt->vm_mm, addr);
435-
if (ptep) {
436-
needs_flush = pte_needs_flush(*ptep);
463+
if (parisc_requires_coherency()) {
464+
for (i = 0; i < nr; i++) {
465+
pte_t *ptep = get_ptep(vma->vm_mm,
466+
addr + i * PAGE_SIZE);
467+
if (!ptep)
468+
continue;
469+
if (pte_needs_flush(*ptep))
470+
flush_user_cache_page(vma,
471+
addr + i * PAGE_SIZE);
472+
/* Optimise accesses to the same table? */
437473
pte_unmap(ptep);
438474
}
439-
if (needs_flush)
440-
flush_user_cache_page(mpnt, addr);
441475
} else {
442476
/*
443477
* The TLB is the engine of coherence on parisc:
@@ -450,27 +484,32 @@ void flush_dcache_page(struct page *page)
450484
* in (until the user or kernel specifically
451485
* accesses it, of course)
452486
*/
453-
flush_tlb_page(mpnt, addr);
487+
for (i = 0; i < nr; i++)
488+
flush_tlb_page(vma, addr + i * PAGE_SIZE);
454489
if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1))
455490
!= (addr & (SHM_COLOUR - 1))) {
456-
__flush_cache_page(mpnt, addr, page_to_phys(page));
491+
for (i = 0; i < nr; i++)
492+
__flush_cache_page(vma,
493+
addr + i * PAGE_SIZE,
494+
(pfn + i) * PAGE_SIZE);
457495
/*
458496
* Software is allowed to have any number
459497
* of private mappings to a page.
460498
*/
461-
if (!(mpnt->vm_flags & VM_SHARED))
499+
if (!(vma->vm_flags & VM_SHARED))
462500
continue;
463501
if (old_addr)
464502
pr_err("INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %pD\n",
465-
old_addr, addr, mpnt->vm_file);
466-
old_addr = addr;
503+
old_addr, addr, vma->vm_file);
504+
if (nr == folio_nr_pages(folio))
505+
old_addr = addr;
467506
}
468507
}
469508
WARN_ON(++count == 4096);
470509
}
471510
flush_dcache_mmap_unlock_irqrestore(mapping, flags);
472511
}
473-
EXPORT_SYMBOL(flush_dcache_page);
512+
EXPORT_SYMBOL(flush_dcache_folio);
474513

475514
/* Defined in arch/parisc/kernel/pacache.S */
476515
EXPORT_SYMBOL(flush_kernel_dcache_range_asm);

0 commit comments

Comments
 (0)