- Add IMB to the palcode in start.inc - Reduce the heap to only 128K in alpha/ldscript.base - In elfboot add checks to make certain we don't overwrite linuxBIOS...
488 lines
14 KiB
C++
488 lines
14 KiB
C++
#include <arch/cpu.h>
|
|
#include <arch/pal.h>
|
|
#include <arch/asm.h>
|
|
.set noat
|
|
.set noreorder
|
|
.text
|
|
|
|
#define PAL_EXCEPT(label,location) . = location ; label:
|
|
#define PAL_EXCEPT_DUMMY(location) . = location ; mb ; mb ; mb; hw_mfpr p7, EV6__EXC_ADDR ; bsr p0, __fatal_error_pal; mb ; mb ; mb
|
|
#define PAL_CALL_DUMMY(location) . = location ; mb ; mb ; mb ; mb ; bsr p0, __fatal_error_pal ; mb ; mb ; mb
|
|
|
|
#define va_48 0
|
|
#define mchk_en 1
|
|
#define tb_mb_en 0
|
|
|
|
#define EV6__I_STAT__W1C ((1 << EV6__I_STAT__TPE__S) | (1 << EV6__I_STAT__DPE__S))
|
|
#define EV6__DC_STAT__W1C ( \
|
|
(1 << EV6__DC_STAT__TPERR_P0__S) | \
|
|
(1 << EV6__DC_STAT__TPERR_P1__S) | \
|
|
(1 << EV6__DC_STAT__ECC_ERR_ST__S) | \
|
|
(1 << EV6__DC_STAT__ECC_ERR_LD__S) | \
|
|
(1 << EV6__DC_STAT__SEO__S))
|
|
|
|
#define EV6__I_CTL__INIT (\
|
|
(3 << EV6__I_CTL__IC_EN__S) | \
|
|
(2 << (EV6__I_CTL__SPE__S + va_48)) | \
|
|
(2 << EV6__I_CTL__SDE__S) | \
|
|
(3 << EV6__I_CTL__SBE__S) | \
|
|
(va_48 << EV6__I_CTL__VA_48__S) | \
|
|
(1 << EV6__I_CTL__CALL_PAL_R23__S) | \
|
|
(mchk_en << EV6__I_CTL__MCHK_EN__S) | \
|
|
(tb_mb_en << EV6__I_CTL__TB_MB_EN__S))
|
|
|
|
#define EV6__PCTX__INIT (1 << EV6__PCTX__FPE__S)
|
|
|
|
#define EV6__M_CTL__INIT (2 << (EV6__M_CTL__SPE__S+va_48))
|
|
|
|
#define EV6__IER__INIT 0
|
|
|
|
#define EV6__HW_INT_CLR__INIT ( \
|
|
(1 << (EV6__HW_INT_CLR__MCHK_D__S - EV6__HW_INT_CLR__MCHK_D__S)) | \
|
|
(3 << (EV6__HW_INT_CLR__PC__S - EV6__HW_INT_CLR__MCHK_D__S)) | \
|
|
(1 << (EV6__HW_INT_CLR__CR__S - EV6__HW_INT_CLR__MCHK_D__S)) | \
|
|
(1 << (EV6__HW_INT_CLR__SL__S - EV6__HW_INT_CLR__MCHK_D__S)))
|
|
|
|
#define EV6__VA_CTL__INIT (va_48 << EV6__VA_CTL__VA_48__S)
|
|
|
|
EntryPoint:
|
|
/* On startup
|
|
* R19 - Signature (0xDEC?????) likely (0xDECB001)
|
|
* R23 - Memory size in bytes.
|
|
* r22 - CPU speed in picoseconds.
|
|
* R25 - Chip revision.
|
|
* excAddr - Address of ICache flush code to execute in PALmode.
|
|
*/
|
|
|
|
/* Palcode switching entry point */
|
|
mb
|
|
bis a3, a3, a0 /* Signature */
|
|
bis t9, t9, a1 /* Memory size in bytes */
|
|
bis t8, t8, a2 /* CPU speed in picoseconds */
|
|
br zero, pal_mode_start
|
|
mb
|
|
mb
|
|
mb
|
|
|
|
PAL_EXCEPT_DUMMY(EV6__DTBM_DOUBLE_3_ENTRY)
|
|
PAL_EXCEPT_DUMMY(EV6__DTBM_DOUBLE_4_ENTRY)
|
|
PAL_EXCEPT_DUMMY(EV6__FEN_ENTRY)
|
|
PAL_EXCEPT_DUMMY(EV6__UNALIGN_ENTRY)
|
|
|
|
/* DTBM */
|
|
PAL_EXCEPT(DTBM_SINGLE, EV6__DTBM_SINGLE_ENTRY)
|
|
hw_mfpr p7, EV6__EXC_ADDR /* (0L,1) get exception address */
|
|
hw_mfpr p2, EV6__VA /* (4-7,1L,3) get original va */
|
|
|
|
lda p1, 0x3301(zero) /* all r/w enable */
|
|
srl p2, 13, p0 /* shift out the byte offset */
|
|
sll p0, EV6__DTB_PTE0__PFN__S, p0 /* get pfn into position */
|
|
bis p0, p1, p0 /* produce the pte */
|
|
|
|
FETCH_BLOCK_ALIGN
|
|
hw_mtpr p2, EV6__DTB_TAG0 /* (2&6,0L) write tag0 */
|
|
hw_mtpr p2, EV6__DTB_TAG1 /* (1&5,1L) write tag1 */
|
|
hw_mtpr p0, EV6__DTB_PTE0 /* (0,4,2,6) (0L) write pte0 */
|
|
hw_mtpr p0, EV6__DTB_PTE1 /* (3,7,1,5) (1L) write pte1 */
|
|
|
|
hw_mtpr zero, EV6__MM_STAT /* (4-7,0L) start outside IQ */
|
|
FETCH_BLOCK_ALIGN
|
|
hw_ret (p7) /* return with jmp */
|
|
br zero, .-4 /* stop predictor */
|
|
|
|
PAL_EXCEPT_DUMMY(EV6__DFAULT_ENTRY)
|
|
PAL_EXCEPT_DUMMY(EV6__OPCDEC_ENTRY)
|
|
PAL_EXCEPT_DUMMY(EV6__IACV_ENTRY)
|
|
PAL_EXCEPT_DUMMY(EV6__MCHK_ENTRY)
|
|
|
|
/* *ITBM* */
|
|
PAL_EXCEPT(ITB_MISS, EV6__ITB_MISS_ENTRY)
|
|
hw_mfpr p7, EV6__EXC_ADDR /* (0L,1) get exception address */
|
|
srl p7, 13, p2 /* shift out the byte offset */
|
|
lda p1, 0x301(zero) /* all read enable */
|
|
sll p2, EV6__ITB_PTE__PFN__S, p2 /* get pfn into position */
|
|
bis p2, p1, p2 /* produce the pte */
|
|
|
|
FETCH_BLOCK_ALIGN
|
|
hw_mtpr p7, EV6__ITB_TAG /* (2&6,0L) write tag0 */
|
|
hw_mtpr p2, EV6__ITB_PTE /* (0&4,0L) write pte0 */
|
|
FETCH_BLOCK_ALIGN
|
|
hw_ret/stall (p7) /* (0L) return */
|
|
br zero, .-4
|
|
|
|
PAL_EXCEPT_DUMMY(EV6__ARITH_ENTRY)
|
|
PAL_EXCEPT_DUMMY(EV6__INTERRUPT_ENTRY)
|
|
PAL_EXCEPT_DUMMY(EV6__MT_FPCR_ENTRY)
|
|
PAL_EXCEPT_DUMMY(EV6__RESET_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_00_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_01_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_02_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_03_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_04_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_05_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_06_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_07_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_08_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_09_ENTRY)
|
|
|
|
#if 0
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_0A_ENTRY)
|
|
#else
|
|
/* swppal */
|
|
PAL_EXCEPT(SWPPAL, EV6__CALL_PAL_0A_ENTRY)
|
|
#define OSF_P_MISC__SWITCH__S 62
|
|
/* new pal base is in a0 */
|
|
bis a0, a0, p1 /* base in p1 */
|
|
lda p0, 0x7fff(zero) /* check for pal base */
|
|
and p1, p0, p0 /* get low 15 bits */
|
|
cmpeq p0, 0, v0 /* check for non-zero bits */
|
|
|
|
blbc v0, call_pal__swppal_fail /* if not clear say unknown */
|
|
|
|
bis zero, 1, p0 /* get a '1' */
|
|
sll p0, OSF_P_MISC__SWITCH__S, p0 /* switch bit into position */
|
|
bis zero, p0, p6 /* mark switch */
|
|
|
|
bis zero, zero, v0 /* status success */
|
|
bis p1, 1, p1 /* set pal mode bit */
|
|
hw_ret (p1) /* go to it */
|
|
bis zero, zero, zero /* nop */
|
|
|
|
call_pal__swppal_fail:
|
|
bis zero, 1, v0 /* failure */
|
|
hw_ret (p7)
|
|
bis zero, zero, zero /* nop */
|
|
bis zero, zero, zero /* nop */
|
|
#endif
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_0B_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_0C_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_0D_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_0E_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_0F_ENTRY)
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_10_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_11_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_12_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_13_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_14_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_15_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_16_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_17_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_18_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_19_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_1A_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_1B_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_1C_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_1D_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_1E_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_1F_ENTRY)
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_20_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_21_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_22_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_23_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_24_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_25_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_26_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_27_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_28_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_29_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_2A_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_2B_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_2C_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_2D_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_2E_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_2F_ENTRY)
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_30_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_31_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_32_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_33_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_34_ENTRY)
|
|
|
|
#if 0
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_35_ENTRY)
|
|
#else
|
|
/* swpipl */
|
|
PAL_EXCEPT(SWPIPL, EV6__CALL_PAL_35_ENTRY)
|
|
/* Fake the swpipl call just return the maximum ipl
|
|
* I'm not going to enable interrupts anyway.
|
|
*/
|
|
bis zero, 7, v0
|
|
hw_ret/stall(p7)
|
|
#endif
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_36_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_37_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_38_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_39_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_3A_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_3B_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_3C_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_3D_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_3E_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_3F_ENTRY)
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_80_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_81_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_82_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_83_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_84_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_85_ENTRY)
|
|
|
|
#if 0
|
|
/* PAL_CALL_DUMMY(EV6__CALL_PAL_86_ENTRY) */
|
|
#else
|
|
/* imb */
|
|
PAL_EXCEPT(IMB, EV6__CALL_PAL_86_ENTRY)
|
|
mb
|
|
bis zero, zero, zero /* nop */
|
|
bis zero, zero, zero /* nop */
|
|
bis zero, zero, zero /* nop */
|
|
|
|
hw_mtpr zero, EV6__IC_FLUSH /* (4,0L) flush the icache
|
|
bne zero, . /* pvc #24 */
|
|
hw_ret/stall(p7) /* return with stall */
|
|
#endif
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_87_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_88_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_89_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_8A_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_8B_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_8C_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_8D_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_8E_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_8F_ENTRY)
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_90_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_91_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_92_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_93_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_94_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_95_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_96_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_97_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_98_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_99_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_9A_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_9B_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_9C_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_9D_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_9E_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_9F_ENTRY)
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A0_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A1_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A2_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A3_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A4_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A5_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A6_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A7_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A8_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_A9_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_AA_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_AB_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_AC_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_AD_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_AE_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_AF_ENTRY)
|
|
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B0_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B1_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B2_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B3_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B4_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B5_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B6_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B7_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B8_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_B9_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_BA_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_BB_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_BC_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_BD_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_BE_ENTRY)
|
|
PAL_CALL_DUMMY(EV6__CALL_PAL_BF_ENTRY)
|
|
|
|
PAL_EXCEPT(dummy, EV6__CALL_PAL_BF_ENTRY + 0x80)
|
|
|
|
/* Data for pal_mode_start
|
|
* I can't use the magic linker gp magic here so roll my own.
|
|
* Note: The linker script ensures that EntryPoint _edata & _end
|
|
* are all 8 byte aligned.
|
|
*/
|
|
EntryPoint_addr:
|
|
.quad EntryPoint
|
|
_edata_addr:
|
|
.quad _edata
|
|
_end_addr:
|
|
.quad _end
|
|
kernel_mode_start_addr:
|
|
.quad kernel_mode_start
|
|
__fatal_error_non_pal_addr:
|
|
.quad __fatal_error_non_pal
|
|
|
|
pal_mode_start:
|
|
/* relocate to address zero */
|
|
/* The following move routine is not totally
|
|
* general. In particular it does not handle
|
|
* overlapping memory locations or moving to a higher
|
|
* address in memory.
|
|
*/
|
|
br pv, relocate
|
|
relocate:
|
|
lda t0,(EntryPoint - relocate)(pv)
|
|
ldq_p t1,(EntryPoint_addr - relocate)(pv)
|
|
ldq_p t2,(_edata_addr - relocate)(pv)
|
|
subq t2, t1, t2
|
|
br Mstart
|
|
|
|
/* Move the program */
|
|
Move: ldq_p t3, 0(t0)
|
|
subq t2, 8, t2
|
|
addq t0, 8, t0
|
|
stq_p t3, 0(t1)
|
|
addq t1, 8, t1
|
|
Mstart: bne t2, Move
|
|
|
|
/* set up pal_base register */
|
|
FETCH_BLOCK_ALIGN
|
|
ldq_p t0, (EntryPoint_addr - relocate)(pv)
|
|
hw_mtpr t0, EV6__PAL_BASE
|
|
|
|
/* flush ITB & DTB */
|
|
FETCH_BLOCK_ALIGN
|
|
hw_mtpr zero, EV6__ITB_IA
|
|
hw_mtpr zero, EV6__DTB_IA
|
|
|
|
/* flush I_CACHE */
|
|
FETCH_BLOCK_ALIGN
|
|
hw_mtpr zero, EV6__IC_FLUSH
|
|
|
|
/* clear i_stat & dc_stat */
|
|
LOAD_CONSTANT32(t0, EV6__I_STAT__W1C)
|
|
LOAD_CONSTANT16(t2, EV6__DC_STAT__W1C)
|
|
FETCH_BLOCK_ALIGN
|
|
hw_mtpr t0, EV6__I_STAT
|
|
hw_mtpr t2, EV6__DC_STAT
|
|
|
|
/* Initialize I_CTL */
|
|
LOAD_CONSTANT32(t0, EV6__I_CTL__INIT)
|
|
FETCH_BLOCK_ALIGN
|
|
hw_mtpr t0, EV6__I_CTL
|
|
|
|
/* Initialize pctx & m_ctl */
|
|
FETCH_BLOCK_ALIGN
|
|
LOAD_CONSTANT16(t0, EV6__PCTX__INIT)
|
|
LOAD_CONSTANT16(t2, EV6__M_CTL__INIT)
|
|
hw_mtpr t0, EV6__PCTX
|
|
hw_mtpr t2, EV6__M_CTL
|
|
|
|
/* Initialize ier_cm */
|
|
LOAD_CONSTANT32(t0, EV6__IER__INIT)
|
|
hw_mtpr t0, EV6__IER_CM
|
|
hw_mtpr zero, EV6__CC
|
|
|
|
/* Initialize SIRR */
|
|
bis zero, 1, t0
|
|
sll t0, 32, t0
|
|
hw_mtpr zero, EV6__SIRR
|
|
hw_mtpr $1, EV6__CC_CTL
|
|
|
|
/* Initialize int_clr */
|
|
LOAD_CONSTANT16(t0, EV6__HW_INT_CLR__INIT)
|
|
sll t0, EV6__HW_INT_CLR__MCHK_D__S, t0
|
|
hw_mtpr t0, EV6__HW_INT_CLR
|
|
hw_mtpr zero, EV6__DTB_ALT_MODE
|
|
|
|
/* set pctr_ctl & va_ctl */
|
|
hw_mtpr zero, EV6__PCTR_CTL
|
|
LOAD_CONSTANT16(t0, EV6__VA_CTL__INIT)
|
|
hw_mtpr t0, EV6__VA_CTL
|
|
FETCH_BLOCK_ALIGN
|
|
|
|
/* Clear the asn */
|
|
hw_mtpr zero, EV6__DTB_ASN0
|
|
hw_mtpr zero, EV6__DTB_ASN1
|
|
FETCH_BLOCK_ALIGN
|
|
|
|
/* write pctrl_ctl again to clear the 2nd stage overflow flag.
|
|
* and force other mtpr to retwir while we are at it.
|
|
*/
|
|
hw_mtpr zero, EV6__PCTR_CTL | 0xF0
|
|
FETCH_BLOCK_ALIGN
|
|
|
|
/* We need to write HW_INT_CLR to avoid a interrup that can occur
|
|
* the counters come up in an unpredictable state near overflow.
|
|
*/
|
|
|
|
lda t0, 3(zero)
|
|
sll t0, EV6__HW_INT_CLR__PC__S, t0
|
|
hw_mtpr t0, EV6__HW_INT_CLR
|
|
FETCH_BLOCK_ALIGN
|
|
hw_mtpr t0, EV6__HW_INT_CLR
|
|
FETCH_BLOCK_ALIGN
|
|
|
|
/* Clear the fpcr */
|
|
mt_fpcr $f31
|
|
|
|
#if 0
|
|
/* Setup 48 bit address space */
|
|
FETCH_BLOCK_ALIGN
|
|
bis zero, 2, t0
|
|
hw_mtpr t0, EV6__VA_CTL
|
|
bis zero, 8, t0
|
|
hw_mtpr t0, EV6__M_CTL
|
|
#else
|
|
/* Setup 40 bit address space */
|
|
FETCH_BLOCK_ALIGN
|
|
bis zero, 0, t0
|
|
hw_mtpr t0, EV6__VA_CTL
|
|
bis zero, 4, t0
|
|
hw_mtpr t0, EV6__M_CTL
|
|
#endif
|
|
|
|
FETCH_BLOCK_ALIGN
|
|
/* Enable special pal instructions in kernel mode */
|
|
hw_mfpr t0, EV6__I_CTL
|
|
lda t1, 1(zero)
|
|
sll t1, EV6__I_CTL__HWE__S, t1
|
|
bis t0, t1, t0
|
|
hw_mtpr t0, EV6__I_CTL
|
|
|
|
/* Now get out of palmode */
|
|
FETCH_BLOCK_ALIGN
|
|
ldq_p pv, (kernel_mode_start_addr - relocate)(pv)
|
|
hw_jmp (pv)
|
|
|
|
GLOBL(start)
|
|
br pv, __start
|
|
__start:
|
|
/* Some dummy parameters for debugging */
|
|
bis zero, zero, t8 /* CPU speed in picoseconds */
|
|
lda t9, 128*1024*1024 /* Memory size in bytes 128MB */
|
|
bis zero, zero, t11 /* Chip revision */
|
|
|
|
lda a0, (EntryPoint - __start)(pv)
|
|
call_pal PAL_swppal
|
|
br zero, .-4 /* spin in place */
|
|
|
|
/* __fatal_error_pal Called with:
|
|
* p0 - Exception handler that caught the exception
|
|
* p7 - Address where the exception occured.
|
|
* ra - Potentially valid return address from the code
|
|
* that took the exception.
|
|
*/
|
|
FETCH_BLOCK_ALIGN
|
|
__fatal_error_pal:
|
|
subq p0, 0x14, a0
|
|
bis p7, p7, a1
|
|
bis ra, ra, a2
|
|
bsr pv, __fatal_error_pal2
|
|
__fatal_error_pal2:
|
|
lda pv, (__fatal_error_non_pal - __fatal_error_pal2)(pv)
|
|
hw_ret (pv)
|
|
|