From 96c01bff098fb826da09337df877fe904bd31d5a Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 23 May 2022 15:59:58 +0200 Subject: libbsd.txt: Move initialization details --- CONTRIBUTING.rst | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libbsd.txt | 147 ------------------------------------------------------- 2 files changed, 139 insertions(+), 147 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c1268121..99c778f6 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -453,3 +453,142 @@ the priority inheritance protocol. * `SYSINIT(9) `_: A framework for dynamic kernel initialization * `TASKQUEUE(9) `_: Asynchronous task execution * `UMA(9) `_: General-purpose kernel object allocator + +LibBSD Initialization Details +============================= + +The initialization of LibBSD is based on the FreeBSD +`SYSINIT(9) `_ +infrastructure. The key to initializing a system is to ensure that the desired +device drivers are explicitly pulled into the linked application. This plus +linking against the LibBSD (``libbsd.a``) will pull in the necessary FreeBSD +infrastructure. + +The FreeBSD kernel is not a library like the RTEMS kernel. It is a bunch of +object files linked together. If we have a library, then creating the +executable is simple. We begin with a start symbol and recursively resolve all +references. With a bunch of object files linked together we need a different +mechanism. Most object files don't know each other. Lets say we have a driver +module. The rest of the system has no references to this driver module. The +driver module needs a way to tell the rest of the system: Hey, kernel I am +here, please use my services! + +This registration of independent components is performed by SYSINIT(9) and +specializations + +The SYSINIT(9) uses some global data structures that are placed in a certain +section. In the linker command file we need this: + +.. code-block:: none + + .rtemsroset : { + KEEP (*(SORT(.rtemsroset.*))) + } + + .rtemsrwset : { + KEEP (*(SORT(.rtemsrwset.*))) + } + +This results for example in this executable layout: + +.. code-block:: none + + [...] + *(SORT(.rtemsroset.*)) + .rtemsroset.bsd.modmetadata_set.begin + 0x000000000025fe00 0x0 libbsd.a(rtems-bsd-init.o) + 0x000000000025fe00 _bsd__start_set_modmetadata_set + .rtemsroset.bsd.modmetadata_set.content + 0x000000000025fe00 0x8 libbsd.a(rtems-bsd-nexus.o) + .rtemsroset.bsd.modmetadata_set.content + 0x000000000025fe08 0x4 libbsd.a(kern_module.o) + [...] + .rtemsroset.bsd.modmetadata_set.content + 0x000000000025fe68 0x4 libbsd.a(mii.o) + .rtemsroset.bsd.modmetadata_set.content + 0x000000000025fe6c 0x4 libbsd.a(mii_bitbang.o) + .rtemsroset.bsd.modmetadata_set.end + 0x000000000025fe70 0x0 libbsd.a(rtems-bsd-init.o) + 0x000000000025fe70 _bsd__stop_set_modmetadata_set + [...] + .rtemsrwset 0x000000000030bad0 0x290 + *(SORT(.rtemsrwset.*)) + .rtemsrwset.bsd.sysinit_set.begin + 0x000000000030bad0 0x0 libbsd.a(rtems-bsd-init.o) + 0x000000000030bad0 _bsd__start_set_sysinit_set + .rtemsrwset.bsd.sysinit_set.content + 0x000000000030bad0 0x4 libbsd.a(rtems-bsd-nexus.o) + .rtemsrwset.bsd.sysinit_set.content + 0x000000000030bad4 0x8 libbsd.a(rtems-bsd-thread.o) + .rtemsrwset.bsd.sysinit_set.content + 0x000000000030badc 0x4 libbsd.a(init_main.o) + [...] + .rtemsrwset.bsd.sysinit_set.content + 0x000000000030bd54 0x4 libbsd.a(frag6.o) + .rtemsrwset.bsd.sysinit_set.content + 0x000000000030bd58 0x8 libbsd.a(uipc_accf.o) + .rtemsrwset.bsd.sysinit_set.end + 0x000000000030bd60 0x0 libbsd.a(rtems-bsd-init.o) + 0x000000000030bd60 _bsd__stop_set_sysinit_set + [...] + +Here you can see, that some global data structures are collected into +continuous memory areas. This memory area can be identified by start and stop +symbols. This constructs a table of uniform items. + +The low level FreeBSD code calls at some time during the initialization the +mi_startup() function (machine independent startup). This function will sort +the SYSINIT(9) set and call handler functions which perform further +initialization. The last step is the scheduler invocation. + +The SYSINIT(9) routines are run in ``mi_startup()`` which is called by +``rtems_bsd_initialize()``. This is also explained in "The Design and +Implementation of the FreeBSD Operating System" section 14.3 "Kernel +Initialization". + +In RTEMS, we have a library and not a bunch of object files. Thus we need a +way to pull-in the desired services out of the libbsd. Here the +``rtems-bsd-sysinit.h`` comes into play. The SYSINIT(9) macros have been +modified and extended for RTEMS in ````: + +.. code-block:: none + + #ifndef __rtems__ + #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \ + static struct sysinit uniquifier ## _sys_init = { \ + subsystem, \ + order, \ + func, \ + (ident) \ + }; \ + DATA_SET(sysinit_set,uniquifier ## _sys_init) + #else /* __rtems__ */ + #define SYSINIT_ENTRY_NAME(uniquifier) \ + _bsd_ ## uniquifier ## _sys_init + #define SYSINIT_REFERENCE_NAME(uniquifier) \ + _bsd_ ## uniquifier ## _sys_init_ref + #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \ + struct sysinit SYSINIT_ENTRY_NAME(uniquifier) = { \ + subsystem, \ + order, \ + func, \ + (ident) \ + }; \ + RWDATA_SET(sysinit_set,SYSINIT_ENTRY_NAME(uniquifier)) + #define SYSINIT_REFERENCE(uniquifier) \ + extern struct sysinit SYSINIT_ENTRY_NAME(uniquifier); \ + static struct sysinit const * const \ + SYSINIT_REFERENCE_NAME(uniquifier) __used \ + = &SYSINIT_ENTRY_NAME(uniquifier) + #define SYSINIT_MODULE_REFERENCE(mod) \ + SYSINIT_REFERENCE(mod ## module) + #define SYSINIT_DRIVER_REFERENCE(driver, bus) \ + SYSINIT_MODULE_REFERENCE(driver ## _ ## bus) + #define SYSINIT_DOMAIN_REFERENCE(dom) \ + SYSINIT_REFERENCE(domain_add_ ## dom) + #endif /* __rtems__ */ + +Here you see that the SYSINIT(9) entries are no longer static. The +``*_REFERENCE()`` macros will create references to the corresponding modules +which are later resolved by the linker. The application has to provide an +object file with references to all required FreeBSD modules. diff --git a/libbsd.txt b/libbsd.txt index cd6c8dae..33033c4c 100644 --- a/libbsd.txt +++ b/libbsd.txt @@ -104,153 +104,6 @@ be addressed. - The ISA drivers require more BSD infrastructure to be addressed. This was outside the scope of the initial porting effort. -== FreeBSD Source - -You should be able to rely on FreebSD manual pages and documentation -for details on the code itself. - -== BSD Library Source - -== Initialization of the BSD Library - -The initialization of the BSD library is based on the FreeBSD SYSINIT(9) -infrastructure. The key to initializing a system is to ensure that the desired -device drivers are explicitly pulled into the linked application. This plus -linking against the BSD library (`libbsd.a`) will pull in the necessary FreeBSD -infrastructure. - -The FreeBSD kernel is not a library like the RTEMS kernel. It is a bunch of -object files linked together. If we have a library, then creating the -executable is simple. We begin with a start symbol and recursively resolve all -references. With a bunch of object files linked together we need a different -mechanism. Most object files don't know each other. Lets say we have a driver -module. The rest of the system has no references to this driver module. The -driver module needs a way to tell the rest of the system: Hey, kernel I am -here, please use my services! - -This registration of independent components is performed by SYSINIT(9) and -specializations: - -http://www.freebsd.org/cgi/man.cgi?query=SYSINIT - -The SYSINIT(9) uses some global data structures that are placed in a certain -section. In the linker command file we need this: - -------------------------------------------------------------------------------- -.rtemsroset : { - KEEP (*(SORT(.rtemsroset.*))) -} - -.rtemsrwset : { - KEEP (*(SORT(.rtemsrwset.*))) -} -------------------------------------------------------------------------------- - -This results for example in this executable layout: - -------------------------------------------------------------------------------- -[...] - *(SORT(.rtemsroset.*)) - .rtemsroset.bsd.modmetadata_set.begin - 0x000000000025fe00 0x0 libbsd.a(rtems-bsd-init.o) - 0x000000000025fe00 _bsd__start_set_modmetadata_set - .rtemsroset.bsd.modmetadata_set.content - 0x000000000025fe00 0x8 libbsd.a(rtems-bsd-nexus.o) - .rtemsroset.bsd.modmetadata_set.content - 0x000000000025fe08 0x4 libbsd.a(kern_module.o) -[...] - .rtemsroset.bsd.modmetadata_set.content - 0x000000000025fe68 0x4 libbsd.a(mii.o) - .rtemsroset.bsd.modmetadata_set.content - 0x000000000025fe6c 0x4 libbsd.a(mii_bitbang.o) - .rtemsroset.bsd.modmetadata_set.end - 0x000000000025fe70 0x0 libbsd.a(rtems-bsd-init.o) - 0x000000000025fe70 _bsd__stop_set_modmetadata_set -[...] -.rtemsrwset 0x000000000030bad0 0x290 - *(SORT(.rtemsrwset.*)) - .rtemsrwset.bsd.sysinit_set.begin - 0x000000000030bad0 0x0 libbsd.a(rtems-bsd-init.o) - 0x000000000030bad0 _bsd__start_set_sysinit_set - .rtemsrwset.bsd.sysinit_set.content - 0x000000000030bad0 0x4 libbsd.a(rtems-bsd-nexus.o) - .rtemsrwset.bsd.sysinit_set.content - 0x000000000030bad4 0x8 libbsd.a(rtems-bsd-thread.o) - .rtemsrwset.bsd.sysinit_set.content - 0x000000000030badc 0x4 libbsd.a(init_main.o) -[...] - .rtemsrwset.bsd.sysinit_set.content - 0x000000000030bd54 0x4 libbsd.a(frag6.o) - .rtemsrwset.bsd.sysinit_set.content - 0x000000000030bd58 0x8 libbsd.a(uipc_accf.o) - .rtemsrwset.bsd.sysinit_set.end - 0x000000000030bd60 0x0 libbsd.a(rtems-bsd-init.o) - 0x000000000030bd60 _bsd__stop_set_sysinit_set -[...] -------------------------------------------------------------------------------- - -Here you can see, that some global data structures are collected into -continuous memory areas. This memory area can be identified by start and stop -symbols. This constructs a table of uniform items. - -The low level FreeBSD code calls at some time during the initialization the -mi_startup() function (machine independent startup). This function will sort -the SYSINIT(9) set and call handler functions which perform further -initialization. The last step is the scheduler invocation. - -The SYSINIT(9) routines are run in mi_startup() which is called by -rtems_bsd_initialize(). - -This is also explained in "The Design and Implementation of the FreeBSD -Operating System" section 14.3 "Kernel Initialization". - -In RTEMS we have a library and not a bunch of object files. Thus we need a way -to pull-in the desired services out of the libbsd. Here the -`rtems-bsd-sysinit.h` comes into play. The SYSINIT(9) macros have been -modified and extended for RTEMS in ``: - -------------------------------------------------------------------------------- -#ifndef __rtems__ -#define C_SYSINIT(uniquifier, subsystem, order, func, ident) \ - static struct sysinit uniquifier ## _sys_init = { \ - subsystem, \ - order, \ - func, \ - (ident) \ - }; \ - DATA_SET(sysinit_set,uniquifier ## _sys_init) -#else /* __rtems__ */ -#define SYSINIT_ENTRY_NAME(uniquifier) \ - _bsd_ ## uniquifier ## _sys_init -#define SYSINIT_REFERENCE_NAME(uniquifier) \ - _bsd_ ## uniquifier ## _sys_init_ref -#define C_SYSINIT(uniquifier, subsystem, order, func, ident) \ - struct sysinit SYSINIT_ENTRY_NAME(uniquifier) = { \ - subsystem, \ - order, \ - func, \ - (ident) \ - }; \ - RWDATA_SET(sysinit_set,SYSINIT_ENTRY_NAME(uniquifier)) -#define SYSINIT_REFERENCE(uniquifier) \ - extern struct sysinit SYSINIT_ENTRY_NAME(uniquifier); \ - static struct sysinit const * const \ - SYSINIT_REFERENCE_NAME(uniquifier) __used \ - = &SYSINIT_ENTRY_NAME(uniquifier) -#define SYSINIT_MODULE_REFERENCE(mod) \ - SYSINIT_REFERENCE(mod ## module) -#define SYSINIT_DRIVER_REFERENCE(driver, bus) \ - SYSINIT_MODULE_REFERENCE(driver ## _ ## bus) -#define SYSINIT_DOMAIN_REFERENCE(dom) \ - SYSINIT_REFERENCE(domain_add_ ## dom) -#endif /* __rtems__ */ -------------------------------------------------------------------------------- - -Here you see that the SYSINIT(9) entries are no longer static. The -\*_REFERENCE() macros will create references to the corresponding modules which -are later resolved by the linker. The application has to provide an object -file with references to all required FreeBSD modules. - The FreeBSD device model is quite elaborated (with follow-ups): http://www.freebsd.org/cgi/man.cgi?query=driver -- cgit v1.2.3