Update RISC-V port to Privileged Architecture Version 1.9.
Sponsored by: DARPA, AFRL Sponsored by: HEIF5
This commit is contained in:
parent
a937127683
commit
1167f0cf7c
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by SRI International and the
|
||||
@ -37,8 +37,8 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
model = "UC Berkeley Spike Simulator RV64I";
|
||||
compatible = "riscv,rv64i";
|
||||
model = "UC Berkeley Spike Simulator RV64";
|
||||
compatible = "riscv,rv64";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <1>;
|
||||
@ -49,14 +49,14 @@
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "riscv,rv64i";
|
||||
reg = <0x40002000>;
|
||||
compatible = "riscv,rv64";
|
||||
reg = <0x40001000>;
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
device_type = "cpu";
|
||||
compatible = "riscv,rv64i";
|
||||
reg = <0x4000a000>;
|
||||
compatible = "riscv,rv64";
|
||||
reg = <0x40002000>;
|
||||
};
|
||||
};
|
||||
|
||||
@ -66,12 +66,12 @@
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x40000000>; /* 1GB at 0x0 */
|
||||
reg = <0x80000000 0x40000000>; /* 1GB at 0x80000000 */
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
compatible = "simple-bus";
|
||||
@ -84,14 +84,15 @@
|
||||
|
||||
timer0: timer@0 {
|
||||
compatible = "riscv,timer";
|
||||
interrupts = < 1 >;
|
||||
reg = < 0x40000000 0x100 >;
|
||||
interrupts = < 5 >;
|
||||
interrupt-parent = < &pic0 >;
|
||||
clock-frequency = < 1000000 >;
|
||||
};
|
||||
|
||||
htif0: htif@0 {
|
||||
compatible = "riscv,htif";
|
||||
interrupts = < 0 >;
|
||||
interrupts = < 1 >;
|
||||
interrupt-parent = < &pic0 >;
|
||||
|
||||
console0: console@0 {
|
||||
|
@ -2498,8 +2498,8 @@ extern void dtrace_helpers_destroy(proc_t *);
|
||||
|
||||
#elif defined(__riscv__)
|
||||
|
||||
#define SD_RA_SP_MASK 0x1fff07f
|
||||
#define SD_RA_SP 0x0113023
|
||||
#define SD_RA_SP_MASK 0x01fff07f
|
||||
#define SD_RA_SP 0x00113023
|
||||
|
||||
#define DTRACE_INVOP_SD 1
|
||||
#define DTRACE_INVOP_RET 2
|
||||
|
@ -57,8 +57,8 @@ END(dtrace_membar_consumer)
|
||||
dtrace_icookie_t dtrace_interrupt_disable(void)
|
||||
*/
|
||||
ENTRY(dtrace_interrupt_disable)
|
||||
csrrci a0, sstatus, SSTATUS_IE
|
||||
andi a0, a0, SSTATUS_IE
|
||||
csrrci a0, sstatus, (SSTATUS_SIE)
|
||||
andi a0, a0, (SSTATUS_SIE)
|
||||
RET
|
||||
END(dtrace_interrupt_disable)
|
||||
|
||||
|
@ -203,9 +203,9 @@ dtrace_trap(struct trapframe *frame, u_int type)
|
||||
* All the rest will be handled in the usual way.
|
||||
*/
|
||||
switch (type) {
|
||||
case EXCP_LOAD_ACCESS_FAULT:
|
||||
case EXCP_STORE_ACCESS_FAULT:
|
||||
case EXCP_INSTR_ACCESS_FAULT:
|
||||
case EXCP_FAULT_LOAD:
|
||||
case EXCP_FAULT_STORE:
|
||||
case EXCP_FAULT_FETCH:
|
||||
/* Flag a bad address. */
|
||||
cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR;
|
||||
cpu_core[curcpu].cpuc_dtrace_illval = 0;
|
||||
|
@ -6,7 +6,7 @@ SEARCH_DIR(/usr/lib);
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = kernbase + 0x100;
|
||||
. = kernbase + 0x80000000 /* KERNENTRY */;
|
||||
.text : AT(ADDR(.text) - kernbase)
|
||||
{
|
||||
*(.text)
|
||||
|
@ -26,6 +26,7 @@ makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
|
||||
|
||||
# FIXME: linker error. "--relax and -r may not be used together"
|
||||
makeoptions WITHOUT_MODULES="usb otusfw mwlfw ispfw mwlfw ralfw rtwnfw urtwnfw"
|
||||
# makeoptions NO_MODULES
|
||||
|
||||
options SCHED_ULE # ULE scheduler
|
||||
options PREEMPTION # Enable kernel thread preemption
|
||||
@ -40,7 +41,6 @@ options UFS_ACL # Support for access control lists
|
||||
options UFS_DIRHASH # Improve performance on big directories
|
||||
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
|
||||
options QUOTA # Enable disk quotas for UFS
|
||||
options MD_ROOT # MD is a potential root device
|
||||
options NFSCL # Network Filesystem Client
|
||||
options NFSD # Network Filesystem Server
|
||||
options NFSLOCKD # Network Lock Manager
|
||||
@ -93,6 +93,7 @@ options INVARIANT_SUPPORT # Extra sanity checks of internal structures, require
|
||||
# options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
|
||||
options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
|
||||
# options EARLY_PRINTF
|
||||
# options VERBOSE_SYSINIT
|
||||
|
||||
# Pseudo devices.
|
||||
device loop # Network loopback
|
||||
|
@ -177,11 +177,6 @@ htif_enumerate(struct htif_softc *sc)
|
||||
|
||||
htif_command(cmd);
|
||||
|
||||
/* Do poll as interrupts are disabled yet */
|
||||
while (sc->identify_done == 0) {
|
||||
htif_handle_entry(sc);
|
||||
}
|
||||
|
||||
len = strnlen(id, sizeof(id));
|
||||
if (len <= 0)
|
||||
break;
|
||||
|
@ -202,6 +202,7 @@ htif_blk_task(void *arg)
|
||||
uint64_t req_paddr;
|
||||
struct bio *bp;
|
||||
uint64_t paddr;
|
||||
uint64_t resp;
|
||||
uint64_t cmd;
|
||||
int i;
|
||||
|
||||
@ -239,7 +240,8 @@ htif_blk_task(void *arg)
|
||||
cmd |= req_paddr;
|
||||
|
||||
sc->cmd_done = 0;
|
||||
htif_command(cmd);
|
||||
resp = htif_command(cmd);
|
||||
htif_blk_intr(sc, resp);
|
||||
|
||||
/* Wait for interrupt */
|
||||
i = 0;
|
||||
|
@ -57,8 +57,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <ddb/ddb.h>
|
||||
|
||||
extern uint64_t console_intr;
|
||||
|
||||
static tsw_outwakeup_t riscvtty_outwakeup;
|
||||
|
||||
static struct ttydevsw riscv_ttydevsw = {
|
||||
@ -102,7 +100,7 @@ struct queue_entry *entry_last;
|
||||
struct queue_entry *entry_served;
|
||||
|
||||
static void
|
||||
htif_putc(int c)
|
||||
riscv_putc(int c)
|
||||
{
|
||||
uint64_t cmd;
|
||||
|
||||
@ -110,57 +108,7 @@ 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
|
||||
htif_getc(void)
|
||||
{
|
||||
uint64_t cmd;
|
||||
uint8_t res;
|
||||
|
||||
cmd = (HTIF_CMD_READ << HTIF_CMD_SHIFT);
|
||||
cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
|
||||
|
||||
res = htif_command(cmd);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
static void
|
||||
riscv_putc(int c)
|
||||
{
|
||||
uint64_t counter;
|
||||
uint64_t *cc;
|
||||
uint64_t val;
|
||||
|
||||
val = 0;
|
||||
counter = 0;
|
||||
|
||||
cc = (uint64_t*)&console_intr;
|
||||
*cc = 0;
|
||||
|
||||
htif_putc(c);
|
||||
|
||||
#ifndef SPIN_IN_MACHINE_MODE
|
||||
/* Wait for an interrupt */
|
||||
__asm __volatile(
|
||||
"li %0, 1\n" /* counter = 1 */
|
||||
"slli %0, %0, 12\n" /* counter <<= 12 */
|
||||
"1:"
|
||||
"addi %0, %0, -1\n" /* counter -= 1 */
|
||||
"beqz %0, 2f\n" /* counter == 0 ? finish */
|
||||
"ld %1, 0(%2)\n" /* val = *cc */
|
||||
"beqz %1, 1b\n" /* val == 0 ? repeat */
|
||||
"2:"
|
||||
: "=&r"(counter), "=&r"(val) : "r"(cc)
|
||||
);
|
||||
#endif
|
||||
machine_command(ECALL_HTIF_CMD, cmd);
|
||||
}
|
||||
|
||||
#ifdef EARLY_PRINTF
|
||||
@ -272,14 +220,19 @@ riscv_cngetc(struct consdev *cp)
|
||||
uint64_t entry;
|
||||
uint64_t devid;
|
||||
#endif
|
||||
uint64_t cmd;
|
||||
uint8_t data;
|
||||
int ch;
|
||||
|
||||
htif_getc();
|
||||
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)
|
||||
if (kdb_active) {
|
||||
entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
|
||||
|
||||
entry = machine_command(ECALL_HTIF_CMD_RESP, 0);
|
||||
while (entry) {
|
||||
devid = HTIF_DEV_ID(entry);
|
||||
devcmd = HTIF_DEV_CMD(entry);
|
||||
@ -294,7 +247,7 @@ riscv_cngetc(struct consdev *cp)
|
||||
devid);
|
||||
}
|
||||
|
||||
entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
|
||||
entry = machine_command(ECALL_HTIF_CMD_RESP, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by SRI International and the
|
||||
@ -67,11 +67,10 @@
|
||||
|
||||
#define CPU_PART_SHIFT 62
|
||||
#define CPU_PART_MASK (0x3ul << CPU_PART_SHIFT)
|
||||
#define CPU_PART(mcpuid) ((mcpuid & CPU_PART_MASK) >> CPU_PART_SHIFT)
|
||||
#define CPU_PART_RV32I 0x0
|
||||
#define CPU_PART_RV32E 0x1
|
||||
#define CPU_PART_RV64I 0x2
|
||||
#define CPU_PART_RV128I 0x3
|
||||
#define CPU_PART(misa) ((misa & CPU_PART_MASK) >> CPU_PART_SHIFT)
|
||||
#define CPU_PART_RV32 0x1
|
||||
#define CPU_PART_RV64 0x2
|
||||
#define CPU_PART_RV128 0x3
|
||||
|
||||
extern char btext[];
|
||||
extern char etext[];
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by SRI International and the
|
||||
@ -54,11 +54,11 @@ intr_disable(void)
|
||||
uint64_t ret;
|
||||
|
||||
__asm __volatile(
|
||||
"csrrci %0, sstatus, 1"
|
||||
: "=&r" (ret)
|
||||
"csrrci %0, sstatus, %1"
|
||||
: "=&r" (ret) : "i" (SSTATUS_SIE)
|
||||
);
|
||||
|
||||
return (ret & SSTATUS_IE);
|
||||
return (ret & (SSTATUS_SIE));
|
||||
}
|
||||
|
||||
static __inline void
|
||||
@ -76,7 +76,8 @@ intr_enable(void)
|
||||
{
|
||||
|
||||
__asm __volatile(
|
||||
"csrsi sstatus, 1"
|
||||
"csrsi sstatus, %0"
|
||||
:: "i" (SSTATUS_SIE)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <machine/frame.h>
|
||||
#include <machine/trap.h>
|
||||
|
||||
#define T_BREAKPOINT (EXCP_INSTR_BREAKPOINT)
|
||||
#define T_BREAKPOINT (EXCP_BREAKPOINT)
|
||||
#define T_WATCHPOINT (0)
|
||||
|
||||
typedef vm_offset_t db_addr_t;
|
||||
|
@ -57,11 +57,23 @@ void riscv_unmask_ipi(void);
|
||||
#endif
|
||||
|
||||
enum {
|
||||
IRQ_SOFTWARE,
|
||||
IRQ_TIMER,
|
||||
IRQ_HTIF,
|
||||
IRQ_SOFTWARE_USER,
|
||||
IRQ_SOFTWARE_SUPERVISOR,
|
||||
IRQ_SOFTWARE_HYPERVISOR,
|
||||
IRQ_SOFTWARE_MACHINE,
|
||||
IRQ_TIMER_USER,
|
||||
IRQ_TIMER_SUPERVISOR,
|
||||
IRQ_TIMER_HYPERVISOR,
|
||||
IRQ_TIMER_MACHINE,
|
||||
IRQ_EXTERNAL_USER,
|
||||
IRQ_EXTERNAL_SUPERVISOR,
|
||||
IRQ_EXTERNAL_HYPERVISOR,
|
||||
IRQ_EXTERNAL_MACHINE,
|
||||
#if 0
|
||||
/* lowRISC TODO */
|
||||
IRQ_COP, /* lowRISC only */
|
||||
IRQ_UART, /* lowRISC only */
|
||||
#endif
|
||||
NIRQS
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Andrew Turner
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by SRI International and the
|
||||
@ -66,29 +66,18 @@ typedef uint64_t pn_t; /* page number */
|
||||
#define Ln_ADDR_MASK (Ln_ENTRIES - 1)
|
||||
|
||||
/* Bits 9:7 are reserved for software */
|
||||
#define PTE_SW_MANAGED (1 << 8)
|
||||
#define PTE_SW_WIRED (1 << 7)
|
||||
#define PTE_DIRTY (1 << 6) /* Virtual page is written */
|
||||
#define PTE_REF (1 << 5) /* Virtual page is referenced */
|
||||
#define PTE_VALID (1 << 0) /* Virtual page is valid */
|
||||
#define PTE_TYPE_S 1
|
||||
#define PTE_TYPE_M (0xf << PTE_TYPE_S)
|
||||
#define PTE_TYPE_PTR 0
|
||||
#define PTE_TYPE_PTR_G 1
|
||||
#define PTE_TYPE_SROURX 2 /* Supervisor read-only, user read-execute page. */
|
||||
#define PTE_TYPE_SRWURWX 3 /* Supervisor read-write, user read-write-execute page. */
|
||||
#define PTE_TYPE_SURO 4 /* Supervisor and user read-only page. */
|
||||
#define PTE_TYPE_SURW 5 /* Supervisor and user read-write page. */
|
||||
#define PTE_TYPE_SURX 6 /* Supervisor and user read-execute page. */
|
||||
#define PTE_TYPE_SURWX 7 /* Supervisor and User Read Write Execute */
|
||||
#define PTE_TYPE_SRO 8 /* Supervisor read-only page. */
|
||||
#define PTE_TYPE_SRW 9 /* Supervisor read-write page. */
|
||||
#define PTE_TYPE_SRX 10 /* Supervisor read-execute page. */
|
||||
#define PTE_TYPE_SRWX 11 /* Supervisor read-write-execute page. */
|
||||
#define PTE_TYPE_SRO_G 12 /* Supervisor read-only page--global mapping. */
|
||||
#define PTE_TYPE_SRW_G 13 /* Supervisor read-write page--global mapping. */
|
||||
#define PTE_TYPE_SRX_G 14 /* Supervisor read-execute page--global mapping. */
|
||||
#define PTE_TYPE_SRWX_G 15 /* Supervisor Read Write Execute Global */
|
||||
#define PTE_SW_MANAGED (1 << 9)
|
||||
#define PTE_SW_WIRED (1 << 8)
|
||||
#define PTE_D (1 << 7) /* Dirty */
|
||||
#define PTE_A (1 << 6) /* Accessed */
|
||||
#define PTE_G (1 << 5) /* Global */
|
||||
#define PTE_U (1 << 4) /* User */
|
||||
#define PTE_X (1 << 3) /* Execute */
|
||||
#define PTE_W (1 << 2) /* Write */
|
||||
#define PTE_R (1 << 1) /* Read */
|
||||
#define PTE_V (1 << 0) /* Valid */
|
||||
#define PTE_RWX (PTE_R | PTE_W | PTE_X)
|
||||
#define PTE_RX (PTE_R | PTE_X)
|
||||
|
||||
#define PTE_PPN0_S 10
|
||||
#define PTE_PPN1_S 19
|
||||
|
@ -39,88 +39,127 @@
|
||||
|
||||
/* Machine mode requests */
|
||||
#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 0x0a
|
||||
#define ECALL_IO_IRQ_MASK 0x0b
|
||||
#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_INSTR_ADDR_MISALIGNED 0
|
||||
#define EXCP_INSTR_ACCESS_FAULT 1
|
||||
#define EXCP_INSTR_ILLEGAL 2
|
||||
#define EXCP_INSTR_BREAKPOINT 3
|
||||
#define EXCP_LOAD_ADDR_MISALIGNED 4
|
||||
#define EXCP_LOAD_ACCESS_FAULT 5
|
||||
#define EXCP_STORE_ADDR_MISALIGNED 6
|
||||
#define EXCP_STORE_ACCESS_FAULT 7
|
||||
#define EXCP_UMODE_ENV_CALL 8
|
||||
#define EXCP_SMODE_ENV_CALL 9
|
||||
#define EXCP_HMODE_ENV_CALL 10
|
||||
#define EXCP_MMODE_ENV_CALL 11
|
||||
#define EXCP_INTR (1 << 31)
|
||||
#define EXCP_MISALIGNED_FETCH 0
|
||||
#define EXCP_FAULT_FETCH 1
|
||||
#define EXCP_ILLEGAL_INSTRUCTION 2
|
||||
#define EXCP_BREAKPOINT 3
|
||||
#define EXCP_MISALIGNED_LOAD 4
|
||||
#define EXCP_FAULT_LOAD 5
|
||||
#define EXCP_MISALIGNED_STORE 6
|
||||
#define EXCP_FAULT_STORE 7
|
||||
#define EXCP_USER_ECALL 8
|
||||
#define EXCP_SUPERVISOR_ECALL 9
|
||||
#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_IE (1 << 0)
|
||||
#define SSTATUS_PIE (1 << 3)
|
||||
#define SSTATUS_PS (1 << 4)
|
||||
#define SSTATUS_UIE (1 << 0)
|
||||
#define SSTATUS_SIE (1 << 1)
|
||||
#define SSTATUS_UPIE (1 << 4)
|
||||
#define SSTATUS_SPIE (1 << 5)
|
||||
#define SSTATUS_SPIE_SHIFT 5
|
||||
#define SSTATUS_SPP (1 << 8)
|
||||
#define SSTATUS_SPP_SHIFT 8
|
||||
#define SSTATUS_FS_MASK 0x3
|
||||
#define SSTATUS_FS_SHIFT 13
|
||||
#define SSTATUS_XS_MASK 0x3
|
||||
#define SSTATUS_XS_SHIFT 15
|
||||
#define SSTATUS_PUM (1 << 18)
|
||||
#define SSTATUS32_SD (1 << 63)
|
||||
#define SSTATUS64_SD (1 << 31)
|
||||
|
||||
#define MSTATUS_MPRV (1 << 16)
|
||||
#define MSTATUS_PRV_SHIFT 1
|
||||
#define MSTATUS_PRV1_SHIFT 4
|
||||
#define MSTATUS_PRV2_SHIFT 7
|
||||
#define MSTATUS_PRV_MASK (0x3 << MSTATUS_PRV_SHIFT)
|
||||
#define MSTATUS_PRV_U 0 /* user */
|
||||
#define MSTATUS_PRV_S 1 /* supervisor */
|
||||
#define MSTATUS_PRV_H 2 /* hypervisor */
|
||||
#define MSTATUS_PRV_M 3 /* machine */
|
||||
#define MSTATUS_UIE (1 << 0)
|
||||
#define MSTATUS_SIE (1 << 1)
|
||||
#define MSTATUS_HIE (1 << 2)
|
||||
#define MSTATUS_MIE (1 << 3)
|
||||
#define MSTATUS_UPIE (1 << 4)
|
||||
#define MSTATUS_SPIE (1 << 5)
|
||||
#define MSTATUS_SPIE_SHIFT 5
|
||||
#define MSTATUS_HPIE (1 << 6)
|
||||
#define MSTATUS_MPIE (1 << 7)
|
||||
#define MSTATUS_MPIE_SHIFT 7
|
||||
#define MSTATUS_SPP (1 << 8)
|
||||
#define MSTATUS_SPP_SHIFT 8
|
||||
#define MSTATUS_HPP_MASK 0x3
|
||||
#define MSTATUS_HPP_SHIFT 9
|
||||
#define MSTATUS_MPP_MASK 0x3
|
||||
#define MSTATUS_MPP_SHIFT 11
|
||||
#define MSTATUS_FS_MASK 0x3
|
||||
#define MSTATUS_FS_SHIFT 13
|
||||
#define MSTATUS_XS_MASK 0x3
|
||||
#define MSTATUS_XS_SHIFT 15
|
||||
#define MSTATUS_MPRV (1 << 17)
|
||||
#define MSTATUS_PUM (1 << 18)
|
||||
#define MSTATUS_VM_MASK 0x1f
|
||||
#define MSTATUS_VM_SHIFT 24
|
||||
#define MSTATUS_VM_MBARE 0
|
||||
#define MSTATUS_VM_MBB 1
|
||||
#define MSTATUS_VM_MBBID 2
|
||||
#define MSTATUS_VM_SV32 8
|
||||
#define MSTATUS_VM_SV39 9
|
||||
#define MSTATUS_VM_SV48 10
|
||||
#define MSTATUS_VM_SV57 11
|
||||
#define MSTATUS_VM_SV64 12
|
||||
#define MSTATUS32_SD (1 << 63)
|
||||
#define MSTATUS64_SD (1 << 31)
|
||||
|
||||
#define MSTATUS_VM_SHIFT 17
|
||||
#define MSTATUS_VM_MASK 0x1f
|
||||
#define MSTATUS_VM_MBARE 0
|
||||
#define MSTATUS_VM_MBB 1
|
||||
#define MSTATUS_VM_MBBID 2
|
||||
#define MSTATUS_VM_SV32 8
|
||||
#define MSTATUS_VM_SV39 9
|
||||
#define MSTATUS_VM_SV48 10
|
||||
#define MSTATUS_PRV_U 0 /* user */
|
||||
#define MSTATUS_PRV_S 1 /* supervisor */
|
||||
#define MSTATUS_PRV_H 2 /* hypervisor */
|
||||
#define MSTATUS_PRV_M 3 /* machine */
|
||||
|
||||
#define MIE_USIE (1 << 0)
|
||||
#define MIE_SSIE (1 << 1)
|
||||
#define MIE_HSIE (1 << 2)
|
||||
#define MIE_MSIE (1 << 3)
|
||||
#define MIE_UTIE (1 << 4)
|
||||
#define MIE_STIE (1 << 5)
|
||||
#define MIE_HTIE (1 << 6)
|
||||
#define MIE_MTIE (1 << 7)
|
||||
|
||||
#define MIP_USIP (1 << 0)
|
||||
#define MIP_SSIP (1 << 1)
|
||||
#define MIP_HSIP (1 << 2)
|
||||
#define MIP_MSIP (1 << 3)
|
||||
#define MIP_UTIP (1 << 4)
|
||||
#define MIP_STIP (1 << 5)
|
||||
#define MIP_HTIP (1 << 6)
|
||||
#define MIP_MTIP (1 << 7)
|
||||
|
||||
#define SR_IE (1 << 0)
|
||||
#define SR_IE1 (1 << 3)
|
||||
#define SR_IE2 (1 << 6)
|
||||
#define SR_IE3 (1 << 9)
|
||||
|
||||
#define SIE_USIE (1 << 0)
|
||||
#define SIE_SSIE (1 << 1)
|
||||
#define SIE_UTIE (1 << 4)
|
||||
#define SIE_STIE (1 << 5)
|
||||
|
||||
#define MIP_SEIP (1 << 9)
|
||||
|
||||
/* Note: sip register has no SIP_STIP bit in Spike simulator */
|
||||
#define SIP_SSIP (1 << 1)
|
||||
#define SIP_STIP (1 << 5)
|
||||
|
||||
#if 0
|
||||
/* lowRISC TODO */
|
||||
#define NCSRS 4096
|
||||
#define CSR_IPI 0x783
|
||||
#define CSR_IO_IRQ 0x7c0 /* lowRISC only? */
|
||||
#endif
|
||||
|
||||
#define XLEN 8
|
||||
#define INSN_SIZE 4
|
||||
|
||||
|
@ -196,7 +196,7 @@
|
||||
#define SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE)
|
||||
#define USRSTACK SHAREDPAGE
|
||||
|
||||
#define KERNENTRY (0x200)
|
||||
#define KERNENTRY (0x80000000)
|
||||
|
||||
/*
|
||||
* How many physical pages per kmem arena virtual page.
|
||||
|
@ -117,14 +117,15 @@ __FBSDID("$FreeBSD$");
|
||||
ld t0, (TF_SSTATUS)(sp)
|
||||
.if \el == 0
|
||||
/* Ensure user interrupts will be enabled on eret. */
|
||||
ori t0, t0, SSTATUS_PIE
|
||||
li t1, SSTATUS_SPIE
|
||||
or t0, t0, t1
|
||||
.else
|
||||
/*
|
||||
* Disable interrupts for supervisor mode exceptions.
|
||||
* For user mode exceptions we have already done this
|
||||
* in do_ast.
|
||||
*/
|
||||
li t1, ~SSTATUS_IE
|
||||
li t1, ~SSTATUS_SIE
|
||||
and t0, t0, t1
|
||||
.endif
|
||||
csrw sstatus, t0
|
||||
@ -182,7 +183,7 @@ __FBSDID("$FreeBSD$");
|
||||
/* Disable interrupts */
|
||||
csrr a4, sstatus
|
||||
1:
|
||||
csrci sstatus, SSTATUS_IE
|
||||
csrci sstatus, (SSTATUS_SIE)
|
||||
|
||||
ld a1, PC_CURTHREAD(gp)
|
||||
lw a2, TD_FLAGS(a1)
|
||||
@ -192,7 +193,7 @@ __FBSDID("$FreeBSD$");
|
||||
beqz a2, 2f
|
||||
|
||||
/* Restore interrupts */
|
||||
andi a4, a4, SSTATUS_IE
|
||||
andi a4, a4, (SSTATUS_SIE)
|
||||
csrs sstatus, a4
|
||||
|
||||
/* Handle the ast */
|
||||
@ -204,12 +205,24 @@ __FBSDID("$FreeBSD$");
|
||||
2:
|
||||
.endm
|
||||
|
||||
ENTRY(cpu_exception_handler)
|
||||
csrrw sp, sscratch, sp
|
||||
beqz sp, 1f
|
||||
/* User mode detected */
|
||||
csrrw sp, sscratch, sp
|
||||
j cpu_exception_handler_user
|
||||
1:
|
||||
/* Supervisor mode detected */
|
||||
csrrw sp, sscratch, sp
|
||||
j cpu_exception_handler_supervisor
|
||||
END(cpu_exception_handler)
|
||||
|
||||
ENTRY(cpu_exception_handler_supervisor)
|
||||
save_registers 1
|
||||
mv a0, sp
|
||||
call _C_LABEL(do_trap_supervisor)
|
||||
load_registers 1
|
||||
eret
|
||||
sret
|
||||
END(cpu_exception_handler_supervisor)
|
||||
|
||||
ENTRY(cpu_exception_handler_user)
|
||||
@ -220,7 +233,7 @@ ENTRY(cpu_exception_handler_user)
|
||||
do_ast
|
||||
load_registers 0
|
||||
csrrw sp, sscratch, sp
|
||||
eret
|
||||
sret
|
||||
END(cpu_exception_handler_user)
|
||||
|
||||
/*
|
||||
@ -230,7 +243,7 @@ END(cpu_exception_handler_user)
|
||||
bad_trap:
|
||||
j bad_trap
|
||||
|
||||
user_trap:
|
||||
machine_trap:
|
||||
/* Save state */
|
||||
csrrw sp, mscratch, sp
|
||||
addi sp, sp, -64
|
||||
@ -242,91 +255,84 @@ user_trap:
|
||||
sd t5, (8 * 5)(sp)
|
||||
sd a0, (8 * 7)(sp)
|
||||
|
||||
la t2, _C_LABEL(cpu_exception_handler_user)
|
||||
|
||||
csrr t0, mcause
|
||||
bltz t0, machine_interrupt
|
||||
j exit_mrts
|
||||
|
||||
supervisor_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)
|
||||
|
||||
la t2, _C_LABEL(cpu_exception_handler_supervisor)
|
||||
|
||||
csrr t3, mstatus /* Required for debug */
|
||||
csrr t0, mcause
|
||||
bltz t0, machine_interrupt
|
||||
|
||||
li t1, EXCP_SMODE_ENV_CALL
|
||||
li t1, EXCP_SUPERVISOR_ECALL
|
||||
beq t0, t1, supervisor_call
|
||||
j exit_mrts
|
||||
4:
|
||||
/* NOT REACHED */
|
||||
j 4b
|
||||
|
||||
machine_interrupt:
|
||||
/* Type of interrupt ? */
|
||||
csrr t0, mcause
|
||||
andi t0, t0, EXCP_MASK
|
||||
li t1, 0
|
||||
beq t1, t0, software_interrupt
|
||||
li t1, 1
|
||||
beq t1, t0, timer_interrupt
|
||||
li t1, 2
|
||||
beq t1, t0, htif_interrupt
|
||||
#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 */
|
||||
/* 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
|
||||
|
||||
software_interrupt:
|
||||
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
|
||||
|
||||
/* 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
|
||||
|
||||
supervisor_timer_interrupt:
|
||||
1:
|
||||
/* Handle the trap in supervisor mode */
|
||||
j exit_mrts
|
||||
/* Nothing here as we are using mideleg feature */
|
||||
j 1b
|
||||
|
||||
timer_interrupt:
|
||||
machine_timer_interrupt:
|
||||
/* Disable machine timer interrupts */
|
||||
li t0, MIE_MTIE
|
||||
csrc mie, t0
|
||||
|
||||
/* Clear machine pending */
|
||||
/* Clear machine timer interrupt pending */
|
||||
li t0, MIP_MTIP
|
||||
csrc mip, t0
|
||||
|
||||
@ -334,54 +340,32 @@ timer_interrupt:
|
||||
li t0, MIP_STIP
|
||||
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.
|
||||
* Check for HTIF interrupts.
|
||||
* The only interrupt expected here is key press.
|
||||
*/
|
||||
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
|
||||
la t0, htif_lock
|
||||
li t2, 1
|
||||
amoswap.d t3, t2, 0(t0)
|
||||
bnez t3, 5f /* Another operation in progress, give up */
|
||||
|
||||
j exit
|
||||
/* We have lock */
|
||||
la t1, fromhost
|
||||
ld t5, 0(t1)
|
||||
beqz t5, 4f
|
||||
|
||||
1:
|
||||
/* Serve a trap in supervisor mode */
|
||||
j exit_mrts
|
||||
|
||||
htif_interrupt:
|
||||
1:
|
||||
li t5, 0
|
||||
csrrw t5, mfromhost, t5
|
||||
beqz t5, 3f
|
||||
|
||||
/* Console PUT intr ? */
|
||||
/* Console GET intr ? */
|
||||
mv t1, t5
|
||||
li t0, 0x101
|
||||
li t0, 0x100
|
||||
srli t1, t1, 48
|
||||
bne t1, t0, 2f
|
||||
/* Yes */
|
||||
la t0, console_intr
|
||||
li t1, 1
|
||||
sd t1, 0(t0)
|
||||
|
||||
/* Check if there is any other pending event */
|
||||
beq t1, t0, 2f
|
||||
1:
|
||||
/* There is no interrupts except keypress */
|
||||
j 1b
|
||||
|
||||
2:
|
||||
/* Save 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 */
|
||||
|
||||
@ -397,10 +381,18 @@ htif_interrupt:
|
||||
li t0, MIP_SSIP
|
||||
csrs mip, t0
|
||||
|
||||
/* Check if there is any other pending event */
|
||||
j 1b
|
||||
|
||||
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:
|
||||
@ -408,12 +400,14 @@ supervisor_call:
|
||||
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_CLEAR_PENDING
|
||||
beq t5, t4, clear_pending
|
||||
li t4, ECALL_MCPUID_GET
|
||||
beq t5, t4, mcpuid_get
|
||||
li t4, ECALL_MIMPID_GET
|
||||
@ -422,24 +416,28 @@ supervisor_call:
|
||||
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
|
||||
#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, mcpuid
|
||||
csrr t6, misa
|
||||
j exit_next_instr
|
||||
|
||||
mimpid_get:
|
||||
@ -447,10 +445,8 @@ mimpid_get:
|
||||
j exit_next_instr
|
||||
|
||||
send_ipi:
|
||||
/* CPU mmio base in t6 */
|
||||
/* CPU ipi MMIO register 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
|
||||
@ -458,10 +454,6 @@ send_ipi:
|
||||
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 */
|
||||
@ -478,10 +470,6 @@ clear_ipi:
|
||||
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 */
|
||||
|
||||
@ -502,41 +490,81 @@ htif_get_entry:
|
||||
/* Exit. Result is stored in t6 */
|
||||
j exit_next_instr
|
||||
|
||||
htif_cmd:
|
||||
htif_cmd_resp:
|
||||
la t0, htif_lock
|
||||
li t2, 1
|
||||
1:
|
||||
mv t0, t6
|
||||
csrrw t0, mtohost, t0
|
||||
bnez t0, 1b
|
||||
j exit_next_instr
|
||||
amoswap.d t3, t2, 0(t0)
|
||||
bnez t3, 1b
|
||||
|
||||
htif_lowputc:
|
||||
1:
|
||||
mv t0, t6
|
||||
csrrw t0, mtohost, t0
|
||||
bnez t0, 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:
|
||||
li t4, 0
|
||||
csrrw t5, mfromhost, t4
|
||||
beqz t5, 2b
|
||||
/* Release lock */
|
||||
la t0, htif_lock
|
||||
li t2, 0
|
||||
amoswap.d t3, t2, 0(t0)
|
||||
|
||||
/* Console PUT intr ? */
|
||||
mv t2, t5
|
||||
srli t2, t2, 48
|
||||
li t3, 0x0101
|
||||
beq t2, t3, 3f
|
||||
j exit_next_instr
|
||||
|
||||
/* Not a console PUT, so save entry */
|
||||
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
|
||||
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 */
|
||||
sd t6, 0(t2) /* put entry */
|
||||
li t4, 1
|
||||
sd t4, 8(t2) /* mark used */
|
||||
ld t4, 16(t2) /* take next */
|
||||
@ -547,27 +575,30 @@ htif_lowputc:
|
||||
li t0, MIP_SSIP
|
||||
csrs mip, t0
|
||||
|
||||
/* Wait for console intr again */
|
||||
/* 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:
|
||||
csrr t2, stime
|
||||
add t6, t6, t2
|
||||
csrw mtimecmp, t6
|
||||
|
||||
/* Enable interrupts */
|
||||
li t0, (MIE_MTIE | MIE_STIE)
|
||||
csrs mie, t0
|
||||
j exit_next_instr
|
||||
|
||||
clear_pending:
|
||||
li t0, MIP_STIP
|
||||
csrc mip, t0
|
||||
j exit_next_instr
|
||||
|
||||
/*
|
||||
* Trap exit functions
|
||||
*/
|
||||
@ -585,27 +616,7 @@ exit:
|
||||
ld a0, (8 * 7)(sp)
|
||||
addi sp, sp, 64
|
||||
csrrw sp, mscratch, sp
|
||||
eret
|
||||
mret
|
||||
|
||||
/*
|
||||
* Redirect to supervisor
|
||||
*/
|
||||
exit_mrts:
|
||||
/* Setup exception handler */
|
||||
li t1, KERNBASE
|
||||
add t2, t2, t1
|
||||
csrw stvec, t2
|
||||
|
||||
/* 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
|
||||
|
||||
/* Redirect to supervisor */
|
||||
mrts
|
||||
j exit_mrts
|
||||
|
@ -57,6 +57,7 @@ __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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by SRI International and the
|
||||
@ -67,28 +67,16 @@ struct cpu_parts {
|
||||
struct cpu_implementers {
|
||||
u_int impl_id;
|
||||
const char *impl_name;
|
||||
/*
|
||||
* Part number is implementation defined
|
||||
* so each vendor will have its own set of values and names.
|
||||
*/
|
||||
const struct cpu_parts *cpu_parts;
|
||||
};
|
||||
#define CPU_IMPLEMENTER_NONE { 0, "Unknown Implementer", cpu_parts_none }
|
||||
#define CPU_IMPLEMENTER_NONE { 0, "Unknown Implementer" }
|
||||
|
||||
/*
|
||||
* Per-implementer table of (PartNum, CPU Name) pairs.
|
||||
* CPU base
|
||||
*/
|
||||
/* UC Berkeley */
|
||||
static const struct cpu_parts cpu_parts_ucb[] = {
|
||||
{ CPU_PART_RV32I, "RV32I" },
|
||||
{ CPU_PART_RV32E, "RV32E" },
|
||||
{ CPU_PART_RV64I, "RV64I" },
|
||||
{ CPU_PART_RV128I, "RV128I" },
|
||||
CPU_PART_NONE,
|
||||
};
|
||||
|
||||
/* Unknown */
|
||||
static const struct cpu_parts cpu_parts_none[] = {
|
||||
static const struct cpu_parts cpu_parts_std[] = {
|
||||
{ CPU_PART_RV32, "RV32" },
|
||||
{ CPU_PART_RV64, "RV64" },
|
||||
{ CPU_PART_RV128, "RV128" },
|
||||
CPU_PART_NONE,
|
||||
};
|
||||
|
||||
@ -96,7 +84,7 @@ static const struct cpu_parts cpu_parts_none[] = {
|
||||
* Implementers table.
|
||||
*/
|
||||
const struct cpu_implementers cpu_implementers[] = {
|
||||
{ CPU_IMPL_UCB_ROCKET, "UC Berkeley Rocket", cpu_parts_ucb },
|
||||
{ CPU_IMPL_UCB_ROCKET, "UC Berkeley Rocket" },
|
||||
CPU_IMPLEMENTER_NONE,
|
||||
};
|
||||
|
||||
@ -107,16 +95,15 @@ identify_cpu(void)
|
||||
uint32_t part_id;
|
||||
uint32_t impl_id;
|
||||
uint64_t mimpid;
|
||||
uint64_t mcpuid;
|
||||
uint64_t misa;
|
||||
u_int cpu;
|
||||
size_t i;
|
||||
|
||||
cpu_partsp = NULL;
|
||||
|
||||
mimpid = machine_command(ECALL_MIMPID_GET, 0);
|
||||
mcpuid = machine_command(ECALL_MCPUID_GET, 0);
|
||||
misa = machine_command(ECALL_MCPUID_GET, 0);
|
||||
|
||||
/* SMPTODO: use mhartid ? */
|
||||
cpu = PCPU_GET(cpuid);
|
||||
|
||||
impl_id = CPU_IMPL(mimpid);
|
||||
@ -125,12 +112,12 @@ identify_cpu(void)
|
||||
cpu_implementers[i].impl_id == 0) {
|
||||
cpu_desc[cpu].cpu_impl = impl_id;
|
||||
cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
|
||||
cpu_partsp = cpu_implementers[i].cpu_parts;
|
||||
cpu_partsp = cpu_parts_std;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
part_id = CPU_PART(mcpuid);
|
||||
part_id = CPU_PART(misa);
|
||||
for (i = 0; &cpu_partsp[i] != NULL; i++) {
|
||||
if (part_id == cpu_partsp[i].part_id ||
|
||||
cpu_partsp[i].part_id == -1) {
|
||||
|
@ -95,15 +95,20 @@ riscv_mask_irq(void *source)
|
||||
irq = (uintptr_t)source;
|
||||
|
||||
switch (irq) {
|
||||
case IRQ_TIMER:
|
||||
case IRQ_TIMER_SUPERVISOR:
|
||||
csr_clear(sie, SIE_STIE);
|
||||
break;
|
||||
case IRQ_SOFTWARE:
|
||||
case IRQ_SOFTWARE_USER:
|
||||
csr_clear(sie, SIE_USIE);
|
||||
case IRQ_SOFTWARE_SUPERVISOR:
|
||||
csr_clear(sie, SIE_SSIE);
|
||||
break;
|
||||
#if 0
|
||||
/* lowRISC TODO */
|
||||
case IRQ_UART:
|
||||
machine_command(ECALL_IO_IRQ_MASK, 0);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Unknown irq %d\n", irq);
|
||||
}
|
||||
@ -117,15 +122,21 @@ riscv_unmask_irq(void *source)
|
||||
irq = (uintptr_t)source;
|
||||
|
||||
switch (irq) {
|
||||
case IRQ_TIMER:
|
||||
case IRQ_TIMER_SUPERVISOR:
|
||||
csr_set(sie, SIE_STIE);
|
||||
break;
|
||||
case IRQ_SOFTWARE:
|
||||
case IRQ_SOFTWARE_USER:
|
||||
csr_set(sie, SIE_USIE);
|
||||
break;
|
||||
case IRQ_SOFTWARE_SUPERVISOR:
|
||||
csr_set(sie, SIE_SSIE);
|
||||
break;
|
||||
#if 0
|
||||
/* lowRISC TODO */
|
||||
case IRQ_UART:
|
||||
machine_command(ECALL_IO_IRQ_MASK, 1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Unknown irq %d\n", irq);
|
||||
}
|
||||
@ -209,18 +220,18 @@ riscv_cpu_intr(struct trapframe *frame)
|
||||
active_irq = (frame->tf_scause & EXCP_MASK);
|
||||
|
||||
switch (active_irq) {
|
||||
#if 0
|
||||
/* lowRISC TODO */
|
||||
case IRQ_UART:
|
||||
case IRQ_SOFTWARE:
|
||||
case IRQ_TIMER:
|
||||
#endif
|
||||
case IRQ_SOFTWARE_USER:
|
||||
case IRQ_SOFTWARE_SUPERVISOR:
|
||||
case IRQ_TIMER_SUPERVISOR:
|
||||
event = intr_events[active_irq];
|
||||
/* Update counters */
|
||||
atomic_add_long(riscv_intr_counters[active_irq], 1);
|
||||
PCPU_INC(cnt.v_intr);
|
||||
break;
|
||||
case IRQ_HTIF:
|
||||
/* HTIF interrupts are only handled in machine mode */
|
||||
panic("%s: HTIF interrupt", __func__);
|
||||
break;
|
||||
default:
|
||||
event = NULL;
|
||||
}
|
||||
@ -237,7 +248,7 @@ void
|
||||
riscv_setup_ipihandler(driver_filter_t *filt)
|
||||
{
|
||||
|
||||
riscv_setup_intr("ipi", filt, NULL, NULL, IRQ_SOFTWARE,
|
||||
riscv_setup_intr("ipi", filt, NULL, NULL, IRQ_SOFTWARE_SUPERVISOR,
|
||||
INTR_TYPE_MISC, NULL);
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@
|
||||
#define HW_STACK_SIZE (96)
|
||||
|
||||
/*
|
||||
* Event queue for each CPU core:
|
||||
* Event queue:
|
||||
*
|
||||
* struct htif_ring {
|
||||
* uint64_t data;
|
||||
@ -62,12 +62,6 @@
|
||||
|
||||
.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 */
|
||||
@ -101,31 +95,48 @@
|
||||
.text
|
||||
|
||||
mentry:
|
||||
/* User mode entry point (mtvec + 0x000) */
|
||||
.align 6
|
||||
j user_trap
|
||||
|
||||
/* Supervisor mode entry point (mtvec + 0x040) */
|
||||
.align 6
|
||||
j supervisor_trap
|
||||
|
||||
/* Hypervisor mode entry point (mtvec + 0x080) */
|
||||
.align 6
|
||||
j bad_trap
|
||||
|
||||
/* Machine mode entry point (mtvec + 0x0C0) */
|
||||
.align 6
|
||||
j bad_trap
|
||||
/* Vectors */
|
||||
j _start /* reset */
|
||||
j bad_trap /* NMI (non-maskable interrupt) */
|
||||
j machine_trap
|
||||
|
||||
/* Reset vector */
|
||||
.text
|
||||
.align 8
|
||||
.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
|
||||
|
||||
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
|
||||
|
||||
@ -149,7 +160,7 @@ _start:
|
||||
li a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE)
|
||||
srli a5, a5, L1_SHIFT /* >> L1_SHIFT */
|
||||
andi a5, a5, 0x1ff /* & 0x1ff */
|
||||
li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
|
||||
li t4, PTE_V
|
||||
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
|
||||
or t6, t4, t5
|
||||
|
||||
@ -164,10 +175,10 @@ _start:
|
||||
la s2, pagetable_l2 /* Link to next level PN */
|
||||
srli s2, s2, PAGE_SHIFT
|
||||
|
||||
li a5, KERNBASE
|
||||
li a5, (KERNBASE + KERNENTRY)
|
||||
srli a5, a5, L1_SHIFT /* >> L1_SHIFT */
|
||||
andi a5, a5, 0x1ff /* & 0x1ff */
|
||||
li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
|
||||
li t4, PTE_V
|
||||
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
|
||||
or t6, t4, t5
|
||||
|
||||
@ -179,11 +190,13 @@ _start:
|
||||
|
||||
/* Level 2 superpages (512 x 2MiB) */
|
||||
la s1, pagetable_l2
|
||||
li t3, 512 /* Build 512 entries */
|
||||
li t4, 0 /* Counter */
|
||||
li t4, KERNENTRY
|
||||
srli t4, t4, 21 /* Div by 2 MiB */
|
||||
li t2, 512 /* Build 512 entries */
|
||||
add t3, t4, t2
|
||||
li t5, 0
|
||||
2:
|
||||
li t0, (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S))
|
||||
li t0, (PTE_V | PTE_RWX)
|
||||
slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */
|
||||
or t5, t0, t2
|
||||
sd t5, (s1) /* Store PTE entry to position */
|
||||
@ -194,15 +207,14 @@ _start:
|
||||
|
||||
/* Set page tables base register */
|
||||
la s1, pagetable_l1
|
||||
srli s1, s1, PAGE_SHIFT
|
||||
csrw sptbr, s1
|
||||
|
||||
/* Page tables END */
|
||||
|
||||
/* Enter supervisor mode */
|
||||
li s0, ((MSTATUS_VM_SV39 << MSTATUS_VM_SHIFT) | \
|
||||
(MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \
|
||||
(MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \
|
||||
(MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT));
|
||||
(MSTATUS_PRV_S << MSTATUS_MPP_SHIFT));
|
||||
csrw mstatus, s0
|
||||
|
||||
/*
|
||||
@ -217,7 +229,7 @@ _start:
|
||||
li s11, KERNBASE
|
||||
add t0, t0, s11
|
||||
csrw mepc, t0
|
||||
eret
|
||||
mret
|
||||
|
||||
.Lmmu_on:
|
||||
/* Initialize stack pointer */
|
||||
@ -254,10 +266,12 @@ hardstack_end:
|
||||
|
||||
.globl htif_ring
|
||||
htif_ring:
|
||||
.space ((HTIF_RING_SIZE + 16) * MAXCPU)
|
||||
|
||||
.globl console_intr
|
||||
console_intr:
|
||||
.space (HTIF_RING_SIZE + 16)
|
||||
htif_lock:
|
||||
.space (8)
|
||||
tohost:
|
||||
.space (8)
|
||||
fromhost:
|
||||
.space (8)
|
||||
|
||||
ENTRY(sigcode)
|
||||
@ -325,18 +339,14 @@ ENTRY(mpentry)
|
||||
lw t1, 0(t0)
|
||||
beqz t1, 1b
|
||||
|
||||
/* Build event queue ring for this core */
|
||||
build_ring
|
||||
|
||||
/* 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_M << MSTATUS_PRV_SHIFT) | \
|
||||
(MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \
|
||||
(MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT));
|
||||
(MSTATUS_PRV_S << MSTATUS_MPP_SHIFT));
|
||||
csrw mstatus, s0
|
||||
|
||||
/* Setup stack for machine mode exceptions */
|
||||
@ -364,7 +374,7 @@ ENTRY(mpentry)
|
||||
li s11, KERNBASE
|
||||
add t0, t0, s11
|
||||
csrw mepc, t0
|
||||
eret
|
||||
mret
|
||||
|
||||
mp_virtdone:
|
||||
/* We are now in virtual address space */
|
||||
|
@ -440,10 +440,10 @@ sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
|
||||
/*
|
||||
* Make sure the processor mode has not been tampered with and
|
||||
* interrupts have not been disabled.
|
||||
* Supervisor interrupts in user mode are always enabled.
|
||||
*/
|
||||
sstatus = uc.uc_mcontext.mc_gpregs.gp_sstatus;
|
||||
if ((sstatus & SSTATUS_PS) != 0 ||
|
||||
(sstatus & SSTATUS_PIE) == 0)
|
||||
if ((sstatus & SSTATUS_SPP) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
error = set_mcontext(td, &uc.uc_mcontext);
|
||||
@ -743,7 +743,8 @@ initriscv(struct riscv_bootparams *rvbp)
|
||||
if (kmdp == NULL)
|
||||
kmdp = preload_search_by_type("elf64 kernel");
|
||||
|
||||
boothowto = 0;
|
||||
boothowto = RB_VERBOSE | RB_SINGLE;
|
||||
boothowto = RB_VERBOSE;
|
||||
|
||||
kern_envp = NULL;
|
||||
|
||||
@ -775,7 +776,7 @@ initriscv(struct riscv_bootparams *rvbp)
|
||||
|
||||
cache_setup();
|
||||
|
||||
/* Bootstrap enough of pmap to enter the kernel proper */
|
||||
/* Bootstrap enough of pmap to enter the kernel proper */
|
||||
kernlen = (lastaddr - KERNBASE);
|
||||
pmap_bootstrap(rvbp->kern_l1pt, KERNENTRY, kernlen);
|
||||
|
||||
|
@ -311,9 +311,9 @@ pmap_l2(pmap_t pmap, vm_offset_t va)
|
||||
l1 = pmap_l1(pmap, va);
|
||||
if (l1 == NULL)
|
||||
return (NULL);
|
||||
if ((pmap_load(l1) & PTE_VALID) == 0)
|
||||
if ((pmap_load(l1) & PTE_V) == 0)
|
||||
return (NULL);
|
||||
if ((pmap_load(l1) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S))
|
||||
if ((pmap_load(l1) & PTE_RX) != 0)
|
||||
return (NULL);
|
||||
|
||||
return (pmap_l1_to_l2(l1, va));
|
||||
@ -339,9 +339,9 @@ pmap_l3(pmap_t pmap, vm_offset_t va)
|
||||
l2 = pmap_l2(pmap, va);
|
||||
if (l2 == NULL)
|
||||
return (NULL);
|
||||
if ((pmap_load(l2) & PTE_VALID) == 0)
|
||||
if ((pmap_load(l2) & PTE_V) == 0)
|
||||
return (NULL);
|
||||
if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S))
|
||||
if ((pmap_load(l2) & PTE_RX) != 0)
|
||||
return (NULL);
|
||||
|
||||
return (pmap_l2_to_l3(l2, va));
|
||||
@ -352,10 +352,7 @@ static __inline int
|
||||
pmap_is_write(pt_entry_t entry)
|
||||
{
|
||||
|
||||
if (entry & (1 << PTE_TYPE_S))
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
return (entry & PTE_W);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
@ -370,7 +367,7 @@ static __inline int
|
||||
pmap_l3_valid(pt_entry_t l3)
|
||||
{
|
||||
|
||||
return (l3 & PTE_VALID);
|
||||
return (l3 & PTE_V);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
@ -389,7 +386,7 @@ static inline int
|
||||
pmap_page_dirty(pt_entry_t pte)
|
||||
{
|
||||
|
||||
return (pte & PTE_DIRTY);
|
||||
return (pte & PTE_D);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
@ -442,7 +439,7 @@ pmap_early_page_idx(vm_offset_t l1pt, vm_offset_t va, u_int *l1_slot,
|
||||
*l1_slot = (va >> L1_SHIFT) & Ln_ADDR_MASK;
|
||||
|
||||
/* Check locore has used a table L1 map */
|
||||
KASSERT((l1[*l1_slot] & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S),
|
||||
KASSERT((l1[*l1_slot] & PTE_RX) == 0,
|
||||
("Invalid bootstrap L1 table"));
|
||||
|
||||
/* Find the address of the L2 table */
|
||||
@ -478,6 +475,13 @@ 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;
|
||||
va = DMAP_MIN_ADDRESS;
|
||||
l1 = (pd_entry_t *)l1pt;
|
||||
@ -489,7 +493,7 @@ pmap_bootstrap_dmap(vm_offset_t l1pt, vm_paddr_t kernstart)
|
||||
|
||||
/* superpages */
|
||||
pn = (pa / PAGE_SIZE);
|
||||
entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S));
|
||||
entry = (PTE_V | PTE_RWX);
|
||||
entry |= (pn << PTE_PPN0_S);
|
||||
pmap_load_store(&l1[l1_slot], entry);
|
||||
}
|
||||
@ -521,19 +525,20 @@ pmap_bootstrap_l3(vm_offset_t l1pt, vm_offset_t va, vm_offset_t l3_start)
|
||||
|
||||
pa = pmap_early_vtophys(l1pt, l3pt);
|
||||
pn = (pa / PAGE_SIZE);
|
||||
entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
|
||||
entry = (PTE_V);
|
||||
entry |= (pn << PTE_PPN0_S);
|
||||
pmap_load_store(&l2[l2_slot], entry);
|
||||
l3pt += PAGE_SIZE;
|
||||
}
|
||||
|
||||
|
||||
/* Clean the L2 page table */
|
||||
memset((void *)l3_start, 0, l3pt - l3_start);
|
||||
cpu_dcache_wb_range(l3_start, l3pt - l3_start);
|
||||
|
||||
cpu_dcache_wb_range((vm_offset_t)l2, PAGE_SIZE);
|
||||
|
||||
return l3pt;
|
||||
return (l3pt);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -598,6 +603,10 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
|
||||
if (physmap[map_slot] == physmap[map_slot + 1])
|
||||
continue;
|
||||
|
||||
if (physmap[map_slot] <= pa &&
|
||||
physmap[map_slot + 1] > pa)
|
||||
break;
|
||||
|
||||
phys_avail[avail_slot] = physmap[map_slot];
|
||||
phys_avail[avail_slot + 1] = physmap[map_slot + 1];
|
||||
physmem += (phys_avail[avail_slot + 1] -
|
||||
@ -627,11 +636,11 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
|
||||
|
||||
/* Find how many pages we have mapped */
|
||||
for (; l2_slot < Ln_ENTRIES; l2_slot++) {
|
||||
if ((l2[l2_slot] & PTE_VALID) == 0)
|
||||
if ((l2[l2_slot] & PTE_V) == 0)
|
||||
break;
|
||||
|
||||
/* Check locore used L2 superpages */
|
||||
KASSERT((l2[l2_slot] & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S),
|
||||
KASSERT((l2[l2_slot] & PTE_RX) != 0,
|
||||
("Invalid bootstrap L2 table"));
|
||||
|
||||
va += L2_SIZE;
|
||||
@ -672,12 +681,14 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
|
||||
map_slot = used_map_slot;
|
||||
for (; avail_slot < (PHYS_AVAIL_SIZE - 2) &&
|
||||
map_slot < (physmap_idx * 2); map_slot += 2) {
|
||||
if (physmap[map_slot] == physmap[map_slot + 1])
|
||||
if (physmap[map_slot] == physmap[map_slot + 1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Have we used the current range? */
|
||||
if (physmap[map_slot + 1] <= pa)
|
||||
if (physmap[map_slot + 1] <= pa) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Do we need to split the entry? */
|
||||
if (physmap[map_slot] < pa) {
|
||||
@ -797,7 +808,7 @@ pmap_extract(pmap_t pmap, vm_offset_t va)
|
||||
l2p = pmap_l2(pmap, va);
|
||||
if (l2p != NULL) {
|
||||
l2 = pmap_load(l2p);
|
||||
if ((l2 & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S)) {
|
||||
if ((l2 & PTE_RX) == 0) {
|
||||
l3p = pmap_l2_to_l3(l2p, va);
|
||||
if (l3p != NULL) {
|
||||
l3 = pmap_load(l3p);
|
||||
@ -861,7 +872,7 @@ pmap_kextract(vm_offset_t va)
|
||||
l2 = pmap_l2(kernel_pmap, va);
|
||||
if (l2 == NULL)
|
||||
panic("pmap_kextract: No l2");
|
||||
if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S)) {
|
||||
if ((pmap_load(l2) & PTE_RX) != 0) {
|
||||
/* superpages */
|
||||
pa = (pmap_load(l2) >> PTE_PPN1_S) << L2_SHIFT;
|
||||
pa |= (va & L2_OFFSET);
|
||||
@ -902,7 +913,7 @@ pmap_kenter_device(vm_offset_t sva, vm_size_t size, vm_paddr_t pa)
|
||||
KASSERT(l3 != NULL, ("Invalid page table, va: 0x%lx", va));
|
||||
|
||||
pn = (pa / PAGE_SIZE);
|
||||
entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S));
|
||||
entry = (PTE_V | PTE_RWX);
|
||||
entry |= (pn << PTE_PPN0_S);
|
||||
pmap_load_store(l3, entry);
|
||||
|
||||
@ -1004,7 +1015,7 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count)
|
||||
pn = (pa / PAGE_SIZE);
|
||||
l3 = pmap_l3(kernel_pmap, va);
|
||||
|
||||
entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S));
|
||||
entry = (PTE_V | PTE_RWX);
|
||||
entry |= (pn << PTE_PPN0_S);
|
||||
pmap_load_store(l3, entry);
|
||||
|
||||
@ -1261,7 +1272,7 @@ _pmap_alloc_l3(pmap_t pmap, vm_pindex_t ptepindex, struct rwlock **lockp)
|
||||
l1 = &pmap->pm_l1[l1index];
|
||||
|
||||
pn = (VM_PAGE_TO_PHYS(m) / PAGE_SIZE);
|
||||
entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
|
||||
entry = (PTE_V);
|
||||
entry |= (pn << PTE_PPN0_S);
|
||||
pmap_load_store(l1, entry);
|
||||
pmap_distribute_l1(pmap, l1index, entry);
|
||||
@ -1294,7 +1305,7 @@ _pmap_alloc_l3(pmap_t pmap, vm_pindex_t ptepindex, struct rwlock **lockp)
|
||||
l2 = &l2[ptepindex & Ln_ADDR_MASK];
|
||||
|
||||
pn = (VM_PAGE_TO_PHYS(m) / PAGE_SIZE);
|
||||
entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
|
||||
entry = (PTE_V);
|
||||
entry |= (pn << PTE_PPN0_S);
|
||||
pmap_load_store(l2, entry);
|
||||
|
||||
@ -1428,7 +1439,7 @@ pmap_growkernel(vm_offset_t addr)
|
||||
paddr = VM_PAGE_TO_PHYS(nkpg);
|
||||
|
||||
pn = (paddr / PAGE_SIZE);
|
||||
entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
|
||||
entry = (PTE_V);
|
||||
entry |= (pn << PTE_PPN0_S);
|
||||
pmap_load_store(l1, entry);
|
||||
pmap_distribute_l1(kernel_pmap,
|
||||
@ -1438,7 +1449,7 @@ pmap_growkernel(vm_offset_t addr)
|
||||
continue; /* try again */
|
||||
}
|
||||
l2 = pmap_l1_to_l2(l1, kernel_vm_end);
|
||||
if ((pmap_load(l2) & PTE_REF) != 0) {
|
||||
if ((pmap_load(l2) & PTE_A) != 0) {
|
||||
kernel_vm_end = (kernel_vm_end + L2_SIZE) & ~L2_OFFSET;
|
||||
if (kernel_vm_end - 1 >= kernel_map->max_offset) {
|
||||
kernel_vm_end = kernel_map->max_offset;
|
||||
@ -1452,12 +1463,13 @@ pmap_growkernel(vm_offset_t addr)
|
||||
VM_ALLOC_ZERO);
|
||||
if (nkpg == NULL)
|
||||
panic("pmap_growkernel: no memory to grow kernel");
|
||||
if ((nkpg->flags & PG_ZERO) == 0)
|
||||
if ((nkpg->flags & PG_ZERO) == 0) {
|
||||
pmap_zero_page(nkpg);
|
||||
}
|
||||
paddr = VM_PAGE_TO_PHYS(nkpg);
|
||||
|
||||
pn = (paddr / PAGE_SIZE);
|
||||
entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
|
||||
entry = (PTE_V);
|
||||
entry |= (pn << PTE_PPN0_S);
|
||||
pmap_load_store(l2, entry);
|
||||
|
||||
@ -1754,7 +1766,7 @@ pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_t va,
|
||||
m = PHYS_TO_VM_PAGE(phys);
|
||||
if (pmap_page_dirty(old_l3))
|
||||
vm_page_dirty(m);
|
||||
if (old_l3 & PTE_REF)
|
||||
if (old_l3 & PTE_A)
|
||||
vm_page_aflag_set(m, PGA_REFERENCED);
|
||||
CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m);
|
||||
pmap_pvh_free(&m->md, pmap, va);
|
||||
@ -1822,7 +1834,7 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
|
||||
*/
|
||||
if (l3_pte == 0)
|
||||
continue;
|
||||
if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S))
|
||||
if ((pmap_load(l2) & PTE_RX) != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
@ -1899,7 +1911,7 @@ pmap_remove_all(vm_page_t m)
|
||||
KASSERT(l2 != NULL, ("pmap_remove_all: no l2 table found"));
|
||||
tl2 = pmap_load(l2);
|
||||
|
||||
KASSERT((tl2 & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S),
|
||||
KASSERT((tl2 & PTE_RX) == 0,
|
||||
("pmap_remove_all: found a table when expecting "
|
||||
"a block in %p's pv list", m));
|
||||
|
||||
@ -1912,7 +1924,7 @@ pmap_remove_all(vm_page_t m)
|
||||
pmap_invalidate_page(pmap, pv->pv_va);
|
||||
if (tl3 & PTE_SW_WIRED)
|
||||
pmap->pm_stats.wired_count--;
|
||||
if ((tl3 & PTE_REF) != 0)
|
||||
if ((tl3 & PTE_A) != 0)
|
||||
vm_page_aflag_set(m, PGA_REFERENCED);
|
||||
|
||||
/*
|
||||
@ -1969,7 +1981,7 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
|
||||
l2 = pmap_l1_to_l2(l1, sva);
|
||||
if (l2 == NULL)
|
||||
continue;
|
||||
if ((pmap_load(l2) & PTE_TYPE_M) != (PTE_TYPE_PTR << PTE_TYPE_S))
|
||||
if ((pmap_load(l2) & PTE_RX) != 0)
|
||||
continue;
|
||||
|
||||
if (va_next > eva)
|
||||
@ -1981,7 +1993,7 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
|
||||
l3 = pmap_load(l3p);
|
||||
if (pmap_l3_valid(l3)) {
|
||||
entry = pmap_load(l3p);
|
||||
entry &= ~(1 << PTE_TYPE_S);
|
||||
entry &= ~(PTE_W);
|
||||
pmap_load_store(l3p, entry);
|
||||
PTE_SYNC(l3p);
|
||||
/* XXX: Use pmap_invalidate_range */
|
||||
@ -2030,19 +2042,11 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
|
||||
pa = VM_PAGE_TO_PHYS(m);
|
||||
pn = (pa / PAGE_SIZE);
|
||||
|
||||
new_l3 = PTE_VALID;
|
||||
|
||||
if ((prot & VM_PROT_WRITE) == 0) { /* Read-only */
|
||||
if ((va >> 63) == 0) /* USER */
|
||||
new_l3 |= (PTE_TYPE_SURX << PTE_TYPE_S);
|
||||
else /* KERNEL */
|
||||
new_l3 |= (PTE_TYPE_SRX << PTE_TYPE_S);
|
||||
} else {
|
||||
if ((va >> 63) == 0) /* USER */
|
||||
new_l3 |= (PTE_TYPE_SURWX << PTE_TYPE_S);
|
||||
else /* KERNEL */
|
||||
new_l3 |= (PTE_TYPE_SRWX << PTE_TYPE_S);
|
||||
}
|
||||
new_l3 = PTE_V | PTE_R | PTE_X;
|
||||
if (prot & VM_PROT_WRITE)
|
||||
new_l3 |= PTE_W;
|
||||
if ((va >> 63) == 0)
|
||||
new_l3 |= PTE_U;
|
||||
|
||||
new_l3 |= (pn << PTE_PPN0_S);
|
||||
if ((flags & PMAP_ENTER_WIRED) != 0)
|
||||
@ -2086,7 +2090,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
|
||||
l2_pn = (l2_pa / PAGE_SIZE);
|
||||
|
||||
l1 = pmap_l1(pmap, va);
|
||||
entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
|
||||
entry = (PTE_V);
|
||||
entry |= (l2_pn << PTE_PPN0_S);
|
||||
pmap_load_store(l1, entry);
|
||||
pmap_distribute_l1(pmap, pmap_l1_index(va), entry);
|
||||
@ -2107,7 +2111,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
|
||||
|
||||
l3_pa = VM_PAGE_TO_PHYS(l3_m);
|
||||
l3_pn = (l3_pa / PAGE_SIZE);
|
||||
entry = (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S));
|
||||
entry = (PTE_V);
|
||||
entry |= (l3_pn << PTE_PPN0_S);
|
||||
pmap_load_store(l2, entry);
|
||||
PTE_SYNC(l2);
|
||||
@ -2201,7 +2205,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
|
||||
om = PHYS_TO_VM_PAGE(opa);
|
||||
if (pmap_page_dirty(orig_l3))
|
||||
vm_page_dirty(om);
|
||||
if ((orig_l3 & PTE_REF) != 0)
|
||||
if ((orig_l3 & PTE_A) != 0)
|
||||
vm_page_aflag_set(om, PGA_REFERENCED);
|
||||
CHANGE_PV_LIST_LOCK_TO_PHYS(&lock, opa);
|
||||
pmap_pvh_free(&om->md, pmap, va);
|
||||
@ -2388,7 +2392,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
|
||||
pn = (pa / PAGE_SIZE);
|
||||
|
||||
/* RISCVTODO: check permissions */
|
||||
entry = (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S));
|
||||
entry = (PTE_V | PTE_RWX);
|
||||
entry |= (pn << PTE_PPN0_S);
|
||||
|
||||
/*
|
||||
@ -2831,12 +2835,12 @@ pmap_page_test_mappings(vm_page_t m, boolean_t accessed, boolean_t modified)
|
||||
mask = 0;
|
||||
value = 0;
|
||||
if (modified) {
|
||||
mask |= PTE_DIRTY;
|
||||
value |= PTE_DIRTY;
|
||||
mask |= PTE_D;
|
||||
value |= PTE_D;
|
||||
}
|
||||
if (accessed) {
|
||||
mask |= PTE_REF;
|
||||
value |= PTE_REF;
|
||||
mask |= PTE_A;
|
||||
value |= PTE_A;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -2968,11 +2972,11 @@ pmap_remove_write(vm_page_t m)
|
||||
oldl3 = pmap_load(l3);
|
||||
|
||||
if (pmap_is_write(oldl3)) {
|
||||
newl3 = oldl3 & ~(1 << PTE_TYPE_S);
|
||||
newl3 = oldl3 & ~(PTE_W);
|
||||
if (!atomic_cmpset_long(l3, oldl3, newl3))
|
||||
goto retry;
|
||||
/* TODO: use pmap_page_dirty(oldl3) ? */
|
||||
if ((oldl3 & PTE_REF) != 0)
|
||||
if ((oldl3 & PTE_A) != 0)
|
||||
vm_page_dirty(m);
|
||||
pmap_invalidate_page(pmap, pv->pv_va);
|
||||
}
|
||||
@ -3045,11 +3049,11 @@ pmap_ts_referenced(vm_page_t m)
|
||||
}
|
||||
l2 = pmap_l2(pmap, pv->pv_va);
|
||||
|
||||
KASSERT((pmap_load(l2) & PTE_TYPE_M) == (PTE_TYPE_PTR << PTE_TYPE_S),
|
||||
KASSERT((pmap_load(l2) & PTE_RX) == 0,
|
||||
("pmap_ts_referenced: found an invalid l2 table"));
|
||||
|
||||
l3 = pmap_l2_to_l3(l2, pv->pv_va);
|
||||
if ((pmap_load(l3) & PTE_REF) != 0) {
|
||||
if ((pmap_load(l3) & PTE_A) != 0) {
|
||||
if (safe_to_clear_referenced(pmap, pmap_load(l3))) {
|
||||
/*
|
||||
* TODO: We don't handle the access flag
|
||||
@ -3178,7 +3182,7 @@ pmap_activate(struct thread *td)
|
||||
pmap = vmspace_pmap(td->td_proc->p_vmspace);
|
||||
td->td_pcb->pcb_l1addr = vtophys(pmap->pm_l1);
|
||||
|
||||
__asm __volatile("csrw sptbr, %0" :: "r"(td->td_pcb->pcb_l1addr));
|
||||
__asm __volatile("csrw sptbr, %0" :: "r"(td->td_pcb->pcb_l1addr >> PAGE_SHIFT));
|
||||
|
||||
pmap_invalidate_all(pmap);
|
||||
critical_exit();
|
||||
|
@ -56,6 +56,7 @@ ENTRY(cpu_throw)
|
||||
|
||||
/* Switch to the new pmap */
|
||||
ld t0, PCB_L1ADDR(x13)
|
||||
srli t0, t0, PAGE_SHIFT
|
||||
csrw sptbr, t0
|
||||
|
||||
/* TODO: Invalidate the TLB */
|
||||
@ -79,6 +80,7 @@ ENTRY(cpu_throw)
|
||||
ld s9, (PCB_S + 9 * 8)(x13)
|
||||
ld s10, (PCB_S + 10 * 8)(x13)
|
||||
ld s11, (PCB_S + 11 * 8)(x13)
|
||||
|
||||
ret
|
||||
|
||||
.Lcpu_throw_panic_str:
|
||||
@ -135,6 +137,7 @@ ENTRY(cpu_switch)
|
||||
|
||||
/* Switch to the new pmap */
|
||||
ld t0, PCB_L1ADDR(x13)
|
||||
srli t0, t0, PAGE_SHIFT
|
||||
csrw sptbr, t0
|
||||
|
||||
/* TODO: Invalidate the TLB */
|
||||
@ -187,7 +190,7 @@ ENTRY(fork_trampoline)
|
||||
/* Restore sstatus */
|
||||
ld t0, (TF_SSTATUS)(sp)
|
||||
/* Ensure interrupts disabled */
|
||||
li t1, ~SSTATUS_IE
|
||||
li t1, ~SSTATUS_SIE
|
||||
and t0, t0, t1
|
||||
csrw sstatus, t0
|
||||
|
||||
@ -244,7 +247,7 @@ ENTRY(fork_trampoline)
|
||||
/* Load user stack */
|
||||
ld sp, (TF_SP - TF_SIZE)(sp)
|
||||
|
||||
eret
|
||||
sret
|
||||
END(fork_trampoline)
|
||||
|
||||
ENTRY(savectx)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by SRI International and the
|
||||
@ -67,9 +67,19 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define DEFAULT_FREQ 1000000
|
||||
|
||||
#define TIMER_COUNTS 0x00
|
||||
#define TIMER_MTIMECMP(cpu) (0x08 + (cpu * 8))
|
||||
|
||||
#define READ8(_sc, _reg) \
|
||||
bus_space_read_8(_sc->bst, _sc->bsh, _reg)
|
||||
#define WRITE8(_sc, _reg, _val) \
|
||||
bus_space_write_8(_sc->bst, _sc->bsh, _reg, _val)
|
||||
|
||||
struct riscv_tmr_softc {
|
||||
struct resource *res[1];
|
||||
void *ihl[1];
|
||||
struct resource *res[2];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
void *ih;
|
||||
uint32_t clkfreq;
|
||||
struct eventtimer et;
|
||||
};
|
||||
@ -77,6 +87,7 @@ struct riscv_tmr_softc {
|
||||
static struct riscv_tmr_softc *riscv_tmr_sc = NULL;
|
||||
|
||||
static struct resource_spec timer_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
@ -93,30 +104,39 @@ static struct timecounter riscv_tmr_timecount = {
|
||||
};
|
||||
|
||||
static long
|
||||
get_counts(void)
|
||||
get_counts(struct riscv_tmr_softc *sc)
|
||||
{
|
||||
|
||||
return (csr_read(stime));
|
||||
return (READ8(sc, TIMER_COUNTS));
|
||||
}
|
||||
|
||||
static unsigned
|
||||
riscv_tmr_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
struct riscv_tmr_softc *sc;
|
||||
|
||||
return (get_counts());
|
||||
sc = tc->tc_priv;
|
||||
|
||||
return (get_counts(sc));
|
||||
}
|
||||
|
||||
static int
|
||||
riscv_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
|
||||
{
|
||||
struct riscv_tmr_softc *sc;
|
||||
int counts;
|
||||
uint64_t counts;
|
||||
int cpu;
|
||||
|
||||
sc = (struct riscv_tmr_softc *)et->et_priv;
|
||||
|
||||
if (first != 0) {
|
||||
counts = ((uint32_t)et->et_frequency * first) >> 32;
|
||||
counts += READ8(sc, TIMER_COUNTS);
|
||||
cpu = PCPU_GET(cpuid);
|
||||
WRITE8(sc, TIMER_MTIMECMP(cpu), counts);
|
||||
csr_set(sie, SIE_STIE);
|
||||
machine_command(ECALL_MTIMECMP, counts);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -143,13 +163,7 @@ riscv_tmr_intr(void *arg)
|
||||
|
||||
sc = (struct riscv_tmr_softc *)arg;
|
||||
|
||||
/*
|
||||
* Clear interrupt pending bit.
|
||||
* Note: SIP_STIP bit is not implemented in sip register
|
||||
* in Spike simulator, so use machine command to clear
|
||||
* interrupt pending bit in mip.
|
||||
*/
|
||||
machine_command(ECALL_CLEAR_PENDING, 0);
|
||||
csr_clear(sip, SIP_STIP);
|
||||
|
||||
if (sc->et.et_active)
|
||||
sc->et.et_event_cb(&sc->et, sc->et.et_arg);
|
||||
@ -207,17 +221,22 @@ riscv_tmr_attach(device_t dev)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
riscv_tmr_sc = sc;
|
||||
|
||||
/* Setup IRQs handler */
|
||||
error = bus_setup_intr(dev, sc->res[0], INTR_TYPE_CLK,
|
||||
riscv_tmr_intr, NULL, sc, &sc->ihl[0]);
|
||||
error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK,
|
||||
riscv_tmr_intr, NULL, sc, &sc->ih);
|
||||
if (error) {
|
||||
device_printf(dev, "Unable to alloc int resource.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
riscv_tmr_timecount.tc_frequency = sc->clkfreq;
|
||||
riscv_tmr_timecount.tc_priv = sc;
|
||||
tc_init(&riscv_tmr_timecount);
|
||||
|
||||
sc->et.et_name = "RISC-V Eventtimer";
|
||||
@ -257,8 +276,8 @@ EARLY_DRIVER_MODULE(timer, ofwbus, riscv_tmr_fdt_driver, riscv_tmr_fdt_devclass,
|
||||
void
|
||||
DELAY(int usec)
|
||||
{
|
||||
int32_t counts, counts_per_usec;
|
||||
uint32_t first, last;
|
||||
int64_t counts, counts_per_usec;
|
||||
uint64_t first, last;
|
||||
|
||||
/*
|
||||
* Check the timers are setup, if not just
|
||||
@ -289,11 +308,11 @@ DELAY(int usec)
|
||||
else
|
||||
counts = usec * counts_per_usec;
|
||||
|
||||
first = get_counts();
|
||||
first = get_counts(riscv_tmr_sc);
|
||||
|
||||
while (counts > 0) {
|
||||
last = get_counts();
|
||||
counts -= (int32_t)(last - first);
|
||||
last = get_counts(riscv_tmr_sc);
|
||||
counts -= (int64_t)(last - first);
|
||||
first = last;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by SRI International and the
|
||||
@ -211,7 +211,7 @@ data_abort(struct trapframe *frame, int lower)
|
||||
|
||||
va = trunc_page(sbadaddr);
|
||||
|
||||
if (frame->tf_scause == EXCP_STORE_ACCESS_FAULT) {
|
||||
if (frame->tf_scause == EXCP_FAULT_STORE) {
|
||||
ftype = (VM_PROT_READ | VM_PROT_WRITE);
|
||||
} else {
|
||||
ftype = (VM_PROT_READ);
|
||||
@ -269,6 +269,12 @@ void
|
||||
do_trap_supervisor(struct trapframe *frame)
|
||||
{
|
||||
uint64_t exception;
|
||||
uint64_t sstatus;
|
||||
|
||||
/* Ensure we came from supervisor mode, interrupts disabled */
|
||||
__asm __volatile("csrr %0, sstatus" : "=&r" (sstatus));
|
||||
KASSERT((sstatus & (SSTATUS_SPP | SSTATUS_SIE)) == SSTATUS_SPP,
|
||||
("We must came from S mode with interrupts disabled"));
|
||||
|
||||
exception = (frame->tf_scause & EXCP_MASK);
|
||||
if (frame->tf_scause & EXCP_INTR) {
|
||||
@ -286,12 +292,12 @@ do_trap_supervisor(struct trapframe *frame)
|
||||
curthread, frame->tf_sepc, frame);
|
||||
|
||||
switch(exception) {
|
||||
case EXCP_LOAD_ACCESS_FAULT:
|
||||
case EXCP_STORE_ACCESS_FAULT:
|
||||
case EXCP_INSTR_ACCESS_FAULT:
|
||||
case EXCP_FAULT_LOAD:
|
||||
case EXCP_FAULT_STORE:
|
||||
case EXCP_FAULT_FETCH:
|
||||
data_abort(frame, 0);
|
||||
break;
|
||||
case EXCP_INSTR_BREAKPOINT:
|
||||
case EXCP_BREAKPOINT:
|
||||
#ifdef KDTRACE_HOOKS
|
||||
if (dtrace_invop_jump_addr != 0) {
|
||||
dtrace_invop_jump_addr(frame);
|
||||
@ -305,7 +311,7 @@ do_trap_supervisor(struct trapframe *frame)
|
||||
panic("No debugger in kernel.\n");
|
||||
#endif
|
||||
break;
|
||||
case EXCP_INSTR_ILLEGAL:
|
||||
case EXCP_ILLEGAL_INSTRUCTION:
|
||||
dump_regs(frame);
|
||||
panic("Illegal instruction at 0x%016lx\n", frame->tf_sepc);
|
||||
break;
|
||||
@ -321,10 +327,16 @@ do_trap_user(struct trapframe *frame)
|
||||
{
|
||||
uint64_t exception;
|
||||
struct thread *td;
|
||||
uint64_t sstatus;
|
||||
|
||||
td = curthread;
|
||||
td->td_frame = frame;
|
||||
|
||||
/* Ensure we came from usermode, interrupts disabled */
|
||||
__asm __volatile("csrr %0, sstatus" : "=&r" (sstatus));
|
||||
KASSERT((sstatus & (SSTATUS_SPP | SSTATUS_SIE)) == 0,
|
||||
("We must came from U mode with interrupts disabled"));
|
||||
|
||||
exception = (frame->tf_scause & EXCP_MASK);
|
||||
if (frame->tf_scause & EXCP_INTR) {
|
||||
/* Interrupt */
|
||||
@ -336,20 +348,20 @@ do_trap_user(struct trapframe *frame)
|
||||
curthread, frame->tf_sepc, frame);
|
||||
|
||||
switch(exception) {
|
||||
case EXCP_LOAD_ACCESS_FAULT:
|
||||
case EXCP_STORE_ACCESS_FAULT:
|
||||
case EXCP_INSTR_ACCESS_FAULT:
|
||||
case EXCP_FAULT_LOAD:
|
||||
case EXCP_FAULT_STORE:
|
||||
case EXCP_FAULT_FETCH:
|
||||
data_abort(frame, 1);
|
||||
break;
|
||||
case EXCP_UMODE_ENV_CALL:
|
||||
case EXCP_USER_ECALL:
|
||||
frame->tf_sepc += 4; /* Next instruction */
|
||||
svc_handler(frame);
|
||||
break;
|
||||
case EXCP_INSTR_ILLEGAL:
|
||||
case EXCP_ILLEGAL_INSTRUCTION:
|
||||
call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_sepc);
|
||||
userret(td, frame);
|
||||
break;
|
||||
case EXCP_INSTR_BREAKPOINT:
|
||||
case EXCP_BREAKPOINT:
|
||||
call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_sepc);
|
||||
userret(td, frame);
|
||||
break;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed by SRI International and the
|
||||
@ -86,7 +86,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
/* Arguments for child */
|
||||
tf->tf_a[0] = 0;
|
||||
tf->tf_a[1] = 0;
|
||||
tf->tf_sstatus = SSTATUS_PIE;
|
||||
tf->tf_sstatus = (SSTATUS_SPIE);
|
||||
tf->tf_sstatus |= (MSTATUS_PRV_U << MSTATUS_SPP_SHIFT);
|
||||
|
||||
td2->td_frame = tf;
|
||||
|
||||
@ -98,7 +99,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
|
||||
/* Setup to release spin count in fork_exit(). */
|
||||
td2->td_md.md_spinlock_count = 1;
|
||||
td2->td_md.md_saved_sstatus_ie = 1;
|
||||
td2->td_md.md_saved_sstatus_ie = (SSTATUS_SIE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -166,7 +167,7 @@ cpu_copy_thread(struct thread *td, struct thread *td0)
|
||||
|
||||
/* Setup to release spin count in fork_exit(). */
|
||||
td->td_md.md_spinlock_count = 1;
|
||||
td->td_md.md_saved_sstatus_ie = 1;
|
||||
td->td_md.md_saved_sstatus_ie = (SSTATUS_SIE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user