Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to read control register mstatus #181

Open
qushaoru opened this issue Aug 13, 2023 · 12 comments
Open

Failed to read control register mstatus #181

qushaoru opened this issue Aug 13, 2023 · 12 comments

Comments

@qushaoru
Copy link

Hello, Sorry for bothering you. I'm a student who has just started learning the RISC-V instruction set. After setting up the environment you provided (program the rocket64y1 bitstream into the VC707 board and running the Linux system), I wanted to read the control register 'mstatus' through inline assembly in C language. I'm using the g++ compiler directly from apt-get on the Linux system, without adding any compiler options (g++ ./main.cpp -o main). The inline assembly code is as follows:

inline unsigned long int read_mstatus() {
    unsigned long int value;
    __asm__ volatile ("csrr %0, mstatus" : "=r" (value));
    return value;
}

However, when I run this program as the root user, I encounter the following error message (I have confirmed that the error is generated by the code above):

[42215.872380] spmm[2643]: unhandled signal 4 code 0x1 at 0x0000002ad493680c in spmm[2ad4935000+2000]
[42215.883632] CPU: 0 PID: 2643 Comm: spmm Not tainted 6.3.8-dirty #1
[42215.889971] Hardware name: freechips,rocketchip-vivado (DT)
[42215.895436] epc : 0000002ad493680c ra : 0000002ad49366c4 sp : 0000003fda269850
[42215.902518]  gp : 0000002ad4938800 tp : 0000003f95fe6ec0 t0 : 0000003f963d1290
[42215.909913]  t1 : 0000003f9624284c t2 : 0000000000000006 s0 : 0000003fda269870
[42215.916908]  s1 : 0000003f963a3fa0 a0 : 0000003f963a3fa0 a1 : 0000002ad4936929
[42215.924115]  a2 : 0000000000000020 a3 : 0000000000000000 a4 : 4008000000000000
[42215.931328]  a5 : 0000000000001002 a6 : fefefefefefefeff a7 : 0000000000000040
[42215.938780]  s2 : 0000000000000000 s3 : 0000002ad4937df8 s4 : 0000002ad4936568
[42215.945964]  s5 : 0000003fda269c48 s6 : 0000002ad4937df8 s7 : 0000003f963cfd88
[42215.952931]  s8 : 0000003f963d0030 s9 : 0000000000000000 s10: 0000002ab7d28a4c
[42215.960131]  s11: 0000002ab7d289c0 t3 : 0000003f960b0646 t4 : 000000000010b380
[42215.967337]  t5 : 0000000000000010 t6 : 0000000001e57f2d
[42215.972643] status: 8000000200006020 badaddr: 00000000000027f3 cause: 0000000000000002
Illegal instruction

Could you please advise me on how to resolve this issue?

@eugene-tarassov
Copy link
Owner

By convention, register names starting with letter 'm' belong to the Machine (M) mode of RISC-V processor. Such registers are not accessible from other modes. In particular, Linux processes run in User (U) mode, and similar register is called ustatus. M-mode is running Supervisor Binary Interface (SBI): OpenSBI. I don't know if SBI provides U-mode applications a method to read mstatus.

@qushaoru
Copy link
Author

"I have attempted to access the ustatus control register in user mode with the following code:

inline unsigned long int read_ustatus() {
    unsigned long int value;
    __asm__ volatile ("csrr %0, ustatus" : "=r" (value));
    return value;
}

I have also tried to write a simple Linux driver module to read the mstatus control register:

static int hello_init(void)
{
    printk("Hello kernel world!\n");
    printk("mstatus: %lu\n", read_mstatus());
    printk("Read CSR PASS!\n");
    return 0;
}
...
module_init(hello_init);

However, both of these solutions still result in the error message as shown above. Can this rule out privilege-level issues? Or is it possible that this microarchitecture lacks the implementation of the ustatus control register, and the driver module executed through 'insmod hello.ko' isn't running in the kernel mode of Linux? Additionally, is it possible that this error message could be due to me not including the correct compilation options?"

@eugene-tarassov
Copy link
Owner

is it possible that this microarchitecture lacks the implementation of the ustatus control register

I recommend to try 64b1 config (Rocket Chip) instead of 64y1 (BOOM). Rocket Chip is the original RISC-V reference implementation, the most accurate and stable, while BOOM is an experimental implementation of superscalar RISC-V, it appears incomplete and not 100% stable.

Also, ustatus looks accessible OK in the debugger. So, it is more likely a software issue.

'insmod hello.ko' isn't running in the kernel mode of Linux?

It is running in the kernel mode. However, the Linux kernel runs in RISC-V Supervisor (S) mode, and the register name is sstatus.

is it possible that this error message could be due to me not including the correct compilation options?

I don't know. I don't own GCC :)

@qushaoru
Copy link
Author

If accessing the ustatus control register through a debugger, is the program actually running directly on bare metal, rather than running on Linux system? Or has it been confirmed that an application can directly read the ustatus control register on a 64b1 configuration (Rocket Chip) with Linux system?

@eugene-tarassov
Copy link
Owner

I tried to run the debugger, ustatus in not accessible, sstatus and mstatus work OK. As I understand, a while ago ustatus became part of optional RISC-V N extension, then both the N extension and the register were removed. The latest specs don't mention ustatus.

@qushaoru
Copy link
Author

thank you very much, I get it. However, I have one more question. Is the current Linux system in this project not supporting the 'perf' tool, or is it that the hardware architecture doesn't support the control registers for tracking hardware performance metrics? I noticed in /patches/linux.config there is the following code related to enabling the PMU:

CONFIG_RISCV_PMU=y
CONFIG_RISCV_PMU_LEGACY=y
CONFIG_RISCV_PMU_SBI=y

However, when I log into the operating system, I encounter the situation where 'perf: command not found' occurs.

@eugene-tarassov
Copy link
Owner

To install perf:

sudo apt update
sudo apt upgrade
sudo apt install linux-perf

However, I don't know how much of perf functionality is supported by RISC-V.

@qushaoru
Copy link
Author

Got it, understood.
You previously mentioned that the Linux system running in RISC-V S privilege mode. In that case, which privilege mode do U-Boot and OpenSBI run in? Also, when U-Boot hands over CPU control to the Linux kernel, which privilege mode is the system in at that moment?

@eugene-tarassov
Copy link
Owner

OpenSBI runs in M-mode, U-Boot and Linux kernel - S-mode.

when U-Boot hands over CPU control to the Linux kernel, which privilege mode is the system

S-mode.

@qushaoru
Copy link
Author

Understood, I see. Thank you very much. I have another question regarding rocket64y1. Does this core implement mhpmcounter3-mhpmcounter31 according to the RISC-V instruction set? I've observed a phenomenon where writing 0xffffffff to the mcounteren register results in reading a value of 0x00000007. If the mhpmcounters are implemented, which performance events are supported for recording?

@eugene-tarassov
Copy link
Owner

Does this core implement mhpmcounter3-mhpmcounter31 according to the RISC-V instruction set?

For BOOM implementation details, you better ask BOOM developers at riscv-boom.

@qushaoru
Copy link
Author

ok, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants