blob: f4d0145445394dd39541214e08f2a26bdd243ea0 [file] [log] [blame]
Compile
=======
Run:
make
Simulated boots
==============
This programs simulates boot in on both bare metal and xen.
The goal of the code is to illustrate an issue of dead code
and how we can fix this.
Emulate bare metal boot:
./main
Emulate xen boot:
./main -x
Section ranges and tables
=========================
There are standard ELF sections and over time Linux has defined a series of
custom ELF sections which are now de facto Linux sections. Together we refer
to these as Linux ELF sections. History shows there are two forms in which Linux
sections can be used for:
o Section ranges - typically used for grouping a set of executable functions
o Section tables - typically used for grouping a set of data structures
In order to help build concrete and clean, separate semantics for both, we
provide separate helpers for code to declare and use them. There is also
a common set of helpers which both make use of, this is provided in
include/linux/sections.h -- the file consists of of all known Linux ELF
sections, a few helpers used for alignment, size, and building section names.
Two common set of helpers are used to help distinguish whether or not a
particular section range or section table is const or not:
#define DECLARE_LINUX_SECTION(type, name) \
extern type name[], name##__end[];
#define DECLARE_LINUX_SECTION_RO(type, name) \
extern const type name[], name##__end[];
Linux section ranges only use DECLARE_LINUX_SECTION_RO(). So the only thing
else needed is to be able to specify the actual Linux section associated with
the range. You use DECLARE_SECTION_RANGE() to declare section ranges with an
associated name on header files, this lets other code access it. You define
section ranges in code with DEFINE_SECTION_RANGE() which associates the
specific section range with a Linux section.
Linux section tables can be of const or non-const type as such can use either
DECLARE_LINUX_SECTION() or DECLARE_LINUX_SECTION_RO() under the hood. Helpers
are provided to help associate Linux section tables to specific sections with
an appropriate common helper declaration.
The two main section types, section ranges, section tables, then are referred
to with the following macros for declaring each on their respective header
files so others can refer to them; and defining them in the respective code
that defines its proper use:
-------------------------------------------------------------------------------
Section type |ELF name| Declared on header | Defined in code
-------------------------------------------------------------------------------
SECTION_TYPE_RANGES |.ranges | DECLARE_SECTION_RANGE() | DEFINE_SECTION_RANGE()
SECTION_TYPE_TABLES |.ranges | DECLARE_LINKTABLE*() | DEFINE_LINKTABLE*()
-------------------------------------------------------------------------------
There are only two declarations for linker tables, which would be used in
header files:
o DECLARE_LINKTABLE() for data
o DECLARE_LINKTABLE_RO() for read-only data
The tables have a series of definitions (DEFINE_LINKTABLE_*()) given to help
with setup for the different supported Linux sections used. The definitions
would be used in the code defining the use of tables -- the actual
implementation.
The definitions currently supported for tables are:
-------------------------------------------------------------------------------
Linux section | const-or-not | Definition
-------------------------------------------------------------------------------
.data | non-const | DEFINE_LINKTABLE()
.text | const | DEFINE_LINKTABLE_TEXT()
.init | const | DEFINE_LINKTABLE_INIT()
.init.data | non-const | DEFINE_LINKTABLE_INIT_DATA()
.rodata | const | DEFINE_LINKTABLE_RO()
-------------------------------------------------------------------------------
x86 bzimage parser
================
An x86 image parser has been added to aid the integration requirements
of using futher boot_params for dead code concerns. Example usage:
./parse-bzimage ~/linux/arch/x86/boot/bzImage
kernel: /home/mcgrof/linux/arch/x86/boot/bzImage
kernel size: 5668000 bytes
Going to parse kernel...
Xen Expects: 0x53726448
Qemu Expects: 0x53726448
On image: 0x53726448
bzImage protocol Version: v2.13
Xen hdr->version: 525
Qemu protocol: 525
Qemu VERSION(2,8): 520
-------------------------------------------------
Boot protocol 2.07: 0x0207 (supports hardware_subarch)
Boot protocol 2.08: 0x0208
Boot protocol 2.09: 0x0209
Boot protocol 2.10: 0x020a
Boot protocol 2.11: 0x020b
Boot protocol 2.12: 0x020c
Boot protocol 2.13: 0x020d
Member Offset Expected Match
-------------------------------------------------------------------------
setup_header->loadflags 0x0211 0x0211 YES
setup_header->hardware_subarch 0x023c
setup_header->hardware_subarch_data 0x0240
TODO
====
o Finish checking LTO_REFERENCE_INITCALL() is indeed needed. I've aksed [0].
so now just waiting on that discussion to complete. If its not needed,
rip it out of the Linux kernel and then from here.
[0] https://lkml.kernel.org/r/CAB=NE6W6Eh1tU=NXf20f-CPYeT22mtXGzrYqM9W-f14dGBrEsA@mail.gmail.com
Table solution history
======================
The init table solution implemented here is a combination of how the
Linux IOMMU init framework was implemented *and* how GPXE sorts its
own init work.
Table sorting
=============
The Linux IOMMU solution gives us dependency annotations,
so one set of routines will not run until its dependency runs. The
sorting for this takes place with a C routine which ultimately
memmove()'s the routines in order.
The sorting done by the GPXE solution is all done by the linker
by the good 'ol SORT() through in the object's linker script.
We want to enable different subsystems to implement their own
table solutions and this can mean having different init structure
members, that is how the gpxe solution works. Sorting is done automatically
for you through linker at build time. The sorting through the IOMMU init
solution works using the actual specific structure for the subsystem
used and the semantics for the sorting must be clearly documented and
defined. For instance the original IOMMU init solution requires only
one init solution to have a NULL set for its depends callback. For
our mockup x86 init solution we are allowing both "depends" and
"detect" to be NULL. For changes to how our sorting implementation
was modified refer to commit 9e01858bbc74a11 ("init: enable support
for no depends() callback). The sorting for routines that do not have
a "depends" callback set would happen through the order table level
used, a la gpxe solution. When the order levels are the same we rely
on order of linking -- for instance: placement of the routines in the
C file, and at the file level based on order in the Makefile.
Furthermore, upon initialization the mockup x86 init solution relies
on the subarchitecture to skip routines which are not supported or
intended for its subarchitecture.
It might be possible to share a common C sort routine for all tables
but the first challenge is we'd likely be constraining our init structures.
For instance since the current sorting looks for an init routine's "depends"
callback, that callback will be placed in a specific location as part of the
structure. In order to share a sort we'd have to enforce a common set of
table structures for at least the sorting semantics, for instance this
could perhaps be accomplished by placing all relevant members relevant to
sorting semantics in the beginning of the structure. The next challenge
has to do with size, given that we move structures around with memmove()
and this is done depending on the size of the init structure, and that
is up to each subsystem to define. This could be resolved by fixating the
size of all table init structures.
For now each subsystem must then define its own sorting scheme. A sorting
algorithm is only necessary if the linker script sorting does not suffice
for the semantics of the subsystem.
File mapping upstream
=====================
In case this project maintains a matching with upstream this project strives
to maintain a one to one direct mapping as things are or we hope would
be on upstream Linux.