Skip to content

Commit 31a2033

Browse files
committed
Switch to on_event system for EmulatedDevice
1 parent 216bf7a commit 31a2033

File tree

19 files changed

+499
-677
lines changed

19 files changed

+499
-677
lines changed

mythril/src/emulate/memio.rs

Lines changed: 77 additions & 68 deletions
Large diffs are not rendered by default.

mythril/src/emulate/portio.rs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::error::Result;
22
use crate::memory;
3-
use crate::virtdev::{InterruptArray, Port, PortReadRequest, PortWriteRequest};
3+
use crate::virtdev::{
4+
DeviceEvent, Port, PortReadRequest, PortWriteRequest, ResponseEventArray,
5+
};
46
use crate::{vcpu, vmcs, vmexit};
57
use core::convert::TryFrom;
68

@@ -9,7 +11,7 @@ fn emulate_outs(
911
port: Port,
1012
guest_cpu: &mut vmexit::GuestCpuState,
1113
exit: vmexit::IoInstructionInformation,
12-
interrupts: &mut InterruptArray,
14+
responses: &mut ResponseEventArray,
1315
) -> Result<()> {
1416
let mut vm = vcpu.vm.write();
1517

@@ -37,7 +39,12 @@ fn emulate_outs(
3739
// FIXME: Actually test for REP
3840
for chunk in bytes.chunks_exact(exit.size as usize) {
3941
let request = PortWriteRequest::try_from(chunk)?;
40-
vm.on_port_write(vcpu, port, request, interrupts)?;
42+
vm.dispatch_event(
43+
port,
44+
DeviceEvent::PortWrite((port, request)),
45+
vcpu,
46+
responses,
47+
)?;
4148
}
4249

4350
guest_cpu.rsi += bytes.len() as u64;
@@ -50,7 +57,7 @@ fn emulate_ins(
5057
port: Port,
5158
guest_cpu: &mut vmexit::GuestCpuState,
5259
exit: vmexit::IoInstructionInformation,
53-
interrupts: &mut InterruptArray,
60+
responses: &mut ResponseEventArray,
5461
) -> Result<()> {
5562
let mut vm = vcpu.vm.write();
5663

@@ -62,7 +69,12 @@ fn emulate_ins(
6269
let mut bytes = vec![0u8; guest_cpu.rcx as usize];
6370
for chunk in bytes.chunks_exact_mut(exit.size as usize) {
6471
let request = PortReadRequest::try_from(chunk)?;
65-
vm.on_port_read(vcpu, port, request, interrupts)?;
72+
vm.dispatch_event(
73+
port,
74+
DeviceEvent::PortRead((port, request)),
75+
vcpu,
76+
responses,
77+
)?;
6678
}
6779

6880
let mut view = memory::GuestAddressSpaceViewMut::from_vmcs(
@@ -80,7 +92,7 @@ pub fn emulate_portio(
8092
vcpu: &mut vcpu::VCpu,
8193
guest_cpu: &mut vmexit::GuestCpuState,
8294
exit: vmexit::IoInstructionInformation,
83-
interrupts: &mut InterruptArray,
95+
responses: &mut ResponseEventArray,
8496
) -> Result<()> {
8597
let (port, input, size, string) =
8698
(exit.port, exit.input, exit.size, exit.string);
@@ -89,25 +101,32 @@ pub fn emulate_portio(
89101
let mut vm = vcpu.vm.write();
90102
if !input {
91103
let arr = (guest_cpu.rax as u32).to_be_bytes();
92-
vm.on_port_write(
93-
vcpu,
104+
let request =
105+
PortWriteRequest::try_from(&arr[4 - size as usize..])?;
106+
vm.dispatch_event(
94107
port,
95-
PortWriteRequest::try_from(&arr[4 - size as usize..])?,
96-
interrupts,
108+
DeviceEvent::PortWrite((port, request)),
109+
vcpu,
110+
responses,
97111
)?;
98112
} else {
99113
let mut arr = [0u8; 4];
100114
let request =
101115
PortReadRequest::try_from(&mut arr[4 - size as usize..])?;
102-
vm.on_port_read(vcpu, port, request, interrupts)?;
116+
vm.dispatch_event(
117+
port,
118+
DeviceEvent::PortRead((port, request)),
119+
vcpu,
120+
responses,
121+
)?;
103122
guest_cpu.rax &= (!guest_cpu.rax) << (size * 8);
104123
guest_cpu.rax |= u32::from_be_bytes(arr) as u64;
105124
};
106125
} else {
107126
if !input {
108-
emulate_outs(vcpu, port, guest_cpu, exit, interrupts)?;
127+
emulate_outs(vcpu, port, guest_cpu, exit, responses)?;
109128
} else {
110-
emulate_ins(vcpu, port, guest_cpu, exit, interrupts)?;
129+
emulate_ins(vcpu, port, guest_cpu, exit, responses)?;
111130
}
112131
}
113132

mythril/src/vcpu.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ impl VCpu {
446446

447447
fn handle_uart_keypress(
448448
&mut self,
449-
interrupts: &mut virtdev::InterruptArray,
449+
responses: &mut virtdev::ResponseEventArray,
450450
) -> Result<()> {
451451
let vm = self.vm.read();
452452

@@ -460,11 +460,11 @@ impl VCpu {
460460

461461
let mut vm = self.vm.write();
462462
if let Some((key, port)) = serial_info {
463-
vm.on_event(
464-
self,
465-
&virtdev::DeviceMessage::UartKeyPressed(key),
463+
vm.dispatch_event(
466464
port,
467-
interrupts,
465+
virtdev::DeviceEvent::HostUartReceived(key),
466+
self,
467+
responses,
468468
)
469469
} else {
470470
Ok(())
@@ -476,9 +476,7 @@ impl VCpu {
476476
guest_cpu: &mut vmexit::GuestCpuState,
477477
exit: vmexit::ExitReason,
478478
) -> Result<()> {
479-
// An array of outstanding interrupts/exceptions that should be injected
480-
// into the guest as a result of this vmexit
481-
let mut interrupts = virtdev::InterruptArray::default();
479+
let mut responses = virtdev::ResponseEventArray::default();
482480

483481
match exit.info {
484482
vmexit::ExitInformation::CrAccess(info) => {
@@ -542,7 +540,7 @@ impl VCpu {
542540
self,
543541
guest_cpu,
544542
info,
545-
&mut interrupts,
543+
&mut responses,
546544
)?;
547545
self.skip_emulated_instruction()?;
548546
}
@@ -551,7 +549,7 @@ impl VCpu {
551549
self,
552550
guest_cpu,
553551
info,
554-
&mut interrupts,
552+
&mut responses,
555553
)?;
556554
self.skip_emulated_instruction()?;
557555
}
@@ -566,7 +564,7 @@ impl VCpu {
566564
vmexit::ExitInformation::InterruptWindow => {}
567565
vmexit::ExitInformation::ExternalInterrupt(info) => unsafe {
568566
match info.vector {
569-
0x24 => self.handle_uart_keypress(&mut interrupts)?,
567+
0x24 => self.handle_uart_keypress(&mut responses)?,
570568
_ => (),
571569
}
572570

@@ -584,11 +582,13 @@ impl VCpu {
584582
}
585583
}
586584

587-
for interrupt in interrupts {
588-
self.inject_interrupt(
589-
interrupt,
590-
InjectedInterruptType::ExternalInterrupt,
591-
);
585+
for response in responses {
586+
match response {
587+
virtdev::DeviceEventResponse::Interrupt((vector, kind)) => {
588+
self.inject_interrupt(vector, kind);
589+
}
590+
_ => (),
591+
}
592592
}
593593

594594
Ok(())

mythril/src/virtdev/acpi.rs

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
use crate::error::Result;
2-
use crate::memory::GuestAddressSpaceViewMut;
32
use crate::time;
4-
use crate::virtdev::{
5-
DeviceRegion, EmulatedDevice, InterruptArray, Port, PortReadRequest,
6-
PortWriteRequest,
7-
};
3+
use crate::virtdev::{DeviceEvent, DeviceRegion, EmulatedDevice, Event, Port};
84
use alloc::sync::Arc;
95
use alloc::vec::Vec;
106
use spin::RwLock;
@@ -71,33 +67,25 @@ impl EmulatedDevice for AcpiRuntime {
7167
]
7268
}
7369

74-
fn on_port_read(
75-
&mut self,
76-
port: Port,
77-
mut val: PortReadRequest,
78-
_space: GuestAddressSpaceViewMut,
79-
_interrupts: &mut InterruptArray,
80-
) -> Result<()> {
81-
if port == self.pmtimer() {
82-
let on_duration = time::now() - time::system_start_time();
83-
let pm_time =
84-
(on_duration.as_nanos() * PMTIMER_HZ as u128) / 1_000_000_000;
85-
val.copy_from_u32(pm_time as u32);
70+
fn on_event(&mut self, event: Event) -> Result<()> {
71+
match event.kind {
72+
DeviceEvent::PortRead((port, mut val)) => {
73+
if port == self.pmtimer() {
74+
let on_duration = time::now() - time::system_start_time();
75+
let pm_time = (on_duration.as_nanos() * PMTIMER_HZ as u128)
76+
/ 1_000_000_000;
77+
val.copy_from_u32(pm_time as u32);
78+
}
79+
}
80+
DeviceEvent::PortWrite((port, val)) => {
81+
info!(
82+
"Attempt to write to AcpiRuntime port=0x{:x}, val={}. Ignoring",
83+
port, val
84+
);
85+
}
86+
_ => (),
8687
}
87-
Ok(())
88-
}
8988

90-
fn on_port_write(
91-
&mut self,
92-
port: Port,
93-
val: PortWriteRequest,
94-
_space: GuestAddressSpaceViewMut,
95-
_interrupts: &mut InterruptArray,
96-
) -> Result<()> {
97-
info!(
98-
"Attempt to write to AcpiRuntime port=0x{:x}, val={}. Ignoring",
99-
port, val
100-
);
10189
Ok(())
10290
}
10391
}

0 commit comments

Comments
 (0)