162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2003 Ralf Baechle 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#ifndef _ASM_PGTABLE_H 962306a36Sopenharmony_ci#define _ASM_PGTABLE_H 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/mm_types.h> 1262306a36Sopenharmony_ci#include <linux/mmzone.h> 1362306a36Sopenharmony_ci#ifdef CONFIG_32BIT 1462306a36Sopenharmony_ci#include <asm/pgtable-32.h> 1562306a36Sopenharmony_ci#endif 1662306a36Sopenharmony_ci#ifdef CONFIG_64BIT 1762306a36Sopenharmony_ci#include <asm/pgtable-64.h> 1862306a36Sopenharmony_ci#endif 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <asm/cmpxchg.h> 2162306a36Sopenharmony_ci#include <asm/io.h> 2262306a36Sopenharmony_ci#include <asm/pgtable-bits.h> 2362306a36Sopenharmony_ci#include <asm/cpu-features.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct mm_struct; 2662306a36Sopenharmony_cistruct vm_area_struct; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define PAGE_SHARED vm_get_page_prot(VM_READ|VM_WRITE|VM_SHARED) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ 3162306a36Sopenharmony_ci _PAGE_GLOBAL | _page_cachable_default) 3262306a36Sopenharmony_ci#define PAGE_KERNEL_NC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ 3362306a36Sopenharmony_ci _PAGE_GLOBAL | _CACHE_CACHABLE_NONCOHERENT) 3462306a36Sopenharmony_ci#define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \ 3562306a36Sopenharmony_ci __WRITEABLE | _PAGE_GLOBAL | _CACHE_UNCACHED) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* 3862306a36Sopenharmony_ci * If _PAGE_NO_EXEC is not defined, we can't do page protection for 3962306a36Sopenharmony_ci * execute, and consider it to be the same as read. Also, write 4062306a36Sopenharmony_ci * permissions imply read permissions. This is the closest we can get 4162306a36Sopenharmony_ci * by reasonable means.. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciextern unsigned long _page_cachable_default; 4562306a36Sopenharmony_ciextern void __update_cache(unsigned long address, pte_t pte); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci * ZERO_PAGE is a global shared page that is always zero; used 4962306a36Sopenharmony_ci * for zero-mapped memory areas etc.. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciextern unsigned long empty_zero_page; 5362306a36Sopenharmony_ciextern unsigned long zero_page_mask; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define ZERO_PAGE(vaddr) \ 5662306a36Sopenharmony_ci (virt_to_page((void *)(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))) 5762306a36Sopenharmony_ci#define __HAVE_COLOR_ZERO_PAGE 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciextern void paging_init(void); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* 6262306a36Sopenharmony_ci * Conversion functions: convert a page and protection to a page entry, 6362306a36Sopenharmony_ci * and a page entry and page directory to the page they refer to. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci#define pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd)) 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic inline unsigned long pmd_pfn(pmd_t pmd) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci return pmd_val(pmd) >> PFN_PTE_SHIFT; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#ifndef CONFIG_MIPS_HUGE_TLB_SUPPORT 7362306a36Sopenharmony_ci#define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) 7462306a36Sopenharmony_ci#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */ 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define pmd_page_vaddr(pmd) pmd_val(pmd) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define htw_stop() \ 7962306a36Sopenharmony_cido { \ 8062306a36Sopenharmony_ci unsigned long __flags; \ 8162306a36Sopenharmony_ci \ 8262306a36Sopenharmony_ci if (cpu_has_htw) { \ 8362306a36Sopenharmony_ci local_irq_save(__flags); \ 8462306a36Sopenharmony_ci if(!raw_current_cpu_data.htw_seq++) { \ 8562306a36Sopenharmony_ci write_c0_pwctl(read_c0_pwctl() & \ 8662306a36Sopenharmony_ci ~(1 << MIPS_PWCTL_PWEN_SHIFT)); \ 8762306a36Sopenharmony_ci back_to_back_c0_hazard(); \ 8862306a36Sopenharmony_ci } \ 8962306a36Sopenharmony_ci local_irq_restore(__flags); \ 9062306a36Sopenharmony_ci } \ 9162306a36Sopenharmony_ci} while(0) 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci#define htw_start() \ 9462306a36Sopenharmony_cido { \ 9562306a36Sopenharmony_ci unsigned long __flags; \ 9662306a36Sopenharmony_ci \ 9762306a36Sopenharmony_ci if (cpu_has_htw) { \ 9862306a36Sopenharmony_ci local_irq_save(__flags); \ 9962306a36Sopenharmony_ci if (!--raw_current_cpu_data.htw_seq) { \ 10062306a36Sopenharmony_ci write_c0_pwctl(read_c0_pwctl() | \ 10162306a36Sopenharmony_ci (1 << MIPS_PWCTL_PWEN_SHIFT)); \ 10262306a36Sopenharmony_ci back_to_back_c0_hazard(); \ 10362306a36Sopenharmony_ci } \ 10462306a36Sopenharmony_ci local_irq_restore(__flags); \ 10562306a36Sopenharmony_ci } \ 10662306a36Sopenharmony_ci} while(0) 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci#ifdef CONFIG_XPA 11162306a36Sopenharmony_ci# define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) 11262306a36Sopenharmony_ci#else 11362306a36Sopenharmony_ci# define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL)) 11462306a36Sopenharmony_ci#endif 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci#define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) 11762306a36Sopenharmony_ci#define pte_no_exec(pte) ((pte).pte_low & _PAGE_NO_EXEC) 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic inline void set_pte(pte_t *ptep, pte_t pte) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci ptep->pte_high = pte.pte_high; 12262306a36Sopenharmony_ci smp_wmb(); 12362306a36Sopenharmony_ci ptep->pte_low = pte.pte_low; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#ifdef CONFIG_XPA 12662306a36Sopenharmony_ci if (pte.pte_high & _PAGE_GLOBAL) { 12762306a36Sopenharmony_ci#else 12862306a36Sopenharmony_ci if (pte.pte_low & _PAGE_GLOBAL) { 12962306a36Sopenharmony_ci#endif 13062306a36Sopenharmony_ci pte_t *buddy = ptep_buddy(ptep); 13162306a36Sopenharmony_ci /* 13262306a36Sopenharmony_ci * Make sure the buddy is global too (if it's !none, 13362306a36Sopenharmony_ci * it better already be global) 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ci if (pte_none(*buddy)) { 13662306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_XPA)) 13762306a36Sopenharmony_ci buddy->pte_low |= _PAGE_GLOBAL; 13862306a36Sopenharmony_ci buddy->pte_high |= _PAGE_GLOBAL; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci pte_t null = __pte(0); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci htw_stop(); 14862306a36Sopenharmony_ci /* Preserve global status for the pair */ 14962306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_XPA)) { 15062306a36Sopenharmony_ci if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) 15162306a36Sopenharmony_ci null.pte_high = _PAGE_GLOBAL; 15262306a36Sopenharmony_ci } else { 15362306a36Sopenharmony_ci if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL) 15462306a36Sopenharmony_ci null.pte_low = null.pte_high = _PAGE_GLOBAL; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci set_pte(ptep, null); 15862306a36Sopenharmony_ci htw_start(); 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci#else 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci#define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL)) 16362306a36Sopenharmony_ci#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) 16462306a36Sopenharmony_ci#define pte_no_exec(pte) (pte_val(pte) & _PAGE_NO_EXEC) 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci/* 16762306a36Sopenharmony_ci * Certain architectures need to do special things when pte's 16862306a36Sopenharmony_ci * within a page table are directly modified. Thus, the following 16962306a36Sopenharmony_ci * hook is made available. 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_cistatic inline void set_pte(pte_t *ptep, pte_t pteval) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci *ptep = pteval; 17462306a36Sopenharmony_ci#if !defined(CONFIG_CPU_R3K_TLB) 17562306a36Sopenharmony_ci if (pte_val(pteval) & _PAGE_GLOBAL) { 17662306a36Sopenharmony_ci pte_t *buddy = ptep_buddy(ptep); 17762306a36Sopenharmony_ci /* 17862306a36Sopenharmony_ci * Make sure the buddy is global too (if it's !none, 17962306a36Sopenharmony_ci * it better already be global) 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ci# if defined(CONFIG_PHYS_ADDR_T_64BIT) && !defined(CONFIG_CPU_MIPS32) 18262306a36Sopenharmony_ci cmpxchg64(&buddy->pte, 0, _PAGE_GLOBAL); 18362306a36Sopenharmony_ci# else 18462306a36Sopenharmony_ci cmpxchg(&buddy->pte, 0, _PAGE_GLOBAL); 18562306a36Sopenharmony_ci# endif 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci#endif 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci htw_stop(); 19362306a36Sopenharmony_ci#if !defined(CONFIG_CPU_R3K_TLB) 19462306a36Sopenharmony_ci /* Preserve global status for the pair */ 19562306a36Sopenharmony_ci if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL) 19662306a36Sopenharmony_ci set_pte(ptep, __pte(_PAGE_GLOBAL)); 19762306a36Sopenharmony_ci else 19862306a36Sopenharmony_ci#endif 19962306a36Sopenharmony_ci set_pte(ptep, __pte(0)); 20062306a36Sopenharmony_ci htw_start(); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci#endif 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic inline void set_ptes(struct mm_struct *mm, unsigned long addr, 20562306a36Sopenharmony_ci pte_t *ptep, pte_t pte, unsigned int nr) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci unsigned int i; 20862306a36Sopenharmony_ci bool do_sync = false; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci for (i = 0; i < nr; i++) { 21162306a36Sopenharmony_ci if (!pte_present(pte)) 21262306a36Sopenharmony_ci continue; 21362306a36Sopenharmony_ci if (pte_present(ptep[i]) && 21462306a36Sopenharmony_ci (pte_pfn(ptep[i]) == pte_pfn(pte))) 21562306a36Sopenharmony_ci continue; 21662306a36Sopenharmony_ci do_sync = true; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (do_sync) 22062306a36Sopenharmony_ci __update_cache(addr, pte); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci for (;;) { 22362306a36Sopenharmony_ci set_pte(ptep, pte); 22462306a36Sopenharmony_ci if (--nr == 0) 22562306a36Sopenharmony_ci break; 22662306a36Sopenharmony_ci ptep++; 22762306a36Sopenharmony_ci pte = __pte(pte_val(pte) + (1UL << PFN_PTE_SHIFT)); 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci#define set_ptes set_ptes 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci/* 23362306a36Sopenharmony_ci * (pmds are folded into puds so this doesn't get actually called, 23462306a36Sopenharmony_ci * but the define is needed for a generic inline function.) 23562306a36Sopenharmony_ci */ 23662306a36Sopenharmony_ci#define set_pmd(pmdptr, pmdval) do { *(pmdptr) = (pmdval); } while(0) 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci#ifndef __PAGETABLE_PMD_FOLDED 23962306a36Sopenharmony_ci/* 24062306a36Sopenharmony_ci * (puds are folded into pgds so this doesn't get actually called, 24162306a36Sopenharmony_ci * but the define is needed for a generic inline function.) 24262306a36Sopenharmony_ci */ 24362306a36Sopenharmony_ci#define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while(0) 24462306a36Sopenharmony_ci#endif 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci#define PGD_T_LOG2 (__builtin_ffs(sizeof(pgd_t)) - 1) 24762306a36Sopenharmony_ci#define PMD_T_LOG2 (__builtin_ffs(sizeof(pmd_t)) - 1) 24862306a36Sopenharmony_ci#define PTE_T_LOG2 (__builtin_ffs(sizeof(pte_t)) - 1) 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci/* 25162306a36Sopenharmony_ci * We used to declare this array with size but gcc 3.3 and older are not able 25262306a36Sopenharmony_ci * to find that this expression is a constant, so the size is dropped. 25362306a36Sopenharmony_ci */ 25462306a36Sopenharmony_ciextern pgd_t swapper_pg_dir[]; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci/* 25762306a36Sopenharmony_ci * Platform specific pte_special() and pte_mkspecial() definitions 25862306a36Sopenharmony_ci * are required only when ARCH_HAS_PTE_SPECIAL is enabled. 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci#if defined(CONFIG_ARCH_HAS_PTE_SPECIAL) 26162306a36Sopenharmony_ci#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) 26262306a36Sopenharmony_cistatic inline int pte_special(pte_t pte) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci return pte.pte_low & _PAGE_SPECIAL; 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic inline pte_t pte_mkspecial(pte_t pte) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci pte.pte_low |= _PAGE_SPECIAL; 27062306a36Sopenharmony_ci return pte; 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci#else 27362306a36Sopenharmony_cistatic inline int pte_special(pte_t pte) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci return pte_val(pte) & _PAGE_SPECIAL; 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic inline pte_t pte_mkspecial(pte_t pte) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci pte_val(pte) |= _PAGE_SPECIAL; 28162306a36Sopenharmony_ci return pte; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci#endif 28462306a36Sopenharmony_ci#endif /* CONFIG_ARCH_HAS_PTE_SPECIAL */ 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci/* 28762306a36Sopenharmony_ci * The following only work if pte_present() is true. 28862306a36Sopenharmony_ci * Undefined behaviour if not.. 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_ci#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) 29162306a36Sopenharmony_cistatic inline int pte_write(pte_t pte) { return pte.pte_low & _PAGE_WRITE; } 29262306a36Sopenharmony_cistatic inline int pte_dirty(pte_t pte) { return pte.pte_low & _PAGE_MODIFIED; } 29362306a36Sopenharmony_cistatic inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci pte.pte_low &= ~_PAGE_WRITE; 29862306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_XPA)) 29962306a36Sopenharmony_ci pte.pte_low &= ~_PAGE_SILENT_WRITE; 30062306a36Sopenharmony_ci pte.pte_high &= ~_PAGE_SILENT_WRITE; 30162306a36Sopenharmony_ci return pte; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci pte.pte_low &= ~_PAGE_MODIFIED; 30762306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_XPA)) 30862306a36Sopenharmony_ci pte.pte_low &= ~_PAGE_SILENT_WRITE; 30962306a36Sopenharmony_ci pte.pte_high &= ~_PAGE_SILENT_WRITE; 31062306a36Sopenharmony_ci return pte; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci pte.pte_low &= ~_PAGE_ACCESSED; 31662306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_XPA)) 31762306a36Sopenharmony_ci pte.pte_low &= ~_PAGE_SILENT_READ; 31862306a36Sopenharmony_ci pte.pte_high &= ~_PAGE_SILENT_READ; 31962306a36Sopenharmony_ci return pte; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic inline pte_t pte_mkwrite_novma(pte_t pte) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci pte.pte_low |= _PAGE_WRITE; 32562306a36Sopenharmony_ci if (pte.pte_low & _PAGE_MODIFIED) { 32662306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_XPA)) 32762306a36Sopenharmony_ci pte.pte_low |= _PAGE_SILENT_WRITE; 32862306a36Sopenharmony_ci pte.pte_high |= _PAGE_SILENT_WRITE; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci return pte; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci pte.pte_low |= _PAGE_MODIFIED; 33662306a36Sopenharmony_ci if (pte.pte_low & _PAGE_WRITE) { 33762306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_XPA)) 33862306a36Sopenharmony_ci pte.pte_low |= _PAGE_SILENT_WRITE; 33962306a36Sopenharmony_ci pte.pte_high |= _PAGE_SILENT_WRITE; 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci return pte; 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci pte.pte_low |= _PAGE_ACCESSED; 34762306a36Sopenharmony_ci if (!(pte.pte_low & _PAGE_NO_READ)) { 34862306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_XPA)) 34962306a36Sopenharmony_ci pte.pte_low |= _PAGE_SILENT_READ; 35062306a36Sopenharmony_ci pte.pte_high |= _PAGE_SILENT_READ; 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci return pte; 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci#else 35562306a36Sopenharmony_cistatic inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } 35662306a36Sopenharmony_cistatic inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; } 35762306a36Sopenharmony_cistatic inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); 36262306a36Sopenharmony_ci return pte; 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); 36862306a36Sopenharmony_ci return pte; 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci pte_val(pte) &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ); 37462306a36Sopenharmony_ci return pte; 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic inline pte_t pte_mkwrite_novma(pte_t pte) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci pte_val(pte) |= _PAGE_WRITE; 38062306a36Sopenharmony_ci if (pte_val(pte) & _PAGE_MODIFIED) 38162306a36Sopenharmony_ci pte_val(pte) |= _PAGE_SILENT_WRITE; 38262306a36Sopenharmony_ci return pte; 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci pte_val(pte) |= _PAGE_MODIFIED | _PAGE_SOFT_DIRTY; 38862306a36Sopenharmony_ci if (pte_val(pte) & _PAGE_WRITE) 38962306a36Sopenharmony_ci pte_val(pte) |= _PAGE_SILENT_WRITE; 39062306a36Sopenharmony_ci return pte; 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci pte_val(pte) |= _PAGE_ACCESSED; 39662306a36Sopenharmony_ci if (!(pte_val(pte) & _PAGE_NO_READ)) 39762306a36Sopenharmony_ci pte_val(pte) |= _PAGE_SILENT_READ; 39862306a36Sopenharmony_ci return pte; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci#define pte_sw_mkyoung pte_mkyoung 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT 40462306a36Sopenharmony_cistatic inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_HUGE; } 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic inline pte_t pte_mkhuge(pte_t pte) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci pte_val(pte) |= _PAGE_HUGE; 40962306a36Sopenharmony_ci return pte; 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci#define pmd_write pmd_write 41362306a36Sopenharmony_cistatic inline int pmd_write(pmd_t pmd) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci return !!(pmd_val(pmd) & _PAGE_WRITE); 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic inline struct page *pmd_page(pmd_t pmd) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci if (pmd_val(pmd) & _PAGE_HUGE) 42162306a36Sopenharmony_ci return pfn_to_page(pmd_pfn(pmd)); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci return pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT); 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci#endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */ 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY 42862306a36Sopenharmony_cistatic inline bool pte_soft_dirty(pte_t pte) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci return pte_val(pte) & _PAGE_SOFT_DIRTY; 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci#define pte_swp_soft_dirty pte_soft_dirty 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistatic inline pte_t pte_mksoft_dirty(pte_t pte) 43562306a36Sopenharmony_ci{ 43662306a36Sopenharmony_ci pte_val(pte) |= _PAGE_SOFT_DIRTY; 43762306a36Sopenharmony_ci return pte; 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci#define pte_swp_mksoft_dirty pte_mksoft_dirty 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cistatic inline pte_t pte_clear_soft_dirty(pte_t pte) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci pte_val(pte) &= ~(_PAGE_SOFT_DIRTY); 44462306a36Sopenharmony_ci return pte; 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci#define pte_swp_clear_soft_dirty pte_clear_soft_dirty 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci#endif 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci/* 45362306a36Sopenharmony_ci * Macro to make mark a page protection value as "uncacheable". Note 45462306a36Sopenharmony_ci * that "protection" is really a misnomer here as the protection value 45562306a36Sopenharmony_ci * contains the memory attribute bits, dirty bits, and various other 45662306a36Sopenharmony_ci * bits as well. 45762306a36Sopenharmony_ci */ 45862306a36Sopenharmony_ci#define pgprot_noncached pgprot_noncached 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cistatic inline pgprot_t pgprot_noncached(pgprot_t _prot) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci unsigned long prot = pgprot_val(_prot); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci return __pgprot(prot); 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci#define pgprot_writecombine pgprot_writecombine 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic inline pgprot_t pgprot_writecombine(pgprot_t _prot) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci unsigned long prot = pgprot_val(_prot); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci /* cpu_data[0].writecombine is already shifted by _CACHE_SHIFT */ 47662306a36Sopenharmony_ci prot = (prot & ~_CACHE_MASK) | cpu_data[0].writecombine; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci return __pgprot(prot); 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma, 48262306a36Sopenharmony_ci unsigned long address, 48362306a36Sopenharmony_ci pte_t *ptep) 48462306a36Sopenharmony_ci{ 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci#define __HAVE_ARCH_PTE_SAME 48862306a36Sopenharmony_cistatic inline int pte_same(pte_t pte_a, pte_t pte_b) 48962306a36Sopenharmony_ci{ 49062306a36Sopenharmony_ci return pte_val(pte_a) == pte_val(pte_b); 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS 49462306a36Sopenharmony_cistatic inline int ptep_set_access_flags(struct vm_area_struct *vma, 49562306a36Sopenharmony_ci unsigned long address, pte_t *ptep, 49662306a36Sopenharmony_ci pte_t entry, int dirty) 49762306a36Sopenharmony_ci{ 49862306a36Sopenharmony_ci if (!pte_same(*ptep, entry)) 49962306a36Sopenharmony_ci set_pte(ptep, entry); 50062306a36Sopenharmony_ci /* 50162306a36Sopenharmony_ci * update_mmu_cache will unconditionally execute, handling both 50262306a36Sopenharmony_ci * the case that the PTE changed and the spurious fault case. 50362306a36Sopenharmony_ci */ 50462306a36Sopenharmony_ci return true; 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci/* 50862306a36Sopenharmony_ci * Conversion functions: convert a page and protection to a page entry, 50962306a36Sopenharmony_ci * and a page entry and page directory to the page they refer to. 51062306a36Sopenharmony_ci */ 51162306a36Sopenharmony_ci#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci#if defined(CONFIG_XPA) 51462306a36Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 51562306a36Sopenharmony_ci{ 51662306a36Sopenharmony_ci pte.pte_low &= (_PAGE_MODIFIED | _PAGE_ACCESSED | _PFNX_MASK); 51762306a36Sopenharmony_ci pte.pte_high &= (_PFN_MASK | _CACHE_MASK); 51862306a36Sopenharmony_ci pte.pte_low |= pgprot_val(newprot) & ~_PFNX_MASK; 51962306a36Sopenharmony_ci pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK); 52062306a36Sopenharmony_ci return pte; 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) 52362306a36Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci pte.pte_low &= _PAGE_CHG_MASK; 52662306a36Sopenharmony_ci pte.pte_high &= (_PFN_MASK | _CACHE_MASK); 52762306a36Sopenharmony_ci pte.pte_low |= pgprot_val(newprot); 52862306a36Sopenharmony_ci pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK); 52962306a36Sopenharmony_ci return pte; 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci#else 53262306a36Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci pte_val(pte) &= _PAGE_CHG_MASK; 53562306a36Sopenharmony_ci pte_val(pte) |= pgprot_val(newprot) & ~_PAGE_CHG_MASK; 53662306a36Sopenharmony_ci if ((pte_val(pte) & _PAGE_ACCESSED) && !(pte_val(pte) & _PAGE_NO_READ)) 53762306a36Sopenharmony_ci pte_val(pte) |= _PAGE_SILENT_READ; 53862306a36Sopenharmony_ci return pte; 53962306a36Sopenharmony_ci} 54062306a36Sopenharmony_ci#endif 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) 54362306a36Sopenharmony_cistatic inline int pte_swp_exclusive(pte_t pte) 54462306a36Sopenharmony_ci{ 54562306a36Sopenharmony_ci return pte.pte_low & _PAGE_SWP_EXCLUSIVE; 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic inline pte_t pte_swp_mkexclusive(pte_t pte) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci pte.pte_low |= _PAGE_SWP_EXCLUSIVE; 55162306a36Sopenharmony_ci return pte; 55262306a36Sopenharmony_ci} 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_cistatic inline pte_t pte_swp_clear_exclusive(pte_t pte) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci pte.pte_low &= ~_PAGE_SWP_EXCLUSIVE; 55762306a36Sopenharmony_ci return pte; 55862306a36Sopenharmony_ci} 55962306a36Sopenharmony_ci#else 56062306a36Sopenharmony_cistatic inline int pte_swp_exclusive(pte_t pte) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_cistatic inline pte_t pte_swp_mkexclusive(pte_t pte) 56662306a36Sopenharmony_ci{ 56762306a36Sopenharmony_ci pte_val(pte) |= _PAGE_SWP_EXCLUSIVE; 56862306a36Sopenharmony_ci return pte; 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic inline pte_t pte_swp_clear_exclusive(pte_t pte) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci pte_val(pte) &= ~_PAGE_SWP_EXCLUSIVE; 57462306a36Sopenharmony_ci return pte; 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci#endif 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ciextern void __update_tlb(struct vm_area_struct *vma, unsigned long address, 57962306a36Sopenharmony_ci pte_t pte); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_cistatic inline void update_mmu_cache_range(struct vm_fault *vmf, 58262306a36Sopenharmony_ci struct vm_area_struct *vma, unsigned long address, 58362306a36Sopenharmony_ci pte_t *ptep, unsigned int nr) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci for (;;) { 58662306a36Sopenharmony_ci pte_t pte = *ptep; 58762306a36Sopenharmony_ci __update_tlb(vma, address, pte); 58862306a36Sopenharmony_ci if (--nr == 0) 58962306a36Sopenharmony_ci break; 59062306a36Sopenharmony_ci ptep++; 59162306a36Sopenharmony_ci address += PAGE_SIZE; 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci} 59462306a36Sopenharmony_ci#define update_mmu_cache(vma, address, ptep) \ 59562306a36Sopenharmony_ci update_mmu_cache_range(NULL, vma, address, ptep, 1) 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci#define __HAVE_ARCH_UPDATE_MMU_TLB 59862306a36Sopenharmony_ci#define update_mmu_tlb update_mmu_cache 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic inline void update_mmu_cache_pmd(struct vm_area_struct *vma, 60162306a36Sopenharmony_ci unsigned long address, pmd_t *pmdp) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci pte_t pte = *(pte_t *)pmdp; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci __update_tlb(vma, address, pte); 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci/* 60962306a36Sopenharmony_ci * Allow physical addresses to be fixed up to help 36-bit peripherals. 61062306a36Sopenharmony_ci */ 61162306a36Sopenharmony_ci#ifdef CONFIG_MIPS_FIXUP_BIGPHYS_ADDR 61262306a36Sopenharmony_ciphys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size); 61362306a36Sopenharmony_ciint io_remap_pfn_range(struct vm_area_struct *vma, unsigned long vaddr, 61462306a36Sopenharmony_ci unsigned long pfn, unsigned long size, pgprot_t prot); 61562306a36Sopenharmony_ci#define io_remap_pfn_range io_remap_pfn_range 61662306a36Sopenharmony_ci#else 61762306a36Sopenharmony_ci#define fixup_bigphys_addr(addr, size) (addr) 61862306a36Sopenharmony_ci#endif /* CONFIG_MIPS_FIXUP_BIGPHYS_ADDR */ 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci/* We don't have hardware dirty/accessed bits, generic_pmdp_establish is fine.*/ 62362306a36Sopenharmony_ci#define pmdp_establish generic_pmdp_establish 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci#define has_transparent_hugepage has_transparent_hugepage 62662306a36Sopenharmony_ciextern int has_transparent_hugepage(void); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_cistatic inline int pmd_trans_huge(pmd_t pmd) 62962306a36Sopenharmony_ci{ 63062306a36Sopenharmony_ci return !!(pmd_val(pmd) & _PAGE_HUGE); 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic inline pmd_t pmd_mkhuge(pmd_t pmd) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci pmd_val(pmd) |= _PAGE_HUGE; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci return pmd; 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ciextern void set_pmd_at(struct mm_struct *mm, unsigned long addr, 64162306a36Sopenharmony_ci pmd_t *pmdp, pmd_t pmd); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic inline pmd_t pmd_wrprotect(pmd_t pmd) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); 64662306a36Sopenharmony_ci return pmd; 64762306a36Sopenharmony_ci} 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_cistatic inline pmd_t pmd_mkwrite_novma(pmd_t pmd) 65062306a36Sopenharmony_ci{ 65162306a36Sopenharmony_ci pmd_val(pmd) |= _PAGE_WRITE; 65262306a36Sopenharmony_ci if (pmd_val(pmd) & _PAGE_MODIFIED) 65362306a36Sopenharmony_ci pmd_val(pmd) |= _PAGE_SILENT_WRITE; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci return pmd; 65662306a36Sopenharmony_ci} 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_cistatic inline int pmd_dirty(pmd_t pmd) 65962306a36Sopenharmony_ci{ 66062306a36Sopenharmony_ci return !!(pmd_val(pmd) & _PAGE_MODIFIED); 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cistatic inline pmd_t pmd_mkclean(pmd_t pmd) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci pmd_val(pmd) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); 66662306a36Sopenharmony_ci return pmd; 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_cistatic inline pmd_t pmd_mkdirty(pmd_t pmd) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci pmd_val(pmd) |= _PAGE_MODIFIED | _PAGE_SOFT_DIRTY; 67262306a36Sopenharmony_ci if (pmd_val(pmd) & _PAGE_WRITE) 67362306a36Sopenharmony_ci pmd_val(pmd) |= _PAGE_SILENT_WRITE; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci return pmd; 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci#define pmd_young pmd_young 67962306a36Sopenharmony_cistatic inline int pmd_young(pmd_t pmd) 68062306a36Sopenharmony_ci{ 68162306a36Sopenharmony_ci return !!(pmd_val(pmd) & _PAGE_ACCESSED); 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_cistatic inline pmd_t pmd_mkold(pmd_t pmd) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci pmd_val(pmd) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci return pmd; 68962306a36Sopenharmony_ci} 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_cistatic inline pmd_t pmd_mkyoung(pmd_t pmd) 69262306a36Sopenharmony_ci{ 69362306a36Sopenharmony_ci pmd_val(pmd) |= _PAGE_ACCESSED; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci if (!(pmd_val(pmd) & _PAGE_NO_READ)) 69662306a36Sopenharmony_ci pmd_val(pmd) |= _PAGE_SILENT_READ; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci return pmd; 69962306a36Sopenharmony_ci} 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY 70262306a36Sopenharmony_cistatic inline int pmd_soft_dirty(pmd_t pmd) 70362306a36Sopenharmony_ci{ 70462306a36Sopenharmony_ci return !!(pmd_val(pmd) & _PAGE_SOFT_DIRTY); 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cistatic inline pmd_t pmd_mksoft_dirty(pmd_t pmd) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci pmd_val(pmd) |= _PAGE_SOFT_DIRTY; 71062306a36Sopenharmony_ci return pmd; 71162306a36Sopenharmony_ci} 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_cistatic inline pmd_t pmd_clear_soft_dirty(pmd_t pmd) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci pmd_val(pmd) &= ~(_PAGE_SOFT_DIRTY); 71662306a36Sopenharmony_ci return pmd; 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci/* Extern to avoid header file madness */ 72262306a36Sopenharmony_ciextern pmd_t mk_pmd(struct page *page, pgprot_t prot); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_cistatic inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci pmd_val(pmd) = (pmd_val(pmd) & (_PAGE_CHG_MASK | _PAGE_HUGE)) | 72762306a36Sopenharmony_ci (pgprot_val(newprot) & ~_PAGE_CHG_MASK); 72862306a36Sopenharmony_ci return pmd; 72962306a36Sopenharmony_ci} 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_cistatic inline pmd_t pmd_mkinvalid(pmd_t pmd) 73262306a36Sopenharmony_ci{ 73362306a36Sopenharmony_ci pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci return pmd; 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci/* 73962306a36Sopenharmony_ci * The generic version pmdp_huge_get_and_clear uses a version of pmd_clear() with a 74062306a36Sopenharmony_ci * different prototype. 74162306a36Sopenharmony_ci */ 74262306a36Sopenharmony_ci#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR 74362306a36Sopenharmony_cistatic inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, 74462306a36Sopenharmony_ci unsigned long address, pmd_t *pmdp) 74562306a36Sopenharmony_ci{ 74662306a36Sopenharmony_ci pmd_t old = *pmdp; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci pmd_clear(pmdp); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci return old; 75162306a36Sopenharmony_ci} 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci#ifdef _PAGE_HUGE 75662306a36Sopenharmony_ci#define pmd_leaf(pmd) ((pmd_val(pmd) & _PAGE_HUGE) != 0) 75762306a36Sopenharmony_ci#define pud_leaf(pud) ((pud_val(pud) & _PAGE_HUGE) != 0) 75862306a36Sopenharmony_ci#endif 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci#define gup_fast_permitted(start, end) (!cpu_has_dc_aliases) 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci/* 76362306a36Sopenharmony_ci * We provide our own get_unmapped area to cope with the virtual aliasing 76462306a36Sopenharmony_ci * constraints placed on us by the cache architecture. 76562306a36Sopenharmony_ci */ 76662306a36Sopenharmony_ci#define HAVE_ARCH_UNMAPPED_AREA 76762306a36Sopenharmony_ci#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci#endif /* _ASM_PGTABLE_H */ 770