18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
48c2ecf20Sopenharmony_ci * Copyright (C) 2008-2009 PetaLogix
58c2ecf20Sopenharmony_ci * Copyright (C) 2006 Atmark Techno, Inc.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef _ASM_MICROBLAZE_PGTABLE_H
98c2ecf20Sopenharmony_ci#define _ASM_MICROBLAZE_PGTABLE_H
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <asm/setup.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
148c2ecf20Sopenharmony_ciextern int mem_init_done;
158c2ecf20Sopenharmony_ci#endif
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#ifndef CONFIG_MMU
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define pgd_present(pgd)	(1) /* pages are always present on non MMU */
208c2ecf20Sopenharmony_ci#define pgd_none(pgd)		(0)
218c2ecf20Sopenharmony_ci#define pgd_bad(pgd)		(0)
228c2ecf20Sopenharmony_ci#define pgd_clear(pgdp)
238c2ecf20Sopenharmony_ci#define kern_addr_valid(addr)	(1)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define PAGE_NONE		__pgprot(0) /* these mean nothing to non MMU */
268c2ecf20Sopenharmony_ci#define PAGE_SHARED		__pgprot(0) /* these mean nothing to non MMU */
278c2ecf20Sopenharmony_ci#define PAGE_COPY		__pgprot(0) /* these mean nothing to non MMU */
288c2ecf20Sopenharmony_ci#define PAGE_READONLY		__pgprot(0) /* these mean nothing to non MMU */
298c2ecf20Sopenharmony_ci#define PAGE_KERNEL		__pgprot(0) /* these mean nothing to non MMU */
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define pgprot_noncached(x)	(x)
328c2ecf20Sopenharmony_ci#define pgprot_writecombine	pgprot_noncached
338c2ecf20Sopenharmony_ci#define pgprot_device		pgprot_noncached
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define __swp_type(x)		(0)
368c2ecf20Sopenharmony_ci#define __swp_offset(x)		(0)
378c2ecf20Sopenharmony_ci#define __swp_entry(typ, off)	((swp_entry_t) { ((typ) | ((off) << 7)) })
388c2ecf20Sopenharmony_ci#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
398c2ecf20Sopenharmony_ci#define __swp_entry_to_pte(x)	((pte_t) { (x).val })
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define ZERO_PAGE(vaddr)	({ BUG(); NULL; })
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define swapper_pg_dir ((pgd_t *) NULL)
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define arch_enter_lazy_cpu_mode()	do {} while (0)
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define pgprot_noncached_wc(prot)	prot
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/*
508c2ecf20Sopenharmony_ci * All 32bit addresses are effectively valid for vmalloc...
518c2ecf20Sopenharmony_ci * Sort of meaningless for non-VM targets.
528c2ecf20Sopenharmony_ci */
538c2ecf20Sopenharmony_ci#define	VMALLOC_START	0
548c2ecf20Sopenharmony_ci#define	VMALLOC_END	0xffffffff
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#else /* CONFIG_MMU */
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#include <asm-generic/pgtable-nopmd.h>
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#ifdef __KERNEL__
618c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci#include <linux/sched.h>
648c2ecf20Sopenharmony_ci#include <linux/threads.h>
658c2ecf20Sopenharmony_ci#include <asm/processor.h>		/* For TASK_SIZE */
668c2ecf20Sopenharmony_ci#include <asm/mmu.h>
678c2ecf20Sopenharmony_ci#include <asm/page.h>
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci#define FIRST_USER_ADDRESS	0UL
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciextern unsigned long va_to_phys(unsigned long address);
728c2ecf20Sopenharmony_ciextern pte_t *va_to_pte(unsigned long address);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/*
758c2ecf20Sopenharmony_ci * The following only work if pte_present() is true.
768c2ecf20Sopenharmony_ci * Undefined behaviour if not..
778c2ecf20Sopenharmony_ci */
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/* Start and end of the vmalloc area. */
808c2ecf20Sopenharmony_ci/* Make sure to map the vmalloc area above the pinned kernel memory area
818c2ecf20Sopenharmony_ci   of 32Mb.  */
828c2ecf20Sopenharmony_ci#define VMALLOC_START	(CONFIG_KERNEL_START + CONFIG_LOWMEM_SIZE)
838c2ecf20Sopenharmony_ci#define VMALLOC_END	ioremap_bot
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/*
888c2ecf20Sopenharmony_ci * Macro to mark a page protection value as "uncacheable".
898c2ecf20Sopenharmony_ci */
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci#define _PAGE_CACHE_CTL	(_PAGE_GUARDED | _PAGE_NO_CACHE | \
928c2ecf20Sopenharmony_ci							_PAGE_WRITETHRU)
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#define pgprot_noncached(prot) \
958c2ecf20Sopenharmony_ci			(__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
968c2ecf20Sopenharmony_ci					_PAGE_NO_CACHE | _PAGE_GUARDED))
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci#define pgprot_noncached_wc(prot) \
998c2ecf20Sopenharmony_ci			 (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
1008c2ecf20Sopenharmony_ci							_PAGE_NO_CACHE))
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci/*
1038c2ecf20Sopenharmony_ci * The MicroBlaze MMU is identical to the PPC-40x MMU, and uses a hash
1048c2ecf20Sopenharmony_ci * table containing PTEs, together with a set of 16 segment registers, to
1058c2ecf20Sopenharmony_ci * define the virtual to physical address mapping.
1068c2ecf20Sopenharmony_ci *
1078c2ecf20Sopenharmony_ci * We use the hash table as an extended TLB, i.e. a cache of currently
1088c2ecf20Sopenharmony_ci * active mappings.  We maintain a two-level page table tree, much
1098c2ecf20Sopenharmony_ci * like that used by the i386, for the sake of the Linux memory
1108c2ecf20Sopenharmony_ci * management code.  Low-level assembler code in hashtable.S
1118c2ecf20Sopenharmony_ci * (procedure hash_page) is responsible for extracting ptes from the
1128c2ecf20Sopenharmony_ci * tree and putting them into the hash table when necessary, and
1138c2ecf20Sopenharmony_ci * updating the accessed and modified bits in the page table tree.
1148c2ecf20Sopenharmony_ci */
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci/*
1178c2ecf20Sopenharmony_ci * The MicroBlaze processor has a TLB architecture identical to PPC-40x. The
1188c2ecf20Sopenharmony_ci * instruction and data sides share a unified, 64-entry, semi-associative
1198c2ecf20Sopenharmony_ci * TLB which is maintained totally under software control. In addition, the
1208c2ecf20Sopenharmony_ci * instruction side has a hardware-managed, 2,4, or 8-entry, fully-associative
1218c2ecf20Sopenharmony_ci * TLB which serves as a first level to the shared TLB. These two TLBs are
1228c2ecf20Sopenharmony_ci * known as the UTLB and ITLB, respectively (see "mmu.h" for definitions).
1238c2ecf20Sopenharmony_ci */
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci/*
1268c2ecf20Sopenharmony_ci * The normal case is that PTEs are 32-bits and we have a 1-page
1278c2ecf20Sopenharmony_ci * 1024-entry pgdir pointing to 1-page 1024-entry PTE pages.  -- paulus
1288c2ecf20Sopenharmony_ci *
1298c2ecf20Sopenharmony_ci */
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci/* PGDIR_SHIFT determines what a top-level page table entry can map */
1328c2ecf20Sopenharmony_ci#define PGDIR_SHIFT	(PAGE_SHIFT + PTE_SHIFT)
1338c2ecf20Sopenharmony_ci#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
1348c2ecf20Sopenharmony_ci#define PGDIR_MASK	(~(PGDIR_SIZE-1))
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci/*
1378c2ecf20Sopenharmony_ci * entries per page directory level: our page-table tree is two-level, so
1388c2ecf20Sopenharmony_ci * we don't really have any PMD directory.
1398c2ecf20Sopenharmony_ci */
1408c2ecf20Sopenharmony_ci#define PTRS_PER_PTE	(1 << PTE_SHIFT)
1418c2ecf20Sopenharmony_ci#define PTRS_PER_PMD	1
1428c2ecf20Sopenharmony_ci#define PTRS_PER_PGD	(1 << (32 - PGDIR_SHIFT))
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
1458c2ecf20Sopenharmony_ci#define FIRST_USER_PGD_NR	0
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
1488c2ecf20Sopenharmony_ci#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci#define pte_ERROR(e) \
1518c2ecf20Sopenharmony_ci	printk(KERN_ERR "%s:%d: bad pte "PTE_FMT".\n", \
1528c2ecf20Sopenharmony_ci		__FILE__, __LINE__, pte_val(e))
1538c2ecf20Sopenharmony_ci#define pgd_ERROR(e) \
1548c2ecf20Sopenharmony_ci	printk(KERN_ERR "%s:%d: bad pgd %08lx.\n", \
1558c2ecf20Sopenharmony_ci		__FILE__, __LINE__, pgd_val(e))
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci/*
1588c2ecf20Sopenharmony_ci * Bits in a linux-style PTE.  These match the bits in the
1598c2ecf20Sopenharmony_ci * (hardware-defined) PTE as closely as possible.
1608c2ecf20Sopenharmony_ci */
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci/* There are several potential gotchas here.  The hardware TLBLO
1638c2ecf20Sopenharmony_ci * field looks like this:
1648c2ecf20Sopenharmony_ci *
1658c2ecf20Sopenharmony_ci * 0  1  2  3  4  ... 18 19 20 21 22 23 24 25 26 27 28 29 30 31
1668c2ecf20Sopenharmony_ci * RPN.....................  0  0 EX WR ZSEL.......  W  I  M  G
1678c2ecf20Sopenharmony_ci *
1688c2ecf20Sopenharmony_ci * Where possible we make the Linux PTE bits match up with this
1698c2ecf20Sopenharmony_ci *
1708c2ecf20Sopenharmony_ci * - bits 20 and 21 must be cleared, because we use 4k pages (4xx can
1718c2ecf20Sopenharmony_ci * support down to 1k pages), this is done in the TLBMiss exception
1728c2ecf20Sopenharmony_ci * handler.
1738c2ecf20Sopenharmony_ci * - We use only zones 0 (for kernel pages) and 1 (for user pages)
1748c2ecf20Sopenharmony_ci * of the 16 available.  Bit 24-26 of the TLB are cleared in the TLB
1758c2ecf20Sopenharmony_ci * miss handler.  Bit 27 is PAGE_USER, thus selecting the correct
1768c2ecf20Sopenharmony_ci * zone.
1778c2ecf20Sopenharmony_ci * - PRESENT *must* be in the bottom two bits because swap cache
1788c2ecf20Sopenharmony_ci * entries use the top 30 bits.  Because 4xx doesn't support SMP
1798c2ecf20Sopenharmony_ci * anyway, M is irrelevant so we borrow it for PAGE_PRESENT.  Bit 30
1808c2ecf20Sopenharmony_ci * is cleared in the TLB miss handler before the TLB entry is loaded.
1818c2ecf20Sopenharmony_ci * - All other bits of the PTE are loaded into TLBLO without
1828c2ecf20Sopenharmony_ci *  * modification, leaving us only the bits 20, 21, 24, 25, 26, 30 for
1838c2ecf20Sopenharmony_ci * software PTE bits.  We actually use bits 21, 24, 25, and
1848c2ecf20Sopenharmony_ci * 30 respectively for the software bits: ACCESSED, DIRTY, RW, and
1858c2ecf20Sopenharmony_ci * PRESENT.
1868c2ecf20Sopenharmony_ci */
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci/* Definitions for MicroBlaze. */
1898c2ecf20Sopenharmony_ci#define	_PAGE_GUARDED	0x001	/* G: page is guarded from prefetch */
1908c2ecf20Sopenharmony_ci#define _PAGE_PRESENT	0x002	/* software: PTE contains a translation */
1918c2ecf20Sopenharmony_ci#define	_PAGE_NO_CACHE	0x004	/* I: caching is inhibited */
1928c2ecf20Sopenharmony_ci#define	_PAGE_WRITETHRU	0x008	/* W: caching is write-through */
1938c2ecf20Sopenharmony_ci#define	_PAGE_USER	0x010	/* matches one of the zone permission bits */
1948c2ecf20Sopenharmony_ci#define	_PAGE_RW	0x040	/* software: Writes permitted */
1958c2ecf20Sopenharmony_ci#define	_PAGE_DIRTY	0x080	/* software: dirty page */
1968c2ecf20Sopenharmony_ci#define _PAGE_HWWRITE	0x100	/* hardware: Dirty & RW, set in exception */
1978c2ecf20Sopenharmony_ci#define _PAGE_HWEXEC	0x200	/* hardware: EX permission */
1988c2ecf20Sopenharmony_ci#define _PAGE_ACCESSED	0x400	/* software: R: page referenced */
1998c2ecf20Sopenharmony_ci#define _PMD_PRESENT	PAGE_MASK
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci/*
2028c2ecf20Sopenharmony_ci * Some bits are unused...
2038c2ecf20Sopenharmony_ci */
2048c2ecf20Sopenharmony_ci#ifndef _PAGE_HASHPTE
2058c2ecf20Sopenharmony_ci#define _PAGE_HASHPTE	0
2068c2ecf20Sopenharmony_ci#endif
2078c2ecf20Sopenharmony_ci#ifndef _PTE_NONE_MASK
2088c2ecf20Sopenharmony_ci#define _PTE_NONE_MASK	0
2098c2ecf20Sopenharmony_ci#endif
2108c2ecf20Sopenharmony_ci#ifndef _PAGE_SHARED
2118c2ecf20Sopenharmony_ci#define _PAGE_SHARED	0
2128c2ecf20Sopenharmony_ci#endif
2138c2ecf20Sopenharmony_ci#ifndef _PAGE_EXEC
2148c2ecf20Sopenharmony_ci#define _PAGE_EXEC	0
2158c2ecf20Sopenharmony_ci#endif
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci/*
2208c2ecf20Sopenharmony_ci * Note: the _PAGE_COHERENT bit automatically gets set in the hardware
2218c2ecf20Sopenharmony_ci * PTE if CONFIG_SMP is defined (hash_page does this); there is no need
2228c2ecf20Sopenharmony_ci * to have it in the Linux PTE, and in fact the bit could be reused for
2238c2ecf20Sopenharmony_ci * another purpose.  -- paulus.
2248c2ecf20Sopenharmony_ci */
2258c2ecf20Sopenharmony_ci#define _PAGE_BASE	(_PAGE_PRESENT | _PAGE_ACCESSED)
2268c2ecf20Sopenharmony_ci#define _PAGE_WRENABLE	(_PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE)
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci#define _PAGE_KERNEL \
2298c2ecf20Sopenharmony_ci	(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED | _PAGE_HWEXEC)
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci#define _PAGE_IO	(_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED)
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci#define PAGE_NONE	__pgprot(_PAGE_BASE)
2348c2ecf20Sopenharmony_ci#define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER)
2358c2ecf20Sopenharmony_ci#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
2368c2ecf20Sopenharmony_ci#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
2378c2ecf20Sopenharmony_ci#define PAGE_SHARED_X \
2388c2ecf20Sopenharmony_ci		__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
2398c2ecf20Sopenharmony_ci#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_USER)
2408c2ecf20Sopenharmony_ci#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci#define PAGE_KERNEL	__pgprot(_PAGE_KERNEL)
2438c2ecf20Sopenharmony_ci#define PAGE_KERNEL_RO	__pgprot(_PAGE_BASE | _PAGE_SHARED)
2448c2ecf20Sopenharmony_ci#define PAGE_KERNEL_CI	__pgprot(_PAGE_IO)
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci/*
2478c2ecf20Sopenharmony_ci * We consider execute permission the same as read.
2488c2ecf20Sopenharmony_ci * Also, write permissions imply read permissions.
2498c2ecf20Sopenharmony_ci */
2508c2ecf20Sopenharmony_ci#define __P000	PAGE_NONE
2518c2ecf20Sopenharmony_ci#define __P001	PAGE_READONLY_X
2528c2ecf20Sopenharmony_ci#define __P010	PAGE_COPY
2538c2ecf20Sopenharmony_ci#define __P011	PAGE_COPY_X
2548c2ecf20Sopenharmony_ci#define __P100	PAGE_READONLY
2558c2ecf20Sopenharmony_ci#define __P101	PAGE_READONLY_X
2568c2ecf20Sopenharmony_ci#define __P110	PAGE_COPY
2578c2ecf20Sopenharmony_ci#define __P111	PAGE_COPY_X
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci#define __S000	PAGE_NONE
2608c2ecf20Sopenharmony_ci#define __S001	PAGE_READONLY_X
2618c2ecf20Sopenharmony_ci#define __S010	PAGE_SHARED
2628c2ecf20Sopenharmony_ci#define __S011	PAGE_SHARED_X
2638c2ecf20Sopenharmony_ci#define __S100	PAGE_READONLY
2648c2ecf20Sopenharmony_ci#define __S101	PAGE_READONLY_X
2658c2ecf20Sopenharmony_ci#define __S110	PAGE_SHARED
2668c2ecf20Sopenharmony_ci#define __S111	PAGE_SHARED_X
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
2698c2ecf20Sopenharmony_ci/*
2708c2ecf20Sopenharmony_ci * ZERO_PAGE is a global shared page that is always zero: used
2718c2ecf20Sopenharmony_ci * for zero-mapped memory areas etc..
2728c2ecf20Sopenharmony_ci */
2738c2ecf20Sopenharmony_ciextern unsigned long empty_zero_page[1024];
2748c2ecf20Sopenharmony_ci#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci#define pte_none(pte)		((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
2798c2ecf20Sopenharmony_ci#define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
2808c2ecf20Sopenharmony_ci#define pte_clear(mm, addr, ptep) \
2818c2ecf20Sopenharmony_ci	do { set_pte_at((mm), (addr), (ptep), __pte(0)); } while (0)
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci#define pmd_none(pmd)		(!pmd_val(pmd))
2848c2ecf20Sopenharmony_ci#define	pmd_bad(pmd)		((pmd_val(pmd) & _PMD_PRESENT) == 0)
2858c2ecf20Sopenharmony_ci#define	pmd_present(pmd)	((pmd_val(pmd) & _PMD_PRESENT) != 0)
2868c2ecf20Sopenharmony_ci#define	pmd_clear(pmdp)		do { pmd_val(*(pmdp)) = 0; } while (0)
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci#define pte_page(x)		(mem_map + (unsigned long) \
2898c2ecf20Sopenharmony_ci				((pte_val(x) - memory_start) >> PAGE_SHIFT))
2908c2ecf20Sopenharmony_ci#define PFN_SHIFT_OFFSET	(PAGE_SHIFT)
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci#define pte_pfn(x)		(pte_val(x) >> PFN_SHIFT_OFFSET)
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci#define pfn_pte(pfn, prot) \
2958c2ecf20Sopenharmony_ci	__pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) | pgprot_val(prot))
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
2988c2ecf20Sopenharmony_ci/*
2998c2ecf20Sopenharmony_ci * The following only work if pte_present() is true.
3008c2ecf20Sopenharmony_ci * Undefined behaviour if not..
3018c2ecf20Sopenharmony_ci */
3028c2ecf20Sopenharmony_cistatic inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_USER; }
3038c2ecf20Sopenharmony_cistatic inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
3048c2ecf20Sopenharmony_cistatic inline int pte_exec(pte_t pte)  { return pte_val(pte) & _PAGE_EXEC; }
3058c2ecf20Sopenharmony_cistatic inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
3068c2ecf20Sopenharmony_cistatic inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistatic inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
3098c2ecf20Sopenharmony_cistatic inline void pte_cache(pte_t pte)   { pte_val(pte) &= ~_PAGE_NO_CACHE; }
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistatic inline pte_t pte_rdprotect(pte_t pte) \
3128c2ecf20Sopenharmony_ci		{ pte_val(pte) &= ~_PAGE_USER; return pte; }
3138c2ecf20Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte) \
3148c2ecf20Sopenharmony_ci	{ pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
3158c2ecf20Sopenharmony_cistatic inline pte_t pte_exprotect(pte_t pte) \
3168c2ecf20Sopenharmony_ci	{ pte_val(pte) &= ~_PAGE_EXEC; return pte; }
3178c2ecf20Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte) \
3188c2ecf20Sopenharmony_ci	{ pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
3198c2ecf20Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte) \
3208c2ecf20Sopenharmony_ci	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic inline pte_t pte_mkread(pte_t pte) \
3238c2ecf20Sopenharmony_ci	{ pte_val(pte) |= _PAGE_USER; return pte; }
3248c2ecf20Sopenharmony_cistatic inline pte_t pte_mkexec(pte_t pte) \
3258c2ecf20Sopenharmony_ci	{ pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; }
3268c2ecf20Sopenharmony_cistatic inline pte_t pte_mkwrite(pte_t pte) \
3278c2ecf20Sopenharmony_ci	{ pte_val(pte) |= _PAGE_RW; return pte; }
3288c2ecf20Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte) \
3298c2ecf20Sopenharmony_ci	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
3308c2ecf20Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte) \
3318c2ecf20Sopenharmony_ci	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci/*
3348c2ecf20Sopenharmony_ci * Conversion functions: convert a page and protection to a page entry,
3358c2ecf20Sopenharmony_ci * and a page entry and page directory to the page they refer to.
3368c2ecf20Sopenharmony_ci */
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_cistatic inline pte_t mk_pte_phys(phys_addr_t physpage, pgprot_t pgprot)
3398c2ecf20Sopenharmony_ci{
3408c2ecf20Sopenharmony_ci	pte_t pte;
3418c2ecf20Sopenharmony_ci	pte_val(pte) = physpage | pgprot_val(pgprot);
3428c2ecf20Sopenharmony_ci	return pte;
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci#define mk_pte(page, pgprot) \
3468c2ecf20Sopenharmony_ci({									   \
3478c2ecf20Sopenharmony_ci	pte_t pte;							   \
3488c2ecf20Sopenharmony_ci	pte_val(pte) = (((page - mem_map) << PAGE_SHIFT) + memory_start) |  \
3498c2ecf20Sopenharmony_ci			pgprot_val(pgprot);				   \
3508c2ecf20Sopenharmony_ci	pte;								   \
3518c2ecf20Sopenharmony_ci})
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
3568c2ecf20Sopenharmony_ci	return pte;
3578c2ecf20Sopenharmony_ci}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci/*
3608c2ecf20Sopenharmony_ci * Atomic PTE updates.
3618c2ecf20Sopenharmony_ci *
3628c2ecf20Sopenharmony_ci * pte_update clears and sets bit atomically, and returns
3638c2ecf20Sopenharmony_ci * the old pte value.
3648c2ecf20Sopenharmony_ci * The ((unsigned long)(p+1) - 4) hack is to get to the least-significant
3658c2ecf20Sopenharmony_ci * 32 bits of the PTE regardless of whether PTEs are 32 or 64 bits.
3668c2ecf20Sopenharmony_ci */
3678c2ecf20Sopenharmony_cistatic inline unsigned long pte_update(pte_t *p, unsigned long clr,
3688c2ecf20Sopenharmony_ci				unsigned long set)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	unsigned long flags, old, tmp;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	raw_local_irq_save(flags);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	__asm__ __volatile__(	"lw	%0, %2, r0	\n"
3758c2ecf20Sopenharmony_ci				"andn	%1, %0, %3	\n"
3768c2ecf20Sopenharmony_ci				"or	%1, %1, %4	\n"
3778c2ecf20Sopenharmony_ci				"sw	%1, %2, r0	\n"
3788c2ecf20Sopenharmony_ci			: "=&r" (old), "=&r" (tmp)
3798c2ecf20Sopenharmony_ci			: "r" ((unsigned long)(p + 1) - 4), "r" (clr), "r" (set)
3808c2ecf20Sopenharmony_ci			: "cc");
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	raw_local_irq_restore(flags);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	return old;
3858c2ecf20Sopenharmony_ci}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci/*
3888c2ecf20Sopenharmony_ci * set_pte stores a linux PTE into the linux page table.
3898c2ecf20Sopenharmony_ci */
3908c2ecf20Sopenharmony_cistatic inline void set_pte(struct mm_struct *mm, unsigned long addr,
3918c2ecf20Sopenharmony_ci		pte_t *ptep, pte_t pte)
3928c2ecf20Sopenharmony_ci{
3938c2ecf20Sopenharmony_ci	*ptep = pte;
3948c2ecf20Sopenharmony_ci}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_cistatic inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
3978c2ecf20Sopenharmony_ci		pte_t *ptep, pte_t pte)
3988c2ecf20Sopenharmony_ci{
3998c2ecf20Sopenharmony_ci	*ptep = pte;
4008c2ecf20Sopenharmony_ci}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
4038c2ecf20Sopenharmony_cistatic inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
4048c2ecf20Sopenharmony_ci		unsigned long address, pte_t *ptep)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	return (pte_update(ptep, _PAGE_ACCESSED, 0) & _PAGE_ACCESSED) != 0;
4078c2ecf20Sopenharmony_ci}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_cistatic inline int ptep_test_and_clear_dirty(struct mm_struct *mm,
4108c2ecf20Sopenharmony_ci		unsigned long addr, pte_t *ptep)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	return (pte_update(ptep, \
4138c2ecf20Sopenharmony_ci		(_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
4178c2ecf20Sopenharmony_cistatic inline pte_t ptep_get_and_clear(struct mm_struct *mm,
4188c2ecf20Sopenharmony_ci		unsigned long addr, pte_t *ptep)
4198c2ecf20Sopenharmony_ci{
4208c2ecf20Sopenharmony_ci	return __pte(pte_update(ptep, ~_PAGE_HASHPTE, 0));
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci/*static inline void ptep_set_wrprotect(struct mm_struct *mm,
4248c2ecf20Sopenharmony_ci		unsigned long addr, pte_t *ptep)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), 0);
4278c2ecf20Sopenharmony_ci}*/
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_cistatic inline void ptep_mkdirty(struct mm_struct *mm,
4308c2ecf20Sopenharmony_ci		unsigned long addr, pte_t *ptep)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	pte_update(ptep, 0, _PAGE_DIRTY);
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci/*#define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)*/
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci/* Convert pmd entry to page */
4388c2ecf20Sopenharmony_ci/* our pmd entry is an effective address of pte table*/
4398c2ecf20Sopenharmony_ci/* returns effective address of the pmd entry*/
4408c2ecf20Sopenharmony_cistatic inline unsigned long pmd_page_vaddr(pmd_t pmd)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	return ((unsigned long) (pmd_val(pmd) & PAGE_MASK));
4438c2ecf20Sopenharmony_ci}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci/* returns struct *page of the pmd entry*/
4468c2ecf20Sopenharmony_ci#define pmd_page(pmd)	(pfn_to_page(__pa(pmd_val(pmd)) >> PAGE_SHIFT))
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci/* Find an entry in the third-level page table.. */
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ciextern pgd_t swapper_pg_dir[PTRS_PER_PGD];
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci/*
4538c2ecf20Sopenharmony_ci * Encode and decode a swap entry.
4548c2ecf20Sopenharmony_ci * Note that the bits we use in a PTE for representing a swap entry
4558c2ecf20Sopenharmony_ci * must not include the _PAGE_PRESENT bit, or the _PAGE_HASHPTE bit
4568c2ecf20Sopenharmony_ci * (if used).  -- paulus
4578c2ecf20Sopenharmony_ci */
4588c2ecf20Sopenharmony_ci#define __swp_type(entry)		((entry).val & 0x3f)
4598c2ecf20Sopenharmony_ci#define __swp_offset(entry)	((entry).val >> 6)
4608c2ecf20Sopenharmony_ci#define __swp_entry(type, offset) \
4618c2ecf20Sopenharmony_ci		((swp_entry_t) { (type) | ((offset) << 6) })
4628c2ecf20Sopenharmony_ci#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) >> 2 })
4638c2ecf20Sopenharmony_ci#define __swp_entry_to_pte(x)	((pte_t) { (x).val << 2 })
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ciextern unsigned long iopa(unsigned long addr);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci/* Values for nocacheflag and cmode */
4688c2ecf20Sopenharmony_ci/* These are not used by the APUS kernel_map, but prevents
4698c2ecf20Sopenharmony_ci * compilation errors.
4708c2ecf20Sopenharmony_ci */
4718c2ecf20Sopenharmony_ci#define	IOMAP_FULL_CACHING	0
4728c2ecf20Sopenharmony_ci#define	IOMAP_NOCACHE_SER	1
4738c2ecf20Sopenharmony_ci#define	IOMAP_NOCACHE_NONSER	2
4748c2ecf20Sopenharmony_ci#define	IOMAP_NO_COPYBACK	3
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
4778c2ecf20Sopenharmony_ci#define kern_addr_valid(addr)	(1)
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_civoid do_page_fault(struct pt_regs *regs, unsigned long address,
4808c2ecf20Sopenharmony_ci		   unsigned long error_code);
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_civoid mapin_ram(void);
4838c2ecf20Sopenharmony_ciint map_page(unsigned long va, phys_addr_t pa, int flags);
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ciextern int mem_init_done;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ciasmlinkage void __init mmu_init(void);
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_civoid __init *early_get_page(void);
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
4928c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci#endif /* CONFIG_MMU */
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
4978c2ecf20Sopenharmony_ciextern unsigned long ioremap_bot, ioremap_base;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_civoid setup_memory(void);
5008c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci#endif /* _ASM_MICROBLAZE_PGTABLE_H */
503