Skip to content

Commit

Permalink
platform: move I/O port driver into platform abstraction
Browse files Browse the repository at this point in the history
The `SVSMIOPort` and `NativeIOPort` objects are platform-specific, and
thus they should be implemented in the platform abstraction instead of
in common code.  Furthermore, the console serial port object is common
and need not be duplicated in every platform abstraction.

Signed-off-by: Jon Lange <[email protected]>
  • Loading branch information
msft-jlange committed Sep 19, 2024
1 parent f23151f commit d8bef31
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 163 deletions.
15 changes: 13 additions & 2 deletions kernel/src/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
//
// Author: Joerg Roedel <[email protected]>

use crate::error::SvsmError;
use crate::io::IOPort;
use crate::locking::SpinLock;
use crate::serial::{Terminal, DEFAULT_SERIAL_PORT};
use crate::serial::{SerialPort, Terminal, DEFAULT_SERIAL_PORT};
use crate::utils::immut_after_init::{ImmutAfterInitCell, ImmutAfterInitResult};
use core::fmt;

Expand All @@ -27,14 +29,23 @@ static WRITER: SpinLock<Console> = SpinLock::new(Console {
writer: &DEFAULT_SERIAL_PORT,
});
static CONSOLE_INITIALIZED: ImmutAfterInitCell<bool> = ImmutAfterInitCell::new(false);
static CONSOLE_SERIAL: ImmutAfterInitCell<SerialPort<'_>> = ImmutAfterInitCell::uninit();

pub fn init_console(writer: &'static dyn Terminal) -> ImmutAfterInitResult<()> {
fn init_console(writer: &'static dyn Terminal) -> ImmutAfterInitResult<()> {
WRITER.lock().writer = writer;
CONSOLE_INITIALIZED.reinit(&true)?;
log::info!("COCONUT Secure Virtual Machine Service Module");
Ok(())
}

pub fn init_svsm_console(writer: &'static dyn IOPort, port: u16) -> Result<(), SvsmError> {
CONSOLE_SERIAL
.init(&SerialPort::new(writer, port))
.map_err(|_| SvsmError::Console)?;
(*CONSOLE_SERIAL).init();
init_console(&*CONSOLE_SERIAL).map_err(|_| SvsmError::Console)
}

#[doc(hidden)]
pub fn _print(args: fmt::Arguments<'_>) {
use core::fmt::Write;
Expand Down
1 change: 0 additions & 1 deletion kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ pub mod requests;
pub mod serial;
pub mod sev;
pub mod string;
pub mod svsm_console;
pub mod svsm_paging;
pub mod syscall;
pub mod task;
Expand Down
18 changes: 4 additions & 14 deletions kernel/src/platform/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,16 @@
// Author: Jon Lange <[email protected]>

use crate::address::{PhysAddr, VirtAddr};
use crate::console::init_console;
use crate::console::init_svsm_console;
use crate::cpu::cpuid::CpuidResult;
use crate::cpu::msr::write_msr;
use crate::cpu::percpu::PerCpu;
use crate::error::SvsmError;
use crate::io::IOPort;
use crate::io::{IOPort, DEFAULT_IO_DRIVER};
use crate::platform::{PageEncryptionMasks, PageStateChangeOp, SvsmPlatform};
use crate::serial::SerialPort;
use crate::svsm_console::NativeIOPort;
use crate::types::PageSize;
use crate::utils::immut_after_init::ImmutAfterInitCell;
use crate::utils::MemoryRegion;

static CONSOLE_IO: NativeIOPort = NativeIOPort::new();
static CONSOLE_SERIAL: ImmutAfterInitCell<SerialPort<'_>> = ImmutAfterInitCell::uninit();

const APIC_MSR_ICR: u32 = 0x830;

#[derive(Clone, Copy, Debug)]
Expand All @@ -42,11 +36,7 @@ impl SvsmPlatform for NativePlatform {
fn env_setup(&mut self, debug_serial_port: u16, _vtom: usize) -> Result<(), SvsmError> {
// In the native platform, console output does not require the use of
// any platform services, so it can be initialized immediately.
CONSOLE_SERIAL
.init(&SerialPort::new(&CONSOLE_IO, debug_serial_port))
.map_err(|_| SvsmError::Console)?;
(*CONSOLE_SERIAL).init();
init_console(&*CONSOLE_SERIAL).map_err(|_| SvsmError::Console)
init_svsm_console(&DEFAULT_IO_DRIVER, debug_serial_port)
}

fn env_setup_late(&mut self, _debug_serial_port: u16) -> Result<(), SvsmError> {
Expand Down Expand Up @@ -83,7 +73,7 @@ impl SvsmPlatform for NativePlatform {
fn setup_guest_host_comm(&mut self, _cpu: &PerCpu, _is_bsp: bool) {}

fn get_io_port(&self) -> &'static dyn IOPort {
&CONSOLE_IO
&DEFAULT_IO_DRIVER
}

fn page_state_change(
Expand Down
76 changes: 64 additions & 12 deletions kernel/src/platform/snp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,29 @@
// Author: Jon Lange <[email protected]>

use crate::address::{PhysAddr, VirtAddr};
use crate::console::init_console;
use crate::console::init_svsm_console;
use crate::cpu::cpuid::{cpuid_table, CpuidResult};
use crate::cpu::percpu::{current_ghcb, this_cpu, PerCpu};
use crate::error::ApicError::Registration;
use crate::error::SvsmError;
use crate::io::IOPort;
use crate::platform::{PageEncryptionMasks, PageStateChangeOp, SvsmPlatform};
use crate::serial::SerialPort;
use crate::sev::ghcb::GHCBIOSize;
use crate::sev::hv_doorbell::current_hv_doorbell;
use crate::sev::msr_protocol::{hypervisor_ghcb_features, verify_ghcb_version, GHCBHvFeatures};
use crate::sev::msr_protocol::{
hypervisor_ghcb_features, request_termination_msr, verify_ghcb_version, GHCBHvFeatures,
};
use crate::sev::status::vtom_enabled;
use crate::sev::{
init_hypervisor_ghcb_features, pvalidate_range, sev_status_init, sev_status_verify, PvalidateOp,
};
use crate::svsm_console::SVSMIOPort;
use crate::types::PageSize;
use crate::utils::immut_after_init::ImmutAfterInitCell;
use crate::utils::MemoryRegion;

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

static CONSOLE_IO: SVSMIOPort = SVSMIOPort::new();
static CONSOLE_SERIAL: ImmutAfterInitCell<SerialPort<'_>> = ImmutAfterInitCell::uninit();
static GHCB_IO_DRIVER: GHCBIOPort = GHCBIOPort::new();

static VTOM: ImmutAfterInitCell<usize> = ImmutAfterInitCell::uninit();

Expand Down Expand Up @@ -56,11 +56,7 @@ impl SvsmPlatform for SnpPlatform {
}

fn env_setup_late(&mut self, debug_serial_port: u16) -> Result<(), SvsmError> {
CONSOLE_SERIAL
.init(&SerialPort::new(&CONSOLE_IO, debug_serial_port))
.map_err(|_| SvsmError::Console)?;
(*CONSOLE_SERIAL).init();
init_console(&*CONSOLE_SERIAL).map_err(|_| SvsmError::Console)?;
init_svsm_console(&GHCB_IO_DRIVER, debug_serial_port)?;
sev_status_verify();
init_hypervisor_ghcb_features()?;
Ok(())
Expand Down Expand Up @@ -126,7 +122,7 @@ impl SvsmPlatform for SnpPlatform {
}

fn get_io_port(&self) -> &'static dyn IOPort {
&CONSOLE_IO
&GHCB_IO_DRIVER
}

fn page_state_change(
Expand Down Expand Up @@ -227,3 +223,59 @@ impl SvsmPlatform for SnpPlatform {
current_ghcb().ap_create(vmsa_pa, cpu.get_apic_id().into(), 0, sev_features)
}
}

#[derive(Clone, Copy, Debug, Default)]
pub struct GHCBIOPort {}

impl GHCBIOPort {
pub const fn new() -> Self {
GHCBIOPort {}
}
}

impl IOPort for GHCBIOPort {
fn outb(&self, port: u16, value: u8) {
let ret = current_ghcb().ioio_out(port, GHCBIOSize::Size8, value as u64);
if ret.is_err() {
request_termination_msr();
}
}

fn inb(&self, port: u16) -> u8 {
let ret = current_ghcb().ioio_in(port, GHCBIOSize::Size8);
match ret {
Ok(v) => (v & 0xff) as u8,
Err(_e) => request_termination_msr(),
}
}

fn outw(&self, port: u16, value: u16) {
let ret = current_ghcb().ioio_out(port, GHCBIOSize::Size16, value as u64);
if ret.is_err() {
request_termination_msr();
}
}

fn inw(&self, port: u16) -> u16 {
let ret = current_ghcb().ioio_in(port, GHCBIOSize::Size16);
match ret {
Ok(v) => (v & 0xffff) as u16,
Err(_e) => request_termination_msr(),
}
}

fn outl(&self, port: u16, value: u32) {
let ret = current_ghcb().ioio_out(port, GHCBIOSize::Size32, value as u64);
if ret.is_err() {
request_termination_msr();
}
}

fn inl(&self, port: u16) -> u32 {
let ret = current_ghcb().ioio_in(port, GHCBIOSize::Size32);
match ret {
Ok(v) => (v & 0xffffffff) as u32,
Err(_e) => request_termination_msr(),
}
}
}
21 changes: 6 additions & 15 deletions kernel/src/platform/tdp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,16 @@
// Author: Peter Fang <[email protected]>

use crate::address::{PhysAddr, VirtAddr};
use crate::console::init_console;
use crate::console::init_svsm_console;
use crate::cpu::cpuid::CpuidResult;
use crate::cpu::percpu::PerCpu;
use crate::error::SvsmError;
use crate::io::IOPort;
use crate::io::{IOPort, DEFAULT_IO_DRIVER};
use crate::platform::{PageEncryptionMasks, PageStateChangeOp, SvsmPlatform};
use crate::serial::SerialPort;
use crate::svsm_console::SVSMIOPort;
use crate::types::PageSize;
use crate::utils::immut_after_init::ImmutAfterInitCell;
use crate::utils::MemoryRegion;

// FIXME - SVSMIOPort doesn't work on TDP, but the platform does not yet have
// an alternative available.
static CONSOLE_IO: SVSMIOPort = SVSMIOPort::new();
static CONSOLE_SERIAL: ImmutAfterInitCell<SerialPort<'_>> = ImmutAfterInitCell::uninit();

static VTOM: ImmutAfterInitCell<usize> = ImmutAfterInitCell::uninit();

#[derive(Clone, Copy, Debug)]
Expand All @@ -45,11 +38,7 @@ impl SvsmPlatform for TdpPlatform {
}

fn env_setup_late(&mut self, debug_serial_port: u16) -> Result<(), SvsmError> {
CONSOLE_SERIAL
.init(&SerialPort::new(&CONSOLE_IO, debug_serial_port))
.map_err(|_| SvsmError::Console)?;
(*CONSOLE_SERIAL).init();
init_console(&*CONSOLE_SERIAL).map_err(|_| SvsmError::Console)
init_svsm_console(&DEFAULT_IO_DRIVER, debug_serial_port)
}

fn env_setup_svsm(&self) -> Result<(), SvsmError> {
Expand Down Expand Up @@ -83,7 +72,9 @@ impl SvsmPlatform for TdpPlatform {
fn setup_guest_host_comm(&mut self, _cpu: &PerCpu, _is_bsp: bool) {}

fn get_io_port(&self) -> &'static dyn IOPort {
&CONSOLE_IO
// FIXME - the default I/O port implementation doesn't work on TDP,
// but the platform does not yet have an alternative available.
&DEFAULT_IO_DRIVER
}

fn page_state_change(
Expand Down
119 changes: 0 additions & 119 deletions kernel/src/svsm_console.rs

This file was deleted.

0 comments on commit d8bef31

Please sign in to comment.