X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc%2Fkernel%2Fhead.S;h=53ea845fb9118446fd067754371cd11560fb8aad;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=01303efeddadb5a7a268da24363d43730068348f;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 01303efed..53ea845fb 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -37,6 +37,19 @@ #include #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 */ \ @@ -53,6 +66,7 @@ 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 @@ -115,6 +129,11 @@ _start: .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 @@ -129,6 +148,14 @@ __start: */ 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. @@ -142,6 +169,7 @@ __start: */ bl mmu_off __after_mmu_off: +#ifndef CONFIG_POWER4 bl clear_bats bl flush_tlbs @@ -149,6 +177,10 @@ __after_mmu_off: #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 @@ -160,11 +192,18 @@ __after_mmu_off: 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. */ @@ -319,19 +358,51 @@ i##n: \ #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 */ @@ -343,10 +414,21 @@ DataAccess: 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 */ @@ -356,6 +438,12 @@ InstructionAccess: 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) @@ -620,9 +708,15 @@ DataStoreTLBMiss: 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) @@ -660,6 +754,28 @@ AltiVecUnavailable: 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 @@ -932,6 +1048,13 @@ __secondary_start_pmac_0: .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 @@ -942,6 +1065,10 @@ __secondary_start: 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 @@ -982,12 +1109,12 @@ __secondary_start: * 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) */ /* @@ -1005,6 +1132,11 @@ load_up_mmu: 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 */ @@ -1013,7 +1145,7 @@ load_up_mmu: 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 @@ -1026,7 +1158,7 @@ load_up_mmu: LOAD_BAT(1,r3,r4,r5) LOAD_BAT(2,r3,r4,r5) LOAD_BAT(3,r3,r4,r5) - +#endif /* CONFIG_POWER4 */ blr /* @@ -1137,6 +1269,9 @@ _GLOBAL(set_context) 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 */ @@ -1223,6 +1358,7 @@ mmu_off: 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 @@ -1230,6 +1366,7 @@ mmu_off: */ 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 @@ -1244,6 +1381,7 @@ initial_bats: mtspr SPRN_IBAT1L,r10 isync blr +#endif /* CONFIG_PPC64BRIDGE */ 4: tophys(r8,r11) #ifdef CONFIG_SMP @@ -1257,6 +1395,11 @@ initial_bats: 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 @@ -1289,6 +1432,38 @@ setup_disp_bat: #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.