arch/i386/mm/init.c
7148 /*
7149 * linux/arch/i386/mm/init.c
7150 *
7151 * Copyright (C) 1995 Linus Torvalds
7152 */
7153
7154 #include <linux/config.h>
7155 #include <linux/signal.h>
7156 #include <linux/sched.h>
7157 #include <linux/kernel.h>
7158 #include <linux/errno.h>
7159 #include <linux/string.h>
7160 #include <linux/types.h>
7161 #include <linux/ptrace.h>
7162 #include <linux/mman.h>
7163 #include <linux/mm.h>
7164 #include <linux/swap.h>
7165 #include <linux/smp.h>
7166 #include <linux/init.h>
7167 #ifdef CONFIG_BLK_DEV_INITRD
7168 #include <linux/blk.h>
7169 #endif
7170
7171 #include <asm/processor.h>
7172 #include <asm/system.h>
7173 #include <asm/uaccess.h>
7174 #include <asm/pgtable.h>
7175 #include <asm/dma.h>
7176 #include <asm/fixmap.h>
7177
7178 extern void show_net_buffers(void);
7179 extern unsigned long init_smp_mappings(unsigned long);
7180
7181 void __bad_pte_kernel(pmd_t *pmd)
7182 {
7183 printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
7184 pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE);
7185 }
7186
7187 void __bad_pte(pmd_t *pmd)
7188 {
7189 printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
7190 pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
7191 }
7192
7193 pte_t *get_pte_kernel_slow(pmd_t *pmd,
7194 unsigned long offset)
7195 {
7196 pte_t *pte;
7197
7198 pte = (pte_t *) __get_free_page(GFP_KERNEL);
7199 if (pmd_none(*pmd)) {
7200 if (pte) {
7201 clear_page((unsigned long)pte);
7202 pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte);
7203 return pte + offset;
7204 }
7205 pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE);
7206 return NULL;
7207 }
7208 free_page((unsigned long)pte);
7209 if (pmd_bad(*pmd)) {
7210 __bad_pte_kernel(pmd);
7211 return NULL;
7212 }
7213 return (pte_t *) pmd_page(*pmd) + offset;
7214 }
7215
7216 pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
7217 {
7218 unsigned long pte;
7219
7220 pte = (unsigned long) __get_free_page(GFP_KERNEL);
7221 if (pmd_none(*pmd)) {
7222 if (pte) {
7223 clear_page(pte);
7224 pmd_val(*pmd) = _PAGE_TABLE + __pa(pte);
7225 return (pte_t *)(pte + offset);
7226 }
7227 pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
7228 return NULL;
7229 }
7230 free_page(pte);
7231 if (pmd_bad(*pmd)) {
7232 __bad_pte(pmd);
7233 return NULL;
7234 }
7235 return (pte_t *) (pmd_page(*pmd) + offset);
7236 }
7237
7238 int do_check_pgt_cache(int low, int high)
7239 {
7240 int freed = 0;
7241 if(pgtable_cache_size > high) {
7242 do {
7243 if(pgd_quicklist)
7244 free_pgd_slow(get_pgd_fast()), freed++;
7245 if(pmd_quicklist)
7246 free_pmd_slow(get_pmd_fast()), freed++;
7247 if(pte_quicklist)
7248 free_pte_slow(get_pte_fast()), freed++;
7249 } while(pgtable_cache_size > low);
7250 }
7251 return freed;
7252 }
7253
7254 /* BAD_PAGE is the page that is used for page faults when
7255 * linux is out-of-memory. Older versions of linux just
7256 * did a do_exit(), but using this instead means there is
7257 * less risk for a process dying in kernel mode, possibly
7258 * leaving an inode unused etc..
7259 *
7260 * BAD_PAGETABLE is the accompanying page-table: it is
7261 * initialized to point to BAD_PAGE entries.
7262 *
7263 * ZERO_PAGE is a special page that is used for
7264 * zero-initialized data and COW. */
7265 pte_t * __bad_pagetable(void)
7266 {
7267 extern char empty_bad_page_table[PAGE_SIZE];
7268 int d0, d1;
7269
7270 __asm__ __volatile__("cld ; rep ; stosl"
7271 : "=&D" (d0), "=&c" (d1)
7272 : "a" (pte_val(BAD_PAGE)),
7273 "0" ((long) empty_bad_page_table),
7274 "1" (PAGE_SIZE/4)
7275 : "memory");
7276 return (pte_t *) empty_bad_page_table;
7277 }
7278
7279 pte_t __bad_page(void)
7280 {
7281 extern char empty_bad_page[PAGE_SIZE];
7282 int d0, d1;
7283
7284 __asm__ __volatile__("cld ; rep ; stosl"
7285 : "=&D" (d0), "=&c" (d1)
7286 : "a" (0),
7287 "0" ((long) empty_bad_page),
7288 "1" (PAGE_SIZE/4)
7289 : "memory");
7290 return pte_mkdirty(mk_pte((unsigned long)empty_bad_page
7291 , PAGE_SHARED));
7292 }
7293
7294 void show_mem(void)
7295 {
7296 int i,free = 0,total = 0,reserved = 0;
7297 int shared = 0, cached = 0;
7298
7299 printk("Mem-info:\n");
7300 show_free_areas();
7301 printk("Free swap: %6dkB\n",
7302 nr_swap_pages<<(PAGE_SHIFT-10));
7303 i = max_mapnr;
7304 while (i-- > 0) {
7305 total++;
7306 if (PageReserved(mem_map+i))
7307 reserved++;
7308 else if (PageSwapCache(mem_map+i))
7309 cached++;
7310 else if (!atomic_read(&mem_map[i].count))
7311 free++;
7312 else
7313 shared += atomic_read(&mem_map[i].count) - 1;
7314 }
7315 printk("%d pages of RAM\n",total);
7316 printk("%d reserved pages\n",reserved);
7317 printk("%d pages shared\n",shared);
7318 printk("%d pages swap cached\n",cached);
7319 printk("%ld pages in page table cache\n",
7320 pgtable_cache_size);
7321 show_buffers();
7322 #ifdef CONFIG_NET
7323 show_net_buffers();
7324 #endif
7325 }
7326
7327 extern unsigned long free_area_init(unsigned long,
7328 unsigned long);
7329
7330 /* References to section boundaries */
7331
7332 extern char _text, _etext, _edata, __bss_start, _end;
7333 extern char __init_begin, __init_end;
7334
7335 #define X86_CR4_VME 0x0001 /* enable vm86 extensions */
7336 #define X86_CR4_PVI 0x0002 /* virt intrs flag enable */
7337 #define X86_CR4_TSD 0x0004 /* disable tm stamp at ipl 3*/
7338 #define X86_CR4_DE 0x0008 /* enable debug extensions */
7339 #define X86_CR4_PSE 0x0010 /* enable pg size extensions*/
7340 #define X86_CR4_PAE 0x0020 /* enable phys addr extnsns */
7341 #define X86_CR4_MCE 0x0040 /* Machine check enable */
7342 #define X86_CR4_PGE 0x0080 /* enable global pages */
7343 #define X86_CR4_PCE 0x0100 /* enable performance counters
7344 * at ipl 3 */
7345
7346 /* Save the cr4 feature set we're using (ie Pentium 4MB
7347 * enable and PPro Global page enable), so that any CPU's
7348 * that boot up after us can get the correct flags. */
7349 unsigned long mmu_cr4_features __initdata = 0;
7350
7351 static inline void set_in_cr4(unsigned long mask)
7352 {
7353 mmu_cr4_features |= mask;
7354 __asm__("movl %%cr4,%%eax\n\t"
7355 "orl %0,%%eax\n\t"
7356 "movl %%eax,%%cr4\n"
7357 : : "irg" (mask)
7358 :"ax");
7359 }
7360
7361 /* allocate page table(s) for compile-time fixed
7362 * mappings */
7363 static unsigned long __init fixmap_init(
7364 unsigned long start_mem)
7365 {
7366 pgd_t * pg_dir;
7367 unsigned int idx;
7368 unsigned long address;
7369
7370 start_mem = PAGE_ALIGN(start_mem);
7371
7372 for (idx=1; idx <= __end_of_fixed_addresses;
7373 idx += PTRS_PER_PTE)
7374 {
7375 address =__fix_to_virt(__end_of_fixed_addresses-idx);
7376 pg_dir = swapper_pg_dir + (address >> PGDIR_SHIFT);
7377 memset((void *)start_mem, 0, PAGE_SIZE);
7378 pgd_val(*pg_dir) = _PAGE_TABLE | __pa(start_mem);
7379 start_mem += PAGE_SIZE;
7380 }
7381
7382 return start_mem;
7383 }
7384
7385 static void set_pte_phys (unsigned long vaddr,
7386 unsigned long phys)
7387 {
7388 pgprot_t prot;
7389 pte_t * pte;
7390
7391 pte = pte_offset(pmd_offset(pgd_offset_k(vaddr), vaddr)
7392 , vaddr);
7393 prot = PAGE_KERNEL;
7394 if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
7395 pgprot_val(prot) |= _PAGE_GLOBAL;
7396 set_pte(pte, mk_pte_phys(phys, prot));
7397
7398 local_flush_tlb();
7399 }
7400
7401 void set_fixmap (enum fixed_addresses idx,
7402 unsigned long phys)
7403 {
7404 unsigned long address = __fix_to_virt(idx);
7405
7406 if (idx >= __end_of_fixed_addresses) {
7407 printk("Invalid set_fixmap\n");
7408 return;
7409 }
7410 set_pte_phys (address,phys);
7411 }
7412
7413 /* paging_init() sets up the page tables - note that the
7414 * first 4MB are already mapped by head.S.
7415 *
7416 * This routines also unmaps the page at virtual kernel
7417 * address 0, so that we can trap those pesky
7418 * NULL-reference errors in the kernel. */
7419 __initfunc(unsigned long paging_init(
7420 unsigned long start_mem, unsigned long end_mem))
7421 {
7422 pgd_t * pg_dir;
7423 pte_t * pg_table;
7424 unsigned long tmp;
7425 unsigned long address;
7426
7427 /* Physical page 0 is special; it's not touched by Linux
7428 * since BIOS and SMM (for laptops with [34]86/SL chips)
7429 * may need it. It is read and write protected to detect
7430 * null pointer references in the kernel. It may also
7431 * hold the MP configuration table when we are booting
7432 * SMP. */
7433 start_mem = PAGE_ALIGN(start_mem);
7434 address = PAGE_OFFSET;
7435 pg_dir = swapper_pg_dir;
7436 /* unmap the original low memory mappings */
7437 pgd_val(pg_dir[0]) = 0;
7438
7439 /* Map whole memory from PAGE_OFFSET */
7440 pg_dir += USER_PGD_PTRS;
7441 while (address < end_mem) {
7442 /* If we're running on a Pentium CPU, we can use the
7443 * 4MB page tables.
7444 *
7445 * The page tables we create span up to the next 4MB
7446 * virtual memory boundary, but that's OK as we won't
7447 * use that memory anyway. */
7448 if (boot_cpu_data.x86_capability & X86_FEATURE_PSE) {
7449 unsigned long __pe;
7450
7451 set_in_cr4(X86_CR4_PSE);
7452 boot_cpu_data.wp_works_ok = 1;
7453 __pe = _KERNPG_TABLE + _PAGE_4M + __pa(address);
7454 /* Make it "global" too if supported */
7455 if(boot_cpu_data.x86_capability & X86_FEATURE_PGE){
7456 set_in_cr4(X86_CR4_PGE);
7457 __pe += _PAGE_GLOBAL;
7458 }
7459 pgd_val(*pg_dir) = __pe;
7460 pg_dir++;
7461 address += 4*1024*1024;
7462 continue;
7463 }
7464
7465 /* We're on a [34]86, use normal page tables.
7466 * pg_table is physical at this point */
7467 pg_table = (pte_t *) (PAGE_MASK & pgd_val(*pg_dir));
7468 if (!pg_table) {
7469 pg_table = (pte_t *) __pa(start_mem);
7470 start_mem += PAGE_SIZE;
7471 }
7472
7473 pgd_val(*pg_dir) = _PAGE_TABLE |
7474 (unsigned long) pg_table;
7475 pg_dir++;
7476
7477 /* now change pg_table to kernel virtual addresses */
7478 pg_table = (pte_t *) __va(pg_table);
7479 for (tmp = 0; tmp < PTRS_PER_PTE; tmp++,pg_table++) {
7480 pte_t pte = mk_pte(address, PAGE_KERNEL);
7481 if (address >= end_mem)
7482 pte_val(pte) = 0;
7483 set_pte(pg_table, pte);
7484 address += PAGE_SIZE;
7485 }
7486 }
7487 start_mem = fixmap_init(start_mem);
7488 #ifdef __SMP__
7489 start_mem = init_smp_mappings(start_mem);
7490 #endif
7491 local_flush_tlb();
7492
7493 return free_area_init(start_mem, end_mem);
7494 }
7495
7496 /* Test if the WP bit works in supervisor mode. It isn't
7497 * supported on 386's and also on some strange 486's
7498 * (NexGen etc.). All 586+'s are OK. The jumps before and
7499 * after the test are here to work-around some nasty CPU
7500 * bugs. */
7501 __initfunc(void test_wp_bit(void))
7502 {
7503 unsigned char tmp_reg;
7504 unsigned long old = pg0[0];
7505
7506 printk("Checking if this processor honours the WP bit "
7507 "even in supervisor mode... ");
7508 pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY));
7509 local_flush_tlb();
7510 current->mm->mmap->vm_start += PAGE_SIZE;
7511 __asm__ __volatile__(
7512 "jmp 1f; 1:\n"
7513 "movb %0,%1\n"
7514 "movb %1,%0\n"
7515 "jmp 1f; 1:\n"
7516 :"=m" (*(char *) __va(0)),
7517 "=q" (tmp_reg)
7518 :/* no inputs */
7519 :"memory");
7520 pg0[0] = old;
7521 local_flush_tlb();
7522 current->mm->mmap->vm_start -= PAGE_SIZE;
7523 if (boot_cpu_data.wp_works_ok < 0) {
7524 boot_cpu_data.wp_works_ok = 0;
7525 printk("No.\n");
7526 #ifdef CONFIG_X86_WP_WORKS_OK
7527 panic("This kernel doesn't support CPU's with broken"
7528 " WP. Recompile it for a 386!");
7529 #endif
7530 } else
7531 printk(".\n");
7532 }
7533
7534 __initfunc(void mem_init(unsigned long start_mem,
7535 unsigned long end_mem))
7536 {
7537 unsigned long start_low_mem = PAGE_SIZE;
7538 int codepages = 0;
7539 int reservedpages = 0;
7540 int datapages = 0;
7541 int initpages = 0;
7542 unsigned long tmp;
7543
7544 end_mem &= PAGE_MASK;
7545 high_memory = (void *) end_mem;
7546 max_mapnr = num_physpages = MAP_NR(end_mem);
7547
7548 /* clear the zero-page */
7549 memset(empty_zero_page, 0, PAGE_SIZE);
7550
7551 /* mark usable pages in the mem_map[] */
7552 start_low_mem = PAGE_ALIGN(start_low_mem)+PAGE_OFFSET;
7553
7554 #ifdef __SMP__
7555 /* But first pinch a few for the stack/trampoline stuff
7556 * FIXME: Don't need the extra page at 4K, but need to
7557 * fix trampoline before removing it. (see the GDT
7558 * stuff) */
7559 start_low_mem += PAGE_SIZE; /* 32bit startup code */
7560 /* AP processor stacks */
7561 start_low_mem = smp_alloc_memory(start_low_mem);
7562 #endif
7563 start_mem = PAGE_ALIGN(start_mem);
7564
7565 /* IBM messed up *AGAIN* in their thinkpad: 0xA0000 ->
7566 * 0x9F000. They seem to have done something stupid
7567 * with the floppy controller as well.. */
7568 while (start_low_mem < 0x9f000+PAGE_OFFSET) {
7569 clear_bit(PG_reserved,
7570 &mem_map[MAP_NR(start_low_mem)].flags);
7571 start_low_mem += PAGE_SIZE;
7572 }
7573
7574 while (start_mem < end_mem) {
7575 clear_bit(PG_reserved,
7576 &mem_map[MAP_NR(start_mem)].flags);
7577 start_mem += PAGE_SIZE;
7578 }
7579 for (tmp = PAGE_OFFSET; tmp < end_mem;
7580 tmp += PAGE_SIZE) {
7581 if (tmp >= MAX_DMA_ADDRESS)
7582 clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
7583 if (PageReserved(mem_map+MAP_NR(tmp))) {
7584 if (tmp >= (unsigned long) &_text &&
7585 tmp < (unsigned long) &_edata) {
7586 if (tmp < (unsigned long) &_etext)
7587 codepages++;
7588 else
7589 datapages++;
7590 } else if (tmp >= (unsigned long) &__init_begin
7591 && tmp < (unsigned long) &__init_end)
7592 initpages++;
7593 else if (tmp >= (unsigned long) &__bss_start
7594 && tmp < (unsigned long) start_mem)
7595 datapages++;
7596 else
7597 reservedpages++;
7598 continue;
7599 }
7600 atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
7601 #ifdef CONFIG_BLK_DEV_INITRD
7602 if (!initrd_start || (tmp < initrd_start || tmp >=
7603 initrd_end))
7604 #endif
7605 free_page(tmp);
7606 }
7607 printk("Memory: %luk/%luk available (%dk kernel code, "
7608 "%dk reserved, %dk data, %dk init)\n",
7609 (unsigned long) nr_free_pages << (PAGE_SHIFT-10),
7610 max_mapnr << (PAGE_SHIFT-10),
7611 codepages << (PAGE_SHIFT-10),
7612 reservedpages << (PAGE_SHIFT-10),
7613 datapages << (PAGE_SHIFT-10),
7614 initpages << (PAGE_SHIFT-10));
7615
7616 if (boot_cpu_data.wp_works_ok < 0)
7617 test_wp_bit();
7618 }
7619
7620 void free_initmem(void)
7621 {
7622 unsigned long addr;
7623
7624 addr = (unsigned long)(&__init_begin);
7625 for (; addr < (unsigned long)(&__init_end);
7626 addr += PAGE_SIZE) {
7627 mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
7628 atomic_set(&mem_map[MAP_NR(addr)].count, 1);
7629 free_page(addr);
7630 }
7631 printk("Freeing unused kernel memory: %dk freed\n",
7632 (&__init_end - &__init_begin) >> 10);
7633 }
7634
7635 void si_meminfo(struct sysinfo *val)
7636 {
7637 int i;
7638
7639 i = max_mapnr;
7640 val->totalram = 0;
7641 val->sharedram = 0;
7642 val->freeram = nr_free_pages << PAGE_SHIFT;
7643 val->bufferram = buffermem;
7644 while (i-- > 0) {
7645 if (PageReserved(mem_map+i))
7646 continue;
7647 val->totalram++;
7648 if (!atomic_read(&mem_map[i].count))
7649 continue;
7650 val->sharedram += atomic_read(&mem_map[i].count) - 1;
7651 }
7652 val->totalram <<= PAGE_SHIFT;
7653 val->sharedram <<= PAGE_SHIFT;
7654 return;
7655 }
Сайт управляется системой
uCoz