CPU 管理:vCPU 生命周期
概述
cpu.rs 实现了 vCPU 的完整生命周期管理,包括创建、配置、运行、暂停和快照。本文深入分析其设计和实现。
核心结构
CpuManager
rust
// vmm/src/cpu.rs (2773 行)
pub struct CpuManager {
// vCPU 列表
vcpus: Vec<Option<Vcpu>>,
// 配置
config: CpusConfig,
// 内存管理器
memory_manager: Arc<Mutex<MemoryManager>>,
// 设备管理器
device_manager: Arc<Mutex<DeviceManager>>,
// 中断管理器
interrupt_manager: Arc<dyn InterruptManager>,
// 事件
vcpu_exit_evt: EventFd,
vcpu_pause_evt: EventFd,
// 状态
boot_vcpus: u8,
max_vcpus: u8,
// 拓扑
topology: Option<CpuTopology>,
}Vcpu 结构
rust
// vmm/src/cpu.rs
pub struct Vcpu {
// vCPU ID
id: u8,
// hypervisor vCPU
vcpu: Arc<dyn hypervisor::Vcpu>,
// 状态
state: VcpuState,
// 线程
thread: Option<JoinHandle<Result<()>>>,
// 事件
kill_evt: EventFd,
pause_evt: EventFd,
}
pub enum VcpuState {
Created,
Running,
Paused,
Exited,
}vCPU 创建
创建流程
实现代码
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn new(
config: &CpusConfig,
memory_manager: &Arc<Mutex<MemoryManager>>,
device_manager: &Arc<Mutex<DeviceManager>>,
) -> Result<Self> {
// 1. 创建 hypervisor
let hypervisor = hypervisor::new()?;
// 2. 创建 VM
let vm = hypervisor.create_vm()?;
// 3. 创建 vCPU 列表
let mut vcpus = Vec::new();
for id in 0..config.boot_vcpus {
// 创建 vCPU
let vcpu = vm.create_vcpu(id)?;
// 创建 Vcpu 实例
let vcpu_instance = Vcpu::new(id, vcpu)?;
vcpus.push(Some(vcpu_instance));
}
Ok(Self {
vcpus,
config: config.clone(),
memory_manager: memory_manager.clone(),
device_manager: device_manager.clone(),
// ...
})
}
}vCPU 配置
CPUID 配置
rust
// vmm/src/cpu.rs
impl Vcpu {
pub fn configure_cpuid(&self, config: &CpusConfig) -> Result<()> {
// 获取主机 CPUID
let mut cpuid = self.vcpu.get_cpuid2()?;
// 过滤 CPUID
arch::x86_64::cpuid_filter::filter_cpuid(
&mut cpuid,
config.boot_vcpus,
config.max_vcpus,
config.topology.as_ref(),
config.kvm_hyperv,
)?;
// 设置 CPUID
self.vcpu.set_cpuid2(&cpuid)?;
Ok(())
}
}寄存器配置
rust
// vmm/src/cpu.rs
impl Vcpu {
pub fn configure_registers(&self, entry_point: EntryPoint) -> Result<()> {
// 设置通用寄存器
let mut regs = self.vcpu.get_regs()?;
regs.rip = entry_point.kernel_addr.raw_value();
regs.rsp = arch::x86_64::layout::BOOT_STACK_POINTER.raw_value();
regs.rbp = arch::x86_64::layout::BOOT_STACK_POINTER.raw_value();
regs.rsi = arch::x86_64::layout::ZERO_PAGE_START.raw_value();
regs.rflags = 0x00000002;
self.vcpu.set_regs(®s)?;
// 设置特殊寄存器
let mut sregs = self.vcpu.get_sregs()?;
sregs.cs.base = 0;
sregs.cs.limit = 0xFFFFFFFF;
sregs.cs.g = true;
// ... 配置其他段寄存器
self.vcpu.set_sregs(&sregs)?;
// 设置 MSR
self.configure_msrs()?;
// 设置 FPU
self.configure_fpu()?;
Ok(())
}
}aarch64 配置
rust
// vmm/src/cpu.rs
impl Vcpu {
pub fn configure_aarch64(&self, entry_point: EntryPoint) -> Result<()> {
// 设置寄存器
let mut regs = self.vcpu.get_regs_aarch64()?;
regs.pc = entry_point.kernel_addr.raw_value();
regs.sp = arch::aarch64::layout::BOOT_STACK_POINTER.raw_value();
regs.x0 = arch::aarch64::layout::FDT_START.raw_value();
self.vcpu.set_regs_aarch64(®s)?;
Ok(())
}
}vCPU 运行
运行循环
实现代码
rust
// vmm/src/cpu.rs
impl Vcpu {
pub fn run(&mut self) -> Result<()> {
// 1. 配置 vCPU
self.configure()?;
// 2. 启动事件循环
loop {
// 检查暂停事件
if self.pause_evt.read().is_ok() {
self.state = VcpuState::Paused;
// 等待恢复
self.wait_for_resume()?;
}
// 检查退出事件
if self.kill_evt.read().is_ok() {
break;
}
// 运行 vCPU
match self.vcpu.run() {
Ok(exit) => {
match exit {
VmExit::IoOut(addr, data) => {
self.handle_io_out(addr, data)?;
}
VmExit::IoIn(addr, data) => {
self.handle_io_in(addr, &mut data)?;
}
VmExit::MmioRead(addr, data) => {
self.handle_mmio_read(addr, &mut data)?;
}
VmExit::MmioWrite(addr, data) => {
self.handle_mmio_write(addr, &data)?;
}
VmExit::Hlt => {
// 停机,等待中断
}
VmExit::Shutdown => {
break;
}
_ => {}
}
}
Err(e) => {
error!("vCPU run error: {:?}", e);
break;
}
}
}
self.state = VcpuState::Exited;
Ok(())
}
}I/O 处理
rust
// vmm/src/cpu.rs
impl Vcpu {
fn handle_io_out(&self, addr: u16, data: &[u8]) -> Result<()> {
// 查找设备
if let Some(device) = self.device_manager.get_io_device(addr) {
// 写入设备
device.write(addr, data)?;
}
Ok(())
}
fn handle_io_in(&self, addr: u16, data: &mut [u8]) -> Result<()> {
// 查找设备
if let Some(device) = self.device_manager.get_io_device(addr) {
// 读取设备
device.read(addr, data)?;
}
Ok(())
}
fn handle_mmio_read(&self, addr: u64, data: &mut [u8]) -> Result<()> {
// 查找设备
if let Some(device) = self.device_manager.get_mmio_device(addr) {
// 读取设备
device.read(addr, data)?;
}
Ok(())
}
fn handle_mmio_write(&self, addr: u64, data: &[u8]) -> Result<()> {
// 查找设备
if let Some(device) = self.device_manager.get_mmio_device(addr) {
// 写入设备
device.write(addr, data)?;
}
Ok(())
}
}vCPU 管理
启动 vCPU
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn start_vcpus(&mut self) -> Result<()> {
for vcpu in self.vcpus.iter_mut().flatten() {
// 创建事件
let kill_evt = EventFd::new(EFD_NONBLOCK)?;
let pause_evt = EventFd::new(EFD_NONBLOCK)?;
// 克隆 vCPU
let mut vcpu_clone = vcpu.clone();
// 启动线程
let thread = thread::Builder::new()
.name(format!("vcpu-{}", vcpu.id))
.spawn(move || {
vcpu_clone.run()
})?;
vcpu.thread = Some(thread);
vcpu.kill_evt = kill_evt;
vcpu.pause_evt = pause_evt;
vcpu.state = VcpuState::Running;
}
Ok(())
}
}暂停 vCPU
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn pause_vcpus(&mut self) -> Result<()> {
for vcpu in self.vcpus.iter_mut().flatten() {
// 发送暂停事件
vcpu.pause_evt.write(1)?;
vcpu.state = VcpuState::Paused;
}
Ok(())
}
}恢复 vCPU
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn resume_vcpus(&mut self) -> Result<()> {
for vcpu in self.vcpus.iter_mut().flatten() {
// 发送恢复事件
vcpu.pause_evt.write(1)?;
vcpu.state = VcpuState::Running;
}
Ok(())
}
}停止 vCPU
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn stop_vcpus(&mut self) -> Result<()> {
for vcpu in self.vcpus.iter_mut().flatten() {
// 发送退出事件
vcpu.kill_evt.write(1)?;
// 等待线程结束
if let Some(thread) = vcpu.thread.take() {
thread.join().unwrap()?;
}
vcpu.state = VcpuState::Exited;
}
Ok(())
}
}vCPU 热插拔
添加 vCPU
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn add_vcpu(&mut self) -> Result<()> {
let id = self.vcpus.len() as u8;
// 检查是否超过最大值
if id >= self.max_vcpus {
return Err(Error::MaxVcpusReached);
}
// 创建 vCPU
let vcpu = self.vm.create_vcpu(id)?;
let mut vcpu_instance = Vcpu::new(id, vcpu)?;
// 配置 vCPU
vcpu_instance.configure()?;
// 启动 vCPU
vcpu_instance.start()?;
self.vcpus.push(Some(vcpu_instance));
Ok(())
}
}移除 vCPU
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn remove_vcpu(&mut self, id: u8) -> Result<()> {
// 查找 vCPU
let vcpu = self.vcpus.get_mut(id as usize)
.ok_or(Error::VcpuNotFound)?;
if let Some(vcpu) = vcpu.take() {
// 停止 vCPU
vcpu.stop()?;
}
Ok(())
}
}快照与恢复
vCPU 快照
rust
// vmm/src/cpu.rs
impl Vcpu {
pub fn snapshot(&self) -> Result<VcpuSnapshot> {
// 获取寄存器状态
let regs = self.vcpu.get_regs()?;
let sregs = self.vcpu.get_sregs()?;
let xsave = self.vcpu.get_xsave()?;
let lapic = self.vcpu.get_lapic()?;
Ok(VcpuSnapshot {
id: self.id,
regs,
sregs,
xsave,
lapic,
state: self.state.clone(),
})
}
}vCPU 恢复
rust
// vmm/src/cpu.rs
impl Vcpu {
pub fn restore(&mut self, snapshot: VcpuSnapshot) -> Result<()> {
// 恢复寄存器状态
self.vcpu.set_regs(&snapshot.regs)?;
self.vcpu.set_sregs(&snapshot.sregs)?;
self.vcpu.set_xsave(&snapshot.xsave)?;
self.vcpu.set_lapic(&snapshot.lapic)?;
self.state = snapshot.state;
Ok(())
}
}性能优化
1. CPU 亲和性
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn set_cpu_affinity(&self, vcpu_id: u8, host_cpus: &[u8]) -> Result<()> {
// 设置 CPU 亲和性
unsafe {
let mut cpu_set = libc::cpu_set_t::new();
for cpu in host_cpus {
libc::CPU_SET(*cpu as usize, &mut cpu_set);
}
libc::sched_setaffinity(
0,
std::mem::size_of::<libc::cpu_set_t>(),
&cpu_set,
);
}
Ok(())
}
}2. NUMA 绑定
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn bind_to_numa_node(&self, vcpu_id: u8, node_id: u32) -> Result<()> {
// 绑定到 NUMA 节点
let node_mask = 1u64 << node_id;
unsafe {
libc::set_mempolicy(
MPOL_BIND,
&node_mask as *const u64,
64,
);
}
Ok(())
}
}3. 中断优化
rust
// vmm/src/cpu.rs
impl CpuManager {
pub fn enable_interrupt_window(&self, vcpu_id: u8) -> Result<()> {
// 启用中断窗口
self.vcpus[vcpu_id as usize]
.as_ref()
.unwrap()
.vcpu
.enable_interrupt_window()?;
Ok(())
}
}错误处理
错误类型
rust
// vmm/src/cpu.rs
#[derive(Debug, Error)]
pub enum Error {
#[error("Error creating vCPU: {0}")]
VcpuCreate(#[source] anyhow::Error),
#[error("Error running vCPU: {0}")]
VcpuRun(#[source] anyhow::Error),
#[error("Error spawning vCPU thread: {0}")]
VcpuSpawn(#[source] io::Error),
#[error("Error generating common CPUID: {0}")]
CommonCpuId(#[source] arch::Error),
#[error("Error configuring vCPU: {0}")]
VcpuConfiguration(#[source] arch::Error),
#[error("vCPU not found")]
VcpuNotFound,
#[error("Maximum vCPUs reached")]
MaxVcpusReached,
// ...
}