root/include/asm-sparc/pgtable.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. alloc_mmu_ctx
  2. alloc_sun4c_pseg
  3. age_sun4c_psegs
  4. update_mmu_cache

   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 #include <linux/mm.h>
  11 #include <asm/asi.h>
  12 #include <asm/pgtsun4c.h>
  13 #include <asm/pgtsrmmu.h>
  14 
  15 extern void load_mmu(void);
  16 
  17 extern unsigned int pmd_shift;
  18 extern unsigned int pmd_size;
  19 extern unsigned int pmd_mask;
  20 extern unsigned int (*pmd_align)(unsigned int);
  21 
  22 extern unsigned int pgdir_shift;
  23 extern unsigned int pgdir_size;
  24 extern unsigned int pgdir_mask;
  25 extern unsigned int (*pgdir_align)(unsigned int);
  26 
  27 extern unsigned int ptrs_per_pte;
  28 extern unsigned int ptrs_per_pmd;
  29 extern unsigned int ptrs_per_pgd;
  30 
  31 extern unsigned int ptrs_per_page;
  32 
  33 extern unsigned long (*(vmalloc_start))(void);
  34 
  35 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
  36 #define VMALLOC_START vmalloc_start()
  37 
  38 extern pgprot_t page_none;
  39 extern pgprot_t page_shared;
  40 extern pgprot_t page_copy;
  41 extern pgprot_t page_readonly;
  42 extern pgprot_t page_kernel;
  43 extern pgprot_t page_invalid;
  44 
  45 #define PMD_SHIFT      (pmd_shift)
  46 #define PMD_SIZE       (pmd_size)
  47 #define PMD_MASK       (pmd_mask)
  48 #define PMD_ALIGN      (pmd_align)
  49 #define PGDIR_SHIFT    (pgdir_shift)
  50 #define PGDIR_SIZE     (pgdir_size)
  51 #define PGDIR_MASK     (pgdir_mask)
  52 #define PGDIR_ALIGN    (pgdir_align)
  53 #define PTRS_PER_PTE   (ptrs_per_pte)
  54 #define PTRS_PER_PMD   (ptrs_per_pmd)
  55 #define PTRS_PER_PGD   (ptrs_per_pgd)
  56 
  57 #define PAGE_NONE      (page_none)
  58 #define PAGE_SHARED    (page_shared)
  59 #define PAGE_COPY      (page_copy)
  60 #define PAGE_READONLY  (page_readonly)
  61 #define PAGE_KERNEL    (page_kernel)
  62 #define PAGE_INVALID   (page_invalid)
  63 
  64 /* Top-level page directory */
  65 extern pgd_t swapper_pg_dir[1024];
  66 
  67 /* Page table for 0-4MB for everybody, on the Sparc this
  68  * holds the same as on the i386.
  69  */
  70 extern unsigned long pg0[1024];
  71 
  72 extern unsigned long ptr_in_current_pgd;
  73 
  74 /* the no. of pointers that fit on a page: this will go away */
  75 #define PTRS_PER_PAGE   (PAGE_SIZE/sizeof(void*))
  76 
  77 /* I define these like the i386 does because the check for text or data fault
  78  * is done at trap time by the low level handler. Maybe I can set these bits
  79  * then once determined. I leave them like this for now though.
  80  */
  81 #define __P000  PAGE_NONE
  82 #define __P001  PAGE_READONLY
  83 #define __P010  PAGE_COPY
  84 #define __P011  PAGE_COPY
  85 #define __P100  PAGE_READONLY
  86 #define __P101  PAGE_READONLY
  87 #define __P110  PAGE_COPY
  88 #define __P111  PAGE_COPY
  89 
  90 #define __S000  PAGE_NONE
  91 #define __S001  PAGE_READONLY
  92 #define __S010  PAGE_SHARED
  93 #define __S011  PAGE_SHARED
  94 #define __S100  PAGE_READONLY
  95 #define __S101  PAGE_READONLY
  96 #define __S110  PAGE_SHARED
  97 #define __S111  PAGE_SHARED
  98 
  99 /* Contexts on the Sparc. */
 100 #define MAX_CTXS 256
 101 #define NO_CTX   0xffff     /* In tss.context means task has no context currently */
 102 extern struct task_struct * ctx_tasks[MAX_CTXS];
 103 extern int ctx_tasks_last_frd;
 104 
 105 extern int num_contexts;
 106 
 107 /* This routine allocates a new context.  And 'p' must not be 'current'! */
 108 extern inline int alloc_mmu_ctx(struct task_struct *p)
     /* [previous][next][first][last][top][bottom][index][help] */
 109 {
 110         int i;
 111 
 112         for(i=0; i<num_contexts; i++)
 113                 if(ctx_tasks[i] == NULL) break;
 114 
 115         if(i<num_contexts) {
 116                 p->tss.context = i;
 117                 ctx_tasks[i] = p;
 118                 return i;
 119         }
 120 
 121         /* Have to free one up */
 122         ctx_tasks_last_frd++;
 123         if(ctx_tasks_last_frd >= num_contexts) ctx_tasks_last_frd=0;
 124         /* Right here is where we invalidate the user mappings that were
 125          * present.  TODO
 126          */
 127         ctx_tasks[ctx_tasks_last_frd]->tss.context = NO_CTX;
 128         ctx_tasks[ctx_tasks_last_frd] = p;
 129         p->tss.context = ctx_tasks_last_frd;
 130         return ctx_tasks_last_frd;
 131 }
 132 
 133 /*
 134  * BAD_PAGETABLE is used when we need a bogus page-table, while
 135  * BAD_PAGE is used for a bogus page.
 136  *
 137  * ZERO_PAGE is a global shared page that is always zero: used
 138  * for zero-mapped memory areas etc..
 139  */
 140 extern pte_t __bad_page(void);
 141 extern pte_t * __bad_pagetable(void);
 142 
 143 extern unsigned long __zero_page(void);
 144 
 145 
 146 #define BAD_PAGETABLE __bad_pagetable()
 147 #define BAD_PAGE __bad_page()
 148 #define ZERO_PAGE __zero_page()
 149 
 150 /* number of bits that fit into a memory pointer */
 151 #define BITS_PER_PTR      (8*sizeof(unsigned long))
 152 
 153 /* to align the pointer to a pointer address */
 154 #define PTR_MASK          (~(sizeof(void*)-1))
 155 
 156 
 157 #define SIZEOF_PTR_LOG2   2
 158 
 159 extern unsigned long (*pte_page)(pte_t);
 160 extern unsigned long (*pmd_page)(pmd_t);
 161 extern unsigned long (*pgd_page)(pgd_t);
 162 
 163 /* to set the page-dir
 164  *
 165  * On the Sparc the page segments hold 64 pte's which means 256k/segment.
 166  * Therefore there is no global idea of 'the' page directory, although we
 167  * make a virtual one in kernel memory so that we can keep the stats on
 168  * all the pages since not all can be loaded at once in the mmu.
 169  *
 170  * Actually on the SRMMU things do work exactly like the i386, the
 171  * page tables live in real physical ram, no funky TLB buisness.  But
 172  * we have to do lots of flushing. And we have to update the root level
 173  * page table pointer for this process if it has a context.
 174  */
 175 
 176 extern void (*sparc_update_rootmmu_dir)(struct task_struct *, pgd_t *pgdir);
 177 
 178 #define SET_PAGE_DIR(tsk,pgdir) \
 179 do { sparc_update_rootmmu_dir(tsk, pgdir); } while (0)
 180        
 181 /* to find an entry in a page-table */
 182 #define PAGE_PTR(address) \
 183 ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
 184 
 185 extern unsigned long high_memory;
 186 
 187 extern int (*pte_none)(pte_t);
 188 extern int (*pte_present)(pte_t);
 189 extern int (*pte_inuse)(pte_t *);
 190 extern void (*pte_clear)(pte_t *);
 191 extern void (*pte_reuse)(pte_t *);
 192 
 193 extern int (*pmd_none)(pmd_t);
 194 extern int (*pmd_bad)(pmd_t);
 195 extern int (*pmd_present)(pmd_t);
 196 extern int (*pmd_inuse)(pmd_t *);
 197 extern void (*pmd_clear)(pmd_t *);
 198 extern void (*pmd_reuse)(pmd_t *);
 199 
 200 extern int (*pgd_none)(pgd_t);
 201 extern int (*pgd_bad)(pgd_t);
 202 extern int (*pgd_present)(pgd_t);
 203 extern int (*pgd_inuse)(pgd_t *);
 204 extern void (*pgd_clear)(pgd_t *);
 205 extern void (*pgd_reuse)(pgd_t *);
 206 
 207 /*
 208  * The following only work if pte_present() is true.
 209  * Undefined behaviour if not..
 210  */
 211 extern int (*pte_read)(pte_t);
 212 extern int (*pte_write)(pte_t);
 213 extern int (*pte_exec)(pte_t);
 214 extern int (*pte_dirty)(pte_t);
 215 extern int (*pte_young)(pte_t);
 216 extern int (*pte_cow)(pte_t);
 217 
 218 extern pte_t (*pte_wrprotect)(pte_t);
 219 extern pte_t (*pte_rdprotect)(pte_t);
 220 extern pte_t (*pte_exprotect)(pte_t);
 221 extern pte_t (*pte_mkclean)(pte_t);
 222 extern pte_t (*pte_mkold)(pte_t);
 223 extern pte_t (*pte_uncow)(pte_t);
 224 extern pte_t (*pte_mkwrite)(pte_t);
 225 extern pte_t (*pte_mkread)(pte_t);
 226 extern pte_t (*pte_mkexec)(pte_t);
 227 extern pte_t (*pte_mkdirty)(pte_t);
 228 extern pte_t (*pte_mkyoung)(pte_t);
 229 extern pte_t (*pte_mkcow)(pte_t);
 230 
 231 /*
 232  * Conversion functions: convert a page and protection to a page entry,
 233  * and a page entry and page directory to the page they refer to.
 234  */
 235 extern pte_t (*mk_pte)(unsigned long, pgprot_t);
 236 
 237 extern void (*pgd_set)(pgd_t *, pte_t *);
 238 
 239 extern pte_t (*pte_modify)(pte_t, pgprot_t);
 240 
 241 /* to find an entry in a page-table-directory */
 242 extern pgd_t * (*pgd_offset)(struct task_struct *, unsigned long);
 243 
 244 /* Find an entry in the second-level page table.. */
 245 extern pmd_t * (*pmd_offset)(pgd_t *, unsigned long);
 246 
 247 /* Find an entry in the third-level page table.. */ 
 248 extern pte_t * (*pte_offset)(pmd_t *, unsigned long);
 249 
 250 /*
 251  * Allocate and free page tables. The xxx_kernel() versions are
 252  * used to allocate a kernel page table - this turns on ASN bits
 253  * if any, and marks the page tables reserved.
 254  */
 255 extern void (*pte_free_kernel)(pte_t *);
 256 
 257 extern pte_t * (*pte_alloc_kernel)(pmd_t *, unsigned long);
 258 
 259 /*
 260  * allocating and freeing a pmd is trivial: the 1-entry pmd is
 261  * inside the pgd, so has no extra memory associated with it.
 262  */
 263 extern void (*pmd_free_kernel)(pmd_t *);
 264 
 265 extern pmd_t * (*pmd_alloc_kernel)(pgd_t *, unsigned long);
 266 
 267 extern void (*pte_free)(pte_t *);
 268 
 269 extern pte_t * (*pte_alloc)(pmd_t *, unsigned long);
 270 
 271 /*
 272  * allocating and freeing a pmd is trivial: the 1-entry pmd is
 273  * inside the pgd, so has no extra memory associated with it.
 274  */
 275 extern void (*pmd_free)(pmd_t *);
 276 
 277 extern pmd_t * (*pmd_alloc)(pgd_t *, unsigned long);
 278 
 279 extern void (*pgd_free)(pgd_t *);
 280 
 281 /* A page directory on the sun4c needs 16k, thus we request an order of
 282  * two.
 283  *
 284  * I need 16k for a sun4c page table, so I use kmalloc since kmalloc_init()
 285  * is called before pgd_alloc ever is (I think).
 286  */
 287 
 288 extern pgd_t * (*pgd_alloc)(void);
 289 
 290 extern int invalid_segment;
 291 
 292 /* Sun4c specific routines.  They can stay inlined. */
 293 extern inline int alloc_sun4c_pseg(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 294 {
 295         int oldseg, i;
 296         /* First see if any are free already */
 297         for(i=0; i<PSEG_ENTRIES; i++)
 298                 if(phys_seg_map[i]==PSEG_AVL) return i;
 299 
 300         /* Uh-oh, gotta unallocate a TLB pseg */
 301         oldseg=0;
 302         for(i=0; i<PSEG_ENTRIES; i++) {
 303                 /* Can not touch PSEG_KERNEL and PSEG_RSV segmaps */
 304                 if(phys_seg_map[i]!=PSEG_USED) continue;
 305                 /* Ok, take a look at it's lifespan */
 306                 oldseg = (phys_seg_life[i]>oldseg) ? phys_seg_life[i] : oldseg;
 307         }
 308         phys_seg_life[oldseg]=PSEG_BORN;
 309         return oldseg;
 310 }
 311 
 312 /* Age all psegs except pseg_skip */
 313 extern inline void age_sun4c_psegs(int pseg_skip)
     /* [previous][next][first][last][top][bottom][index][help] */
 314 {
 315         int i;
 316 
 317         for(i=0; i<pseg_skip; i++) phys_seg_life[i]++;
 318         i++;
 319         while(i<PSEG_ENTRIES) phys_seg_life[i++]++;
 320         return;
 321 }
 322 
 323 /*
 324  * This is only ever called when the sun4c page fault routines run
 325  * so we can keep this here as the srmmu code will never get to it.
 326  */
 327 extern inline void update_mmu_cache(struct vm_area_struct * vma,
     /* [previous][next][first][last][top][bottom][index][help] */
 328         unsigned long address, pte_t pte)
 329 {
 330   unsigned long clr_addr;
 331   int segmap;
 332 
 333   segmap = (int) get_segmap(address & SUN4C_REAL_PGDIR_MASK);
 334   if(segmap == invalid_segment) {
 335     segmap = alloc_sun4c_pseg();
 336     put_segmap((address & SUN4C_REAL_PGDIR_MASK), segmap);
 337     phys_seg_map[segmap] = PSEG_USED;
 338 
 339     /* We got a segmap, clear all the pte's in it. */
 340     for(clr_addr=(address&SUN4C_REAL_PGDIR_MASK); clr_addr<((address&SUN4C_REAL_PGDIR_MASK) + SUN4C_REAL_PGDIR_SIZE); 
 341         clr_addr+=PAGE_SIZE)
 342             put_pte(clr_addr, 0);
 343   }
 344 
 345   /* Do aging */
 346   age_sun4c_psegs(segmap);
 347   put_pte((address & PAGE_MASK), pte_val(pte));
 348   return;
 349 
 350 }
 351 
 352 #endif /* !(_SPARC_PGTABLE_H) */

/* [previous][next][first][last][top][bottom][index][help] */