Skip to content

Commit

Permalink
kernel: fix test-in-svsm use of the test serial port
Browse files Browse the repository at this point in the history
The test serial port must use the same platform abstraction as the rest
of the I/O port abstraction.  Since serial port construction is now
platform-specific, the construction is moved to the first use of the
test serial port.  The serial port cell is changed to an `Option` to
simplify the synchronization of the dynamic initialization across
consumers.

Also, for better abstraction, the operation to obtain the test serial
port doesn't emit a byte; it simply returns the port so the caller can
write whatever it wants.

Signed-off-by: Jon Lange <[email protected]>
  • Loading branch information
msft-jlange committed Oct 2, 2024
1 parent cf2cbce commit b722a58
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 18 deletions.
4 changes: 3 additions & 1 deletion kernel/src/greq/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ mod tests {

use alloc::vec;

let sp = svsm_test_io(IORequest::GetLaunchMeasurement);
let sp = svsm_test_io().unwrap();

sp.put_byte(IORequest::GetLaunchMeasurement as u8);

let mut expected_measurement = [0u8; 48];
for byte in &mut expected_measurement {
Expand Down
27 changes: 10 additions & 17 deletions kernel/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ use test::ShouldPanic;
use crate::{
cpu::percpu::current_ghcb,
locking::{LockGuard, SpinLock},
serial::{SerialPort, Terminal},
platform::SVSM_PLATFORM,
serial::SerialPort,
sev::ghcb::GHCBIOSize,
svsm_console::SVSMIOPort,
};

use core::sync::atomic::{AtomicBool, Ordering};

#[macro_export]
macro_rules! assert_eq_warn {
($left:expr, $right:expr) => {
Expand All @@ -30,10 +28,7 @@ macro_rules! assert_eq_warn {
}
pub use assert_eq_warn;

static SERIAL_INITIALIZED: AtomicBool = AtomicBool::new(false);
static IOPORT: SVSMIOPort = SVSMIOPort::new();
static SERIAL_PORT: SpinLock<SerialPort<'_>> =
SpinLock::new(SerialPort::new(&IOPORT, 0x2e8 /*COM4*/));
static SERIAL_PORT: SpinLock<Option<SerialPort<'_>>> = SpinLock::new(None);

/// Byte used to tell the host the request we need for the test.
/// These values must be aligned with `test_io()` in scripts/test-in-svsm.sh
Expand All @@ -49,17 +44,15 @@ pub enum IORequest {
/// used in a test. The request (first byte) is sent by this function, so the
/// caller can start using the serial port according to the request implemented
/// in `test_io()` in scripts/test-in-svsm.sh
pub fn svsm_test_io(req: IORequest) -> LockGuard<'static, SerialPort<'static>> {
let sp = SERIAL_PORT.lock();
if SERIAL_INITIALIZED
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_ok()
{
sp.init();
pub fn svsm_test_io() -> LockGuard<'static, Option<SerialPort<'static>>> {
let mut sp = SERIAL_PORT.lock();
if sp.is_none() {
let io_port = SVSM_PLATFORM.as_dyn_ref().get_io_port();
let serial_port = SerialPort::new(io_port, 0x2e8 /*COM4*/);
*sp = Some(serial_port);
serial_port.init();
}

sp.put_byte(req as u8);

sp
}

Expand Down

0 comments on commit b722a58

Please sign in to comment.