o Remove operation in machine mode.

Machine privilege level was specially designed to use in vendor's
  firmware or bootloader. We have implemented operation in machine
  mode in FreeBSD as part of understanding RISC-V ISA, but it is time
  to remove it.
  We now use BBL (Berkeley Boot Loader) -- standard RISC-V firmware,
  which provides operation in machine mode for us.
  We now use standard SBI calls to machine mode, instead of handmade
  'syscalls'.
o Remove HTIF bus.
  HTIF bus is now legacy and no longer exists in RISC-V specification.
  HTIF code still exists in Spike simulator, but BBL do not provide
  raw interface to it.
  Memory disk is only choice for now to have multiuser booted in Spike,
  until Spike has implemented more devices (e.g. Virtio, etc).

Sponsored by:	DARPA, AFRL
Sponsored by:	HEIF5
This commit is contained in:
Ruslan Bukin 2016-08-10 12:41:36 +00:00
parent 4cf6e978b4
commit 5f8228b2f3
28 changed files with 362 additions and 1385 deletions

View File

@ -72,15 +72,11 @@
clock-frequency = < 400000000 >;
};
htif0: htif@0 {
compatible = "riscv,htif";
interrupts = < 0 >;
console0: console@0 {
compatible = "riscv,console";
status = "okay";
interrupts = < 1 >;
interrupt-parent = < &pic0 >;
console0: console@0 {
compatible = "htif,console";
status = "okay";
};
};
};

View File

@ -83,15 +83,11 @@
clock-frequency = < 1000000 >;
};
htif0: htif@0 {
compatible = "riscv,htif";
interrupts = < 0 >;
console0: console@0 {
compatible = "riscv,console";
status = "okay";
interrupts = < 1 >;
interrupt-parent = < &pic0 >;
console0: console@0 {
compatible = "htif,console";
status = "okay";
};
};
};

View File

@ -65,6 +65,10 @@
};
memory {
/*
* This is not used currently.
* We take information from sbi_query_memory.
*/
device_type = "memory";
reg = <0x80000000 0x40000000>; /* 1GB at 0x80000000 */
};
@ -90,15 +94,11 @@
clock-frequency = < 1000000 >;
};
htif0: htif@0 {
compatible = "riscv,htif";
console0: console@0 {
compatible = "riscv,console";
status = "okay";
interrupts = < 1 >;
interrupt-parent = < &pic0 >;
console0: console@0 {
compatible = "htif,console";
status = "okay";
};
};
};

View File

@ -19,9 +19,6 @@ libkern/flsl.c standard
libkern/flsll.c standard
libkern/memmove.c standard
libkern/memset.c standard
riscv/htif/htif.c optional htif
riscv/htif/htif_block.c optional htif
riscv/htif/htif_console.c optional htif
riscv/riscv/autoconf.c standard
riscv/riscv/bcopy.c standard
riscv/riscv/bus_machdep.c standard
@ -36,6 +33,7 @@ riscv/riscv/db_interface.c optional ddb
riscv/riscv/db_trace.c optional ddb
riscv/riscv/dump_machdep.c standard
riscv/riscv/elf_machdep.c standard
riscv/riscv/exception.S standard
riscv/riscv/intr_machdep.c standard
riscv/riscv/in_cksum.c optional inet | inet6
riscv/riscv/identcpu.c standard
@ -47,6 +45,8 @@ riscv/riscv/mem.c standard
riscv/riscv/nexus.c standard
riscv/riscv/ofw_machdep.c optional fdt
riscv/riscv/pmap.c standard
riscv/riscv/riscv_console.c optional rcons
riscv/riscv/sbi.S standard
riscv/riscv/stack_machdep.c optional ddb | stack
riscv/riscv/support.S standard
riscv/riscv/swtch.S standard

View File

@ -6,7 +6,7 @@ SEARCH_DIR(/usr/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = kernbase + 0x80000000 /* KERNENTRY */;
. = kernbase;
.text : AT(ADDR(.text) - kernbase)
{
*(.text)

View File

@ -76,7 +76,7 @@ options SMP
# Uncomment for memory disk
# options MD_ROOT
# options MD_ROOT_SIZE=8192 # 8MB ram disk
# options MD_ROOT_SIZE=32768 # 32MB ram disk
# makeoptions MFS_IMAGE=/path/to/img
# options ROOTDEVNAME=\"ufs:/dev/md0\"

View File

@ -21,8 +21,8 @@
include GENERIC
ident QEMU
device htif
options ROOTDEVNAME=\"ufs:/dev/htif_blk0\"
device rcons
options ROOTDEVNAME=\"ufs:/dev/md0\"
# RISCVTODO: This needs to be done via loader (when it's available).
options FDT_DTB_STATIC

View File

@ -21,8 +21,8 @@
include GENERIC
ident ROCKET
device htif
options ROOTDEVNAME=\"ufs:/dev/htif_blk0\"
device rcons
options ROOTDEVNAME=\"ufs:/dev/md0\"
# RISCVTODO: This needs to be done via loader (when it's available).
options FDT_DTB_STATIC

View File

@ -21,8 +21,8 @@
include GENERIC
ident SPIKE
device htif
options ROOTDEVNAME=\"ufs:/dev/htif_blk0\"
device rcons
options ROOTDEVNAME=\"ufs:/dev/md0\"
# RISCVTODO: This needs to be done via loader (when it's available).
options FDT_DTB_STATIC

View File

@ -1,278 +0,0 @@
/*-
* Copyright (c) 2015-2016 Ruslan Bukin <br@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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <machine/asm.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include "htif.h"
static struct resource_spec htif_spec[] = {
{ SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE},
{ -1, 0 }
};
struct intr_entry {
void (*func) (void *, uint64_t);
void *arg;
};
struct intr_entry intrs[HTIF_NDEV];
uint64_t
htif_command(uint64_t arg)
{
return (machine_command(ECALL_HTIF_CMD, arg));
}
int
htif_setup_intr(int id, void *func, void *arg)
{
if (id >= HTIF_NDEV)
return (-1);
intrs[id].func = func;
intrs[id].arg = arg;
return (0);
}
static void
htif_handle_entry(struct htif_softc *sc)
{
uint64_t entry;
uint8_t devcmd;
uint8_t devid;
entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
while (entry) {
devid = HTIF_DEV_ID(entry);
devcmd = HTIF_DEV_CMD(entry);
if (devcmd == HTIF_CMD_IDENTIFY) {
/* Enumeration interrupt */
if (devid == sc->identify_id)
sc->identify_done = 1;
} else {
/* Device interrupt */
if (intrs[devid].func != NULL)
intrs[devid].func(intrs[devid].arg, entry);
}
entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
}
}
static int
htif_intr(void *arg)
{
struct htif_softc *sc;
sc = arg;
csr_clear(sip, SIP_SSIP);
htif_handle_entry(sc);
return (FILTER_HANDLED);
}
static int
htif_add_device(struct htif_softc *sc, int i, char *id, char *name)
{
struct htif_dev_ivars *di;
di = malloc(sizeof(struct htif_dev_ivars), M_DEVBUF, M_WAITOK | M_ZERO);
di->sc = sc;
di->index = i;
di->id = malloc(HTIF_ID_LEN, M_DEVBUF, M_WAITOK | M_ZERO);
memcpy(di->id, id, HTIF_ID_LEN);
di->dev = device_add_child(sc->dev, name, -1);
device_set_ivars(di->dev, di);
return (0);
}
static int
htif_enumerate(struct htif_softc *sc)
{
char id[HTIF_ID_LEN] __aligned(HTIF_ALIGN);
uint64_t paddr;
uint64_t data;
uint64_t cmd;
int len;
int i;
device_printf(sc->dev, "Enumerating devices\n");
for (i = 0; i < HTIF_NDEV; i++) {
paddr = pmap_kextract((vm_offset_t)&id);
data = (paddr << IDENTIFY_PADDR_SHIFT);
data |= IDENTIFY_IDENT;
sc->identify_id = i;
sc->identify_done = 0;
cmd = i;
cmd <<= HTIF_DEV_ID_SHIFT;
cmd |= (HTIF_CMD_IDENTIFY << HTIF_CMD_SHIFT);
cmd |= data;
htif_command(cmd);
len = strnlen(id, sizeof(id));
if (len <= 0)
break;
if (bootverbose)
printf(" %d %s\n", i, id);
if (strncmp(id, "disk", 4) == 0)
htif_add_device(sc, i, id, "htif_blk");
else if (strncmp(id, "bcd", 3) == 0)
htif_add_device(sc, i, id, "htif_console");
else if (strncmp(id, "syscall_proxy", 13) == 0)
htif_add_device(sc, i, id, "htif_syscall_proxy");
}
return (bus_generic_attach(sc->dev));
}
int
htif_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct htif_dev_ivars *ivars;
ivars = device_get_ivars(child);
switch (which) {
case HTIF_IVAR_INDEX:
*result = ivars->index;
break;
case HTIF_IVAR_ID:
*result = (uintptr_t)ivars->id;
default:
return (EINVAL);
}
return (0);
}
static int
htif_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "riscv,htif"))
return (ENXIO);
device_set_desc(dev, "HTIF bus device");
return (BUS_PROBE_DEFAULT);
}
static int
htif_attach(device_t dev)
{
struct htif_softc *sc;
int error;
sc = device_get_softc(dev);
sc->dev = dev;
if (bus_alloc_resources(dev, htif_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
/* Setup IRQs handler */
error = bus_setup_intr(dev, sc->res[0], INTR_TYPE_CLK,
htif_intr, NULL, sc, &sc->ihl[0]);
if (error) {
device_printf(dev, "Unable to alloc int resource.\n");
return (ENXIO);
}
csr_set(sie, SIE_SSIE);
return (htif_enumerate(sc));
}
static device_method_t htif_methods[] = {
DEVMETHOD(device_probe, htif_probe),
DEVMETHOD(device_attach, htif_attach),
/* Bus interface */
DEVMETHOD(bus_read_ivar, htif_read_ivar),
DEVMETHOD_END
};
static driver_t htif_driver = {
"htif",
htif_methods,
sizeof(struct htif_softc)
};
static devclass_t htif_devclass;
DRIVER_MODULE(htif, simplebus, htif_driver,
htif_devclass, 0, 0);

View File

@ -1,299 +0,0 @@
/*-
* Copyright (c) 2015-2016 Ruslan Bukin <br@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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/selinfo.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
#include <sys/sysctl.h>
#include <sys/uio.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/disk.h>
#include <geom/geom_disk.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/md_var.h>
#include <machine/bus.h>
#include <machine/trap.h>
#include <sys/rman.h>
#include "htif.h"
#define SECTOR_SIZE_SHIFT (9)
#define SECTOR_SIZE (1 << SECTOR_SIZE_SHIFT)
#define HTIF_BLK_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define HTIF_BLK_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define HTIF_BLK_LOCK_INIT(_sc) \
mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
"htif_blk", MTX_DEF)
#define HTIF_BLK_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
#define HTIF_BLK_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
#define HTIF_BLK_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
static void htif_blk_task(void *arg);
static disk_open_t htif_blk_open;
static disk_close_t htif_blk_close;
static disk_strategy_t htif_blk_strategy;
struct htif_blk_softc {
device_t dev;
struct disk *disk;
struct mtx htif_io_mtx;
struct mtx sc_mtx;
struct proc *p;
struct bio_queue_head bio_queue;
int running;
int intr_chan;
int cmd_done;
int index;
uint16_t curtag;
};
struct htif_blk_request {
uint64_t addr;
uint64_t offset; /* offset in bytes */
uint64_t size; /* length in bytes */
uint64_t tag;
};
static void
htif_blk_intr(void *arg, uint64_t entry)
{
struct htif_blk_softc *sc;
uint64_t devcmd;
uint64_t data;
sc = arg;
devcmd = HTIF_DEV_CMD(entry);
data = HTIF_DEV_DATA(entry);
if (sc->curtag == data) {
wmb();
sc->cmd_done = 1;
wakeup(&sc->intr_chan);
} else {
device_printf(sc->dev, "Unexpected tag %d (should be %d)\n",
data, sc->curtag);
}
}
static int
htif_blk_probe(device_t dev)
{
return (0);
}
static int
htif_blk_attach(device_t dev)
{
struct htif_blk_softc *sc;
char prefix[] = " size=";
char *str;
long size;
sc = device_get_softc(dev);
sc->dev = dev;
mtx_init(&sc->htif_io_mtx, device_get_nameunit(dev), "htif_blk", MTX_DEF);
HTIF_BLK_LOCK_INIT(sc);
str = strstr(htif_get_id(dev), prefix);
size = strtol((str + 6), NULL, 10);
if (size == 0) {
return (ENXIO);
}
sc->index = htif_get_index(dev);
if (sc->index < 0)
return (EINVAL);
htif_setup_intr(sc->index, htif_blk_intr, sc);
sc->disk = disk_alloc();
sc->disk->d_drv1 = sc;
sc->disk->d_maxsize = 4096; /* Max transfer */
sc->disk->d_name = "htif_blk";
sc->disk->d_open = htif_blk_open;
sc->disk->d_close = htif_blk_close;
sc->disk->d_strategy = htif_blk_strategy;
sc->disk->d_unit = 0;
sc->disk->d_sectorsize = SECTOR_SIZE;
sc->disk->d_mediasize = size;
disk_create(sc->disk, DISK_VERSION);
bioq_init(&sc->bio_queue);
sc->running = 1;
kproc_create(&htif_blk_task, sc, &sc->p, 0, 0, "%s: transfer",
device_get_nameunit(dev));
return (0);
}
static int
htif_blk_open(struct disk *dp)
{
return (0);
}
static int
htif_blk_close(struct disk *dp)
{
return (0);
}
static void
htif_blk_task(void *arg)
{
struct htif_blk_request req __aligned(HTIF_ALIGN);
struct htif_blk_softc *sc;
uint64_t req_paddr;
struct bio *bp;
uint64_t paddr;
uint64_t resp;
uint64_t cmd;
int i;
sc = (struct htif_blk_softc *)arg;
while (1) {
HTIF_BLK_LOCK(sc);
do {
bp = bioq_takefirst(&sc->bio_queue);
if (bp == NULL)
msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
} while (bp == NULL);
HTIF_BLK_UNLOCK(sc);
if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
HTIF_BLK_LOCK(sc);
rmb();
req.offset = (bp->bio_pblkno * sc->disk->d_sectorsize);
req.size = bp->bio_bcount;
paddr = vtophys(bp->bio_data);
KASSERT(paddr != 0, ("paddr is 0"));
req.addr = paddr;
sc->curtag++;
req.tag = sc->curtag;
cmd = sc->index;
cmd <<= HTIF_DEV_ID_SHIFT;
if (bp->bio_cmd == BIO_READ)
cmd |= (HTIF_CMD_READ << HTIF_CMD_SHIFT);
else
cmd |= (HTIF_CMD_WRITE << HTIF_CMD_SHIFT);
req_paddr = vtophys(&req);
KASSERT(req_paddr != 0, ("req_paddr is 0"));
cmd |= req_paddr;
sc->cmd_done = 0;
resp = htif_command(cmd);
htif_blk_intr(sc, resp);
/* Wait for interrupt */
i = 0;
while (sc->cmd_done == 0) {
msleep(&sc->intr_chan, &sc->sc_mtx, PRIBIO, "intr", hz/2);
if (i++ > 2) {
/* TODO: try to re-issue operation on timeout ? */
bp->bio_error = EIO;
bp->bio_flags |= BIO_ERROR;
disk_err(bp, "hard error", -1, 1);
break;
}
}
HTIF_BLK_UNLOCK(sc);
biodone(bp);
} else {
printf("unknown op %d\n", bp->bio_cmd);
}
}
}
static void
htif_blk_strategy(struct bio *bp)
{
struct htif_blk_softc *sc;
sc = bp->bio_disk->d_drv1;
HTIF_BLK_LOCK(sc);
if (sc->running > 0) {
bioq_disksort(&sc->bio_queue, bp);
HTIF_BLK_UNLOCK(sc);
wakeup(sc);
} else {
HTIF_BLK_UNLOCK(sc);
biofinish(bp, NULL, ENXIO);
}
}
static device_method_t htif_blk_methods[] = {
DEVMETHOD(device_probe, htif_blk_probe),
DEVMETHOD(device_attach, htif_blk_attach),
};
static driver_t htif_blk_driver = {
"htif_blk",
htif_blk_methods,
sizeof(struct htif_blk_softc)
};
static devclass_t htif_blk_devclass;
DRIVER_MODULE(htif_blk, htif, htif_blk_driver, htif_blk_devclass, 0, 0);

View File

@ -81,21 +81,6 @@ intr_enable(void)
);
}
static __inline register_t
machine_command(uint64_t cmd, uint64_t arg)
{
uint64_t res;
__asm __volatile(
"mv t5, %2\n"
"mv t6, %1\n"
"ecall\n"
"mv %0, t6" : "=&r"(res) : "r"(arg), "r"(cmd)
);
return (res);
}
#define cpu_nullop() riscv_nullop()
#define cpufunc_nullop() riscv_nullop()
#define cpu_setttb(a) riscv_setttb(a)

View File

@ -46,8 +46,7 @@
#define PCPU_MD_FIELDS \
uint32_t pc_pending_ipis; /* IPIs pending to this CPU */ \
uint64_t pc_reg; /* CPU MMIO base (PA) */ \
char __pad[117]
char __pad[125]
#ifdef _KERNEL

View File

@ -37,19 +37,6 @@
#ifndef _MACHINE_RISCVREG_H_
#define _MACHINE_RISCVREG_H_
/* Machine mode requests */
#define ECALL_MTIMECMP 0x01
#define ECALL_HTIF_GET_ENTRY 0x02
#define ECALL_MCPUID_GET 0x03
#define ECALL_MIMPID_GET 0x04
#define ECALL_SEND_IPI 0x05
#define ECALL_CLEAR_IPI 0x06
#define ECALL_MIE_SET 0x07
#define ECALL_IO_IRQ_MASK 0x08
#define ECALL_HTIF_CMD 0x09
#define ECALL_HTIF_CMD_REQ 0x0a
#define ECALL_HTIF_CMD_RESP 0x0b
#define EXCP_SHIFT 0
#define EXCP_MASK (0xf << EXCP_SHIFT)
#define EXCP_MISALIGNED_FETCH 0
@ -65,9 +52,6 @@
#define EXCP_HYPERVISOR_ECALL 10
#define EXCP_MACHINE_ECALL 11
#define EXCP_INTR (1ul << 63)
#define EXCP_INTR_SOFTWARE 0
#define EXCP_INTR_TIMER 1
#define EXCP_INTR_HTIF 2
#define SSTATUS_UIE (1 << 0)
#define SSTATUS_SIE (1 << 1)

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
@ -34,60 +34,32 @@
* $FreeBSD$
*/
#define HTIF_DEV_ID_SHIFT (56)
#define HTIF_DEV_ID_MASK (0xfful << HTIF_DEV_ID_SHIFT)
#define HTIF_CMD_SHIFT (48)
#define HTIF_CMD_MASK (0xfful << HTIF_CMD_SHIFT)
#define HTIF_DATA_SHIFT (0)
#define HTIF_DATA_MASK (0xffffffff << HTIF_DATA_SHIFT)
#ifndef _MACHINE_SBI_H_
#define _MACHINE_SBI_H_
#define HTIF_CMD_READ (0x00ul)
#define HTIF_CMD_WRITE (0x01ul)
#define HTIF_CMD_READ_CONTROL_REG (0x02ul)
#define HTIF_CMD_WRITE_CONTROL_REG (0x03ul)
#define HTIF_CMD_IDENTIFY (0xfful)
#define IDENTIFY_PADDR_SHIFT 8
#define IDENTIFY_IDENT 0xff
typedef struct {
uint64_t base;
uint64_t size;
uint64_t node_id;
} memory_block_info;
#define HTIF_NDEV (256)
#define HTIF_ID_LEN (64)
#define HTIF_ALIGN (64)
uint64_t sbi_query_memory(uint64_t id, memory_block_info *p);
uint64_t sbi_hart_id(void);
uint64_t sbi_num_harts(void);
uint64_t sbi_timebase(void);
void sbi_set_timer(uint64_t stime_value);
void sbi_send_ipi(uint64_t hart_id);
uint64_t sbi_clear_ipi(void);
void sbi_shutdown(void);
#define HTIF_DEV_CMD(entry) ((entry & HTIF_CMD_MASK) >> HTIF_CMD_SHIFT)
#define HTIF_DEV_ID(entry) ((entry & HTIF_DEV_ID_MASK) >> HTIF_DEV_ID_SHIFT)
#define HTIF_DEV_DATA(entry) ((entry & HTIF_DATA_MASK) >> HTIF_DATA_SHIFT)
void sbi_console_putchar(unsigned char ch);
int sbi_console_getchar(void);
/* bus softc */
struct htif_softc {
struct resource *res[1];
void *ihl[1];
device_t dev;
uint64_t identify_id;
uint64_t identify_done;
};
void sbi_remote_sfence_vm(uint64_t hart_mask_ptr, uint64_t asid);
void sbi_remote_sfence_vm_range(uint64_t hart_mask_ptr, uint64_t asid, uint64_t start, uint64_t size);
void sbi_remote_fence_i(uint64_t hart_mask_ptr);
/* device private data */
struct htif_dev_ivars {
char *id;
int index;
device_t dev;
struct htif_softc *sc;
};
uint64_t sbi_mask_interrupt(uint64_t which);
uint64_t sbi_unmask_interrupt(uint64_t which);
uint64_t htif_command(uint64_t);
int htif_setup_intr(int id, void *func, void *arg);
int htif_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
enum htif_device_ivars {
HTIF_IVAR_INDEX,
HTIF_IVAR_ID,
};
/*
* Simplified accessors for HTIF devices
*/
#define HTIF_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(htif, var, HTIF, ivar, type)
HTIF_ACCESSOR(index, INDEX, int);
HTIF_ACCESSOR(id, ID, char *);
#endif /* !_MACHINE_SBI_H_ */

View File

@ -156,26 +156,26 @@
#define VM_MIN_KERNEL_ADDRESS (0xffffffc000000000UL)
#define VM_MAX_KERNEL_ADDRESS (0xffffffc800000000UL)
/* Direct Map for 128 GiB of PA: 0x0 - 0x1fffffffff */
/* 128 GiB maximum for the direct map region */
#define DMAP_MIN_ADDRESS (0xffffffd000000000UL)
#define DMAP_MAX_ADDRESS (0xffffffefffffffffUL)
#define DMAP_MAX_ADDRESS (0xfffffff000000000UL)
#define DMAP_MIN_PHYSADDR (0x0000000000000000UL)
#define DMAP_MAX_PHYSADDR (DMAP_MAX_ADDRESS - DMAP_MIN_ADDRESS)
#define DMAP_MIN_PHYSADDR (dmap_phys_base)
#define DMAP_MAX_PHYSADDR (dmap_phys_max)
/* True if pa is in the dmap range */
#define PHYS_IN_DMAP(pa) ((pa) >= DMAP_MIN_PHYSADDR && \
(pa) <= DMAP_MAX_PHYSADDR)
(pa) < DMAP_MAX_PHYSADDR)
/* True if va is in the dmap range */
#define VIRT_IN_DMAP(va) ((va) >= DMAP_MIN_ADDRESS && \
(va) <= DMAP_MAX_ADDRESS)
(va) < (dmap_max_addr))
#define PHYS_TO_DMAP(pa) \
({ \
KASSERT(PHYS_IN_DMAP(pa), \
("%s: PA out of range, PA: 0x%lx", __func__, \
(vm_paddr_t)(pa))); \
(pa) | DMAP_MIN_ADDRESS; \
((pa) - dmap_phys_base) + DMAP_MIN_ADDRESS; \
})
#define DMAP_TO_PHYS(va) \
@ -183,7 +183,7 @@
KASSERT(VIRT_IN_DMAP(va), \
("%s: VA out of range, VA: 0x%lx", __func__, \
(vm_offset_t)(va))); \
(va) & ~DMAP_MIN_ADDRESS; \
((va) - DMAP_MIN_ADDRESS) + dmap_phys_base; \
})
#define VM_MIN_USER_ADDRESS (0x0000000000000000UL)
@ -196,7 +196,7 @@
#define SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE)
#define USRSTACK SHAREDPAGE
#define KERNENTRY (0x80000000)
#define KERNENTRY (0)
/*
* How many physical pages per kmem arena virtual page.
@ -233,9 +233,14 @@
* #define UMA_MD_SMALL_ALLOC
*/
#ifndef LOCORE
extern vm_paddr_t dmap_phys_base;
extern vm_paddr_t dmap_phys_max;
extern vm_offset_t dmap_max_addr;
extern u_int tsb_kernel_ldd_phys;
extern vm_offset_t vm_max_kernel_address;
extern vm_offset_t init_pt_va;
#endif
#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */

View File

@ -235,388 +235,3 @@ ENTRY(cpu_exception_handler_user)
csrrw sp, sscratch, sp
sret
END(cpu_exception_handler_user)
/*
* Trap handlers
*/
.text
bad_trap:
j bad_trap
machine_trap:
/* Save state */
csrrw sp, mscratch, sp
addi sp, sp, -64
sd t0, (8 * 0)(sp)
sd t1, (8 * 1)(sp)
sd t2, (8 * 2)(sp)
sd t3, (8 * 3)(sp)
sd t4, (8 * 4)(sp)
sd t5, (8 * 5)(sp)
sd a0, (8 * 7)(sp)
csrr t3, mstatus /* Required for debug */
csrr t0, mcause
bltz t0, machine_interrupt
li t1, EXCP_SUPERVISOR_ECALL
beq t0, t1, supervisor_call
4:
/* NOT REACHED */
j 4b
machine_interrupt:
/* Type of interrupt ? */
csrr t0, mcause
andi t0, t0, EXCP_MASK
#if 0
/* lowRISC TODO */
li t1, 4
beq t1, t0, io_interrupt /* lowRISC only */
#endif
li t1, 1
beq t1, t0, supervisor_software_interrupt
li t1, 3
beq t1, t0, machine_software_interrupt
li t1, 5
beq t1, t0, supervisor_timer_interrupt
li t1, 7
beq t1, t0, machine_timer_interrupt
/* NOT REACHED */
1:
j 1b
#if 0
/* lowRISC TODO */
io_interrupt:
/* Disable IO interrupts so we can go to supervisor mode */
csrwi CSR_IO_IRQ, 0
/* Handle the trap in supervisor mode */
j exit_mrts
#endif
supervisor_software_interrupt:
1:
/* Nothing here as we are using mideleg feature */
j 1b
machine_software_interrupt:
/* Clear IPI */
li t0, 0x40001000
csrr t2, mhartid
li t3, 0x1000
mul t2, t2, t3
add t0, t0, t2
li t2, 0
sd t2, 0(t0)
/* Clear machine software pending bit */
li t0, MIP_MSIP
csrc mip, t0
/* Post supervisor software interrupt */
li t0, MIP_SSIP
csrs mip, t0
j exit
supervisor_timer_interrupt:
1:
/* Nothing here as we are using mideleg feature */
j 1b
machine_timer_interrupt:
/* Disable machine timer interrupts */
li t0, MIE_MTIE
csrc mie, t0
/* Clear machine timer interrupt pending */
li t0, MIP_MTIP
csrc mip, t0
/* Post supervisor timer interrupt */
li t0, MIP_STIP
csrs mip, t0
/*
* Check for HTIF interrupts.
* The only interrupt expected here is key press.
*/
la t0, htif_lock
li t2, 1
amoswap.d t3, t2, 0(t0)
bnez t3, 5f /* Another operation in progress, give up */
/* We have lock */
la t1, fromhost
ld t5, 0(t1)
beqz t5, 4f
/* Console GET intr ? */
mv t1, t5
li t0, 0x100
srli t1, t1, 48
beq t1, t0, 2f
1:
/* There is no interrupts except keypress */
j 1b
2:
/* Save entry */
la t0, htif_ring
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(t1) /* mark used */
ld t4, 16(t1) /* take next */
/* Update cursor */
sd t4, 0(t0)
/* Post supervisor software interrupt */
li t0, MIP_SSIP
csrs mip, t0
3:
la t1, fromhost
li t5, 0
sd t5, 0(t1)
4:
/* Release lock */
la t0, htif_lock
li t2, 0
amoswap.d t3, t2, 0(t0)
5:
j exit
supervisor_call:
csrr t1, mepc
addi t1, t1, 4 /* Next instruction in t1 */
li t4, ECALL_HTIF_CMD
beq t5, t4, htif_cmd
li t4, ECALL_HTIF_CMD_REQ
beq t5, t4, htif_cmd_req
li t4, ECALL_HTIF_CMD_RESP
beq t5, t4, htif_cmd_resp
li t4, ECALL_HTIF_GET_ENTRY
beq t5, t4, htif_get_entry
li t4, ECALL_MTIMECMP
beq t5, t4, set_mtimecmp
li t4, ECALL_MCPUID_GET
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_MIE_SET
beq t5, t4, mie_set
#if 0
/* lowRISC TODO */
li t4, ECALL_IO_IRQ_MASK
beq t5, t4, io_irq_mask
#endif
j exit_next_instr
#if 0
/* lowRISC TODO */
io_irq_mask:
csrw CSR_IO_IRQ, t6
j exit_next_instr
#endif
mie_set:
csrs mie, t6
j exit_next_instr
mcpuid_get:
csrr t6, misa
j exit_next_instr
mimpid_get:
csrr t6, mimpid
j exit_next_instr
send_ipi:
/* CPU ipi MMIO register in t6 */
mv t0, t6
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
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
li t4, (HTIF_RING_SIZE + 8)
add t0, t0, t4 /* t0 == htif_ring_last */
/* Check for new entries */
li t6, 0 /* preset return value */
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(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_resp:
la t0, htif_lock
li t2, 1
1:
amoswap.d t3, t2, 0(t0)
bnez t3, 1b
/* We have lock. Read for data */
la t4, fromhost
ld t6, 0(t4)
beqz t6, 2f
/* Clear event */
li t5, 0
sd t5, 0(t4)
2:
/* Release lock */
la t0, htif_lock
li t2, 0
amoswap.d t3, t2, 0(t0)
j exit_next_instr
htif_cmd_req:
la t0, htif_lock
li t2, 1
1:
amoswap.d t3, t2, 0(t0)
bnez t3, 1b
/* We have lock. Store new request */
la t4, tohost
sd t6, 0(t4)
/* Release lock */
la t0, htif_lock
li t2, 0
amoswap.d t3, t2, 0(t0)
j exit_next_instr
htif_cmd:
la t0, htif_lock
li t2, 1
1:
amoswap.d t3, t2, 0(t0)
bnez t3, 1b
mv t3, t6
/* We have lock. Store new request */
la t4, tohost
sd t6, 0(t4)
2:
/* Poll for result */
la t4, fromhost
ld t6, 0(t4)
beqz t6, 2b
/* Check for unexpected event */
srli t0, t6, 48
srli t2, t3, 48
beq t2, t0, 3f
/*
* We have something unexpected (e.g. keyboard keypress)
* Save entry.
*/
la t0, htif_ring
li t4, (HTIF_RING_SIZE)
add t0, t0, t4 /* t0 == htif_ring_cursor */
ld t2, 0(t0) /* load ptr to cursor */
sd t6, 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
/* Clear and look for response again */
la t2, fromhost
li t5, 0
sd t5, 0(t2)
j 2b
3:
la t2, fromhost
li t5, 0
sd t5, 0(t2)
/* Release lock */
la t0, htif_lock
li t2, 0
amoswap.d t3, t2, 0(t0)
j exit_next_instr
set_mtimecmp:
/* Enable interrupts */
li t0, (MIE_MTIE | MIE_STIE)
csrs mie, t0
j exit_next_instr
/*
* Trap exit functions
*/
exit_next_instr:
/* Next instruction is in t1 */
csrw mepc, t1
exit:
/* Restore state */
ld t0, (8 * 0)(sp)
ld t1, (8 * 1)(sp)
ld t2, (8 * 2)(sp)
ld t3, (8 * 3)(sp)
ld t4, (8 * 4)(sp)
ld t5, (8 * 5)(sp)
ld a0, (8 * 7)(sp)
addi sp, sp, 64
csrrw sp, mscratch, sp
mret
exit_mrts:
j exit_mrts

View File

@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
ASSYM(KERNBASE, KERNBASE);
ASSYM(KERNENTRY, KERNENTRY);
ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS);
ASSYM(VM_MAX_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS);
ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);

View File

@ -101,8 +101,9 @@ identify_cpu(void)
cpu_partsp = NULL;
mimpid = machine_command(ECALL_MIMPID_GET, 0);
misa = machine_command(ECALL_MCPUID_GET, 0);
/* TODO: can we get mimpid and misa somewhere ? */
mimpid = 0;
misa = 0;
cpu = PCPU_GET(cpuid);

View File

@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpufunc.h>
#include <machine/frame.h>
#include <machine/intr.h>
#include <machine/sbi.h>
#ifdef SMP
#include <machine/smp.h>
@ -267,7 +268,7 @@ 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);
sbi_send_ipi(pc->pc_cpuid);
CTR1(KTR_SMP, "%s: sent", __func__);
}

View File

@ -43,118 +43,47 @@
#include <machine/riscvreg.h>
#include <machine/pte.h>
#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:
*
* 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
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)
li t6, 0
add t4, t0, t5
1:
addi t3, t3, HTIF_RING_ENTRY_SZ /* pointer to next */
beq t3, t4, 2f /* finish */
sd t3, 16(t2) /* store pointer */
addi t2, t2, HTIF_RING_ENTRY_SZ /* next entry */
addi t6, t6, 1 /* counter */
j 1b
2:
addi t3, t3, -HTIF_RING_ENTRY_SZ
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
/* Trap entries */
.text
mentry:
/* Vectors */
j _start /* reset */
j bad_trap /* NMI (non-maskable interrupt) */
j machine_trap
/* Reset vector */
.text
.globl _start
_start:
/* Setup machine trap vector */
la t0, machine_trap
csrw mtvec, t0
/* Delegate interrupts to supervisor mode */
li t0, (MIP_SSIP | MIP_STIP | MIP_SEIP)
csrw mideleg, t0
/* Delegate exceptions to supervisor mode */
li t0, (1 << EXCP_MISALIGNED_FETCH) | \
(1 << EXCP_FAULT_FETCH) | \
(1 << EXCP_ILLEGAL_INSTRUCTION) | \
(1 << EXCP_FAULT_LOAD) | \
(1 << EXCP_FAULT_STORE) | \
(1 << EXCP_BREAKPOINT) | \
(1 << EXCP_USER_ECALL)
csrw medeleg, t0
/* Setup supervisor trap vector */
la t0, cpu_exception_handler
li t1, KERNBASE
add t0, t0, t1
csrw stvec, t0
/* Direct secondary cores to mpentry */
csrr a0, mhartid
bnez a0, mpentry
li t1, 0
la t0, tohost
sd t1, 0(t0)
la t0, fromhost
sd t1, 0(t0)
/* Build event queue for current core */
build_ring
/* Setup machine-mode stack for CPU 0 */
la t0, hardstack_end
csrw mscratch, t0
/* Ensure sscratch is zero */
li t0, 0
csrw sscratch, t0
li s10, PAGE_SIZE
li s9, (PAGE_SIZE * KSTACK_PAGES)
/* Load physical memory information */
li a0, 0
la a1, memory_info
call sbi_query_memory
/* Page tables */
/* Store base to s6 */
la s6, memory_info
ld s6, 0(s6) /* s6 = physmem base */
/* Direct secondary cores to mpentry */
call sbi_hart_id
bnez a0, mpentry
/*
* Page tables
*/
/* Create an L1 page for early devmap */
la s1, pagetable_l1
la s2, pagetable_l2_devmap /* Link to next level PN */
li t0, KERNBASE
sub s2, s2, t0
add s2, s2, s6
srli s2, s2, PAGE_SHIFT
li a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE)
@ -170,19 +99,74 @@ _start:
add t0, s1, a5
sd t6, (t0)
/* Add single Level 1 entry for kernel */
/* Create an L1 page for SBI */
la s1, pagetable_l1
la s2, pagetable_l2_sbi /* Link to next level PN */
li t0, KERNBASE
sub s2, s2, t0
add s2, s2, s6
srli s2, s2, PAGE_SHIFT
li a5, 511
li t4, PTE_V
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
or t6, t4, t5
/* Store SBI L1 PTE entry to position */
li a6, PTE_SIZE
mulw a5, a5, a6
add t0, s1, a5
sd t6, (t0)
/* Create an L2 page for SBI */
la s1, pagetable_l2_sbi
la s2, pagetable_l3_sbi /* Link to next level PN */
li t0, KERNBASE
sub s2, s2, t0
add s2, s2, s6
srli s2, s2, PAGE_SHIFT
li a5, 511
li t4, PTE_V
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
or t6, t4, t5
/* Store SBI L2 PTE entry to position */
li a6, PTE_SIZE
mulw a5, a5, a6
add t0, s1, a5
sd t6, (t0)
/* Create an L3 page for SBI */
la s1, pagetable_l3_sbi
li s2, 0x80009000
srli s2, s2, PAGE_SHIFT
li a5, 511
li t4, PTE_V | PTE_RX | PTE_W
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
or t6, t4, t5
/* Store SBI L3 PTE entry to position */
li a6, PTE_SIZE
mulw a5, a5, a6
add t0, s1, a5
sd t6, (t0)
/* END SBI page creation */
/* Add L1 entry for kernel */
la s1, pagetable_l1
la s2, pagetable_l2 /* Link to next level PN */
li t0, KERNBASE
sub s2, s2, t0
add s2, s2, s6
srli s2, s2, PAGE_SHIFT
li a5, (KERNBASE + KERNENTRY)
li a5, KERNBASE
srli a5, a5, L1_SHIFT /* >> L1_SHIFT */
andi a5, a5, 0x1ff /* & 0x1ff */
li t4, PTE_V
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
or t6, t4, t5
/* Store single level1 PTE entry to position */
/* Store L1 PTE entry to position */
li a6, PTE_SIZE
mulw a5, a5, a6
add t0, s1, a5
@ -190,8 +174,7 @@ _start:
/* Level 2 superpages (512 x 2MiB) */
la s1, pagetable_l2
li t4, KERNENTRY
srli t4, t4, 21 /* Div by 2 MiB */
srli t4, s6, 21 /* Div physmem base by 2 MiB */
li t2, 512 /* Build 512 entries */
add t3, t4, t2
li t5, 0
@ -206,32 +189,13 @@ _start:
bltu t4, t3, 2b
/* Set page tables base register */
la s1, pagetable_l1
srli s1, s1, PAGE_SHIFT
csrw sptbr, s1
la s2, pagetable_l1
li t0, KERNBASE
sub s2, s2, t0
add s2, s2, s6
srli s2, s2, PAGE_SHIFT
csrw sptbr, s2
/* Page tables END */
/* Enter supervisor mode */
li s0, ((MSTATUS_VM_SV39 << MSTATUS_VM_SHIFT) | \
(MSTATUS_PRV_S << MSTATUS_MPP_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
mret
.Lmmu_on:
/* Initialize stack pointer */
la s3, initstack_end
mv sp, s3
@ -247,8 +211,10 @@ _start:
/* Fill riscv_bootparams */
addi sp, sp, -16
la t0, pagetable_l1
sd t0, 0(sp) /* kern_l1pt */
la t0, initstack_end
sd t0, 8(sp) /* kern_stack */
@ -260,19 +226,6 @@ _start:
initstack:
.space (PAGE_SIZE * KSTACK_PAGES)
initstack_end:
hardstack:
.space (HW_STACK_SIZE * MAXCPU)
hardstack_end:
.globl htif_ring
htif_ring:
.space (HTIF_RING_SIZE + 16)
htif_lock:
.space (8)
tohost:
.space (8)
fromhost:
.space (8)
ENTRY(sigcode)
mv a0, sp
@ -305,6 +258,14 @@ pagetable_l2:
.space PAGE_SIZE
pagetable_l2_devmap:
.space PAGE_SIZE
pagetable_l2_sbi:
.space PAGE_SIZE
pagetable_l3_sbi:
.space PAGE_SIZE
.globl memory_info
memory_info:
.space (24)
.globl init_pt_va
init_pt_va:
@ -321,7 +282,6 @@ END(mpentry)
* 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)
/*
@ -340,44 +300,12 @@ ENTRY(mpentry)
beqz t1, 1b
/* Set page tables base register */
la t0, pagetable_l1
srli t0, t0, PAGE_SHIFT
csrw sptbr, t0
/* Configure mstatus */
li s0, ((MSTATUS_VM_SV39 << MSTATUS_VM_SHIFT) | \
(MSTATUS_PRV_S << MSTATUS_MPP_SHIFT));
csrw mstatus, s0
/* Setup stack for machine mode exceptions */
la t0, hardstack_end
li t1, HW_STACK_SIZE
mulw t1, t1, a0
sub t0, t0, t1
csrw mscratch, t0
li t0, 0
csrw sscratch, t0
/*
* Enable machine-mode software interrupts
* so we can deliver IPI to this core.
*/
li t0, MIE_MSIE
csrs mie, t0
/*
* Exit from machine mode and go to
* the virtual address space.
*/
la t0, mp_virtdone
li s11, KERNBASE
add t0, t0, s11
csrw mepc, t0
mret
mp_virtdone:
/* We are now in virtual address space */
la s2, pagetable_l1
li t0, KERNBASE
sub s2, s2, t0
add s2, s2, s6
srli s2, s2, PAGE_SHIFT
csrw sptbr, s2
/* Setup stack pointer */
la t0, secondary_stacks
@ -388,5 +316,3 @@ mp_virtdone:
call init_secondary
END(mpentry)
#endif
#include "exception.S"

View File

@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$");
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <machine/intr.h>
#include <machine/sbi.h>
#include <machine/asm.h>
@ -116,6 +117,7 @@ int64_t idcache_line_size; /* The minimum cache line size */
extern int *end;
extern int *initstack_end;
extern memory_block_info memory_info;
struct pcpu *pcpup;
@ -728,12 +730,9 @@ fake_preload_metadata(struct riscv_bootparams *rvbp __unused)
void
initriscv(struct riscv_bootparams *rvbp)
{
struct mem_region mem_regions[FDT_MEM_REGIONS];
vm_offset_t lastaddr;
int mem_regions_sz;
vm_size_t kernlen;
caddr_t kmdp;
int i;
/* Set the module data location */
lastaddr = fake_preload_metadata(rvbp);
@ -755,12 +754,20 @@ initriscv(struct riscv_bootparams *rvbp)
/* Load the physical memory ranges */
physmap_idx = 0;
#if 0
struct mem_region mem_regions[FDT_MEM_REGIONS];
int mem_regions_sz;
int i;
/* Grab physical memory regions information from device tree. */
if (fdt_get_mem_regions(mem_regions, &mem_regions_sz, NULL) != 0)
panic("Cannot get physical memory regions");
for (i = 0; i < mem_regions_sz; i++)
add_physmap_entry(mem_regions[i].mr_start,
mem_regions[i].mr_size, physmap, &physmap_idx);
#endif
add_physmap_entry(memory_info.base, memory_info.size,
physmap, &physmap_idx);
/* Set the pcpu data, this is needed by pmap_bootstrap */
pcpup = &__pcpu[0];
@ -778,14 +785,15 @@ initriscv(struct riscv_bootparams *rvbp)
/* Bootstrap enough of pmap to enter the kernel proper */
kernlen = (lastaddr - KERNBASE);
pmap_bootstrap(rvbp->kern_l1pt, KERNENTRY, kernlen);
pmap_bootstrap(rvbp->kern_l1pt, memory_info.base, kernlen);
cninit();
init_proc0(rvbp->kern_stack);
/* set page table base register for thread0 */
thread0.td_pcb->pcb_l1addr = (rvbp->kern_l1pt - KERNBASE);
thread0.td_pcb->pcb_l1addr = \
(rvbp->kern_l1pt - KERNBASE + memory_info.base);
msgbufinit(msgbufp, msgbufsize);
mutex_init();

View File

@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/smp.h>
#include <machine/sbi.h>
#ifdef VFP
#include <machine/vfp.h>
#endif
@ -273,14 +274,7 @@ ipi_handler(void *arg)
u_int cpu, ipi;
int bit;
/*
* We have shared interrupt line for both IPI and HTIF,
* so we don't really need to clear pending bit here
* as it will be cleared later in htif_intr.
* But lets assume HTIF is optional part, so do clear
* pending bit if there is no new entires in htif_ring.
*/
machine_command(ECALL_CLEAR_IPI, 0);
sbi_clear_ipi();
cpu = PCPU_GET(cpuid);
@ -382,12 +376,10 @@ cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
/* We are already running on cpu 0 */
if (id == 0) {
pcpup->pc_reg = target_cpu;
return (1);
}
pcpu_init(pcpup, id, sizeof(struct pcpu));
pcpup->pc_reg = target_cpu;
dpcpu[id - 1] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE,
M_WAITOK | M_ZERO);

View File

@ -220,6 +220,14 @@ vm_offset_t kernel_vm_end = 0;
struct msgbuf *msgbufp = NULL;
vm_paddr_t dmap_phys_base; /* The start of the dmap region */
vm_paddr_t dmap_phys_max; /* The limit of the dmap region */
vm_offset_t dmap_max_addr; /* The virtual address limit of the dmap */
/* This code assumes all L1 DMAP entries will be used */
CTASSERT((DMAP_MIN_ADDRESS & ~L1_OFFSET) == DMAP_MIN_ADDRESS);
CTASSERT((DMAP_MAX_ADDRESS & ~L1_OFFSET) == DMAP_MAX_ADDRESS);
static struct rwlock_padalign pvh_global_lock;
/*
@ -458,6 +466,10 @@ pmap_early_vtophys(vm_offset_t l1pt, vm_offset_t va)
l2 = pmap_early_page_idx(l1pt, va, &l1_slot, &l2_slot);
/* Check locore has used L2 superpages */
KASSERT((l2[l2_slot] & PTE_RX) != 0,
("Invalid bootstrap L2 table"));
/* L2 is superpages */
ret = (l2[l2_slot] >> PTE_PPN1_S) << L2_SHIFT;
ret += (va & L2_OFFSET);
@ -466,7 +478,7 @@ pmap_early_vtophys(vm_offset_t l1pt, vm_offset_t va)
}
static void
pmap_bootstrap_dmap(vm_offset_t l1pt, vm_paddr_t kernstart)
pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa, vm_paddr_t max_pa)
{
vm_offset_t va;
vm_paddr_t pa;
@ -475,19 +487,12 @@ pmap_bootstrap_dmap(vm_offset_t l1pt, vm_paddr_t kernstart)
pt_entry_t entry;
pn_t pn;
/*
* Initialize DMAP starting from zero physical address.
* TODO: remove this once machine-mode code splitted out.
*/
kernstart = 0;
printf("%s: l1pt 0x%016lx kernstart 0x%016lx\n", __func__, l1pt, kernstart);
pa = kernstart & ~L1_OFFSET;
pa = dmap_phys_base = min_pa & ~L1_OFFSET;
va = DMAP_MIN_ADDRESS;
l1 = (pd_entry_t *)l1pt;
l1 = (pd_entry_t *)kern_l1;
l1_slot = pmap_l1_index(DMAP_MIN_ADDRESS);
for (; va < DMAP_MAX_ADDRESS;
for (; va < DMAP_MAX_ADDRESS && pa < max_pa;
pa += L1_SIZE, va += L1_SIZE, l1_slot++) {
KASSERT(l1_slot < Ln_ENTRIES, ("Invalid L1 index"));
@ -498,6 +503,10 @@ pmap_bootstrap_dmap(vm_offset_t l1pt, vm_paddr_t kernstart)
pmap_load_store(&l1[l1_slot], entry);
}
/* Set the upper limit of the DMAP region */
dmap_phys_max = pa;
dmap_max_addr = va;
cpu_dcache_wb_range((vm_offset_t)l1, PAGE_SIZE);
cpu_tlb_flushID();
}
@ -552,7 +561,7 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
pt_entry_t *l2;
vm_offset_t va, freemempos;
vm_offset_t dpcpu, msgbufpv;
vm_paddr_t pa, min_pa;
vm_paddr_t pa, min_pa, max_pa;
int i;
kern_delta = KERNBASE - kernstart;
@ -574,7 +583,7 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
LIST_INIT(&allpmaps);
/* Assume the address we were loaded to is a valid physical address */
min_pa = KERNBASE - kern_delta;
min_pa = max_pa = KERNBASE - kern_delta;
/*
* Find the minimum physical address. physmap is sorted,
@ -585,11 +594,13 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
continue;
if (physmap[i] <= min_pa)
min_pa = physmap[i];
if (physmap[i + 1] > max_pa)
max_pa = physmap[i + 1];
break;
}
/* Create a direct map region early so we can use it for pa -> va */
pmap_bootstrap_dmap(l1pt, min_pa);
pmap_bootstrap_dmap(l1pt, min_pa, max_pa);
va = KERNBASE;
pa = KERNBASE - kern_delta;

View File

@ -47,16 +47,41 @@ __FBSDID("$FreeBSD$");
#include <sys/tty.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <machine/trap.h>
#include "htif.h"
#include <sys/rman.h>
#include <dev/ofw/openfirm.h>
#include <ddb/ddb.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <machine/asm.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <machine/sbi.h>
static struct resource_spec rcons_spec[] = {
{ SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE},
{ -1, 0 }
};
/* bus softc */
struct rcons_softc {
struct resource *res[1];
void *ihl[1];
device_t dev;
};
/* CN Console interface */
static tsw_outwakeup_t riscvtty_outwakeup;
static struct ttydevsw riscv_ttydevsw = {
@ -86,8 +111,6 @@ 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;
@ -102,13 +125,8 @@ struct queue_entry *entry_served;
static void
riscv_putc(int c)
{
uint64_t cmd;
cmd = (HTIF_CMD_WRITE << HTIF_CMD_SHIFT);
cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
cmd |= c;
machine_command(ECALL_HTIF_CMD, cmd);
sbi_console_putchar(c);
}
#ifdef EARLY_PRINTF
@ -215,39 +233,23 @@ riscv_cnungrab(struct consdev *cp)
static int
riscv_cngetc(struct consdev *cp)
{
#if defined(KDB)
uint64_t devcmd;
uint64_t entry;
uint64_t devid;
#endif
uint64_t cmd;
uint8_t data;
int ch;
cmd = (HTIF_CMD_READ << HTIF_CMD_SHIFT);
cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
machine_command(ECALL_HTIF_CMD_REQ, cmd);
#if defined(KDB)
/*
* RISCVTODO: BBL polls for console data on timer interrupt,
* but interrupts are turned off in KDB.
* So we currently do not have console in KDB.
*/
if (kdb_active) {
ch = sbi_console_getchar();
while (ch) {
entry_last->data = ch;
entry_last->used = 1;
entry_last = entry_last->next;
entry = machine_command(ECALL_HTIF_CMD_RESP, 0);
while (entry) {
devid = HTIF_DEV_ID(entry);
devcmd = HTIF_DEV_CMD(entry);
data = HTIF_DEV_DATA(entry);
if (devid == CONSOLE_DEFAULT_ID && devcmd == 0) {
entry_last->data = data;
entry_last->used = 1;
entry_last = entry_last->next;
} else {
printf("Lost interrupt: devid %d\n",
devid);
}
entry = machine_command(ECALL_HTIF_CMD_RESP, 0);
ch = sbi_console_getchar();
}
}
#endif
@ -275,75 +277,83 @@ riscv_cnputc(struct consdev *cp, int c)
riscv_putc(c);
}
/*
* Bus interface.
*/
/* Bus interface */
struct htif_console_softc {
device_t dev;
int running;
int intr_chan;
int cmd_done;
int curtag;
int index;
};
static void
htif_console_intr(void *arg, uint64_t entry)
static int
rcons_intr(void *arg)
{
struct htif_console_softc *sc;
uint8_t devcmd;
uint64_t data;
int c;
sc = arg;
devcmd = HTIF_DEV_CMD(entry);
data = HTIF_DEV_DATA(entry);
if (devcmd == 0) {
entry_last->data = data;
c = sbi_console_getchar();
if (c > 0 && c < 0xff) {
entry_last->data = c;
entry_last->used = 1;
entry_last = entry_last->next;
}
csr_clear(sip, SIP_SSIP);
return (FILTER_HANDLED);
}
static int
htif_console_probe(device_t dev)
rcons_probe(device_t dev)
{
return (0);
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "riscv,console"))
return (ENXIO);
device_set_desc(dev, "RISC-V console");
return (BUS_PROBE_DEFAULT);
}
static int
htif_console_attach(device_t dev)
rcons_attach(device_t dev)
{
struct htif_console_softc *sc;
struct rcons_softc *sc;
int error;
sc = device_get_softc(dev);
sc->dev = dev;
sc->index = htif_get_index(dev);
if (sc->index < 0)
return (EINVAL);
if (bus_alloc_resources(dev, rcons_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
htif_setup_intr(sc->index, htif_console_intr, sc);
/* Setup IRQs handler */
error = bus_setup_intr(dev, sc->res[0], INTR_TYPE_CLK,
rcons_intr, NULL, sc, &sc->ihl[0]);
if (error) {
device_printf(dev, "Unable to alloc int resource.\n");
return (ENXIO);
}
csr_set(sie, SIE_SSIE);
bus_generic_attach(sc->dev);
sbi_console_getchar();
return (0);
}
static device_method_t htif_console_methods[] = {
DEVMETHOD(device_probe, htif_console_probe),
DEVMETHOD(device_attach, htif_console_attach),
static device_method_t rcons_methods[] = {
DEVMETHOD(device_probe, rcons_probe),
DEVMETHOD(device_attach, rcons_attach),
DEVMETHOD_END
};
static driver_t htif_console_driver = {
"htif_console",
htif_console_methods,
sizeof(struct htif_console_softc)
static driver_t rcons_driver = {
"rcons",
rcons_methods,
sizeof(struct rcons_softc)
};
static devclass_t htif_console_devclass;
static devclass_t rcons_devclass;
DRIVER_MODULE(htif_console, htif, htif_console_driver,
htif_console_devclass, 0, 0);
DRIVER_MODULE(rcons, simplebus, rcons_driver, rcons_devclass, 0, 0);

52
sys/riscv/riscv/sbi.S Normal file
View File

@ -0,0 +1,52 @@
/*-
* Copyright (c) 2016 Ruslan Bukin <br@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.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
.globl sbi_hart_id; sbi_hart_id = -2048
.globl sbi_num_harts; sbi_num_harts = -2032
.globl sbi_query_memory; sbi_query_memory = -2016
.globl sbi_console_putchar; sbi_console_putchar = -2000
.globl sbi_console_getchar; sbi_console_getchar = -1984
.globl sbi_send_ipi; sbi_send_ipi = -1952
.globl sbi_clear_ipi; sbi_clear_ipi = -1936
.globl sbi_timebase; sbi_timebase = -1920
.globl sbi_shutdown; sbi_shutdown = -1904
.globl sbi_set_timer; sbi_set_timer = -1888
.globl sbi_mask_interrupt; sbi_mask_interrupt = -1872
.globl sbi_unmask_interrupt; sbi_unmask_interrupt = -1856
.globl sbi_remote_sfence_vm; sbi_remote_sfence_vm = -1840
.globl sbi_remote_sfence_vm_range; sbi_remote_sfence_vm_range = -1824
.globl sbi_remote_fence_i; sbi_remote_fence_i = -1808

View File

@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/asm.h>
#include <machine/trap.h>
#include <machine/sbi.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
@ -135,7 +136,7 @@ riscv_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
cpu = PCPU_GET(cpuid);
WRITE8(sc, TIMER_MTIMECMP(cpu), counts);
csr_set(sie, SIE_STIE);
machine_command(ECALL_MTIMECMP, counts);
sbi_set_timer(counts);
return (0);
}

View File

@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/pcb.h>
#include <machine/frame.h>
#include <machine/sbi.h>
/*
* Finish a fork operation, with process p2 nearly set up.
@ -106,9 +107,9 @@ void
cpu_reset(void)
{
printf("cpu_reset");
while(1)
__asm volatile("wfi" ::: "memory");
sbi_shutdown();
while(1);
}
void