Skip to content

Commit 29de9ff

Browse files
committed
Basic input working
1 parent 894f9d1 commit 29de9ff

File tree

30 files changed

+638
-276
lines changed

30 files changed

+638
-276
lines changed

mythril/src/boot.S

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,36 @@ _start:
148148
call map_page_directory
149149
pop edi
150150

151-
; Disable IRQs (probably not necessary)
152-
mov al, 0xFF ; Out 0xFF to 0xA1 and 0x21 to disable all IRQs.
153-
out 0xA1, al
151+
; Setup PIC
152+
mov al, 0x11
153+
out 0x20, al
154+
out 0xa0, al
155+
156+
; Setup offsets
157+
mov al, 0x20
158+
out 0x21, al
159+
mov al, 0x28
160+
out 0xa1, al
161+
162+
mov al, 0x4
163+
out 0x21, al
164+
mov al, 0x2
165+
out 0xa1, al
166+
167+
mov al, 0x1
168+
out 0x21, al
169+
out 0xa1, al
170+
171+
; Set IRQ masks
172+
mov al, 0xED ; Unmask IRQ1 (ps2) and IRQ4 (COM1)
154173
out 0x21, al
174+
mov al, 0xFF
175+
out 0xA1, al
176+
177+
; ACK any pending interrupts
178+
mov al, 0x20
179+
out 0x20, al
180+
out 0xa0, al
155181

156182
; Enter long mode.
157183
mov eax, 10100000b ; Set the PAE and PGE bit.

mythril/src/emulate/memio.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use crate::device::{MemReadRequest, MemWriteRequest};
21
use crate::error::{Error, Result};
32
use crate::memory;
3+
use crate::virtdev::{MemReadRequest, MemWriteRequest};
44
use crate::{vcpu, vmcs, vmexit};
55
use arrayvec::ArrayVec;
66
use iced_x86;

mythril/src/emulate/portio.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use crate::device::{InterruptArray, Port, PortReadRequest, PortWriteRequest};
21
use crate::error::Result;
32
use crate::memory;
3+
use crate::virtdev::{InterruptArray, Port, PortReadRequest, PortWriteRequest};
44
use crate::{vcpu, vmcs, vmexit};
55
use core::convert::TryFrom;
66

mythril/src/interrupt/idt.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,31 @@ 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+
192208
pub unsafe fn init() {
193209
IDT[0].set_func(zero_division_handler);
194210
IDT[2].set_func(nmi_handler);
195211
IDT[13].set_func(protection_fault_handler);
196212
IDT[14].set_func(page_fault_handler);
197213

214+
// IDT[33].set_func(ps2_input_handler);
215+
// IDT[36].set_func(uart_input_handler);
216+
198217
ap_init();
199218
}
200219

mythril/src/kmain.rs

Lines changed: 75 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ use crate::acpi;
22
use crate::ap;
33
use crate::apic;
44
use crate::boot_info::BootInfo;
5-
use crate::device;
65
use crate::interrupt;
76
use crate::linux;
87
use crate::logger;
98
use crate::memory;
109
use crate::multiboot2;
1110
use crate::percore;
11+
use crate::physdev;
1212
use crate::time;
1313
use crate::vcpu;
14+
use crate::virtdev;
1415
use crate::vm;
1516

1617
use alloc::collections::BTreeMap;
@@ -39,57 +40,45 @@ fn default_vm(
3940

4041
let device_map = config.device_map();
4142
device_map
42-
.register_device(device::acpi::AcpiRuntime::new(0xb000).unwrap())
43+
.register_device(virtdev::acpi::AcpiRuntime::new(0xb000).unwrap())
4344
.unwrap();
4445
device_map
45-
.register_device(device::com::ComDevice::new(core as u64, 0x3F8))
46+
.register_device(virtdev::debug::DebugPort::new(core as u64, 0x402))
4647
.unwrap();
4748
device_map
48-
.register_device(device::com::ComDevice::new(core as u64, 0x2F8))
49+
.register_device(virtdev::vga::VgaController::new())
4950
.unwrap();
5051
device_map
51-
.register_device(device::com::ComDevice::new(core as u64, 0x3E8))
52+
.register_device(virtdev::dma::Dma8237::new())
5253
.unwrap();
5354
device_map
54-
.register_device(device::com::ComDevice::new(core as u64, 0x2E8))
55+
.register_device(virtdev::ignore::IgnoredDevice::new())
5556
.unwrap();
5657
device_map
57-
.register_device(device::debug::DebugPort::new(core as u64, 0x402))
58+
.register_device(virtdev::pci::PciRootComplex::new())
5859
.unwrap();
5960
device_map
60-
.register_device(device::vga::VgaController::new())
61+
.register_device(virtdev::pic::Pic8259::new())
6162
.unwrap();
6263
device_map
63-
.register_device(device::dma::Dma8237::new())
64+
.register_device(virtdev::keyboard::Keyboard8042::new())
6465
.unwrap();
6566
device_map
66-
.register_device(device::ignore::IgnoredDevice::new())
67+
.register_device(virtdev::pit::Pit8254::new())
6768
.unwrap();
6869
device_map
69-
.register_device(device::pci::PciRootComplex::new())
70+
.register_device(virtdev::pos::ProgrammableOptionSelect::new())
7071
.unwrap();
7172
device_map
72-
.register_device(device::pic::Pic8259::new())
73-
.unwrap();
74-
device_map
75-
.register_device(device::keyboard::Keyboard8042::new())
76-
.unwrap();
77-
device_map
78-
.register_device(device::pit::Pit8254::new())
79-
.unwrap();
80-
device_map
81-
.register_device(device::pos::ProgrammableOptionSelect::new())
82-
.unwrap();
83-
device_map
84-
.register_device(device::rtc::CmosRtc::new(mem))
73+
.register_device(virtdev::rtc::CmosRtc::new(mem))
8574
.unwrap();
8675

8776
//TODO: this should actually be per-vcpu
8877
device_map
89-
.register_device(device::lapic::LocalApic::new())
78+
.register_device(virtdev::lapic::LocalApic::new())
9079
.unwrap();
9180

92-
let mut fw_cfg_builder = device::qemu_fw_cfg::QemuFwCfgBuilder::new();
81+
let mut fw_cfg_builder = virtdev::qemu_fw_cfg::QemuFwCfgBuilder::new();
9382

9483
// The 'linuxboot' file is an option rom that loads the linux kernel
9584
// via qemu_fw_cfg
@@ -116,7 +105,7 @@ fn default_vm(
116105
"rodata=0 nopti disableapic acpi=off ",
117106
"earlyprintk=serial,0x3f8,115200 ",
118107
"console=ttyS0 debug nokaslr noapic mitigations=off ",
119-
"root=/dev/ram0 rdinit=/init\0"
108+
"root=/dev/ram0 rdinit=/bin/sh\0"
120109
)
121110
.as_bytes(),
122111
mem,
@@ -143,6 +132,8 @@ pub extern "C" fn ap_entry(_ap_data: &ap::ApData) -> ! {
143132
local_apic.version()
144133
);
145134

135+
unsafe { interrupt::enable_interrupts() };
136+
146137
vcpu::mp_entry_point()
147138
}
148139

@@ -168,6 +159,13 @@ unsafe fn kmain(mut boot_info: BootInfo) -> ! {
168159
// Calibrate the global time source
169160
time::init_global_time().expect("Failed to init global timesource");
170161

162+
// physdev::keyboard::Ps2Controller::init().expect("Failed to init ps2 controller");
163+
164+
// let uart = physdev::com::Uart8250::new(0x3f8);
165+
// unsafe {interrupt::enable_interrupts()};
166+
167+
// loop {}
168+
171169
// If the boot method provided an RSDT, use that one. Otherwise, search the
172170
// BIOS areas for it.
173171
let rsdt = boot_info
@@ -212,56 +210,56 @@ unsafe fn kmain(mut boot_info: BootInfo) -> ! {
212210

213211
debug!("AP_STARTUP address: 0x{:x}", AP_STARTUP_ADDR);
214212

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

266264
vcpu::mp_entry_point()
267265
}

mythril/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ pub mod ap;
2828
/// Support for the local APIC.
2929
pub mod apic;
3030
pub mod boot_info;
31-
pub mod device;
31+
3232
pub mod emulate;
3333
pub mod error;
34-
mod global_alloc;
34+
pub mod global_alloc;
3535
pub mod interrupt;
3636
pub mod ioapic;
3737
pub mod kmain;
@@ -40,12 +40,13 @@ pub mod logger;
4040
pub mod memory;
4141
pub mod multiboot2;
4242
pub mod percore;
43-
pub mod pit;
44-
mod registers;
43+
pub mod physdev;
44+
pub mod registers;
4545
pub mod time;
4646
pub mod tsc;
4747
pub mod vcpu;
48+
pub mod virtdev;
4849
pub mod vm;
4950
pub mod vmcs;
50-
mod vmexit;
51+
pub mod vmexit;
5152
pub mod vmx;

mythril/src/linux.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::boot_info::BootInfo;
2-
use crate::device::qemu_fw_cfg::{FwCfgSelector, QemuFwCfgBuilder};
32
use crate::error::{Error, Result};
3+
use crate::virtdev::qemu_fw_cfg::{FwCfgSelector, QemuFwCfgBuilder};
44
use bitflags::bitflags;
55
use byteorder::{ByteOrder, LittleEndian};
66

0 commit comments

Comments
 (0)