OSDN Git Service

SMP implementation. Not working yet.
authorTakuya ASADA <syuu@dokukino.com>
Thu, 2 Sep 2010 04:40:22 +0000 (13:40 +0900)
committerTakuya ASADA <syuu@dokukino.com>
Thu, 2 Sep 2010 04:40:22 +0000 (13:40 +0900)
src/sys/arch/octeon/dev/mainbus.c
src/sys/arch/octeon/dev/obio.c
src/sys/arch/octeon/dev/obiovar.h
src/sys/arch/octeon/dev/octeonreg.h
src/sys/arch/octeon/octeon/locore.S
src/sys/arch/octeon/octeon/machdep.c

index 88f32cb..f56a0a3 100644 (file)
@@ -59,7 +59,10 @@ void
 mainbus_attach(struct device *parent, struct device *self, void *aux)
 {
        struct cpu_attach_args caa;
-
+#ifdef MULTIPROCESSOR
+       struct cpu_hwinfo hw;
+#endif
+       
        printf(": %s %s\n", sys_platform->vendor, sys_platform->product);
 
        bzero(&caa, sizeof caa);
@@ -67,6 +70,12 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
        caa.caa_hw = &bootcpu_hwinfo;
        config_found(self, &caa, mainbus_print);
 
+#ifdef MULTIPROCESSOR
+       bcopy(&bootcpu_hwinfo, &hw, sizeof(struct cpu_hwinfo));
+       caa.caa_hw = &hw;
+       config_found(self, &caa, mainbus_print);
+#endif
+       
        caa.caa_maa.maa_name = "clock";
        config_found(self, &caa.caa_maa, mainbus_print);
 
index cd8ee60..02a4f74 100644 (file)
@@ -150,10 +150,13 @@ struct obio_intrhand {
 };
 struct obio_intrhand *obio_intrhand[OBIO_NINTS];
 
-#define        INTPRI_CIU      (INTPRI_CLOCK + 1)
+#define        INTPRI_CIU_0    (INTPRI_CLOCK + 1)
+#define INTPRI_CIU_1   (INTPRI_CIU_0 + 1)
+#define INTPRI_CIU_2   (INTPRI_CIU_1 + 1)
+#define INTPRI_CIU_3   (INTPRI_CIU_2 + 1)
 
-uint64_t obio_intem, obio_intem;
-uint64_t obio_imask[NIPLS];
+uint64_t obio_intem[MAXCPUS];
+uint64_t obio_imask[MAXCPUS][NIPLS];
 
 /*
  * List of obio child devices.
@@ -236,7 +239,10 @@ obioattach(struct device *parent, struct device *self, void *aux)
        bus_space_write_8(&obio_tag, obio_h, CIU_INT0_EN4_1, 0);
        bus_space_write_8(&obio_tag, obio_h, CIU_INT1_EN4_1, 0);
 
-       set_intr(INTPRI_CIU, CR_INT_0, obio_iointr);
+       set_intr(INTPRI_CIU_0, CR_INT_0, obio_iointr);
+       set_intr(INTPRI_CIU_1, CR_INT_1, obio_iointr);
+       set_intr(INTPRI_CIU_2, CR_INT_2, obio_iointr);
+       set_intr(INTPRI_CIU_3, CR_INT_3, obio_iointr);
        register_splx_handler(obio_splx);
 
        /*
@@ -404,6 +410,7 @@ void *
 obio_intr_establish(int irq, int level,
     int (*ih_fun)(void *), void *ih_arg, const char *ih_what)
 {
+       int cpuid = cpu_number();
        struct obio_intrhand **p, *q, *ih;
        int s;
 
@@ -436,7 +443,7 @@ obio_intr_establish(int irq, int level,
                ;
        *p = ih;
 
-       obio_intem |= 1UL << irq;
+       obio_intem[cpuid] |= 1UL << irq;
        obio_intr_makemasks();
 
        splx(s);        /* causes hw mask update */
@@ -473,19 +480,23 @@ obio_splx(int newipl)
 void
 obio_intr_makemasks()
 {
+       int cpuid = cpu_number();
        int irq, level;
        struct intrhand *q;
        uint intrlevel[OBIO_NINTS];
 
+       printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
        /* First, figure out which levels each IRQ uses. */
        for (irq = 0; irq < OBIO_NINTS; irq++) {
                uint levels = 0;
+               printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
                for (q = (struct intrhand *)obio_intrhand[irq]; q != NULL; 
                        q = q->ih_next)
                        levels |= 1 << q->ih_level;
+               printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
                intrlevel[irq] = levels;
        }
-
+       printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
        /*
         * Then figure out which IRQs use each level.
         * Note that we make sure never to overwrite imask[IPL_HIGH], in
@@ -494,12 +505,15 @@ obio_intr_makemasks()
         */
        for (level = IPL_NONE; level < NIPLS; level++) {
                uint64_t irqs = 0;
+               printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
                for (irq = 0; irq < OBIO_NINTS; irq++)
                        if (intrlevel[irq] & (1 << level))
                                irqs |= 1UL << irq;
-               obio_imask[level] = irqs;
+               printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
+               obio_imask[cpuid][level] = irqs;
+               printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
        }
-
+       printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
        /*
         * There are tty, network and disk drivers that use free() at interrupt
         * time, so vm > (tty | net | bio).
@@ -507,17 +521,18 @@ obio_intr_makemasks()
         * Enforce a hierarchy that gives slow devices a better chance at not
         * dropping data.
         */
-       obio_imask[IPL_NET] |= obio_imask[IPL_BIO];
-       obio_imask[IPL_TTY] |= obio_imask[IPL_NET];
-       obio_imask[IPL_VM] |= obio_imask[IPL_TTY];
-       obio_imask[IPL_CLOCK] |= obio_imask[IPL_VM];
-       obio_imask[IPL_HIGH] |= obio_imask[IPL_CLOCK];
-       obio_imask[IPL_IPI] |= obio_imask[IPL_HIGH];
-
+       obio_imask[cpuid][IPL_NET] |= obio_imask[cpuid][IPL_BIO];
+       obio_imask[cpuid][IPL_TTY] |= obio_imask[cpuid][IPL_NET];
+       obio_imask[cpuid][IPL_VM] |= obio_imask[cpuid][IPL_TTY];
+       obio_imask[cpuid][IPL_CLOCK] |= obio_imask[cpuid][IPL_VM];
+       obio_imask[cpuid][IPL_HIGH] |= obio_imask[cpuid][IPL_CLOCK];
+       obio_imask[cpuid][IPL_IPI] |= obio_imask[cpuid][IPL_HIGH];
+       printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
        /*
         * These are pseudo-levels.
         */
-       obio_imask[IPL_NONE] = 0;
+       obio_imask[cpuid][IPL_NONE] = 0;
+       printf("%d %s:%s:%d\n", cpu_number(), __FILE__, __func__, __LINE__);
 }
 
 /*
@@ -527,14 +542,17 @@ uint32_t
 obio_iointr(uint32_t hwpend, struct trap_frame *frame)
 {
        struct cpu_info *ci = curcpu();
+       int cpuid = cpu_number();
        uint64_t imr, isr, mask;
        int ipl;
        int bit;
        struct intrhand *ih;
        int rc;
+       uint64_t sum0 = CIU_INT_SUM0(cpuid * 2);
+       uint64_t en0 = CIU_INT_EN0(cpuid * 2);
 
-       isr = bus_space_read_8(&obio_tag, obio_h, CIU_INT0_SUM0);
-       imr = bus_space_read_8(&obio_tag, obio_h, CIU_INT0_EN0);
+       isr = bus_space_read_8(&obio_tag, obio_h, sum0);
+       imr = bus_space_read_8(&obio_tag, obio_h, en0);
        bit = 63;
 
        isr &= imr;
@@ -544,13 +562,13 @@ obio_iointr(uint32_t hwpend, struct trap_frame *frame)
        /*
         * Mask all pending interrupts.
         */
-       bus_space_write_8(&obio_tag, obio_h, CIU_INT0_EN0, imr & ~isr);
+       bus_space_write_8(&obio_tag, obio_h, en0, imr & ~isr);
 
        /*
         * If interrupts are spl-masked, mask them and wait for splx()
         * to reenable them when necessary.
         */
-       if ((mask = isr & obio_imask[frame->ipl]) != 0) {
+       if ((mask = isr & obio_imask[cpuid][frame->ipl]) != 0) {
                isr &= ~mask;
                imr &= ~mask;
        }
@@ -568,7 +586,7 @@ obio_iointr(uint32_t hwpend, struct trap_frame *frame)
 
                /* Service higher level interrupts first */
                for (lvl = NIPLS - 1; lvl != IPL_NONE; lvl--) {
-                       tmpisr = isr & (obio_imask[lvl] ^ obio_imask[lvl - 1]);
+                       tmpisr = isr & (obio_imask[cpuid][lvl] ^ obio_imask[cpuid][lvl - 1]);
                        if (tmpisr == 0)
                                continue;
                        for (bitno = bit, mask = 1UL << bitno; mask != 0;
@@ -619,7 +637,7 @@ obio_iointr(uint32_t hwpend, struct trap_frame *frame)
                /*
                 * Reenable interrupts which have been serviced.
                 */
-               bus_space_write_8(&obio_tag, obio_h, CIU_INT0_EN0, imr);
+               bus_space_write_8(&obio_tag, obio_h, en0, imr);
        }
 
        return hwpend;
@@ -628,6 +646,9 @@ obio_iointr(uint32_t hwpend, struct trap_frame *frame)
 void
 obio_setintrmask(int level)
 {
+       int cpuid = cpu_number();
+       uint64_t en0 = CIU_INT_EN0(cpuid * 2);
+
        *(volatile uint64_t *)(PHYS_TO_XKPHYS(OCTEON_CIU_BASE, CCA_NC) +
-           CIU_INT0_EN0) = obio_intem & ~obio_imask[level];
+           en0) = obio_intem[cpuid] & ~obio_imask[cpuid][level];
 }
index a0afdec..1ff8fdb 100644 (file)
@@ -44,6 +44,7 @@ struct obio_attach_args {
        int              oba_intr;
 };
 
+void    obio_setintrmask(int);
 void   *obio_intr_establish(int, int, int (*)(void *),
            void *, const char *);
 void   obio_intr_disestablish(void *);
index 1b730ba..69839cc 100644 (file)
@@ -65,6 +65,7 @@
 #define CIU_INT_GPIO15         31
 #define CIU_INT_MBOX0          32
 #define CIU_INT_MBOX1          33
+#define CIU_INT_MBOX(x)                (CIU_INT_MBOX0+(x))
 #define CIU_INT_UART0          34
 #define CIU_INT_UART1          35
 #define CIU_INT_PCI_INTA       36
 #define CIU_INT1_SUM0          0x00000008
 #define CIU_INT2_SUM0          0x00000010
 #define CIU_INT3_SUM0          0x00000018
+#define CIU_INT_SUM0(x)                (CIU_INT0_SUM0+((x)*8))
 #define CIU_INT32_SUM0         0x00000100
 #define CIU_INT32_SUM1         0x00000108
 #define CIU_INT0_EN0           0x00000200
 #define CIU_INT1_EN0           0x00000210
 #define CIU_INT2_EN0           0x00000220
 #define CIU_INT3_EN0           0x00000230
+#define CIU_INT_EN0(x)         (CIU_INT0_EN0+((x)*8))
 #define CIU_INT32_EN0          0x00000400
 #define CIU_INT0_EN1           0x00000208
 #define CIU_INT1_EN1           0x00000218
 #define CIU_PP_POKE1            0x00000588
 #define CIU_MBOX_SET0           0x00000600
 #define CIU_MBOX_SET1           0x00000608
+#define CIU_MBOX_SET(x)                (CIU_MBOX_SET0+((x)*8))
 #define CIU_MBOX_CLR0           0x00000680
 #define CIU_MBOX_CLR1           0x00000688
+#define CIU_MBOX_CLR(x)                (CIU_MBOX_CLR0+((x)*8))
 #define CIU_PP_RST              0x00000700
 #define CIU_PP_DBG              0x00000708
 #define CIU_GSTOP               0x00000710
index 7d09a97..53af4a1 100644 (file)
@@ -51,13 +51,22 @@ start:
        dmtc0   t0, COP_0_CVMCTL
 
 /* initialize cvmmemctl */
-       dli     t0, 0x46104
+       dli     t0, 0x1846104
        dmtc0   t0, COP_0_CVMMEMCTL
 
 /* initialize pagegrain */
        dli     t0, 0x20000000
        dmtc0   t0, COP_0_TLB_PG_GRAIN
 
+#if defined(MULTIPROCESSOR)
+       rdhwr   t2, $0
+       beqz    t2, 1f
+       nop
+       j       octeon_ap_wait
+       nop
+1:
+#endif
+
        mfc0    v0, COP_0_STATUS_REG
        li      v1, ~(SR_INT_ENAB | SR_ERL | SR_EXL)
        and     v0, v1
@@ -116,6 +125,8 @@ LEAF(hw_cpu_spinup_trampoline, 0)
        mtc0    v0, COP_0_STATUS_REG            # disable all interrupts
        mtc0    zero, COP_0_CAUSE_REG           # Clear soft interrupts
        LA      gp, _gp
+       LA      a0, cpu_info_boot_secondary
+       ld      a0, 0(a0)
        jal     hw_cpu_hatch
        nop
 END(hw_cpu_spinup_trampoline)
@@ -131,4 +142,34 @@ LEAF(hw_setcurcpu, 0)
        j       ra
        nop
 END(hw_setcurcpu)
+
+/*
+ * This function must be implemented in assembly because it is called early
+ * in AP boot without a valid stack.
+ */
+LEAF(platform_processor_id, 0)
+       jr      ra
+       rdhwr   v0, $0
+END(platform_processor_id)
+
+/*
+ * Called on APs to wait until they are told to launch.
+ */
+LEAF(octeon_ap_wait, 0)
+       jal     platform_processor_id
+       nop
+
+1:     ll      t0, octeon_ap_boot
+       bne     v0, t0, 1b
+       nop
+
+       move    t0, zero
+       sc      t0, octeon_ap_boot
+
+       beqz    t0, 1b
+       nop
+
+       j       hw_cpu_spinup_trampoline
+       nop
+END(octeon_ap_wait)
 #endif /* MULTIPROCESSOR */
index cc013bf..5a68510 100644 (file)
@@ -79,6 +79,9 @@
 
 #include <machine/octeon_pcmap_regs.h>
 
+#include <octeon/dev/obiovar.h>
+#include <octeon/dev/octeonreg.h>
+
 #define btoc(x) (((vm_offset_t)(x)+PAGE_MASK)>>PAGE_SHIFT)
 #define MIPS_PHYS_MASK                  (0x1fffffff)
 #define   MIPS_KSEG0_TO_PHYS(x)           ((__uintptr_t)(x) & MIPS_PHYS_MASK)
@@ -691,11 +694,13 @@ octeon_memory_init(void)
        if ((octeon_board_real()) &&
            (realmem_bytes > OCTEON_DRAM_FIRST_256_END)) {
                /* take out the upper non-cached 1/2 */
+#if 0
                realmem_bytes -= OCTEON_DRAM_FIRST_256_END;
                realmem_bytes &= ~(PAGE_SIZE - 1);
+#endif
                /* Now map the rest of the memory */
-               phys_avail[2] = 0x20000000;
-               phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes);
+               phys_avail[2] = 0x10000000;
+               phys_avail[3] = ((uint32_t) 0x10000000 + realmem_bytes);
                physmem += btoc(phys_avail[3] - phys_avail[2]);
                mem_layout[1].mem_first_page = atop(phys_avail[2]);
                mem_layout[1].mem_last_page = atop(phys_avail[3]-1);
@@ -757,11 +762,9 @@ memrange_register(uint64_t startpfn, uint64_t endpfn, uint64_t bmask,
        if (m == NULL)
                return ENOMEM;
        
-       printf("mem_layout:%p m:%p\n", mem_layout, m);
        m->mem_first_page = startpfn;
        m->mem_last_page = endpfn;
        m->mem_freelist = freelist;
-       printf("first_page:%x last_page:%x freelist:%p\n", startpfn, endpfn, freelist);
        return 0;
 }
 
@@ -896,7 +899,7 @@ mips_init(__register_t a0, __register_t a1, __register_t a2 __unused,
        bootcpu_hwinfo.type = (prid >> 8) & 0xff;
        /* FPU reports itself as type 5, version 0.1... */
        bootcpu_hwinfo.c1prid = bootcpu_hwinfo.c0prid;
-       bootcpu_hwinfo.tlbsize = 32;
+       bootcpu_hwinfo.tlbsize = 64;
        bcopy(&bootcpu_hwinfo, &curcpu()->ci_hw, sizeof(struct cpu_hwinfo));
 
        /*
@@ -1694,6 +1697,9 @@ is_memory_range(paddr_t pa, psize_t len, psize_t limit)
 }
 
 #ifdef MULTIPROCESSOR
+unsigned octeon_ap_boot = ~0;
+struct cpu_info *cpu_info_boot_secondary = NULL;
+
 void
 hw_cpu_boot_secondary(struct cpu_info *ci)
 {
@@ -1704,6 +1710,12 @@ hw_cpu_boot_secondary(struct cpu_info *ci)
                panic("unable to allocate idle stack\n");
        ci->ci_curprocpaddr = (void *)kstack;
 
+       cpu_info_boot_secondary = ci;
+
+       printf("spinup ci:%p cpuid:%d\n", ci, ci->ci_cpuid);
+       
+       octeon_ap_boot = ci->ci_cpuid;
+
        while (!cpuset_isset(&cpus_running, ci))
                ;
 }
@@ -1712,7 +1724,7 @@ void
 hw_cpu_hatch(struct cpu_info *ci)
 {
        int s;
-
+       
        /*
         * Set curcpu address on this processor.
         */
@@ -1745,11 +1757,13 @@ hw_cpu_hatch(struct cpu_info *ci)
 
        cpu_startclock(ci);
 
+       printf("ci:%p cpu_number:%d\n", ci, cpu_number());
+       
        ncpus++;
        cpuset_add(&cpus_running, ci);
 
        mips64_ipi_init();
-//     xheart_setintrmask(0);
+       obio_setintrmask(0);
 
        spl0();
        (void)updateimask(0);
@@ -1761,17 +1775,24 @@ hw_cpu_hatch(struct cpu_info *ci)
 int
 hw_ipi_intr_establish(int (*func)(void *), u_long cpuid)
 {
+       printf("hw_ipi_intr_establish(%d)\n", cpuid);
+       obio_intr_establish(CIU_INT_MBOX(cpuid), IPL_IPI, func,
+               (void *)cpuid, NULL);
        return 0;
 };
 
 void
 hw_ipi_intr_set(u_long cpuid)
 {
+       printf("hw_ipi_intr_set(%d)\n", cpuid);
+       *(uint64_t *)OCTEON_CIU_MBOX_SETX(cpuid) = 1;
 }
 
 void
 hw_ipi_intr_clear(u_long cpuid)
 {
+       printf("hw_ipi_intr_clear(%d)\n", cpuid);
+       *(uint64_t *)OCTEON_CIU_MBOX_CLRX(cpuid) = 1;
 }
 
 #endif