📄 setup.c
字号:
add_memory_region(0, LOWMEMSIZE(), E820_RAM); } mem_size = memparse(from+4, &from); if (*from == '@') start_at = memparse(from+1, &from); else { start_at = HIGH_MEMORY; mem_size -= HIGH_MEMORY; usermem=0; } add_memory_region(start_at, mem_size, E820_RAM); } } c = *(from++); if (!c) break; if (COMMAND_LINE_SIZE <= ++len) break; *(to++) = c; } *to = '\0'; *cmdline_p = command_line; if (usermem) { printk("user-defined physical RAM map:\n"); print_memory_map("user"); }}void __init setup_arch(char **cmdline_p){ unsigned long bootmap_size; unsigned long start_pfn, max_pfn, max_low_pfn; int i;#ifdef CONFIG_VISWS visws_get_board_type_and_rev();#endif ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); drive_info = DRIVE_INFO; screen_info = SCREEN_INFO; apm_info.bios = APM_BIOS_INFO; if( SYS_DESC_TABLE.length != 0 ) { MCA_bus = SYS_DESC_TABLE.table[3] &0x2; machine_id = SYS_DESC_TABLE.table[0]; machine_submodel_id = SYS_DESC_TABLE.table[1]; BIOS_revision = SYS_DESC_TABLE.table[2]; } aux_device_present = AUX_DEVICE_INFO;#ifdef CONFIG_BLK_DEV_RAM rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);#endif setup_memory_region(); if (!MOUNT_ROOT_RDONLY) root_mountflags &= ~MS_RDONLY; init_mm.start_code = (unsigned long) &_text; init_mm.end_code = (unsigned long) &_etext; init_mm.end_data = (unsigned long) &_edata; init_mm.brk = (unsigned long) &_end; code_resource.start = virt_to_bus(&_text); code_resource.end = virt_to_bus(&_etext)-1; data_resource.start = virt_to_bus(&_etext); data_resource.end = virt_to_bus(&_edata)-1; parse_mem_cmdline(cmdline_p);#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)#define PFN_PHYS(x) ((x) << PAGE_SHIFT)/* * 128MB for vmalloc and initrd */#define VMALLOC_RESERVE (unsigned long)(128 << 20)#define MAXMEM (unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE)#define MAXMEM_PFN PFN_DOWN(MAXMEM)#define MAX_NONPAE_PFN (1 << 20) /* * partially used pages are not usable - thus * we are rounding upwards: */ start_pfn = PFN_UP(__pa(&_end)); /* * Find the highest page frame number we have available */ max_pfn = 0; 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; } /* * Determine low and high memory ranges: */ max_low_pfn = max_pfn; if (max_low_pfn > MAXMEM_PFN) { max_low_pfn = MAXMEM_PFN;#ifndef CONFIG_HIGHMEM /* Maximum memory usable is what is directly addressable */ printk(KERN_WARNING "Warning only %ldMB will be used.\n", MAXMEM>>20); if (max_pfn > MAX_NONPAE_PFN) printk(KERN_WARNING "Use a PAE enabled kernel.\n"); else printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");#else /* !CONFIG_HIGHMEM */#ifndef CONFIG_X86_PAE if (max_pfn > MAX_NONPAE_PFN) { max_pfn = MAX_NONPAE_PFN; printk(KERN_WARNING "Warning only 4GB will be used.\n"); printk(KERN_WARNING "Use a PAE enabled kernel.\n"); }#endif /* !CONFIG_X86_PAE */#endif /* !CONFIG_HIGHMEM */ }#ifdef CONFIG_HIGHMEM highstart_pfn = highend_pfn = max_pfn; if (max_pfn > MAXMEM_PFN) { highstart_pfn = MAXMEM_PFN; printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", pages_to_mb(highend_pfn - highstart_pfn)); }#endif /* * Initialize the boot-time allocator (with low memory only): */ bootmap_size = init_bootmem(start_pfn, max_low_pfn); /* * Register fully available low RAM pages with the bootmem allocator. */ 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)); } /* * Reserve the bootmem bitmap itself as well. We do this in two * steps (first step was init_bootmem()) because this catches * the (very unlikely) case of us accidentally initializing the * bootmem allocator with an invalid RAM area. */ reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY)); /* * reserve physical page 0 - it's a special BIOS page on many boxes, * enabling clean reboots, SMP operation, laptop functions. */ reserve_bootmem(0, PAGE_SIZE);#ifdef CONFIG_SMP /* * But first pinch a few for the stack/trampoline stuff * FIXME: Don't need the extra page at 4K, but need to fix * trampoline before removing it. (see the GDT stuff) */ reserve_bootmem(PAGE_SIZE, PAGE_SIZE); smp_alloc_memory(); /* AP processor realmode stacks in low memory*/#endif#ifdef CONFIG_X86_IO_APIC /* * Find and reserve possible boot-time SMP configuration: */ find_smp_config();#endif paging_init();#ifdef CONFIG_X86_IO_APIC /* * get boot-time SMP configuration: */ if (smp_found_config) get_smp_config();#endif#ifdef CONFIG_X86_LOCAL_APIC init_apic_mappings();#endif#ifdef CONFIG_BLK_DEV_INITRD if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { reserve_bootmem(INITRD_START, INITRD_SIZE); initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0; initrd_end = initrd_start+INITRD_SIZE; } else { printk("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", INITRD_START + INITRD_SIZE, max_low_pfn << PAGE_SHIFT); initrd_start = 0; } }#endif /* * Request address space for all standard RAM and ROM resources * and also for regions reported as reserved by the e820. */ probe_roms(); for (i = 0; i < e820.nr_map; i++) { struct resource *res; if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL) continue; res = alloc_bootmem_low(sizeof(struct resource)); switch (e820.map[i].type) { case E820_RAM: res->name = "System RAM"; break; case E820_ACPI: res->name = "ACPI Tables"; break; case E820_NVS: res->name = "ACPI Non-volatile Storage"; break; default: res->name = "reserved"; } res->start = e820.map[i].addr; res->end = res->start + e820.map[i].size - 1; res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); if (e820.map[i].type == E820_RAM) { /* * We dont't know which RAM region contains kernel data, * so we try it repeatedly and let the resource manager * test it. */ request_resource(res, &code_resource); request_resource(res, &data_resource); } } request_resource(&iomem_resource, &vram_resource); /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < STANDARD_IO_RESOURCES; i++) request_resource(&ioport_resource, standard_io_resources+i);#ifdef CONFIG_VT#if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con;#elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con;#endif#endif}#ifndef CONFIG_X86_TSCstatic int tsc_disable __initdata = 0;static int __init tsc_setup(char *str){ tsc_disable = 1; return 1;}__setup("notsc", tsc_setup);#endifstatic int __init get_model_name(struct cpuinfo_x86 *c){ unsigned int *v; char *p, *q; if (cpuid_eax(0x80000000) < 0x80000004) return 0; v = (unsigned int *) c->x86_model_id; cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]); cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); c->x86_model_id[48] = 0; /* Intel chips right-justify this string for some dumb reason; undo that brain damage */ p = q = &c->x86_model_id[0]; while ( *p == ' ' ) p++; if ( p != q ) { while ( *p ) *q++ = *p++; while ( q <= &c->x86_model_id[48] ) *q++ = '\0'; /* Zero-pad the rest */ } return 1;}static void __init display_cacheinfo(struct cpuinfo_x86 *c){ unsigned int n, dummy, ecx, edx, l2size; n = cpuid_eax(0x80000000); if (n >= 0x80000005) { cpuid(0x80000005, &dummy, &dummy, &ecx, &edx); printk("CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); c->x86_cache_size=(ecx>>24)+(edx>>24); } if (n < 0x80000006) /* Some chips just has a large L1. */ return; ecx = cpuid_ecx(0x80000006); l2size = ecx >> 16; /* AMD errata T13 (order #21922) */ if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 6 && c->x86_model == 3 && c->x86_mask == 0) { l2size = 64; } if ( l2size == 0 ) return; /* Again, no L2 cache is possible */ c->x86_cache_size = l2size; printk("CPU: L2 Cache: %dK (%d bytes/line)\n", l2size, ecx & 0xFF);}/* * B step AMD K6 before B 9730xxxx have hardware bugs that can cause * misexecution of code under Linux. Owners of such processors should * contact AMD for precise details and a CPU swap. * * See http://www.mygale.com/~poulot/k6bug.html * http://www.amd.com/K6/k6docs/revgd.html * * The following test is erm.. interesting. AMD neglected to up * the chip setting when fixing the bug but they also tweaked some * performance at the same time.. */ extern void vide(void);__asm__(".align 4\nvide: ret");static int __init init_amd(struct cpuinfo_x86 *c){ u32 l, h; unsigned long flags; int mbytes = max_mapnr >> (20-PAGE_SHIFT); int r; /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ clear_bit(0*32+31, &c->x86_capability); r = get_model_name(c); switch(c->x86) { case 5: if( c->x86_model < 6 ) { /* Based on AMD doc 20734R - June 2000 */ if ( c->x86_model == 0 ) { clear_bit(X86_FEATURE_APIC, &c->x86_capability); set_bit(X86_FEATURE_PGE, &c->x86_capability); } break; } if ( c->x86_model == 6 && c->x86_mask == 1 ) { const int K6_BUG_LOOP = 1000000; int n; void (*f_vide)(void); unsigned long d, d2; printk(KERN_INFO "AMD K6 stepping B detected - "); /* * It looks like AMD fixed the 2.6.2 bug and improved indirect * calls at the same time. */ n = K6_BUG_LOOP; f_vide = vide; rdtscl(d); while (n--) f_vide(); rdtscl(d2); d = d2-d; /* Knock these two lines out if it debugs out ok */ printk(KERN_INFO "K6 BUG %ld %d (Report these if test report is incorrect)\n", d, 20*K6_BUG_LOOP); printk(KERN_INFO "AMD K6 stepping B detected - "); /* -- cut here -- */ if (d > 20*K6_BUG_LOOP) printk("system stability may be impaired when more than 32 MB are used.\n"); else printk("probably OK (after B9730xxxx).\n"); printk(KERN_INFO "Please see http://www.mygale.com/~poulot/k6bug.html\n"); } /* K6 with old style WHCR */ if( c->x86_model < 8 || (c->x86_model== 8 && c->x86_mask < 8)) { /* We can only write allocate on the low 508Mb */ if(mbytes>508) mbytes=508; rdmsr(0xC0000082, l, h); if((l&0x0000FFFF)==0) { l=(1<<0)|((mbytes/4)<<1); save_flags(flags); __cli(); __asm__ __volatile__ ("wbinvd": : :"memory"); wrmsr(0xC0000082, l, h); restore_flags(flags); printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n", mbytes); } break; } if (c->x86_model == 8 || c->x86_model == 9 || c->x86_model == 13) { /* The more serious chips .. */ if(mbytes>4092) mbytes=4092; rdmsr(0xC0000082, l, h); if((l&0xFFFF0000)==0) { l=((mbytes>>2)<<22)|(1<<16); save_flags(flags); __cli(); __asm__ __volatile__ ("wbinvd": : :"memory"); wrmsr(0xC0000082, l, h); restore_flags(flags); printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n", mbytes); } /* Set MTRR capability flag if appropriate */ if ( (c->x86_model == 13) || (c->x86_model == 9) || ((c->x86_model == 8) && (c->x86_mask >= 8)) ) set_bit(X86_FEATURE_K6_MTRR, &c->x86_capability); break; } break; case 6: /* An Athlon/Duron. We can trust the BIOS probably */ break; } display_cacheinfo(c); return r;}/* * Read Cyrix DEVID registers (DIR) to get more detailed info. about the CPU */static inline void do_cyrix_devid(unsigned char *dir0, unsigned char *dir1){ unsigned char ccr2, ccr3; /* we test for DEVID by checking whether CCR3 is writable */ cli(); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, ccr3 ^ 0x80); getCx86(0xc0); /* dummy to change bus */ if (getCx86(CX86_CCR3) == ccr3) { /* no DEVID regs. */ ccr2 = getCx86(CX86_CCR2); setCx86(CX86_CCR2, ccr2 ^ 0x04); getCx86(0xc0); /* dummy */ if (getCx86(CX86_CCR2) == ccr2) /* old Cx486SLC/DLC */ *dir0 = 0xfd; else { /* Cx486S A step */ setCx86(CX86_CCR2, ccr2); *dir0 = 0xfe; } } else { setCx86(CX86_CCR3, ccr3); /* restore CCR3 */ /* read DIR0 and DIR1 CPU registers */ *dir0 = getCx86(CX86_DIR0); *dir1 = getCx86(CX86_DIR1); } sti();}/* * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in * order to identify the Cyrix CPU model after we're out of setup.c */unsigned char Cx86_dir0_msb __initdata = 0;static char Cx86_model[][9] __initdata = { "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ", "M II ", "Unknown"};static char Cx486_name[][5] __initdata = { "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx", "SRx2", "DRx2"};static char Cx486S_name[][4] __initdata = { "S", "S2", "Se", "S2e"};static char Cx486D_name[][4] __initdata = { "DX", "DX2", "?", "?", "?", "DX4"};static char Cx86_cb[] __initdata = "?.5x Core/Bus Clock";static char cyrix_model_mult1[] __initdata = "12??43";static char cyrix_model_mult2[] __initdata = "12233445";/* * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old * BIOSes for compatability with DOS games. This makes the udelay loop * work correctly, and improves performance. */extern void calibrate_delay(void) __init;static void __init check_cx686_slop(struct cpuinfo_x86 *c){ if (Cx86_dir0_msb == 3) { unsigned char ccr3, ccr5;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -