From 799073f17c3e5f3ff7a5acf3885d70517a0c648f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 23 Jan 2023 15:27:14 +0530 Subject: [PATCH] gpio: Migrate to the upstream version of libgpiod The upstream version doesn't compile the .c files locally and depends on the package to be locally compiled and installed in advance. It also doesn't provide pre-generated bindings, and requires bindgen support. Signed-off-by: Viresh Kumar --- Cargo.lock | 124 ++++++++++++++++++++++++++++++++++-- README.md | 13 ++++ coverage_config_x86_64.json | 2 +- crates/gpio/Cargo.toml | 2 +- crates/gpio/src/gpio.rs | 34 +++++++--- 5 files changed, 159 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 457d376..68c836d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,28 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bindgen" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -41,12 +63,32 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.1.4" @@ -97,6 +139,12 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + [[package]] name = "env_logger" version = "0.10.0" @@ -143,9 +191,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -251,6 +299,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "hashbrown" version = "0.12.3" @@ -327,6 +381,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.139" @@ -336,7 +396,7 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libgpiod" version = "0.1.0" -source = "git+https://github.com/vireshk/libgpiod?branch=vhost-gpio#b412261453c3bcde60ac7597f19a042899acb68a" +source = "git+https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/?rev=d8d3a84b2ddf#d8d3a84b2ddfc29670430fc73ff8483a44b8f61e" dependencies = [ "errno", "intmap", @@ -348,11 +408,22 @@ dependencies = [ [[package]] name = "libgpiod-sys" version = "0.1.0" -source = "git+https://github.com/vireshk/libgpiod?branch=vhost-gpio#b412261453c3bcde60ac7597f19a042899acb68a" +source = "git+https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/?rev=d8d3a84b2ddf#d8d3a84b2ddfc29670430fc73ff8483a44b8f61e" dependencies = [ + "bindgen", "cc", ] +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "linux-raw-sys" version = "0.1.4" @@ -384,6 +455,22 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num_cpus" version = "1.15.0" @@ -429,6 +516,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -554,6 +647,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" version = "0.36.8" @@ -599,6 +698,12 @@ dependencies = [ "syn", ] +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + [[package]] name = "slab" version = "0.4.7" @@ -845,6 +950,17 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/README.md b/README.md index 61fa52b..06673f7 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,16 @@ devices](https://github.com/rust-vmm/vm-virtio/tree/main/crates/devices). This way a monolithic rust-vmm VMM implementation can reuse the core logic to service the virtio requests directly in the application. +## Build dependency + +The GPIO crate needs a local installation of libgpiod library to be available, +which can be done like: + +$ git clone --depth 1 --branch v2.0-rc1 https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/ +$ cd libgpiod +$ ./autogen.sh && make + +Either you can do a 'make install' now on your system, or provide path to the +locally build library like this while building vhost-device crates: + +$ RUSTFLAGS='-L /home//libgpiod/lib/.libs/' cargo build --release diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json index 5bc39d8..e3d7752 100644 --- a/coverage_config_x86_64.json +++ b/coverage_config_x86_64.json @@ -1,5 +1,5 @@ { - "coverage_score": 68.9, + "coverage_score": 67.6, "exclude_path": "", "crate_features": "" } diff --git a/crates/gpio/Cargo.toml b/crates/gpio/Cargo.toml index cc0f9ea..c430c96 100644 --- a/crates/gpio/Cargo.toml +++ b/crates/gpio/Cargo.toml @@ -25,7 +25,7 @@ vm-memory = "0.10" vmm-sys-util = "0.11" [target.'cfg(target_env = "gnu")'.dependencies] -libgpiod = { git = "https://github.com/vireshk/libgpiod", branch = "vhost-gpio" } +libgpiod = { git = "https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/", rev = "d8d3a84b2ddf" } [dev-dependencies] virtio-queue = { version = "0.7", features = ["test-utils"] } diff --git a/crates/gpio/src/gpio.rs b/crates/gpio/src/gpio.rs index f4399e7..e891a4e 100644 --- a/crates/gpio/src/gpio.rs +++ b/crates/gpio/src/gpio.rs @@ -6,7 +6,7 @@ // SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause use log::error; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc, Mutex, RwLock}; use std::time::Duration; use libgpiod::{chip, line, request, Error as LibGpiodError}; @@ -110,7 +110,7 @@ pub(crate) trait GpioDevice: Send + Sync + 'static { pub(crate) struct PhysLineState { // See wait_for_interrupt() for explanation of Arc. - request: Option>, + request: Option>>, buffer: Option, } @@ -201,27 +201,29 @@ impl GpioDevice for PhysDevice { _ => return Err(Error::GpioDirectionInvalid(value)), }; - let lconfig = line::Config::new().map_err(Error::GpiodFailed)?; + let mut lconfig = line::Config::new().map_err(Error::GpiodFailed)?; lconfig .add_line_settings(&[gpio as u32], lsettings) .map_err(Error::GpiodFailed)?; - if let Some(request) = &state.request { + if let Some(request) = &mut state.request { request + .lock() + .unwrap() .reconfigure_lines(&lconfig) .map_err(Error::GpiodFailed)?; } else { - let rconfig = request::Config::new().map_err(Error::GpiodFailed)?; + let mut rconfig = request::Config::new().map_err(Error::GpiodFailed)?; rconfig .set_consumer("vhu-gpio") .map_err(Error::GpiodFailed)?; - state.request = Some(Arc::new( + state.request = Some(Arc::new(Mutex::new( self.chip .request_lines(Some(&rconfig), &lconfig) .map_err(Error::GpiodFailed)?, - )); + ))); } Ok(()) @@ -231,7 +233,11 @@ impl GpioDevice for PhysDevice { let state = &self.state[gpio as usize].read().unwrap(); if let Some(request) = &state.request { - Ok(request.value(gpio as u32).map_err(Error::GpiodFailed)? as u8) + Ok(request + .lock() + .unwrap() + .value(gpio as u32) + .map_err(Error::GpiodFailed)? as u8) } else { Err(Error::GpioDirectionInvalid( VIRTIO_GPIO_DIRECTION_NONE as u32, @@ -247,6 +253,8 @@ impl GpioDevice for PhysDevice { if let Some(request) = &state.request { let value = line::Value::new(value as i32).map_err(Error::GpiodFailed)?; request + .lock() + .unwrap() .set_value(gpio as u32, value) .map_err(Error::GpiodFailed)?; } @@ -281,7 +289,7 @@ impl GpioDevice for PhysDevice { .set_edge_detection(Some(edge)) .map_err(Error::GpiodFailed)?; - let lconfig = line::Config::new().map_err(Error::GpiodFailed)?; + let mut lconfig = line::Config::new().map_err(Error::GpiodFailed)?; lconfig .add_line_settings(&[gpio as u32], lsettings) .map_err(Error::GpiodFailed)?; @@ -296,8 +304,12 @@ impl GpioDevice for PhysDevice { .request .as_ref() .unwrap() + .lock() + .unwrap() .reconfigure_lines(&lconfig) - .map_err(Error::GpiodFailed) + .map_err(Error::GpiodFailed)?; + + Ok(()) } fn wait_for_interrupt(&self, gpio: u16) -> Result { @@ -336,6 +348,8 @@ impl GpioDevice for PhysDevice { } }; + let request = request.lock().unwrap(); + // Wait for the interrupt for a second. if !request .wait_edge_events(Some(Duration::new(1, 0)))