⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 e820_32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
				 (change_point[i]->addr == change_point[i]->pbios->addr) &&				 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))			   )			{				change_tmp = change_point[i];				change_point[i] = change_point[i-1];				change_point[i-1] = change_tmp;				still_changing=1;			}		}	}	/* create a new bios memory map, removing overlaps */	overlap_entries=0;	 /* number of entries in the overlap table */	new_bios_entry=0;	 /* index for creating new bios map entries */	last_type = 0;		 /* start with undefined memory type */	last_addr = 0;		 /* start with 0 as last starting address */	/* loop through change-points, determining affect on the new bios map */	for (chgidx=0; chgidx < chg_nr; chgidx++)	{		/* keep track of all overlapping bios entries */		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)		{			/* add map entry to overlap list (> 1 entry implies an overlap) */			overlap_list[overlap_entries++]=change_point[chgidx]->pbios;		}		else		{			/* remove entry from list (order independent, so swap with last) */			for (i=0; i<overlap_entries; i++)			{				if (overlap_list[i] == change_point[chgidx]->pbios)					overlap_list[i] = overlap_list[overlap_entries-1];			}			overlap_entries--;		}		/* if there are overlapping entries, decide which "type" to use */		/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */		current_type = 0;		for (i=0; i<overlap_entries; i++)			if (overlap_list[i]->type > current_type)				current_type = overlap_list[i]->type;		/* continue building up new bios map based on this information */		if (current_type != last_type)	{			if (last_type != 0)	 {				new_bios[new_bios_entry].size =					change_point[chgidx]->addr - last_addr;				/* move forward only if the new size was non-zero */				if (new_bios[new_bios_entry].size != 0)					if (++new_bios_entry >= E820MAX)						break; 	/* no more space left for new bios entries */			}			if (current_type != 0)	{				new_bios[new_bios_entry].addr = change_point[chgidx]->addr;				new_bios[new_bios_entry].type = current_type;				last_addr=change_point[chgidx]->addr;			}			last_type = current_type;		}	}	new_nr = new_bios_entry;   /* retain count for new bios entries */	/* copy new bios mapping into original location */	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));	*pnr_map = new_nr;	return 0;}/* * Copy the BIOS e820 map into a safe place. * * Sanity-check it while we're at it.. * * If we're lucky and live on a modern system, the setup code * will have given us a memory map that we can use to properly * set up memory.  If we aren't, we'll fake a memory map. * * We check to see that the memory map contains at least 2 elements * before we'll use it, because the detection code in setup.S may * not be perfect and most every PC known to man has two memory * regions: one from 0 to 640k, and one from 1mb up.  (The IBM * thinkpad 560x, for example, does not cooperate with the memory * detection code.) */int __init copy_e820_map(struct e820entry * biosmap, int nr_map){	/* Only one memory region (or negative)? Ignore it */	if (nr_map < 2)		return -1;	do {		unsigned long long start = biosmap->addr;		unsigned long long size = biosmap->size;		unsigned long long end = start + size;		unsigned long type = biosmap->type;		/* Overflow in 64 bits? Ignore the memory map. */		if (start > end)			return -1;		/*		 * Some BIOSes claim RAM in the 640k - 1M region.		 * Not right. Fix it up.		 */		if (type == E820_RAM) {			if (start < 0x100000ULL && end > 0xA0000ULL) {				if (start < 0xA0000ULL)					add_memory_region(start, 0xA0000ULL-start, type);				if (end <= 0x100000ULL)					continue;				start = 0x100000ULL;				size = end - start;			}		}		add_memory_region(start, size, type);	} while (biosmap++,--nr_map);	return 0;}/* * Callback for efi_memory_walk. */static int __initefi_find_max_pfn(unsigned long start, unsigned long end, void *arg){	unsigned long *max_pfn = arg, pfn;	if (start < end) {		pfn = PFN_UP(end -1);		if (pfn > *max_pfn)			*max_pfn = pfn;	}	return 0;}static int __initefi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg){	memory_present(0, PFN_UP(start), PFN_DOWN(end));	return 0;}/* * Find the highest page frame number we have available */void __init find_max_pfn(void){	int i;	max_pfn = 0;	if (efi_enabled) {		efi_memmap_walk(efi_find_max_pfn, &max_pfn);		efi_memmap_walk(efi_memory_present_wrapper, NULL);		return;	}	for (i = 0; i < e820.nr_map; i++) {		unsigned long start, end;		/* RAM? */		if (e820.map[i].type != E820_RAM)			continue;		start = PFN_UP(e820.map[i].addr);		end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);		if (start >= end)			continue;		if (end > max_pfn)			max_pfn = end;		memory_present(0, start, end);	}}/* * Free all available memory for boot time allocation.  Used * as a callback function by efi_memory_walk() */static int __initfree_available_memory(unsigned long start, unsigned long end, void *arg){	/* check max_low_pfn */	if (start >= (max_low_pfn << PAGE_SHIFT))		return 0;	if (end >= (max_low_pfn << PAGE_SHIFT))		end = max_low_pfn << PAGE_SHIFT;	if (start < end)		free_bootmem(start, end - start);	return 0;}/* * Register fully available low RAM pages with the bootmem allocator. */void __init register_bootmem_low_pages(unsigned long max_low_pfn){	int i;	if (efi_enabled) {		efi_memmap_walk(free_available_memory, NULL);		return;	}	for (i = 0; i < e820.nr_map; i++) {		unsigned long curr_pfn, last_pfn, size;		/*		 * Reserve usable low memory		 */		if (e820.map[i].type != E820_RAM)			continue;		/*		 * We are rounding up the start address of usable memory:		 */		curr_pfn = PFN_UP(e820.map[i].addr);		if (curr_pfn >= max_low_pfn)			continue;		/*		 * ... and at the end of the usable range downwards:		 */		last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);		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;		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));	}}void __init e820_register_memory(void){	unsigned long gapstart, gapsize, round;	unsigned long long last;	int i;	/*	 * Search for the biggest gap in the low 32 bits of the e820	 * memory space.	 */	last = 0x100000000ull;	gapstart = 0x10000000;	gapsize = 0x400000;	i = e820.nr_map;	while (--i >= 0) {		unsigned long long start = e820.map[i].addr;		unsigned long long end = start + e820.map[i].size;		/*		 * Since "last" is at most 4GB, we know we'll		 * fit in 32 bits if this condition is true		 */		if (last > end) {			unsigned long gap = last - end;			if (gap > gapsize) {				gapsize = gap;				gapstart = end;			}		}		if (start < last)			last = start;	}	/*	 * See how much we want to round up: start off with	 * rounding to the next 1MB area.	 */	round = 0x100000;	while ((gapsize >> 4) > round)		round += round;	/* Fun with two's complement */	pci_mem_start = (gapstart + round) & -round;	printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",		pci_mem_start, gapstart, gapsize);}void __init print_memory_map(char *who){	int i;	for (i = 0; i < e820.nr_map; i++) {		printk(" %s: %016Lx - %016Lx ", who,			e820.map[i].addr,			e820.map[i].addr + e820.map[i].size);		switch (e820.map[i].type) {		case E820_RAM:	printk("(usable)\n");				break;		case E820_RESERVED:				printk("(reserved)\n");				break;		case E820_ACPI:				printk("(ACPI data)\n");				break;		case E820_NVS:				printk("(ACPI NVS)\n");				break;		default:	printk("type %u\n", e820.map[i].type);				break;		}	}}static __init __always_inline void efi_limit_regions(unsigned long long size){	unsigned long long current_addr = 0;	efi_memory_desc_t *md, *next_md;	void *p, *p1;	int i, j;	j = 0;	p1 = memmap.map;	for (p = p1, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) {		md = p;		next_md = p1;		current_addr = md->phys_addr +			PFN_PHYS(md->num_pages);		if (is_available_memory(md)) {			if (md->phys_addr >= size) continue;			memcpy(next_md, md, memmap.desc_size);			if (current_addr >= size) {				next_md->num_pages -=					PFN_UP(current_addr-size);			}			p1 += memmap.desc_size;			next_md = p1;			j++;		} else if ((md->attribute & EFI_MEMORY_RUNTIME) ==			   EFI_MEMORY_RUNTIME) {			/* In order to make runtime services			 * available we have to include runtime			 * memory regions in memory map */			memcpy(next_md, md, memmap.desc_size);			p1 += memmap.desc_size;			next_md = p1;			j++;		}	}	memmap.nr_map = j;	memmap.map_end = memmap.map +		(memmap.nr_map * memmap.desc_size);}void __init limit_regions(unsigned long long size){	unsigned long long current_addr;	int i;	print_memory_map("limit_regions start");	if (efi_enabled) {		efi_limit_regions(size);		return;	}	for (i = 0; i < e820.nr_map; i++) {		current_addr = e820.map[i].addr + e820.map[i].size;		if (current_addr < size)			continue;		if (e820.map[i].type != E820_RAM)			continue;		if (e820.map[i].addr >= size) {			/*			 * This region starts past the end of the			 * requested size, skip it completely.			 */			e820.nr_map = i;		} else {			e820.nr_map = i + 1;			e820.map[i].size -= current_addr - size;		}		print_memory_map("limit_regions endfor");		return;	}	print_memory_map("limit_regions endfunc");}/* * This function checks if any part of the range <start,end> is mapped * with type. */inte820_any_mapped(u64 start, u64 end, unsigned type){	int i;	for (i = 0; i < e820.nr_map; i++) {		const struct e820entry *ei = &e820.map[i];		if (type && ei->type != type)			continue;		if (ei->addr >= end || ei->addr + ei->size <= start)			continue;		return 1;	}	return 0;}EXPORT_SYMBOL_GPL(e820_any_mapped); /*  * This function checks if the entire range <start,end> is mapped with type.  *  * Note: this function only works correct if the e820 table is sorted and  * not-overlapping, which is the case  */int __inite820_all_mapped(unsigned long s, unsigned long e, unsigned type){	u64 start = s;	u64 end = e;	int i;	for (i = 0; i < e820.nr_map; i++) {		struct e820entry *ei = &e820.map[i];		if (type && ei->type != type)			continue;		/* is the region (part) in overlap with the current region ?*/		if (ei->addr >= end || ei->addr + ei->size <= start)			continue;		/* if the region is at the beginning of <start,end> we move		 * start to the end of the region since it's ok until there		 */		if (ei->addr <= start)			start = ei->addr + ei->size;		/* if start is now at or beyond end, we're done, full		 * coverage */		if (start >= end)			return 1; /* we're done */	}	return 0;}static int __init parse_memmap(char *arg){	if (!arg)		return -EINVAL;	if (strcmp(arg, "exactmap") == 0) {#ifdef CONFIG_CRASH_DUMP		/* If we are doing a crash dump, we		 * still need to know the real mem		 * size before original memory map is		 * reset.		 */		find_max_pfn();		saved_max_pfn = max_pfn;#endif		e820.nr_map = 0;		user_defined_memmap = 1;	} else {		/* If the user specifies memory size, we		 * limit the BIOS-provided memory map to		 * that size. exactmap can be used to specify		 * the exact map. mem=number can be used to		 * trim the existing memory map.		 */		unsigned long long start_at, mem_size;		mem_size = memparse(arg, &arg);		if (*arg == '@') {			start_at = memparse(arg+1, &arg);			add_memory_region(start_at, mem_size, E820_RAM);		} else if (*arg == '#') {			start_at = memparse(arg+1, &arg);			add_memory_region(start_at, mem_size, E820_ACPI);		} else if (*arg == '$') {			start_at = memparse(arg+1, &arg);			add_memory_region(start_at, mem_size, E820_RESERVED);		} else {			limit_regions(mem_size);			user_defined_memmap = 1;		}	}	return 0;}early_param("memmap", parse_memmap);

⌨️ 快捷键说明

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