From 1606184551a422bca968f62102335fb1af4c4a73 Mon Sep 17 00:00:00 2001 From: Masato Imai Date: Sun, 24 Aug 2025 12:24:53 +0000 Subject: [PATCH] Serial I/O buffer #2 --- nel_os_kernel/src/serial.rs | 12 +++++++ nel_os_kernel/src/vmm/x86_64/intel/io.rs | 41 +++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/nel_os_kernel/src/serial.rs b/nel_os_kernel/src/serial.rs index 5ee848b..f886916 100644 --- a/nel_os_kernel/src/serial.rs +++ b/nel_os_kernel/src/serial.rs @@ -56,6 +56,18 @@ pub fn write_byte(byte: u8) { }); } +#[inline(always)] +pub fn write_bytes(bytes: &[u8]) { + use x86_64::instructions::interrupts; + + interrupts::without_interrupts(|| { + let mut serial = SERIAL1.lock(); + for &b in bytes { + serial.send(b); + } + }); +} + #[macro_export] macro_rules! print { ($($arg:tt)*) => { diff --git a/nel_os_kernel/src/vmm/x86_64/intel/io.rs b/nel_os_kernel/src/vmm/x86_64/intel/io.rs index 3e7884f..c8f2432 100644 --- a/nel_os_kernel/src/vmm/x86_64/intel/io.rs +++ b/nel_os_kernel/src/vmm/x86_64/intel/io.rs @@ -61,6 +61,7 @@ pub struct Pic { pub primary_read_sel: ReadSel, pub secondary_read_sel: ReadSel, pub serial: Serial, + pub serial_buffer: SerialBuffer, } impl Pic { @@ -79,6 +80,7 @@ impl Pic { primary_read_sel: ReadSel::Irr, secondary_read_sel: ReadSel::Irr, serial: Serial::default(), + serial_buffer: SerialBuffer::default(), } } @@ -235,7 +237,17 @@ impl Pic { fn handle_serial_out(&mut self, regs: &mut GuestRegisters, qual: QualIo) { match qual.port() { - 0x3F8 => serial::write_byte(regs.rax as u8), + 0x3F8 => { + let byte = regs.rax as u8; + if self.serial_buffer.end < self.serial_buffer.buffer.len() { + self.serial_buffer.buffer[self.serial_buffer.end] = byte; + self.serial_buffer.end += 1; + } + + if byte == b'\n' || self.serial_buffer.end == self.serial_buffer.buffer.len() { + self.serial_buffer.flush(); + } + } 0x3F9 => self.serial.ier = regs.rax as u8, 0x3FA => {} 0x3FB => {} @@ -406,3 +418,30 @@ impl IOBitmap { } } } + +#[derive(Debug, Clone, Copy)] +pub struct SerialBuffer { + pub buffer: [u8; 1024], + pub end: usize, +} + +impl SerialBuffer { + pub fn flush(&mut self) { + if self.end == 0 { + return; + } + + serial::write_bytes(&self.buffer[..self.end]); + + self.end = 0; + } +} + +impl Default for SerialBuffer { + fn default() -> Self { + Self { + buffer: [0; 1024], + end: 0, + } + } +}