0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/version.h>
0015 #include <linux/init.h>
0016
0017 #include <asm/head.h>
0018 #include <asm/asi.h>
0019 #include <asm/contregs.h>
0020 #include <asm/ptrace.h>
0021 #include <asm/psr.h>
0022 #include <asm/page.h>
0023 #include <asm/kdebug.h>
0024 #include <asm/winmacro.h>
0025 #include <asm/thread_info.h> /* TI_UWINMASK */
0026 #include <asm/errno.h>
0027 #include <asm/pgtable.h> /* PGDIR_SHIFT */
0028 #include <asm/export.h>
0029
0030 .data
0031
0032
0033
0034 .align 4
0035 .globl cputypval
0036 cputypval:
0037 .asciz "sun4m"
0038 .ascii " "
0039
0040
0041 .align 4
0042 cputypvar:
0043 .asciz "compatible"
0044
0045 .align 4
0046
0047 notsup:
0048 .asciz "Sparc-Linux sun4/sun4c or MMU-less not supported\n\n"
0049 .align 4
0050
0051 sun4e_notsup:
0052 .asciz "Sparc-Linux sun4e support does not exist\n\n"
0053 .align 4
0054
0055
0056 #include "ttable_32.S"
0057
0058 .align PAGE_SIZE
0059
0060
0061
0062
0063 .globl empty_zero_page
0064 empty_zero_page: .skip PAGE_SIZE
0065 EXPORT_SYMBOL(empty_zero_page)
0066
0067 .global root_flags
0068 .global ram_flags
0069 .global root_dev
0070 .global sparc_ramdisk_image
0071 .global sparc_ramdisk_size
0072
0073
0074
0075
0076
0077 .ascii "HdrS"
0078 .word LINUX_VERSION_CODE
0079 .half 0x0203
0080 root_flags:
0081 .half 1
0082 root_dev:
0083 .half 0
0084 ram_flags:
0085 .half 0
0086 sparc_ramdisk_image:
0087 .word 0
0088 sparc_ramdisk_size:
0089 .word 0
0090 .word reboot_command
0091 .word 0, 0, 0
0092 .word _end
0093
0094
0095
0096
0097
0098 gokernel:
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 mov %o7, %g4 ! Save %o7
0111
0112
0113 current_pc:
0114 call 1f
0115 nop
0116
0117 1:
0118 mov %o7, %g3
0119
0120 tst %o0
0121 be no_sun4u_here
0122 mov %g4, %o7
0123
0124 mov %o0, %l0 ! stash away romvec
0125 mov %o0, %g7 ! put it here too
0126 mov %o1, %l1 ! stash away debug_vec too
0127
0128
0129 set current_pc, %g5
0130 cmp %g3, %g5
0131 be already_mapped
0132 nop
0133
0134
0135
0136
0137
0138
0139 set KERNBASE, %l6
0140 b copy_prom_lvl14
0141 nop
0142
0143 already_mapped:
0144 mov 0, %l6
0145
0146
0147 copy_prom_lvl14:
0148 #if 1
0149
0150
0151
0152 set lvl14_save, %g1
0153 set t_irq14, %g3
0154 sub %g1, %l6, %g1 ! translate to physical
0155 sub %g3, %l6, %g3 ! translate to physical
0156 ldd [%g3], %g4
0157 std %g4, [%g1]
0158 ldd [%g3+8], %g4
0159 std %g4, [%g1+8]
0160 #endif
0161 rd %tbr, %g1
0162 andn %g1, 0xfff, %g1 ! proms trap table base
0163 or %g0, (0x1e<<4), %g2 ! offset to lvl14 intr
0164 or %g1, %g2, %g2
0165 set t_irq14, %g3
0166 sub %g3, %l6, %g3
0167 ldd [%g2], %g4
0168 std %g4, [%g3]
0169 ldd [%g2 + 0x8], %g4
0170 std %g4, [%g3 + 0x8] ! Copy proms handler
0171
0172
0173
0174
0175
0176
0177
0178
0179 copy_prom_done:
0180 cmp %l6, 0
0181 be go_to_highmem ! this will be a nop then
0182 nop
0183
0184
0185
0186
0187 set 0x4000, %g6
0188 cmp %g7, %g6
0189 bne not_a_sun4
0190 nop
0191
0192 halt_notsup:
0193 ld [%g7 + 0x68], %o1
0194 set notsup, %o0
0195 sub %o0, %l6, %o0
0196 call %o1
0197 nop
0198 ba halt_me
0199 nop
0200
0201 not_a_sun4:
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211 rd %psr, %g3
0212 srl %g3, PSR_IMPL_SHIFT, %g3
0213 and %g3, PSR_IMPL_SHIFTED_MASK, %g3
0214 cmp %g3, PSR_IMPL_LEON
0215 be leon_remap
0216 nop
0217
0218
0219 lda [%g0] ASI_M_MMUREGS, %g1
0220 andcc %g1, 1, %g0
0221 be halt_notsup
0222 nop
0223
0224
0225 cmp %g3, PSR_IMPL_TI
0226 bne srmmu_not_viking
0227 nop
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237 set 0x800, %g2
0238 lda [%g0] ASI_M_MMUREGS, %g3 ! peek in the control reg
0239 and %g2, %g3, %g3
0240 subcc %g3, 0x0, %g0
0241 bnz srmmu_not_viking ! is in mbus mode
0242 nop
0243
0244 rd %psr, %g3 ! DO NOT TOUCH %g3
0245 andn %g3, PSR_ET, %g2
0246 wr %g2, 0x0, %psr
0247 WRITE_PAUSE
0248
0249
0250
0251
0252 set AC_M_CTPR, %g4
0253 lda [%g4] ASI_M_MMUREGS, %g4
0254 sll %g4, 0x4, %g4 ! We use this below
0255 ! DO NOT TOUCH %g4
0256
0257
0258 lda [%g0] ASI_M_MMUREGS, %g5 ! DO NOT TOUCH %g5
0259 set 0x8000, %g6 ! AC bit mask
0260 or %g5, %g6, %g6 ! Or it in...
0261 sta %g6, [%g0] ASI_M_MMUREGS ! Close your eyes...
0262
0263
0264
0265
0266
0267
0268 lda [%g4] ASI_M_BYPASS, %o1 ! This is a level 1 ptr
0269 srl %o1, 0x4, %o1 ! Clear low 4 bits
0270 sll %o1, 0x8, %o1 ! Make physical
0271
0272
0273 lda [%o1] ASI_M_BYPASS, %o2 ! This is the 0x0 16MB pgd
0274
0275
0276 add %o1, KERNBASE >> (PGDIR_SHIFT - 2), %o3
0277
0278
0279 sta %o2, [%o3] ASI_M_BYPASS
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292 sta %g5, [%g0] ASI_M_MMUREGS ! POW... ouch
0293
0294
0295 wr %g3, 0x0, %psr ! tick tock, tick tock
0296
0297
0298 WRITE_PAUSE
0299
0300
0301
0302
0303 b go_to_highmem
0304 nop
0305
0306 srmmu_not_viking:
0307
0308
0309
0310
0311
0312 set AC_M_CTPR, %g1
0313 lda [%g1] ASI_M_MMUREGS, %g1 ! get ctx table ptr
0314 sll %g1, 0x4, %g1 ! make physical addr
0315 lda [%g1] ASI_M_BYPASS, %g1 ! ptr to level 1 pg_table
0316 srl %g1, 0x4, %g1
0317 sll %g1, 0x8, %g1 ! make phys addr for l1 tbl
0318
0319 lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0
0320 add %g1, KERNBASE >> (PGDIR_SHIFT - 2), %g3
0321 sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry
0322 b go_to_highmem
0323 nop ! wheee....
0324
0325
0326 leon_remap:
0327
0328 lda [%g0] ASI_LEON_MMUREGS, %g1
0329 andcc %g1, 1, %g0
0330 be halt_notsup
0331 nop
0332
0333
0334
0335
0336 set AC_M_CTPR, %g1
0337 lda [%g1] ASI_LEON_MMUREGS, %g1 ! get ctx table ptr
0338 sll %g1, 0x4, %g1 ! make physical addr
0339 lda [%g1] ASI_M_BYPASS, %g1 ! ptr to level 1 pg_table
0340 srl %g1, 0x4, %g1
0341 sll %g1, 0x8, %g1 ! make phys addr for l1 tbl
0342
0343 lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0
0344 add %g1, KERNBASE >> (PGDIR_SHIFT - 2), %g3
0345 sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry
0346 b go_to_highmem
0347 nop ! wheee....
0348
0349
0350 go_to_highmem:
0351 set execute_in_high_mem, %g1
0352 jmpl %g1, %g0
0353 nop
0354
0355
0356
0357
0358 __INIT
0359
0360
0361
0362 execute_in_high_mem:
0363 mov %l0, %o0 ! put back romvec
0364 mov %l1, %o1 ! and debug_vec
0365
0366 sethi %hi(prom_vector_p), %g1
0367 st %o0, [%g1 + %lo(prom_vector_p)]
0368
0369 sethi %hi(linux_dbvec), %g1
0370 st %o1, [%g1 + %lo(linux_dbvec)]
0371
0372
0373
0374
0375 add %g7, 0x1c, %l1
0376 ld [%l1], %l0
0377 ld [%l0], %l0
0378 call %l0
0379 or %g0, %g0, %o0 ! next_node(0) = first_node
0380 or %o0, %g0, %g6
0381
0382 sethi %hi(cputypvar), %o1 ! First node has cpu-arch
0383 or %o1, %lo(cputypvar), %o1
0384 sethi %hi(cputypval), %o2 ! information, the string
0385 or %o2, %lo(cputypval), %o2
0386 ld [%l1], %l0 ! 'compatible' tells
0387 ld [%l0 + 0xc], %l0 ! that we want 'sun4x' where
0388 call %l0 ! x is one of 'm', 'd' or 'e'.
0389 nop ! %o2 holds pointer
0390 ! to a buf where above string
0391 ! will get stored by the prom.
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405 set cputypval, %o2
0406
0407 ldub [%o2], %l1
0408 cmp %l1, 'l'
0409 be leon_init
0410 nop
0411
0412
0413 ldub [%o2 + 0x4], %l1
0414
0415 cmp %l1, 'm'
0416 be sun4m_init
0417 cmp %l1, 's'
0418 be sun4m_init
0419 cmp %l1, 'd'
0420 be sun4d_init
0421 cmp %l1, 'e'
0422 be no_sun4e_here ! Could be a sun4e.
0423 nop
0424 b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :))
0425 nop
0426
0427 leon_init:
0428
0429 sethi %hi(boot_cpu_id), %g2 ! boot-cpu index
0430
0431 #ifdef CONFIG_SMP
0432 ldub [%g2 + %lo(boot_cpu_id)], %g1
0433 cmp %g1, 0xff ! unset means first CPU
0434 bne leon_smp_cpu_startup ! continue only with master
0435 nop
0436 #endif
0437
0438 rd %asr17, %g1
0439 srl %g1, 28, %g1
0440
0441
0442 stub %g1, [%g2 + %lo(boot_cpu_id)]
0443
0444 ba continue_boot
0445 nop
0446
0447
0448 #define SUN4D_BOOTBUS_CPUID 0xf0140000
0449
0450 sun4d_init:
0451
0452 set patch_handler_irq, %g4
0453 set sun4d_handler_irq, %g5
0454 sethi %hi(0x40000000), %g3 ! call
0455 sub %g5, %g4, %g5
0456 srl %g5, 2, %g5
0457 or %g5, %g3, %g5
0458 st %g5, [%g4]
0459
0460 #ifdef CONFIG_SMP
0461
0462 set SUN4D_BOOTBUS_CPUID, %g3
0463 lduba [%g3] ASI_M_CTL, %g3
0464 and %g3, 0xf8, %g3
0465 srl %g3, 3, %g4
0466 sta %g4, [%g0] ASI_M_VIKING_TMP1
0467 sethi %hi(boot_cpu_id), %g5
0468 stb %g4, [%g5 + %lo(boot_cpu_id)]
0469 #endif
0470
0471
0472
0473 sun4m_init:
0474
0475
0476
0477
0478
0479 2:
0480 rd %psr, %o1
0481 srl %o1, PSR_IMPL_SHIFT, %o1 ! Get a type of the CPU
0482
0483 subcc %o1, PSR_IMPL_TI, %g0 ! TI: Viking or MicroSPARC
0484 be continue_boot
0485 nop
0486
0487 set AC_M_SFSR, %o0
0488 lda [%o0] ASI_M_MMUREGS, %g0
0489 set AC_M_SFAR, %o0
0490 lda [%o0] ASI_M_MMUREGS, %g0
0491
0492
0493 subcc %o1, 0, %g0
0494 be continue_boot
0495 nop
0496
0497 set AC_M_AFSR, %o0
0498 lda [%o0] ASI_M_MMUREGS, %g0
0499 set AC_M_AFAR, %o0
0500 lda [%o0] ASI_M_MMUREGS, %g0
0501 nop
0502
0503
0504 continue_boot:
0505
0506
0507
0508
0509
0510
0511
0512 set (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
0513 wr %g2, 0x0, %psr
0514 WRITE_PAUSE
0515
0516
0517 set init_thread_union, %g1
0518 set (THREAD_SIZE - STACKFRAME_SZ - TRACEREG_SZ), %g2
0519 add %g1, %g2, %sp
0520 mov 0, %fp
0521
0522
0523 set __bss_start , %o0 ! First address of BSS
0524 set _end , %o1 ! Last address of BSS
0525 add %o0, 0x1, %o0
0526 1:
0527 stb %g0, [%o0]
0528 subcc %o0, %o1, %g0
0529 bl 1b
0530 add %o0, 0x1, %o0
0531
0532
0533
0534
0535 sethi %hi(boot_cpu_id), %g2
0536 ldub [%g2 + %lo(boot_cpu_id)], %g3
0537 cmp %g3, 0xff
0538 bne 1f
0539 nop
0540 mov %g0, %g3
0541 stub %g3, [%g2 + %lo(boot_cpu_id)]
0542
0543 1: sll %g3, 2, %g3
0544
0545
0546
0547
0548 set init_thread_union, %g6
0549 set current_set, %g2
0550 #ifdef CONFIG_SMP
0551 st %g6, [%g2]
0552 add %g2, %g3, %g2
0553 #endif
0554 st %g6, [%g2]
0555
0556 st %g0, [%g6 + TI_UWINMASK]
0557
0558
0559
0560
0561
0562
0563 wr %g0, 0x0, %wim ! so we do not get a trap
0564 WRITE_PAUSE
0565
0566 save
0567
0568 rd %psr, %g3
0569
0570 restore
0571
0572 and %g3, 0x1f, %g3
0573 add %g3, 0x1, %g3
0574
0575 mov 2, %g1
0576 wr %g1, 0x0, %wim ! make window 1 invalid
0577 WRITE_PAUSE
0578
0579 cmp %g3, 0x7
0580 bne 2f
0581 nop
0582
0583
0584
0585
0586
0587 #define PATCH_INSN(src, dest) \
0588 set src, %g5; \
0589 set dest, %g2; \
0590 ld [%g5], %g4; \
0591 st %g4, [%g2];
0592
0593
0594 PATCH_INSN(spnwin_patch1_7win, spnwin_patch1)
0595 PATCH_INSN(spnwin_patch2_7win, spnwin_patch2)
0596 PATCH_INSN(spnwin_patch3_7win, spnwin_patch3)
0597
0598
0599 PATCH_INSN(fnwin_patch1_7win, fnwin_patch1)
0600 PATCH_INSN(fnwin_patch2_7win, fnwin_patch2)
0601
0602
0603 PATCH_INSN(tsetup_7win_patch1, tsetup_patch1)
0604 PATCH_INSN(tsetup_7win_patch2, tsetup_patch2)
0605 PATCH_INSN(tsetup_7win_patch3, tsetup_patch3)
0606 PATCH_INSN(tsetup_7win_patch4, tsetup_patch4)
0607 PATCH_INSN(tsetup_7win_patch5, tsetup_patch5)
0608 PATCH_INSN(tsetup_7win_patch6, tsetup_patch6)
0609
0610
0611 PATCH_INSN(rtrap_7win_patch1, rtrap_patch1)
0612 PATCH_INSN(rtrap_7win_patch2, rtrap_patch2)
0613 PATCH_INSN(rtrap_7win_patch3, rtrap_patch3)
0614 PATCH_INSN(rtrap_7win_patch4, rtrap_patch4)
0615 PATCH_INSN(rtrap_7win_patch5, rtrap_patch5)
0616
0617
0618 PATCH_INSN(kuw_patch1_7win, kuw_patch1)
0619
0620
0621
0622
0623 set 0x01000000, %g4
0624 set flush_patch_one, %g5
0625 st %g4, [%g5 + 0x18]
0626 st %g4, [%g5 + 0x1c]
0627 set flush_patch_two, %g5
0628 st %g4, [%g5 + 0x18]
0629 st %g4, [%g5 + 0x1c]
0630 set flush_patch_three, %g5
0631 st %g4, [%g5 + 0x18]
0632 st %g4, [%g5 + 0x1c]
0633 set flush_patch_four, %g5
0634 st %g4, [%g5 + 0x18]
0635 st %g4, [%g5 + 0x1c]
0636 set flush_patch_exception, %g5
0637 st %g4, [%g5 + 0x18]
0638 st %g4, [%g5 + 0x1c]
0639 set flush_patch_switch, %g5
0640 st %g4, [%g5 + 0x18]
0641 st %g4, [%g5 + 0x1c]
0642
0643 2:
0644 sethi %hi(nwindows), %g4
0645 st %g3, [%g4 + %lo(nwindows)] ! store final value
0646 sub %g3, 0x1, %g3
0647 sethi %hi(nwindowsm1), %g4
0648 st %g3, [%g4 + %lo(nwindowsm1)]
0649
0650
0651 set trapbase, %g3
0652 wr %g3, 0x0, %tbr
0653 WRITE_PAUSE
0654
0655
0656 rd %psr, %g3
0657 wr %g3, 0x0, %psr
0658 WRITE_PAUSE
0659
0660 wr %g3, PSR_ET, %psr
0661 WRITE_PAUSE
0662
0663
0664 sethi %hi(prom_vector_p), %g5
0665 ld [%g5 + %lo(prom_vector_p)], %o0
0666 call sparc32_start_kernel
0667 nop
0668
0669
0670 call halt_me
0671 nop
0672
0673 no_sun4e_here:
0674 ld [%g7 + 0x68], %o1
0675 set sun4e_notsup, %o0
0676 call %o1
0677 nop
0678 b halt_me
0679 nop
0680
0681 __INITDATA
0682
0683 sun4u_1:
0684 .asciz "finddevice"
0685 .align 4
0686 sun4u_2:
0687 .asciz "/chosen"
0688 .align 4
0689 sun4u_3:
0690 .asciz "getprop"
0691 .align 4
0692 sun4u_4:
0693 .asciz "stdout"
0694 .align 4
0695 sun4u_5:
0696 .asciz "write"
0697 .align 4
0698 sun4u_6:
0699 .asciz "\n\rOn sun4u you have to use sparc64 kernel\n\rand not a sparc32 version\n\r\n\r"
0700 sun4u_6e:
0701 .align 4
0702 sun4u_7:
0703 .asciz "exit"
0704 .align 8
0705 sun4u_a1:
0706 .word 0, sun4u_1, 0, 1, 0, 1, 0, sun4u_2, 0
0707 sun4u_r1:
0708 .word 0
0709 sun4u_a2:
0710 .word 0, sun4u_3, 0, 4, 0, 1, 0
0711 sun4u_i2:
0712 .word 0, 0, sun4u_4, 0, sun4u_1, 0, 8, 0
0713 sun4u_r2:
0714 .word 0
0715 sun4u_a3:
0716 .word 0, sun4u_5, 0, 3, 0, 1, 0
0717 sun4u_i3:
0718 .word 0, 0, sun4u_6, 0, sun4u_6e - sun4u_6 - 1, 0
0719 sun4u_r3:
0720 .word 0
0721 sun4u_a4:
0722 .word 0, sun4u_7, 0, 0, 0, 0
0723 sun4u_r4:
0724
0725 __INIT
0726 no_sun4u_here:
0727 set sun4u_a1, %o0
0728 set current_pc, %l2
0729 cmp %l2, %g3
0730 be 1f
0731 mov %o4, %l0
0732 sub %g3, %l2, %l6
0733 add %o0, %l6, %o0
0734 mov %o0, %l4
0735 mov sun4u_r4 - sun4u_a1, %l3
0736 ld [%l4], %l5
0737 2:
0738 add %l4, 4, %l4
0739 cmp %l5, %l2
0740 add %l5, %l6, %l5
0741 bgeu,a 3f
0742 st %l5, [%l4 - 4]
0743 3:
0744 subcc %l3, 4, %l3
0745 bne 2b
0746 ld [%l4], %l5
0747 1:
0748 call %l0
0749 mov %o0, %l1
0750
0751 ld [%l1 + (sun4u_r1 - sun4u_a1)], %o1
0752 add %l1, (sun4u_a2 - sun4u_a1), %o0
0753 call %l0
0754 st %o1, [%o0 + (sun4u_i2 - sun4u_a2)]
0755
0756 ld [%l1 + (sun4u_1 - sun4u_a1)], %o1
0757 add %l1, (sun4u_a3 - sun4u_a1), %o0
0758 call %l0
0759 st %o1, [%o0 + (sun4u_i3 - sun4u_a3)]
0760
0761 call %l0
0762 add %l1, (sun4u_a4 - sun4u_a1), %o0
0763
0764
0765 halt_me:
0766 ld [%g7 + 0x74], %o0
0767 call %o0 ! Get us out of here...
0768 nop ! Apparently Solaris is better.
0769
0770
0771
0772 .data
0773 .align 4
0774
0775
0776
0777
0778
0779
0780
0781 prom_vector_p:
0782 .word 0
0783
0784
0785
0786
0787
0788 .align 4
0789 .globl nwindows
0790 .globl nwindowsm1
0791 nwindows:
0792 .word 8
0793 nwindowsm1:
0794 .word 7
0795
0796
0797
0798 .align 4
0799 .globl linux_dbvec
0800 linux_dbvec:
0801 .word 0
0802 .word 0
0803
0804 .align 8
0805
0806 .globl lvl14_save
0807 lvl14_save:
0808 .word 0
0809 .word 0
0810 .word 0
0811 .word 0
0812 .word t_irq14