Skip to content

Commit f362f85

Browse files
committed
feat: 实现 x86_64 架构的虚拟机管理,添加 VM 初始化和运行逻辑
1 parent b80c27e commit f362f85

File tree

9 files changed

+471
-81
lines changed

9 files changed

+471
-81
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ axvmconfig = {version = "0.1", default-features = false}
4444
fdt-edit = "0.1"
4545

4646
[target.'cfg(target_arch = "x86_64")'.dependencies]
47+
raw-cpuid = "11"
4748
x86_vcpu = "0.1"
4849
axplat-x86-qemu-q35.workspace = true
4950

src/arch/x86_64/cpu.rs

Lines changed: 174 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use core::{
22
fmt::{self, Debug, Display},
33
ops::Deref,
44
};
5+
use std::os::arceos::modules::axalloc;
56

67
use axvm_types::addr::*;
7-
use x86_vcpu::*;
8+
use memory_addr::{PAGE_SIZE_4K, PhysAddr, VirtAddr};
89

910
use crate::{
1011
RunError,
@@ -16,34 +17,76 @@ use crate::{
1617
},
1718
};
1819

20+
// ==================== x86 VCPU HAL 实现 ====================
21+
// x86_vcpu 现在使用自己的 Hal trait,不需要 AxVCpuHal
22+
23+
/// x86 VCPU 的 HAL 实现 - 实现 x86_vcpu::Hal trait
24+
pub(super) struct X86VcpuHal;
25+
26+
impl x86_vcpu::Hal for X86VcpuHal {
27+
fn alloc_frame() -> Option<usize> {
28+
axalloc::global_allocator()
29+
.alloc_pages(1, PAGE_SIZE_4K, axalloc::UsageKind::Global)
30+
.ok()
31+
}
32+
33+
fn dealloc_frame(paddr: usize) {
34+
axalloc::global_allocator().dealloc_pages(paddr, 1, axalloc::UsageKind::Global);
35+
}
36+
37+
fn phys_to_virt(paddr: usize) -> usize {
38+
axhal::mem::phys_to_virt(PhysAddr::from(paddr)).into()
39+
}
40+
41+
fn virt_to_phys(vaddr: usize) -> usize {
42+
axhal::mem::virt_to_phys(VirtAddr::from(vaddr)).into()
43+
}
44+
}
45+
46+
// 使用具体的泛型类型
47+
type VmxPerCpuState = x86_vcpu::VmxArchPerCpuState<X86VcpuHal>;
48+
type VmxVcpu = x86_vcpu::VmxArchVCpu<X86VcpuHal>;
49+
1950
pub struct HCpu {
2051
pub id: CpuId,
2152
pub hard_id: CpuHardId,
22-
vpercpu: VmxArchVCpu,
53+
vpercpu: VmxPerCpuState,
2354
max_guest_page_table_levels: usize,
2455
pub pa_range: core::ops::Range<usize>,
56+
pub pa_bits: usize,
2557
}
2658

2759
impl HCpu {
2860
pub fn new(id: CpuId) -> Self {
29-
let mpidr = MPIDR_EL1.get() as usize;
30-
let hard_id = mpidr & 0xff_ff_ff;
61+
// 使用 raw_cpuid 获取 x86 APIC ID
62+
let apic_id = raw_cpuid::CpuId::new()
63+
.get_feature_info()
64+
.map(|f| f.initial_local_apic_id() as usize)
65+
.unwrap_or(0);
66+
let hard_id = CpuHardId::new(apic_id);
3167

32-
let vpercpu = Aarch64PerCpu::new();
68+
// 创建 x86 PerCpu 状态
69+
let vpercpu = VmxPerCpuState::new(id.raw()).expect("Failed to create VmxPerCpuState");
3370

3471
HCpu {
3572
id,
36-
hard_id: CpuHardId::new(hard_id),
73+
hard_id,
3774
vpercpu,
3875
max_guest_page_table_levels: 0,
3976
pa_range: 0..0,
77+
pa_bits: 0,
4078
}
4179
}
4280

4381
pub fn init(&mut self) -> anyhow::Result<()> {
44-
self.vpercpu.hardware_enable();
45-
self.max_guest_page_table_levels = self.vpercpu.max_guest_page_table_levels();
46-
self.pa_range = self.vpercpu.pa_range();
82+
// 启用 VMX 硬件虚拟化
83+
self.vpercpu.hardware_enable()?;
84+
85+
// x86_64 平台的固定配置
86+
self.max_guest_page_table_levels = 4; // 4-level page tables (PML4)
87+
self.pa_bits = 48; // 典型的 x86_64 物理地址宽度
88+
self.pa_range = 0..(1 << self.pa_bits);
89+
4790
Ok(())
4891
}
4992

@@ -65,46 +108,54 @@ impl Display for HCpu {
65108
"
66109
CPU {}:
67110
Hard ID: {}
68-
PT Levels: {}",
69-
self.id, self.hard_id, self.max_guest_page_table_levels
111+
PT Levels: {}
112+
PA Bits: {}",
113+
self.id, self.hard_id, self.max_guest_page_table_levels, self.pa_bits
70114
)
71115
}
72116
}
73117

74-
pub(super) struct VCpuHal;
75-
76-
impl arm_vcpu::CpuHal for VCpuHal {
77-
fn irq_hanlder(&self) {
78-
axhal::irq::irq_handler(0);
79-
}
80-
81-
fn inject_interrupt(&self, irq: usize) {
82-
todo!()
83-
}
84-
}
85-
118+
// x86 特定的 VCPU
86119
pub struct VCpu {
87-
pub vcpu: arm_vcpu::Aarch64VCpu,
120+
pub vcpu: VmxVcpu,
88121
common: VCpuCommon,
89122
}
90123

91124
impl VCpu {
92125
pub fn new(
93126
host_cpuid: Option<CpuId>,
94-
dtb_addr: GuestPhysAddr,
127+
_dtb_addr: GuestPhysAddr, // 参数保留以保持接口兼容性,x86 不使用设备树
95128
vm: VmDataWeak,
96129
) -> anyhow::Result<Self> {
97130
let common = VCpuCommon::new_exclusive(host_cpuid, vm)?;
98131

99132
let hard_id = common.hard_id();
133+
let vm_id = common.vm_id().into();
134+
let vcpu_id = common.bind_id().raw();
135+
136+
// 使用 x86_vcpu 的新方法创建 VCPU
137+
let vcpu = VmxVcpu::new(vm_id, vcpu_id)
138+
.map_err(|e| anyhow::anyhow!("Failed to create VmxVcpu: {:?}", e))?;
139+
140+
info!(
141+
"Created x86 VCPU: vm_id={}, vcpu_id={}, hard_id={}",
142+
vm_id,
143+
vcpu_id,
144+
hard_id.raw()
145+
);
100146

101-
let vcpu = arm_vcpu::Aarch64VCpu::new(Aarch64VCpuCreateConfig {
102-
mpidr_el1: hard_id.raw() as u64,
103-
dtb_addr: dtb_addr.as_usize(),
104-
})
105-
.unwrap();
106147
Ok(VCpu { vcpu, common })
107148
}
149+
150+
pub fn set_pt_level(&mut self, level: usize) {
151+
// x86 通过 EPT 配置,此方法预留以保持接口兼容性
152+
debug!("Setting page table level to {} (no-op on x86)", level);
153+
}
154+
155+
pub fn set_pa_bits(&mut self, pa_bits: usize) {
156+
// x86 通过 EPT 配置,此方法预留以保持接口兼容性
157+
debug!("Setting PA bits to {} (no-op on x86)", pa_bits);
158+
}
108159
}
109160

110161
impl VCpuOp for VCpu {
@@ -117,62 +168,119 @@ impl VCpuOp for VCpu {
117168
}
118169

119170
fn run(&mut self) -> Result<(), RunError> {
120-
info!("Starting vCPU {}", self.bind_id());
121-
self.vcpu
122-
.setup_current_cpu(self.vm_id().into())
123-
.map_err(|e| anyhow!("{e}"))?;
171+
info!("Starting x86 vCPU {}", self.bind_id());
172+
173+
// 绑定到当前 CPU - 使用 x86_vcpu 的新方法
174+
self.vcpu.bind().map_err(|e| {
175+
RunError::ExitWithError(anyhow::anyhow!("Failed to bind VCPU: {:?}", e))
176+
})?;
177+
124178
while self.is_active() {
125-
debug!("vCPU {} entering guest", self.bind_id());
126-
let exit_reason = self.vcpu.run().map_err(|e| anyhow!("{e}"))?;
179+
debug!("x86 vCPU {} entering guest", self.bind_id());
180+
181+
// 使用 x86_vcpu 的 run_arch 方法,返回自己的 VmxExitReason
182+
let exit_reason = self.vcpu.run().map_err(|e| {
183+
RunError::ExitWithError(anyhow::anyhow!("VCPU run failed: {:?}", e))
184+
})?;
185+
127186
debug!(
128-
"vCPU {} exited with reason: {:?}",
187+
"x86 vCPU {} exited with reason: {:?}",
129188
self.bind_id(),
130189
exit_reason
131190
);
191+
192+
// 根据用户优先级处理退出原因 - 使用 x86_vcpu 的 VmxExitReason
132193
match exit_reason {
133-
arm_vcpu::AxVCpuExitReason::Hypercall { nr, args } => todo!(),
134-
arm_vcpu::AxVCpuExitReason::MmioRead {
135-
addr,
136-
width,
137-
reg,
138-
reg_width,
139-
signed_ext,
140-
} => todo!(),
141-
arm_vcpu::AxVCpuExitReason::MmioWrite { addr, width, data } => todo!(),
142-
arm_vcpu::AxVCpuExitReason::SysRegRead { addr, reg } => todo!(),
143-
arm_vcpu::AxVCpuExitReason::SysRegWrite { addr, value } => todo!(),
144-
arm_vcpu::AxVCpuExitReason::ExternalInterrupt => {
145-
axhal::irq::irq_handler(0);
194+
// 高优先级:外部中断(必须实现)
195+
x86_vcpu::VmxExitReason::ExternalInterrupt { vector } => {
196+
debug!("Handling external interrupt, vector={}", vector);
197+
axhal::irq::irq_handler(vector);
198+
}
199+
200+
// 高优先级:系统寄存器访问 (MSR)
201+
x86_vcpu::VmxExitReason::SysRegRead { addr, reg } => {
202+
// TODO: 实现 MSR 读取处理
203+
// x86_vcpu 的 VmxVcpu 已经处理了 x2APIC MSR 访问
204+
// 这里需要处理其他 MSR 的读取
205+
todo!("MSR read: addr={:?}, reg={}", addr, reg);
206+
}
207+
x86_vcpu::VmxExitReason::SysRegWrite { addr, value } => {
208+
// TODO: 实现 MSR 写入处理
209+
todo!("MSR write: addr={:?}, value={:#x}", addr, value);
210+
}
211+
212+
// 高优先级:IO 指令
213+
x86_vcpu::VmxExitReason::IoRead { port, width } => {
214+
// TODO: 实现端口 IO 读取
215+
// 需要连接到设备模拟层
216+
todo!("IO read: port={:?}, width={:?}", port, width);
217+
}
218+
x86_vcpu::VmxExitReason::IoWrite { port, width, data } => {
219+
// TODO: 实现端口 IO 写入
220+
// 需要连接到设备模拟层
221+
todo!(
222+
"IO write: port={:?}, width={:?}, data={:#x}",
223+
port,
224+
width,
225+
data
226+
);
146227
}
147-
arm_vcpu::AxVCpuExitReason::CpuUp {
228+
229+
// 中优先级:超级调用
230+
x86_vcpu::VmxExitReason::Hypercall { nr, args } => {
231+
// TODO: 实现超级调用接口
232+
todo!("Hypercall: nr={:#x}, args={:?}", nr, args);
233+
}
234+
235+
// 低优先级:CPU 启动
236+
x86_vcpu::VmxExitReason::CpuUp {
148237
target_cpu,
149238
entry_point,
150239
arg,
151240
} => {
152-
debug!("vCPU {} requested CPU {} up", self.bind_id(), target_cpu);
241+
debug!(
242+
"x86 vCPU {} requested CPU {} up",
243+
self.bind_id(),
244+
target_cpu
245+
);
153246
self.vm()?.with_machine_running_mut(|running| {
154247
debug!("vCPU {} is bringing up CPU {}", self.bind_id(), target_cpu);
155-
running.cpu_up(CpuHardId::new(target_cpu as _), entry_point, arg)
248+
// 将 axaddrspace::GuestPhysAddr 转换为 axvm_types::addr::GuestPhysAddr
249+
// 先转为 usize,再转为目标类型
250+
let entry: GuestPhysAddr = entry_point.as_usize().into();
251+
running.cpu_up(CpuHardId::new(target_cpu), entry, arg)
156252
})??;
253+
// x86 使用 SIPI (Startup IPI) 启动 AP,返回值在 RAX 中
157254
self.vcpu.set_gpr(0, 0);
158255
}
159-
arm_vcpu::AxVCpuExitReason::CpuDown { _state } => todo!(),
160-
arm_vcpu::AxVCpuExitReason::SystemDown => {
161-
info!("vCPU {} requested system shutdown", self.bind_id());
256+
257+
x86_vcpu::VmxExitReason::CpuDown { state } => {
258+
// TODO: 实现 CPU 关闭
259+
todo!("CPU down: state={:?}", state);
260+
}
261+
262+
// 系统关闭
263+
x86_vcpu::VmxExitReason::SystemDown => {
264+
info!("x86 vCPU {} requested system shutdown", self.bind_id());
162265
self.vm()?.stop()?;
266+
break;
267+
}
268+
269+
x86_vcpu::VmxExitReason::Nothing => {
270+
// 无操作,继续运行
271+
}
272+
273+
_ => {
274+
warn!("Unhandled x86 VCPU exit reason: {:?}", exit_reason);
163275
}
164-
arm_vcpu::AxVCpuExitReason::Nothing => {}
165-
arm_vcpu::AxVCpuExitReason::SendIPI {
166-
target_cpu,
167-
target_cpu_aux,
168-
send_to_all,
169-
send_to_self,
170-
vector,
171-
} => todo!(),
172-
_ => todo!(),
173276
}
174277
}
175278

279+
// 解绑 VCPU - 使用 x86_vcpu 的新方法
280+
self.vcpu.unbind().map_err(|e| {
281+
RunError::ExitWithError(anyhow::anyhow!("Failed to unbind VCPU: {:?}", e))
282+
})?;
283+
176284
Ok(())
177285
}
178286
}
@@ -187,7 +295,7 @@ impl Deref for VCpu {
187295

188296
impl Debug for VCpu {
189297
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190-
f.debug_struct("VCpu")
298+
f.debug_struct("x86::VCpu")
191299
.field("bind_id", &self.bind_id())
192300
.field("hard_id", &self.hard_id())
193301
.field("vcpu", &self.vcpu)

0 commit comments

Comments
 (0)