15#define LOG_SIZE (1024 * 1024)
17#define PCI_SYSFS_PATH "/sys/bus/pci/devices"
18#define QUADRA_VENDOR_ID 0x1d82
19#define QUADRA_DEVICE_ID 0x0401
23const char *
const core_names[
NUM_CORES] = {
"np",
"dp",
"ep",
"tp",
"fp"};
31 unsigned char *bar4_base;
37int bdf_to_sysfs(
const char* bdf,
char* sysfs_path,
size_t pathsz,
int *domain,
int *bus,
int *slot)
39 unsigned d=0, b=0, s=0, f=0;
40 if (sscanf(bdf,
"%x:%x:%x.%x", &d, &b, &s, &f) != 4)
42 if (snprintf(sysfs_path, pathsz,
"/sys/bus/pci/devices/%04x:%02x:%02x.%x", d, b, s, f) < 0)
44 if (domain) *domain = (int)d;
45 if (bus) *bus = (int)b;
46 if (slot) *slot = (int)s;
50static int safe_realloc_devices(QuadraDevice **p_devs,
int new_cap)
52 QuadraDevice *new_devs = realloc(*p_devs, new_cap *
sizeof(**p_devs));
63int quadra_device_find(QuadraDevice **out_devs)
68 perror(
"opendir(sysfs)");
73 QuadraDevice *devs = calloc(8,
sizeof(*devs));
74 int dev_count = 0, capacity = 8;
82 while ((entry = readdir(dir)))
84 if (entry->d_name[0] ==
'.')
87 if (snprintf(path,
sizeof(path),
"%s/%s",
PCI_SYSFS_PATH, entry->d_name) < 0)
91 if (stat(path, &st) < 0 || !S_ISDIR(st.st_mode))
94 char ven_path[PATH_MAX], dev_path[PATH_MAX];
95 if (snprintf(ven_path,
sizeof(ven_path),
"%s/vendor", path) < 0)
97 if (snprintf(dev_path,
sizeof(dev_path),
"%s/device", path) < 0)
100 FILE *fv = fopen(ven_path,
"r");
105 if (!fgets(buf,
sizeof(buf), fv))
112 unsigned long ven = strtoul(buf, NULL, 0);
117 FILE *fd = fopen(dev_path,
"r");
121 if (!fgets(buf,
sizeof(buf), fd))
128 unsigned long dev = strtoul(buf, NULL, 0);
132 if (dev_count >= capacity)
135 if (safe_realloc_devices(&devs, capacity) < 0)
142 if (bdf_to_sysfs(entry->d_name,
143 devs[dev_count].sysfs_path,
sizeof(devs[dev_count].sysfs_path),
144 &devs[dev_count].domain, &devs[dev_count].bus, &devs[dev_count].slot) == 0)
162int quadra_init_mmap(QuadraDevice *qd)
164 char bar4path[PATH_MAX];
165 struct stat bar4stat;
166 if (snprintf(bar4path,
sizeof(bar4path),
"%s/resource4", qd->sysfs_path) < 0)
170 (void)fprintf(stderr,
"Permission error: You must run as root (sudo)\n");
173 qd->bar4_fd = open(bar4path, O_RDWR | O_SYNC);
174 if (qd->bar4_fd == -1)
176 perror(
"open(bar4)");
179 if (fstat(qd->bar4_fd, &bar4stat) == 0)
181 qd->barsize = bar4stat.st_size;
183 qd->bar4_base = mmap(NULL, qd->barsize, PROT_READ | PROT_WRITE, MAP_SHARED, qd->bar4_fd, 0);
184 if (qd->bar4_base == MAP_FAILED)
187 (void)fprintf(stderr,
"Permission error: Cannot mmap %s. Run as root (sudo).\n", bar4path);
188 else if (errno == EINVAL)
189 (void)fprintf(stderr,
"EINVAL: mmap() on BAR4 failed. Try kernel flag 'iomem=relaxed'.\n");
191 (
void)fprintf(stderr,
"Failed to mmap BAR4 at %s: %s\n", bar4path, strerror(errno));
199void fill_core_log_offsets(QuadraDevice *qd)
201 uint8_t *base = qd->bar4_base;
202 off_t offset = 0xf8f5000;
205 qd->core_log_offsets[i] = *(uint32_t *)(base + offset + 4 * (
size_t)i) & 0x0FFFFFFF;
207 qd->log_size = 1024 * 1024;
210void fill_core_reset_log_offsets(QuadraDevice *qd)
212 uint8_t *base = qd->bar4_base;
213 off_t offset = 0xf8fd0c0;
216 qd->core_log_offsets[i] = *(uint32_t *)(base + offset + 4 * (
size_t)i) & 0x0FFFFFFF;
218 qd->log_size = 64 * 1024;
221int dump_raw_logs(QuadraDevice *qd,
const char *outdir,
bool core_reset_log)
225 fill_core_reset_log_offsets(qd);
229 fill_core_log_offsets(qd);
232 for (
int core_idx = 0; core_idx <
NUM_CORES; ++core_idx)
234 const char *core = core_names[core_idx];
235 uint32_t log_offset = qd->core_log_offsets[core_idx];
236 char fname[PATH_MAX];
237 if (snprintf(fname,
sizeof(fname),
"%s/raw_%s_slot_%02x_%04x.bin",
238 outdir, core, qd->bus, qd->domain) < 0)
continue;
239 FILE *fp = fopen(fname,
"wb");
246 if (fwrite(qd->bar4_base + log_offset, 1, (
size_t)qd->log_size, fp) != (
size_t)qd->log_size)
248 (void)fprintf(stderr,
"Short write on %s\n", fname);
253 if (memcmp(qd->bar4_base + log_offset,
"hashid", 6) == 0)
256 memcpy(hstr, qd->bar4_base + log_offset, 16);
257 (void)fprintf(stderr,
"%s: %s\n", core, hstr);
259 (void)fprintf(stderr,
"[INFO] Dumped log: %s\n", fname);
264int ni_rsrc_log_dump(
const char *outdir,
bool core_reset_log)
266 QuadraDevice *devs = NULL;
267 int ndev = quadra_device_find(&devs);
271 (void)fprintf(stderr,
"[WARN] No Quadra devices found in sysfs (vendor 1d82).\n");
275 for (
int i = 0; i < ndev; ++i)
277 if (quadra_init_mmap(&devs[i]) == 0)
279 int rc = dump_raw_logs(&devs[i], outdir ? outdir :
".", core_reset_log);
280 fail_count += (rc != 0);
284 (void)fprintf(stderr,
"[ERROR] Failed to mmap device %d\n", i);
289 return (fail_count == 0) ? 0 : 2;