Add the first user of NVKV encode/decode which is the request and response for GSP init. Later patches will support GMCAPI in `Cmdq` and use these messages.
Signed-off-by: Eliot Courtney <[email protected]> --- drivers/gpu/nova-core/gsp/fw/commands.rs | 157 ++++++++++++++++++++++++++++++- drivers/gpu/nova-core/gsp/nvkv.rs | 2 - drivers/gpu/nova-core/gsp/nvkv/decode.rs | 1 - drivers/gpu/nova-core/gsp/nvkv/encode.rs | 2 +- 4 files changed, 157 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/nova-core/gsp/fw/commands.rs b/drivers/gpu/nova-core/gsp/fw/commands.rs index 567c56fbbfe3..88111aec3ddb 100644 --- a/drivers/gpu/nova-core/gsp/fw/commands.rs +++ b/drivers/gpu/nova-core/gsp/fw/commands.rs @@ -4,6 +4,8 @@ use core::ops::Range; use kernel::{ + alloc::ArrayVec, + bitfield, device, pci, prelude::*, @@ -15,7 +17,19 @@ use crate::{ gpu::Chipset, - gsp::GSP_PAGE_SIZE, + gsp::{ + nvkv::{ + nvkv_decode, + nvkv_encode, + Accumulated, + Encodable, + Encoder, + Key, + Required, + TruncatingArray, // + }, + GSP_PAGE_SIZE, // + }, num::IntoSafeCast, // }; @@ -245,3 +259,144 @@ unsafe impl AsBytes for UnloadingGuestDriver {} // SAFETY: This struct only contains integer types for which all bit patterns // are valid. unsafe impl FromBytes for UnloadingGuestDriver {} + +/// The host CPU architecture. +#[derive(Clone, Copy)] +enum HostArch { + None = 0, + X86_64 = 1, + Ppc64le = 2, + Arm = 3, + Aarch64 = 4, + Riscv64 = 5, +} + +// TODO[FPRI]: This is a temporary solution to be replaced with the corresponding derive macros once +// they land. +impl TryFrom<u32> for HostArch { + type Error = Error; + + fn try_from(value: u32) -> Result<Self> { + match value { + 0 => Ok(Self::None), + 1 => Ok(Self::X86_64), + 2 => Ok(Self::Ppc64le), + 3 => Ok(Self::Arm), + 4 => Ok(Self::Aarch64), + 5 => Ok(Self::Riscv64), + _ => Err(EINVAL), + } + } +} + +impl From<HostArch> for u32 { + fn from(value: HostArch) -> Self { + value as u32 + } +} + +nvkv_encode! { + /// A GSP registry entry. + struct RegKey { + key_name: Key<&'static [u8], 0x3070>, + key_value: Key<u32, 0x3071>, + } +} + +impl Encodable for KVVec<RegKey> { + fn encode(&self, encoder: &mut Encoder) -> Result { + for regkey in self { + regkey.encode(encoder)?; + } + Ok(()) + } +} + +nvkv_encode! { + /// SR-IOV virtual function information. + struct VfInfo { + total_vfs: Key<u32, 0x0080>, + first_vf_offset: Key<u32, 0x0081>, + flags: Key<u64, 0x1003>, + first_bar0_address: Key<u64, 0x1050>, + first_bar1_address: Key<u64, 0x1051>, + first_bar2_address: Key<u64, 0x1052>, + } +} + +nvkv_encode! { + /// Payload of the `GSP_INIT` command. + // TODO: expect() doesn't work here before rustc 1.97.0 + // https://github.com/rust-lang/rust/pull/154377 + #[allow(dead_code)] + struct GspInitRequest { + pci_device_id: Key<u32, 0x0001>, + pci_sub_device_id: Key<u32, 0x0002>, + pci_revision_id: Key<u32, 0x0003>, + pci_config_mirror_base: Key<u32, 0x0010>, + pci_config_mirror_size: Key<u32, 0x0011>, + host_arch: Key<HostArch, 0x0070, u32>, + bus_device_func: Key<u64, 0x1020>, + regkeys: KVVec<RegKey>, + vf_info: Option<VfInfo>, + } +} + +// Decode: + +// Should decode with UnknownKeyPolicy::Ignore. +nvkv_decode! { + /// Schema for the `GSP_INIT` response. + // TODO: expect() doesn't work here before rustc 1.97.0 + // https://github.com/rust-lang/rust/pull/154377 + #[allow(dead_code)] + struct GspInitResponseSchema => GspInitResponse { + gpu_name: TruncatingArray<u8, { GspInitResponse::MAX_GPU_NAME_LEN }, 0x2000>, + fb_regions: Accumulated<FbRegionSchema>, + bar1_pde_base: Required<Key<u64, 0x1020>>, + vmmu_segment_size: Key<u64, 0x1050>, + } +} + +/// Payload of the `GSP_INIT` response. +// TODO: expect() doesn't work here before rustc 1.97.0 +// https://github.com/rust-lang/rust/pull/154377 +#[allow(dead_code)] +struct GspInitResponse { + gpu_name: ArrayVec<u8, { Self::MAX_GPU_NAME_LEN }>, + fb_regions: KVVec<FbRegion>, + bar1_pde_base: u64, + vmmu_segment_size: u64, +} + +impl GspInitResponse { + const MAX_GPU_NAME_LEN: usize = 64; +} + +nvkv_decode! { + /// Schema for one FB region of the `GSP_INIT` response. + struct FbRegionSchema => FbRegion { + base: Required<Key<u64, 0x1011>>, + limit: Required<Key<u64, 0x1012>>, + flags: Required<Key<FbRegionFlags, 0x0012, u32>>, + tag: Required<Key<u32, 0x0013>>, + } +} + +bitfield! { + /// FB region attribute flags. + #[derive(Default)] + struct FbRegionFlags(u32) { + 0:0 support_compressed => bool; + 1:1 support_iso => bool; + 2:2 protected => bool; + } +} + +/// One FB memory region. +struct FbRegion { + base: u64, + limit: u64, + flags: FbRegionFlags, + tag: u32, +} diff --git a/drivers/gpu/nova-core/gsp/nvkv.rs b/drivers/gpu/nova-core/gsp/nvkv.rs index 9a4f3e40f811..8b10de9b48c8 100644 --- a/drivers/gpu/nova-core/gsp/nvkv.rs +++ b/drivers/gpu/nova-core/gsp/nvkv.rs @@ -9,8 +9,6 @@ //! speaking, the function calls will map to some struct - for example, f(GPU_NAME_STRING_KEY, 0, //! b"some gpu") naturally maps to storing a &str with the GPU name. -#![cfg_attr(not(CONFIG_KUNIT = "y"), expect(unused_imports))] - use core::{ marker::PhantomData, ops::{ diff --git a/drivers/gpu/nova-core/gsp/nvkv/decode.rs b/drivers/gpu/nova-core/gsp/nvkv/decode.rs index 43693cb4d31c..7637be89ea31 100644 --- a/drivers/gpu/nova-core/gsp/nvkv/decode.rs +++ b/drivers/gpu/nova-core/gsp/nvkv/decode.rs @@ -60,7 +60,6 @@ /// } /// } /// ``` -#[cfg_attr(not(CONFIG_KUNIT = "y"), expect(unused_macros))] macro_rules! nvkv_decode { // A schema which doesn't borrow from the stream. The macro uses a generic lifetime for the // [`Visit`] implementation but not for the struct itself. This allows omitting the unused diff --git a/drivers/gpu/nova-core/gsp/nvkv/encode.rs b/drivers/gpu/nova-core/gsp/nvkv/encode.rs index 64b4ea46d59c..b40aff41196e 100644 --- a/drivers/gpu/nova-core/gsp/nvkv/encode.rs +++ b/drivers/gpu/nova-core/gsp/nvkv/encode.rs @@ -38,7 +38,6 @@ pub(crate) trait Encodable { /// } /// } /// ``` -#[cfg_attr(not(CONFIG_KUNIT = "y"), expect(unused_macros))] macro_rules! nvkv_encode { ( $(#[$attr:meta])* @@ -65,6 +64,7 @@ fn encode(&self, encoder: &mut $crate::gsp::nvkv::Encoder) -> ::kernel::error::R } }; } +pub(crate) use nvkv_encode; impl<const KEY_ID: KeyId> Encodable for IndexedKey<u32, KEY_ID> { fn encode(&self, encoder: &mut Encoder) -> Result { -- 2.56.0
