diff options
author | Ian Moffett <ian@osmora.org> | 2025-05-28 23:51:15 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-05-28 23:51:15 -0400 |
commit | e15790fa1fa9954f0209a5d589381f99a05521de (patch) | |
tree | 686fe00fae42ff45190c4b045a95e42b6372e62e | |
parent | 51ca9c82c3e8fb323d238e1f58a085f4cb306110 (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.ld | 6 | ||||
-rw-r--r-- | sys/arch/amd64/conf/link.ld | 6 | ||||
-rw-r--r-- | sys/include/sys/driver.h | 61 | ||||
-rw-r--r-- | sys/kern/driver_subr.c | 64 | ||||
-rw-r--r-- | sys/kern/init_main.c | 9 |
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"); |