Skip to content

Commit e1d5326

Browse files
committed
feat: 添加 x86_64 架构支持,包含 CPU 和 HAL 模块的实现
1 parent ce4ce80 commit e1d5326

File tree

6 files changed

+247
-4
lines changed

6 files changed

+247
-4
lines changed

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ anyhow = {version = "1.0", default-features = false}
1414
cfg-if = "1.0"
1515
lazyinit = "0.2"
1616
log = "0.4"
17+
ranges-ext.workspace = true
1718
spin = "0.10"
1819
thiserror = {version = "2", default-features = false}
1920
timer_list = "0.1"
20-
ranges-ext.workspace = true
2121

2222
# System independent crates provided by ArceOS.
2323
axerrno = "0.1.0"
@@ -31,7 +31,6 @@ percpu = {version = "0.2", features = ["arm-el2"]}
3131
vm-allocator.workspace = true
3232
vm-fdt.workspace = true
3333

34-
3534
# System dependent modules provided by ArceOS-Hypervisor.
3635
axaddrspace = "0.2"
3736
# axdevice = {git = "https://github.com/arceos-hypervisor/axdevice.git"}
@@ -45,7 +44,8 @@ axvmconfig = {version = "0.1", default-features = false}
4544
fdt-edit = "0.1"
4645

4746
[target.'cfg(target_arch = "x86_64")'.dependencies]
48-
# x86_vcpu = "0.1"
47+
x86_vcpu = "0.1"
48+
axplat-x86-qemu-q35.workspace = true
4949

5050
[target.'cfg(target_arch = "riscv64")'.dependencies]
5151
# riscv_vcpu = "0.1"

src/arch/aarch64/cpu.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,15 @@ impl VCpu {
102102
let vcpu = arm_vcpu::Aarch64VCpu::new(Aarch64VCpuCreateConfig {
103103
mpidr_el1: hard_id.raw() as u64,
104104
dtb_addr: dtb_addr.as_usize(),
105+
pt_level: 4,
105106
})
106107
.unwrap();
107108
Ok(VCpu { vcpu, common })
108109
}
110+
111+
pub fn set_pt_level(&mut self, level: usize) {
112+
self.vcpu.pt_level = level;
113+
}
109114
}
110115

111116
impl VCpuOp for VCpu {
@@ -119,6 +124,7 @@ impl VCpuOp for VCpu {
119124

120125
fn run(&mut self) -> Result<(), RunError> {
121126
info!("Starting vCPU {}", self.bind_id());
127+
122128
self.vcpu
123129
.setup_current_cpu(self.vm_id().into())
124130
.map_err(|e| anyhow!("{e}"))?;

src/arch/aarch64/vm/unint.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ impl VmMachineUninit {
120120
for vcpu in &mut cpus {
121121
vcpu.vcpu.set_entry(kernel_entry).unwrap();
122122
vcpu.vcpu.set_dtb_addr(dtb_addr).unwrap();
123+
vcpu.set_pt_level(self.pt_levels);
123124

124125
let setup_config = Aarch64VCpuSetupConfig {
125126
passthrough_interrupt: self.config.interrupt_mode()

src/arch/x86_64/cpu.rs

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
use core::{
2+
fmt::{self, Debug, Display},
3+
ops::Deref,
4+
};
5+
6+
use axvm_types::addr::*;
7+
use x86_vcpu::*;
8+
9+
use crate::{
10+
RunError,
11+
data::VmDataWeak,
12+
vcpu::{VCpuCommon, VCpuOp},
13+
vhal::{
14+
ArchCpuData,
15+
cpu::{CpuHardId, CpuId},
16+
},
17+
};
18+
19+
pub struct HCpu {
20+
pub id: CpuId,
21+
pub hard_id: CpuHardId,
22+
vpercpu: VmxArchVCpu,
23+
max_guest_page_table_levels: usize,
24+
pub pa_range: core::ops::Range<usize>,
25+
}
26+
27+
impl HCpu {
28+
pub fn new(id: CpuId) -> Self {
29+
let mpidr = MPIDR_EL1.get() as usize;
30+
let hard_id = mpidr & 0xff_ff_ff;
31+
32+
let vpercpu = Aarch64PerCpu::new();
33+
34+
HCpu {
35+
id,
36+
hard_id: CpuHardId::new(hard_id),
37+
vpercpu,
38+
max_guest_page_table_levels: 0,
39+
pa_range: 0..0,
40+
}
41+
}
42+
43+
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();
47+
Ok(())
48+
}
49+
50+
pub fn max_guest_page_table_levels(&self) -> usize {
51+
self.max_guest_page_table_levels
52+
}
53+
}
54+
55+
impl ArchCpuData for HCpu {
56+
fn hard_id(&self) -> CpuHardId {
57+
self.hard_id
58+
}
59+
}
60+
61+
impl Display for HCpu {
62+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
63+
write!(
64+
f,
65+
"
66+
CPU {}:
67+
Hard ID: {}
68+
PT Levels: {}",
69+
self.id, self.hard_id, self.max_guest_page_table_levels
70+
)
71+
}
72+
}
73+
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+
86+
pub struct VCpu {
87+
pub vcpu: arm_vcpu::Aarch64VCpu,
88+
common: VCpuCommon,
89+
}
90+
91+
impl VCpu {
92+
pub fn new(
93+
host_cpuid: Option<CpuId>,
94+
dtb_addr: GuestPhysAddr,
95+
vm: VmDataWeak,
96+
) -> anyhow::Result<Self> {
97+
let common = VCpuCommon::new_exclusive(host_cpuid, vm)?;
98+
99+
let hard_id = common.hard_id();
100+
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();
106+
Ok(VCpu { vcpu, common })
107+
}
108+
}
109+
110+
impl VCpuOp for VCpu {
111+
fn bind_id(&self) -> CpuId {
112+
self.common.bind_id()
113+
}
114+
115+
fn hard_id(&self) -> CpuHardId {
116+
self.common.hard_id()
117+
}
118+
119+
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}"))?;
124+
while self.is_active() {
125+
debug!("vCPU {} entering guest", self.bind_id());
126+
let exit_reason = self.vcpu.run().map_err(|e| anyhow!("{e}"))?;
127+
debug!(
128+
"vCPU {} exited with reason: {:?}",
129+
self.bind_id(),
130+
exit_reason
131+
);
132+
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);
146+
}
147+
arm_vcpu::AxVCpuExitReason::CpuUp {
148+
target_cpu,
149+
entry_point,
150+
arg,
151+
} => {
152+
debug!("vCPU {} requested CPU {} up", self.bind_id(), target_cpu);
153+
self.vm()?.with_machine_running_mut(|running| {
154+
debug!("vCPU {} is bringing up CPU {}", self.bind_id(), target_cpu);
155+
running.cpu_up(CpuHardId::new(target_cpu as _), entry_point, arg)
156+
})??;
157+
self.vcpu.set_gpr(0, 0);
158+
}
159+
arm_vcpu::AxVCpuExitReason::CpuDown { _state } => todo!(),
160+
arm_vcpu::AxVCpuExitReason::SystemDown => {
161+
info!("vCPU {} requested system shutdown", self.bind_id());
162+
self.vm()?.stop()?;
163+
}
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!(),
173+
}
174+
}
175+
176+
Ok(())
177+
}
178+
}
179+
180+
impl Deref for VCpu {
181+
type Target = VCpuCommon;
182+
183+
fn deref(&self) -> &Self::Target {
184+
&self.common
185+
}
186+
}
187+
188+
impl Debug for VCpu {
189+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190+
f.debug_struct("VCpu")
191+
.field("bind_id", &self.bind_id())
192+
.field("hard_id", &self.hard_id())
193+
.field("vcpu", &self.vcpu)
194+
.finish()
195+
}
196+
}

src/arch/x86_64/hal.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use alloc::vec::Vec;
2+
3+
use crate::vhal::{
4+
ArchHal,
5+
cpu::{CpuHardId, CpuId},
6+
};
7+
8+
use super::cpu::{HCpu, VCpuHal};
9+
10+
pub struct Hal;
11+
12+
impl ArchHal for Hal {
13+
fn current_cpu_init(id: CpuId) -> anyhow::Result<HCpu> {
14+
info!("Enabling virtualization on cpu {id}");
15+
let mut cpu = HCpu::new(id);
16+
cpu.init()?;
17+
info!("{cpu}");
18+
Ok(cpu)
19+
}
20+
21+
fn init() -> anyhow::Result<()> {
22+
23+
24+
Ok(())
25+
}
26+
27+
fn cpu_list() -> Vec<CpuHardId> {
28+
29+
}
30+
31+
fn cpu_hard_id() -> CpuHardId {
32+
let mpidr = MPIDR_EL1.get() as usize;
33+
CpuHardId::new(mpidr)
34+
}
35+
36+
fn cache_flush(vaddr: arm_vcpu::HostVirtAddr, size: usize) {
37+
dcache_range(CacheOp::CleanAndInvalidate, vaddr.as_usize(), size);
38+
}
39+
}

src/arch/x86_64/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
1+
mod cpu;
2+
mod hal;

0 commit comments

Comments
 (0)