Serial I/O virtualization #2
This commit is contained in:
@@ -47,6 +47,15 @@ pub fn _print(args: ::core::fmt::Arguments) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn write_byte(byte: u8) {
|
||||||
|
use x86_64::instructions::interrupts;
|
||||||
|
|
||||||
|
interrupts::without_interrupts(|| {
|
||||||
|
SERIAL1.lock().send(byte);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! print {
|
macro_rules! print {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
use x86::vmx::{self, vmcs};
|
use x86::{
|
||||||
|
io::inb,
|
||||||
|
vmx::{self, vmcs},
|
||||||
|
};
|
||||||
use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB};
|
use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB};
|
||||||
|
|
||||||
use super::qual::QualIo;
|
use super::qual::QualIo;
|
||||||
use crate::{
|
use crate::{
|
||||||
info,
|
info,
|
||||||
interrupt::subscriber::InterruptContext,
|
interrupt::subscriber::InterruptContext,
|
||||||
|
serial,
|
||||||
vmm::x86_64::intel::{
|
vmm::x86_64::intel::{
|
||||||
register::GuestRegisters, vmcs::controls::EntryIntrInfo, vmread, vmwrite,
|
register::GuestRegisters, vmcs::controls::EntryIntrInfo, vmread, vmwrite,
|
||||||
},
|
},
|
||||||
@@ -37,6 +41,12 @@ pub enum ReadSel {
|
|||||||
Isr,
|
Isr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct Serial {
|
||||||
|
pub ier: u8,
|
||||||
|
pub mcr: u8,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Pic {
|
pub struct Pic {
|
||||||
pub primary_mask: u8,
|
pub primary_mask: u8,
|
||||||
pub secondary_mask: u8,
|
pub secondary_mask: u8,
|
||||||
@@ -50,6 +60,7 @@ pub struct Pic {
|
|||||||
pub secondary_isr: u8,
|
pub secondary_isr: u8,
|
||||||
pub primary_read_sel: ReadSel,
|
pub primary_read_sel: ReadSel,
|
||||||
pub secondary_read_sel: ReadSel,
|
pub secondary_read_sel: ReadSel,
|
||||||
|
pub serial: Serial,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pic {
|
impl Pic {
|
||||||
@@ -67,6 +78,7 @@ impl Pic {
|
|||||||
secondary_isr: 0,
|
secondary_isr: 0,
|
||||||
primary_read_sel: ReadSel::Irr,
|
primary_read_sel: ReadSel::Irr,
|
||||||
secondary_read_sel: ReadSel::Irr,
|
secondary_read_sel: ReadSel::Irr,
|
||||||
|
serial: Serial::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +200,7 @@ impl Pic {
|
|||||||
0x20..=0x21 => self.handle_pic_in(regs, qual),
|
0x20..=0x21 => self.handle_pic_in(regs, qual),
|
||||||
0xA0..=0xA1 => self.handle_pic_in(regs, qual),
|
0xA0..=0xA1 => self.handle_pic_in(regs, qual),
|
||||||
0x0070..=0x0071 => regs.rax = 0,
|
0x0070..=0x0071 => regs.rax = 0,
|
||||||
|
0x03F..=0x03FF => self.handle_serial_in(regs, qual),
|
||||||
_ => regs.rax = 0,
|
_ => regs.rax = 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,11 +211,43 @@ impl Pic {
|
|||||||
0xC000..=0xCFFF => {} //ignore
|
0xC000..=0xCFFF => {} //ignore
|
||||||
0x20..=0x21 => self.handle_pic_out(regs, qual),
|
0x20..=0x21 => self.handle_pic_out(regs, qual),
|
||||||
0xA0..=0xA1 => self.handle_pic_out(regs, qual),
|
0xA0..=0xA1 => self.handle_pic_out(regs, qual),
|
||||||
|
0x03F8..=0x03FF => self.handle_serial_out(regs, qual),
|
||||||
0x0070..=0x0071 => {} //ignore
|
0x0070..=0x0071 => {} //ignore
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_serial_in(&self, regs: &mut GuestRegisters, qual: QualIo) {
|
||||||
|
match qual.port() {
|
||||||
|
0x3F8 => regs.rax = unsafe { inb(qual.port()).into() },
|
||||||
|
0x3F9 => regs.rax = self.serial.ier as u64,
|
||||||
|
0x3FA => regs.rax = unsafe { inb(qual.port()).into() },
|
||||||
|
0x3FB => regs.rax = 0,
|
||||||
|
0x3FC => regs.rax = self.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(&mut self, regs: &mut GuestRegisters, qual: QualIo) {
|
||||||
|
match qual.port() {
|
||||||
|
0x3F8 => serial::write_byte(regs.rax as u8),
|
||||||
|
0x3F9 => self.serial.ier = regs.rax as u8,
|
||||||
|
0x3FA => {}
|
||||||
|
0x3FB => {}
|
||||||
|
0x3FC => self.serial.mcr = regs.rax as u8,
|
||||||
|
0x3FD => {}
|
||||||
|
0x3FF => {}
|
||||||
|
_ => {
|
||||||
|
panic!("Serial out: invalid port: {:#x}", qual.port());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_pic_in(&self, regs: &mut GuestRegisters, qual: QualIo) {
|
fn handle_pic_in(&self, regs: &mut GuestRegisters, qual: QualIo) {
|
||||||
match qual.port() {
|
match qual.port() {
|
||||||
0x20 => {
|
0x20 => {
|
||||||
@@ -324,7 +369,6 @@ impl IOBitmap {
|
|||||||
core::ptr::write_bytes(bitmap_b_addr as *mut u8, u8::MAX, 4096);
|
core::ptr::write_bytes(bitmap_b_addr as *mut u8, u8::MAX, 4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_io_ports(0x02F8..=0x03FF);
|
|
||||||
self.set_io_ports(0x0040..=0x0047);
|
self.set_io_ports(0x0040..=0x0047);
|
||||||
|
|
||||||
vmwrite(vmcs::control::IO_BITMAP_A_ADDR_FULL, bitmap_a_addr as u64)?;
|
vmwrite(vmcs::control::IO_BITMAP_A_ADDR_FULL, bitmap_a_addr as u64)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user