setup.c
来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 2,464 行 · 第 1/5 页
C
2,464 行
/* * linux/arch/i386/kernel/setup.c * * Copyright (C) 1995 Linus Torvalds * * Enhanced CPU type detection by Mike Jagdis, Patrick St. Jean * and Martin Mares, November 1997. * * Force Cyrix 6x86(MX) and M II processors to report MTRR capability * and Cyrix "coma bug" recognition by * Zolt醤 B鰏z鰎m閚yi <zboszor@mail.externet.hu> February 1999. * * Force Centaur C6 processors to report MTRR capability. * Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999. * * Intel Mobile Pentium II detection fix. Sean Gilley, June 1999. * * IDT Winchip tweaks, misc clean ups. * Dave Jones <davej@suse.de>, August 1999 * * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 * * Better detection of Centaur/IDT WinChip models. * Bart Hartgers <bart@etpmod.phys.tue.nl>, August 1999. * * Memory region support * David Parsons <orc@pell.chi.il.us>, July-August 1999 * * Cleaned up cache-detection code * Dave Jones <davej@suse.de>, October 1999 * * Added proper L2 cache detection for Coppermine * Dragan Stancevic <visitor@valinux.com>, October 1999 * * Added the original array for capability flags but forgot to credit * myself :) (~1998) Fixed/cleaned up some cpu_model_info and other stuff * Jauder Ho <jauderho@carumba.com>, January 2000 * * Detection for Celeron coppermine, identify_cpu() overhauled, * and a few other clean ups. * Dave Jones <davej@suse.de>, April 2000 * * Pentium III FXSR, SSE support * General FPU state handling cleanups * Gareth Hughes <gareth@valinux.com>, May 2000 * * Added proper Cascades CPU and L2 cache detection for Cascades * and 8-way type cache happy bunch from Intel:^) * Dragan Stancevic <visitor@valinux.com>, May 2000 * * Forward port AMD Duron errata T13 from 2.2.17pre * Dave Jones <davej@suse.de>, August 2000 * * Forward port lots of fixes/improvements from 2.2.18pre * Cyrix III, Pentium IV support. * Dave Jones <davej@suse.de>, October 2000 * * Massive cleanup of CPU detection and bug handling; * Transmeta CPU detection, * H. Peter Anvin <hpa@zytor.com>, November 2000 * * Added E820 sanitization routine (removes overlapping memory regions); * Brian Moyle <bmoyle@mvista.com>, February 2001 * * VIA C3 Support. * Dave Jones <davej@suse.de>, March 2001 * * AMD Athlon/Duron/Thunderbird bluesmoke support. * Dave Jones <davej@suse.de>, April 2001. * * CacheSize bug workaround updates for AMD, Intel & VIA Cyrix. * Dave Jones <davej@suse.de>, September, October 2001. * *//* * This file handles the architecture-dependent parts of initialization */#include <linux/errno.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/stddef.h>#include <linux/unistd.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/user.h>#include <linux/a.out.h>#include <linux/tty.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/config.h>#include <linux/init.h>#include <linux/acpi.h>#include <linux/apm_bios.h>#ifdef CONFIG_BLK_DEV_RAM#include <linux/blk.h>#endif#include <linux/highmem.h>#include <linux/bootmem.h>#include <linux/pci.h>#include <linux/pci_ids.h>#include <linux/seq_file.h>#include <linux/console.h>#include <asm/processor.h>#include <asm/mtrr.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/io.h>#include <asm/smp.h>#include <asm/cobalt.h>#include <asm/msr.h>#include <asm/desc.h>#include <asm/e820.h>#include <asm/dma.h>#include <asm/mpspec.h>#include <asm/mmu_context.h>/* * Machine setup.. */char ignore_irq13; /* set if exception 16 works */struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };unsigned long mmu_cr4_features;/* * Bus types .. */int MCA_bus;/* for MCA, but anyone else can use it if they want */unsigned int machine_id;unsigned int machine_submodel_id;unsigned int BIOS_revision;unsigned int mca_pentium_flag;/* For PCI or other memory-mapped resources */unsigned long pci_mem_start = 0x10000000;/* user-defined highmem size */static unsigned int highmem_pages = -1;/* * Setup options */struct drive_info_struct { char dummy[32]; } drive_info;struct screen_info screen_info;struct apm_info apm_info;struct sys_desc_table_struct { unsigned short length; unsigned char table[0];};struct e820map e820;unsigned char aux_device_present;extern void mcheck_init(struct cpuinfo_x86 *c);extern void dmi_scan_machine(void);extern int root_mountflags;extern char _text, _etext, _edata, _end;extern int blk_nohighio;void __init visws_get_board_type_and_rev(void);static int disable_x86_serial_nr __initdata = 1;static int disable_x86_fxsr __initdata = 0;/* * This is set up by the setup-routine at boot-time */#define PARAM ((unsigned char *)empty_zero_page)#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))#define EXT_MEM_K (*(unsigned short *) (PARAM+2))#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))#define E820_MAP_NR (*(char*) (PARAM+E820NR))#define E820_MAP ((struct e820entry *) (PARAM+E820MAP))#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))#define KERNEL_START (*(unsigned long *) (PARAM+0x214))#define INITRD_START (*(unsigned long *) (PARAM+0x218))#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))#define COMMAND_LINE ((char *) (PARAM+2048))#define COMMAND_LINE_SIZE 256#define RAMDISK_IMAGE_START_MASK 0x07FF#define RAMDISK_PROMPT_FLAG 0x8000#define RAMDISK_LOAD_FLAG 0x4000 static char command_line[COMMAND_LINE_SIZE]; char saved_command_line[COMMAND_LINE_SIZE];struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, { "pic1", 0x20, 0x3f, IORESOURCE_BUSY }, { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, { "pic2", 0xa0, 0xbf, IORESOURCE_BUSY }, { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, { "fpu", 0xf0, 0xff, IORESOURCE_BUSY }};#ifdef CONFIG_MELANstandard_io_resources[1] = { "pic1", 0x20, 0x21, IORESOURCE_BUSY };standard_io_resources[5] = { "pic2", 0xa0, 0xa1, IORESOURCE_BUSY };#endif#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))static struct resource code_resource = { "Kernel code", 0x100000, 0 };static struct resource data_resource = { "Kernel data", 0, 0 };static struct resource vram_resource = { "Video RAM area", 0xa0000, 0xbffff, IORESOURCE_BUSY };/* System ROM resources */#define MAXROMS 6static struct resource rom_resources[MAXROMS] = { { "System ROM", 0xF0000, 0xFFFFF, IORESOURCE_BUSY }, { "Video ROM", 0xc0000, 0xc7fff, IORESOURCE_BUSY }};#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)static void __init probe_roms(void){ int roms = 1; unsigned long base; unsigned char *romstart; request_resource(&iomem_resource, rom_resources+0); /* Video ROM is standard at C000:0000 - C7FF:0000, check signature */ for (base = 0xC0000; base < 0xE0000; base += 2048) { romstart = isa_bus_to_virt(base); if (!romsignature(romstart)) continue; request_resource(&iomem_resource, rom_resources + roms); roms++; break; } /* Extension roms at C800:0000 - DFFF:0000 */ for (base = 0xC8000; base < 0xE0000; base += 2048) { unsigned long length; romstart = isa_bus_to_virt(base); if (!romsignature(romstart)) continue; length = romstart[2] * 512; if (length) { unsigned int i; unsigned char chksum; chksum = 0; for (i = 0; i < length; i++) chksum += romstart[i]; /* Good checksum? */ if (!chksum) { rom_resources[roms].start = base; rom_resources[roms].end = base + length - 1; rom_resources[roms].name = "Extension ROM"; rom_resources[roms].flags = IORESOURCE_BUSY; request_resource(&iomem_resource, rom_resources + roms); roms++; if (roms >= MAXROMS) return; } } } /* Final check for motherboard extension rom at E000:0000 */ base = 0xE0000; romstart = isa_bus_to_virt(base); if (romsignature(romstart)) { rom_resources[roms].start = base; rom_resources[roms].end = base + 65535; rom_resources[roms].name = "Extension ROM"; rom_resources[roms].flags = IORESOURCE_BUSY; request_resource(&iomem_resource, rom_resources + roms); }}static void __init add_memory_region(unsigned long long start, unsigned long long size, int type){ int x = e820.nr_map; if (x == E820MAX) { printk(KERN_ERR "Ooops! Too many entries in the memory map!\n"); return; } e820.map[x].addr = start; e820.map[x].size = size; e820.map[x].type = type; e820.nr_map++;} /* add_memory_region */#define E820_DEBUG 1static 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 %lu\n", e820.map[i].type); break; } }}/* * Sanitize the BIOS e820 map. * * Some e820 responses include overlapping entries. The following * replaces the original e820 map with a new one, removing overlaps. * */static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map){ struct change_member { struct e820entry *pbios; /* pointer to original bios entry */ unsigned long long addr; /* address for this change point */ }; struct change_member change_point_list[2*E820MAX]; struct change_member *change_point[2*E820MAX]; struct e820entry *overlap_list[E820MAX]; struct e820entry new_bios[E820MAX]; struct change_member *change_tmp; unsigned long current_type, last_type; unsigned long long last_addr; int chgidx, still_changing; int overlap_entries; int new_bios_entry; int old_nr, new_nr; int i; /* Visually we're performing the following (1,2,3,4 = memory types)... Sample memory map (w/overlaps): ____22__________________ ______________________4_ ____1111________________ _44_____________________ 11111111________________ ____________________33__ ___________44___________ __________33333_________ ______________22________ ___________________2222_ _________111111111______ _____________________11_ _________________4______ Sanitized equivalent (no overlap): 1_______________________ _44_____________________ ___1____________________ ____22__________________ ______11________________ _________1______________ __________3_____________ ___________44___________ _____________33_________ _______________2________ ________________1_______ _________________4______ ___________________2____ ____________________33__ ______________________4_ */ /* if there's only one memory region, don't bother */ if (*pnr_map < 2) return -1; old_nr = *pnr_map; /* bail out if we find any unreasonable addresses in bios map */ for (i=0; i<old_nr; i++) if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) return -1; /* create pointers for initial change-point information (for sorting) */ for (i=0; i < 2*old_nr; i++) change_point[i] = &change_point_list[i]; /* record all known change-points (starting and ending addresses) */ chgidx = 0; for (i=0; i < old_nr; i++) { change_point[chgidx]->addr = biosmap[i].addr; change_point[chgidx++]->pbios = &biosmap[i]; change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size; change_point[chgidx++]->pbios = &biosmap[i]; } /* sort change-point list by memory addresses (low -> high) */ still_changing = 1; while (still_changing) { still_changing = 0; for (i=1; i < 2*old_nr; i++) { /* if <current_addr> > <last_addr>, swap */ /* or, if current=<start_addr> & last=<end_addr>, swap */ if ((change_point[i]->addr < change_point[i-1]->addr) || ((change_point[i]->addr == change_point[i-1]->addr) && (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 < 2*old_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; } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?