mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-05-14 04:29:18 +08:00
libbsd.txt: Move initialization details
This commit is contained in:
parent
3d36dc0239
commit
96c01bff09
139
CONTRIBUTING.rst
139
CONTRIBUTING.rst
@ -453,3 +453,142 @@ the priority inheritance protocol.
|
|||||||
* `SYSINIT(9) <http://www.freebsd.org/cgi/man.cgi?query=sysinit&sektion=9>`_: A framework for dynamic kernel initialization
|
* `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
|
* `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
|
* `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.
|
||||||
|
147
libbsd.txt
147
libbsd.txt
@ -104,153 +104,6 @@ be addressed.
|
|||||||
- The ISA drivers require more BSD infrastructure to be addressed. This was
|
- The ISA drivers require more BSD infrastructure to be addressed. This was
|
||||||
outside the scope of the initial porting effort.
|
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 `<sys/kernel.h>`:
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
#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):
|
The FreeBSD device model is quite elaborated (with follow-ups):
|
||||||
|
|
||||||
http://www.freebsd.org/cgi/man.cgi?query=driver
|
http://www.freebsd.org/cgi/man.cgi?query=driver
|
||||||
|
Loading…
x
Reference in New Issue
Block a user