Author: br
Date: Wed Feb 24 16:50:34 2016
New Revision: 295972
URL: https://svnweb.freebsd.org/changeset/base/295972

Log:
  Add support for symmetric multiprocessing (SMP).
  
  Tested on Spike simulator with 2 and 16 cores (tlb enabled),
  so set MAXCPU to 16 at this time.
  
  This uses FDT data to get information about CPUs
  (code based on arm64 mp_machdep).
  
  Invalidate entire TLB cache as it is the only way yet.
  
  Sponsored by: DARPA, AFRL
  Sponsored by: HEIF5

Added:
  head/sys/riscv/riscv/mp_machdep.c   (contents, props changed)
Modified:
  head/sys/boot/fdt/dts/riscv/spike.dts
  head/sys/conf/files.riscv
  head/sys/riscv/conf/GENERIC
  head/sys/riscv/htif/htif.c
  head/sys/riscv/htif/htif_block.c
  head/sys/riscv/htif/htif_console.c
  head/sys/riscv/include/intr.h
  head/sys/riscv/include/param.h
  head/sys/riscv/include/pcpu.h
  head/sys/riscv/include/riscvreg.h
  head/sys/riscv/include/smp.h
  head/sys/riscv/riscv/cpufunc_asm.S
  head/sys/riscv/riscv/exception.S
  head/sys/riscv/riscv/genassym.c
  head/sys/riscv/riscv/intr_machdep.c
  head/sys/riscv/riscv/locore.S
  head/sys/riscv/riscv/machdep.c
  head/sys/riscv/riscv/pmap.c
  head/sys/riscv/riscv/swtch.S

Modified: head/sys/boot/fdt/dts/riscv/spike.dts
==============================================================================
--- head/sys/boot/fdt/dts/riscv/spike.dts       Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/boot/fdt/dts/riscv/spike.dts       Wed Feb 24 16:50:34 2016        
(r295972)
@@ -43,6 +43,23 @@
        #size-cells = <1>;
        #interrupt-cells = <1>;
 
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "riscv,rv64i";
+                       reg = <0x40002000>;
+               };
+
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "riscv,rv64i";
+                       reg = <0x4000a000>;
+               };
+       };
+
        aliases {
                console0 = &console0;
        };

Modified: head/sys/conf/files.riscv
==============================================================================
--- head/sys/conf/files.riscv   Wed Feb 24 15:15:46 2016        (r295971)
+++ head/sys/conf/files.riscv   Wed Feb 24 16:50:34 2016        (r295972)
@@ -1,6 +1,7 @@
 # $FreeBSD$
 crypto/blowfish/bf_enc.c       optional        crypto | ipsec
 crypto/des/des_enc.c           optional        crypto | ipsec | netsmb
+dev/ofw/ofw_cpu.c              optional        fdt
 kern/kern_clocksource.c                standard
 kern/subr_dummy_vdso_tc.c      standard
 libkern/bcmp.c                 standard
@@ -29,8 +30,9 @@ riscv/riscv/intr_machdep.c    standard
 riscv/riscv/in_cksum.c         optional        inet | inet6
 riscv/riscv/identcpu.c         standard
 riscv/riscv/locore.S           standard        no-obj
-riscv/riscv/minidump_machdep.c standard
 riscv/riscv/machdep.c          standard
+riscv/riscv/minidump_machdep.c standard
+riscv/riscv/mp_machdep.c       optional        smp
 riscv/riscv/mem.c              standard
 riscv/riscv/nexus.c            standard
 riscv/riscv/pmap.c             standard

Modified: head/sys/riscv/conf/GENERIC
==============================================================================
--- head/sys/riscv/conf/GENERIC Wed Feb 24 15:15:46 2016        (r295971)
+++ head/sys/riscv/conf/GENERIC Wed Feb 24 16:50:34 2016        (r295972)
@@ -70,7 +70,13 @@ options      MAC                     # TrustedBSD MAC 
Framewor
 options        RACCT                   # Resource accounting framework
 options        RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
 options        RCTL                    # Resource limits
-# options      SMP
+options        SMP
+
+# Uncomment for memory disk
+# options      MD_ROOT
+# options      MD_ROOT_SIZE=8192       # 8MB ram disk
+# makeoptions  MFS_IMAGE=/path/to/img
+# options      ROOTDEVNAME=\"ufs:/dev/md0\"
 
 # Debugging support.  Always need this:
 # options      KDB                     # Enable kernel debugger support.

Modified: head/sys/riscv/htif/htif.c
==============================================================================
--- head/sys/riscv/htif/htif.c  Wed Feb 24 15:15:46 2016        (r295971)
+++ head/sys/riscv/htif/htif.c  Wed Feb 24 16:50:34 2016        (r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -62,7 +62,7 @@ __FBSDID("$FreeBSD$");
 #include "htif.h"
 
 static struct resource_spec htif_spec[] = {
-       { SYS_RES_IRQ,          0,      RF_ACTIVE },
+       { SYS_RES_IRQ,          0,      RF_ACTIVE | RF_SHAREABLE},
        { -1, 0 }
 };
 
@@ -126,9 +126,9 @@ htif_intr(void *arg)
 
        sc = arg;
 
-       htif_handle_entry(sc);
+       csr_clear(sip, SIP_SSIP);
 
-       csr_clear(sip, SIE_SSIE);
+       htif_handle_entry(sc);
 
        return (FILTER_HANDLED);
 }

Modified: head/sys/riscv/htif/htif_block.c
==============================================================================
--- head/sys/riscv/htif/htif_block.c    Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/htif/htif_block.c    Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -117,6 +117,9 @@ htif_blk_intr(void *arg, uint64_t entry)
        if (sc->curtag == data) {
                sc->cmd_done = 1;
                wakeup(&sc->intr_chan);
+       } else {
+               device_printf(sc->dev, "Unexpected tag %d (should be %d)\n",
+                   data, sc->curtag);
        }
 }
 
@@ -212,6 +215,8 @@ htif_blk_task(void *arg)
                HTIF_BLK_UNLOCK(sc);
 
                if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
+                       HTIF_BLK_LOCK(sc);
+
                        req.offset = (bp->bio_pblkno * sc->disk->d_sectorsize);
                        req.size = bp->bio_bcount;
                        paddr = vtophys(bp->bio_data);
@@ -233,7 +238,6 @@ htif_blk_task(void *arg)
                        htif_command(cmd);
 
                        /* Wait for interrupt */
-                       HTIF_BLK_LOCK(sc);
                        i = 0;
                        while (sc->cmd_done == 0) {
                                msleep(&sc->intr_chan, &sc->sc_mtx, PRIBIO, 
"intr", hz/2);

Modified: head/sys/riscv/htif/htif_console.c
==============================================================================
--- head/sys/riscv/htif/htif_console.c  Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/htif/htif_console.c  Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -89,6 +89,7 @@ CONSOLE_DRIVER(riscv);
 #define        MAX_BURST_LEN           1
 #define        QUEUE_SIZE              256
 #define        CONSOLE_DEFAULT_ID      1ul
+#define        SPIN_IN_MACHINE_MODE    1
 
 struct queue_entry {
        uint64_t data;
@@ -109,7 +110,12 @@ htif_putc(int c)
        cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
        cmd |= c;
 
+#ifdef SPIN_IN_MACHINE_MODE
+       machine_command(ECALL_HTIF_LOWPUTC, cmd);
+#else
        htif_command(cmd);
+#endif
+
 }
 
 static uint8_t
@@ -141,6 +147,7 @@ riscv_putc(int c)
 
        htif_putc(c);
 
+#ifndef SPIN_IN_MACHINE_MODE
        /* Wait for an interrupt */
        __asm __volatile(
                "li     %0, 1\n"        /* counter = 1 */
@@ -153,6 +160,7 @@ riscv_putc(int c)
        "2:"
                : "=&r"(counter), "=&r"(val) : "r"(cc)
        );
+#endif
 }
 
 #ifdef EARLY_PRINTF

Modified: head/sys/riscv/include/intr.h
==============================================================================
--- head/sys/riscv/include/intr.h       Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/include/intr.h       Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -51,4 +51,16 @@ typedef unsigned long * riscv_intrcnt_t;
 riscv_intrcnt_t riscv_intrcnt_create(const char *);
 void riscv_intrcnt_setname(riscv_intrcnt_t, const char *);
 
+#ifdef SMP
+void riscv_setup_ipihandler(driver_filter_t *);
+void riscv_unmask_ipi(void);
+#endif
+
+enum {
+       IRQ_SOFTWARE,
+       IRQ_TIMER,
+       IRQ_HTIF,
+       NIRQS
+};
+
 #endif /* !_MACHINE_INTR_MACHDEP_H_ */

Modified: head/sys/riscv/include/param.h
==============================================================================
--- head/sys/riscv/include/param.h      Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/include/param.h      Wed Feb 24 16:50:34 2016        
(r295972)
@@ -51,7 +51,7 @@
 
 #if defined(SMP) || defined(KLD_MODULE)
 #ifndef MAXCPU
-#define        MAXCPU          2
+#define        MAXCPU          16
 #endif
 #else
 #define        MAXCPU          1

Modified: head/sys/riscv/include/pcpu.h
==============================================================================
--- head/sys/riscv/include/pcpu.h       Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/include/pcpu.h       Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,7 +1,16 @@
 /*-
  * Copyright (c) 1999 Luoqi Chen <lu...@freebsd.org>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -36,7 +45,10 @@
 #define        ALT_STACK_SIZE  128
 
 #define        PCPU_MD_FIELDS                                                  
\
-       char __pad[129]
+       uint32_t pc_pending_ipis;       /* IPIs pending to this CPU */  \
+       uint64_t pc_sptbr;              /* L0 page table base (VA) */   \
+       uint64_t pc_reg;                /* CPU MMIO base (PA) */        \
+       char __pad[109]
 
 #ifdef _KERNEL
 

Modified: head/sys/riscv/include/riscvreg.h
==============================================================================
--- head/sys/riscv/include/riscvreg.h   Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/include/riscvreg.h   Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -38,12 +38,16 @@
 #define        _MACHINE_RISCVREG_H_
 
 /* Machine mode requests */
-#define        ECALL_MTIMECMP          0x1
-#define        ECALL_CLEAR_PENDING     0x2
-#define        ECALL_HTIF_CMD          0x3
-#define        ECALL_HTIF_GET_ENTRY    0x4
-#define        ECALL_MCPUID_GET        0x5
-#define        ECALL_MIMPID_GET        0x6
+#define        ECALL_MTIMECMP          0x01
+#define        ECALL_CLEAR_PENDING     0x02
+#define        ECALL_HTIF_CMD          0x03
+#define        ECALL_HTIF_GET_ENTRY    0x04
+#define        ECALL_MCPUID_GET        0x05
+#define        ECALL_MIMPID_GET        0x06
+#define        ECALL_SEND_IPI          0x07
+#define        ECALL_CLEAR_IPI         0x08
+#define        ECALL_HTIF_LOWPUTC      0x09
+#define        ECALL_MIE_SET           0x10
 
 #define        EXCP_SHIFT                      0
 #define        EXCP_MASK                       (0xf << EXCP_SHIFT)
@@ -109,9 +113,14 @@
 #define        SIE_SSIE        (1 << 1)
 #define        SIE_STIE        (1 << 5)
 
-/* Note: sip register is not yet implement in Spike simulator */
+/* Note: sip register has no SIP_STIP bit in Spike simulator */
+#define        SIP_SSIP        (1 << 1)
 #define        SIP_STIP        (1 << 5)
 
+#define        NCSRS   4096
+#define        CSR_IPI 0x783
+#define        XLEN    8
+
 #define        CSR_ZIMM(val)                                                   
\
        (__builtin_constant_p(val) && ((u_long)(val) < 32))
 

Modified: head/sys/riscv/include/smp.h
==============================================================================
--- head/sys/riscv/include/smp.h        Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/include/smp.h        Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1 +1,55 @@
-/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2016 Ruslan Bukin <b...@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef        _MACHINE_SMP_H_
+#define        _MACHINE_SMP_H_
+
+#include <machine/pcb.h>
+
+#define        IPI_AST         (1 << 0)
+#define        IPI_PREEMPT     (1 << 1)
+#define        IPI_RENDEZVOUS  (1 << 2)
+#define        IPI_STOP        (1 << 3)
+#define        IPI_STOP_HARD   (1 << 4)
+#define        IPI_HARDCLOCK   (1 << 5)
+
+void ipi_all_but_self(u_int ipi);
+void ipi_cpu(int cpu, u_int ipi);
+void ipi_selected(cpuset_t cpus, u_int ipi);
+
+extern struct pcb stoppcbs[];
+
+#endif /* !_MACHINE_SMP_H_ */

Modified: head/sys/riscv/riscv/cpufunc_asm.S
==============================================================================
--- head/sys/riscv/riscv/cpufunc_asm.S  Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/riscv/cpufunc_asm.S  Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -64,7 +64,7 @@ END(riscv_tlb_flushID_SE)
  * void riscv_dcache_wb_range(vm_offset_t, vm_size_t)
  */
 ENTRY(riscv_dcache_wb_range)
-       /* RISCVTODO */
+       sfence.vm
        ret
 END(riscv_dcache_wb_range)
 
@@ -72,7 +72,7 @@ END(riscv_dcache_wb_range)
  * void riscv_dcache_wbinv_range(vm_offset_t, vm_size_t)
  */
 ENTRY(riscv_dcache_wbinv_range)
-       /* RISCVTODO */
+       sfence.vm
        ret
 END(riscv_dcache_wbinv_range)
 
@@ -80,7 +80,7 @@ END(riscv_dcache_wbinv_range)
  * void riscv_dcache_inv_range(vm_offset_t, vm_size_t)
  */
 ENTRY(riscv_dcache_inv_range)
-       /* RISCVTODO */
+       sfence.vm
        ret
 END(riscv_dcache_inv_range)
 
@@ -88,7 +88,8 @@ END(riscv_dcache_inv_range)
  * void riscv_idcache_wbinv_range(vm_offset_t, vm_size_t)
  */
 ENTRY(riscv_idcache_wbinv_range)
-       /* RISCVTODO */
+       fence.i
+       sfence.vm
        ret
 END(riscv_idcache_wbinv_range)
 
@@ -96,6 +97,6 @@ END(riscv_idcache_wbinv_range)
  * void riscv_icache_sync_range(vm_offset_t, vm_size_t)
  */
 ENTRY(riscv_icache_sync_range)
-       /* RISCVTODO */
+       fence.i
        ret
 END(riscv_icache_sync_range)

Modified: head/sys/riscv/riscv/exception.S
==============================================================================
--- head/sys/riscv/riscv/exception.S    Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/riscv/exception.S    Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -229,6 +229,7 @@ bad_trap:
        j bad_trap
 
 user_trap:
+       /* Save state */
        csrrw   sp, mscratch, sp
        addi    sp, sp, -64
        sd      t0, (8 * 0)(sp)
@@ -282,7 +283,31 @@ machine_interrupt:
        j       1b
 
 software_interrupt:
-       /* Redirect to supervisor */
+       li      t0, MIP_MSIP
+       csrc    mip, t0
+       li      t0, MIP_SSIP
+       csrs    mip, t0
+
+       /* If PRV1 is PRV_U (user) then serve the trap */
+       csrr    t0, mstatus
+       li      t1, (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT)
+       and     t0, t0, t1
+       beqz    t0, 1f
+
+       /*
+        * If PRV1 is supervisor and interrupts were enabled,
+        * then serve the trap.
+        */
+       csrr    t0, mstatus
+       li      t1, (SR_IE1 | (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT))
+       and     t0, t0, t1
+       li      t1, (SR_IE1 | (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT))
+       beq     t0, t1, 1f
+
+       j       exit
+
+1:
+       /* Serve a trap in supervisor mode */
        j       exit_mrts
 
 timer_interrupt:
@@ -294,17 +319,20 @@ timer_interrupt:
        li      t0, MIP_MTIP
        csrc    mip, t0
 
-       /* Post supervisor software interrupt */
+       /* Post supervisor timer interrupt */
        li      t0, MIP_STIP
        csrs    mip, t0
 
-       /* If PRV1 is PRV_U (user) then serve a trap */
+       /* If PRV1 is PRV_U (user) then serve the trap */
        csrr    t0, mstatus
        li      t1, (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT)
        and     t0, t0, t1
        beqz    t0, 1f
 
-       /* If PRV1 is supervisor and interrupts were enabled, then serve a trap 
*/
+       /*
+        * If PRV1 is supervisor and interrupts were enabled,
+        * then serve the trap.
+        */
        csrr    t0, mstatus
        li      t1, (SR_IE1 | (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT))
        and     t0, t0, t1
@@ -332,25 +360,35 @@ htif_interrupt:
        la      t0, console_intr
        li      t1, 1
        sd      t1, 0(t0)
-       j       3f
+
+       /* Check if there is any other pending event */
+       j       1b
 
 2:
        /* Save entry */
-       la      t0, htif_ring_cursor
-       beqz    t0, 3f          /* not initialized */
-       ld      t0, 0(t0)       /* load struct */
-       sd      t5, 0(t0)       /* put entry */
+       la      t0, htif_ring
+       csrr    t1, mhartid
+       li      t4, (HTIF_RING_SIZE + 16)
+       mulw    t4, t4, t1
+       add     t0, t0, t4
+       li      t4, (HTIF_RING_SIZE)
+       add     t0, t0, t4      /* t0 == htif_ring_cursor */
+
+       ld      t1, 0(t0)       /* load ptr to cursor */
+       sd      t5, 0(t1)       /* put entry */
        li      t4, 1
-       sd      t4, 8(t0)       /* mark used */
-       ld      t4, 16(t0)      /* take next */
+       sd      t4, 8(t1)       /* mark used */
+       ld      t4, 16(t1)      /* take next */
        /* Update cursor */
-       la      t0, htif_ring_cursor
        sd      t4, 0(t0)
 
        /* Post supervisor software interrupt */
        li      t0, MIP_SSIP
        csrs    mip, t0
 
+       /* Check if there is any other pending event */
+       j       1b
+
 3:
        j       exit
 
@@ -369,6 +407,18 @@ supervisor_call:
        beq     t5, t4, mcpuid_get
        li      t4, ECALL_MIMPID_GET
        beq     t5, t4, mimpid_get
+       li      t4, ECALL_SEND_IPI
+       beq     t5, t4, send_ipi
+       li      t4, ECALL_CLEAR_IPI
+       beq     t5, t4, clear_ipi
+       li      t4, ECALL_HTIF_LOWPUTC
+       beq     t5, t4, htif_lowputc
+       li      t4, ECALL_MIE_SET
+       beq     t5, t4, mie_set
+       j       exit_next_instr
+
+mie_set:
+       csrs    mie, t6
        j       exit_next_instr
 
 mcpuid_get:
@@ -379,28 +429,111 @@ mimpid_get:
        csrr    t6, mimpid
        j       exit_next_instr
 
+send_ipi:
+       /* CPU mmio base in t6 */
+       mv      t0, t6
+       li      t2, (CSR_IPI * XLEN)
+       add     t0, t0, t2      /* t0 = CSR_IPI */
+       li      t2, 1
+       sd      t2, 0(t0)
+       j       exit_next_instr
+
+clear_ipi:
+       /* Do only clear if there are no new entries in HTIF ring */
+       la      t0, htif_ring
+       csrr    t2, mhartid
+       li      t4, (HTIF_RING_SIZE + 16)
+       mulw    t4, t4, t2
+       add     t0, t0, t4
+       li      t4, (HTIF_RING_SIZE)
+       add     t0, t0, t4      /* t0  == ptr to htif_ring_cursor */
+       ld      t2, 8(t0)       /* load htif_ring_last */
+       ld      t2, 8(t2)       /* load used */
+       bnez    t2, 1f
+
+       /* Clear supervisor software interrupt pending bit */
+       li      t0, MIP_SSIP
+       csrc    mip, t0
+
+1:
+       j       exit_next_instr
+
 htif_get_entry:
+       /* Get a htif_ring for current core */
+       la      t0, htif_ring
+       csrr    t2, mhartid
+       li      t4, (HTIF_RING_SIZE + 16)
+       mulw    t4, t4, t2
+       add     t0, t0, t4
+       li      t4, (HTIF_RING_SIZE + 8)
+       add     t0, t0, t4      /* t0 == htif_ring_last */
+
+       /* Check for new entries */
        li      t6, 0           /* preset return value */
-       la      t0, htif_ring_last
-       ld      t0, 0(t0)       /* load struct */
-       ld      t4, 8(t0)       /* get used */
-       beqz    t4, 1f
-       ld      t6, 0(t0)       /* get entry */
+       ld      t2, 0(t0)       /* load ptr to last */
+       ld      t4, 8(t2)       /* get used */
+       beqz    t4, 1f          /* No new entries. Exit */
+
+       /* Get one */
+       ld      t6, 0(t2)       /* get entry */
        li      t4, 0
-       sd      t4, 8(t0)       /* mark free */
-       sd      t4, 0(t0)       /* free entry, just in case */
-       ld      t4, 16(t0)      /* take next */
-       la      t0, htif_ring_last
-       sd      t4, 0(t0)
+       sd      t4, 8(t2)       /* mark free */
+       sd      t4, 0(t2)       /* free entry, just in case */
+       ld      t4, 16(t2)      /* take next */
+       sd      t4, 0(t0)       /* update ptr to last */
 1:
        /* Exit. Result is stored in t6 */
        j       exit_next_instr
 
 htif_cmd:
+1:
        mv      t0, t6
+       csrrw   t0, mtohost, t0
+       bnez    t0, 1b
+       j       exit_next_instr
+
+htif_lowputc:
 1:
+       mv      t0, t6
        csrrw   t0, mtohost, t0
        bnez    t0, 1b
+
+2:
+       li      t4, 0
+       csrrw   t5, mfromhost, t4
+       beqz    t5, 2b
+
+       /* Console PUT intr ? */
+       mv      t2, t5
+       srli    t2, t2, 48
+       li      t3, 0x0101
+       beq     t2, t3, 3f
+
+       /* Not a console PUT, so save entry */
+       la      t0, htif_ring
+       csrr    t2, mhartid
+       li      t4, (HTIF_RING_SIZE + 16)
+       mulw    t4, t4, t2
+       add     t0, t0, t4
+       li      t4, (HTIF_RING_SIZE)
+       add     t0, t0, t4      /* t0 == htif_ring_cursor */
+
+       ld      t2, 0(t0)       /* load ptr to cursor */
+       sd      t5, 0(t2)       /* put entry */
+       li      t4, 1
+       sd      t4, 8(t2)       /* mark used */
+       ld      t4, 16(t2)      /* take next */
+       /* Update cursor */
+       sd      t4, 0(t0)
+
+       /* Post supervisor software interrupt */
+       li      t0, MIP_SSIP
+       csrs    mip, t0
+
+       /* Wait for console intr again */
+       j       2b
+
+3:
        j       exit_next_instr
 
 set_mtimecmp:

Modified: head/sys/riscv/riscv/genassym.c
==============================================================================
--- head/sys/riscv/riscv/genassym.c     Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/riscv/genassym.c     Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -75,6 +75,7 @@ ASSYM(PCB_A, offsetof(struct pcb, pcb_a)
 ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
 
 ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
+ASSYM(PC_SPTBR, offsetof(struct pcpu, pc_sptbr));
 ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
 
 ASSYM(TD_PCB, offsetof(struct thread, td_pcb));

Modified: head/sys/riscv/riscv/intr_machdep.c
==============================================================================
--- head/sys/riscv/riscv/intr_machdep.c Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/riscv/intr_machdep.c Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -38,7 +38,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
+#include <sys/cpuset.h>
 #include <sys/interrupt.h>
+#include <sys/smp.h>
 
 #include <machine/clock.h>
 #include <machine/cpu.h>
@@ -46,12 +48,9 @@ __FBSDID("$FreeBSD$");
 #include <machine/frame.h>
 #include <machine/intr.h>
 
-enum {
-       IRQ_SOFTWARE,
-       IRQ_TIMER,
-       IRQ_HTIF,
-       NIRQS
-};
+#ifdef SMP
+#include <machine/smp.h>
+#endif
 
 u_long intrcnt[NIRQS];
 size_t sintrcnt = sizeof(intrcnt);
@@ -159,8 +158,12 @@ riscv_setup_intr(const char *name, drive
                riscv_unmask_irq((void*)(uintptr_t)irq);
        }
 
-       intr_event_add_handler(event, name, filt, handler, arg,
+       error = intr_event_add_handler(event, name, filt, handler, arg,
            intr_priority(flags), flags, cookiep);
+       if (error) {
+               printf("Failed to setup intr: %d\n", irq);
+               return (error);
+       }
 
        riscv_intrcnt_setname(riscv_intr_counters[irq],
                             event->ie_fullname);
@@ -221,3 +224,74 @@ riscv_cpu_intr(struct trapframe *frame)
 
        critical_exit();
 }
+
+#ifdef SMP
+void
+riscv_setup_ipihandler(driver_filter_t *filt)
+{
+
+       riscv_setup_intr("ipi", filt, NULL, NULL, IRQ_SOFTWARE,
+           INTR_TYPE_MISC, NULL);
+}
+
+void
+riscv_unmask_ipi(void)
+{
+
+       csr_set(sie, SIE_SSIE);
+}
+
+/* Sending IPI */
+static void
+ipi_send(struct pcpu *pc, int ipi)
+{
+
+       CTR3(KTR_SMP, "%s: cpu=%d, ipi=%x", __func__, pc->pc_cpuid, ipi);
+
+       atomic_set_32(&pc->pc_pending_ipis, ipi);
+       machine_command(ECALL_SEND_IPI, pc->pc_reg);
+
+       CTR1(KTR_SMP, "%s: sent", __func__);
+}
+
+void
+ipi_all_but_self(u_int ipi)
+{
+       cpuset_t other_cpus;
+
+       other_cpus = all_cpus;
+       CPU_CLR(PCPU_GET(cpuid), &other_cpus);
+
+       CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
+       ipi_selected(other_cpus, ipi);
+}
+
+void
+ipi_cpu(int cpu, u_int ipi)
+{
+       cpuset_t cpus;
+
+       CPU_ZERO(&cpus);
+       CPU_SET(cpu, &cpus);
+
+       CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x\n", __func__, cpu, ipi);
+       ipi_send(cpuid_to_pcpu[cpu], ipi);
+}
+
+void
+ipi_selected(cpuset_t cpus, u_int ipi)
+{
+       struct pcpu *pc;
+
+       CTR1(KTR_SMP, "ipi_selected: ipi: %x", ipi);
+
+       STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
+               if (CPU_ISSET(pc->pc_cpuid, &cpus)) {
+                       CTR3(KTR_SMP, "%s: pc: %p, ipi: %x\n", __func__, pc,
+                           ipi);
+                       ipi_send(pc, ipi);
+               }
+       }
+}
+
+#endif

Modified: head/sys/riscv/riscv/locore.S
==============================================================================
--- head/sys/riscv/riscv/locore.S       Wed Feb 24 15:15:46 2016        
(r295971)
+++ head/sys/riscv/riscv/locore.S       Wed Feb 24 16:50:34 2016        
(r295972)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015 Ruslan Bukin <b...@bsdpad.com>
+ * Copyright (c) 2015-2016 Ruslan Bukin <b...@bsdpad.com>
  * All rights reserved.
  *
  * Portions of this software were developed by SRI International and the
@@ -43,8 +43,55 @@
 #include <machine/riscvreg.h>
 #include <machine/pte.h>
 
-#define        HTIF_RING_SIZE  (64)
-#define        HTIF_RING_LAST  (24 * (HTIF_RING_SIZE - 1))
+#define        HTIF_RING_NENTRIES      (512)
+#define        HTIF_RING_ENTRY_SZ      (24)
+#define        HTIF_RING_SIZE          (HTIF_RING_ENTRY_SZ * 
HTIF_RING_NENTRIES)
+#define        HW_STACK_SIZE           (96)
+
+/*
+ * Event queue for each CPU core:
+ *
+ * struct htif_ring {
+ *     uint64_t data;
+ *     uint64_t used;
+ *     uint64_t next;
+ * } htif_ring[HTIF_RING_NENTRIES];
+ * uint64_t htif_ring_cursor;
+ * uint64_t htif_ring_last;
+ */
+
+.macro build_ring
+       la      t0, htif_ring
+#ifdef SMP
+       csrr    a0, mhartid
+       li      s0, (HTIF_RING_SIZE + 16)
+       mulw    s0, a0, s0
+       add     t0, t0, s0
+#endif
+       li      t1, 0
+       sd      t1, 0(t0)       /* zero data */
+       sd      t1, 8(t0)       /* zero used */
+       mv      t2, t0
+       mv      t3, t0
+       li      t5, (HTIF_RING_SIZE - HTIF_RING_ENTRY_SZ)
+       li      t6, 0
+       add     t4, t0, t5
+1:
+       addi    t3, t3, 24      /* pointer to next */
+       beq     t3, t4, 2f      /* finish */
+       sd      t3, 16(t2)      /* store pointer */
+       addi    t2, t2, 24      /* next entry */
+       addi    t6, t6, 1       /* counter */
+       j       1b
+2:
+       sd      t0, 16(t3)      /* last -> first */
+
+       li      t2, (HTIF_RING_SIZE)
+       add     s0, t0, t2
+       sd      t0, 0(s0)       /* cursor */
+       sd      t0, 8(s0)       /* last */
+       /* finish building ring */
+.endm
 
        .globl  kernbase
        .set    kernbase, KERNBASE
@@ -74,33 +121,14 @@ mentry:
        .align 8
        .globl _start
 _start:
-       li      s11, KERNBASE
+       /* Direct secondary cores to mpentry */
+       csrr    a0, mhartid
+       bnez    a0, mpentry
 
-       /* Build ring */
-       la      t0, htif_ring
-       li      t1, 0
-       sd      t1, 0(t0)       /* zero data */
-       sd      t1, 8(t0)       /* zero used */
-       mv      t2, t0
-       mv      t3, t0
-       li      t5, HTIF_RING_LAST
-       li      t6, 0
-       add     t4, t0, t5
-1:
-       addi    t3, t3, 24      /* pointer to next */
-       beq     t3, t4, 2f      /* finish */
-       sd      t3, 16(t2)      /* store pointer */
-       addi    t2, t2, 24      /* next entry */
-       addi    t6, t6, 1       /* counter */
-       j       1b
-2:
-       sd      t0, 16(t3)      /* last -> first */
-       la      t1, htif_ring_cursor
-       sd      t0, 0(t1)
-       la      t1, htif_ring_last
-       sd      t0, 0(t1)
-       /* finish building ring */
+       /* Build event queue for current core */
+       build_ring
 
+       /* Setup machine-mode stack for CPU 0 */
        la      t0, hardstack_end
        csrw    mscratch, t0
 
@@ -129,7 +157,14 @@ _start:
        li      a6, PTE_SIZE
        mulw    a5, a5, a6
        add     t0, s1, a5
+       /* Store it to pagetable_l0 for each cpu */
+       li      t1, MAXCPU
+       li      t2, PAGE_SIZE
+1:
        sd      t6, 0(t0)
+       add     t0, t0, t2
+       addi    t1, t1, -1
+       bnez    t1, 1b
 
        /* Level 1 */
        la      s1, pagetable_l1
@@ -177,8 +212,16 @@ _start:
                     (MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT));
        csrw    mstatus, s0
 
+       /*
+        * Enable machine-mode software interrupts
+        * so we can deliver IPI to this core.
+        */
+       li      t0, MIE_MSIE
+       csrs    mie, t0
+
        /* Exit from machine mode */
        la      t0, .Lmmu_on
+       li      s11, KERNBASE
        add     t0, t0, s11
        csrw    mepc, t0
        eret
@@ -213,24 +256,16 @@ initstack:
        .space  (PAGE_SIZE * KSTACK_PAGES)
 initstack_end:
 hardstack:
-       .space  (PAGE_SIZE)
+       .space  (HW_STACK_SIZE * MAXCPU)
 hardstack_end:
 
        .globl htif_ring
 htif_ring:
-       .space  (24 * 1024)
-
-       .globl htif_ring_cursor
-htif_ring_cursor:
-       .space  (8)
-
-       .globl htif_ring_last
-htif_ring_last:
-       .space  (8)
+       .space ((HTIF_RING_SIZE + 16) * MAXCPU)
 
        .globl console_intr
 console_intr:
-       .space  (8)
+       .space (8)
 
 ENTRY(sigcode)
        mv      a0, sp
@@ -259,7 +294,7 @@ szsigcode:
        .align  12
        .globl pagetable_l0
 pagetable_l0:
-       .space  PAGE_SIZE
+       .space (PAGE_SIZE * MAXCPU)
 pagetable_l1:
        .space  PAGE_SIZE
 pagetable_l2:
@@ -270,4 +305,95 @@ pagetable_end:
 init_pt_va:
        .quad pagetable_l2      /* XXX: Keep page tables VA */
 
+#ifndef SMP
+ENTRY(mpentry)
+1:
+       wfi
+       j       1b
+END(mpentry)
+#else
+/*
+ * mpentry(unsigned long)
+ *
+ * Called by a core when it is being brought online.
+ * The data in x0 is passed straight to init_secondary.
+ */
+ENTRY(mpentry)
+       /*

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to