Skip to content

Commit 216bf7a

Browse files
committed
Make InterruptArray an argument
1 parent 29de9ff commit 216bf7a

File tree

23 files changed

+1024
-547
lines changed

23 files changed

+1024
-547
lines changed

mythril/src/emulate/memio.rs

Lines changed: 530 additions & 189 deletions
Large diffs are not rendered by default.

mythril/src/emulate/portio.rs

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ fn emulate_outs(
99
port: Port,
1010
guest_cpu: &mut vmexit::GuestCpuState,
1111
exit: vmexit::IoInstructionInformation,
12+
interrupts: &mut InterruptArray,
1213
) -> Result<()> {
1314
let mut vm = vcpu.vm.write();
1415

@@ -34,22 +35,13 @@ fn emulate_outs(
3435
)?;
3536

3637
// FIXME: Actually test for REP
37-
let mut interrupts = InterruptArray::default();
3838
for chunk in bytes.chunks_exact(exit.size as usize) {
3939
let request = PortWriteRequest::try_from(chunk)?;
40-
interrupts = vm.on_port_write(vcpu, port, request)?;
40+
vm.on_port_write(vcpu, port, request, interrupts)?;
4141
}
4242

4343
guest_cpu.rsi += bytes.len() as u64;
4444
guest_cpu.rcx = 0;
45-
drop(vm);
46-
47-
for interrupt in interrupts {
48-
vcpu.inject_interrupt(
49-
interrupt,
50-
vcpu::InjectedInterruptType::ExternalInterrupt,
51-
);
52-
}
5345
Ok(())
5446
}
5547

@@ -58,6 +50,7 @@ fn emulate_ins(
5850
port: Port,
5951
guest_cpu: &mut vmexit::GuestCpuState,
6052
exit: vmexit::IoInstructionInformation,
53+
interrupts: &mut InterruptArray,
6154
) -> Result<()> {
6255
let mut vm = vcpu.vm.write();
6356

@@ -67,12 +60,9 @@ fn emulate_ins(
6760
let access = memory::GuestAccess::Read(memory::PrivilegeLevel(0));
6861

6962
let mut bytes = vec![0u8; guest_cpu.rcx as usize];
70-
let mut interrupts = InterruptArray::default();
7163
for chunk in bytes.chunks_exact_mut(exit.size as usize) {
7264
let request = PortReadRequest::try_from(chunk)?;
73-
74-
//TODO: For now, only consider the _last_ interrupt/exception/fault
75-
interrupts = vm.on_port_read(vcpu, port, request)?;
65+
vm.on_port_read(vcpu, port, request, interrupts)?;
7666
}
7767

7868
let mut view = memory::GuestAddressSpaceViewMut::from_vmcs(
@@ -83,57 +73,43 @@ fn emulate_ins(
8373

8474
guest_cpu.rdi += bytes.len() as u64;
8575
guest_cpu.rcx = 0;
86-
drop(vm);
87-
88-
for interrupt in interrupts {
89-
vcpu.inject_interrupt(
90-
interrupt,
91-
vcpu::InjectedInterruptType::ExternalInterrupt,
92-
);
93-
}
9476
Ok(())
9577
}
9678

9779
pub fn emulate_portio(
9880
vcpu: &mut vcpu::VCpu,
9981
guest_cpu: &mut vmexit::GuestCpuState,
10082
exit: vmexit::IoInstructionInformation,
83+
interrupts: &mut InterruptArray,
10184
) -> Result<()> {
10285
let (port, input, size, string) =
10386
(exit.port, exit.input, exit.size, exit.string);
10487

10588
if !string {
10689
let mut vm = vcpu.vm.write();
107-
108-
let interrupts = if !input {
90+
if !input {
10991
let arr = (guest_cpu.rax as u32).to_be_bytes();
11092
vm.on_port_write(
11193
vcpu,
11294
port,
11395
PortWriteRequest::try_from(&arr[4 - size as usize..])?,
114-
)?
96+
interrupts,
97+
)?;
11598
} else {
11699
let mut arr = [0u8; 4];
117100
let request =
118101
PortReadRequest::try_from(&mut arr[4 - size as usize..])?;
119-
let interrupts = vm.on_port_read(vcpu, port, request)?;
102+
vm.on_port_read(vcpu, port, request, interrupts)?;
120103
guest_cpu.rax &= (!guest_cpu.rax) << (size * 8);
121104
guest_cpu.rax |= u32::from_be_bytes(arr) as u64;
122-
interrupts
123105
};
124-
drop(vm);
125-
for interrupt in interrupts {
126-
vcpu.inject_interrupt(
127-
interrupt,
128-
vcpu::InjectedInterruptType::ExternalInterrupt,
129-
);
130-
}
131106
} else {
132107
if !input {
133-
emulate_outs(vcpu, port, guest_cpu, exit)?;
108+
emulate_outs(vcpu, port, guest_cpu, exit, interrupts)?;
134109
} else {
135-
emulate_ins(vcpu, port, guest_cpu, exit)?;
110+
emulate_ins(vcpu, port, guest_cpu, exit, interrupts)?;
136111
}
137112
}
113+
138114
Ok(())
139115
}

mythril/src/interrupt/idt.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -189,31 +189,12 @@ fault_fn!(zero_division_handler, state, {
189189
panic!("Divide by zero handler (rip=0x{:x})", state.rip);
190190
});
191191

192-
interrupt_fn!(ps2_input_handler, state, {
193-
use x86::io::{inb, outb};
194-
195-
let input = inb(0x60);
196-
let status = inb(0x64);
197-
info!("Key 0x{:x} pressed (status = 0x{:x})", input, status);
198-
outb(0x20, 0x20);
199-
});
200-
201-
interrupt_fn!(uart_input_handler, state, {
202-
use x86::io::{inb, outb};
203-
204-
info!("Uart input");
205-
outb(0x20, 0x20);
206-
});
207-
208192
pub unsafe fn init() {
209193
IDT[0].set_func(zero_division_handler);
210194
IDT[2].set_func(nmi_handler);
211195
IDT[13].set_func(protection_fault_handler);
212196
IDT[14].set_func(page_fault_handler);
213197

214-
// IDT[33].set_func(ps2_input_handler);
215-
// IDT[36].set_func(uart_input_handler);
216-
217198
ap_init();
218199
}
219200

mythril/src/kmain.rs

Lines changed: 69 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,35 @@ fn default_vm(
3232
core: usize,
3333
mem: u64,
3434
info: &BootInfo,
35+
add_uart: bool,
3536
) -> Arc<RwLock<vm::VirtualMachine>> {
36-
let mut config = vm::VirtualMachineConfig::new(vec![core as u8], mem);
37+
let physical_config = if add_uart == false {
38+
vm::PhysicalDeviceConfig::default()
39+
} else {
40+
vm::PhysicalDeviceConfig {
41+
serial: Some(
42+
physdev::com::Uart8250::new(0x3f8)
43+
.expect("Failed to create UART"),
44+
),
45+
}
46+
};
47+
48+
let mut config =
49+
vm::VirtualMachineConfig::new(vec![core as u8], mem, physical_config);
3750

3851
// FIXME: When `map_bios` may return an error, log the error.
3952
config.map_bios("seabios.bin".into()).unwrap_or(());
4053

41-
let device_map = config.device_map();
54+
let device_map = config.virtual_devices_mut();
4255
device_map
4356
.register_device(virtdev::acpi::AcpiRuntime::new(0xb000).unwrap())
4457
.unwrap();
4558
device_map
4659
.register_device(virtdev::debug::DebugPort::new(core as u64, 0x402))
4760
.unwrap();
61+
device_map
62+
.register_device(virtdev::com::Uart8250::new(core as u64, 0x3F8))
63+
.unwrap();
4864
device_map
4965
.register_device(virtdev::vga::VgaController::new())
5066
.unwrap();
@@ -161,11 +177,6 @@ unsafe fn kmain(mut boot_info: BootInfo) -> ! {
161177

162178
// physdev::keyboard::Ps2Controller::init().expect("Failed to init ps2 controller");
163179

164-
// let uart = physdev::com::Uart8250::new(0x3f8);
165-
// unsafe {interrupt::enable_interrupts()};
166-
167-
// loop {}
168-
169180
// If the boot method provided an RSDT, use that one. Otherwise, search the
170181
// BIOS areas for it.
171182
let rsdt = boot_info
@@ -202,64 +213,64 @@ unsafe fn kmain(mut boot_info: BootInfo) -> ! {
202213
for apic_id in apic_ids.iter() {
203214
map.insert(
204215
*apic_id as usize,
205-
default_vm(*apic_id as usize, 256, &boot_info),
216+
default_vm(*apic_id as usize, 256, &boot_info, *apic_id == 0),
206217
);
207218
}
208219

209220
vm::VM_MAP = Some(map);
210221

211222
debug!("AP_STARTUP address: 0x{:x}", AP_STARTUP_ADDR);
212223

213-
// for (idx, apic_id) in apic_ids.into_iter().enumerate() {
214-
// if apic_id == local_apic.id() as u32 {
215-
// continue;
216-
// }
217-
218-
// // Allocate a stack for the AP
219-
// let stack = vec![0u8; 100 * 1024];
220-
221-
// // Get the the bottom of the stack and align
222-
// let stack_bottom =
223-
// (stack.as_ptr() as u64 + stack.len() as u64) & 0xFFFFFFFFFFFFFFF0;
224-
225-
// core::mem::forget(stack);
226-
227-
// core::ptr::write_volatile(&mut AP_STACK_ADDR as *mut u64, stack_bottom);
228-
229-
// // Map the APIC ids to a sequential list and pass it to the AP
230-
// core::ptr::write_volatile(&mut AP_IDX as *mut u64, idx as u64);
231-
232-
// // mfence to ensure that the APs see the new stack address
233-
// core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
234-
235-
// debug!("Send INIT to AP id={}", apic_id);
236-
// local_apic.send_ipi(
237-
// apic_id,
238-
// apic::DstShorthand::NoShorthand,
239-
// apic::TriggerMode::Edge,
240-
// apic::Level::Assert,
241-
// apic::DstMode::Physical,
242-
// apic::DeliveryMode::Init,
243-
// 0,
244-
// );
245-
246-
// debug!("Send SIPI to AP id={}", apic_id);
247-
// local_apic.send_ipi(
248-
// apic_id,
249-
// apic::DstShorthand::NoShorthand,
250-
// apic::TriggerMode::Edge,
251-
// apic::Level::Assert,
252-
// apic::DstMode::Physical,
253-
// apic::DeliveryMode::StartUp,
254-
// (AP_STARTUP_ADDR >> 12) as u8,
255-
// );
256-
257-
// // Wait until the AP reports that it is done with startup
258-
// while core::ptr::read_volatile(&AP_READY as *const u8) != 1 {}
259-
260-
// // Once the AP is done, clear the ready flag
261-
// core::ptr::write_volatile(&mut AP_READY as *mut u8, 0);
262-
// }
224+
for (idx, apic_id) in apic_ids.into_iter().enumerate() {
225+
if apic_id == local_apic.id() as u32 {
226+
continue;
227+
}
228+
229+
// Allocate a stack for the AP
230+
let stack = vec![0u8; 100 * 1024];
231+
232+
// Get the the bottom of the stack and align
233+
let stack_bottom =
234+
(stack.as_ptr() as u64 + stack.len() as u64) & 0xFFFFFFFFFFFFFFF0;
235+
236+
core::mem::forget(stack);
237+
238+
core::ptr::write_volatile(&mut AP_STACK_ADDR as *mut u64, stack_bottom);
239+
240+
// Map the APIC ids to a sequential list and pass it to the AP
241+
core::ptr::write_volatile(&mut AP_IDX as *mut u64, idx as u64);
242+
243+
// mfence to ensure that the APs see the new stack address
244+
core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
245+
246+
debug!("Send INIT to AP id={}", apic_id);
247+
local_apic.send_ipi(
248+
apic_id,
249+
apic::DstShorthand::NoShorthand,
250+
apic::TriggerMode::Edge,
251+
apic::Level::Assert,
252+
apic::DstMode::Physical,
253+
apic::DeliveryMode::Init,
254+
0,
255+
);
256+
257+
debug!("Send SIPI to AP id={}", apic_id);
258+
local_apic.send_ipi(
259+
apic_id,
260+
apic::DstShorthand::NoShorthand,
261+
apic::TriggerMode::Edge,
262+
apic::Level::Assert,
263+
apic::DstMode::Physical,
264+
apic::DeliveryMode::StartUp,
265+
(AP_STARTUP_ADDR >> 12) as u8,
266+
);
267+
268+
// Wait until the AP reports that it is done with startup
269+
while core::ptr::read_volatile(&AP_READY as *const u8) != 1 {}
270+
271+
// Once the AP is done, clear the ready flag
272+
core::ptr::write_volatile(&mut AP_READY as *mut u8, 0);
273+
}
263274

264275
vcpu::mp_entry_point()
265276
}

mythril/src/physdev/com.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ impl Uart8250 {
5555
Ok(uart)
5656
}
5757

58+
pub fn base_port(&self) -> u16 {
59+
self.base
60+
}
61+
5862
fn read_ier(&self) -> IerFlags {
5963
IerFlags::from_bits_truncate(unsafe {
6064
inb(self.base + SerialOffset::IER)

mythril/src/physdev/keyboard.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,6 @@ impl Ps2Controller {
9393
}
9494

9595
Self::flush_read("init finished");
96-
97-
// info!("{:?}", Self::read_status_port());
98-
// info!("{:?}", Self::read_configuration());
99-
// Self::write_command_port(Command::EnableFirst);
100-
info!("Done with ps2 initialization");
10196
Ok(())
10297
}
10398

@@ -152,12 +147,4 @@ impl Ps2Controller {
152147
outb(PS2_COMMAND_PORT, cmd as u8);
153148
}
154149
}
155-
156-
fn output_available() -> bool {
157-
Self::read_status_port().contains(Ps2StatusFlags::OUTPUT_BUFFER_FULL)
158-
}
159-
160-
fn ready_for_input() -> bool {
161-
!Self::read_status_port().contains(Ps2StatusFlags::INPUT_BUFFER_FULL)
162-
}
163150
}

0 commit comments

Comments
 (0)