root/arch/sparc/mm/sun4c.c

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

DEFINITIONS

This source file includes following definitions.
  1. sun4c_flush_all
  2. sun4c_flush_context
  3. sun4c_flush_segment
  4. sun4c_flush_page
  5. sun4c_complete_all_stores
  6. sun4c_init_clean_segmap
  7. sun4c_init_clean_mmu
  8. sun4c_probe_vac
  9. sun4c_probe_mmu
  10. sun4c_init_ss2_cache_bug
  11. sun4c_init_alloc_dvma_pages
  12. sun4c_init_mmu_entry_pool
  13. fix_permissions
  14. sun4c_init_map_kernelprom
  15. sun4c_init_lock_area
  16. sun4c_init_rings
  17. add_ring
  18. remove_ring
  19. recycle_ring
  20. free_user_entry
  21. assign_user_entry
  22. free_kernel_entry
  23. assign_kernel_entry
  24. reassign_kernel_entry
  25. sun4c_init_fill_kernel_ring
  26. sun4c_init_fill_user_ring
  27. sun4c_kernel_unmap
  28. sun4c_kernel_map
  29. sun4c_user_unmap
  30. sun4c_user_map
  31. sun4c_demap_context
  32. sun4c_demap_one
  33. sun4c_user_strategy
  34. sun4c_kernel_strategy
  35. alloc_user_segment
  36. alloc_kernel_segment
  37. sun4c_update_mmu_cache
  38. sun4c_quick_kernel_fault
  39. get_task_segment
  40. free_task_segment
  41. garbage_collect
  42. sun4c_alloc_task_struct
  43. sun4c_alloc_kernel_stack
  44. sun4c_free_kernel_stack
  45. sun4c_free_task_struct
  46. sun4c_init_buckets
  47. sun4c_lockpage
  48. sun4c_unlockpage
  49. sun4c_get_scsi_buffer
  50. sun4c_release_scsi_buffer
  51. sun4c_init_lock_areas
  52. sun4c_invalidate_all
  53. sun4c_invalidate_mm
  54. sun4c_invalidate_range
  55. sun4c_invalidate_page
  56. sun4c_set_pte
  57. sun4c_mapioaddr
  58. sun4c_alloc_context
  59. sun4c_switch_heuristic
  60. sun4c_switch_to_context
  61. sun4c_flush_hook
  62. sun4c_exit_hook
  63. sun4c_test_wp
  64. sun4c_mmu_info
  65. sun4c_pmd_align
  66. sun4c_pgdir_align
  67. sun4c_vmalloc_start
  68. sun4c_pte_none
  69. sun4c_pte_present
  70. sun4c_pte_inuse
  71. sun4c_pte_clear
  72. sun4c_pte_reuse
  73. sun4c_pmd_none
  74. sun4c_pmd_bad
  75. sun4c_pmd_present
  76. sun4c_pmd_inuse
  77. sun4c_pmd_clear
  78. sun4c_pmd_reuse
  79. sun4c_pgd_none
  80. sun4c_pgd_bad
  81. sun4c_pgd_present
  82. sun4c_pgd_inuse
  83. sun4c_pgd_clear
  84. sun4c_pte_write
  85. sun4c_pte_dirty
  86. sun4c_pte_young
  87. sun4c_pte_wrprotect
  88. sun4c_pte_mkclean
  89. sun4c_pte_mkold
  90. sun4c_pte_mkwrite
  91. sun4c_pte_mkdirty
  92. sun4c_pte_mkyoung
  93. sun4c_mk_pte
  94. sun4c_mk_pte_io
  95. sun4c_pte_modify
  96. sun4c_pte_page
  97. sun4c_pmd_page
  98. sun4c_pgd_offset
  99. sun4c_pmd_offset
  100. sun4c_pte_offset
  101. sun4c_update_rootmmu_dir
  102. sun4c_pte_free_kernel
  103. sun4c_pte_alloc_kernel
  104. sun4c_pmd_free_kernel
  105. sun4c_pmd_alloc_kernel
  106. sun4c_pte_free
  107. sun4c_pte_alloc
  108. sun4c_pmd_free
  109. sun4c_pmd_alloc
  110. sun4c_pgd_free
  111. sun4c_pgd_alloc
  112. sun4c_paging_init
  113. ld_mmu_sun4c

   1 /* sun4c.c: Doing in software what should be done in hardware.
   2  *
   3  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
   4  */
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/mm.h>
   8 
   9 #include <asm/page.h>
  10 #include <asm/pgtable.h>
  11 #include <asm/vaddrs.h>
  12 #include <asm/idprom.h>
  13 #include <asm/machines.h>
  14 #include <asm/memreg.h>
  15 #include <asm/processor.h>
  16 
  17 extern int num_segmaps, num_contexts;
  18 
  19 /* Flushing the cache. */
  20 struct sun4c_vac_props sun4c_vacinfo;
  21 static int ctxflushes, segflushes, pageflushes;
  22 
  23 /* Invalidate every sun4c cache line tag. */
  24 void sun4c_flush_all(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  25 {
  26         unsigned long begin, end;
  27 
  28         if(sun4c_vacinfo.on)
  29                 panic("SUN4C: AIEEE, trying to invalidate vac while"
  30                       " it is on.");
  31 
  32         /* Clear 'valid' bit in all cache line tags */
  33         begin = AC_CACHETAGS;
  34         end = (AC_CACHETAGS + sun4c_vacinfo.num_bytes);
  35         while(begin < end) {
  36                 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
  37                                      "r" (begin), "i" (ASI_CONTROL));
  38                 begin += sun4c_vacinfo.linesize;
  39         }
  40 }
  41 
  42 /* Blow the entire current context out of the virtual cache. */
  43 /* static */ inline void sun4c_flush_context(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  44 {
  45         unsigned long vaddr;
  46 
  47         ctxflushes++;
  48         if(sun4c_vacinfo.do_hwflushes) {
  49                 for(vaddr=0; vaddr < sun4c_vacinfo.num_bytes; vaddr+=PAGE_SIZE)
  50                         __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
  51                                              "r" (vaddr), "i" (ASI_HWFLUSHCONTEXT));
  52         } else {
  53                 int incr = sun4c_vacinfo.linesize;
  54                 for(vaddr=0; vaddr < sun4c_vacinfo.num_bytes; vaddr+=incr)
  55                         __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
  56                                              "r" (vaddr), "i" (ASI_FLUSHCTX));
  57         }
  58 }
  59 
  60 /* Scrape the segment starting at ADDR from the virtual cache. */
  61 static inline void sun4c_flush_segment(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63         unsigned long end;
  64 
  65         segflushes++;
  66         addr &= SUN4C_REAL_PGDIR_MASK;
  67         end = (addr + sun4c_vacinfo.num_bytes);
  68         if(sun4c_vacinfo.do_hwflushes) {
  69                 for( ; addr < end; addr += PAGE_SIZE)
  70                         __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
  71                                              "r" (addr), "i" (ASI_HWFLUSHSEG));
  72         } else {
  73                 int incr = sun4c_vacinfo.linesize;
  74                 for( ; addr < end; addr += incr)
  75                         __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
  76                                              "r" (addr), "i" (ASI_FLUSHSEG));
  77         }
  78 }
  79 
  80 /* Bolix one page from the virtual cache. */
  81 static inline void sun4c_flush_page(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         addr &= PAGE_MASK;
  84 
  85         pageflushes++;
  86         if(sun4c_vacinfo.do_hwflushes) {
  87                 __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
  88                                      "r" (addr), "i" (ASI_HWFLUSHPAGE));
  89         } else {
  90                 unsigned long end = addr + PAGE_SIZE;
  91                 int incr = sun4c_vacinfo.linesize;
  92 
  93                 for( ; addr < end; addr += incr)
  94                         __asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
  95                                              "r" (addr), "i" (ASI_FLUSHPG));
  96         }
  97 }
  98 
  99 /* The sun4c's do have an on chip store buffer.  And the way you
 100  * clear them out isn't so obvious.  The only way I can think of
 101  * to accomplish this is to read the current context register,
 102  * store the same value there, then do a bunch of nops for the
 103  * pipeline to clear itself completely.  This is only used for
 104  * dealing with memory errors, so it is not that critical.
 105  */
 106 void sun4c_complete_all_stores(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108         volatile int _unused;
 109 
 110         _unused = sun4c_get_context();
 111         sun4c_set_context(_unused);
 112         nop(); nop(); nop(); nop();
 113         nop(); nop(); nop(); nop();
 114         /* Is that enough? */
 115 }
 116 
 117 /* Bootup utility functions. */
 118 static inline void sun4c_init_clean_segmap(unsigned char pseg)
     /* [previous][next][first][last][top][bottom][index][help] */
 119 {
 120         unsigned long vaddr;
 121 
 122         sun4c_put_segmap(0, pseg);
 123         for(vaddr = 0; vaddr < SUN4C_REAL_PGDIR_SIZE; vaddr+=PAGE_SIZE)
 124                 sun4c_put_pte(vaddr, 0);
 125         sun4c_put_segmap(0, invalid_segment);
 126 }
 127 
 128 static inline void sun4c_init_clean_mmu(unsigned long kernel_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130         unsigned long vaddr;
 131         unsigned char savectx, ctx;
 132 
 133         savectx = sun4c_get_context();
 134         kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
 135         for(ctx = 0; ctx < num_contexts; ctx++) {
 136                 sun4c_set_context(ctx);
 137                 for(vaddr = 0; vaddr < 0x20000000; vaddr += SUN4C_REAL_PGDIR_SIZE)
 138                         sun4c_put_segmap(vaddr, invalid_segment);
 139                 for(vaddr = 0xe0000000; vaddr < KERNBASE; vaddr += SUN4C_REAL_PGDIR_SIZE)
 140                         sun4c_put_segmap(vaddr, invalid_segment);
 141                 for(vaddr = kernel_end; vaddr < KADB_DEBUGGER_BEGVM; vaddr += SUN4C_REAL_PGDIR_SIZE)
 142                         sun4c_put_segmap(vaddr, invalid_segment);
 143                 for(vaddr = LINUX_OPPROM_ENDVM; vaddr; vaddr += SUN4C_REAL_PGDIR_SIZE)
 144                         sun4c_put_segmap(vaddr, invalid_segment);
 145         }
 146         sun4c_set_context(ctx);
 147 }
 148 
 149 void sun4c_probe_vac(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         int propval;
 152 
 153         sun4c_disable_vac();
 154         sun4c_vacinfo.num_bytes = prom_getintdefault(prom_root_node,
 155                                                      "vac-size", 65536);
 156         sun4c_vacinfo.linesize = prom_getintdefault(prom_root_node,
 157                                                     "vac-linesize", 16);
 158         sun4c_vacinfo.num_lines =
 159                 (sun4c_vacinfo.num_bytes / sun4c_vacinfo.linesize);
 160         switch(sun4c_vacinfo.linesize) {
 161         case 16:
 162                 sun4c_vacinfo.log2lsize = 4;
 163                 break;
 164         case 32:
 165                 sun4c_vacinfo.log2lsize = 5;
 166                 break;
 167         default:
 168                 prom_printf("probe_vac: Didn't expect vac-linesize of %d, halting\n",
 169                             sun4c_vacinfo.linesize);
 170                 prom_halt();
 171         };
 172 
 173         propval = prom_getintdefault(prom_root_node, "vac_hwflush", -1);
 174         sun4c_vacinfo.do_hwflushes = (propval == -1 ?
 175                                       prom_getintdefault(prom_root_node,
 176                                                          "vac-hwflush", 0) :
 177                                       propval);
 178 
 179         if(sun4c_vacinfo.num_bytes != 65536) {
 180                 prom_printf("WEIRD Sun4C VAC cache size, tell davem");
 181                 prom_halt();
 182         }
 183 
 184         sun4c_flush_all();
 185         sun4c_enable_vac();
 186 }
 187 
 188 static void sun4c_probe_mmu(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190         num_segmaps = prom_getintdefault(prom_root_node, "mmu-npmg", 128);
 191         num_contexts = prom_getintdefault(prom_root_node, "mmu-nctx", 0x8);
 192 }
 193 
 194 static inline void sun4c_init_ss2_cache_bug(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 195 {
 196         extern unsigned long start;
 197 
 198         if(idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) {
 199                 /* Whee.. */
 200                 printk("SS2 cache bug detected, uncaching trap table page\n");
 201                 sun4c_flush_page((unsigned int) &start);
 202                 sun4c_put_pte(((unsigned long) &start),
 203                         (sun4c_get_pte((unsigned long) &start) | _SUN4C_PAGE_NOCACHE));
 204         }
 205 }
 206 
 207 static inline unsigned long sun4c_init_alloc_dvma_pages(unsigned long start_mem)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209         unsigned long addr, pte;
 210 
 211         for(addr = DVMA_VADDR; addr < DVMA_END; addr += PAGE_SIZE) {
 212                 pte = (start_mem - PAGE_OFFSET) >> PAGE_SHIFT;
 213                 pte |= (_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE | _SUN4C_PAGE_NOCACHE);
 214                 sun4c_put_pte(addr, pte);
 215                 start_mem += PAGE_SIZE;
 216         }
 217         return start_mem;
 218 }
 219 
 220 /* TLB management. */
 221 struct sun4c_mmu_entry {
 222         struct sun4c_mmu_entry *next;
 223         struct sun4c_mmu_entry *prev;
 224         unsigned long vaddr;
 225         unsigned char pseg;
 226         unsigned char locked;
 227 };
 228 static struct sun4c_mmu_entry mmu_entry_pool[256];
 229 
 230 static void sun4c_init_mmu_entry_pool(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232         int i;
 233 
 234         for(i=0; i < 256; i++) {
 235                 mmu_entry_pool[i].pseg = i;
 236                 mmu_entry_pool[i].next = 0;
 237                 mmu_entry_pool[i].prev = 0;
 238                 mmu_entry_pool[i].vaddr = 0;
 239                 mmu_entry_pool[i].locked = 0;
 240         }
 241         mmu_entry_pool[invalid_segment].locked = 1;
 242 }
 243 
 244 static inline void fix_permissions(unsigned long vaddr, unsigned long bits_on,
     /* [previous][next][first][last][top][bottom][index][help] */
 245                                    unsigned long bits_off)
 246 {
 247         unsigned long start, end;
 248 
 249         end = vaddr + SUN4C_REAL_PGDIR_SIZE;
 250         for(start = vaddr; start < end; start += PAGE_SIZE)
 251                 if(sun4c_get_pte(start) & _SUN4C_PAGE_VALID)
 252                         sun4c_put_pte(start, (sun4c_get_pte(start) | bits_on) &
 253                                       ~bits_off);
 254 }
 255 
 256 static inline void sun4c_init_map_kernelprom(unsigned long kernel_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 257 {
 258         unsigned long vaddr;
 259         unsigned char pseg, ctx;
 260 
 261         for(vaddr = KADB_DEBUGGER_BEGVM;
 262             vaddr < LINUX_OPPROM_ENDVM;
 263             vaddr += SUN4C_REAL_PGDIR_SIZE) {
 264                 pseg = sun4c_get_segmap(vaddr);
 265                 if(pseg != invalid_segment) {
 266                         mmu_entry_pool[pseg].locked = 1;
 267                         for(ctx = 0; ctx < num_contexts; ctx++)
 268                                 prom_putsegment(ctx, vaddr, pseg);
 269                         fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0);
 270                 }
 271         }
 272         for(vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) {
 273                 pseg = sun4c_get_segmap(vaddr);
 274                 mmu_entry_pool[pseg].locked = 1;
 275                 for(ctx = 0; ctx < num_contexts; ctx++)
 276                         prom_putsegment(ctx, vaddr, pseg);
 277                 fix_permissions(vaddr, _SUN4C_PAGE_PRIV, _SUN4C_PAGE_NOCACHE);
 278         }
 279 }
 280 
 281 static void sun4c_init_lock_area(unsigned long start, unsigned long end)
     /* [previous][next][first][last][top][bottom][index][help] */
 282 {
 283         int i, ctx;
 284 
 285         while(start < end) {
 286                 for(i=0; i < invalid_segment; i++)
 287                         if(!mmu_entry_pool[i].locked)
 288                                 break;
 289                 mmu_entry_pool[i].locked = 1;
 290                 sun4c_init_clean_segmap(i);
 291                 for(ctx = 0; ctx < num_contexts; ctx++)
 292                         prom_putsegment(ctx, start, mmu_entry_pool[i].pseg);
 293                 start += SUN4C_REAL_PGDIR_SIZE;
 294         }
 295 }
 296 
 297 struct sun4c_mmu_ring {
 298         struct sun4c_mmu_entry ringhd;
 299         int num_entries;
 300 };
 301 static struct sun4c_mmu_ring sun4c_context_ring[16]; /* used user entries */
 302 static struct sun4c_mmu_ring sun4c_ufree_ring;       /* free user entries */
 303 static struct sun4c_mmu_ring sun4c_kernel_ring;      /* used kernel entries */
 304 static struct sun4c_mmu_ring sun4c_kfree_ring;       /* free kernel entries */
 305 
 306 static inline void sun4c_init_rings(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308         int i;
 309         for(i=0; i<16; i++) {
 310                 sun4c_context_ring[i].ringhd.next =
 311                         sun4c_context_ring[i].ringhd.prev =
 312                         &sun4c_context_ring[i].ringhd;
 313                 sun4c_context_ring[i].num_entries = 0;
 314         }
 315         sun4c_ufree_ring.ringhd.next = sun4c_ufree_ring.ringhd.prev =
 316                 &sun4c_ufree_ring.ringhd;
 317         sun4c_kernel_ring.ringhd.next = sun4c_kernel_ring.ringhd.prev =
 318                 &sun4c_kernel_ring.ringhd;
 319         sun4c_kfree_ring.ringhd.next = sun4c_kfree_ring.ringhd.prev =
 320                 &sun4c_kfree_ring.ringhd;
 321         sun4c_ufree_ring.num_entries = sun4c_kernel_ring.num_entries =
 322                 sun4c_kfree_ring.num_entries = 0;
 323 }
 324 
 325 static inline void add_ring(struct sun4c_mmu_ring *ring, struct sun4c_mmu_entry *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 326 {
 327         struct sun4c_mmu_entry *head = &ring->ringhd;
 328 
 329         entry->prev = head;
 330         (entry->next = head->next)->prev = entry;
 331         head->next = entry;
 332         ring->num_entries++;
 333 }
 334 
 335 static inline void remove_ring(struct sun4c_mmu_ring *ring, struct sun4c_mmu_entry *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 336 {
 337         struct sun4c_mmu_entry *next = entry->next;
 338 
 339         (next->prev = entry->prev)->next = next;
 340         ring->num_entries--;
 341 }
 342 
 343 static inline void recycle_ring(struct sun4c_mmu_ring *ring, struct sun4c_mmu_entry *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 344 {
 345         struct sun4c_mmu_entry *head = &ring->ringhd;
 346         struct sun4c_mmu_entry *next = entry->next;
 347 
 348         (next->prev = entry->prev)->next = next;
 349         entry->prev = head; (entry->next = head->next)->prev = entry;
 350         head->next = entry;
 351         /* num_entries stays the same */
 352 }
 353 
 354 static inline void free_user_entry(int ctx, struct sun4c_mmu_entry *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 355 {
 356         remove_ring(sun4c_context_ring+ctx, entry);
 357         add_ring(&sun4c_ufree_ring, entry);
 358 }
 359 
 360 static inline void assign_user_entry(int ctx, struct sun4c_mmu_entry *entry) 
     /* [previous][next][first][last][top][bottom][index][help] */
 361 {
 362         remove_ring(&sun4c_ufree_ring, entry);
 363         add_ring(sun4c_context_ring+ctx, entry);
 364 }
 365 
 366 static inline void free_kernel_entry(struct sun4c_mmu_entry *entry, struct sun4c_mmu_ring *ring)
     /* [previous][next][first][last][top][bottom][index][help] */
 367 {
 368         remove_ring(ring, entry);
 369         add_ring(&sun4c_kfree_ring, entry);
 370 }
 371 
 372 static inline void assign_kernel_entry(struct sun4c_mmu_entry *entry, struct sun4c_mmu_ring *ring) 
     /* [previous][next][first][last][top][bottom][index][help] */
 373 {
 374         remove_ring(ring, entry);
 375         add_ring(&sun4c_kernel_ring, entry);
 376 }
 377 
 378 static inline void reassign_kernel_entry(struct sun4c_mmu_entry *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 379 {
 380         recycle_ring(&sun4c_kernel_ring, entry);
 381 }
 382 
 383 static void sun4c_init_fill_kernel_ring(int howmany)
     /* [previous][next][first][last][top][bottom][index][help] */
 384 {
 385         int i;
 386 
 387         while(howmany) {
 388                 for(i=0; i < invalid_segment; i++)
 389                         if(!mmu_entry_pool[i].locked)
 390                                 break;
 391                 mmu_entry_pool[i].locked = 1;
 392                 sun4c_init_clean_segmap(i);
 393                 add_ring(&sun4c_kfree_ring, &mmu_entry_pool[i]);
 394                 howmany--;
 395         }
 396 }
 397 
 398 static void sun4c_init_fill_user_ring(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400         int i;
 401 
 402         for(i=0; i < invalid_segment; i++) {
 403                 if(mmu_entry_pool[i].locked)
 404                         continue;
 405                 sun4c_init_clean_segmap(i);
 406                 add_ring(&sun4c_ufree_ring, &mmu_entry_pool[i]);
 407         }
 408 }
 409 
 410 static inline void sun4c_kernel_unmap(struct sun4c_mmu_entry *kentry)
     /* [previous][next][first][last][top][bottom][index][help] */
 411 {
 412         int savectx, ctx;
 413 
 414         savectx = sun4c_get_context();
 415         flush_user_windows();
 416         sun4c_flush_segment(kentry->vaddr);
 417         for(ctx = 0; ctx < num_contexts; ctx++) {
 418                 sun4c_set_context(ctx);
 419                 sun4c_put_segmap(kentry->vaddr, invalid_segment);
 420         }
 421         sun4c_set_context(savectx);
 422 }
 423 
 424 static inline void sun4c_kernel_map(struct sun4c_mmu_entry *kentry)
     /* [previous][next][first][last][top][bottom][index][help] */
 425 {
 426         int savectx, ctx;
 427 
 428         savectx = sun4c_get_context();
 429         flush_user_windows();
 430         for(ctx = 0; ctx < num_contexts; ctx++) {
 431                 sun4c_set_context(ctx);
 432                 sun4c_put_segmap(kentry->vaddr, kentry->pseg);
 433         }
 434         sun4c_set_context(savectx);
 435 }
 436 
 437 static inline void sun4c_user_unmap(struct sun4c_mmu_entry *uentry)
     /* [previous][next][first][last][top][bottom][index][help] */
 438 {
 439         sun4c_flush_segment(uentry->vaddr);
 440         sun4c_put_segmap(uentry->vaddr, invalid_segment);
 441 }
 442 
 443 static inline void sun4c_user_map(struct sun4c_mmu_entry *uentry)
     /* [previous][next][first][last][top][bottom][index][help] */
 444 {
 445         unsigned long start = uentry->vaddr;
 446         unsigned long end = start + SUN4C_REAL_PGDIR_SIZE;
 447 
 448         sun4c_put_segmap(uentry->vaddr, uentry->pseg);
 449         while(start < end) {
 450                 sun4c_put_pte(start, 0);
 451                 start += PAGE_SIZE;
 452         }
 453 }
 454 
 455 static inline void sun4c_demap_context(struct sun4c_mmu_ring *crp, unsigned char ctx)
     /* [previous][next][first][last][top][bottom][index][help] */
 456 {
 457         struct sun4c_mmu_entry *this_entry, *next_entry;
 458         int savectx = sun4c_get_context();
 459 
 460         this_entry = crp->ringhd.next;
 461         flush_user_windows();
 462         sun4c_set_context(ctx);
 463         while(crp->num_entries) {
 464                 next_entry = this_entry->next;
 465                 sun4c_user_unmap(this_entry);
 466                 free_user_entry(ctx, this_entry);
 467                 this_entry = next_entry;
 468         }
 469         sun4c_set_context(savectx);
 470 }
 471 
 472 static inline void sun4c_demap_one(struct sun4c_mmu_ring *crp, unsigned char ctx)
     /* [previous][next][first][last][top][bottom][index][help] */
 473 {
 474         struct sun4c_mmu_entry *entry = crp->ringhd.next;
 475         int savectx = sun4c_get_context();
 476 
 477         flush_user_windows();
 478         sun4c_set_context(ctx);
 479         sun4c_user_unmap(entry);
 480         free_user_entry(ctx, entry);
 481         sun4c_set_context(savectx);
 482 }
 483 
 484 /* Using this method to free up mmu entries eliminates a lot of
 485  * potention races since we have a kernel that incurs tlb
 486  * replacement faults.  There may be performance penalties.
 487  */
 488 static inline struct sun4c_mmu_entry *sun4c_user_strategy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 489 {
 490         struct sun4c_mmu_ring *rp = 0;
 491         unsigned char mmuhog, i, ctx = 0;
 492 
 493         /* If some are free, return first one. */
 494         if(sun4c_ufree_ring.num_entries)
 495                 return sun4c_ufree_ring.ringhd.next;
 496 
 497         /* Else free one up. */
 498         mmuhog = 0;
 499         for(i=0; i < num_contexts; i++) {
 500                 if(sun4c_context_ring[i].num_entries > mmuhog) {
 501                         rp = &sun4c_context_ring[i];
 502                         mmuhog = rp->num_entries;
 503                         ctx = i;
 504                 }
 505         }
 506         sun4c_demap_one(rp, ctx);
 507         return sun4c_ufree_ring.ringhd.next;
 508 }
 509 
 510 static inline struct sun4c_mmu_entry *sun4c_kernel_strategy(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 511 {
 512         struct sun4c_mmu_entry *this_entry;
 513 
 514         /* If some are free, return first one. */
 515         if(sun4c_kfree_ring.num_entries)
 516                 return sun4c_kfree_ring.ringhd.next;
 517 
 518         /* Else free one up. */
 519         this_entry = sun4c_kernel_ring.ringhd.prev;
 520         sun4c_kernel_unmap(this_entry);
 521         free_kernel_entry(this_entry, &sun4c_kernel_ring);
 522         return sun4c_kfree_ring.ringhd.next;
 523 }
 524 
 525 static inline void alloc_user_segment(unsigned long address, unsigned char ctx)
     /* [previous][next][first][last][top][bottom][index][help] */
 526 {
 527         struct sun4c_mmu_entry *entry;
 528 
 529         address &= SUN4C_REAL_PGDIR_MASK;
 530         entry = sun4c_user_strategy();
 531         assign_user_entry(ctx, entry);
 532         entry->vaddr = address;
 533         sun4c_user_map(entry);
 534 }
 535 
 536 static inline void alloc_kernel_segment(unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
 537 {
 538         struct sun4c_mmu_entry *entry;
 539 
 540         address &= SUN4C_REAL_PGDIR_MASK;
 541         entry = sun4c_kernel_strategy();
 542 
 543         assign_kernel_entry(entry, &sun4c_kfree_ring);
 544         entry->vaddr = address;
 545         sun4c_kernel_map(entry);
 546 }
 547 
 548 /* XXX Just like kernel tlb replacement we'd like to have a low level
 549  * XXX equivalent for user faults which need not go through the mm
 550  * XXX subsystem just to load a mmu entry.  But this might not be as
 551  * XXX feasible since we need to go through the kernel page tables
 552  * XXX for this process, which we currently don't lock into the mmu
 553  * XXX so we would fault with traps off... must think about this...
 554  */
 555 static void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
     /* [previous][next][first][last][top][bottom][index][help] */
 556 {
 557         unsigned long flags;
 558 
 559         save_flags(flags); cli();
 560         address &= PAGE_MASK;
 561         if(sun4c_get_segmap(address) == invalid_segment)
 562                 alloc_user_segment(address, sun4c_get_context());
 563         sun4c_put_pte(address, pte_val(pte));
 564         restore_flags(flags);
 565 }
 566 
 567 /* READ THIS:  If you put any diagnostic printing code in any of the kernel
 568  *             fault handling code you will lose badly.  This is the most
 569  *             delicate piece of code in the entire kernel, atomicity of
 570  *             kernel tlb replacement must be guarenteed.  This is why we
 571  *             have seperate user and kernel allocation rings to alleviate
 572  *             as many bad interactions as possible.
 573  *
 574  * XXX Someday make this into a fast in-window trap handler to avoid
 575  * XXX any and all races.  *High* priority, also for performance.
 576  */
 577 static void sun4c_quick_kernel_fault(unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
 578 {
 579         unsigned long end, flags;
 580 
 581         save_flags(flags); cli();
 582         address &= SUN4C_REAL_PGDIR_MASK;
 583         end = address + SUN4C_REAL_PGDIR_SIZE;
 584         if(sun4c_get_segmap(address) == invalid_segment)
 585                 alloc_kernel_segment(address);
 586 
 587         if(address < SUN4C_VMALLOC_START) {
 588                 unsigned long pte;
 589                 pte = (address - PAGE_OFFSET) >> PAGE_SHIFT;
 590                 pte |= pgprot_val(SUN4C_PAGE_KERNEL);
 591                 /* Stupid pte tricks... */
 592                 while(address < end) {
 593                         sun4c_put_pte(address, pte++);
 594                         address += PAGE_SIZE;
 595                 }
 596         } else {
 597                 pte_t *ptep;
 598 
 599                 ptep = (pte_t *) (PAGE_MASK & pgd_val(swapper_pg_dir[address>>SUN4C_PGDIR_SHIFT]));
 600                 ptep = (ptep + ((address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1)));
 601                 while(address < end) {
 602                         sun4c_put_pte(address, pte_val(*ptep++));
 603                         address += PAGE_SIZE;
 604                 }
 605         }
 606         restore_flags(flags);
 607 }
 608 
 609 /*
 610  * 4 page buckets for task struct and kernel stack allocation.
 611  *
 612  * TASK_STACK_BEGIN
 613  * bucket[0]
 614  * bucket[1]
 615  *   [ ... ]
 616  * bucket[NR_TASKS-1]
 617  * TASK_STACK_BEGIN + (sizeof(struct task_bucket) * NR_TASKS)
 618  *
 619  * Each slot looks like:
 620  *
 621  *  page 1   --  task struct
 622  *  page 2   --  unmapped, for stack redzone (maybe use for pgd)
 623  *  page 3/4 --  kernel stack
 624  */
 625 
 626 struct task_bucket {
 627         struct task_struct task;
 628         char _unused1[PAGE_SIZE - sizeof(struct task_struct)];
 629         char _unused2[PAGE_SIZE];
 630         char kstack[(PAGE_SIZE<<1)];
 631 };
 632 
 633 struct task_bucket *sun4c_bucket[NR_TASKS];
 634 
 635 #define BUCKET_EMPTY     ((struct task_bucket *) 0)
 636 #define BUCKET_SIZE      (PAGE_SIZE << 2)
 637 #define BUCKET_SHIFT     14        /* log2(sizeof(struct task_bucket)) */
 638 #define BUCKET_NUM(addr) ((((addr) - SUN4C_LOCK_VADDR) >> BUCKET_SHIFT))
 639 #define BUCKET_ADDR(num) (((num) << BUCKET_SHIFT) + SUN4C_LOCK_VADDR)
 640 #define BUCKET_PTE(page)       \
 641         ((((page) - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(SUN4C_PAGE_KERNEL))
 642 #define BUCKET_PTE_PAGE(pte)   \
 643         (PAGE_OFFSET + (((pte) & 0xffff) << PAGE_SHIFT))
 644 
 645 static inline void get_task_segment(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 646 {
 647         struct sun4c_mmu_entry *stolen;
 648         unsigned long flags;
 649 
 650         save_flags(flags); cli();
 651         addr &= SUN4C_REAL_PGDIR_MASK;
 652         stolen = sun4c_user_strategy();
 653         remove_ring(&sun4c_ufree_ring, stolen);
 654         stolen->vaddr = addr;
 655         sun4c_kernel_map(stolen);
 656         restore_flags(flags);
 657 }
 658 
 659 static inline void free_task_segment(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 660 {
 661         struct sun4c_mmu_entry *entry;
 662         unsigned long flags;
 663         unsigned char pseg;
 664 
 665         save_flags(flags); cli();
 666         addr &= SUN4C_REAL_PGDIR_MASK;
 667         pseg = sun4c_get_segmap(addr);
 668         entry = &mmu_entry_pool[pseg];
 669         sun4c_flush_segment(addr);
 670         sun4c_kernel_unmap(entry);
 671         add_ring(&sun4c_ufree_ring, entry);
 672         restore_flags(flags);
 673 }
 674 
 675 static inline void garbage_collect(int entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 676 {
 677         int start, end;
 678 
 679         /* 16 buckets per segment... */
 680         entry &= ~15;
 681         start = entry;
 682         for(end = (start + 16); start < end; start++)
 683                 if(sun4c_bucket[start] != BUCKET_EMPTY)
 684                         return;
 685         /* Entire segment empty, release it. */
 686         free_task_segment(BUCKET_ADDR(entry));
 687 }
 688 
 689 static struct task_struct *sun4c_alloc_task_struct(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 690 {
 691         unsigned long addr, page;
 692         int entry;
 693 
 694         page = get_free_page(GFP_KERNEL);
 695         if(!page)
 696                 return (struct task_struct *) 0;
 697         /* XXX Bahh, linear search too slow, use hash
 698          * XXX table in final implementation.  Or
 699          * XXX keep track of first free when we free
 700          * XXX a bucket... anything but this.
 701          */
 702         for(entry = 0; entry < NR_TASKS; entry++)
 703                 if(sun4c_bucket[entry] == BUCKET_EMPTY)
 704                         break;
 705         if(entry == NR_TASKS) {
 706                 free_page(page);
 707                 return (struct task_struct *) 0;
 708         }
 709         addr = BUCKET_ADDR(entry);
 710         sun4c_bucket[entry] = (struct task_bucket *) addr;
 711         if(sun4c_get_segmap(addr) == invalid_segment)
 712                 get_task_segment(addr);
 713         sun4c_put_pte(addr, BUCKET_PTE(page));
 714         return (struct task_struct *) addr;
 715 }
 716 
 717 static unsigned long sun4c_alloc_kernel_stack(struct task_struct *tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 718 {
 719         unsigned long saddr = (unsigned long) tsk;
 720         unsigned long page[2];
 721 
 722         if(!saddr)
 723                 return 0;
 724         page[0] = get_free_page(GFP_KERNEL);
 725         if(!page[0])
 726                 return 0;
 727         page[1] = get_free_page(GFP_KERNEL);
 728         if(!page[1]) {
 729                 free_page(page[0]);
 730                 return 0;
 731         }
 732         saddr += (PAGE_SIZE << 1);
 733         sun4c_put_pte(saddr - PAGE_SIZE, 0);
 734         sun4c_put_pte(saddr, BUCKET_PTE(page[0]));
 735         sun4c_put_pte(saddr + PAGE_SIZE, BUCKET_PTE(page[1]));
 736         return saddr;
 737 }
 738 
 739 static void sun4c_free_kernel_stack(unsigned long stack)
     /* [previous][next][first][last][top][bottom][index][help] */
 740 {
 741         unsigned long page[2];
 742 
 743         page[0] = BUCKET_PTE_PAGE(sun4c_get_pte(stack));
 744         page[1] = BUCKET_PTE_PAGE(sun4c_get_pte(stack+PAGE_SIZE));
 745         sun4c_flush_segment(stack & SUN4C_REAL_PGDIR_MASK);
 746         sun4c_put_pte(stack, 0);
 747         sun4c_put_pte(stack + PAGE_SIZE, 0);
 748         free_page(page[0]);
 749         free_page(page[1]);
 750 }
 751 
 752 static void sun4c_free_task_struct(struct task_struct *tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
 753 {
 754         unsigned long tsaddr = (unsigned long) tsk;
 755         unsigned long page = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr));
 756         int entry = BUCKET_NUM(tsaddr);
 757 
 758         sun4c_flush_segment(tsaddr & SUN4C_REAL_PGDIR_MASK);
 759         sun4c_put_pte(tsaddr, 0);
 760         sun4c_bucket[entry] = BUCKET_EMPTY;
 761         free_page(page);
 762         garbage_collect(entry);
 763 }
 764 
 765 static void sun4c_init_buckets(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 766 {
 767         int entry;
 768 
 769         if(sizeof(struct task_bucket) != (PAGE_SIZE << 2)) {
 770                 prom_printf("task bucket not 4 pages!\n");
 771                 prom_halt();
 772         }
 773         for(entry = 0; entry < NR_TASKS; entry++)
 774                 sun4c_bucket[entry] = BUCKET_EMPTY;
 775 }
 776 
 777 static unsigned long sun4c_iobuffer_start;
 778 static unsigned long sun4c_iobuffer_end;
 779 static unsigned long *sun4c_iobuffer_map;
 780 static int iobuffer_map_size;
 781 
 782 static char *sun4c_lockpage(char *vaddr, unsigned long _unused)
     /* [previous][next][first][last][top][bottom][index][help] */
 783 {
 784         unsigned long vpage, voffset, search, pte;
 785         unsigned long npage;
 786 
 787         vpage = ((unsigned long) vaddr) & PAGE_MASK;
 788         voffset = ((unsigned long) vaddr) & ~PAGE_MASK;
 789         pte = ((vpage-PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(SUN4C_PAGE_KERNEL);
 790         pte |= _SUN4C_PAGE_NOCACHE;
 791         search = find_first_zero_bit(sun4c_iobuffer_map, iobuffer_map_size);
 792         set_bit(search, sun4c_iobuffer_map);
 793         npage = (search << PAGE_SHIFT) + sun4c_iobuffer_start;
 794         sun4c_flush_page(vpage);
 795         sun4c_put_pte(npage, pte);
 796         return (char *) (npage + voffset);
 797 }
 798 
 799 static void sun4c_unlockpage(char *vaddr, unsigned long _unused)
     /* [previous][next][first][last][top][bottom][index][help] */
 800 {
 801         unsigned long vpage, nr;
 802 
 803         vpage = (unsigned long) vaddr;
 804         vpage &= PAGE_MASK;
 805         nr = (vpage - sun4c_iobuffer_start) >> PAGE_SHIFT;
 806         sun4c_put_pte(vpage, 0);
 807         clear_bit(nr, sun4c_iobuffer_map);
 808 }
 809 
 810 /* Note the scsi code at init time passes to here buffers
 811  * which sit on the kernel stack, those are already locked
 812  * by implication and fool the page locking code above
 813  * if passed to by mistake.
 814  */
 815 static char *sun4c_get_scsi_buffer(char *bufptr, unsigned long len, struct linux_sbus *sbus)
     /* [previous][next][first][last][top][bottom][index][help] */
 816 {
 817         unsigned long page1, page2;
 818 
 819         page1 = ((unsigned long) bufptr) & PAGE_MASK;
 820         page2 = (((unsigned long) bufptr) + len - 1) & PAGE_MASK;
 821         if(page1 != page2) {
 822                 printk("Problem, trying to lock multipage scsi buffer.\n");
 823                 printk("page1<%08lx> page2<%08lx>\n", page1, page2);
 824                 panic("Scsi buffer too big.");
 825         }
 826         if(page1 > high_memory)
 827                 return bufptr; /* already locked */
 828         return sun4c_lockpage(bufptr, PAGE_SIZE);
 829 }
 830 
 831 static void sun4c_release_scsi_buffer(char *bufptr, unsigned long len, struct linux_sbus *sbus)
     /* [previous][next][first][last][top][bottom][index][help] */
 832 {
 833         unsigned long page = (unsigned long) bufptr;
 834 
 835         if(page < sun4c_iobuffer_start)
 836                 return; /* On kernel stack or similar, see above */
 837         sun4c_unlockpage(bufptr, PAGE_SIZE);
 838 }
 839 
 840 #define TASK_ENTRY_SIZE    (3 * PAGE_SIZE)
 841 #define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
 842 
 843 struct vm_area_struct sun4c_kstack_vma;
 844 
 845 static unsigned long sun4c_init_lock_areas(unsigned long start_mem)
     /* [previous][next][first][last][top][bottom][index][help] */
 846 {
 847         unsigned long sun4c_taskstack_start;
 848         unsigned long sun4c_taskstack_end;
 849         int bitmap_size;
 850 
 851         sun4c_init_buckets();
 852         sun4c_taskstack_start = SUN4C_LOCK_VADDR;
 853         sun4c_taskstack_end = (sun4c_taskstack_start +
 854                                (TASK_ENTRY_SIZE * NR_TASKS));
 855         if(sun4c_taskstack_end >= SUN4C_LOCK_END) {
 856                 prom_printf("Too many tasks, decrease NR_TASKS please.\n");
 857                 prom_halt();
 858         }
 859 
 860         sun4c_iobuffer_start = SUN4C_REAL_PGDIR_ALIGN(sun4c_taskstack_end);
 861         sun4c_iobuffer_end = sun4c_iobuffer_start + SUN4C_REAL_PGDIR_SIZE;
 862         bitmap_size = (sun4c_iobuffer_end - sun4c_iobuffer_start) >> PAGE_SHIFT;
 863         bitmap_size = (bitmap_size + 7) >> 3;
 864         bitmap_size = LONG_ALIGN(bitmap_size);
 865         iobuffer_map_size = bitmap_size << 3;
 866         sun4c_iobuffer_map = (unsigned long *) start_mem;
 867         memset((void *) start_mem, 0, bitmap_size);
 868         start_mem += bitmap_size;
 869 
 870         /* Now get us some mmu entries for I/O maps. */
 871         sun4c_init_lock_area(sun4c_iobuffer_start, sun4c_iobuffer_end);
 872         sun4c_kstack_vma.vm_mm = init_task.mm;
 873         sun4c_kstack_vma.vm_start = sun4c_taskstack_start;
 874         sun4c_kstack_vma.vm_end = sun4c_taskstack_end;
 875         sun4c_kstack_vma.vm_page_prot = PAGE_SHARED;
 876         sun4c_kstack_vma.vm_flags = VM_READ | VM_WRITE | VM_EXEC;
 877         insert_vm_struct(&init_task, &sun4c_kstack_vma);
 878         return start_mem;
 879 }
 880 
 881 static void sun4c_invalidate_all(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 882 {
 883         struct sun4c_mmu_entry *this_entry, *next_entry;
 884 
 885         this_entry = sun4c_kernel_ring.ringhd.next;
 886         while(sun4c_kernel_ring.num_entries) {
 887                 next_entry = this_entry->next;
 888                 sun4c_kernel_unmap(this_entry);
 889                 free_kernel_entry(this_entry, &sun4c_kernel_ring);
 890                 this_entry = next_entry;
 891         }
 892 }
 893 
 894 static void sun4c_invalidate_mm(struct mm_struct *mm)
     /* [previous][next][first][last][top][bottom][index][help] */
 895 {
 896         if(mm->context == NO_CONTEXT)
 897                 return;
 898         sun4c_demap_context(&sun4c_context_ring[mm->context], mm->context);
 899 }
 900 
 901 static void sun4c_invalidate_range(struct mm_struct *mm, unsigned long start, unsigned long end)
     /* [previous][next][first][last][top][bottom][index][help] */
 902 {
 903         struct sun4c_mmu_entry *this_entry;
 904         unsigned char pseg, savectx;
 905 
 906         if(mm->context == NO_CONTEXT)
 907                 return;
 908         flush_user_windows();
 909         savectx = sun4c_get_context();
 910         sun4c_set_context(mm->context);
 911         start &= SUN4C_REAL_PGDIR_MASK;
 912         while(start < end) {
 913                 pseg = sun4c_get_segmap(start);
 914                 if(pseg == invalid_segment)
 915                         goto next_one;
 916                 this_entry = &mmu_entry_pool[pseg];
 917                 sun4c_user_unmap(this_entry);
 918                 free_user_entry(mm->context, this_entry);
 919         next_one:
 920                 start += SUN4C_REAL_PGDIR_SIZE;
 921         }
 922         sun4c_set_context(savectx);
 923 }
 924 
 925 static void sun4c_invalidate_page(struct vm_area_struct *vma, unsigned long page)
     /* [previous][next][first][last][top][bottom][index][help] */
 926 {
 927         struct mm_struct *mm = vma->vm_mm;
 928         unsigned char savectx;
 929 
 930         if(mm->context == NO_CONTEXT)
 931                 return;
 932         flush_user_windows();
 933         savectx = sun4c_get_context();
 934         sun4c_set_context(mm->context);
 935         page &= PAGE_MASK;
 936         if(sun4c_get_pte(page) & _SUN4C_PAGE_VALID) {
 937                 sun4c_flush_page(page);
 938                 sun4c_put_pte(page, 0);
 939         }
 940         sun4c_set_context(savectx);
 941 }
 942 
 943 /* Sun4c mmu hardware doesn't update the dirty bit in the pte's
 944  * for us, so we do it in software.
 945  */
 946 static void sun4c_set_pte(pte_t *ptep, pte_t pte)
     /* [previous][next][first][last][top][bottom][index][help] */
 947 {
 948 
 949         if((pte_val(pte) & (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_DIRTY)) ==
 950            _SUN4C_PAGE_WRITE)
 951                 pte_val(pte) |= _SUN4C_PAGE_DIRTY;
 952 
 953         *ptep = pte;
 954 }
 955 
 956 /* static */ void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr,
     /* [previous][next][first][last][top][bottom][index][help] */
 957                      int bus_type, int rdonly)
 958 {
 959         unsigned long page_entry;
 960 
 961         page_entry = ((physaddr >> PAGE_SHIFT) & 0xffff);
 962         page_entry |= (_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE |
 963                        _SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_IO);
 964         if(rdonly)
 965                 page_entry &= (~_SUN4C_PAGE_WRITE);
 966         sun4c_flush_page(virt_addr);
 967         sun4c_put_pte(virt_addr, page_entry);
 968 }
 969 
 970 static inline void sun4c_alloc_context(struct mm_struct *mm)
     /* [previous][next][first][last][top][bottom][index][help] */
 971 {
 972         struct ctx_list *ctxp;
 973 
 974         ctxp = ctx_free.next;
 975         if(ctxp != &ctx_free) {
 976                 remove_from_ctx_list(ctxp);
 977                 add_to_used_ctxlist(ctxp);
 978                 mm->context = ctxp->ctx_number;
 979                 ctxp->ctx_mm = mm;
 980                 return;
 981         }
 982         ctxp = ctx_used.next;
 983         if(ctxp->ctx_mm == current->mm)
 984                 ctxp = ctxp->next;
 985         if(ctxp == &ctx_used)
 986                 panic("out of mmu contexts");
 987         remove_from_ctx_list(ctxp);
 988         add_to_used_ctxlist(ctxp);
 989         ctxp->ctx_mm->context = NO_CONTEXT;
 990         ctxp->ctx_mm = mm;
 991         mm->context = ctxp->ctx_number;
 992         sun4c_demap_context(&sun4c_context_ring[ctxp->ctx_number], ctxp->ctx_number);
 993 }
 994 
 995 #if some_day_soon /* We need some tweaking to start using this */
 996 extern void force_user_fault(unsigned long, int);
 997 
 998 void sun4c_switch_heuristic(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 999 {
1000         unsigned long sp = regs->u_regs[UREG_FP];
1001         unsigned long sp2 = sp + REGWIN_SZ - 0x8;
1002 
1003         force_user_fault(regs->pc, 0);
1004         force_user_fault(sp, 0);
1005         if((sp&PAGE_MASK) != (sp2&PAGE_MASK))
1006                 force_user_fault(sp2, 0);
1007 }
1008 #endif
1009 
1010 static void sun4c_switch_to_context(struct task_struct *tsk)
     /* [previous][next][first][last][top][bottom][index][help] */
1011 {
1012         /* Kernel threads can execute in any context and so can tasks
1013          * sleeping in the middle of exiting. If this task has already
1014          * been allocated a piece of the mmu realestate, just jump to
1015          * it.
1016          */
1017         if((tsk->tss.flags & SPARC_FLAG_KTHREAD) ||
1018            (tsk->flags & PF_EXITING))
1019                 return;
1020         if(tsk->mm->context == NO_CONTEXT)
1021                 sun4c_alloc_context(tsk->mm);
1022 
1023         sun4c_set_context(tsk->mm->context);
1024 }
1025 
1026 static void sun4c_flush_hook(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1027 {
1028         if(current->tss.flags & SPARC_FLAG_KTHREAD) {
1029                 sun4c_alloc_context(current->mm);
1030                 sun4c_set_context(current->mm->context);
1031         }
1032 }
1033 
1034 static void sun4c_exit_hook(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1035 {
1036         struct ctx_list *ctx_old;
1037         struct mm_struct *mm = current->mm;
1038 
1039         if(mm->context != NO_CONTEXT) {
1040                 sun4c_demap_context(&sun4c_context_ring[mm->context], mm->context);
1041                 ctx_old = ctx_list_pool + mm->context;
1042                 remove_from_ctx_list(ctx_old);
1043                 add_to_free_ctxlist(ctx_old);
1044                 mm->context = NO_CONTEXT;
1045         }
1046 }
1047 
1048 void sun4c_test_wp(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1049 {
1050         wp_works_ok = -1;
1051 
1052         /* Let it rip... */
1053         sun4c_put_pte((unsigned long) 0x0, (_SUN4C_PAGE_VALID | _SUN4C_PAGE_PRIV));
1054         __asm__ __volatile__("st %%g0, [0x0]\n\t": : :"memory");
1055         sun4c_put_pte((unsigned long) 0x0, 0x0);
1056         if (wp_works_ok < 0)
1057                 wp_works_ok = 0;
1058 }
1059 
1060 static char s4cinfo[512];
1061 
1062 static char *sun4c_mmu_info(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1063 {
1064         int used_user_entries, i;
1065 
1066         used_user_entries = 0;
1067         for(i=0; i < num_contexts; i++)
1068                 used_user_entries += sun4c_context_ring[i].num_entries;
1069 
1070         sprintf(s4cinfo, "vacsize: %d bytes\n"
1071                 "vachwflush\t: %s\n"
1072                 "vaclinesize\t: %d bytes\n"
1073                 "mmuctxs\t\t: %d\n"
1074                 "mmupsegs\t: %d\n"
1075                 "usedpsegs\t: %d\n"
1076                 "ufreepsegs\t: %d\n"
1077                 "context\t\t: %d flushes\n"
1078                 "segment\t\t: %d flushes\n"
1079                 "page\t\t: %d flushes\n",
1080                 sun4c_vacinfo.num_bytes,
1081                 (sun4c_vacinfo.do_hwflushes ? "yes" : "no"),
1082                 sun4c_vacinfo.linesize,
1083                 num_contexts,
1084                 (invalid_segment + 1),
1085                 used_user_entries,
1086                 sun4c_ufree_ring.num_entries,
1087                 ctxflushes, segflushes, pageflushes);
1088 
1089         return s4cinfo;
1090 }
1091 
1092 /* Nothing below here should touch the mmu hardware nor the mmu_entry
1093  * data structures.
1094  */
1095 
1096 static unsigned int sun4c_pmd_align(unsigned int addr) { return SUN4C_PMD_ALIGN(addr); }
     /* [previous][next][first][last][top][bottom][index][help] */
1097 static unsigned int sun4c_pgdir_align(unsigned int addr) { return SUN4C_PGDIR_ALIGN(addr); }
     /* [previous][next][first][last][top][bottom][index][help] */
1098 
1099 /* First the functions which the mid-level code uses to directly
1100  * manipulate the software page tables.  Some defines since we are
1101  * emulating the i386 page directory layout.
1102  */
1103 #define PGD_PRESENT  0x001
1104 #define PGD_RW       0x002
1105 #define PGD_USER     0x004
1106 #define PGD_ACCESSED 0x020
1107 #define PGD_DIRTY    0x040
1108 #define PGD_TABLE    (PGD_PRESENT | PGD_RW | PGD_USER | PGD_ACCESSED | PGD_DIRTY)
1109 
1110 static unsigned long sun4c_vmalloc_start(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1111 {
1112         return SUN4C_VMALLOC_START;
1113 }
1114 
1115 static int sun4c_pte_none(pte_t pte)            { return !pte_val(pte); }
     /* [previous][next][first][last][top][bottom][index][help] */
1116 static int sun4c_pte_present(pte_t pte)         { return pte_val(pte) & _SUN4C_PAGE_VALID; }
     /* [previous][next][first][last][top][bottom][index][help] */
1117 static int sun4c_pte_inuse(pte_t *ptep)         { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
     /* [previous][next][first][last][top][bottom][index][help] */
1118 static void sun4c_pte_clear(pte_t *ptep)        { pte_val(*ptep) = 0; }
     /* [previous][next][first][last][top][bottom][index][help] */
1119 static void sun4c_pte_reuse(pte_t *ptep)
     /* [previous][next][first][last][top][bottom][index][help] */
1120 {
1121         if(!mem_map[MAP_NR(ptep)].reserved)
1122                 mem_map[MAP_NR(ptep)].count++;
1123 }
1124 
1125 static int sun4c_pmd_none(pmd_t pmd)            { return !pmd_val(pmd); }
     /* [previous][next][first][last][top][bottom][index][help] */
1126 static int sun4c_pmd_bad(pmd_t pmd)
     /* [previous][next][first][last][top][bottom][index][help] */
1127 {
1128         return (pmd_val(pmd) & ~PAGE_MASK) != PGD_TABLE || pmd_val(pmd) > high_memory;
1129 }
1130 
1131 static int sun4c_pmd_present(pmd_t pmd)         { return pmd_val(pmd) & PGD_PRESENT; }
     /* [previous][next][first][last][top][bottom][index][help] */
1132 static int sun4c_pmd_inuse(pmd_t *pmdp)         { return 0; }
     /* [previous][next][first][last][top][bottom][index][help] */
1133 static void sun4c_pmd_clear(pmd_t *pmdp)        { pmd_val(*pmdp) = 0; }
     /* [previous][next][first][last][top][bottom][index][help] */
1134 static void sun4c_pmd_reuse(pmd_t * pmdp)       { }
     /* [previous][next][first][last][top][bottom][index][help] */
1135 
1136 static int sun4c_pgd_none(pgd_t pgd)            { return 0; }
     /* [previous][next][first][last][top][bottom][index][help] */
1137 static int sun4c_pgd_bad(pgd_t pgd)             { return 0; }
     /* [previous][next][first][last][top][bottom][index][help] */
1138 static int sun4c_pgd_present(pgd_t pgd)         { return 1; }
     /* [previous][next][first][last][top][bottom][index][help] */
1139 static int sun4c_pgd_inuse(pgd_t *pgdp)         { return mem_map[MAP_NR(pgdp)].reserved; }
     /* [previous][next][first][last][top][bottom][index][help] */
1140 static void sun4c_pgd_clear(pgd_t * pgdp)       { }
     /* [previous][next][first][last][top][bottom][index][help] */
1141 
1142 /*
1143  * The following only work if pte_present() is true.
1144  * Undefined behaviour if not..
1145  */
1146 static int sun4c_pte_write(pte_t pte)           { return pte_val(pte) & _SUN4C_PAGE_WRITE; }
     /* [previous][next][first][last][top][bottom][index][help] */
1147 static int sun4c_pte_dirty(pte_t pte)           { return pte_val(pte) & _SUN4C_PAGE_DIRTY; }
     /* [previous][next][first][last][top][bottom][index][help] */
1148 static int sun4c_pte_young(pte_t pte)           { return pte_val(pte) & _SUN4C_PAGE_REF; }
     /* [previous][next][first][last][top][bottom][index][help] */
1149 
1150 static pte_t sun4c_pte_wrprotect(pte_t pte)     { pte_val(pte) &= ~_SUN4C_PAGE_WRITE; return pte; }
     /* [previous][next][first][last][top][bottom][index][help] */
1151 static pte_t sun4c_pte_mkclean(pte_t pte)       { pte_val(pte) &= ~_SUN4C_PAGE_DIRTY; return pte; }
     /* [previous][next][first][last][top][bottom][index][help] */
1152 static pte_t sun4c_pte_mkold(pte_t pte)         { pte_val(pte) &= ~_SUN4C_PAGE_REF; return pte; }
     /* [previous][next][first][last][top][bottom][index][help] */
1153 static pte_t sun4c_pte_mkwrite(pte_t pte)       { pte_val(pte) |= _SUN4C_PAGE_WRITE; return pte; }
     /* [previous][next][first][last][top][bottom][index][help] */
1154 static pte_t sun4c_pte_mkdirty(pte_t pte)       { pte_val(pte) |= _SUN4C_PAGE_DIRTY; return pte; }
     /* [previous][next][first][last][top][bottom][index][help] */
1155 static pte_t sun4c_pte_mkyoung(pte_t pte)       { pte_val(pte) |= _SUN4C_PAGE_REF; return pte; }
     /* [previous][next][first][last][top][bottom][index][help] */
1156 
1157 /*
1158  * Conversion functions: convert a page and protection to a page entry,
1159  * and a page entry and page directory to the page they refer to.
1160  */
1161 static pte_t sun4c_mk_pte(unsigned long page, pgprot_t pgprot)
     /* [previous][next][first][last][top][bottom][index][help] */
1162 {
1163         return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot));
1164 }
1165 
1166 static pte_t sun4c_mk_pte_io(unsigned long page, pgprot_t pgprot)
     /* [previous][next][first][last][top][bottom][index][help] */
1167 {
1168         return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot));
1169 }
1170 
1171 static pte_t sun4c_pte_modify(pte_t pte, pgprot_t newprot)
     /* [previous][next][first][last][top][bottom][index][help] */
1172 {
1173         return __pte((pte_val(pte) & _SUN4C_PAGE_CHG_MASK) | pgprot_val(newprot));
1174 }
1175 
1176 static unsigned long sun4c_pte_page(pte_t pte)
     /* [previous][next][first][last][top][bottom][index][help] */
1177 {
1178         return (PAGE_OFFSET + ((pte_val(pte) & 0xffff) << (PAGE_SHIFT)));
1179 }
1180 
1181 static unsigned long sun4c_pmd_page(pmd_t pmd)
     /* [previous][next][first][last][top][bottom][index][help] */
1182 {
1183         return (pmd_val(pmd) & PAGE_MASK);
1184 }
1185 
1186 /* to find an entry in a page-table-directory */
1187 static pgd_t *sun4c_pgd_offset(struct mm_struct * mm, unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
1188 {
1189         return mm->pgd + (address >> SUN4C_PGDIR_SHIFT);
1190 }
1191 
1192 /* Find an entry in the second-level page table.. */
1193 static pmd_t *sun4c_pmd_offset(pgd_t * dir, unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
1194 {
1195         return (pmd_t *) dir;
1196 }
1197 
1198 /* Find an entry in the third-level page table.. */ 
1199 static pte_t *sun4c_pte_offset(pmd_t * dir, unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
1200 {
1201         return (pte_t *) sun4c_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1));
1202 }
1203 
1204 /* Update the root mmu directory. */
1205 static void sun4c_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdir)
     /* [previous][next][first][last][top][bottom][index][help] */
1206 {
1207 }
1208 
1209 /* Allocate and free page tables. The xxx_kernel() versions are
1210  * used to allocate a kernel page table - this turns on ASN bits
1211  * if any, and marks the page tables reserved.
1212  */
1213 static void sun4c_pte_free_kernel(pte_t *pte)
     /* [previous][next][first][last][top][bottom][index][help] */
1214 {
1215         mem_map[MAP_NR(pte)].reserved = 0;
1216         free_page((unsigned long) pte);
1217 }
1218 
1219 static pte_t *sun4c_pte_alloc_kernel(pmd_t *pmd, unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
1220 {
1221         address = (address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1);
1222         if (sun4c_pmd_none(*pmd)) {
1223                 pte_t *page = (pte_t *) get_free_page(GFP_KERNEL);
1224                 if (sun4c_pmd_none(*pmd)) {
1225                         if (page) {
1226                                 pmd_val(*pmd) = PGD_TABLE | (unsigned long) page;
1227                                 mem_map[MAP_NR(page)].reserved = 1;
1228                                 return page + address;
1229                         }
1230                         pmd_val(*pmd) = PGD_TABLE | (unsigned long) BAD_PAGETABLE;
1231                         return NULL;
1232                 }
1233                 free_page((unsigned long) page);
1234         }
1235         if (sun4c_pmd_bad(*pmd)) {
1236                 printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
1237                 pmd_val(*pmd) = PGD_TABLE | (unsigned long) BAD_PAGETABLE;
1238                 return NULL;
1239         }
1240         return (pte_t *) sun4c_pmd_page(*pmd) + address;
1241 }
1242 
1243 /*
1244  * allocating and freeing a pmd is trivial: the 1-entry pmd is
1245  * inside the pgd, so has no extra memory associated with it.
1246  */
1247 static void sun4c_pmd_free_kernel(pmd_t *pmd)
     /* [previous][next][first][last][top][bottom][index][help] */
1248 {
1249         pmd_val(*pmd) = 0;
1250 }
1251 
1252 static pmd_t *sun4c_pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
1253 {
1254         return (pmd_t *) pgd;
1255 }
1256 
1257 static void sun4c_pte_free(pte_t *pte)
     /* [previous][next][first][last][top][bottom][index][help] */
1258 {
1259         free_page((unsigned long) pte);
1260 }
1261 
1262 static pte_t *sun4c_pte_alloc(pmd_t * pmd, unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
1263 {
1264         address = (address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1);
1265         if (sun4c_pmd_none(*pmd)) {
1266                 pte_t *page = (pte_t *) get_free_page(GFP_KERNEL);
1267                 if (sun4c_pmd_none(*pmd)) {
1268                         if (page) {
1269                                 pmd_val(*pmd) = PGD_TABLE | (unsigned long) page;
1270                                 return page + address;
1271                         }
1272                         pmd_val(*pmd) = PGD_TABLE | (unsigned long) BAD_PAGETABLE;
1273                         return NULL;
1274                 }
1275                 free_page((unsigned long) page);
1276         }
1277         if (sun4c_pmd_bad(*pmd)) {
1278                 printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
1279                 pmd_val(*pmd) = PGD_TABLE | (unsigned long) BAD_PAGETABLE;
1280                 return NULL;
1281         }
1282         return (pte_t *) sun4c_pmd_page(*pmd) + address;
1283 }
1284 
1285 /*
1286  * allocating and freeing a pmd is trivial: the 1-entry pmd is
1287  * inside the pgd, so has no extra memory associated with it.
1288  */
1289 static void sun4c_pmd_free(pmd_t * pmd)
     /* [previous][next][first][last][top][bottom][index][help] */
1290 {
1291         pmd_val(*pmd) = 0;
1292 }
1293 
1294 static pmd_t *sun4c_pmd_alloc(pgd_t * pgd, unsigned long address)
     /* [previous][next][first][last][top][bottom][index][help] */
1295 {
1296         return (pmd_t *) pgd;
1297 }
1298 
1299 static void sun4c_pgd_free(pgd_t *pgd)
     /* [previous][next][first][last][top][bottom][index][help] */
1300 {
1301         free_page((unsigned long) pgd);
1302 }
1303 
1304 static pgd_t *sun4c_pgd_alloc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1305 {
1306         return (pgd_t *) get_free_page(GFP_KERNEL);
1307 }
1308 
1309 #define SUN4C_KERNEL_BUCKETS   16
1310 extern unsigned long free_area_init(unsigned long, unsigned long);
1311 extern unsigned long sparc_context_init(unsigned long, int);
1312 extern unsigned long end;
1313 
1314 unsigned long sun4c_paging_init(unsigned long start_mem, unsigned long end_mem)
     /* [previous][next][first][last][top][bottom][index][help] */
1315 {
1316         int i, cnt;
1317         unsigned long kernel_end;
1318 
1319         kernel_end = (unsigned long) &end;
1320         kernel_end += (SUN4C_REAL_PGDIR_SIZE * 3);
1321         kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
1322         sun4c_probe_mmu();
1323         invalid_segment = (num_segmaps - 1);
1324         sun4c_init_mmu_entry_pool();
1325         sun4c_init_rings();
1326         sun4c_init_map_kernelprom(kernel_end);
1327         sun4c_init_clean_mmu(kernel_end);
1328         sun4c_init_fill_kernel_ring(SUN4C_KERNEL_BUCKETS);
1329         sun4c_init_lock_area(IOBASE_VADDR, IOBASE_END);
1330         sun4c_init_lock_area(DVMA_VADDR, DVMA_END);
1331         start_mem = sun4c_init_lock_areas(start_mem);
1332         sun4c_init_fill_user_ring();
1333 
1334         sun4c_set_context(0);
1335         memset(swapper_pg_dir, 0, PAGE_SIZE);
1336         memset(pg0, 0, PAGE_SIZE);
1337         /* Save work later. */
1338         pgd_val(swapper_pg_dir[SUN4C_VMALLOC_START>>SUN4C_PGDIR_SHIFT]) =
1339                 PGD_TABLE | (unsigned long) pg0;
1340         sun4c_init_ss2_cache_bug();
1341         start_mem = PAGE_ALIGN(start_mem);
1342         start_mem = sun4c_init_alloc_dvma_pages(start_mem);
1343         start_mem = sparc_context_init(start_mem, num_contexts);
1344         start_mem = free_area_init(start_mem, end_mem);
1345         cnt = 0;
1346         for(i = 0; i < num_segmaps; i++)
1347                 if(mmu_entry_pool[i].locked)
1348                         cnt++;
1349         printk("SUN4C: %d mmu entries for the kernel\n", cnt);
1350         return start_mem;
1351 }
1352 
1353 /* Load up routines and constants for sun4c mmu */
1354 void ld_mmu_sun4c(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1355 {
1356         printk("Loading sun4c MMU routines\n");
1357 
1358         /* First the constants */
1359         pmd_shift = SUN4C_PMD_SHIFT;
1360         pmd_size = SUN4C_PMD_SIZE;
1361         pmd_mask = SUN4C_PMD_MASK;
1362         pgdir_shift = SUN4C_PGDIR_SHIFT;
1363         pgdir_size = SUN4C_PGDIR_SIZE;
1364         pgdir_mask = SUN4C_PGDIR_MASK;
1365 
1366         ptrs_per_pte = SUN4C_PTRS_PER_PTE;
1367         ptrs_per_pmd = SUN4C_PTRS_PER_PMD;
1368         ptrs_per_pgd = SUN4C_PTRS_PER_PGD;
1369 
1370         page_none = SUN4C_PAGE_NONE;
1371         page_shared = SUN4C_PAGE_SHARED;
1372         page_copy = SUN4C_PAGE_COPY;
1373         page_readonly = SUN4C_PAGE_READONLY;
1374         page_kernel = SUN4C_PAGE_KERNEL;
1375         pg_iobits = _SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_IO | _SUN4C_PAGE_VALID
1376             | _SUN4C_PAGE_WRITE | _SUN4C_PAGE_DIRTY;
1377         
1378         /* Functions */
1379         invalidate_all = sun4c_invalidate_all;
1380         invalidate_mm = sun4c_invalidate_mm;
1381         invalidate_range = sun4c_invalidate_range;
1382         invalidate_page = sun4c_invalidate_page;
1383         set_pte = sun4c_set_pte;
1384         switch_to_context = sun4c_switch_to_context;
1385         pmd_align = sun4c_pmd_align;
1386         pgdir_align = sun4c_pgdir_align;
1387         vmalloc_start = sun4c_vmalloc_start;
1388 
1389         pte_page = sun4c_pte_page;
1390         pmd_page = sun4c_pmd_page;
1391 
1392         sparc_update_rootmmu_dir = sun4c_update_rootmmu_dir;
1393 
1394         pte_none = sun4c_pte_none;
1395         pte_present = sun4c_pte_present;
1396         pte_inuse = sun4c_pte_inuse;
1397         pte_clear = sun4c_pte_clear;
1398         pte_reuse = sun4c_pte_reuse;
1399 
1400         pmd_none = sun4c_pmd_none;
1401         pmd_bad = sun4c_pmd_bad;
1402         pmd_present = sun4c_pmd_present;
1403         pmd_inuse = sun4c_pmd_inuse;
1404         pmd_clear = sun4c_pmd_clear;
1405         pmd_reuse = sun4c_pmd_reuse;
1406 
1407         pgd_none = sun4c_pgd_none;
1408         pgd_bad = sun4c_pgd_bad;
1409         pgd_present = sun4c_pgd_present;
1410         pgd_inuse = sun4c_pgd_inuse;
1411         pgd_clear = sun4c_pgd_clear;
1412 
1413         mk_pte = sun4c_mk_pte;
1414         mk_pte_io = sun4c_mk_pte_io;
1415         pte_modify = sun4c_pte_modify;
1416         pgd_offset = sun4c_pgd_offset;
1417         pmd_offset = sun4c_pmd_offset;
1418         pte_offset = sun4c_pte_offset;
1419         pte_free_kernel = sun4c_pte_free_kernel;
1420         pmd_free_kernel = sun4c_pmd_free_kernel;
1421         pte_alloc_kernel = sun4c_pte_alloc_kernel;
1422         pmd_alloc_kernel = sun4c_pmd_alloc_kernel;
1423         pte_free = sun4c_pte_free;
1424         pte_alloc = sun4c_pte_alloc;
1425         pmd_free = sun4c_pmd_free;
1426         pmd_alloc = sun4c_pmd_alloc;
1427         pgd_free = sun4c_pgd_free;
1428         pgd_alloc = sun4c_pgd_alloc;
1429 
1430         pte_write = sun4c_pte_write;
1431         pte_dirty = sun4c_pte_dirty;
1432         pte_young = sun4c_pte_young;
1433         pte_wrprotect = sun4c_pte_wrprotect;
1434         pte_mkclean = sun4c_pte_mkclean;
1435         pte_mkold = sun4c_pte_mkold;
1436         pte_mkwrite = sun4c_pte_mkwrite;
1437         pte_mkdirty = sun4c_pte_mkdirty;
1438         pte_mkyoung = sun4c_pte_mkyoung;
1439         update_mmu_cache = sun4c_update_mmu_cache;
1440         mmu_exit_hook = sun4c_exit_hook;
1441         mmu_flush_hook = sun4c_flush_hook;
1442         mmu_lockarea = sun4c_lockpage;
1443         mmu_unlockarea = sun4c_unlockpage;
1444         mmu_get_scsi_buffer = sun4c_get_scsi_buffer;
1445         mmu_release_scsi_buffer = sun4c_release_scsi_buffer;
1446         
1447         /* Task struct and kernel stack allocating/freeing. */
1448         alloc_kernel_stack = sun4c_alloc_kernel_stack;
1449         alloc_task_struct = sun4c_alloc_task_struct;
1450         free_kernel_stack = sun4c_free_kernel_stack;
1451         free_task_struct = sun4c_free_task_struct;
1452 
1453         quick_kernel_fault = sun4c_quick_kernel_fault;
1454         mmu_info = sun4c_mmu_info;
1455 
1456         /* These should _never_ get called with two level tables. */
1457         pgd_set = 0;
1458         pgd_reuse = 0;
1459         pgd_page = 0;
1460 }

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