Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sparc/kernel/head_64.S
26424 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/* head.S: Initial boot code for the Sparc64 port of Linux.
3
*
4
* Copyright (C) 1996, 1997, 2007 David S. Miller ([email protected])
5
* Copyright (C) 1996 David Sitsky ([email protected])
6
* Copyright (C) 1997, 1998 Jakub Jelinek ([email protected])
7
* Copyright (C) 1997 Miguel de Icaza ([email protected])
8
*/
9
10
#include <linux/version.h>
11
#include <linux/errno.h>
12
#include <linux/export.h>
13
#include <linux/threads.h>
14
#include <linux/init.h>
15
#include <linux/linkage.h>
16
#include <linux/pgtable.h>
17
#include <asm/thread_info.h>
18
#include <asm/asi.h>
19
#include <asm/pstate.h>
20
#include <asm/ptrace.h>
21
#include <asm/spitfire.h>
22
#include <asm/page.h>
23
#include <asm/errno.h>
24
#include <asm/signal.h>
25
#include <asm/processor.h>
26
#include <asm/lsu.h>
27
#include <asm/dcr.h>
28
#include <asm/dcu.h>
29
#include <asm/head.h>
30
#include <asm/ttable.h>
31
#include <asm/mmu.h>
32
#include <asm/cpudata.h>
33
#include <asm/pil.h>
34
#include <asm/estate.h>
35
#include <asm/sfafsr.h>
36
#include <asm/unistd.h>
37
38
/* This section from from _start to sparc64_boot_end should fit into
39
* 0x0000000000404000 to 0x0000000000408000.
40
*/
41
.text
42
.globl start, _start, stext, _stext
43
_start:
44
start:
45
_stext:
46
stext:
47
! 0x0000000000404000
48
b sparc64_boot
49
flushw /* Flush register file. */
50
51
/* This stuff has to be in sync with SILO and other potential boot loaders
52
* Fields should be kept upward compatible and whenever any change is made,
53
* HdrS version should be incremented.
54
*/
55
.global root_flags, ram_flags, root_dev
56
.global sparc_ramdisk_image, sparc_ramdisk_size
57
.global sparc_ramdisk_image64
58
59
.ascii "HdrS"
60
.word LINUX_VERSION_CODE
61
62
/* History:
63
*
64
* 0x0300 : Supports being located at other than 0x4000
65
* 0x0202 : Supports kernel params string
66
* 0x0201 : Supports reboot_command
67
*/
68
.half 0x0301 /* HdrS version */
69
70
root_flags:
71
.half 1
72
root_dev:
73
.half 0
74
ram_flags:
75
.half 0
76
sparc_ramdisk_image:
77
.word 0
78
sparc_ramdisk_size:
79
.word 0
80
.xword reboot_command
81
.xword bootstr_info
82
sparc_ramdisk_image64:
83
.xword 0
84
.word _end
85
86
/* PROM cif handler code address is in %o4. */
87
sparc64_boot:
88
mov %o4, %l7
89
90
/* We need to remap the kernel. Use position independent
91
* code to remap us to KERNBASE.
92
*
93
* SILO can invoke us with 32-bit address masking enabled,
94
* so make sure that's clear.
95
*/
96
rdpr %pstate, %g1
97
andn %g1, PSTATE_AM, %g1
98
wrpr %g1, 0x0, %pstate
99
ba,a,pt %xcc, 1f
100
nop
101
102
.globl prom_finddev_name, prom_chosen_path, prom_root_node
103
.globl prom_getprop_name, prom_mmu_name, prom_peer_name
104
.globl prom_callmethod_name, prom_translate_name, prom_root_compatible
105
.globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
106
.globl prom_boot_mapped_pc, prom_boot_mapping_mode
107
.globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
108
.globl prom_compatible_name, prom_cpu_path, prom_cpu_compatible
109
.globl is_sun4v, sun4v_chip_type, prom_set_trap_table_name
110
prom_peer_name:
111
.asciz "peer"
112
prom_compatible_name:
113
.asciz "compatible"
114
prom_finddev_name:
115
.asciz "finddevice"
116
prom_chosen_path:
117
.asciz "/chosen"
118
prom_cpu_path:
119
.asciz "/cpu"
120
prom_getprop_name:
121
.asciz "getprop"
122
prom_mmu_name:
123
.asciz "mmu"
124
prom_callmethod_name:
125
.asciz "call-method"
126
prom_translate_name:
127
.asciz "translate"
128
prom_map_name:
129
.asciz "map"
130
prom_unmap_name:
131
.asciz "unmap"
132
prom_set_trap_table_name:
133
.asciz "SUNW,set-trap-table"
134
prom_sun4v_name:
135
.asciz "sun4v"
136
prom_niagara_prefix:
137
.asciz "SUNW,UltraSPARC-T"
138
prom_sparc_prefix:
139
.asciz "SPARC-"
140
prom_sparc64x_prefix:
141
.asciz "SPARC64-X"
142
.align 4
143
prom_root_compatible:
144
.skip 64
145
prom_cpu_compatible:
146
.skip 64
147
prom_root_node:
148
.word 0
149
EXPORT_SYMBOL(prom_root_node)
150
prom_mmu_ihandle_cache:
151
.word 0
152
prom_boot_mapped_pc:
153
.word 0
154
prom_boot_mapping_mode:
155
.word 0
156
.align 8
157
prom_boot_mapping_phys_high:
158
.xword 0
159
prom_boot_mapping_phys_low:
160
.xword 0
161
is_sun4v:
162
.word 0
163
sun4v_chip_type:
164
.word SUN4V_CHIP_INVALID
165
EXPORT_SYMBOL(sun4v_chip_type)
166
1:
167
rd %pc, %l0
168
169
mov (1b - prom_peer_name), %l1
170
sub %l0, %l1, %l1
171
mov 0, %l2
172
173
/* prom_root_node = prom_peer(0) */
174
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "peer"
175
mov 1, %l3
176
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1
177
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
178
stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, 0
179
stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1
180
call %l7
181
add %sp, (2047 + 128), %o0 ! argument array
182
183
ldx [%sp + 2047 + 128 + 0x20], %l4 ! prom root node
184
mov (1b - prom_root_node), %l1
185
sub %l0, %l1, %l1
186
stw %l4, [%l1]
187
188
mov (1b - prom_getprop_name), %l1
189
mov (1b - prom_compatible_name), %l2
190
mov (1b - prom_root_compatible), %l5
191
sub %l0, %l1, %l1
192
sub %l0, %l2, %l2
193
sub %l0, %l5, %l5
194
195
/* prom_getproperty(prom_root_node, "compatible",
196
* &prom_root_compatible, 64)
197
*/
198
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop"
199
mov 4, %l3
200
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4
201
mov 1, %l3
202
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
203
stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, prom_root_node
204
stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "compatible"
205
stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_root_compatible
206
mov 64, %l3
207
stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, size
208
stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1
209
call %l7
210
add %sp, (2047 + 128), %o0 ! argument array
211
212
mov (1b - prom_finddev_name), %l1
213
mov (1b - prom_chosen_path), %l2
214
mov (1b - prom_boot_mapped_pc), %l3
215
sub %l0, %l1, %l1
216
sub %l0, %l2, %l2
217
sub %l0, %l3, %l3
218
stw %l0, [%l3]
219
sub %sp, (192 + 128), %sp
220
221
/* chosen_node = prom_finddevice("/chosen") */
222
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice"
223
mov 1, %l3
224
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1
225
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
226
stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/chosen"
227
stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1
228
call %l7
229
add %sp, (2047 + 128), %o0 ! argument array
230
231
ldx [%sp + 2047 + 128 + 0x20], %l4 ! chosen device node
232
233
mov (1b - prom_getprop_name), %l1
234
mov (1b - prom_mmu_name), %l2
235
mov (1b - prom_mmu_ihandle_cache), %l5
236
sub %l0, %l1, %l1
237
sub %l0, %l2, %l2
238
sub %l0, %l5, %l5
239
240
/* prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu") */
241
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop"
242
mov 4, %l3
243
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4
244
mov 1, %l3
245
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
246
stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, chosen_node
247
stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "mmu"
248
stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_mmu_ihandle_cache
249
mov 4, %l3
250
stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, sizeof(arg3)
251
stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1
252
call %l7
253
add %sp, (2047 + 128), %o0 ! argument array
254
255
mov (1b - prom_callmethod_name), %l1
256
mov (1b - prom_translate_name), %l2
257
sub %l0, %l1, %l1
258
sub %l0, %l2, %l2
259
lduw [%l5], %l5 ! prom_mmu_ihandle_cache
260
261
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "call-method"
262
mov 3, %l3
263
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 3
264
mov 5, %l3
265
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 5
266
stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1: "translate"
267
stx %l5, [%sp + 2047 + 128 + 0x20] ! arg2: prom_mmu_ihandle_cache
268
/* PAGE align */
269
srlx %l0, 13, %l3
270
sllx %l3, 13, %l3
271
stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: vaddr, our PC
272
stx %g0, [%sp + 2047 + 128 + 0x30] ! res1
273
stx %g0, [%sp + 2047 + 128 + 0x38] ! res2
274
stx %g0, [%sp + 2047 + 128 + 0x40] ! res3
275
stx %g0, [%sp + 2047 + 128 + 0x48] ! res4
276
stx %g0, [%sp + 2047 + 128 + 0x50] ! res5
277
call %l7
278
add %sp, (2047 + 128), %o0 ! argument array
279
280
ldx [%sp + 2047 + 128 + 0x40], %l1 ! translation mode
281
mov (1b - prom_boot_mapping_mode), %l4
282
sub %l0, %l4, %l4
283
stw %l1, [%l4]
284
mov (1b - prom_boot_mapping_phys_high), %l4
285
sub %l0, %l4, %l4
286
ldx [%sp + 2047 + 128 + 0x48], %l2 ! physaddr high
287
stx %l2, [%l4 + 0x0]
288
ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low
289
/* 4MB align */
290
srlx %l3, ILOG2_4MB, %l3
291
sllx %l3, ILOG2_4MB, %l3
292
stx %l3, [%l4 + 0x8]
293
294
/* Leave service as-is, "call-method" */
295
mov 7, %l3
296
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 7
297
mov 1, %l3
298
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
299
mov (1b - prom_map_name), %l3
300
sub %l0, %l3, %l3
301
stx %l3, [%sp + 2047 + 128 + 0x18] ! arg1: "map"
302
/* Leave arg2 as-is, prom_mmu_ihandle_cache */
303
mov -1, %l3
304
stx %l3, [%sp + 2047 + 128 + 0x28] ! arg3: mode (-1 default)
305
/* 4MB align the kernel image size. */
306
set (_end - KERNBASE), %l3
307
set ((4 * 1024 * 1024) - 1), %l4
308
add %l3, %l4, %l3
309
andn %l3, %l4, %l3
310
stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4: roundup(ksize, 4MB)
311
sethi %hi(KERNBASE), %l3
312
stx %l3, [%sp + 2047 + 128 + 0x38] ! arg5: vaddr (KERNBASE)
313
stx %g0, [%sp + 2047 + 128 + 0x40] ! arg6: empty
314
mov (1b - prom_boot_mapping_phys_low), %l3
315
sub %l0, %l3, %l3
316
ldx [%l3], %l3
317
stx %l3, [%sp + 2047 + 128 + 0x48] ! arg7: phys addr
318
call %l7
319
add %sp, (2047 + 128), %o0 ! argument array
320
321
add %sp, (192 + 128), %sp
322
323
sethi %hi(prom_root_compatible), %g1
324
or %g1, %lo(prom_root_compatible), %g1
325
sethi %hi(prom_sun4v_name), %g7
326
or %g7, %lo(prom_sun4v_name), %g7
327
mov 5, %g3
328
90: ldub [%g7], %g2
329
ldub [%g1], %g4
330
cmp %g2, %g4
331
bne,pn %icc, 80f
332
add %g7, 1, %g7
333
subcc %g3, 1, %g3
334
bne,pt %xcc, 90b
335
add %g1, 1, %g1
336
337
sethi %hi(is_sun4v), %g1
338
or %g1, %lo(is_sun4v), %g1
339
mov 1, %g7
340
stw %g7, [%g1]
341
342
/* cpu_node = prom_finddevice("/cpu") */
343
mov (1b - prom_finddev_name), %l1
344
mov (1b - prom_cpu_path), %l2
345
sub %l0, %l1, %l1
346
sub %l0, %l2, %l2
347
sub %sp, (192 + 128), %sp
348
349
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "finddevice"
350
mov 1, %l3
351
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1
352
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
353
stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, "/cpu"
354
stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1
355
call %l7
356
add %sp, (2047 + 128), %o0 ! argument array
357
358
ldx [%sp + 2047 + 128 + 0x20], %l4 ! cpu device node
359
360
mov (1b - prom_getprop_name), %l1
361
mov (1b - prom_compatible_name), %l2
362
mov (1b - prom_cpu_compatible), %l5
363
sub %l0, %l1, %l1
364
sub %l0, %l2, %l2
365
sub %l0, %l5, %l5
366
367
/* prom_getproperty(cpu_node, "compatible",
368
* &prom_cpu_compatible, 64)
369
*/
370
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop"
371
mov 4, %l3
372
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4
373
mov 1, %l3
374
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
375
stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, cpu_node
376
stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "compatible"
377
stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_cpu_compatible
378
mov 64, %l3
379
stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, size
380
stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1
381
call %l7
382
add %sp, (2047 + 128), %o0 ! argument array
383
384
add %sp, (192 + 128), %sp
385
386
sethi %hi(prom_cpu_compatible), %g1
387
or %g1, %lo(prom_cpu_compatible), %g1
388
sethi %hi(prom_niagara_prefix), %g7
389
or %g7, %lo(prom_niagara_prefix), %g7
390
mov 17, %g3
391
90: ldub [%g7], %g2
392
ldub [%g1], %g4
393
cmp %g2, %g4
394
bne,pn %icc, 89f
395
add %g7, 1, %g7
396
subcc %g3, 1, %g3
397
bne,pt %xcc, 90b
398
add %g1, 1, %g1
399
ba,pt %xcc, 91f
400
nop
401
402
89: sethi %hi(prom_cpu_compatible), %g1
403
or %g1, %lo(prom_cpu_compatible), %g1
404
sethi %hi(prom_sparc_prefix), %g7
405
or %g7, %lo(prom_sparc_prefix), %g7
406
mov 6, %g3
407
90: ldub [%g7], %g2
408
ldub [%g1], %g4
409
cmp %g2, %g4
410
bne,pn %icc, 4f
411
add %g7, 1, %g7
412
subcc %g3, 1, %g3
413
bne,pt %xcc, 90b
414
add %g1, 1, %g1
415
416
sethi %hi(prom_cpu_compatible), %g1
417
or %g1, %lo(prom_cpu_compatible), %g1
418
ldub [%g1 + 6], %g2
419
cmp %g2, 'T'
420
be,pt %xcc, 70f
421
cmp %g2, 'M'
422
be,pt %xcc, 70f
423
cmp %g2, 'S'
424
bne,pn %xcc, 49f
425
nop
426
427
70: ldub [%g1 + 7], %g2
428
cmp %g2, CPU_ID_NIAGARA3
429
be,pt %xcc, 5f
430
mov SUN4V_CHIP_NIAGARA3, %g4
431
cmp %g2, CPU_ID_NIAGARA4
432
be,pt %xcc, 5f
433
mov SUN4V_CHIP_NIAGARA4, %g4
434
cmp %g2, CPU_ID_NIAGARA5
435
be,pt %xcc, 5f
436
mov SUN4V_CHIP_NIAGARA5, %g4
437
cmp %g2, CPU_ID_M6
438
be,pt %xcc, 5f
439
mov SUN4V_CHIP_SPARC_M6, %g4
440
cmp %g2, CPU_ID_M7
441
be,pt %xcc, 5f
442
mov SUN4V_CHIP_SPARC_M7, %g4
443
cmp %g2, CPU_ID_M8
444
be,pt %xcc, 5f
445
mov SUN4V_CHIP_SPARC_M8, %g4
446
cmp %g2, CPU_ID_SONOMA1
447
be,pt %xcc, 5f
448
mov SUN4V_CHIP_SPARC_SN, %g4
449
ba,pt %xcc, 49f
450
nop
451
452
91: sethi %hi(prom_cpu_compatible), %g1
453
or %g1, %lo(prom_cpu_compatible), %g1
454
ldub [%g1 + 17], %g2
455
cmp %g2, CPU_ID_NIAGARA1
456
be,pt %xcc, 5f
457
mov SUN4V_CHIP_NIAGARA1, %g4
458
cmp %g2, CPU_ID_NIAGARA2
459
be,pt %xcc, 5f
460
mov SUN4V_CHIP_NIAGARA2, %g4
461
462
4:
463
/* Athena */
464
sethi %hi(prom_cpu_compatible), %g1
465
or %g1, %lo(prom_cpu_compatible), %g1
466
sethi %hi(prom_sparc64x_prefix), %g7
467
or %g7, %lo(prom_sparc64x_prefix), %g7
468
mov 9, %g3
469
41: ldub [%g7], %g2
470
ldub [%g1], %g4
471
cmp %g2, %g4
472
bne,pn %icc, 49f
473
add %g7, 1, %g7
474
subcc %g3, 1, %g3
475
bne,pt %xcc, 41b
476
add %g1, 1, %g1
477
ba,pt %xcc, 5f
478
mov SUN4V_CHIP_SPARC64X, %g4
479
480
49:
481
mov SUN4V_CHIP_UNKNOWN, %g4
482
5: sethi %hi(sun4v_chip_type), %g2
483
or %g2, %lo(sun4v_chip_type), %g2
484
stw %g4, [%g2]
485
486
80:
487
BRANCH_IF_SUN4V(g1, jump_to_sun4u_init)
488
BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
489
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
490
ba,pt %xcc, spitfire_boot
491
nop
492
493
cheetah_plus_boot:
494
/* Preserve OBP chosen DCU and DCR register settings. */
495
ba,pt %xcc, cheetah_generic_boot
496
nop
497
498
cheetah_boot:
499
mov DCR_BPE | DCR_RPE | DCR_SI | DCR_IFPOE | DCR_MS, %g1
500
wr %g1, %asr18
501
502
sethi %uhi(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7
503
or %g7, %ulo(DCU_ME|DCU_RE|DCU_HPE|DCU_SPE|DCU_SL|DCU_WE), %g7
504
sllx %g7, 32, %g7
505
or %g7, DCU_DM | DCU_IM | DCU_DC | DCU_IC, %g7
506
stxa %g7, [%g0] ASI_DCU_CONTROL_REG
507
membar #Sync
508
509
cheetah_generic_boot:
510
mov TSB_EXTENSION_P, %g3
511
stxa %g0, [%g3] ASI_DMMU
512
stxa %g0, [%g3] ASI_IMMU
513
membar #Sync
514
515
mov TSB_EXTENSION_S, %g3
516
stxa %g0, [%g3] ASI_DMMU
517
membar #Sync
518
519
mov TSB_EXTENSION_N, %g3
520
stxa %g0, [%g3] ASI_DMMU
521
stxa %g0, [%g3] ASI_IMMU
522
membar #Sync
523
524
ba,a,pt %xcc, jump_to_sun4u_init
525
526
spitfire_boot:
527
/* Typically PROM has already enabled both MMU's and both on-chip
528
* caches, but we do it here anyway just to be paranoid.
529
*/
530
mov (LSU_CONTROL_IC|LSU_CONTROL_DC|LSU_CONTROL_IM|LSU_CONTROL_DM), %g1
531
stxa %g1, [%g0] ASI_LSU_CONTROL
532
membar #Sync
533
534
jump_to_sun4u_init:
535
/*
536
* Make sure we are in privileged mode, have address masking,
537
* using the ordinary globals and have enabled floating
538
* point.
539
*
540
* Again, typically PROM has left %pil at 13 or similar, and
541
* (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE) in %pstate.
542
*/
543
wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
544
wr %g0, 0, %fprs
545
546
set sun4u_init, %g2
547
jmpl %g2 + %g0, %g0
548
nop
549
550
__REF
551
sun4u_init:
552
BRANCH_IF_SUN4V(g1, sun4v_init)
553
554
/* Set ctx 0 */
555
mov PRIMARY_CONTEXT, %g7
556
stxa %g0, [%g7] ASI_DMMU
557
membar #Sync
558
559
mov SECONDARY_CONTEXT, %g7
560
stxa %g0, [%g7] ASI_DMMU
561
membar #Sync
562
563
ba,a,pt %xcc, sun4u_continue
564
565
sun4v_init:
566
/* Set ctx 0 */
567
mov PRIMARY_CONTEXT, %g7
568
stxa %g0, [%g7] ASI_MMU
569
membar #Sync
570
571
mov SECONDARY_CONTEXT, %g7
572
stxa %g0, [%g7] ASI_MMU
573
membar #Sync
574
ba,a,pt %xcc, niagara_tlb_fixup
575
576
sun4u_continue:
577
BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup)
578
579
ba,a,pt %xcc, spitfire_tlb_fixup
580
581
niagara_tlb_fixup:
582
mov 3, %g2 /* Set TLB type to hypervisor. */
583
sethi %hi(tlb_type), %g1
584
stw %g2, [%g1 + %lo(tlb_type)]
585
586
/* Patch copy/clear ops. */
587
sethi %hi(sun4v_chip_type), %g1
588
lduw [%g1 + %lo(sun4v_chip_type)], %g1
589
cmp %g1, SUN4V_CHIP_NIAGARA1
590
be,pt %xcc, niagara_patch
591
cmp %g1, SUN4V_CHIP_NIAGARA2
592
be,pt %xcc, niagara2_patch
593
nop
594
cmp %g1, SUN4V_CHIP_NIAGARA3
595
be,pt %xcc, niagara2_patch
596
nop
597
cmp %g1, SUN4V_CHIP_NIAGARA4
598
be,pt %xcc, niagara4_patch
599
nop
600
cmp %g1, SUN4V_CHIP_NIAGARA5
601
be,pt %xcc, niagara4_patch
602
nop
603
cmp %g1, SUN4V_CHIP_SPARC_M6
604
be,pt %xcc, niagara4_patch
605
nop
606
cmp %g1, SUN4V_CHIP_SPARC_M7
607
be,pt %xcc, sparc_m7_patch
608
nop
609
cmp %g1, SUN4V_CHIP_SPARC_M8
610
be,pt %xcc, sparc_m7_patch
611
nop
612
cmp %g1, SUN4V_CHIP_SPARC_SN
613
be,pt %xcc, niagara4_patch
614
nop
615
616
call generic_patch_copyops
617
nop
618
call generic_patch_bzero
619
nop
620
call generic_patch_pageops
621
nop
622
623
ba,a,pt %xcc, 80f
624
nop
625
626
sparc_m7_patch:
627
call m7_patch_copyops
628
nop
629
call m7_patch_bzero
630
nop
631
call m7_patch_pageops
632
nop
633
634
ba,a,pt %xcc, 80f
635
nop
636
637
niagara4_patch:
638
call niagara4_patch_copyops
639
nop
640
call niagara4_patch_bzero
641
nop
642
call niagara4_patch_pageops
643
nop
644
call niagara4_patch_fls
645
nop
646
647
ba,a,pt %xcc, 80f
648
nop
649
650
niagara2_patch:
651
call niagara2_patch_copyops
652
nop
653
call niagara_patch_bzero
654
nop
655
call niagara_patch_pageops
656
nop
657
658
ba,a,pt %xcc, 80f
659
nop
660
661
niagara_patch:
662
call niagara_patch_copyops
663
nop
664
call niagara_patch_bzero
665
nop
666
call niagara_patch_pageops
667
nop
668
669
80:
670
/* Patch TLB/cache ops. */
671
call hypervisor_patch_cachetlbops
672
nop
673
674
ba,a,pt %xcc, tlb_fixup_done
675
676
cheetah_tlb_fixup:
677
mov 2, %g2 /* Set TLB type to cheetah+. */
678
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
679
680
mov 1, %g2 /* Set TLB type to cheetah. */
681
682
1: sethi %hi(tlb_type), %g1
683
stw %g2, [%g1 + %lo(tlb_type)]
684
685
/* Patch copy/page operations to cheetah optimized versions. */
686
call cheetah_patch_copyops
687
nop
688
call cheetah_patch_copy_page
689
nop
690
call cheetah_patch_cachetlbops
691
nop
692
693
ba,a,pt %xcc, tlb_fixup_done
694
695
spitfire_tlb_fixup:
696
/* Set TLB type to spitfire. */
697
mov 0, %g2
698
sethi %hi(tlb_type), %g1
699
stw %g2, [%g1 + %lo(tlb_type)]
700
701
tlb_fixup_done:
702
sethi %hi(init_thread_union), %g6
703
or %g6, %lo(init_thread_union), %g6
704
ldx [%g6 + TI_TASK], %g4
705
706
wr %g0, ASI_P, %asi
707
mov 1, %g1
708
sllx %g1, THREAD_SHIFT, %g1
709
sub %g1, (STACKFRAME_SZ + STACK_BIAS + TRACEREG_SZ), %g1
710
add %g6, %g1, %sp
711
712
/* Set per-cpu pointer initially to zero, this makes
713
* the boot-cpu use the in-kernel-image per-cpu areas
714
* before setup_per_cpu_area() is invoked.
715
*/
716
clr %g5
717
718
wrpr %g0, 0, %wstate
719
wrpr %g0, 0x0, %tl
720
721
/* Clear the bss */
722
sethi %hi(__bss_start), %o0
723
or %o0, %lo(__bss_start), %o0
724
sethi %hi(_end), %o1
725
or %o1, %lo(_end), %o1
726
call __bzero
727
sub %o1, %o0, %o1
728
729
call prom_init
730
mov %l7, %o0 ! OpenPROM cif handler
731
732
/* To create a one-register-window buffer between the kernel's
733
* initial stack and the last stack frame we use from the firmware,
734
* do the rest of the boot from a C helper function.
735
*/
736
call start_early_boot
737
nop
738
/* Not reached... */
739
740
.previous
741
742
/* This is meant to allow the sharing of this code between
743
* boot processor invocation (via setup_tba() below) and
744
* secondary processor startup (via trampoline.S). The
745
* former does use this code, the latter does not yet due
746
* to some complexities. That should be fixed up at some
747
* point.
748
*
749
* There used to be enormous complexity wrt. transferring
750
* over from the firmware's trap table to the Linux kernel's.
751
* For example, there was a chicken & egg problem wrt. building
752
* the OBP page tables, yet needing to be on the Linux kernel
753
* trap table (to translate PAGE_OFFSET addresses) in order to
754
* do that.
755
*
756
* We now handle OBP tlb misses differently, via linear lookups
757
* into the prom_trans[] array. So that specific problem no
758
* longer exists. Yet, unfortunately there are still some issues
759
* preventing trampoline.S from using this code... ho hum.
760
*/
761
.globl setup_trap_table
762
setup_trap_table:
763
save %sp, -192, %sp
764
765
/* Force interrupts to be disabled. */
766
rdpr %pstate, %l0
767
andn %l0, PSTATE_IE, %o1
768
wrpr %o1, 0x0, %pstate
769
rdpr %pil, %l1
770
wrpr %g0, PIL_NORMAL_MAX, %pil
771
772
/* Make the firmware call to jump over to the Linux trap table. */
773
sethi %hi(is_sun4v), %o0
774
lduw [%o0 + %lo(is_sun4v)], %o0
775
brz,pt %o0, 1f
776
nop
777
778
TRAP_LOAD_TRAP_BLOCK(%g2, %g3)
779
add %g2, TRAP_PER_CPU_FAULT_INFO, %g2
780
stxa %g2, [%g0] ASI_SCRATCHPAD
781
782
/* Compute physical address:
783
*
784
* paddr = kern_base + (mmfsa_vaddr - KERNBASE)
785
*/
786
sethi %hi(KERNBASE), %g3
787
sub %g2, %g3, %g2
788
sethi %hi(kern_base), %g3
789
ldx [%g3 + %lo(kern_base)], %g3
790
add %g2, %g3, %o1
791
sethi %hi(sparc64_ttable_tl0), %o0
792
793
set prom_set_trap_table_name, %g2
794
stx %g2, [%sp + 2047 + 128 + 0x00]
795
mov 2, %g2
796
stx %g2, [%sp + 2047 + 128 + 0x08]
797
mov 0, %g2
798
stx %g2, [%sp + 2047 + 128 + 0x10]
799
stx %o0, [%sp + 2047 + 128 + 0x18]
800
stx %o1, [%sp + 2047 + 128 + 0x20]
801
sethi %hi(p1275buf), %g2
802
or %g2, %lo(p1275buf), %g2
803
ldx [%g2 + 0x08], %o1
804
call %o1
805
add %sp, (2047 + 128), %o0
806
807
ba,a,pt %xcc, 2f
808
809
1: sethi %hi(sparc64_ttable_tl0), %o0
810
set prom_set_trap_table_name, %g2
811
stx %g2, [%sp + 2047 + 128 + 0x00]
812
mov 1, %g2
813
stx %g2, [%sp + 2047 + 128 + 0x08]
814
mov 0, %g2
815
stx %g2, [%sp + 2047 + 128 + 0x10]
816
stx %o0, [%sp + 2047 + 128 + 0x18]
817
sethi %hi(p1275buf), %g2
818
or %g2, %lo(p1275buf), %g2
819
ldx [%g2 + 0x08], %o1
820
call %o1
821
add %sp, (2047 + 128), %o0
822
823
/* Start using proper page size encodings in ctx register. */
824
2: sethi %hi(sparc64_kern_pri_context), %g3
825
ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
826
827
mov PRIMARY_CONTEXT, %g1
828
829
661: stxa %g2, [%g1] ASI_DMMU
830
.section .sun4v_1insn_patch, "ax"
831
.word 661b
832
stxa %g2, [%g1] ASI_MMU
833
.previous
834
835
membar #Sync
836
837
BRANCH_IF_SUN4V(o2, 1f)
838
839
/* Kill PROM timer */
840
sethi %hi(0x80000000), %o2
841
sllx %o2, 32, %o2
842
wr %o2, 0, %tick_cmpr
843
844
BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
845
846
ba,a,pt %xcc, 2f
847
848
/* Disable STICK_INT interrupts. */
849
1:
850
sethi %hi(0x80000000), %o2
851
sllx %o2, 32, %o2
852
wr %o2, %asr25
853
854
2:
855
wrpr %g0, %g0, %wstate
856
857
call init_irqwork_curcpu
858
nop
859
860
/* Now we can restore interrupt state. */
861
wrpr %l0, 0, %pstate
862
wrpr %l1, 0x0, %pil
863
864
ret
865
restore
866
867
.globl setup_tba
868
setup_tba:
869
save %sp, -192, %sp
870
871
/* The boot processor is the only cpu which invokes this
872
* routine, the other cpus set things up via trampoline.S.
873
* So save the OBP trap table address here.
874
*/
875
rdpr %tba, %g7
876
sethi %hi(prom_tba), %o1
877
or %o1, %lo(prom_tba), %o1
878
stx %g7, [%o1]
879
880
call setup_trap_table
881
nop
882
883
ret
884
restore
885
sparc64_boot_end:
886
887
#include "etrap_64.S"
888
#include "rtrap_64.S"
889
#include "winfixup.S"
890
#include "fpu_traps.S"
891
#include "ivec.S"
892
#include "getsetcc.S"
893
#include "utrap.S"
894
#include "spiterrs.S"
895
#include "cherrs.S"
896
#include "misctrap.S"
897
#include "syscalls.S"
898
#include "helpers.S"
899
#include "sun4v_tlb_miss.S"
900
#include "sun4v_mcd.S"
901
#include "sun4v_ivec.S"
902
#include "ktlb.S"
903
#include "tsb.S"
904
905
/*
906
* The following skip makes sure the trap table in ttable.S is aligned
907
* on a 32K boundary as required by the v9 specs for TBA register.
908
*
909
* We align to a 32K boundary, then we have the 32K kernel TSB,
910
* the 64K kernel 4MB TSB, and then the 32K aligned trap table.
911
*/
912
1:
913
.skip 0x4000 + _start - 1b
914
915
! 0x0000000000408000
916
917
.globl swapper_tsb
918
swapper_tsb:
919
.skip (32 * 1024)
920
921
.globl swapper_4m_tsb
922
swapper_4m_tsb:
923
.skip (64 * 1024)
924
925
! 0x0000000000420000
926
927
/* Some care needs to be exercised if you try to move the
928
* location of the trap table relative to other things. For
929
* one thing there are br* instructions in some of the
930
* trap table entires which branch back to code in ktlb.S
931
* Those instructions can only handle a signed 16-bit
932
* displacement.
933
*
934
* There is a binutils bug (bugzilla #4558) which causes
935
* the relocation overflow checks for such instructions to
936
* not be done correctly. So bintuils will not notice the
937
* error and will instead write junk into the relocation and
938
* you'll have an unbootable kernel.
939
*/
940
#include "ttable_64.S"
941
942
! 0x0000000000428000
943
944
#include "hvcalls.S"
945
#include "systbls_64.S"
946
947
.data
948
.align 8
949
.globl prom_tba, tlb_type
950
prom_tba: .xword 0
951
tlb_type: .word 0 /* Must NOT end up in BSS */
952
EXPORT_SYMBOL(tlb_type)
953
.section ".fixup",#alloc,#execinstr
954
955
ENTRY(__retl_efault)
956
retl
957
mov -EFAULT, %o0
958
ENDPROC(__retl_efault)
959
960
ENTRY(__retl_o1)
961
retl
962
mov %o1, %o0
963
ENDPROC(__retl_o1)
964
965
ENTRY(__retl_o1_asi)
966
wr %o5, 0x0, %asi
967
retl
968
mov %o1, %o0
969
ENDPROC(__retl_o1_asi)
970
971