[PATCH v2 18/30] powerpc: Implement the new page table range API

Christophe Leroy christophe.leroy at csgroup.eu
Tue Feb 28 17:58:18 AEDT 2023



Le 27/02/2023 à 21:20, Matthew Wilcox a écrit :
> On Mon, Feb 27, 2023 at 07:45:08PM +0000, Christophe Leroy wrote:
>> Hi,
>>
>> Le 27/02/2023 à 18:57, Matthew Wilcox (Oracle) a écrit :
>>> Add set_ptes(), update_mmu_cache_range() and flush_dcache_folio().
>>> Change the PG_arch_1 (aka PG_dcache_dirty) flag from being per-page to
>>> per-folio.
>>>
>>> I'm unsure about my merging of flush_dcache_icache_hugepage() and
>>> flush_dcache_icache_page() into flush_dcache_icache_folio() and subsequent
>>> removal of flush_dcache_icache_phys().  Please review.
>>
>> Not sure why you want to remove flush_dcache_icache_phys().
> 
> Well, I didn't, necessarily.  It's just that when I merged
> flush_dcache_icache_hugepage() and flush_dcache_icache_page()
> together, it was left with no callers.
> 
>> Allthough that's only feasible when address bus is not wider than 32
>> bits and cannot be done on BOOKE as you can't switch off MMU on BOOKE,
>> flush_dcache_icache_phys() allows to flush not mapped pages without
>> having to map them. So it is more efficient.
> 
> And it was just never done for the hugepage case?

I think on PPC32 hugepages are available only on 8xx and BOOKE. 8xx 
doesn't have HIGHMEM and BOOKE cannot switch MMU off. So there is no use 
case for flush_dcache_icache_phys() with hugepages.

> 
>>> @@ -148,17 +103,20 @@ static void __flush_dcache_icache(void *p)
>>>    	invalidate_icache_range(addr, addr + PAGE_SIZE);
>>>    }
>>>    
>>> -static void flush_dcache_icache_hugepage(struct page *page)
>>> +void flush_dcache_icache_folio(struct folio *folio)
>>>    {
>>> -	int i;
>>> -	int nr = compound_nr(page);
>>> +	unsigned int i, nr = folio_nr_pages(folio);
>>>    
>>> -	if (!PageHighMem(page)) {
>>> +	if (flush_coherent_icache())
>>> +		return;
>>> +
>>> +	if (!folio_test_highmem(folio)) {
>>> +		void *addr = folio_address(folio);
>>>    		for (i = 0; i < nr; i++)
>>> -			__flush_dcache_icache(lowmem_page_address(page + i));
>>> +			__flush_dcache_icache(addr + i * PAGE_SIZE);
>>>    	} else {
>>>    		for (i = 0; i < nr; i++) {
>>> -			void *start = kmap_local_page(page + i);
>>> +			void *start = kmap_local_folio(folio, i * PAGE_SIZE);
>>>    
>>>    			__flush_dcache_icache(start);
>>>    			kunmap_local(start);
> 
> So you'd like this to be:
> 
> 	} else if (IS_ENABLED(CONFIG_BOOKE) || sizeof(phys_addr_t) > sizeof(void *)) {
> 		for (i = 0; i < nr; i++) {
> 			 void *start = kmap_local_folio(folio, i * PAGE_SIZE);
> 			 __flush_dcache_icache(start);
> 			 kunmap_local(start);
> 		}
> 	} else {
> 		unsigned long pfn = folio_pfn(folio);
> 		for (i = 0; i < nr; i++)
> 			flush_dcache_icache_phys((pfn + i) * PAGE_SIZE;
> 	}
> 
> (or maybe you'd prefer a flush_dcache_icache_pfn() that doesn't need to
> worry about PAGE_MASK).

Yes looks good.


Christophe


More information about the Linuxppc-dev mailing list