diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-08-23 10:18:09 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-10-09 08:16:58 -0400 |
commit | 51eee033dca3d6dc81febc5a69f30b964f3bddf3 (patch) | |
tree | 5f5a7b981e2febf38671cb5808e4acddde0005d3 /arch/s390/kernel/head.S | |
parent | cc5b9a45184e90037e6d5353279ec358e57965fd (diff) |
s390: add support to start the kernel in 64 bit mode.
Do the switch to z/Architecture (alias 64 bit) mode early in head.S.
If the machine is already running in 64 bit mode the sigp turns into
a nop. With this change it doesn't matter in which mode the kernel
is started.
Reviewd-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/head.S')
-rw-r--r-- | arch/s390/kernel/head.S | 101 |
1 files changed, 70 insertions, 31 deletions
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 805b6686b641..984726cbce16 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S | |||
@@ -52,7 +52,7 @@ __HEAD | |||
52 | .long 0x02000370,0x60000050 # the channel program the PSW | 52 | .long 0x02000370,0x60000050 # the channel program the PSW |
53 | .long 0x020003c0,0x60000050 # at location 0 is loaded. | 53 | .long 0x020003c0,0x60000050 # at location 0 is loaded. |
54 | .long 0x02000410,0x60000050 # Initial processing starts | 54 | .long 0x02000410,0x60000050 # Initial processing starts |
55 | .long 0x02000460,0x60000050 # at 0xf0 = iplstart. | 55 | .long 0x02000460,0x60000050 # at 0x200 = iplstart. |
56 | .long 0x020004b0,0x60000050 | 56 | .long 0x020004b0,0x60000050 |
57 | .long 0x02000500,0x60000050 | 57 | .long 0x02000500,0x60000050 |
58 | .long 0x02000550,0x60000050 | 58 | .long 0x02000550,0x60000050 |
@@ -62,11 +62,54 @@ __HEAD | |||
62 | .long 0x02000690,0x60000050 | 62 | .long 0x02000690,0x60000050 |
63 | .long 0x020006e0,0x20000050 | 63 | .long 0x020006e0,0x20000050 |
64 | 64 | ||
65 | .org 0xf0 | 65 | .org 0x200 |
66 | # | ||
67 | # subroutine to set architecture mode | ||
68 | # | ||
69 | .Lsetmode: | ||
70 | #ifdef CONFIG_64BIT | ||
71 | mvi __LC_AR_MODE_ID,1 # set esame flag | ||
72 | slr %r0,%r0 # set cpuid to zero | ||
73 | lhi %r1,2 # mode 2 = esame (dump) | ||
74 | sigp %r1,%r0,0x12 # switch to esame mode | ||
75 | bras %r13,0f | ||
76 | .fill 16,4,0x0 | ||
77 | 0: lmh %r0,%r15,0(%r13) # clear high-order half of gprs | ||
78 | sam31 # switch to 31 bit addressing mode | ||
79 | #else | ||
80 | mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0) | ||
81 | #endif | ||
82 | br %r14 | ||
83 | |||
84 | # | ||
85 | # subroutine to wait for end I/O | ||
86 | # | ||
87 | .Lirqwait: | ||
88 | #ifdef CONFIG_64BIT | ||
89 | mvc 0x1f0(16),.Lnewpsw # set up IO interrupt psw | ||
90 | lpsw .Lwaitpsw | ||
91 | .Lioint: | ||
92 | br %r14 | ||
93 | .align 8 | ||
94 | .Lnewpsw: | ||
95 | .quad 0x0000000080000000,.Lioint | ||
96 | #else | ||
97 | mvc 0x78(8),.Lnewpsw # set up IO interrupt psw | ||
98 | lpsw .Lwaitpsw | ||
99 | .Lioint: | ||
100 | br %r14 | ||
101 | .align 8 | ||
102 | .Lnewpsw: | ||
103 | .long 0x00080000,0x80000000+.Lioint | ||
104 | #endif | ||
105 | .Lwaitpsw: | ||
106 | .long 0x020a0000,0x80000000+.Lioint | ||
107 | |||
66 | # | 108 | # |
67 | # subroutine for loading cards from the reader | 109 | # subroutine for loading cards from the reader |
68 | # | 110 | # |
69 | .Lloader: | 111 | .Lloader: |
112 | la %r4,0(%r14) | ||
70 | la %r3,.Lorb # r2 = address of orb into r2 | 113 | la %r3,.Lorb # r2 = address of orb into r2 |
71 | la %r5,.Lirb # r4 = address of irb | 114 | la %r5,.Lirb # r4 = address of irb |
72 | la %r6,.Lccws | 115 | la %r6,.Lccws |
@@ -83,9 +126,7 @@ __HEAD | |||
83 | ssch 0(%r3) # load chunk of 1600 bytes | 126 | ssch 0(%r3) # load chunk of 1600 bytes |
84 | bnz .Llderr | 127 | bnz .Llderr |
85 | .Lwait4irq: | 128 | .Lwait4irq: |
86 | mvc 0x78(8),.Lnewpsw # set up IO interrupt psw | 129 | bas %r14,.Lirqwait |
87 | lpsw .Lwaitpsw | ||
88 | .Lioint: | ||
89 | c %r1,0xb8 # compare subchannel number | 130 | c %r1,0xb8 # compare subchannel number |
90 | bne .Lwait4irq | 131 | bne .Lwait4irq |
91 | tsch 0(%r5) | 132 | tsch 0(%r5) |
@@ -104,7 +145,7 @@ __HEAD | |||
104 | sr %r0,%r3 # #ccws*80-residual=#bytes read | 145 | sr %r0,%r3 # #ccws*80-residual=#bytes read |
105 | ar %r2,%r0 | 146 | ar %r2,%r0 |
106 | 147 | ||
107 | br %r14 # r2 contains the total size | 148 | br %r4 # r2 contains the total size |
108 | 149 | ||
109 | .Lcont: | 150 | .Lcont: |
110 | ahi %r2,0x640 # add 0x640 to total size | 151 | ahi %r2,0x640 # add 0x640 to total size |
@@ -128,10 +169,6 @@ __HEAD | |||
128 | .Lloadp:.long 0,0 | 169 | .Lloadp:.long 0,0 |
129 | .align 8 | 170 | .align 8 |
130 | .Lcrash:.long 0x000a0000,0x00000000 | 171 | .Lcrash:.long 0x000a0000,0x00000000 |
131 | .Lnewpsw: | ||
132 | .long 0x00080000,0x80000000+.Lioint | ||
133 | .Lwaitpsw: | ||
134 | .long 0x020a0000,0x80000000+.Lioint | ||
135 | 172 | ||
136 | .align 8 | 173 | .align 8 |
137 | .Lccws: .rept 19 | 174 | .Lccws: .rept 19 |
@@ -140,6 +177,7 @@ __HEAD | |||
140 | .long 0x02200050,0x00000000 | 177 | .long 0x02200050,0x00000000 |
141 | 178 | ||
142 | iplstart: | 179 | iplstart: |
180 | bas %r14,.Lsetmode # Immediately switch to 64 bit mode | ||
143 | lh %r1,0xb8 # test if subchannel number | 181 | lh %r1,0xb8 # test if subchannel number |
144 | bct %r1,.Lnoload # is valid | 182 | bct %r1,.Lnoload # is valid |
145 | l %r1,0xb8 # load ipl subchannel number | 183 | l %r1,0xb8 # load ipl subchannel number |
@@ -209,8 +247,8 @@ iplstart: | |||
209 | # | 247 | # |
210 | # reset files in VM reader | 248 | # reset files in VM reader |
211 | # | 249 | # |
212 | stidp __LC_SAVE_AREA_SYNC # store cpuid | 250 | stidp .Lcpuid # store cpuid |
213 | tm __LC_SAVE_AREA_SYNC,0xff# running VM ? | 251 | tm .Lcpuid,0xff # running VM ? |
214 | bno .Lnoreset | 252 | bno .Lnoreset |
215 | la %r2,.Lreset | 253 | la %r2,.Lreset |
216 | lhi %r3,26 | 254 | lhi %r3,26 |
@@ -222,23 +260,14 @@ iplstart: | |||
222 | tm 31(%r5),0xff # bits is set in the schib | 260 | tm 31(%r5),0xff # bits is set in the schib |
223 | bz .Lnoreset | 261 | bz .Lnoreset |
224 | .Lwaitforirq: | 262 | .Lwaitforirq: |
225 | mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw | 263 | bas %r14,.Lirqwait # wait for IO interrupt |
226 | .Lwaitrdrirq: | ||
227 | lpsw .Lrdrwaitpsw | ||
228 | .Lrdrint: | ||
229 | c %r1,0xb8 # compare subchannel number | 264 | c %r1,0xb8 # compare subchannel number |
230 | bne .Lwaitrdrirq | 265 | bne .Lwaitforirq |
231 | la %r5,.Lirb | 266 | la %r5,.Lirb |
232 | tsch 0(%r5) | 267 | tsch 0(%r5) |
233 | .Lnoreset: | 268 | .Lnoreset: |
234 | b .Lnoload | 269 | b .Lnoload |
235 | 270 | ||
236 | .align 8 | ||
237 | .Lrdrnewpsw: | ||
238 | .long 0x00080000,0x80000000+.Lrdrint | ||
239 | .Lrdrwaitpsw: | ||
240 | .long 0x020a0000,0x80000000+.Lrdrint | ||
241 | |||
242 | # | 271 | # |
243 | # everything loaded, go for it | 272 | # everything loaded, go for it |
244 | # | 273 | # |
@@ -254,6 +283,8 @@ iplstart: | |||
254 | .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" | 283 | .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" |
255 | .L_eof: .long 0xc5d6c600 /* C'EOF' */ | 284 | .L_eof: .long 0xc5d6c600 /* C'EOF' */ |
256 | .L_hdr: .long 0xc8c4d900 /* C'HDR' */ | 285 | .L_hdr: .long 0xc8c4d900 /* C'HDR' */ |
286 | .align 8 | ||
287 | .Lcpuid:.fill 8,1,0 | ||
257 | 288 | ||
258 | # | 289 | # |
259 | # SALIPL loader support. Based on a patch by Rob van der Heij. | 290 | # SALIPL loader support. Based on a patch by Rob van der Heij. |
@@ -263,6 +294,7 @@ iplstart: | |||
263 | .org 0x800 | 294 | .org 0x800 |
264 | ENTRY(start) | 295 | ENTRY(start) |
265 | stm %r0,%r15,0x07b0 # store registers | 296 | stm %r0,%r15,0x07b0 # store registers |
297 | bas %r14,.Lsetmode # Immediately switch to 64 bit mode | ||
266 | basr %r12,%r0 | 298 | basr %r12,%r0 |
267 | .base: | 299 | .base: |
268 | l %r11,.parm | 300 | l %r11,.parm |
@@ -343,6 +375,18 @@ ENTRY(startup) | |||
343 | ENTRY(startup_kdump) | 375 | ENTRY(startup_kdump) |
344 | j .Lep_startup_kdump | 376 | j .Lep_startup_kdump |
345 | .Lep_startup_normal: | 377 | .Lep_startup_normal: |
378 | #ifdef CONFIG_64BIT | ||
379 | mvi __LC_AR_MODE_ID,1 # set esame flag | ||
380 | slr %r0,%r0 # set cpuid to zero | ||
381 | lhi %r1,2 # mode 2 = esame (dump) | ||
382 | sigp %r1,%r0,0x12 # switch to esame mode | ||
383 | bras %r13,0f | ||
384 | .fill 16,4,0x0 | ||
385 | 0: lmh %r0,%r15,0(%r13) # clear high-order half of gprs | ||
386 | sam31 # switch to 31 bit addressing mode | ||
387 | #else | ||
388 | mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0) | ||
389 | #endif | ||
346 | basr %r13,0 # get base | 390 | basr %r13,0 # get base |
347 | .LPG0: | 391 | .LPG0: |
348 | xc 0x200(256),0x200 # partially clear lowcore | 392 | xc 0x200(256),0x200 # partially clear lowcore |
@@ -410,22 +454,17 @@ ENTRY(startup_kdump) | |||
410 | #endif | 454 | #endif |
411 | 455 | ||
412 | #ifdef CONFIG_64BIT | 456 | #ifdef CONFIG_64BIT |
413 | mvi __LC_AR_MODE_ID,1 # set esame flag | 457 | /* Continue with 64bit startup code in head64.S */ |
414 | slr %r0,%r0 # set cpuid to zero | ||
415 | lhi %r1,2 # mode 2 = esame (dump) | ||
416 | sigp %r1,%r0,0x12 # switch to esame mode | ||
417 | sam64 # switch to 64 bit mode | 458 | sam64 # switch to 64 bit mode |
418 | larl %r13,4f | ||
419 | lmh %r0,%r15,0(%r13) # clear high-order half | ||
420 | jg startup_continue | 459 | jg startup_continue |
421 | 4: .fill 16,4,0x0 | ||
422 | #else | 460 | #else |
423 | mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0) | 461 | /* Continue with 31bit startup code in head31.S */ |
424 | l %r13,4f-.LPG0(%r13) | 462 | l %r13,4f-.LPG0(%r13) |
425 | b 0(%r13) | 463 | b 0(%r13) |
426 | .align 8 | 464 | .align 8 |
427 | 4: .long startup_continue | 465 | 4: .long startup_continue |
428 | #endif | 466 | #endif |
467 | |||
429 | .align 8 | 468 | .align 8 |
430 | 5: .long 0x7fffffff,0xffffffff | 469 | 5: .long 0x7fffffff,0xffffffff |
431 | 470 | ||