aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorHongjie Yang <hongjie@us.ibm.com>2007-02-05 15:18:24 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-02-05 15:18:24 -0500
commitfe355b7f1c7400cbb71762a1237461be03f88265 (patch)
tree8ef581c8ff0889a200bae88a4961395bcb80aec4 /arch/s390
parent1b2782948997cf5a0d1747de13d43ba7dfa7c543 (diff)
[S390] boot from NSS support
Add support to boot from a named saved segment (NSS). Signed-off-by: Hongjie Yang <hongjie@us.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/head31.S34
-rw-r--r--arch/s390/kernel/head64.S30
-rw-r--r--arch/s390/kernel/ipl.c87
-rw-r--r--arch/s390/kernel/setup.c178
-rw-r--r--arch/s390/kernel/vmlinux.lds.S10
5 files changed, 275 insertions, 64 deletions
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index eca507050e47..b3dcdcdc80c0 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -51,20 +51,12 @@ startup_continue:
51 st %r15,__LC_KERNEL_STACK # set end of kernel stack 51 st %r15,__LC_KERNEL_STACK # set end of kernel stack
52 ahi %r15,-96 52 ahi %r15,-96
53 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain 53 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
54
55 l %r14,.Lipl_save_parameters-.LPG1(%r13)
56 basr %r14,%r14
57# 54#
58# clear bss memory 55# Save ipl parameters, clear bss memory, initialize storage key for kernel pages,
56# and create a kernel NSS if the SAVESYS= parm is defined
59# 57#
60 l %r2,.Lbss_bgn-.LPG1(%r13) # start of bss 58 l %r14,.Lstartup_init-.LPG1(%r13)
61 l %r3,.Lbss_end-.LPG1(%r13) # end of bss 59 basr %r14,%r14
62 sr %r3,%r2 # length of bss
63 sr %r4,%r4
64 sr %r5,%r5 # set src,length and pad to zero
65 sr %r0,%r0
66 mvcle %r2,%r4,0 # clear mem
67 jo .-4 # branch back, if not finish
68 60
69 l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word 61 l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
70.Lservicecall: 62.Lservicecall:
@@ -125,10 +117,10 @@ startup_continue:
125 b .Lfchunk-.LPG1(%r13) 117 b .Lfchunk-.LPG1(%r13)
126 118
127 .align 4 119 .align 4
128.Lipl_save_parameters:
129 .long ipl_save_parameters
130.Linittu: 120.Linittu:
131 .long init_thread_union 121 .long init_thread_union
122.Lstartup_init:
123 .long startup_init
132.Lpmask: 124.Lpmask:
133 .byte 0 125 .byte 0
134 .align 8 126 .align 8
@@ -207,20 +199,6 @@ startup_continue:
207.Ldonemem: 199.Ldonemem:
208 l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags 200 l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
209# 201#
210# find out if we are running under VM
211#
212 stidp __LC_CPUID # store cpuid
213 tm __LC_CPUID,0xff # running under VM ?
214 bno .Lnovm-.LPG1(%r13)
215 oi 3(%r12),1 # set VM flag
216.Lnovm:
217 lh %r0,__LC_CPUID+4 # get cpu version
218 chi %r0,0x7490 # running on a P/390 ?
219 bne .Lnop390-.LPG1(%r13)
220 oi 3(%r12),4 # set P/390 flag
221.Lnop390:
222
223#
224# find out if we have an IEEE fpu 202# find out if we have an IEEE fpu
225# 203#
226 mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13) 204 mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index e940e802cb40..030a1c95f47c 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -58,18 +58,11 @@ startup_continue:
58 stg %r15,__LC_KERNEL_STACK # set end of kernel stack 58 stg %r15,__LC_KERNEL_STACK # set end of kernel stack
59 aghi %r15,-160 59 aghi %r15,-160
60 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain 60 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
61
62 brasl %r14,ipl_save_parameters
63# 61#
64# clear bss memory 62# Save ipl parameters, clear bss memory, initialize storage key for kernel pages,
63# and create a kernel NSS if the SAVESYS= parm is defined
65# 64#
66 larl %r2,__bss_start # start of bss segment 65 brasl %r14,startup_init
67 larl %r3,_end # end of bss segment
68 sgr %r3,%r2 # length of bss
69 sgr %r4,%r4 #
70 sgr %r5,%r5 # set src,length and pad to zero
71 mvcle %r2,%r4,0 # clear mem
72 jo .-4 # branch back, if not finish
73 # set program check new psw mask 66 # set program check new psw mask
74 mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) 67 mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
75 larl %r1,.Lslowmemdetect # set program check address 68 larl %r1,.Lslowmemdetect # set program check address
@@ -78,6 +71,10 @@ startup_continue:
78 diag %r0,%r1,0x260 # get memory size of virtual machine 71 diag %r0,%r1,0x260 # get memory size of virtual machine
79 cgr %r0,%r1 # different? -> old detection routine 72 cgr %r0,%r1 # different? -> old detection routine
80 jne .Lslowmemdetect 73 jne .Lslowmemdetect
74 larl %r3,ipl_flags
75 llgt %r3,0(%r3)
76 chi %r3,4 # ipled from an kernel NSS
77 je .Lslowmemdetect
81 aghi %r1,1 # size is one more than end 78 aghi %r1,1 # size is one more than end
82 larl %r2,memory_chunk 79 larl %r2,memory_chunk
83 stg %r1,8(%r2) # store size of chunk 80 stg %r1,8(%r2) # store size of chunk
@@ -226,19 +223,6 @@ startup_continue:
226 223
227 larl %r12,machine_flags 224 larl %r12,machine_flags
228# 225#
229# find out if we are running under VM
230#
231 stidp __LC_CPUID # store cpuid
232 tm __LC_CPUID,0xff # running under VM ?
233 bno 0f-.LPG1(%r13)
234 oi 7(%r12),1 # set VM flag
2350: lh %r0,__LC_CPUID+4 # get cpu version
236 chi %r0,0x7490 # running on a P/390 ?
237 bne 1f-.LPG1(%r13)
238 oi 7(%r12),4 # set P/390 flag
2391:
240
241#
242# find out if we have the MVPG instruction 226# find out if we have the MVPG instruction
243# 227#
244 la %r1,0f-.LPG1(%r13) # set program check address 228 la %r1,0f-.LPG1(%r13) # set program check address
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 2c91226e1d40..13eacce62011 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -34,12 +34,14 @@ enum ipl_type {
34 IPL_TYPE_UNKNOWN = 2, 34 IPL_TYPE_UNKNOWN = 2,
35 IPL_TYPE_CCW = 4, 35 IPL_TYPE_CCW = 4,
36 IPL_TYPE_FCP = 8, 36 IPL_TYPE_FCP = 8,
37 IPL_TYPE_NSS = 16,
37}; 38};
38 39
39#define IPL_NONE_STR "none" 40#define IPL_NONE_STR "none"
40#define IPL_UNKNOWN_STR "unknown" 41#define IPL_UNKNOWN_STR "unknown"
41#define IPL_CCW_STR "ccw" 42#define IPL_CCW_STR "ccw"
42#define IPL_FCP_STR "fcp" 43#define IPL_FCP_STR "fcp"
44#define IPL_NSS_STR "nss"
43 45
44static char *ipl_type_str(enum ipl_type type) 46static char *ipl_type_str(enum ipl_type type)
45{ 47{
@@ -50,6 +52,8 @@ static char *ipl_type_str(enum ipl_type type)
50 return IPL_CCW_STR; 52 return IPL_CCW_STR;
51 case IPL_TYPE_FCP: 53 case IPL_TYPE_FCP:
52 return IPL_FCP_STR; 54 return IPL_FCP_STR;
55 case IPL_TYPE_NSS:
56 return IPL_NSS_STR;
53 case IPL_TYPE_UNKNOWN: 57 case IPL_TYPE_UNKNOWN:
54 default: 58 default:
55 return IPL_UNKNOWN_STR; 59 return IPL_UNKNOWN_STR;
@@ -64,6 +68,7 @@ enum ipl_method {
64 IPL_METHOD_FCP_RO_DIAG, 68 IPL_METHOD_FCP_RO_DIAG,
65 IPL_METHOD_FCP_RW_DIAG, 69 IPL_METHOD_FCP_RW_DIAG,
66 IPL_METHOD_FCP_RO_VM, 70 IPL_METHOD_FCP_RO_VM,
71 IPL_METHOD_NSS,
67}; 72};
68 73
69enum shutdown_action { 74enum shutdown_action {
@@ -114,11 +119,14 @@ enum diag308_rc {
114static int diag308_set_works = 0; 119static int diag308_set_works = 0;
115 120
116static int reipl_capabilities = IPL_TYPE_UNKNOWN; 121static int reipl_capabilities = IPL_TYPE_UNKNOWN;
122
117static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; 123static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
118static enum ipl_method reipl_method = IPL_METHOD_NONE; 124static enum ipl_method reipl_method = IPL_METHOD_NONE;
119static struct ipl_parameter_block *reipl_block_fcp; 125static struct ipl_parameter_block *reipl_block_fcp;
120static struct ipl_parameter_block *reipl_block_ccw; 126static struct ipl_parameter_block *reipl_block_ccw;
121 127
128static char reipl_nss_name[NSS_NAME_SIZE + 1];
129
122static int dump_capabilities = IPL_TYPE_NONE; 130static int dump_capabilities = IPL_TYPE_NONE;
123static enum ipl_type dump_type = IPL_TYPE_NONE; 131static enum ipl_type dump_type = IPL_TYPE_NONE;
124static enum ipl_method dump_method = IPL_METHOD_NONE; 132static enum ipl_method dump_method = IPL_METHOD_NONE;
@@ -173,6 +181,24 @@ static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
173 sys_##_prefix##_##_name##_show, \ 181 sys_##_prefix##_##_name##_show, \
174 sys_##_prefix##_##_name##_store); 182 sys_##_prefix##_##_name##_store);
175 183
184#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
185static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
186 char *page) \
187{ \
188 return sprintf(page, _fmt_out, _value); \
189} \
190static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
191 const char *buf, size_t len) \
192{ \
193 if (sscanf(buf, _fmt_in, _value) != 1) \
194 return -EINVAL; \
195 return len; \
196} \
197static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
198 __ATTR(_name,(S_IRUGO | S_IWUSR), \
199 sys_##_prefix##_##_name##_show, \
200 sys_##_prefix##_##_name##_store);
201
176static void make_attrs_ro(struct attribute **attrs) 202static void make_attrs_ro(struct attribute **attrs)
177{ 203{
178 while (*attrs) { 204 while (*attrs) {
@@ -189,6 +215,8 @@ static enum ipl_type ipl_get_type(void)
189{ 215{
190 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; 216 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
191 217
218 if (ipl_flags & IPL_NSS_VALID)
219 return IPL_TYPE_NSS;
192 if (!(ipl_flags & IPL_DEVNO_VALID)) 220 if (!(ipl_flags & IPL_DEVNO_VALID))
193 return IPL_TYPE_UNKNOWN; 221 return IPL_TYPE_UNKNOWN;
194 if (!(ipl_flags & IPL_PARMBLOCK_VALID)) 222 if (!(ipl_flags & IPL_PARMBLOCK_VALID))
@@ -324,6 +352,20 @@ static struct attribute_group ipl_ccw_attr_group = {
324 .attrs = ipl_ccw_attrs, 352 .attrs = ipl_ccw_attrs,
325}; 353};
326 354
355/* NSS ipl device attributes */
356
357DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
358
359static struct attribute *ipl_nss_attrs[] = {
360 &sys_ipl_type_attr.attr,
361 &sys_ipl_nss_name_attr.attr,
362 NULL,
363};
364
365static struct attribute_group ipl_nss_attr_group = {
366 .attrs = ipl_nss_attrs,
367};
368
327/* UNKNOWN ipl device attributes */ 369/* UNKNOWN ipl device attributes */
328 370
329static struct attribute *ipl_unknown_attrs[] = { 371static struct attribute *ipl_unknown_attrs[] = {
@@ -432,6 +474,21 @@ static struct attribute_group reipl_ccw_attr_group = {
432 .attrs = reipl_ccw_attrs, 474 .attrs = reipl_ccw_attrs,
433}; 475};
434 476
477
478/* NSS reipl device attributes */
479
480DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name);
481
482static struct attribute *reipl_nss_attrs[] = {
483 &sys_reipl_nss_name_attr.attr,
484 NULL,
485};
486
487static struct attribute_group reipl_nss_attr_group = {
488 .name = IPL_NSS_STR,
489 .attrs = reipl_nss_attrs,
490};
491
435/* reipl type */ 492/* reipl type */
436 493
437static int reipl_set_type(enum ipl_type type) 494static int reipl_set_type(enum ipl_type type)
@@ -454,6 +511,9 @@ static int reipl_set_type(enum ipl_type type)
454 else 511 else
455 reipl_method = IPL_METHOD_FCP_RO_DIAG; 512 reipl_method = IPL_METHOD_FCP_RO_DIAG;
456 break; 513 break;
514 case IPL_TYPE_NSS:
515 reipl_method = IPL_METHOD_NSS;
516 break;
457 default: 517 default:
458 reipl_method = IPL_METHOD_NONE; 518 reipl_method = IPL_METHOD_NONE;
459 } 519 }
@@ -475,6 +535,8 @@ static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf,
475 rc = reipl_set_type(IPL_TYPE_CCW); 535 rc = reipl_set_type(IPL_TYPE_CCW);
476 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0) 536 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
477 rc = reipl_set_type(IPL_TYPE_FCP); 537 rc = reipl_set_type(IPL_TYPE_FCP);
538 else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
539 rc = reipl_set_type(IPL_TYPE_NSS);
478 return (rc != 0) ? rc : len; 540 return (rc != 0) ? rc : len;
479} 541}
480 542
@@ -647,6 +709,10 @@ void do_reipl(void)
647 case IPL_METHOD_FCP_RO_VM: 709 case IPL_METHOD_FCP_RO_VM:
648 __cpcmd("IPL", NULL, 0, NULL); 710 __cpcmd("IPL", NULL, 0, NULL);
649 break; 711 break;
712 case IPL_METHOD_NSS:
713 sprintf(buf, "IPL %s", reipl_nss_name);
714 __cpcmd(buf, NULL, 0, NULL);
715 break;
650 case IPL_METHOD_NONE: 716 case IPL_METHOD_NONE:
651 default: 717 default:
652 if (MACHINE_IS_VM) 718 if (MACHINE_IS_VM)
@@ -733,6 +799,10 @@ static int __init ipl_init(void)
733 case IPL_TYPE_FCP: 799 case IPL_TYPE_FCP:
734 rc = ipl_register_fcp_files(); 800 rc = ipl_register_fcp_files();
735 break; 801 break;
802 case IPL_TYPE_NSS:
803 rc = sysfs_create_group(&ipl_subsys.kset.kobj,
804 &ipl_nss_attr_group);
805 break;
736 default: 806 default:
737 rc = sysfs_create_group(&ipl_subsys.kset.kobj, 807 rc = sysfs_create_group(&ipl_subsys.kset.kobj,
738 &ipl_unknown_attr_group); 808 &ipl_unknown_attr_group);
@@ -755,6 +825,20 @@ static void __init reipl_probe(void)
755 free_page((unsigned long)buffer); 825 free_page((unsigned long)buffer);
756} 826}
757 827
828static int __init reipl_nss_init(void)
829{
830 int rc;
831
832 if (!MACHINE_IS_VM)
833 return 0;
834 rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group);
835 if (rc)
836 return rc;
837 strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
838 reipl_capabilities |= IPL_TYPE_NSS;
839 return 0;
840}
841
758static int __init reipl_ccw_init(void) 842static int __init reipl_ccw_init(void)
759{ 843{
760 int rc; 844 int rc;
@@ -837,6 +921,9 @@ static int __init reipl_init(void)
837 rc = reipl_fcp_init(); 921 rc = reipl_fcp_init();
838 if (rc) 922 if (rc)
839 return rc; 923 return rc;
924 rc = reipl_nss_init();
925 if (rc)
926 return rc;
840 rc = reipl_set_type(ipl_get_type()); 927 rc = reipl_set_type(ipl_get_type());
841 if (rc) 928 if (rc)
842 return rc; 929 return rc;
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
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index fe0f2e97ba7b..8fedb1f9fc97 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -31,11 +31,6 @@ SECTIONS
31 31
32 _etext = .; /* End of text section */ 32 _etext = .; /* End of text section */
33 33
34 . = ALIGN(16); /* Exception table */
35 __start___ex_table = .;
36 __ex_table : { *(__ex_table) }
37 __stop___ex_table = .;
38
39 RODATA 34 RODATA
40 35
41#ifdef CONFIG_SHARED_KERNEL 36#ifdef CONFIG_SHARED_KERNEL
@@ -44,6 +39,11 @@ SECTIONS
44 _eshared = .; /* End of shareable data */ 39 _eshared = .; /* End of shareable data */
45#endif 40#endif
46 41
42 . = ALIGN(16); /* Exception table */
43 __start___ex_table = .;
44 __ex_table : { *(__ex_table) }
45 __stop___ex_table = .;
46
47 .data : { /* Data */ 47 .data : { /* Data */
48 *(.data) 48 *(.data)
49 CONSTRUCTORS 49 CONSTRUCTORS