📄 setup.c
字号:
/* * linux/arch/alpha/kernel/setup.c * * Copyright (C) 1995 Linus Torvalds *//* 2.3.x bootmem, 1999 Andrea Arcangeli <andrea@suse.de> *//* * Bootup setup stuff. */#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/delay.h>#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */#include <linux/mc146818rtc.h>#include <linux/console.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/string.h>#include <linux/ioport.h>#include <linux/bootmem.h>#include <linux/pci.h>#include <linux/seq_file.h>#include <linux/root_dev.h>#include <linux/initrd.h>#include <linux/eisa.h>#ifdef CONFIG_MAGIC_SYSRQ#include <linux/sysrq.h>#include <linux/reboot.h>#endif#include <linux/notifier.h>#include <asm/setup.h>#include <asm/io.h>extern struct notifier_block *panic_notifier_list;static int alpha_panic_event(struct notifier_block *, unsigned long, void *);static struct notifier_block alpha_panic_block = { alpha_panic_event, NULL, INT_MAX /* try to do it first */};#include <asm/uaccess.h>#include <asm/pgtable.h>#include <asm/system.h>#include <asm/hwrpb.h>#include <asm/dma.h>#include <asm/io.h>#include <asm/mmu_context.h>#include <asm/console.h>#include "proto.h"#include "pci_impl.h"struct hwrpb_struct *hwrpb;unsigned long srm_hae;int alpha_l1i_cacheshape;int alpha_l1d_cacheshape;int alpha_l2_cacheshape;int alpha_l3_cacheshape;#ifdef CONFIG_VERBOSE_MCHECK/* 0=minimum, 1=verbose, 2=all *//* These can be overridden via the command line, ie "verbose_mcheck=2") */unsigned long alpha_verbose_mcheck = CONFIG_VERBOSE_MCHECK_ON;#endif/* Which processor we booted from. */int boot_cpuid;/* * Using SRM callbacks for initial console output. This works from * setup_arch() time through the end of time_init(), as those places * are under our (Alpha) control. * "srmcons" specified in the boot command arguments allows us to * see kernel messages during the period of time before the true * console device is "registered" during console_init(). * As of this version (2.5.59), console_init() will call * disable_early_printk() as the last action before initializing * the console drivers. That's the last possible time srmcons can be * unregistered without interfering with console behavior. * * By default, OFF; set it with a bootcommand arg of "srmcons" or * "console=srm". The meaning of these two args is: * "srmcons" - early callback prints * "console=srm" - full callback based console, including early prints */int srmcons_output = 0;/* Enforce a memory size limit; useful for testing. By default, none. */unsigned long mem_size_limit = 0;/* Set AGP GART window size (0 means disabled). */unsigned long alpha_agpgart_size = DEFAULT_AGP_APER_SIZE;#ifdef CONFIG_ALPHA_GENERICstruct alpha_machine_vector alpha_mv;int alpha_using_srm;#endif#define N(a) (sizeof(a)/sizeof(a[0]))static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long, unsigned long);static struct alpha_machine_vector *get_sysvec_byname(const char *);static void get_sysnames(unsigned long, unsigned long, unsigned long, char **, char **);static void determine_cpu_caches (unsigned int);static char command_line[COMMAND_LINE_SIZE];/* * The format of "screen_info" is strange, and due to early * i386-setup code. This is just enough to make the console * code think we're on a VGA color display. */struct screen_info screen_info = { .orig_x = 0, .orig_y = 25, .orig_video_cols = 80, .orig_video_lines = 25, .orig_video_isVGA = 1, .orig_video_points = 16};/* * The direct map I/O window, if any. This should be the same * for all busses, since it's used by virt_to_bus. */unsigned long __direct_map_base;unsigned long __direct_map_size;/* * Declare all of the machine vectors. *//* GCC 2.7.2 (on alpha at least) is lame. It does not support either __attribute__((weak)) or #pragma weak. Bypass it and talk directly to the assembler. */#define WEAK(X) \ extern struct alpha_machine_vector X; \ asm(".weak "#X)WEAK(alcor_mv);WEAK(alphabook1_mv);WEAK(avanti_mv);WEAK(cabriolet_mv);WEAK(clipper_mv);WEAK(dp264_mv);WEAK(eb164_mv);WEAK(eb64p_mv);WEAK(eb66_mv);WEAK(eb66p_mv);WEAK(eiger_mv);WEAK(jensen_mv);WEAK(lx164_mv);WEAK(lynx_mv);WEAK(marvel_ev7_mv);WEAK(miata_mv);WEAK(mikasa_mv);WEAK(mikasa_primo_mv);WEAK(monet_mv);WEAK(nautilus_mv);WEAK(noname_mv);WEAK(noritake_mv);WEAK(noritake_primo_mv);WEAK(p2k_mv);WEAK(pc164_mv);WEAK(privateer_mv);WEAK(rawhide_mv);WEAK(ruffian_mv);WEAK(rx164_mv);WEAK(sable_mv);WEAK(sable_gamma_mv);WEAK(shark_mv);WEAK(sx164_mv);WEAK(takara_mv);WEAK(titan_mv);WEAK(webbrick_mv);WEAK(wildfire_mv);WEAK(xl_mv);WEAK(xlt_mv);#undef WEAK/* * I/O resources inherited from PeeCees. Except for perhaps the * turbochannel alphas, everyone has these on some sort of SuperIO chip. * * ??? If this becomes less standard, move the struct out into the * machine vector. */static void __initreserve_std_resources(void){ static struct resource standard_io_resources[] = { { .name = "rtc", .start = -1, .end = -1 }, { .name = "dma1", .start = 0x00, .end = 0x1f }, { .name = "pic1", .start = 0x20, .end = 0x3f }, { .name = "timer", .start = 0x40, .end = 0x5f }, { .name = "keyboard", .start = 0x60, .end = 0x6f }, { .name = "dma page reg", .start = 0x80, .end = 0x8f }, { .name = "pic2", .start = 0xa0, .end = 0xbf }, { .name = "dma2", .start = 0xc0, .end = 0xdf }, }; struct resource *io = &ioport_resource; size_t i; if (hose_head) { struct pci_controller *hose; for (hose = hose_head; hose; hose = hose->next) if (hose->index == 0) { io = hose->io_space; break; } } /* Fix up for the Jensen's queer RTC placement. */ standard_io_resources[0].start = RTC_PORT(0); standard_io_resources[0].end = RTC_PORT(0) + 0x10; for (i = 0; i < N(standard_io_resources); ++i) request_resource(io, standard_io_resources+i);}#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)#define PFN_PHYS(x) ((x) << PAGE_SHIFT)#define PFN_MAX PFN_DOWN(0x80000000)#define for_each_mem_cluster(memdesc, cluster, i) \ for ((cluster) = (memdesc)->cluster, (i) = 0; \ (i) < (memdesc)->numclusters; (i)++, (cluster)++)static unsigned long __initget_mem_size_limit(char *s){ unsigned long end = 0; char *from = s; end = simple_strtoul(from, &from, 0); if ( *from == 'K' || *from == 'k' ) { end = end << 10; from++; } else if ( *from == 'M' || *from == 'm' ) { end = end << 20; from++; } else if ( *from == 'G' || *from == 'g' ) { end = end << 30; from++; } return end >> PAGE_SHIFT; /* Return the PFN of the limit. */}#ifdef CONFIG_BLK_DEV_INITRDvoid * __initmove_initrd(unsigned long mem_limit){ void *start; unsigned long size; size = initrd_end - initrd_start; start = __alloc_bootmem(PAGE_ALIGN(size), PAGE_SIZE, 0); if (!start || __pa(start) + size > mem_limit) { initrd_start = initrd_end = 0; return NULL; } memmove(start, (void *)initrd_start, size); initrd_start = (unsigned long)start; initrd_end = initrd_start + size; printk("initrd moved to %p\n", start); return start;}#endif#ifndef CONFIG_DISCONTIGMEMstatic void __initsetup_memory(void *kernel_end){ struct memclust_struct * cluster; struct memdesc_struct * memdesc; unsigned long start_kernel_pfn, end_kernel_pfn; unsigned long bootmap_size, bootmap_pages, bootmap_start; unsigned long start, end; unsigned long i; /* Find free clusters, and init and free the bootmem accordingly. */ memdesc = (struct memdesc_struct *) (hwrpb->mddt_offset + (unsigned long) hwrpb); for_each_mem_cluster(memdesc, cluster, i) { printk("memcluster %lu, usage %01lx, start %8lu, end %8lu\n", i, cluster->usage, cluster->start_pfn, cluster->start_pfn + cluster->numpages); /* Bit 0 is console/PALcode reserved. Bit 1 is non-volatile memory -- we might want to mark this for later. */ if (cluster->usage & 3) continue; end = cluster->start_pfn + cluster->numpages; if (end > max_low_pfn) max_low_pfn = end; } /* * Except for the NUMA systems (wildfire, marvel) all of the * Alpha systems we run on support 32GB of memory or less. * Since the NUMA systems introduce large holes in memory addressing, * we can get into a situation where there is not enough contiguous * memory for the memory map. * * Limit memory to the first 32GB to limit the NUMA systems to * memory on their first node (wildfire) or 2 (marvel) to avoid * not being able to produce the memory map. In order to access * all of the memory on the NUMA systems, build with discontiguous * memory support. * * If the user specified a memory limit, let that memory limit stand. */ if (!mem_size_limit) mem_size_limit = (32ul * 1024 * 1024 * 1024) >> PAGE_SHIFT; if (mem_size_limit && max_low_pfn >= mem_size_limit) { printk("setup: forcing memory size to %ldK (from %ldK).\n", mem_size_limit << (PAGE_SHIFT - 10), max_low_pfn << (PAGE_SHIFT - 10)); max_low_pfn = mem_size_limit; } /* Find the bounds of kernel memory. */ start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS); end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end)); bootmap_start = -1; try_again: if (max_low_pfn <= end_kernel_pfn) panic("not enough memory to boot"); /* We need to know how many physically contiguous pages we'll need for the bootmap. */ bootmap_pages = bootmem_bootmap_pages(max_low_pfn); /* Now find a good region where to allocate the bootmap. */ for_each_mem_cluster(memdesc, cluster, i) { if (cluster->usage & 3) continue; start = cluster->start_pfn; end = start + cluster->numpages; if (start >= max_low_pfn) continue; if (end > max_low_pfn) end = max_low_pfn; if (start < start_kernel_pfn) { if (end > end_kernel_pfn && end - end_kernel_pfn >= bootmap_pages) { bootmap_start = end_kernel_pfn; break; } else if (end > start_kernel_pfn) end = start_kernel_pfn; } else if (start < end_kernel_pfn) start = end_kernel_pfn; if (end - start >= bootmap_pages) { bootmap_start = start; break; } } if (bootmap_start == ~0UL) { max_low_pfn >>= 1; goto try_again; } /* Allocate the bootmap and mark the whole MM as reserved. */ bootmap_size = init_bootmem(bootmap_start, max_low_pfn); /* Mark the free regions. */ for_each_mem_cluster(memdesc, cluster, i) { if (cluster->usage & 3) continue; start = cluster->start_pfn; end = cluster->start_pfn + cluster->numpages; if (start >= max_low_pfn) continue; if (end > max_low_pfn) end = max_low_pfn; if (start < start_kernel_pfn) { if (end > end_kernel_pfn) { free_bootmem(PFN_PHYS(start), (PFN_PHYS(start_kernel_pfn) - PFN_PHYS(start))); printk("freeing pages %ld:%ld\n", start, start_kernel_pfn); start = end_kernel_pfn; } else if (end > start_kernel_pfn) end = start_kernel_pfn; } else if (start < end_kernel_pfn) start = end_kernel_pfn; if (start >= end) continue; free_bootmem(PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start)); printk("freeing pages %ld:%ld\n", start, end); } /* Reserve the bootmap memory. */ reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size); printk("reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size));#ifdef CONFIG_BLK_DEV_INITRD initrd_start = INITRD_START; if (initrd_start) { initrd_end = initrd_start+INITRD_SIZE; printk("Initial ramdisk at: 0x%p (%lu bytes)\n", (void *) initrd_start, INITRD_SIZE); if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) { if (!move_initrd(PFN_PHYS(max_low_pfn))) printk("initrd extends beyond end of memory " "(0x%08lx > 0x%p)\ndisabling initrd\n", initrd_end, phys_to_virt(PFN_PHYS(max_low_pfn))); } else { reserve_bootmem(virt_to_phys((void *)initrd_start), INITRD_SIZE); } }#endif /* CONFIG_BLK_DEV_INITRD */}#elseextern void setup_memory(void *);#endif /* !CONFIG_DISCONTIGMEM */int __initpage_is_ram(unsigned long pfn){ struct memclust_struct * cluster; struct memdesc_struct * memdesc; unsigned long i; memdesc = (struct memdesc_struct *) (hwrpb->mddt_offset + (unsigned long) hwrpb); for_each_mem_cluster(memdesc, cluster, i) { if (pfn >= cluster->start_pfn && pfn < cluster->start_pfn + cluster->numpages) { return (cluster->usage & 3) ? 0 : 1; } } return 0;}#undef PFN_UP#undef PFN_DOWN#undef PFN_PHYS#undef PFN_MAXvoid __initsetup_arch(char **cmdline_p){ extern char _end[]; struct alpha_machine_vector *vec = NULL; struct percpu_struct *cpu; char *type_name, *var_name, *p; void *kernel_end = _end; /* end of kernel */ char *args = command_line; hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr); boot_cpuid = hard_smp_processor_id(); /* * Pre-process the system type to make sure it will be valid. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -