tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Loading kernel modules with the boot loader
Hi,
Someone asked me to write about how this works. There are a few things
required of MD code:
- Modules must be loaded to a page-aligned address, and must be mapped
contiguously in VA space. Some combination of activity by the boot loader
and MD kernel accomplishes this.
- If there are restrictions on the architecture's jump/call reach, they have
to be mapped close to the kernel text. As examples, this means within 4GB
(2GB? can't remember) on amd64, on i386 it doesn't matter.
- MD code provides a module_init_md() function. When called this should loop
over all objects loaded by the boot loader and call module_prime() for
each, passing in the address and size (if known, -1 if not). Example:
http://nxr.homeunix.org/source/xref/sys/arch/x86/x86/x86_machdep.c#133
- The boot loader has to know about kernel versions in order to search
for modules in the correct location. That means it first builds a list
of modules, loads the kernel and gets the kernel version, and then tries
to load the modules. Then the kernel starts. libsa pulls the kernel
version from an ELF note so MD code doesn't need to do that. Example:
http://nxr.homeunix.org/source/xref/sys/arch/i386/stand/lib/exec.c#323
- The x86 boot loader loads both i386 and amd64 kernels so it knows to look
for modules in an arch directory matching the kernel image. Don't know if
this matters for other platforms.
- Absolute paths given from the boot loader should also work.
-----
Here's how it works on x86 in brief. The boot loader passes in a bunch of
information to the kernel about the console, boot device, loaded modules,
and so on. The module related stuff is here:
http://nxr.homeunix.org/source/xref/sys/arch/x86/include/bootinfo.h#167
module_init_md() digests this and registers the loaded modules with
module_prime(). From that point on MI code takes care of them.
The x86 memory layout and how it's set up by the boot loader / kernel is
ugly and boring so I won't go into much detail. In short the kernel starts
with the MMU disabled, and the kernel image is contiguous in PA space.
Loaded modules start on PAGE_SIZE boundaries immediatley after the kernel
image. When the kernel starts running, pmap/locore code sets up page tables
and the kernel pmap. Part of that is mapping kernel/module text, the symbol
table, and so on. The kernel is mapped to the correct address in virtual
space, again all contiguous, and then the MMU is switched on. So what we end
up with is a series of ELF objects on PAGE_SIZE boundaries. The first is
always the kernel, and the remainder are described by BTINFO_MODULELIST.
I'll note that there is a 'type' field in bi_modulelist_entry so that the
loader can later pull in anything we want: a kernel config file, or
firmware, or whatever. Right now only modules are loaded.
Cheers,
Andrew
Home |
Main Index |
Thread Index |
Old Index