From nobody Fri Oct 31 11:00:03 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass header.i=teddy.astie@vates.tech; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=vates.tech ARC-Seal: i=1; a=rsa-sha256; t=1755789980; cv=none; d=zohomail.com; s=zohoarc; b=ZxbGgDV/Atkwloz1jK+hEw/rGCQfrLF8NFyUYDQxhjZYyqQbyuXKDpvlkNajQMalR2Btw/YlTp4hg1XYxAh1pf3CwZAFK4aAKC8h62kCY8tzcvRjeH56a2/Wh7QsYAl74ipPUOxCl+KnKNPxLB2sVwlPZzIo2Z9i7c59v3UHo2I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1755789980; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=dB5KCjXLMLA/zGiXspyIEC0oMRY7D9rqpGbR0gjZJDU=; b=QvCTtVKrR+RSx+sX+kZB1gdbNg4EhtytSu/J/Q2GAtmkcxJZalSaFtq3CL2Aj5eFQ4El9IJRQCAyt+spV9OvHvh46/ZoWMts6GBpK/xbHXoLcx47ce+si1TCr4blFRXI1CzzAPnX7UJYZPBOnIv/nt3DqnfPCERvqXxYIrb3glY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=teddy.astie@vates.tech; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1755789980469429.3777678833743; Thu, 21 Aug 2025 08:26:20 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1088824.1446615 (Exim 4.92) (envelope-from ) id 1up7Ay-0007xV-Ij; Thu, 21 Aug 2025 15:26:04 +0000 Received: by outflank-mailman (output) from mailman id 1088824.1446615; Thu, 21 Aug 2025 15:26:04 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1up7Ay-0007uv-6K; Thu, 21 Aug 2025 15:26:04 +0000 Received: by outflank-mailman (input) for mailman id 1088824; Thu, 21 Aug 2025 15:26:02 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1up7Aw-0005na-D0 for xen-devel@lists.xenproject.org; Thu, 21 Aug 2025 15:26:02 +0000 Received: from mail137-3.atl71.mandrillapp.com (mail137-3.atl71.mandrillapp.com [198.2.137.3]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 24540d96-7ea3-11f0-b898-0df219b8e170; Thu, 21 Aug 2025 17:26:00 +0200 (CEST) Received: from pmta07.mandrill.prod.atl01.rsglab.com (localhost [127.0.0.1]) by mail137-3.atl71.mandrillapp.com (Mailchimp) with ESMTP id 4c76bW5MwRzBsW3G7 for ; Thu, 21 Aug 2025 15:25:59 +0000 (GMT) Received: from [37.26.189.201] by mandrillapp.com id d8fda27edc9d4cb49aff6b07b7f2a894; Thu, 21 Aug 2025 15:25:59 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 24540d96-7ea3-11f0-b898-0df219b8e170 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandrillapp.com; s=mte1; t=1755789959; x=1756059959; bh=dB5KCjXLMLA/zGiXspyIEC0oMRY7D9rqpGbR0gjZJDU=; h=From:Subject:To:Cc:Message-Id:In-Reply-To:References:Feedback-ID: Date:MIME-Version:Content-Type:Content-Transfer-Encoding:CC:Date: Subject:From; b=MUdVl9RX3BPRg4F5DxnVIsZNFSEaQBbEEhIMPvXWcuHCWUnudTpppPOql4Yv5Cvs8 oNN5Ji2KNStP1l61idT5LzE88K4/ow2ivY4Pox1dv3pxjZlqGtY0epL7MrEJFqlLql QK/Pt95Gr4llt7k/2uPBWqtB/F/0IZsTI0D8ExOjCDWCS+pTtbUsoMjPlzoDpHSLxG QPCcw+Gy1/AZsvw5Fz18mN3SJebijS69n3yd5plGDzSX7Tu6R7ogAAwX91jMy4RcWa 5W68AXjUpeHb01IgvoNz6VngOJtAKB9grJh8JOSRrMWd4TWhRwOhK20xriSCoyQSZO NEYgdYkuTZYyA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vates.tech; s=mte1; t=1755789959; x=1756050459; i=teddy.astie@vates.tech; bh=dB5KCjXLMLA/zGiXspyIEC0oMRY7D9rqpGbR0gjZJDU=; h=From:Subject:To:Cc:Message-Id:In-Reply-To:References:Feedback-ID: Date:MIME-Version:Content-Type:Content-Transfer-Encoding:CC:Date: Subject:From; b=q9vcWxZv40nZ467ibqaYzqkbfJSn49OCUiqGHAEBVRAgmua6N5qWjRb0LfzZj7yUH gXPKxuKH0aeUHXBha+IES+04VmWhHVSaDSgjRCLwwrA55Ww40YShZVkvcA2ilhvQ0q n/UbW5m4oDkFTlJxt6ZBtNL3GmGE1QNq2TKGj8kLx/unU1OaWtAc4hpAGPr4JMC0zn 9/qDXXs5eO3GdbLszazbU2ihy2GPxa4E7YvRdjQZlKf/1d1YmIVeTVXVAfy7W+PDrO 6Qz9S+W6ZsVgQcF/8V5evs02447CXg4Pu5RxMElfwQW1Hq8y6WEaSThULPZ3Jcd3Mx LC/RZ5JBT5/ug== From: "Teddy Astie" Subject: =?utf-8?Q?[RFC=20PATCH=209/9]=20tools:=20Introduce=20abi-tool?= X-Mailer: git-send-email 2.50.1 X-Bm-Disclaimer: Yes X-Bm-Milter-Handled: 4ffbd6c1-ee69-4e1b-aabd-f977039bd3e2 X-Bm-Transport-Timestamp: 1755789958067 To: xen-devel@lists.xenproject.org Cc: "Teddy Astie" , "Andrew Cooper" , "Anthony PERARD" , "Michal Orzel" , "Jan Beulich" , "Julien Grall" , "=?utf-8?Q?Roger=20Pau=20Monn=C3=A9?=" , "Stefano Stabellini" Message-Id: <20b01deb2f53351103fce2e36a586a6a996a841b.1755785258.git.teddy.astie@vates.tech> In-Reply-To: References: X-Native-Encoded: 1 X-Report-Abuse: =?UTF-8?Q?Please=20forward=20a=20copy=20of=20this=20message,=20including=20all=20headers,=20to=20abuse@mandrill.com.=20You=20can=20also=20report=20abuse=20here:=20https://mandrillapp.com/contact/abuse=3Fid=3D30504962.d8fda27edc9d4cb49aff6b07b7f2a894?= X-Mandrill-User: md_30504962 Feedback-ID: 30504962:30504962.20250821:md Date: Thu, 21 Aug 2025 15:25:59 +0000 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity teddy.astie@vates.tech) (identity @mandrillapp.com) X-ZM-MESSAGEID: 1755789981333116600 Content-Type: text/plain; charset="utf-8" abi-tool is a small Rust tool that is able to parse ABI yaml files and generate C stubs for performing hypercalls. Signed-off-by: Teddy Astie --- Usage : ./abi-tool < abi.yaml > abi.h --- xen/tools/abi-tool/.gitignore | 1 + xen/tools/abi-tool/Cargo.lock | 145 ++++++++++++++++++++++++++ xen/tools/abi-tool/Cargo.toml | 11 ++ xen/tools/abi-tool/src/abi.rs | 23 ++++ xen/tools/abi-tool/src/c_lang.rs | 173 +++++++++++++++++++++++++++++++ xen/tools/abi-tool/src/main.rs | 17 +++ xen/tools/abi-tool/src/spec.rs | 61 +++++++++++ 7 files changed, 431 insertions(+) create mode 100644 xen/tools/abi-tool/.gitignore create mode 100644 xen/tools/abi-tool/Cargo.lock create mode 100644 xen/tools/abi-tool/Cargo.toml create mode 100644 xen/tools/abi-tool/src/abi.rs create mode 100644 xen/tools/abi-tool/src/c_lang.rs create mode 100644 xen/tools/abi-tool/src/main.rs create mode 100644 xen/tools/abi-tool/src/spec.rs diff --git a/xen/tools/abi-tool/.gitignore b/xen/tools/abi-tool/.gitignore new file mode 100644 index 0000000000..1de565933b --- /dev/null +++ b/xen/tools/abi-tool/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/xen/tools/abi-tool/Cargo.lock b/xen/tools/abi-tool/Cargo.lock new file mode 100644 index 0000000000..056a68f20f --- /dev/null +++ b/xen/tools/abi-tool/Cargo.lock @@ -0,0 +1,145 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version =3D 4 + +[[package]] +name =3D "abi-tool" +version =3D "0.1.0" +dependencies =3D [ + "anyhow", + "bimap", + "indexmap", + "serde", + "serde_yaml", +] + +[[package]] +name =3D "anyhow" +version =3D "1.0.98" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdc= d487" + +[[package]] +name =3D "arbitrary" +version =3D "1.4.1" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517= f223" + +[[package]] +name =3D "bimap" +version =3D "0.6.3" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46d= a4f7" +dependencies =3D [ + "serde", +] + +[[package]] +name =3D "equivalent" +version =3D "1.0.2" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe= 5c0f" + +[[package]] +name =3D "hashbrown" +version =3D "0.15.4" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521= e0d5" + +[[package]] +name =3D "indexmap" +version =3D "2.10.0" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78= a661" +dependencies =3D [ + "arbitrary", + "equivalent", + "hashbrown", + "serde", +] + +[[package]] +name =3D "itoa" +version =3D "1.0.15" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f26792= 8e2c" + +[[package]] +name =3D "proc-macro2" +version =3D "1.0.95" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7= f778" +dependencies =3D [ + "unicode-ident", +] + +[[package]] +name =3D "quote" +version =3D "1.0.40" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467= 248d" +dependencies =3D [ + "proc-macro2", +] + +[[package]] +name =3D "ryu" +version =3D "1.0.20" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829= 481f" + +[[package]] +name =3D "serde" +version =3D "1.0.219" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb7= 86b6" +dependencies =3D [ + "serde_derive", +] + +[[package]] +name =3D "serde_derive" +version =3D "1.0.219" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc= 2a00" +dependencies =3D [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name =3D "serde_yaml" +version =3D "0.9.34+deprecated" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d50= 4b47" +dependencies =3D [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name =3D "syn" +version =3D "2.0.104" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b43= 5a40" +dependencies =3D [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name =3D "unicode-ident" +version =3D "1.0.18" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c9= 6512" + +[[package]] +name =3D "unsafe-libyaml" +version =3D "0.2.11" +source =3D "registry+https://github.com/rust-lang/crates.io-index" +checksum =3D "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32= b861" diff --git a/xen/tools/abi-tool/Cargo.toml b/xen/tools/abi-tool/Cargo.toml new file mode 100644 index 0000000000..eee8ad18a9 --- /dev/null +++ b/xen/tools/abi-tool/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name =3D "abi-tool" +version =3D "0.1.0" +edition =3D "2024" + +[dependencies] +anyhow =3D "1.0.98" +bimap =3D { version =3D "0.6.3", features =3D ["serde"] } +indexmap =3D { version =3D "2.10.0", features =3D ["arbitrary", "serde"] } +serde =3D { version =3D "1.0.219", features =3D ["derive"] } +serde_yaml =3D "0.9.34" diff --git a/xen/tools/abi-tool/src/abi.rs b/xen/tools/abi-tool/src/abi.rs new file mode 100644 index 0000000000..9ca427e821 --- /dev/null +++ b/xen/tools/abi-tool/src/abi.rs @@ -0,0 +1,23 @@ +pub trait XenABI { + fn get_register_name(id: u8) -> &'static str; +} + +pub struct Amd64ABI; + +impl XenABI for Amd64ABI { + fn get_register_name(id: u8) -> &'static str { + match id { + 0 =3D> "rax", + 1 =3D> "rdi", + 2 =3D> "rsi", + 3 =3D> "r8", + 4 =3D> "r9", + 5 =3D> "r10", + 6 =3D> "r11", + 7 =3D> "r12", + 8 =3D> "r13", + + _ =3D> panic!("Unexpected register id: {id}"), + } + } +} diff --git a/xen/tools/abi-tool/src/c_lang.rs b/xen/tools/abi-tool/src/c_la= ng.rs new file mode 100644 index 0000000000..20389d305d --- /dev/null +++ b/xen/tools/abi-tool/src/c_lang.rs @@ -0,0 +1,173 @@ +use std::{collections::HashMap, fmt::Write}; + +use crate::{ + abi::{Amd64ABI, XenABI}, + spec::{AbiSpec, CType, HypercallOp}, +}; + +fn emit_register_variable( + w: &mut impl Write, + id: u8, + value: Option<&str>, +) -> anyhow::Result<()> { + write!( + w, + " register {ctype} reg{id} __asm__(\"{reg}\")", + ctype =3D if id =3D=3D 0 { "long" } else { "uint64_t" }, + reg =3D ABI::get_register_name(id) + )?; + if let Some(value) =3D value { + write!(w, " =3D {value}")?; + } + writeln!(w, ";")?; + + Ok(()) +} + +fn emit_hypercall( + w: &mut impl Write, + op: &HypercallOp, + ident: usize, + instruction: &str, +) -> anyhow::Result<()> { + let start =3D format!("{:ident$}__asm__ volatile (\"{instruction}\" ",= ""); + let pad =3D start.len(); + + /* All the exclusive inputs. */ + let reg_input =3D op + .input + .right_values() + .filter(|&input| !op.output.contains_right(input)) + .map(|input| format!("\"r\"(reg{input})")) + .collect::>() + .join(", "); + + /* Outputs that are also inputs are transformed into +r, the rest is = =3Dr */ + let reg_output =3D op + .output + .right_values() + .chain(&[0]) /* 0 is always a input/output */ + .map(|output| { + if *output =3D=3D 0 || op.input.contains_right(output) { + format!("\"+r\"(reg{output})") + } else { + format!("\"=3Dr\"(reg{output})") + } + }) + .collect::>() + .join(", "); + + writeln!(w, "{:ident$}{start}: {reg_output}", "")?; + writeln!(w, "{:ident$}{:pad$}: {reg_input}", "", "")?; + writeln!(w, "{:ident$}{:pad$}: \"memory\");", "", "")?; + + Ok(()) +} + +fn generate_hypercall_function( + w: &mut impl Write, + hypercall_name: &str, + op: &HypercallOp, + function_name: &str, + subop_index: Option, +) -> anyhow::Result<()> { + writeln!(w, "static inline")?; + + eprintln!("Processing {hypercall_name}.{function_name}"); + let annotations =3D op.c_lang.clone().unwrap_or_default(); + + assert!( + annotations.cstruct.is_some() || op.output.is_empty(), + "struct-less wrappers doesn't allow outputs, please use a C struct= ure" + ); + + // Match each input register with its C value. + let input_map: HashMap =3D op + .input + .iter() + .map(|(name, &id)| { + if annotations.params.contains_key(name) { + (id, name.clone()) + } else { + // Struct may have a custom mapping + let field =3D annotations.mapping.get(name).unwrap_or(name= ); + + (id, format!("param->{field}")) + } + }) + .collect(); + + write!(w, "long {function_name}(enum xen_hypercall_vendor vendor")?; + let pad =3D 6 + function_name.len(); + + if let Some(cstruct) =3D &annotations.cstruct { + write!(w, ",\n{:pad$}struct {cstruct} *param", "",)?; + } + + for (name, CType(ctype)) in &annotations.params { + write!(w, ",\n{:pad$}{ctype} {name}", "",)?; + } + + writeln!(w, ")")?; + + writeln!(w, "{{")?; + + for id in op.used_registers() { + // If it is a input, we need to set it here. + let value =3D match (id, subop_index) { + /* Hypercall index */ + (0, _) =3D> Some(format!( + "__HYPERVISOR_FASTABI_MASK | __HYPERVISOR_{hypercall_name}= _op" + )), + /* Sub-operation index */ + (1, Some(subop_index)) =3D> Some(format!("{subop_index}")), + /* Other input parameter */ + (id, _) =3D> input_map.get(&id).cloned(), + }; + + emit_register_variable::(w, id, value.as_deref())?; + } + writeln!(w)?; + + writeln!(w, " if ( vendor =3D=3D Intel )")?; + emit_hypercall::(w, op, 4, "vmcall")?; + writeln!(w, " else")?; + emit_hypercall::(w, op, 4, "vmmcall")?; + + writeln!(w, "")?; + + for (field, output) in &op.output { + let field =3D annotations.mapping.get(field).unwrap_or(field); + + writeln!(w, " param->{field} =3D reg{output};")?; + } + + writeln!(w, " return reg0;")?; + + writeln!(w, "}}")?; + + Ok(()) +} + +pub fn generate_code(w: &mut impl Write, spec: AbiSpec) -> anyhow::Result<= ()> { + writeln!(w, "/* SPDX-License-Identifier: MIT */")?; + writeln!(w, "/* AUTOGENERATED. DO NOT MODIFY */")?; + writeln!(w)?; + + if let Some(op) =3D spec.direct { + let function_name =3D ["xen_hypercall", &spec.name].join("_"); + + generate_hypercall_function(w, &spec.name, &op, &function_name, No= ne)?; + writeln!(w)?; + } + + for (name, mut subop) in spec.subops { + let function_name =3D ["xen_hypercall", &spec.name, &name].join("_= "); + subop.op.input.insert("subop_index".to_string(), 1); + + generate_hypercall_function(w, &spec.name, &subop.op, &function_na= me, Some(subop.index))?; + writeln!(w)?; + } + + Ok(()) +} diff --git a/xen/tools/abi-tool/src/main.rs b/xen/tools/abi-tool/src/main.rs new file mode 100644 index 0000000000..dda85c24d5 --- /dev/null +++ b/xen/tools/abi-tool/src/main.rs @@ -0,0 +1,17 @@ +use std::io::{Read, stdin}; + +pub mod abi; +pub mod c_lang; +pub mod spec; + +fn main() { + let mut buffer =3D String::new(); + stdin().read_to_string(&mut buffer).unwrap(); + + let abi_spec: spec::AbiSpec =3D serde_yaml::from_str(&buffer).unwrap(); + + let mut buffer =3D String::new(); + + c_lang::generate_code(&mut buffer, abi_spec).unwrap(); + print!("{buffer}"); +} diff --git a/xen/tools/abi-tool/src/spec.rs b/xen/tools/abi-tool/src/spec.rs new file mode 100644 index 0000000000..e5fb2c85d2 --- /dev/null +++ b/xen/tools/abi-tool/src/spec.rs @@ -0,0 +1,61 @@ +use std::collections::{BTreeSet, HashMap}; + +use bimap::BiBTreeMap; +use indexmap::IndexMap; /* use indexmap to keep consistent ordering */ +use serde::Deserialize; + +fn default_ctype() -> String { + "uint64_t".into() +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Hash)] +pub struct CType(#[serde(default =3D "default_ctype")] pub String); + +#[derive(Clone, Debug, Default, Deserialize)] +pub struct CAnnotations { + #[serde(rename =3D "struct")] + pub cstruct: Option, + #[serde(default)] + pub mapping: HashMap, + #[serde(default)] + pub params: HashMap, +} + +#[derive(Debug, Deserialize)] +pub struct HypercallOp { + #[serde(default)] + pub input: BiBTreeMap, + #[serde(default)] + pub output: BiBTreeMap, + + pub c_lang: Option, +} + +impl HypercallOp { + pub fn used_registers(&self) -> BTreeSet { + self.input + .right_values() + .chain(self.output.right_values()) + .chain(&[0]) + .cloned() + .collect() + } +} + +#[derive(Debug, Deserialize)] +pub struct HypercallSubOp { + pub index: u32, + #[serde(flatten)] + pub op: HypercallOp, +} + +#[derive(Debug, Deserialize)] +pub struct AbiSpec { + pub hypercall_index: u32, + pub name: String, + + pub direct: Option, + + #[serde(default)] + pub subops: IndexMap, +} --=20 2.50.1 Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech