sys/info: more CPU feature detection for RISC-V

This commit is contained in:
laytan
2024-09-02 14:06:19 +00:00
parent 28c643d23f
commit 35731e66cf
6 changed files with 297 additions and 29 deletions
+89 -22
View File
@@ -8,35 +8,102 @@ import "core:sys/linux"
@(init, private)
init_cpu_features :: proc() {
fd, err := linux.open("/proc/self/auxv", {})
if err != .NONE { return }
defer linux.close(fd)
_features: CPU_Features
defer cpu_features = _features
// This is probably enough right?
buf: [4096]byte
n, rerr := linux.read(fd, buf[:])
if rerr != .NONE || n == 0 { return }
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]
ulong :: u64
AT_HWCAP :: 16
// 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)
// TODO: using these we could get more information than just the basics.
// AT_HWCAP2 :: 26
// AT_HWCAP3 :: 29
// AT_HWCAP4 :: 30
// This is probably enough right?
buf: [4096]byte
n, rerr := linux.read(fd, buf[:])
if rerr != .NONE || n == 0 { return }
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):]
ulong :: u64
AT_HWCAP :: 16
if key != AT_HWCAP {
continue
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
}
cpu_features = transmute(CPU_Features)(val)
break
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 }
}
}
}
}
+91 -7
View File
@@ -1,13 +1,97 @@
package sysinfo
CPU_Feature :: enum u64 {
I = 'I' - 'A', // Base features, don't think this is ever not here.
M = 'M' - 'A', // Integer multiplication and division, currently required by Odin.
A = 'A' - 'A', // Atomics.
F = 'F' - 'A', // Single precision floating point, currently required by Odin.
D = 'D' - 'A', // Double precision floating point, currently required by Odin.
C = 'C' - 'A', // Compressed instructions.
V = 'V' - 'A', // Vector operations.
// Bit-Manipulation ISA Extensions v1.
Zba = 3,
Zbb,
Zbs,
// CMOs (ratified).
Zicboz,
// Bit-Manipulation ISA Extensions v1.
Zbc,
// Scalar Crypto ISA extensions v1.
Zbkb,
Zbkc,
Zbkx,
Zknd,
Zkne,
Zknh,
Zksed,
Zksh,
Zkt,
// Cryptography Extensions Volume II v1.
Zvbb,
Zvbc,
Zvkb,
Zvkg,
Zvkned,
Zvknha,
Zvknhb,
Zvksed,
Zvksh,
Zvkt,
// ISA Manual v1.
Zfh,
Zfhmin,
Zihintntl,
// ISA manual (ratified).
Zvfh,
Zvfhmin,
Zfa,
Ztso,
// Atomic Compare-and-Swap Instructions Manual (ratified).
Zacas,
Zicond,
// ISA manual (ratified).
Zihintpause,
// Vector Extensions Manual v1.
Zve32x,
Zve32f,
Zve64x,
Zve64f,
Zve64d,
// ISA manual (ratified).
Zimop,
// Code Size Reduction (ratified).
Zca,
Zcb,
Zcd,
Zcf,
// ISA manual (ratified).
Zcmop,
Zawrs,
// Base features, don't think this is ever not here.
I,
// Integer multiplication and division, currently required by Odin.
M,
// Atomics.
A,
// Single precision floating point, currently required by Odin.
F,
// Double precision floating point, currently required by Odin.
D,
// Compressed instructions.
C,
// Vector operations.
V,
// Indicates Misaligned Scalar Loads will not trap the program.
Misaligned_Supported,
// Indicates Hardware Support for Misaligned Scalar Loads.
Misaligned_Fast,
}
CPU_Features :: distinct bit_set[CPU_Feature; u64]