Port-sparc archive

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

partially working SMP again



hi folks.


i spent a bunch of time investigating sparc SMP issues this weekend
and i've gotten my system to the point it turns on interrupts and
then loses, instead of crashing before printing the copyright or
while attaching cpus.

i haven't yet looked at the interrupt problem -- i'm seeing both
stray intrs and lockups, but i thought i'd post this here for others
(hi martin!) to look at.


basic changes are:
         - kill union cpu_info_pg
         - allocate USPACE after the intstack (this is the real
           bug fix)
         - make cpus[] as array of cpu_info{} *'s.
         - allocate cpu_info{}'s in pmap_bootstrap via stealing
           pages aka pmap_bootstrap style.
         - we waste a page of for cpu0's cpu_info above, but for
           now just ignore this, we use the VA it would use, but
           remap the boot CPUINFO_VA physaddr to there

anyone wants to jump in and look at the interrupt lossage is more
than welcome.  i'll update here if i have more news.


.mrg.


Index: sparc/cpu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpu.c,v
retrieving revision 1.213
diff -p -r1.213 cpu.c
*** sparc/cpu.c 10 Mar 2009 23:58:20 -0000      1.213
--- sparc/cpu.c 17 May 2009 22:21:21 -0000
*************** extern char machine_model[];
*** 103,109 ****
  
  int   sparc_ncpus;                    /* # of CPUs detected by PROM */
  #ifdef MULTIPROCESSOR
! union cpu_info_pg *cpus;
  u_int cpu_ready_mask;                 /* the set of CPUs marked as READY */
  #endif
  
--- 103,109 ----
  
  int   sparc_ncpus;                    /* # of CPUs detected by PROM */
  #ifdef MULTIPROCESSOR
! struct cpu_info *cpus[4];             /* we only support 4 CPUs. */
  u_int cpu_ready_mask;                 /* the set of CPUs marked as READY */
  #endif
  
*************** init_cpuinfo(struct cpu_info *cpi, int n
*** 158,164 ****
        /*
         * Arrange pcb and interrupt stack.
         */
!       intstack = uvm_km_alloc(kernel_map, INT_STACK_SIZE,
                0, UVM_KMF_WIRED);
        if (intstack == 0)
                panic("%s: no uspace/intstack", __func__);
--- 158,164 ----
        /*
         * Arrange pcb and interrupt stack.
         */
!       intstack = uvm_km_alloc(kernel_map, INT_STACK_SIZE + USPACE,
                0, UVM_KMF_WIRED);
        if (intstack == 0)
                panic("%s: no uspace/intstack", __func__);
*************** cpu_attach(struct cpu_softc *sc, int nod
*** 339,345 ****
                getcpuinfo(&cpuinfo, node);
  
  #if defined(MULTIPROCESSOR)
!               cpi = sc->sc_cpuinfo = cpuinfo.ci_self;
  #else
                /* The `local' VA is global for uniprocessor. */
                cpi = sc->sc_cpuinfo = (struct cpu_info *)CPUINFO_VA;
--- 339,345 ----
                getcpuinfo(&cpuinfo, node);
  
  #if defined(MULTIPROCESSOR)
!               cpi = sc->sc_cpuinfo = cpus[idx];
  #else
                /* The `local' VA is global for uniprocessor. */
                cpi = sc->sc_cpuinfo = (struct cpu_info *)CPUINFO_VA;
*************** cpu_attach(struct cpu_softc *sc, int nod
*** 362,368 ****
                /*
                 * Initialise this cpu's cpu_info.
                 */
!               cpi = sc->sc_cpuinfo = &cpus[idx].ci;
                init_cpuinfo(cpi, node);
  
                /*
--- 362,368 ----
                /*
                 * Initialise this cpu's cpu_info.
                 */
!               cpi = sc->sc_cpuinfo = cpus[idx];
                init_cpuinfo(cpi, node);
  
                /*
Index: sparc/cpuvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpuvar.h,v
retrieving revision 1.76
diff -p -r1.76 cpuvar.h
*** sparc/cpuvar.h      10 Mar 2009 23:58:20 -0000      1.76
--- sparc/cpuvar.h      17 May 2009 22:21:21 -0000
*************** struct cpu_info {
*** 416,422 ****
  
  #define CPU_INFO_ITERATOR             int
  #ifdef MULTIPROCESSOR
! #define CPU_INFO_FOREACH(cii, cp)     cii = 0; cp = &cpus[cii].ci, cii < 
sparc_ncpus; cii++
  #else
  #define       CPU_INFO_FOREACH(cii, cp)       (void)cii, cp = curcpu(); cp != 
NULL; cp = NULL
  #endif
--- 416,422 ----
  
  #define CPU_INFO_ITERATOR             int
  #ifdef MULTIPROCESSOR
! #define CPU_INFO_FOREACH(cii, cp)     cii = 0; cp = cpus[cii], cii < 
sparc_ncpus; cii++
  #else
  #define       CPU_INFO_FOREACH(cii, cp)       (void)cii, cp = curcpu(); cp != 
NULL; cp = NULL
  #endif
*************** extern int bootmid;                     /* Module ID of bo
*** 473,483 ****
  #define CPU_MID2CPUNO(mid)            ((mid) != 0 ? (mid) - 8 : 0)
  
  #ifdef MULTIPROCESSOR
! union cpu_info_pg {
!       struct cpu_info ci;     /* cpu info (aliased (per cpu) to CPUINFO_VA */
!       char pad[32 * 1024];    /* XXX: force 32K alignment for now */
! };                            /* SMP capable cpu types */
! extern union cpu_info_pg *cpus;
  extern u_int cpu_ready_mask;          /* the set of CPUs marked as READY */
  #endif
  
--- 473,479 ----
  #define CPU_MID2CPUNO(mid)            ((mid) != 0 ? (mid) - 8 : 0)
  
  #ifdef MULTIPROCESSOR
! extern struct cpu_info *cpus[];
  extern u_int cpu_ready_mask;          /* the set of CPUs marked as READY */
  #endif
  
Index: sparc/db_interface.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/sparc/db_interface.c,v
retrieving revision 1.83
diff -p -r1.83 db_interface.c
*** sparc/db_interface.c        10 Mar 2009 23:58:20 -0000      1.83
--- sparc/db_interface.c        17 May 2009 22:21:21 -0000
*************** db_cpu_cmd(db_expr_t addr, bool have_add
*** 463,469 ****
                db_printf("%ld: CPU out of range\n", addr);
                return;
        }
!       ci = &cpus[addr].ci;
        if (ci == NULL) {
                db_printf("CPU %ld not configured\n", addr);
                return;
--- 463,469 ----
                db_printf("%ld: CPU out of range\n", addr);
                return;
        }
!       ci = cpus[addr];
        if (ci == NULL) {
                db_printf("CPU %ld not configured\n", addr);
                return;
Index: sparc/pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/sparc/pmap.c,v
retrieving revision 1.326
diff -p -r1.326 pmap.c
*** sparc/pmap.c        18 Mar 2009 16:00:14 -0000      1.326
--- sparc/pmap.c        17 May 2009 22:21:21 -0000
*************** pmap_bootstrap4m(void *top)
*** 3467,3473 ****
        vaddr_t va;
  #ifdef MULTIPROCESSOR
        vsize_t off;
!       struct vm_page *pg;
  #endif
  
        /*
--- 3467,3474 ----
        vaddr_t va;
  #ifdef MULTIPROCESSOR
        vsize_t off;
!       size_t cpuinfo_len;
!       struct cpu_info *cpuinfo_data;
  #endif
  
        /*
*************** pmap_bootstrap4m(void *top)
*** 3546,3551 ****
--- 3547,3566 ----
         */
        p = (p + NBPG - 1) & ~PGOFSET;
  
+ #if defined(MULTIPROCESSOR)
+       /*
+        * allocate the rest of the cpu_info{} area.  note we waste the
+        * first one to get a VA space.
+        */
+ //    p = (p + NBPG - 1) & ~PGOFSET;
+       cpuinfo_data = (struct cpu_info *)p;
+       cpuinfo_len = ((sizeof(struct cpu_info) + NBPG - 1) & ~PGOFSET);
+       /* XXX waste the first one? */
+       p += cpuinfo_len * (sparc_ncpus);
+       prom_printf("extra cpus: %p, p: %p, gap start: %p, gap end: %p\n",
+           cpus, p, etext_gap_start, etext_gap_end);
+ #endif
+ 
        /*
         * Reserve memory for MMU pagetables. Some of these have severe
         * alignment restrictions. We allocate in a sequence that
*************** pmap_bootstrap4m(void *top)
*** 3781,3842 ****
        mmu_install_tables(&cpuinfo);
  
  #ifdef MULTIPROCESSOR
!       /* Allocate VA for all the cpu_info structurs */
!       cpus = (union cpu_info_pg*)uvm_km_alloc(kernel_map,
!           sizeof cpus[sparc_ncpus], 32*1024, UVM_KMF_VAONLY);
!       /*
!        * Add an alias mapping for the CPUINFO_VA allocation created
!        * early during bootstrap for the first CPU
!        */
!       off = 0;
!       for (va = (vaddr_t)&cpus[0].ci;
!            off < sizeof(struct cpu_info);
!            va += NBPG, off += NBPG) {
!               paddr_t pa = PMAP_BOOTSTRAP_VA2PA(CPUINFO_VA + off);
!               pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
!       }
!       /*
!        * Now allocate memory for all other CPUs cpu_info and map
!        * it into the coresponding space in the cpus array. We will
!        * later duplicate the mapping into CPUINFO_VA.
!        */
!       for (i = 1; i < sparc_ncpus; i++) {
!               off = 0;
!               for (va = (vaddr_t)&cpus[i].ci;
!                    off < sizeof(struct cpu_info);
!                    va += NBPG, off += NBPG) {
!                       pg = uvm_pagealloc(NULL, 0, NULL, 0);
!                       paddr_t pa = VM_PAGE_TO_PHYS(pg);
!                       pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
!               }
!       }
! 
!       /* clear new cpu infos */
!       prom_printf("clearing other cpus cpu info\n");
!       memset(&cpus[1].ci, 0, (sparc_ncpus-1)*sizeof(union cpu_info_pg));
! 
!       /* setup self refernces, and cpu "cpuinfo" */
!       prom_printf("setting cpus self reference and mapping\n");
        for (i = 0; i < sparc_ncpus; i++) {
! 
!               prom_printf("going to set cpu%d ci_self address: %p\n", i, 
&cpus[i].ci);
!               cpus[i].ci.ci_self = &cpus[i].ci;
! 
!               /* mapped above. */
!               if (i == 0)
!                       continue;
! 
!               off = 0;
!               for (va = (vaddr_t)&cpus[i].ci;
!                    off < sizeof(struct cpu_info);
!                    va += NBPG, off += NBPG) {
!                       paddr_t pa = PMAP_BOOTSTRAP_VA2PA(va + off);
!                       prom_printf("going to pmap_kenter_pa(va=%p, pa=%p)\n", 
va, pa);
!                       pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
                }
        }
  #endif
        pmap_update(pmap_kernel());
  }
  
  static u_long prom_ctxreg;
--- 3796,3828 ----
        mmu_install_tables(&cpuinfo);
  
  #ifdef MULTIPROCESSOR
!       /*
!        * Now fill in the ci_self pointers in the space allocated for the
!        * other cpus.  We will later remap this at CPUINFO_VA in
!        * pmap_alloc_cpu().
!        */
!       prom_printf("setting cpus self reference\n");
        for (i = 0; i < sparc_ncpus; i++) {
!               cpus[i] = (struct cpu_info *)((uint8_t *)cpuinfo_data + 
(cpuinfo_len * i));
!               if (i == 0) {
!                       /* remap this cpuinfo */
!                       for (off = 0, va = (vaddr_t)cpus[i];
!                            off < sizeof(struct cpu_info);
!                            va += NBPG, off += NBPG) {
!                               paddr_t pa = PMAP_BOOTSTRAP_VA2PA(CPUINFO_VA + 
off);
!                               prom_printf("going to pmap_kenter_pa(va=%p, 
pa=%p)\n", va, pa);
!                               pmap_kenter_pa(va, pa, VM_PROT_READ | 
VM_PROT_WRITE);
!                       }
!               } else {
!                       /* clear new cpu info */
!                       memset(cpus[i], 0, cpuinfo_len);
                }
+               cpus[i]->ci_self = cpus[i];
+               prom_printf("set cpu%d ci_self address: %p\n", i, cpus[i]);
        }
  #endif
        pmap_update(pmap_kernel());
+       prom_printf("pmap_bootstrap4m done\n");
  }
  
  static u_long prom_ctxreg;
*************** pgt_lvl23_remove4m(struct pmap *pm, stru
*** 4448,4454 ****
  #ifdef MULTIPROCESSOR
                /* Invalidate level 1 PTP entries on all CPUs */
                for (; n < sparc_ncpus; n++) {
!                       if ((cpus[n].ci.flags & CPUFLG_HATCHED) == 0)
                                continue;
  #endif
                        setpgt4m(&pm->pm_reg_ptps[n][vr], SRMMU_TEINVALID);
--- 4434,4440 ----
  #ifdef MULTIPROCESSOR
                /* Invalidate level 1 PTP entries on all CPUs */
                for (; n < sparc_ncpus; n++) {
!                       if ((cpus[n]->flags & CPUFLG_HATCHED) == 0)
                                continue;
  #endif
                        setpgt4m(&pm->pm_reg_ptps[n][vr], SRMMU_TEINVALID);
*************** pmap_enu4m(struct pmap *pm, vaddr_t va, 
*** 6285,6291 ****
  #endif
                {
  #if defined(MULTIPROCESSOR)
!                       if ((cpus[i].ci.flags & CPUFLG_HATCHED) == 0)
                                continue;
  #endif
                        setpgt4m(&pm->pm_reg_ptps[i][vr],
--- 6271,6277 ----
  #endif
                {
  #if defined(MULTIPROCESSOR)
!                       if ((cpus[i]->flags & CPUFLG_HATCHED) == 0)
                                continue;
  #endif
                        setpgt4m(&pm->pm_reg_ptps[i][vr],


Home | Main Index | Thread Index | Old Index