Port-sparc64 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: sparc[64] smp



>>> Martin Husemann <martin%duskware.de@localhost> wrote

> Not quite, sorry. Loking is solved "good enough" now (or so I think), but
> tlb shootdown is not completely adapted (actually it is mostly disabled
> right now) and some interrupt changes are missing. I'm working on it.

I made a patch to make interrupt pending list per-CPU and tickintr
MP-safe. (and remove unused port-sparc derived interrupt code.)

Please review this patch.

-- Takeshi Nakayama
Index: include/cpu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/include/cpu.h,v
retrieving revision 1.74
diff -u -d -r1.74 cpu.h
--- include/cpu.h       28 Feb 2008 11:50:40 -0000      1.74
+++ include/cpu.h       2 Mar 2008 12:50:10 -0000
@@ -70,6 +70,7 @@
 #include <sparc64/sparc64/intreg.h>
 
 #include <sys/cpu_data.h>
+#include <sys/evcnt.h>
 /*
  * The cpu_info structure is part of a 64KB structure mapped both the kernel
  * pmap and a single locked TTE a CPUINFO_VA for that particular processor.
@@ -124,6 +125,11 @@
        u_long                  ci_tick_increment;
        uint64_t                ci_cpu_clockrate[2];
 
+       /* Interrupts */
+       struct intrhand         *ci_intrpending[16];
+       struct intrhand         *ci_intrlev0;
+       struct evcnt            ci_tick_evcnt;
+
        int                     ci_flags;
        int                     ci_want_ast;
        int                     ci_want_resched;
@@ -317,6 +323,7 @@
 int    tickintr(void *);       /* level 10 (tick) interrupt code */
 int    clockintr(void *);      /* level 10 (clock) interrupt code */
 int    statintr(void *);       /* level 14 (statclock) interrupt code */
+void   tickintr_establish(void);
 /* locore.s */
 struct fpstate64;
 void   savefpstate(struct fpstate64 *);
Index: sparc64/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/clock.c,v
retrieving revision 1.88
diff -u -d -r1.88 clock.c
--- sparc64/clock.c     17 Oct 2007 19:57:30 -0000      1.88
+++ sparc64/clock.c     2 Mar 2008 12:50:10 -0000
@@ -112,11 +112,9 @@
 int schedintr(void *);
 
 static struct intrhand level10 = { .ih_fun = clockintr };
-static struct intrhand level0 = { .ih_fun = tickintr };
 static struct intrhand level14 = { .ih_fun = statintr };
 static struct intrhand schedint = { .ih_fun = schedintr };
 
-void           tickintr_establish(void);
 static int     timermatch(struct device *, struct cfdata *, void *);
 static void    timerattach(struct device *, struct device *, void *);
 
@@ -262,21 +260,23 @@
 void
 tickintr_establish()
 {
-       static bool done = false;       /* only do this once */
+       struct intrhand *ih;
 
-       if (!done) {
-               done = true;
+       ih = malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT|M_ZERO);
+       KASSERT(ih != NULL);
 
-               level0.ih_clr = 0;
-               /* 
-                * Establish a level 10 interrupt handler 
-                *
-                * We will have a conflict with the softint handler,
-                * so we set the ih_number to 1.
-                */
-               level0.ih_number = 1;
-               intr_establish(10, &level0);
+       ih->ih_fun = tickintr;
+       ih->ih_arg = 0;
+       ih->ih_clr = 0;
+       ih->ih_number = 1;
+       if (CPU_IS_PRIMARY(curcpu()))
+               intr_establish(10, ih);
+       else {
+               ih->ih_pil = 10;
+               ih->ih_pending = 0;
+               ih->ih_next = NULL;
        }
+       curcpu()->ci_intrlev0 = ih;
 
        /* set the next interrupt time */
        curcpu()->ci_tick_increment = curcpu()->ci_cpu_clockrate[0] / hz;
@@ -476,6 +476,7 @@
        /* Reset the interrupt */
        next_tick(curcpu()->ci_tick_increment);
        splx(s);
+       curcpu()->ci_tick_evcnt.ev_count++;
 
        return (1);
 }
Index: sparc64/cpu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/cpu.c,v
retrieving revision 1.67
diff -u -d -r1.67 cpu.c
--- sparc64/cpu.c       28 Feb 2008 11:50:40 -0000      1.67
+++ sparc64/cpu.c       2 Mar 2008 12:50:10 -0000
@@ -54,6 +54,8 @@
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.67 2008/02/28 11:50:40 martin Exp $");
 
+#include "opt_multiprocessor.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/device.h>
@@ -150,13 +152,16 @@
        cpi->ci_self = cpi;
        cpi->ci_node = cpu_node;
        cpi->ci_idepth = -1;
+       memset(cpi->ci_intrpending, -1, sizeof(cpi->ci_intrpending));
 
        /*
         * Finally, add itself to the list of active cpus.
         */
        for (ci = cpus; ci->ci_next != NULL; ci = ci->ci_next)
                ;
+#ifdef MULTIPROCESSOR
        ci->ci_next = cpi;
+#endif
        return (cpi);
 }
 
@@ -231,6 +236,8 @@
                mi_cpu_attach(ci);
                ci->ci_cpcb = (struct pcb *)ci->ci_data.cpu_idlelwp->l_addr;
        }
+       evcnt_attach_dynamic(&ci->ci_tick_evcnt, EVCNT_TYPE_INTR, NULL,
+                            dev->dv_xname, "timer");
 #endif
 
        clk = prom_getpropint(node, "clock-frequency", 0);
@@ -401,6 +408,7 @@
        cpu_reset_fpustate();
        curlwp = curcpu()->ci_data.cpu_idlelwp;
        membar_sync();
+       tickintr_establish();
        spl0();
 }
 #endif /* MULTIPROCESSOR */
Index: sparc64/genassym.cf
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/genassym.cf,v
retrieving revision 1.52
diff -u -d -r1.52 genassym.cf
--- sparc64/genassym.cf 28 Feb 2008 11:50:40 -0000      1.52
+++ sparc64/genassym.cf 2 Mar 2008 12:50:10 -0000
@@ -173,6 +173,8 @@
 define CI_IDLELWP      offsetof(struct cpu_info, ci_data.cpu_idlelwp)
 define CI_CLOCKRATE    offsetof(struct cpu_info, ci_cpu_clockrate)
 define CI_IDEPTH       offsetof(struct cpu_info, ci_idepth)
+define CI_INTRPENDING  offsetof(struct cpu_info, ci_intrpending)
+define CI_INTRLEV0     offsetof(struct cpu_info, ci_intrlev0)
 define CI_CTXBUSY      offsetof(struct cpu_info, ci_ctxbusy)
 define CI_TSB_DMMU     offsetof(struct cpu_info, ci_tsb_dmmu)
 define CI_TSB_IMMU     offsetof(struct cpu_info, ci_tsb_immu)
Index: sparc64/intr.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/intr.c,v
retrieving revision 1.55
diff -u -d -r1.55 intr.c
--- sparc64/intr.c      18 Feb 2008 12:16:37 -0000      1.55
+++ sparc64/intr.c      2 Mar 2008 12:50:10 -0000
@@ -44,7 +44,7 @@
 __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.55 2008/02/18 12:16:37 martin Exp $");
 
 #include "opt_ddb.h"
-#include "pcons.h"
+#include "opt_multiprocessor.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -67,7 +67,6 @@
 struct intrhand *intrlev[MAXINTNUM];
 
 void   strayintr(const struct trapframe64 *, int);
-int    softintr(void *);
 int    intr_list_handler(void *);
 
 /*
@@ -116,57 +115,6 @@
 }
 
 /*
- * Level 1 software interrupt (could also be Sbus level 1 interrupt).
- * Three possible reasons:
- *     Network software interrupt
- *     Soft clock interrupt
- */
-int
-softintr(void *fp)
-{
-#if NPCONS >0
-       extern void pcons_dopoll(void);
-
-       pcons_dopoll();
-#endif
-       return (1);
-}
-
-
-struct intrhand soft01intr = { .ih_fun = softintr, .ih_number = 1 };
-
-#if 0
-void 
-setsoftint() {
-       send_softint(-1, IPL_SOFTINT, &soft01intr);
-}
-#endif
-
-/*
- * Level 15 interrupts are special, and not vectored here.
- * Only `prewired' interrupts appear here; boot-time configured devices
- * are attached via intr_establish() below.
- */
-struct intrhand *intrhand[16] = {
-       NULL,                   /*  0 = error */
-       &soft01intr,            /*  1 = software level 1 + Sbus */
-       NULL,                   /*  2 = Sbus level 2 (4m: Sbus L1) */
-       NULL,                   /*  3 = SCSI + DMA + Sbus level 3 (4m: L2,lpt)*/
-       NULL,                   /*  4 = software level 4 (tty softint) (scsi) */
-       NULL,                   /*  5 = Ethernet + Sbus level 4 (4m: Sbus L3) */
-       NULL,                   /*  6 = software level 6 (not used) (4m: enet)*/
-       NULL,                   /*  7 = video + Sbus level 5 */
-       NULL,                   /*  8 = Sbus level 6 */
-       NULL,                   /*  9 = Sbus level 7 */
-       NULL,                   /* 10 = counter 0 = clock */
-       NULL,                   /* 11 = floppy */
-       NULL,                   /* 12 = zs hardware interrupt */
-       NULL,                   /* 13 = audio chip */
-       NULL,                   /* 14 = counter 1 = profiling timer */
-       NULL                    /* 15 = async faults */
-};
-
-/*
  * PCI devices can share interrupts so we need to have
  * a handler to hand out interrupts.
  */
@@ -217,7 +165,7 @@
 void
 intr_establish(int level, struct intrhand *ih)
 {
-       struct intrhand **p, *q = NULL;
+       struct intrhand *q = NULL;
 #ifdef MULTIPROCESSOR
        bool mpsafe = (level != IPL_VM);
 #endif
@@ -289,12 +237,5 @@
        } else
                panic("intr_establish: bad intr number %x", ih->ih_number);
 
-       /* If it's not shared, stick it in the intrhand list for that level. */
-       if (q == NULL) {
-               for (p = &intrhand[level]; (q = *p) != NULL; p = &q->ih_next)
-                       ;
-               *p = ih;
-       }
-
        splx(s);
 }
Index: sparc64/locore.s
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/locore.s,v
retrieving revision 1.268
diff -u -d -r1.268 locore.s
--- sparc64/locore.s    2 Mar 2008 12:19:00 -0000       1.268
+++ sparc64/locore.s    2 Mar 2008 12:50:13 -0000
@@ -3595,16 +3595,14 @@
  * and invokes the interrupt handler.
  */
 
-       .data
-       .globl  intrpending
-intrpending:
-       .space  16 * 8 * PTRSZ, -1
+/* intrpending array is now in per-CPU structure. */
 
 #ifdef DEBUG
 #define INTRDEBUG_VECTOR       0x1
 #define INTRDEBUG_LEVEL                0x2
 #define INTRDEBUG_FUNC         0x4
 #define INTRDEBUG_SPUR         0x8
+       .data
        .globl  _C_LABEL(intrdebug)
 _C_LABEL(intrdebug):   .word 0x0
 /*
@@ -3672,9 +3670,9 @@
        LDPTR   [%g5+IH_PEND], %g6      ! Read pending flag
        brnz,pn %g6, ret_from_intr_vector ! Skip it if it's running
         ldub   [%g5+IH_PIL], %g6       ! Read interrupt mask
-       sethi   %hi(intrpending), %g1
-       sll     %g6, PTRSHFT+3, %g3     ! Find start of table for this IPL
-       or      %g1, %lo(intrpending), %g1
+       sethi   %hi(CPUINFO_VA+CI_INTRPENDING), %g1
+       sll     %g6, PTRSHFT, %g3       ! Find start of table for this IPL
+       or      %g1, %lo(CPUINFO_VA+CI_INTRPENDING), %g1
         add    %g1, %g3, %g1
 1:
        LDPTR   [%g1], %g3              ! Load list head
@@ -4017,18 +4015,17 @@
        rd      SOFTINT, %g1
        btst    1, %g1
        bz,pt   %icc, 0f
-        set    _C_LABEL(intrlev), %g3
+        sethi  %hi(CPUINFO_VA+CI_INTRLEV0), %g3
        wr      %g0, 1, CLEAR_SOFTINT
-       DLFLUSH(%g3, %g2)
        ba,pt   %icc, setup_sparcintr
-        LDPTR  [%g3 + PTRSZ], %g5      ! intrlev[1] is reserved for %tick intr.
+        LDPTR  [%g3 + %lo(CPUINFO_VA+CI_INTRLEV0)], %g5
 0:
 
        ! Increment the per-cpu interrupt level
-       set     CPUINFO_VA+CI_IDEPTH, %g1
-       ld      [%g1], %g2
+       sethi   %hi(CPUINFO_VA+CI_IDEPTH), %g1
+       ld      [%g1 + %lo(CPUINFO_VA+CI_IDEPTH)], %g2
        inc     %g2
-       st      %g2, [%g1]
+       st      %g2, [%g1 + %lo(CPUINFO_VA+CI_IDEPTH)]
 
 #ifdef TRAPSTATS
        sethi   %hi(_C_LABEL(kintrcnt)), %g1
@@ -4112,10 +4109,9 @@
 
 sparc_intr_retry:
        wr      %l3, 0, CLEAR_SOFTINT   ! (don't clear possible %tick IRQ)
-       sll     %l6, PTRSHFT+3, %l2
-       sethi   %hi(intrpending), %l4
-       or      %l4, %lo(intrpending), %l4
-       mov     8, %l7
+       sethi   %hi(CPUINFO_VA+CI_INTRPENDING), %l4
+       sll     %l6, PTRSHFT, %l2
+       or      %l4, %lo(CPUINFO_VA+CI_INTRPENDING), %l4
        add     %l2, %l4, %l4
 
 1:
@@ -4128,8 +4124,9 @@
        CASPTR  [%l4] ASI_N, %l2, %l7   ! Grab the entire list
        cmp     %l7, %l2
        bne,pn  %icc, 1b
-        add    %sp, CC64FSZ+STKB, %o2  ! tf = %sp + CC64FSZ + STKB
+        nop
 2:
+       add     %sp, CC64FSZ+STKB, %o2  ! tf = %sp + CC64FSZ + STKB
        LDPTR   [%l2 + IH_PEND], %l7    ! save ih->ih_pending
        membar  #LoadStore
        STPTR   %g0, [%l2 + IH_PEND]    ! Clear pending flag
@@ -4166,10 +4163,10 @@
         mov    1, %l5                  ! initialize intr count for next run
 
        ! Decrement this cpu's interrupt depth
-       set     CPUINFO_VA+CI_IDEPTH, %l4
-       ld      [%l4], %l5
+       sethi   %hi(CPUINFO_VA+CI_IDEPTH), %l4
+       ld      [%l4 + %lo(CPUINFO_VA+CI_IDEPTH)], %l5
        dec     %l5
-       st      %l5, [%l4]
+       st      %l5, [%l4 + %lo(CPUINFO_VA+CI_IDEPTH)]
 
 #ifdef DEBUG
        set     _C_LABEL(intrdebug), %o2
@@ -5121,6 +5118,10 @@
         *      %g2 = cpu_args
         */
 ENTRY(cpu_mp_startup)
+       mov     1, %o0
+       sllx    %o0, 63, %o0
+       wr      %o0, TICK_CMPR  ! XXXXXXX clear and disable %tick_cmpr for now
+       wrpr    %g0, 0, %tick   ! XXXXXXX clear %tick register as well
        wrpr    %g0, 0, %cleanwin
        wrpr    %g0, 0, %tl                     ! Make sure we're not in 
NUCLEUS mode
        wrpr    %g0, WSTATE_KERN, %wstate
@@ -9528,10 +9529,11 @@
 
        ldx     [%o0 + FS_FSR], %o4     ! if (f->fs_fsr & QNE)
        btst    %o2, %o4
-       add     %o0, FS_REGS, %o2
        bnz     Lfp_storeq              !       goto storeq;
+        nop
 Lfp_finish:
-        btst   BLOCK_ALIGN, %o2        ! Needs to be re-executed
+       add     %o0, FS_REGS, %o2
+       btst    BLOCK_ALIGN, %o2        ! Needs to be re-executed
        bnz,pn  %icc, 3f                ! Check alignment
         st     %o3, [%o0 + FS_QSIZE]   ! f->fs_qsize = qsize;
        btst    FPRS_DL, %o5            ! Lower FPU clean?
@@ -9631,7 +9633,7 @@
        stx     %o4, [%o1 + %o3]        ! q[qsize++] = fsr_qfront();
        stx     %fsr, [%o0 + FS_FSR]    ! reread fsr
        ldx     [%o0 + FS_FSR], %o4     ! if fsr & QNE, loop
-       btst    %o5, %o4
+       btst    %o2, %o4
        bnz     1b
         inc    8, %o3
        b       Lfp_finish              ! set qsize and finish storing fregs
@@ -9757,10 +9759,11 @@
        andn    %g1, PSTATE_IE, %g2     ! clear PSTATE.IE
        wrpr    %g2, 0, %pstate
 
-       set     intrpending, %o3
+       sethi   %hi(CPUINFO_VA+CI_INTRPENDING), %o3
        LDPTR   [%o2 + IH_PEND], %o5
+       or      %o3, %lo(CPUINFO_VA+CI_INTRPENDING), %o3
        brnz    %o5, 1f
-        sll    %o1, PTRSHFT+3, %o5     ! Find start of table for this IPL
+        sll    %o1, PTRSHFT, %o5       ! Find start of table for this IPL
        add     %o3, %o5, %o3
 2:
        LDPTR   [%o3], %o5              ! Load list head
Index: sparc64/pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/pmap.c,v
retrieving revision 1.210
diff -u -d -r1.210 pmap.c
--- sparc64/pmap.c      28 Feb 2008 11:50:40 -0000      1.210
+++ sparc64/pmap.c      2 Mar 2008 12:50:14 -0000
@@ -1055,6 +1055,7 @@
                cpus->ci_cpcb = (struct pcb *)u0va;
                proc0paddr = cpus->ci_cpcb;
                cpus->ci_idepth = -1;
+               memset(cpus->ci_intrpending, -1, sizeof(cpus->ci_intrpending));
 
                lwp0.l_addr = (struct user*)u0va;
                lwp0.l_md.md_tf = (struct trapframe64*)(u0va + USPACE


Home | Main Index | Thread Index | Old Index