📄 init.c
字号:
/* $Id: init.c,v 1.96 2000/11/30 08:51:50 anton Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) */#include <linux/config.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/types.h>#include <linux/ptrace.h>#include <linux/mman.h>#include <linux/mm.h>#include <linux/swap.h>#include <linux/swapctl.h>#ifdef CONFIG_BLK_DEV_INITRD#include <linux/blk.h>#endif#include <linux/init.h>#include <linux/highmem.h>#include <linux/bootmem.h>#include <asm/system.h>#include <asm/segment.h>#include <asm/vac-ops.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/vaddrs.h>unsigned long *sparc_valid_addr_bitmap;unsigned long phys_base;unsigned long page_kernel;struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];unsigned long sparc_unmapped_base;struct pgtable_cache_struct pgt_quicklists;/* References to section boundaries */extern char __init_begin, __init_end, _start, _end, etext , edata;/* Initial ramdisk setup */extern unsigned int sparc_ramdisk_image;extern unsigned int sparc_ramdisk_size;unsigned long highstart_pfn, highend_pfn;unsigned long totalram_pages;static unsigned long totalhigh_pages;/* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a * do_exit(), but using this instead means there is less risk * for a process dying in kernel mode, possibly leaving an inode * unused etc.. * * BAD_PAGETABLE is the accompanying page-table: it is initialized * to point to BAD_PAGE entries. * * ZERO_PAGE is a special page that is used for zero-initialized * data and COW. */pte_t *__bad_pagetable(void){ memset((void *) &empty_bad_page_table, 0, PAGE_SIZE); return (pte_t *) &empty_bad_page_table;}pte_t __bad_page(void){ memset((void *) &empty_bad_page, 0, PAGE_SIZE); return pte_mkdirty(mk_pte_phys((unsigned long)__pa(&empty_bad_page) + phys_base, PAGE_SHARED));}pte_t *kmap_pte;pgprot_t kmap_prot;#define kmap_get_fixed_pte(vaddr) \ pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))void __init kmap_init(void){ /* cache the first kmap pte */ kmap_pte = kmap_get_fixed_pte(FIX_KMAP_BEGIN); kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE);}void show_mem(void){ printk("Mem-info:\n"); show_free_areas(); printk("Free swap: %6dkB\n", nr_swap_pages << (PAGE_SHIFT-10)); printk("%ld pages of RAM\n", totalram_pages); printk("%d free pages\n", nr_free_pages()); printk("%ld pages in page table cache\n",pgtable_cache_size);#ifndef CONFIG_SMP if (sparc_cpu_model == sun4m || sparc_cpu_model == sun4d) printk("%ld entries in page dir cache\n",pgd_cache_size);#endif show_buffers();}extern pgprot_t protection_map[16];void __init sparc_context_init(int numctx){ int ctx; ctx_list_pool = __alloc_bootmem(numctx * sizeof(struct ctx_list), SMP_CACHE_BYTES, 0UL); for(ctx = 0; ctx < numctx; ctx++) { struct ctx_list *clist; clist = (ctx_list_pool + ctx); clist->ctx_number = ctx; clist->ctx_mm = 0; } ctx_free.next = ctx_free.prev = &ctx_free; ctx_used.next = ctx_used.prev = &ctx_used; for(ctx = 0; ctx < numctx; ctx++) add_to_free_ctxlist(ctx_list_pool + ctx);}#define DEBUG_BOOTMEMextern unsigned long cmdline_memory_size;extern unsigned long last_valid_pfn;void __init bootmem_init(void){ unsigned long bootmap_size, start_pfn, max_pfn; unsigned long end_of_phys_memory = 0UL; unsigned long bootmap_pfn; int i; /* XXX It is a bit ambiguous here, whether we should * XXX treat the user specified mem=xxx as total wanted * XXX physical memory, or as a limit to the upper * XXX physical address we allow. For now it is the * XXX latter. -DaveM */#ifdef DEBUG_BOOTMEM prom_printf("bootmem_init: Scan sp_banks, ");#endif for (i = 0; sp_banks[i].num_bytes != 0; i++) { end_of_phys_memory = sp_banks[i].base_addr + sp_banks[i].num_bytes; if (cmdline_memory_size) { if (end_of_phys_memory > cmdline_memory_size) { if (cmdline_memory_size < sp_banks[i].base_addr) { end_of_phys_memory = sp_banks[i-1].base_addr + sp_banks[i-1].num_bytes; sp_banks[i].base_addr = 0xdeadbeef; sp_banks[i].num_bytes = 0; } else { sp_banks[i].num_bytes -= (end_of_phys_memory - cmdline_memory_size); end_of_phys_memory = cmdline_memory_size; sp_banks[++i].base_addr = 0xdeadbeef; sp_banks[i].num_bytes = 0; } break; } } } /* Start with page aligned address of last symbol in kernel * image. */ start_pfn = (unsigned long)__pa(PAGE_ALIGN((unsigned long) &_end)); /* Adjust up to the physical address where the kernel begins. */ start_pfn += phys_base; /* Now shift down to get the real physical page frame number. */ start_pfn >>= PAGE_SHIFT; bootmap_pfn = start_pfn; max_pfn = end_of_phys_memory >> PAGE_SHIFT; max_low_pfn = max_pfn; highstart_pfn = highend_pfn = max_pfn; if (max_low_pfn > (SRMMU_MAXMEM >> PAGE_SHIFT)) { highstart_pfn = max_low_pfn = (SRMMU_MAXMEM >> PAGE_SHIFT); printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", (highend_pfn - highstart_pfn) >> (20-PAGE_SHIFT)); }#ifdef CONFIG_BLK_DEV_INITRD /* Now have to check initial ramdisk, so that bootmap does not overwrite it */ if (sparc_ramdisk_image) { if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE) sparc_ramdisk_image -= KERNBASE; initrd_start = sparc_ramdisk_image + phys_base; initrd_end = initrd_start + sparc_ramdisk_size; if (initrd_end > end_of_phys_memory) { printk(KERN_CRIT "initrd extends beyond end of memory " "(0x%016lx > 0x%016lx)\ndisabling initrd\n", initrd_end, end_of_phys_memory); initrd_start = 0; } if (initrd_start) { if (initrd_start >= (start_pfn << PAGE_SHIFT) && initrd_start < (start_pfn << PAGE_SHIFT) + 2 * PAGE_SIZE) bootmap_pfn = PAGE_ALIGN (initrd_end) >> PAGE_SHIFT; } }#endif /* Initialize the boot-time allocator. */#ifdef DEBUG_BOOTMEM prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],mlpfn[%lx])\n", start_pfn, bootmap_pfn, max_low_pfn);#endif bootmap_size = init_bootmem(bootmap_pfn, max_low_pfn); /* Now register the available physical memory with the * allocator. */ for (i = 0; sp_banks[i].num_bytes != 0; i++) { unsigned long curr_pfn, last_pfn, size; curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; if (curr_pfn >= max_low_pfn) break; last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT; if (last_pfn > max_low_pfn) last_pfn = max_low_pfn; /* * .. finally, did all the rounding and playing * around just make the area go away? */ if (last_pfn <= curr_pfn) continue; size = (last_pfn - curr_pfn) << PAGE_SHIFT;#ifdef DEBUG_BOOTMEM prom_printf("free_bootmem: base[%lx] size[%lx]\n", sp_banks[i].base_addr, size);#endif free_bootmem(sp_banks[i].base_addr, size); } /* Reserve the kernel text/data/bss, the bootmem bitmap and initrd. */#ifdef DEBUG_BOOTMEM#ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", initrd_start, initrd_end - initrd_start);#endif prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", phys_base, (start_pfn << PAGE_SHIFT) - phys_base); prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", (bootmap_pfn << PAGE_SHIFT), bootmap_size);#endif#ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) { reserve_bootmem(initrd_start, initrd_end - initrd_start); initrd_start += PAGE_OFFSET; initrd_end += PAGE_OFFSET; }#endif reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base); reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size); last_valid_pfn = max_pfn;}/* * paging_init() sets up the page tables: We call the MMU specific * init routine based upon the Sun model type on the Sparc. * */extern void sun4c_paging_init(void);extern void srmmu_paging_init(void);extern void device_scan(void);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -