File:  [Apple XNU] / XNU / osfmk / ppc / start.s
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:45:02 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, Apple
CVS tags: v68_4-1_1, HEAD
xnu-68.4-1.1

/*
 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * The contents of this file constitute Original Code as defined in and
 * are subject to the Apple Public Source License Version 1.1 (the
 * "License").  You may not use this file except in compliance with the
 * License.  Please obtain a copy of the License at
 * http://www.apple.com/publicsource and read it before using this file.
 * 
 * This Original Code and all software distributed under the License are
 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*
 * @OSF_COPYRIGHT@
 */
#include <cpus.h>
#include <mach_kdb.h>
#include <mach_kdp.h>
#include <mach_kgdb.h>

#include <ppc/asm.h>
#include <ppc/proc_reg.h>
#include <mach/ppc/vm_param.h>
#include <assym.s>
	
/*
 * Interrupt and bootup stack for initial processor
 */

	.file	"start.s"
	
	.data

		/* Align on page boundry */
	.align  PPC_PGSHIFT
		/* Red zone for interrupt stack, one page (will be unmapped)*/
	.set	., .+PPC_PGBYTES
		/* intstack itself */

     .globl  EXT(FixedStackStart)
EXT(FixedStackStart):
     
	 .globl  EXT(intstack)
EXT(intstack):
	.set	., .+INTSTACK_SIZE*NCPUS
	
	/* Debugger stack - used by the debugger if present */
	/* NOTE!!! Keep the debugger stack right after the interrupt stack */

#if MACH_KDP || MACH_KDB
    .globl  EXT(debstack)
EXT(debstack):
	.set	., .+KERNEL_STACK_SIZE*NCPUS
     
	 .globl  EXT(FixedStackEnd)
EXT(FixedStackEnd):

	.align	ALIGN
    .globl  EXT(intstack_top_ss)
EXT(intstack_top_ss):
	.long	EXT(intstack)+INTSTACK_SIZE-SS_SIZE			/* intstack_top_ss points to the top of interrupt stack */

	.align	ALIGN
    .globl  EXT(debstack_top_ss)	
EXT(debstack_top_ss):

	.long	EXT(debstack)+KERNEL_STACK_SIZE-SS_SIZE		/* debstack_top_ss points to the top of debug stack */

    .globl  EXT(debstackptr)
EXT(debstackptr):	
	.long	EXT(debstack)+KERNEL_STACK_SIZE-SS_SIZE

#endif /* MACH_KDP || MACH_KDB */

/*
 * All CPUs start here.
 *
 * This code is called from SecondaryLoader
 *
 * Various arguments are passed via a table:
 *   ARG0 = pointer to other startup parameters
 */
	.text
	
ENTRY(_start_cpu,TAG_NO_FRAME_USED)
			li		r30,1
			b		allstart
			
ENTRY(_start,TAG_NO_FRAME_USED)
			li		r30,0
allstart:
			mr		r31,r3						/* Save away arguments */

			li		r7,MSR_VM_OFF				/* Get real mode MSR */
			mtmsr	r7							/* Set the real mode SRR */
			isync					

;			Map in the first 256Mb in both instruction and data BATs

			li		r7,((0x7FF<<2)|2)  					; Set up for V=R 256MB in supervisor space
			li      r8,((2<<3)|2)						; Physical address = 0, coherent, R/W
			li		r9,0								; Clear out a register
			
			mtsprg	0,r9								; Insure the SPRGs are clear
			mtsprg	1,r9
			mtsprg	2,r9
			mtsprg	3,r9

			sync
			isync
			mtdbatu 0,r7								; Map bottom 256MB
			mtdbatl 0,r8								; Map bottom 256MB
			mtdbatu 1,r9								; Invalidate maps
			mtdbatl 1,r9								; Invalidate maps
			mtdbatu 2,r9								; Invalidate maps
			mtdbatl 2,r9								; Invalidate maps
			mtdbatu 3,r9								; Invalidate maps
			mtdbatl 3,r9								; Invalidate maps
			sync
			isync
			mtibatu 0,r7								; Map bottom 256MB
			mtibatl 0,r8								; Map bottom 256MB
			mtibatu 1,r9								; Invalidate maps
			mtibatl 1,r9								; Invalidate maps
			mtibatu 2,r9								; Invalidate maps
			mtibatl 2,r9								; Invalidate maps
			mtibatu 3,r9								; Invalidate maps
			mtibatl 3,r9								; Invalidate maps
			sync
			isync

			mfpvr	r10
			rlwinm	r11,r10,16,16,31
			cmplwi	r11,PROCESSOR_VERSION_Max			; Do we have Altivec?
			blt		novmx								; Nope...

; ?
			rlwinm	r13,r10,0,16,31						; ?
			cmplwi	r13, 0x0200							; ?
			bge	notMaxV1								; ?

			sync
			mfspr	r11,msscr0							; ?
			mfspr	r12,msscr1							; ?
			
			oris	r11,r11,hi16(shden)					; ?
			
			andis.	r0,r11,hi16(emodem)					; ?
			bne		inmaxbus							; ?
			ori		r11,r11,lo16(tfstm)					; ?
			b		nomaxbus							; ?

inmaxbus:	oris	r12,r12,hi16(cqdm)					; ?

nomaxbus:	rlwinm	r12,r12,0,csqe+1,csqs-1				; ?
			oris	r12,r12,0x2000						; ?
			
			sync
			mtspr	msscr0,r11							; ?
			mtspr	msscr1,r12							; ?
			sync
			isync

notMaxV1:
; ?
			cmplwi	r13,0x0202							; ?
			bge	notMaxV2_0								; ?

			lis	r11, 0xffff
			ori	r11, r11, 0xfffe
			mtspr	iabr, r11
			isync

notMaxV2_0:

			li		r0,0								; Clear out a register
			
			lis		r7,hi16(MSR_VEC_ON)					; Get real mode MSR + FP + Altivec
			ori		r7,r7,lo16(MSR_VM_OFF|MASK(MSR_FP))	; Get real mode MSR + FP + Altivec
			mtmsr	r7									; Set the real mode SRR */
			isync										; Make sure it has happened									
		
			lis		r5,hi16(EXT(QNaNbarbarian))			; Altivec initializer
			ori		r5,r5,lo16(EXT(QNaNbarbarian))		; Altivec initializer

			mtspr	vrsave,r0							; Set that no VRs are used yet */
			
			vspltisw	v1,0							; Clear a register
			lvx		v0,br0,r5							; Initialize VR0
			mtvscr	v1									; Clear the vector status register
			vor		v2,v0,v0							; Copy into the next register
			vor		v1,v0,v0							; Copy into the next register
			vor		v3,v0,v0							; Copy into the next register
			vor		v4,v0,v0							; Copy into the next register
			vor		v5,v0,v0							; Copy into the next register
			vor		v6,v0,v0							; Copy into the next register
			vor		v7,v0,v0							; Copy into the next register
			vor		v8,v0,v0							; Copy into the next register
			vor		v9,v0,v0							; Copy into the next register
			vor		v10,v0,v0							; Copy into the next register
			vor		v11,v0,v0							; Copy into the next register
			vor		v12,v0,v0							; Copy into the next register
			vor		v13,v0,v0							; Copy into the next register
			vor		v14,v0,v0							; Copy into the next register
			vor		v15,v0,v0							; Copy into the next register
			vor		v16,v0,v0							; Copy into the next register
			vor		v17,v0,v0							; Copy into the next register
			vor		v18,v0,v0							; Copy into the next register
			vor		v19,v0,v0							; Copy into the next register
			vor		v20,v0,v0							; Copy into the next register
			vor		v21,v0,v0							; Copy into the next register
			vor		v22,v0,v0							; Copy into the next register
			vor		v23,v0,v0							; Copy into the next register
			vor		v24,v0,v0							; Copy into the next register
			vor		v25,v0,v0							; Copy into the next register
			vor		v26,v0,v0							; Copy into the next register
			vor		v27,v0,v0							; Copy into the next register
			vor		v28,v0,v0							; Copy into the next register
			vor		v29,v0,v0							; Copy into the next register
			vor		v30,v0,v0							; Copy into the next register
			vor		v31,v0,v0							; Copy into the next register

			cmplwi	r30,1								; Are we the boot processor?
			mfspr	r11,msscr0							; Get the memory system control register
			dssall										; Force all data stream stuff to stop
			oris	r11,r11,hi16(dl1hwfm)				; Turn on the hardware flush request
			sync
			beq		invl1								; Not boot, invalidate L1...
			
			mtspr	msscr0,r11							; Start the flush operation
			
rstbsy:		mfspr	r11,msscr0							; Get the control register again
			
			rlwinm.	r11,r11,0,dl1hwf,dl1hwf				; Has the flush request been reset yet?
			bne		rstbsy								; No, flush is still in progress...
			
			sync										; Make sure all flushes have been committed
			b		setmck								; Go set mck handling...
			
invl1:		mfspr	r8,hid0								; Set the HID0 bits for enable, and invalidate
			ori		r8,r8,lo16(0x0000CC00)				; Do an isync just incase the cache was off 
			sync
			isync										; Start the invalidate 
			mtspr	hid0,r8								; To finish the invalidate clear the inval bits
			li		r9,lo16(0x00000C00)
			andc	r8,r8,r9							; End the invalidate
			mtspr	hid0,r8								; Make sure all is done
			sync										; Make sure it is really done
			sync
			
setmck:		mfspr	r11,hid0							; ?
			ori		r11,r11,hi16(eiecm)					; ?
			mtspr	hid0,r11							; ?
			isync
			
#if 0
;			(TEST/DEBUG) Flush and turn off L2 Cache so I can display memory with the durn ESP unit
			b		flushl2								; (TEST/DEBUG) Jump to start

			.align	5									; (TEST/DEBUG) Force alignment to cache
			nop
			nop
			nop
			nop
			nop
flushl2:	mfspr	r11,l2cr							; (TEST/DEBUG) Get L2 control register
			ori		r11,r11,0x0800						; (TEST/DEBUG) Turn on L2 hardware flush request
			sync										; (TEST/DEBUG) 

;			Cache boundary here 
;			The following flush and cache disable are all in the same line

			mtspr	l2cr,r11							; (TEST/DEBUG) Start the flush
			
flushl2d:	mfspr	r11,l2cr							; (TEST/DEBUG) Get the control reg again
			rlwinm.	r8,r11,0,20,20						; (TEST/DEBUG) Have we finished?
			bne		flushl2d							; (TEST/DEBUG) Nope...
			sync										; (TEST/DEBUG) 
			rlwinm	r11,r11,0,1,31						; (TEST/DEBUG) Turn off L2
			mtspr	l2cr,r11							; (TEST/DEBUG) Finish it
			sync										; (TEST/DEBUG) Quiet down

;			Cache boundary here 
;			Invalidate the L2 cache, just for funsies...

			oris	r8,r11,0x0020						; (TEST/DEBUG) Turn on invalidate request
			mtspr	l2cr,r8								; (TEST/DEBUG) Start invalidation
			sync										; (TEST/DEBUG)

invl2:		mfspr	r8,l2cr								; (TEST/DEBUG) Get the L2 control register
			rlwinm.	r8,r8,0,31,31						; (TEST/DEBUG) Is the invalidation still going on?
			bne+	invl2								; (TEST/DEBUG) Yes, keep going...
			
			mtspr	l2cr,r11							; (TEST/DEBUG) Turn off invalidate request, leaving L2 disabled
			sync
;			Cache boundary here 
#endif			
			b		invcache							; (TEST/DEBUG) Now, go invalidate level 1...


novmx:
/*
 *			We need to have our memory coherent, but we may not be here.  If we just switch the 
 *			BATs, we could end up with memory paradoxes, i.e., cache entries left over from
 *			when the memory was incoherent, just babbling away...  To prevent this, we have to get
 *			rid of all non-coherent lines.  Since we just loaded the system, we could have tons
 *			of lines with and unknown address ranges, so we would have to do a whole slew of DCBSTs
 *			to force them all out.  We can't just flash invalidate, 'cause we'd lose a few lines.
 *			So, we go translate off, load up some safe lines (from the ROM), and then flash invalidate 
 *			the caches.  We don't do this for a 601 'cause there ain't no DBATs or flash invalidate.
 */
			
			
realcode:	lis		r8,0xFFF0							/* Point to the ROM */
			addis	r9,r8,0x0002						/* Point 128k later */
			subi	r8,r8,32							/* Start back one */
			
readROM:	lwz		r10,32(r8)							/* Get a line into cache */
			addi	r8,r8,32
			cmplw	cr0,r8,r9							/* See if we're done */
			blt+	readROM								/* Do it all... */
			
			sync

		
invcache:
			mfspr	r8,hid0								; Turn on the L1 and invalidate it
			ori		r8,r8,lo16(0x0000CC00)				; Set the HID0 bits for enable, and invalidate
			isync										; Do an isync just incase the cache was off
			mtspr	hid0,r8								; Start the invalidate
			li		r9,lo16(0x00000C00)					; To finish the invalidate clear the inval bits
			andc	r8,r8,r9
			mtspr	hid0,r8								; End the invalidate
			sync										; Make sure all is done
			sync										; Make sure it is really done 

/* */
/*			Clear out the TLB.  They be garbage after hard reset. */
/* */

			lis		r12,hi16(EXT(tlb_system_lock))		/* Get the TLBIE lock */
			li		r0,512								/* Get number of TLB entries (overestimate at 512 entries) */
			ori		r12,r12,lo16(EXT(tlb_system_lock))	/* Grab up the bottom part */
			li		r3,0								/* Start at 0 */

			lwarx	r5,0,r12							; ?

itlbhang:	lwarx	r5,0,r12							/* Get the TLBIE lock */
			mr.		r5,r5								/* Is it locked? */
			bne-	itlbhang							/* It's locked, go wait... */
			stwcx.	r0,0,r12							/* Try to get it */
			bne-	itlbhang							/* We was beat... */

			mtctr	r0									/* Set the CTR */
			
IRpurgeTLB:	tlbie	r3									/* Purge this entry */
			addi	r3,r3,4096							/* Next page */
			bdnz	IRpurgeTLB							/* Do 'em all... */
			
			sync										/* Make sure all TLB purges are done */

			mfpvr	r10
			rlwinm	r10,r10,16,16,31

			eieio										/* Make sure that the tlbie happens first */
			
			cmplwi	r10,PROCESSOR_VERSION_603			/* Got a 603 */
			beq		donttsync							/* Yeah, don't sync... */

			cmplwi	r10,PROCESSOR_VERSION_603e			/* Got a 603e */
			beq		donttsync							/* Yeah, don't sync... */

			cmplwi	r10,PROCESSOR_VERSION_750			/* Got a 750 */
			beq		donttsync							/* Yeah, don't sync... */

			tlbsync										/* Make sure on other processors also */
			sync										/* Make sure the TLBSYNC is done */
	
donttsync:	stw		r5,0(r12)							; Unlock the TLBIE interlock	

			li		r0,MSR_SUPERVISOR_INT_OFF|MASK(MSR_FP)		/* Make sure we don't have ints enabled */
			mtmsr	r0									/* Set the standard MSR values */
			isync
			
			lis		r5,HIGH_ADDR(EXT(FloatInit))		/* Get top of floating point init value */
			ori		r5,r5,LOW_ADDR(EXT(FloatInit))		/* Slam bottom */
			lfd		f0,0(r5)							/* Initialize FP0 */
			fmr		f1,f0								/* Ours in not */					
			fmr		f2,f0								/* to wonder why, */
			fmr		f3,f0								/* ours is but to */
			fmr		f4,f0								/* do or die! */
			fmr		f5,f0						
			fmr		f6,f0						
			fmr		f7,f0						
			fmr		f8,f0						
			fmr		f9,f0						
			fmr		f10,f0						
			fmr		f11,f0						
			fmr		f12,f0						
			fmr		f13,f0						
			fmr		f14,f0						
			fmr		f15,f0						
			fmr		f16,f0						
			fmr		f17,f0						
			fmr		f18,f0						
			fmr		f19,f0						
			fmr		f20,f0						
			fmr		f21,f0						
			fmr		f22,f0						
			fmr		f23,f0						
			fmr		f24,f0						
			fmr		f25,f0						
			fmr		f26,f0						
			fmr		f27,f0						
			fmr		f28,f0						
			fmr		f29,f0						
			fmr		f30,f0						
			fmr		f31,f0						
		
			li		r0,	MSR_SUPERVISOR_INT_OFF			/* Make sure we don't have FP enabled */
			mtmsr	r0									/* Set the standard MSR values */
			isync

#if 0
			li		r3,0				/* (TEST/DEBUG) */
			bl		EXT(fwSCCinit)		/* (TEST/DEBUG) */
#endif
#if 0
			li		r3,1				/* (TEST/DEBUG) */
			bl		EXT(fwSCCinit)		/* (TEST/DEBUG) */
#endif

			lis		r20,HIGH_ADDR(fwdisplock)	/* Get address of the firmware display lock */
			li		r19,0						/* Zorch a register */
			ori		r20,r20,LOW_ADDR(fwdisplock)	/* Get address of the firmware display lock */
			stw		r19,0(r20)					/* Make sure the lock is free */

#if 0
			li		r3,0				/* (TEST/DEBUG) */
			lis		r4,0x6D65			/* (TEST/DEBUG) 'memg' */
			ori		r4,r4,0x6D67		/* (TEST/DEBUG) */
			li		r5,0				/* (TEST/DEBUG) */
			bl		EXT(dbgDispLL)		/* (TEST/DEBUG) */
#endif
			cmpi	cr0, r30, 1
			beq		callcpu
	/* move onto interrupt stack */

			lis		r29,HIGH_ADDR(EXT(intstack_top_ss))
			ori		r29,r29,LOW_ADDR(EXT(intstack_top_ss))
#if 0
			li		r3,0				/* (TEST/DEBUG) */
			lis		r4,0x7232			/* (TEST/DEBUG) 'r29a' */
			ori		r4,r4,0x3961		/* (TEST/DEBUG) */
			mr		r5,r29				/* (TEST/DEBUG) */
			bl		EXT(dbgDispLL)		/* (TEST/DEBUG) */
#endif
			lwz		r29,0(r29)
#if 0
			li		r3,0				/* (TEST/DEBUG) */
			lis		r4,0x7232			/* (TEST/DEBUG) 'r29b' */
			ori		r4,r4,0x3962		/* (TEST/DEBUG) */
			mr		r5,r29				/* (TEST/DEBUG) */
			bl		EXT(dbgDispLL)		/* (TEST/DEBUG) */
#endif

	li	r28,	0
	stw	r28,	FM_BACKPTR(r29) /* store a null frame backpointer */

	/* move onto new stack */
	
#if 0
			li		r3,0				/* (TEST/DEBUG) */
			lis		r4,0x676F			/* (TEST/DEBUG) 'gogo' */
			ori		r4,r4,0x676F		/* (TEST/DEBUG) */
			mr		r5,r29				/* (TEST/DEBUG) */
			bl		EXT(dbgDispLL)		/* (TEST/DEBUG) */
#endif

			mr		r1,r29
			mr		r3,r31				/* Restore any arguments we may have trashed */

			bl	EXT(ppc_init)

			/* Should never return */

			BREAKPOINT_TRAP

callcpu:
			/* move onto interrupt stack */
			lwz		r29,PP_INTSTACK_TOP_SS(r31)
			li		r28,	0
			stw		r28,	FM_BACKPTR(r29) /* store a null frame backpointer */

			/* move onto new stack */
			mr		r1,r29
			mr		r3,r31				/* Restore any arguments we may have trashed */

			bl	EXT(ppc_init_cpu)

			/* Should never return */

			BREAKPOINT_TRAP


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.