Skip to content

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(&regs)?;
        
        // 设置特殊寄存器
        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(&regs)?;
        
        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,
    
    // ...
}

下一步