[S390] zfcpdump support.
[linux-2.6.git] / arch / s390 / kernel / head64.S
1 /*
2  * arch/s390/kernel/head64.S
3  *
4  * Copyright (C) IBM Corp. 1999,2006
5  *
6  *   Author(s): Hartmut Penner <hp@de.ibm.com>
7  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
8  *              Rob van der Heij <rvdhei@iae.nl>
9  *              Heiko Carstens <heiko.carstens@de.ibm.com>
10  *
11  */
12
13 #
14 # startup-code at 0x10000, running in absolute addressing mode
15 # this is called either by the ipl loader or directly by PSW restart
16 # or linload or SALIPL
17 #
18         .org    0x10000
19 startup:basr    %r13,0                  # get base
20 .LPG0:  l       %r13,0f-.LPG0(%r13)
21         b       0(%r13)
22 0:      .long   startup_continue
23
24 #
25 # params at 10400 (setup.h)
26 #
27         .org    PARMAREA
28         .quad   0                       # IPL_DEVICE
29         .quad   0                       # INITRD_START
30         .quad   0                       # INITRD_SIZE
31
32         .org    COMMAND_LINE
33         .byte   "root=/dev/ram0 ro"
34         .byte   0
35
36         .org    0x11000
37
38 startup_continue:
39         basr    %r13,0                  # get base
40 .LPG1:  sll     %r13,1                  # remove high order bit
41         srl     %r13,1
42
43 #ifdef CONFIG_ZFCPDUMP
44
45         # check if we have been ipled using zfcp dump:
46
47         tm      0xb9,0x01               # test if subchannel is enabled
48         jno     .nodump                 # subchannel disabled
49         l       %r1,0xb8
50         la      %r5,.Lipl_schib-.LPG1(%r13)
51         stsch   0(%r5)                  # get schib of subchannel
52         jne     .nodump                 # schib not available
53         tm      5(%r5),0x01             # devno valid?
54         jno     .nodump
55         tm      4(%r5),0x80             # qdio capable device?
56         jno     .nodump
57         l       %r2,20(%r0)             # address of ipl parameter block
58         lhi     %r3,0
59         ic      %r3,0x148(%r2)          # get opt field
60         chi     %r3,0x20                # load with dump?
61         jne     .nodump
62
63         # store all prefix registers in case of load with dump:
64
65         la      %r7,0                   # base register for 0 page
66         la      %r8,0                   # first cpu
67         l       %r11,.Lpref_arr_ptr-.LPG1(%r13) # address of prefix array
68         ahi     %r11,4                  # skip boot cpu
69         lr      %r12,%r11
70         ahi     %r12,(CONFIG_NR_CPUS*4) # end of prefix array
71         stap    .Lcurrent_cpu+2-.LPG1(%r13)     # store current cpu addr
72 1:
73         cl      %r8,.Lcurrent_cpu-.LPG1(%r13)   # is ipl cpu ?
74         je      4f                              # if yes get next cpu
75 2:
76         lr      %r9,%r7
77         sigp    %r9,%r8,0x9             # stop & store status of cpu
78         brc     8,3f                    # accepted
79         brc     4,4f                    # status stored: next cpu
80         brc     2,2b                    # busy:          try again
81         brc     1,4f                    # not op:        next cpu
82 3:
83         mvc     0(4,%r11),264(%r7)      # copy prefix register to prefix array
84         ahi     %r11,4                  # next element in prefix array
85         clr     %r11,%r12
86         je      5f                      # no more space in prefix array
87 4:
88         ahi     %r8,1                           # next cpu (r8 += 1)
89         cl      %r8,.Llast_cpu-.LPG1(%r13)      # is last possible cpu ?
90         jl      1b                              # jump if not last cpu
91 5:
92         lhi     %r1,2                   # mode 2 = esame (dump)
93         j       6f
94         .align 4
95 .Lipl_schib:
96         .rept 13
97         .long 0
98         .endr
99 .nodump:
100         lhi     %r1,1                   # mode 1 = esame (normal ipl)
101 6:
102 #else
103         lhi     %r1,1                   # mode 1 = esame (normal ipl)
104 #endif /* CONFIG_ZFCPDUMP */
105         mvi     __LC_AR_MODE_ID,1       # set esame flag
106         slr     %r0,%r0                 # set cpuid to zero
107         sigp    %r1,%r0,0x12            # switch to esame mode
108         sam64                           # switch to 64 bit mode
109         lctlg   %c0,%c15,.Lctl-.LPG1(%r13)      # load control registers
110         lg      %r12,.Lparmaddr-.LPG1(%r13)     # pointer to parameter area
111                                         # move IPL device to lowcore
112         mvc     __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
113 #
114 # Setup stack
115 #
116         larl    %r15,init_thread_union
117         lg      %r14,__TI_task(%r15)    # cache current in lowcore
118         stg     %r14,__LC_CURRENT
119         aghi    %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
120         stg     %r15,__LC_KERNEL_STACK  # set end of kernel stack
121         aghi    %r15,-160
122         xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
123 #
124 # Save ipl parameters, clear bss memory, initialize storage key for kernel pages,
125 # and create a kernel NSS if the SAVESYS= parm is defined
126 #
127         brasl   %r14,startup_init
128                                         # set program check new psw mask
129         mvc     __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
130         larl    %r12,machine_flags
131 #
132 # find out if we have the MVPG instruction
133 #
134         la      %r1,0f-.LPG1(%r13)      # set program check address
135         stg     %r1,__LC_PGM_NEW_PSW+8
136         sgr     %r0,%r0
137         lghi    %r1,0
138         lghi    %r2,0
139         mvpg    %r1,%r2                 # test MVPG instruction
140         oi      7(%r12),16              # set MVPG flag
141 0:
142
143 #
144 # find out if the diag 0x44 works in 64 bit mode
145 #
146         la      %r1,0f-.LPG1(%r13)      # set program check address
147         stg     %r1,__LC_PGM_NEW_PSW+8
148         diag    0,0,0x44                # test diag 0x44
149         oi      7(%r12),32              # set diag44 flag
150 0:
151
152 #
153 # find out if we have the IDTE instruction
154 #
155         la      %r1,0f-.LPG1(%r13)      # set program check address
156         stg     %r1,__LC_PGM_NEW_PSW+8
157         .long   0xb2b10000              # store facility list
158         tm      0xc8,0x08               # check bit for clearing-by-ASCE
159         bno     0f-.LPG1(%r13)
160         lhi     %r1,2094
161         lhi     %r2,0
162         .long   0xb98e2001
163         oi      7(%r12),0x80            # set IDTE flag
164 0:
165
166 #
167 # find out if the diag 0x9c is available
168 #
169         la      %r1,0f-.LPG1(%r13)      # set program check address
170         stg     %r1,__LC_PGM_NEW_PSW+8
171         stap    __LC_CPUID+4            # store cpu address
172         lh      %r1,__LC_CPUID+4
173         diag    %r1,0,0x9c              # test diag 0x9c
174         oi      6(%r12),1               # set diag9c flag
175 0:
176
177 #
178 # find out if we have the MVCOS instruction
179 #
180         la      %r1,0f-.LPG1(%r13)      # set program check address
181         stg     %r1,__LC_PGM_NEW_PSW+8
182         .short  0xc800                  # mvcos 0(%r0),0(%r0),%r0
183         .short  0x0000
184         .short  0x0000
185 0:      tm      0x8f,0x13               # special-operation exception?
186         bno     1f-.LPG1(%r13)          # if yes, MVCOS is present
187         oi      6(%r12),2               # set MVCOS flag
188 1:
189
190         lpswe   .Lentry-.LPG1(13)       # jump to _stext in primary-space,
191                                         # virtual and never return ...
192         .align  16
193 .Lentry:.quad   0x0000000180000000,_stext
194 .Lctl:  .quad   0x04b50002              # cr0: various things
195         .quad   0                       # cr1: primary space segment table
196         .quad   .Lduct                  # cr2: dispatchable unit control table
197         .quad   0                       # cr3: instruction authorization
198         .quad   0                       # cr4: instruction authorization
199         .quad   .Lduct                  # cr5: primary-aste origin
200         .quad   0                       # cr6:  I/O interrupts
201         .quad   0                       # cr7:  secondary space segment table
202         .quad   0                       # cr8:  access registers translation
203         .quad   0                       # cr9:  tracing off
204         .quad   0                       # cr10: tracing off
205         .quad   0                       # cr11: tracing off
206         .quad   0                       # cr12: tracing off
207         .quad   0                       # cr13: home space segment table
208         .quad   0xc0000000              # cr14: machine check handling off
209         .quad   0                       # cr15: linkage stack operations
210 .Lpcmsk:.quad   0x0000000180000000
211 .L4malign:.quad 0xffffffffffc00000
212 .Lscan2g:.quad  0x80000000 + 0x20000 - 8        # 2GB + 128K - 8
213 .Lnop:  .long   0x07000700
214 #ifdef CONFIG_ZFCPDUMP
215 .Lcurrent_cpu:
216         .long 0x0
217 .Llast_cpu:
218         .long 0x0000ffff
219 .Lpref_arr_ptr:
220         .long zfcpdump_prefix_array
221 #endif /* CONFIG_ZFCPDUMP */
222 .Lparmaddr:
223         .quad   PARMAREA
224         .align  64
225 .Lduct: .long   0,0,0,0,.Lduald,0,0,0
226         .long   0,0,0,0,0,0,0,0
227         .align  128
228 .Lduald:.rept   8
229         .long   0x80000000,0,0,0        # invalid access-list entries
230         .endr
231
232         .org    0x12000
233         .globl  _ehead
234 _ehead:
235 #ifdef CONFIG_SHARED_KERNEL
236         .org    0x100000
237 #endif
238
239 #
240 # startup-code, running in absolute addressing mode
241 #
242         .globl  _stext
243 _stext: basr    %r13,0                  # get base
244 .LPG3:
245 # check control registers
246         stctg   %c0,%c15,0(%r15)
247         oi      6(%r15),0x40            # enable sigp emergency signal
248         oi      4(%r15),0x10            # switch on low address proctection
249         lctlg   %c0,%c15,0(%r15)
250
251         lam     0,15,.Laregs-.LPG3(%r13)        # load acrs needed by uaccess
252         brasl   %r14,start_kernel       # go to C code
253 #
254 # We returned from start_kernel ?!? PANIK
255 #
256         basr    %r13,0
257         lpswe   .Ldw-.(%r13)            # load disabled wait psw
258
259         .align  8
260 .Ldw:   .quad   0x0002000180000000,0x0000000000000000
261 .Laregs:.long   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0