diff --git a/bin/propolis-standalone/README.md b/bin/propolis-standalone/README.md index 663daf30f..e2b846d5d 100644 --- a/bin/propolis-standalone/README.md +++ b/bin/propolis-standalone/README.md @@ -61,7 +61,7 @@ are some options to get up-and-running quickly: ### Guest bootrom The current recommended and tested guest bootrom is available -[here](https://buildomat.eng.oxide.computer/public/file/oxidecomputer/edk2/image_debug/907a5fd1763ce5ddd74001261e5b52cd200a25f9/OVMF_CODE.fd). +[here](https://buildomat.eng.oxide.computer/public/file/oxidecomputer/edk2/image_debug/bf64f45b1a58e69d126a3c6ca1e4512c88668132/OVMF_CODE.fd). Other UEFI firmware images built from the [Open Virtual Machine Firmware project](https://github.com/tianocore/tianocore.github.io/wiki/OVMF) may also diff --git a/lib/propolis/src/hw/nvme/admin.rs b/lib/propolis/src/hw/nvme/admin.rs index df8746a62..085b770e8 100644 --- a/lib/propolis/src/hw/nvme/admin.rs +++ b/lib/propolis/src/hw/nvme/admin.rs @@ -403,6 +403,19 @@ impl NvmeCtrl { ) } + cmds::FeatureIdent::OxideDeviceFeatures => { + if cmd.cdw11 != 0 { + // We don't currently accept any parameters for this feature + cmds::Completion::generic_err(STS_INVAL_FIELD) + } else { + cmds::Completion::success_val( + cmds::OxideDeviceFeatures(0) + .with_read_only(self.read_only) + .0, + ) + } + } + cmds::FeatureIdent::Reserved | cmds::FeatureIdent::LbaRangeType | cmds::FeatureIdent::SoftwareProgressMarker @@ -457,6 +470,7 @@ impl NvmeCtrl { | cmds::FeatureIdent::WriteAtomicity | cmds::FeatureIdent::AsynchronousEventConfiguration | cmds::FeatureIdent::SoftwareProgressMarker + | cmds::FeatureIdent::OxideDeviceFeatures | cmds::FeatureIdent::Vendor(_) => { cmds::Completion::generic_err(STS_INVAL_FIELD).dnr() } diff --git a/lib/propolis/src/hw/nvme/bits.rs b/lib/propolis/src/hw/nvme/bits.rs index 130bb3013..c227ae1f4 100644 --- a/lib/propolis/src/hw/nvme/bits.rs +++ b/lib/propolis/src/hw/nvme/bits.rs @@ -699,6 +699,15 @@ pub const FEAT_ID_WRITE_ATOMIC: u8 = 0x0A; /// See NVMe 1.0e Section 5.12.1.11 Asynchronous Event Configuration (Feature Identifier 0Bh) pub const FEAT_ID_ASYNC_EVENT_CFG: u8 = 0x0B; +/// Oxide-specific feature. +/// +/// Provides device-specific features beyond the standard NVMe capabilities as +/// a single Dword result: +/// Bit 0 [ReadOnly] - If set, the device will complete all writes with +/// STS_WRITE_READ_ONLY_RANGE. +/// Bits 31-1 - Reserved. +pub const FEAT_ID_OXIDE_DEVICE_FEATURES: u8 = 0xF0; + // Identify CNS values /// Identify - Namespace Structure diff --git a/lib/propolis/src/hw/nvme/cmds.rs b/lib/propolis/src/hw/nvme/cmds.rs index 88438ee3b..b11234aea 100644 --- a/lib/propolis/src/hw/nvme/cmds.rs +++ b/lib/propolis/src/hw/nvme/cmds.rs @@ -452,7 +452,12 @@ pub enum FeatureIdent { /// This feature is persistent across power states. /// See NVMe 1.0e Section 7.6.1.1 Software Progress Marker SoftwareProgressMarker, - /// Vendor specific feature. + + // Vendor specific features. + /// Oxide-specific feature - returns relevant device features. + OxideDeviceFeatures, + + /// All other vendor specific features. Vendor(#[allow(dead_code)] u8), } @@ -476,6 +481,7 @@ impl From for FeatureIdent { 0xC..=0x7F => Reserved, 0x80 => SoftwareProgressMarker, 0x81..=0xBF => Reserved, + FEAT_ID_OXIDE_DEVICE_FEATURES => OxideDeviceFeatures, 0xC0..=0xFF => Vendor(fid), } } @@ -651,6 +657,17 @@ impl From for u32 { } } +bitstruct! { + pub struct OxideDeviceFeatures(pub u32) { + /// Indicates the device is read-only and will complete all attempted + /// writes with `STS_WRITE_READ_ONLY_RANGE`. + pub read_only: bool = 0; + + /// Reserved + reserved: u32 = 1..32; + } +} + /// A parsed NVM Command #[allow(dead_code)] #[derive(Debug)] diff --git a/lib/propolis/src/hw/nvme/mod.rs b/lib/propolis/src/hw/nvme/mod.rs index 78d0b1ffa..9a3bf657d 100644 --- a/lib/propolis/src/hw/nvme/mod.rs +++ b/lib/propolis/src/hw/nvme/mod.rs @@ -207,6 +207,8 @@ struct NvmeCtrl { /// The Identify structure returned for Identify namespace commands ns_ident: IdentifyNamespace, + + read_only: bool, } impl NvmeCtrl { @@ -566,6 +568,8 @@ impl NvmeCtrl { .iter() .filter_map(Option::as_ref) .for_each(|sq| sq.update_params(params)); + + self.read_only = info.read_only; } /// Get Memory Page Size (MPS), expressed in bytes @@ -899,6 +903,7 @@ impl PciNvme { sqs: Default::default(), ctrl_ident, ns_ident, + read_only: false, }; let pci_state = builder diff --git a/packaging/package-manifest.toml b/packaging/package-manifest.toml index d33103f4c..809bf6bf6 100644 --- a/packaging/package-manifest.toml +++ b/packaging/package-manifest.toml @@ -14,6 +14,6 @@ output.type = "zone" [[package.propolis-server.source.buildomat_blobs]] repo = "edk2" series = "image_debug" -commit = "907a5fd1763ce5ddd74001261e5b52cd200a25f9" +commit = "bf64f45b1a58e69d126a3c6ca1e4512c88668132" artifact = "OVMF_CODE.fd" -sha256 = "ff12d5cb021e34447b44301f70434e861b07d2779c16abe2f2efef49ff02fffb" +sha256 = "740187046a7267d0de72d3455070333547dbc0ea023531471fb2b2a61effa448" diff --git a/phd-tests/artifacts.toml b/phd-tests/artifacts.toml index 4b61634e2..0a0789bb9 100644 --- a/phd-tests/artifacts.toml +++ b/phd-tests/artifacts.toml @@ -13,5 +13,5 @@ kind = "bootrom" [artifacts.ovmf.source.buildomat] repo = "oxidecomputer/edk2" series = "image_debug" -commit = "907a5fd1763ce5ddd74001261e5b52cd200a25f9" -sha256 = "ff12d5cb021e34447b44301f70434e861b07d2779c16abe2f2efef49ff02fffb" +commit = "bf64f45b1a58e69d126a3c6ca1e4512c88668132" +sha256 = "740187046a7267d0de72d3455070333547dbc0ea023531471fb2b2a61effa448"