home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / include / asm-sparc / pgtable.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-01  |  12.0 KB  |  343 lines

  1. #ifndef _SPARC_PGTABLE_H
  2. #define _SPARC_PGTABLE_H
  3.  
  4. /*  asm-sparc/pgtable.h:  Defines and functions used to work
  5.  *                        with Sparc page tables.
  6.  *
  7.  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  8.  */
  9.  
  10. /* PMD_SHIFT determines the size of the area a second-level page table can map */
  11. #define PMD_SHIFT       18
  12. #define PMD_SIZE        (1UL << PMD_SHIFT)
  13. #define PMD_MASK        (~(PMD_SIZE-1))
  14.  
  15. /* PGDIR_SHIFT determines what a third-level page table entry can map */
  16. #define PGDIR_SHIFT       18
  17. #define PGDIR_SIZE        (1UL << PGDIR_SHIFT)
  18. #define PGDIR_MASK        (~(PGDIR_SIZE-1))
  19. #define PGDIR_ALIGN(addr) (((addr)+PGDIR_SIZE-1)&PGDIR_MASK)
  20.  
  21. /*
  22.  * Just following the i386 lead, because it works on the Sparc sun4c
  23.  * machines.  Two-level, therefore there is no real PMD.
  24.  */
  25.  
  26. #define PTRS_PER_PTE    1024
  27. #define PTRS_PER_PMD    1
  28. #define PTRS_PER_PGD    1024
  29.  
  30. /* the no. of pointers that fit on a page: this will go away */
  31. #define PTRS_PER_PAGE   (PAGE_SIZE/sizeof(void*))
  32.  
  33. /* Just any arbitrary offset to the start of the vmalloc VM area: the
  34.  * current 8MB value just means that there will be a 8MB "hole" after the
  35.  * physical memory until the kernel virtual memory starts.  That means that
  36.  * any out-of-bounds memory accesses will hopefully be caught.
  37.  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  38.  * area for the same reason. ;)
  39.  */
  40. #define VMALLOC_OFFSET  (8*1024*1024)
  41. #define VMALLOC_START ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
  42. #define VMALLOC_VMADDR(x) (TASK_SIZE + (unsigned long)(x))
  43.  
  44. /*
  45.  * Sparc page table fields.
  46.  */
  47.  
  48. #define _PAGE_VALID     0x80000000   /* valid page */
  49. #define _PAGE_WRITE     0x40000000   /* can be written to */
  50. #define _PAGE_PRIV      0x20000000   /* bit to signify privileged page */
  51. #define _PAGE_NOCACHE   0x10000000   /* non-cacheable page */
  52. #define _PAGE_REF       0x02000000   /* Page has been accessed/referenced */
  53. #define _PAGE_DIRTY     0x01000000   /* Page has been modified, is dirty */
  54. #define _PAGE_COW       0x00800000   /* COW page, hardware ignores this bit (untested) */
  55.  
  56.  
  57. /* Sparc sun4c mmu has only a writable bit. Thus if a page is valid it can be
  58.  * read in a load, and executed as code automatically. Although, the memory fault
  59.  * hardware does make a distinction between date-read faults and insn-read faults
  60.  * which is determined by which trap happened plus magic sync/async fault register
  61.  * values which must be checked in the actual fault handler.
  62.  */
  63.  
  64. /* We want the swapper not to swap out page tables, thus dirty and writable
  65.  * so that the kernel can change the entries as needed. Also valid for
  66.  * obvious reasons.
  67.  */
  68. #define _PAGE_TABLE     (_PAGE_VALID | _PAGE_WRITE | _PAGE_DIRTY)
  69. #define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_REF | _PAGE_DIRTY)
  70.  
  71. #define PAGE_NONE       __pgprot(_PAGE_VALID | _PAGE_REF)
  72. #define PAGE_SHARED     __pgprot(_PAGE_VALID | _PAGE_WRITE | _PAGE_REF)
  73. #define PAGE_COPY       __pgprot(_PAGE_VALID | _PAGE_REF | _PAGE_COW)
  74. #define PAGE_READONLY   __pgprot(_PAGE_VALID | _PAGE_REF)
  75. #define PAGE_KERNEL     __pgprot(_PAGE_VALID | _PAGE_WRITE | _PAGE_NOCACHE | _PAGE_REF | _PAGE_PRIV)
  76. #define PAGE_INVALID    __pgprot(_PAGE_PRIV)
  77.  
  78. #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | _PAGE_REF | (x))
  79.  
  80. /* I define these like the i386 does because the check for text or data fault
  81.  * is done at trap time by the low level handler. Maybe I can set these bits
  82.  * then once determined. I leave them like this for now though.
  83.  */
  84. #define __P000  PAGE_NONE
  85. #define __P001  PAGE_READONLY
  86. #define __P010  PAGE_COPY
  87. #define __P011  PAGE_COPY
  88. #define __P100  PAGE_READONLY
  89. #define __P101  PAGE_READONLY
  90. #define __P110  PAGE_COPY
  91. #define __P111  PAGE_COPY
  92.  
  93. #define __S000    PAGE_NONE
  94. #define __S001    PAGE_READONLY
  95. #define __S010    PAGE_SHARED
  96. #define __S011    PAGE_SHARED
  97. #define __S100    PAGE_READONLY
  98. #define __S101    PAGE_READONLY
  99. #define __S110    PAGE_SHARED
  100. #define __S111    PAGE_SHARED
  101.  
  102.  
  103. extern unsigned long pg0[1024];
  104.  
  105. /*
  106.  * BAD_PAGETABLE is used when we need a bogus page-table, while
  107.  * BAD_PAGE is used for a bogus page.
  108.  *
  109.  * ZERO_PAGE is a global shared page that is always zero: used
  110.  * for zero-mapped memory areas etc..
  111.  */
  112. extern pte_t __bad_page(void);
  113. extern pte_t * __bad_pagetable(void);
  114.  
  115. extern unsigned long __zero_page(void);
  116.  
  117.  
  118. #define BAD_PAGETABLE __bad_pagetable()
  119. #define BAD_PAGE __bad_page()
  120. #define ZERO_PAGE __zero_page()
  121.  
  122. /* number of bits that fit into a memory pointer */
  123. #define BITS_PER_PTR      (8*sizeof(unsigned long))   /* better check this stuff */
  124.  
  125. /* to align the pointer to a pointer address */
  126. #define PTR_MASK          (~(sizeof(void*)-1))
  127.  
  128.  
  129. #define SIZEOF_PTR_LOG2   2
  130.  
  131.  
  132. /* to set the page-dir
  133.  *
  134.  * On the Sparc the page segments hold 64 pte's which means 256k/segment.
  135.  * Therefore there is no global idea of 'the' page directory, although we
  136.  * make a virtual one in kernel memory so that we can keep the stats on
  137.  * all the pages since not all can be loaded at once in the mmu.
  138.  */
  139.  
  140. #define SET_PAGE_DIR(tsk,pgdir)
  141.  
  142. /* to find an entry in a page-table */
  143. #define PAGE_PTR(address) \
  144. ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
  145.  
  146. extern unsigned long high_memory;
  147.  
  148. extern inline int pte_none(pte_t pte)        { return !pte_val(pte); }
  149. extern inline int pte_present(pte_t pte)    { return pte_val(pte) & _PAGE_VALID; }
  150. extern inline int pte_inuse(pte_t *ptep)        { return mem_map[MAP_NR(ptep)] > 1; }
  151. extern inline void pte_clear(pte_t *ptep)    { pte_val(*ptep) = 0; }
  152. extern inline void pte_reuse(pte_t *ptep)
  153. {
  154.   if(!(mem_map[MAP_NR(ptep)] & MAP_PAGE_RESERVED))
  155.     mem_map[MAP_NR(ptep)]++;
  156. }
  157.  
  158. extern inline int pmd_none(pmd_t pmd)        { return !pmd_val(pmd); }
  159. extern inline int pmd_bad(pmd_t pmd)        { return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE || pmd_val(pmd) > high_memory; }
  160. extern inline int pmd_present(pmd_t pmd)    { return pmd_val(pmd) & _PAGE_VALID; }
  161. extern inline int pmd_inuse(pmd_t *pmdp)        { return 0; }
  162. extern inline void pmd_clear(pmd_t *pmdp)    { pmd_val(*pmdp) = 0; }
  163. extern inline void pmd_reuse(pmd_t * pmdp)      { }
  164.  
  165. extern inline int pgd_none(pgd_t pgd)        { return !pgd_val(pgd); }
  166. extern inline int pgd_bad(pgd_t pgd)        { return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; }
  167. extern inline int pgd_present(pgd_t pgd)    { return pgd_val(pgd) & _PAGE_VALID; }
  168. extern inline int pgd_inuse(pgd_t *pgdp)        { return mem_map[MAP_NR(pgdp)] > 1; }
  169. extern inline void pgd_clear(pgd_t * pgdp)    { pgd_val(*pgdp) = 0; }
  170. extern inline void pgd_reuse(pgd_t *pgdp)
  171. {
  172.   if (!(mem_map[MAP_NR(pgdp)] & MAP_PAGE_RESERVED))
  173.     mem_map[MAP_NR(pgdp)]++;
  174. }
  175.  
  176. /*
  177.  * The following only work if pte_present() is true.
  178.  * Undefined behaviour if not..
  179.  */
  180. extern inline int pte_read(pte_t pte)        { return pte_val(pte) & _PAGE_VALID; }
  181. extern inline int pte_write(pte_t pte)        { return pte_val(pte) & _PAGE_WRITE; }
  182. extern inline int pte_exec(pte_t pte)        { return pte_val(pte) & _PAGE_VALID; }
  183. extern inline int pte_dirty(pte_t pte)        { return pte_val(pte) & _PAGE_REF; }
  184. extern inline int pte_young(pte_t pte)        { return pte_val(pte) & _PAGE_REF; }
  185. extern inline int pte_cow(pte_t pte)        { return pte_val(pte) & _PAGE_COW; }
  186.  
  187. extern inline pte_t pte_wrprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_WRITE; return pte; }
  188. extern inline pte_t pte_rdprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_VALID; return pte; }
  189. extern inline pte_t pte_exprotect(pte_t pte)    { pte_val(pte) &= ~_PAGE_VALID; return pte; }
  190. extern inline pte_t pte_mkclean(pte_t pte)    { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
  191. extern inline pte_t pte_mkold(pte_t pte)    { pte_val(pte) &= ~_PAGE_REF; return pte; }
  192. extern inline pte_t pte_uncow(pte_t pte)    { pte_val(pte) &= ~_PAGE_COW; return pte; }
  193. extern inline pte_t pte_mkwrite(pte_t pte)    { pte_val(pte) |= _PAGE_WRITE; return pte; }
  194. extern inline pte_t pte_mkread(pte_t pte)    { pte_val(pte) |= _PAGE_VALID; return pte; }
  195. extern inline pte_t pte_mkexec(pte_t pte)    { pte_val(pte) |= _PAGE_VALID; return pte; }
  196. extern inline pte_t pte_mkdirty(pte_t pte)    { pte_val(pte) |= _PAGE_DIRTY; return pte; }
  197. extern inline pte_t pte_mkyoung(pte_t pte)    { pte_val(pte) |= _PAGE_REF; return pte; }
  198. extern inline pte_t pte_mkcow(pte_t pte)    { pte_val(pte) |= _PAGE_COW; return pte; }
  199.  
  200. /*
  201.  * Conversion functions: convert a page and protection to a page entry,
  202.  * and a page entry and page directory to the page they refer to.
  203.  */
  204. extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
  205. { pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; }
  206.  
  207. extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
  208. { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
  209.  
  210. extern inline unsigned long pte_page(pte_t pte)    { return pte_val(pte) & PAGE_MASK; }
  211.  
  212. extern inline unsigned long pmd_page(pmd_t pmd) { return pmd_val(pmd) & PAGE_MASK; }
  213.  
  214. extern inline unsigned long pgd_page(pgd_t pgd)    { return pgd_val(pgd) & PAGE_MASK; }
  215.  
  216. extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep)
  217. { pgd_val(*pgdp) = _PAGE_TABLE | (unsigned long) ptep; }
  218.  
  219. /* to find an entry in a page-table-directory */
  220. #define PAGE_DIR_OFFSET(tsk,address) \
  221. ((((unsigned long)(address)) >> 22) + (pgd_t *) (tsk)->tss.cr3)
  222.  
  223. /* to find an entry in a page-table-directory */
  224. extern inline pgd_t * pgd_offset(struct task_struct * tsk, unsigned long address)
  225. {
  226.     return (pgd_t *) tsk->tss.cr3 + (address >> PGDIR_SHIFT);
  227. }
  228.  
  229. /* Find an entry in the second-level page table.. */
  230. extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
  231. {
  232.     return (pmd_t *) dir;
  233. }
  234.  
  235. /* Find an entry in the third-level page table.. */ 
  236. extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
  237. {
  238.     return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
  239. }
  240.  
  241.  
  242. /*
  243.  * Allocate and free page tables. The xxx_kernel() versions are
  244.  * used to allocate a kernel page table - this turns on ASN bits
  245.  * if any, and marks the page tables reserved.
  246.  */
  247. extern inline void pte_free_kernel(pte_t * pte)
  248. {
  249.     mem_map[MAP_NR(pte)] = 1;
  250.     free_page((unsigned long) pte);
  251. }
  252.  
  253. extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
  254. {
  255.     address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
  256.     if (pmd_none(*pmd)) {
  257.         pte_t * page = (pte_t *) get_free_page(GFP_KERNEL);
  258.         if (pmd_none(*pmd)) {
  259.             if (page) {
  260.                 pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) page;
  261.                 mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED;
  262.                 return page + address;
  263.             }
  264.             pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE;
  265.             return NULL;
  266.         }
  267.         free_page((unsigned long) page);
  268.     }
  269.     if (pmd_bad(*pmd)) {
  270.         printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
  271.         pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE;
  272.         return NULL;
  273.     }
  274.     return (pte_t *) pmd_page(*pmd) + address;
  275. }
  276.  
  277. /*
  278.  * allocating and freeing a pmd is trivial: the 1-entry pmd is
  279.  * inside the pgd, so has no extra memory associated with it.
  280.  */
  281. extern inline void pmd_free_kernel(pmd_t * pmd)
  282. {
  283. }
  284.  
  285. extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
  286. {
  287.     return (pmd_t *) pgd;
  288. }
  289.  
  290. extern inline void pte_free(pte_t * pte)
  291. {
  292.     free_page((unsigned long) pte);
  293. }
  294.  
  295. extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
  296. {
  297.     address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
  298.     if (pmd_none(*pmd)) {
  299.         pte_t * page = (pte_t *) get_free_page(GFP_KERNEL);
  300.         if (pmd_none(*pmd)) {
  301.             if (page) {
  302.                 pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) page;
  303.                 return page + address;
  304.             }
  305.             pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE;
  306.             return NULL;
  307.         }
  308.         free_page((unsigned long) page);
  309.     }
  310.     if (pmd_bad(*pmd)) {
  311.         printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
  312.         pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE;
  313.         return NULL;
  314.     }
  315.     return (pte_t *) pmd_page(*pmd) + address;
  316. }
  317.  
  318. /*
  319.  * allocating and freeing a pmd is trivial: the 1-entry pmd is
  320.  * inside the pgd, so has no extra memory associated with it.
  321.  */
  322. extern inline void pmd_free(pmd_t * pmd)
  323. {
  324. }
  325.  
  326. extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
  327. {
  328.     return (pmd_t *) pgd;
  329. }
  330.  
  331. extern inline void pgd_free(pgd_t *pgd)
  332. {
  333.   free_page((unsigned long) pgd);
  334. }
  335. extern inline pgd_t *pgd_alloc(void)
  336. {
  337.   return (pgd_t *) get_free_page(GFP_KERNEL);
  338. }
  339.  
  340. extern pgd_t swapper_pg_dir[1024];
  341.  
  342. #endif /* !(_SPARC_PGTABLE_H) */
  343.