Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163431820
D58237.id181997.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D58237.id181997.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D58237: exterror(9): dynamic kernel categories
Attached
Detach File
Event Timeline
Log In to Comment