diff --git a/tools/rust/xenbindgen/src/c_lang.rs b/tools/rust/xenbindgen/src/c_lang.rs
index bba310233e60..be6be3756dc0 100644
--- a/tools/rust/xenbindgen/src/c_lang.rs
+++ b/tools/rust/xenbindgen/src/c_lang.rs
@@ -17,7 +17,7 @@
 
 use std::fmt::Write;
 
-use crate::spec::{BitmapDef, EnumDef, OutFileDef, StructDef, Typ};
+use crate::spec::{BitmapDef, EnumDef, IncludeDef, OutFileDef, StructDef, Typ};
 
 use convert_case::{Case, Casing};
 use log::{debug, error, trace};
@@ -109,6 +109,39 @@ fn comment(out: &mut String, comment: &str, ind: Indentation) {
     }
 }
 
+/// Adds specified `includes`. `arch` must be treated specially in order to
+/// demultiplex the target architecture.
+///
+/// The reason for the inclusion must be printed as a comment on top of the
+/// `include` itself.
+fn includegen(out: &mut String, def: &IncludeDef) {
+    if !def.imports.is_empty() {
+        comment(
+            out,
+            &format!("for {}", def.imports.join(",\n    ")),
+            Indentation(0),
+        );
+    }
+
+    if def.from == "arch" {
+        writeln!(out, "#if defined(__i386__) || defined(__x86_64__)").unwrap();
+        writeln!(out, "#include \"arch_x86.h\"").unwrap();
+        writeln!(out, "#elif defined(__arm__) || defined(__aarch64__)").unwrap();
+        writeln!(out, "#include \"arch_arm.h\"").unwrap();
+        writeln!(out, "#elif defined(__powerpc64__)").unwrap();
+        writeln!(out, "#include \"arch_ppc.h\"").unwrap();
+        writeln!(out, "#elif defined(__riscv)").unwrap();
+        writeln!(out, "#include \"arch_riscv.h\"").unwrap();
+        writeln!(out, "#else").unwrap();
+        writeln!(out, "#error \"Unsupported architecture\"").unwrap();
+        writeln!(out, "#endif").unwrap();
+    } else {
+        writeln!(out, "#include \"{}.h\"", def.from).unwrap();
+    }
+
+    writeln!(out).unwrap();
+}
+
 /// Write a C-compatible struct onto `out`
 fn structgen(out: &mut String, filedef: &OutFileDef, def: &StructDef) {
     debug!("struct {}", def.name);
@@ -212,6 +245,10 @@ pub fn parse(filedef: &OutFileDef) -> String {
     writeln!(out, "#ifndef __XEN_AUTOGEN_{name}_H").unwrap();
     writeln!(out, "#define __XEN_AUTOGEN_{name}_H\n").unwrap();
 
+    for def in &filedef.includes {
+        includegen(&mut out, def);
+    }
+
     for def in &filedef.enums {
         enumgen(&mut out, def);
     }
diff --git a/tools/rust/xenbindgen/src/spec.rs b/tools/rust/xenbindgen/src/spec.rs
index 4a9c5e7d028b..04be05187ac8 100644
--- a/tools/rust/xenbindgen/src/spec.rs
+++ b/tools/rust/xenbindgen/src/spec.rs
@@ -134,9 +134,24 @@ pub struct VariantDef {
     pub value: u64,
 }
 
+/// Dependency links between files.
+///
+/// Used in specifications to state a number of types (described in `imports`)
+/// is needed from another generated file (the `from` field).
+#[derive(Debug, serde::Deserialize)]
+pub struct IncludeDef {
+    /// Name of the [`InFileDef`] that contains the imported tokens of
+    /// `imports`.
+    pub from: String,
+    /// List of tokens used in this spec file that exist in `from`.
+    pub imports: Vec<String>,
+}
+
 /// A language-agnostic specification.
 #[derive(Debug, serde::Deserialize)]
 struct InFileDef {
+    /// List of types described in other [`InFileDef`] that are required here.
+    includes: Option<Vec<IncludeDef>>,
     /// List of structs described in this input specification.
     structs: Option<Vec<StructDef>>,
     /// List of lang-agnostic enumerated descriptions.
@@ -152,7 +167,12 @@ struct InFileDef {
 pub struct OutFileDef {
     /// The name of the output file, without the final extension.
     pub name: String,
+    /// Represents the dependencies between various [`OutFileDef`]. A language
+    /// backend is free to ignore these if they are not required.
+    pub includes: Vec<IncludeDef>,
     /// List of structs described by all input spec files merged on this file.
+    ///
+    /// Implementation is lang-specific.
     pub structs: Vec<StructDef>,
     /// List of enumerated descriptions.
     ///
@@ -176,6 +196,7 @@ impl OutFileDef {
 
         let mut ret = Self {
             name,
+            includes: Vec::new(),
             structs: Vec::new(),
             enums: Vec::new(),
             bitmaps: Vec::new(),
@@ -195,6 +216,9 @@ impl OutFileDef {
             if let Some(bitmaps) = filedef.bitmaps {
                 ret.bitmaps.extend(bitmaps);
             }
+            if let Some(includes) = filedef.includes {
+                ret.includes.extend(includes);
+            }
         }
 
         Ok(ret)
