xref: /aosp_15_r20/external/crosvm/devices/src/pci/pvpanic.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! pvpanic is a simulated device, through which a guest panic event is sent to a VMM.
6*bb4ee6a4SAndroid Build Coastguard Worker //! This was initially developed for qemu with linux in-tree drivers and opensource
7*bb4ee6a4SAndroid Build Coastguard Worker //! driver for windows also exist now.
8*bb4ee6a4SAndroid Build Coastguard Worker //! <https://fossies.org/linux/qemu/docs/specs/pvpanic.txt>
9*bb4ee6a4SAndroid Build Coastguard Worker //!
10*bb4ee6a4SAndroid Build Coastguard Worker //! This implementation emulates pci interface for pvpanic virtual device.
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker // TODO(218575411): Support pvpanic on windows crosvm.
13*bb4ee6a4SAndroid Build Coastguard Worker #![cfg_attr(windows, allow(dead_code))]
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
20*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::SharedMemory;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::VmEventType;
23*bb4ee6a4SAndroid Build Coastguard Worker use resources::Alloc;
24*bb4ee6a4SAndroid Build Coastguard Worker use resources::AllocOptions;
25*bb4ee6a4SAndroid Build Coastguard Worker use resources::SystemAllocator;
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciBarConfiguration;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciBarPrefetchable;
29*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciBarRegionType;
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciClassCode;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciConfiguration;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciHeaderType;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_configuration::PciOtherSubclass;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device;
35*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::BarRange;
36*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::PciDevice;
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::pci_device::Result;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciAddress;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciBarIndex;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PciDeviceError;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::PCI_VENDOR_ID_REDHAT;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable;
43*bb4ee6a4SAndroid Build Coastguard Worker 
44*bb4ee6a4SAndroid Build Coastguard Worker const PCI_DEVICE_ID_REDHAT_PVPANIC: u16 = 0x0011;
45*bb4ee6a4SAndroid Build Coastguard Worker const PCI_PVPANIC_REVISION_ID: u8 = 1;
46*bb4ee6a4SAndroid Build Coastguard Worker 
47*bb4ee6a4SAndroid Build Coastguard Worker const PVPANIC_BAR_INDEX: PciBarIndex = 0;
48*bb4ee6a4SAndroid Build Coastguard Worker const PVPANIC_REG_SIZE: u64 = 0x10;
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker // Guest panicked
51*bb4ee6a4SAndroid Build Coastguard Worker pub const PVPANIC_PANICKED: u8 = 1 << 0;
52*bb4ee6a4SAndroid Build Coastguard Worker // Guest kexeced crash kernel
53*bb4ee6a4SAndroid Build Coastguard Worker pub const PVPANIC_CRASH_LOADED: u8 = 1 << 1;
54*bb4ee6a4SAndroid Build Coastguard Worker 
55*bb4ee6a4SAndroid Build Coastguard Worker const PVPANIC_CAPABILITIES: u8 = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker #[repr(u8)]
58*bb4ee6a4SAndroid Build Coastguard Worker #[derive(PartialEq, Eq)]
59*bb4ee6a4SAndroid Build Coastguard Worker pub enum PvPanicCode {
60*bb4ee6a4SAndroid Build Coastguard Worker     Panicked = PVPANIC_PANICKED,
61*bb4ee6a4SAndroid Build Coastguard Worker     CrashLoaded = PVPANIC_CRASH_LOADED,
62*bb4ee6a4SAndroid Build Coastguard Worker     Unknown = 0xFF,
63*bb4ee6a4SAndroid Build Coastguard Worker }
64*bb4ee6a4SAndroid Build Coastguard Worker 
65*bb4ee6a4SAndroid Build Coastguard Worker impl PvPanicCode {
from_u8(val: u8) -> PvPanicCode66*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_u8(val: u8) -> PvPanicCode {
67*bb4ee6a4SAndroid Build Coastguard Worker         match val {
68*bb4ee6a4SAndroid Build Coastguard Worker             PVPANIC_PANICKED => PvPanicCode::Panicked,
69*bb4ee6a4SAndroid Build Coastguard Worker             PVPANIC_CRASH_LOADED => PvPanicCode::CrashLoaded,
70*bb4ee6a4SAndroid Build Coastguard Worker             _ => PvPanicCode::Unknown,
71*bb4ee6a4SAndroid Build Coastguard Worker         }
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker }
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker impl fmt::Display for PvPanicCode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result76*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77*bb4ee6a4SAndroid Build Coastguard Worker         match self {
78*bb4ee6a4SAndroid Build Coastguard Worker             PvPanicCode::Panicked => write!(f, "Guest panicked"),
79*bb4ee6a4SAndroid Build Coastguard Worker             PvPanicCode::CrashLoaded => write!(f, "Guest panicked and crash kernel loaded"),
80*bb4ee6a4SAndroid Build Coastguard Worker             PvPanicCode::Unknown => write!(f, "Guest panicked with unknown code"),
81*bb4ee6a4SAndroid Build Coastguard Worker         }
82*bb4ee6a4SAndroid Build Coastguard Worker     }
83*bb4ee6a4SAndroid Build Coastguard Worker }
84*bb4ee6a4SAndroid Build Coastguard Worker 
85*bb4ee6a4SAndroid Build Coastguard Worker pub struct PvPanicPciDevice {
86*bb4ee6a4SAndroid Build Coastguard Worker     pci_address: Option<PciAddress>,
87*bb4ee6a4SAndroid Build Coastguard Worker     config_regs: PciConfiguration,
88*bb4ee6a4SAndroid Build Coastguard Worker     evt_wrtube: SendTube,
89*bb4ee6a4SAndroid Build Coastguard Worker }
90*bb4ee6a4SAndroid Build Coastguard Worker 
91*bb4ee6a4SAndroid Build Coastguard Worker impl PvPanicPciDevice {
new(evt_wrtube: SendTube) -> PvPanicPciDevice92*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(evt_wrtube: SendTube) -> PvPanicPciDevice {
93*bb4ee6a4SAndroid Build Coastguard Worker         let config_regs = PciConfiguration::new(
94*bb4ee6a4SAndroid Build Coastguard Worker             PCI_VENDOR_ID_REDHAT,
95*bb4ee6a4SAndroid Build Coastguard Worker             PCI_DEVICE_ID_REDHAT_PVPANIC,
96*bb4ee6a4SAndroid Build Coastguard Worker             PciClassCode::Other,
97*bb4ee6a4SAndroid Build Coastguard Worker             &PciOtherSubclass::Other,
98*bb4ee6a4SAndroid Build Coastguard Worker             None,
99*bb4ee6a4SAndroid Build Coastguard Worker             PciHeaderType::Device,
100*bb4ee6a4SAndroid Build Coastguard Worker             0xFF,
101*bb4ee6a4SAndroid Build Coastguard Worker             0xFF,
102*bb4ee6a4SAndroid Build Coastguard Worker             PCI_PVPANIC_REVISION_ID,
103*bb4ee6a4SAndroid Build Coastguard Worker         );
104*bb4ee6a4SAndroid Build Coastguard Worker 
105*bb4ee6a4SAndroid Build Coastguard Worker         Self {
106*bb4ee6a4SAndroid Build Coastguard Worker             pci_address: None,
107*bb4ee6a4SAndroid Build Coastguard Worker             config_regs,
108*bb4ee6a4SAndroid Build Coastguard Worker             evt_wrtube,
109*bb4ee6a4SAndroid Build Coastguard Worker         }
110*bb4ee6a4SAndroid Build Coastguard Worker     }
111*bb4ee6a4SAndroid Build Coastguard Worker }
112*bb4ee6a4SAndroid Build Coastguard Worker 
113*bb4ee6a4SAndroid Build Coastguard Worker impl PciDevice for PvPanicPciDevice {
debug_label(&self) -> String114*bb4ee6a4SAndroid Build Coastguard Worker     fn debug_label(&self) -> String {
115*bb4ee6a4SAndroid Build Coastguard Worker         "PvPanic".to_owned()
116*bb4ee6a4SAndroid Build Coastguard Worker     }
117*bb4ee6a4SAndroid Build Coastguard Worker 
allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress>118*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_address(&mut self, resources: &mut SystemAllocator) -> Result<PciAddress> {
119*bb4ee6a4SAndroid Build Coastguard Worker         if self.pci_address.is_none() {
120*bb4ee6a4SAndroid Build Coastguard Worker             self.pci_address = match resources.allocate_pci(0, self.debug_label()) {
121*bb4ee6a4SAndroid Build Coastguard Worker                 Some(Alloc::PciBar {
122*bb4ee6a4SAndroid Build Coastguard Worker                     bus,
123*bb4ee6a4SAndroid Build Coastguard Worker                     dev,
124*bb4ee6a4SAndroid Build Coastguard Worker                     func,
125*bb4ee6a4SAndroid Build Coastguard Worker                     bar: _,
126*bb4ee6a4SAndroid Build Coastguard Worker                 }) => Some(PciAddress { bus, dev, func }),
127*bb4ee6a4SAndroid Build Coastguard Worker                 _ => None,
128*bb4ee6a4SAndroid Build Coastguard Worker             }
129*bb4ee6a4SAndroid Build Coastguard Worker         }
130*bb4ee6a4SAndroid Build Coastguard Worker         self.pci_address.ok_or(PciDeviceError::PciAllocationFailed)
131*bb4ee6a4SAndroid Build Coastguard Worker     }
132*bb4ee6a4SAndroid Build Coastguard Worker 
allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>>133*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_io_bars(&mut self, resources: &mut SystemAllocator) -> Result<Vec<BarRange>> {
134*bb4ee6a4SAndroid Build Coastguard Worker         let address = self
135*bb4ee6a4SAndroid Build Coastguard Worker             .pci_address
136*bb4ee6a4SAndroid Build Coastguard Worker             .expect("allocate_address must be called prior to allocate_io_bars");
137*bb4ee6a4SAndroid Build Coastguard Worker         let mut ranges: Vec<BarRange> = Vec::new();
138*bb4ee6a4SAndroid Build Coastguard Worker         let pvpanic_reg_addr = resources
139*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_mmio(
140*bb4ee6a4SAndroid Build Coastguard Worker                 PVPANIC_REG_SIZE,
141*bb4ee6a4SAndroid Build Coastguard Worker                 Alloc::PciBar {
142*bb4ee6a4SAndroid Build Coastguard Worker                     bus: address.bus,
143*bb4ee6a4SAndroid Build Coastguard Worker                     dev: address.dev,
144*bb4ee6a4SAndroid Build Coastguard Worker                     func: address.func,
145*bb4ee6a4SAndroid Build Coastguard Worker                     bar: PVPANIC_BAR_INDEX as u8,
146*bb4ee6a4SAndroid Build Coastguard Worker                 },
147*bb4ee6a4SAndroid Build Coastguard Worker                 "pvpanic_reg".to_string(),
148*bb4ee6a4SAndroid Build Coastguard Worker                 AllocOptions::new()
149*bb4ee6a4SAndroid Build Coastguard Worker                     .max_address(u32::MAX.into())
150*bb4ee6a4SAndroid Build Coastguard Worker                     .align(PVPANIC_REG_SIZE),
151*bb4ee6a4SAndroid Build Coastguard Worker             )
152*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| pci_device::Error::IoAllocationFailed(PVPANIC_REG_SIZE, e))?;
153*bb4ee6a4SAndroid Build Coastguard Worker         let pvpanic_config = PciBarConfiguration::new(
154*bb4ee6a4SAndroid Build Coastguard Worker             PVPANIC_BAR_INDEX,
155*bb4ee6a4SAndroid Build Coastguard Worker             PVPANIC_REG_SIZE,
156*bb4ee6a4SAndroid Build Coastguard Worker             PciBarRegionType::Memory32BitRegion,
157*bb4ee6a4SAndroid Build Coastguard Worker             PciBarPrefetchable::NotPrefetchable,
158*bb4ee6a4SAndroid Build Coastguard Worker         )
159*bb4ee6a4SAndroid Build Coastguard Worker         .set_address(pvpanic_reg_addr);
160*bb4ee6a4SAndroid Build Coastguard Worker         self.config_regs
161*bb4ee6a4SAndroid Build Coastguard Worker             .add_pci_bar(pvpanic_config)
162*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| pci_device::Error::IoRegistrationFailed(pvpanic_reg_addr, e))?;
163*bb4ee6a4SAndroid Build Coastguard Worker         ranges.push(BarRange {
164*bb4ee6a4SAndroid Build Coastguard Worker             addr: pvpanic_reg_addr,
165*bb4ee6a4SAndroid Build Coastguard Worker             size: PVPANIC_REG_SIZE,
166*bb4ee6a4SAndroid Build Coastguard Worker             prefetchable: false,
167*bb4ee6a4SAndroid Build Coastguard Worker         });
168*bb4ee6a4SAndroid Build Coastguard Worker 
169*bb4ee6a4SAndroid Build Coastguard Worker         Ok(ranges)
170*bb4ee6a4SAndroid Build Coastguard Worker     }
171*bb4ee6a4SAndroid Build Coastguard Worker 
keep_rds(&self) -> Vec<RawDescriptor>172*bb4ee6a4SAndroid Build Coastguard Worker     fn keep_rds(&self) -> Vec<RawDescriptor> {
173*bb4ee6a4SAndroid Build Coastguard Worker         Vec::new()
174*bb4ee6a4SAndroid Build Coastguard Worker     }
175*bb4ee6a4SAndroid Build Coastguard Worker 
get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>176*bb4ee6a4SAndroid Build Coastguard Worker     fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> {
177*bb4ee6a4SAndroid Build Coastguard Worker         self.config_regs.get_bar_configuration(bar_num)
178*bb4ee6a4SAndroid Build Coastguard Worker     }
179*bb4ee6a4SAndroid Build Coastguard Worker 
read_config_register(&self, reg_idx: usize) -> u32180*bb4ee6a4SAndroid Build Coastguard Worker     fn read_config_register(&self, reg_idx: usize) -> u32 {
181*bb4ee6a4SAndroid Build Coastguard Worker         self.config_regs.read_reg(reg_idx)
182*bb4ee6a4SAndroid Build Coastguard Worker     }
183*bb4ee6a4SAndroid Build Coastguard Worker 
write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8])184*bb4ee6a4SAndroid Build Coastguard Worker     fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) {
185*bb4ee6a4SAndroid Build Coastguard Worker         self.config_regs.write_reg(reg_idx, offset, data);
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker 
setup_pci_config_mapping( &mut self, shmem: &SharedMemory, base: usize, len: usize, ) -> Result<bool>188*bb4ee6a4SAndroid Build Coastguard Worker     fn setup_pci_config_mapping(
189*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
190*bb4ee6a4SAndroid Build Coastguard Worker         shmem: &SharedMemory,
191*bb4ee6a4SAndroid Build Coastguard Worker         base: usize,
192*bb4ee6a4SAndroid Build Coastguard Worker         len: usize,
193*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<bool> {
194*bb4ee6a4SAndroid Build Coastguard Worker         self.config_regs
195*bb4ee6a4SAndroid Build Coastguard Worker             .setup_mapping(shmem, base, len)
196*bb4ee6a4SAndroid Build Coastguard Worker             .map(|_| true)
197*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(PciDeviceError::MmioSetup)
198*bb4ee6a4SAndroid Build Coastguard Worker     }
199*bb4ee6a4SAndroid Build Coastguard Worker 
read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8])200*bb4ee6a4SAndroid Build Coastguard Worker     fn read_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &mut [u8]) {
201*bb4ee6a4SAndroid Build Coastguard Worker         data[0] = if bar_index == PVPANIC_BAR_INDEX && offset == 0 && data.len() == 1 {
202*bb4ee6a4SAndroid Build Coastguard Worker             PVPANIC_CAPABILITIES
203*bb4ee6a4SAndroid Build Coastguard Worker         } else {
204*bb4ee6a4SAndroid Build Coastguard Worker             0
205*bb4ee6a4SAndroid Build Coastguard Worker         };
206*bb4ee6a4SAndroid Build Coastguard Worker     }
207*bb4ee6a4SAndroid Build Coastguard Worker 
write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8])208*bb4ee6a4SAndroid Build Coastguard Worker     fn write_bar(&mut self, bar_index: PciBarIndex, offset: u64, data: &[u8]) {
209*bb4ee6a4SAndroid Build Coastguard Worker         if bar_index != PVPANIC_BAR_INDEX || offset != 0 || data.len() != 1 {
210*bb4ee6a4SAndroid Build Coastguard Worker             return;
211*bb4ee6a4SAndroid Build Coastguard Worker         }
212*bb4ee6a4SAndroid Build Coastguard Worker 
213*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self
214*bb4ee6a4SAndroid Build Coastguard Worker             .evt_wrtube
215*bb4ee6a4SAndroid Build Coastguard Worker             .send::<VmEventType>(&VmEventType::Panic(data[0]))
216*bb4ee6a4SAndroid Build Coastguard Worker         {
217*bb4ee6a4SAndroid Build Coastguard Worker             error!("Failed to write to the event tube: {}", e);
218*bb4ee6a4SAndroid Build Coastguard Worker         }
219*bb4ee6a4SAndroid Build Coastguard Worker     }
220*bb4ee6a4SAndroid Build Coastguard Worker }
221*bb4ee6a4SAndroid Build Coastguard Worker 
222*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for PvPanicPciDevice {
snapshot(&mut self) -> anyhow::Result<serde_json::Value>223*bb4ee6a4SAndroid Build Coastguard Worker     fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
224*bb4ee6a4SAndroid Build Coastguard Worker         self.config_regs
225*bb4ee6a4SAndroid Build Coastguard Worker             .snapshot()
226*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to serialize PvPanicPciDevice")
227*bb4ee6a4SAndroid Build Coastguard Worker     }
228*bb4ee6a4SAndroid Build Coastguard Worker 
restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>229*bb4ee6a4SAndroid Build Coastguard Worker     fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
230*bb4ee6a4SAndroid Build Coastguard Worker         self.config_regs
231*bb4ee6a4SAndroid Build Coastguard Worker             .restore(data)
232*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed to deserialize PvPanicPciDevice")
233*bb4ee6a4SAndroid Build Coastguard Worker     }
234*bb4ee6a4SAndroid Build Coastguard Worker 
sleep(&mut self) -> anyhow::Result<()>235*bb4ee6a4SAndroid Build Coastguard Worker     fn sleep(&mut self) -> anyhow::Result<()> {
236*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
237*bb4ee6a4SAndroid Build Coastguard Worker     }
238*bb4ee6a4SAndroid Build Coastguard Worker 
wake(&mut self) -> anyhow::Result<()>239*bb4ee6a4SAndroid Build Coastguard Worker     fn wake(&mut self) -> anyhow::Result<()> {
240*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
241*bb4ee6a4SAndroid Build Coastguard Worker     }
242*bb4ee6a4SAndroid Build Coastguard Worker }
243*bb4ee6a4SAndroid Build Coastguard Worker 
244*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
245*bb4ee6a4SAndroid Build Coastguard Worker mod test {
246*bb4ee6a4SAndroid Build Coastguard Worker     use base::Tube;
247*bb4ee6a4SAndroid Build Coastguard Worker     use resources::AddressRange;
248*bb4ee6a4SAndroid Build Coastguard Worker     use resources::SystemAllocator;
249*bb4ee6a4SAndroid Build Coastguard Worker     use resources::SystemAllocatorConfig;
250*bb4ee6a4SAndroid Build Coastguard Worker 
251*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
252*bb4ee6a4SAndroid Build Coastguard Worker 
253*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
pvpanic_read_write()254*bb4ee6a4SAndroid Build Coastguard Worker     fn pvpanic_read_write() {
255*bb4ee6a4SAndroid Build Coastguard Worker         let mut allocator = SystemAllocator::new(
256*bb4ee6a4SAndroid Build Coastguard Worker             SystemAllocatorConfig {
257*bb4ee6a4SAndroid Build Coastguard Worker                 io: Some(AddressRange {
258*bb4ee6a4SAndroid Build Coastguard Worker                     start: 0x1000,
259*bb4ee6a4SAndroid Build Coastguard Worker                     end: 0xffff,
260*bb4ee6a4SAndroid Build Coastguard Worker                 }),
261*bb4ee6a4SAndroid Build Coastguard Worker                 low_mmio: AddressRange {
262*bb4ee6a4SAndroid Build Coastguard Worker                     start: 0x2000_0000,
263*bb4ee6a4SAndroid Build Coastguard Worker                     end: 0x2fffffff,
264*bb4ee6a4SAndroid Build Coastguard Worker                 },
265*bb4ee6a4SAndroid Build Coastguard Worker                 high_mmio: AddressRange {
266*bb4ee6a4SAndroid Build Coastguard Worker                     start: 0x1_0000_0000,
267*bb4ee6a4SAndroid Build Coastguard Worker                     end: 0x1_0fff_ffff,
268*bb4ee6a4SAndroid Build Coastguard Worker                 },
269*bb4ee6a4SAndroid Build Coastguard Worker                 platform_mmio: None,
270*bb4ee6a4SAndroid Build Coastguard Worker                 first_irq: 5,
271*bb4ee6a4SAndroid Build Coastguard Worker             },
272*bb4ee6a4SAndroid Build Coastguard Worker             None,
273*bb4ee6a4SAndroid Build Coastguard Worker             &[],
274*bb4ee6a4SAndroid Build Coastguard Worker         )
275*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
276*bb4ee6a4SAndroid Build Coastguard Worker 
277*bb4ee6a4SAndroid Build Coastguard Worker         let (evt_wrtube, evt_rdtube) = Tube::directional_pair().unwrap();
278*bb4ee6a4SAndroid Build Coastguard Worker         let mut device = PvPanicPciDevice::new(evt_wrtube);
279*bb4ee6a4SAndroid Build Coastguard Worker 
280*bb4ee6a4SAndroid Build Coastguard Worker         assert!(device.allocate_address(&mut allocator).is_ok());
281*bb4ee6a4SAndroid Build Coastguard Worker         assert!(device.allocate_io_bars(&mut allocator).is_ok());
282*bb4ee6a4SAndroid Build Coastguard Worker 
283*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 1] = [0; 1];
284*bb4ee6a4SAndroid Build Coastguard Worker 
285*bb4ee6a4SAndroid Build Coastguard Worker         // Read from an invalid addr
286*bb4ee6a4SAndroid Build Coastguard Worker         device.read_bar(0, 1, &mut data);
287*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], 0);
288*bb4ee6a4SAndroid Build Coastguard Worker 
289*bb4ee6a4SAndroid Build Coastguard Worker         // Read from the valid addr
290*bb4ee6a4SAndroid Build Coastguard Worker         device.read_bar(0, 0, &mut data);
291*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data[0], PVPANIC_CAPABILITIES);
292*bb4ee6a4SAndroid Build Coastguard Worker 
293*bb4ee6a4SAndroid Build Coastguard Worker         // Write to the valid addr.
294*bb4ee6a4SAndroid Build Coastguard Worker         data[0] = PVPANIC_CRASH_LOADED;
295*bb4ee6a4SAndroid Build Coastguard Worker         device.write_bar(0, 0, &data);
296*bb4ee6a4SAndroid Build Coastguard Worker 
297*bb4ee6a4SAndroid Build Coastguard Worker         // Verify the event
298*bb4ee6a4SAndroid Build Coastguard Worker         let val = evt_rdtube.recv::<VmEventType>().unwrap();
299*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(val, VmEventType::Panic(PVPANIC_CRASH_LOADED));
300*bb4ee6a4SAndroid Build Coastguard Worker     }
301*bb4ee6a4SAndroid Build Coastguard Worker }
302