xref: /cloud-hypervisor/devices/src/legacy/debug_port.rs (revision 88a9f799449c04180c6b9a21d3b9c0c4b57e2bd6)
1 // Copyright © 2022 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5 
6 use std::fmt;
7 use std::time::Instant;
8 
9 use vm_device::BusDevice;
10 
11 /// Debug I/O port, see:
12 /// https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html
13 ///
14 /// Since we're not a physical platform, we can freely assign code ranges for
15 /// debugging specific parts of our virtual platform.
16 pub enum DebugIoPortRange {
17     Firmware,
18     Bootloader,
19     Kernel,
20     Userspace,
21     Custom,
22 }
23 
24 #[cfg(target_arch = "x86_64")]
25 const DEBUG_IOPORT_PREFIX: &str = "Debug I/O port";
26 
27 #[cfg(target_arch = "x86_64")]
28 impl DebugIoPortRange {
from_u8(value: u8) -> DebugIoPortRange29     fn from_u8(value: u8) -> DebugIoPortRange {
30         match value {
31             0x00..=0x1f => DebugIoPortRange::Firmware,
32             0x20..=0x3f => DebugIoPortRange::Bootloader,
33             0x40..=0x5f => DebugIoPortRange::Kernel,
34             0x60..=0x7f => DebugIoPortRange::Userspace,
35             _ => DebugIoPortRange::Custom,
36         }
37     }
38 }
39 
40 #[cfg(target_arch = "x86_64")]
41 impl fmt::Display for DebugIoPortRange {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result42     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43         match self {
44             DebugIoPortRange::Firmware => write!(f, "{DEBUG_IOPORT_PREFIX}: Firmware"),
45             DebugIoPortRange::Bootloader => write!(f, "{DEBUG_IOPORT_PREFIX}: Bootloader"),
46             DebugIoPortRange::Kernel => write!(f, "{DEBUG_IOPORT_PREFIX}: Kernel"),
47             DebugIoPortRange::Userspace => write!(f, "{DEBUG_IOPORT_PREFIX}: Userspace"),
48             DebugIoPortRange::Custom => write!(f, "{DEBUG_IOPORT_PREFIX}: Custom"),
49         }
50     }
51 }
52 
53 pub struct DebugPort {
54     timestamp: Instant,
55 }
56 
57 impl DebugPort {
new(timestamp: Instant) -> Self58     pub fn new(timestamp: Instant) -> Self {
59         Self { timestamp }
60     }
61 }
62 
63 impl BusDevice for DebugPort {
read(&mut self, _base: u64, _offset: u64, _data: &mut [u8])64     fn read(&mut self, _base: u64, _offset: u64, _data: &mut [u8]) {
65         error!("Invalid read to debug port")
66     }
67 
write( &mut self, _base: u64, _offset: u64, data: &[u8], ) -> Option<std::sync::Arc<std::sync::Barrier>>68     fn write(
69         &mut self,
70         _base: u64,
71         _offset: u64,
72         data: &[u8],
73     ) -> Option<std::sync::Arc<std::sync::Barrier>> {
74         let elapsed = self.timestamp.elapsed();
75 
76         let code = data[0];
77         warn!(
78             "[{} code 0x{:x}] {}.{:>06} seconds",
79             DebugIoPortRange::from_u8(code),
80             code,
81             elapsed.as_secs(),
82             elapsed.as_micros()
83         );
84 
85         None
86     }
87 }
88