@@ -94,25 +94,29 @@ static inline void flush_data_cache(void)
94
94
/* Kernel virtual address of pfn. */
95
95
#define pfn_va (pfn ) __va(PFN_PHYS(pfn))
96
96
97
- void
98
- __update_cache (pte_t pte )
97
+ void __update_cache (pte_t pte )
99
98
{
100
99
unsigned long pfn = pte_pfn (pte );
101
- struct page * page ;
100
+ struct folio * folio ;
101
+ unsigned int nr ;
102
102
103
103
/* We don't have pte special. As a result, we can be called with
104
104
an invalid pfn and we don't need to flush the kernel dcache page.
105
105
This occurs with FireGL card in C8000. */
106
106
if (!pfn_valid (pfn ))
107
107
return ;
108
108
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 );
114
117
} 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 ));
116
120
}
117
121
118
122
void
@@ -366,6 +370,20 @@ static void flush_user_cache_page(struct vm_area_struct *vma, unsigned long vmad
366
370
preempt_enable ();
367
371
}
368
372
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
+
369
387
static inline pte_t * get_ptep (struct mm_struct * mm , unsigned long addr )
370
388
{
371
389
pte_t * ptep = NULL ;
@@ -394,27 +412,30 @@ static inline bool pte_needs_flush(pte_t pte)
394
412
== (_PAGE_PRESENT | _PAGE_ACCESSED );
395
413
}
396
414
397
- void flush_dcache_page (struct page * page )
415
+ void flush_dcache_folio (struct folio * folio )
398
416
{
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 ;
402
419
unsigned long addr , old_addr = 0 ;
420
+ void * kaddr ;
403
421
unsigned long count = 0 ;
404
- unsigned long flags ;
422
+ unsigned long i , nr , flags ;
405
423
pgoff_t pgoff ;
406
424
407
425
if (mapping && !mapping_mapped (mapping )) {
408
- set_bit (PG_dcache_dirty , & page -> flags );
426
+ set_bit (PG_dcache_dirty , & folio -> flags );
409
427
return ;
410
428
}
411
429
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 );
413
434
414
435
if (!mapping )
415
436
return ;
416
437
417
- pgoff = page -> index ;
438
+ pgoff = folio -> index ;
418
439
419
440
/*
420
441
* We have carefully arranged in arch_get_unmapped_area() that
@@ -424,20 +445,33 @@ void flush_dcache_page(struct page *page)
424
445
* on machines that support equivalent aliasing
425
446
*/
426
447
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 ;
433
462
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? */
437
473
pte_unmap (ptep );
438
474
}
439
- if (needs_flush )
440
- flush_user_cache_page (mpnt , addr );
441
475
} else {
442
476
/*
443
477
* The TLB is the engine of coherence on parisc:
@@ -450,27 +484,32 @@ void flush_dcache_page(struct page *page)
450
484
* in (until the user or kernel specifically
451
485
* accesses it, of course)
452
486
*/
453
- flush_tlb_page (mpnt , addr );
487
+ for (i = 0 ; i < nr ; i ++ )
488
+ flush_tlb_page (vma , addr + i * PAGE_SIZE );
454
489
if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1 ))
455
490
!= (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 );
457
495
/*
458
496
* Software is allowed to have any number
459
497
* of private mappings to a page.
460
498
*/
461
- if (!(mpnt -> vm_flags & VM_SHARED ))
499
+ if (!(vma -> vm_flags & VM_SHARED ))
462
500
continue ;
463
501
if (old_addr )
464
502
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 ;
467
506
}
468
507
}
469
508
WARN_ON (++ count == 4096 );
470
509
}
471
510
flush_dcache_mmap_unlock_irqrestore (mapping , flags );
472
511
}
473
- EXPORT_SYMBOL (flush_dcache_page );
512
+ EXPORT_SYMBOL (flush_dcache_folio );
474
513
475
514
/* Defined in arch/parisc/kernel/pacache.S */
476
515
EXPORT_SYMBOL (flush_kernel_dcache_range_asm );
0 commit comments