Browse Source

New M-mode timer and SBI call to use it

pull/12/head
Andrew Waterman 11 years ago
parent
commit
a6da37f217
  1. 78
      pk/encoding.h
  2. 1
      pk/mcall.h
  3. 34
      pk/mentry.S
  4. 6
      pk/minit.c
  5. 15
      pk/mtrap.c
  6. 1
      pk/sbi.S
  7. 1
      pk/sbi.h
  8. 6
      pk/sbi_entry.S

78
pk/encoding.h

@ -221,47 +221,63 @@
#define MASK_BLTU 0x707f
#define MATCH_BNE 0x1063
#define MASK_BNE 0x707f
#define MATCH_C_ADD 0x6000
#define MATCH_C_ADD 0x1000
#define MASK_C_ADD 0xf003
#define MATCH_C_ADDI 0x8000
#define MATCH_C_ADD3 0xa000
#define MASK_C_ADD3 0xe063
#define MATCH_C_ADDI 0xc002
#define MASK_C_ADDI 0xe003
#define MATCH_C_ADDI4 0xa000
#define MASK_C_ADDI4 0xe003
#define MATCH_C_ADDIW 0xe000
#define MATCH_C_ADDI4SPN 0xa001
#define MASK_C_ADDI4SPN 0xe003
#define MATCH_C_ADDIW 0xe002
#define MASK_C_ADDIW 0xe003
#define MATCH_C_ADDW 0x7000
#define MATCH_C_ADDW 0x9000
#define MASK_C_ADDW 0xf003
#define MATCH_C_BEQZ 0x2002
#define MATCH_C_AND3 0xa060
#define MASK_C_AND3 0xe063
#define MATCH_C_BEQZ 0x4002
#define MASK_C_BEQZ 0xe003
#define MATCH_C_BNEZ 0x6002
#define MASK_C_BNEZ 0xe003
#define MATCH_C_J 0xa002
#define MATCH_C_J 0x2
#define MASK_C_J 0xe003
#define MATCH_C_JALR 0x5000
#define MASK_C_JALR 0xf003
#define MATCH_C_LD 0x2001
#define MATCH_C_JAL 0x2002
#define MASK_C_JAL 0xe003
#define MATCH_C_LD 0xe000
#define MASK_C_LD 0xe003
#define MATCH_C_LDSP 0xc001
#define MATCH_C_LDSP 0xe001
#define MASK_C_LDSP 0xe003
#define MATCH_C_LI 0x0
#define MATCH_C_LI 0x8002
#define MASK_C_LI 0xe003
#define MATCH_C_LUI 0x2000
#define MATCH_C_LUI 0xa002
#define MASK_C_LUI 0xe003
#define MATCH_C_LW 0x1
#define MATCH_C_LW 0xc000
#define MASK_C_LW 0xe003
#define MATCH_C_LWSP 0x8001
#define MATCH_C_LWSP 0xc001
#define MASK_C_LWSP 0xe003
#define MATCH_C_MV 0x4000
#define MATCH_C_MV 0x0
#define MASK_C_MV 0xf003
#define MATCH_C_SD 0x6001
#define MATCH_C_OR3 0xa040
#define MASK_C_OR3 0xe063
#define MATCH_C_SD 0x6000
#define MASK_C_SD 0xe003
#define MATCH_C_SDSP 0xe001
#define MATCH_C_SDSP 0x6001
#define MASK_C_SDSP 0xe003
#define MATCH_C_SLLI 0xc000
#define MATCH_C_SLLI 0x1
#define MASK_C_SLLI 0xe003
#define MATCH_C_SW 0x4001
#define MATCH_C_SLLIW 0x8001
#define MASK_C_SLLIW 0xe003
#define MATCH_C_SRAI 0x2000
#define MASK_C_SRAI 0xe003
#define MATCH_C_SRLI 0x2001
#define MASK_C_SRLI 0xe003
#define MATCH_C_SUB 0x8000
#define MASK_C_SUB 0xf003
#define MATCH_C_SUB3 0xa020
#define MASK_C_SUB3 0xe063
#define MATCH_C_SW 0x4000
#define MASK_C_SW 0xe003
#define MATCH_C_SWSP 0xa001
#define MATCH_C_SWSP 0x4001
#define MASK_C_SWSP 0xe003
#define MATCH_CSRRC 0x3073
#define MASK_CSRRC 0x707f
@ -551,7 +567,6 @@
#define CSR_SSTATUS 0x100
#define CSR_STVEC 0x101
#define CSR_SIE 0x104
#define CSR_STIMECMP 0x121
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
#define CSR_SIP 0x144
@ -590,6 +605,7 @@
#define CSR_INSTRETHW 0x982
#define CSR_STIMEH 0xd81
#define CSR_STIMEHW 0xa81
#define CSR_MTIMECMPH 0x361
#define CSR_MTIMEH 0x741
#define CAUSE_MISALIGNED_FETCH 0x0
#define CAUSE_FAULT_FETCH 0x1
@ -637,14 +653,16 @@ DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
DECLARE_INSN(c_add3, MATCH_C_ADD3, MASK_C_ADD3)
DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
DECLARE_INSN(c_addi4, MATCH_C_ADDI4, MASK_C_ADDI4)
DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
DECLARE_INSN(c_and3, MATCH_C_AND3, MASK_C_AND3)
DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR)
DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
@ -652,9 +670,15 @@ DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
DECLARE_INSN(c_or3, MATCH_C_OR3, MASK_C_OR3)
DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
DECLARE_INSN(c_slliw, MATCH_C_SLLIW, MASK_C_SLLIW)
DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
DECLARE_INSN(c_sub3, MATCH_C_SUB3, MASK_C_SUB3)
DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
@ -816,7 +840,6 @@ DECLARE_CSR(uarch15, CSR_UARCH15)
DECLARE_CSR(sstatus, CSR_SSTATUS)
DECLARE_CSR(stvec, CSR_STVEC)
DECLARE_CSR(sie, CSR_SIE)
DECLARE_CSR(stimecmp, CSR_STIMECMP)
DECLARE_CSR(sscratch, CSR_SSCRATCH)
DECLARE_CSR(sepc, CSR_SEPC)
DECLARE_CSR(sip, CSR_SIP)
@ -855,6 +878,7 @@ DECLARE_CSR(timehw, CSR_TIMEHW)
DECLARE_CSR(instrethw, CSR_INSTRETHW)
DECLARE_CSR(stimeh, CSR_STIMEH)
DECLARE_CSR(stimehw, CSR_STIMEHW)
DECLARE_CSR(mtimecmph, CSR_MTIMECMPH)
DECLARE_CSR(mtimeh, CSR_MTIMEH)
#endif
#ifdef DECLARE_CAUSE
@ -884,7 +908,6 @@ DECLARE_CAUSE("uarch15", CAUSE_UARCH15)
DECLARE_CAUSE("sstatus", CAUSE_SSTATUS)
DECLARE_CAUSE("stvec", CAUSE_STVEC)
DECLARE_CAUSE("sie", CAUSE_SIE)
DECLARE_CAUSE("stimecmp", CAUSE_STIMECMP)
DECLARE_CAUSE("sscratch", CAUSE_SSCRATCH)
DECLARE_CAUSE("sepc", CAUSE_SEPC)
DECLARE_CAUSE("sip", CAUSE_SIP)
@ -923,5 +946,6 @@ DECLARE_CAUSE("timehw", CAUSE_TIMEHW)
DECLARE_CAUSE("instrethw", CAUSE_INSTRETHW)
DECLARE_CAUSE("stimeh", CAUSE_STIMEH)
DECLARE_CAUSE("stimehw", CAUSE_STIMEHW)
DECLARE_CAUSE("mtimecmph", CAUSE_MTIMECMPH)
DECLARE_CAUSE("mtimeh", CAUSE_MTIMEH)
#endif

1
pk/mcall.h

@ -8,6 +8,7 @@
#define MCALL_SEND_IPI 4
#define MCALL_CLEAR_IPI 5
#define MCALL_SHUTDOWN 6
#define MCALL_SET_TIMER 7
#ifndef __ASSEMBLER__

34
pk/mentry.S

@ -162,23 +162,21 @@ mentry:
.Linterrupt:
sll a0, a0, 1 # discard MSB
# See if this is a timer interrupt; post a supervisor interrupt if so.
li a1, IRQ_TIMER * 2
# Send timer interrupts to the OS.
beq a0, a1, .Lmrts
# See if this is an IPI; register a supervisor SW interrupt if so.
#if IRQ_SOFT != 0
#error
#endif
bnez a0, 1f
csrr a0, mstatus
csrc mip, MIP_MSIP
csrs mip, MIP_SSIP
bne a0, a1, 1f
li a0, MIP_MTIP
csrc mip, a0
li a1, MIP_STIP
csrc mie, a0
csrs mip, a1
.Linterrupt_supervisor:
# There are three cases: PRV1=U; PRV1=S and IE1=1; and PRV1=S and IE1=0.
# For cases 1-2, do an MRTS; for case 3, we can't, so ERET.
and a0, a0, MSTATUS_PRV1 | MSTATUS_IE1
csrr a0, mstatus
li a1, (MSTATUS_PRV1 & ~(MSTATUS_PRV1<<1)) * PRV_S
and a0, a0, MSTATUS_PRV1 | MSTATUS_IE1
bne a0, a1, .Lmrts
# And then go back whence we came.
@ -186,6 +184,16 @@ mentry:
LOAD a1, 11*REGBYTES(sp)
csrrw sp, mscratch, sp
eret
1:
# See if this is an IPI; register a supervisor SW interrupt if so.
#if IRQ_SOFT != 0
#error
#endif
bnez a0, 1f
csrc mip, MIP_MSIP
csrs mip, MIP_SSIP
j .Linterrupt_supervisor
1:
# See if this is an HTIF interrupt; if so, handle it in machine mode.

6
pk/minit.c

@ -79,8 +79,10 @@ static void init_other_hart()
write_csr(sptbr, root_page_table);
// then make sure we're in bounds
if (HLS()->hart_id >= num_harts)
panic("too many harts");
if (HLS()->hart_id >= num_harts) {
while (1)
wfi();
}
boot_other_hart();
}

15
pk/mtrap.c

@ -207,6 +207,18 @@ static uintptr_t mcall_shutdown()
return 0;
}
static uintptr_t mcall_set_timer(unsigned long long when)
{
// bbl/pk don't use the timer, so there's no need to virtualize it
write_csr(mtimecmp, when);
#ifndef __riscv64
write_csr(mtimecmph, when >> 32);
#endif
clear_csr(mip, MIP_STIP);
set_csr(mie, MIP_MTIP);
return 0;
}
uintptr_t mcall_trap(uintptr_t mcause, uintptr_t* regs)
{
uintptr_t n = regs[17], arg0 = regs[10], retval;
@ -233,6 +245,9 @@ uintptr_t mcall_trap(uintptr_t mcause, uintptr_t* regs)
case MCALL_SHUTDOWN:
retval = mcall_shutdown();
break;
case MCALL_SET_TIMER:
retval = mcall_set_timer(arg0);
break;
default:
retval = -ENOSYS;
break;

1
pk/sbi.S

@ -8,3 +8,4 @@
.globl sbi_clear_ipi; sbi_clear_ipi = -1936
.globl sbi_timebase; sbi_timebase = -1920
.globl sbi_shutdown; sbi_shutdown = -1904
.globl sbi_set_timer; sbi_set_timer = -1888

1
pk/sbi.h

@ -12,6 +12,7 @@ unsigned long sbi_query_memory(unsigned long id, memory_block_info *p);
unsigned long sbi_hart_id(void);
unsigned long sbi_num_harts(void);
unsigned long sbi_timebase(void);
void sbi_set_timer(unsigned long long stime_value);
void sbi_send_ipi(unsigned long hart_id);
unsigned long sbi_clear_ipi(void);
void sbi_console_putchar(unsigned long ch);

6
pk/sbi_entry.S

@ -65,6 +65,12 @@ sbi_base:
li a7, MCALL_SHUTDOWN
ecall
# set_timer
.align 4
li a7, MCALL_SET_TIMER
ecall
ret
# end of SBI trampolines
.globl do_mcall

Loading…
Cancel
Save