Skip to content

Commit 9829723

Browse files
committed
feat: 添加 MMIO 读写处理逻辑,优化 VDeviceList 设备管理
1 parent 85248d9 commit 9829723

File tree

5 files changed

+93
-18
lines changed

5 files changed

+93
-18
lines changed

src/arch/aarch64/cpu.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,22 @@ impl VCpuOp for CPUState {
168168

169169
self.vcpu.set_gpr(reg, val);
170170
} else {
171-
return Err(RunError::ExitWithError(anyhow!(
172-
"MMIO read @{addr:#x} no device"
173-
)));
171+
// TODO handle MMIO read failure
172+
warn!(
173+
"vCPU {:#x} MMIO read failed at addr {:#x}",
174+
self.mpidr_el1, addr
175+
);
174176
}
175-
176-
todo!()
177177
}
178178
arm_vcpu::AxVCpuExitReason::MmioWrite { addr, width, data } => {
179179
debug!("vCPU {:#x} MMIO write at addr {:#x}", self.mpidr_el1, addr);
180+
let res = vm.handle_mmio_write(addr, width, data as _);
181+
if res.is_none() {
182+
warn!(
183+
"vCPU {:#x} MMIO write failed at addr {:#x}",
184+
self.mpidr_el1, addr
185+
);
186+
}
180187
}
181188
arm_vcpu::AxVCpuExitReason::SysRegRead { addr, reg } => {
182189
todo!()

src/arch/aarch64/plat.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,21 @@ impl PlatData {
3434
let gicd = regs.get(0).ok_or(anyhow!("No GICD reg"))?;
3535
let gicr = regs.get(1).ok_or(anyhow!("No GICR reg"))?;
3636
let plat = self.vdev.new_plat();
37+
let mut gic = v3::VGic::new();
38+
39+
// self.vdev.add_device(|plat| {
40+
// let gic = v3::VGic::new(
41+
// (gicd.address as usize).into(),
42+
// (gicr.address as usize).into(),
43+
// plat.clone(),
44+
// );
45+
// Ok(gic)
46+
// });
3747

3848
self.vdev.add_device(|plat| {
39-
let gic = v3::VGic::new(
40-
(gicd.address as usize).into(),
41-
(gicr.address as usize).into(),
42-
plat.clone(),
43-
);
44-
Ok(gic)
45-
});
49+
let gicd = gic.new_gicd(plat.clone(), (gicd.address as usize).into());
50+
Ok(gicd)
51+
})?;
4652

4753
Ok(())
4854
}

src/vm/machine/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,16 @@ impl<H: HalOp> Machine<H> {
4545
};
4646
running.vdevs.handle_mmio_read(addr, width)
4747
}
48+
49+
pub fn handle_mmio_write(
50+
&self,
51+
addr: GuestPhysAddr,
52+
width: AccessWidth,
53+
data: usize,
54+
) -> Option<()> {
55+
let Machine::Running(running) = self else {
56+
panic!("VM is not in running state");
57+
};
58+
running.vdevs.handle_mmio_write(addr, width, data)
59+
}
4860
}

src/vm/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,16 @@ impl Vm {
171171
let machine = self.machine.read();
172172
machine.handle_mmio_read(addr, width)
173173
}
174+
175+
pub(crate) fn handle_mmio_write(
176+
&self,
177+
addr: GuestPhysAddr,
178+
width: AccessWidth,
179+
data: usize,
180+
) -> Option<()> {
181+
let machine = self.machine.read();
182+
machine.handle_mmio_write(addr, width, data)
183+
}
174184
}
175185

176186
#[derive(Clone)]

src/vm/vdev.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ impl VDevice {
2424
self.id
2525
}
2626

27-
pub fn run(&self) {
28-
let mut dev = self.raw.lock();
29-
dev.run();
27+
pub fn try_invoke(&self) {
28+
if let Some(mut dev) = self.raw.try_lock() {
29+
dev.invoke();
30+
}
3031
}
3132
}
3233

@@ -84,7 +85,7 @@ impl VDeviceList {
8485

8586
pub fn handle_mmio_read(&self, addr: GuestPhysAddr, width: AccessWidth) -> Option<usize> {
8687
let mmio = &self.mmio;
87-
for (id, region) in unsafe { &(*mmio.inner.get()).regions } {
88+
for (&id, region) in unsafe { &(*mmio.inner.get()).regions } {
8889
if addr >= region.gpa()
8990
&& addr.as_usize() + width.size() <= region.gpa().as_usize() + region.size()
9091
{
@@ -94,7 +95,7 @@ impl VDeviceList {
9495
width,
9596
id
9697
);
97-
self.get_device(*id).unwrap().run();
98+
self.device_try_invoke(id);
9899

99100
let offset = addr.as_usize() - region.gpa().as_usize();
100101
let access_ptr = unsafe { region.hva().as_ptr().add(offset) };
@@ -109,6 +110,45 @@ impl VDeviceList {
109110
}
110111
None
111112
}
113+
114+
pub fn handle_mmio_write(
115+
&self,
116+
addr: GuestPhysAddr,
117+
width: AccessWidth,
118+
data: usize,
119+
) -> Option<()> {
120+
let mmio = &self.mmio;
121+
for (&id, region) in unsafe { &(*mmio.inner.get()).regions } {
122+
if addr >= region.gpa()
123+
&& addr.as_usize() + width.size() <= region.gpa().as_usize() + region.size()
124+
{
125+
debug!(
126+
"VDev MMIO write addr={:#x} width={:?} data={:#x} dev_id={}",
127+
addr.as_usize(),
128+
width,
129+
data,
130+
id
131+
);
132+
133+
let offset = addr.as_usize() - region.gpa().as_usize();
134+
let access_ptr = unsafe { region.hva().as_ptr().add(offset) };
135+
match width {
136+
AccessWidth::Byte => unsafe { *(access_ptr as *mut u8) = data as u8 },
137+
AccessWidth::Word => unsafe { *(access_ptr as *mut u16) = data as u16 },
138+
AccessWidth::Dword => unsafe { *(access_ptr as *mut u32) = data as u32 },
139+
AccessWidth::Qword => unsafe { *(access_ptr as *mut u64) = data as u64 },
140+
};
141+
142+
self.device_try_invoke(id);
143+
return Some(());
144+
}
145+
}
146+
None
147+
}
148+
149+
fn device_try_invoke(&self, id: u32) {
150+
self.get_device(*id).unwrap().try_invoke();
151+
}
112152
}
113153

114154
#[derive(Clone)]
@@ -140,7 +180,7 @@ impl VirtPlatformOp for VDevPlat {
140180
todo!()
141181
}
142182

143-
fn invoke_irq(&self, irq: IrqNum) {
183+
fn send_irq(&self, irq: IrqNum) {
144184
todo!()
145185
}
146186
}

0 commit comments

Comments
 (0)