patch-2.3.99-pre8 linux/arch/s390/kernel/setup.c
Next file: linux/arch/s390/kernel/signal.c
Previous file: linux/arch/s390/kernel/semaphore.c
Back to the patch index
Back to the overall index
- Lines: 386
- Date:
Fri May 12 11:41:45 2000
- Orig file:
v2.3.99-pre7/linux/arch/s390/kernel/setup.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.99-pre7/linux/arch/s390/kernel/setup.c linux/arch/s390/kernel/setup.c
@@ -0,0 +1,385 @@
+/*
+ * arch/s390/kernel/setup.c
+ *
+ * S390 version
+ * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Hartmut Penner (hp@de.ibm.com),
+ * Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ * Derived from "arch/i386/kernel/setup.c"
+ * Copyright (C) 1995, Linus Torvalds
+ */
+
+/*
+ * 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/malloc.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>
+#ifdef CONFIG_BLK_DEV_RAM
+#include <linux/blk.h>
+#endif
+#include <linux/bootmem.h>
+#include <linux/console.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/smp.h>
+#include <asm/mmu_context.h>
+
+/*
+ * Machine setup..
+ */
+__u16 boot_cpu_addr;
+int cpus_initialized = 0;
+unsigned long cpu_initialized = 0;
+
+/*
+ * Setup options
+ */
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt*/
+extern int rd_image_start; /* starting block # of image */
+#endif
+
+extern int root_mountflags;
+extern int _text,_etext, _edata, _end;
+
+
+/*
+ * This is set up by the setup-routine at boot-time
+ * for S390 need to find out, what we have to setup
+ * using address 0x10400 ...
+ */
+
+#include <asm/setup.h>
+
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+ char saved_command_line[COMMAND_LINE_SIZE];
+
+static struct resource code_resource = { "Kernel code", 0x100000, 0 };
+static struct resource data_resource = { "Kernel data", 0, 0 };
+
+/*
+ * cpu_init() initializes state that is per-CPU.
+ */
+void __init cpu_init (void)
+{
+ int nr = smp_processor_id();
+
+ if (test_and_set_bit(nr,&cpu_initialized)) {
+ printk("CPU#%d ALREADY INITIALIZED!!!!!!!!!\n", nr);
+ for (;;) __sti();
+ }
+ cpus_initialized++;
+
+ /*
+ * Store processor id in lowcore (used e.g. in timer_interrupt)
+ */
+ asm volatile ("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
+ S390_lowcore.cpu_data.cpu_addr = hard_smp_processor_id();
+ S390_lowcore.cpu_data.cpu_nr = nr;
+
+ /*
+ * Force FPU initialization:
+ */
+ current->flags &= ~PF_USEDFPU;
+ current->used_math = 0;
+
+ /* Setup active_mm for idle_task */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+ if (current->mm)
+ BUG();
+ enter_lazy_tlb(&init_mm, current, nr);
+}
+
+/*
+ * VM halt and poweroff setup routines
+ */
+char vmhalt_cmd[128] = "";
+char vmpoff_cmd[128] = "";
+
+static inline void strncpy_skip_quote(char *dst, char *src, int n)
+{
+ int sx, dx;
+
+ dx = 0;
+ for (sx = 0; src[sx] != 0; sx++) {
+ if (src[sx] == '"') continue;
+ dst[dx++] = src[sx];
+ if (dx >= n) break;
+ }
+}
+
+static int __init vmhalt_setup(char *str)
+{
+ strncpy_skip_quote(vmhalt_cmd, str, 127);
+ vmhalt_cmd[127] = 0;
+ return 1;
+}
+
+__setup("vmhalt=", vmhalt_setup);
+
+static int __init vmpoff_setup(char *str)
+{
+ strncpy_skip_quote(vmpoff_cmd, str, 127);
+ vmpoff_cmd[127] = 0;
+ return 1;
+}
+
+__setup("vmpoff=", vmpoff_setup);
+
+/*
+ * Reboot, halt and power_off routines for non SMP.
+ */
+
+#ifndef CONFIG_SMP
+void machine_restart(char * __unused)
+{
+ reipl(S390_lowcore.ipl_device);
+}
+
+void machine_halt(void)
+{
+ if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
+ cpcmd(vmhalt_cmd, NULL, 0);
+ disabled_wait(0);
+}
+
+void machine_power_off(void)
+{
+ if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
+ cpcmd(vmpoff_cmd, NULL, 0);
+ disabled_wait(0);
+}
+#endif
+
+/*
+ * Waits for 'delay' microseconds using the tod clock
+ */
+void tod_wait(unsigned long delay)
+{
+ uint64_t start_cc, end_cc;
+
+ if (delay == 0)
+ return;
+ asm volatile ("STCK %0" : "=m" (start_cc));
+ do {
+ asm volatile ("STCK %0" : "=m" (end_cc));
+ } while (((end_cc - start_cc)/4096) < delay);
+}
+
+/*
+ * Setup function called from init/main.c just after the banner
+ * was printed.
+ */
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long bootmap_size;
+ unsigned long memory_start, memory_end;
+ char c = ' ', *to = command_line, *from = COMMAND_LINE;
+ struct resource *res;
+ unsigned long start_pfn, end_pfn;
+ static unsigned int smptrap=0;
+ unsigned long delay = 0;
+ int len = 0;
+
+ if (smptrap)
+ return;
+ smptrap=1;
+
+ printk("Command line is: %s\n", COMMAND_LINE);
+
+ /*
+ * Setup lowcore information for boot cpu
+ */
+ cpu_init();
+ boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
+
+ /*
+ * print what head.S has found out about the machine
+ */
+ printk((MACHINE_IS_VM) ?
+ "We are running under VM\n" :
+ "We are running native\n");
+ printk((MACHINE_HAS_IEEE) ?
+ "This machine has an IEEE fpu\n" :
+ "This machine has no IEEE fpu\n");
+
+ ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
+#ifdef CONFIG_BLK_DEV_RAM
+ rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+ rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+ rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+ /* nasty stuff with PARMAREAs. we use head.S or parameterline
+ if (!MOUNT_ROOT_RDONLY)
+ root_mountflags &= ~MS_RDONLY;
+ */
+ memory_start = (unsigned long) &_end; /* fixit if use $CODELO etc*/
+ memory_end = MEMORY_SIZE; /* detected in head.s */
+ init_mm.start_code = PAGE_OFFSET;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) &_end;
+
+ code_resource.start = (unsigned long) &_text;
+ code_resource.end = (unsigned long) &_etext - 1;
+ data_resource.start = (unsigned long) &_etext;
+ data_resource.end = (unsigned long) &_edata - 1;
+
+ /* 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 (;;) {
+ /*
+ * "mem=XXX[kKmM]" sets memsize
+ */
+ if (c == ' ' && strncmp(from, "mem=", 4) == 0) {
+ if (to != command_line) to--;
+ memory_end = simple_strtoul(from+4, &from, 0);
+ if ( *from == 'K' || *from == 'k' ) {
+ memory_end = memory_end << 10;
+ from++;
+ } else if ( *from == 'M' || *from == 'm' ) {
+ memory_end = memory_end << 20;
+ from++;
+ }
+ }
+ /*
+ * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes
+ */
+ if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) {
+ if (to != command_line) to--;
+ delay = simple_strtoul(from+9, &from, 0);
+ if (*from == 's' || *from == 'S') {
+ delay = delay*1000000;
+ from++;
+ } else if (*from == 'm' || *from == 'M') {
+ delay = delay*60*1000000;
+ from++;
+ }
+ /* now wait for the requestion amount of time */
+ tod_wait(delay);
+ }
+ c = *(from++);
+ if (!c)
+ break;
+ if (COMMAND_LINE_SIZE <= ++len)
+ break;
+ *(to++) = c;
+ }
+ *to = '\0';
+ *cmdline_p = command_line;
+
+ /*
+ * partially used pages are not usable - thus
+ * we are rounding upwards:
+ */
+ start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ end_pfn = memory_end >> PAGE_SHIFT;
+
+ /*
+ * Initialize the boot-time allocator (with low memory only):
+ */
+ bootmap_size = init_bootmem(start_pfn, end_pfn);
+
+ /*
+ * Register RAM pages with the bootmem allocator.
+ */
+ free_bootmem(start_pfn << PAGE_SHIFT,
+ (end_pfn - start_pfn) << PAGE_SHIFT);
+
+ /*
+ * Reserve the bootmem bitmap itself as well. We do this in two
+ * steps (first step was init_bootmem()) because this catches
+ * the (very unlikely) case of us accidentally initializing the
+ * bootmem allocator with an invalid RAM area.
+ */
+ reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);
+
+ paging_init();
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (INITRD_START) {
+ if (INITRD_START + INITRD_SIZE < memory_end) {
+ reserve_bootmem(INITRD_START, INITRD_SIZE);
+ initrd_start = INITRD_START;
+ initrd_end = initrd_start + INITRD_SIZE;
+ } else {
+ printk("initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ initrd_start + INITRD_SIZE, memory_end);
+ initrd_start = initrd_end = 0;
+ }
+ }
+#endif
+ res = alloc_bootmem_low(sizeof(struct resource));
+ res->start = 0;
+ res->end = memory_end;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ request_resource(&iomem_resource, res);
+ request_resource(res, &code_resource);
+ request_resource(res, &data_resource);
+}
+
+void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
+{
+ printk("cpu %d "
+#ifdef CONFIG_SMP
+ "phys_idx=%d "
+#endif
+ "vers=%02X ident=%06X machine=%04X unused=%04X\n",
+ cpuinfo->cpu_nr,
+#ifdef CONFIG_SMP
+ cpuinfo->cpu_addr,
+#endif
+ cpuinfo->cpu_id.version,
+ cpuinfo->cpu_id.ident,
+ cpuinfo->cpu_id.machine,
+ cpuinfo->cpu_id.unused);
+}
+
+/*
+ * Get CPU information for use by the procfs.
+ */
+
+int get_cpuinfo(char * buffer)
+{
+ struct cpuinfo_S390 *cpuinfo;
+ char *p = buffer;
+ int i;
+
+ p += sprintf(p,"vendor_id : IBM/S390\n"
+ "# processors : %i\n"
+ "bogomips per cpu: %lu.%02lu\n",
+ smp_num_cpus, loops_per_sec/500000,
+ (loops_per_sec/5000)%100);
+ for (i = 0; i < smp_num_cpus; i++) {
+ cpuinfo = &safe_get_cpu_lowcore(i).cpu_data;
+ p += sprintf(p,"processor %i: "
+ "version = %02X, "
+ "identification = %06X, "
+ "machine = %04X\n",
+ i, cpuinfo->cpu_id.version,
+ cpuinfo->cpu_id.ident,
+ cpuinfo->cpu_id.machine);
+ }
+ return p - buffer;
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)