You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
从Timer到一般的设备虚拟化
对于目前能想到的绝大部分虚拟设备,它们和 Guest OS 的交互都可以分为两个部分:
Guest OS 到虚拟设备的访问
Guest OS 可能通过以下方式访问虚拟设备:
MSR/CSR
、MMIO
、SBI
(RISC-V
下的Timer
设备)和端口(仅x86
)等。对于这些访问,我们已经有了一定的抽象。这些访问应该被 VCpu 拦截,以AxVCpuExitReason
的形式返回给 AxVM,再交由对应的虚拟设备处理。可以考虑进一步抽象,将所有访问方式都抽象为“地址+读/写+数据”的 tuple,通过泛型或宏等方式,尽量合并不同访问方式的处理逻辑。
AxVCpuExitReason
ControlRegisterRead
{id: usize, reg: usize}
ControlRegisterWrite
{id: usize, reg: usize, value: u64}
MmioRead
MmioWrite
SbiCall
(SbiFunction)
RISC-V
IoRead
x86
IoWrite
x86
虚拟设备到 Guest OS 的通知
绝大多数情况下,虚拟设备通知 Guest OS 的方式是虚拟中断。但虚拟中断并不完全来自虚拟设备,也可能来自直通设备的物理中断(由 Hypervisor 转发)或者来自某个 VCpu 的虚拟 IPI(同样由 Hypervisor 转发)。因此,需要一个统一的虚拟中断注入接口,用以向指定的 VCpu 注入中断。
这个接口应该放置在
AxVM
中,签名类似于inject_interrupt_to_vcpu(target: Option<CpuMask>, vector: usize) -> AxResult
。其中target
可以控制中断注入的目标 VCpu,是任意一个 VCpu,指定一个 VCpu,指定一组 VCpu,或者所有 VCpu;vector
是中断向量。放置在AxVM
中的原因是,中断注入的操作可能需要访问 VGIC 等设备。为了设备不直接依赖于
AxVM
或者AxVCpu
,虚拟设备结构体不能直接调用inject_interrupt_to_vcpu
,而是应当通过提供给设备的一个闭包来实现中断注入。inject_interrupt_to_vcpu
的实现为了保持
AxVM
的架构无关性,AxVCpu
和AxArchVCpu
仍然应该提供一个inject_interrupt
方法,用以向当前 VCpu 注入中断。AxVM
的inject_interrupt_to_vcpu
方法应该根据target
参数,调用对应AxVCpu
的inject_interrupt
方法。在 aarch64 和 riscv64 平台上,AxArchVCpu
在setup
时,应该通过SetupConfig
得到一个实际完成中断注入的闭包;而在 x86 平台上,AxArchVCpu
本身具有中断注入的能力,因此无需进一步的配置。当被注入中断时,如果 VCpu 正在当前核心上运行,可以直接通过各个架构的虚拟化机制注入中断;如果 VCpu 处于当前核心就绪队列中,则应该记录中断,等 VCpu 下次运行时再注入;如果 VCpu 在非当前核心上运行,可以通过 IPI 通知目标核心的 Hypervisor,由 Hypervisor 负责注入中断。
上述的 IPI 通知部分,可以借鉴 shyper 的实现。
附录:关于
TimerList
的设计TimerList
应该成为 Hypervisor 中的一个基础设施,用以管理所有的定时事件。目前来说,TimerList
的作用至少有两个:Timer
设备提供服务,用以实现 Guest OS 的定时器功能;为了尽量提升
TimerList
的通用性,TimerList
中的每一个事件应该仅记录两个信息:到期时间和回调函数。其他信息,如Task
等,都应该放在闭包之内。Beta Was this translation helpful? Give feedback.
All reactions