#include <asm/amigappc.h>
#endif
+#ifdef CONFIG_PPC64BRIDGE
+#define LOAD_BAT(n, reg, RA, RB) \
+ ld RA,(n*32)+0(reg); \
+ ld RB,(n*32)+8(reg); \
+ mtspr SPRN_IBAT##n##U,RA; \
+ mtspr SPRN_IBAT##n##L,RB; \
+ ld RA,(n*32)+16(reg); \
+ ld RB,(n*32)+24(reg); \
+ mtspr SPRN_DBAT##n##U,RA; \
+ mtspr SPRN_DBAT##n##L,RB; \
+
+#else /* CONFIG_PPC64BRIDGE */
+
/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
#define LOAD_BAT(n, reg, RA, RB) \
/* see the comment for clear_bats() -- Cort */ \
mtspr SPRN_DBAT##n##U,RA; \
mtspr SPRN_DBAT##n##L,RB; \
1:
+#endif /* CONFIG_PPC64BRIDGE */
.text
.stabs "arch/ppc/kernel/",N_SO,0,0,0f
.globl __start
__start:
+/*
+ * We have to do any OF calls before we map ourselves to KERNELBASE,
+ * because OF may have I/O devices mapped into that area
+ * (particularly on CHRP).
+ */
mr r31,r3 /* save parameters */
mr r30,r4
mr r29,r5
*/
bl early_init
+/*
+ * On POWER4, we first need to tweak some CPU configuration registers
+ * like real mode cache inhibit or exception base
+ */
+#ifdef CONFIG_POWER4
+ bl __970_cpu_preinit
+#endif /* CONFIG_POWER4 */
+
#ifdef CONFIG_APUS
/* On APUS the __va/__pa constants need to be set to the correct
* values before continuing.
*/
bl mmu_off
__after_mmu_off:
+#ifndef CONFIG_POWER4
bl clear_bats
bl flush_tlbs
#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
bl setup_disp_bat
#endif
+#else /* CONFIG_POWER4 */
+ bl reloc_offset
+ bl initial_mm_power4
+#endif /* CONFIG_POWER4 */
/*
* Call setup_cpu for CPU 0 and initialize 6xx Idle
bl reloc_offset
bl init_idle_6xx
#endif /* CONFIG_6xx */
+#ifdef CONFIG_POWER4
+ bl reloc_offset
+ bl init_idle_power4
+#endif /* CONFIG_POWER4 */
#ifndef CONFIG_APUS
/*
* We need to run with _start at physical address 0.
+ * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
+ * the exception vectors at 0 (and therefore this copy
+ * overwrites OF's exception vectors with our own).
* If the MMU is already turned on, we copy stuff to KERNELBASE,
* otherwise we copy it to 0.
*/
#endif
/* Machine check */
+/*
+ * On CHRP, this is complicated by the fact that we could get a
+ * machine check inside RTAS, and we have no guarantee that certain
+ * critical registers will have the values we expect. The set of
+ * registers that might have bad values includes all the GPRs
+ * and all the BATs. We indicate that we are in RTAS by putting
+ * a non-zero value, the address of the exception frame to use,
+ * in SPRG2. The machine check handler checks SPRG2 and uses its
+ * value if it is non-zero. If we ever needed to free up SPRG2,
+ * we could use a field in the thread_info or thread_struct instead.
+ * (Other exception handlers assume that r1 is a valid kernel stack
+ * pointer when we take an exception from supervisor mode.)
+ * -- paulus.
+ */
. = 0x200
mtspr SPRN_SPRG0,r10
mtspr SPRN_SPRG1,r11
mfcr r10
+#ifdef CONFIG_PPC_CHRP
+ mfspr r11,SPRN_SPRG2
+ cmpwi 0,r11,0
+ bne 7f
+#endif /* CONFIG_PPC_CHRP */
EXCEPTION_PROLOG_1
7: EXCEPTION_PROLOG_2
addi r3,r1,STACK_FRAME_OVERHEAD
+#ifdef CONFIG_PPC_CHRP
+ mfspr r4,SPRN_SPRG2
+ cmpwi cr1,r4,0
+ bne cr1,1f
+#endif
EXC_XFER_STD(0x200, machine_check_exception)
+#ifdef CONFIG_PPC_CHRP
+1: b machine_check_in_rtas
+#endif
/* Data access exception. */
. = 0x300
+#ifdef CONFIG_PPC64BRIDGE
+ b DataAccess
+DataAccessCont:
+#else
DataAccess:
EXCEPTION_PROLOG
+#endif /* CONFIG_PPC64BRIDGE */
mfspr r10,SPRN_DSISR
andis. r0,r10,0xa470 /* weird error? */
bne 1f /* if not, try to put a PTE */
mfspr r4,SPRN_DAR
EXC_XFER_EE_LITE(0x300, handle_page_fault)
+#ifdef CONFIG_PPC64BRIDGE
+/* SLB fault on data access. */
+ . = 0x380
+ b DataSegment
+#endif /* CONFIG_PPC64BRIDGE */
+
/* Instruction access exception. */
. = 0x400
+#ifdef CONFIG_PPC64BRIDGE
+ b InstructionAccess
+InstructionAccessCont:
+#else
InstructionAccess:
EXCEPTION_PROLOG
+#endif /* CONFIG_PPC64BRIDGE */
andis. r0,r9,0x4000 /* no pte found? */
beq 1f /* if so, try to put a PTE */
li r3,0 /* into the hash table */
mr r5,r9
EXC_XFER_EE_LITE(0x400, handle_page_fault)
+#ifdef CONFIG_PPC64BRIDGE
+/* SLB fault on instruction access. */
+ . = 0x480
+ b InstructionSegment
+#endif /* CONFIG_PPC64BRIDGE */
+
/* External interrupt */
EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception, EXC_XFER_EE)
EXCEPTION(0x1400, SMI, SMIException, EXC_XFER_EE)
EXCEPTION(0x1500, Trap_15, unknown_exception, EXC_XFER_EE)
+#ifdef CONFIG_POWER4
+ EXCEPTION(0x1600, Trap_16, unknown_exception, EXC_XFER_EE)
+ EXCEPTION(0x1700, Trap_17, altivec_assist_exception, EXC_XFER_EE)
+ EXCEPTION(0x1800, Trap_18, TAUException, EXC_XFER_STD)
+#else /* !CONFIG_POWER4 */
EXCEPTION(0x1600, Trap_16, altivec_assist_exception, EXC_XFER_EE)
EXCEPTION(0x1700, Trap_17, TAUException, EXC_XFER_STD)
EXCEPTION(0x1800, Trap_18, unknown_exception, EXC_XFER_EE)
+#endif /* CONFIG_POWER4 */
EXCEPTION(0x1900, Trap_19, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x1a00, Trap_1a, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x1b00, Trap_1b, unknown_exception, EXC_XFER_EE)
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
+#ifdef CONFIG_PPC64BRIDGE
+DataAccess:
+ EXCEPTION_PROLOG
+ b DataAccessCont
+
+InstructionAccess:
+ EXCEPTION_PROLOG
+ b InstructionAccessCont
+
+DataSegment:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ mfspr r4,SPRN_DAR
+ stw r4,_DAR(r11)
+ EXC_XFER_STD(0x380, unknown_exception)
+
+InstructionSegment:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_STD(0x480, unknown_exception)
+#endif /* CONFIG_PPC64BRIDGE */
+
#ifdef CONFIG_ALTIVEC
/* Note that the AltiVec support is closely modeled after the FP
* support. Changes to one are likely to be applicable to the
.globl __secondary_start
__secondary_start:
+#ifdef CONFIG_PPC64BRIDGE
+ mfmsr r0
+ clrldi r0,r0,1 /* make sure it's in 32-bit mode */
+ SYNC
+ MTMSRD(r0)
+ isync
+#endif
/* Copy some CPU settings from CPU 0 */
bl __restore_cpu_setup
lis r3,-KERNELBASE@h
bl init_idle_6xx
#endif /* CONFIG_6xx */
+#ifdef CONFIG_POWER4
+ lis r3,-KERNELBASE@h
+ bl init_idle_power4
+#endif /* CONFIG_POWER4 */
/* get current_thread_info and current */
lis r1,secondary_ti@ha
* Those generic dummy functions are kept for CPUs not
* included in CONFIG_6xx
*/
-#if !defined(CONFIG_6xx)
+#if !defined(CONFIG_6xx) && !defined(CONFIG_POWER4)
_GLOBAL(__save_cpu_setup)
blr
_GLOBAL(__restore_cpu_setup)
blr
-#endif /* !defined(CONFIG_6xx) */
+#endif /* !defined(CONFIG_6xx) && !defined(CONFIG_POWER4) */
/*
tophys(r6,r6)
lwz r6,_SDR1@l(r6)
mtspr SPRN_SDR1,r6
+#ifdef CONFIG_PPC64BRIDGE
+ /* clear the ASR so we only use the pseudo-segment registers. */
+ li r6,0
+ mtasr r6
+#endif /* CONFIG_PPC64BRIDGE */
li r0,16 /* load up segment register values */
mtctr r0 /* for context 0 */
lis r3,0x2000 /* Ku = 1, VSID = 0 */
addi r3,r3,0x111 /* increment VSID */
addis r4,r4,0x1000 /* address of next segment */
bdnz 3b
-
+#ifndef CONFIG_POWER4
/* Load the BAT registers with the values set up by MMU_init.
MMU_init takes care of whether we're on a 601 or not. */
mfpvr r3
LOAD_BAT(1,r3,r4,r5)
LOAD_BAT(2,r3,r4,r5)
LOAD_BAT(3,r3,r4,r5)
-
+#endif /* CONFIG_POWER4 */
blr
/*
li r4,0
isync
3:
+#ifdef CONFIG_PPC64BRIDGE
+ slbie r4
+#endif /* CONFIG_PPC64BRIDGE */
mtsrin r3,r4
addi r3,r3,0x111 /* next VSID */
rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */
sync
RFI
+#ifndef CONFIG_POWER4
/*
* Use the first pair of BAT registers to map the 1st 16MB
* of RAM to KERNELBASE. From this point on we can't safely
*/
initial_bats:
lis r11,KERNELBASE@h
+#ifndef CONFIG_PPC64BRIDGE
mfspr r9,SPRN_PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpwi 0,r9,1
mtspr SPRN_IBAT1L,r10
isync
blr
+#endif /* CONFIG_PPC64BRIDGE */
4: tophys(r8,r11)
#ifdef CONFIG_SMP
ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */
#endif /* CONFIG_APUS */
+#ifdef CONFIG_PPC64BRIDGE
+ /* clear out the high 32 bits in the BAT */
+ clrldi r11,r11,32
+ clrldi r8,r8,32
+#endif /* CONFIG_PPC64BRIDGE */
mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
mtspr SPRN_IBAT0L,r8
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
+#else /* CONFIG_POWER4 */
+/*
+ * Load up the SDR1 and segment register values now
+ * since we don't have the BATs.
+ * Also make sure we are running in 32-bit mode.
+ */
+
+initial_mm_power4:
+ addis r14,r3,_SDR1@ha /* get the value from _SDR1 */
+ lwz r14,_SDR1@l(r14) /* assume hash table below 4GB */
+ mtspr SPRN_SDR1,r14
+ slbia
+ lis r4,0x2000 /* set pseudo-segment reg 12 */
+ ori r5,r4,0x0ccc
+ mtsr 12,r5
+#if 0
+ ori r5,r4,0x0888 /* set pseudo-segment reg 8 */
+ mtsr 8,r5 /* (for access to serial port) */
+#endif
+#ifdef CONFIG_BOOTX_TEXT
+ ori r5,r4,0x0999 /* set pseudo-segment reg 9 */
+ mtsr 9,r5 /* (for access to screen) */
+#endif
+ mfmsr r0
+ clrldi r0,r0,1
+ sync
+ mtmsr r0
+ isync
+ blr
+
+#endif /* CONFIG_POWER4 */
+
#ifdef CONFIG_8260
/* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address.