Author: nwhitehorn
Date: Thu Nov 11 02:40:00 2010
New Revision: 215107
URL: http://svn.freebsd.org/changeset/base/215107

Log:
  Add support for the IMISS, DLMISS, and DSMISS traps required to run
  FreeBSD on a G2 core.
  
  PR:           powerpc/111296
  Submitted by: Andrew Turner

Modified:
  head/sys/powerpc/aim/machdep.c
  head/sys/powerpc/aim/trap_subr32.S

Modified: head/sys/powerpc/aim/machdep.c
==============================================================================
--- head/sys/powerpc/aim/machdep.c      Thu Nov 11 02:37:50 2010        
(r215106)
+++ head/sys/powerpc/aim/machdep.c      Thu Nov 11 02:40:00 2010        
(r215107)
@@ -245,6 +245,9 @@ extern void *dsitrap, *dsisize;
 extern void    *decrint, *decrsize;
 extern void     *extint, *extsize;
 extern void    *dblow, *dbsize;
+extern void    *imisstrap, *imisssize;
+extern void    *dlmisstrap, *dlmisssize;
+extern void    *dsmisstrap, *dsmisssize;
 
 uintptr_t
 powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
@@ -491,6 +494,12 @@ powerpc_init(vm_offset_t startkernel, vm
        bcopy(generictrap, (void *)EXC_VEC,  (size_t)&trapsize);
        bcopy(generictrap, (void *)EXC_VECAST_G4, (size_t)&trapsize);
        bcopy(generictrap, (void *)EXC_VECAST_G5, (size_t)&trapsize);
+       #ifndef __powerpc64__
+       /* G2-specific TLB miss helper handlers */
+       bcopy(&imisstrap, (void *)EXC_IMISS,  (size_t)&imisssize);
+       bcopy(&dlmisstrap, (void *)EXC_DLMISS,  (size_t)&dlmisssize);
+       bcopy(&dsmisstrap, (void *)EXC_DSMISS,  (size_t)&dsmisssize);
+       #endif
        __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
 
        /*

Modified: head/sys/powerpc/aim/trap_subr32.S
==============================================================================
--- head/sys/powerpc/aim/trap_subr32.S  Thu Nov 11 02:37:50 2010        
(r215106)
+++ head/sys/powerpc/aim/trap_subr32.S  Thu Nov 11 02:40:00 2010        
(r215107)
@@ -362,6 +362,207 @@ CNAME(alitrap):
 CNAME(alisize) = .-CNAME(alitrap)
 
 /*
+ * G2 specific: instuction TLB miss.
+ */
+       .globl  CNAME(imisstrap),CNAME(imisssize)
+CNAME(imisstrap):
+       mfspr %r2, SPR_HASH1            /* get first pointer */
+       addi %r1, 0, 8                  /* load 8 for counter */
+       mfctr %r0                       /* save counter */
+       mfspr %r3, SPR_ICMP             /* get first compare value */
+       addi %r2, %r2, -8               /* pre dec the pointer */
+im0:
+       mtctr %r1                       /* load counter */
+im1:
+       lwzu %r1, 8(%r2)                /* get next pte */
+       cmp 0, %r1, %r3                 /* see if found pte */
+       bdnzf 2, im1                    /* dec count br if cmp ne and if
+                                        * count not zero */
+       bne instr_sec_hash              /* if not found set up second hash
+                                        * or exit */
+       lwz %r1, +4(%r2)                /* load tlb entry lower-word */
+       andi. %r3, %r1, 8               /* check G bit */
+       bne do_isi_prot                 /* if guarded, take an ISI */
+       mtctr %r0                       /* restore counter */
+       mfspr %r0, SPR_IMISS            /* get the miss address for the tlbli */
+       mfspr %r3, SPR_SRR1             /* get the saved cr0 bits */
+       mtcrf 0x80, %r3                 /* restore CR0 */
+       mtspr SPR_RPA, %r1              /* set the pte */
+       ori %r1, %r1, 0x100             /* set reference bit */
+       srwi %r1, %r1, 8                /* get byte 7 of pte */
+       tlbli %r0                       /* load the itlb */
+       stb %r1, +6(%r2)                /* update page table */
+       rfi                             /* return to executing program */
+
+instr_sec_hash:
+       andi. %r1, %r3, 0x0040          /* see if we have done second hash */
+       bne do_isi                      /* if so, go to ISI interrupt */
+       mfspr %r2, SPR_HASH2            /* get the second pointer */
+       ori %r3, %r3, 0x0040            /* change the compare value */
+       addi %r1, %r0, 8                /* load 8 for counter */
+       addi %r2, %r2, -8               /* pre dec for update on load */
+       b im0                           /* try second hash */
+
+/* Create a faked ISI interrupt as the address was not found */ 
+do_isi_prot:
+       mfspr %r3, SPR_SRR1             /* get srr1 */
+       andi. %r2, %r3, 0xffff          /* clean upper srr1 */
+       addis %r2, %r2, 0x0800          /* or in srr<4> = 1 to flag prot
+                                        * violation */
+       b isi1
+do_isi:
+       mfspr %r3, SPR_SRR1             /* get srr1 */
+       andi. %r2, %r3, 0xffff          /* clean srr1 */
+       addis %r2, %r2, 0x4000          /* or in srr1<1> = 1 to flag pte
+                                        * not found */
+isi1: 
+       mtctr %r0                       /* restore counter */
+       mtspr SPR_SRR1, %r2             /* set srr1 */
+       mfmsr %r0                       /* get msr */
+       xoris %r0, %r0, 0x2             /* flip the msr<tgpr> bit */
+       mtcrf 0x80, %r3                 /* restore CR0 */
+       mtmsr %r0                       /* flip back to the native gprs */
+       ba EXC_ISI                      /* go to instr. access interrupt */
+
+CNAME(imisssize) = .-CNAME(imisstrap)
+
+/*
+ * G2 specific: data load TLB miss.
+ */
+       .globl  CNAME(dlmisstrap),CNAME(dlmisssize)
+CNAME(dlmisstrap):
+       mfspr %r2, SPR_HASH1            /* get first pointer */
+       addi %r1, 0, 8                  /* load 8 for counter */
+       mfctr %r0                       /* save counter */
+       mfspr %r3, SPR_DCMP             /* get first compare value */
+       addi %r2, %r2, -8               /* pre dec the pointer */
+dm0: 
+       mtctr %r1                       /* load counter */
+dm1:   
+       lwzu %r1, 8(%r2)                /* get next pte */
+       cmp 0, 0, %r1, %r3              /* see if found pte */
+       bdnzf 2, dm1                    /* dec count br if cmp ne and if
+                                        * count not zero */
+       bne data_sec_hash               /* if not found set up second hash
+                                        * or exit */
+       lwz %r1, +4(%r2)                /* load tlb entry lower-word */
+       mtctr %r0                       /* restore counter */
+       mfspr %r0, SPR_DMISS            /* get the miss address for the tlbld */
+       mfspr %r3, SPR_SRR1             /* get the saved cr0 bits */
+       mtcrf 0x80, %r3                 /* restore CR0 */
+       mtspr SPR_RPA, %r1              /* set the pte */
+       ori %r1, %r1, 0x100             /* set reference bit */
+       srwi %r1, %r1, 8                /* get byte 7 of pte */
+       tlbld %r0                       /* load the dtlb */
+       stb %r1, +6(%r2)                /* update page table */
+       rfi                             /* return to executing program */
+ 
+data_sec_hash:
+       andi. %r1, %r3, 0x0040          /* see if we have done second hash */
+       bne do_dsi                      /* if so, go to DSI interrupt */
+       mfspr %r2, SPR_HASH2            /* get the second pointer */
+       ori %r3, %r3, 0x0040            /* change the compare value */
+       addi %r1, 0, 8                  /* load 8 for counter */
+       addi %r2, %r2, -8               /* pre dec for update on load */
+       b dm0                           /* try second hash */
+
+CNAME(dlmisssize) = .-CNAME(dlmisstrap)
+
+/*
+ *  G2 specific: data store TLB miss.
+ */
+       .globl  CNAME(dsmisstrap),CNAME(dsmisssize)
+CNAME(dsmisstrap):
+       mfspr %r2, SPR_HASH1            /* get first pointer */
+       addi %r1, 0, 8                  /* load 8 for counter */
+       mfctr %r0                       /* save counter */
+       mfspr %r3, SPR_DCMP             /* get first compare value */
+       addi %r2, %r2, -8               /* pre dec the pointer */
+ds0:
+       mtctr %r1                       /* load counter */
+ds1:
+       lwzu %r1, 8(%r2)                /* get next pte */
+       cmp 0, 0, %r1, %r3              /* see if found pte */
+       bdnzf 2, ds1                    /* dec count br if cmp ne and if
+                                        * count not zero */
+       bne data_store_sec_hash         /* if not found set up second hash
+                                        * or exit */
+       lwz %r1, +4(%r2)                /* load tlb entry lower-word */
+       andi. %r3, %r1, 0x80            /* check the C-bit */
+       beq data_store_chk_prot         /* if (C==0)
+                                        *     go check protection modes */
+ds2:
+       mtctr %r0                       /* restore counter */
+       mfspr %r0, SPR_DMISS            /* get the miss address for the tlbld */
+       mfspr %r3, SPR_SRR1             /* get the saved cr0 bits */
+       mtcrf 0x80, %r3                 /* restore CR0 */
+       mtspr SPR_RPA, %r1              /* set the pte */
+       tlbld %r0                       /* load the dtlb */
+       rfi                             /* return to executing program */
+
+data_store_sec_hash:
+       andi. %r1, %r3, 0x0040          /* see if we have done second hash */
+       bne do_dsi                      /* if so, go to DSI interrupt */
+       mfspr %r2, SPR_HASH2            /* get the second pointer */
+       ori %r3, %r3, 0x0040            /* change the compare value */
+       addi %r1, 0, 8                  /* load 8 for counter */
+       addi %r2, %r2, -8               /* pre dec for update on load */
+       b ds0                           /* try second hash */
+       
+/* Check the protection before setting PTE(c-bit) */
+data_store_chk_prot:
+       rlwinm. %r3,%r1,30,0,1          /* test PP */
+       bge- chk0                       /* if (PP == 00 or PP == 01)
+                                        *     goto chk0: */
+       andi. %r3, %r1, 1               /* test PP[0] */
+       beq+ chk2                       /* return if PP[0] == 0 */
+       b do_dsi_prot                   /* else DSIp */
+chk0:
+       mfspr %r3,SPR_SRR1              /* get old msr */
+       andis. %r3,%r3,0x0008           /* test the KEY bit (SRR1-bit 12) */
+       beq chk2                        /* if (KEY==0) goto chk2: */
+       b do_dsi_prot                   /* else do_dsi_prot */
+chk2:
+       ori %r1, %r1, 0x180             /* set reference and change bit */
+       sth %r1, 6(%r2)                 /* update page table */
+       b ds2                           /* and back we go */
+       
+/* Create a faked DSI interrupt as the address was not found */ 
+do_dsi:
+       mfspr %r3, SPR_SRR1             /* get srr1 */
+       rlwinm %r1,%r3,9,6,6            /* get srr1<flag> to bit 6 for
+                                        * load/store, zero rest */
+       addis %r1, %r1, 0x4000          /* or in dsisr<1> = 1 to flag pte
+                                        * not found */
+       b dsi1
+
+do_dsi_prot:
+       mfspr %r3, SPR_SRR1             /* get srr1 */
+       rlwinm %r1,%r3,9,6,6            /* get srr1<flag> to bit 6 for
+                                          *load/store, zero rest */
+       addis %r1, %r1, 0x0800          /* or in dsisr<4> = 1 to flag prot
+                                        * violation */
+
+dsi1:
+       mtctr %r0                       /* restore counter */
+       andi. %r2, %r3, 0xffff          /* clear upper bits of srr1 */
+       mtspr SPR_SRR1, %r2             /* set srr1 */
+       mtspr SPR_DSISR, %r1            /* load the dsisr */
+       mfspr %r1, SPR_DMISS            /* get miss address */
+       rlwinm. %r2,%r2,0,31,31         /* test LE bit */
+       beq dsi2                        /* if little endian then: */
+       xor %r1, %r1, 0x07              /* de-mung the data address */
+dsi2:
+       mtspr SPR_DAR, %r1              /* put in dar */
+       mfmsr %r0                       /* get msr */
+       xoris %r0, %r0, 0x2             /* flip the msr<tgpr> bit */
+       mtcrf 0x80, %r3                 /* restore CR0 */
+       mtmsr %r0                       /* flip back to the native gprs */
+       ba EXC_DSI                      /* branch to DSI interrupt */
+
+CNAME(dsmisssize) = .-CNAME(dsmisstrap)
+
+/*
  * Similar to the above for DSI
  * Has to handle BAT spills
  * and standard pagetable spills
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to