Serial I/O virtualization #2

This commit is contained in:
Masato Imai
2025-08-24 12:14:02 +00:00
parent db650f470f
commit a0188056f0
2 changed files with 55 additions and 2 deletions

View File

@@ -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_rules! print {
($($arg:tt)*) => {

View File

@@ -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 super::qual::QualIo;
use crate::{
info,
interrupt::subscriber::InterruptContext,
serial,
vmm::x86_64::intel::{
register::GuestRegisters, vmcs::controls::EntryIntrInfo, vmread, vmwrite,
},
@@ -37,6 +41,12 @@ pub enum ReadSel {
Isr,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Serial {
pub ier: u8,
pub mcr: u8,
}
pub struct Pic {
pub primary_mask: u8,
pub secondary_mask: u8,
@@ -50,6 +60,7 @@ pub struct Pic {
pub secondary_isr: u8,
pub primary_read_sel: ReadSel,
pub secondary_read_sel: ReadSel,
pub serial: Serial,
}
impl Pic {
@@ -67,6 +78,7 @@ impl Pic {
secondary_isr: 0,
primary_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),
0xA0..=0xA1 => self.handle_pic_in(regs, qual),
0x0070..=0x0071 => regs.rax = 0,
0x03F..=0x03FF => self.handle_serial_in(regs, qual),
_ => regs.rax = 0,
}
}
@@ -198,11 +211,43 @@ impl Pic {
0xC000..=0xCFFF => {} //ignore
0x20..=0x21 => 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
_ => {}
}
}
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) {
match qual.port() {
0x20 => {
@@ -324,7 +369,6 @@ impl IOBitmap {
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);
vmwrite(vmcs::control::IO_BITMAP_A_ADDR_FULL, bitmap_a_addr as u64)?;