aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/setup.c')
-rw-r--r--arch/s390/kernel/setup.c178
1 files changed, 170 insertions, 8 deletions
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index b1b9a931237d..2569aafcc543 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -38,6 +38,7 @@
38#include <linux/device.h> 38#include <linux/device.h>
39#include <linux/notifier.h> 39#include <linux/notifier.h>
40#include <linux/pfn.h> 40#include <linux/pfn.h>
41#include <linux/ctype.h>
41#include <linux/reboot.h> 42#include <linux/reboot.h>
42 43
43#include <asm/uaccess.h> 44#include <asm/uaccess.h>
@@ -50,6 +51,7 @@
50#include <asm/page.h> 51#include <asm/page.h>
51#include <asm/ptrace.h> 52#include <asm/ptrace.h>
52#include <asm/sections.h> 53#include <asm/sections.h>
54#include <asm/ebcdic.h>
53#include <asm/compat.h> 55#include <asm/compat.h>
54 56
55long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | 57long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY |
@@ -282,6 +284,140 @@ static void __init conmode_default(void)
282 } 284 }
283} 285}
284 286
287/*
288 * Create a Kernel NSS if the SAVESYS= parameter is defined
289*/
290#define DEFSYS_CMD_SIZE 96
291#define SAVESYS_CMD_SIZE 32
292
293extern int _eshared;
294char kernel_nss_name[NSS_NAME_SIZE + 1];
295
296#ifdef CONFIG_SHARED_KERNEL
297static __init void create_kernel_nss(void)
298{
299 unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
300#ifdef CONFIG_BLK_DEV_INITRD
301 unsigned int sinitrd_pfn, einitrd_pfn;
302#endif
303 int response;
304 char *savesys_ptr;
305 char upper_command_line[COMMAND_LINE_SIZE];
306 char defsys_cmd[DEFSYS_CMD_SIZE];
307 char savesys_cmd[SAVESYS_CMD_SIZE];
308
309 /* Do nothing if we are not running under VM */
310 if (!MACHINE_IS_VM)
311 return;
312
313 /* Convert COMMAND_LINE to upper case */
314 for (i = 0; i < strlen(COMMAND_LINE); i++)
315 upper_command_line[i] = toupper(COMMAND_LINE[i]);
316
317 savesys_ptr = strstr(upper_command_line, "SAVESYS=");
318
319 if (!savesys_ptr)
320 return;
321
322 savesys_ptr += 8; /* Point to the beginning of the NSS name */
323 for (i = 0; i < NSS_NAME_SIZE; i++) {
324 if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0')
325 break;
326 kernel_nss_name[i] = savesys_ptr[i];
327 }
328
329 stext_pfn = PFN_DOWN(__pa(&_stext));
330 eshared_pfn = PFN_DOWN(__pa(&_eshared));
331 end_pfn = PFN_UP(__pa(&_end));
332 min_size = end_pfn << 2;
333
334 sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X",
335 kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1,
336 eshared_pfn, end_pfn);
337
338#ifdef CONFIG_BLK_DEV_INITRD
339 if (INITRD_START && INITRD_SIZE) {
340 sinitrd_pfn = PFN_DOWN(__pa(INITRD_START));
341 einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE));
342 min_size = einitrd_pfn << 2;
343 sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd,
344 sinitrd_pfn, einitrd_pfn);
345 }
346#endif
347
348 sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size);
349 sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
350 kernel_nss_name, kernel_nss_name);
351
352 __cpcmd(defsys_cmd, NULL, 0, &response);
353
354 if (response != 0)
355 return;
356
357 __cpcmd(savesys_cmd, NULL, 0, &response);
358
359 if (response != strlen(savesys_cmd))
360 return;
361
362 ipl_flags = IPL_NSS_VALID;
363}
364
365#else /* CONFIG_SHARED_KERNEL */
366
367static inline void create_kernel_nss(void) { }
368
369#endif /* CONFIG_SHARED_KERNEL */
370
371/*
372 * Clear bss memory
373 */
374static __init void clear_bss_section(void)
375{
376 memset(__bss_start, 0, _end - __bss_start);
377}
378
379/*
380 * Initialize storage key for kernel pages
381 */
382static __init void init_kernel_storage_key(void)
383{
384 unsigned long end_pfn, init_pfn;
385
386 end_pfn = PFN_UP(__pa(&_end));
387
388 for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
389 page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
390}
391
392static __init void detect_machine_type(void)
393{
394 struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
395
396 asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
397
398 /* Running under z/VM ? */
399 if (cpuinfo->cpu_id.version == 0xff)
400 machine_flags |= 1;
401
402 /* Running on a P/390 ? */
403 if (cpuinfo->cpu_id.machine == 0x7490)
404 machine_flags |= 4;
405}
406
407/*
408 * Save ipl parameters, clear bss memory, initialize storage keys
409 * and create a kernel NSS at startup if the SAVESYS= parm is defined
410 */
411void __init startup_init(void)
412{
413 ipl_save_parameters();
414 clear_bss_section();
415 init_kernel_storage_key();
416 lockdep_init();
417 detect_machine_type();
418 create_kernel_nss();
419}
420
285#ifdef CONFIG_SMP 421#ifdef CONFIG_SMP
286void (*_machine_restart)(char *command) = machine_restart_smp; 422void (*_machine_restart)(char *command) = machine_restart_smp;
287void (*_machine_halt)(void) = machine_halt_smp; 423void (*_machine_halt)(void) = machine_halt_smp;
@@ -523,7 +659,7 @@ setup_lowcore(void)
523static void __init 659static void __init
524setup_resources(void) 660setup_resources(void)
525{ 661{
526 struct resource *res; 662 struct resource *res, *sub_res;
527 int i; 663 int i;
528 664
529 code_resource.start = (unsigned long) &_text; 665 code_resource.start = (unsigned long) &_text;
@@ -548,8 +684,38 @@ setup_resources(void)
548 res->start = memory_chunk[i].addr; 684 res->start = memory_chunk[i].addr;
549 res->end = memory_chunk[i].addr + memory_chunk[i].size - 1; 685 res->end = memory_chunk[i].addr + memory_chunk[i].size - 1;
550 request_resource(&iomem_resource, res); 686 request_resource(&iomem_resource, res);
551 request_resource(res, &code_resource); 687
552 request_resource(res, &data_resource); 688 if (code_resource.start >= res->start &&
689 code_resource.start <= res->end &&
690 code_resource.end > res->end) {
691 sub_res = alloc_bootmem_low(sizeof(struct resource));
692 memcpy(sub_res, &code_resource,
693 sizeof(struct resource));
694 sub_res->end = res->end;
695 code_resource.start = res->end + 1;
696 request_resource(res, sub_res);
697 }
698
699 if (code_resource.start >= res->start &&
700 code_resource.start <= res->end &&
701 code_resource.end <= res->end)
702 request_resource(res, &code_resource);
703
704 if (data_resource.start >= res->start &&
705 data_resource.start <= res->end &&
706 data_resource.end > res->end) {
707 sub_res = alloc_bootmem_low(sizeof(struct resource));
708 memcpy(sub_res, &data_resource,
709 sizeof(struct resource));
710 sub_res->end = res->end;
711 data_resource.start = res->end + 1;
712 request_resource(res, sub_res);
713 }
714
715 if (data_resource.start >= res->start &&
716 data_resource.start <= res->end &&
717 data_resource.end <= res->end)
718 request_resource(res, &data_resource);
553 } 719 }
554} 720}
555 721
@@ -585,7 +751,7 @@ static void __init
585setup_memory(void) 751setup_memory(void)
586{ 752{
587 unsigned long bootmap_size; 753 unsigned long bootmap_size;
588 unsigned long start_pfn, end_pfn, init_pfn; 754 unsigned long start_pfn, end_pfn;
589 int i; 755 int i;
590 756
591 /* 757 /*
@@ -595,10 +761,6 @@ setup_memory(void)
595 start_pfn = PFN_UP(__pa(&_end)); 761 start_pfn = PFN_UP(__pa(&_end));
596 end_pfn = max_pfn = PFN_DOWN(memory_end); 762 end_pfn = max_pfn = PFN_DOWN(memory_end);
597 763
598 /* Initialize storage key for kernel pages */
599 for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++)
600 page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
601
602#ifdef CONFIG_BLK_DEV_INITRD 764#ifdef CONFIG_BLK_DEV_INITRD
603 /* 765 /*
604 * Move the initrd in case the bitmap of the bootmem allocater 766 * Move the initrd in case the bitmap of the bootmem allocater