📄 setup.c
字号:
/* * Architecture-specific setup. * * Copyright (C) 1998-2001 Hewlett-Packard Co * David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 1998, 1999, 2001 Stephane Eranian <eranian@hpl.hp.com> * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com> * Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> * * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo(). * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map * 03/31/00 R.Seth cpu_initialized and current->processor fixes * 02/04/00 D.Mosberger some more get_cpuinfo fixes... * 02/01/00 R.Seth fixed get_cpuinfo for SMP * 01/07/99 S.Eranian added the support for command line argument * 06/24/99 W.Drummond added boot_cpu_data. */#include <linux/config.h>#include <linux/init.h>#include <linux/bootmem.h>#include <linux/delay.h>#include <linux/kernel.h>#include <linux/reboot.h>#include <linux/sched.h>#include <linux/seq_file.h>#include <linux/string.h>#include <linux/threads.h>#include <linux/console.h>#include <asm/acpi-ext.h>#include <asm/ia32.h>#include <asm/page.h>#include <asm/machvec.h>#include <asm/processor.h>#include <asm/sal.h>#include <asm/system.h>#include <asm/efi.h>#include <asm/mca.h>#include <asm/smp.h>#ifdef CONFIG_BLK_DEV_RAM# include <linux/blk.h>#endif#if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)# error "struct cpuinfo_ia64 too big!"#endif#define MIN(a,b) ((a) < (b) ? (a) : (b))#define MAX(a,b) ((a) > (b) ? (a) : (b))extern char _end;#ifdef CONFIG_NUMA struct cpuinfo_ia64 *boot_cpu_data;#else struct cpuinfo_ia64 _cpu_data[NR_CPUS] __attribute__ ((section ("__special_page_section")));#endifunsigned long ia64_cycles_per_usec;struct ia64_boot_param *ia64_boot_param;struct screen_info screen_info;unsigned long ia64_iobase; /* virtual address for I/O accesses */#define COMMAND_LINE_SIZE 512char saved_command_line[COMMAND_LINE_SIZE]; /* used in proc filesystem *//* * Entries defined so far: * - boot param structure itself * - memory map * - initrd (optional) * - command line string * - kernel code & data * * More could be added if necessary */#define IA64_MAX_RSVD_REGIONS 5struct rsvd_region { unsigned long start; /* virtual address of beginning of element */ unsigned long end; /* virtual address of end of element + 1 */};/* * We use a special marker for the end of memory and it uses the extra (+1) slot */static struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];static int num_rsvd_regions;static unsigned long bootmap_start; /* physical address where the bootmem map is located */static intfind_max_pfn (unsigned long start, unsigned long end, void *arg){ unsigned long *max_pfn = arg, pfn; pfn = (PAGE_ALIGN(end - 1) - PAGE_OFFSET) >> PAGE_SHIFT; if (pfn > *max_pfn) *max_pfn = pfn; return 0;}#define IGNORE_PFN0 1 /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... *//* * Free available memory based on the primitive map created from * the boot parameters. This routine does not assume the incoming * segments are sorted. */static intfree_available_memory (unsigned long start, unsigned long end, void *arg){ unsigned long range_start, range_end, prev_start; int i;#if IGNORE_PFN0 if (start == PAGE_OFFSET) { printk("warning: skipping physical page 0\n"); start += PAGE_SIZE; if (start >= end) return 0; }#endif /* * lowest possible address(walker uses virtual) */ prev_start = PAGE_OFFSET; for (i = 0; i < num_rsvd_regions; ++i) { range_start = MAX(start, prev_start); range_end = MIN(end, rsvd_region[i].start); if (range_start < range_end) free_bootmem(__pa(range_start), range_end - range_start); /* nothing more available in this segment */ if (range_end == end) return 0; prev_start = rsvd_region[i].end; } /* end of memory marker allows full processing inside loop body */ return 0;}static intfind_bootmap_location (unsigned long start, unsigned long end, void *arg){ unsigned long needed = *(unsigned long *)arg; unsigned long range_start, range_end, free_start; int i;#if IGNORE_PFN0 if (start == PAGE_OFFSET) { start += PAGE_SIZE; if (start >= end) return 0; }#endif free_start = PAGE_OFFSET; for (i = 0; i < num_rsvd_regions; i++) { range_start = MAX(start, free_start); range_end = MIN(end, rsvd_region[i].start); if (range_end <= range_start) continue; /* skip over empty range */ if (range_end - range_start >= needed) { bootmap_start = __pa(range_start); return 1; /* done */ } /* nothing more available in this segment */ if (range_end == end) return 0; free_start = rsvd_region[i].end; } return 0;}static voidsort_regions (struct rsvd_region *rsvd_region, int max){ int j; /* simple bubble sorting */ while (max--) { for (j = 0; j < max; ++j) { if (rsvd_region[j].start > rsvd_region[j+1].start) { struct rsvd_region tmp; tmp = rsvd_region[j]; rsvd_region[j] = rsvd_region[j + 1]; rsvd_region[j + 1] = tmp; } } }}static voidfind_memory (void){# define KERNEL_END ((unsigned long) &_end) unsigned long bootmap_size; unsigned long max_pfn; int n = 0; /* * none of the entries in this table overlap */ rsvd_region[n].start = (unsigned long) ia64_boot_param; rsvd_region[n].end = rsvd_region[n].start + sizeof(*ia64_boot_param); n++; rsvd_region[n].start = (unsigned long) __va(ia64_boot_param->efi_memmap); rsvd_region[n].end = rsvd_region[n].start + ia64_boot_param->efi_memmap_size; n++; rsvd_region[n].start = (unsigned long) __va(ia64_boot_param->command_line); rsvd_region[n].end = (rsvd_region[n].start + strlen(__va(ia64_boot_param->command_line)) + 1); n++; rsvd_region[n].start = KERNEL_START; rsvd_region[n].end = KERNEL_END; n++;#ifdef CONFIG_BLK_DEV_INITRD if (ia64_boot_param->initrd_start) { rsvd_region[n].start = (unsigned long)__va(ia64_boot_param->initrd_start); rsvd_region[n].end = rsvd_region[n].start + ia64_boot_param->initrd_size; n++; }#endif /* end of memory marker */ rsvd_region[n].start = ~0UL; rsvd_region[n].end = ~0UL; n++; num_rsvd_regions = n; sort_regions(rsvd_region, num_rsvd_regions); /* first find highest page frame number */ max_pfn = 0; efi_memmap_walk(find_max_pfn, &max_pfn); /* how many bytes to cover all the pages */ bootmap_size = bootmem_bootmap_pages(max_pfn) << PAGE_SHIFT; /* look for a location to hold the bootmap */ bootmap_start = ~0UL; efi_memmap_walk(find_bootmap_location, &bootmap_size); if (bootmap_start == ~0UL) panic("Cannot find %ld bytes for bootmap\n", bootmap_size); bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn); /* Free all available memory, then mark bootmem-map as being in use. */ efi_memmap_walk(free_available_memory, 0); reserve_bootmem(bootmap_start, bootmap_size);#ifdef CONFIG_BLK_DEV_INITRD if (ia64_boot_param->initrd_start) { initrd_start = (unsigned long)__va(ia64_boot_param->initrd_start); initrd_end = initrd_start+ia64_boot_param->initrd_size; printk("Initial ramdisk at: 0x%lx (%lu bytes)\n", initrd_start, ia64_boot_param->initrd_size); }#endif}void __initsetup_arch (char **cmdline_p){ extern unsigned long ia64_iobase; unw_init(); *cmdline_p = __va(ia64_boot_param->command_line); strncpy(saved_command_line, *cmdline_p, sizeof(saved_command_line)); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; /* for safety */ efi_init(); find_memory();#if 0 /* XXX fix me */ init_mm.start_code = (unsigned long) &_stext; 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;#endif /* process SAL system table: */ ia64_sal_init(efi.sal_systab); /* * Set `iobase' to the appropriate address in region 6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -