[PATCH 07/10] gpu: nova-core: gsp: Create RM registry and sysinfo commands

Alistair Popple
Wed, 27 Aug 2025 08:20:04 -0000

Add the RM registry and system information commands that enable the host
driver to configure GSP firmware parameters during initialization.

The RM registry is serialized into a packed format and sent via the
command queue. For now only two parameters which are required to boot
GSP are hardcoded. In future a kernel module parameter will be added to
enable other parameters to be added.

Also add the system info command, which provides required hardware
information to the GSP. These commands use the GSP command queue
infrastructure to issue commands to the GSP which is read during GSP
boot.

Signed-off-by: Alistair Popple <apopple at nvidia.com>
---
 drivers/gpu/nova-core/gpu.rs                  |   2 +-
 drivers/gpu/nova-core/gsp.rs                  |   7 +
 drivers/gpu/nova-core/gsp/cmdq.rs             |   3 -
 drivers/gpu/nova-core/gsp/commands.rs         | 201 ++++++++++++++++++
 drivers/gpu/nova-core/nvfw.rs                 |   8 +
 .../gpu/nova-core/nvfw/r570_144_bindings.rs   | 179 ++++++++++++++++
 6 files changed, 396 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/nova-core/gsp/commands.rs

diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index bf762353f1d91..c070bd581e2c9 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -312,7 +312,7 @@ pub(crate) fn new(

         Self::run_fwsec_frts(pdev.as_ref(), &gsp_falcon, bar, &bios,
&fb_layout)?;

-        let libos = gsp::GspMemObjects::new(pdev, &fw, &fb_layout)?;
+        let libos = gsp::GspMemObjects::new(pdev, bar, &fw,
&fb_layout)?;
         let _libos_handle = libos.libos_dma_handle();
         let _wpr_handle = libos.wpr_meta.dma_handle();

diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs
index 56a6be7b9eb15..9776c643f5276 100644
--- a/drivers/gpu/nova-core/gsp.rs
+++ b/drivers/gpu/nova-core/gsp.rs
@@ -11,9 +11,11 @@
 use kernel::sizes::SZ_128K;
 use kernel::transmute::{AsBytes, FromBytes};

+use crate::driver::Bar0;
 use crate::fb::FbLayout;
 use crate::firmware::Firmware;
 use crate::gsp::cmdq::GspCmdq;
+use crate::gsp::commands::{build_registry, set_system_info};
 use crate::nvfw::{
     GspFwWprMeta, GspFwWprMetaBootInfo, GspFwWprMetaBootResumeInfo,
LibosMemoryRegionInitArgument,
     LibosMemoryRegionKind_LIBOS_MEMORY_REGION_CONTIGUOUS,
@@ -23,6 +25,7 @@
 };

 pub(crate) mod cmdq;
+pub(crate) mod commands;

 pub(crate) const GSP_PAGE_SHIFT: usize = 12;
 pub(crate) const GSP_PAGE_SIZE: usize = 1 << GSP_PAGE_SHIFT;
@@ -176,6 +179,7 @@ fn create_coherent_dma_object<A: AsBytes + FromBytes>(
 impl GspMemObjects {
     pub(crate) fn new(
         pdev: &pci::Device<device::Bound>,
+        bar: &Bar0,
         fw: &Firmware,
         fb_layout: &FbLayout,
     ) -> Result<Self> {
@@ -218,6 +222,9 @@ pub(crate) fn new(
         )?;
         dma_write!(rmargs[0].bDmemStack = 1)?;

+        set_system_info(&mut cmdq, pdev, bar)?;
+        build_registry(&mut cmdq, bar)?;
+
         Ok(GspMemObjects {
             libos,
             loginit,
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs
b/drivers/gpu/nova-core/gsp/cmdq.rs
index 134ed0e20d9e3..4e4fbaa81e8e7 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -228,7 +228,6 @@ pub(crate) struct GspQueueCommand<'a> {
 );

 impl<'a> GspQueueCommand<'a> {
-    #[expect(unused)]
     pub(crate) fn try_as<'b, M: GspCommandToGsp>(&'b mut
self) -> GspQueueCommandData<'b, M> {
         // SAFETY: The slice references the cmdq message memory which is
         // guaranteed to outlive the returned GspQueueCommandData by the
@@ -247,7 +246,6 @@ pub(crate) fn try_as<'b, M:
GspCommandToGsp>(&'b mut self) -> GspQueueCommandDat
         (msg, sbuf)
     }

-    #[expect(unused)]
     pub(crate) fn send_to_gsp(self, bar: &Bar0) -> Result {
         self.cmdq.wait_for_free_cmd_to_gsp(
             Delta::from_secs(GSP_COMMAND_TIMEOUT),
@@ -361,7 +359,6 @@ pub(crate) fn wait_for_free_cmd_to_gsp(&self, timeout:
Delta, size: usize) -> Re
         })
     }

-    #[expect(unused)]
     pub(crate) fn alloc_gsp_queue_command<'a>(
         &'a mut self,
         cmd_size: usize,
diff --git a/drivers/gpu/nova-core/gsp/commands.rs
b/drivers/gpu/nova-core/gsp/commands.rs
new file mode 100644
index 0000000000000..12ea8cdec21db
--- /dev/null
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use core::alloc::Layout;
+
+use kernel::alloc::allocator::Kmalloc;
+use kernel::alloc::Allocator;
+use kernel::build_assert;
+use kernel::device;
+use kernel::pci;
+use kernel::prelude::*;
+use kernel::transmute::{AsBytes, FromBytes};
+
+use crate::driver::Bar0;
+use crate::gsp::cmdq::GspCommandToGsp;
+use crate::gsp::cmdq::GspCmdq;
+use crate::gsp::GSP_PAGE_SIZE;
+use crate::nvfw::{
+    NV_VGPU_MSG_FUNCTION_SET_REGISTRY,
+    NV_VGPU_MSG_FUNCTION_GSP_SET_SYSTEM_INFO,
+    GspSystemInfo,
+    PACKED_REGISTRY_TABLE,
+    PACKED_REGISTRY_ENTRY,
+    REGISTRY_TABLE_ENTRY_TYPE_DWORD,
+};
+use crate::sbuffer::SBuffer;
+
+// SAFETY: These structs don't meet the no-padding requirements of AsBytes
but
+//         that is not a problem because they are not used outside the kernel.
+unsafe impl AsBytes for GspSystemInfo {}
+
+// SAFETY: These structs don't meet the no-padding requirements of
FromBytes but
+//         that is not a problem because they are not used outside the kernel.
+unsafe impl FromBytes for GspSystemInfo {}
+
+const GSP_REGISTRY_NUM_ENTRIES: usize = 2;
+struct RegistryEntry {
+    key: &'static str,
+    value: u32,
+}
+
+struct RegistryTable {
+    entries: [RegistryEntry; GSP_REGISTRY_NUM_ENTRIES],
+}
+
+struct GspRegistryTable;
+impl GspCommandToGsp for GspRegistryTable {
+    const FUNCTION: u32 = NV_VGPU_MSG_FUNCTION_SET_REGISTRY;
+}
+
+impl RegistryTable {
+    fn serialize_registry_table(&self) -> Result<KVec<u8>> {
+        let entries = &self.entries;
+        let total_size = self.size();
+        let align = core::mem::align_of::<PACKED_REGISTRY_TABLE>();
+        let layout = Layout::from_size_align(total_size, align).map_err(|_|
ENOMEM)?;
+        debug_assert_eq!(layout.size(), total_size);
+        let mut string_data_offset = size_of::<PACKED_REGISTRY_TABLE>()
+            + GSP_REGISTRY_NUM_ENTRIES *
size_of::<PACKED_REGISTRY_ENTRY>();
+        let allocation = Kmalloc::alloc(layout, GFP_KERNEL)?;
+        let ptr = allocation.as_ptr().cast::<u8>();
+
+        // We allocate the memory for the vector ourselves to ensure it has the
+        // correct layout to cast to a PACKED_REGISTRY_TABLE and subsequent
+        // fw:PACKED_REGISTRY_ENTRIES.
+        //
+        // SAFETY:
+        //  - ptr was allocated with Kmalloc as required for KVec.
+        //  - ptr trivally meets the alignment requirements for u8.
+        //  - No elements have been initialised so this is zero length.
+        //  - The capacity matches the total size of the allocation.
+        let mut table_vec = unsafe { KVec::<u8>::from_raw_parts(ptr, 0,
layout.size()) };
+        let table_slice = table_vec.spare_capacity_mut();
+        let table =
table_slice.as_mut_ptr().cast::<PACKED_REGISTRY_TABLE>();
+
+        // SAFETY: We ensured the alignment was correct when allocating the
vector.
+        unsafe {
+            // Set the table header
+            (*table).numEntries = GSP_REGISTRY_NUM_ENTRIES as u32;
+            (*table).size = total_size as u32;
+        }
+
+        for (i, entry) in
entries.iter().enumerate().take(GSP_REGISTRY_NUM_ENTRIES) {
+            // SAFETY: The allocation meets the alignment requirements for
+            // fw::PACKED_REGISTRY_TABLE which includes a zero length array for
the entries.
+            unsafe {
+                let entry_ptr = table_slice
+                    .as_mut_ptr()
+                    .add(
+                        size_of::<PACKED_REGISTRY_TABLE>()
+                            + i * size_of::<PACKED_REGISTRY_ENTRY>(),
+                    )
+                    .cast::<PACKED_REGISTRY_ENTRY>();
+
+                // Set entry metadata
+                (*entry_ptr).nameOffset = string_data_offset as u32;
+                (*entry_ptr).type_ = REGISTRY_TABLE_ENTRY_TYPE_DWORD as u8;
+                (*entry_ptr).data = entry.value;
+                (*entry_ptr).length = 0;
+            }
+
+            let key_bytes = entry.key.as_bytes();
+            let string_dest_slice +                &mut
table_slice[string_data_offset..string_data_offset + key_bytes.len() + 1];
+
+            // Can't use copy_from_slice() because string_dest_slice is
MaybeUninit<u8>.
+            for (i, &byte) in key_bytes.iter().enumerate() {
+                string_dest_slice[i].write(byte);
+            }
+
+            // Add null terminator
+            string_dest_slice[key_bytes.len()].write(0);
+
+            // Update offset for next string
+            string_data_offset += string_dest_slice.len();
+        }
+
+        debug_assert_eq!(total_size, string_data_offset);
+
+        // SAFETY: All data has been written to as asserted above and the
+        // capacity matches the original allocation.
+        unsafe { table_vec.inc_len(layout.size()) };
+
+        Ok(table_vec)
+    }
+
+    fn copy_to_sbuf_iter(&self, mut sbuf:
SBuffer<core::array::IntoIter<&mut [u8], 2>>) -> Result {
+        let table_vec = self.serialize_registry_table()?;
+        sbuf.write_all(&table_vec)?;
+        Ok(())
+    }
+
+    fn size(&self) -> usize {
+        let mut key_size = 0;
+        for i in 0..GSP_REGISTRY_NUM_ENTRIES {
+            key_size += self.entries[i].key.len() + 1; // +1 for NULL
terminator
+        }
+        size_of::<PACKED_REGISTRY_TABLE>()
+            + GSP_REGISTRY_NUM_ENTRIES *
size_of::<PACKED_REGISTRY_ENTRY>()
+            + key_size
+    }
+}
+
+pub(crate) fn build_registry(cmdq: &mut GspCmdq, bar: &Bar0) ->
Result {
+    let registry = RegistryTable {
+        entries: [
+            RegistryEntry {
+                key: "RMSecBusResetEnable",
+                value: 1,
+            },
+            RegistryEntry {
+                key: "RMForcePcieConfigSave",
+                value: 1,
+            },
+        ],
+    };
+    let mut msg = cmdq.alloc_gsp_queue_command(registry.size())?;
+    {
+        let (_, some_sbuf) = msg.try_as::<GspRegistryTable>();
+        let sbuf = some_sbuf.ok_or(ENOMEM)?;
+        registry.copy_to_sbuf_iter(sbuf)?;
+    }
+    msg.send_to_gsp(bar)?;
+
+    Ok(())
+}
+
+impl GspCommandToGsp for GspSystemInfo {
+    const FUNCTION: u32 = NV_VGPU_MSG_FUNCTION_GSP_SET_SYSTEM_INFO;
+}
+
+pub(crate) fn set_system_info(
+    cmdq: &mut GspCmdq,
+    dev: &pci::Device<device::Bound>,
+    bar: &Bar0,
+) -> Result {
+    build_assert!(size_of::<GspSystemInfo>() < GSP_PAGE_SIZE);
+    let mut msg =
cmdq.alloc_gsp_queue_command(size_of::<GspSystemInfo>())?;
+    {
+        let (info, _) = msg.try_as::<GspSystemInfo>();
+
+        info.gpuPhysAddr = dev.resource_start(0)?;
+        info.gpuPhysFbAddr = dev.resource_start(1)?;
+        info.gpuPhysInstAddr = dev.resource_start(3)?;
+        info.nvDomainBusDeviceFunc = u64::from(dev.dev_id());
+
+        // Using TASK_SIZE in r535_gsp_rpc_set_system_info() seems wrong
because
+        // TASK_SIZE is per-task. That's probably a design issue in GSP-RM
though.
+        info.maxUserVa = (1 << 47) - 4096;
+        info.pciConfigMirrorBase = 0x088000;
+        info.pciConfigMirrorSize = 0x001000;
+
+        info.PCIDeviceID = (u32::from(dev.device_id()) << 16) |
u32::from(dev.vendor_id());
+        info.PCISubDeviceID +            (u32::from(dev.subsystem_device_id())
<< 16) | u32::from(dev.subsystem_vendor_id());
+        info.PCIRevisionID = u32::from(dev.revision_id());
+        info.bIsPrimary = 0;
+        info.bPreserveVideoMemoryAllocations = 0;
+    }
+    msg.send_to_gsp(bar)?;
+    Ok(())
+}
diff --git a/drivers/gpu/nova-core/nvfw.rs b/drivers/gpu/nova-core/nvfw.rs
index 3d934cc95feb0..aa883d4588388 100644
--- a/drivers/gpu/nova-core/nvfw.rs
+++ b/drivers/gpu/nova-core/nvfw.rs
@@ -42,6 +42,9 @@ pub(crate) struct LibosParams {
 pub(crate) use r570_144::GspFwWprMeta;

 pub(crate) use r570_144::{
+    // Core GSP structures
+    GspSystemInfo,
+
     // LibOS memory structures
     LibosMemoryRegionInitArgument,
     LibosMemoryRegionKind_LIBOS_MEMORY_REGION_CONTIGUOUS,
@@ -87,6 +90,11 @@ pub(crate) struct LibosParams {
     NV_VGPU_MSG_FUNCTION_NOP,
     NV_VGPU_MSG_FUNCTION_SET_GUEST_SYSTEM_INFO,
     NV_VGPU_MSG_FUNCTION_SET_REGISTRY,
+
+    // RM registry structures
+    PACKED_REGISTRY_ENTRY,
+    PACKED_REGISTRY_TABLE,
+    REGISTRY_TABLE_ENTRY_TYPE_DWORD,
 };

 pub(crate) type GspFwWprMetaBootResumeInfo =
r570_144::GspFwWprMeta__bindgen_ty_1;
diff --git a/drivers/gpu/nova-core/nvfw/r570_144_bindings.rs
b/drivers/gpu/nova-core/nvfw/r570_144_bindings.rs
index ab331fe6b1c81..3832d0b7a0b92 100644
--- a/drivers/gpu/nova-core/nvfw/r570_144_bindings.rs
+++ b/drivers/gpu/nova-core/nvfw/r570_144_bindings.rs
@@ -1,5 +1,35 @@
 // SPDX-License-Identifier: GPL-2.0

+#[repr(C)]
+#[derive(Default)]
+pub struct
__IncompleteArrayField<T>(::core::marker::PhantomData<T>, [T; 0]);
+impl<T> __IncompleteArrayField<T> {
+    #[inline]
+    pub const fn new() -> Self {
+        __IncompleteArrayField(::core::marker::PhantomData, [])
+    }
+    #[inline]
+    pub fn as_ptr(&self) -> *const T {
+        self as *const _ as *const T
+    }
+    #[inline]
+    pub fn as_mut_ptr(&mut self) -> *mut T {
+        self as *mut _ as *mut T
+    }
+    #[inline]
+    pub unsafe fn as_slice(&self, len: usize) -> &[T] {
+        ::core::slice::from_raw_parts(self.as_ptr(), len)
+    }
+    #[inline]
+    pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
+        ::core::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
+    }
+}
+impl<T> ::core::fmt::Debug for __IncompleteArrayField<T> {
+    fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) ->
::core::fmt::Result {
+        fmt.write_str("__IncompleteArrayField")
+    }
+}
 pub const GSP_FW_HEAP_PARAM_OS_SIZE_LIBOS2: u32 = 0;
 pub const GSP_FW_HEAP_PARAM_OS_SIZE_LIBOS3_BAREMETAL: u32 = 23068672;
 pub const GSP_FW_HEAP_PARAM_BASE_RM_SIZE_TU10X: u32 = 8388608;
@@ -11,6 +41,7 @@
 pub const GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MAX_MB: u32 = 280;
 pub const GSP_FW_WPR_META_REVISION: u32 = 1;
 pub const GSP_FW_WPR_META_MAGIC: i64 = -2577556379034558285;
+pub const REGISTRY_TABLE_ENTRY_TYPE_DWORD: u32 = 1;
 pub type __u8 = ffi::c_uchar;
 pub type __u16 = ffi::c_ushort;
 pub type __u32 = ffi::c_uint;
@@ -289,6 +320,138 @@
 pub type _bindgen_ty_3 = ffi::c_uint;
 #[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
+pub struct DOD_METHOD_DATA {
+    pub status: u32_,
+    pub acpiIdListLen: u32_,
+    pub acpiIdList: [u32_; 16usize],
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct JT_METHOD_DATA {
+    pub status: u32_,
+    pub jtCaps: u32_,
+    pub jtRevId: u16_,
+    pub bSBIOSCaps: u8_,
+    pub __bindgen_padding_0: u8,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct MUX_METHOD_DATA_ELEMENT {
+    pub acpiId: u32_,
+    pub mode: u32_,
+    pub status: u32_,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct MUX_METHOD_DATA {
+    pub tableLen: u32_,
+    pub acpiIdMuxModeTable: [MUX_METHOD_DATA_ELEMENT; 16usize],
+    pub acpiIdMuxPartTable: [MUX_METHOD_DATA_ELEMENT; 16usize],
+    pub acpiIdMuxStateTable: [MUX_METHOD_DATA_ELEMENT; 16usize],
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct CAPS_METHOD_DATA {
+    pub status: u32_,
+    pub optimusCaps: u32_,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct ACPI_METHOD_DATA {
+    pub bValid: u8_,
+    pub __bindgen_padding_0: [u8; 3usize],
+    pub dodMethodData: DOD_METHOD_DATA,
+    pub jtMethodData: JT_METHOD_DATA,
+    pub muxMethodData: MUX_METHOD_DATA,
+    pub capsMethodData: CAPS_METHOD_DATA,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct BUSINFO {
+    pub deviceID: u16_,
+    pub vendorID: u16_,
+    pub subdeviceID: u16_,
+    pub subvendorID: u16_,
+    pub revisionID: u8_,
+    pub __bindgen_padding_0: u8,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct GSP_VF_INFO {
+    pub totalVFs: u32_,
+    pub firstVFOffset: u32_,
+    pub FirstVFBar0Address: u64_,
+    pub FirstVFBar1Address: u64_,
+    pub FirstVFBar2Address: u64_,
+    pub b64bitBar0: u8_,
+    pub b64bitBar1: u8_,
+    pub b64bitBar2: u8_,
+    pub __bindgen_padding_0: [u8; 5usize],
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct GSP_PCIE_CONFIG_REG {
+    pub linkCap: u32_,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct GspSystemInfo {
+    pub gpuPhysAddr: u64_,
+    pub gpuPhysFbAddr: u64_,
+    pub gpuPhysInstAddr: u64_,
+    pub gpuPhysIoAddr: u64_,
+    pub nvDomainBusDeviceFunc: u64_,
+    pub simAccessBufPhysAddr: u64_,
+    pub notifyOpSharedSurfacePhysAddr: u64_,
+    pub pcieAtomicsOpMask: u64_,
+    pub consoleMemSize: u64_,
+    pub maxUserVa: u64_,
+    pub pciConfigMirrorBase: u32_,
+    pub pciConfigMirrorSize: u32_,
+    pub PCIDeviceID: u32_,
+    pub PCISubDeviceID: u32_,
+    pub PCIRevisionID: u32_,
+    pub pcieAtomicsCplDeviceCapMask: u32_,
+    pub oorArch: u8_,
+    pub __bindgen_padding_0: [u8; 7usize],
+    pub clPdbProperties: u64_,
+    pub Chipset: u32_,
+    pub bGpuBehindBridge: u8_,
+    pub bFlrSupported: u8_,
+    pub b64bBar0Supported: u8_,
+    pub bMnocAvailable: u8_,
+    pub chipsetL1ssEnable: u32_,
+    pub bUpstreamL0sUnsupported: u8_,
+    pub bUpstreamL1Unsupported: u8_,
+    pub bUpstreamL1PorSupported: u8_,
+    pub bUpstreamL1PorMobileOnly: u8_,
+    pub bSystemHasMux: u8_,
+    pub upstreamAddressValid: u8_,
+    pub FHBBusInfo: BUSINFO,
+    pub chipsetIDInfo: BUSINFO,
+    pub __bindgen_padding_1: [u8; 2usize],
+    pub acpiMethodData: ACPI_METHOD_DATA,
+    pub hypervisorType: u32_,
+    pub bIsPassthru: u8_,
+    pub __bindgen_padding_2: [u8; 7usize],
+    pub sysTimerOffsetNs: u64_,
+    pub gspVFInfo: GSP_VF_INFO,
+    pub bIsPrimary: u8_,
+    pub isGridBuild: u8_,
+    pub __bindgen_padding_3: [u8; 2usize],
+    pub pcieConfigReg: GSP_PCIE_CONFIG_REG,
+    pub gridBuildCsp: u32_,
+    pub bPreserveVideoMemoryAllocations: u8_,
+    pub bTdrEventSupported: u8_,
+    pub bFeatureStretchVblankCapable: u8_,
+    pub bEnableDynamicGranularityPageArrays: u8_,
+    pub bClockBoostSupported: u8_,
+    pub bRouteDispIntrsToCPU: u8_,
+    pub __bindgen_padding_4: [u8; 6usize],
+    pub hostPageSize: u64_,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
 pub struct MESSAGE_QUEUE_INIT_ARGUMENTS {
     pub sharedMemPhysAddr: u64_,
     pub pageTableEntryCount: u32_,
@@ -446,3 +609,19 @@ pub struct LibosMemoryRegionInitArgument {
     pub loc: u8_,
     pub __bindgen_padding_0: [u8; 6usize],
 }
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct PACKED_REGISTRY_ENTRY {
+    pub nameOffset: u32_,
+    pub type_: u8_,
+    pub __bindgen_padding_0: [u8; 3usize],
+    pub data: u32_,
+    pub length: u32_,
+}
+#[repr(C)]
+#[derive(Debug, Default)]
+pub struct PACKED_REGISTRY_TABLE {
+    pub size: u32_,
+    pub numEntries: u32_,
+    pub entries: __IncompleteArrayField<PACKED_REGISTRY_ENTRY>,
+}
--
2.47.2