mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm, devices: Move logging of 0x80 timestamp to its own device
This is a cleaner approach to handling the I/O port write to 0x80. Whilst doing this also use generate the timestamp at the start of the VM creation. For consistency use the same timestamp for the ARM equivalent. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
86
devices/src/legacy/debug_port.rs
Normal file
86
devices/src/legacy/debug_port.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
// Copyright © 2022 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::fmt;
|
||||
use std::time::Instant;
|
||||
use vm_device::BusDevice;
|
||||
|
||||
/// Debug I/O port, see:
|
||||
/// https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html
|
||||
///
|
||||
/// Since we're not a physical platform, we can freely assign code ranges for
|
||||
/// debugging specific parts of our virtual platform.
|
||||
pub enum DebugIoPortRange {
|
||||
Firmware,
|
||||
Bootloader,
|
||||
Kernel,
|
||||
Userspace,
|
||||
Custom,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const DEBUG_IOPORT_PREFIX: &str = "Debug I/O port";
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl DebugIoPortRange {
|
||||
fn from_u8(value: u8) -> DebugIoPortRange {
|
||||
match value {
|
||||
0x00..=0x1f => DebugIoPortRange::Firmware,
|
||||
0x20..=0x3f => DebugIoPortRange::Bootloader,
|
||||
0x40..=0x5f => DebugIoPortRange::Kernel,
|
||||
0x60..=0x7f => DebugIoPortRange::Userspace,
|
||||
_ => DebugIoPortRange::Custom,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl fmt::Display for DebugIoPortRange {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
DebugIoPortRange::Firmware => write!(f, "{}: Firmware", DEBUG_IOPORT_PREFIX),
|
||||
DebugIoPortRange::Bootloader => write!(f, "{}: Bootloader", DEBUG_IOPORT_PREFIX),
|
||||
DebugIoPortRange::Kernel => write!(f, "{}: Kernel", DEBUG_IOPORT_PREFIX),
|
||||
DebugIoPortRange::Userspace => write!(f, "{}: Userspace", DEBUG_IOPORT_PREFIX),
|
||||
DebugIoPortRange::Custom => write!(f, "{}: Custom", DEBUG_IOPORT_PREFIX),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DebugPort {
|
||||
timestamp: Instant,
|
||||
}
|
||||
|
||||
impl DebugPort {
|
||||
pub fn new(timestamp: Instant) -> Self {
|
||||
Self { timestamp }
|
||||
}
|
||||
}
|
||||
|
||||
impl BusDevice for DebugPort {
|
||||
fn read(&mut self, _base: u64, _offset: u64, _data: &mut [u8]) {
|
||||
error!("Invalid read to debug port")
|
||||
}
|
||||
|
||||
fn write(
|
||||
&mut self,
|
||||
_base: u64,
|
||||
_offset: u64,
|
||||
data: &[u8],
|
||||
) -> Option<std::sync::Arc<std::sync::Barrier>> {
|
||||
let elapsed = self.timestamp.elapsed();
|
||||
|
||||
let code = data[0];
|
||||
info!(
|
||||
"[{} code 0x{:x}] {}.{:>06} seconds",
|
||||
DebugIoPortRange::from_u8(code),
|
||||
code,
|
||||
elapsed.as_secs(),
|
||||
elapsed.as_micros()
|
||||
);
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
|
||||
mod cmos;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod debug_port;
|
||||
#[cfg(feature = "fwdebug")]
|
||||
mod fwdebug;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
@@ -18,6 +20,8 @@ mod serial;
|
||||
mod uart_pl011;
|
||||
|
||||
pub use self::cmos::Cmos;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use self::debug_port::DebugPort;
|
||||
#[cfg(feature = "fwdebug")]
|
||||
pub use self::fwdebug::FwDebugDevice;
|
||||
pub use self::i8042::I8042Device;
|
||||
|
||||
@@ -10,6 +10,7 @@ use crate::{read_le_u32, write_le_u32};
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::time::Instant;
|
||||
use std::{io, result};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
@@ -120,6 +121,7 @@ impl Pl011 {
|
||||
id: String,
|
||||
irq: Arc<dyn InterruptSourceGroup>,
|
||||
out: Option<Box<dyn io::Write + Send>>,
|
||||
timestamp: Instant,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
@@ -140,7 +142,7 @@ impl Pl011 {
|
||||
read_trigger: 1u32,
|
||||
irq,
|
||||
out,
|
||||
timestamp: std::time::Instant::now(),
|
||||
timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,6 +497,7 @@ mod tests {
|
||||
String::from(SERIAL_NAME),
|
||||
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
||||
Some(Box::new(pl011_out.clone())),
|
||||
Instant::now(),
|
||||
);
|
||||
|
||||
pl011.write(0, UARTDR as u64, &[b'x', b'y']);
|
||||
@@ -515,6 +518,7 @@ mod tests {
|
||||
String::from(SERIAL_NAME),
|
||||
Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
||||
Some(Box::new(pl011_out)),
|
||||
Instant::now(),
|
||||
);
|
||||
|
||||
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
|
||||
|
||||
Reference in New Issue
Block a user