1*14cf11afSPaul Mackerras/* 2*14cf11afSPaul Mackerras * arch/ppc/kernel/head_44x.S 3*14cf11afSPaul Mackerras * 4*14cf11afSPaul Mackerras * Kernel execution entry point code. 5*14cf11afSPaul Mackerras * 6*14cf11afSPaul Mackerras * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> 7*14cf11afSPaul Mackerras * Initial PowerPC version. 8*14cf11afSPaul Mackerras * Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu> 9*14cf11afSPaul Mackerras * Rewritten for PReP 10*14cf11afSPaul Mackerras * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au> 11*14cf11afSPaul Mackerras * Low-level exception handers, MMU support, and rewrite. 12*14cf11afSPaul Mackerras * Copyright (c) 1997 Dan Malek <dmalek@jlc.net> 13*14cf11afSPaul Mackerras * PowerPC 8xx modifications. 14*14cf11afSPaul Mackerras * Copyright (c) 1998-1999 TiVo, Inc. 15*14cf11afSPaul Mackerras * PowerPC 403GCX modifications. 16*14cf11afSPaul Mackerras * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> 17*14cf11afSPaul Mackerras * PowerPC 403GCX/405GP modifications. 18*14cf11afSPaul Mackerras * Copyright 2000 MontaVista Software Inc. 19*14cf11afSPaul Mackerras * PPC405 modifications 20*14cf11afSPaul Mackerras * PowerPC 403GCX/405GP modifications. 21*14cf11afSPaul Mackerras * Author: MontaVista Software, Inc. 22*14cf11afSPaul Mackerras * frank_rowand@mvista.com or source@mvista.com 23*14cf11afSPaul Mackerras * debbie_chu@mvista.com 24*14cf11afSPaul Mackerras * Copyright 2002-2005 MontaVista Software, Inc. 25*14cf11afSPaul Mackerras * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> 26*14cf11afSPaul Mackerras * 27*14cf11afSPaul Mackerras * This program is free software; you can redistribute it and/or modify it 28*14cf11afSPaul Mackerras * under the terms of the GNU General Public License as published by the 29*14cf11afSPaul Mackerras * Free Software Foundation; either version 2 of the License, or (at your 30*14cf11afSPaul Mackerras * option) any later version. 31*14cf11afSPaul Mackerras */ 32*14cf11afSPaul Mackerras 33*14cf11afSPaul Mackerras#include <linux/config.h> 34*14cf11afSPaul Mackerras#include <asm/processor.h> 35*14cf11afSPaul Mackerras#include <asm/page.h> 36*14cf11afSPaul Mackerras#include <asm/mmu.h> 37*14cf11afSPaul Mackerras#include <asm/pgtable.h> 38*14cf11afSPaul Mackerras#include <asm/ibm4xx.h> 39*14cf11afSPaul Mackerras#include <asm/ibm44x.h> 40*14cf11afSPaul Mackerras#include <asm/cputable.h> 41*14cf11afSPaul Mackerras#include <asm/thread_info.h> 42*14cf11afSPaul Mackerras#include <asm/ppc_asm.h> 43*14cf11afSPaul Mackerras#include <asm/asm-offsets.h> 44*14cf11afSPaul Mackerras#include "head_booke.h" 45*14cf11afSPaul Mackerras 46*14cf11afSPaul Mackerras 47*14cf11afSPaul Mackerras/* As with the other PowerPC ports, it is expected that when code 48*14cf11afSPaul Mackerras * execution begins here, the following registers contain valid, yet 49*14cf11afSPaul Mackerras * optional, information: 50*14cf11afSPaul Mackerras * 51*14cf11afSPaul Mackerras * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.) 52*14cf11afSPaul Mackerras * r4 - Starting address of the init RAM disk 53*14cf11afSPaul Mackerras * r5 - Ending address of the init RAM disk 54*14cf11afSPaul Mackerras * r6 - Start of kernel command line string (e.g. "mem=128") 55*14cf11afSPaul Mackerras * r7 - End of kernel command line string 56*14cf11afSPaul Mackerras * 57*14cf11afSPaul Mackerras */ 58*14cf11afSPaul Mackerras .text 59*14cf11afSPaul Mackerras_GLOBAL(_stext) 60*14cf11afSPaul Mackerras_GLOBAL(_start) 61*14cf11afSPaul Mackerras /* 62*14cf11afSPaul Mackerras * Reserve a word at a fixed location to store the address 63*14cf11afSPaul Mackerras * of abatron_pteptrs 64*14cf11afSPaul Mackerras */ 65*14cf11afSPaul Mackerras nop 66*14cf11afSPaul Mackerras/* 67*14cf11afSPaul Mackerras * Save parameters we are passed 68*14cf11afSPaul Mackerras */ 69*14cf11afSPaul Mackerras mr r31,r3 70*14cf11afSPaul Mackerras mr r30,r4 71*14cf11afSPaul Mackerras mr r29,r5 72*14cf11afSPaul Mackerras mr r28,r6 73*14cf11afSPaul Mackerras mr r27,r7 74*14cf11afSPaul Mackerras li r24,0 /* CPU number */ 75*14cf11afSPaul Mackerras 76*14cf11afSPaul Mackerras/* 77*14cf11afSPaul Mackerras * Set up the initial MMU state 78*14cf11afSPaul Mackerras * 79*14cf11afSPaul Mackerras * We are still executing code at the virtual address 80*14cf11afSPaul Mackerras * mappings set by the firmware for the base of RAM. 81*14cf11afSPaul Mackerras * 82*14cf11afSPaul Mackerras * We first invalidate all TLB entries but the one 83*14cf11afSPaul Mackerras * we are running from. We then load the KERNELBASE 84*14cf11afSPaul Mackerras * mappings so we can begin to use kernel addresses 85*14cf11afSPaul Mackerras * natively and so the interrupt vector locations are 86*14cf11afSPaul Mackerras * permanently pinned (necessary since Book E 87*14cf11afSPaul Mackerras * implementations always have translation enabled). 88*14cf11afSPaul Mackerras * 89*14cf11afSPaul Mackerras * TODO: Use the known TLB entry we are running from to 90*14cf11afSPaul Mackerras * determine which physical region we are located 91*14cf11afSPaul Mackerras * in. This can be used to determine where in RAM 92*14cf11afSPaul Mackerras * (on a shared CPU system) or PCI memory space 93*14cf11afSPaul Mackerras * (on a DRAMless system) we are located. 94*14cf11afSPaul Mackerras * For now, we assume a perfect world which means 95*14cf11afSPaul Mackerras * we are located at the base of DRAM (physical 0). 96*14cf11afSPaul Mackerras */ 97*14cf11afSPaul Mackerras 98*14cf11afSPaul Mackerras/* 99*14cf11afSPaul Mackerras * Search TLB for entry that we are currently using. 100*14cf11afSPaul Mackerras * Invalidate all entries but the one we are using. 101*14cf11afSPaul Mackerras */ 102*14cf11afSPaul Mackerras /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */ 103*14cf11afSPaul Mackerras mfspr r3,SPRN_PID /* Get PID */ 104*14cf11afSPaul Mackerras mfmsr r4 /* Get MSR */ 105*14cf11afSPaul Mackerras andi. r4,r4,MSR_IS@l /* TS=1? */ 106*14cf11afSPaul Mackerras beq wmmucr /* If not, leave STS=0 */ 107*14cf11afSPaul Mackerras oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */ 108*14cf11afSPaul Mackerraswmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */ 109*14cf11afSPaul Mackerras sync 110*14cf11afSPaul Mackerras 111*14cf11afSPaul Mackerras bl invstr /* Find our address */ 112*14cf11afSPaul Mackerrasinvstr: mflr r5 /* Make it accessible */ 113*14cf11afSPaul Mackerras tlbsx r23,0,r5 /* Find entry we are in */ 114*14cf11afSPaul Mackerras li r4,0 /* Start at TLB entry 0 */ 115*14cf11afSPaul Mackerras li r3,0 /* Set PAGEID inval value */ 116*14cf11afSPaul Mackerras1: cmpw r23,r4 /* Is this our entry? */ 117*14cf11afSPaul Mackerras beq skpinv /* If so, skip the inval */ 118*14cf11afSPaul Mackerras tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */ 119*14cf11afSPaul Mackerrasskpinv: addi r4,r4,1 /* Increment */ 120*14cf11afSPaul Mackerras cmpwi r4,64 /* Are we done? */ 121*14cf11afSPaul Mackerras bne 1b /* If not, repeat */ 122*14cf11afSPaul Mackerras isync /* If so, context change */ 123*14cf11afSPaul Mackerras 124*14cf11afSPaul Mackerras/* 125*14cf11afSPaul Mackerras * Configure and load pinned entry into TLB slot 63. 126*14cf11afSPaul Mackerras */ 127*14cf11afSPaul Mackerras 128*14cf11afSPaul Mackerras lis r3,KERNELBASE@h /* Load the kernel virtual address */ 129*14cf11afSPaul Mackerras ori r3,r3,KERNELBASE@l 130*14cf11afSPaul Mackerras 131*14cf11afSPaul Mackerras /* Kernel is at the base of RAM */ 132*14cf11afSPaul Mackerras li r4, 0 /* Load the kernel physical address */ 133*14cf11afSPaul Mackerras 134*14cf11afSPaul Mackerras /* Load the kernel PID = 0 */ 135*14cf11afSPaul Mackerras li r0,0 136*14cf11afSPaul Mackerras mtspr SPRN_PID,r0 137*14cf11afSPaul Mackerras sync 138*14cf11afSPaul Mackerras 139*14cf11afSPaul Mackerras /* Initialize MMUCR */ 140*14cf11afSPaul Mackerras li r5,0 141*14cf11afSPaul Mackerras mtspr SPRN_MMUCR,r5 142*14cf11afSPaul Mackerras sync 143*14cf11afSPaul Mackerras 144*14cf11afSPaul Mackerras /* pageid fields */ 145*14cf11afSPaul Mackerras clrrwi r3,r3,10 /* Mask off the effective page number */ 146*14cf11afSPaul Mackerras ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M 147*14cf11afSPaul Mackerras 148*14cf11afSPaul Mackerras /* xlat fields */ 149*14cf11afSPaul Mackerras clrrwi r4,r4,10 /* Mask off the real page number */ 150*14cf11afSPaul Mackerras /* ERPN is 0 for first 4GB page */ 151*14cf11afSPaul Mackerras 152*14cf11afSPaul Mackerras /* attrib fields */ 153*14cf11afSPaul Mackerras /* Added guarded bit to protect against speculative loads/stores */ 154*14cf11afSPaul Mackerras li r5,0 155*14cf11afSPaul Mackerras ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G) 156*14cf11afSPaul Mackerras 157*14cf11afSPaul Mackerras li r0,63 /* TLB slot 63 */ 158*14cf11afSPaul Mackerras 159*14cf11afSPaul Mackerras tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ 160*14cf11afSPaul Mackerras tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ 161*14cf11afSPaul Mackerras tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ 162*14cf11afSPaul Mackerras 163*14cf11afSPaul Mackerras /* Force context change */ 164*14cf11afSPaul Mackerras mfmsr r0 165*14cf11afSPaul Mackerras mtspr SPRN_SRR1, r0 166*14cf11afSPaul Mackerras lis r0,3f@h 167*14cf11afSPaul Mackerras ori r0,r0,3f@l 168*14cf11afSPaul Mackerras mtspr SPRN_SRR0,r0 169*14cf11afSPaul Mackerras sync 170*14cf11afSPaul Mackerras rfi 171*14cf11afSPaul Mackerras 172*14cf11afSPaul Mackerras /* If necessary, invalidate original entry we used */ 173*14cf11afSPaul Mackerras3: cmpwi r23,63 174*14cf11afSPaul Mackerras beq 4f 175*14cf11afSPaul Mackerras li r6,0 176*14cf11afSPaul Mackerras tlbwe r6,r23,PPC44x_TLB_PAGEID 177*14cf11afSPaul Mackerras isync 178*14cf11afSPaul Mackerras 179*14cf11afSPaul Mackerras4: 180*14cf11afSPaul Mackerras#ifdef CONFIG_SERIAL_TEXT_DEBUG 181*14cf11afSPaul Mackerras /* 182*14cf11afSPaul Mackerras * Add temporary UART mapping for early debug. 183*14cf11afSPaul Mackerras * We can map UART registers wherever we want as long as they don't 184*14cf11afSPaul Mackerras * interfere with other system mappings (e.g. with pinned entries). 185*14cf11afSPaul Mackerras * For an example of how we handle this - see ocotea.h. --ebs 186*14cf11afSPaul Mackerras */ 187*14cf11afSPaul Mackerras /* pageid fields */ 188*14cf11afSPaul Mackerras lis r3,UART0_IO_BASE@h 189*14cf11afSPaul Mackerras ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_4K 190*14cf11afSPaul Mackerras 191*14cf11afSPaul Mackerras /* xlat fields */ 192*14cf11afSPaul Mackerras lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */ 193*14cf11afSPaul Mackerras#ifndef CONFIG_440EP 194*14cf11afSPaul Mackerras ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */ 195*14cf11afSPaul Mackerras#endif 196*14cf11afSPaul Mackerras 197*14cf11afSPaul Mackerras /* attrib fields */ 198*14cf11afSPaul Mackerras li r5,0 199*14cf11afSPaul Mackerras ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G) 200*14cf11afSPaul Mackerras 201*14cf11afSPaul Mackerras li r0,0 /* TLB slot 0 */ 202*14cf11afSPaul Mackerras 203*14cf11afSPaul Mackerras tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ 204*14cf11afSPaul Mackerras tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ 205*14cf11afSPaul Mackerras tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ 206*14cf11afSPaul Mackerras 207*14cf11afSPaul Mackerras /* Force context change */ 208*14cf11afSPaul Mackerras isync 209*14cf11afSPaul Mackerras#endif /* CONFIG_SERIAL_TEXT_DEBUG */ 210*14cf11afSPaul Mackerras 211*14cf11afSPaul Mackerras /* Establish the interrupt vector offsets */ 212*14cf11afSPaul Mackerras SET_IVOR(0, CriticalInput); 213*14cf11afSPaul Mackerras SET_IVOR(1, MachineCheck); 214*14cf11afSPaul Mackerras SET_IVOR(2, DataStorage); 215*14cf11afSPaul Mackerras SET_IVOR(3, InstructionStorage); 216*14cf11afSPaul Mackerras SET_IVOR(4, ExternalInput); 217*14cf11afSPaul Mackerras SET_IVOR(5, Alignment); 218*14cf11afSPaul Mackerras SET_IVOR(6, Program); 219*14cf11afSPaul Mackerras SET_IVOR(7, FloatingPointUnavailable); 220*14cf11afSPaul Mackerras SET_IVOR(8, SystemCall); 221*14cf11afSPaul Mackerras SET_IVOR(9, AuxillaryProcessorUnavailable); 222*14cf11afSPaul Mackerras SET_IVOR(10, Decrementer); 223*14cf11afSPaul Mackerras SET_IVOR(11, FixedIntervalTimer); 224*14cf11afSPaul Mackerras SET_IVOR(12, WatchdogTimer); 225*14cf11afSPaul Mackerras SET_IVOR(13, DataTLBError); 226*14cf11afSPaul Mackerras SET_IVOR(14, InstructionTLBError); 227*14cf11afSPaul Mackerras SET_IVOR(15, Debug); 228*14cf11afSPaul Mackerras 229*14cf11afSPaul Mackerras /* Establish the interrupt vector base */ 230*14cf11afSPaul Mackerras lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ 231*14cf11afSPaul Mackerras mtspr SPRN_IVPR,r4 232*14cf11afSPaul Mackerras 233*14cf11afSPaul Mackerras#ifdef CONFIG_440EP 234*14cf11afSPaul Mackerras /* Clear DAPUIB flag in CCR0 (enable APU between CPU and FPU) */ 235*14cf11afSPaul Mackerras mfspr r2,SPRN_CCR0 236*14cf11afSPaul Mackerras lis r3,0xffef 237*14cf11afSPaul Mackerras ori r3,r3,0xffff 238*14cf11afSPaul Mackerras and r2,r2,r3 239*14cf11afSPaul Mackerras mtspr SPRN_CCR0,r2 240*14cf11afSPaul Mackerras isync 241*14cf11afSPaul Mackerras#endif 242*14cf11afSPaul Mackerras 243*14cf11afSPaul Mackerras /* 244*14cf11afSPaul Mackerras * This is where the main kernel code starts. 245*14cf11afSPaul Mackerras */ 246*14cf11afSPaul Mackerras 247*14cf11afSPaul Mackerras /* ptr to current */ 248*14cf11afSPaul Mackerras lis r2,init_task@h 249*14cf11afSPaul Mackerras ori r2,r2,init_task@l 250*14cf11afSPaul Mackerras 251*14cf11afSPaul Mackerras /* ptr to current thread */ 252*14cf11afSPaul Mackerras addi r4,r2,THREAD /* init task's THREAD */ 253*14cf11afSPaul Mackerras mtspr SPRN_SPRG3,r4 254*14cf11afSPaul Mackerras 255*14cf11afSPaul Mackerras /* stack */ 256*14cf11afSPaul Mackerras lis r1,init_thread_union@h 257*14cf11afSPaul Mackerras ori r1,r1,init_thread_union@l 258*14cf11afSPaul Mackerras li r0,0 259*14cf11afSPaul Mackerras stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1) 260*14cf11afSPaul Mackerras 261*14cf11afSPaul Mackerras bl early_init 262*14cf11afSPaul Mackerras 263*14cf11afSPaul Mackerras/* 264*14cf11afSPaul Mackerras * Decide what sort of machine this is and initialize the MMU. 265*14cf11afSPaul Mackerras */ 266*14cf11afSPaul Mackerras mr r3,r31 267*14cf11afSPaul Mackerras mr r4,r30 268*14cf11afSPaul Mackerras mr r5,r29 269*14cf11afSPaul Mackerras mr r6,r28 270*14cf11afSPaul Mackerras mr r7,r27 271*14cf11afSPaul Mackerras bl machine_init 272*14cf11afSPaul Mackerras bl MMU_init 273*14cf11afSPaul Mackerras 274*14cf11afSPaul Mackerras /* Setup PTE pointers for the Abatron bdiGDB */ 275*14cf11afSPaul Mackerras lis r6, swapper_pg_dir@h 276*14cf11afSPaul Mackerras ori r6, r6, swapper_pg_dir@l 277*14cf11afSPaul Mackerras lis r5, abatron_pteptrs@h 278*14cf11afSPaul Mackerras ori r5, r5, abatron_pteptrs@l 279*14cf11afSPaul Mackerras lis r4, KERNELBASE@h 280*14cf11afSPaul Mackerras ori r4, r4, KERNELBASE@l 281*14cf11afSPaul Mackerras stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */ 282*14cf11afSPaul Mackerras stw r6, 0(r5) 283*14cf11afSPaul Mackerras 284*14cf11afSPaul Mackerras /* Let's move on */ 285*14cf11afSPaul Mackerras lis r4,start_kernel@h 286*14cf11afSPaul Mackerras ori r4,r4,start_kernel@l 287*14cf11afSPaul Mackerras lis r3,MSR_KERNEL@h 288*14cf11afSPaul Mackerras ori r3,r3,MSR_KERNEL@l 289*14cf11afSPaul Mackerras mtspr SPRN_SRR0,r4 290*14cf11afSPaul Mackerras mtspr SPRN_SRR1,r3 291*14cf11afSPaul Mackerras rfi /* change context and jump to start_kernel */ 292*14cf11afSPaul Mackerras 293*14cf11afSPaul Mackerras/* 294*14cf11afSPaul Mackerras * Interrupt vector entry code 295*14cf11afSPaul Mackerras * 296*14cf11afSPaul Mackerras * The Book E MMUs are always on so we don't need to handle 297*14cf11afSPaul Mackerras * interrupts in real mode as with previous PPC processors. In 298*14cf11afSPaul Mackerras * this case we handle interrupts in the kernel virtual address 299*14cf11afSPaul Mackerras * space. 300*14cf11afSPaul Mackerras * 301*14cf11afSPaul Mackerras * Interrupt vectors are dynamically placed relative to the 302*14cf11afSPaul Mackerras * interrupt prefix as determined by the address of interrupt_base. 303*14cf11afSPaul Mackerras * The interrupt vectors offsets are programmed using the labels 304*14cf11afSPaul Mackerras * for each interrupt vector entry. 305*14cf11afSPaul Mackerras * 306*14cf11afSPaul Mackerras * Interrupt vectors must be aligned on a 16 byte boundary. 307*14cf11afSPaul Mackerras * We align on a 32 byte cache line boundary for good measure. 308*14cf11afSPaul Mackerras */ 309*14cf11afSPaul Mackerras 310*14cf11afSPaul Mackerrasinterrupt_base: 311*14cf11afSPaul Mackerras /* Critical Input Interrupt */ 312*14cf11afSPaul Mackerras CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException) 313*14cf11afSPaul Mackerras 314*14cf11afSPaul Mackerras /* Machine Check Interrupt */ 315*14cf11afSPaul Mackerras#ifdef CONFIG_440A 316*14cf11afSPaul Mackerras MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException) 317*14cf11afSPaul Mackerras#else 318*14cf11afSPaul Mackerras CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException) 319*14cf11afSPaul Mackerras#endif 320*14cf11afSPaul Mackerras 321*14cf11afSPaul Mackerras /* Data Storage Interrupt */ 322*14cf11afSPaul Mackerras START_EXCEPTION(DataStorage) 323*14cf11afSPaul Mackerras mtspr SPRN_SPRG0, r10 /* Save some working registers */ 324*14cf11afSPaul Mackerras mtspr SPRN_SPRG1, r11 325*14cf11afSPaul Mackerras mtspr SPRN_SPRG4W, r12 326*14cf11afSPaul Mackerras mtspr SPRN_SPRG5W, r13 327*14cf11afSPaul Mackerras mfcr r11 328*14cf11afSPaul Mackerras mtspr SPRN_SPRG7W, r11 329*14cf11afSPaul Mackerras 330*14cf11afSPaul Mackerras /* 331*14cf11afSPaul Mackerras * Check if it was a store fault, if not then bail 332*14cf11afSPaul Mackerras * because a user tried to access a kernel or 333*14cf11afSPaul Mackerras * read-protected page. Otherwise, get the 334*14cf11afSPaul Mackerras * offending address and handle it. 335*14cf11afSPaul Mackerras */ 336*14cf11afSPaul Mackerras mfspr r10, SPRN_ESR 337*14cf11afSPaul Mackerras andis. r10, r10, ESR_ST@h 338*14cf11afSPaul Mackerras beq 2f 339*14cf11afSPaul Mackerras 340*14cf11afSPaul Mackerras mfspr r10, SPRN_DEAR /* Get faulting address */ 341*14cf11afSPaul Mackerras 342*14cf11afSPaul Mackerras /* If we are faulting a kernel address, we have to use the 343*14cf11afSPaul Mackerras * kernel page tables. 344*14cf11afSPaul Mackerras */ 345*14cf11afSPaul Mackerras lis r11, TASK_SIZE@h 346*14cf11afSPaul Mackerras cmplw r10, r11 347*14cf11afSPaul Mackerras blt+ 3f 348*14cf11afSPaul Mackerras lis r11, swapper_pg_dir@h 349*14cf11afSPaul Mackerras ori r11, r11, swapper_pg_dir@l 350*14cf11afSPaul Mackerras 351*14cf11afSPaul Mackerras mfspr r12,SPRN_MMUCR 352*14cf11afSPaul Mackerras rlwinm r12,r12,0,0,23 /* Clear TID */ 353*14cf11afSPaul Mackerras 354*14cf11afSPaul Mackerras b 4f 355*14cf11afSPaul Mackerras 356*14cf11afSPaul Mackerras /* Get the PGD for the current thread */ 357*14cf11afSPaul Mackerras3: 358*14cf11afSPaul Mackerras mfspr r11,SPRN_SPRG3 359*14cf11afSPaul Mackerras lwz r11,PGDIR(r11) 360*14cf11afSPaul Mackerras 361*14cf11afSPaul Mackerras /* Load PID into MMUCR TID */ 362*14cf11afSPaul Mackerras mfspr r12,SPRN_MMUCR /* Get MMUCR */ 363*14cf11afSPaul Mackerras mfspr r13,SPRN_PID /* Get PID */ 364*14cf11afSPaul Mackerras rlwimi r12,r13,0,24,31 /* Set TID */ 365*14cf11afSPaul Mackerras 366*14cf11afSPaul Mackerras4: 367*14cf11afSPaul Mackerras mtspr SPRN_MMUCR,r12 368*14cf11afSPaul Mackerras 369*14cf11afSPaul Mackerras rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 370*14cf11afSPaul Mackerras lwzx r11, r12, r11 /* Get pgd/pmd entry */ 371*14cf11afSPaul Mackerras rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 372*14cf11afSPaul Mackerras beq 2f /* Bail if no table */ 373*14cf11afSPaul Mackerras 374*14cf11afSPaul Mackerras rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 375*14cf11afSPaul Mackerras lwz r11, 4(r12) /* Get pte entry */ 376*14cf11afSPaul Mackerras 377*14cf11afSPaul Mackerras andi. r13, r11, _PAGE_RW /* Is it writeable? */ 378*14cf11afSPaul Mackerras beq 2f /* Bail if not */ 379*14cf11afSPaul Mackerras 380*14cf11afSPaul Mackerras /* Update 'changed'. 381*14cf11afSPaul Mackerras */ 382*14cf11afSPaul Mackerras ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE 383*14cf11afSPaul Mackerras stw r11, 4(r12) /* Update Linux page table */ 384*14cf11afSPaul Mackerras 385*14cf11afSPaul Mackerras li r13, PPC44x_TLB_SR@l /* Set SR */ 386*14cf11afSPaul Mackerras rlwimi r13, r11, 29, 29, 29 /* SX = _PAGE_HWEXEC */ 387*14cf11afSPaul Mackerras rlwimi r13, r11, 0, 30, 30 /* SW = _PAGE_RW */ 388*14cf11afSPaul Mackerras rlwimi r13, r11, 29, 28, 28 /* UR = _PAGE_USER */ 389*14cf11afSPaul Mackerras rlwimi r12, r11, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ 390*14cf11afSPaul Mackerras rlwimi r12, r11, 29, 30, 30 /* (_PAGE_USER>>3)->r12 */ 391*14cf11afSPaul Mackerras and r12, r12, r11 /* HWEXEC/RW & USER */ 392*14cf11afSPaul Mackerras rlwimi r13, r12, 0, 26, 26 /* UX = HWEXEC & USER */ 393*14cf11afSPaul Mackerras rlwimi r13, r12, 3, 27, 27 /* UW = RW & USER */ 394*14cf11afSPaul Mackerras 395*14cf11afSPaul Mackerras rlwimi r11,r13,0,26,31 /* Insert static perms */ 396*14cf11afSPaul Mackerras 397*14cf11afSPaul Mackerras rlwinm r11,r11,0,20,15 /* Clear U0-U3 */ 398*14cf11afSPaul Mackerras 399*14cf11afSPaul Mackerras /* find the TLB index that caused the fault. It has to be here. */ 400*14cf11afSPaul Mackerras tlbsx r10, 0, r10 401*14cf11afSPaul Mackerras 402*14cf11afSPaul Mackerras tlbwe r11, r10, PPC44x_TLB_ATTRIB /* Write ATTRIB */ 403*14cf11afSPaul Mackerras 404*14cf11afSPaul Mackerras /* Done...restore registers and get out of here. 405*14cf11afSPaul Mackerras */ 406*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG7R 407*14cf11afSPaul Mackerras mtcr r11 408*14cf11afSPaul Mackerras mfspr r13, SPRN_SPRG5R 409*14cf11afSPaul Mackerras mfspr r12, SPRN_SPRG4R 410*14cf11afSPaul Mackerras 411*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG1 412*14cf11afSPaul Mackerras mfspr r10, SPRN_SPRG0 413*14cf11afSPaul Mackerras rfi /* Force context change */ 414*14cf11afSPaul Mackerras 415*14cf11afSPaul Mackerras2: 416*14cf11afSPaul Mackerras /* 417*14cf11afSPaul Mackerras * The bailout. Restore registers to pre-exception conditions 418*14cf11afSPaul Mackerras * and call the heavyweights to help us out. 419*14cf11afSPaul Mackerras */ 420*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG7R 421*14cf11afSPaul Mackerras mtcr r11 422*14cf11afSPaul Mackerras mfspr r13, SPRN_SPRG5R 423*14cf11afSPaul Mackerras mfspr r12, SPRN_SPRG4R 424*14cf11afSPaul Mackerras 425*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG1 426*14cf11afSPaul Mackerras mfspr r10, SPRN_SPRG0 427*14cf11afSPaul Mackerras b data_access 428*14cf11afSPaul Mackerras 429*14cf11afSPaul Mackerras /* Instruction Storage Interrupt */ 430*14cf11afSPaul Mackerras INSTRUCTION_STORAGE_EXCEPTION 431*14cf11afSPaul Mackerras 432*14cf11afSPaul Mackerras /* External Input Interrupt */ 433*14cf11afSPaul Mackerras EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE) 434*14cf11afSPaul Mackerras 435*14cf11afSPaul Mackerras /* Alignment Interrupt */ 436*14cf11afSPaul Mackerras ALIGNMENT_EXCEPTION 437*14cf11afSPaul Mackerras 438*14cf11afSPaul Mackerras /* Program Interrupt */ 439*14cf11afSPaul Mackerras PROGRAM_EXCEPTION 440*14cf11afSPaul Mackerras 441*14cf11afSPaul Mackerras /* Floating Point Unavailable Interrupt */ 442*14cf11afSPaul Mackerras#ifdef CONFIG_PPC_FPU 443*14cf11afSPaul Mackerras FP_UNAVAILABLE_EXCEPTION 444*14cf11afSPaul Mackerras#else 445*14cf11afSPaul Mackerras EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE) 446*14cf11afSPaul Mackerras#endif 447*14cf11afSPaul Mackerras 448*14cf11afSPaul Mackerras /* System Call Interrupt */ 449*14cf11afSPaul Mackerras START_EXCEPTION(SystemCall) 450*14cf11afSPaul Mackerras NORMAL_EXCEPTION_PROLOG 451*14cf11afSPaul Mackerras EXC_XFER_EE_LITE(0x0c00, DoSyscall) 452*14cf11afSPaul Mackerras 453*14cf11afSPaul Mackerras /* Auxillary Processor Unavailable Interrupt */ 454*14cf11afSPaul Mackerras EXCEPTION(0x2020, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE) 455*14cf11afSPaul Mackerras 456*14cf11afSPaul Mackerras /* Decrementer Interrupt */ 457*14cf11afSPaul Mackerras DECREMENTER_EXCEPTION 458*14cf11afSPaul Mackerras 459*14cf11afSPaul Mackerras /* Fixed Internal Timer Interrupt */ 460*14cf11afSPaul Mackerras /* TODO: Add FIT support */ 461*14cf11afSPaul Mackerras EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE) 462*14cf11afSPaul Mackerras 463*14cf11afSPaul Mackerras /* Watchdog Timer Interrupt */ 464*14cf11afSPaul Mackerras /* TODO: Add watchdog support */ 465*14cf11afSPaul Mackerras#ifdef CONFIG_BOOKE_WDT 466*14cf11afSPaul Mackerras CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException) 467*14cf11afSPaul Mackerras#else 468*14cf11afSPaul Mackerras CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException) 469*14cf11afSPaul Mackerras#endif 470*14cf11afSPaul Mackerras 471*14cf11afSPaul Mackerras /* Data TLB Error Interrupt */ 472*14cf11afSPaul Mackerras START_EXCEPTION(DataTLBError) 473*14cf11afSPaul Mackerras mtspr SPRN_SPRG0, r10 /* Save some working registers */ 474*14cf11afSPaul Mackerras mtspr SPRN_SPRG1, r11 475*14cf11afSPaul Mackerras mtspr SPRN_SPRG4W, r12 476*14cf11afSPaul Mackerras mtspr SPRN_SPRG5W, r13 477*14cf11afSPaul Mackerras mfcr r11 478*14cf11afSPaul Mackerras mtspr SPRN_SPRG7W, r11 479*14cf11afSPaul Mackerras mfspr r10, SPRN_DEAR /* Get faulting address */ 480*14cf11afSPaul Mackerras 481*14cf11afSPaul Mackerras /* If we are faulting a kernel address, we have to use the 482*14cf11afSPaul Mackerras * kernel page tables. 483*14cf11afSPaul Mackerras */ 484*14cf11afSPaul Mackerras lis r11, TASK_SIZE@h 485*14cf11afSPaul Mackerras cmplw r10, r11 486*14cf11afSPaul Mackerras blt+ 3f 487*14cf11afSPaul Mackerras lis r11, swapper_pg_dir@h 488*14cf11afSPaul Mackerras ori r11, r11, swapper_pg_dir@l 489*14cf11afSPaul Mackerras 490*14cf11afSPaul Mackerras mfspr r12,SPRN_MMUCR 491*14cf11afSPaul Mackerras rlwinm r12,r12,0,0,23 /* Clear TID */ 492*14cf11afSPaul Mackerras 493*14cf11afSPaul Mackerras b 4f 494*14cf11afSPaul Mackerras 495*14cf11afSPaul Mackerras /* Get the PGD for the current thread */ 496*14cf11afSPaul Mackerras3: 497*14cf11afSPaul Mackerras mfspr r11,SPRN_SPRG3 498*14cf11afSPaul Mackerras lwz r11,PGDIR(r11) 499*14cf11afSPaul Mackerras 500*14cf11afSPaul Mackerras /* Load PID into MMUCR TID */ 501*14cf11afSPaul Mackerras mfspr r12,SPRN_MMUCR 502*14cf11afSPaul Mackerras mfspr r13,SPRN_PID /* Get PID */ 503*14cf11afSPaul Mackerras rlwimi r12,r13,0,24,31 /* Set TID */ 504*14cf11afSPaul Mackerras 505*14cf11afSPaul Mackerras4: 506*14cf11afSPaul Mackerras mtspr SPRN_MMUCR,r12 507*14cf11afSPaul Mackerras 508*14cf11afSPaul Mackerras rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 509*14cf11afSPaul Mackerras lwzx r11, r12, r11 /* Get pgd/pmd entry */ 510*14cf11afSPaul Mackerras rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 511*14cf11afSPaul Mackerras beq 2f /* Bail if no table */ 512*14cf11afSPaul Mackerras 513*14cf11afSPaul Mackerras rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 514*14cf11afSPaul Mackerras lwz r11, 4(r12) /* Get pte entry */ 515*14cf11afSPaul Mackerras andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 516*14cf11afSPaul Mackerras beq 2f /* Bail if not present */ 517*14cf11afSPaul Mackerras 518*14cf11afSPaul Mackerras ori r11, r11, _PAGE_ACCESSED 519*14cf11afSPaul Mackerras stw r11, 4(r12) 520*14cf11afSPaul Mackerras 521*14cf11afSPaul Mackerras /* Jump to common tlb load */ 522*14cf11afSPaul Mackerras b finish_tlb_load 523*14cf11afSPaul Mackerras 524*14cf11afSPaul Mackerras2: 525*14cf11afSPaul Mackerras /* The bailout. Restore registers to pre-exception conditions 526*14cf11afSPaul Mackerras * and call the heavyweights to help us out. 527*14cf11afSPaul Mackerras */ 528*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG7R 529*14cf11afSPaul Mackerras mtcr r11 530*14cf11afSPaul Mackerras mfspr r13, SPRN_SPRG5R 531*14cf11afSPaul Mackerras mfspr r12, SPRN_SPRG4R 532*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG1 533*14cf11afSPaul Mackerras mfspr r10, SPRN_SPRG0 534*14cf11afSPaul Mackerras b data_access 535*14cf11afSPaul Mackerras 536*14cf11afSPaul Mackerras /* Instruction TLB Error Interrupt */ 537*14cf11afSPaul Mackerras /* 538*14cf11afSPaul Mackerras * Nearly the same as above, except we get our 539*14cf11afSPaul Mackerras * information from different registers and bailout 540*14cf11afSPaul Mackerras * to a different point. 541*14cf11afSPaul Mackerras */ 542*14cf11afSPaul Mackerras START_EXCEPTION(InstructionTLBError) 543*14cf11afSPaul Mackerras mtspr SPRN_SPRG0, r10 /* Save some working registers */ 544*14cf11afSPaul Mackerras mtspr SPRN_SPRG1, r11 545*14cf11afSPaul Mackerras mtspr SPRN_SPRG4W, r12 546*14cf11afSPaul Mackerras mtspr SPRN_SPRG5W, r13 547*14cf11afSPaul Mackerras mfcr r11 548*14cf11afSPaul Mackerras mtspr SPRN_SPRG7W, r11 549*14cf11afSPaul Mackerras mfspr r10, SPRN_SRR0 /* Get faulting address */ 550*14cf11afSPaul Mackerras 551*14cf11afSPaul Mackerras /* If we are faulting a kernel address, we have to use the 552*14cf11afSPaul Mackerras * kernel page tables. 553*14cf11afSPaul Mackerras */ 554*14cf11afSPaul Mackerras lis r11, TASK_SIZE@h 555*14cf11afSPaul Mackerras cmplw r10, r11 556*14cf11afSPaul Mackerras blt+ 3f 557*14cf11afSPaul Mackerras lis r11, swapper_pg_dir@h 558*14cf11afSPaul Mackerras ori r11, r11, swapper_pg_dir@l 559*14cf11afSPaul Mackerras 560*14cf11afSPaul Mackerras mfspr r12,SPRN_MMUCR 561*14cf11afSPaul Mackerras rlwinm r12,r12,0,0,23 /* Clear TID */ 562*14cf11afSPaul Mackerras 563*14cf11afSPaul Mackerras b 4f 564*14cf11afSPaul Mackerras 565*14cf11afSPaul Mackerras /* Get the PGD for the current thread */ 566*14cf11afSPaul Mackerras3: 567*14cf11afSPaul Mackerras mfspr r11,SPRN_SPRG3 568*14cf11afSPaul Mackerras lwz r11,PGDIR(r11) 569*14cf11afSPaul Mackerras 570*14cf11afSPaul Mackerras /* Load PID into MMUCR TID */ 571*14cf11afSPaul Mackerras mfspr r12,SPRN_MMUCR 572*14cf11afSPaul Mackerras mfspr r13,SPRN_PID /* Get PID */ 573*14cf11afSPaul Mackerras rlwimi r12,r13,0,24,31 /* Set TID */ 574*14cf11afSPaul Mackerras 575*14cf11afSPaul Mackerras4: 576*14cf11afSPaul Mackerras mtspr SPRN_MMUCR,r12 577*14cf11afSPaul Mackerras 578*14cf11afSPaul Mackerras rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ 579*14cf11afSPaul Mackerras lwzx r11, r12, r11 /* Get pgd/pmd entry */ 580*14cf11afSPaul Mackerras rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ 581*14cf11afSPaul Mackerras beq 2f /* Bail if no table */ 582*14cf11afSPaul Mackerras 583*14cf11afSPaul Mackerras rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ 584*14cf11afSPaul Mackerras lwz r11, 4(r12) /* Get pte entry */ 585*14cf11afSPaul Mackerras andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ 586*14cf11afSPaul Mackerras beq 2f /* Bail if not present */ 587*14cf11afSPaul Mackerras 588*14cf11afSPaul Mackerras ori r11, r11, _PAGE_ACCESSED 589*14cf11afSPaul Mackerras stw r11, 4(r12) 590*14cf11afSPaul Mackerras 591*14cf11afSPaul Mackerras /* Jump to common TLB load point */ 592*14cf11afSPaul Mackerras b finish_tlb_load 593*14cf11afSPaul Mackerras 594*14cf11afSPaul Mackerras2: 595*14cf11afSPaul Mackerras /* The bailout. Restore registers to pre-exception conditions 596*14cf11afSPaul Mackerras * and call the heavyweights to help us out. 597*14cf11afSPaul Mackerras */ 598*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG7R 599*14cf11afSPaul Mackerras mtcr r11 600*14cf11afSPaul Mackerras mfspr r13, SPRN_SPRG5R 601*14cf11afSPaul Mackerras mfspr r12, SPRN_SPRG4R 602*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG1 603*14cf11afSPaul Mackerras mfspr r10, SPRN_SPRG0 604*14cf11afSPaul Mackerras b InstructionStorage 605*14cf11afSPaul Mackerras 606*14cf11afSPaul Mackerras /* Debug Interrupt */ 607*14cf11afSPaul Mackerras DEBUG_EXCEPTION 608*14cf11afSPaul Mackerras 609*14cf11afSPaul Mackerras/* 610*14cf11afSPaul Mackerras * Local functions 611*14cf11afSPaul Mackerras */ 612*14cf11afSPaul Mackerras /* 613*14cf11afSPaul Mackerras * Data TLB exceptions will bail out to this point 614*14cf11afSPaul Mackerras * if they can't resolve the lightweight TLB fault. 615*14cf11afSPaul Mackerras */ 616*14cf11afSPaul Mackerrasdata_access: 617*14cf11afSPaul Mackerras NORMAL_EXCEPTION_PROLOG 618*14cf11afSPaul Mackerras mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ 619*14cf11afSPaul Mackerras stw r5,_ESR(r11) 620*14cf11afSPaul Mackerras mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ 621*14cf11afSPaul Mackerras EXC_XFER_EE_LITE(0x0300, handle_page_fault) 622*14cf11afSPaul Mackerras 623*14cf11afSPaul Mackerras/* 624*14cf11afSPaul Mackerras 625*14cf11afSPaul Mackerras * Both the instruction and data TLB miss get to this 626*14cf11afSPaul Mackerras * point to load the TLB. 627*14cf11afSPaul Mackerras * r10 - EA of fault 628*14cf11afSPaul Mackerras * r11 - available to use 629*14cf11afSPaul Mackerras * r12 - Pointer to the 64-bit PTE 630*14cf11afSPaul Mackerras * r13 - available to use 631*14cf11afSPaul Mackerras * MMUCR - loaded with proper value when we get here 632*14cf11afSPaul Mackerras * Upon exit, we reload everything and RFI. 633*14cf11afSPaul Mackerras */ 634*14cf11afSPaul Mackerrasfinish_tlb_load: 635*14cf11afSPaul Mackerras /* 636*14cf11afSPaul Mackerras * We set execute, because we don't have the granularity to 637*14cf11afSPaul Mackerras * properly set this at the page level (Linux problem). 638*14cf11afSPaul Mackerras * If shared is set, we cause a zero PID->TID load. 639*14cf11afSPaul Mackerras * Many of these bits are software only. Bits we don't set 640*14cf11afSPaul Mackerras * here we (properly should) assume have the appropriate value. 641*14cf11afSPaul Mackerras */ 642*14cf11afSPaul Mackerras 643*14cf11afSPaul Mackerras /* Load the next available TLB index */ 644*14cf11afSPaul Mackerras lis r13, tlb_44x_index@ha 645*14cf11afSPaul Mackerras lwz r13, tlb_44x_index@l(r13) 646*14cf11afSPaul Mackerras /* Load the TLB high watermark */ 647*14cf11afSPaul Mackerras lis r11, tlb_44x_hwater@ha 648*14cf11afSPaul Mackerras lwz r11, tlb_44x_hwater@l(r11) 649*14cf11afSPaul Mackerras 650*14cf11afSPaul Mackerras /* Increment, rollover, and store TLB index */ 651*14cf11afSPaul Mackerras addi r13, r13, 1 652*14cf11afSPaul Mackerras cmpw 0, r13, r11 /* reserve entries */ 653*14cf11afSPaul Mackerras ble 7f 654*14cf11afSPaul Mackerras li r13, 0 655*14cf11afSPaul Mackerras7: 656*14cf11afSPaul Mackerras /* Store the next available TLB index */ 657*14cf11afSPaul Mackerras lis r11, tlb_44x_index@ha 658*14cf11afSPaul Mackerras stw r13, tlb_44x_index@l(r11) 659*14cf11afSPaul Mackerras 660*14cf11afSPaul Mackerras lwz r11, 0(r12) /* Get MS word of PTE */ 661*14cf11afSPaul Mackerras lwz r12, 4(r12) /* Get LS word of PTE */ 662*14cf11afSPaul Mackerras rlwimi r11, r12, 0, 0 , 19 /* Insert RPN */ 663*14cf11afSPaul Mackerras tlbwe r11, r13, PPC44x_TLB_XLAT /* Write XLAT */ 664*14cf11afSPaul Mackerras 665*14cf11afSPaul Mackerras /* 666*14cf11afSPaul Mackerras * Create PAGEID. This is the faulting address, 667*14cf11afSPaul Mackerras * page size, and valid flag. 668*14cf11afSPaul Mackerras */ 669*14cf11afSPaul Mackerras li r11, PPC44x_TLB_VALID | PPC44x_TLB_4K 670*14cf11afSPaul Mackerras rlwimi r10, r11, 0, 20, 31 /* Insert valid and page size */ 671*14cf11afSPaul Mackerras tlbwe r10, r13, PPC44x_TLB_PAGEID /* Write PAGEID */ 672*14cf11afSPaul Mackerras 673*14cf11afSPaul Mackerras li r10, PPC44x_TLB_SR@l /* Set SR */ 674*14cf11afSPaul Mackerras rlwimi r10, r12, 0, 30, 30 /* Set SW = _PAGE_RW */ 675*14cf11afSPaul Mackerras rlwimi r10, r12, 29, 29, 29 /* SX = _PAGE_HWEXEC */ 676*14cf11afSPaul Mackerras rlwimi r10, r12, 29, 28, 28 /* UR = _PAGE_USER */ 677*14cf11afSPaul Mackerras rlwimi r11, r12, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ 678*14cf11afSPaul Mackerras and r11, r12, r11 /* HWEXEC & USER */ 679*14cf11afSPaul Mackerras rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */ 680*14cf11afSPaul Mackerras 681*14cf11afSPaul Mackerras rlwimi r12, r10, 0, 26, 31 /* Insert static perms */ 682*14cf11afSPaul Mackerras rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */ 683*14cf11afSPaul Mackerras tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */ 684*14cf11afSPaul Mackerras 685*14cf11afSPaul Mackerras /* Done...restore registers and get out of here. 686*14cf11afSPaul Mackerras */ 687*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG7R 688*14cf11afSPaul Mackerras mtcr r11 689*14cf11afSPaul Mackerras mfspr r13, SPRN_SPRG5R 690*14cf11afSPaul Mackerras mfspr r12, SPRN_SPRG4R 691*14cf11afSPaul Mackerras mfspr r11, SPRN_SPRG1 692*14cf11afSPaul Mackerras mfspr r10, SPRN_SPRG0 693*14cf11afSPaul Mackerras rfi /* Force context change */ 694*14cf11afSPaul Mackerras 695*14cf11afSPaul Mackerras/* 696*14cf11afSPaul Mackerras * Global functions 697*14cf11afSPaul Mackerras */ 698*14cf11afSPaul Mackerras 699*14cf11afSPaul Mackerras/* 700*14cf11afSPaul Mackerras * extern void giveup_altivec(struct task_struct *prev) 701*14cf11afSPaul Mackerras * 702*14cf11afSPaul Mackerras * The 44x core does not have an AltiVec unit. 703*14cf11afSPaul Mackerras */ 704*14cf11afSPaul Mackerras_GLOBAL(giveup_altivec) 705*14cf11afSPaul Mackerras blr 706*14cf11afSPaul Mackerras 707*14cf11afSPaul Mackerras/* 708*14cf11afSPaul Mackerras * extern void giveup_fpu(struct task_struct *prev) 709*14cf11afSPaul Mackerras * 710*14cf11afSPaul Mackerras * The 44x core does not have an FPU. 711*14cf11afSPaul Mackerras */ 712*14cf11afSPaul Mackerras#ifndef CONFIG_PPC_FPU 713*14cf11afSPaul Mackerras_GLOBAL(giveup_fpu) 714*14cf11afSPaul Mackerras blr 715*14cf11afSPaul Mackerras#endif 716*14cf11afSPaul Mackerras 717*14cf11afSPaul Mackerras/* 718*14cf11afSPaul Mackerras * extern void abort(void) 719*14cf11afSPaul Mackerras * 720*14cf11afSPaul Mackerras * At present, this routine just applies a system reset. 721*14cf11afSPaul Mackerras */ 722*14cf11afSPaul Mackerras_GLOBAL(abort) 723*14cf11afSPaul Mackerras mfspr r13,SPRN_DBCR0 724*14cf11afSPaul Mackerras oris r13,r13,DBCR0_RST_SYSTEM@h 725*14cf11afSPaul Mackerras mtspr SPRN_DBCR0,r13 726*14cf11afSPaul Mackerras 727*14cf11afSPaul Mackerras_GLOBAL(set_context) 728*14cf11afSPaul Mackerras 729*14cf11afSPaul Mackerras#ifdef CONFIG_BDI_SWITCH 730*14cf11afSPaul Mackerras /* Context switch the PTE pointer for the Abatron BDI2000. 731*14cf11afSPaul Mackerras * The PGDIR is the second parameter. 732*14cf11afSPaul Mackerras */ 733*14cf11afSPaul Mackerras lis r5, abatron_pteptrs@h 734*14cf11afSPaul Mackerras ori r5, r5, abatron_pteptrs@l 735*14cf11afSPaul Mackerras stw r4, 0x4(r5) 736*14cf11afSPaul Mackerras#endif 737*14cf11afSPaul Mackerras mtspr SPRN_PID,r3 738*14cf11afSPaul Mackerras isync /* Force context change */ 739*14cf11afSPaul Mackerras blr 740*14cf11afSPaul Mackerras 741*14cf11afSPaul Mackerras/* 742*14cf11afSPaul Mackerras * We put a few things here that have to be page-aligned. This stuff 743*14cf11afSPaul Mackerras * goes at the beginning of the data segment, which is page-aligned. 744*14cf11afSPaul Mackerras */ 745*14cf11afSPaul Mackerras .data 746*14cf11afSPaul Mackerras_GLOBAL(sdata) 747*14cf11afSPaul Mackerras_GLOBAL(empty_zero_page) 748*14cf11afSPaul Mackerras .space 4096 749*14cf11afSPaul Mackerras 750*14cf11afSPaul Mackerras/* 751*14cf11afSPaul Mackerras * To support >32-bit physical addresses, we use an 8KB pgdir. 752*14cf11afSPaul Mackerras */ 753*14cf11afSPaul Mackerras_GLOBAL(swapper_pg_dir) 754*14cf11afSPaul Mackerras .space 8192 755*14cf11afSPaul Mackerras 756*14cf11afSPaul Mackerras/* Reserved 4k for the critical exception stack & 4k for the machine 757*14cf11afSPaul Mackerras * check stack per CPU for kernel mode exceptions */ 758*14cf11afSPaul Mackerras .section .bss 759*14cf11afSPaul Mackerras .align 12 760*14cf11afSPaul Mackerrasexception_stack_bottom: 761*14cf11afSPaul Mackerras .space BOOKE_EXCEPTION_STACK_SIZE 762*14cf11afSPaul Mackerras_GLOBAL(exception_stack_top) 763*14cf11afSPaul Mackerras 764*14cf11afSPaul Mackerras/* 765*14cf11afSPaul Mackerras * This space gets a copy of optional info passed to us by the bootstrap 766*14cf11afSPaul Mackerras * which is used to pass parameters into the kernel like root=/dev/sda1, etc. 767*14cf11afSPaul Mackerras */ 768*14cf11afSPaul Mackerras_GLOBAL(cmd_line) 769*14cf11afSPaul Mackerras .space 512 770*14cf11afSPaul Mackerras 771*14cf11afSPaul Mackerras/* 772*14cf11afSPaul Mackerras * Room for two PTE pointers, usually the kernel and current user pointers 773*14cf11afSPaul Mackerras * to their respective root page table. 774*14cf11afSPaul Mackerras */ 775*14cf11afSPaul Mackerrasabatron_pteptrs: 776*14cf11afSPaul Mackerras .space 8 777*14cf11afSPaul Mackerras 778*14cf11afSPaul Mackerras 779