Alioth Code Coverage

pvpanic.rs88.24%

1// Copyright 2024 Google LLC
2//
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 at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// 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 and
13// limitations under the License.
14
15use std::sync::Arc;
16
17use crate::bitflags;
18use crate::device::{self, Pause};
19use crate::mem::emulated::{Action, Mmio};
20use crate::mem::{self, MemRegion};
21use crate::pci::cap::PciCapList;
22use crate::pci::config::{
23 BAR_MEM64, BAR_PREFETCHABLE, CommonHeader, DeviceHeader, EmulatedConfig, HeaderType, PciConfig,
24};
25use crate::pci::{self, Pci, PciBar};
26
27bitflags! {
28 struct PvPanicByte(u8) {
29 PANICKED = 1 << 0;
30 CRASH_LOADED = 1 << 1;
31 }
32}
33
34pub const PVPANIC_VENDOR_ID: u16 = 0x1b36;
35pub const PVPANIC_DEVICE_ID: u16 = 0x0011;
36
37const BAR_SIZE: u64 = 0x1000;
38
39#[derive(Debug)]
40struct PvPanicBar;
41
42impl Mmio for PvPanicBar {
43 fn size(&self) -> u64 {75x
44 BAR_SIZE75x
45 }75x
46
47 fn read(&self, _offset: u64, _size: u8) -> mem::Result<u64> {3x
48 Ok(PvPanicByte::all().bits() as u64)3x
49 }3x
50
51 fn write(&self, _offset: u64, _size: u8, val: u64) -> mem::Result<Action> {3x
52 log::info!("pvpanic: {:x?}", PvPanicByte::from_bits_retain(val as u8));3x
53 Ok(Action::Shutdown)3x
54 }3x
55}
56
57#[derive(Debug)]
58pub struct PvPanic {
59 pub config: EmulatedConfig,
60}
61
62impl PvPanic {
63 pub fn new() -> Self {75x
64 let header = DeviceHeader {75x
65 common: CommonHeader {75x
66 vendor: PVPANIC_VENDOR_ID,75x
67 device: PVPANIC_DEVICE_ID,75x
68 revision: 1,75x
69 header_type: HeaderType::DEVICE,75x
70 class: 0x08,75x
71 subclass: 0x80,75x
72 ..Default::default()75x
73 },75x
74 bars: [BAR_MEM64 | BAR_PREFETCHABLE, 0, 0, 0, 0, 0],75x
75 ..Default::default()75x
76 };75x
77 let bar0 = PciBar::Mem(Arc::new(MemRegion::with_emulated(75x
78 Arc::new(PvPanicBar),75x
79 mem::MemRegionType::Hidden,75x
80 )));75x
81 let mut bars = [const { PciBar::Empty }; 6];75x
82 bars[0] = bar0;75x
83 let config = EmulatedConfig::new_device(header, bars, PciCapList::new());75x
84 PvPanic { config }75x
85 }75x
86}
87
88impl Default for PvPanic {
89 fn default() -> Self {36x
90 PvPanic::new()36x
91 }36x
92}
93
94impl Pause for PvPanic {
95 fn pause(&self) -> device::Result<()> {
96 Ok(())
97 }
98
99 fn resume(&self) -> device::Result<()> {
100 Ok(())
101 }
102}
103
104impl Pci for PvPanic {
105 fn name(&self) -> &str {36x
106 "pvpanic"36x
107 }36x
108
109 fn config(&self) -> &dyn PciConfig {60x
110 &self.config60x
111 }60x
112
113 fn reset(&self) -> pci::Result<()> {36x
114 Ok(())36x
115 }36x
116}
117
118#[cfg(test)]
119#[path = "pvpanic_test.rs"]
120mod tests;
121