1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
|
/*
* Low level routines for legacy iSeries support.
*
* Extracted from head_64.S
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
* Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
* Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
* Adapted for Power Macintosh by Paul Mackerras.
* Low-level exception handlers and MMU support
* rewritten by Paul Mackerras.
* Copyright (C) 1996 Paul Mackerras.
*
* Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
* Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
*
* This file contains the low-level support and setup for the
* PowerPC-64 platform, including trap and interrupt dispatch.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <asm/reg.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/ptrace.h>
#include <asm/cputable.h>
#include <asm/mmu.h>
#include "exception.h"
.text
.globl system_reset_iSeries
system_reset_iSeries:
bl .relative_toc
mfspr r13,SPRN_SPRG3 /* Get alpaca address */
LOAD_REG_ADDR(r23, alpaca)
li r0,ALPACA_SIZE
sub r23,r13,r23
divdu r24,r23,r0 /* r24 has cpu number */
cmpwi 0,r24,0 /* Are we processor 0? */
bne 1f
LOAD_REG_ADDR(r13, boot_paca)
mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */
mfmsr r23
ori r23,r23,MSR_RI
mtmsrd r23 /* RI on */
b .__start_initialization_iSeries /* Start up the first processor */
1: mfspr r4,SPRN_CTRLF
li r5,CTRL_RUNLATCH /* Turn off the run light */
andc r4,r4,r5
mtspr SPRN_CTRLT,r4
/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
/* In the UP case we'll yield() later, and we will not access the paca anyway */
#ifdef CONFIG_SMP
iSeries_secondary_wait_paca:
HMT_LOW
LOAD_REG_ADDR(r23, __secondary_hold_spinloop)
ld r23,0(r23)
cmpdi 0,r23,0
bne 2f /* go on when the master is ready */
/* Keep poking the Hypervisor until we're released */
/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
lis r3,0x8002
rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
li r0,-1 /* r0=-1 indicates a Hypervisor call */
sc /* Invoke the hypervisor via a system call */
b iSeries_secondary_wait_paca
2:
HMT_MEDIUM
sync
LOAD_REG_ADDR(r3, nr_cpu_ids) /* get number of pacas allocated */
lwz r3,0(r3) /* nr_cpus= or NR_CPUS can limit */
cmpld 0,r24,r3 /* is our cpu number allocated? */
bge iSeries_secondary_yield /* no, yield forever */
/* Load our paca now that it's been allocated */
LOAD_REG_ADDR(r13, paca)
ld r13,0(r13)
mulli r0,r24,PACA_SIZE
add r13,r13,r0
mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */
mfmsr r23
ori r23,r23,MSR_RI
mtmsrd r23 /* RI on */
iSeries_secondary_smp_loop:
lbz r23,PACAPROCSTART(r13) /* Test if this processor
* should start */
cmpwi 0,r23,0
bne 3f /* go on when we are told */
HMT_LOW
/* Let the Hypervisor know we are alive */
/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
lis r3,0x8002
rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
li r0,-1 /* r0=-1 indicates a Hypervisor call */
sc /* Invoke the hypervisor via a system call */
mfspr r13,SPRN_SPRG_PACA /* Put r13 back ???? */
b iSeries_secondary_smp_loop /* wait for signal to start */
3:
HMT_MEDIUM
sync
LOAD_REG_ADDR(r3,current_set)
sldi r28,r24,3 /* get current_set[cpu#] */
ldx r3,r3,r28
addi r1,r3,THREAD_SIZE
subi r1,r1,STACK_FRAME_OVERHEAD
b __secondary_start /* Loop until told to go */
#endif /* CONFIG_SMP */
iSeries_secondary_yield:
/* Yield the processor. This is required for non-SMP kernels
which are running on multi-threaded machines. */
HMT_LOW
lis r3,0x8000
rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */
addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */
li r4,0 /* "yield timed" */
li r5,-1 /* "yield forever" */
li r0,-1 /* r0=-1 indicates a Hypervisor call */
sc /* Invoke the hypervisor via a system call */
mfspr r13,SPRN_SPRG_PACA /* Put r13 back ???? */
b iSeries_secondary_yield /* If SMP not configured, secondaries
* loop forever */
/*** ISeries-LPAR interrupt handlers ***/
STD_EXCEPTION_ISERIES(machine_check, PACA_EXMC)
.globl data_access_iSeries
data_access_iSeries:
mtspr SPRN_SPRG_SCRATCH0,r13
BEGIN_FTR_SECTION
mfspr r13,SPRN_SPRG_PACA
std r9,PACA_EXSLB+EX_R9(r13)
std r10,PACA_EXSLB+EX_R10(r13)
mfspr r10,SPRN_DAR
mfspr r9,SPRN_DSISR
srdi r10,r10,60
rlwimi r10,r9,16,0x20
mfcr r9
cmpwi r10,0x2c
beq .do_stab_bolted_iSeries
ld r10,PACA_EXSLB+EX_R10(r13)
std r11,PACA_EXGEN+EX_R11(r13)
ld r11,PACA_EXSLB+EX_R9(r13)
std r12,PACA_EXGEN+EX_R12(r13)
mfspr r12,SPRN_SPRG_SCRATCH0
std r10,PACA_EXGEN+EX_R10(r13)
std r11,PACA_EXGEN+EX_R9(r13)
std r12,PACA_EXGEN+EX_R13(r13)
EXCEPTION_PROLOG_ISERIES_1
FTR_SECTION_ELSE
EXCEPTION_PROLOG_1(PACA_EXGEN)
EXCEPTION_PROLOG_ISERIES_1
ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
b data_access_common
.do_stab_bolted_iSeries:
std r11,PACA_EXSLB+EX_R11(r13)
std r12,PACA_EXSLB+EX_R12(r13)
mfspr r10,SPRN_SPRG_SCRATCH0
std r10,PACA_EXSLB+EX_R13(r13)
EXCEPTION_PROLOG_ISERIES_1
b .do_stab_bolted
.globl data_access_slb_iSeries
data_access_slb_iSeries:
mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
std r3,PACA_EXSLB+EX_R3(r13)
mfspr r3,SPRN_DAR
std r9,PACA_EXSLB+EX_R9(r13)
mfcr r9
#ifdef __DISABLED__
cmpdi r3,0
bge slb_miss_user_iseries
#endif
std r10,PACA_EXSLB+EX_R10(r13)
std r11,PACA_EXSLB+EX_R11(r13)
std r12,PACA_EXSLB+EX_R12(r13)
mfspr r10,SPRN_SPRG_SCRATCH0
std r10,PACA_EXSLB+EX_R13(r13)
ld r12,PACALPPACAPTR(r13)
ld r12,LPPACASRR1(r12)
b .slb_miss_realmode
STD_EXCEPTION_ISERIES(instruction_access, PACA_EXGEN)
.globl instruction_access_slb_iSeries
instruction_access_slb_iSeries:
mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
std r3,PACA_EXSLB+EX_R3(r13)
ld r3,PACALPPACAPTR(r13)
ld r3,LPPACASRR0(r3) /* get SRR0 value */
std r9,PACA_EXSLB+EX_R9(r13)
mfcr r9
#ifdef __DISABLED__
cmpdi r3,0
bge slb_miss_user_iseries
#endif
std r10,PACA_EXSLB+EX_R10(r13)
std r11,PACA_EXSLB+EX_R11(r13)
std r12,PACA_EXSLB+EX_R12(r13)
mfspr r10,SPRN_SPRG_SCRATCH0
std r10,PACA_EXSLB+EX_R13(r13)
ld r12,PACALPPACAPTR(r13)
ld r12,LPPACASRR1(r12)
b .slb_miss_realmode
#ifdef __DISABLED__
slb_miss_user_iseries:
std r10,PACA_EXGEN+EX_R10(r13)
std r11,PACA_EXGEN+EX_R11(r13)
std r12,PACA_EXGEN+EX_R12(r13)
mfspr r10,SPRG_SCRATCH0
ld r11,PACA_EXSLB+EX_R9(r13)
ld r12,PACA_EXSLB+EX_R3(r13)
std r10,PACA_EXGEN+EX_R13(r13)
std r11,PACA_EXGEN+EX_R9(r13)
std r12,PACA_EXGEN+EX_R3(r13)
EXCEPTION_PROLOG_ISERIES_1
b slb_miss_user_common
#endif
MASKABLE_EXCEPTION_ISERIES(hardware_interrupt)
STD_EXCEPTION_ISERIES(alignment, PACA_EXGEN)
STD_EXCEPTION_ISERIES(program_check, PACA_EXGEN)
STD_EXCEPTION_ISERIES(fp_unavailable, PACA_EXGEN)
MASKABLE_EXCEPTION_ISERIES(decrementer)
STD_EXCEPTION_ISERIES(trap_0a, PACA_EXGEN)
STD_EXCEPTION_ISERIES(trap_0b, PACA_EXGEN)
.globl system_call_iSeries
system_call_iSeries:
mr r9,r13
mfspr r13,SPRN_SPRG_PACA
EXCEPTION_PROLOG_ISERIES_1
b system_call_common
STD_EXCEPTION_ISERIES(single_step, PACA_EXGEN)
STD_EXCEPTION_ISERIES(trap_0e, PACA_EXGEN)
STD_EXCEPTION_ISERIES(performance_monitor, PACA_EXGEN)
decrementer_iSeries_masked:
/* We may not have a valid TOC pointer in here. */
li r11,1
ld r12,PACALPPACAPTR(r13)
stb r11,LPPACADECRINT(r12)
li r12,-1
clrldi r12,r12,33 /* set DEC to 0x7fffffff */
mtspr SPRN_DEC,r12
/* fall through */
hardware_interrupt_iSeries_masked:
mtcrf 0x80,r9 /* Restore regs */
ld r12,PACALPPACAPTR(r13)
ld r11,LPPACASRR0(r12)
ld r12,LPPACASRR1(r12)
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r12
ld r9,PACA_EXGEN+EX_R9(r13)
ld r10,PACA_EXGEN+EX_R10(r13)
ld r11,PACA_EXGEN+EX_R11(r13)
ld r12,PACA_EXGEN+EX_R12(r13)
ld r13,PACA_EXGEN+EX_R13(r13)
rfid
b . /* prevent speculative execution */
_INIT_STATIC(__start_initialization_iSeries)
/* Clear out the BSS */
LOAD_REG_ADDR(r11,__bss_stop)
LOAD_REG_ADDR(r8,__bss_start)
sub r11,r11,r8 /* bss size */
addi r11,r11,7 /* round up to an even double word */
rldicl. r11,r11,61,3 /* shift right by 3 */
beq 4f
addi r8,r8,-8
li r0,0
mtctr r11 /* zero this many doublewords */
3: stdu r0,8(r8)
bdnz 3b
4:
LOAD_REG_ADDR(r1,init_thread_union)
addi r1,r1,THREAD_SIZE
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
bl .iSeries_early_setup
bl .early_setup
/* relocation is on at this point */
b .start_here_common
|