123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- #+build riscv64
- #+build linux
- package sysinfo
- import "base:intrinsics"
- import "core:sys/linux"
- @(init, private)
- init_cpu_features :: proc() {
- _features: CPU_Features
- defer cpu_features = _features
- HWCAP_Bits :: enum u64 {
- I = 'I' - 'A',
- M = 'M' - 'A',
- A = 'A' - 'A',
- F = 'F' - 'A',
- D = 'D' - 'A',
- C = 'C' - 'A',
- V = 'V' - 'A',
- }
- HWCAP :: bit_set[HWCAP_Bits; u64]
- // Read HWCAP for base extensions, we can get this info through hwprobe too but that is Linux 6.4+ only.
- {
- fd, err := linux.open("/proc/self/auxv", {})
- if err != .NONE { return }
- defer linux.close(fd)
- // This is probably enough right?
- buf: [4096]byte
- n, rerr := linux.read(fd, buf[:])
- if rerr != .NONE || n == 0 { return }
- ulong :: u64
- AT_HWCAP :: 16
- auxv := buf[:n]
- for len(auxv) >= size_of(ulong)*2 {
- key := intrinsics.unaligned_load((^ulong)(&auxv[0]))
- val := intrinsics.unaligned_load((^ulong)(&auxv[size_of(ulong)]))
- auxv = auxv[2*size_of(ulong):]
- if key != AT_HWCAP {
- continue
- }
- cap := transmute(HWCAP)(val)
- if .I in cap {
- _features += { .I }
- }
- if .M in cap {
- _features += { .M }
- }
- if .A in cap {
- _features += { .A }
- }
- if .F in cap {
- _features += { .F }
- }
- if .D in cap {
- _features += { .D }
- }
- if .C in cap {
- _features += { .C }
- }
- if .V in cap {
- _features += { .V }
- }
- break
- }
- }
- // hwprobe for other features.
- {
- pairs := []linux.RISCV_HWProbe{
- { key = .IMA_EXT_0 },
- { key = .CPUPERF_0 },
- { key = .MISALIGNED_SCALAR_PERF },
- }
- err := linux.riscv_hwprobe(raw_data(pairs), len(pairs), 0, nil, {})
- if err != nil {
- assert(err == .ENOSYS, "unexpected error from riscv_hwprobe()")
- return
- }
- assert(pairs[0].key == .IMA_EXT_0)
- exts := pairs[0].value.ima_ext_0
- exts -= { .FD, .C, .V }
- _features += transmute(CPU_Features)exts
- if pairs[2].key == .MISALIGNED_SCALAR_PERF {
- if pairs[2].value.misaligned_scalar_perf == .FAST {
- _features += { .Misaligned_Supported, .Misaligned_Fast }
- } else if pairs[2].value.misaligned_scalar_perf != .UNSUPPORTED {
- _features += { .Misaligned_Supported }
- }
- } else {
- assert(pairs[1].key == .CPUPERF_0)
- if .FAST in pairs[1].value.cpu_perf_0 {
- _features += { .Misaligned_Supported, .Misaligned_Fast }
- } else if .UNSUPPORTED not_in pairs[1].value.cpu_perf_0 {
- _features += { .Misaligned_Supported }
- }
- }
- }
- }
- @(init, private)
- init_cpu_name :: proc() {
- cpu_name = "RISCV64"
- }
|