mirror of
https://github.com/mii443/nel_os.git
synced 2025-08-22 16:15:38 +00:00
io emulation
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use uart_16550::SerialPort;
|
use uart_16550::SerialPort;
|
||||||
@ -23,6 +25,19 @@ pub fn _print(args: ::core::fmt::Arguments) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn write_byte(byte: u8) {
|
||||||
|
use x86_64::instructions::interrupts;
|
||||||
|
|
||||||
|
if interrupts::are_enabled() {
|
||||||
|
interrupts::without_interrupts(|| {
|
||||||
|
SERIAL1.lock().send(byte);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SERIAL1.lock().send(byte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! serial_print {
|
macro_rules! serial_print {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {
|
||||||
|
83
src/vmm/io.rs
Normal file
83
src/vmm/io.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use x86::io::inb;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
serial,
|
||||||
|
vmm::{qual::QualIo, vcpu::VCpu},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Serial {
|
||||||
|
pub ier: u8,
|
||||||
|
pub mcr: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_io(vcpu: &mut VCpu, qual: QualIo) {
|
||||||
|
match qual.direction() {
|
||||||
|
0 => {
|
||||||
|
handle_io_out(vcpu, qual);
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
handle_io_in(vcpu, qual);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_io_in(vcpu: &mut VCpu, qual: QualIo) {
|
||||||
|
let regs = &mut vcpu.guest_registers;
|
||||||
|
match qual.port() {
|
||||||
|
0x0CF8..0x0CFF => {
|
||||||
|
regs.rax = 0;
|
||||||
|
}
|
||||||
|
0xC000..0xCFFF => {} //ignore
|
||||||
|
0x03F..0x03FF => handle_serial_in(vcpu, qual),
|
||||||
|
_ => {
|
||||||
|
panic!("IO in: invalid port: {:#x}", qual.port());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_io_out(vcpu: &mut VCpu, qual: QualIo) {
|
||||||
|
let regs = &vcpu.guest_registers;
|
||||||
|
match qual.port() {
|
||||||
|
0x0CF8..0x0CFF => {} //ignore
|
||||||
|
0xC000..0xCFFF => {} //ignore
|
||||||
|
0x03F8..0x03FF => handle_serial_out(vcpu, qual),
|
||||||
|
_ => {
|
||||||
|
panic!("IO out: invalid port: {:#x}", qual.port());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_serial_in(vcpu: &mut VCpu, qual: QualIo) {
|
||||||
|
let regs = &mut vcpu.guest_registers;
|
||||||
|
match qual.port() {
|
||||||
|
0x3F8 => regs.rax = unsafe { inb(qual.port()).into() },
|
||||||
|
0x3F9 => regs.rax = vcpu.serial.ier as u64,
|
||||||
|
0x3FA => regs.rax = unsafe { inb(qual.port()).into() },
|
||||||
|
0x3FB => regs.rax = 0,
|
||||||
|
0x3FC => regs.rax = vcpu.serial.mcr as u64,
|
||||||
|
0x3FD => regs.rax = unsafe { inb(qual.port()).into() },
|
||||||
|
0x3FE => regs.rax = unsafe { inb(qual.port()).into() },
|
||||||
|
0x3FF => regs.rax = 0,
|
||||||
|
_ => {
|
||||||
|
panic!("Serial in: invalid port: {:#x}", qual.port());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_serial_out(vcpu: &mut VCpu, qual: QualIo) {
|
||||||
|
let regs = &mut vcpu.guest_registers;
|
||||||
|
match qual.port() {
|
||||||
|
0x3F8 => serial::write_byte(regs.rax as u8),
|
||||||
|
0x3F9 => vcpu.serial.ier = regs.rax as u8,
|
||||||
|
0x3FA => {}
|
||||||
|
0x3FB => {}
|
||||||
|
0x3FC => vcpu.serial.mcr = regs.rax as u8,
|
||||||
|
0x3FD => {}
|
||||||
|
0x3FF => {}
|
||||||
|
_ => {
|
||||||
|
panic!("Serial out: invalid port: {:#x}", qual.port());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ pub mod cr;
|
|||||||
pub mod ept;
|
pub mod ept;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod fpu;
|
pub mod fpu;
|
||||||
|
pub mod io;
|
||||||
pub mod linux;
|
pub mod linux;
|
||||||
pub mod msr;
|
pub mod msr;
|
||||||
pub mod qual;
|
pub mod qual;
|
||||||
|
@ -131,10 +131,10 @@ bitfield! {
|
|||||||
pub struct QualIo(u64);
|
pub struct QualIo(u64);
|
||||||
impl Debug;
|
impl Debug;
|
||||||
|
|
||||||
u8, size, set_size: 3, 0;
|
pub u8, size, set_size: 3, 0;
|
||||||
u8, direction, set_direction: 4, 4;
|
pub u8, direction, set_direction: 4, 4;
|
||||||
u8, string, set_string: 5, 5;
|
pub u8, string, set_string: 5, 5;
|
||||||
u8, rep, set_rep: 6, 6;
|
pub u8, rep, set_rep: 6, 6;
|
||||||
u8, operand_encoding, set_operand_encoding: 7, 7;
|
pub u8, operand_encoding, set_operand_encoding: 7, 7;
|
||||||
u16, port, set_port: 31, 16;
|
pub u16, port, set_port: 31, 16;
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,10 @@ use crate::{
|
|||||||
info,
|
info,
|
||||||
memory::BootInfoFrameAllocator,
|
memory::BootInfoFrameAllocator,
|
||||||
vmm::{
|
vmm::{
|
||||||
cpuid, cr, fpu, msr,
|
cpuid, cr, fpu,
|
||||||
qual::QualCr,
|
io::{self, Serial},
|
||||||
|
msr,
|
||||||
|
qual::{QualCr, QualIo},
|
||||||
vmcs::{
|
vmcs::{
|
||||||
DescriptorType, EntryControls, Granularity, PrimaryExitControls,
|
DescriptorType, EntryControls, Granularity, PrimaryExitControls,
|
||||||
PrimaryProcessorBasedVmExecutionControls, SecondaryProcessorBasedVmExecutionControls,
|
PrimaryProcessorBasedVmExecutionControls, SecondaryProcessorBasedVmExecutionControls,
|
||||||
@ -50,6 +52,7 @@ pub struct VCpu {
|
|||||||
pub ia32e_enabled: bool,
|
pub ia32e_enabled: bool,
|
||||||
pub xcr0: XCR0,
|
pub xcr0: XCR0,
|
||||||
pub host_xcr0: u64,
|
pub host_xcr0: u64,
|
||||||
|
pub serial: Serial,
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEMP_STACK_SIZE: usize = 4096;
|
const TEMP_STACK_SIZE: usize = 4096;
|
||||||
@ -76,6 +79,7 @@ impl VCpu {
|
|||||||
ia32e_enabled: false,
|
ia32e_enabled: false,
|
||||||
xcr0: XCR0(3),
|
xcr0: XCR0(3),
|
||||||
host_xcr0: 0,
|
host_xcr0: 0,
|
||||||
|
serial: Serial::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -694,7 +698,6 @@ impl VCpu {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info!("RIP: {:#x}", unsafe { vmread(vmcs::guest::RIP) }.unwrap());
|
|
||||||
match info.get_reason() {
|
match info.get_reason() {
|
||||||
VmxExitReason::HLT => {
|
VmxExitReason::HLT => {
|
||||||
info!("HLT instruction executed");
|
info!("HLT instruction executed");
|
||||||
@ -730,7 +733,9 @@ impl VCpu {
|
|||||||
self.step_next_inst().unwrap();
|
self.step_next_inst().unwrap();
|
||||||
}
|
}
|
||||||
VmxExitReason::IO_INSTRUCTION => {
|
VmxExitReason::IO_INSTRUCTION => {
|
||||||
info!("IO instruction executed");
|
let qual = unsafe { vmread(vmcs::ro::EXIT_QUALIFICATION).unwrap() };
|
||||||
|
let qual = QualIo(qual);
|
||||||
|
io::handle_io(self, qual);
|
||||||
self.step_next_inst().unwrap();
|
self.step_next_inst().unwrap();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
Reference in New Issue
Block a user