patch-2.3.43 linux/arch/ia64/kernel/setup.c
Next file: linux/arch/ia64/kernel/signal.c
Previous file: linux/arch/ia64/kernel/semaphore.c
Back to the patch index
Back to the overall index
- Lines: 327
- Date:
Sun Feb 6 18:42:40 2000
- Orig file:
v2.3.42/linux/arch/ia64/kernel/setup.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/setup.c linux/arch/ia64/kernel/setup.c
@@ -0,0 +1,326 @@
+/*
+ * Architecture-specific setup.
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999 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>
+ *
+ * 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/string.h>
+#include <linux/threads.h>
+#include <linux/console.h>
+
+#include <asm/acpi-ext.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>
+
+extern char _end;
+
+/* cpu_data[bootstrap_processor] is data for the bootstrap processor: */
+struct cpuinfo_ia64 cpu_data[NR_CPUS];
+
+unsigned long ia64_cycles_per_usec;
+struct ia64_boot_param ia64_boot_param;
+struct screen_info screen_info;
+unsigned long cpu_initialized = 0;
+/* This tells _start which CPU is booting. */
+int cpu_now_booting = 0;
+
+#define COMMAND_LINE_SIZE 512
+
+char saved_command_line[COMMAND_LINE_SIZE]; /* used in proc filesystem */
+
+static int
+find_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;
+}
+
+static int
+free_available_memory (unsigned long start, unsigned long end, void *arg)
+{
+# define KERNEL_END ((unsigned long) &_end)
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+ unsigned long range_start, range_end;
+
+ range_start = MIN(start, KERNEL_START);
+ range_end = MIN(end, KERNEL_START);
+
+ /*
+ * XXX This should not be necessary, but the bootmem allocator
+ * is broken and fails to work correctly when the starting
+ * address is not properly aligned.
+ */
+ range_start = PAGE_ALIGN(range_start);
+
+ if (range_start < range_end)
+ free_bootmem(__pa(range_start), range_end - range_start);
+
+ range_start = MAX(start, KERNEL_END);
+ range_end = MAX(end, KERNEL_END);
+
+ /*
+ * XXX This should not be necessary, but the bootmem allocator
+ * is broken and fails to work correctly when the starting
+ * address is not properly aligned.
+ */
+ range_start = PAGE_ALIGN(range_start);
+
+ if (range_start < range_end)
+ free_bootmem(__pa(range_start), range_end - range_start);
+
+ return 0;
+}
+
+void __init
+setup_arch (char **cmdline_p)
+{
+ unsigned long max_pfn, bootmap_start, bootmap_size;
+
+ /*
+ * The secondary bootstrap loader passes us the boot
+ * parameters at the beginning of the ZERO_PAGE, so let's
+ * stash away those values before ZERO_PAGE gets cleared out.
+ */
+ memcpy(&ia64_boot_param, (void *) ZERO_PAGE_ADDR, sizeof(ia64_boot_param));
+
+ efi_init();
+
+ max_pfn = 0;
+ efi_memmap_walk(find_max_pfn, &max_pfn);
+
+ /*
+ * This is wrong, wrong, wrong. Darn it, you'd think if they
+ * change APIs, they'd do things for the better. Grumble...
+ */
+ bootmap_start = PAGE_ALIGN(__pa(&_end));
+ bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn);
+
+ efi_memmap_walk(free_available_memory, 0);
+
+ reserve_bootmem(bootmap_start, bootmap_size);
+#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);
+
+ *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 */
+
+ printk("args to kernel: %s\n", *cmdline_p);
+
+#ifndef CONFIG_SMP
+ cpu_init();
+ identify_cpu(&cpu_data[0]);
+#endif
+
+ if (efi.acpi) {
+ /* Parse the ACPI tables */
+ acpi_parse(efi.acpi);
+ }
+
+#ifdef CONFIG_IA64_GENERIC
+ machvec_init(acpi_get_sysname());
+#endif
+
+#ifdef CONFIG_VT
+# if defined(CONFIG_VGA_CONSOLE)
+ conswitchp = &vga_con;
+# elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+# endif
+#endif
+ platform_setup(cmdline_p);
+}
+
+/*
+ * Display cpu info for all cpu's.
+ */
+int
+get_cpuinfo (char *buffer)
+{
+ char family[32], model[32], features[128], *cp, *p = buffer;
+ struct cpuinfo_ia64 *c;
+ unsigned long mask;
+
+ for (c = cpu_data; c < cpu_data + NR_CPUS; ++c) {
+ if (!(cpu_initialized & (1UL << (c - cpu_data))))
+ continue;
+
+ mask = c->features;
+
+ if (c->family == 7)
+ memcpy(family, "IA-64", 6);
+ else
+ sprintf(family, "%u", c->family);
+
+ switch (c->model) {
+ case 0: strcpy(model, "Itanium"); break;
+ default: sprintf(model, "%u", c->model); break;
+ }
+
+ /* build the feature string: */
+ memcpy(features, " standard", 10);
+ cp = features;
+ if (mask & 1) {
+ strcpy(cp, " branchlong");
+ cp = strchr(cp, '\0');
+ mask &= ~1UL;
+ }
+ if (mask)
+ sprintf(cp, " 0x%lx", mask);
+
+ p += sprintf(buffer,
+ "CPU# %lu\n"
+ "\tvendor : %s\n"
+ "\tfamily : %s\n"
+ "\tmodel : %s\n"
+ "\trevision : %u\n"
+ "\tarchrev : %u\n"
+ "\tfeatures :%s\n" /* don't change this---it _is_ right! */
+ "\tcpu number : %lu\n"
+ "\tcpu regs : %u\n"
+ "\tcpu MHz : %lu.%06lu\n"
+ "\titc MHz : %lu.%06lu\n"
+ "\tBogoMIPS : %lu.%02lu\n\n",
+ c - cpu_data, c->vendor, family, model, c->revision, c->archrev,
+ features,
+ c->ppn, c->number, c->proc_freq / 1000000, c->proc_freq % 1000000,
+ c->itc_freq / 1000000, c->itc_freq % 1000000,
+ loops_per_sec() / 500000, (loops_per_sec() / 5000) % 100);
+ }
+ return p - buffer;
+}
+
+void
+identify_cpu (struct cpuinfo_ia64 *c)
+{
+ union {
+ unsigned long bits[5];
+ struct {
+ /* id 0 & 1: */
+ char vendor[16];
+
+ /* id 2 */
+ u64 ppn; /* processor serial number */
+
+ /* id 3: */
+ unsigned number : 8;
+ unsigned revision : 8;
+ unsigned model : 8;
+ unsigned family : 8;
+ unsigned archrev : 8;
+ unsigned reserved : 24;
+
+ /* id 4: */
+ u64 features;
+ } field;
+ } cpuid;
+ int i;
+
+ for (i = 0; i < 5; ++i) {
+ cpuid.bits[i] = ia64_get_cpuid(i);
+ }
+
+#ifdef CONFIG_SMP
+ /*
+ * XXX Instead of copying the ITC info from the bootstrap
+ * processor, ia64_init_itm() should be done per CPU. That
+ * should get you the right info. --davidm 1/24/00
+ */
+ if (c != &cpu_data[bootstrap_processor]) {
+ memset(c, 0, sizeof(struct cpuinfo_ia64));
+ c->proc_freq = cpu_data[bootstrap_processor].proc_freq;
+ c->itc_freq = cpu_data[bootstrap_processor].itc_freq;
+ c->cyc_per_usec = cpu_data[bootstrap_processor].cyc_per_usec;
+ c->usec_per_cyc = cpu_data[bootstrap_processor].usec_per_cyc;
+ }
+#else
+ memset(c, 0, sizeof(struct cpuinfo_ia64));
+#endif
+
+ memcpy(c->vendor, cpuid.field.vendor, 16);
+#ifdef CONFIG_IA64_SOFTSDV_HACKS
+ /* BUG: SoftSDV doesn't support the cpuid registers. */
+ if (c->vendor[0] == '\0')
+ memcpy(c->vendor, "Intel", 6);
+#endif
+ c->ppn = cpuid.field.ppn;
+ c->number = cpuid.field.number;
+ c->revision = cpuid.field.revision;
+ c->model = cpuid.field.model;
+ c->family = cpuid.field.family;
+ c->archrev = cpuid.field.archrev;
+ c->features = cpuid.field.features;
+#ifdef CONFIG_SMP
+ c->loops_per_sec = loops_per_sec;
+#endif
+}
+
+/*
+ * cpu_init() initializes state that is per-CPU. This function acts
+ * as a 'CPU state barrier', nothing should get across.
+ */
+void
+cpu_init (void)
+{
+ int nr = smp_processor_id();
+
+ /* Clear the stack memory reserved for pt_regs: */
+ memset(ia64_task_regs(current), 0, sizeof(struct pt_regs));
+
+ /*
+ * Initialize default control register to defer speculative
+ * faults. On a speculative load, we want to defer access
+ * right, key miss, and key permission faults. We currently
+ * do NOT defer TLB misses, page-not-present, access bit, or
+ * debug faults but kernel code should not rely on any
+ * particular setting of these bits.
+ */
+ ia64_set_dcr(IA64_DCR_DR | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_PP);
+ ia64_set_fpu_owner(0); /* initialize ar.k5 */
+
+ if (test_and_set_bit(nr, &cpu_initialized)) {
+ printk("CPU#%d already initialized!\n", nr);
+ machine_halt();
+ }
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)