google/cpu_features

Add support for riscv64?

yuzibo opened this issue · 14 comments

Hi,
Do we have a plan to support riscv64?
I am willing to do it but maybe need your help.
I am stuck on how to define RiscvFeatures struct:

cat /proc/cpuinfo
processor       : 0
hart            : 2
isa             : rv64imafdc
mmu             : sv39
uarch           : sifive,bullet0

processor       : 1
hart            : 1
isa             : rv64imafdc
mmu             : sv39
uarch           : sifive,bullet0

processor       : 2
hart            : 3
isa             : rv64imafdc
mmu             : sv39
uarch           : sifive,bullet0

processor       : 3
hart            : 4
isa             : rv64imafdc
mmu             : sv39
uarch           : sifive,bullet0

I have a real riscv64 hardware by hand:)

Since riscv cpu identification instructions can only be performed in M-mode. Machine level is the highest level and as far as I understand we can't even run it in userland so the best approach is to parse proc/cpuinfo see Linux implementation https://github.com/google/cpu_features/blob/main/src/impl_x86_linux_or_android.c and the same approach we can use for FreeBSD https://github.com/google/cpu_features/blob/main/src/impl_x86_freebsd.c. if I'm not mistaken macOS and Windows don't support riscv

@yuzibo Which board have you used? I would need this information to add a test

Hi, @DaniAffCH
Thanks for working on that. My locally real riscv64 hardware is Unmatched boards.

Linux unmatched 5.18.0-2-riscv64 #1 SMP Debian 5.18.5-1 (2022-06-16) riscv64 GNU/Linux

So how can I help you to do test?
Or:
You can apply for access to Unmatched boards' resources from here:
https://github.com/plctlab/riscv-lab-access
Any issue please let me know, thanks

More info about Unmatched board is here:
https://www.sifive.com/boards/hifive-unmatched
The machines from plct is the same

Thanks a lot! @yuzibo

Hi @yuzibo, I'm wondering if we can run M-mode code in userspace as is the case with aarch64 for Linux.

Could you run the code under Linux riscv to see if you are getting an illegal instruction or some result, please?

#include <stdio.h>

static unsigned long cpuid()
{
  unsigned long res;
  asm ("csrr %0, mcpuid" : "=r"(res));
  return res;
}

int main() {
   unsigned long mcpuid = cpuid();
   printf("mcpuid: %lu", mcpuid);
   return 0;
}

Oops:

vimer@unmatched:~/build/cpu$ gcc -g get_cpuid.c -o test
get_cpuid.c: Assembler messages:
get_cpuid.c:12: Error: unknown CSR `mcpuid'

It can be compiled but fail on runtime:

vimer@unmatched:~/build/cpu$ gcc -g get_cpuid.c -o test
vimer@unmatched:~/build/cpu$ ./test
Illegal instruction
vimer@unmatched:~/build/cpu$ cat get_cpuid.c
#include <stdio.h>

static unsigned long cpuid()
{
  unsigned long res;
   __asm__ volatile ("csrr %0, misa" : "=r"(res));
  return res;
}

int main() {
   unsigned long misa = cpuid();
   printf("misa: %lu", misa);
   return 0;
}

I think the right way to do this is that the kernel reads the FDT from the boot rom, and uses that to work out which extensions the CPU supports. Then userspace parses /proc/cpuinfo or uses hwcap.h.

There are extensions that aren't in CSR's, and have to be determined from the FDT.

@yuzibo thank you! This is the expected result, but it was necessary to check

@michael-roe, what advantages of using fdt compared with proc/cpuinfo or hwcap? Since we have stable functionality to parse via these features

User space programs (which includes cpu_features) ought to use proc/cpuinfo and/or hwcap.

But the part of the Linux kernel that creates /proc/cpuinfo (and, probably, hwcap) looks at the FDT to work out which options the CPU supports. Some of the information can't be derived just from cpu status registers.

So the basic flow is:

a) kernel reads the FDT from the boot rom, works out what options are supported and saves this info somewhere
b) cpu_features tries to read /proc/cpuinfo
c) kernel remembers the answer from step (a), and returns this in text form as the result of the read of /proc/cpuinfo
d) cpu_features parses the text it got from /proc/cpuinfo

See
https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/cpufeature.c
for the part of the Linux kernel that works out which ISA features are supported.

What I think is happening here is that it's getting the information from the FDT.