📄 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>#ifdef CONFIG_BLK_DEV_INITRD#include <linux/blk.h>#endif#include <linux/notifier.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;/* 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.4.20), 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;#endifunsigned char aux_device_present = 0xaa;#define N(a) (sizeof(a)/sizeof(a[0]))static struct alpha_machine_vector *get_sysvec(long, long, long);static struct alpha_machine_vector *get_sysvec_byname(const char *);static void get_sysnames(long, long, long, char **, char **);static char command_line[COMMAND_LINE_SIZE];char saved_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(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[] = { { "rtc", -1, -1 }, { "dma1", 0x00, 0x1f }, { "pic1", 0x20, 0x3f }, { "timer", 0x40, 0x5f }, { "keyboard", 0x60, 0x6f }, { "dma page reg", 0x80, 0x8f }, { "pic2", 0xa0, 0xbf }, { "dma2", 0xc0, 0xdf }, }; struct resource *io = &ioport_resource; long 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(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(KERN_INFO "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; int 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 %d, 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 == -1) { 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -