/*1* Kernel execution entry point code.2*3* Copyright (c) 1995-1996 Gary Thomas <[email protected]>4* Initial PowerPC version.5* Copyright (c) 1996 Cort Dougan <[email protected]>6* Rewritten for PReP7* Copyright (c) 1996 Paul Mackerras <[email protected]>8* Low-level exception handers, MMU support, and rewrite.9* Copyright (c) 1997 Dan Malek <[email protected]>10* PowerPC 8xx modifications.11* Copyright (c) 1998-1999 TiVo, Inc.12* PowerPC 403GCX modifications.13* Copyright (c) 1999 Grant Erickson <[email protected]>14* PowerPC 403GCX/405GP modifications.15* Copyright 2000 MontaVista Software Inc.16* PPC405 modifications17* PowerPC 403GCX/405GP modifications.18* Author: MontaVista Software, Inc.19* [email protected] or [email protected]20* [email protected]21* Copyright 2002-2005 MontaVista Software, Inc.22* PowerPC 44x support, Matt Porter <[email protected]>23*24* This program is free software; you can redistribute it and/or modify it25* under the terms of the GNU General Public License as published by the26* Free Software Foundation; either version 2 of the License, or (at your27* option) any later version.28*/2930#include <linux/init.h>31#include <asm/processor.h>32#include <asm/page.h>33#include <asm/mmu.h>34#include <asm/pgtable.h>35#include <asm/cputable.h>36#include <asm/thread_info.h>37#include <asm/ppc_asm.h>38#include <asm/asm-offsets.h>39#include <asm/ptrace.h>40#include <asm/synch.h>41#include "head_booke.h"424344/* As with the other PowerPC ports, it is expected that when code45* execution begins here, the following registers contain valid, yet46* optional, information:47*48* r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)49* r4 - Starting address of the init RAM disk50* r5 - Ending address of the init RAM disk51* r6 - Start of kernel command line string (e.g. "mem=128")52* r7 - End of kernel command line string53*54*/55__HEAD56_ENTRY(_stext);57_ENTRY(_start);58/*59* Reserve a word at a fixed location to store the address60* of abatron_pteptrs61*/62nop63/*64* Save parameters we are passed65*/66mr r31,r367mr r30,r468mr r29,r569mr r28,r670mr r27,r771li r24,0 /* CPU number */7273bl init_cpu_state7475/*76* This is where the main kernel code starts.77*/7879/* ptr to current */80lis r2,init_task@h81ori r2,r2,init_task@l8283/* ptr to current thread */84addi r4,r2,THREAD /* init task's THREAD */85mtspr SPRN_SPRG_THREAD,r48687/* stack */88lis r1,init_thread_union@h89ori r1,r1,init_thread_union@l90li r0,091stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)9293bl early_init9495/*96* Decide what sort of machine this is and initialize the MMU.97*/98mr r3,r3199mr r4,r30100mr r5,r29101mr r6,r28102mr r7,r27103bl machine_init104bl MMU_init105106/* Setup PTE pointers for the Abatron bdiGDB */107lis r6, swapper_pg_dir@h108ori r6, r6, swapper_pg_dir@l109lis r5, abatron_pteptrs@h110ori r5, r5, abatron_pteptrs@l111lis r4, KERNELBASE@h112ori r4, r4, KERNELBASE@l113stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */114stw r6, 0(r5)115116/* Clear the Machine Check Syndrome Register */117li r0,0118mtspr SPRN_MCSR,r0119120/* Let's move on */121lis r4,start_kernel@h122ori r4,r4,start_kernel@l123lis r3,MSR_KERNEL@h124ori r3,r3,MSR_KERNEL@l125mtspr SPRN_SRR0,r4126mtspr SPRN_SRR1,r3127rfi /* change context and jump to start_kernel */128129/*130* Interrupt vector entry code131*132* The Book E MMUs are always on so we don't need to handle133* interrupts in real mode as with previous PPC processors. In134* this case we handle interrupts in the kernel virtual address135* space.136*137* Interrupt vectors are dynamically placed relative to the138* interrupt prefix as determined by the address of interrupt_base.139* The interrupt vectors offsets are programmed using the labels140* for each interrupt vector entry.141*142* Interrupt vectors must be aligned on a 16 byte boundary.143* We align on a 32 byte cache line boundary for good measure.144*/145146interrupt_base:147/* Critical Input Interrupt */148CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)149150/* Machine Check Interrupt */151CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)152MCHECK_EXCEPTION(0x0210, MachineCheckA, machine_check_exception)153154/* Data Storage Interrupt */155DATA_STORAGE_EXCEPTION156157/* Instruction Storage Interrupt */158INSTRUCTION_STORAGE_EXCEPTION159160/* External Input Interrupt */161EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)162163/* Alignment Interrupt */164ALIGNMENT_EXCEPTION165166/* Program Interrupt */167PROGRAM_EXCEPTION168169/* Floating Point Unavailable Interrupt */170#ifdef CONFIG_PPC_FPU171FP_UNAVAILABLE_EXCEPTION172#else173EXCEPTION(0x2010, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE)174#endif175/* System Call Interrupt */176START_EXCEPTION(SystemCall)177NORMAL_EXCEPTION_PROLOG178EXC_XFER_EE_LITE(0x0c00, DoSyscall)179180/* Auxiliary Processor Unavailable Interrupt */181EXCEPTION(0x2020, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)182183/* Decrementer Interrupt */184DECREMENTER_EXCEPTION185186/* Fixed Internal Timer Interrupt */187/* TODO: Add FIT support */188EXCEPTION(0x1010, FixedIntervalTimer, unknown_exception, EXC_XFER_EE)189190/* Watchdog Timer Interrupt */191/* TODO: Add watchdog support */192#ifdef CONFIG_BOOKE_WDT193CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException)194#else195CRITICAL_EXCEPTION(0x1020, WatchdogTimer, unknown_exception)196#endif197198/* Data TLB Error Interrupt */199START_EXCEPTION(DataTLBError44x)200mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */201mtspr SPRN_SPRG_WSCRATCH1, r11202mtspr SPRN_SPRG_WSCRATCH2, r12203mtspr SPRN_SPRG_WSCRATCH3, r13204mfcr r11205mtspr SPRN_SPRG_WSCRATCH4, r11206mfspr r10, SPRN_DEAR /* Get faulting address */207208/* If we are faulting a kernel address, we have to use the209* kernel page tables.210*/211lis r11, PAGE_OFFSET@h212cmplw r10, r11213blt+ 3f214lis r11, swapper_pg_dir@h215ori r11, r11, swapper_pg_dir@l216217mfspr r12,SPRN_MMUCR218rlwinm r12,r12,0,0,23 /* Clear TID */219220b 4f221222/* Get the PGD for the current thread */2233:224mfspr r11,SPRN_SPRG_THREAD225lwz r11,PGDIR(r11)226227/* Load PID into MMUCR TID */228mfspr r12,SPRN_MMUCR229mfspr r13,SPRN_PID /* Get PID */230rlwimi r12,r13,0,24,31 /* Set TID */2312324:233mtspr SPRN_MMUCR,r12234235/* Mask of required permission bits. Note that while we236* do copy ESR:ST to _PAGE_RW position as trying to write237* to an RO page is pretty common, we don't do it with238* _PAGE_DIRTY. We could do it, but it's a fairly rare239* event so I'd rather take the overhead when it happens240* rather than adding an instruction here. We should measure241* whether the whole thing is worth it in the first place242* as we could avoid loading SPRN_ESR completely in the first243* place...244*245* TODO: Is it worth doing that mfspr & rlwimi in the first246* place or can we save a couple of instructions here ?247*/248mfspr r12,SPRN_ESR249li r13,_PAGE_PRESENT|_PAGE_ACCESSED250rlwimi r13,r12,10,30,30251252/* Load the PTE */253/* Compute pgdir/pmd offset */254rlwinm r12, r10, PPC44x_PGD_OFF_SHIFT, PPC44x_PGD_OFF_MASK_BIT, 29255lwzx r11, r12, r11 /* Get pgd/pmd entry */256rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */257beq 2f /* Bail if no table */258259/* Compute pte address */260rlwimi r12, r10, PPC44x_PTE_ADD_SHIFT, PPC44x_PTE_ADD_MASK_BIT, 28261lwz r11, 0(r12) /* Get high word of pte entry */262lwz r12, 4(r12) /* Get low word of pte entry */263264lis r10,tlb_44x_index@ha265266andc. r13,r13,r12 /* Check permission */267268/* Load the next available TLB index */269lwz r13,tlb_44x_index@l(r10)270271bne 2f /* Bail if permission mismach */272273/* Increment, rollover, and store TLB index */274addi r13,r13,1275276/* Compare with watermark (instruction gets patched) */277.globl tlb_44x_patch_hwater_D278tlb_44x_patch_hwater_D:279cmpwi 0,r13,1 /* reserve entries */280ble 5f281li r13,02825:283/* Store the next available TLB index */284stw r13,tlb_44x_index@l(r10)285286/* Re-load the faulting address */287mfspr r10,SPRN_DEAR288289/* Jump to common tlb load */290b finish_tlb_load_44x2912922:293/* The bailout. Restore registers to pre-exception conditions294* and call the heavyweights to help us out.295*/296mfspr r11, SPRN_SPRG_RSCRATCH4297mtcr r11298mfspr r13, SPRN_SPRG_RSCRATCH3299mfspr r12, SPRN_SPRG_RSCRATCH2300mfspr r11, SPRN_SPRG_RSCRATCH1301mfspr r10, SPRN_SPRG_RSCRATCH0302b DataStorage303304/* Instruction TLB Error Interrupt */305/*306* Nearly the same as above, except we get our307* information from different registers and bailout308* to a different point.309*/310START_EXCEPTION(InstructionTLBError44x)311mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */312mtspr SPRN_SPRG_WSCRATCH1, r11313mtspr SPRN_SPRG_WSCRATCH2, r12314mtspr SPRN_SPRG_WSCRATCH3, r13315mfcr r11316mtspr SPRN_SPRG_WSCRATCH4, r11317mfspr r10, SPRN_SRR0 /* Get faulting address */318319/* If we are faulting a kernel address, we have to use the320* kernel page tables.321*/322lis r11, PAGE_OFFSET@h323cmplw r10, r11324blt+ 3f325lis r11, swapper_pg_dir@h326ori r11, r11, swapper_pg_dir@l327328mfspr r12,SPRN_MMUCR329rlwinm r12,r12,0,0,23 /* Clear TID */330331b 4f332333/* Get the PGD for the current thread */3343:335mfspr r11,SPRN_SPRG_THREAD336lwz r11,PGDIR(r11)337338/* Load PID into MMUCR TID */339mfspr r12,SPRN_MMUCR340mfspr r13,SPRN_PID /* Get PID */341rlwimi r12,r13,0,24,31 /* Set TID */3423434:344mtspr SPRN_MMUCR,r12345346/* Make up the required permissions */347li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC348349/* Compute pgdir/pmd offset */350rlwinm r12, r10, PPC44x_PGD_OFF_SHIFT, PPC44x_PGD_OFF_MASK_BIT, 29351lwzx r11, r12, r11 /* Get pgd/pmd entry */352rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */353beq 2f /* Bail if no table */354355/* Compute pte address */356rlwimi r12, r10, PPC44x_PTE_ADD_SHIFT, PPC44x_PTE_ADD_MASK_BIT, 28357lwz r11, 0(r12) /* Get high word of pte entry */358lwz r12, 4(r12) /* Get low word of pte entry */359360lis r10,tlb_44x_index@ha361362andc. r13,r13,r12 /* Check permission */363364/* Load the next available TLB index */365lwz r13,tlb_44x_index@l(r10)366367bne 2f /* Bail if permission mismach */368369/* Increment, rollover, and store TLB index */370addi r13,r13,1371372/* Compare with watermark (instruction gets patched) */373.globl tlb_44x_patch_hwater_I374tlb_44x_patch_hwater_I:375cmpwi 0,r13,1 /* reserve entries */376ble 5f377li r13,03785:379/* Store the next available TLB index */380stw r13,tlb_44x_index@l(r10)381382/* Re-load the faulting address */383mfspr r10,SPRN_SRR0384385/* Jump to common TLB load point */386b finish_tlb_load_44x3873882:389/* The bailout. Restore registers to pre-exception conditions390* and call the heavyweights to help us out.391*/392mfspr r11, SPRN_SPRG_RSCRATCH4393mtcr r11394mfspr r13, SPRN_SPRG_RSCRATCH3395mfspr r12, SPRN_SPRG_RSCRATCH2396mfspr r11, SPRN_SPRG_RSCRATCH1397mfspr r10, SPRN_SPRG_RSCRATCH0398b InstructionStorage399400/*401* Both the instruction and data TLB miss get to this402* point to load the TLB.403* r10 - EA of fault404* r11 - PTE high word value405* r12 - PTE low word value406* r13 - TLB index407* MMUCR - loaded with proper value when we get here408* Upon exit, we reload everything and RFI.409*/410finish_tlb_load_44x:411/* Combine RPN & ERPN an write WS 0 */412rlwimi r11,r12,0,0,31-PAGE_SHIFT413tlbwe r11,r13,PPC44x_TLB_XLAT414415/*416* Create WS1. This is the faulting address (EPN),417* page size, and valid flag.418*/419li r11,PPC44x_TLB_VALID | PPC44x_TLBE_SIZE420/* Insert valid and page size */421rlwimi r10,r11,0,PPC44x_PTE_ADD_MASK_BIT,31422tlbwe r10,r13,PPC44x_TLB_PAGEID /* Write PAGEID */423424/* And WS 2 */425li r10,0xf85 /* Mask to apply from PTE */426rlwimi r10,r12,29,30,30 /* DIRTY -> SW position */427and r11,r12,r10 /* Mask PTE bits to keep */428andi. r10,r12,_PAGE_USER /* User page ? */429beq 1f /* nope, leave U bits empty */430rlwimi r11,r11,3,26,28 /* yes, copy S bits to U */4311: tlbwe r11,r13,PPC44x_TLB_ATTRIB /* Write ATTRIB */432433/* Done...restore registers and get out of here.434*/435mfspr r11, SPRN_SPRG_RSCRATCH4436mtcr r11437mfspr r13, SPRN_SPRG_RSCRATCH3438mfspr r12, SPRN_SPRG_RSCRATCH2439mfspr r11, SPRN_SPRG_RSCRATCH1440mfspr r10, SPRN_SPRG_RSCRATCH0441rfi /* Force context change */442443/* TLB error interrupts for 476444*/445#ifdef CONFIG_PPC_47x446START_EXCEPTION(DataTLBError47x)447mtspr SPRN_SPRG_WSCRATCH0,r10 /* Save some working registers */448mtspr SPRN_SPRG_WSCRATCH1,r11449mtspr SPRN_SPRG_WSCRATCH2,r12450mtspr SPRN_SPRG_WSCRATCH3,r13451mfcr r11452mtspr SPRN_SPRG_WSCRATCH4,r11453mfspr r10,SPRN_DEAR /* Get faulting address */454455/* If we are faulting a kernel address, we have to use the456* kernel page tables.457*/458lis r11,PAGE_OFFSET@h459cmplw cr0,r10,r11460blt+ 3f461lis r11,swapper_pg_dir@h462ori r11,r11, swapper_pg_dir@l463li r12,0 /* MMUCR = 0 */464b 4f465466/* Get the PGD for the current thread and setup MMUCR */4673: mfspr r11,SPRN_SPRG3468lwz r11,PGDIR(r11)469mfspr r12,SPRN_PID /* Get PID */4704: mtspr SPRN_MMUCR,r12 /* Set MMUCR */471472/* Mask of required permission bits. Note that while we473* do copy ESR:ST to _PAGE_RW position as trying to write474* to an RO page is pretty common, we don't do it with475* _PAGE_DIRTY. We could do it, but it's a fairly rare476* event so I'd rather take the overhead when it happens477* rather than adding an instruction here. We should measure478* whether the whole thing is worth it in the first place479* as we could avoid loading SPRN_ESR completely in the first480* place...481*482* TODO: Is it worth doing that mfspr & rlwimi in the first483* place or can we save a couple of instructions here ?484*/485mfspr r12,SPRN_ESR486li r13,_PAGE_PRESENT|_PAGE_ACCESSED487rlwimi r13,r12,10,30,30488489/* Load the PTE */490/* Compute pgdir/pmd offset */491rlwinm r12,r10,PPC44x_PGD_OFF_SHIFT,PPC44x_PGD_OFF_MASK_BIT,29492lwzx r11,r12,r11 /* Get pgd/pmd entry */493494/* Word 0 is EPN,V,TS,DSIZ */495li r12,PPC47x_TLB0_VALID | PPC47x_TLBE_SIZE496rlwimi r10,r12,0,32-PAGE_SHIFT,31 /* Insert valid and page size*/497li r12,0498tlbwe r10,r12,0499500/* XXX can we do better ? Need to make sure tlbwe has established501* latch V bit in MMUCR0 before the PTE is loaded further down */502#ifdef CONFIG_SMP503isync504#endif505506rlwinm. r12,r11,0,0,20 /* Extract pt base address */507/* Compute pte address */508rlwimi r12,r10,PPC44x_PTE_ADD_SHIFT,PPC44x_PTE_ADD_MASK_BIT,28509beq 2f /* Bail if no table */510lwz r11,0(r12) /* Get high word of pte entry */511512/* XXX can we do better ? maybe insert a known 0 bit from r11 into the513* bottom of r12 to create a data dependency... We can also use r10514* as destination nowadays515*/516#ifdef CONFIG_SMP517lwsync518#endif519lwz r12,4(r12) /* Get low word of pte entry */520521andc. r13,r13,r12 /* Check permission */522523/* Jump to common tlb load */524beq finish_tlb_load_47x5255262: /* The bailout. Restore registers to pre-exception conditions527* and call the heavyweights to help us out.528*/529mfspr r11,SPRN_SPRG_RSCRATCH4530mtcr r11531mfspr r13,SPRN_SPRG_RSCRATCH3532mfspr r12,SPRN_SPRG_RSCRATCH2533mfspr r11,SPRN_SPRG_RSCRATCH1534mfspr r10,SPRN_SPRG_RSCRATCH0535b DataStorage536537/* Instruction TLB Error Interrupt */538/*539* Nearly the same as above, except we get our540* information from different registers and bailout541* to a different point.542*/543START_EXCEPTION(InstructionTLBError47x)544mtspr SPRN_SPRG_WSCRATCH0,r10 /* Save some working registers */545mtspr SPRN_SPRG_WSCRATCH1,r11546mtspr SPRN_SPRG_WSCRATCH2,r12547mtspr SPRN_SPRG_WSCRATCH3,r13548mfcr r11549mtspr SPRN_SPRG_WSCRATCH4,r11550mfspr r10,SPRN_SRR0 /* Get faulting address */551552/* If we are faulting a kernel address, we have to use the553* kernel page tables.554*/555lis r11,PAGE_OFFSET@h556cmplw cr0,r10,r11557blt+ 3f558lis r11,swapper_pg_dir@h559ori r11,r11, swapper_pg_dir@l560li r12,0 /* MMUCR = 0 */561b 4f562563/* Get the PGD for the current thread and setup MMUCR */5643: mfspr r11,SPRN_SPRG_THREAD565lwz r11,PGDIR(r11)566mfspr r12,SPRN_PID /* Get PID */5674: mtspr SPRN_MMUCR,r12 /* Set MMUCR */568569/* Make up the required permissions */570li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC571572/* Load PTE */573/* Compute pgdir/pmd offset */574rlwinm r12,r10,PPC44x_PGD_OFF_SHIFT,PPC44x_PGD_OFF_MASK_BIT,29575lwzx r11,r12,r11 /* Get pgd/pmd entry */576577/* Word 0 is EPN,V,TS,DSIZ */578li r12,PPC47x_TLB0_VALID | PPC47x_TLBE_SIZE579rlwimi r10,r12,0,32-PAGE_SHIFT,31 /* Insert valid and page size*/580li r12,0581tlbwe r10,r12,0582583/* XXX can we do better ? Need to make sure tlbwe has established584* latch V bit in MMUCR0 before the PTE is loaded further down */585#ifdef CONFIG_SMP586isync587#endif588589rlwinm. r12,r11,0,0,20 /* Extract pt base address */590/* Compute pte address */591rlwimi r12,r10,PPC44x_PTE_ADD_SHIFT,PPC44x_PTE_ADD_MASK_BIT,28592beq 2f /* Bail if no table */593594lwz r11,0(r12) /* Get high word of pte entry */595/* XXX can we do better ? maybe insert a known 0 bit from r11 into the596* bottom of r12 to create a data dependency... We can also use r10597* as destination nowadays598*/599#ifdef CONFIG_SMP600lwsync601#endif602lwz r12,4(r12) /* Get low word of pte entry */603604andc. r13,r13,r12 /* Check permission */605606/* Jump to common TLB load point */607beq finish_tlb_load_47x6086092: /* The bailout. Restore registers to pre-exception conditions610* and call the heavyweights to help us out.611*/612mfspr r11, SPRN_SPRG_RSCRATCH4613mtcr r11614mfspr r13, SPRN_SPRG_RSCRATCH3615mfspr r12, SPRN_SPRG_RSCRATCH2616mfspr r11, SPRN_SPRG_RSCRATCH1617mfspr r10, SPRN_SPRG_RSCRATCH0618b InstructionStorage619620/*621* Both the instruction and data TLB miss get to this622* point to load the TLB.623* r10 - free to use624* r11 - PTE high word value625* r12 - PTE low word value626* r13 - free to use627* MMUCR - loaded with proper value when we get here628* Upon exit, we reload everything and RFI.629*/630finish_tlb_load_47x:631/* Combine RPN & ERPN an write WS 1 */632rlwimi r11,r12,0,0,31-PAGE_SHIFT633tlbwe r11,r13,1634635/* And make up word 2 */636li r10,0xf85 /* Mask to apply from PTE */637rlwimi r10,r12,29,30,30 /* DIRTY -> SW position */638and r11,r12,r10 /* Mask PTE bits to keep */639andi. r10,r12,_PAGE_USER /* User page ? */640beq 1f /* nope, leave U bits empty */641rlwimi r11,r11,3,26,28 /* yes, copy S bits to U */6421: tlbwe r11,r13,2643644/* Done...restore registers and get out of here.645*/646mfspr r11, SPRN_SPRG_RSCRATCH4647mtcr r11648mfspr r13, SPRN_SPRG_RSCRATCH3649mfspr r12, SPRN_SPRG_RSCRATCH2650mfspr r11, SPRN_SPRG_RSCRATCH1651mfspr r10, SPRN_SPRG_RSCRATCH0652rfi653654#endif /* CONFIG_PPC_47x */655656/* Debug Interrupt */657/*658* This statement needs to exist at the end of the IVPR659* definition just in case you end up taking a debug660* exception within another exception.661*/662DEBUG_CRIT_EXCEPTION663664/*665* Global functions666*/667668/*669* Adjust the machine check IVOR on 440A cores670*/671_GLOBAL(__fixup_440A_mcheck)672li r3,MachineCheckA@l673mtspr SPRN_IVOR1,r3674sync675blr676677/*678* extern void giveup_altivec(struct task_struct *prev)679*680* The 44x core does not have an AltiVec unit.681*/682_GLOBAL(giveup_altivec)683blr684685/*686* extern void giveup_fpu(struct task_struct *prev)687*688* The 44x core does not have an FPU.689*/690#ifndef CONFIG_PPC_FPU691_GLOBAL(giveup_fpu)692blr693#endif694695_GLOBAL(set_context)696697#ifdef CONFIG_BDI_SWITCH698/* Context switch the PTE pointer for the Abatron BDI2000.699* The PGDIR is the second parameter.700*/701lis r5, abatron_pteptrs@h702ori r5, r5, abatron_pteptrs@l703stw r4, 0x4(r5)704#endif705mtspr SPRN_PID,r3706isync /* Force context change */707blr708709/*710* Init CPU state. This is called at boot time or for secondary CPUs711* to setup initial TLB entries, setup IVORs, etc...712*713*/714_GLOBAL(init_cpu_state)715mflr r22716#ifdef CONFIG_PPC_47x717/* We use the PVR to differenciate 44x cores from 476 */718mfspr r3,SPRN_PVR719srwi r3,r3,16720cmplwi cr0,r3,PVR_476@h721beq head_start_47x722cmplwi cr0,r3,PVR_476_ISS@h723beq head_start_47x724#endif /* CONFIG_PPC_47x */725726/*727* In case the firmware didn't do it, we apply some workarounds728* that are good for all 440 core variants here729*/730mfspr r3,SPRN_CCR0731rlwinm r3,r3,0,0,27 /* disable icache prefetch */732isync733mtspr SPRN_CCR0,r3734isync735sync736737/*738* Set up the initial MMU state for 44x739*740* We are still executing code at the virtual address741* mappings set by the firmware for the base of RAM.742*743* We first invalidate all TLB entries but the one744* we are running from. We then load the KERNELBASE745* mappings so we can begin to use kernel addresses746* natively and so the interrupt vector locations are747* permanently pinned (necessary since Book E748* implementations always have translation enabled).749*750* TODO: Use the known TLB entry we are running from to751* determine which physical region we are located752* in. This can be used to determine where in RAM753* (on a shared CPU system) or PCI memory space754* (on a DRAMless system) we are located.755* For now, we assume a perfect world which means756* we are located at the base of DRAM (physical 0).757*/758759/*760* Search TLB for entry that we are currently using.761* Invalidate all entries but the one we are using.762*/763/* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */764mfspr r3,SPRN_PID /* Get PID */765mfmsr r4 /* Get MSR */766andi. r4,r4,MSR_IS@l /* TS=1? */767beq wmmucr /* If not, leave STS=0 */768oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */769wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */770sync771772bl invstr /* Find our address */773invstr: mflr r5 /* Make it accessible */774tlbsx r23,0,r5 /* Find entry we are in */775li r4,0 /* Start at TLB entry 0 */776li r3,0 /* Set PAGEID inval value */7771: cmpw r23,r4 /* Is this our entry? */778beq skpinv /* If so, skip the inval */779tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */780skpinv: addi r4,r4,1 /* Increment */781cmpwi r4,64 /* Are we done? */782bne 1b /* If not, repeat */783isync /* If so, context change */784785/*786* Configure and load pinned entry into TLB slot 63.787*/788789lis r3,PAGE_OFFSET@h790ori r3,r3,PAGE_OFFSET@l791792/* Kernel is at the base of RAM */793li r4, 0 /* Load the kernel physical address */794795/* Load the kernel PID = 0 */796li r0,0797mtspr SPRN_PID,r0798sync799800/* Initialize MMUCR */801li r5,0802mtspr SPRN_MMUCR,r5803sync804805/* pageid fields */806clrrwi r3,r3,10 /* Mask off the effective page number */807ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M808809/* xlat fields */810clrrwi r4,r4,10 /* Mask off the real page number */811/* ERPN is 0 for first 4GB page */812813/* attrib fields */814/* Added guarded bit to protect against speculative loads/stores */815li r5,0816ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)817818li r0,63 /* TLB slot 63 */819820tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */821tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */822tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */823824/* Force context change */825mfmsr r0826mtspr SPRN_SRR1, r0827lis r0,3f@h828ori r0,r0,3f@l829mtspr SPRN_SRR0,r0830sync831rfi832833/* If necessary, invalidate original entry we used */8343: cmpwi r23,63835beq 4f836li r6,0837tlbwe r6,r23,PPC44x_TLB_PAGEID838isync8398404:841#ifdef CONFIG_PPC_EARLY_DEBUG_44x842/* Add UART mapping for early debug. */843844/* pageid fields */845lis r3,PPC44x_EARLY_DEBUG_VIRTADDR@h846ori r3,r3,PPC44x_TLB_VALID|PPC44x_TLB_TS|PPC44x_TLB_64K847848/* xlat fields */849lis r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h850ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH851852/* attrib fields */853li r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G)854li r0,62 /* TLB slot 0 */855856tlbwe r3,r0,PPC44x_TLB_PAGEID857tlbwe r4,r0,PPC44x_TLB_XLAT858tlbwe r5,r0,PPC44x_TLB_ATTRIB859860/* Force context change */861isync862#endif /* CONFIG_PPC_EARLY_DEBUG_44x */863864/* Establish the interrupt vector offsets */865SET_IVOR(0, CriticalInput);866SET_IVOR(1, MachineCheck);867SET_IVOR(2, DataStorage);868SET_IVOR(3, InstructionStorage);869SET_IVOR(4, ExternalInput);870SET_IVOR(5, Alignment);871SET_IVOR(6, Program);872SET_IVOR(7, FloatingPointUnavailable);873SET_IVOR(8, SystemCall);874SET_IVOR(9, AuxillaryProcessorUnavailable);875SET_IVOR(10, Decrementer);876SET_IVOR(11, FixedIntervalTimer);877SET_IVOR(12, WatchdogTimer);878SET_IVOR(13, DataTLBError44x);879SET_IVOR(14, InstructionTLBError44x);880SET_IVOR(15, DebugCrit);881882b head_start_common883884885#ifdef CONFIG_PPC_47x886887#ifdef CONFIG_SMP888889/* Entry point for secondary 47x processors */890_GLOBAL(start_secondary_47x)891mr r24,r3 /* CPU number */892893bl init_cpu_state894895/* Now we need to bolt the rest of kernel memory which896* is done in C code. We must be careful because our task897* struct or our stack can (and will probably) be out898* of reach of the initial 256M TLB entry, so we use a899* small temporary stack in .bss for that. This works900* because only one CPU at a time can be in this code901*/902lis r1,temp_boot_stack@h903ori r1,r1,temp_boot_stack@l904addi r1,r1,1024-STACK_FRAME_OVERHEAD905li r0,0906stw r0,0(r1)907bl mmu_init_secondary908909/* Now we can get our task struct and real stack pointer */910911/* Get current_thread_info and current */912lis r1,secondary_ti@ha913lwz r1,secondary_ti@l(r1)914lwz r2,TI_TASK(r1)915916/* Current stack pointer */917addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD918li r0,0919stw r0,0(r1)920921/* Kernel stack for exception entry in SPRG3 */922addi r4,r2,THREAD /* init task's THREAD */923mtspr SPRN_SPRG3,r4924925b start_secondary926927#endif /* CONFIG_SMP */928929/*930* Set up the initial MMU state for 44x931*932* We are still executing code at the virtual address933* mappings set by the firmware for the base of RAM.934*/935936head_start_47x:937/* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */938mfspr r3,SPRN_PID /* Get PID */939mfmsr r4 /* Get MSR */940andi. r4,r4,MSR_IS@l /* TS=1? */941beq 1f /* If not, leave STS=0 */942oris r3,r3,PPC47x_MMUCR_STS@h /* Set STS=1 */9431: mtspr SPRN_MMUCR,r3 /* Put MMUCR */944sync945946/* Find the entry we are running from */947bl 1f9481: mflr r23949tlbsx r23,0,r23950tlbre r24,r23,0951tlbre r25,r23,1952tlbre r26,r23,2953954/*955* Cleanup time956*/957958/* Initialize MMUCR */959li r5,0960mtspr SPRN_MMUCR,r5961sync962963clear_all_utlb_entries:964965#; Set initial values.966967addis r3,0,0x8000968addi r4,0,0969addi r5,0,0970b clear_utlb_entry971972#; Align the loop to speed things up.973974.align 6975976clear_utlb_entry:977978tlbwe r4,r3,0979tlbwe r5,r3,1980tlbwe r5,r3,2981addis r3,r3,0x2000982cmpwi r3,0983bne clear_utlb_entry984addis r3,0,0x8000985addis r4,r4,0x100986cmpwi r4,0987bne clear_utlb_entry988989#; Restore original entry.990991oris r23,r23,0x8000 /* specify the way */992tlbwe r24,r23,0993tlbwe r25,r23,1994tlbwe r26,r23,2995996/*997* Configure and load pinned entry into TLB for the kernel core998*/9991000lis r3,PAGE_OFFSET@h1001ori r3,r3,PAGE_OFFSET@l10021003/* Kernel is at the base of RAM */1004li r4, 0 /* Load the kernel physical address */10051006/* Load the kernel PID = 0 */1007li r0,01008mtspr SPRN_PID,r01009sync10101011/* Word 0 */1012clrrwi r3,r3,12 /* Mask off the effective page number */1013ori r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_256M10141015/* Word 1 */1016clrrwi r4,r4,12 /* Mask off the real page number */1017/* ERPN is 0 for first 4GB page */1018/* Word 2 */1019li r5,01020ori r5,r5,PPC47x_TLB2_S_RWX1021#ifdef CONFIG_SMP1022ori r5,r5,PPC47x_TLB2_M1023#endif10241025/* We write to way 0 and bolted 0 */1026lis r0,0x88001027tlbwe r3,r0,01028tlbwe r4,r0,11029tlbwe r5,r0,210301031/*1032* Configure SSPCR, ISPCR and USPCR for now to search everything, we can fix1033* them up later1034*/1035LOAD_REG_IMMEDIATE(r3, 0x9abcdef0)1036mtspr SPRN_SSPCR,r31037mtspr SPRN_USPCR,r31038LOAD_REG_IMMEDIATE(r3, 0x12345670)1039mtspr SPRN_ISPCR,r310401041/* Force context change */1042mfmsr r01043mtspr SPRN_SRR1, r01044lis r0,3f@h1045ori r0,r0,3f@l1046mtspr SPRN_SRR0,r01047sync1048rfi10491050/* Invalidate original entry we used */10513:1052rlwinm r24,r24,0,21,19 /* clear the "valid" bit */1053tlbwe r24,r23,01054addi r24,0,01055tlbwe r24,r23,11056tlbwe r24,r23,21057isync /* Clear out the shadow TLB entries */10581059#ifdef CONFIG_PPC_EARLY_DEBUG_44x1060/* Add UART mapping for early debug. */10611062/* Word 0 */1063lis r3,PPC44x_EARLY_DEBUG_VIRTADDR@h1064ori r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_TS | PPC47x_TLB0_1M10651066/* Word 1 */1067lis r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW@h1068ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH10691070/* Word 2 */1071li r5,(PPC47x_TLB2_S_RW | PPC47x_TLB2_IMG)10721073/* Bolted in way 0, bolt slot 5, we -hope- we don't hit the same1074* congruence class as the kernel, we need to make sure of it at1075* some point1076*/1077lis r0,0x8d001078tlbwe r3,r0,01079tlbwe r4,r0,11080tlbwe r5,r0,210811082/* Force context change */1083isync1084#endif /* CONFIG_PPC_EARLY_DEBUG_44x */10851086/* Establish the interrupt vector offsets */1087SET_IVOR(0, CriticalInput);1088SET_IVOR(1, MachineCheckA);1089SET_IVOR(2, DataStorage);1090SET_IVOR(3, InstructionStorage);1091SET_IVOR(4, ExternalInput);1092SET_IVOR(5, Alignment);1093SET_IVOR(6, Program);1094SET_IVOR(7, FloatingPointUnavailable);1095SET_IVOR(8, SystemCall);1096SET_IVOR(9, AuxillaryProcessorUnavailable);1097SET_IVOR(10, Decrementer);1098SET_IVOR(11, FixedIntervalTimer);1099SET_IVOR(12, WatchdogTimer);1100SET_IVOR(13, DataTLBError47x);1101SET_IVOR(14, InstructionTLBError47x);1102SET_IVOR(15, DebugCrit);11031104/* We configure icbi to invalidate 128 bytes at a time since the1105* current 32-bit kernel code isn't too happy with icache != dcache1106* block size1107*/1108mfspr r3,SPRN_CCR01109oris r3,r3,0x00201110mtspr SPRN_CCR0,r31111isync11121113#endif /* CONFIG_PPC_47x */11141115/*1116* Here we are back to code that is common between 44x and 47x1117*1118* We proceed to further kernel initialization and return to the1119* main kernel entry1120*/1121head_start_common:1122/* Establish the interrupt vector base */1123lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */1124mtspr SPRN_IVPR,r411251126addis r22,r22,KERNELBASE@h1127mtlr r221128isync1129blr11301131/*1132* We put a few things here that have to be page-aligned. This stuff1133* goes at the beginning of the data segment, which is page-aligned.1134*/1135.data1136.align PAGE_SHIFT1137.globl sdata1138sdata:1139.globl empty_zero_page1140empty_zero_page:1141.space PAGE_SIZE11421143/*1144* To support >32-bit physical addresses, we use an 8KB pgdir.1145*/1146.globl swapper_pg_dir1147swapper_pg_dir:1148.space PGD_TABLE_SIZE11491150/*1151* Room for two PTE pointers, usually the kernel and current user pointers1152* to their respective root page table.1153*/1154abatron_pteptrs:1155.space 811561157#ifdef CONFIG_SMP1158.align 121159temp_boot_stack:1160.space 10241161#endif /* CONFIG_SMP */116211631164