diff --git a/.gitignore b/.gitignore index ea8c4bf..06f5fec 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +/.idea +/.vscode diff --git a/Cargo.lock b/Cargo.lock index f002891..6ff4280 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,22 +1,16 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -34,9 +28,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -49,36 +43,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -89,28 +83,28 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.4", + "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -127,35 +121,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" - -[[package]] -name = "c2rust-bitfields" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b43c3f07ab0ef604fa6f595aa46ec2f8a22172c975e186f6f5bf9829a3b72c41" -dependencies = [ - "c2rust-bitfields-derive", -] - -[[package]] -name = "c2rust-bitfields-derive" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3cbc102e2597c9744c8bd8c15915d554300601c91a079430d309816b0912545" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.1.10" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -171,9 +148,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "crc32fast" @@ -221,12 +198,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -242,9 +219,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "hashbrown" @@ -252,12 +229,6 @@ version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "humantime" version = "2.1.0" @@ -266,9 +237,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -290,20 +261,17 @@ dependencies = [ "nix", "thiserror", "tokio", - "uuid", ] [[package]] name = "krata-xenclient" version = "0.0.23" dependencies = [ - "async-trait", "env_logger", "indexmap", "krata-xencall", "krata-xenplatform", "krata-xenstore", - "libc", "log", "regex", "thiserror", @@ -337,11 +305,8 @@ name = "krata-xenplatform" version = "0.0.23" dependencies = [ "async-trait", - "c2rust-bitfields", "elf", - "env_logger", "flate2", - "indexmap", "krata-xencall", "libc", "log", @@ -369,9 +334,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.162" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "lock_api" @@ -406,15 +371,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -426,14 +382,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", "wasi", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -450,9 +405,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] @@ -482,39 +437,39 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags", ] @@ -533,9 +488,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -560,6 +515,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -583,30 +544,19 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "syn" -version = "1.0.109" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -615,29 +565,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.65" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.65" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -648,7 +598,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -659,14 +609,14 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "utf8parse" @@ -698,6 +648,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index e6610dd..e473f12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ repository = "https://github.com/edera-dev/krata" [workspace.dependencies] async-trait = "0.1.83" byteorder = "1" -c2rust-bitfields = "0.18.0" +c2rust-bitfields = "0.19.0" elf = "0.7.4" env_logger = "0.11.5" flate2 = "1.0" @@ -29,13 +29,9 @@ memchr = "2" nix = "0.29.0" regex = "1.11.1" slice-copy = "0.3.0" -thiserror = "1.0" +thiserror = "2.0.7" xz2 = "0.1" -[workspace.dependencies.serde] -version = "1.0.209" -features = ["derive"] - [workspace.dependencies.tokio] version = "1.41.1" features = ["full"] diff --git a/crates/xen/xencall/Cargo.toml b/crates/xen/xencall/Cargo.toml index aad9050..4b69839 100644 --- a/crates/xen/xencall/Cargo.toml +++ b/crates/xen/xencall/Cargo.toml @@ -14,7 +14,6 @@ log = { workspace = true } nix = { workspace = true, features = ["ioctl"] } thiserror = { workspace = true } tokio = { workspace = true } -uuid = { workspace = true } [lib] name = "xencall" diff --git a/crates/xen/xencall/src/error.rs b/crates/xen/xencall/src/error.rs index f6633c2..7e7a1ac 100644 --- a/crates/xen/xencall/src/error.rs +++ b/crates/xen/xencall/src/error.rs @@ -1,5 +1,7 @@ use std::io; +use tokio::task::JoinError; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error("version of xen is not supported")] @@ -16,6 +18,8 @@ pub enum Error { MmapBatchFailed(nix::errno::Errno), #[error("specified value is too long")] ValueTooLong, + #[error("failed to join async task: {0}")] + JoinError(JoinError), } pub type Result = std::result::Result; diff --git a/crates/xen/xencall/src/lib.rs b/crates/xen/xencall/src/lib.rs index 4898607..22d9285 100644 --- a/crates/xen/xencall/src/lib.rs +++ b/crates/xen/xencall/src/lib.rs @@ -35,7 +35,6 @@ use sys::{ XEN_SYSCTL_PHYSINFO, XEN_SYSCTL_PM_OP, XEN_SYSCTL_PM_OP_DISABLE_TURBO, XEN_SYSCTL_PM_OP_ENABLE_TURBO, XEN_SYSCTL_PM_OP_SET_CPUFREQ_GOV, XEN_SYSCTL_READCONSOLE, }; -use tokio::sync::Semaphore; use tokio::time::sleep; use std::fs::{File, OpenOptions}; @@ -46,7 +45,6 @@ use std::slice; #[derive(Clone)] pub struct XenCall { pub handle: Arc, - semaphore: Arc, domctl_interface_version: u32, sysctl_interface_version: u32, } @@ -62,7 +60,6 @@ impl XenCall { let sysctl_interface_version = XenCall::detect_sysctl_interface_version(&handle)?; Ok(XenCall { handle: Arc::new(handle), - semaphore: Arc::new(Semaphore::new(1)), domctl_interface_version, sysctl_interface_version, }) @@ -119,7 +116,6 @@ impl XenCall { } pub async fn mmap(&self, addr: u64, len: u64) -> Option { - let _permit = self.semaphore.acquire().await.ok()?; trace!( "call fd={} mmap addr={:#x} len={}", self.handle.as_raw_fd(), @@ -127,14 +123,20 @@ impl XenCall { len ); unsafe { - let ptr = mmap( - addr as *mut c_void, - len as usize, - PROT_READ | PROT_WRITE, - MAP_SHARED, - self.handle.as_raw_fd(), - 0, - ); + let handle = self.handle.clone(); + let ptr = tokio::task::spawn_blocking(move || { + mmap( + addr as *mut c_void, + len as usize, + PROT_READ | PROT_WRITE, + MAP_SHARED, + handle.as_raw_fd(), + 0, + ) as u64 + }) + .await + .map_err(Error::JoinError) + .ok()? as *mut c_void; if ptr == MAP_FAILED { None } else { @@ -151,18 +153,22 @@ impl XenCall { } pub async fn hypercall(&self, op: c_ulong, arg: [c_ulong; 5]) -> Result { - let _permit = self.semaphore.acquire().await?; trace!( "call fd={} hypercall op={:#x} arg={:?}", self.handle.as_raw_fd(), op, arg ); - unsafe { + + let handle = self.handle.clone(); + tokio::task::spawn_blocking(move || unsafe { let mut call = Hypercall { op, arg }; - let result = sys::hypercall(self.handle.as_raw_fd(), &mut call)?; - Ok(result as c_long) - } + sys::hypercall(handle.as_raw_fd(), &mut call) + .map(|x| x as c_long) + .map_err(|e| e.into()) + }) + .await + .map_err(Error::JoinError)? } pub async fn hypercall0(&self, op: c_ulong) -> Result { @@ -234,18 +240,21 @@ impl XenCall { num: u64, addr: u64, ) -> Result<()> { - let _permit = self.semaphore.acquire().await?; - let mut resource = MmapResource { - dom: domid as u16, - typ, - id, - idx, - num, - addr, - }; - unsafe { - sys::mmap_resource(self.handle.as_raw_fd(), &mut resource)?; - } + let handle = self.handle.clone(); + tokio::task::spawn_blocking(move || { + let mut resource = MmapResource { + dom: domid as u16, + typ, + id, + idx, + num, + addr, + }; + + unsafe { sys::mmap_resource(handle.as_raw_fd(), &mut resource) } + }) + .await + .map_err(Error::JoinError)??; Ok(()) } @@ -256,7 +265,6 @@ impl XenCall { addr: u64, mfns: Vec, ) -> Result { - let _permit = self.semaphore.acquire().await?; trace!( "call fd={} mmap_batch domid={} num={} addr={:#x} mfns={:?}", self.handle.as_raw_fd(), @@ -322,7 +330,7 @@ impl XenCall { break; } - let count = result.unwrap(); + let count = result?; if count <= 0 { break; } @@ -330,7 +338,7 @@ impl XenCall { return Ok(paged as c_long); } - Ok(result.unwrap() as c_long) + Ok(result? as c_long) } } @@ -618,6 +626,11 @@ impl XenCall { } pub async fn get_memory_map(&self, max_entries: u32) -> Result> { + trace!( + "fd={} get_memory_map max_entries={}", + self.handle.as_raw_fd(), + max_entries, + ); let mut memory_map = MemoryMap { count: max_entries, buffer: 0, diff --git a/crates/xen/xencall/src/sys.rs b/crates/xen/xencall/src/sys.rs index 049a05d..10e7ae5 100644 --- a/crates/xen/xencall/src/sys.rs +++ b/crates/xen/xencall/src/sys.rs @@ -205,6 +205,16 @@ pub const XEN_DOMCTL_GDBSX_PAUSEVCPU: u32 = 1001; pub const XEN_DOMCTL_GDBSX_UNPAUSEVCPU: u32 = 1002; pub const XEN_DOMCTL_GDBSX_DOMSTATUS: u32 = 1003; +pub const XEN_DOMINF_DYING: u32 = 1u32 << 0; +pub const XEN_DOMINF_HVM_GUEST: u32 = 1u32 << 1; +pub const XEN_DOMINF_SHUTDOWN: u32 = 1u32 << 2; +pub const XEN_DOMINF_PAUSED: u32 = 1u32 << 3; +pub const XEN_DOMINF_BLOCKED: u32 = 1u32 << 4; +pub const XEN_DOMINF_RUNNING: u32 = 1u32 << 5; +pub const XEN_DOMINF_DEBUGGED: u32 = 1u32 << 6; +pub const XEN_DOMINF_XS_DOMAIN: u32 = 1u32 << 7; +pub const XEN_DOMINF_HAP: u32 = 1u32 << 8; + #[repr(C)] #[derive(Copy, Clone)] pub struct DomCtl { diff --git a/crates/xen/xenclient/Cargo.toml b/crates/xen/xenclient/Cargo.toml index fd14611..6fd2fca 100644 --- a/crates/xen/xenclient/Cargo.toml +++ b/crates/xen/xenclient/Cargo.toml @@ -9,9 +9,7 @@ edition = "2021" resolver = "2" [dependencies] -async-trait = { workspace = true } indexmap = { workspace = true } -libc = { workspace = true } log = { workspace = true } krata-xencall = { path = "../xencall", version = "^0.0.23" } krata-xenplatform = { path = "../xenplatform", version = "^0.0.23" } diff --git a/crates/xen/xenevtchn/src/error.rs b/crates/xen/xenevtchn/src/error.rs index ec9e729..e1faa98 100644 --- a/crates/xen/xenevtchn/src/error.rs +++ b/crates/xen/xenevtchn/src/error.rs @@ -12,6 +12,8 @@ pub enum Error { LockAcquireFailed, #[error("event port already in use")] PortInUse, + #[error("failed to join blocking task")] + BlockingTaskJoin, } pub type Result = std::result::Result; diff --git a/crates/xen/xenevtchn/src/lib.rs b/crates/xen/xenevtchn/src/lib.rs index 61a4e4f..f22e8d2 100644 --- a/crates/xen/xenevtchn/src/lib.rs +++ b/crates/xen/xenevtchn/src/lib.rs @@ -3,7 +3,10 @@ pub mod raw; pub mod sys; use crate::error::{Error, Result}; -use crate::sys::{BindInterdomain, BindUnboundPort, BindVirq, Notify, UnbindPort}; +use crate::sys::{ + BindInterdomainRequest, BindUnboundPortRequest, BindVirqRequest, NotifyRequest, + UnbindPortRequest, +}; use crate::raw::EVENT_CHANNEL_DEVICE; use byteorder::{LittleEndian, ReadBytesExt}; @@ -16,12 +19,9 @@ use std::os::raw::c_void; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use tokio::fs::{File, OpenOptions}; -use tokio::sync::mpsc::{channel, Receiver, Sender}; -use tokio::sync::{Mutex, RwLock}; +use tokio::sync::{Mutex, Notify}; -const CHANNEL_QUEUE_LEN: usize = 30; - -type WakeMap = Arc>>>; +type WakeMap = Arc>>>; #[derive(Clone)] pub struct EventChannelService { @@ -32,7 +32,7 @@ pub struct EventChannelService { pub struct BoundEventChannel { pub local_port: u32, - pub receiver: Receiver, + pub receiver: Arc, pub service: EventChannelService, } @@ -59,7 +59,7 @@ impl EventChannelService { .write(true) .open(EVENT_CHANNEL_DEVICE) .await?; - let wakes = Arc::new(RwLock::new(HashMap::new())); + let wakes = Arc::new(Mutex::new(HashMap::new())); let flag = Arc::new(AtomicBool::new(false)); let processor = EventChannelProcessor { flag: flag.clone(), @@ -77,43 +77,52 @@ impl EventChannelService { pub async fn bind_virq(&self, virq: u32) -> Result { let handle = self.handle.lock().await; - unsafe { - let mut request = BindVirq { virq }; - Ok(sys::bind_virq(handle.as_raw_fd(), &mut request)? as u32) - } + let fd = handle.as_raw_fd(); + let mut request = BindVirqRequest { virq }; + let result = + tokio::task::spawn_blocking(move || unsafe { sys::bind_virq(fd, &mut request) }) + .await + .map_err(|_| Error::BlockingTaskJoin)?? as u32; + Ok(result) } pub async fn bind_interdomain(&self, domid: u32, port: u32) -> Result { let handle = self.handle.lock().await; - unsafe { - let mut request = BindInterdomain { - remote_domain: domid, - remote_port: port, - }; - Ok(sys::bind_interdomain(handle.as_raw_fd(), &mut request)? as u32) - } + let fd = handle.as_raw_fd(); + let mut request = BindInterdomainRequest { + remote_domain: domid, + remote_port: port, + }; + let result = + tokio::task::spawn_blocking(move || unsafe { sys::bind_interdomain(fd, &mut request) }) + .await + .map_err(|_| Error::BlockingTaskJoin)?? as u32; + Ok(result) } pub async fn bind_unbound_port(&self, domid: u32) -> Result { let handle = self.handle.lock().await; - unsafe { - let mut request = BindUnboundPort { - remote_domain: domid, - }; - Ok(sys::bind_unbound_port(handle.as_raw_fd(), &mut request)? as u32) - } + let fd = handle.as_raw_fd(); + let mut request = BindUnboundPortRequest { + remote_domain: domid, + }; + let result = tokio::task::spawn_blocking(move || unsafe { + sys::bind_unbound_port(fd, &mut request) + }) + .await + .map_err(|_| Error::BlockingTaskJoin)?? as u32; + Ok(result) } pub async fn unmask(&self, port: u32) -> Result<()> { let handle = self.handle.lock().await; let mut port = port; - let result = unsafe { - libc::write( - handle.as_raw_fd(), - &mut port as *mut u32 as *mut c_void, - size_of::(), - ) - }; + let fd = handle.as_raw_fd(); + let result = tokio::task::spawn_blocking(move || unsafe { + libc::write(fd, &mut port as *mut u32 as *mut c_void, size_of::()) + }) + .await + .map_err(|_| Error::BlockingTaskJoin)?; if result != size_of::() as isize { return Err(Error::Io(std::io::Error::from_raw_os_error(result as i32))); } @@ -122,25 +131,32 @@ impl EventChannelService { pub async fn unbind(&self, port: u32) -> Result { let handle = self.handle.lock().await; - unsafe { - let mut request = UnbindPort { port }; - let result = sys::unbind(handle.as_raw_fd(), &mut request)? as u32; - self.wakes.write().await.remove(&port); - Ok(result) - } + let mut request = UnbindPortRequest { port }; + let fd = handle.as_raw_fd(); + let result = tokio::task::spawn_blocking(move || unsafe { sys::unbind(fd, &mut request) }) + .await + .map_err(|_| Error::BlockingTaskJoin)?? as u32; + self.wakes.lock().await.remove(&port); + Ok(result) } pub async fn notify(&self, port: u32) -> Result { let handle = self.handle.lock().await; - unsafe { - let mut request = Notify { port }; - Ok(sys::notify(handle.as_raw_fd(), &mut request)? as u32) - } + let mut request = NotifyRequest { port }; + let fd = handle.as_raw_fd(); + let result = tokio::task::spawn_blocking(move || unsafe { sys::notify(fd, &mut request) }) + .await + .map_err(|_| Error::BlockingTaskJoin)?? as u32; + Ok(result) } pub async fn reset(&self) -> Result { let handle = self.handle.lock().await; - unsafe { Ok(sys::reset(handle.as_raw_fd())? as u32) } + let fd = handle.as_raw_fd(); + let result = tokio::task::spawn_blocking(move || unsafe { sys::reset(fd) }) + .await + .map_err(|_| Error::BlockingTaskJoin)?? as u32; + Ok(result) } pub async fn bind(&self, domid: u32, port: u32) -> Result { @@ -154,17 +170,15 @@ impl EventChannelService { Ok(bound) } - pub async fn subscribe(&self, port: u32) -> Result> { - let mut wakes = self.wakes.write().await; + pub async fn subscribe(&self, port: u32) -> Result> { + let mut wakes = self.wakes.lock().await; let receiver = match wakes.entry(port) { - Entry::Occupied(_) => { - return Err(Error::PortInUse); - } + Entry::Occupied(entry) => entry.get().clone(), Entry::Vacant(entry) => { - let (sender, receiver) = channel::(CHANNEL_QUEUE_LEN); - entry.insert(sender); - receiver + let notify = Arc::new(Notify::new()); + entry.insert(notify.clone()); + notify } }; Ok(receiver) @@ -194,9 +208,16 @@ impl EventChannelProcessor { pub fn process(&mut self) -> Result<()> { loop { let port = self.handle.read_u32::()?; - if let Some(wake) = self.wakes.blocking_read().get(&port) { - let _ = wake.try_send(port); - } + let receiver = match self.wakes.blocking_lock().entry(port) { + Entry::Occupied(entry) => entry.get().clone(), + + Entry::Vacant(entry) => { + let notify = Arc::new(Notify::new()); + entry.insert(notify.clone()); + notify + } + }; + receiver.notify_one(); } } } diff --git a/crates/xen/xenevtchn/src/raw.rs b/crates/xen/xenevtchn/src/raw.rs index 763b712..a2e727a 100644 --- a/crates/xen/xenevtchn/src/raw.rs +++ b/crates/xen/xenevtchn/src/raw.rs @@ -32,13 +32,13 @@ impl RawEventChannelService { pub fn bind_virq(&self, virq: u32) -> Result { let handle = self.handle.lock().map_err(|_| Error::LockAcquireFailed)?; - let mut request = sys::BindVirq { virq }; + let mut request = sys::BindVirqRequest { virq }; Ok(unsafe { sys::bind_virq(handle.as_raw_fd(), &mut request)? as u32 }) } pub fn bind_interdomain(&self, domid: u32, port: u32) -> Result { let handle = self.handle.lock().map_err(|_| Error::LockAcquireFailed)?; - let mut request = sys::BindInterdomain { + let mut request = sys::BindInterdomainRequest { remote_domain: domid, remote_port: port, }; @@ -47,7 +47,7 @@ impl RawEventChannelService { pub fn bind_unbound_port(&self, domid: u32) -> Result { let handle = self.handle.lock().map_err(|_| Error::LockAcquireFailed)?; - let mut request = sys::BindUnboundPort { + let mut request = sys::BindUnboundPortRequest { remote_domain: domid, }; Ok(unsafe { sys::bind_unbound_port(handle.as_raw_fd(), &mut request)? as u32 }) @@ -55,13 +55,13 @@ impl RawEventChannelService { pub fn unbind(&self, port: u32) -> Result { let handle = self.handle.lock().map_err(|_| Error::LockAcquireFailed)?; - let mut request = sys::UnbindPort { port }; + let mut request = sys::UnbindPortRequest { port }; Ok(unsafe { sys::unbind(handle.as_raw_fd(), &mut request)? as u32 }) } pub fn notify(&self, port: u32) -> Result { let handle = self.handle.lock().map_err(|_| Error::LockAcquireFailed)?; - let mut request = sys::Notify { port }; + let mut request = sys::NotifyRequest { port }; Ok(unsafe { sys::notify(handle.as_raw_fd(), &mut request)? as u32 }) } diff --git a/crates/xen/xenevtchn/src/sys.rs b/crates/xen/xenevtchn/src/sys.rs index 22154a3..67dbef1 100644 --- a/crates/xen/xenevtchn/src/sys.rs +++ b/crates/xen/xenevtchn/src/sys.rs @@ -2,34 +2,34 @@ use nix::{ioctl_none, ioctl_readwrite_bad}; use std::ffi::c_uint; #[repr(C)] -pub struct BindVirq { +pub struct BindVirqRequest { pub virq: c_uint, } #[repr(C)] -pub struct BindInterdomain { +pub struct BindInterdomainRequest { pub remote_domain: c_uint, pub remote_port: c_uint, } #[repr(C)] -pub struct BindUnboundPort { +pub struct BindUnboundPortRequest { pub remote_domain: c_uint, } #[repr(C)] -pub struct UnbindPort { +pub struct UnbindPortRequest { pub port: c_uint, } #[repr(C)] -pub struct Notify { +pub struct NotifyRequest { pub port: c_uint, } -ioctl_readwrite_bad!(bind_virq, 0x44500, BindVirq); -ioctl_readwrite_bad!(bind_interdomain, 0x84501, BindInterdomain); -ioctl_readwrite_bad!(bind_unbound_port, 0x44503, BindUnboundPort); -ioctl_readwrite_bad!(unbind, 0x44502, UnbindPort); -ioctl_readwrite_bad!(notify, 0x44504, Notify); +ioctl_readwrite_bad!(bind_virq, 0x44500, BindVirqRequest); +ioctl_readwrite_bad!(bind_interdomain, 0x84501, BindInterdomainRequest); +ioctl_readwrite_bad!(bind_unbound_port, 0x44503, BindUnboundPortRequest); +ioctl_readwrite_bad!(unbind, 0x44502, UnbindPortRequest); +ioctl_readwrite_bad!(notify, 0x44504, NotifyRequest); ioctl_none!(reset, 0x4505, 5); diff --git a/crates/xen/xenplatform/Cargo.toml b/crates/xen/xenplatform/Cargo.toml index 98700e5..b408940 100644 --- a/crates/xen/xenplatform/Cargo.toml +++ b/crates/xen/xenplatform/Cargo.toml @@ -10,10 +10,8 @@ resolver = "2" [dependencies] async-trait = { workspace = true } -c2rust-bitfields = { workspace = true } elf = { workspace = true } flate2 = { workspace = true } -indexmap = { workspace = true } libc = { workspace = true } log = { workspace = true } krata-xencall = { path = "../xencall", version = "^0.0.23" } @@ -27,7 +25,6 @@ uuid = { workspace = true } xz2 = { workspace = true } [dev-dependencies] -env_logger = { workspace = true } tokio = { workspace = true } [lib] diff --git a/crates/xen/xenplatform/src/boot.rs b/crates/xen/xenplatform/src/boot.rs index 58d184d..b766846 100644 --- a/crates/xen/xenplatform/src/boot.rs +++ b/crates/xen/xenplatform/src/boot.rs @@ -63,7 +63,7 @@ impl BootDomain { } let local_page_size: u32 = (1i64 << XEN_PAGE_SHIFT) as u32; - let pages = (size + local_page_size as u64 - 1) / local_page_size as u64; + let pages = size.div_ceil(local_page_size as u64); let start = self.virt_alloc_end; let mut segment = DomainSegment { diff --git a/crates/xen/xenplatform/src/unsupported.rs b/crates/xen/xenplatform/src/unsupported.rs index dce15ce..64fe07b 100644 --- a/crates/xen/xenplatform/src/unsupported.rs +++ b/crates/xen/xenplatform/src/unsupported.rs @@ -44,19 +44,11 @@ impl BootSetupPlatform for UnsupportedPlatform { panic!("unsupported platform") } - async fn alloc_p2m_segment(&mut self, _: &mut BootDomain) -> Result> { - panic!("unsupported platform") - } - async fn alloc_page_tables(&mut self, _: &mut BootDomain) -> Result> { panic!("unsupported platform") } - async fn setup_page_tables(&mut self, _: &mut BootDomain) -> Result<()> { - panic!("unsupported platform") - } - - async fn setup_hypercall_page(&mut self, _: &mut BootDomain) -> Result<()> { + async fn alloc_p2m_segment(&mut self, _: &mut BootDomain) -> Result> { panic!("unsupported platform") } @@ -64,6 +56,10 @@ impl BootSetupPlatform for UnsupportedPlatform { panic!("unsupported platform") } + async fn setup_page_tables(&mut self, _: &mut BootDomain) -> Result<()> { + panic!("unsupported platform") + } + async fn setup_shared_info(&mut self, _: &mut BootDomain, _: u64) -> Result<()> { panic!("unsupported platform") } @@ -76,11 +72,15 @@ impl BootSetupPlatform for UnsupportedPlatform { panic!("unsupported platform") } + async fn gnttab_seed(&mut self, _: &mut BootDomain) -> Result<()> { + panic!("unsupported platform") + } + async fn vcpu(&mut self, _: &mut BootDomain) -> Result<()> { panic!("unsupported platform") } - async fn gnttab_seed(&mut self, _: &mut BootDomain) -> Result<()> { + async fn setup_hypercall_page(&mut self, _: &mut BootDomain) -> Result<()> { panic!("unsupported platform") } } diff --git a/crates/xen/xenplatform/src/x86pv.rs b/crates/xen/xenplatform/src/x86pv.rs index c9650bd..51492d8 100644 --- a/crates/xen/xenplatform/src/x86pv.rs +++ b/crates/xen/xenplatform/src/x86pv.rs @@ -474,31 +474,6 @@ impl BootSetupPlatform for X86PvPlatform { Ok(()) } - async fn alloc_p2m_segment( - &mut self, - domain: &mut BootDomain, - ) -> Result> { - let mut p2m_alloc_size = - ((domain.phys.p2m_size() * 8) + X86_PAGE_SIZE - 1) & !(X86_PAGE_SIZE - 1); - let from = domain.image_info.virt_p2m_base; - let to = from + p2m_alloc_size - 1; - let m = self.count_page_tables(domain, from, to, domain.pfn_alloc_end)?; - - let pgtables: usize; - { - let map = &mut self.table.mappings[m]; - map.area.pfn = domain.pfn_alloc_end; - for lvl_idx in 0..4 { - map.levels[lvl_idx].pfn += p2m_alloc_size >> X86_PAGE_SHIFT; - } - pgtables = map.area.pgtables; - } - self.table.mappings_count += 1; - p2m_alloc_size += (pgtables << X86_PAGE_SHIFT) as u64; - let p2m_segment = domain.alloc_segment(0, p2m_alloc_size).await?; - Ok(Some(p2m_segment)) - } - async fn alloc_page_tables( &mut self, domain: &mut BootDomain, @@ -533,6 +508,61 @@ impl BootSetupPlatform for X86PvPlatform { Ok(Some(segment)) } + async fn alloc_p2m_segment( + &mut self, + domain: &mut BootDomain, + ) -> Result> { + let mut p2m_alloc_size = + ((domain.phys.p2m_size() * 8) + X86_PAGE_SIZE - 1) & !(X86_PAGE_SIZE - 1); + let from = domain.image_info.virt_p2m_base; + let to = from + p2m_alloc_size - 1; + let m = self.count_page_tables(domain, from, to, domain.pfn_alloc_end)?; + + let pgtables: usize; + { + let map = &mut self.table.mappings[m]; + map.area.pfn = domain.pfn_alloc_end; + for lvl_idx in 0..4 { + map.levels[lvl_idx].pfn += p2m_alloc_size >> X86_PAGE_SHIFT; + } + pgtables = map.area.pgtables; + } + self.table.mappings_count += 1; + p2m_alloc_size += (pgtables << X86_PAGE_SHIFT) as u64; + let p2m_segment = domain.alloc_segment(0, p2m_alloc_size).await?; + Ok(Some(p2m_segment)) + } + + async fn alloc_magic_pages(&mut self, domain: &mut BootDomain) -> Result<()> { + if domain.image_info.virt_p2m_base >= domain.image_info.virt_base + || (domain.image_info.virt_p2m_base & ((1 << self.page_shift()) - 1)) != 0 + { + self.p2m_segment = self.alloc_p2m_segment(domain).await?; + } + self.start_info_segment = Some(domain.alloc_page()?); + self.xenstore_segment = Some(domain.alloc_page()?); + domain.store_mfn = domain.phys.p2m[self.xenstore_segment.as_ref().unwrap().pfn as usize]; + let evtchn = domain.call.evtchn_alloc_unbound(domain.domid, 0).await?; + let page = domain.alloc_page()?; + domain.console_evtchn = evtchn; + domain.console_mfn = domain.phys.p2m[page.pfn as usize]; + self.page_table_segment = self.alloc_page_tables(domain).await?; + self.boot_stack_segment = Some(domain.alloc_page()?); + + if domain.virt_pgtab_end > 0 { + domain.alloc_padding_pages(domain.virt_pgtab_end)?; + } + + if self.p2m_segment.is_none() { + if let Some(mut p2m_segment) = self.alloc_p2m_segment(domain).await? { + p2m_segment.vstart = domain.image_info.virt_p2m_base; + self.p2m_segment = Some(p2m_segment); + } + } + + Ok(()) + } + async fn setup_page_tables(&mut self, domain: &mut BootDomain) -> Result<()> { let p2m_segment = self .p2m_segment @@ -594,47 +624,6 @@ impl BootSetupPlatform for X86PvPlatform { Ok(()) } - async fn setup_hypercall_page(&mut self, domain: &mut BootDomain) -> Result<()> { - if domain.image_info.virt_hypercall == u64::MAX { - return Ok(()); - } - let pfn = - (domain.image_info.virt_hypercall - domain.image_info.virt_base) >> self.page_shift(); - let mfn = domain.phys.p2m[pfn as usize]; - domain.call.hypercall_init(domain.domid, mfn).await?; - Ok(()) - } - - async fn alloc_magic_pages(&mut self, domain: &mut BootDomain) -> Result<()> { - if domain.image_info.virt_p2m_base >= domain.image_info.virt_base - || (domain.image_info.virt_p2m_base & ((1 << self.page_shift()) - 1)) != 0 - { - self.p2m_segment = self.alloc_p2m_segment(domain).await?; - } - self.start_info_segment = Some(domain.alloc_page()?); - self.xenstore_segment = Some(domain.alloc_page()?); - domain.store_mfn = domain.phys.p2m[self.xenstore_segment.as_ref().unwrap().pfn as usize]; - let evtchn = domain.call.evtchn_alloc_unbound(domain.domid, 0).await?; - let page = domain.alloc_page()?; - domain.console_evtchn = evtchn; - domain.console_mfn = domain.phys.p2m[page.pfn as usize]; - self.page_table_segment = self.alloc_page_tables(domain).await?; - self.boot_stack_segment = Some(domain.alloc_page()?); - - if domain.virt_pgtab_end > 0 { - domain.alloc_padding_pages(domain.virt_pgtab_end)?; - } - - if self.p2m_segment.is_none() { - if let Some(mut p2m_segment) = self.alloc_p2m_segment(domain).await? { - p2m_segment.vstart = domain.image_info.virt_p2m_base; - self.p2m_segment = Some(p2m_segment); - } - } - - Ok(()) - } - async fn setup_shared_info( &mut self, domain: &mut BootDomain, @@ -739,6 +728,39 @@ impl BootSetupPlatform for X86PvPlatform { Ok(()) } + async fn gnttab_seed(&mut self, domain: &mut BootDomain) -> Result<()> { + let xenstore_segment = self + .xenstore_segment + .as_ref() + .ok_or(Error::MemorySetupFailed("xenstore_segment missing"))?; + + let console_gfn = domain.console_mfn as usize; + let xenstore_gfn = domain.phys.p2m[xenstore_segment.pfn as usize]; + let addr = domain + .call + .mmap(0, 1 << XEN_PAGE_SHIFT) + .await + .ok_or(Error::MmapFailed)?; + domain + .call + .map_resource(domain.domid, 1, 0, 0, 1, addr) + .await?; + let entries = unsafe { slice::from_raw_parts_mut(addr as *mut GrantEntry, 2) }; + entries[0].flags = 1 << 0; + entries[0].domid = 0; + entries[0].frame = console_gfn as u32; + entries[1].flags = 1 << 0; + entries[1].domid = 0; + entries[1].frame = xenstore_gfn as u32; + unsafe { + let result = munmap(addr as *mut c_void, 1 << XEN_PAGE_SHIFT); + if result != 0 { + return Err(Error::UnmapFailed(Errno::from_raw(result))); + } + } + Ok(()) + } + async fn vcpu(&mut self, domain: &mut BootDomain) -> Result<()> { let page_table_segment = self .page_table_segment @@ -783,36 +805,14 @@ impl BootSetupPlatform for X86PvPlatform { Ok(()) } - async fn gnttab_seed(&mut self, domain: &mut BootDomain) -> Result<()> { - let xenstore_segment = self - .xenstore_segment - .as_ref() - .ok_or(Error::MemorySetupFailed("xenstore_segment missing"))?; - - let console_gfn = domain.console_mfn as usize; - let xenstore_gfn = domain.phys.p2m[xenstore_segment.pfn as usize]; - let addr = domain - .call - .mmap(0, 1 << XEN_PAGE_SHIFT) - .await - .ok_or(Error::MmapFailed)?; - domain - .call - .map_resource(domain.domid, 1, 0, 0, 1, addr) - .await?; - let entries = unsafe { slice::from_raw_parts_mut(addr as *mut GrantEntry, 2) }; - entries[0].flags = 1 << 0; - entries[0].domid = 0; - entries[0].frame = console_gfn as u32; - entries[1].flags = 1 << 0; - entries[1].domid = 0; - entries[1].frame = xenstore_gfn as u32; - unsafe { - let result = munmap(addr as *mut c_void, 1 << XEN_PAGE_SHIFT); - if result != 0 { - return Err(Error::UnmapFailed(Errno::from_raw(result))); - } + async fn setup_hypercall_page(&mut self, domain: &mut BootDomain) -> Result<()> { + if domain.image_info.virt_hypercall == u64::MAX { + return Ok(()); } + let pfn = + (domain.image_info.virt_hypercall - domain.image_info.virt_base) >> self.page_shift(); + let mfn = domain.phys.p2m[pfn as usize]; + domain.call.hypercall_init(domain.domid, mfn).await?; Ok(()) } } diff --git a/crates/xen/xenstore/examples/list.rs b/crates/xen/xenstore/examples/list.rs index cd564d9..bbd6922 100644 --- a/crates/xen/xenstore/examples/list.rs +++ b/crates/xen/xenstore/examples/list.rs @@ -10,11 +10,12 @@ async fn list_recursive(client: &XsdClient, path: &str) -> Result<()> { let children = client.list(path).await?; for child in children { let full = format!("{}/{}", if path == "/" { "" } else { path }, child); - let value = client - .read_string(full.as_str()) - .await? - .expect("expected value"); - println!("{} = {:?}", full, value,); + let value = client.read(full.as_str()).await?.expect("expected value"); + let stringified = match String::from_utf8(value) { + Ok(string) => format!("\"{}\"", string), + Err(error) => format!("{:?}", error.into_bytes()), + }; + println!("{} = {}", full, stringified); pending.push(full); } } diff --git a/crates/xen/xenstore/src/error.rs b/crates/xen/xenstore/src/error.rs index 7bdb85a..4c1b86a 100644 --- a/crates/xen/xenstore/src/error.rs +++ b/crates/xen/xenstore/src/error.rs @@ -48,6 +48,13 @@ impl Error { _ => false, } } + + pub fn is_again_response(&self) -> bool { + match self { + Error::ResponseError(message) => message == "EAGAIN", + _ => false, + } + } } pub type Result = std::result::Result; diff --git a/crates/xen/xenstore/src/lib.rs b/crates/xen/xenstore/src/lib.rs index 5749110..95cd1d7 100644 --- a/crates/xen/xenstore/src/lib.rs +++ b/crates/xen/xenstore/src/lib.rs @@ -55,6 +55,27 @@ impl Drop for XsdWatchHandle { } } +pub struct XsdMultiWatchHandle { + pub paths: Vec, + pub id: u32, + unwatch_sender: Sender<(u32, String)>, + pub receiver: Receiver, +} + +impl XsdMultiWatchHandle { + pub fn add_path(&mut self, path: impl AsRef) { + self.paths.push(path.as_ref().to_string()); + } +} + +impl Drop for XsdMultiWatchHandle { + fn drop(&mut self) { + for path in &self.paths { + let _ = self.unwatch_sender.try_send((self.id, path.clone())); + } + } +} + #[allow(async_fn_in_trait)] pub trait XsdInterface { async fn list>(&self, path: P) -> Result>; @@ -141,7 +162,7 @@ impl XsdClient { } return Err(error); } - result.unwrap().parse_bool() + result?.parse_bool() } async fn set_perms>( @@ -197,6 +218,16 @@ impl XsdClient { response.parse_bool() } + pub async fn create_multi_watch(&self) -> Result { + let (id, receiver, unwatch_sender) = self.socket.add_watch().await?; + Ok(XsdMultiWatchHandle { + paths: vec![], + id, + receiver, + unwatch_sender, + }) + } + pub async fn create_watch>(&self, path: P) -> Result { let (id, receiver, unwatch_sender) = self.socket.add_watch().await?; Ok(XsdWatchHandle { @@ -319,6 +350,20 @@ impl XsdTransaction { .parse_bool() } + pub async fn maybe_commit(&self) -> Result { + match self.end(false).await { + Ok(result) => Ok(result), + + Err(error) => { + if error.is_again_response() { + Ok(false) + } else { + Err(error) + } + } + } + } + pub async fn commit(&self) -> Result { self.end(false).await }