root/arch/i386/mm/init.c

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

DEFINITIONS

This source file includes following definitions.
  1. __bad_pagetable
  2. __bad_page
  3. show_mem
  4. paging_init
  5. mem_init
  6. si_meminfo

   1 /*
   2  *  linux/arch/i386/mm/init.c
   3  *
   4  *  Copyright (C) 1995  Linus Torvalds
   5  */
   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 #include <linux/smp.h>
  19 
  20 #include <asm/system.h>
  21 #include <asm/segment.h>
  22 #include <asm/pgtable.h>
  23 
  24 /*
  25  * The SMP kernel can't handle the 4MB page table optimizations yet
  26  */
  27 #ifdef __SMP__
  28 #undef USE_PENTIUM_MM
  29 #endif
  30 
  31 extern void scsi_mem_init(unsigned long);
  32 extern void die_if_kernel(char *,struct pt_regs *,long);
  33 extern void show_net_buffers(void);
  34 
  35 /*
  36  * BAD_PAGE is the page that is used for page faults when linux
  37  * is out-of-memory. Older versions of linux just did a
  38  * do_exit(), but using this instead means there is less risk
  39  * for a process dying in kernel mode, possibly leaving a inode
  40  * unused etc..
  41  *
  42  * BAD_PAGETABLE is the accompanying page-table: it is initialized
  43  * to point to BAD_PAGE entries.
  44  *
  45  * ZERO_PAGE is a special page that is used for zero-initialized
  46  * data and COW.
  47  */
  48 pte_t * __bad_pagetable(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  49 {
  50         extern char empty_bad_page_table[PAGE_SIZE];
  51 
  52         __asm__ __volatile__("cld ; rep ; stosl":
  53                 :"a" (pte_val(BAD_PAGE)),
  54                  "D" ((long) empty_bad_page_table),
  55                  "c" (PAGE_SIZE/4)
  56                 :"di","cx");
  57         return (pte_t *) empty_bad_page_table;
  58 }
  59 
  60 pte_t __bad_page(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  61 {
  62         extern char empty_bad_page[PAGE_SIZE];
  63 
  64         __asm__ __volatile__("cld ; rep ; stosl":
  65                 :"a" (0),
  66                  "D" ((long) empty_bad_page),
  67                  "c" (PAGE_SIZE/4)
  68                 :"di","cx");
  69         return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
  70 }
  71 
  72 void show_mem(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74         int i,free = 0,total = 0,reserved = 0;
  75         int shared = 0;
  76 
  77         printk("Mem-info:\n");
  78         show_free_areas();
  79         printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
  80         i = high_memory >> PAGE_SHIFT;
  81         while (i-- > 0) {
  82                 total++;
  83                 if (mem_map[i].reserved)
  84                         reserved++;
  85                 else if (!mem_map[i].count)
  86                         free++;
  87                 else
  88                         shared += mem_map[i].count-1;
  89         }
  90         printk("%d pages of RAM\n",total);
  91         printk("%d free pages\n",free);
  92         printk("%d reserved pages\n",reserved);
  93         printk("%d pages shared\n",shared);
  94         show_buffers();
  95 #ifdef CONFIG_NET
  96         show_net_buffers();
  97 #endif
  98 }
  99 
 100 extern unsigned long free_area_init(unsigned long, unsigned long);
 101 
 102 /*
 103  * paging_init() sets up the page tables - note that the first 4MB are
 104  * already mapped by head.S.
 105  *
 106  * This routines also unmaps the page at virtual kernel address 0, so
 107  * that we can trap those pesky NULL-reference errors in the kernel.
 108  */
 109 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         pgd_t * pg_dir;
 112         pte_t * pg_table;
 113         unsigned long tmp;
 114         unsigned long address;
 115 
 116 /*
 117  * Physical page 0 is special; it's not touched by Linux since BIOS
 118  * and SMM (for laptops with [34]86/SL chips) may need it.  It is read
 119  * and write protected to detect null pointer references in the
 120  * kernel.
 121  * It may also hold the MP configuration table when we are booting SMP.
 122  */
 123 #if 0
 124         memset((void *) 0, 0, PAGE_SIZE);
 125 #endif
 126 #ifdef __SMP__
 127         smp_scan_config(0x0,0x400);     /* Scan the bottom 1K for a signature */
 128         /*
 129          *      FIXME: Linux assumes you have 640K of base ram.. this continues
 130          *      the error...
 131          */
 132         smp_scan_config(639*0x400,0x400);       /* Scan the top 1K of base RAM */
 133         smp_scan_config(0xF0000,0x10000);       /* Scan the 64K of bios */
 134         /*
 135          *      If it is an SMP machine we should know now, unless the configuration
 136          *      is in an EISA/MCA bus machine with an extended bios data area. I don't
 137          *      have such a machine so someone else can fill in the check of the EBDA
 138          *      here.
 139          */
 140 /*      smp_alloc_memory(8192); */
 141 #endif
 142 #ifdef TEST_VERIFY_AREA
 143         wp_works_ok = 0;
 144 #endif
 145         start_mem = PAGE_ALIGN(start_mem);
 146         address = 0;
 147         pg_dir = swapper_pg_dir;
 148         while (address < end_mem) {
 149 #ifdef USE_PENTIUM_MM
 150                 if (address <= end_mem + 4*1024*1024 &&
 151                     (x86_capability & 8)) {
 152 #ifdef GAS_KNOWS_CR4
 153                         __asm__("movl %%cr4,%%eax\n\t"
 154                                 "orl $16,%%eax\n\t"
 155                                 "movl %%eax,%%cr4"
 156                                 : : :"ax");
 157 #else
 158                         __asm__(".byte 0x0f,0x20,0xe0\n\t"
 159                                 "orl $16,%%eax\n\t"
 160                                 ".byte 0x0f,0x22,0xe0"
 161                                 : : :"ax");
 162 #endif
 163                         wp_works_ok = 1;
 164                         pgd_val(pg_dir[0]) = _PAGE_TABLE | _PAGE_4M | address;
 165                         pgd_val(pg_dir[768]) = _PAGE_TABLE | _PAGE_4M | address;
 166                         pg_dir++;
 167                         address += 4*1024*1024;
 168                         continue;
 169                 }
 170 #endif
 171                 /* map the memory at virtual addr 0xC0000000 */
 172                 pg_table = (pte_t *) (PAGE_MASK & pgd_val(pg_dir[768]));
 173                 if (!pg_table) {
 174                         pg_table = (pte_t *) start_mem;
 175                         start_mem += PAGE_SIZE;
 176                 }
 177 
 178                 /* also map it temporarily at 0x0000000 for init */
 179                 pgd_val(pg_dir[0])   = _PAGE_TABLE | (unsigned long) pg_table;
 180                 pgd_val(pg_dir[768]) = _PAGE_TABLE | (unsigned long) pg_table;
 181                 pg_dir++;
 182                 for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
 183                         if (address < end_mem)
 184                                 set_pte(pg_table, mk_pte(address, PAGE_SHARED));
 185                         else
 186                                 pte_clear(pg_table);
 187                         address += PAGE_SIZE;
 188                 }
 189         }
 190         invalidate();
 191         return free_area_init(start_mem, end_mem);
 192 }
 193 
 194 void mem_init(unsigned long start_mem, unsigned long end_mem)
     /* [previous][next][first][last][top][bottom][index][help] */
 195 {
 196         unsigned long start_low_mem = PAGE_SIZE;
 197         int codepages = 0;
 198         int reservedpages = 0;
 199         int datapages = 0;
 200         unsigned long tmp;
 201         extern int _etext;
 202 
 203         end_mem &= PAGE_MASK;
 204         high_memory = end_mem;
 205 
 206         /* clear the zero-page */
 207         memset(empty_zero_page, 0, PAGE_SIZE);
 208 
 209         /* mark usable pages in the mem_map[] */
 210         start_low_mem = PAGE_ALIGN(start_low_mem);
 211 
 212 #ifdef __SMP__
 213         /*
 214          * But first pinch a few for the stack/trampoline stuff
 215          */
 216         start_low_mem += PAGE_SIZE;                             /* 32bit startup code */
 217         start_low_mem = smp_alloc_memory(start_low_mem);        /* AP processor stacks */
 218 #endif
 219         start_mem = PAGE_ALIGN(start_mem);
 220 
 221         /*
 222          * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
 223          * They seem to have done something stupid with the floppy
 224          * controller as well..
 225          */
 226         while (start_low_mem < 0x9f000) {
 227                 mem_map[MAP_NR(start_low_mem)].reserved = 0;
 228                 start_low_mem += PAGE_SIZE;
 229         }
 230 
 231         while (start_mem < high_memory) {
 232                 mem_map[MAP_NR(start_mem)].reserved = 0;
 233                 start_mem += PAGE_SIZE;
 234         }
 235 #ifdef CONFIG_SCSI
 236         scsi_mem_init(high_memory);
 237 #endif
 238         for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) {
 239                 if (mem_map[MAP_NR(tmp)].reserved) {
 240                         if (tmp >= 0xA0000 && tmp < 0x100000)
 241                                 reservedpages++;
 242                         else if (tmp < (unsigned long) &_etext)
 243                                 codepages++;
 244                         else
 245                                 datapages++;
 246                         continue;
 247                 }
 248                 mem_map[MAP_NR(tmp)].count = 1;
 249                 free_page(tmp);
 250         }
 251         tmp = nr_free_pages << PAGE_SHIFT;
 252         printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
 253                 tmp >> 10,
 254                 high_memory >> 10,
 255                 codepages << (PAGE_SHIFT-10),
 256                 reservedpages << (PAGE_SHIFT-10),
 257                 datapages << (PAGE_SHIFT-10));
 258 /* test if the WP bit is honoured in supervisor mode */
 259         if (wp_works_ok < 0) {
 260                 pg0[0] = pte_val(mk_pte(0, PAGE_READONLY));
 261                 invalidate();
 262                 __asm__ __volatile__("movb 0,%%al ; movb %%al,0": : :"ax", "memory");
 263                 pg0[0] = 0;
 264                 invalidate();
 265                 if (wp_works_ok < 0)
 266                         wp_works_ok = 0;
 267         }
 268         return;
 269 }
 270 
 271 void si_meminfo(struct sysinfo *val)
     /* [previous][next][first][last][top][bottom][index][help] */
 272 {
 273         int i;
 274 
 275         i = high_memory >> PAGE_SHIFT;
 276         val->totalram = 0;
 277         val->sharedram = 0;
 278         val->freeram = nr_free_pages << PAGE_SHIFT;
 279         val->bufferram = buffermem;
 280         while (i-- > 0)  {
 281                 if (mem_map[i].reserved)
 282                         continue;
 283                 val->totalram++;
 284                 if (!mem_map[i].count)
 285                         continue;
 286                 val->sharedram += mem_map[i].count-1;
 287         }
 288         val->totalram <<= PAGE_SHIFT;
 289         val->sharedram <<= PAGE_SHIFT;
 290         return;
 291 }

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