root/arch/mips/mm/init.c

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

DEFINITIONS

This source file includes following definitions.
  1. __bad_pagetable
  2. __zeropage
  3. zeropage
  4. __bad_page
  5. __zero_page
  6. __copy_page
  7. show_mem
  8. paging_init
  9. mem_init
  10. si_meminfo

   1 /*
   2  *  arch/mips/mm/init.c
   3  *
   4  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
   5  *  Ported to MIPS by Ralf Baechle
   6  */
   7 #include <linux/config.h>
   8 #include <linux/signal.h>
   9 #include <linux/sched.h>
  10 #include <linux/head.h>
  11 #include <linux/kernel.h>
  12 #include <linux/errno.h>
  13 #include <linux/string.h>
  14 #include <linux/types.h>
  15 #include <linux/ptrace.h>
  16 #include <linux/mman.h>
  17 #include <linux/mm.h>
  18 
  19 #include <asm/cachectl.h>
  20 #include <asm/jazzdma.h>
  21 #include <asm/vector.h>
  22 #include <asm/system.h>
  23 #include <asm/segment.h>
  24 #include <asm/pgtable.h>
  25 
  26 extern void deskstation_tyne_dma_init(void);
  27 extern void sound_mem_init(void);
  28 extern void die_if_kernel(char *,struct pt_regs *,long);
  29 extern void show_net_buffers(void);
  30 
  31 extern char empty_zero_page[PAGE_SIZE];
  32 
  33 /*
  34  * BAD_PAGE is the page that is used for page faults when linux
  35  * is out-of-memory. Older versions of linux just did a
  36  * do_exit(), but using this instead means there is less risk
  37  * for a process dying in kernel mode, possibly leaving a inode
  38  * unused etc..
  39  *
  40  * BAD_PAGETABLE is the accompanying page-table: it is initialized
  41  * to point to BAD_PAGE entries.
  42  *
  43  * ZERO_PAGE is a special page that is used for zero-initialized
  44  * data and COW.
  45  */
  46 pte_t * __bad_pagetable(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         extern char empty_bad_page_table[PAGE_SIZE];
  49         unsigned long page;
  50         unsigned long dummy1, dummy2;
  51 
  52         page = ((unsigned long)empty_bad_page_table) + (PT_OFFSET - PAGE_OFFSET);
  53 #if __mips__ >= 3
  54         /*
  55          * Use 64bit code even for Linux/MIPS 32bit on R4000
  56          */
  57         __asm__ __volatile__(
  58                 ".set\tnoreorder\n"
  59                 ".set\tnoat\n\t"
  60                 ".set\tmips3\n\t"
  61                 "dsll32\t$1,%2,0\n\t"
  62                 "dsrl32\t%2,$1,0\n\t"
  63                 "or\t%2,$1\n"
  64                 "1:\tsd\t%2,(%0)\n\t"
  65                 "subu\t%1,1\n\t"
  66                 "bnez\t%1,1b\n\t"
  67                 "addiu\t%0,8\n\t"
  68                 ".set\tmips0\n\t"
  69                 ".set\tat\n"
  70                 ".set\treorder"
  71                 :"=r" (dummy1),
  72                  "=r" (dummy2)
  73                 :"r" (pte_val(BAD_PAGE)),
  74                  "0" (page),
  75                  "1" (PAGE_SIZE/8));
  76 #else
  77         __asm__ __volatile__(
  78                 ".set\tnoreorder\n"
  79                 "1:\tsw\t%2,(%0)\n\t"
  80                 "subu\t%1,1\n\t"
  81                 "bnez\t%1,1b\n\t"
  82                 "addiu\t%0,4\n\t"
  83                 ".set\treorder"
  84                 :"=r" (dummy1),
  85                  "=r" (dummy2)
  86                 :"r" (pte_val(BAD_PAGE)),
  87                  "0" (page),
  88                  "1" (PAGE_SIZE/4));
  89 #endif
  90 
  91         return (pte_t *)page;
  92 }
  93 
  94 static inline void
  95 __zeropage(unsigned long page)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97         unsigned long dummy1, dummy2;
  98 
  99 #ifdef __R4000__
 100         /*
 101          * Use 64bit code even for Linux/MIPS 32bit on R4000
 102          */
 103         __asm__ __volatile__(
 104                 ".set\tnoreorder\n"
 105                 ".set\tnoat\n\t"
 106                 ".set\tmips3\n"
 107                 "1:\tsd\t$0,(%0)\n\t"
 108                 "subu\t%1,1\n\t"
 109                 "bnez\t%1,1b\n\t"
 110                 "addiu\t%0,8\n\t"
 111                 ".set\tmips0\n\t"
 112                 ".set\tat\n"
 113                 ".set\treorder"
 114                 :"=r" (dummy1),
 115                  "=r" (dummy2)
 116                 :"0" (page),
 117                  "1" (PAGE_SIZE/8));
 118 #else
 119         __asm__ __volatile__(
 120                 ".set\tnoreorder\n"
 121                 "1:\tsw\t$0,(%0)\n\t"
 122                 "subu\t%1,1\n\t"
 123                 "bnez\t%1,1b\n\t"
 124                 "addiu\t%0,4\n\t"
 125                 ".set\treorder"
 126                 :"=r" (dummy1),
 127                  "=r" (dummy2)
 128                 :"0" (page),
 129                  "1" (PAGE_SIZE/4));
 130 #endif
 131 }
 132 
 133 static inline void
 134 zeropage(unsigned long page)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136         sys_cacheflush((void *)page, PAGE_SIZE, BCACHE);
 137         sync_mem();
 138         __zeropage(page + (PT_OFFSET - PAGE_OFFSET));
 139 }
 140 
 141 pte_t __bad_page(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143         extern char empty_bad_page[PAGE_SIZE];
 144         unsigned long page = (unsigned long)empty_bad_page;
 145 
 146         zeropage(page);
 147         return pte_mkdirty(mk_pte(page, PAGE_SHARED));
 148 }
 149 
 150 unsigned long __zero_page(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152         unsigned long page = (unsigned long) empty_zero_page;
 153 
 154         zeropage(page);
 155         return page;
 156 }
 157 
 158 /*
 159  * This is horribly inefficient ...
 160  */
 161 void __copy_page(unsigned long from, unsigned long to)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163         /*
 164          * Now copy page from uncached KSEG1 to KSEG0.  The copy destination
 165          * is in KSEG0 so that we keep stupid L2 caches happy.
 166          */
 167         if(from == (unsigned long) empty_zero_page)
 168         {
 169                 /*
 170                  * The page copied most is the COW empty_zero_page.  Since we
 171                  * know it's contents we can avoid the writeback reading of
 172                  * the page.  Speeds up the standard case alot.
 173                  */
 174                 __zeropage(to);
 175         }
 176         else
 177         {
 178                 /*
 179                  * Force writeback of old page to memory.  We don't know the
 180                  * virtual address, so we have to flush the entire cache ...
 181                  */
 182                 sys_cacheflush(0, ~0, DCACHE);
 183                 sync_mem();
 184                 memcpy((void *) to,
 185                        (void *) (from + (PT_OFFSET - PAGE_OFFSET)), PAGE_SIZE);
 186         }
 187         /*
 188          * Now writeback the page again if colour has changed.
 189          * Actually this does a Hit_Writeback, but due to an artifact in
 190          * the R4xx0 implementation this should be slightly faster.
 191          * Then sweep chipset controlled secondary caches and the ICACHE.
 192          */
 193         if (page_colour(from) != page_colour(to))
 194                 sys_cacheflush(0, ~0, DCACHE);
 195         sys_cacheflush(0, ~0, ICACHE);
 196 }
 197 
 198 void show_mem(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 199 {
 200         int i, free = 0, total = 0, reserved = 0;
 201         int shared = 0;
 202 
 203         printk("Mem-info:\n");
 204         show_free_areas();
 205         printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 206         i = (high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
 207         while (i-- > 0) {
 208                 total++;
 209                 if (mem_map[i].reserved)
 210                         reserved++;
 211                 else if (!mem_map[i].count)
 212                         free++;
 213                 else
 214                         shared += mem_map[i].count-1;
 215         }
 216         printk("%d pages of RAM\n", total);
 217         printk("%d free pages\n", free);
 218         printk("%d reserved pages\n", reserved);
 219         printk("%d pages shared\n", shared);
 220         show_buffers();
 221 #ifdef CONFIG_NET
 222         show_net_buffers();
 223 #endif
 224 }
 225 
 226 extern unsigned long free_area_init(unsigned long, unsigned long);
 227 
 228 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
     /* [previous][next][first][last][top][bottom][index][help] */
 229 {
 230         pgd_init((unsigned long)swapper_pg_dir - (PT_OFFSET - PAGE_OFFSET));
 231         return free_area_init(start_mem, end_mem);
 232 }
 233 
 234 void mem_init(unsigned long start_mem, unsigned long end_mem)
     /* [previous][next][first][last][top][bottom][index][help] */
 235 {
 236         int codepages = 0;
 237         int datapages = 0;
 238         unsigned long tmp;
 239         extern int _etext;
 240 
 241 #ifdef CONFIG_MIPS_JAZZ
 242         start_mem = vdma_init(start_mem, end_mem);
 243 #endif
 244 
 245         end_mem &= PAGE_MASK;
 246         high_memory = end_mem;
 247 
 248         /* mark usable pages in the mem_map[] */
 249         start_mem = PAGE_ALIGN(start_mem);
 250 
 251         tmp = start_mem;
 252         while (tmp < high_memory) {
 253                 mem_map[MAP_NR(tmp)].reserved = 0;
 254                 tmp += PAGE_SIZE;
 255         }
 256 
 257 #ifdef CONFIG_DESKSTATION_TYNE
 258         deskstation_tyne_dma_init();
 259 #endif
 260 #ifdef CONFIG_SOUND
 261         sound_mem_init();
 262 #endif
 263         for (tmp = PAGE_OFFSET ; tmp < high_memory ; tmp += PAGE_SIZE) {
 264                 if (mem_map[MAP_NR(tmp)].reserved) {
 265                         if (tmp < (unsigned long) &_etext)
 266                                 codepages++;
 267                         else if (tmp < start_mem)
 268                                 datapages++;
 269                         continue;
 270                 }
 271                 mem_map[MAP_NR(tmp)].count = 1;
 272                 free_page(tmp);
 273         }
 274         tmp = nr_free_pages << PAGE_SHIFT;
 275         printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n",
 276                 tmp >> 10,
 277                 (high_memory - PAGE_OFFSET) >> 10,
 278                 codepages << (PAGE_SHIFT-10),
 279                 datapages << (PAGE_SHIFT-10));
 280 
 281         return;
 282 }
 283 
 284 void si_meminfo(struct sysinfo *val)
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286         int i;
 287 
 288         i = high_memory >> PAGE_SHIFT;
 289         val->totalram = 0;
 290         val->sharedram = 0;
 291         val->freeram = nr_free_pages << PAGE_SHIFT;
 292         val->bufferram = buffermem;
 293         while (i-- > 0)  {
 294                 if (mem_map[i].reserved)
 295                         continue;
 296                 val->totalram++;
 297                 if (!mem_map[i].count)
 298                         continue;
 299                 val->sharedram += mem_map[i].count-1;
 300         }
 301         val->totalram <<= PAGE_SHIFT;
 302         val->sharedram <<= PAGE_SHIFT;
 303         return;
 304 }

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