Home | History | Annotate | Line # | Download | only in booke
      1  1.3    matt /*-
      2  1.3    matt  * Copyright (c) 2011, 2012 The NetBSD Foundation, Inc.
      3  1.3    matt  * All rights reserved.
      4  1.3    matt  *
      5  1.3    matt  * This code is derived from software contributed to The NetBSD Foundation
      6  1.3    matt  * by Matt Thomas of 3am Software Foundry.
      7  1.3    matt  *
      8  1.3    matt  * Redistribution and use in source and binary forms, with or without
      9  1.3    matt  * modification, are permitted provided that the following conditions
     10  1.3    matt  * are met:
     11  1.3    matt  * 1. Redistributions of source code must retain the above copyright
     12  1.3    matt  *    notice, this list of conditions and the following disclaimer.
     13  1.3    matt  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.3    matt  *    notice, this list of conditions and the following disclaimer in the
     15  1.3    matt  *    documentation and/or other materials provided with the distribution.
     16  1.3    matt  *
     17  1.3    matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     18  1.3    matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     19  1.3    matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     20  1.3    matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     21  1.3    matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  1.3    matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  1.3    matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  1.3    matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25  1.3    matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26  1.3    matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  1.3    matt  * POSSIBILITY OF SUCH DAMAGE.
     28  1.3    matt  */
     29  1.1    matt 
     30  1.1    matt /*
     31  1.1    matt  * r3 = fdt pointer (ignored)
     32  1.1    matt  * r4 = 0
     33  1.1    matt  * r5 = 0
     34  1.1    matt  * r6 = EPAPR magic (0x45505150)
     35  1.1    matt  * r7 = TLB1[0] entry size (64MB)
     36  1.1    matt  * r8 = 0
     37  1.1    matt  * r9 = 0
     38  1.1    matt  */
     39  1.2    matt 	.p2align 5
     40  1.2    matt ENTRY_NOPROFILE(e500_spinup_trampoline)
     41  1.2    matt 
     42  1.2    matt 	lis	%r31, 0xdeadbeef@h
     43  1.2    matt 	ori	%r31, %r31, 0xdeadbeef@l
     44  1.2    matt 	mr	%r30, %r31
     45  1.2    matt 	mr	%r29, %r31
     46  1.2    matt 	mr	%r28, %r31
     47  1.2    matt 	mr	%r27, %r31
     48  1.2    matt 	mr	%r26, %r31
     49  1.2    matt 	mr	%r25, %r31
     50  1.2    matt 	mr	%r24, %r31
     51  1.2    matt 	mr	%r23, %r31
     52  1.2    matt 	mr	%r22, %r31
     53  1.2    matt 	mr	%r21, %r31
     54  1.2    matt 	mr	%r20, %r31
     55  1.2    matt 	mr	%r19, %r31
     56  1.2    matt 	mr	%r18, %r31
     57  1.2    matt 	mr	%r17, %r31
     58  1.2    matt 	mr	%r16, %r31
     59  1.2    matt 	mr	%r15, %r31
     60  1.2    matt 	mr	%r14, %r31
     61  1.2    matt 	mr	%r13, %r31
     62  1.2    matt 	mr	%r12, %r31
     63  1.2    matt 	mr	%r11, %r31
     64  1.2    matt 	mr	%r10, %r31
     65  1.2    matt 	mr	%r2, %r31
     66  1.1    matt 
     67  1.1    matt 	/*
     68  1.1    matt 	 * First thing we need to do is to set SPRG0 with our cpu_info
     69  1.1    matt 	 * and get our initial stack pointer (this must be within the
     70  1.1    matt 	 * bounds of the TLB1[0] entry U-boot setup for us).
     71  1.1    matt 	 *
     72  1.1    matt 	 * cpu_hatch will return a new SP to use.
     73  1.1    matt 	 *
     74  1.1    matt 	 * All the caller-saved register are ours to use.  So we will.
     75  1.1    matt 	 */
     76  1.2    matt 	lis	%r20, _C_LABEL(cpu_hatch_data)@h
     77  1.2    matt 	ori	%r20, %r20, _C_LABEL(cpu_hatch_data)@l
     78  1.3    matt 	sync
     79  1.3    matt 
     80  1.3    matt 	/*
     81  1.3    matt 	 * Ensure that the TLB entry we are using is memory coherent.
     82  1.3    matt 	 */
     83  1.3    matt 	lis	%r0, (MASX_TLBSEL_MAKE(1)|MAS0_ESEL_MAKE(0))@h
     84  1.3    matt 	mtspr	SPR_MAS0, %r0 			/* setup MAS0 */
     85  1.3    matt 	lis	%r3, (MAS1_V|MAS1_IPROT)@h	/* V | IPROT */
     86  1.3    matt 	ori	%r3, %r3, MASX_TSIZE_64MB	/* and 64MB */
     87  1.3    matt 	mtspr	SPR_MAS1, %r3 			/* save MAS1 */
     88  1.3    matt 	li	%r3, MAS2_M			/* set M bit */
     89  1.3    matt 	mtspr	SPR_MAS2, %r3 			/* save MAS2 */
     90  1.3    matt 	li	%r3, MAS3_SX|MAS3_SR|MAS3_SW	/* set kernel RWX */
     91  1.3    matt 	mtspr	SPR_MAS3, %r3 			/* save MAS3 */
     92  1.3    matt 	tlbwe					/* update entry */
     93  1.3    matt 	isync					/* flush i-stream */
     94  1.3    matt 	sync					/* sync memory. */
     95  1.2    matt 
     96  1.2    matt 	li	%r0, 0
     97  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
     98  1.3    matt 	sync
     99  1.3    matt #if 0
    100  1.3    matt 	dcbf	0, %r20
    101  1.3    matt #endif
    102  1.1    matt 
    103  1.2    matt 	lwz	%r1, HATCH_SP(%r20)		/* get hatch SP */
    104  1.1    matt 	lwz	%r21, HATCH_CI(%r20)		/* get cpu_info */
    105  1.1    matt 	mtsprg0	%r21				/* save cpu_info */
    106  1.2    matt 	lwz	%r13, CI_CURLWP(%r21)		/* load r13 with curlwp */
    107  1.2    matt 	mtsprg2	%r13				/* save it in sprg2 */
    108  1.3    matt 	addi    %r0,%r21,CI_SAVELIFO		/* get SAVE area start */
    109  1.3    matt 	mtsprg3 %r0				/* save it in sprg3 */
    110  1.2    matt 
    111  1.2    matt 	/*
    112  1.2    matt 	 * Now to synchronize timebase values.  First to make sure HID0 is
    113  1.2    matt 	 * set correctly, except with the timebase disabled.
    114  1.2    matt 	 */
    115  1.2    matt 	lwz	%r22, HATCH_HID0(%r20)		/* get HID0 */
    116  1.2    matt 	li	%r28, HID0_TBEN			/* HID0_TBEN */
    117  1.2    matt 	andc	%r0,%r22,%r28			/* clear TBEN from HID0 */
    118  1.2    matt 	mtspr	SPR_HID0, %r0			/* set HID0 (timebase off) */
    119  1.2    matt 	isync
    120  1.2    matt 	lwz	%r24, HATCH_TBL(%r20)		/* get lower timebase value */
    121  1.2    matt 	lwz	%r23, HATCH_TBU(%r20)		/* get upper timebase value */
    122  1.2    matt 
    123  1.2    matt 	/*
    124  1.2    matt 	 * Figure out how much we are adjusting the timebase
    125  1.2    matt 	 */
    126  1.2    matt 	mftbl	%r4				/* get lower timebase */
    127  1.2    matt 	subfc	%r0, %r4, %r24			/* subtract from new value */
    128  1.2    matt 	stw	%r0, HATCH_TBL(%r20)		/* save it */
    129  1.2    matt 	mftbu	%r3				/* get upper timebase */
    130  1.2    matt 	subfe	%r0, %r3, %r23			/* subtract from new value */
    131  1.2    matt 	stw	%r0, HATCH_TBU(%r20)		/* save it */
    132  1.2    matt 
    133  1.2    matt 	/*
    134  1.2    matt 	 * Since we've disabled timebase, we can set the timebase registers
    135  1.2    matt 	 * without fear of them changing.  Have to do this after we read the
    136  1.2    matt 	 * previous values.
    137  1.2    matt 	 */
    138  1.2    matt 	mttbu	%r23				/* set upper timebase */
    139  1.2    matt 	mttbl	%r24				/* set lower timebase */
    140  1.2    matt 
    141  1.2    matt 	/*
    142  1.2    matt 	 * Now we loop until the boot cpu tells us to enable timebase
    143  1.2    matt 	 */
    144  1.2    matt 1:	lwz	%r0, HATCH_RUNNING(%r20)	/* is it time? */
    145  1.2    matt 	cmplwi	%r0, 0
    146  1.2    matt 	beq+	1b
    147  1.2    matt 
    148  1.2    matt 	mtspr	SPR_HID0, %r22			/* start timebase running */
    149  1.2    matt 	isync
    150  1.2    matt 
    151  1.2    matt 	li	%r0, 2
    152  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    153  1.3    matt 	sync
    154  1.2    matt 
    155  1.1    matt 	/*
    156  1.1    matt 	 * We have to setup the IVOR SPRs since the ones u-boot setup
    157  1.1    matt 	 * don't work for us.
    158  1.1    matt 	 */
    159  1.1    matt 	bl	_C_LABEL(exception_init)	/* setup IVORs */
    160  1.1    matt 
    161  1.2    matt 	li	%r0, 3
    162  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    163  1.2    matt 
    164  1.1    matt 	/*
    165  1.1    matt 	 * U-boot has mapped the bottom 64MB in TLB1[0].  We are going to need
    166  1.2    matt 	 * to change this entry and it's not safe to do so while running out
    167  1.2    matt 	 * of it.  So we copy TLB1[0] to TLB1[1] but set it for AS1.  We then
    168  1.2    matt 	 * switch to AS1 and reload TLB1[0] with its correct value, and then we
    169  1.2    matt 	 * switch back to AS0.  After that, we can load the rest of the TLB1
    170  1.2    matt 	 * entries.
    171  1.1    matt 	 */
    172  1.1    matt 
    173  1.1    matt 	/*
    174  1.1    matt 	 * Fetch TLB1[0]
    175  1.1    matt 	 */
    176  1.1    matt 	lis	%r16, (MASX_TLBSEL_MAKE(1)|MAS0_ESEL_MAKE(0))@h
    177  1.1    matt 	mtspr	SPR_MAS0, %r16
    178  1.1    matt 	tlbre
    179  1.1    matt 
    180  1.2    matt 	li	%r0, 4
    181  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    182  1.2    matt 
    183  1.1    matt 	/*
    184  1.1    matt 	 * Copy TLB1[0] to TLB[1] and set it to use AS1
    185  1.1    matt 	 */
    186  1.1    matt 	mfspr	%r3, SPR_MAS0
    187  1.1    matt 	addis	%r3, %r3, MAS0_ESEL@h		/* advance to next TLB entry */
    188  1.1    matt 	mtspr	SPR_MAS0, %r3			/* place into SPR */
    189  1.1    matt 	mfspr	%r4, SPR_MAS1
    190  1.1    matt 	ori	%r4, %r4, MAS1_TS@l		/* Make it use AS1 */
    191  1.1    matt 	mtspr	SPR_MAS1, %r4
    192  1.1    matt 	tlbwe					/* write the TLB entry */
    193  1.1    matt 
    194  1.2    matt 	li	%r0, 5
    195  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    196  1.2    matt 
    197  1.1    matt 	/*
    198  1.3    matt 	 * Let's find out what TLB1 entry we are supposed to use.
    199  1.1    matt 	 */
    200  1.3    matt 	lwz	%r3, HATCH_TLBIDX(%r20)
    201  1.1    matt 	bl	_C_LABEL(e500_tlb1_fetch)
    202  1.3    matt 	lmw	%r28, 0(%r3)			/* load the saved TLB1 entry */
    203  1.1    matt 
    204  1.2    matt 	li	%r0, 6
    205  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    206  1.2    matt 
    207  1.1    matt 	/*
    208  1.1    matt 	 * Now to switch to running in AS1
    209  1.1    matt 	 */
    210  1.1    matt 	mfmsr	%r3
    211  1.1    matt 	ori	%r4,%r3,(PSL_DS|PSL_IS)@l
    212  1.1    matt 	mtsrr1	%r4
    213  1.1    matt 
    214  1.1    matt 	bl	1f
    215  1.1    matt 1:	mflr	%r11
    216  1.1    matt 	addi	%r4,%r11,.Las1start-1b
    217  1.1    matt 	addi	%r5,%r11,.Las1end-1b
    218  1.1    matt 	mtsrr0	%r4
    219  1.2    matt 	li	%r0, 7
    220  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    221  1.1    matt 	rfi			/* switch to AS1, context synchronizing */
    222  1.1    matt 
    223  1.1    matt .Las1start:
    224  1.1    matt 	/*
    225  1.1    matt 	 * We are now running in AS1, update TLB1[0]
    226  1.1    matt 	 */
    227  1.2    matt 	li	%r0, 8
    228  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    229  1.2    matt 
    230  1.3    matt 	/*
    231  1.3    matt 	 * Let's clear TBL1[0] and TBL1[1]
    232  1.3    matt 	 */
    233  1.3    matt 	li	%r8, 0
    234  1.3    matt 	mtspr	SPR_MAS1, %r8
    235  1.3    matt 	mtspr	SPR_MAS2, %r8
    236  1.3    matt 	mtspr	SPR_MAS3, %r8
    237  1.3    matt 	mtspr	SPR_MAS7, %r8
    238  1.3    matt 
    239  1.3    matt 	lis	%r8, (MASX_TLBSEL_MAKE(1)|MAS0_ESEL_MAKE(0))@h
    240  1.3    matt 	mtspr	SPR_MAS0, %r8
    241  1.3    matt 	tlbwe
    242  1.3    matt 
    243  1.3    matt 	lis	%r8, (MASX_TLBSEL_MAKE(1)|MAS0_ESEL_MAKE(1))@h
    244  1.3    matt 	mtspr	SPR_MAS0, %r8
    245  1.3    matt 	tlbwe
    246  1.3    matt 
    247  1.3    matt 	/*
    248  1.3    matt 	 * Now load the new TLB data into the MAS registers.
    249  1.3    matt 	 */
    250  1.3    matt 	mtspr	SPR_MAS0, %r28			/* place into SPRs */
    251  1.3    matt 	mtspr	SPR_MAS1, %r29
    252  1.3    matt 	mtspr	SPR_MAS2, %r30
    253  1.3    matt 	mtspr	SPR_MAS3, %r31
    254  1.1    matt 	tlbwe
    255  1.1    matt 
    256  1.1    matt 	mtsrr0	%r5
    257  1.1    matt 	mtsrr1	%r3
    258  1.2    matt 
    259  1.2    matt 	li	%r0, 9
    260  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    261  1.2    matt 
    262  1.1    matt 	rfi			/* switch back to AS0, context synchronizing */
    263  1.1    matt 
    264  1.1    matt .Las1end:
    265  1.2    matt 	li	%r0, 10
    266  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    267  1.2    matt 
    268  1.2    matt 	/*
    269  1.3    matt 	 * We now have our TLB1[0] in place.  Now we need to load the rest of
    270  1.3    matt 	 * TLB1 with our entries.  After this is done, we should have access
    271  1.3    matt 	 * to everything.
    272  1.2    matt 	 */
    273  1.3    matt 	bl	_C_LABEL(e500_tlb1_sync)
    274  1.2    matt 
    275  1.2    matt 	li	%r0, 11
    276  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    277  1.2    matt 
    278  1.2    matt 	/*
    279  1.3    matt 	 * Now we can use our stack...
    280  1.2    matt 	 */
    281  1.4  nonaka 	lwz	%r3, CI_CURPCB(%r21)
    282  1.4  nonaka 	lwz	%r1, PCB_SP(%r3)
    283  1.2    matt 
    284  1.2    matt 	li	%r0, 12
    285  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    286  1.2    matt 
    287  1.1    matt 	/*
    288  1.3    matt 	 * Tell spinup code we are done with the hatch stack.
    289  1.1    matt 	 */
    290  1.3    matt 	li	%r0, 0
    291  1.3    matt 	stw	%r0, HATCH_SP(%r20)
    292  1.1    matt 
    293  1.2    matt 	li	%r0, 13
    294  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    295  1.2    matt 
    296  1.1    matt 	/*
    297  1.1    matt 	 * We've gotten the low level stuff done.
    298  1.1    matt 	 * Now to do more advanced stuff.
    299  1.1    matt 	 */
    300  1.2    matt 	mr	%r3, %r21
    301  1.2    matt 	bl	_C_LABEL(e500_cpu_hatch)
    302  1.2    matt 
    303  1.2    matt 	li	%r0, 14
    304  1.2    matt 	stw	%r0, HATCH_RUNNING(%r20)	/* progress */
    305  1.2    matt 
    306  1.2    matt 	/*
    307  1.2    matt 	 * Now wait to become runnable
    308  1.2    matt 	 */
    309  1.2    matt 	bl	_C_LABEL(cpu_hatch)
    310  1.1    matt 
    311  1.1    matt 	wrteei	1				/* allow interrupts */
    312  1.2    matt 	bl	_C_LABEL(spl0)			/* unblock interrupts */
    313  1.1    matt 
    314  1.1    matt 	b	_C_LABEL(idle_loop)
    315