Skip to content

Commit

Permalink
Added uhyve buffered serial output for aarch64
Browse files Browse the repository at this point in the history
  • Loading branch information
jounathaen committed Dec 2, 2024
1 parent b5784f6 commit ea7ebb9
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 36 deletions.
19 changes: 6 additions & 13 deletions src/arch/aarch64/kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::env;

const SERIAL_PORT_BAUDRATE: u32 = 115200;

static COM1: SpinMutex<SerialPort> = SpinMutex::new(SerialPort::new(0x800));
static COM1: SpinMutex<Option<SerialPort>> = SpinMutex::new(None);

/// `CPU_ONLINE` is the count of CPUs that finished initialization.
///
Expand Down Expand Up @@ -81,9 +81,7 @@ pub fn args() -> Option<&'static str> {
pub fn message_output_init() {
CoreLocal::install();

let mut com1 = COM1.lock();

com1.port_address = env::boot_info()
let com_port_address = env::boot_info()
.hardware_info
.serial_port_base
.map(|uartport| uartport.get())
Expand All @@ -93,18 +91,13 @@ pub fn message_output_init() {

// We can only initialize the serial port here, because VGA requires processor
// configuration first.
com1.init(SERIAL_PORT_BAUDRATE);
}

pub fn output_message_byte(byte: u8) {
// Output messages to the serial port.
COM1.lock().write_byte(byte);
let com = SerialPort::new(com_port_address);
com.init(SERIAL_PORT_BAUDRATE);
*COM1.lock() = Some(com);
}

pub fn output_message_buf(buf: &[u8]) {
for byte in buf {
output_message_byte(*byte);
}
COM1.lock().as_mut().unwrap().write_buf(buf);
}

/// Real Boot Processor initialization as soon as we have put the first Welcome message on the screen.
Expand Down
94 changes: 71 additions & 23 deletions src/arch/aarch64/kernel/serial.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,84 @@
use core::arch::asm;

use heapless::Vec;

use crate::syscalls::interfaces::serial_buf_hypercall;

const SERIAL_BUFFER_SIZE: usize = 256;

#[allow(clippy::large_enum_variant)]
enum SerialInner {
Uart(u32),
Uhyve(Vec<u8, SERIAL_BUFFER_SIZE>), // heapless vec to have print before allocators are initialized
}

pub struct SerialPort {
pub port_address: u32,
inner: SerialInner,
}

impl SerialPort {
pub const fn new(port_address: u32) -> Self {
Self { port_address }
pub fn new(port_address: u32) -> Self {
if crate::env::is_uhyve() {
Self {
inner: SerialInner::Uhyve(Vec::new()),
}
} else {
Self {
inner: SerialInner::Uart(port_address),
}
}
}

pub fn write_byte(&self, byte: u8) {
let port = core::ptr::with_exposed_provenance_mut::<u8>(self.port_address as usize);

// LF newline characters need to be extended to CRLF over a real serial port.
if byte == b'\n' {
unsafe {
asm!(
"strb w8, [{port}]",
port = in(reg) port,
in("x8") b'\r',
options(nostack),
);
pub fn write_buf(&mut self, buf: &[u8]) {
match &mut self.inner {
SerialInner::Uhyve(output_buf) => {
if SERIAL_BUFFER_SIZE - output_buf.len() >= buf.len() {
// unwrap: we checked that buf fits in output_buf
output_buf.extend_from_slice(buf).unwrap();
if buf.contains(&b'\n') {
serial_buf_hypercall(output_buf);
output_buf.clear();
}
} else {
serial_buf_hypercall(output_buf);
output_buf.clear();
if buf.len() >= SERIAL_BUFFER_SIZE {
serial_buf_hypercall(buf);
} else {
// unwrap: we checked that buf fits in output_buf
output_buf.extend_from_slice(buf).unwrap();
if buf.contains(&b'\n') {
serial_buf_hypercall(output_buf);
output_buf.clear();
}
}
}
}
}
SerialInner::Uart(port_address) => {
let port = core::ptr::with_exposed_provenance_mut::<u8>(*port_address as usize);
for &byte in buf {
// LF newline characters need to be extended to CRLF over a real serial port.
if byte == b'\n' {
unsafe {
asm!(
"strb w8, [{port}]",
port = in(reg) port,
in("x8") b'\r',
options(nostack),
);
}
}

unsafe {
asm!(
"strb w8, [{port}]",
port = in(reg) port,
in("x8") byte,
options(nostack),
);
unsafe {
asm!(
"strb w8, [{port}]",
port = in(reg) port,
in("x8") byte,
options(nostack),
);
}
}
}
}
}

Expand Down

0 comments on commit ea7ebb9

Please sign in to comment.