Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a log buffer to store log messages. #52

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
# ld to work, so build all the objects without performing the
# final linking step.
- name: Build
run: make FEATURES="default,enable-gdb" bin/svsm-kernel.elf stage1/stage1.o stage1/reset.o
run: make FEATURES="default-debug,enable-gdb" bin/svsm-kernel.elf stage1/stage1.o stage1/reset.o

- name: Run tests
run: make test
Expand Down
11 changes: 7 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
FEATURES ?= "default"
SVSM_ARGS = --features ${FEATURES}

SVSM_ARGS_TEST = --no-default-features
ifdef FEATURES_TEST
SVSM_ARGS_TEST += --features ${FEATURES_TEST}
endif

ifdef RELEASE
TARGET_PATH=release
FEATURES ?= "default"
SVSM_ARGS = --features ${FEATURES}
CARGO_ARGS += --release
STAGE2_ARGS =
else
TARGET_PATH=debug
FEATURES ?= "default-debug"
SVSM_ARGS = --features ${FEATURES}
STAGE2_ARGS = --features "enable-console-log"
endif

ifdef OFFLINE
Expand Down Expand Up @@ -111,7 +114,7 @@ bin/meta.bin: utils/gen_meta utils/print-meta
./utils/gen_meta $@

bin/stage2.bin: bin
cargo build --manifest-path kernel/Cargo.toml ${CARGO_ARGS} --no-default-features --bin stage2
cargo build --manifest-path kernel/Cargo.toml ${CARGO_ARGS} ${STAGE2_ARGS} --no-default-features --bin stage2
objcopy -O binary ${STAGE2_ELF} $@

bin/svsm-kernel.elf: bin
Expand Down
2 changes: 0 additions & 2 deletions igvmbuilder/src/gpa_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ pub struct GpaMap {
pub general_params: GpaRange,
pub memory_map: GpaRange,
pub guest_context: GpaRange,
pub firmware: GpaRange,
pub kernel: GpaRange,
pub vmsa: GpaRange,
}
Expand Down Expand Up @@ -172,7 +171,6 @@ impl GpaMap {
general_params,
memory_map,
guest_context,
firmware: firmware_range,
kernel,
vmsa,
};
Expand Down
2 changes: 2 additions & 0 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ test.workspace = true

[features]
default = ["mstpm"]
default-debug = ["enable-console-log", "mstpm"]
enable-gdb = ["dep:gdbstub", "dep:gdbstub_arch"]
mstpm = ["dep:libmstpm"]
enable-console-log = []

[dev-dependencies]

Expand Down
130 changes: 130 additions & 0 deletions kernel/src/cpu/line_buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2022-2023 SUSE LLC
//
// Author: Vasant Karasulli <[email protected]>

use crate::console::_print;
use crate::cpu::percpu::this_cpu;
use crate::log_buffer::log_buffer;
use crate::string::FixedString;
use crate::types::LINE_BUFFER_SIZE;
use crate::utils::immut_after_init::{ImmutAfterInitCell, ImmutAfterInitResult};
use core::fmt;
use core::fmt::Write;

#[derive(Debug)]
pub struct LineBuffer {
buf: FixedString<LINE_BUFFER_SIZE>,
}

impl LineBuffer {
pub const fn new() -> Self {
LineBuffer {
buf: FixedString::new(),
}
}

pub fn write_buffer(&mut self, s: &str) {
for c in s.chars() {
self.buf.push(c);
if c == '\n' || self.buf.length() == LINE_BUFFER_SIZE {
// when buffer is full or '\n' character is encountered
log_buffer().write_log(&self.buf);
self.buf.clear();
}
}
}
}

impl Write for LineBuffer {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.write_buffer(s);
Ok(())
}
}

impl Default for LineBuffer {
fn default() -> Self {
Self::new()
}
}

#[derive(Clone, Copy)]
struct BufferLogger {
component: &'static str,
}

impl BufferLogger {
fn new(component: &'static str) -> BufferLogger {
BufferLogger { component }
}
}

impl log::Log for BufferLogger {
fn enabled(&self, _metadata: &log::Metadata<'_>) -> bool {
true
}

fn log(&self, record: &log::Record<'_>) {
let comp: &'static str = self.component;
let line_buf = &mut this_cpu().get_line_buffer();
// Log format/detail depends on the level.
let rec_args = record.args();
let lvl = record.metadata().level().as_str();
let target = record.metadata().target();
match record.metadata().level() {
log::Level::Error | log::Level::Warn => {
line_buf
.write_fmt(format_args!("[{}] {}: {}\n", comp, lvl, rec_args))
.unwrap();
#[cfg(feature = "enable-console-log")]
{
_print(format_args!("[{}] {}: {}\n", comp, lvl, rec_args));
}
}

log::Level::Info => {
line_buf
.write_fmt(format_args!("[{}] {}\n", comp, rec_args))
.unwrap();
#[cfg(feature = "enable-console-log")]
{
_print(format_args!("[{}] {}\n", comp, rec_args));
}
}

log::Level::Debug | log::Level::Trace => {
line_buf
.write_fmt(format_args!("[{}/{}] {} {}\n", comp, target, lvl, rec_args))
.unwrap();
#[cfg(feature = "enable-console-log")]
{
_print(format_args!("[{}/{}] {} {}\n", comp, target, lvl, rec_args));
}
}
}
}

fn flush(&self) {}
}

static BUFFER_LOGGER: ImmutAfterInitCell<BufferLogger> = ImmutAfterInitCell::uninit();

pub fn install_buffer_logger(component: &'static str) -> ImmutAfterInitResult<()> {
BUFFER_LOGGER.init(&BufferLogger::new(component))?;

if let Err(e) = log::set_logger(&*BUFFER_LOGGER) {
// Failed to install the BufferLogger, presumably because something had
// installed another logger before. No logs will be stored in the buffer.
// Print an error string.
_print(format_args!(
"[{}]: ERROR: failed to install buffer logger: {:?}",
component, e,
));
}

// Log levels are to be configured via the log's library feature configuration.
log::set_max_level(log::LevelFilter::Trace);
Ok(())
}
1 change: 1 addition & 0 deletions kernel/src/cpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod extable;
pub mod features;
pub mod gdt;
pub mod idt;
pub mod line_buffer;
pub mod msr;
pub mod percpu;
pub mod registers;
Expand Down
7 changes: 7 additions & 0 deletions kernel/src/cpu/percpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use super::tss::{X86Tss, IST_DF};
use crate::address::{Address, PhysAddr, VirtAddr};
use crate::cpu::apic::ApicError;
use crate::cpu::idt::common::INT_INJ_VECTOR;
use crate::cpu::line_buffer::LineBuffer;
use crate::cpu::tss::TSS_LIMIT;
use crate::cpu::vmsa::init_guest_vmsa;
use crate::cpu::vmsa::vmsa_mut_ref_from_vaddr;
Expand Down Expand Up @@ -337,6 +338,7 @@ pub struct PerCpu {
hv_doorbell: Cell<*const HVDoorbell>,
init_stack: Cell<Option<VirtAddr>>,
ist: IstStacks,
ln_buf: RefCell<LineBuffer>,

/// Stack boundaries of the currently running task.
current_stack: Cell<MemoryRegion<VirtAddr>>,
Expand All @@ -362,6 +364,7 @@ impl PerCpu {
hv_doorbell: Cell::new(ptr::null()),
init_stack: Cell::new(None),
ist: IstStacks::new(),
ln_buf: RefCell::new(LineBuffer::new()),
current_stack: Cell::new(MemoryRegion::new(VirtAddr::null(), 0)),
}
}
Expand Down Expand Up @@ -843,6 +846,10 @@ impl PerCpu {
tss.stacks[0] = addr;
self.tss.set(tss);
}

pub fn get_line_buffer(&self) -> RefMut<'_, LineBuffer> {
self.ln_buf.borrow_mut()
}
}

pub fn this_cpu() -> &'static PerCpu {
Expand Down
2 changes: 2 additions & 0 deletions kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub mod insn_decode;
pub mod io;
pub mod kernel_region;
pub mod locking;
pub mod log_buffer;
pub mod migrate;
pub mod mm;
pub mod platform;
pub mod protocols;
Expand Down
Loading
Loading