I have a HiFive rev b and I’m trying out different things out in assembly. I’m using the command line environment riscv64-unknown-elf-gcc-8.2.0-2019.02.0-x86_64-apple-darwin and the latest version of freedom-e-sdk.
In machine mode I have no problem what so ever to call printf from assembly, but I get no output when calling printf from user mode, nor do I get any output when calling printf in the isr after causing a fault in user mode. What could be the reason?
I have tested several things to find the issue:
- I can call printf successfully from machine mode
- I can read, write and execute in user mode
- I have expanded the stack space
- I have called other methods written in C and there is not problem calling a method such as “int addition(int a, int b)”. Adding printf gives no output.
- if I induce a fault in machine mode then a call to printf in the isr works
- if I induce a fault in user mode then a call to printf gives no printout
- my own methods using the uart works in user mode
- I have checked that the registers such as gp etc have to same values as in machine mode
Here is my C code that calls the assembly:
Blockquote
#include <stdio.h>
extern void assembler();int main() {
assembler();return 0;
}
Here is my assembly ( I don’t know what to do to prevent comments to be interpreted as titles):
.global assembler
.section .text.equ pmp_A, 8 # 0b01 << 3, TOR
.equ pmp_R, 1 # 1, read
.equ pmp_W, 2 # 2, write
.equ pmp_X, 4 # 4, execute
.equ PMP_CONFIG_0, (pmp_A | pmp_X | pmp_W | pmp_R).equ mstatus_mprv, 0x20000 # 1 << 17, mprv = modify privilege
.equ mstatus_mpp, 0x00000 # 0b00 << 11, mpp = privilege mode = user mode
.equ MSTATUS_MODPRIV, (mstatus_mprv | mstatus_mpp).equ mstatus_mpp_mask, 0x01800 # 3 << 11
.equ mstatus_mpp_user, 0 # 0b00 = usermodeassembler:
la a0, mhello
call printfestablish the interrupt service route
la t0, fault
csrw mtvec, t0every address, below max
li t0, -1
srli t0, t0, 2
csrw pmpaddr0, t0from TOR and below, read, write and execute in user mode
li t0, PMP_CONFIG_0
csrw pmpcfg0, t0check protection for user mode according to pmp configuration
csrr t1, mstatus
li t0, MSTATUS_MODPRIV
or t0, t0, t1
csrw mstatus, t0setup user mode registers
csrr t0, mstatus
li t1, mstatus_mpp_mask
not t1, t1
and t0, t0, t1
li t1, mstatus_mpp_user
or t0, t0, t1
csrw mstatus, t0 # indicate that we want user modela sp, ustack
la t0, usermode
csrw mepc, t0
la ra, usermode
mret # “return” to previous mode (carefully set up to be user mode)la a0, wtf
call print_stringret
usermode:
la a0, hello
call printf100:
j 100bfault:
This fails if something happens in user mode…
csrr a2, mstatus
csrr a1, mcause
la a0, error
call printf100:
j 100bhello:
.string “Hello from user mode.\r\n”
mhello:
.string “Hello from machine mode.\r\n”
wtf:
.string “\033[91mWTF?\r\n”
error:
.string “\033[91mInterrupted, cause: 0x%x, mstatus: 0x%x\r\n”.section .data
.balign 16test:
.word 0xdeadbeefguard:
.word 0xdeadbeef # if the stack has been overrun, then this guard will not say 0xdeadbeef anymore.space 24*4
ustack: