[rtems-libbsd commit] libbsd.txt: Move initialization details

Sebastian Huber sebh at rtems.org
Wed May 25 06:05:24 UTC 2022


Module:    rtems-libbsd
Branch:    6-freebsd-12
Commit:    0a1a47c11f1901351e46d75f3203533eb57eede8
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=0a1a47c11f1901351e46d75f3203533eb57eede8

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon May 23 15:59:58 2022 +0200

libbsd.txt: Move initialization details

---

 CONTRIBUTING.rst | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 1c3164b2..316a851a 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -530,3 +530,142 @@ the priority inheritance protocol.
 * `SYSINIT(9) <http://www.freebsd.org/cgi/man.cgi?query=sysinit&sektion=9>`_: A framework for dynamic kernel initialization
 * `TASKQUEUE(9) <http://www.freebsd.org/cgi/man.cgi?query=taskqueue&sektion=9>`_: Asynchronous task execution
 * `UMA(9) <http://www.freebsd.org/cgi/man.cgi?query=uma&sektion=9>`_: General-purpose kernel object allocator
+
+LibBSD Initialization Details
+=============================
+
+The initialization of LibBSD is based on the FreeBSD
+`SYSINIT(9) <http://www.freebsd.org/cgi/man.cgi?query=sysinit&sektion=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 ``<sys/kernel.h>``:
+
+.. 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.



More information about the vc mailing list