📄 setup.c
字号:
APs have less capabilities than the boot processor are not handled. In this case boot with "noreplacement". */ void apply_alternatives(void *start, void *end) { struct alt_instr *a; int diff, i, k; for (a = start; (void *)a < end; a++) { if (!boot_cpu_has(a->cpuid)) continue; BUG_ON(a->replacementlen > a->instrlen); __inline_memcpy(a->instr, a->replacement, a->replacementlen); diff = a->instrlen - a->replacementlen; /* Pad the rest with nops */ for (i = a->replacementlen; diff > 0; diff -= k, i += k) { k = diff; if (k > ASM_NOP_MAX) k = ASM_NOP_MAX; __inline_memcpy(a->instr + i, k8_nops[k], k); } }} static int no_replacement __initdata = 0; void __init alternative_instructions(void){ extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; if (no_replacement) return; apply_alternatives(__alt_instructions, __alt_instructions_end);}static int __init noreplacement_setup(char *s){ no_replacement = 1; return 0; } __setup("noreplacement", noreplacement_setup); #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)struct edd edd;#ifdef CONFIG_EDD_MODULEEXPORT_SYMBOL(edd);#endif/** * copy_edd() - Copy the BIOS EDD information * from boot_params into a safe place. * */static inline void copy_edd(void){ memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature)); memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info)); edd.mbr_signature_nr = EDD_MBR_SIG_NR; edd.edd_info_nr = EDD_NR;}#elsestatic inline void copy_edd(void){}#endif#define EBDA_ADDR_POINTER 0x40Estatic void __init reserve_ebda_region(void){ unsigned int addr; /** * there is a real-mode segmented pointer pointing to the * 4K EBDA area at 0x40E */ addr = *(unsigned short *)phys_to_virt(EBDA_ADDR_POINTER); addr <<= 4; if (addr) reserve_bootmem_generic(addr, PAGE_SIZE);}void __init setup_arch(char **cmdline_p){ unsigned long kernel_end; ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); drive_info = DRIVE_INFO; screen_info = SCREEN_INFO; edid_info = EDID_INFO; saved_video_mode = SAVED_VIDEO_MODE; bootloader_type = LOADER_TYPE;#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(); copy_edd(); 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_phys(&_text); code_resource.end = virt_to_phys(&_etext)-1; data_resource.start = virt_to_phys(&_etext); data_resource.end = virt_to_phys(&_edata)-1; parse_cmdline_early(cmdline_p); early_identify_cpu(&boot_cpu_data); /* * partially used pages are not usable - thus * we are rounding upwards: */ end_pfn = e820_end_of_ram(); check_efer(); init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT)); zap_low_mappings(0);#ifdef CONFIG_ACPI /* * Initialize the ACPI boot-time table parser (gets the RSDP and SDT). * Call this early for SRAT node setup. */ acpi_boot_table_init();#endif#ifdef CONFIG_ACPI_NUMA /* * Parse SRAT to discover nodes. */ acpi_numa_init();#endif#ifdef CONFIG_NUMA numa_initmem_init(0, end_pfn); #else contig_initmem_init(0, end_pfn);#endif /* Reserve direct mapping */ reserve_bootmem_generic(table_start << PAGE_SHIFT, (table_end - table_start) << PAGE_SHIFT); /* reserve kernel */ kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE); reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY); /* * reserve physical page 0 - it's a special BIOS page on many boxes, * enabling clean reboots, SMP operation, laptop functions. */ reserve_bootmem_generic(0, PAGE_SIZE); /* reserve ebda region */ reserve_ebda_region();#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_generic(PAGE_SIZE, PAGE_SIZE); /* Reserve SMP trampoline */ reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, PAGE_SIZE);#endif#ifdef CONFIG_ACPI_SLEEP /* * Reserve low memory region for sleep support. */ acpi_reserve_bootmem();#endif#ifdef CONFIG_X86_LOCAL_APIC /* * Find and reserve possible boot-time SMP configuration: */ find_smp_config();#endif#ifdef CONFIG_BLK_DEV_INITRD if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) { reserve_bootmem_generic(INITRD_START, INITRD_SIZE); initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0; initrd_end = initrd_start+INITRD_SIZE; } else { printk(KERN_ERR "initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", (unsigned long)(INITRD_START + INITRD_SIZE), (unsigned long)(end_pfn << PAGE_SHIFT)); initrd_start = 0; } }#endif#ifdef CONFIG_KEXEC if (crashk_res.start != crashk_res.end) { reserve_bootmem(crashk_res.start, crashk_res.end - crashk_res.start + 1); }#endif paging_init(); check_ioapic();#ifdef CONFIG_ACPI /* * Read APIC and some other early information from ACPI tables. */ acpi_boot_init();#endif#ifdef CONFIG_X86_LOCAL_APIC /* * get boot-time SMP configuration: */ if (smp_found_config) get_smp_config(); init_apic_mappings();#endif /* * Request address space for all standard RAM and ROM resources * and also for regions reported as reserved by the e820. */ probe_roms(); e820_reserve_resources(); request_resource(&iomem_resource, &video_ram_resource); { unsigned i; /* 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]); } e820_setup_gap();#ifdef CONFIG_GART_IOMMU iommu_hole_init();#endif#ifdef CONFIG_VT#if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con;#elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con;#endif#endif}static int __cpuinit get_model_name(struct cpuinfo_x86 *c){ unsigned int *v; if (c->extended_cpuid_level < 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; return 1;}static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c){ unsigned int n, dummy, eax, ebx, ecx, edx; n = c->extended_cpuid_level; if (n >= 0x80000005) { cpuid(0x80000005, &dummy, &ebx, &ecx, &edx); printk(KERN_INFO "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); /* On K8 L1 TLB is inclusive, so don't count it */ c->x86_tlbsize = 0; } if (n >= 0x80000006) { cpuid(0x80000006, &dummy, &ebx, &ecx, &edx); ecx = cpuid_ecx(0x80000006); c->x86_cache_size = ecx >> 16; c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff); printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n", c->x86_cache_size, ecx & 0xFF); } if (n >= 0x80000007) cpuid(0x80000007, &dummy, &dummy, &dummy, &c->x86_power); if (n >= 0x80000008) { cpuid(0x80000008, &eax, &dummy, &dummy, &dummy); c->x86_virt_bits = (eax >> 8) & 0xff; c->x86_phys_bits = eax & 0xff; }}#ifdef CONFIG_NUMAstatic int nearby_node(int apicid){ int i; for (i = apicid - 1; i >= 0; i--) { int node = apicid_to_node[i]; if (node != NUMA_NO_NODE && node_online(node)) return node; } for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) { int node = apicid_to_node[i]; if (node != NUMA_NO_NODE && node_online(node)) return node; } return first_node(node_online_map); /* Shouldn't happen */}#endif/* * On a AMD dual core setup the lower bits of the APIC id distingush the cores. * Assumes number of cores is a power of two. */static void __init amd_detect_cmp(struct cpuinfo_x86 *c){#ifdef CONFIG_SMP int cpu = smp_processor_id(); unsigned bits;#ifdef CONFIG_NUMA int node = 0; unsigned apicid = phys_proc_id[cpu];#endif bits = 0; while ((1 << bits) < c->x86_max_cores) bits++; /* Low order bits define the core id (index of core in socket) */ cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1); /* Convert the APIC ID into the socket ID */ phys_proc_id[cpu] >>= bits;#ifdef CONFIG_NUMA node = phys_proc_id[cpu]; if (apicid_to_node[apicid] != NUMA_NO_NODE) node = apicid_to_node[apicid]; if (!node_online(node)) { /* Two possibilities here: - The CPU is missing memory and no node was created. In that case try picking one from a nearby CPU - The APIC IDs differ from the HyperTransport node IDs which the K8 northbridge parsing fills in. Assume they are all increased by a constant offset, but in the same order as the HT nodeids. If that doesn't result in a usable node fall back to the path for the previous case. */ int ht_nodeid = apicid - (phys_proc_id[0] << bits); if (ht_nodeid >= 0 && apicid_to_node[ht_nodeid] != NUMA_NO_NODE) node = apicid_to_node[ht_nodeid]; /* Pick a nearby node */ if (!node_online(node)) node = nearby_node(apicid); } numa_set_node(cpu, node); printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n", cpu, c->x86_max_cores, node, cpu_core_id[cpu]);#endif#endif}static int __init init_amd(struct cpuinfo_x86 *c){ int r; int level;#ifdef CONFIG_SMP unsigned long value; /* * Disable TLB flush filter by setting HWCR.FFDIS on K8 * bit 6 of msr C001_0015 * * Errata 63 for SH-B3 steppings * Errata 122 for all steppings (F+ have it disabled by default) */ if (c->x86 == 15) { rdmsrl(MSR_K8_HWCR, value); value |= 1 << 6; wrmsrl(MSR_K8_HWCR, value); }#endif /* 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); /* C-stepping K8? */ level = cpuid_eax(1); if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58) set_bit(X86_FEATURE_K8_C, &c->x86_capability); r = get_model_name(c); if (!r) { switch (c->x86) { case 15: /* Should distinguish Models here, but this is only a fallback anyways. */ strcpy(c->x86_model_id, "Hammer"); break; } } display_cacheinfo(c); if (c->extended_cpuid_level >= 0x80000008) { c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1; if (c->x86_max_cores & (c->x86_max_cores - 1)) c->x86_max_cores = 1; amd_detect_cmp(c); } return r;}static void __cpuinit detect_ht(struct cpuinfo_x86 *c){#ifdef CONFIG_SMP u32 eax, ebx, ecx, edx; int index_msb, core_bits; int cpu = smp_processor_id(); cpuid(1, &eax, &ebx, &ecx, &edx); c->apicid = phys_pkg_id(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -