mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Zhi Wang <zhiw@nvidia.com>
To: <dakr@kernel.org>, <acourbot@nvidia.com>
Cc: <alex@shazbot.org>, <jgg@nvidia.com>, <yishaih@nvidia.com>,
	<skolothumtho@nvidia.com>, <kevin.tian@intel.com>,
	<airlied@gmail.com>, <simona@ffwll.ch>, <ojeda@kernel.org>,
	<alex.gaynor@gmail.com>, <boqun.feng@gmail.com>,
	<gary@garyguo.net>, <bjorn3_gh@protonmail.com>,
	<lossin@kernel.org>, <a.hindborg@kernel.org>,
	<aliceryhl@google.com>, <tmgross@umich.edu>,
	<jhubbard@nvidia.com>, <ecourtney@nvidia.com>, <cjia@nvidia.com>,
	<smitra@nvidia.com>, <kjaju@nvidia.com>, <alkumar@nvidia.com>,
	<ankita@nvidia.com>, <aniketa@nvidia.com>, <kwankhede@nvidia.com>,
	<targupta@nvidia.com>, <nova-gpu@lists.linux.dev>,
	<linux-kernel@vger.kernel.org>, <zhiwang@kernel.org>,
	Zhi Wang <zhiw@nvidia.com>
Subject: [PATCH v2 22/32] gpu: nova-core: vgpu: encode vGPU boot requests
Date: Mon, 14 Sep 2026 10:48:57 +0300	[thread overview]
Message-ID: <20260914074907.1399629-23-zhiw@nvidia.com> (raw)
In-Reply-To: <20260914074907.1399629-1-zhiw@nvidia.com>

The vGPU boot command describes a vGPU's channel assignment, framebuffer,
plugin heap and log buffers to GSP. During vGPU instance creation,
once all resources have been allocated, this command registers them
with GSP-RM and boots the GSP plugin.

Add the NVKV request schema and encoder, including the channel map
and guest framebuffer segment arrays.

Co-developed-by: Eliot Courtney <ecourtney@nvidia.com>
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
 drivers/gpu/nova-core/gsp/nvkv.rs         |  11 ++
 drivers/gpu/nova-core/gsp/nvkv/encode.rs  |  12 ++
 drivers/gpu/nova-core/vgpu/fw/commands.rs | 163 +++++++++++++++++++++-
 3 files changed, 185 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/nova-core/gsp/nvkv.rs b/drivers/gpu/nova-core/gsp/nvkv.rs
index 9f2119b98b26..8d8dd4435354 100644
--- a/drivers/gpu/nova-core/gsp/nvkv.rs
+++ b/drivers/gpu/nova-core/gsp/nvkv.rs
@@ -168,6 +168,17 @@ pub(crate) struct Array<T: Default + Copy, const N: usize, const KEY_ID: KeyId>
     vec: ArrayVec<T, N>,
 }
 
+impl<T: Default + Copy, const N: usize, const KEY_ID: KeyId> Array<T, N, KEY_ID> {
+    /// Creates an array filled from `values`.
+    ///
+    /// Fails with `EINVAL` if `values` is longer than `N`.
+    pub(crate) fn new(values: &[T]) -> Result<Self> {
+        let mut vec = ArrayVec::default();
+        vec.extend_from_slice(values)?;
+        Ok(Self { vec })
+    }
+}
+
 bitfield! {
     /// The op word that starts each NVKV operation.
     struct Op(u64) {
diff --git a/drivers/gpu/nova-core/gsp/nvkv/encode.rs b/drivers/gpu/nova-core/gsp/nvkv/encode.rs
index 0047be65e8a9..1f4df24d8c9c 100644
--- a/drivers/gpu/nova-core/gsp/nvkv/encode.rs
+++ b/drivers/gpu/nova-core/gsp/nvkv/encode.rs
@@ -6,6 +6,7 @@
 use kernel::prelude::*;
 
 use super::{
+    Array,
     EncodedStream,
     Index,
     Key,
@@ -145,6 +146,17 @@ fn encode(&self, encoder: &mut Encoder) -> Result {
     }
 }
 
+impl<T, const N: usize, const KEY_ID: KeyId> Encodable for Array<T, N, KEY_ID>
+where
+    T: Default + Copy,
+    for<'a> IndexedKey<&'a [T], KEY_ID>: Encodable,
+{
+    #[inline(always)]
+    fn encode(&self, encoder: &mut Encoder) -> Result {
+        IndexedKey::<&[T], KEY_ID>::new(Index::new::<0>(), self.vec.as_slice()).encode(encoder)
+    }
+}
+
 impl<T: Encodable> Encodable for Option<T> {
     #[inline(always)]
     fn encode(&self, encoder: &mut Encoder) -> Result {
diff --git a/drivers/gpu/nova-core/vgpu/fw/commands.rs b/drivers/gpu/nova-core/vgpu/fw/commands.rs
index 51226bbca757..3af84c584dd6 100644
--- a/drivers/gpu/nova-core/vgpu/fw/commands.rs
+++ b/drivers/gpu/nova-core/vgpu/fw/commands.rs
@@ -8,12 +8,18 @@
 
 use kernel::{
     alloc::ArrayVec,
-    bitfield, //
+    bitfield,
+    prelude::*, //
 };
 
 use crate::gsp::nvkv::{
     nvkv_decode,
+    nvkv_encode,
     Array,
+    Encodable,
+    EncodedStream,
+    Encoder,
+    Index,
     Key,
     KeyId,
     Required, //
@@ -28,6 +34,161 @@ pub(in crate::vgpu) struct Dbdf(u32) {
     }
 }
 
+#[derive(Clone, Copy)]
+struct SwizzId(u32);
+
+impl SwizzId {
+    const WHOLE_GPU: Self = Self(0xFFFF_FFFF);
+}
+
+impl From<SwizzId> for u32 {
+    fn from(value: SwizzId) -> Self {
+        value.0
+    }
+}
+
+bitfield! {
+    pub(in crate::vgpu) struct ChannelMapEntry(u64) {
+        15:0 engine_type;
+        31:16 index;
+        63:32 chid_offset;
+    }
+}
+
+impl ChannelMapEntry {
+    const KEY: KeyId = 0x1001;
+
+    #[expect(dead_code)]
+    pub(in crate::vgpu) fn new(engine_type: usize, index: u32, chid_offset: u32) -> Result<Self> {
+        Self::zeroed()
+            .try_with_engine_type(u64::try_from(engine_type).map_err(|_| EOVERFLOW)?)
+            .and_then(|entry| entry.try_with_index(u64::from(index)))
+            .and_then(|entry| entry.try_with_chid_offset(u64::from(chid_offset)))
+    }
+}
+
+impl Encodable for KVVec<ChannelMapEntry> {
+    fn encode(&self, encoder: &mut Encoder) -> Result {
+        // SAFETY: `ChannelMapEntry` is a `bitfield!` over `u64`, i.e.
+        // `#[repr(transparent)]` around a `u64`, so the entries are
+        // layout-compatible with `u64` and can be viewed as a `u64` slice.
+        let slice = unsafe { core::slice::from_raw_parts(self.as_ptr().cast::<u64>(), self.len()) };
+        encoder.encode_array64(ChannelMapEntry::KEY, Index::new::<0>(), slice)
+    }
+}
+
+bitfield! {
+    struct VgpuBootloadOptions(u64) {
+    }
+}
+
+nvkv_encode! {
+    struct VgpuBootloadRequest {
+        dbdf: Key<Dbdf, { Self::DBDF_KEY }, u32>,
+        gfid: Key<u32, { Self::GFID_KEY }>,
+        vgpu_type: Key<u32, { Self::VGPU_TYPE_KEY }>,
+        vm_pid: Key<u32, { Self::VM_PID_KEY }>,
+        swizz_id: Key<SwizzId, { Self::SWIZZ_ID_KEY }, u32>,
+        num_channels: Key<u32, { Self::NUM_CHANNELS_KEY }>,
+        num_plugin_channels: Key<u32, { Self::NUM_PLUGIN_CHANNELS_KEY }>,
+        guest_fb_segment_count: Key<u32, { Self::GUEST_FB_SEGMENT_COUNT_KEY }>,
+        options: Key<VgpuBootloadOptions, { Self::OPTIONS_KEY }, u64>,
+        channel_mapping: KVVec<ChannelMapEntry>,
+        guest_fb_segment_phys_addr: Array<u64, 8, { Self::GUEST_FB_SEGMENT_PHYS_ADDR_KEY }>,
+        guest_fb_segment_length: Array<u64, 8, { Self::GUEST_FB_SEGMENT_LENGTH_KEY }>,
+        plugin_heap_phys_addr: Key<u64, { Self::PLUGIN_HEAP_PHYS_ADDR_KEY }>,
+        plugin_heap_length: Key<u64, { Self::PLUGIN_HEAP_LENGTH_KEY }>,
+        ctrl_buff_offset: Key<u64, { Self::CTRL_BUFF_OFFSET_KEY }>,
+        init_task_log_offset: Key<u64, { Self::INIT_TASK_LOG_OFFSET_KEY }>,
+        init_task_log_size: Key<u64, { Self::INIT_TASK_LOG_SIZE_KEY }>,
+        vgpu_task_log_offset: Key<u64, { Self::VGPU_TASK_LOG_OFFSET_KEY }>,
+        vgpu_task_log_size: Key<u64, { Self::VGPU_TASK_LOG_SIZE_KEY }>,
+        kernel_log_offset: Key<u64, { Self::KERNEL_LOG_OFFSET_KEY }>,
+        kernel_log_size: Key<u64, { Self::KERNEL_LOG_SIZE_KEY }>,
+        mig_rm_heap_phys_addr: Key<u64, { Self::MIG_RM_HEAP_PHYS_ADDR_KEY }>,
+        mig_rm_heap_length: Key<u64, { Self::MIG_RM_HEAP_LENGTH_KEY }>,
+    }
+}
+
+impl VgpuBootloadRequest {
+    const DBDF_KEY: KeyId = 0x0001;
+    const GFID_KEY: KeyId = 0x0002;
+    const VGPU_TYPE_KEY: KeyId = 0x0003;
+    const VM_PID_KEY: KeyId = 0x0004;
+    const SWIZZ_ID_KEY: KeyId = 0x0005;
+    const NUM_CHANNELS_KEY: KeyId = 0x0006;
+    const NUM_PLUGIN_CHANNELS_KEY: KeyId = 0x0007;
+    const GUEST_FB_SEGMENT_COUNT_KEY: KeyId = 0x0008;
+    const OPTIONS_KEY: KeyId = 0x1000;
+    const GUEST_FB_SEGMENT_PHYS_ADDR_KEY: KeyId = 0x1002;
+    const GUEST_FB_SEGMENT_LENGTH_KEY: KeyId = 0x1003;
+    const PLUGIN_HEAP_PHYS_ADDR_KEY: KeyId = 0x1004;
+    const PLUGIN_HEAP_LENGTH_KEY: KeyId = 0x1005;
+    const CTRL_BUFF_OFFSET_KEY: KeyId = 0x1006;
+    const INIT_TASK_LOG_OFFSET_KEY: KeyId = 0x1007;
+    const INIT_TASK_LOG_SIZE_KEY: KeyId = 0x1008;
+    const VGPU_TASK_LOG_OFFSET_KEY: KeyId = 0x1009;
+    const VGPU_TASK_LOG_SIZE_KEY: KeyId = 0x100A;
+    const KERNEL_LOG_OFFSET_KEY: KeyId = 0x100B;
+    const KERNEL_LOG_SIZE_KEY: KeyId = 0x100C;
+    const MIG_RM_HEAP_PHYS_ADDR_KEY: KeyId = 0x100D;
+    const MIG_RM_HEAP_LENGTH_KEY: KeyId = 0x100E;
+}
+
+/// Encodes a `VGPU_BOOTLOAD` request using the typed NVKV schema.
+#[expect(dead_code)]
+#[expect(clippy::too_many_arguments)]
+pub(in crate::vgpu) fn encode_vgpu_bootload(
+    dbdf: Dbdf,
+    gfid: u32,
+    vgpu_type: u32,
+    vm_pid: u32,
+    num_channels: u32,
+    num_plugin_channels: u32,
+    channel_mapping: KVVec<ChannelMapEntry>,
+    guest_fb_address: u64,
+    guest_fb_length: u64,
+    plugin_heap_address: u64,
+    plugin_heap_length: u64,
+    ctrl_buffer_offset: u64,
+    init_log_address: u64,
+    init_log_size: u64,
+    vgpu_log_address: u64,
+    vgpu_log_size: u64,
+    kernel_log_address: u64,
+    kernel_log_size: u64,
+) -> Result<EncodedStream> {
+    let request = VgpuBootloadRequest {
+        dbdf: dbdf.into(),
+        gfid: gfid.into(),
+        vgpu_type: vgpu_type.into(),
+        vm_pid: vm_pid.into(),
+        swizz_id: SwizzId::WHOLE_GPU.into(),
+        num_channels: num_channels.into(),
+        num_plugin_channels: num_plugin_channels.into(),
+        guest_fb_segment_count: 1.into(),
+        options: VgpuBootloadOptions::zeroed().into(),
+        channel_mapping,
+        guest_fb_segment_phys_addr: Array::new(&[guest_fb_address])?,
+        guest_fb_segment_length: Array::new(&[guest_fb_length])?,
+        plugin_heap_phys_addr: plugin_heap_address.into(),
+        plugin_heap_length: plugin_heap_length.into(),
+        ctrl_buff_offset: ctrl_buffer_offset.into(),
+        init_task_log_offset: init_log_address.into(),
+        init_task_log_size: init_log_size.into(),
+        vgpu_task_log_offset: vgpu_log_address.into(),
+        vgpu_task_log_size: vgpu_log_size.into(),
+        kernel_log_offset: kernel_log_address.into(),
+        kernel_log_size: kernel_log_size.into(),
+        mig_rm_heap_phys_addr: 0.into(),
+        mig_rm_heap_length: 0.into(),
+    };
+
+    let mut encoder = Encoder::new();
+    request.encode(&mut encoder)?;
+    Ok(encoder.finish())
+}
+
 nvkv_decode! {
     pub(in crate::vgpu) struct VgpuPropertiesSchema => VgpuProperties {
         // TODO: `name`/`class` required?

  parent reply	other threads:[~2026-09-14  7:52 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-14  7:48 [PATCH v2 00/32] Introduce NVIDIA vGPU manager Zhi Wang
2026-09-14  7:48 ` [PATCH v2 01/32] gpu: nova-core: gsp: pass boot context through setup helpers Zhi Wang
2026-09-14  7:48 ` [PATCH v2 02/32] gpu: nova-core: gsp: decouple boot context from VgpuManager Zhi Wang
2026-09-14  7:48 ` [PATCH v2 03/32] gpu: nova-core: vgpu: detect boot state independently Zhi Wang
2026-09-14  7:48 ` [PATCH v2 04/32] gpu: nova-core: gpu: add a channel ID pool for vGPU Zhi Wang
2026-09-14  7:48 ` [PATCH v2 05/32] gpu: nova-core: gsp: expose the VMMU segment size Zhi Wang
2026-09-14  7:48 ` [PATCH v2 06/32] gpu: nova-core: gsp: decode the FIFO engine table Zhi Wang
2026-09-14  7:48 ` [PATCH v2 07/32] gpu: nova-core: vgpu: initialize runtime parameters after GSP boot Zhi Wang
2026-09-14  7:48 ` [PATCH v2 08/32] gpu: nova-core: vgpu: reserve the 48-VM WPR2 heap Zhi Wang
2026-09-14  7:48 ` [PATCH v2 09/32] gpu: nova-core: mm: borrow BarUser for temporary BAR1 access Zhi Wang
2026-09-14  7:48 ` [PATCH v2 10/32] gpu: nova-core: mm: add VramBlock Zhi Wang
2026-09-14  7:48 ` [PATCH v2 11/32] gpu: nova-core: mm: add VramRegion Zhi Wang
2026-09-14  7:48 ` [PATCH v2 12/32] gpu: nova-core: mm: add BarMapping Zhi Wang
2026-09-14  7:48 ` [PATCH v2 13/32] gpu: nova-core: gsp: dispatch RM RPC messages during GMC receive Zhi Wang
2026-09-14  7:48 ` [PATCH v2 14/32] gpu: nova-core: gsp: add synchronous GMC transactions Zhi Wang
2026-09-14  7:48 ` [PATCH v2 15/32] gpu: nova-core: gsp: add status-only " Zhi Wang
2026-09-14  7:48 ` [PATCH v2 16/32] gpu: nova-core: gsp: wait for GMC completion events Zhi Wang
2026-09-14  7:48 ` [PATCH v2 17/32] gpu: nova-core: vgpu: add r000 plugin bindings Zhi Wang
2026-09-14  7:48 ` [PATCH v2 18/32] gpu: nova-core: vgpu: add VRAM slot allocator Zhi Wang
2026-09-14  7:48 ` [PATCH v2 19/32] gpu: nova-core: gsp: factor out NVKV payload conversion Zhi Wang
2026-09-14  7:48 ` [PATCH v2 20/32] gpu: nova-core: vgpu: query VF assignments and properties Zhi Wang
2026-09-14  7:48 ` [PATCH v2 21/32] gpu: nova-core: vgpu: add instance create/destroy Zhi Wang
2026-09-14  7:48 ` Zhi Wang [this message]
2026-09-14  7:48 ` [PATCH v2 23/32] gpu: nova-core: vgpu: add GSP plugin communication buffers Zhi Wang
2026-09-14  7:48 ` [PATCH v2 24/32] gpu: nova-core: vgpu: add instance boot and shutdown Zhi Wang
2026-09-14  7:49 ` [PATCH v2 25/32] gpu: nova-core: vgpu: initialize GSP plugin RPC buffers Zhi Wang
2026-09-14  7:49 ` [PATCH v2 26/32] gpu: nova-core: vgpu: add GSP plugin RPC transactions Zhi Wang
2026-09-14  7:49 ` [PATCH v2 27/32] gpu: nova-core: vgpu: negotiate the GSP plugin RPC version Zhi Wang
2026-09-14  7:49 ` [PATCH v2 28/32] gpu: nova-core: vgpu: send GSP plugin configuration parameters Zhi Wang
2026-09-14  7:49 ` [PATCH v2 29/32] gpu: nova-core: vgpu: update the GSP plugin BME state Zhi Wang
2026-09-14  7:49 ` [PATCH v2 30/32] gpu: nova-core: vgpu: scrub guest VRAM with CeUtils Zhi Wang
2026-09-14  7:49 ` [PATCH v2 31/32] gpu: nova-core: add build ID headers to debugfs log buffer dumps Zhi Wang
2026-09-14  7:49 ` [PATCH v2 32/32] gpu: nova-core: vgpu: export plugin log buffers via debugfs Zhi Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260914074907.1399629-23-zhiw@nvidia.com \
    --to=zhiw@nvidia.com \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=airlied@gmail.com \
    --cc=alex.gaynor@gmail.com \
    --cc=alex@shazbot.org \
    --cc=aliceryhl@google.com \
    --cc=alkumar@nvidia.com \
    --cc=aniketa@nvidia.com \
    --cc=ankita@nvidia.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=cjia@nvidia.com \
    --cc=dakr@kernel.org \
    --cc=ecourtney@nvidia.com \
    --cc=gary@garyguo.net \
    --cc=jgg@nvidia.com \
    --cc=jhubbard@nvidia.com \
    --cc=kevin.tian@intel.com \
    --cc=kjaju@nvidia.com \
    --cc=kwankhede@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=nova-gpu@lists.linux.dev \
    --cc=ojeda@kernel.org \
    --cc=simona@ffwll.ch \
    --cc=skolothumtho@nvidia.com \
    --cc=smitra@nvidia.com \
    --cc=targupta@nvidia.com \
    --cc=tmgross@umich.edu \
    --cc=yishaih@nvidia.com \
    --cc=zhiwang@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®