setup.c
来自「底层驱动开发」· C语言 代码 · 共 1,350 行 · 第 1/3 页
C
1,350 行
/* * linux/arch/x86-64/kernel/setup.c * * Copyright (C) 1995 Linus Torvalds * * Nov 2001 Dave Jones <davej@suse.de> * Forked from i386 setup code. * * $Id$ *//* * 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/initrd.h>#include <linux/highmem.h>#include <linux/bootmem.h>#include <linux/module.h>#include <asm/processor.h>#include <linux/console.h>#include <linux/seq_file.h>#include <linux/root_dev.h>#include <linux/pci.h>#include <linux/acpi.h>#include <linux/kallsyms.h>#include <linux/edd.h>#include <linux/mmzone.h>#include <linux/kexec.h>#include <asm/mtrr.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/io.h>#include <asm/smp.h>#include <asm/msr.h>#include <asm/desc.h>#include <video/edid.h>#include <asm/e820.h>#include <asm/dma.h>#include <asm/mpspec.h>#include <asm/mmu_context.h>#include <asm/bootsetup.h>#include <asm/proto.h>#include <asm/setup.h>#include <asm/mach_apic.h>#include <asm/numa.h>/* * Machine setup.. */struct cpuinfo_x86 boot_cpu_data __read_mostly;unsigned long mmu_cr4_features;int acpi_disabled;EXPORT_SYMBOL(acpi_disabled);#ifdef CONFIG_ACPIextern int __initdata acpi_ht;extern acpi_interrupt_flags acpi_sci_flags;int __initdata acpi_force = 0;#endifint acpi_numa __initdata;/* Boot loader ID as an integer, for the benefit of proc_dointvec */int bootloader_type;unsigned long saved_video_mode;#ifdef CONFIG_SWIOTLBint swiotlb;EXPORT_SYMBOL(swiotlb);#endif/* * Setup options */struct drive_info_struct { char dummy[32]; } drive_info;struct screen_info screen_info;struct sys_desc_table_struct { unsigned short length; unsigned char table[0];};struct edid_info edid_info;struct e820map e820;extern int root_mountflags;extern char _text, _etext, _edata, _end;char command_line[COMMAND_LINE_SIZE];struct resource standard_io_resources[] = { { .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "pic1", .start = 0x20, .end = 0x21, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "timer0", .start = 0x40, .end = 0x43, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "timer1", .start = 0x50, .end = 0x53, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "keyboard", .start = 0x60, .end = 0x6f, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "dma page reg", .start = 0x80, .end = 0x8f, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "pic2", .start = 0xa0, .end = 0xa1, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY | IORESOURCE_IO }, { .name = "fpu", .start = 0xf0, .end = 0xff, .flags = IORESOURCE_BUSY | IORESOURCE_IO }};#define STANDARD_IO_RESOURCES \ (sizeof standard_io_resources / sizeof standard_io_resources[0])#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)struct resource data_resource = { .name = "Kernel data", .start = 0, .end = 0, .flags = IORESOURCE_RAM,};struct resource code_resource = { .name = "Kernel code", .start = 0, .end = 0, .flags = IORESOURCE_RAM,};#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)static struct resource system_rom_resource = { .name = "System ROM", .start = 0xf0000, .end = 0xfffff, .flags = IORESOURCE_ROM,};static struct resource extension_rom_resource = { .name = "Extension ROM", .start = 0xe0000, .end = 0xeffff, .flags = IORESOURCE_ROM,};static struct resource adapter_rom_resources[] = { { .name = "Adapter ROM", .start = 0xc8000, .end = 0, .flags = IORESOURCE_ROM }, { .name = "Adapter ROM", .start = 0, .end = 0, .flags = IORESOURCE_ROM }, { .name = "Adapter ROM", .start = 0, .end = 0, .flags = IORESOURCE_ROM }, { .name = "Adapter ROM", .start = 0, .end = 0, .flags = IORESOURCE_ROM }, { .name = "Adapter ROM", .start = 0, .end = 0, .flags = IORESOURCE_ROM }, { .name = "Adapter ROM", .start = 0, .end = 0, .flags = IORESOURCE_ROM }};#define ADAPTER_ROM_RESOURCES \ (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])static struct resource video_rom_resource = { .name = "Video ROM", .start = 0xc0000, .end = 0xc7fff, .flags = IORESOURCE_ROM,};static struct resource video_ram_resource = { .name = "Video RAM area", .start = 0xa0000, .end = 0xbffff, .flags = IORESOURCE_RAM,};#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)static int __init romchecksum(unsigned char *rom, unsigned long length){ unsigned char *p, sum = 0; for (p = rom; p < rom + length; p++) sum += *p; return sum == 0;}static void __init probe_roms(void){ unsigned long start, length, upper; unsigned char *rom; int i; /* video rom */ upper = adapter_rom_resources[0].start; for (start = video_rom_resource.start; start < upper; start += 2048) { rom = isa_bus_to_virt(start); if (!romsignature(rom)) continue; video_rom_resource.start = start; /* 0 < length <= 0x7f * 512, historically */ length = rom[2] * 512; /* if checksum okay, trust length byte */ if (length && romchecksum(rom, length)) video_rom_resource.end = start + length - 1; request_resource(&iomem_resource, &video_rom_resource); break; } start = (video_rom_resource.end + 1 + 2047) & ~2047UL; if (start < upper) start = upper; /* system rom */ request_resource(&iomem_resource, &system_rom_resource); upper = system_rom_resource.start; /* check for extension rom (ignore length byte!) */ rom = isa_bus_to_virt(extension_rom_resource.start); if (romsignature(rom)) { length = extension_rom_resource.end - extension_rom_resource.start + 1; if (romchecksum(rom, length)) { request_resource(&iomem_resource, &extension_rom_resource); upper = extension_rom_resource.start; } } /* check for adapter roms on 2k boundaries */ for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) { rom = isa_bus_to_virt(start); if (!romsignature(rom)) continue; /* 0 < length <= 0x7f * 512, historically */ length = rom[2] * 512; /* but accept any length that fits if checksum okay */ if (!length || start + length > upper || !romchecksum(rom, length)) continue; adapter_rom_resources[i].start = start; adapter_rom_resources[i].end = start + length - 1; request_resource(&iomem_resource, &adapter_rom_resources[i]); start = adapter_rom_resources[i++].end & ~2047UL; }}static __init void parse_cmdline_early (char ** cmdline_p){ char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; /* Save unparsed command line copy for /proc/cmdline */ memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; for (;;) { if (c != ' ') goto next_char; #ifdef CONFIG_SMP /* * If the BIOS enumerates physical processors before logical, * maxcpus=N at enumeration-time can be used to disable HT. */ else if (!memcmp(from, "maxcpus=", 8)) { extern unsigned int maxcpus; maxcpus = simple_strtoul(from + 8, NULL, 0); }#endif#ifdef CONFIG_ACPI /* "acpi=off" disables both ACPI table parsing and interpreter init */ if (!memcmp(from, "acpi=off", 8)) disable_acpi(); if (!memcmp(from, "acpi=force", 10)) { /* add later when we do DMI horrors: */ acpi_force = 1; acpi_disabled = 0; } /* acpi=ht just means: do ACPI MADT parsing at bootup, but don't enable the full ACPI interpreter */ if (!memcmp(from, "acpi=ht", 7)) { if (!acpi_force) disable_acpi(); acpi_ht = 1; } else if (!memcmp(from, "pci=noacpi", 10)) acpi_disable_pci(); else if (!memcmp(from, "acpi=noirq", 10)) acpi_noirq_set(); else if (!memcmp(from, "acpi_sci=edge", 13)) acpi_sci_flags.trigger = 1; else if (!memcmp(from, "acpi_sci=level", 14)) acpi_sci_flags.trigger = 3; else if (!memcmp(from, "acpi_sci=high", 13)) acpi_sci_flags.polarity = 1; else if (!memcmp(from, "acpi_sci=low", 12)) acpi_sci_flags.polarity = 3; /* acpi=strict disables out-of-spec workarounds */ else if (!memcmp(from, "acpi=strict", 11)) { acpi_strict = 1; }#ifdef CONFIG_X86_IO_APIC else if (!memcmp(from, "acpi_skip_timer_override", 24)) acpi_skip_timer_override = 1;#endif#endif if (!memcmp(from, "disable_timer_pin_1", 19)) disable_timer_pin_1 = 1; if (!memcmp(from, "enable_timer_pin_1", 18)) disable_timer_pin_1 = -1; if (!memcmp(from, "nolapic", 7) || !memcmp(from, "disableapic", 11)) disable_apic = 1; if (!memcmp(from, "noapic", 6)) skip_ioapic_setup = 1; if (!memcmp(from, "apic", 4)) { skip_ioapic_setup = 0; ioapic_force = 1; } if (!memcmp(from, "mem=", 4)) parse_memopt(from+4, &from); #ifdef CONFIG_NUMA if (!memcmp(from, "numa=", 5)) numa_setup(from+5); #endif#ifdef CONFIG_GART_IOMMU if (!memcmp(from,"iommu=",6)) { iommu_setup(from+6); }#endif if (!memcmp(from,"oops=panic", 10)) panic_on_oops = 1; if (!memcmp(from, "noexec=", 7)) nonx_setup(from + 7);#ifdef CONFIG_KEXEC /* crashkernel=size@addr specifies the location to reserve for * a crash kernel. By reserving this memory we guarantee * that linux never set's it up as a DMA target. * Useful for holding code to do something appropriate * after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { unsigned long size, base; size = memparse(from+12, &from); if (*from == '@') { base = memparse(from+1, &from); /* FIXME: Do I want a sanity check * to validate the memory range? */ crashk_res.start = base; crashk_res.end = base + size - 1; } }#endif next_char: c = *(from++); if (!c) break; if (COMMAND_LINE_SIZE <= ++len) break; *(to++) = c; } *to = '\0'; *cmdline_p = command_line;}#ifndef CONFIG_NUMAstatic void __initcontig_initmem_init(unsigned long start_pfn, unsigned long end_pfn){ unsigned long bootmap_size, bootmap; memory_present(0, start_pfn, end_pfn); bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT; bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size); if (bootmap == -1L) panic("Cannot find bootmem map of size %ld\n",bootmap_size); bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn); e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT); reserve_bootmem(bootmap, bootmap_size);} #endif/* Use inline assembly to define this because the nops are defined as inline assembly strings in the include files and we cannot get them easily into strings. */asm("\t.data\nk8nops: " K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6 K8_NOP7 K8_NOP8); extern unsigned char k8nops[];static unsigned char *k8_nops[ASM_NOP_MAX+1] = { NULL, k8nops, k8nops + 1, k8nops + 1 + 2, k8nops + 1 + 2 + 3, k8nops + 1 + 2 + 3 + 4, k8nops + 1 + 2 + 3 + 4 + 5, k8nops + 1 + 2 + 3 + 4 + 5 + 6, k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,}; /* Replace instructions with better alternatives for this CPU type. This runs before SMP is initialized to avoid SMP problems with self modifying code. This implies that assymetric systems where APs have less capabilities than the boot processor are not handled.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?