| |
| 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. |