How to read RISC-V mcycle CSR from Linux userspace app?
From: Maxim Blinov
Date: Mon Jul 25 2022 - 12:58:07 EST
Hi all, stupid question but I can't for the life of me figure this out
even with all the docs open.
I need to get an estimate figure for the cyclecount of a busy loop in
one of my small Linux userspace apps. The app in question is running
in qemu-system-riscv64. I've compiled QEMU myself, and the full code
is like this:
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
uint64_t get_mcycle() {
uint64_t mcycle = 0;
asm volatile ("csrr %0,mcycle" : "=r" (mcycle) );
return mcycle;
}
int main(int argc, char **argv) {
printf("Hello\n");
printf("mcycle is %lu\n", get_mcycle());
return 0;
}
Now I get SIGILL when I hit the `csrr` insn, which makes sense.
According to the "Privileged Architecture Version 1.10", page 32, [1]
we need to set mcounteren, hcounteren, and scounteren low bits to 1 in
order to get the mcycle csr to become available in userspace. So I add
the following function:
void enable_mcount() {
/* Enable IR, TM, CY */
uint64_t mcounteren = 0x5;
asm volatile ("csrw mcounteren,%0" : "=r" (mcounteren));
asm volatile ("csrw hcounteren,%0" : "=r" (mcounteren));
asm volatile ("csrw scounteren,%0" : "=r" (mcounteren));
}
And call it before I call get_mcycle(), but this triggers SIGILL
(unsurprisingly) also, since these CSRs are also privileged. So
there's a bit of a chicken and egg problem.
Could someone more knowledgeable please suggest what the course of
action here is? I've got QEMU revision f45fd24c90 checked out, and I'm
staring at qemu/target/riscv/csr.c:71, which seems to deal with
whether or not to raise a SIGILL upon access. I can see a condition
for when we're in 'S' mode, but nothing for 'U' mode. Does that mean
there is fundamentally no access to these CSR's from 'U' mode? Is it
possible to just hack it in?
Maxim
[1]: https://riscv.org/wp-content/uploads/2017/05/riscv-privileged-v1.10.pdf