diff --git a/tools/rust/xen-sys/src/autogen.rs b/tools/rust/xen-sys/src/autogen.rs
new file mode 100644
index 000000000000..8a1cab8561f2
--- /dev/null
+++ b/tools/rust/xen-sys/src/autogen.rs
@@ -0,0 +1,27 @@
+//! Low-level description of buffers as used in hypercalls with the Xen hypervisor
+//!
+//! This module is fully autogenerated from TOML files defining the hypercall
+//! specification.
+
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub mod arch_x86;
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub use arch_x86 as arch;
+
+#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+pub mod arch_arm;
+#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+pub use arch_arm as arch;
+
+#[cfg(target_arch = "riscv64")]
+pub mod arch_riscv;
+#[cfg(target_arch = "riscv64")]
+pub use arch_riscv as arch;
+
+#[cfg(target_arch = "powerpc64")]
+pub mod arch_ppc;
+#[cfg(target_arch = "powerpc64")]
+pub use arch_ppc as arch;
+
+pub mod domctl;
+pub mod sysctl;
diff --git a/tools/rust/xen-sys/src/autogen/arch_arm.rs b/tools/rust/xen-sys/src/autogen/arch_arm.rs
new file mode 100644
index 000000000000..dc460557b2f0
--- /dev/null
+++ b/tools/rust/xen-sys/src/autogen/arch_arm.rs
@@ -0,0 +1,56 @@
+//! arch-arm
+//!
+//! AUTOGENERATED. DO NOT MODIFY
+
+/// Content of the `gic_version` field of the domainconfig struct.
+#[repr(u8)]
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub enum XenDomctlConfigGic {
+    /// Emulate the underlying GIC present in the current host.
+    #[default]
+    Native = 0,
+    /// Emulate a GICv2.
+    V2 = 1,
+    /// Emulate a GICv3.
+    V3 = 2,
+}
+
+/// TEE mediator exposed to the guest
+#[repr(u16)]
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub enum XenDomctlConfigTee {
+    /// No mediator. Guest can't communicate with the TEE.
+    #[default]
+    None = 0,
+    /// Expose an OP-TEE mediator.
+    Optee = 1,
+    /// Expose an FF-A mediator.
+    Ffa = 2,
+}
+
+/// arm-specific domain settings.
+#[repr(C)]
+#[derive(Clone, Debug, Default)]
+pub struct XenArchDomainconfig {
+    /// IN/OUT: GIC version exposed to the guest.
+    ///
+    /// When `native` on input the output value holds the automatically chosen version.
+    pub gic_version: XenDomctlConfigGic,
+    /// IN: SVE vector length (divided by 128) exposed to the guest.
+    pub sve_vl: u8,
+    /// IN: TEE mediator exposed to the guest.
+    pub tee_type: XenDomctlConfigTee,
+    /// IN: Number of SPIs exposed to the guest.
+    pub nr_spis: u32,
+    /// OUT
+    /// Based on the property clock-frequency in the DT timer node.
+    /// The property may be present when the bootloader/firmware doesn't
+    /// set correctly CNTFRQ which hold the timer frequency.
+    ///
+    /// As it's not possible to trap this register, we have to replicate
+    /// the value in the guest DT.
+    ///
+    /// = 0 => property not present
+    /// > 0 => Value of the property
+    pub clock_frequency: u32,
+}
diff --git a/tools/rust/xen-sys/src/autogen/arch_ppc.rs b/tools/rust/xen-sys/src/autogen/arch_ppc.rs
new file mode 100644
index 000000000000..8b68799648b9
--- /dev/null
+++ b/tools/rust/xen-sys/src/autogen/arch_ppc.rs
@@ -0,0 +1,8 @@
+//! arch-ppc
+//!
+//! AUTOGENERATED. DO NOT MODIFY
+
+/// ppc-specific domain settings.
+#[repr(C)]
+#[derive(Clone, Debug, Default)]
+pub struct XenArchDomainconfig;
diff --git a/tools/rust/xen-sys/src/autogen/arch_riscv.rs b/tools/rust/xen-sys/src/autogen/arch_riscv.rs
new file mode 100644
index 000000000000..1a68c7a02c7f
--- /dev/null
+++ b/tools/rust/xen-sys/src/autogen/arch_riscv.rs
@@ -0,0 +1,8 @@
+//! arch-riscv
+//!
+//! AUTOGENERATED. DO NOT MODIFY
+
+/// riscv-specific domain settings.
+#[repr(C)]
+#[derive(Clone, Debug, Default)]
+pub struct XenArchDomainconfig;
diff --git a/tools/rust/xen-sys/src/autogen/arch_x86.rs b/tools/rust/xen-sys/src/autogen/arch_x86.rs
new file mode 100644
index 000000000000..d63a3920c91e
--- /dev/null
+++ b/tools/rust/xen-sys/src/autogen/arch_x86.rs
@@ -0,0 +1,55 @@
+//! arch-x86
+//!
+//! AUTOGENERATED. DO NOT MODIFY
+
+use bitflags::bitflags;
+
+bitflags! {
+    /// Content of the `emulation_flags` field of the domain creation hypercall.
+    #[repr(C)]
+    #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+    pub struct XenX86Emu: u32 {
+        /// Emulate Local APICs.
+        const Lapic = 1 << 0;
+        /// Emulate a HPET timer.
+        const Hpet = 1 << 1;
+        /// Emulate the ACPI PM timer.
+        const Pm = 1 << 2;
+        /// Emulate the RTC clock.
+        const Rtc = 1 << 3;
+        /// Emulate an IOAPIC device.
+        const Ioapic = 1 << 4;
+        /// Emulate PIC devices.
+        const Pic = 1 << 5;
+        /// Emulate standard VGA.
+        const Vga = 1 << 6;
+        /// Emulate an IOMMU.
+        const Iommu = 1 << 7;
+        /// Emulate a PIT timer.
+        const Pit = 1 << 8;
+        /// Route physical IRQs over event channels.
+        const UsePirq = 1 << 9;
+        /// Handle PCI configuration space traps from within Xen.
+        const Vpci = 1 << 10;
+    }
+}
+
+bitflags! {
+    /// Contents of the `misc_flags` field of the domain creation hypercall
+    #[repr(C)]
+    #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+    pub struct XenX86Misc: u32 {
+        /// Grants access to the real physical MSR registers of the host.
+        const MsrRelaxed = 1 << 0;
+    }
+}
+
+/// x86-specific domain settings.
+#[repr(C)]
+#[derive(Clone, Debug, Default)]
+pub struct XenArchDomainconfig {
+    /// IN: Bitmap of devices to emulate.
+    pub emulation_flags: XenX86Emu,
+    /// IN: Miscellaneous x86-specific toggles.
+    pub misc_flags: XenX86Misc,
+}
diff --git a/tools/rust/xen-sys/src/autogen/domctl.rs b/tools/rust/xen-sys/src/autogen/domctl.rs
new file mode 100644
index 000000000000..7c3b872409be
--- /dev/null
+++ b/tools/rust/xen-sys/src/autogen/domctl.rs
@@ -0,0 +1,104 @@
+//! domctl
+//!
+//! AUTOGENERATED. DO NOT MODIFY
+
+use bitflags::bitflags;
+
+use super::arch::XenArchDomainconfig;
+
+bitflags! {
+    /// Content of the `flags` field of the domain creation hypercall.
+    #[repr(C)]
+    #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+    pub struct XenDomctlCdf: u32 {
+        /// Set if this is an HVM guest. Cleared if it's PV.
+        const Hvm = 1 << 0;
+        /// Use hardware-assisted paging if available
+        const Hap = 1 << 1;
+        /// Set if domain memory integrity is to be verified by tboot during Sx.
+        const S3Integrity = 1 << 2;
+        /// Set if Out-of-Sync shadow page tables are to be disabled
+        const OosOff = 1 << 3;
+        /// Set if this is a xenstore domain
+        const XsDomain = 1 << 4;
+        /// Set if this is domain can make use of the IOMMU
+        const Iommu = 1 << 5;
+        /// Set for the domain to have nested virtualization enabled.
+        const NestedVirt = 1 << 6;
+        /// Set to expose a vPMU to this domain.
+        const Vpmu = 1 << 7;
+    }
+}
+
+bitflags! {
+    /// Content of the `iommu_opts` field of the domain creation hypercall.
+    #[repr(C)]
+    #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+    pub struct XenDomctlIommuOpts: u32 {
+        /// Set to _NOT_ share page tables between the CPU and the IOMMU when it would be possible to do so.
+        const NoSharept = 1 << 0;
+    }
+}
+
+/// Content of the `altp2m_mode` field of the domain creation hypercall.
+#[repr(u8)]
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub enum XenDomctlAltp2MMode {
+    /// Keep altp2m disabled
+    #[default]
+    Disabled = 0,
+    /// Use mixed-mode for the altp2m (not yet evaluated for safety).
+    Mixed = 1,
+    /// Use external mode for the altp2m.
+    External = 2,
+    /// Use limited mode for the altp2m.
+    Limited = 3,
+}
+
+/// Create a new domain with the passed parameters.
+///
+/// IMPORTANT: The domid part of the domctl is IN/OUT. When the passed
+/// domid is 0 or over `DOMID_FIRST_RESERVED` a new domid is auto-allocated
+/// and returned.
+#[repr(C)]
+#[derive(Clone, Debug, Default)]
+pub struct XenDomctlCreatedomain {
+    /// IN: `Source Security IDentifier` (See XSM).
+    pub ssidref: u32,
+    /// IN: Unique identifier for this guest given by the toolstack.
+    pub handle: [u8; 16],
+    /// IN: Bitmap of domain features to enable/disable.
+    pub flags: XenDomctlCdf,
+    /// IN: Bitmap of configuration settings for the IOMMU.
+    pub iommu_opts: XenDomctlIommuOpts,
+    /// IN: Maximum number of CPUs this domain can hold, including hotplug.
+    pub max_vcpus: u32,
+    /// IN: Maximum number of usable event channels
+    pub max_evtchn_port: u32,
+    /// IN: Maximum number of pages this domain is able
+    ///     to grant access to for other domains.
+    ///
+    /// `< 0` means "use default value in the hypervisor."
+    pub max_grant_frames: i32,
+    /// IN: Maximum number of pages of foreign domains
+    ///     can be accessed via the grant mechanism.
+    ///
+    /// `< 0` means "use default value in the hypervisor."
+    pub max_maptrack_frames: i32,
+    /// Maximum grant table version allowed for this domain
+    pub max_grant_version: u8,
+    /// Unused padding. Reserved to zero.
+    pub rsvd_0_a: [u8; 3],
+    /// Which mode to configure altp2m with
+    pub altp_2_m_mode: u8,
+    /// Unused padding. Reserved to zero.
+    pub rsvd_0_b: [u8; 3],
+    /// IN: Per-vCPU buffer size in octets. 0 to disable.
+    pub vmtrace_size: u32,
+    /// IN: CPU pool to use; 0 or an existing CPU pool.
+    pub cpupool_id: u32,
+    /// Arch-specific settings.
+    ///
+    /// Each architecture is free to make its fields IN/OUT/INOUT
+    pub arch: XenArchDomainconfig,
+}
diff --git a/tools/rust/xen-sys/src/autogen/sysctl.rs b/tools/rust/xen-sys/src/autogen/sysctl.rs
new file mode 100644
index 000000000000..a2d8beb91d84
--- /dev/null
+++ b/tools/rust/xen-sys/src/autogen/sysctl.rs
@@ -0,0 +1,26 @@
+//! sysctl
+//!
+//! AUTOGENERATED. DO NOT MODIFY
+
+/// Read console content from Xen buffer ring.
+#[repr(C)]
+#[derive(Clone, Debug, Default)]
+pub struct XenSysctlReadconsole {
+    /// IN: Non-zero -> clear after reading.
+    pub clear: u8,
+    /// IN: Non-zero -> start index specified by `index` field.
+    pub incremental: u8,
+    /// Unused.
+    pub pad: u16,
+    /// IN:  Start index for consuming from ring buffer (if @incremental);
+    /// OUT: End index after consuming from ring buffer.
+    pub index: u32,
+    /// IN: Virtual address to write console data.
+    ///
+    /// NOTE: The pointer itself is IN, but the contents of the buffer are OUT.
+    pub buffer: crate::Align64<*mut u8>,
+    /// IN: Size of buffer; OUT: Bytes written to buffer.
+    pub count: u32,
+    /// Tail padding reserved to zero.
+    pub rsvd_0_a: u32,
+}
diff --git a/tools/rust/xen-sys/src/lib.rs b/tools/rust/xen-sys/src/lib.rs
index efab54ee1025..526193a920f8 100644
--- a/tools/rust/xen-sys/src/lib.rs
+++ b/tools/rust/xen-sys/src/lib.rs
@@ -7,6 +7,8 @@
 
 pub mod autogen;
 
+pub use autogen::*;
+
 use core::ops::{Deref, DerefMut};
 
 /// Wrapper for pointers and 64bit integers so they are _always_ aligned to 8
