summaryrefslogtreecommitdiffstats
path: root/src/detection/gpu/gpu_gnu.c
diff options
context:
space:
mode:
authorsumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
committersumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
commit76424950e373d3b04ac3dd13019151bfba3e8423 (patch)
tree4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/gpu/gpu_gnu.c
Add the files
Diffstat (limited to 'src/detection/gpu/gpu_gnu.c')
-rw-r--r--src/detection/gpu/gpu_gnu.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/detection/gpu/gpu_gnu.c b/src/detection/gpu/gpu_gnu.c
new file mode 100644
index 0000000..27c774b
--- /dev/null
+++ b/src/detection/gpu/gpu_gnu.c
@@ -0,0 +1,146 @@
+#include "gpu.h"
+#include "common/io.h"
+
+#include <hurd.h>
+#include <hurd/pci.h>
+#include <hurd/paths.h>
+
+enum {
+ PCI_VENDOR_ID = 0x00,
+ PCI_DEVICE_ID = 0x02,
+ PCI_REVISION_ID = 0x08,
+ PCI_CLASS_PROG = 0x09,
+ PCI_SUBCLASS = 0x0a,
+ PCI_CLASS_DEVICE = 0x0b,
+ PCI_CONF_SIZE = 0x40,
+};
+
+const char* ffDetectGPUImpl(FF_A_UNUSED const FFGPUOptions* options, FFlist* gpus) {
+ int dDomainFd = open(_SERVERS_BUS "/pci/0000", O_RDONLY | O_CLOEXEC);
+ if (dDomainFd < 0) {
+ return "open(_SERVERS_BUS \"/pci/0000\") failed";
+ }
+
+ FF_AUTO_CLOSE_DIR DIR* dirDomain = fdopendir(dDomainFd);
+ if (dirDomain == NULL) {
+ return "fdopendir(domain) failed";
+ }
+
+ struct dirent* busEntry;
+ while ((busEntry = readdir(dirDomain)) != NULL) {
+ if (busEntry->d_type != DT_DIR || busEntry->d_name[0] == '.') {
+ continue;
+ }
+
+ char* endptr;
+ uint16_t pciBus = (uint16_t) strtoul(busEntry->d_name, &endptr, 16);
+ if (*endptr != '\0') {
+ continue;
+ }
+
+ int dBusFd = openat(dDomainFd, busEntry->d_name, O_RDONLY | O_CLOEXEC);
+ if (dBusFd < 0) {
+ continue;
+ }
+
+ FF_AUTO_CLOSE_DIR DIR* dirBus = fdopendir(dBusFd);
+ if (dirBus == NULL) {
+ continue;
+ }
+
+ struct dirent* devEntry;
+ while ((devEntry = readdir(dirBus)) != NULL) {
+ if (devEntry->d_type != DT_DIR || devEntry->d_name[0] == '.') {
+ continue;
+ }
+
+ uint8_t pciDev = (uint8_t) strtoul(devEntry->d_name, &endptr, 16);
+ if (*endptr != '\0') {
+ continue;
+ }
+
+ int dDevFd = openat(dBusFd, devEntry->d_name, O_RDONLY | O_CLOEXEC);
+ if (dDevFd < 0) {
+ continue;
+ }
+
+ FF_AUTO_CLOSE_DIR DIR* dirDev = fdopendir(dDevFd);
+ if (dirDev == NULL) {
+ continue;
+ }
+
+ struct dirent* funcEntry;
+ while ((funcEntry = readdir(dirDev)) != NULL) {
+ if (funcEntry->d_type != DT_DIR || funcEntry->d_name[0] == '.') {
+ continue;
+ }
+
+ uint8_t pciFunc = (uint8_t) strtoul(funcEntry->d_name, &endptr, 16);
+ if (*endptr != '\0') {
+ continue;
+ }
+
+ char subpath[PATH_MAX];
+ snprintf(subpath, ARRAY_SIZE(subpath), "%s/%s/%s/%s/config", _SERVERS_BUS "/pci/0000", busEntry->d_name, devEntry->d_name, funcEntry->d_name);
+
+ mach_port_t devicePort = file_name_lookup(subpath, 0, 0);
+ if (devicePort == MACH_PORT_NULL) {
+ continue;
+ }
+
+ mach_msg_type_number_t nread = 0;
+
+ uint8_t data[PCI_CONF_SIZE];
+ data_t pData = (data_t) data;
+ kern_return_t kr = pci_conf_read(devicePort, 0, &pData, &nread, PCI_CONF_SIZE);
+ mach_port_deallocate(mach_task_self(), devicePort);
+ if (kr != KERN_SUCCESS || nread < PCI_CONF_SIZE) {
+ continue;
+ }
+
+ if (pData != (data_t) data) {
+ memcpy(data, pData, PCI_CONF_SIZE);
+ vm_deallocate(mach_task_self(), (vm_address_t) pData, nread);
+ }
+
+ uint8_t classBase = data[PCI_CLASS_DEVICE];
+ if (classBase != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) {
+ continue;
+ }
+
+ uint8_t classSub = data[PCI_SUBCLASS];
+ if (pciFunc > 0 && classSub == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/) { // Likely an auxiliary display controller (#2034)
+ continue;
+ }
+
+ uint8_t revision = data[PCI_REVISION_ID];
+ uint16_t vendorId = data[PCI_VENDOR_ID] | (data[PCI_VENDOR_ID + 1] << 8);
+ uint16_t deviceId = data[PCI_DEVICE_ID] | (data[PCI_DEVICE_ID + 1] << 8);
+
+ FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *gpus);
+ ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
+ ffStrbufInit(&gpu->name);
+ ffStrbufInit(&gpu->driver);
+ ffStrbufInitStatic(&gpu->platformApi, "/servers/bus/pci");
+ ffStrbufInit(&gpu->memoryType);
+ gpu->temperature = FF_GPU_TEMP_UNSET;
+ gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
+ gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
+ gpu->type = FF_GPU_TYPE_UNKNOWN;
+ gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
+ gpu->deviceId = ffGPUPciAddr2Id(0, pciBus, pciDev, pciFunc);
+ gpu->frequency = FF_GPU_FREQUENCY_UNSET;
+
+ if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) {
+ ffGPUQueryAmdGpuName(deviceId, revision, gpu);
+ }
+
+ if (gpu->name.length == 0) {
+ ffGPUFillVendorAndName(classSub, vendorId, deviceId, gpu);
+ }
+ }
+ }
+ }
+
+ return NULL;
+}