patch-2.4.13 linux/arch/s390x/kernel/setup.c

Next file: linux/arch/s390x/kernel/signal.c
Previous file: linux/arch/s390x/kernel/s390_ksyms.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.12/linux/arch/s390x/kernel/setup.c linux/arch/s390x/kernel/setup.c
@@ -47,6 +47,9 @@
 unsigned int console_device = -1;
 unsigned long memory_size = 0;
 unsigned long machine_flags = 0;
+struct { unsigned long addr, size, type; } memory_chunk[16];
+#define CHUNK_READ_WRITE 0
+#define CHUNK_READ_ONLY 1
 __u16 boot_cpu_addr;
 int cpus_initialized = 0;
 unsigned long cpu_initialized = 0;
@@ -257,6 +260,8 @@
  * Setup function called from init/main.c just after the banner
  * was printed.
  */
+extern char _pstart, _pend, _stext;
+
 void __init setup_arch(char **cmdline_p)
 {
         unsigned long bootmap_size;
@@ -266,19 +271,14 @@
 	unsigned long start_pfn, end_pfn;
         static unsigned int smptrap=0;
         unsigned long delay = 0;
+	struct _lowcore *lowcore;
+	int i;
 
         if (smptrap)
                 return;
         smptrap=1;
 
         /*
-         * Setup lowcore information for boot cpu
-         */
-        cpu_init();
-        boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
-        __cpu_logical_map[0] = boot_cpu_addr;
-
-        /*
          * print what head.S has found out about the machine 
          */
 	printk((MACHINE_IS_VM) ?
@@ -287,7 +287,7 @@
 
         ROOT_DEV = to_kdev_t(0x0100);
         memory_start = (unsigned long) &_end;    /* fixit if use $CODELO etc*/
-	memory_end = memory_size;                /* detected in head.s */
+	memory_end = memory_size & ~0x200000UL;  /* detected in head.s */
         init_mm.start_code = PAGE_OFFSET;
         init_mm.end_code = (unsigned long) &_etext;
         init_mm.end_data = (unsigned long) &_edata;
@@ -362,11 +362,26 @@
 	bootmap_size = init_bootmem(start_pfn, end_pfn);
 
 	/*
-	 * Register RAM pages with the bootmem allocator.
+	 * Register RAM areas with the bootmem allocator.
 	 */
-	free_bootmem(start_pfn << PAGE_SHIFT, 
-		     (end_pfn - start_pfn) << PAGE_SHIFT);
+	for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) {
+		unsigned long start_chunk, end_chunk;
 
+		if (memory_chunk[i].type != CHUNK_READ_WRITE)
+			continue;
+		start_chunk = (memory_chunk[i].addr + PAGE_SIZE - 1);
+		start_chunk >>= PAGE_SHIFT;
+		end_chunk = (memory_chunk[i].addr + memory_chunk[i].size);
+		end_chunk >>= PAGE_SHIFT;
+		if (start_chunk < start_pfn)
+			start_chunk = start_pfn;
+		if (end_chunk > end_pfn)
+			end_chunk = end_pfn;
+		if (start_chunk < end_chunk)
+			free_bootmem(start_chunk << PAGE_SHIFT,
+				     (end_chunk - start_chunk) << PAGE_SHIFT);
+	}
+	
         /*
          * Reserve the bootmem bitmap itself as well. We do this in two
          * steps (first step was init_bootmem()) because this catches
@@ -390,6 +405,36 @@
         }
 #endif
 
+        /*
+         * Setup lowcore for boot cpu
+         */
+	lowcore = (struct _lowcore *) 
+		__alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0);
+	memset(lowcore, 0, 2*PAGE_SIZE);
+	lowcore->restart_psw.mask = _RESTART_PSW_MASK;
+	lowcore->restart_psw.addr = (addr_t) &restart_int_handler;
+	lowcore->external_new_psw.mask = _EXT_PSW_MASK;
+	lowcore->external_new_psw.addr = (addr_t) &ext_int_handler;
+	lowcore->svc_new_psw.mask = _SVC_PSW_MASK;
+	lowcore->svc_new_psw.addr = (addr_t) &system_call;
+	lowcore->program_new_psw.mask = _PGM_PSW_MASK;
+	lowcore->program_new_psw.addr = (addr_t) &pgm_check_handler;
+	lowcore->mcck_new_psw.mask = _MCCK_PSW_MASK;
+	lowcore->mcck_new_psw.addr = (addr_t) &mcck_int_handler;
+	lowcore->io_new_psw.mask = _IO_PSW_MASK;
+	lowcore->io_new_psw.addr = (addr_t) &io_int_handler;
+	lowcore->ipl_device = S390_lowcore.ipl_device;
+	lowcore->kernel_stack = ((__u32) &init_task_union) + 16384;
+	lowcore->async_stack = (__u64)
+		__alloc_bootmem(4*PAGE_SIZE, 4*PAGE_SIZE, 0) + 16384;
+	set_prefix((__u32)(__u64) lowcore);
+        cpu_init();
+        boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
+        __cpu_logical_map[0] = boot_cpu_addr;
+
+	/*
+	 * Create kernel page tables and switch to virtual addressing.
+	 */
         paging_init();
 
 	res = alloc_bootmem_low(sizeof(struct resource));
@@ -422,30 +467,49 @@
 }
 
 /*
- *	Get CPU information for use by the procfs.
+ * get_cpuinfo - Get information on one CPU for use by procfs.
+ *
+ *	Prints info on the next CPU into buffer.  Beware, doesn't check for
+ *	buffer overflow.  Current implementation of procfs assumes that the
+ *	resulting data is <= 1K.
+ *
+ * Args:
+ *	buffer	-- you guessed it, the data buffer
+ *	cpu_np	-- Input: next cpu to get (start at 0).  Output: Updated.
+ *
+ *	Returns number of bytes written to buffer.
  */
 
-int get_cpuinfo(char * buffer)
+int get_cpuinfo(char *buffer, unsigned *cpu_np)
 {
         struct cpuinfo_S390 *cpuinfo;
         char *p = buffer;
-        int i;
+	unsigned n;
 
-        p += sprintf(p,"vendor_id       : IBM/S390\n"
-                       "# processors    : %i\n"
-                       "bogomips per cpu: %lu.%02lu\n",
-                       smp_num_cpus, loops_per_jiffy/(500000/HZ),
-                       (loops_per_jiffy/(5000/HZ))%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);
-        }
+	n = *cpu_np;
+	while (n < NR_CPUS && (cpu_online_map & (1 << n)) == 0)
+		n++;
+	if (n >= NR_CPUS) {
+		*cpu_np = NR_CPUS;
+		return (0);
+	}
+	*cpu_np = n + 1;
+
+	if (n == 0) {
+		p += sprintf(p, "vendor_id       : IBM/S390\n"
+				"# processors    : %i\n"
+				"bogomips per cpu: %lu.%02lu\n",
+				smp_num_cpus, loops_per_jiffy/(500000/HZ),
+				(loops_per_jiffy/(5000/HZ))%100);
+	}
+	cpuinfo = &safe_get_cpu_lowcore(n).cpu_data;
+	p += sprintf(p, "processor %i: "
+			"version = %02X,  "
+			"identification = %06X,  "
+			"machine = %04X\n",
+			n, 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)