-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This branch adds support for the [pvpanic] virtual device implemented by QEMU. This device allows guests to report kernel panics to the hypervisor. In `propolis-server`, guest-reported kernel panics are handled by incrementing an Oximeter metric. The pvpanic device can be exposed to the guest either as an ISA bus I/O port device or as a PCI bus device. This branch implements the ISA bus device. I'd like to also add a PCI pvpanic device, but will implement that in a subsequent pull request. In order for the guest to detect the ISA bus pvpanic device, it's necessary to add an entry for the panic device to the ACPI DSDT table. This is the AML that QEMU adds to its DSDT when the ISA bus pvpanic device is enabled: ``` // // QEMU panic device // Device (PEVT) { Name (_HID, "QEMU0001") // _HID: Hardware ID Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings { IO (Decode16, 0x0505, // Range Minimum 0x0505, // Range Maximum 0x01, // Alignment 0x01, // Length ) }) OperationRegion (PEOR, SystemIO, 0x0505, One) Field (PEOR, ByteAcc, NoLock, Preserve) { PEPT, 8 } Name (_STA, 0x0F) // _STA: Status Method (RDPT, 0, NotSerialized) { Local0 = PEPT /* \_SB_.PCI0.S08_.PEVT.PEPT */ Return (Local0) } Method (WRPT, 1, NotSerialized) { PEPT = Arg0 } } ``` This means that in order for guests to use this device, we need to boot with an ACPI table that contains this entry. For testing purposes, I modified EDK2 OVMF to add this entry to the DSDT. In the future, though, we'll likely want Propolis to generate ACPI tables dynamically on boot based on the instance spec. The EDK2 changes I used for testing this are available [here][edk2]. To test this change, I ran `propolis-standalone` with an Alpine Linux 3.19 guest,, and the following device added to the VM config file: ```toml [dev.pvpanic] driver = "qemu-pvpanic" enable_mmio = true ``` The guest correctly detects the panic device and loads the appropriate kernel module. If I then trigger a panic in the guest using SysRq, like this: ```console $ echo 1 > /proc/sys/kernel/sysrq $ echo c > /proc/sysrq-trigger ``` The guest crashes, and `propolis-standalone` logs: ``` dev: pvpanic Jan 11 18:14:13.494 DEBG guest kernel panic, guest_handled: false, host_handled: true ``` Closes #592 [pvpanic]: https://www.qemu.org/docs/master/specs/pvpanic.html [edk2]: oxidecomputer/edk2@6ca196f
- Loading branch information
Showing
13 changed files
with
377 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
use super::InstanceUuid; | ||
use oximeter::{ | ||
types::{Cumulative, Sample}, | ||
Metric, MetricsError, Producer, | ||
}; | ||
use propolis::hw::qemu::pvpanic; | ||
use std::sync::Arc; | ||
use uuid::Uuid; | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct PvpanicProducer { | ||
/// The name to use as the Oximeter target, i.e. the identifier of the | ||
/// source of these metrics. | ||
stat_name: InstanceUuid, | ||
|
||
/// Kernel panic counts for the relevant instance. | ||
host_handled_panics: PvPanicHostHandled, | ||
guest_handled_panics: PvPanicGuestHandled, | ||
|
||
pvpanic: Arc<pvpanic::QemuPvpanic>, | ||
} | ||
|
||
/// An Oximeter `Metric` that specifies the number of times an instance's guest | ||
/// reported a guest-handled kernel panic using the QEMU `pvpanic` device. | ||
#[derive(Debug, Default, Copy, Clone, Metric)] | ||
struct PvPanicGuestHandled { | ||
/// The number of times this instance's guest handled a kernel panic. | ||
#[datum] | ||
pub count: Cumulative<i64>, | ||
} | ||
|
||
/// An Oximeter `Metric` that specifies the number of times an instance's guest | ||
/// reported a host-handled kernel panic using the QEMU `pvpanic` device. | ||
#[derive(Debug, Default, Copy, Clone, Metric)] | ||
struct PvPanicHostHandled { | ||
/// The number of times this instance's reported a host-handled kernel panic. | ||
#[datum] | ||
pub count: Cumulative<i64>, | ||
} | ||
|
||
impl PvpanicProducer { | ||
pub fn new(id: Uuid, pvpanic: Arc<pvpanic::QemuPvpanic>) -> Self { | ||
PvpanicProducer { | ||
stat_name: InstanceUuid { uuid: id }, | ||
host_handled_panics: Default::default(), | ||
guest_handled_panics: Default::default(), | ||
pvpanic, | ||
} | ||
} | ||
} | ||
|
||
impl Producer for PvpanicProducer { | ||
fn produce( | ||
&mut self, | ||
) -> Result<Box<dyn Iterator<Item = Sample> + 'static>, MetricsError> { | ||
let pvpanic::PanicCounts { guest_handled, host_handled } = | ||
self.pvpanic.panic_counts(); | ||
|
||
self.host_handled_panics.datum_mut().set(host_handled as i64); | ||
self.guest_handled_panics.datum_mut().set(guest_handled as i64); | ||
|
||
let data = vec![ | ||
Sample::new(&self.stat_name, &self.guest_handled_panics)?, | ||
Sample::new(&self.stat_name, &self.host_handled_panics)?, | ||
]; | ||
|
||
Ok(Box::new(data.into_iter())) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ | |
|
||
pub mod debug; | ||
pub mod fwcfg; | ||
pub mod pvpanic; | ||
pub mod ramfb; |
Oops, something went wrong.