Page MenuHomeFreeBSD

D58237.id181997.diff
No OneTemporary

D58237.id181997.diff

diff --git a/share/man/man9/exterror.9 b/share/man/man9/exterror.9
--- a/share/man/man9/exterror.9
+++ b/share/man/man9/exterror.9
@@ -14,6 +14,7 @@
.Nd provide extended error information to userspace
.Sh SYNOPSIS
.Bd -literal -offset left -compact
+#define EXTERR_CATEGORY_DYNAMIC "path/to/this/file.c"
#define EXTERR_CATEGORY EXTERR_CAT_MYCATEGORY
.Ed
.In sys/exterrvar.h
@@ -56,7 +57,13 @@
Before
.Nm
can be used in the given source .c file, the category of extended errors
-should be allocated in the
+must be defined.
+This can be done by setting the
+.Va EXTERR_CATEGORY_DYNAMIC
+macro to a string containing the name of the file relative to
+.Pa src/sys
+directory.
+Alternatively, an entry may be allocated in the
.In sys/exterr_cat.h
file.
The category is the unique integer, that, together with the source
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3979,6 +3979,7 @@
kern/subr_early.c standard
kern/subr_epoch.c standard
kern/subr_eventhandler.c standard
+kern/subr_exterr.c standard
kern/subr_fattime.c standard
kern/subr_firmware.c optional firmware
kern/subr_filter.c standard
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -331,6 +331,40 @@
sx_xlock(&kld_sx);
}
+static void
+linker_file_register_exterr(linker_file_t lf)
+{
+ struct exterr_cat **start, **stop;
+
+ KLD_DPF(FILE,
+ (__func__ ": registering exterror categories for %s\n",
+ lf->filename));
+
+ sx_assert(&kld_sx, SA_XLOCKED);
+
+ if (linker_file_lookup_set(lf, "exterr_cats", &start, &stop, NULL) != 0)
+ return;
+
+ exterr_cat_register_module(start, stop);
+}
+
+static void
+linker_file_unregister_exterr(linker_file_t lf)
+{
+ struct exterr_cat **start, **stop;
+
+ KLD_DPF(FILE,
+ (__func__ ": unregistering exterror categories for %s\n",
+ lf->filename));
+
+ sx_assert(&kld_sx, SA_XLOCKED);
+
+ if (linker_file_lookup_set(lf, "exterr_cats", &start, &stop, NULL) != 0)
+ return;
+
+ exterr_cat_unregister_module(start, stop);
+}
+
/*
* Invoke the LINKER_CTF_GET implementation for this file. Existing
* implementations will load CTF info from the filesystem upon the first call
@@ -500,6 +534,7 @@
#ifdef VIMAGE
LINKER_PROPAGATE_VNETS(lf);
#endif
+ linker_file_register_exterr(lf);
linker_file_sysinit(lf);
lf->flags |= LINKER_FILE_LINKED;
@@ -775,6 +810,7 @@
if ((file->flags & LINKER_FILE_LINKED) != 0) {
file->flags &= ~LINKER_FILE_LINKED;
linker_file_unregister_sysctls(file);
+ linker_file_unregister_exterr(file);
linker_file_sysuninit(file);
EVENTHANDLER_INVOKE(kld_unload, file->filename, file->address,
file->size);
diff --git a/sys/kern/subr_exterr.c b/sys/kern/subr_exterr.c
new file mode 100644
--- /dev/null
+++ b/sys/kern/subr_exterr.c
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 2026 Capabilities Limited
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * This software was developed by Capabilities Limited with funding from
+ * Innovate UK and the Department for Science, Innovation and Technology
+ * for the adoption and diffusion of CHERI technology under project
+ * 10168042 (“CheriBSD feature extraction, maturity, and testing”).
+ *
+ */
+
+#define EXTERR_CATEGORY_DYNAMIC "kern/subr_exterr.c"
+
+#include <sys/param.h>
+#include <sys/exterrvar.h>
+#include <sys/exterr_cat.h>
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/linker_set.h>
+#include <sys/malloc.h>
+#include <sys/linker.h> /* Need MALLOC_DECLARE */
+#include <sys/mutex.h>
+#include <sys/stddef.h>
+#include <sys/sysctl.h>
+
+struct exterr_cat_span {
+ unsigned int first;
+ unsigned int count;
+ struct exterr_cat **cat_sets;
+ TAILQ_ENTRY(exterr_cat_span) entries;
+};
+
+TAILQ_HEAD(exterr_cat_span_head, exterr_cat_span) cat_span_head;
+
+SET_DECLARE(exterr_cats, struct exterr_cat);
+
+static struct exterr_cat_span kern_cats;
+unsigned int ncats;
+struct mtx cat_mtx;
+
+static bool
+exterr_cat_register_set(struct exterr_cat_span *span, struct exterr_cat **start,
+ struct exterr_cat **stop)
+{
+ struct exterr_cat **catp;
+ ptrdiff_t count;
+
+ count = stop - start;
+ if (count < 1)
+ return (true);
+
+ mtx_lock(&cat_mtx);
+
+ if (ncats + count < ncats) {
+ printf("too many exterror categories\n");
+ mtx_unlock(&cat_mtx);
+ return (false);
+ }
+
+ span->first = ncats + 1;
+ for (catp = start; catp < stop; catp++)
+ (*catp)->cat = ++ncats;
+ span->count = count;
+ span->cat_sets = start;
+ TAILQ_INSERT_TAIL(&cat_span_head, span, entries);
+
+ mtx_unlock(&cat_mtx);
+
+ return (true);
+}
+
+void
+exterr_cat_register_module(struct exterr_cat **start, struct exterr_cat **stop)
+{
+ struct exterr_cat_span *span;
+
+ span = malloc(sizeof(*span), M_LINKER, M_WAITOK | M_ZERO);
+ if (!exterr_cat_register_set(span, start, stop))
+ free(span, M_LINKER);
+}
+
+void
+exterr_cat_unregister_module(struct exterr_cat **start,
+ struct exterr_cat **stop)
+{
+ struct exterr_cat_span *span;
+
+ if (stop - start < 1)
+ return;
+
+ mtx_lock(&cat_mtx);
+
+ TAILQ_FOREACH(span, &cat_span_head, entries) {
+ if (span->cat_sets == start) {
+ MPASS(span->first > 1);
+ MPASS(span->count == stop - start);
+ TAILQ_REMOVE(&cat_span_head, span, entries);
+ break;
+ }
+ }
+ KASSERT(span != NULL, ("start not found in spans"));
+ free(span, M_LINKER);
+
+ /*
+ * NB: we leak category numbers on module unload because we can't
+ * reasonably know which ones are in use in running software.
+ */
+
+ mtx_unlock(&cat_mtx);
+}
+
+static void
+exterr_cat_register_kern(void *arg)
+{
+ mtx_init(&cat_mtx, "exterr dynamic categories", NULL, MTX_DEF);
+
+ TAILQ_INIT(&cat_span_head);
+
+ if (SET_COUNT(exterr_cats) == 0)
+ return;
+
+ exterr_cat_register_set(&kern_cats, SET_BEGIN(exterr_cats),
+ SET_LIMIT(exterr_cats));
+}
+SYSINIT(exterr, SI_SUB_KMEM, SI_ORDER_FIRST, exterr_cat_register_kern, NULL);
+
+static int
+sysctl_exterr_categories(SYSCTL_HANDLER_ARGS)
+{
+ struct exterr_cat_span *span;
+ const struct exterr_cat *cat = NULL;
+ int idx;
+
+ if (arg2 != 1)
+ return (EXTERROR(EINVAL,
+ "too many args to kern.exterr.categories %d", arg2));
+
+ idx = *(int *)arg1;
+
+ mtx_lock(&cat_mtx);
+ if (idx < 1 || idx > ncats) {
+ mtx_unlock(&cat_mtx);
+ return (EXTERROR(EINVAL, "category %d out of range (1...%d)",
+ idx, ncats));
+ }
+
+ TAILQ_FOREACH(span, &cat_span_head, entries) {
+ if (idx < span->first)
+ break; /* Not here any more */
+
+ if (idx < span->first + span->count)
+ cat = span->cat_sets[idx - span->first];
+ }
+ mtx_unlock(&cat_mtx);
+
+ if (cat == NULL)
+ return (EXTERROR(ENOENT, "category not found %d", idx));
+ MPASS(cat->cat == idx);
+ return (SYSCTL_OUT(req, cat->file, strlen(cat->file) + 1));
+}
+
+SYSCTL_NODE(_kern, OID_AUTO, exterr, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
+ "Extended error information");
+SYSCTL_UINT(_kern_exterr, OID_AUTO, ncategories, CTLFLAG_RD | CTLFLAG_MPSAFE,
+ &ncats, 0, "Number of dynamic categories");
+SYSCTL_NODE(_kern_exterr, OID_AUTO, categories, CTLFLAG_RD | CTLFLAG_MPSAFE,
+ sysctl_exterr_categories, "Extended error categories");
diff --git a/sys/sys/exterrvar.h b/sys/sys/exterrvar.h
--- a/sys/sys/exterrvar.h
+++ b/sys/sys/exterrvar.h
@@ -14,6 +14,9 @@
#include <sys/_exterr.h>
#include <sys/_uexterror.h>
#include <sys/exterr_cat.h>
+#ifdef EXTERR_CATEGORY_DYNAMIC
+#include <sys/linker_set.h>
+#endif
#define UEXTERROR_MAXLEN 256
@@ -30,8 +33,19 @@
#ifdef _KERNEL
+struct exterr_cat {
+ unsigned int cat;
+ const char *file;
+};
+
struct thread;
+#ifdef EXTERR_CATEGORY_DYNAMIC
+static struct exterr_cat __dynamic_cat = { .file = EXTERR_CATEGORY_DYNAMIC };
+DATA_WSET(exterr_cats, __dynamic_cat);
+#define EXTERR_CATEGORY (__dynamic_cat.cat | EXTERR_CAT_SRC_KERN_DYNAMIC)
+#endif
+
#ifndef EXTERR_CATEGORY
#error "Specify error category before including sys/exterrvar.h"
#endif
@@ -81,6 +95,10 @@
uint64ptr_t pp2, int line);
int exterr_to_ue(struct thread *td, struct uexterror *ue);
void ktrexterr(struct thread *td);
+void exterr_cat_register_module(struct exterr_cat **start,
+ struct exterr_cat **stop);
+void exterr_cat_unregister_module(struct exterr_cat **start,
+ struct exterr_cat **stop);
#else /* !_KERNEL */

File Metadata

Mime Type
text/plain
Expires
Fri, Jul 24, 3:57 AM (3 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35429052
Default Alt Text
D58237.id181997.diff (8 KB)

Event Timeline