pvpanic.rs88.24%
1
// Copyright 2024 Google LLC2
//3
// Licensed under the Apache License, Version 2.0 (the "License");4
// you may not use this file except in compliance with the License.5
// You may obtain a copy of the License at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// distributed under the License is distributed on an "AS IS" BASIS,11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12
// See the License for the specific language governing permissions and13
// limitations under the License.14
15
use std::sync::Arc;16
17
use crate::bitflags;18
use crate::device::{self, Pause};19
use crate::mem::emulated::{Action, Mmio};20
use crate::mem::{self, MemRegion};21
use crate::pci::cap::PciCapList;22
use crate::pci::config::{23
BAR_MEM64, BAR_PREFETCHABLE, CommonHeader, DeviceHeader, EmulatedConfig, HeaderType, PciConfig,24
};25
use crate::pci::{self, Pci, PciBar};26
27
bitflags! {28
struct PvPanicByte(u8) {29
PANICKED = 1 << 0;30
CRASH_LOADED = 1 << 1;31
}32
}33
34
pub const PVPANIC_VENDOR_ID: u16 = 0x1b36;35
pub const PVPANIC_DEVICE_ID: u16 = 0x0011;36
37
const BAR_SIZE: u64 = 0x1000;38
39
#[derive(Debug)]40
struct PvPanicBar;41
42
impl Mmio for PvPanicBar {43
fn size(&self) -> u64 {75x44
BAR_SIZE75x45
}75x46
47
fn read(&self, _offset: u64, _size: u8) -> mem::Result<u64> {3x48
Ok(PvPanicByte::all().bits() as u64)3x49
}3x50
51
fn write(&self, _offset: u64, _size: u8, val: u64) -> mem::Result<Action> {3x52
log::info!("pvpanic: {:x?}", PvPanicByte::from_bits_retain(val as u8));3x53
Ok(Action::Shutdown)3x54
}3x55
}56
57
#[derive(Debug)]58
pub struct PvPanic {59
pub config: EmulatedConfig,60
}61
62
impl PvPanic {63
pub fn new() -> Self {75x64
let header = DeviceHeader {75x65
common: CommonHeader {75x66
vendor: PVPANIC_VENDOR_ID,75x67
device: PVPANIC_DEVICE_ID,75x68
revision: 1,75x69
header_type: HeaderType::DEVICE,75x70
class: 0x08,75x71
subclass: 0x80,75x72
..Default::default()75x73
},75x74
bars: [BAR_MEM64 | BAR_PREFETCHABLE, 0, 0, 0, 0, 0],75x75
..Default::default()75x76
};75x77
let bar0 = PciBar::Mem(Arc::new(MemRegion::with_emulated(75x78
Arc::new(PvPanicBar),75x79
mem::MemRegionType::Hidden,75x80
)));75x81
let mut bars = [const { PciBar::Empty }; 6];75x82
bars[0] = bar0;75x83
let config = EmulatedConfig::new_device(header, bars, PciCapList::new());75x84
PvPanic { config }75x85
}75x86
}87
88
impl Default for PvPanic {89
fn default() -> Self {36x90
PvPanic::new()36x91
}36x92
}93
94
impl Pause for PvPanic {95
fn pause(&self) -> device::Result<()> {96
Ok(())97
}98
99
fn resume(&self) -> device::Result<()> {100
Ok(())101
}102
}103
104
impl Pci for PvPanic {105
fn name(&self) -> &str {36x106
"pvpanic"36x107
}36x108
109
fn config(&self) -> &dyn PciConfig {60x110
&self.config60x111
}60x112
113
fn reset(&self) -> pci::Result<()> {36x114
Ok(())36x115
}36x116
}117
118
#[cfg(test)]119
#[path = "pvpanic_test.rs"]120
mod tests;121