Copyright clean-up (part 1):
[AROS.git] / arch / ppc-chrp / efika / kernel / mmu.c
blob2cdeac621b6e0156f122764e4f7d60f924463e32
1 /*
2 Copyright © 2008-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <inttypes.h>
7 #include <asm/mpc5200b.h>
8 #include <asm/io.h>
9 #include <aros/kernel.h>
10 #include <aros/libcall.h>
11 #include <stddef.h>
12 #include <string.h>
14 #include <proto/exec.h>
15 #include <proto/kernel.h>
17 #include "kernel_intern.h"
19 typedef struct {
20 uint32_t vsid;
21 uint32_t rpn;
22 } pte_t;
24 /* Search the MMU hash table for page table entry corresponding to virtual address given */
26 pte_t *find_pte(uint64_t virt)
28 pte_t *ret = (pte_t *)0;
30 uint32_t mask;
31 pte_t *pteg;
32 uint32_t vsid;
33 int i;
35 /* Calculate the hash function */
36 uint32_t hash = (((virt >> 12) & 0xffff) ^ (virt >> 28)) & 0x7ffff;
38 /* what vsid we are looking for? */
39 vsid = 0x80000000 | ((virt >> 28) << 7) | ((virt >> 22) & 0x3f);
41 /* What mask are we using? Depends on the size of MMU hashtable */
42 mask = ((rdspr(SDR1) & 0x1ff) << 16) | 0xffc0;
44 /* Get the first group of pte's */
45 pteg = (pte_t *)((rdspr(SDR1) & ~0x1ff) | ((hash << 6) & mask));
47 /* Search the primary group */
48 for (i=0; i < 8; i++)
50 if (pteg[i].vsid == vsid)
52 ret = &pteg[i];
53 break;
58 * If the page was not found in primary group, get the second hash, second
59 * vsid and search the secondary group.
61 if (!ret)
63 uint32_t hash2 = (~hash) & 0x7ffff;
64 vsid |= 0x40;
65 pteg = (pte_t *)((rdspr(SDR1) & ~0x1ff) | ((hash2 << 6) & mask));
67 /* Search the secondary group */
68 for (i=0; i < 8; i++)
70 if (pteg[i].vsid == vsid)
72 ret = &pteg[i];
73 break;
78 return ret;
81 uint16_t mmu_protection(KRN_MapAttr flags)
83 uint16_t ppc_prot = 2 << 3; /* WIMG = 0010 */
85 if (flags & MAP_Readable)
87 ppc_prot |= 0x03;
89 if (flags & MAP_Writable)
91 ppc_prot = (ppc_prot | 2) & ~1;
94 if (flags & MAP_WriteThrough)
96 ppc_prot |= 8 << 3;
98 if (flags & MAP_Guarded)
100 ppc_prot |= 1 << 3;
102 if (flags & MAP_CacheInhibit)
104 ppc_prot = (ppc_prot | 4 << 3) & ~ (8 << 3);
107 return ppc_prot & 0xfff;
110 int mmu_map_page(uint64_t virt, uint32_t phys, uint32_t prot)
112 uint32_t mask = ((rdspr(SDR1) & 0x1ff) << 16) | 0xffc0;
113 pte_t *pteg;
114 pte_t *pte = NULL;
115 pte_t local_pte;
116 int ptenum;
118 /* Calculate the hash function */
119 uint32_t hash = (((uint32_t)(virt >> 12) & 0xffff) ^ (uint32_t)(virt >> 28)) & 0x7ffff;
121 pteg = (pte_t *)((rdspr(SDR1) & ~0x1ff) | ((hash << 6) & mask));
123 for (ptenum = 0; ptenum < 8; ptenum++)
125 if (!(pteg[ptenum].vsid & 0x80000000))
127 pte = &pteg[ptenum];
128 local_pte.vsid = 0;
129 break;
132 if (!pte)
134 uint32_t hash2 = (~hash) & 0x7ffff;
135 pteg = (pte_t *)((rdspr(SDR1) & ~0x1ff) | ((hash2 << 6) & mask));
137 for (ptenum = 0; ptenum < 8; ptenum++)
139 if (!(pteg[ptenum].vsid & 0x80000000))
141 pte = &pteg[ptenum];
142 local_pte.vsid = 0x40;
143 break;
148 if (!pte)
150 D(bug("[KRN] mmu_map_page(%06x%07x, %08x, %08x)\n", (uint32_t)(virt >> 28), (uint32_t)(virt & 0x0fffffff), phys, prot));
151 D(bug("[KRN] Run out of free page table entries\n"));
152 return 0;
155 local_pte.vsid |= ((virt >> 28) << 7);
156 local_pte.vsid |= ((virt >> 22) & 0x3f);
157 local_pte.vsid |= 0x80000000;
158 local_pte.rpn = (phys & ~0xfff) | (prot & 0xfff);
160 *pte = local_pte;
162 asm volatile("dcbst 0,%0; sync;"::"r"(pte));
163 asm volatile("tlbie %0"::"r"((uint32_t)virt));
165 return 1;
168 int mmu_map_area(uint64_t virt, uint32_t phys, uint32_t length, uint32_t prot)
170 bug("[KRN] mmu_map_area(%04x%08x, %08x, %08x, %04x)\n", (uint32_t)(virt >> 32), (uint32_t)virt, phys, length, prot);
171 while (length)
173 if (!mmu_map_page(virt, phys, prot))
174 return 0;
176 virt += 4096;
177 phys += 4096;
178 length -= 4096;
181 return 1;
184 void mmu_init(char *mmu_dir, uint32_t mmu_size)
186 int i;
188 D(bug("[KRN] Initializing MMU\n"));
189 D(bug("[KRN] Location of MMU tables: %08x-%08x\n", mmu_dir, mmu_dir + mmu_size - 1));
191 if ((intptr_t)mmu_dir & (mmu_size - 1))
193 D(bug("[KRN] WRONG! The MMU dir must be located on mmu length boundary\n"));
195 else
197 uint32_t ea;
198 /* Clear the MMU tables */
199 memset(mmu_dir, 0, mmu_size);
201 uint32_t sdr = (intptr_t)mmu_dir | ((mmu_size >> 16) - 1);
203 D(bug("[KRN] SDR1 = %08x\n", sdr));
205 wrspr(SDR1, sdr);
207 /* Prepare the segment registers. The proper values for virtual address
208 * are to be determined later */
210 for (i=0; i < 16; i++)
212 asm volatile ("mtsrin %0,%1"::"r"(0x20000000 | i),"r"(i << 28));
215 D(bug("[KRN] Flushing TLB\n"));
216 for (ea=0x00001000; ea <= 0x0001f000; ea+=0x1000)
217 asm volatile("tlbie %0"::"r"(ea));
221 void __attribute__((noreturn)) mmu_handler(regs_t *ctx, uint8_t exception, void *self)
223 struct KernelBase *KernelBase = getKernelBase();
224 struct ExecBase *SysBase = getSysBase();
226 ctx->dar = rdspr(19);
227 ctx->dsisr = rdspr(18);
229 /* SysBase access at 4UL? Occurs only with lwz instruction and DAR=4 */
230 if ((exception == 3) && (ctx->dar == 4))
232 uint32_t insn = *(uint32_t *)ctx->srr0;
234 if ((insn & 0xfc000000) == 0x80000000)
236 int reg = (insn & 0x03e00000) >> 21;
238 ctx->gpr[reg] = getSysBase();
239 ctx->srr0 += 4;
241 core_LeaveInterrupt(ctx);
245 D(bug("[KRN] Exception %d (%s) handler. Context @ %p, SysBase @ %p, KernelBase @ %p\n", exception, exception == 3 ? "DSI" : "ISI", ctx, SysBase, KernelBase));
246 if (SysBase)
248 struct Task *t = FindTask(NULL);
249 uint32_t offset;
250 char *func, *mod;
252 offset = findNames(ctx->srr0, &mod, &func);
253 D(bug("[KRN] %s %p (%s)\n", t->tc_Node.ln_Type == NT_TASK ? "Task":"Process", t, t->tc_Node.ln_Name ? t->tc_Node.ln_Name : "--unknown--"));
255 if (func)
256 D(bug("[KRN] Crash at byte %d in func %s, module %s\n", offset, func, mod));
257 else if (mod)
258 D(bug("[KRN] Crash at byte %d in module %s\n", offset, mod));
260 D(bug("[KRN] SPLower=%08x SPUpper=%08x\n", t->tc_SPLower, t->tc_SPUpper));
261 D(bug("[KRN] Stack usage: %d bytes (%d %%)\n", t->tc_SPUpper - ctx->gpr[1],
262 100 * ((uintptr_t)t->tc_SPUpper - ctx->gpr[1]) / ((uintptr_t)t->tc_SPUpper - (uintptr_t)t->tc_SPLower)));
264 if (ctx->gpr[1] >= t->tc_SPLower && ctx->gpr[1] < t->tc_SPUpper)
265 D(bug("[KRN] Stack in bounds\n"));
266 else
267 D(bug("[KRN] Stack exceeded the allowed size!\n"));
269 if (exception == 3)
270 D(bug("[KRN] Attempt to %s address %08x.\n", ctx->dsisr & 0x02000000 ? "write to":"read from", ctx->dar));
272 D(bug("[KRN] SRR0=%08x, SRR1=%08x\n",ctx->srr0, ctx->srr1));
273 D(bug("[KRN] CTR=%08x LR=%08x XER=%08x CCR=%08x\n", ctx->ctr, ctx->lr, ctx->xer, ctx->ccr));
274 D(bug("[KRN] DAR=%08x DSISR=%08x\n", ctx->dar, ctx->dsisr));
276 D(bug("[KRN] HASH1=%08x HASH2=%08x IMISS=%08x DMISS=%08x ICMP=%08x DCMP=%08x\n",
277 rdspr(978), rdspr(979), rdspr(980), rdspr(976), rdspr(981), rdspr(977)));
279 D(bug("[KRN] SPRG0=%08x SPRG1=%08x SPRG2=%08x SPRG3=%08x SPRG4=%08x SPRG5=%08x\n",
280 rdspr(SPRG0),rdspr(SPRG1),rdspr(SPRG2),rdspr(SPRG3),rdspr(SPRG4),rdspr(SPRG5)));
282 D(bug("[KRN] GPR00=%08x GPR01=%08x GPR02=%08x GPR03=%08x\n",
283 ctx->gpr[0],ctx->gpr[1],ctx->gpr[2],ctx->gpr[3]));
284 D(bug("[KRN] GPR04=%08x GPR05=%08x GPR06=%08x GPR07=%08x\n",
285 ctx->gpr[4],ctx->gpr[5],ctx->gpr[6],ctx->gpr[7]));
286 D(bug("[KRN] GPR08=%08x GPR09=%08x GPR10=%08x GPR11=%08x\n",
287 ctx->gpr[8],ctx->gpr[9],ctx->gpr[10],ctx->gpr[11]));
288 D(bug("[KRN] GPR12=%08x GPR13=%08x GPR14=%08x GPR15=%08x\n",
289 ctx->gpr[12],ctx->gpr[13],ctx->gpr[14],ctx->gpr[15]));
291 D(bug("[KRN] GPR16=%08x GPR17=%08x GPR18=%08x GPR19=%08x\n",
292 ctx->gpr[16],ctx->gpr[17],ctx->gpr[18],ctx->gpr[19]));
293 D(bug("[KRN] GPR20=%08x GPR21=%08x GPR22=%08x GPR23=%08x\n",
294 ctx->gpr[20],ctx->gpr[21],ctx->gpr[22],ctx->gpr[23]));
295 D(bug("[KRN] GPR24=%08x GPR25=%08x GPR26=%08x GPR27=%08x\n",
296 ctx->gpr[24],ctx->gpr[25],ctx->gpr[26],ctx->gpr[27]));
297 D(bug("[KRN] GPR28=%08x GPR29=%08x GPR30=%08x GPR31=%08x\n",
298 ctx->gpr[28],ctx->gpr[29],ctx->gpr[30],ctx->gpr[31]));
300 int i;
301 D(bug("[KRN] Hash1 dump:\n[KRN] "));
302 uint32_t *hash = (uint32_t)rdspr(978);
303 for (i=0; i < 8; i++)
305 D(bug("%08x.%08x ", hash[0], hash[1]));
306 hash += 2;
307 if (i == 3)
308 D(bug("\n[KRN] "));
310 D(bug("\n[KRN] Hash2 dump:\n[KRN] "));
311 hash = (uint32_t)rdspr(979);
312 for (i=0; i < 8; i++)
314 D(bug("%08x.%08x ", hash[0], hash[1]));
315 hash += 2;
316 if (i == 3)
317 D(bug("\n[KRN] "));
319 D(bug("\n"));
320 D(bug("[KRN] Instruction dump:\n"));
321 ULONG *p = (ULONG*)ctx->srr0;
322 for (i=0; i < 8; i++)
324 if (find_pte((uint32_t)&p[i]))
325 D(bug("[KRN] %08x: %08x\n", &p[i], p[i]));
326 else
327 D(bug("[KRN] %08x: ?\n", &p[i]));
330 D(bug("[KRN] Backtrace:\n"));
331 uint32_t *sp = ctx->gpr[1];
332 while(*sp)
334 char *mod, *func;
335 sp = (uint32_t *)sp[0];
336 uint32_t offset;
338 offset = findNames(sp[1], &mod, &func);
340 if (func)
341 D(bug("[KRN] %08x: byte %d in func %s, module %s\n", sp[1], offset, func, mod));
342 else if (mod)
343 D(bug("[KRN] %08x: byte %d in module %s\n", sp[1], offset, mod));
344 else
345 D(bug("[KRN] %08x\n", sp[1]));
348 if (SysBase)
350 struct Task *dead = SysBase->ThisTask;
352 SysBase->ThisTask = NULL;
353 KernelBase->kb_LastDeadTask = dead;
354 Remove(dead);
355 Enqueue(&KernelBase->kb_DeadTasks, dead);
357 core_Dispatch(ctx);
361 D(bug("[KRN] **UNHANDLED EXCEPTION** stopping here...\n"));
363 while(1) {
364 wrmsr(rdmsr() | MSR_POW);
368 AROS_LH3(void, KrnSetProtection,
369 AROS_LHA(void *, address, A0),
370 AROS_LHA(uint32_t, length, D0),
371 AROS_LHA(KRN_MapAttr, flags, D1),
372 struct KernelBase *, KernelBase, 21, Kernel)
374 AROS_LIBFUNC_INIT
376 uint32_t ppc_prot = mmu_protection(flags);
377 uintptr_t virt = (uintptr_t)address;
378 pte_t *pte;
380 D(bug("[KRN] KrnSetProtection(%08x, %08x, %04x)\n", virt, virt + length - 1, ppc_prot));
382 virt &= ~4095;
383 length = (length + 4095) & ~4095;
385 uint32_t msr;
386 msr = goSuper();
387 while (length)
389 pte = find_pte(virt);
391 if (pte)
393 pte->rpn = (pte->rpn & 0xfffff000) | ppc_prot;
396 virt += 4096;
397 length -= 4096;
399 goUser(msr);
401 AROS_LIBFUNC_EXIT
404 AROS_LH4(int, KrnMapGlobal,
405 AROS_LHA(void *, virtual, A0),
406 AROS_LHA(void *, physical, A1),
407 AROS_LHA(uint32_t, length, D0),
408 AROS_LHA(KRN_MapAttr, flags, D1),
409 struct KernelBase *, KernelBase, 16, Kernel)
411 AROS_LIBFUNC_INIT
413 int retval = 0;
414 uint32_t msr;
415 uint32_t ppc_prot = mmu_protection(flags);
417 D(bug("[KRN] KrnMapGlobal(%08x->%08x %08x %04x)\n", virtual, physical, length, flags));
419 msr = goSuper();
420 retval = mmu_map_area((uint64_t)virtual & 0xffffffff, physical, length, ppc_prot);
421 wrmsr(msr);
423 return retval;
425 AROS_LIBFUNC_EXIT
428 AROS_LH2(int, KrnUnmapGlobal,
429 AROS_LHA(void *, virtual, A0),
430 AROS_LHA(uint32_t, length, D0),
431 struct KernelBase *, KernelBase, 17, Kernel)
433 AROS_LIBFUNC_INIT
435 int retval = 0;
436 uint32_t msr;
437 uintptr_t virt = (uintptr_t)virtual;
438 virt &= ~4095;
439 length = (length + 4095) & ~4095;
441 msr = goSuper();
442 while(length)
444 pte_t *pte = find_pte(virt);
445 pte->vsid = 0;
446 virt += 4096;
447 length -= 4096;
449 goUser(msr);
451 return retval;
453 AROS_LIBFUNC_EXIT
456 uintptr_t virt2phys(uintptr_t virt)
458 uintptr_t phys = 0xffffffff;
459 pte_t *pte = find_pte(virt);
461 if (pte)
463 phys = pte->rpn & ~0xfff;
464 phys |= virt & 0xfff;
467 return phys;
470 AROS_LH1(void *, KrnVirtualToPhysical,
471 AROS_LHA(void *, virtual, A0),
472 struct KernelBase *, KernelBase, 20, Kernel)
474 AROS_LIBFUNC_INIT
476 uintptr_t virt = (uintptr_t)virtual;
477 uintptr_t phys;
478 uint32_t msr = goSuper();
480 phys = virt2phys(virt);
482 goUser(msr);
486 return (void*)phys;
488 AROS_LIBFUNC_EXIT
494 /* MMU exception handlers follow the G2 core manual */
495 static void __attribute__((used)) __exception_template()
497 asm volatile("\n"
498 ".set dMiss, 976\n"
499 ".set dCmp, 977\n"
500 ".set hash1, 978\n"
501 ".set hash2, 979\n"
502 ".set iMiss, 980\n"
503 ".set iCmp, 981\n"
504 ".set rpa, 982\n"
505 ".set c0, 0\n"
506 ".set dar, 19\n"
507 ".set dsisr, 18\n"
508 ".set srr0, 26\n"
509 ".set srr1, 27\n"
512 * Instruction TB miss flow
513 * Entry:
515 * Vec = 1000
516 * srr0 -> address of instruction that missed
517 * srr1 -> 0:3=cr0 4=lru way bit 16:31 = saved MSR
518 * msr<tgpr> -> 1
519 * iMiss -> ea that missed
520 * iCmp -> the compare value for the va that missed
521 * hash1 -> pointer to first hash pteg
522 * hash2 -> pointer to second hash pteg
524 * Register usage:
526 * r0 is saved counter
527 * r1 is junk
528 * r2 is pointer to pteg
529 * r3 is current compare value
531 asm volatile(".align 8; .globl __vector_imiss; .type __vector_imiss,@function\n"
532 "__vector_imiss:\n"
533 " mfspr %r2,hash1 \n"
534 " addi %r1,0,8 \n"
535 " mfctr %r0 \n"
536 " mfspr %r3,iCmp \n"
537 " addi %r2,%r2,-8 \n"
538 "im0: mtctr %r1 \n"
539 "im1: lwzu %r1,8(%r2) \n"
540 " cmp c0,%r1,%r3 \n"
541 " bdnzf eq, im1 \n"
542 " bne instrSecHash\n"
543 " l %r1,+4(%r2) \n"
544 " andi. %r3,%r1,8 \n"
545 " bne doISIp \n"
546 " mtctr %r0 \n"
547 " mfspr %r0,iMiss \n"
548 " mfspr %r3,srr1 \n"
549 " mtcrf 0x80,%r3 \n"
550 " mtspr rpa,%r1 \n"
551 " ori %r1,%r1,0x100 \n"
552 " srwi %r1,%r1,8 \n"
553 " tlbli %r0 \n"
554 " stb %r1,+6(%r2) \n"
555 " rfi \n"
557 "instrSecHash: \n"
558 " andi. %r1,%r3,0x0040 \n"
559 " bne doISI \n"
560 " mfspr %r2,hash2 \n"
561 " ori %r3,%r3,0x0040 \n"
562 " addi %r1,0,8 \n"
563 " addi %r2,%r2,-8 \n"
564 " b im0 \n"
566 "doISIp: \n"
567 " mfspr %r3, srr1 \n"
568 " andi. %r2,%r3,0xffff \n"
569 " addis %r2,%r2,0x0800 \n"
570 " b isi1 \n"
571 "doISI: \n"
572 " mfspr %r3, srr1 \n"
573 " andi. %r2,%r3,0xffff\n"
574 " addis %r2,%r2,0x4000\n"
575 "isi1: \n"
576 " mtctr %r0 \n"
577 " mtspr srr1,%r2 \n"
578 " mfmsr %r0 \n"
579 " xoris %r0,%r0, 0x8002\n"
580 " mtcrf 0x80,%r3 \n"
581 " mtmsr %r0 \n"
582 " ba 0x0400 \n"
586 * Data TLB miss flow
587 * Entry:
589 * Vec = 1100
590 * srr0 -> address of instruction that caused data tlb miss
591 * srr1 -> 0:3=cr0 4=lru way bit 5=1 if store 16:31 = saved MSR
592 * msr<tgpr> -> 1
593 * dMiss -> ea that missed
594 * dCmp -> the compare value for the va that missed
595 * hash1 -> pointer to first hash pteg
596 * hash2 -> pointer to second hash pteg
598 * Register usage:
600 * r0 is saved counter
601 * r1 is junk
602 * r2 is pointer to pteg
603 * r3 is current compare value
605 asm volatile(".align 8; .globl __vector_dmiss; .type __vector_dmiss,@function\n"
606 "__vector_dmiss:\n"
607 " mfspr %r2, hash1 \n"
608 " addi %r1, 0, 8 \n"
609 " mfctr %r0 \n"
610 " mfspr %r3, dCmp \n"
611 " addi %r2, %r2, -8\n"
612 "dm0: mtctr %r1 \n"
613 "dm1: lwzu %r1, 8(%r2) \n"
614 " cmp c0, %r1, %r3\n"
615 " bdnzf eq, dm1 \n"
616 " bne dataSecHash \n"
617 " l %r1, +4(%r2)\n"
618 " mtctr %r0 \n"
619 " mfspr %r0, dMiss \n"
620 " mfspr %r3, srr1 \n"
621 " mtcrf 0x80, %r3 \n"
622 " mtspr rpa, %r1 \n"
623 " ori %r1, %r1, 0x100\n"
624 " srwi %r1, %r1, 8 \n"
625 " tlbld %r0 \n"
626 " stb %r1, +6(%r2)\n"
627 " rfi \n"
629 "dataSecHash: \n"
630 " andi. %r1, %r3, 0x0040\n"
631 " bne doDSI \n"
632 " mfspr %r2, hash2 \n"
633 " ori %r3, %r3, 0x0040\n"
634 " addi %r1, 0, 8 \n"
635 " addi %r2, %r2, -8\n"
636 " b dm0 \n"
640 asm volatile(".align 8; .globl __vector_dmissw; .type __vector_dmiss,@function\n"
641 "__vector_dmissw:\n"
642 " mfspr %r2, hash1 \n"
643 " addi %r1, 0, 8 \n"
644 " mfctr %r0 \n"
645 " mfspr %r3, dCmp \n"
646 " addi %r2, %r2, -8\n"
647 "ceq0: mtctr %r1 \n"
648 "ceq1: lwzu %r1, 8(%r2) \n"
649 " cmp c0, %r1, %r3\n"
650 " bdnzf eq, ceq1 \n"
651 " bne cEq0SecHash \n"
652 " l %r1, +4(%r2)\n"
653 " andi. %r3,%r1,0x80\n"
654 " beq cEq0ChkProt \n"
655 "ceq2: mtctr %r0 \n"
656 " mfspr %r0, dMiss \n"
657 " mfspr %r3, srr1 \n"
658 " mtcrf 0x80, %r3 \n"
659 " mtspr rpa, %r1 \n"
660 " tlbld %r0 \n"
661 " rfi \n"
663 "cEq0SecHash: \n"
664 " andi. %r1, %r3, 0x0040\n"
665 " bne doDSI \n"
666 " mfspr %r2, hash2 \n"
667 " ori %r3, %r3, 0x0040\n"
668 " addi %r1, 0, 8 \n"
669 " addi %r2, %r2, -8\n"
670 " b ceq0 \n"
672 "cEq0ChkProt: \n"
673 " rlwinm. %r3,%r1,30,0,1\n"
674 " bge- chk0 \n"
675 " andi. %r3,%r1,1 \n"
676 " beq+ chk2 \n"
677 " b doDSIp \n"
678 "chk0: mfspr %r3,srr1 \n"
679 " andis. %r3,%r3,0x0008\n"
680 " beq chk2 \n"
681 " b doDSIp \n"
683 "chk2: ori %r1, %r1, 0x180\n"
684 " sth %r1, 6(%r2) \n"
685 " b ceq2 \n"
687 "doDSI: \n"
688 " mfspr %r3, srr1 \n"
689 " rlwinm %r1, %r3, 9,6,6 \n"
690 " addis %r1, %r1, 0x4000 \n"
691 " b dsi1 \n"
693 "doDSIp: \n"
694 " mfspr %r3, srr1 \n"
695 " rlwinm %r1, %r3, 9,6,6 \n"
696 " addis %r1, %r1, 0x0800 \n"
698 "dsi1: \n"
699 " mtctr %r0 \n"
700 " andi. %r2, %r3, 0xffff \n"
701 " mtspr srr1, %r2 \n"
702 " mtspr dsisr, %r1 \n"
703 " mfspr %r1, dMiss \n"
704 " rlwinm. %r2,%r2,0,31,31 \n"
705 " beq dsi2 \n"
706 " xor %r1,%r1,0x07 \n"
708 "dsi2: \n"
709 " mtspr dar, %r1 \n"
710 " mfmsr %r0 \n"
711 " xoris %r0, %r0, 0x2 \n"
712 " mtcrf 0x80, %r3 \n"
713 " mtmsr %r0 \n"
714 " ba 0x0300 \n"
718 asm volatile(".align 8;");