OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [powerpc/] [kernel/] [head_fsl_booke.S] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * Kernel execution entry point code.
3
 *
4
 *    Copyright (c) 1995-1996 Gary Thomas 
5
 *      Initial PowerPC version.
6
 *    Copyright (c) 1996 Cort Dougan 
7
 *      Rewritten for PReP
8
 *    Copyright (c) 1996 Paul Mackerras 
9
 *      Low-level exception handers, MMU support, and rewrite.
10
 *    Copyright (c) 1997 Dan Malek 
11
 *      PowerPC 8xx modifications.
12
 *    Copyright (c) 1998-1999 TiVo, Inc.
13
 *      PowerPC 403GCX modifications.
14
 *    Copyright (c) 1999 Grant Erickson 
15
 *      PowerPC 403GCX/405GP modifications.
16
 *    Copyright 2000 MontaVista Software Inc.
17
 *      PPC405 modifications
18
 *      PowerPC 403GCX/405GP modifications.
19
 *      Author: MontaVista Software, Inc.
20
 *              frank_rowand@mvista.com or source@mvista.com
21
 *              debbie_chu@mvista.com
22
 *    Copyright 2002-2004 MontaVista Software, Inc.
23
 *      PowerPC 44x support, Matt Porter 
24
 *    Copyright 2004 Freescale Semiconductor, Inc
25
 *      PowerPC e500 modifications, Kumar Gala 
26
 *
27
 * This program is free software; you can redistribute  it and/or modify it
28
 * under  the terms of  the GNU General  Public License as published by the
29
 * Free Software Foundation;  either version 2 of the  License, or (at your
30
 * option) any later version.
31
 */
32
 
33
#include 
34
#include 
35
#include 
36
#include 
37
#include 
38
#include 
39
#include 
40
#include 
41
#include 
42
#include "head_booke.h"
43
 
44
/* As with the other PowerPC ports, it is expected that when code
45
 * execution begins here, the following registers contain valid, yet
46
 * optional, information:
47
 *
48
 *   r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
49
 *   r4 - Starting address of the init RAM disk
50
 *   r5 - Ending address of the init RAM disk
51
 *   r6 - Start of kernel command line string (e.g. "mem=128")
52
 *   r7 - End of kernel command line string
53
 *
54
 */
55
        .section        .text.head, "ax"
56
_ENTRY(_stext);
57
_ENTRY(_start);
58
        /*
59
         * Reserve a word at a fixed location to store the address
60
         * of abatron_pteptrs
61
         */
62
        nop
63
/*
64
 * Save parameters we are passed
65
 */
66
        mr      r31,r3
67
        mr      r30,r4
68
        mr      r29,r5
69
        mr      r28,r6
70
        mr      r27,r7
71
        li      r24,0           /* CPU number */
72
 
73
/* We try to not make any assumptions about how the boot loader
74
 * setup or used the TLBs.  We invalidate all mappings from the
75
 * boot loader and load a single entry in TLB1[0] to map the
76
 * first 16M of kernel memory.  Any boot info passed from the
77
 * bootloader needs to live in this first 16M.
78
 *
79
 * Requirement on bootloader:
80
 *  - The page we're executing in needs to reside in TLB1 and
81
 *    have IPROT=1.  If not an invalidate broadcast could
82
 *    evict the entry we're currently executing in.
83
 *
84
 *  r3 = Index of TLB1 were executing in
85
 *  r4 = Current MSR[IS]
86
 *  r5 = Index of TLB1 temp mapping
87
 *
88
 * Later in mapin_ram we will correctly map lowmem, and resize TLB1[0]
89
 * if needed
90
 */
91
 
92
/* 1. Find the index of the entry we're executing in */
93
        bl      invstr                          /* Find our address */
94
invstr: mflr    r6                              /* Make it accessible */
95
        mfmsr   r7
96
        rlwinm  r4,r7,27,31,31                  /* extract MSR[IS] */
97
        mfspr   r7, SPRN_PID0
98
        slwi    r7,r7,16
99
        or      r7,r7,r4
100
        mtspr   SPRN_MAS6,r7
101
        tlbsx   0,r6                            /* search MSR[IS], SPID=PID0 */
102
#ifndef CONFIG_E200
103
        mfspr   r7,SPRN_MAS1
104
        andis.  r7,r7,MAS1_VALID@h
105
        bne     match_TLB
106
        mfspr   r7,SPRN_PID1
107
        slwi    r7,r7,16
108
        or      r7,r7,r4
109
        mtspr   SPRN_MAS6,r7
110
        tlbsx   0,r6                            /* search MSR[IS], SPID=PID1 */
111
        mfspr   r7,SPRN_MAS1
112
        andis.  r7,r7,MAS1_VALID@h
113
        bne     match_TLB
114
        mfspr   r7, SPRN_PID2
115
        slwi    r7,r7,16
116
        or      r7,r7,r4
117
        mtspr   SPRN_MAS6,r7
118
        tlbsx   0,r6                            /* Fall through, we had to match */
119
#endif
120
match_TLB:
121
        mfspr   r7,SPRN_MAS0
122
        rlwinm  r3,r7,16,20,31                  /* Extract MAS0(Entry) */
123
 
124
        mfspr   r7,SPRN_MAS1                    /* Insure IPROT set */
125
        oris    r7,r7,MAS1_IPROT@h
126
        mtspr   SPRN_MAS1,r7
127
        tlbwe
128
 
129
/* 2. Invalidate all entries except the entry we're executing in */
130
        mfspr   r9,SPRN_TLB1CFG
131
        andi.   r9,r9,0xfff
132
        li      r6,0                            /* Set Entry counter to 0 */
133
1:      lis     r7,0x1000                       /* Set MAS0(TLBSEL) = 1 */
134
        rlwimi  r7,r6,16,4,15                   /* Setup MAS0 = TLBSEL | ESEL(r6) */
135
        mtspr   SPRN_MAS0,r7
136
        tlbre
137
        mfspr   r7,SPRN_MAS1
138
        rlwinm  r7,r7,0,2,31                    /* Clear MAS1 Valid and IPROT */
139
        cmpw    r3,r6
140
        beq     skpinv                          /* Dont update the current execution TLB */
141
        mtspr   SPRN_MAS1,r7
142
        tlbwe
143
        isync
144
skpinv: addi    r6,r6,1                         /* Increment */
145
        cmpw    r6,r9                           /* Are we done? */
146
        bne     1b                              /* If not, repeat */
147
 
148
        /* Invalidate TLB0 */
149
        li      r6,0x04
150
        tlbivax 0,r6
151
#ifdef CONFIG_SMP
152
        tlbsync
153
#endif
154
        /* Invalidate TLB1 */
155
        li      r6,0x0c
156
        tlbivax 0,r6
157
#ifdef CONFIG_SMP
158
        tlbsync
159
#endif
160
        msync
161
 
162
/* 3. Setup a temp mapping and jump to it */
163
        andi.   r5, r3, 0x1     /* Find an entry not used and is non-zero */
164
        addi    r5, r5, 0x1
165
        lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
166
        rlwimi  r7,r3,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r3) */
167
        mtspr   SPRN_MAS0,r7
168
        tlbre
169
 
170
        /* Just modify the entry ID and EPN for the temp mapping */
171
        lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
172
        rlwimi  r7,r5,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r5) */
173
        mtspr   SPRN_MAS0,r7
174
        xori    r6,r4,1         /* Setup TMP mapping in the other Address space */
175
        slwi    r6,r6,12
176
        oris    r6,r6,(MAS1_VALID|MAS1_IPROT)@h
177
        ori     r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
178
        mtspr   SPRN_MAS1,r6
179
        mfspr   r6,SPRN_MAS2
180
        li      r7,0            /* temp EPN = 0 */
181
        rlwimi  r7,r6,0,20,31
182
        mtspr   SPRN_MAS2,r7
183
        tlbwe
184
 
185
        xori    r6,r4,1
186
        slwi    r6,r6,5         /* setup new context with other address space */
187
        bl      1f              /* Find our address */
188
1:      mflr    r9
189
        rlwimi  r7,r9,0,20,31
190
        addi    r7,r7,24
191
        mtspr   SPRN_SRR0,r7
192
        mtspr   SPRN_SRR1,r6
193
        rfi
194
 
195
/* 4. Clear out PIDs & Search info */
196
        li      r6,0
197
        mtspr   SPRN_PID0,r6
198
#ifndef CONFIG_E200
199
        mtspr   SPRN_PID1,r6
200
        mtspr   SPRN_PID2,r6
201
#endif
202
        mtspr   SPRN_MAS6,r6
203
 
204
/* 5. Invalidate mapping we started in */
205
        lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
206
        rlwimi  r7,r3,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r3) */
207
        mtspr   SPRN_MAS0,r7
208
        tlbre
209
        mfspr   r6,SPRN_MAS1
210
        rlwinm  r6,r6,0,2,0     /* clear IPROT */
211
        mtspr   SPRN_MAS1,r6
212
        tlbwe
213
        /* Invalidate TLB1 */
214
        li      r9,0x0c
215
        tlbivax 0,r9
216
#ifdef CONFIG_SMP
217
        tlbsync
218
#endif
219
        msync
220
 
221
/* 6. Setup KERNELBASE mapping in TLB1[0] */
222
        lis     r6,0x1000               /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
223
        mtspr   SPRN_MAS0,r6
224
        lis     r6,(MAS1_VALID|MAS1_IPROT)@h
225
        ori     r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_16M))@l
226
        mtspr   SPRN_MAS1,r6
227
        li      r7,0
228
        lis     r6,KERNELBASE@h
229
        ori     r6,r6,KERNELBASE@l
230
        rlwimi  r6,r7,0,20,31
231
        mtspr   SPRN_MAS2,r6
232
        li      r7,(MAS3_SX|MAS3_SW|MAS3_SR)
233
        mtspr   SPRN_MAS3,r7
234
        tlbwe
235
 
236
/* 7. Jump to KERNELBASE mapping */
237
        lis     r7,MSR_KERNEL@h
238
        ori     r7,r7,MSR_KERNEL@l
239
        bl      1f                      /* Find our address */
240
1:      mflr    r9
241
        rlwimi  r6,r9,0,20,31
242
        addi    r6,r6,24
243
        mtspr   SPRN_SRR0,r6
244
        mtspr   SPRN_SRR1,r7
245
        rfi                             /* start execution out of TLB1[0] entry */
246
 
247
/* 8. Clear out the temp mapping */
248
        lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
249
        rlwimi  r7,r5,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r5) */
250
        mtspr   SPRN_MAS0,r7
251
        tlbre
252
        mfspr   r8,SPRN_MAS1
253
        rlwinm  r8,r8,0,2,0     /* clear IPROT */
254
        mtspr   SPRN_MAS1,r8
255
        tlbwe
256
        /* Invalidate TLB1 */
257
        li      r9,0x0c
258
        tlbivax 0,r9
259
#ifdef CONFIG_SMP
260
        tlbsync
261
#endif
262
        msync
263
 
264
        /* Establish the interrupt vector offsets */
265
        SET_IVOR(0,  CriticalInput);
266
        SET_IVOR(1,  MachineCheck);
267
        SET_IVOR(2,  DataStorage);
268
        SET_IVOR(3,  InstructionStorage);
269
        SET_IVOR(4,  ExternalInput);
270
        SET_IVOR(5,  Alignment);
271
        SET_IVOR(6,  Program);
272
        SET_IVOR(7,  FloatingPointUnavailable);
273
        SET_IVOR(8,  SystemCall);
274
        SET_IVOR(9,  AuxillaryProcessorUnavailable);
275
        SET_IVOR(10, Decrementer);
276
        SET_IVOR(11, FixedIntervalTimer);
277
        SET_IVOR(12, WatchdogTimer);
278
        SET_IVOR(13, DataTLBError);
279
        SET_IVOR(14, InstructionTLBError);
280
        SET_IVOR(15, Debug);
281
        SET_IVOR(32, SPEUnavailable);
282
        SET_IVOR(33, SPEFloatingPointData);
283
        SET_IVOR(34, SPEFloatingPointRound);
284
#ifndef CONFIG_E200
285
        SET_IVOR(35, PerformanceMonitor);
286
#endif
287
 
288
        /* Establish the interrupt vector base */
289
        lis     r4,interrupt_base@h     /* IVPR only uses the high 16-bits */
290
        mtspr   SPRN_IVPR,r4
291
 
292
        /* Setup the defaults for TLB entries */
293
        li      r2,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l
294
#ifdef CONFIG_E200
295
        oris    r2,r2,MAS4_TLBSELD(1)@h
296
#endif
297
        mtspr   SPRN_MAS4, r2
298
 
299
#if 0
300
        /* Enable DOZE */
301
        mfspr   r2,SPRN_HID0
302
        oris    r2,r2,HID0_DOZE@h
303
        mtspr   SPRN_HID0, r2
304
#endif
305
#ifdef CONFIG_E200
306
        /* enable dedicated debug exception handling resources (Debug APU) */
307
        mfspr   r2,SPRN_HID0
308
        ori     r2,r2,HID0_DAPUEN@l
309
        mtspr   SPRN_HID0,r2
310
#endif
311
 
312
#if !defined(CONFIG_BDI_SWITCH)
313
        /*
314
         * The Abatron BDI JTAG debugger does not tolerate others
315
         * mucking with the debug registers.
316
         */
317
        lis     r2,DBCR0_IDM@h
318
        mtspr   SPRN_DBCR0,r2
319
        isync
320
        /* clear any residual debug events */
321
        li      r2,-1
322
        mtspr   SPRN_DBSR,r2
323
#endif
324
 
325
        /*
326
         * This is where the main kernel code starts.
327
         */
328
 
329
        /* ptr to current */
330
        lis     r2,init_task@h
331
        ori     r2,r2,init_task@l
332
 
333
        /* ptr to current thread */
334
        addi    r4,r2,THREAD    /* init task's THREAD */
335
        mtspr   SPRN_SPRG3,r4
336
 
337
        /* stack */
338
        lis     r1,init_thread_union@h
339
        ori     r1,r1,init_thread_union@l
340
        li      r0,0
341
        stwu    r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
342
 
343
        bl      early_init
344
 
345
        mfspr   r3,SPRN_TLB1CFG
346
        andi.   r3,r3,0xfff
347
        lis     r4,num_tlbcam_entries@ha
348
        stw     r3,num_tlbcam_entries@l(r4)
349
/*
350
 * Decide what sort of machine this is and initialize the MMU.
351
 */
352
        mr      r3,r31
353
        mr      r4,r30
354
        mr      r5,r29
355
        mr      r6,r28
356
        mr      r7,r27
357
        bl      machine_init
358
        bl      MMU_init
359
 
360
        /* Setup PTE pointers for the Abatron bdiGDB */
361
        lis     r6, swapper_pg_dir@h
362
        ori     r6, r6, swapper_pg_dir@l
363
        lis     r5, abatron_pteptrs@h
364
        ori     r5, r5, abatron_pteptrs@l
365
        lis     r4, KERNELBASE@h
366
        ori     r4, r4, KERNELBASE@l
367
        stw     r5, 0(r4)       /* Save abatron_pteptrs at a fixed location */
368
        stw     r6, 0(r5)
369
 
370
        /* Let's move on */
371
        lis     r4,start_kernel@h
372
        ori     r4,r4,start_kernel@l
373
        lis     r3,MSR_KERNEL@h
374
        ori     r3,r3,MSR_KERNEL@l
375
        mtspr   SPRN_SRR0,r4
376
        mtspr   SPRN_SRR1,r3
377
        rfi                     /* change context and jump to start_kernel */
378
 
379
/* Macros to hide the PTE size differences
380
 *
381
 * FIND_PTE -- walks the page tables given EA & pgdir pointer
382
 *   r10 -- EA of fault
383
 *   r11 -- PGDIR pointer
384
 *   r12 -- free
385
 *   label 2: is the bailout case
386
 *
387
 * if we find the pte (fall through):
388
 *   r11 is low pte word
389
 *   r12 is pointer to the pte
390
 */
391
#ifdef CONFIG_PTE_64BIT
392
#define PTE_FLAGS_OFFSET        4
393
#define FIND_PTE        \
394
        rlwinm  r12, r10, 13, 19, 29;   /* Compute pgdir/pmd offset */  \
395
        lwzx    r11, r12, r11;          /* Get pgd/pmd entry */         \
396
        rlwinm. r12, r11, 0, 0, 20;     /* Extract pt base address */   \
397
        beq     2f;                     /* Bail if no table */          \
398
        rlwimi  r12, r10, 23, 20, 28;   /* Compute pte address */       \
399
        lwz     r11, 4(r12);            /* Get pte entry */
400
#else
401
#define PTE_FLAGS_OFFSET        0
402
#define FIND_PTE        \
403
        rlwimi  r11, r10, 12, 20, 29;   /* Create L1 (pgdir/pmd) address */     \
404
        lwz     r11, 0(r11);            /* Get L1 entry */                      \
405
        rlwinm. r12, r11, 0, 0, 19;     /* Extract L2 (pte) base address */     \
406
        beq     2f;                     /* Bail if no table */                  \
407
        rlwimi  r12, r10, 22, 20, 29;   /* Compute PTE address */               \
408
        lwz     r11, 0(r12);            /* Get Linux PTE */
409
#endif
410
 
411
/*
412
 * Interrupt vector entry code
413
 *
414
 * The Book E MMUs are always on so we don't need to handle
415
 * interrupts in real mode as with previous PPC processors. In
416
 * this case we handle interrupts in the kernel virtual address
417
 * space.
418
 *
419
 * Interrupt vectors are dynamically placed relative to the
420
 * interrupt prefix as determined by the address of interrupt_base.
421
 * The interrupt vectors offsets are programmed using the labels
422
 * for each interrupt vector entry.
423
 *
424
 * Interrupt vectors must be aligned on a 16 byte boundary.
425
 * We align on a 32 byte cache line boundary for good measure.
426
 */
427
 
428
interrupt_base:
429
        /* Critical Input Interrupt */
430
        CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
431
 
432
        /* Machine Check Interrupt */
433
#ifdef CONFIG_E200
434
        /* no RFMCI, MCSRRs on E200 */
435
        CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
436
#else
437
        MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
438
#endif
439
 
440
        /* Data Storage Interrupt */
441
        START_EXCEPTION(DataStorage)
442
        mtspr   SPRN_SPRG0, r10         /* Save some working registers */
443
        mtspr   SPRN_SPRG1, r11
444
        mtspr   SPRN_SPRG4W, r12
445
        mtspr   SPRN_SPRG5W, r13
446
        mfcr    r11
447
        mtspr   SPRN_SPRG7W, r11
448
 
449
        /*
450
         * Check if it was a store fault, if not then bail
451
         * because a user tried to access a kernel or
452
         * read-protected page.  Otherwise, get the
453
         * offending address and handle it.
454
         */
455
        mfspr   r10, SPRN_ESR
456
        andis.  r10, r10, ESR_ST@h
457
        beq     2f
458
 
459
        mfspr   r10, SPRN_DEAR          /* Get faulting address */
460
 
461
        /* If we are faulting a kernel address, we have to use the
462
         * kernel page tables.
463
         */
464
        lis     r11, PAGE_OFFSET@h
465
        cmplw   0, r10, r11
466
        bge     2f
467
 
468
        /* Get the PGD for the current thread */
469
3:
470
        mfspr   r11,SPRN_SPRG3
471
        lwz     r11,PGDIR(r11)
472
4:
473
        FIND_PTE
474
 
475
        /* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */
476
        andi.   r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE
477
        cmpwi   0, r13, _PAGE_RW|_PAGE_USER
478
        bne     2f                      /* Bail if not */
479
 
480
        /* Update 'changed'. */
481
        ori     r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
482
        stw     r11, PTE_FLAGS_OFFSET(r12) /* Update Linux page table */
483
 
484
        /* MAS2 not updated as the entry does exist in the tlb, this
485
           fault taken to detect state transition (eg: COW -> DIRTY)
486
         */
487
        andi.   r11, r11, _PAGE_HWEXEC
488
        rlwimi  r11, r11, 31, 27, 27    /* SX <- _PAGE_HWEXEC */
489
        ori     r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */
490
 
491
        /* update search PID in MAS6, AS = 0 */
492
        mfspr   r12, SPRN_PID0
493
        slwi    r12, r12, 16
494
        mtspr   SPRN_MAS6, r12
495
 
496
        /* find the TLB index that caused the fault.  It has to be here. */
497
        tlbsx   0, r10
498
 
499
        /* only update the perm bits, assume the RPN is fine */
500
        mfspr   r12, SPRN_MAS3
501
        rlwimi  r12, r11, 0, 20, 31
502
        mtspr   SPRN_MAS3,r12
503
        tlbwe
504
 
505
        /* Done...restore registers and get out of here.  */
506
        mfspr   r11, SPRN_SPRG7R
507
        mtcr    r11
508
        mfspr   r13, SPRN_SPRG5R
509
        mfspr   r12, SPRN_SPRG4R
510
        mfspr   r11, SPRN_SPRG1
511
        mfspr   r10, SPRN_SPRG0
512
        rfi                     /* Force context change */
513
 
514
2:
515
        /*
516
         * The bailout.  Restore registers to pre-exception conditions
517
         * and call the heavyweights to help us out.
518
         */
519
        mfspr   r11, SPRN_SPRG7R
520
        mtcr    r11
521
        mfspr   r13, SPRN_SPRG5R
522
        mfspr   r12, SPRN_SPRG4R
523
        mfspr   r11, SPRN_SPRG1
524
        mfspr   r10, SPRN_SPRG0
525
        b       data_access
526
 
527
        /* Instruction Storage Interrupt */
528
        INSTRUCTION_STORAGE_EXCEPTION
529
 
530
        /* External Input Interrupt */
531
        EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
532
 
533
        /* Alignment Interrupt */
534
        ALIGNMENT_EXCEPTION
535
 
536
        /* Program Interrupt */
537
        PROGRAM_EXCEPTION
538
 
539
        /* Floating Point Unavailable Interrupt */
540
#ifdef CONFIG_PPC_FPU
541
        FP_UNAVAILABLE_EXCEPTION
542
#else
543
#ifdef CONFIG_E200
544
        /* E200 treats 'normal' floating point instructions as FP Unavail exception */
545
        EXCEPTION(0x0800, FloatingPointUnavailable, program_check_exception, EXC_XFER_EE)
546
#else
547
        EXCEPTION(0x0800, FloatingPointUnavailable, unknown_exception, EXC_XFER_EE)
548
#endif
549
#endif
550
 
551
        /* System Call Interrupt */
552
        START_EXCEPTION(SystemCall)
553
        NORMAL_EXCEPTION_PROLOG
554
        EXC_XFER_EE_LITE(0x0c00, DoSyscall)
555
 
556
        /* Auxillary Processor Unavailable Interrupt */
557
        EXCEPTION(0x2900, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
558
 
559
        /* Decrementer Interrupt */
560
        DECREMENTER_EXCEPTION
561
 
562
        /* Fixed Internal Timer Interrupt */
563
        /* TODO: Add FIT support */
564
        EXCEPTION(0x3100, FixedIntervalTimer, unknown_exception, EXC_XFER_EE)
565
 
566
        /* Watchdog Timer Interrupt */
567
#ifdef CONFIG_BOOKE_WDT
568
        CRITICAL_EXCEPTION(0x3200, WatchdogTimer, WatchdogException)
569
#else
570
        CRITICAL_EXCEPTION(0x3200, WatchdogTimer, unknown_exception)
571
#endif
572
 
573
        /* Data TLB Error Interrupt */
574
        START_EXCEPTION(DataTLBError)
575
        mtspr   SPRN_SPRG0, r10         /* Save some working registers */
576
        mtspr   SPRN_SPRG1, r11
577
        mtspr   SPRN_SPRG4W, r12
578
        mtspr   SPRN_SPRG5W, r13
579
        mfcr    r11
580
        mtspr   SPRN_SPRG7W, r11
581
        mfspr   r10, SPRN_DEAR          /* Get faulting address */
582
 
583
        /* If we are faulting a kernel address, we have to use the
584
         * kernel page tables.
585
         */
586
        lis     r11, PAGE_OFFSET@h
587
        cmplw   5, r10, r11
588
        blt     5, 3f
589
        lis     r11, swapper_pg_dir@h
590
        ori     r11, r11, swapper_pg_dir@l
591
 
592
        mfspr   r12,SPRN_MAS1           /* Set TID to 0 */
593
        rlwinm  r12,r12,0,16,1
594
        mtspr   SPRN_MAS1,r12
595
 
596
        b       4f
597
 
598
        /* Get the PGD for the current thread */
599
3:
600
        mfspr   r11,SPRN_SPRG3
601
        lwz     r11,PGDIR(r11)
602
 
603
4:
604
        FIND_PTE
605
        andi.   r13, r11, _PAGE_PRESENT /* Is the page present? */
606
        beq     2f                      /* Bail if not present */
607
 
608
#ifdef CONFIG_PTE_64BIT
609
        lwz     r13, 0(r12)
610
#endif
611
        ori     r11, r11, _PAGE_ACCESSED
612
        stw     r11, PTE_FLAGS_OFFSET(r12)
613
 
614
         /* Jump to common tlb load */
615
        b       finish_tlb_load
616
2:
617
        /* The bailout.  Restore registers to pre-exception conditions
618
         * and call the heavyweights to help us out.
619
         */
620
        mfspr   r11, SPRN_SPRG7R
621
        mtcr    r11
622
        mfspr   r13, SPRN_SPRG5R
623
        mfspr   r12, SPRN_SPRG4R
624
        mfspr   r11, SPRN_SPRG1
625
        mfspr   r10, SPRN_SPRG0
626
        b       data_access
627
 
628
        /* Instruction TLB Error Interrupt */
629
        /*
630
         * Nearly the same as above, except we get our
631
         * information from different registers and bailout
632
         * to a different point.
633
         */
634
        START_EXCEPTION(InstructionTLBError)
635
        mtspr   SPRN_SPRG0, r10         /* Save some working registers */
636
        mtspr   SPRN_SPRG1, r11
637
        mtspr   SPRN_SPRG4W, r12
638
        mtspr   SPRN_SPRG5W, r13
639
        mfcr    r11
640
        mtspr   SPRN_SPRG7W, r11
641
        mfspr   r10, SPRN_SRR0          /* Get faulting address */
642
 
643
        /* If we are faulting a kernel address, we have to use the
644
         * kernel page tables.
645
         */
646
        lis     r11, PAGE_OFFSET@h
647
        cmplw   5, r10, r11
648
        blt     5, 3f
649
        lis     r11, swapper_pg_dir@h
650
        ori     r11, r11, swapper_pg_dir@l
651
 
652
        mfspr   r12,SPRN_MAS1           /* Set TID to 0 */
653
        rlwinm  r12,r12,0,16,1
654
        mtspr   SPRN_MAS1,r12
655
 
656
        b       4f
657
 
658
        /* Get the PGD for the current thread */
659
3:
660
        mfspr   r11,SPRN_SPRG3
661
        lwz     r11,PGDIR(r11)
662
 
663
4:
664
        FIND_PTE
665
        andi.   r13, r11, _PAGE_PRESENT /* Is the page present? */
666
        beq     2f                      /* Bail if not present */
667
 
668
#ifdef CONFIG_PTE_64BIT
669
        lwz     r13, 0(r12)
670
#endif
671
        ori     r11, r11, _PAGE_ACCESSED
672
        stw     r11, PTE_FLAGS_OFFSET(r12)
673
 
674
        /* Jump to common TLB load point */
675
        b       finish_tlb_load
676
 
677
2:
678
        /* The bailout.  Restore registers to pre-exception conditions
679
         * and call the heavyweights to help us out.
680
         */
681
        mfspr   r11, SPRN_SPRG7R
682
        mtcr    r11
683
        mfspr   r13, SPRN_SPRG5R
684
        mfspr   r12, SPRN_SPRG4R
685
        mfspr   r11, SPRN_SPRG1
686
        mfspr   r10, SPRN_SPRG0
687
        b       InstructionStorage
688
 
689
#ifdef CONFIG_SPE
690
        /* SPE Unavailable */
691
        START_EXCEPTION(SPEUnavailable)
692
        NORMAL_EXCEPTION_PROLOG
693
        bne     load_up_spe
694
        addi    r3,r1,STACK_FRAME_OVERHEAD
695
        EXC_XFER_EE_LITE(0x2010, KernelSPE)
696
#else
697
        EXCEPTION(0x2020, SPEUnavailable, unknown_exception, EXC_XFER_EE)
698
#endif /* CONFIG_SPE */
699
 
700
        /* SPE Floating Point Data */
701
#ifdef CONFIG_SPE
702
        EXCEPTION(0x2030, SPEFloatingPointData, SPEFloatingPointException, EXC_XFER_EE);
703
#else
704
        EXCEPTION(0x2040, SPEFloatingPointData, unknown_exception, EXC_XFER_EE)
705
#endif /* CONFIG_SPE */
706
 
707
        /* SPE Floating Point Round */
708
        EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception, EXC_XFER_EE)
709
 
710
        /* Performance Monitor */
711
        EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)
712
 
713
 
714
        /* Debug Interrupt */
715
        DEBUG_EXCEPTION
716
 
717
/*
718
 * Local functions
719
 */
720
 
721
        /*
722
         * Data TLB exceptions will bail out to this point
723
         * if they can't resolve the lightweight TLB fault.
724
         */
725
data_access:
726
        NORMAL_EXCEPTION_PROLOG
727
        mfspr   r5,SPRN_ESR             /* Grab the ESR, save it, pass arg3 */
728
        stw     r5,_ESR(r11)
729
        mfspr   r4,SPRN_DEAR            /* Grab the DEAR, save it, pass arg2 */
730
        andis.  r10,r5,(ESR_ILK|ESR_DLK)@h
731
        bne     1f
732
        EXC_XFER_EE_LITE(0x0300, handle_page_fault)
733
1:
734
        addi    r3,r1,STACK_FRAME_OVERHEAD
735
        EXC_XFER_EE_LITE(0x0300, CacheLockingException)
736
 
737
/*
738
 
739
 * Both the instruction and data TLB miss get to this
740
 * point to load the TLB.
741
 *      r10 - EA of fault
742
 *      r11 - TLB (info from Linux PTE)
743
 *      r12, r13 - available to use
744
 *      CR5 - results of addr >= PAGE_OFFSET
745
 *      MAS0, MAS1 - loaded with proper value when we get here
746
 *      MAS2, MAS3 - will need additional info from Linux PTE
747
 *      Upon exit, we reload everything and RFI.
748
 */
749
finish_tlb_load:
750
        /*
751
         * We set execute, because we don't have the granularity to
752
         * properly set this at the page level (Linux problem).
753
         * Many of these bits are software only.  Bits we don't set
754
         * here we (properly should) assume have the appropriate value.
755
         */
756
 
757
        mfspr   r12, SPRN_MAS2
758
#ifdef CONFIG_PTE_64BIT
759
        rlwimi  r12, r11, 26, 24, 31    /* extract ...WIMGE from pte */
760
#else
761
        rlwimi  r12, r11, 26, 27, 31    /* extract WIMGE from pte */
762
#endif
763
        mtspr   SPRN_MAS2, r12
764
 
765
        bge     5, 1f
766
 
767
        /* is user addr */
768
        andi.   r12, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC)
769
        andi.   r10, r11, _PAGE_USER    /* Test for _PAGE_USER */
770
        srwi    r10, r12, 1
771
        or      r12, r12, r10   /* Copy user perms into supervisor */
772
        iseleq  r12, 0, r12
773
        b       2f
774
 
775
        /* is kernel addr */
776
1:      rlwinm  r12, r11, 31, 29, 29    /* Extract _PAGE_HWWRITE into SW */
777
        ori     r12, r12, (MAS3_SX | MAS3_SR)
778
 
779
#ifdef CONFIG_PTE_64BIT
780
2:      rlwimi  r12, r13, 24, 0, 7      /* grab RPN[32:39] */
781
        rlwimi  r12, r11, 24, 8, 19     /* grab RPN[40:51] */
782
        mtspr   SPRN_MAS3, r12
783
BEGIN_FTR_SECTION
784
        srwi    r10, r13, 8             /* grab RPN[8:31] */
785
        mtspr   SPRN_MAS7, r10
786
END_FTR_SECTION_IFSET(CPU_FTR_BIG_PHYS)
787
#else
788
2:      rlwimi  r11, r12, 0, 20, 31     /* Extract RPN from PTE and merge with perms */
789
        mtspr   SPRN_MAS3, r11
790
#endif
791
#ifdef CONFIG_E200
792
        /* Round robin TLB1 entries assignment */
793
        mfspr   r12, SPRN_MAS0
794
 
795
        /* Extract TLB1CFG(NENTRY) */
796
        mfspr   r11, SPRN_TLB1CFG
797
        andi.   r11, r11, 0xfff
798
 
799
        /* Extract MAS0(NV) */
800
        andi.   r13, r12, 0xfff
801
        addi    r13, r13, 1
802
        cmpw    0, r13, r11
803
        addi    r12, r12, 1
804
 
805
        /* check if we need to wrap */
806
        blt     7f
807
 
808
        /* wrap back to first free tlbcam entry */
809
        lis     r13, tlbcam_index@ha
810
        lwz     r13, tlbcam_index@l(r13)
811
        rlwimi  r12, r13, 0, 20, 31
812
7:
813
        mtspr   SPRN_MAS0,r12
814
#endif /* CONFIG_E200 */
815
 
816
        tlbwe
817
 
818
        /* Done...restore registers and get out of here.  */
819
        mfspr   r11, SPRN_SPRG7R
820
        mtcr    r11
821
        mfspr   r13, SPRN_SPRG5R
822
        mfspr   r12, SPRN_SPRG4R
823
        mfspr   r11, SPRN_SPRG1
824
        mfspr   r10, SPRN_SPRG0
825
        rfi                                     /* Force context change */
826
 
827
#ifdef CONFIG_SPE
828
/* Note that the SPE support is closely modeled after the AltiVec
829
 * support.  Changes to one are likely to be applicable to the
830
 * other!  */
831
load_up_spe:
832
/*
833
 * Disable SPE for the task which had SPE previously,
834
 * and save its SPE registers in its thread_struct.
835
 * Enables SPE for use in the kernel on return.
836
 * On SMP we know the SPE units are free, since we give it up every
837
 * switch.  -- Kumar
838
 */
839
        mfmsr   r5
840
        oris    r5,r5,MSR_SPE@h
841
        mtmsr   r5                      /* enable use of SPE now */
842
        isync
843
/*
844
 * For SMP, we don't do lazy SPE switching because it just gets too
845
 * horrendously complex, especially when a task switches from one CPU
846
 * to another.  Instead we call giveup_spe in switch_to.
847
 */
848
#ifndef CONFIG_SMP
849
        lis     r3,last_task_used_spe@ha
850
        lwz     r4,last_task_used_spe@l(r3)
851
        cmpi    0,r4,0
852
        beq     1f
853
        addi    r4,r4,THREAD    /* want THREAD of last_task_used_spe */
854
        SAVE_32EVRS(0,r10,r4)
855
        evxor   evr10, evr10, evr10     /* clear out evr10 */
856
        evmwumiaa evr10, evr10, evr10   /* evr10 <- ACC = 0 * 0 + ACC */
857
        li      r5,THREAD_ACC
858
        evstddx evr10, r4, r5           /* save off accumulator */
859
        lwz     r5,PT_REGS(r4)
860
        lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
861
        lis     r10,MSR_SPE@h
862
        andc    r4,r4,r10       /* disable SPE for previous task */
863
        stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
864
1:
865
#endif /* !CONFIG_SMP */
866
        /* enable use of SPE after return */
867
        oris    r9,r9,MSR_SPE@h
868
        mfspr   r5,SPRN_SPRG3           /* current task's THREAD (phys) */
869
        li      r4,1
870
        li      r10,THREAD_ACC
871
        stw     r4,THREAD_USED_SPE(r5)
872
        evlddx  evr4,r10,r5
873
        evmra   evr4,evr4
874
        REST_32EVRS(0,r10,r5)
875
#ifndef CONFIG_SMP
876
        subi    r4,r5,THREAD
877
        stw     r4,last_task_used_spe@l(r3)
878
#endif /* !CONFIG_SMP */
879
        /* restore registers and return */
880
2:      REST_4GPRS(3, r11)
881
        lwz     r10,_CCR(r11)
882
        REST_GPR(1, r11)
883
        mtcr    r10
884
        lwz     r10,_LINK(r11)
885
        mtlr    r10
886
        REST_GPR(10, r11)
887
        mtspr   SPRN_SRR1,r9
888
        mtspr   SPRN_SRR0,r12
889
        REST_GPR(9, r11)
890
        REST_GPR(12, r11)
891
        lwz     r11,GPR11(r11)
892
        rfi
893
 
894
/*
895
 * SPE unavailable trap from kernel - print a message, but let
896
 * the task use SPE in the kernel until it returns to user mode.
897
 */
898
KernelSPE:
899
        lwz     r3,_MSR(r1)
900
        oris    r3,r3,MSR_SPE@h
901
        stw     r3,_MSR(r1)     /* enable use of SPE after return */
902
        lis     r3,87f@h
903
        ori     r3,r3,87f@l
904
        mr      r4,r2           /* current */
905
        lwz     r5,_NIP(r1)
906
        bl      printk
907
        b       ret_from_except
908
87:     .string "SPE used in kernel  (task=%p, pc=%x)  \n"
909
        .align  4,0
910
 
911
#endif /* CONFIG_SPE */
912
 
913
/*
914
 * Global functions
915
 */
916
 
917
/*
918
 * extern void loadcam_entry(unsigned int index)
919
 *
920
 * Load TLBCAM[index] entry in to the L2 CAM MMU
921
 */
922
_GLOBAL(loadcam_entry)
923
        lis     r4,TLBCAM@ha
924
        addi    r4,r4,TLBCAM@l
925
        mulli   r5,r3,20
926
        add     r3,r5,r4
927
        lwz     r4,0(r3)
928
        mtspr   SPRN_MAS0,r4
929
        lwz     r4,4(r3)
930
        mtspr   SPRN_MAS1,r4
931
        lwz     r4,8(r3)
932
        mtspr   SPRN_MAS2,r4
933
        lwz     r4,12(r3)
934
        mtspr   SPRN_MAS3,r4
935
        tlbwe
936
        isync
937
        blr
938
 
939
/*
940
 * extern void giveup_altivec(struct task_struct *prev)
941
 *
942
 * The e500 core does not have an AltiVec unit.
943
 */
944
_GLOBAL(giveup_altivec)
945
        blr
946
 
947
#ifdef CONFIG_SPE
948
/*
949
 * extern void giveup_spe(struct task_struct *prev)
950
 *
951
 */
952
_GLOBAL(giveup_spe)
953
        mfmsr   r5
954
        oris    r5,r5,MSR_SPE@h
955
        mtmsr   r5                      /* enable use of SPE now */
956
        isync
957
        cmpi    0,r3,0
958
        beqlr-                          /* if no previous owner, done */
959
        addi    r3,r3,THREAD            /* want THREAD of task */
960
        lwz     r5,PT_REGS(r3)
961
        cmpi    0,r5,0
962
        SAVE_32EVRS(0, r4, r3)
963
        evxor   evr6, evr6, evr6        /* clear out evr6 */
964
        evmwumiaa evr6, evr6, evr6      /* evr6 <- ACC = 0 * 0 + ACC */
965
        li      r4,THREAD_ACC
966
        evstddx evr6, r4, r3            /* save off accumulator */
967
        mfspr   r6,SPRN_SPEFSCR
968
        stw     r6,THREAD_SPEFSCR(r3)   /* save spefscr register value */
969
        beq     1f
970
        lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
971
        lis     r3,MSR_SPE@h
972
        andc    r4,r4,r3                /* disable SPE for previous task */
973
        stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
974
1:
975
#ifndef CONFIG_SMP
976
        li      r5,0
977
        lis     r4,last_task_used_spe@ha
978
        stw     r5,last_task_used_spe@l(r4)
979
#endif /* !CONFIG_SMP */
980
        blr
981
#endif /* CONFIG_SPE */
982
 
983
/*
984
 * extern void giveup_fpu(struct task_struct *prev)
985
 *
986
 * Not all FSL Book-E cores have an FPU
987
 */
988
#ifndef CONFIG_PPC_FPU
989
_GLOBAL(giveup_fpu)
990
        blr
991
#endif
992
 
993
/*
994
 * extern void abort(void)
995
 *
996
 * At present, this routine just applies a system reset.
997
 */
998
_GLOBAL(abort)
999
        li      r13,0
1000
        mtspr   SPRN_DBCR0,r13          /* disable all debug events */
1001
        isync
1002
        mfmsr   r13
1003
        ori     r13,r13,MSR_DE@l        /* Enable Debug Events */
1004
        mtmsr   r13
1005
        isync
1006
        mfspr   r13,SPRN_DBCR0
1007
        lis     r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h
1008
        mtspr   SPRN_DBCR0,r13
1009
        isync
1010
 
1011
_GLOBAL(set_context)
1012
 
1013
#ifdef CONFIG_BDI_SWITCH
1014
        /* Context switch the PTE pointer for the Abatron BDI2000.
1015
         * The PGDIR is the second parameter.
1016
         */
1017
        lis     r5, abatron_pteptrs@h
1018
        ori     r5, r5, abatron_pteptrs@l
1019
        stw     r4, 0x4(r5)
1020
#endif
1021
        mtspr   SPRN_PID,r3
1022
        isync                   /* Force context change */
1023
        blr
1024
 
1025
/*
1026
 * We put a few things here that have to be page-aligned. This stuff
1027
 * goes at the beginning of the data segment, which is page-aligned.
1028
 */
1029
        .data
1030
        .align  12
1031
        .globl  sdata
1032
sdata:
1033
        .globl  empty_zero_page
1034
empty_zero_page:
1035
        .space  4096
1036
        .globl  swapper_pg_dir
1037
swapper_pg_dir:
1038
        .space  PGD_TABLE_SIZE
1039
 
1040
/* Reserved 4k for the critical exception stack & 4k for the machine
1041
 * check stack per CPU for kernel mode exceptions */
1042
        .section .bss
1043
        .align 12
1044
exception_stack_bottom:
1045
        .space  BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS
1046
        .globl  exception_stack_top
1047
exception_stack_top:
1048
 
1049
/*
1050
 * Room for two PTE pointers, usually the kernel and current user pointers
1051
 * to their respective root page table.
1052
 */
1053
abatron_pteptrs:
1054
        .space  8

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.