init.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 607 行 · 第 1/2 页

C
607
字号
static unsigned long low_pml4[NR_CPUS];void swap_low_mappings(void){	int i;	for (i = 0; i < NR_CPUS; i++) {	        unsigned long t;		if (!cpu_pda[i].level4_pgt) 			continue;		t = cpu_pda[i].level4_pgt[0];		cpu_pda[i].level4_pgt[0] = low_pml4[i];		low_pml4[i] = t;	}	flush_tlb_all();}void zap_low_mappings(void){	swap_low_mappings();}#ifndef CONFIG_DISCONTIGMEMvoid __init paging_init(void){	{		unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};		unsigned int max_dma;		max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;		if (end_pfn < max_dma)			zones_size[ZONE_DMA] = end_pfn;		else {			zones_size[ZONE_DMA] = max_dma;			zones_size[ZONE_NORMAL] = end_pfn - max_dma;		}		free_area_init(zones_size);	}	return;}#endif/* Unmap a kernel mapping if it exists. This is useful to avoid prefetches   from the CPU leading to inconsistent cache lines. address and size   must be aligned to 2MB boundaries.    Does nothing when the mapping doesn't exist. */void __init clear_kernel_mapping(unsigned long address, unsigned long size) {	unsigned long end = address + size;	BUG_ON(address & ~LARGE_PAGE_MASK);	BUG_ON(size & ~LARGE_PAGE_MASK); 		for (; address < end; address += LARGE_PAGE_SIZE) { 		pgd_t *pgd = pgd_offset_k(address);               pmd_t *pmd;		if (!pgd || pgd_none(*pgd))			continue;                pmd = pmd_offset(pgd, address);		if (!pmd || pmd_none(*pmd))			continue; 		if (0 == (pmd_val(*pmd) & _PAGE_PSE)) { 			/* Could handle this, but it should not happen currently. */			printk(KERN_ERR 	       "clear_kernel_mapping: mapping has been split. will leak memory\n"); 			pmd_ERROR(*pmd); 		}		set_pmd(pmd, __pmd(0)); 			}	__flush_tlb_all();} static inline int page_is_ram (unsigned long pagenr){	int i;	for (i = 0; i < e820.nr_map; i++) {		unsigned long addr, end;		if (e820.map[i].type != E820_RAM)	/* not usable memory */			continue;		/*		 *	!!!FIXME!!! Some BIOSen report areas as RAM that		 *	are not. Notably the 640->1Mb area. We need a sanity		 *	check here.		 */		addr = (e820.map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT;		end = (e820.map[i].addr+e820.map[i].size) >> PAGE_SHIFT;		if  ((pagenr >= addr) && (pagenr < end))			return 1;	}	return 0;}static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,			 kcore_vsyscall;void __init mem_init(void){	int codesize, reservedpages, datasize, initsize;	int tmp;#ifdef CONFIG_SWIOTLB	if (!iommu_aperture && end_pfn >= 0xffffffff>>PAGE_SHIFT)	       swiotlb = 1;	if (swiotlb)		swiotlb_init();	#endif	/* How many end-of-memory variables you have, grandma! */	max_low_pfn = end_pfn;	max_pfn = end_pfn;	num_physpages = end_pfn;	high_memory = (void *) __va(end_pfn * PAGE_SIZE);	/* clear the zero-page */	memset(empty_zero_page, 0, PAGE_SIZE);	reservedpages = 0;	/* this will put all low memory onto the freelists */#ifdef CONFIG_DISCONTIGMEM	totalram_pages += numa_free_all_bootmem();	tmp = 0;	/* should count reserved pages here for all nodes */ #else	max_mapnr = end_pfn;	if (!mem_map) BUG();	totalram_pages += free_all_bootmem();	for (tmp = 0; tmp < end_pfn; tmp++)		/*		 * Only count reserved RAM pages		 */		if (page_is_ram(tmp) && PageReserved(mem_map+tmp))			reservedpages++;#endif	after_bootmem = 1;	codesize =  (unsigned long) &_etext - (unsigned long) &_text;	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;	/* Register memory areas for /proc/kcore */	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); 	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, 		   VMALLOC_END-VMALLOC_START);	kclist_add(&kcore_kernel, &_stext, _end - _stext);	kclist_add(&kcore_modules, (void *)MODULES_VADDR, MODULES_LEN);	kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, 				 VSYSCALL_END - VSYSCALL_START);	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),		end_pfn << (PAGE_SHIFT-10),		codesize >> 10,		reservedpages << (PAGE_SHIFT-10),		datasize >> 10,		initsize >> 10);	/*	 * Subtle. SMP is doing its boot stuff late (because it has to	 * fork idle threads) - but it also needs low mappings for the	 * protected-mode entry to work. We zap these entries only after	 * the WP-bit has been tested.	 */#ifndef CONFIG_SMP	zap_low_mappings();#endif}void free_initmem(void){	unsigned long addr;	addr = (unsigned long)(&__init_begin);	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {		ClearPageReserved(virt_to_page(addr));		set_page_count(virt_to_page(addr), 1);#ifdef CONFIG_INIT_DEBUG		memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); #endif		free_page(addr);		totalram_pages++;	}	printk ("Freeing unused kernel memory: %luk freed\n", (&__init_end - &__init_begin) >> 10);}#ifdef CONFIG_BLK_DEV_INITRDvoid free_initrd_mem(unsigned long start, unsigned long end){	if (start < (unsigned long)&_end)		return;	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);	for (; start < end; start += PAGE_SIZE) {		ClearPageReserved(virt_to_page(start));		set_page_count(virt_to_page(start), 1);		free_page(start);		totalram_pages++;	}}#endifvoid __init reserve_bootmem_generic(unsigned long phys, unsigned len) { 	/* Should check here against the e820 map to avoid double free */ #ifdef CONFIG_DISCONTIGMEM	int nid = phys_to_nid(phys);  	reserve_bootmem_node(NODE_DATA(nid), phys, len);#else       			reserve_bootmem(phys, len);    #endif}int kern_addr_valid(unsigned long addr) { 	unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;       pml4_t *pml4;       pgd_t *pgd;       pmd_t *pmd;       pte_t *pte;	if (above != 0 && above != -1UL)		return 0; 	       pml4 = pml4_offset_k(addr);	if (pml4_none(*pml4))		return 0;       pgd = pgd_offset_k(addr);	if (pgd_none(*pgd))		return 0;        pmd = pmd_offset(pgd, addr);	if (pmd_none(*pmd))		return 0;	if (pmd_large(*pmd))		return pfn_valid(pmd_pfn(*pmd));       pte = pte_offset_kernel(pmd, addr);	if (pte_none(*pte))		return 0;	return pfn_valid(pte_pfn(*pte));}#ifdef CONFIG_SYSCTL#include <linux/sysctl.h>extern int exception_trace, page_fault_trace;static ctl_table debug_table2[] = {	{ 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL,	  proc_dointvec },#ifdef CONFIG_CHECKING	{ 100, "page-fault-trace", &page_fault_trace, sizeof(int), 0644, NULL,	  proc_dointvec },#endif	{ 0, }}; static ctl_table debug_root_table2[] = { 	{ .ctl_name = CTL_DEBUG, .procname = "debug", .mode = 0555, 	   .child = debug_table2 }, 	{ 0 }, }; static __init int x8664_sysctl_init(void){ 	register_sysctl_table(debug_root_table2, 1);	return 0;}__initcall(x8664_sysctl_init);#endif/* Pseudo VMAs to allow ptrace access for the vsyscall pages.  x86-64 has two   different ones: one for 32bit and one for 64bit. Use the appropiate   for the target task. */static struct vm_area_struct gate_vma = {	.vm_start = VSYSCALL_START,	.vm_end = VSYSCALL_END,	.vm_page_prot = PAGE_READONLY};static struct vm_area_struct gate32_vma = {	.vm_start = VSYSCALL32_BASE,	.vm_end = VSYSCALL32_END,	.vm_page_prot = PAGE_READONLY};struct vm_area_struct *get_gate_vma(struct task_struct *tsk){	return test_tsk_thread_flag(tsk, TIF_IA32) ? &gate32_vma : &gate_vma;}int in_gate_area(struct task_struct *task, unsigned long addr){	struct vm_area_struct *vma = get_gate_vma(task);	return (addr >= vma->vm_start) && (addr < vma->vm_end);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?