-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Boot configurator: trait (and associated objects) that write boot params in guest memory #31
Conversation
Coverage test fails, but I'd like to get some preliminary feedback before investing the extra effort into additional unit tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked mostly at the PVH section since that is what I am most familiar with, but the design looks clean and easy to understand even for Rust beginners like me. Thank you! Please see my comment regarding the initrd support.
src/configurator/x86_64/pvh.rs
Outdated
/// # Arguments | ||
/// | ||
/// * `header` - boot parameters encapsulated in a [`hvm_start_info`] struct. | ||
/// * `sections` - memory map table represented as a vector of [`hvm_memmap_table_entry`]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another section type that must be specified for PVH is the list of auxiliary boot modules described by a vector of hvm_modlist_entry structs. This is the mechanism used in PVH for initrd support.
A VMM that implements initrd support with PVH, must write to guest memory a single hvm_modlist_entry
structure that specifies the paddr and size of the initramfs loaded in guest memory. The hvm_start_info
struct then has a field pointing to this hvm_modlist_entry
, similar to how boot_params
has fields for ramdisk_image
and ramdisk_size
.
As far as I know, there are no other current uses of this module mechanism in Linux, so only a single hvm_modlist_entry
is needed in guests that use initrd. Any additional functionality required at boot time is typically embedded in the kernel binary or as part of the initramfs. As an example, I am told that microcode blobs used to be specified using a similar approach in the past, where now they are usually part of initramfs.
So for the current use cases only one hvm_modlist_entry
is needed, but in theory we should be able to handle an arbitrary (to a reasonable extent) number of modules. We would either need another parameter (boot_modules
?) that would be unused by the Linux and ARM implementations, or to extend this sections
parameter to be able to describe both the memory map and the modules entries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the detailed explanation! I updated this PR with some more abstractions over the tuples I initially used, and now the BootConfigurator
works with a BootParams
object that has a (mandatory) header (boot_params
/ hvm_start_info
/ fdt blob), optional sections (PVH memmap) and optional modules (PVH modlist for initrd).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was also going to remark that the boot parameters should all be encapsulated in a single struct.
src/configurator/x86_64/pvh.rs
Outdated
/// # Arguments | ||
/// | ||
/// * `header` - boot parameters encapsulated in a [`hvm_start_info`] struct. | ||
/// * `sections` - memory map table represented as a vector of [`hvm_memmap_table_entry`]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was also going to remark that the boot parameters should all be encapsulated in a single struct.
I used this PR as a starting point to play around with encapsulating bootparams creation too, towards the vision of having all kernel loading logic in this crate. I started with elf + Linux as it's the easiest of combinations (building the fdt for ARM is, I think, beyond this crate). The code is in this branch: https://github.com/aghecenco/linux-loader/tree/build_params elf + Linux boot: Tried it out with Firecracker: https://github.com/aghecenco/firecracker/tree/linloader And cloud-hypervisor: https://github.com/aghecenco/cloud-hypervisor/tree/linloader |
This commit introduces a new configurator module that takes boot parameters created in the VMM (boot_params / start_info + e820 map) and writes them into guest memory. The module is meant to be extended in order to include *building* the boot parameters as well. Fixes rust-vmm#15 Signed-off-by: Alexandra Iordache <aghecen@amazon.com>
be18b76
to
9277d02
Compare
src/configurator/aarch64/fdt.rs
Outdated
.unwrap(); | ||
assert_eq!( | ||
FdtBootConfigurator::write_bootparams::< | ||
FdtPlaceholder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self: to avoid this level of verbosity, maybe impl ByteValued for () {}
in vm-memory
@bonzini the latest version uses a single |
@aghecenco Sorry it took me a bit to reply back. The new types look good to me, but probably others with more Rust experience should take a look. One minor suggestion is to avoid having members of
Perhaps the second field in the Also I noticed that the write_bootparams() implementation in PvhBootConfigurator did not have support yet for copying the module list into guest memory, so I added the (untested!) code here: |
I think adding more generic parameters is not the right approach. BootParams can be kept generic if you make it a convenience for building a |
Added a new struct that encapsulates boot parameters expressed as bytes. * header: section of the parameters that is necessary regardless of boot protocol. For Linux, it's the boot_params struct; for PVH, it's the start_info; for ARM+FDT, it's the device tree blob. * sections: vector of additional boot parameters written at a different address than the header. Unused for Linux & FDT. For PVH, it's the memory map table. * modules: vector of module boot configurations, written at a different address than the header and sections. Unused for Linux & FDT. For PVH, it's (optionally) a vector of 1 modlist_entry containing the initrd configuration, if any. Signed-off-by: Alexandra Iordache <aghecen@amazon.com>
@bonzini I got rid of the 3 generics; the struct still separates |
Nice! My only remaining qualm is that add_sections actually sets the whole Vec, so I would prefer an add_section method that can be called multiple times. Likewise for modules. |
There can still be add_sections and add_modules methods, taking a Vec, for convenience. However it's a bit limiting to assume a single type for all sections/modules. add_section and add_module could return the top address for the section and module to simplify adding heterogenous sections/modules. |
Looks great, thanks! |
b4a986d
to
a3af475
Compare
I added a new commit that replaces the tuples in the original @bonzini many thanks for all the feedback so far, this PR has come a long way since the beginning. Can you take another look? The 3 types of configurators haven't changed much, but the sections/modules rework has built up. |
* boot parameters and corresponding addresses are separate fields in the struct, instead of packed in a tuple * sections and modules (for PVH boot) can be added one at a time and don't need to be of the same type Signed-off-by: Alexandra Iordache <aghecen@amazon.com>
Hi @bonzini @alexandruag, could you please take a(nother) look? |
I don't have approval privileges, but I like the basic API and tests are comprehensive, so it looks good. |
M: GuestMemory, | ||
{ | ||
// The VMM has filled an FDT and passed it as a `ByteValued` object. | ||
guest_memory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to validate guest memory address here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added validation. write_slice
would have returned an error, but the other use cases explicitly validate that the bootparams fit in guest memory, so I added the same here.
725725e
to
be6fed8
Compare
Signed-off-by: Alexandra Iordache <aghecen@amazon.com>
#15
This PR introduces a new
configurator
module, meant to build (TBD) and write (included in this PR) boot parameters in guest memory. To begin with, the VMM will have to build its own boot params, encapsulate them intoByteValued
objects, then pass them on tolinux-loader
.VMM workflow:
The PR adds support for 3 boot protocols:
x86_64
Linux bootheader
:boot_params
struct, everything that goes into the zeropagesections
: unused (e820 map included inheader
)x86_64
PVH bootheader
:hvm_start_info
structsections
: vector ofhvm_memmap_table_entry
structs: memory map table entriesaarch64
bootheader
: byte blob containing the compiled FDTsections
: unused