Skip to content

Commit 70ccc72

Browse files
committed
重构虚拟机内存管理,添加内存区域支持,更新 RunData 结构,优化设备信息管理
1 parent c9dd964 commit 70ccc72

File tree

6 files changed

+159
-27
lines changed

6 files changed

+159
-27
lines changed

src/arch/aarch64/mod.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,3 @@ impl fmt::Display for VmId {
6464
}
6565
}
6666

67-
/// Data needed when VM is running
68-
pub struct RunData {
69-
vcpus: Vec<VCpu>,
70-
address_space: AddrSpace,
71-
devices: BTreeMap<String, DeviceInfo>,
72-
}
73-
74-
/// Information about a device in the VM
75-
#[derive(Debug, Clone)]
76-
pub struct DeviceInfo {}

src/arch/aarch64/vm.rs

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ use super::AddrSpace;
44
use alloc::{collections::BTreeMap, string::String, vec::Vec};
55

66
use crate::{
7-
GuestPhysAddr,
8-
arch::{RunData, cpu::VCpu},
9-
config::AxVMConfig,
10-
vhal::cpu::CpuId,
7+
arch::cpu::VCpu,
8+
config::{AxVMConfig, MemoryKind},
9+
region::Region,
10+
vhal::{cpu::CpuId, phys_to_virt},
1111
vm::{Status, VmId, VmOps},
12+
{GuestPhysAddr, HostPhysAddr, HostVirtAddr},
1213
};
1314

1415
const VM_ASPACE_BASE: usize = 0x0;
@@ -47,11 +48,6 @@ impl ArchVm {
4748

4849
// Create vCPUs
4950
let mut vcpus = Vec::new();
50-
// let dtb_addr = config
51-
// .image_config
52-
// .dtb_load_gpa
53-
// .map(|d| d.as_usize())
54-
// .unwrap_or_default();
5551

5652
let dtb_addr = GuestPhysAddr::from_usize(0);
5753

@@ -94,8 +90,24 @@ impl ArchVm {
9490
)
9591
.map_err(|e| anyhow::anyhow!("Failed to create address space: {:?}", e))?;
9692

97-
// // Initialize devices
98-
// let mut devices = BTreeMap::new();
93+
let mut run_data = RunData {
94+
vcpus,
95+
address_space,
96+
regions: Vec::new(),
97+
devices: BTreeMap::new(),
98+
};
99+
100+
debug!("Mapping memory regions for VM {} ({})", self.id, self.name);
101+
for memory_cfg in config.memory_regions {
102+
run_data.add_memory_region(memory_cfg)?;
103+
}
104+
105+
debug!(
106+
"Mapped {} memory regions for VM {} ({})",
107+
run_data.regions.len(),
108+
self.id,
109+
self.name
110+
);
99111

100112
// // Add emulated devices
101113
// for emu_device in config.emu_devices() {
@@ -184,11 +196,7 @@ impl ArchVm {
184196
// .map_err(|e| anyhow::anyhow!("Failed to setup vCPU {}: {:?}", vcpu_id, e))?;
185197
// }
186198

187-
// self.state = Some(StateMachine::Inited(RunData {
188-
// vcpus,
189-
// address_space,
190-
// devices,
191-
// }));
199+
self.state = Some(StateMachine::Inited(run_data));
192200

193201
Ok(())
194202
}
@@ -499,3 +507,36 @@ enum StateMachine {
499507
ShuttingDown(RunData),
500508
PoweredOff,
501509
}
510+
511+
/// Data needed when VM is running
512+
pub struct RunData {
513+
vcpus: Vec<VCpu>,
514+
address_space: AddrSpace,
515+
regions: Vec<Region>,
516+
devices: BTreeMap<String, DeviceInfo>,
517+
}
518+
519+
impl RunData {
520+
fn add_memory_region(&mut self, config: MemoryKind) -> anyhow::Result<()> {
521+
let region = Region::new(config);
522+
self.address_space
523+
.map_linear(
524+
region.gpa.as_usize().into(),
525+
region.hva.as_usize().into(),
526+
region.size,
527+
axaddrspace::MappingFlags::READ
528+
| axaddrspace::MappingFlags::WRITE
529+
| axaddrspace::MappingFlags::EXECUTE
530+
| axaddrspace::MappingFlags::USER,
531+
)
532+
.map_err(|e| anyhow::anyhow!("Failed to map memory region: {:?}", e))?;
533+
534+
self.regions.push(region);
535+
536+
Ok(())
537+
}
538+
}
539+
540+
/// Information about a device in the VM
541+
#[derive(Debug, Clone)]
542+
pub struct DeviceInfo {}

src/config.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use alloc::string::String;
55
use alloc::vec::Vec;
66

7-
use axvm_types::addr::GuestPhysAddr;
7+
use crate::{GuestPhysAddr, HostPhysAddr};
88

99
pub use axvmconfig::{
1010
AxVMCrateConfig, EmulatedDeviceConfig, PassThroughAddressConfig, PassThroughDeviceConfig,
@@ -51,6 +51,16 @@ pub struct VMImagesConfig {
5151
pub ramdisk: Option<VMImageConfig>,
5252
}
5353

54+
#[derive(Debug, Clone)]
55+
pub enum MemoryKind {
56+
/// Use identical memory regions
57+
Identical { size: usize },
58+
/// Use memory regions mapped from host physical address
59+
Passthrough { hpa: HostPhysAddr, size: usize },
60+
/// Use fixed memory regions
61+
Fixed { gpa: GuestPhysAddr, size: usize },
62+
}
63+
5464
/// A part of `AxVMCrateConfig`, which represents a `VM`.
5565
#[derive(Debug, Default)]
5666
pub struct AxVMConfig {
@@ -63,6 +73,7 @@ pub struct AxVMConfig {
6373
pub pass_through_devices: Vec<PassThroughDeviceConfig>,
6474
pub excluded_devices: Vec<Vec<String>>,
6575
pub pass_through_addresses: Vec<PassThroughAddressConfig>,
76+
pub memory_regions: Vec<MemoryKind>,
6677
// TODO: improve interrupt passthrough
6778
pub spi_list: Vec<u32>,
6879
pub interrupt_mode: VMInterruptMode,

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub(crate) mod arch;
2525
mod fdt;
2626
mod vcpu;
2727
mod vm;
28+
mod region;
2829

2930
pub mod config;
3031
pub mod vhal;

src/region.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use core::{alloc::Layout, ops::Range};
2+
3+
use alloc::vec::Vec;
4+
5+
use crate::{
6+
GuestPhysAddr, HostVirtAddr,
7+
config::MemoryKind,
8+
vhal::{phys_to_virt, virt_to_phys},
9+
};
10+
11+
const ALIGN: usize = 1024 * 1024 * 2;
12+
13+
#[derive(Debug, Clone)]
14+
pub struct Region {
15+
pub gpa: GuestPhysAddr,
16+
pub hva: HostVirtAddr,
17+
pub size: usize,
18+
pub own: bool,
19+
}
20+
21+
impl Region {
22+
pub fn new(kind: MemoryKind) -> Self {
23+
match kind {
24+
MemoryKind::Identical { size } => {
25+
let hva = HostVirtAddr::from(unsafe {
26+
alloc::alloc::alloc(Layout::from_size_align_unchecked(size, ALIGN))
27+
} as usize);
28+
let gpa = GuestPhysAddr::from_usize(virt_to_phys(hva).as_usize());
29+
Region {
30+
gpa,
31+
hva,
32+
size,
33+
own: true,
34+
}
35+
}
36+
MemoryKind::Passthrough { hpa, size } => {
37+
let hva = phys_to_virt(hpa);
38+
let gpa = GuestPhysAddr::from_usize(hva.as_usize());
39+
Region {
40+
gpa,
41+
hva,
42+
size,
43+
own: false,
44+
}
45+
}
46+
MemoryKind::Fixed { gpa, size } => {
47+
let hva = HostVirtAddr::from(unsafe {
48+
alloc::alloc::alloc(Layout::from_size_align_unchecked(size, ALIGN))
49+
} as usize);
50+
Region {
51+
gpa,
52+
hva,
53+
size,
54+
own: true,
55+
}
56+
}
57+
}
58+
}
59+
60+
pub fn buffer_mut(&self) -> &mut [u8] {
61+
unsafe { core::slice::from_raw_parts_mut(self.hva.as_mut_ptr(), self.size) }
62+
}
63+
}
64+
65+
impl Drop for Region {
66+
fn drop(&mut self) {
67+
if self.own {
68+
unsafe {
69+
alloc::alloc::dealloc(
70+
self.hva.as_mut_ptr(),
71+
alloc::alloc::Layout::from_size_align(self.size, ALIGN).unwrap(),
72+
);
73+
}
74+
}
75+
}
76+
}

src/vhal/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
cpu::{CpuHardId, CpuId},
1313
precpu::PreCpuSet,
1414
},
15+
{HostPhysAddr, HostVirtAddr},
1516
};
1617
use axconfig::TASK_STACK_SIZE;
1718
use axtask::AxCpuMask;
@@ -82,3 +83,15 @@ pub(crate) trait ArchHal {
8283
pub(crate) trait ArchCpuData {
8384
fn hard_id(&self) -> CpuHardId;
8485
}
86+
87+
pub fn phys_to_virt(paddr: HostPhysAddr) -> HostVirtAddr {
88+
axhal::mem::phys_to_virt(paddr.as_usize().into())
89+
.as_usize()
90+
.into()
91+
}
92+
93+
pub fn virt_to_phys(vaddr: HostVirtAddr) -> HostPhysAddr {
94+
axhal::mem::virt_to_phys(vaddr.as_usize().into())
95+
.as_usize()
96+
.into()
97+
}

0 commit comments

Comments
 (0)