10个版本 (重大变更)

0.11.0 2024年1月22日
0.10.0 2023年10月16日
0.9.1 2023年9月1日
0.9.0 2023年5月3日
0.1.0 2019年2月19日

#25 in Unix API

Download history 19125/week @ 2024-03-14 12653/week @ 2024-03-21 9988/week @ 2024-03-28 12811/week @ 2024-04-04 7270/week @ 2024-04-11 11298/week @ 2024-04-18 10993/week @ 2024-04-25 10722/week @ 2024-05-02 9259/week @ 2024-05-09 9002/week @ 2024-05-16 8994/week @ 2024-05-23 10702/week @ 2024-05-30 13377/week @ 2024-06-06 12728/week @ 2024-06-13 5373/week @ 2024-06-20 4481/week @ 2024-06-27

每月38,061次下载

Apache-2.0 AND BSD-3-Clause

300KB
7K SLoC

包含 (ELF可执行文件/库, 1KB) src/loader/x86_64/elf/test_bad_align.bin、(ELF可执行文件/库, 1KB) test_dummy_note.bin、(ELF可执行文件/库, 1KB) src/loader/x86_64/elf/test_elf.bin、(ELF可执行文件/库, 1KB) src/loader/x86_64/elf/test_elfnote.bin、(ELF可执行文件/库, 1KB) test_elfnote_8byte_align.bin、(ELF可执行文件/库, 1KB) test_invalid_pvh_note.bin

Linux-loader

crates.io docs.rs

linux-loader crate提供了在x86_64和PE(Image)内核图像上加载原始ELF(vmlinux)和压缩大zImage(bzImage)格式内核图像的支持。ELF支持包括Linux和PVH引导协议。

linux-loader crate目前还不完全独立和自给自足,大部分引导过程仍然是VMM的责任。有关详细信息,请参阅[用法]。

支持的功能

用法

使用 linux-loader 框架启动虚拟机涉及多个步骤,具体取决于所使用的启动协议。以下是简化的概述。

考虑一个与 x86_64 VMM 接口的虚拟机管理程序;

  • linux-loader 进行接口通信;
  • 使用 GuestMemoryMmap 作为其虚拟机内存后端;
  • File 加载 ELF 内核映像。

加载内核

启动虚拟机的第一步之一是从 Reader 将内核加载到虚拟机内存中。为此步骤,VMM 需要配置其虚拟机内存。

在本例中,VMM 指定了内核的起始地址和高内存的起始地址。

use linux_loader::loader::elf::Elf as Loader;
use vm_memory::GuestMemoryMmap;

use std::fs::File;
use std::result::Result;

impl MyVMM {
    fn start_vm(&mut self) {
        let guest_memory = self.create_guest_memory();
        let kernel_file = self.open_kernel_file();

        let load_result = Loader::load::<File, GuestMemoryMmap>(
            &guest_memory,
            Some(self.kernel_start_addr()),
            &mut kernel_file,
            Some(self.himem_start_addr()),
        )
        .expect("Failed to load kernel");
    }
}

配置设备和内核命令行

在创建虚拟机内存、解析和加载内核之后,VMM 可以选择配置设备和内核命令行。然后可以将后者加载到虚拟机内存中。

impl MyVMM {
    fn start_vm(&mut self) {
        ...
        let cmdline_size = self.kernel_cmdline().as_str().len() + 1;
        linux_loader::loader::load_cmdline::<GuestMemoryMmap>(
            &guest_memory,
            self.cmdline_start_addr(),
            &CString::new(kernel_cmdline).expect("Failed to parse cmdline")
        ).expect("Failed to load cmdline");
    }

配置启动参数

在这个阶段,VMM 设置了初始的注册表值,不使用 linux-loader。它还可以使用由 linux-loader 导出的结构体配置额外的启动参数。

use linux_loader::configurator::linux::LinuxBootConfigurator;
use linux_loader::configurator::{BootConfigurator, BootParams};

impl MyVMM {
    fn start_vm(&mut self) {
        ...
        let mut bootparams = boot_params::default();
        self.configure_bootparams(&mut bootparams);
        LinuxBootConfigurator::write_bootparams(
            BootParams::new(&params, self.zeropage_addr()),
            &guest_memory,
        ).expect("Failed to write boot params in guest memory");
    }

完成!

测试

请参阅 docs/TESTING.md

许可证

此项目受以下任一许可证的许可:

依赖项

~0.7–1.3MB
~26K SLoC