ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Comprehensive Rust 实战:用 vmbase 库在 crosvm 下编写 aarch64 裸机虚拟机程序

Comprehensive Rust 实战:用 vmbase 库在 crosvm 下编写 aarch64 裸机虚拟机程序 Comprehensive Rust 实战用 vmbase 库在 crosvm 下编写 aarch64 裸机虚拟机程序【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rust本指南讲解 Comprehensive Rust 课程「Bare Metal on Android」章节中的核心主题如何使用 Google 的vmbase库在 aarch64 架构上编写运行于 crosvm 虚拟机管理程序VMM之下的裸机 Rust 程序。读完本文你将掌握main!宏与println!的用法、vmbase 入口点的启动与关机流程以及如何在 AOSP 中用 Soong 构建规则rust_ffi_staticcc_binaryraw_binary将 Rust 代码链接成可运行的裸机镜像。vmbase 是什么为 crosvm 虚拟机量身定制的 Rust 启动库在 src/bare-metal/android/vmbase.md 中课程这样定义 vmbaseFor VMs running under crosvm on aarch64, the vmbase library provides a linker script and useful defaults for the build rules, along with an entry point, UART console logging and more.拆解一下这句话vmbase 为 aarch64 上的 crosvm 虚拟机提供四类关键能力链接脚本linker script规定镜像的内存布局例如入口符号放置位置、各段.text、.rodata、.data、.bss的排列与对齐方式构建规则默认值defaults for the build rules在 AOSP Soong 构建系统中以vmbase_ffi_defaults、vmbase_elf_defaults等属性集形式提供屏蔽底层繁琐配置入口点entry point接管 CPU 复位后的早期初始化再调用你写的业务函数UART 控制台日志提供println!宏让你能直接向宿主侧控制台输出调试信息。从课程大纲 src/SUMMARY.md 可以看到vmbase 是bare-metal/android小节的正式教学主题它属于整个 src/bare-metal.md 课程中「在 Android 上构建裸机二进制」的收尾环节——前面课程已经教会你写no_std程序、初始化 EL1 异常等级、配置 MMU 页表vmbase 则是把这些繁琐工作打包成开箱即用的库。值得注意的是vmbase 面向的是运行在 crosvm 下的虚拟机VM而不是 QEMUvirt板卡那样的物理模拟环境。两者都属于应用处理器Application Processor裸机编程但 vmbase 场景下存在宿主机的缓存别名、PSCI 电源管理调用等虚拟化特有的问题。最小可运行的 Hello Worldmain!println!vmbase.md 给出的核心示例是一个完整的、可直接照搬的最小程序#![no_main] #![no_std] use vmbase::{main, println}; main!(main); pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) { println!(Hello world); }逐一解释这段代码的要点#![no_main]告知编译器此程序没有标准main入口真正的入口由 vmbase 的链接脚本与汇编启动代码定义。这与课程 src/bare-metal/minimal.md 中「没有main或任何其他入口点需要你自己定义入口点」的结论一致——vmbase 正是替你完成了这一层工作#![no_std]不依赖标准库程序直接面向硬件与虚拟化环境运行main!(main)这是 vmbase 提供的属性宏它把你的main函数注册为「当 vmbase 入口点完成初始化后要被调用的函数」。注意课程里它是按宏调用形式main!(main)使用的不同 vmbase 版本也可能提供#[main]属性形式函数签名固定为接收arg0..arg3四个u64参数——这正是 aarch64 调用约定中x0..x3四个寄存器传入的启动参数在 QEMU/ATF 场景下通常来自固件约定的启动协议println!由 vmbase 提供的宏通过 UART 向宿主控制台输出一行文本。如果没有 vmbase你需要像课程 src/bare-metal/aps/logging.md 那样自己操作 PL011 UART 寄存器——vmbase 把这个过程封装成了宏。代码标注了compile_fail意味着这段代码不能在普通主机host上编译只能在 AOSP 环境中结合 vmbase 的 Soong 构建规则编译这正是下一节要讲的内容。入口点背后做了什么控制台初始化与 PSCI_SYSTEM_OFF 关机vmbase.md 的details折叠区补充了两个关键行为main!宏标记你的 main 函数使其从 vmbase 入口点被调用。也就是说main不是第一个执行的代码它前面还有一段由 vmbase 提供的启动序列vmbase 入口点负责控制台console初始化并在你的 main 函数返回时发出PSCI_SYSTEM_OFF来关闭虚拟机。这第二个行为非常有价值在裸机程序里如果main正常返回程序其实不知道该做什么没有操作系统帮你退出。vmbase 的约定是返回即关机——入口点会通过hvc #0超级调用hypervisor call向 crosvm 发起PSCI_SYSTEM_OFF优雅地终结这台虚拟机。要理解没有 vmbase 时你需要手动做多少事可以对比课程示例 src/bare-metal/aps/examples/src/main_psci.rs它硬编码了const PSCI_SYSTEM_OFF: u32 0x84000008;然后用内联汇编把该值写入w0寄存器并执行hvc #0才能完成关机。这段样板代码在 vmbase 场景下被入口点自动接管你只需保证main函数能够返回即可。类似地控制台初始化在无 vmbase 时意味着要配置 UART 时钟、波特率、FIFO 等寄存器参见课程 src/bare-metal/aps/uart/using.md这些同样由 vmbase 入口点代劳。AOSP 里的三步构建rust_ffi_static → cc_binary → raw_binaryvmbase 不能脱离 Android 构建系统单独使用。src/bare-metal/android.md 给出了完整的 Soong 构建配置这也是 vmbase.md 所依赖的「build rules」的实际形态。构建一个 vmbase 裸机程序需要三个构建目标接力第一步rust_ffi_static编译 Rust 库rust_ffi_static { name: libvmbase_example, defaults: [vmbase_ffi_defaults], crate_name: vmbase_example, srcs: [src/main.rs], rustlibs: [ libvmbase, ], }要点解析rust_ffi_static把 Rust 代码编译成静态库.a因为裸机程序最终要用 C 链接器cc_binary链接Rust 侧必须以 FFI 静态库形式接入defaults: [vmbase_ffi_defaults]这是 vmbase 提供的构建默认值集合内含目标架构aarch64、no_std相关编译选项等避免在每个模块重复配置crate_name必须与 Rust 源码中的 crate 名一致rustlibs: [libvmbase]把 vmbase 库本身链接进来这样源码里才能use vmbase::{main, println};。第二步cc_binary 链接脚本生成 ELFcc_binary { name: vmbase_example, defaults: [vmbase_elf_defaults], srcs: [ idmap.S, ], static_libs: [ libvmbase_example, ], linker_scripts: [ image.ld, :vmbase_sections, ], }defaults: [vmbase_elf_defaults]vmbase 为 ELF 链接阶段准备的默认值srcs: [idmap.S]提供恒等映射identity map页表。在虚拟化场景下内存必须经由 MMU 以缓存一致的方式访问否则宿主机与被访内存之间会出现缓存别名cache alias问题——这正是课程 src/bare-metal/aps/entry-point.md 中强调的「在读写任何内存前需要启用 MMU 和缓存」的原因。仓库中的示例页表 src/bare-metal/aps/examples/src/idmap.S 展示了同样的思路前 1 GiB 映射设备、随后 1 GiB 映射 DRAMstatic_libs: [libvmbase_example]把第一步编译出的 Rust 静态库链接进 ELFlinker_scripts同时使用你自己的image.ld和 vmbase 提供的:vmbase_sections段布局脚本。前者的形态可参考仓库示例 src/bare-metal/aps/examples/image.ld它把镜像放在0x40080000起始、长度 2 MiB 的image内存区域按 4096 字节对齐组织.init、.text、.rodata、.data并让.bss由入口代码清零、预留 40 个 4 KiB 页的启动栈。第三步raw_binary产出可直接运行的裸二进制raw_binary { name: vmbase_example_bin, stem: vmbase_example.bin, src: :vmbase_example, enabled: false, target: { android_arm64: { enabled: true, }, }, }链接产物是 ELF而 crosvm 加载裸机虚拟机需要原始二进制raw binary所以用raw_binary把 ELF 中的代码与数据原样抽取出来enabled: falsetarget.android_arm64.enabled: true保证该产物只在 aarch64 Android 目标上构建避免在宿主编译工具链等其它目标上浪费构建资源stem指定输出文件名为vmbase_example.bin。最终产出的vmbase_example.bin即可作为 crosvm 的--kernel或等效启动参数喂给虚拟机执行。与课程其余内容的衔接为什么需要 vmbasevmbase 不是凭空出现的魔法它把课程前面章节你手写过的内容产品化了课程中手写的内容vmbase 替你完成src/bare-metal/minimal.md 中的自定义 panic handlervmbase 内建示例因compile_fail省略了panic_handler实际库已提供src/bare-metal/aps/entry-point.md 中的entry.S启动汇编清 BSS、设栈指针、配异常向量vbar_el1vmbase 入口点src/bare-metal/aps/examples/src/main_psci.rs 中的 PSCI 关机汇编入口点在 main 返回后自动PSCI_SYSTEM_OFFsrc/bare-metal/aps/logging.md 中的 PL011 UART 驱动println!宏src/bare-metal/aps/examples/image.ld 链接脚本:vmbase_sections链接脚本与构建默认值从源码结构看可以推断 vmbase 的设计目标正是「让应用处理器裸机开发聚焦业务逻辑」你只需要写一个接收四个u64参数的普通函数剩下的启动、打印、关机全部交给库。这也是 Android 虚拟化AVF生态中大量 Rust 虚拟化组件的通用编程模型。实践要点与前提条件环境前提需要 Android 源码树AOSP与 Soong 构建系统vmbase 库本身位于 AOSP 的packages/modules/Virtualization/libs/libvmbase目录随 AOSP 源码分发运行前提目标是 aarch64 上由 crosvm 启动的虚拟机镜像为 raw binary不要试图在普通 Linux 主机或 QEMUvirt板卡上直接运行本文示例目标约束程序运行在 EL1异常等级 1与课程 src/bare-metal/aps/entry-point.md 中「所有下午示例假设运行在 EL1」的约定一致若需运行在其它异常等级需要调整启动环境调试技巧充分利用println!观察 VM 内执行流主机控制台上即可看到输出main 函数返回即关机这也是测试程序「正常结束」的语义。总结vmbase 是 Comprehensive Rust 课程中「Bare-Metal on Android」一节的点睛之笔它用main!宏 println!宏 Soong 构建默认值把 crosvm 虚拟机下 aarch64 裸机 Rust 程序的启动、日志、关机与镜像产出整合成一套最小且好用的工作流。掌握了 src/bare-metal/android/vmbase.md 与 src/bare-metal/android.md 中「三段式」构建规则rust_ffi_static→cc_binary→raw_binary再结合课程 src/bare-metal/aps 系列源码理解入口点、页表与链接脚本的底层细节你就能快速为 Android 虚拟化环境编写可启动、可打印、可正常关机的裸机 Rust 虚拟机程序。【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表