You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

M1 macOS下Hypervisor Framework的hv_vcpu_run无法返回问题

基于Hypervisor Framework开发虚拟机管理器时hv_vcpu_run无法返回的问题

我在基于Hypervisor Framework开发虚拟机管理器时,遇到hv_vcpu_run始终无法返回的问题。按预期,待执行代码会触发MMIO操作,该函数应当返回。相同代码在Asahi Linux的KVM环境中测试时,KVM_RUN可正常返回KVM_EXIT_MMIO,符合预期。

vCPU配置代码

// 设置PSTATE。
    states.set_pstate(
        Pstate::new()
            .with_m(0b0101) // EL1,使用SP_EL1(EL1h)。
            .with_f(true)
            .with_i(true)
            .with_a(true)
            .with_d(true),
    );

    // 启用MMU以支持虚拟地址,并设置TCR_EL1。
    states.set_sctlr(
        Sctlr::new()
            .with_m(true)
            .with_c(true)
            .with_itd(true)
            .with_i(true)
            .with_tscxt(true)
            .with_span(true)
            .with_ntlsmd(true)
            .with_lsmaoe(true),
    );
    states.set_mair_el1(map.memory_attrs);
    states.set_tcr(
        Tcr::new()
            .with_ips(feats.mmfr0.pa_range())
            .with_tg1(match map.page_size.get() {
                0x4000 => 0b01, // TTBR1_EL1使用16K页。
                _ => todo!(),
            })
            .with_sh1(0b11)
            .with_orgn1(0b01)
            .with_irgn1(0b01)
            .with_t1sz(16)
            .with_tg0(match map.page_size.get() {
                0x4000 => 0b10, // TTBR0_EL1使用16K页。
                _ => todo!(),
            })
            .with_sh0(0b11)
            .with_orgn0(0b01)
            .with_irgn0(0b01)
            .with_t0sz(16),
    );

    // 设置页表。由于虚拟设备使用恒等映射,需要同时设置低地址和高地址VA。
    states.set_ttbr0_el1(map.page_table);
    states.set_ttbr1_el1(map.page_table);

    // 设置入口点、参数和栈指针。
    states.set_x0(map.env_vaddr);
    states.set_x1(map.conf_vaddr);
    states.set_sp_el1(map.stack_vaddr + map.stack_len); // 栈向下增长。
    states.set_pc(map.kern_vaddr + entry);

    states
        .commit()
        .map_err(|e| MainCpuError::CommitCpuStatesFailed(Box::new(e)))

commit方法实现

fn commit(self) -> Result<(), Self::Err> {
        use hv_sys::{
            hv_reg_t_HV_REG_CPSR as HV_REG_CPSR, hv_reg_t_HV_REG_PC as HV_REG_PC,
            hv_reg_t_HV_REG_X0 as HV_REG_X0, hv_reg_t_HV_REG_X1 as HV_REG_X1,
            hv_sys_reg_t_HV_SYS_REG_MAIR_EL1 as HV_SYS_REG_MAIR_EL1,
            hv_sys_reg_t_HV_SYS_REG_SCTLR_EL1 as HV_SYS_REG_SCTLR_EL1,
            hv_sys_reg_t_HV_SYS_REG_SP_EL1 as HV_SYS_REG_SP_EL1,
            hv_sys_reg_t_HV_SYS_REG_TCR_EL1 as HV_SYS_REG_TCR_EL1,
            hv_sys_reg_t_HV_SYS_REG_TTBR0_EL1 as HV_SYS_REG_TTBR0_EL1,
            hv_sys_reg_t_HV_SYS_REG_TTBR1_EL1 as HV_SYS_REG_TTBR1_EL1, hv_vcpu_set_reg,
            hv_vcpu_set_sys_reg,
        };

        // 设置PSTATE。Hypervisor Framework使用CPSR表示PSTATE。
        let cpu = self.cpu.instance;
        let set_reg = |reg, val| match NonZero::new(unsafe { hv_vcpu_set_reg(cpu, reg, val) }) {
            Some(v) => Err(v),
            None => Ok(()),
        };

        if let State::Dirty(v) = self.pstate {
            set_reg(HV_REG_CPSR, v).map_err(StatesError::SetPstateFailed)?;
        }

        // 设置系统寄存器。
        let set_sys = |reg, val| match NonZero::new(unsafe { hv_vcpu_set_sys_reg(cpu, reg, val) }) {
            Some(v) => Err(v),
            None => Ok(()),
        };

        if let State::Dirty(v) = self.mair_el1 {
            set_sys(HV_SYS_REG_MAIR_EL1, v).map_err(StatesError::SetMairEl1Failed)?;
        }

        if let State::Dirty(v) = self.ttbr0_el1 {
            set_sys(HV_SYS_REG_TTBR0_EL1, v).map_err(StatesError::SetTtbr0El1Failed)?;
        }

        if let State::Dirty(v) = self.ttbr1_el1 {
            set_sys(HV_SYS_REG_TTBR1_EL1, v).map_err(StatesError::SetTtbr1El1Failed)?;
        }

        if let State::Dirty(v) = self.tcr {
            set_sys(HV_SYS_REG_TCR_EL1, v).map_err(StatesError::SetTcrFailed)?;
        }

        if let State::Dirty(v) = self.sctlr {
            set_sys(HV_SYS_REG_SCTLR_EL1, v).map_err(StatesError::SetSctlrFailed)?;
        }

        if let State::Dirty(v) = self.sp_el1 {
            set_sys(HV_SYS_REG_SP_EL1, v).map_err(StatesError::SetSpEl1Failed)?;
        }

        // 设置通用寄存器。
        if let State::Dirty(v) = self.pc {
            set_reg(HV_REG_PC, v).map_err(StatesError::SetPcFailed)?;
        }

        if let State::Dirty(v) = self.x0 {
            set_reg(HV_REG_X0, v).map_err(StatesError::SetX0Failed)?;
        }

        if let State::Dirty(v) = self.x1 {
            set_reg(HV_REG_X1, v).map_err(StatesError::SetX1Failed)?;
        }

        Ok(())
    }

内容的提问来源于stack exchange,提问作者user1829232

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:57:12