summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-05-28 23:51:15 -0400
committerIan Moffett <ian@osmora.org>2025-05-28 23:51:15 -0400
commite15790fa1fa9954f0209a5d589381f99a05521de (patch)
tree686fe00fae42ff45190c4b045a95e42b6372e62e
parent51ca9c82c3e8fb323d238e1f58a085f4cb306110 (diff)
kernel: drivers: Add DRIVER_DEFER() macro
- Add DRIVER_DEFER() macro to schedule initialization for lower priority drivers - Expose `proc0' to the rest of the kernel Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--sys/arch/aarch64/conf/link.ld6
-rw-r--r--sys/arch/amd64/conf/link.ld6
-rw-r--r--sys/include/sys/driver.h61
-rw-r--r--sys/kern/driver_subr.c64
-rw-r--r--sys/kern/init_main.c9
5 files changed, 142 insertions, 4 deletions
diff --git a/sys/arch/aarch64/conf/link.ld b/sys/arch/aarch64/conf/link.ld
index c64cec3..2aa8c93 100644
--- a/sys/arch/aarch64/conf/link.ld
+++ b/sys/arch/aarch64/conf/link.ld
@@ -40,6 +40,12 @@ SECTIONS
__drivers_init_end = .;
} :rodata
+ .drivers.defer : {
+ __driversd_init_start = .;
+ *(.drivers.defer .drivers.defer)
+ __driversd_init_end = .;
+ } :rodata
+
/* Move to the next memory page for .data */
. += CONSTANT(MAXPAGESIZE);
diff --git a/sys/arch/amd64/conf/link.ld b/sys/arch/amd64/conf/link.ld
index 9c47a81..a43824f 100644
--- a/sys/arch/amd64/conf/link.ld
+++ b/sys/arch/amd64/conf/link.ld
@@ -29,6 +29,12 @@ SECTIONS
__drivers_init_end = .;
} :rodata
+ .drivers.defer : {
+ __driversd_init_start = .;
+ *(.drivers.defer .drivers.defer)
+ __driversd_init_end = .;
+ } :rodata
+
. += CONSTANT(MAXPAGESIZE);
.data : {
diff --git a/sys/include/sys/driver.h b/sys/include/sys/driver.h
index 05c40fa..6e4a267 100644
--- a/sys/include/sys/driver.h
+++ b/sys/include/sys/driver.h
@@ -31,27 +31,88 @@
#define _SYS_DRIVER_H_
#include <sys/cdefs.h>
+#include <sys/proc.h>
+#include <sys/types.h>
#if defined(_KERNEL)
+/* Variable driver data */
+struct driver_var {
+ uint8_t deferred : 1;
+};
+
struct driver {
int(*init)(void);
+ struct driver_var *data;
};
+extern struct proc g_proc0;
+
+/* Early (high priority) drivers */
extern char __drivers_init_start[];
extern char __drivers_init_end[];
+/* Deferred (low priority) drivers */
+extern char __driversd_init_start[];
+extern char __driversd_init_end[];
+
#define DRIVER_EXPORT(INIT) \
+ static struct driver_var __driver_var = { \
+ .deferred = 0 \
+ }; \
+ \
__attribute__((used, section(".drivers"))) \
static struct driver __driver_desc = { \
.init = INIT, \
+ .data = &__driver_var \
+ }
+
+/*
+ * Some drivers are not required to start up
+ * early for proper system operation and may
+ * be deferred to start at a later time.
+ *
+ * Examples of such (deferrable) drivers include code
+ * that waits for I/O (e.g., disks, network cards,
+ * et cetera). This allows for faster boot times
+ * as only *required* drivers are started before
+ * everything else.
+ *
+ * Drivers that wish to be deferred may export themselves
+ * via the DRIVER_DEFER() macro. The DRIVER_DEFERRED()
+ * macro gives the value of 1 if the current driver
+ * context has yet to be initialized. The driver may
+ * use this to defer requests for I/O.
+ */
+#if !defined(_INSTALL_MEDIA)
+#define DRIVER_DEFER(INIT) \
+ static struct driver_var __driver_var = { \
+ .deferred = 1 \
+ }; \
+ \
+ __attribute__((used, section(".drivers.defer"))) \
+ static struct driver __driver_desc = { \
+ .init = INIT, \
+ .data = &__driver_var \
}
+#define DRIVER_DEFERRED() __driver_var.deferred
+#else
+#define DRIVER_DEFER(INIT) DRIVER_EXPORT(INIT)
+#define DRIVER_DEFERRED() 0
+#endif /* _INSTALL_MEDIA */
+
#define DRIVERS_INIT() \
for (struct driver *__d = (struct driver *)__drivers_init_start; \
(uintptr_t)__d < (uintptr_t)__drivers_init_end; ++__d) \
{ \
__d->init(); \
}
+
+#define DRIVERS_SCHED() \
+ spawn(&g_proc0,__driver_init_td, NULL, 0, NULL)
+
+void __driver_init_td(void);
+
#endif /* _KERNEL */
#endif /* !_SYS_DRIVER_H_ */
diff --git a/sys/kern/driver_subr.c b/sys/kern/driver_subr.c
new file mode 100644
index 0000000..29eac71
--- /dev/null
+++ b/sys/kern/driver_subr.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Hyra nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/driver.h>
+#include <sys/proc.h>
+#include <sys/cdefs.h>
+#include <sys/syslog.h>
+#include <sys/panic.h>
+#include <dev/timer.h>
+#include <machine/sync.h>
+
+/*
+ * Initialize early drivers
+ *
+ * XXX: This should *NOT* be called directly,
+ * use DRIVERS_SCHED() instead.
+ */
+void
+__driver_init_td(void)
+{
+ const struct driver *dp;
+ struct driver_var *var;
+ struct proc *td;
+ uintptr_t start, end;
+
+ td = this_td();
+ start = (uintptr_t)__driversd_init_start;
+ end = (uintptr_t)__driversd_init_end;
+
+ for (dp = (void *)start; (uintptr_t)dp < end; ++dp) {
+ var = dp->data;
+ dp->init();
+ var->deferred = 0;
+ }
+
+ exit1(td, 0);
+ __builtin_unreachable();
+}
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 665bade..ae3a666 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -44,7 +44,7 @@
#include <vm/vm.h>
#include <string.h>
-static struct proc proc0;
+struct proc g_proc0;
static void
copyright(void)
@@ -60,7 +60,7 @@ begin_install(void)
struct cpu_info *ci;
ci = this_cpu();
- ci->curtd = &proc0;
+ ci->curtd = &g_proc0;
hyra_install();
}
#endif
@@ -115,14 +115,15 @@ main(void)
md_intoff();
sched_init();
- memset(&proc0, 0, sizeof(proc0));
+ memset(&g_proc0, 0, sizeof(g_proc0));
/* Startup pid 1 */
- spawn(&proc0, start_init, NULL, 0, NULL);
+ spawn(&g_proc0, start_init, NULL, 0, NULL);
md_inton();
/* Load all drivers */
DRIVERS_INIT();
+ DRIVERS_SCHED();
#if defined(_INSTALL_MEDIA)
kprintf("Hyra install media detected\n");