Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
a53c8fab | 2 | * Copyright IBM Corp. 1999, 2010 |
0ad775db HC |
3 | * |
4 | * Author(s): Hartmut Penner <hp@de.ibm.com> | |
5 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | |
6 | * Rob van der Heij <rvdhei@iae.nl> | |
7 | * Heiko Carstens <heiko.carstens@de.ibm.com> | |
1da177e4 LT |
8 | * |
9 | * There are 5 different IPL methods | |
10 | * 1) load the image directly into ram at address 0 and do an PSW restart | |
11 | * 2) linload will load the image from address 0x10000 to memory 0x10000 | |
12 | * and start the code thru LPSW 0x0008000080010000 (VM only, deprecated) | |
13 | * 3) generate the tape ipl header, store the generated image on a tape | |
14 | * and ipl from it | |
15 | * In case of SL tape you need to IPL 5 times to get past VOL1 etc | |
16 | * 4) generate the vm reader ipl header, move the generated image to the | |
17 | * VM reader (use option NOH!) and do a ipl from reader (VM only) | |
18 | * 5) direct call of start by the SALIPL loader | |
19 | * We use the cpuid to distinguish between VM and native ipl | |
20 | * params for kernel are pushed to 0x10400 (see setup.h) | |
0ad775db | 21 | * |
1da177e4 LT |
22 | */ |
23 | ||
2133bb8d | 24 | #include <linux/init.h> |
144d634a | 25 | #include <linux/linkage.h> |
0013a854 | 26 | #include <asm/asm-offsets.h> |
1da177e4 | 27 | #include <asm/thread_info.h> |
0358ecf7 | 28 | #include <asm/facility.h> |
1da177e4 | 29 | #include <asm/page.h> |
c6eafbf9 | 30 | #include <asm/ptrace.h> |
1da177e4 | 31 | |
0ad775db | 32 | #define ARCH_OFFSET 4 |
0ad775db | 33 | |
2133bb8d | 34 | __HEAD |
1da177e4 | 35 | |
25d83cbf HC |
36 | #define IPL_BS 0x730 |
37 | .org 0 | |
38 | .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded | |
39 | .long 0x02000018,0x60000050 # by ipl to addresses 0-23. | |
40 | .long 0x02000068,0x60000050 # (a PSW and two CCWs). | |
41 | .fill 80-24,1,0x40 # bytes 24-79 are discarded !! | |
42 | .long 0x020000f0,0x60000050 # The next 160 byte are loaded | |
43 | .long 0x02000140,0x60000050 # to addresses 0x18-0xb7 | |
44 | .long 0x02000190,0x60000050 # They form the continuation | |
45 | .long 0x020001e0,0x60000050 # of the CCW program started | |
46 | .long 0x02000230,0x60000050 # by ipl and load the range | |
47 | .long 0x02000280,0x60000050 # 0x0f0-0x730 from the image | |
48 | .long 0x020002d0,0x60000050 # to the range 0x0f0-0x730 | |
49 | .long 0x02000320,0x60000050 # in memory. At the end of | |
50 | .long 0x02000370,0x60000050 # the channel program the PSW | |
51 | .long 0x020003c0,0x60000050 # at location 0 is loaded. | |
52 | .long 0x02000410,0x60000050 # Initial processing starts | |
51eee033 | 53 | .long 0x02000460,0x60000050 # at 0x200 = iplstart. |
25d83cbf HC |
54 | .long 0x020004b0,0x60000050 |
55 | .long 0x02000500,0x60000050 | |
56 | .long 0x02000550,0x60000050 | |
57 | .long 0x020005a0,0x60000050 | |
58 | .long 0x020005f0,0x60000050 | |
59 | .long 0x02000640,0x60000050 | |
60 | .long 0x02000690,0x60000050 | |
61 | .long 0x020006e0,0x20000050 | |
1da177e4 | 62 | |
51eee033 | 63 | .org 0x200 |
51eee033 MS |
64 | |
65 | # | |
66 | # subroutine to wait for end I/O | |
67 | # | |
68 | .Lirqwait: | |
51eee033 MS |
69 | mvc 0x1f0(16),.Lnewpsw # set up IO interrupt psw |
70 | lpsw .Lwaitpsw | |
71 | .Lioint: | |
72 | br %r14 | |
73 | .align 8 | |
74 | .Lnewpsw: | |
75 | .quad 0x0000000080000000,.Lioint | |
51eee033 MS |
76 | .Lwaitpsw: |
77 | .long 0x020a0000,0x80000000+.Lioint | |
78 | ||
1da177e4 LT |
79 | # |
80 | # subroutine for loading cards from the reader | |
81 | # | |
25d83cbf | 82 | .Lloader: |
51eee033 | 83 | la %r4,0(%r14) |
25d83cbf HC |
84 | la %r3,.Lorb # r2 = address of orb into r2 |
85 | la %r5,.Lirb # r4 = address of irb | |
86 | la %r6,.Lccws | |
87 | la %r7,20 | |
1da177e4 | 88 | .Linit: |
25d83cbf HC |
89 | st %r2,4(%r6) # initialize CCW data addresses |
90 | la %r2,0x50(%r2) | |
91 | la %r6,8(%r6) | |
92 | bct 7,.Linit | |
1da177e4 | 93 | |
25d83cbf HC |
94 | lctl %c6,%c6,.Lcr6 # set IO subclass mask |
95 | slr %r2,%r2 | |
1da177e4 | 96 | .Lldlp: |
25d83cbf HC |
97 | ssch 0(%r3) # load chunk of 1600 bytes |
98 | bnz .Llderr | |
1da177e4 | 99 | .Lwait4irq: |
51eee033 | 100 | bas %r14,.Lirqwait |
25d83cbf HC |
101 | c %r1,0xb8 # compare subchannel number |
102 | bne .Lwait4irq | |
103 | tsch 0(%r5) | |
1da177e4 | 104 | |
25d83cbf HC |
105 | slr %r0,%r0 |
106 | ic %r0,8(%r5) # get device status | |
107 | chi %r0,8 # channel end ? | |
108 | be .Lcont | |
109 | chi %r0,12 # channel end + device end ? | |
110 | be .Lcont | |
1da177e4 | 111 | |
25d83cbf HC |
112 | l %r0,4(%r5) |
113 | s %r0,8(%r3) # r0/8 = number of ccws executed | |
114 | mhi %r0,10 # *10 = number of bytes in ccws | |
115 | lh %r3,10(%r5) # get residual count | |
116 | sr %r0,%r3 # #ccws*80-residual=#bytes read | |
117 | ar %r2,%r0 | |
118 | ||
51eee033 | 119 | br %r4 # r2 contains the total size |
1da177e4 LT |
120 | |
121 | .Lcont: | |
25d83cbf HC |
122 | ahi %r2,0x640 # add 0x640 to total size |
123 | la %r6,.Lccws | |
124 | la %r7,20 | |
1da177e4 | 125 | .Lincr: |
25d83cbf HC |
126 | l %r0,4(%r6) # update CCW data addresses |
127 | ahi %r0,0x640 | |
128 | st %r0,4(%r6) | |
129 | ahi %r6,8 | |
130 | bct 7,.Lincr | |
1da177e4 | 131 | |
25d83cbf | 132 | b .Lldlp |
1da177e4 | 133 | .Llderr: |
25d83cbf | 134 | lpsw .Lcrash |
1da177e4 | 135 | |
25d83cbf HC |
136 | .align 8 |
137 | .Lorb: .long 0x00000000,0x0080ff00,.Lccws | |
138 | .Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 | |
139 | .Lcr6: .long 0xff000000 | |
140 | .Lloadp:.long 0,0 | |
141 | .align 8 | |
142 | .Lcrash:.long 0x000a0000,0x00000000 | |
1da177e4 | 143 | |
25d83cbf HC |
144 | .align 8 |
145 | .Lccws: .rept 19 | |
146 | .long 0x02600050,0x00000000 | |
147 | .endr | |
148 | .long 0x02200050,0x00000000 | |
1da177e4 LT |
149 | |
150 | iplstart: | |
f52c74fe HC |
151 | mvi __LC_AR_MODE_ID,1 # set esame flag |
152 | slr %r0,%r0 # set cpuid to zero | |
153 | lhi %r1,2 # mode 2 = esame (dump) | |
154 | sigp %r1,%r0,0x12 # switch to esame mode | |
155 | bras %r13,0f | |
156 | .fill 16,4,0x0 | |
157 | 0: lmh %r0,%r15,0(%r13) # clear high-order half of gprs | |
158 | sam31 # switch to 31 bit addressing mode | |
25d83cbf HC |
159 | lh %r1,0xb8 # test if subchannel number |
160 | bct %r1,.Lnoload # is valid | |
161 | l %r1,0xb8 # load ipl subchannel number | |
162 | la %r2,IPL_BS # load start address | |
163 | bas %r14,.Lloader # load rest of ipl image | |
164 | l %r12,.Lparm # pointer to parameter area | |
165 | st %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number | |
1da177e4 LT |
166 | |
167 | # | |
168 | # load parameter file from ipl device | |
169 | # | |
170 | .Lagain1: | |
25d83cbf HC |
171 | l %r2,.Linitrd # ramdisk loc. is temp |
172 | bas %r14,.Lloader # load parameter file | |
173 | ltr %r2,%r2 # got anything ? | |
174 | bz .Lnopf | |
175 | chi %r2,895 | |
176 | bnh .Lnotrunc | |
177 | la %r2,895 | |
1da177e4 | 178 | .Lnotrunc: |
25d83cbf HC |
179 | l %r4,.Linitrd |
180 | clc 0(3,%r4),.L_hdr # if it is HDRx | |
181 | bz .Lagain1 # skip dataset header | |
182 | clc 0(3,%r4),.L_eof # if it is EOFx | |
183 | bz .Lagain1 # skip dateset trailer | |
184 | la %r5,0(%r4,%r2) | |
185 | lr %r3,%r2 | |
61fd330d | 186 | la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line |
25d83cbf HC |
187 | mvc 0(256,%r3),0(%r4) |
188 | mvc 256(256,%r3),256(%r4) | |
189 | mvc 512(256,%r3),512(%r4) | |
190 | mvc 768(122,%r3),768(%r4) | |
191 | slr %r0,%r0 | |
192 | b .Lcntlp | |
1da177e4 | 193 | .Ldelspc: |
25d83cbf HC |
194 | ic %r0,0(%r2,%r3) |
195 | chi %r0,0x20 # is it a space ? | |
196 | be .Lcntlp | |
197 | ahi %r2,1 | |
198 | b .Leolp | |
1da177e4 | 199 | .Lcntlp: |
25d83cbf | 200 | brct %r2,.Ldelspc |
1da177e4 | 201 | .Leolp: |
25d83cbf HC |
202 | slr %r0,%r0 |
203 | stc %r0,0(%r2,%r3) # terminate buffer | |
1da177e4 LT |
204 | .Lnopf: |
205 | ||
206 | # | |
207 | # load ramdisk from ipl device | |
25d83cbf | 208 | # |
1da177e4 | 209 | .Lagain2: |
25d83cbf HC |
210 | l %r2,.Linitrd # addr of ramdisk |
211 | st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) | |
212 | bas %r14,.Lloader # load ramdisk | |
213 | st %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of rd | |
214 | ltr %r2,%r2 | |
215 | bnz .Lrdcont | |
216 | st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found | |
1da177e4 | 217 | .Lrdcont: |
25d83cbf | 218 | l %r2,.Linitrd |
1da177e4 | 219 | |
25d83cbf HC |
220 | clc 0(3,%r2),.L_hdr # skip HDRx and EOFx |
221 | bz .Lagain2 | |
222 | clc 0(3,%r2),.L_eof | |
223 | bz .Lagain2 | |
1da177e4 | 224 | |
1da177e4 LT |
225 | # |
226 | # reset files in VM reader | |
227 | # | |
51eee033 MS |
228 | stidp .Lcpuid # store cpuid |
229 | tm .Lcpuid,0xff # running VM ? | |
25d83cbf HC |
230 | bno .Lnoreset |
231 | la %r2,.Lreset | |
232 | lhi %r3,26 | |
233 | diag %r2,%r3,8 | |
234 | la %r5,.Lirb | |
235 | stsch 0(%r5) # check if irq is pending | |
236 | tm 30(%r5),0x0f # by verifying if any of the | |
237 | bnz .Lwaitforirq # activity or status control | |
238 | tm 31(%r5),0xff # bits is set in the schib | |
239 | bz .Lnoreset | |
350e3ade | 240 | .Lwaitforirq: |
51eee033 | 241 | bas %r14,.Lirqwait # wait for IO interrupt |
25d83cbf | 242 | c %r1,0xb8 # compare subchannel number |
51eee033 | 243 | bne .Lwaitforirq |
25d83cbf HC |
244 | la %r5,.Lirb |
245 | tsch 0(%r5) | |
1da177e4 | 246 | .Lnoreset: |
25d83cbf | 247 | b .Lnoload |
2b071886 | 248 | |
1da177e4 LT |
249 | # |
250 | # everything loaded, go for it | |
251 | # | |
252 | .Lnoload: | |
25d83cbf HC |
253 | l %r1,.Lstartup |
254 | br %r1 | |
1da177e4 | 255 | |
e033b9a0 | 256 | .Linitrd:.long _end # default address of initrd |
1da177e4 LT |
257 | .Lparm: .long PARMAREA |
258 | .Lstartup: .long startup | |
25d83cbf HC |
259 | .Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 |
260 | .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6 | |
261 | .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" | |
262 | .L_eof: .long 0xc5d6c600 /* C'EOF' */ | |
263 | .L_hdr: .long 0xc8c4d900 /* C'HDR' */ | |
51eee033 MS |
264 | .align 8 |
265 | .Lcpuid:.fill 8,1,0 | |
1da177e4 | 266 | |
e37f50e1 MS |
267 | # |
268 | # startup-code at 0x10000, running in absolute addressing mode | |
269 | # this is called either by the ipl loader or directly by PSW restart | |
270 | # or linload or SALIPL | |
271 | # | |
272 | .org 0x10000 | |
144d634a | 273 | ENTRY(startup) |
60a0c68d MH |
274 | j .Lep_startup_normal |
275 | .org 0x10008 | |
276 | # | |
277 | # This is a list of s390 kernel entry points. At address 0x1000f the number of | |
278 | # valid entry points is stored. | |
279 | # | |
280 | # IMPORTANT: Do not change this table, it is s390 kernel ABI! | |
281 | # | |
282 | .ascii "S390EP" | |
283 | .byte 0x00,0x01 | |
284 | # | |
285 | # kdump startup-code at 0x10010, running in 64 bit absolute addressing mode | |
286 | # | |
287 | .org 0x10010 | |
288 | ENTRY(startup_kdump) | |
289 | j .Lep_startup_kdump | |
290 | .Lep_startup_normal: | |
51eee033 MS |
291 | mvi __LC_AR_MODE_ID,1 # set esame flag |
292 | slr %r0,%r0 # set cpuid to zero | |
293 | lhi %r1,2 # mode 2 = esame (dump) | |
294 | sigp %r1,%r0,0x12 # switch to esame mode | |
295 | bras %r13,0f | |
296 | .fill 16,4,0x0 | |
297 | 0: lmh %r0,%r15,0(%r13) # clear high-order half of gprs | |
c6eafbf9 | 298 | sam64 # switch to 64 bit addressing mode |
1844c9bc | 299 | basr %r13,0 # get base |
e37f50e1 | 300 | .LPG0: |
866ba284 MS |
301 | xc 0x200(256),0x200 # partially clear lowcore |
302 | xc 0x300(256),0x300 | |
60a0c68d | 303 | xc 0xe00(256),0xe00 |
76cdd44c | 304 | xc 0xf00(256),0xf00 |
22362a0e | 305 | lctlg %c0,%c15,0x200(%r0) # initialize control registers |
1844c9bc | 306 | stck __LC_LAST_UPDATE_CLOCK |
991c1505 HC |
307 | spt 6f-.LPG0(%r13) |
308 | mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13) | |
be2412c2 | 309 | l %r15,.Lstack-.LPG0(%r13) |
c6eafbf9 | 310 | ahi %r15,-STACK_FRAME_OVERHEAD |
be2412c2 | 311 | brasl %r14,verify_facilities |
bf47dc57 SS |
312 | # For uncompressed images, continue in |
313 | # arch/s390/kernel/head64.S. For compressed images, continue in | |
314 | # arch/s390/boot/compressed/head.S. | |
1844c9bc | 315 | jg startup_continue |
51eee033 | 316 | |
be2412c2 HC |
317 | .Lstack: |
318 | .long 0x8000 + (1<<(PAGE_SHIFT+THREAD_ORDER)) | |
ab96e798 | 319 | .align 8 |
991c1505 | 320 | 6: .long 0x7fffffff,0xffffffff |
e37f50e1 | 321 | |
60a0c68d MH |
322 | #include "head_kdump.S" |
323 | ||
e37f50e1 MS |
324 | # |
325 | # params at 10400 (setup.h) | |
326 | # | |
327 | .org PARMAREA | |
328 | .long 0,0 # IPL_DEVICE | |
329 | .long 0,0 # INITRD_START | |
330 | .long 0,0 # INITRD_SIZE | |
60a0c68d MH |
331 | .long 0,0 # OLDMEM_BASE |
332 | .long 0,0 # OLDMEM_SIZE | |
e37f50e1 MS |
333 | |
334 | .org COMMAND_LINE | |
335 | .byte "root=/dev/ram0 ro" | |
336 | .byte 0 | |
337 | ||
1844c9bc | 338 | .org 0x11000 |