Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/parisc/kernel/hpmc.S
26289 views
1
/* SPDX-License-Identifier: GPL-2.0-or-later */
2
/*
3
* HPMC (High Priority Machine Check) handler.
4
*
5
* Copyright (C) 1999 Philipp Rumpf <[email protected]>
6
* Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
7
* Copyright (C) 2000 Hewlett-Packard (John Marvin)
8
*/
9
10
11
/*
12
* This HPMC handler retrieves the HPMC pim data, resets IO and
13
* returns to the default trap handler with code set to 1 (HPMC).
14
* The default trap handler calls handle interruption, which
15
* does a stack and register dump. This at least allows kernel
16
* developers to get back to C code in virtual mode, where they
17
* have the option to examine and print values from memory that
18
* would help in debugging an HPMC caused by a software bug.
19
*
20
* There is more to do here:
21
*
22
* 1) On MP systems we need to synchronize processors
23
* before calling pdc/iodc.
24
* 2) We should be checking the system state and not
25
* returning to the fault handler if things are really
26
* bad.
27
*
28
*/
29
30
.level 1.1
31
32
#include <asm/assembly.h>
33
#include <asm/pdc.h>
34
#include <asm/psw.h>
35
36
#include <linux/linkage.h>
37
#include <linux/init.h>
38
39
/*
40
* stack for os_hpmc, the HPMC handler.
41
* buffer for IODC procedures (for the HPMC handler).
42
*
43
* IODC requires 7K byte stack. That leaves 1K byte for os_hpmc.
44
*/
45
46
.import toc_stack,data
47
#define hpmc_stack toc_stack /* re-use the TOC stack */
48
49
#define HPMC_IODC_BUF_SIZE 0x8000
50
51
__PAGE_ALIGNED_BSS
52
.align 4096
53
hpmc_iodc_buf:
54
.block HPMC_IODC_BUF_SIZE
55
56
.section .bss
57
.align 8
58
hpmc_raddr:
59
.block 128
60
61
#define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */
62
63
.section .bss
64
.align 8
65
ENTRY(hpmc_pim_data)
66
.block HPMC_PIM_DATA_SIZE
67
END(hpmc_pim_data)
68
69
.text
70
71
.import intr_save, code
72
.align 16
73
ENTRY(os_hpmc)
74
.os_hpmc:
75
76
/*
77
* registers modified:
78
*
79
* Using callee saves registers without saving them. The
80
* original values are in the pim dump if we need them.
81
*
82
* r2 (rp) return pointer
83
* r3 address of PDCE_PROC
84
* r4 scratch
85
* r5 scratch
86
* r23 (arg3) procedure arg
87
* r24 (arg2) procedure arg
88
* r25 (arg1) procedure arg
89
* r26 (arg0) procedure arg
90
* r30 (sp) stack pointer
91
*
92
* registers read:
93
*
94
* r26 contains address of PDCE_PROC on entry
95
* r28 (ret0) return value from procedure
96
*/
97
98
copy arg0, %r3 /* save address of PDCE_PROC */
99
100
/*
101
* disable nested HPMCs
102
*
103
* Increment os_hpmc checksum to invalidate it.
104
* Do this before turning the PSW M bit off.
105
*/
106
107
mfctl %cr14, %r4
108
ldw 52(%r4),%r5
109
addi 1,%r5,%r5
110
stw %r5,52(%r4)
111
112
/* MP_FIXME: synchronize all processors. */
113
114
/* Setup stack pointer. */
115
116
load32 PA(hpmc_stack),sp
117
118
ldo 128(sp),sp /* leave room for arguments */
119
120
/*
121
* Most PDC routines require that the M bit be off.
122
* So turn on the Q bit and turn off the M bit.
123
*/
124
125
ldi PSW_SM_Q,%r4 /* PSW Q on, PSW M off */
126
mtctl %r4,ipsw
127
mtctl %r0,pcsq
128
mtctl %r0,pcsq
129
load32 PA(os_hpmc_1),%r4
130
mtctl %r4,pcoq
131
ldo 4(%r4),%r4
132
mtctl %r4,pcoq
133
rfi
134
nop
135
136
os_hpmc_1:
137
138
/* Call PDC_PIM to get HPMC pim info */
139
140
/*
141
* Note that on some newer boxes, PDC_PIM must be called
142
* before PDC_IO if you want IO to be reset. PDC_PIM sets
143
* a flag that PDC_IO examines.
144
*/
145
146
ldo PDC_PIM(%r0), arg0
147
ldo PDC_PIM_HPMC(%r0),arg1 /* Transfer HPMC data */
148
load32 PA(hpmc_raddr),arg2
149
load32 PA(hpmc_pim_data),arg3
150
load32 HPMC_PIM_DATA_SIZE,%r4
151
stw %r4,-52(sp)
152
153
ldil L%PA(os_hpmc_2), rp
154
bv (r3) /* call pdce_proc */
155
ldo R%PA(os_hpmc_2)(rp), rp
156
157
os_hpmc_2:
158
comib,<> 0,ret0, os_hpmc_fail
159
160
/* Reset IO by calling the hversion dependent PDC_IO routine */
161
162
ldo PDC_IO(%r0),arg0
163
ldo 0(%r0),arg1 /* log IO errors */
164
ldo 0(%r0),arg2 /* reserved */
165
ldo 0(%r0),arg3 /* reserved */
166
stw %r0,-52(sp) /* reserved */
167
168
ldil L%PA(os_hpmc_3),rp
169
bv (%r3) /* call pdce_proc */
170
ldo R%PA(os_hpmc_3)(rp),rp
171
172
os_hpmc_3:
173
174
/* FIXME? Check for errors from PDC_IO (-1 might be OK) */
175
176
/*
177
* Initialize the IODC console device (HPA,SPA, path etc.
178
* are stored on page 0.
179
*/
180
181
/*
182
* Load IODC into hpmc_iodc_buf by calling PDC_IODC.
183
* Note that PDC_IODC handles flushing the appropriate
184
* data and instruction cache lines.
185
*/
186
187
ldo PDC_IODC(%r0),arg0
188
ldo PDC_IODC_READ(%r0),arg1
189
load32 PA(hpmc_raddr),arg2
190
ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */
191
ldo PDC_IODC_RI_INIT(%r0),%r4
192
stw %r4,-52(sp)
193
load32 PA(hpmc_iodc_buf),%r4
194
stw %r4,-56(sp)
195
load32 HPMC_IODC_BUF_SIZE,%r4
196
stw %r4,-60(sp)
197
198
ldil L%PA(os_hpmc_4),rp
199
bv (%r3) /* call pdce_proc */
200
ldo R%PA(os_hpmc_4)(rp),rp
201
202
os_hpmc_4:
203
comib,<> 0,ret0,os_hpmc_fail
204
205
/* Call the entry init (just loaded by PDC_IODC) */
206
207
ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg0 /* console hpa */
208
ldo ENTRY_INIT_MOD_DEV(%r0), arg1
209
ldw BOOT_CONSOLE_SPA_OFFSET(%r0),arg2 /* console spa */
210
depi 0,31,11,arg2 /* clear bits 21-31 */
211
ldo BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */
212
load32 PA(hpmc_raddr),%r4
213
stw %r4, -52(sp)
214
stw %r0, -56(sp) /* HV */
215
stw %r0, -60(sp) /* HV */
216
stw %r0, -64(sp) /* HV */
217
stw %r0, -68(sp) /* lang, must be zero */
218
219
load32 PA(hpmc_iodc_buf),%r5
220
ldil L%PA(os_hpmc_5),rp
221
bv (%r5)
222
ldo R%PA(os_hpmc_5)(rp),rp
223
224
os_hpmc_5:
225
comib,<> 0,ret0,os_hpmc_fail
226
227
/* Prepare to call intr_save */
228
229
/*
230
* Load kernel page directory (load into user also, since
231
* we don't intend to ever return to user land anyway)
232
*/
233
234
load32 PA(swapper_pg_dir),%r4
235
mtctl %r4,%cr24 /* Initialize kernel root pointer */
236
mtctl %r4,%cr25 /* Initialize user root pointer */
237
238
/* Clear sr4-sr7 */
239
240
mtsp %r0, %sr4
241
mtsp %r0, %sr5
242
mtsp %r0, %sr6
243
mtsp %r0, %sr7
244
245
tovirt_r1 %r30 /* make sp virtual */
246
247
rsm PSW_SM_Q,%r0 /* Clear Q bit */
248
ldi 1,%r8 /* Set trap code to "1" for HPMC */
249
load32 PA(intr_save),%r1
250
be 0(%sr7,%r1)
251
nop
252
253
os_hpmc_fail:
254
255
/*
256
* Reset the system
257
*
258
* Some systems may lockup from a broadcast reset, so try the
259
* hversion PDC_BROADCAST_RESET() first.
260
* MP_FIXME: reset all processors if more than one central bus.
261
*/
262
263
/* PDC_BROADCAST_RESET() */
264
265
ldo PDC_BROADCAST_RESET(%r0),arg0
266
ldo 0(%r0),arg1 /* do reset */
267
268
ldil L%PA(os_hpmc_6),rp
269
bv (%r3) /* call pdce_proc */
270
ldo R%PA(os_hpmc_6)(rp),rp
271
272
os_hpmc_6:
273
274
/*
275
* possible return values:
276
* -1 non-existent procedure
277
* -2 non-existent option
278
* -16 unaligned stack
279
*
280
* If call returned, do a broadcast reset.
281
*/
282
283
ldil L%0xfffc0000,%r4 /* IO_BROADCAST */
284
ldo 5(%r0),%r5
285
stw %r5,48(%r4) /* CMD_RESET to IO_COMMAND offset */
286
287
b .
288
nop
289
.align 16 /* make function length multiple of 16 bytes */
290
291