Update RISC-V port to Privileged Architecture Version 1.9.

Sponsored by:	DARPA, AFRL
Sponsored by:	HEIF5
This commit is contained in:
br 2016-08-02 14:50:14 +00:00
parent a937127683
commit 1167f0cf7c
27 changed files with 577 additions and 525 deletions

View File

@ -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 {

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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[];

View File

@ -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)
);
}

View File

@ -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;

View File

@ -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
};

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);

View File

@ -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();

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}
/*