mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 22:58:46 +00:00
sys/info: more CPU feature detection for RISC-V
This commit is contained in:
@@ -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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user