* [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl
@ 2024-08-15 11:42 Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 1/7] Require meson version 1.5.0 Manos Pitsidianakis
` (8 more replies)
0 siblings, 9 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-15 11:42 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Manos Pitsidianakis, Zhao Liu, Peter Maydell, ARM TCG CPUs,
Stefan Hajnoczi, Junjie Mao, Pierrick Bouvier, Richard Henderson,
Gustavo Romero, rowan.hart, Mads Ynddal, Markus Armbruster
Changes
=======
- Incorporated changes by Paolo Bonzini and Junjie Mao as a result of
discussion on the previous patch series version
- Included two squash patches from
<20240814090820.1251026-1-junjie.mao@intel.com>
Junjie Mao (2):
meson: subprojects: Specify Rust edition by rust_std=20XX
rust: Specify Rust edition by rust_std=20XX
Outstanding issues
==================
Outstanding issues that are not blocking for merge are:
- Cross-compilation for aarch64 is not possible out-of-the-box because of this bug:
<https://github.com/rust-lang/rust/issues/125619> in llvm which when
fixed, must be ported to upstream rust's llvm fork. Since the problem
is an extraneous symbol we could strip it with objcopy -N|--strip-symbol
- Adding more than one Rust device ends up with duplicate symbols from
rust std library because we are linking as whole archives because...
constructors are stripped by the linker otherwise :( It can be worked
around if a single Rust library is built with all the devices as
dependencies which is then linked to qemu. The fix is a small change
which I will add either in a next version or when a new Rust device is
added.
Previous version was: <rust-pl011-rfc-v6.git.manos.pitsidianakis@linaro.org>
---
Hello everyone,
This series adds:
- build system support for the Rust compiler
- a small Rust library, qemu-api, which includes bindings to QEMU's C
interface generated with bindgen
- a proof of concept ARM PL011 device implementation in Rust, chosen for
its low complexity. The device is used in the arm virt machine if qemu
is compiled with rust enabled (./configure --enable-rust [...])
Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
---
Manos Pitsidianakis (5):
build-sys: Add rust feature option
rust: add bindgen step as a meson dependency
.gitattributes: add Rust diff and merge attributes
rust: add crate to expose bindings and interfaces
rust: add PL011 device model
Paolo Bonzini (2):
Require meson version 1.5.0
configure, meson: detect Rust toolchain
MAINTAINERS | 20 +
configure | 50 +-
meson.build | 77 ++-
rust/wrapper.h | 39 ++
.gitattributes | 3 +
Kconfig | 1 +
Kconfig.host | 3 +
hw/arm/Kconfig | 33 +-
meson_options.txt | 3 +
python/scripts/vendor.py | 4 +-
python/wheels/meson-1.2.3-py3-none-any.whl | Bin 964928 -> 0 bytes
python/wheels/meson-1.5.0-py3-none-any.whl | Bin 0 -> 959846 bytes
pythondeps.toml | 2 +-
rust/.gitignore | 3 +
rust/Kconfig | 1 +
rust/hw/Kconfig | 2 +
rust/hw/char/Kconfig | 3 +
rust/hw/char/meson.build | 1 +
rust/hw/char/pl011/.gitignore | 2 +
rust/hw/char/pl011/Cargo.lock | 125 +++++
rust/hw/char/pl011/Cargo.toml | 26 +
rust/hw/char/pl011/README.md | 31 ++
rust/hw/char/pl011/meson.build | 21 +
rust/hw/char/pl011/rustfmt.toml | 1 +
rust/hw/char/pl011/src/definitions.rs | 26 +
rust/hw/char/pl011/src/device.rs | 586 +++++++++++++++++++++
rust/hw/char/pl011/src/device_class.rs | 58 ++
rust/hw/char/pl011/src/lib.rs | 584 ++++++++++++++++++++
rust/hw/char/pl011/src/memory_ops.rs | 56 ++
rust/hw/meson.build | 1 +
rust/meson.build | 11 +
rust/qemu-api/.gitignore | 2 +
rust/qemu-api/Cargo.lock | 7 +
rust/qemu-api/Cargo.toml | 23 +
rust/qemu-api/README.md | 17 +
rust/qemu-api/build.rs | 13 +
rust/qemu-api/meson.build | 17 +
rust/qemu-api/rustfmt.toml | 1 +
rust/qemu-api/src/bindings.rs | 7 +
rust/qemu-api/src/definitions.rs | 108 ++++
rust/qemu-api/src/device_class.rs | 128 +++++
rust/qemu-api/src/lib.rs | 100 ++++
rust/qemu-api/src/tests.rs | 48 ++
rust/rustfmt.toml | 7 +
scripts/archive-source.sh | 5 +-
scripts/make-release | 5 +-
scripts/meson-buildoptions.sh | 3 +
scripts/rustc_args.py | 84 +++
subprojects/.gitignore | 11 +
subprojects/arbitrary-int-1-rs.wrap | 7 +
subprojects/bilge-0.2-rs.wrap | 7 +
subprojects/bilge-impl-0.2-rs.wrap | 7 +
subprojects/either-1-rs.wrap | 7 +
subprojects/itertools-0.11-rs.wrap | 7 +
.../packagefiles/arbitrary-int-1-rs/meson.build | 19 +
subprojects/packagefiles/bilge-0.2-rs/meson.build | 29 +
.../packagefiles/bilge-impl-0.2-rs/meson.build | 45 ++
subprojects/packagefiles/either-1-rs/meson.build | 24 +
.../packagefiles/itertools-0.11-rs/meson.build | 30 ++
.../packagefiles/proc-macro-error-1-rs/meson.build | 40 ++
.../proc-macro-error-attr-1-rs/meson.build | 32 ++
.../packagefiles/proc-macro2-1-rs/meson.build | 31 ++
subprojects/packagefiles/quote-1-rs/meson.build | 29 +
subprojects/packagefiles/syn-2-rs/meson.build | 40 ++
.../packagefiles/unicode-ident-1-rs/meson.build | 20 +
subprojects/proc-macro-error-1-rs.wrap | 7 +
subprojects/proc-macro-error-attr-1-rs.wrap | 7 +
subprojects/proc-macro2-1-rs.wrap | 7 +
subprojects/quote-1-rs.wrap | 7 +
subprojects/syn-2-rs.wrap | 7 +
subprojects/unicode-ident-1-rs.wrap | 7 +
tests/lcitool/mappings.yml | 2 +-
72 files changed, 2756 insertions(+), 21 deletions(-)
---
base-commit: a733f37aef3b7d1d33bfe2716af88cdfd67ba64e
change-id: 20240814-rust-pl011-v7
Best regards,
--
γαῖα πυρί μιχθήτω
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v7 1/7] Require meson version 1.5.0
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
@ 2024-08-15 11:42 ` Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 2/7] build-sys: Add rust feature option Manos Pitsidianakis
` (7 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-15 11:42 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Manos Pitsidianakis, Zhao Liu, Peter Maydell, ARM TCG CPUs,
Stefan Hajnoczi, Junjie Mao, Pierrick Bouvier, Richard Henderson,
Gustavo Romero, rowan.hart, Mads Ynddal, Markus Armbruster
From: Paolo Bonzini <pbonzini@redhat.com>
This is needed for Rust support.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 2 +-
python/scripts/vendor.py | 4 ++--
python/wheels/meson-1.2.3-py3-none-any.whl | Bin 964928 -> 0 bytes
python/wheels/meson-1.5.0-py3-none-any.whl | Bin 0 -> 959846 bytes
pythondeps.toml | 2 +-
tests/lcitool/mappings.yml | 2 +-
6 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/meson.build b/meson.build
index 81ecd4bae7..7eb4b8a41c 100644
--- a/meson.build
+++ b/meson.build
@@ -1,4 +1,4 @@
-project('qemu', ['c'], meson_version: '>=1.1.0',
+project('qemu', ['c'], meson_version: '>=1.5.0',
default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto',
'b_staticpic=false', 'stdsplit=false', 'optimization=2', 'b_pie=true'],
version: files('VERSION'))
diff --git a/python/scripts/vendor.py b/python/scripts/vendor.py
index 07aff97cca..0405e910b4 100755
--- a/python/scripts/vendor.py
+++ b/python/scripts/vendor.py
@@ -41,8 +41,8 @@ def main() -> int:
parser.parse_args()
packages = {
- "meson==1.2.3":
- "4533a43c34548edd1f63a276a42690fce15bde9409bcf20c4b8fa3d7e4d7cac1",
+ "meson==1.5.0":
+ "52b34f4903b882df52ad0d533146d4b992c018ea77399f825579737672ae7b20",
}
vendor_dir = Path(__file__, "..", "..", "wheels").resolve()
diff --git a/python/wheels/meson-1.2.3-py3-none-any.whl b/python/wheels/meson-1.2.3-py3-none-any.whl
deleted file mode 100644
index a8b84e5f11..0000000000
Binary files a/python/wheels/meson-1.2.3-py3-none-any.whl and /dev/null differ
diff --git a/python/wheels/meson-1.5.0-py3-none-any.whl b/python/wheels/meson-1.5.0-py3-none-any.whl
new file mode 100644
index 0000000000..c7edeb37ad
Binary files /dev/null and b/python/wheels/meson-1.5.0-py3-none-any.whl differ
diff --git a/pythondeps.toml b/pythondeps.toml
index f6e590fdd8..a1c6ca9662 100644
--- a/pythondeps.toml
+++ b/pythondeps.toml
@@ -19,7 +19,7 @@
[meson]
# The install key should match the version in python/wheels/
-meson = { accepted = ">=1.1.0", installed = "1.2.3", canary = "meson" }
+meson = { accepted = ">=1.5.0", installed = "1.5.0", canary = "meson" }
[docs]
# Please keep the installed versions in sync with docs/requirements.txt
diff --git a/tests/lcitool/mappings.yml b/tests/lcitool/mappings.yml
index 03b974ad02..9721016e0d 100644
--- a/tests/lcitool/mappings.yml
+++ b/tests/lcitool/mappings.yml
@@ -63,7 +63,7 @@ mappings:
pypi_mappings:
# Request more recent version
meson:
- default: meson==0.63.2
+ default: meson==1.5.0
# Drop packages that need devel headers
python3-numpy:
--
2.44.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 2/7] build-sys: Add rust feature option
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 1/7] Require meson version 1.5.0 Manos Pitsidianakis
@ 2024-08-15 11:42 ` Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 3/7] configure, meson: detect Rust toolchain Manos Pitsidianakis
` (6 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-15 11:42 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Manos Pitsidianakis, Zhao Liu, Peter Maydell, ARM TCG CPUs,
Stefan Hajnoczi, Junjie Mao, Pierrick Bouvier, Richard Henderson,
Gustavo Romero, rowan.hart, Mads Ynddal, Markus Armbruster
Add rust feature in meson.build, configure, to prepare for adding Rust
code in the followup commits.
Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
---
MAINTAINERS | 5 +++++
meson.build | 25 ++++++++++++++++++++++++-
Kconfig | 1 +
Kconfig.host | 3 +++
meson_options.txt | 3 +++
rust/Kconfig | 0
scripts/meson-buildoptions.sh | 3 +++
7 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 3584d6a6c6..0bc8e515da 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4243,6 +4243,11 @@ F: docs/sphinx/
F: docs/_templates/
F: docs/devel/docs.rst
+Rust build system integration
+M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+S: Maintained
+F: rust/Kconfig
+
Miscellaneous
-------------
Performance Tools and Tests
diff --git a/meson.build b/meson.build
index 7eb4b8a41c..67eb4eda64 100644
--- a/meson.build
+++ b/meson.build
@@ -70,6 +70,22 @@ if host_os == 'darwin' and \
all_languages += ['objc']
objc = meson.get_compiler('objc')
endif
+if get_option('rust').enabled() and meson.version().version_compare('<1.0.0')
+ error('Rust support requires Meson version >=1.0.0')
+endif
+have_rust = false
+if not get_option('rust').disabled() and add_languages('rust', required: get_option('rust'), native: false)
+ rustc = meson.get_compiler('rust')
+ have_rust = true
+ if rustc.version().version_compare('<1.80.0')
+ if get_option('rust').enabled()
+ error('rustc version ' + rustc.version() + ' is unsupported: Please upgrade to at least 1.80.0')
+ else
+ warning('rustc version ' + rustc.version() + ' is unsupported: Disabling Rust compilation. Please upgrade to at least 1.80.0 to use Rust.')
+ have_rust = false
+ endif
+ endif
+endif
dtrace = not_found
stap = not_found
@@ -2131,6 +2147,7 @@ endif
config_host_data = configuration_data()
+config_host_data.set('CONFIG_HAVE_RUST', have_rust)
audio_drivers_selected = []
if have_system
audio_drivers_available = {
@@ -3076,7 +3093,8 @@ host_kconfig = \
(host_os == 'linux' ? ['CONFIG_LINUX=y'] : []) + \
(multiprocess_allowed ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : []) + \
(vfio_user_server_allowed ? ['CONFIG_VFIO_USER_SERVER_ALLOWED=y'] : []) + \
- (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : [])
+ (hv_balloon ? ['CONFIG_HV_BALLOON_POSSIBLE=y'] : []) + \
+ (have_rust ? ['CONFIG_HAVE_RUST=y'] : [])
ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
@@ -4287,6 +4305,11 @@ if 'objc' in all_languages
else
summary_info += {'Objective-C compiler': false}
endif
+summary_info += {'Rust support': have_rust}
+if have_rust
+ summary_info += {'rustc version': rustc.version()}
+ summary_info += {'rustc': ' '.join(rustc.cmd_array())}
+endif
option_cflags = (get_option('debug') ? ['-g'] : [])
if get_option('optimization') != 'plain'
option_cflags += ['-O' + get_option('optimization')]
diff --git a/Kconfig b/Kconfig
index fb6a24a2de..63ca7f46df 100644
--- a/Kconfig
+++ b/Kconfig
@@ -4,3 +4,4 @@ source accel/Kconfig
source target/Kconfig
source hw/Kconfig
source semihosting/Kconfig
+source rust/Kconfig
diff --git a/Kconfig.host b/Kconfig.host
index 17f405004b..4ade7899d6 100644
--- a/Kconfig.host
+++ b/Kconfig.host
@@ -52,3 +52,6 @@ config VFIO_USER_SERVER_ALLOWED
config HV_BALLOON_POSSIBLE
bool
+
+config HAVE_RUST
+ bool
diff --git a/meson_options.txt b/meson_options.txt
index 0269fa0f16..fa94a5ce97 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -371,3 +371,6 @@ option('hexagon_idef_parser', type : 'boolean', value : true,
option('x86_version', type : 'combo', choices : ['0', '1', '2', '3', '4'], value: '1',
description: 'tweak required x86_64 architecture version beyond compiler default')
+
+option('rust', type: 'feature', value: 'auto',
+ description: 'Rust support')
diff --git a/rust/Kconfig b/rust/Kconfig
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index c97079a38c..5e8a225a6b 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -170,6 +170,7 @@ meson_options_help() {
printf "%s\n" ' rbd Ceph block device driver'
printf "%s\n" ' rdma Enable RDMA-based migration'
printf "%s\n" ' replication replication support'
+ printf "%s\n" ' rust Rust support'
printf "%s\n" ' rutabaga-gfx rutabaga_gfx support'
printf "%s\n" ' sdl SDL user interface'
printf "%s\n" ' sdl-image SDL Image support for icons'
@@ -452,6 +453,8 @@ _meson_option_parse() {
--disable-replication) printf "%s" -Dreplication=disabled ;;
--enable-rng-none) printf "%s" -Drng_none=true ;;
--disable-rng-none) printf "%s" -Drng_none=false ;;
+ --enable-rust) printf "%s" -Drust=enabled ;;
+ --disable-rust) printf "%s" -Drust=disabled ;;
--enable-rutabaga-gfx) printf "%s" -Drutabaga_gfx=enabled ;;
--disable-rutabaga-gfx) printf "%s" -Drutabaga_gfx=disabled ;;
--enable-safe-stack) printf "%s" -Dsafe_stack=true ;;
--
2.44.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 3/7] configure, meson: detect Rust toolchain
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 1/7] Require meson version 1.5.0 Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 2/7] build-sys: Add rust feature option Manos Pitsidianakis
@ 2024-08-15 11:42 ` Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 4/7] rust: add bindgen step as a meson dependency Manos Pitsidianakis
` (5 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-15 11:42 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Manos Pitsidianakis, Zhao Liu, Peter Maydell, ARM TCG CPUs,
Stefan Hajnoczi, Junjie Mao, Pierrick Bouvier, Richard Henderson,
Gustavo Romero, rowan.hart, Mads Ynddal, Markus Armbruster
From: Paolo Bonzini <pbonzini@redhat.com>
Include the correct path and arguments to rustc in the native
and cross files (native compilation is needed for procedural
macros).
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
configure | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
meson.build | 8 +++-----
2 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/configure b/configure
index 019fcbd0ef..9ef6005c55 100755
--- a/configure
+++ b/configure
@@ -207,6 +207,8 @@ for opt do
;;
--objcc=*) objcc="$optarg"
;;
+ --rustc=*) RUSTC="$optarg"
+ ;;
--cpu=*) cpu="$optarg"
;;
--extra-cflags=*)
@@ -252,6 +254,9 @@ python=
download="enabled"
skip_meson=no
use_containers="yes"
+# do not enable by default because cross compilation requires --rust-target-triple
+rust="disabled"
+rust_target_triple=""
gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb")
gdb_arches=""
@@ -317,6 +322,8 @@ windmc="${WINDMC-${cross_prefix}windmc}"
pkg_config="${PKG_CONFIG-${cross_prefix}pkg-config}"
sdl2_config="${SDL2_CONFIG-${cross_prefix}sdl2-config}"
+rustc="${RUSTC-rustc}"
+
check_define() {
cat > $TMPC <<EOF
#if !defined($1)
@@ -636,6 +643,8 @@ for opt do
;;
--objcc=*)
;;
+ --rustc=*)
+ ;;
--make=*)
;;
--install=*)
@@ -755,8 +764,14 @@ for opt do
;;
--container-engine=*) container_engine="$optarg"
;;
+ --rust-target-triple=*) rust_target_triple="$optarg"
+ ;;
--gdb=*) gdb_bin="$optarg"
;;
+ --enable-rust) rust=enabled
+ ;;
+ --disable-rust) rust=disabled
+ ;;
# everything else has the same name in configure and meson
--*) meson_option_parse "$opt" "$optarg"
;;
@@ -859,6 +874,7 @@ Advanced options (experts only):
at build time [$host_cc]
--cxx=CXX use C++ compiler CXX [$cxx]
--objcc=OBJCC use Objective-C compiler OBJCC [$objcc]
+ --rustc=RUSTC use Rust compiler RUSTC [$rustc]
--extra-cflags=CFLAGS append extra C compiler flags CFLAGS
--extra-cxxflags=CXXFLAGS append extra C++ compiler flags CXXFLAGS
--extra-objcflags=OBJCFLAGS append extra Objective C compiler flags OBJCFLAGS
@@ -869,8 +885,9 @@ Advanced options (experts only):
--python=PYTHON use specified python [$python]
--ninja=NINJA use specified ninja [$ninja]
--static enable static build [$static]
- --without-default-features default all --enable-* options to "disabled"
- --without-default-devices do not include any device that is not needed to
+ --rust-target-triple=TRIPLE target for Rust cross compilation
+ --without-default-features default all --enable-* options to "disabled"
+ --without-default-devices do not include any device that is not needed to
start the emulator (only use if you are including
desired devices in configs/devices/)
--with-devices-ARCH=NAME override default configs/devices
@@ -1139,6 +1156,21 @@ EOF
fi
##########################################
+# detect rust triple
+
+if test "$rust" != disabled && has "$rustc" && $rustc -vV > "${TMPDIR1}/${TMPB}.out"; then
+ rust_host_triple=$(sed -n 's/^host: //p' "${TMPDIR1}/${TMPB}.out")
+else
+ if test "$rust" = enabled; then
+ error_exit "could not execute rustc binary \"$rustc\""
+ fi
+ rust=disabled
+fi
+if test "$rust" != disabled && test -z "$rust_target_triple"; then
+ rust_target_triple=$rust_host_triple
+fi
+
+##########################################
# functions to probe cross compilers
container="no"
@@ -1604,6 +1636,9 @@ if test "$container" != no; then
echo "RUNC=$runc" >> $config_host_mak
fi
echo "SUBDIRS=$subdirs" >> $config_host_mak
+if test "$rust" != disabled; then
+ echo "RUST_TARGET_TRIPLE=$rust_target_triple" >> $config_host_mak
+fi
echo "PYTHON=$python" >> $config_host_mak
echo "MKVENV_ENSUREGROUP=$mkvenv ensuregroup $mkvenv_online_flag" >> $config_host_mak
echo "GENISOIMAGE=$genisoimage" >> $config_host_mak
@@ -1735,6 +1770,13 @@ if test "$skip_meson" = no; then
echo "c = [$(meson_quote $cc $CPU_CFLAGS)]" >> $cross
test -n "$cxx" && echo "cpp = [$(meson_quote $cxx $CPU_CFLAGS)]" >> $cross
test -n "$objcc" && echo "objc = [$(meson_quote $objcc $CPU_CFLAGS)]" >> $cross
+ if test "$rust" != disabled; then
+ if test "$rust_host_triple" != "$rust_target_triple"; then
+ echo "rust = [$(meson_quote $rustc --target "$rust_target_triple")]" >> $cross
+ else
+ echo "rust = [$(meson_quote $rustc)]" >> $cross
+ fi
+ fi
echo "ar = [$(meson_quote $ar)]" >> $cross
echo "dlltool = [$(meson_quote $dlltool)]" >> $cross
echo "nm = [$(meson_quote $nm)]" >> $cross
@@ -1770,6 +1812,9 @@ if test "$skip_meson" = no; then
echo "# Automatically generated by configure - do not modify" > $native
echo "[binaries]" >> $native
echo "c = [$(meson_quote $host_cc)]" >> $native
+ if test "$rust" != disabled; then
+ echo "rust = [$(meson_quote $rustc)]" >> $cross
+ fi
mv $native config-meson.native
meson_option_add --native-file
meson_option_add config-meson.native
@@ -1788,6 +1833,7 @@ if test "$skip_meson" = no; then
test "$pie" = no && meson_option_add -Db_pie=false
# QEMU options
+ test "$rust" != "auto" && meson_option_add "-Drust=$rust"
test "$cfi" != false && meson_option_add "-Dcfi=$cfi" "-Db_lto=$cfi"
test "$docs" != auto && meson_option_add "-Ddocs=$docs"
test -n "${LIB_FUZZING_ENGINE+xxx}" && meson_option_add "-Dfuzzing_engine=$LIB_FUZZING_ENGINE"
diff --git a/meson.build b/meson.build
index 67eb4eda64..065739ccb7 100644
--- a/meson.build
+++ b/meson.build
@@ -70,9 +70,6 @@ if host_os == 'darwin' and \
all_languages += ['objc']
objc = meson.get_compiler('objc')
endif
-if get_option('rust').enabled() and meson.version().version_compare('<1.0.0')
- error('Rust support requires Meson version >=1.0.0')
-endif
have_rust = false
if not get_option('rust').disabled() and add_languages('rust', required: get_option('rust'), native: false)
rustc = meson.get_compiler('rust')
@@ -4307,8 +4304,9 @@ else
endif
summary_info += {'Rust support': have_rust}
if have_rust
- summary_info += {'rustc version': rustc.version()}
- summary_info += {'rustc': ' '.join(rustc.cmd_array())}
+ summary_info += {'rustc version': rustc.version()}
+ summary_info += {'rustc': ' '.join(rustc.cmd_array())}
+ summary_info += {'Rust target': config_host['RUST_TARGET_TRIPLE']}
endif
option_cflags = (get_option('debug') ? ['-g'] : [])
if get_option('optimization') != 'plain'
--
2.44.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 4/7] rust: add bindgen step as a meson dependency
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
` (2 preceding siblings ...)
2024-08-15 11:42 ` [PATCH v7 3/7] configure, meson: detect Rust toolchain Manos Pitsidianakis
@ 2024-08-15 11:42 ` Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 5/7] .gitattributes: add Rust diff and merge attributes Manos Pitsidianakis
` (4 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-15 11:42 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Manos Pitsidianakis, Zhao Liu, Peter Maydell, ARM TCG CPUs,
Stefan Hajnoczi, Junjie Mao, Pierrick Bouvier, Richard Henderson,
Gustavo Romero, rowan.hart, Mads Ynddal, Markus Armbruster
Add bindings_rs target for generating rust bindings to target-independent
qemu C APIs.
The bindings need be created before any rust crate that uses them is
compiled.
The bindings.rs file will end up in BUILDDIR/bindings.rs and have the
same name as a target:
ninja bindings.rs
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
---
MAINTAINERS | 4 +++
meson.build | 52 +++++++++++++++++++++++++++++++
rust/wrapper.h | 39 ++++++++++++++++++++++++
rust/.gitignore | 3 ++
rust/meson.build | 0
scripts/rustc_args.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 182 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 0bc8e515da..5464cb2b03 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4246,7 +4246,11 @@ F: docs/devel/docs.rst
Rust build system integration
M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
S: Maintained
+F: scripts/rustc_args.py
+F: rust/.gitignore
F: rust/Kconfig
+F: rust/meson.build
+F: rust/wrapper.h
Miscellaneous
-------------
diff --git a/meson.build b/meson.build
index 065739ccb7..10a8f25068 100644
--- a/meson.build
+++ b/meson.build
@@ -303,6 +303,15 @@ foreach lang : all_languages
endif
endforeach
+if have_rust
+ rust_args = []
+ if get_option('debug')
+ rust_args += ['-g']
+ endif
+ if get_option('optimization') not in ['0', '1', 'g']
+ rust_args += ['-O']
+ endif
+endif
# default flags for all hosts
# We use -fwrapv to tell the compiler that we require a C dialect where
# left shift of signed integers is well defined and has the expected
@@ -3871,6 +3880,49 @@ common_all = static_library('common',
implicit_include_directories: false,
dependencies: common_ss.all_dependencies())
+if have_rust and have_system
+ rust_args += run_command(
+ meson.global_source_root() / 'scripts/rustc_args.py',
+ '--config-headers', meson.project_build_root() / 'config-host.h',
+ capture : true,
+ check: true).stdout().strip().split()
+
+ bindings_rs = import('rust').bindgen(
+ input: 'rust/wrapper.h',
+ dependencies: common_ss.all_dependencies(),
+ output: 'bindings.rs',
+ include_directories: include_directories('.', 'include'),
+ bindgen_version: ['>=0.69.4'],
+ args: [
+ '--raw-line', '// @generated',
+ '--raw-line', '#![allow(dead_code)]',
+ '--raw-line', '#![allow(non_camel_case_types)]',
+ '--raw-line', '#![allow(non_snake_case)]',
+ '--raw-line', '#![allow(non_upper_case_globals)]',
+ '--raw-line', '#![allow(improper_ctypes_definitions)]',
+ '--raw-line', '#![allow(improper_ctypes)]',
+ '--raw-line', 'unsafe impl Send for Property {}',
+ '--raw-line', 'unsafe impl Sync for Property {}',
+ '--raw-line', 'unsafe impl Sync for TypeInfo {}',
+ '--raw-line', 'unsafe impl Sync for VMStateDescription {}',
+ '--ctypes-prefix', 'core::ffi',
+ '--formatter', 'rustfmt',
+ '--generate-block',
+ '--generate-cstr',
+ '--impl-debug',
+ '--merge-extern-blocks',
+ '--no-doc-comments',
+ '--use-core',
+ '--with-derive-default',
+ '--allowlist-file', meson.project_source_root() + '/include/.*',
+ '--allowlist-file', meson.project_source_root() + '/.*',
+ '--allowlist-file', meson.project_build_root() + '/.*'
+ ],
+ )
+ subdir('rust')
+endif
+
+
feature_to_c = find_program('scripts/feature_to_c.py')
if host_os == 'darwin'
diff --git a/rust/wrapper.h b/rust/wrapper.h
new file mode 100644
index 0000000000..51985f0ef1
--- /dev/null
+++ b/rust/wrapper.h
@@ -0,0 +1,39 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu-io.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "exec/memory.h"
+#include "chardev/char-fe.h"
+#include "hw/clock.h"
+#include "hw/qdev-clock.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/irq.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+#include "chardev/char-serial.h"
diff --git a/rust/.gitignore b/rust/.gitignore
new file mode 100644
index 0000000000..1bf71b1f68
--- /dev/null
+++ b/rust/.gitignore
@@ -0,0 +1,3 @@
+# Ignore any cargo development build artifacts; for qemu-wide builds, all build
+# artifacts will go to the meson build directory.
+target
diff --git a/rust/meson.build b/rust/meson.build
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/scripts/rustc_args.py b/scripts/rustc_args.py
new file mode 100644
index 0000000000..e4cc9720e1
--- /dev/null
+++ b/scripts/rustc_args.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+
+"""Generate rustc arguments for meson rust builds.
+
+This program generates --cfg compile flags for the configuration headers passed
+as arguments.
+
+Copyright (c) 2024 Linaro Ltd.
+
+Authors:
+ Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+import argparse
+import logging
+
+from typing import List
+
+
+def generate_cfg_flags(header: str) -> List[str]:
+ """Converts defines from config[..].h headers to rustc --cfg flags."""
+
+ def cfg_name(name: str) -> str:
+ """Filter function for C #defines"""
+ if (
+ name.startswith("CONFIG_")
+ or name.startswith("TARGET_")
+ or name.startswith("HAVE_")
+ ):
+ return name
+ return ""
+
+ with open(header, encoding="utf-8") as cfg:
+ config = [l.split()[1:] for l in cfg if l.startswith("#define")]
+
+ cfg_list = []
+ for cfg in config:
+ name = cfg_name(cfg[0])
+ if not name:
+ continue
+ if len(cfg) >= 2 and cfg[1] != "1":
+ continue
+ cfg_list.append("--cfg")
+ cfg_list.append(name)
+ return cfg_list
+
+
+def main() -> None:
+ # pylint: disable=missing-function-docstring
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-v", "--verbose", action="store_true")
+ parser.add_argument(
+ "--config-headers",
+ metavar="CONFIG_HEADER",
+ action="append",
+ dest="config_headers",
+ help="paths to any configuration C headers (*.h files), if any",
+ required=False,
+ default=[],
+ )
+ args = parser.parse_args()
+ if args.verbose:
+ logging.basicConfig(level=logging.DEBUG)
+ logging.debug("args: %s", args)
+ for header in args.config_headers:
+ for tok in generate_cfg_flags(header):
+ print(tok)
+
+
+if __name__ == "__main__":
+ main()
--
2.44.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 5/7] .gitattributes: add Rust diff and merge attributes
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
` (3 preceding siblings ...)
2024-08-15 11:42 ` [PATCH v7 4/7] rust: add bindgen step as a meson dependency Manos Pitsidianakis
@ 2024-08-15 11:42 ` Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 6/7] rust: add crate to expose bindings and interfaces Manos Pitsidianakis
` (3 subsequent siblings)
8 siblings, 0 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-15 11:42 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Manos Pitsidianakis, Zhao Liu, Peter Maydell, ARM TCG CPUs,
Stefan Hajnoczi, Junjie Mao, Pierrick Bouvier, Richard Henderson,
Gustavo Romero, rowan.hart, Mads Ynddal, Markus Armbruster
Set rust source code to diff=rust (built-in with new git versions)
and merge=binary for Cargo.lock files (they should not be merged but
auto-generated by cargo)
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
---
.gitattributes | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.gitattributes b/.gitattributes
index a217cb7bfe..6dc6383d3d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2,3 +2,6 @@
*.h.inc diff=c
*.m diff=objc
*.py diff=python
+*.rs diff=rust
+*.rs.inc diff=rust
+Cargo.lock diff=toml merge=binary
--
2.44.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 6/7] rust: add crate to expose bindings and interfaces
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
` (4 preceding siblings ...)
2024-08-15 11:42 ` [PATCH v7 5/7] .gitattributes: add Rust diff and merge attributes Manos Pitsidianakis
@ 2024-08-15 11:42 ` Manos Pitsidianakis
2024-08-15 14:01 ` Philippe Mathieu-Daudé
2024-08-16 8:26 ` Junjie Mao
2024-08-15 11:42 ` [PATCH v7 7/7] rust: add PL011 device model Manos Pitsidianakis
` (2 subsequent siblings)
8 siblings, 2 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-15 11:42 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Manos Pitsidianakis, Zhao Liu, Peter Maydell, ARM TCG CPUs,
Stefan Hajnoczi, Junjie Mao, Pierrick Bouvier, Richard Henderson,
Gustavo Romero, rowan.hart, Mads Ynddal, Markus Armbruster
Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and
provides some declaration macros for symbols visible to the rest of
QEMU.
Co-authored-by: Junjie Mao <junjie.mao@intel.com>
Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
---
MAINTAINERS | 6 ++
rust/meson.build | 9 +++
rust/qemu-api/.gitignore | 2 +
rust/qemu-api/Cargo.lock | 7 +++
rust/qemu-api/Cargo.toml | 23 +++++++
rust/qemu-api/README.md | 17 +++++
rust/qemu-api/build.rs | 13 ++++
rust/qemu-api/meson.build | 17 +++++
rust/qemu-api/rustfmt.toml | 1 +
rust/qemu-api/src/bindings.rs | 7 +++
rust/qemu-api/src/definitions.rs | 108 ++++++++++++++++++++++++++++++++
rust/qemu-api/src/device_class.rs | 128 ++++++++++++++++++++++++++++++++++++++
rust/qemu-api/src/lib.rs | 100 +++++++++++++++++++++++++++++
rust/qemu-api/src/tests.rs | 48 ++++++++++++++
rust/rustfmt.toml | 7 +++
15 files changed, 493 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 5464cb2b03..56a88048d2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3348,6 +3348,12 @@ F: hw/core/register.c
F: include/hw/register.h
F: include/hw/registerfields.h
+Rust
+M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+S: Maintained
+F: rust/qemu-api
+F: rust/rustfmt.toml
+
SLIRP
M: Samuel Thibault <samuel.thibault@ens-lyon.org>
S: Maintained
diff --git a/rust/meson.build b/rust/meson.build
index e69de29bb2..d5f32aed25 100644
--- a/rust/meson.build
+++ b/rust/meson.build
@@ -0,0 +1,9 @@
+_lib_bindings_rs = static_library(
+ '_bindings_rs',
+ bindings_rs,
+ gnu_symbol_visibility: 'hidden',
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+)
+
+subdir('qemu-api')
diff --git a/rust/qemu-api/.gitignore b/rust/qemu-api/.gitignore
new file mode 100644
index 0000000000..71eaff2035
--- /dev/null
+++ b/rust/qemu-api/.gitignore
@@ -0,0 +1,2 @@
+# Ignore generated bindings file overrides.
+src/bindings.rs.inc
diff --git a/rust/qemu-api/Cargo.lock b/rust/qemu-api/Cargo.lock
new file mode 100644
index 0000000000..e9c51a243a
--- /dev/null
+++ b/rust/qemu-api/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "qemu_api"
+version = "0.1.0"
diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml
new file mode 100644
index 0000000000..51260cbe42
--- /dev/null
+++ b/rust/qemu-api/Cargo.toml
@@ -0,0 +1,23 @@
+[package]
+name = "qemu_api"
+version = "0.1.0"
+edition = "2021"
+authors = ["Manos Pitsidianakis <manos.pitsidianakis@linaro.org>"]
+license = "GPL-2.0 OR GPL-3.0-or-later"
+readme = "README.md"
+homepage = "https://www.qemu.org"
+description = "Rust bindings for QEMU"
+repository = "https://gitlab.com/qemu-project/qemu/"
+resolver = "2"
+publish = false
+keywords = []
+categories = []
+
+[dependencies]
+
+[features]
+default = ["allocator"]
+allocator = []
+
+# Do not include in any global workspace
+[workspace]
diff --git a/rust/qemu-api/README.md b/rust/qemu-api/README.md
new file mode 100644
index 0000000000..7588fa29ef
--- /dev/null
+++ b/rust/qemu-api/README.md
@@ -0,0 +1,17 @@
+# QEMU bindings and API wrappers
+
+This library exports helper Rust types, Rust macros and C FFI bindings for internal QEMU APIs.
+
+The C bindings can be generated with `bindgen`, using this build target:
+
+```console
+$ ninja bindings.rs
+```
+
+## Generate Rust documentation
+
+To generate docs for this crate, including private items:
+
+```sh
+cargo doc --no-deps --document-private-items
+```
diff --git a/rust/qemu-api/build.rs b/rust/qemu-api/build.rs
new file mode 100644
index 0000000000..2f57c2b3d4
--- /dev/null
+++ b/rust/qemu-api/build.rs
@@ -0,0 +1,13 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+
+use std::path::Path;
+
+fn main() {
+ if !Path::new("src/bindings.rs.inc").exists() {
+ panic!(
+ "No generated C bindings found! Either build them manually with bindgen or with meson \
+ (`ninja bindings.rs`) and copy them to src/bindings.rs.inc, or build through meson."
+ );
+ }
+}
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
new file mode 100644
index 0000000000..997d478309
--- /dev/null
+++ b/rust/qemu-api/meson.build
@@ -0,0 +1,17 @@
+_qemu_api_rs = static_library(
+ 'qemu_api',
+ [files('src/lib.rs')],
+ gnu_symbol_visibility: 'hidden',
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ rust_args: rust_args + [
+ '--cfg', 'MESON_BINDINGS_RS',
+ ],
+ link_with: [
+ _lib_bindings_rs,
+ ],
+)
+
+qemu_api = declare_dependency(
+ link_with: _qemu_api_rs,
+)
diff --git a/rust/qemu-api/rustfmt.toml b/rust/qemu-api/rustfmt.toml
new file mode 120000
index 0000000000..39f97b043b
--- /dev/null
+++ b/rust/qemu-api/rustfmt.toml
@@ -0,0 +1 @@
+../rustfmt.toml
\ No newline at end of file
diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs
new file mode 100644
index 0000000000..fb595f1469
--- /dev/null
+++ b/rust/qemu-api/src/bindings.rs
@@ -0,0 +1,7 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+#[cfg(not(MESON_BINDINGS_RS))]
+include!("bindings.rs.inc");
+
+#[cfg(MESON_BINDINGS_RS)]
+pub use ::_bindings_rs::*;
diff --git a/rust/qemu-api/src/definitions.rs b/rust/qemu-api/src/definitions.rs
new file mode 100644
index 0000000000..6de42229b6
--- /dev/null
+++ b/rust/qemu-api/src/definitions.rs
@@ -0,0 +1,108 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+
+//! Definitions required by QEMU when registering a device.
+
+/// Trait a type must implement to be registered with QEMU.
+pub trait ObjectImpl {
+ type Class;
+ const TYPE_INFO: crate::bindings::TypeInfo;
+ const TYPE_NAME: &'static ::core::ffi::CStr;
+ const PARENT_TYPE_NAME: Option<&'static ::core::ffi::CStr>;
+ const INSTANCE_INIT: ::core::option::Option<
+ unsafe extern "C" fn(obj: *mut crate::bindings::Object),
+ >;
+ const INSTANCE_POST_INIT: ::core::option::Option<
+ unsafe extern "C" fn(obj: *mut crate::bindings::Object),
+ >;
+ const INSTANCE_FINALIZE: ::core::option::Option<
+ unsafe extern "C" fn(obj: *mut crate::bindings::Object),
+ >;
+ const ABSTRACT: bool;
+}
+
+pub trait Class {
+ const CLASS_INIT: ::core::option::Option<
+ unsafe extern "C" fn(
+ klass: *mut crate::bindings::ObjectClass,
+ data: *mut core::ffi::c_void,
+ ),
+ >;
+ const CLASS_BASE_INIT: ::core::option::Option<
+ unsafe extern "C" fn(
+ klass: *mut crate::bindings::ObjectClass,
+ data: *mut core::ffi::c_void,
+ ),
+ >;
+}
+
+#[macro_export]
+macro_rules! module_init {
+ ($func:expr, $type:expr) => {
+ #[used]
+ #[cfg_attr(target_os = "linux", link_section = ".ctors")]
+ #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
+ #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
+ pub static LOAD_MODULE: extern "C" fn() = {
+ assert!($type < $crate::bindings::module_init_type_MODULE_INIT_MAX);
+
+ extern "C" fn __load() {
+ unsafe {
+ $crate::bindings::register_module_init(Some($func), $type);
+ }
+ }
+
+ __load
+ };
+ };
+ (qom: $func:ident => $body:block) => {
+ // NOTE: To have custom identifiers for the ctor func we need to either supply
+ // them directly as a macro argument or create them with a proc macro.
+ #[used]
+ #[cfg_attr(target_os = "linux", link_section = ".ctors")]
+ #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
+ #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
+ pub static LOAD_MODULE: extern "C" fn() = {
+ extern "C" fn __load() {
+ #[no_mangle]
+ unsafe extern "C" fn $func() {
+ $body
+ }
+
+ unsafe {
+ $crate::bindings::register_module_init(
+ Some($func),
+ $crate::bindings::module_init_type_MODULE_INIT_QOM,
+ );
+ }
+ }
+
+ __load
+ };
+ };
+}
+
+#[macro_export]
+macro_rules! type_info {
+ ($t:ty) => {
+ $crate::bindings::TypeInfo {
+ name: <$t as $crate::definitions::ObjectImpl>::TYPE_NAME.as_ptr(),
+ parent: if let Some(pname) = <$t as $crate::definitions::ObjectImpl>::PARENT_TYPE_NAME {
+ pname.as_ptr()
+ } else {
+ ::core::ptr::null_mut()
+ },
+ instance_size: ::core::mem::size_of::<$t>(),
+ instance_align: ::core::mem::align_of::<$t>(),
+ instance_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_INIT,
+ instance_post_init: <$t as $crate::definitions::ObjectImpl>::INSTANCE_POST_INIT,
+ instance_finalize: <$t as $crate::definitions::ObjectImpl>::INSTANCE_FINALIZE,
+ abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT,
+ class_size: ::core::mem::size_of::<<$t as $crate::definitions::ObjectImpl>::Class>(),
+ class_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_INIT,
+ class_base_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_BASE_INIT,
+ class_data: ::core::ptr::null_mut(),
+ interfaces: ::core::ptr::null_mut(),
+ };
+ }
+}
diff --git a/rust/qemu-api/src/device_class.rs b/rust/qemu-api/src/device_class.rs
new file mode 100644
index 0000000000..f8d4c04e03
--- /dev/null
+++ b/rust/qemu-api/src/device_class.rs
@@ -0,0 +1,128 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+
+use std::sync::OnceLock;
+
+use crate::bindings::Property;
+
+#[macro_export]
+macro_rules! device_class_init {
+ ($func:ident, props => $props:ident, realize_fn => $realize_fn:expr, reset_fn => $reset_fn:expr, vmsd => $vmsd:ident$(,)*) => {
+ #[no_mangle]
+ pub unsafe extern "C" fn $func(
+ klass: *mut $crate::bindings::ObjectClass,
+ _: *mut ::core::ffi::c_void,
+ ) {
+ let mut dc =
+ ::core::ptr::NonNull::new(klass.cast::<$crate::bindings::DeviceClass>()).unwrap();
+ dc.as_mut().realize = $realize_fn;
+ dc.as_mut().reset = $reset_fn;
+ dc.as_mut().vmsd = &$vmsd;
+ $crate::bindings::device_class_set_props(dc.as_mut(), $props.as_mut_ptr());
+ }
+ };
+}
+
+#[macro_export]
+macro_rules! define_property {
+ ($name:expr, $state:ty, $field:expr, $prop:expr, $type:expr, default = $defval:expr$(,)*) => {
+ $crate::bindings::Property {
+ name: {
+ #[used]
+ static _TEMP: &::core::ffi::CStr = $name;
+ _TEMP.as_ptr()
+ },
+ info: $prop,
+ offset: ::core::mem::offset_of!($state, $field)
+ .try_into()
+ .expect("Could not fit offset value to type"),
+ bitnr: 0,
+ bitmask: 0,
+ set_default: true,
+ defval: $crate::bindings::Property__bindgen_ty_1 { u: $defval.into() },
+ arrayoffset: 0,
+ arrayinfo: ::core::ptr::null(),
+ arrayfieldsize: 0,
+ link_type: ::core::ptr::null(),
+ }
+ };
+ ($name:expr, $state:ty, $field:expr, $prop:expr, $type:expr$(,)*) => {
+ $crate::bindings::Property {
+ name: {
+ #[used]
+ static _TEMP: &::core::ffi::CStr = $name;
+ _TEMP.as_ptr()
+ },
+ info: $prop,
+ offset: ::core::mem::offset_of!($state, $field)
+ .try_into()
+ .expect("Could not fit offset value to type"),
+ bitnr: 0,
+ bitmask: 0,
+ set_default: false,
+ defval: $crate::bindings::Property__bindgen_ty_1 { i: 0 },
+ arrayoffset: 0,
+ arrayinfo: ::core::ptr::null(),
+ arrayfieldsize: 0,
+ link_type: ::core::ptr::null(),
+ }
+ };
+}
+
+#[repr(C)]
+pub struct Properties<const N: usize>(pub OnceLock<[Property; N]>, pub fn() -> [Property; N]);
+
+impl<const N: usize> Properties<N> {
+ pub fn as_mut_ptr(&mut self) -> *mut Property {
+ _ = self.0.get_or_init(self.1);
+ self.0.get_mut().unwrap().as_mut_ptr()
+ }
+}
+
+#[macro_export]
+macro_rules! declare_properties {
+ ($ident:ident, $($prop:expr),*$(,)*) => {
+
+ const fn _calc_prop_len() -> usize {
+ let mut len = 1;
+ $({
+ _ = stringify!($prop);
+ len += 1;
+ })*
+ len
+ }
+ const PROP_LEN: usize = _calc_prop_len();
+
+ #[no_mangle]
+ fn _make_properties() -> [$crate::bindings::Property; PROP_LEN] {
+ [
+ $($prop),*,
+ unsafe { ::core::mem::MaybeUninit::<$crate::bindings::Property>::zeroed().assume_init() },
+ ]
+ }
+
+ #[no_mangle]
+ pub static mut $ident: $crate::device_class::Properties<PROP_LEN> = $crate::device_class::Properties(::std::sync::OnceLock::new(), _make_properties);
+ };
+}
+
+#[macro_export]
+macro_rules! vm_state_description {
+ ($(#[$outer:meta])*
+ $name:ident,
+ $(name: $vname:expr,)*
+ $(unmigratable: $um_val:expr,)*
+ ) => {
+ #[used]
+ $(#[$outer])*
+ pub static $name: $crate::bindings::VMStateDescription = $crate::bindings::VMStateDescription {
+ $(name: {
+ #[used]
+ static VMSTATE_NAME: &::core::ffi::CStr = $vname;
+ $vname.as_ptr()
+ },)*
+ unmigratable: true,
+ ..unsafe { ::core::mem::MaybeUninit::<$crate::bindings::VMStateDescription>::zeroed().assume_init() }
+ };
+ }
+}
diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs
new file mode 100644
index 0000000000..6f02ac45e2
--- /dev/null
+++ b/rust/qemu-api/src/lib.rs
@@ -0,0 +1,100 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+
+#![doc = include_str!("../README.md")]
+
+#[cfg(MESON_BINDINGS_RS)]
+extern crate _bindings_rs;
+
+#[cfg_attr(not(MESON_BINDINGS_RS), allow(
+ improper_ctypes_definitions,
+ improper_ctypes,
+ non_camel_case_types,
+ non_snake_case,
+ non_upper_case_globals
+))]
+#[cfg_attr(not(MESON_BINDINGS_RS), allow(
+ clippy::missing_const_for_fn,
+ clippy::too_many_arguments,
+ clippy::approx_constant,
+ clippy::use_self,
+ clippy::useless_transmute,
+ clippy::missing_safety_doc,
+))]
+#[cfg_attr(not(MESON_BINDINGS_RS), rustfmt::skip)]
+pub mod bindings;
+
+pub mod definitions;
+pub mod device_class;
+
+#[cfg(test)]
+mod tests;
+
+use std::alloc::{GlobalAlloc, Layout};
+
+extern "C" {
+ pub fn g_aligned_alloc0(
+ n_blocks: bindings::gsize,
+ n_block_bytes: bindings::gsize,
+ alignment: bindings::gsize,
+ ) -> bindings::gpointer;
+ pub fn g_aligned_free(mem: bindings::gpointer);
+ pub fn g_malloc0(n_bytes: bindings::gsize) -> bindings::gpointer;
+ pub fn g_free(mem: bindings::gpointer);
+}
+
+/// An allocator that uses the same allocator as QEMU in C.
+///
+/// It is enabled by default with the `allocator` feature.
+///
+/// To set it up manually as a global allocator in your crate:
+///
+/// ```ignore
+/// use qemu_api::QemuAllocator;
+///
+/// #[global_allocator]
+/// static GLOBAL: QemuAllocator = QemuAllocator::new();
+/// ```
+#[derive(Clone, Copy, Debug)]
+#[repr(C)]
+pub struct QemuAllocator {
+ _unused: [u8; 0],
+}
+
+#[cfg_attr(feature = "allocator", global_allocator)]
+pub static GLOBAL: QemuAllocator = QemuAllocator::new();
+
+impl QemuAllocator {
+ pub const fn new() -> Self {
+ Self { _unused: [] }
+ }
+}
+
+impl Default for QemuAllocator {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+unsafe impl GlobalAlloc for QemuAllocator {
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ if layout.align() == 0 {
+ g_malloc0(layout.size().try_into().unwrap()).cast::<u8>()
+ } else {
+ g_aligned_alloc0(
+ layout.size().try_into().unwrap(),
+ 1,
+ layout.align().try_into().unwrap(),
+ )
+ .cast::<u8>()
+ }
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+ if layout.align() == 0 {
+ g_free(ptr.cast::<_>())
+ } else {
+ g_aligned_free(ptr.cast::<_>())
+ }
+ }
+}
diff --git a/rust/qemu-api/src/tests.rs b/rust/qemu-api/src/tests.rs
new file mode 100644
index 0000000000..88c26308ee
--- /dev/null
+++ b/rust/qemu-api/src/tests.rs
@@ -0,0 +1,48 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+
+use crate::{
+ bindings::*, declare_properties, define_property, device_class_init, vm_state_description,
+};
+
+#[test]
+fn test_device_decl_macros() {
+ // Test that macros can compile.
+ vm_state_description! {
+ VMSTATE,
+ name: c"name",
+ unmigratable: true,
+ }
+
+ #[repr(C)]
+ pub struct DummyState {
+ pub char_backend: CharBackend,
+ pub migrate_clock: bool,
+ }
+
+ declare_properties! {
+ DUMMY_PROPERTIES,
+ define_property!(
+ c"chardev",
+ DummyState,
+ char_backend,
+ unsafe { &qdev_prop_chr },
+ CharBackend
+ ),
+ define_property!(
+ c"migrate-clk",
+ DummyState,
+ migrate_clock,
+ unsafe { &qdev_prop_bool },
+ bool
+ ),
+ }
+
+ device_class_init! {
+ dummy_class_init,
+ props => DUMMY_PROPERTIES,
+ realize_fn => None,
+ reset_fn => None,
+ vmsd => VMSTATE,
+ }
+}
diff --git a/rust/rustfmt.toml b/rust/rustfmt.toml
new file mode 100644
index 0000000000..ebecb99fe0
--- /dev/null
+++ b/rust/rustfmt.toml
@@ -0,0 +1,7 @@
+edition = "2021"
+format_generated_files = false
+format_code_in_doc_comments = true
+format_strings = true
+imports_granularity = "Crate"
+group_imports = "StdExternalCrate"
+wrap_comments = true
--
2.44.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 7/7] rust: add PL011 device model
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
` (5 preceding siblings ...)
2024-08-15 11:42 ` [PATCH v7 6/7] rust: add crate to expose bindings and interfaces Manos Pitsidianakis
@ 2024-08-15 11:42 ` Manos Pitsidianakis
2024-08-15 17:10 ` [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Peter Maydell
2024-08-16 8:06 ` Junjie Mao
8 siblings, 0 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-15 11:42 UTC (permalink / raw)
To: qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Manos Pitsidianakis, Zhao Liu, Peter Maydell, ARM TCG CPUs,
Stefan Hajnoczi, Junjie Mao, Pierrick Bouvier, Richard Henderson,
Gustavo Romero, rowan.hart, Mads Ynddal, Markus Armbruster
This commit adds a re-implementation of hw/char/pl011.c in Rust.
How to build:
1. Configure a QEMU build with:
--enable-system --target-list=aarch64-softmmu --enable-rust
2. Launching a VM with qemu-system-aarch64 should use the Rust version
of the pl011 device
Co-authored-by: Junjie Mao <junjie.mao@intel.com>
Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
---
MAINTAINERS | 5 +
hw/arm/Kconfig | 33 +-
rust/Kconfig | 1 +
rust/hw/Kconfig | 2 +
rust/hw/char/Kconfig | 3 +
rust/hw/char/meson.build | 1 +
rust/hw/char/pl011/.gitignore | 2 +
rust/hw/char/pl011/Cargo.lock | 125 +++++
rust/hw/char/pl011/Cargo.toml | 26 +
rust/hw/char/pl011/README.md | 31 ++
rust/hw/char/pl011/meson.build | 21 +
rust/hw/char/pl011/rustfmt.toml | 1 +
rust/hw/char/pl011/src/definitions.rs | 26 +
rust/hw/char/pl011/src/device.rs | 586 +++++++++++++++++++++
rust/hw/char/pl011/src/device_class.rs | 58 ++
rust/hw/char/pl011/src/lib.rs | 584 ++++++++++++++++++++
rust/hw/char/pl011/src/memory_ops.rs | 56 ++
rust/hw/meson.build | 1 +
rust/meson.build | 2 +
scripts/archive-source.sh | 5 +-
scripts/make-release | 5 +-
subprojects/.gitignore | 11 +
subprojects/arbitrary-int-1-rs.wrap | 7 +
subprojects/bilge-0.2-rs.wrap | 7 +
subprojects/bilge-impl-0.2-rs.wrap | 7 +
subprojects/either-1-rs.wrap | 7 +
subprojects/itertools-0.11-rs.wrap | 7 +
.../packagefiles/arbitrary-int-1-rs/meson.build | 19 +
subprojects/packagefiles/bilge-0.2-rs/meson.build | 29 +
.../packagefiles/bilge-impl-0.2-rs/meson.build | 45 ++
subprojects/packagefiles/either-1-rs/meson.build | 24 +
.../packagefiles/itertools-0.11-rs/meson.build | 30 ++
.../packagefiles/proc-macro-error-1-rs/meson.build | 40 ++
.../proc-macro-error-attr-1-rs/meson.build | 32 ++
.../packagefiles/proc-macro2-1-rs/meson.build | 31 ++
subprojects/packagefiles/quote-1-rs/meson.build | 29 +
subprojects/packagefiles/syn-2-rs/meson.build | 40 ++
.../packagefiles/unicode-ident-1-rs/meson.build | 20 +
subprojects/proc-macro-error-1-rs.wrap | 7 +
subprojects/proc-macro-error-attr-1-rs.wrap | 7 +
subprojects/proc-macro2-1-rs.wrap | 7 +
subprojects/quote-1-rs.wrap | 7 +
subprojects/syn-2-rs.wrap | 7 +
subprojects/unicode-ident-1-rs.wrap | 7 +
44 files changed, 1988 insertions(+), 13 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 56a88048d2..604543b303 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1189,6 +1189,11 @@ F: include/hw/*/microbit*.h
F: tests/qtest/microbit-test.c
F: docs/system/arm/nrf.rst
+ARM PL011 Rust device
+M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+S: Maintained
+F: rust/hw/char/pl011/
+
AVR Machines
-------------
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 1ad60da7aa..45438c1bc4 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -20,7 +20,8 @@ config ARM_VIRT
select PCI_EXPRESS
select PCI_EXPRESS_GENERIC_BRIDGE
select PFLASH_CFI01
- select PL011 # UART
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select PL031 # RTC
select PL061 # GPIO
select GPIO_PWR
@@ -80,7 +81,8 @@ config HIGHBANK
select AHCI
select ARM_TIMER # sp804
select ARM_V7M
- select PL011 # UART
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select PL022 # SPI
select PL031 # RTC
select PL061 # GPIO
@@ -93,7 +95,8 @@ config INTEGRATOR
depends on TCG && ARM
select ARM_TIMER
select INTEGRATOR_DEBUG
- select PL011 # UART
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select PL031 # RTC
select PL041 # audio
select PL050 # keyboard/mouse
@@ -119,7 +122,8 @@ config MUSCA
default y
depends on TCG && ARM
select ARMSSE
- select PL011
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select PL031
select SPLIT_IRQ
select UNIMP
@@ -228,7 +232,8 @@ config Z2
depends on TCG && ARM
select PFLASH_CFI01
select WM8750
- select PL011 # UART
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select PXA2XX
config REALVIEW
@@ -248,7 +253,8 @@ config REALVIEW
select WM8750 # audio codec
select LSI_SCSI_PCI
select PCI
- select PL011 # UART
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select PL031 # RTC
select PL041 # audio codec
select PL050 # keyboard/mouse
@@ -273,7 +279,8 @@ config SBSA_REF
select PCI_EXPRESS
select PCI_EXPRESS_GENERIC_BRIDGE
select PFLASH_CFI01
- select PL011 # UART
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select PL031 # RTC
select PL061 # GPIO
select USB_XHCI_SYSBUS
@@ -297,7 +304,8 @@ config STELLARIS
select ARM_V7M
select CMSDK_APB_WATCHDOG
select I2C
- select PL011 # UART
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select PL022 # SPI
select PL061 # GPIO
select SSD0303 # OLED display
@@ -356,7 +364,8 @@ config VEXPRESS
select ARM_TIMER # sp804
select LAN9118
select PFLASH_CFI01
- select PL011 # UART
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select PL041 # audio codec
select PL181 # display
select REALVIEW
@@ -440,7 +449,8 @@ config RASPI
default y
depends on TCG && ARM
select FRAMEBUFFER
- select PL011 # UART
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select SDHCI
select USB_DWC2
select BCM2835_SPI
@@ -515,7 +525,8 @@ config XLNX_VERSAL
select ARM_GIC
select CPU_CLUSTER
select DEVICE_TREE
- select PL011
+ select PL011 if !HAVE_RUST # UART
+ select X_PL011_RUST if HAVE_RUST # UART
select CADENCE
select VIRTIO_MMIO
select UNIMP
diff --git a/rust/Kconfig b/rust/Kconfig
index e69de29bb2..f9f5c39098 100644
--- a/rust/Kconfig
+++ b/rust/Kconfig
@@ -0,0 +1 @@
+source hw/Kconfig
diff --git a/rust/hw/Kconfig b/rust/hw/Kconfig
new file mode 100644
index 0000000000..4d934f30af
--- /dev/null
+++ b/rust/hw/Kconfig
@@ -0,0 +1,2 @@
+# devices Kconfig
+source char/Kconfig
diff --git a/rust/hw/char/Kconfig b/rust/hw/char/Kconfig
new file mode 100644
index 0000000000..a1732a9e97
--- /dev/null
+++ b/rust/hw/char/Kconfig
@@ -0,0 +1,3 @@
+config X_PL011_RUST
+ bool
+ default y if HAVE_RUST
diff --git a/rust/hw/char/meson.build b/rust/hw/char/meson.build
new file mode 100644
index 0000000000..5716dc43ef
--- /dev/null
+++ b/rust/hw/char/meson.build
@@ -0,0 +1 @@
+subdir('pl011')
diff --git a/rust/hw/char/pl011/.gitignore b/rust/hw/char/pl011/.gitignore
new file mode 100644
index 0000000000..71eaff2035
--- /dev/null
+++ b/rust/hw/char/pl011/.gitignore
@@ -0,0 +1,2 @@
+# Ignore generated bindings file overrides.
+src/bindings.rs.inc
diff --git a/rust/hw/char/pl011/Cargo.lock b/rust/hw/char/pl011/Cargo.lock
new file mode 100644
index 0000000000..411bfed9c9
--- /dev/null
+++ b/rust/hw/char/pl011/Cargo.lock
@@ -0,0 +1,125 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "arbitrary-int"
+version = "1.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c84fc003e338a6f69fbd4f7fe9f92b535ff13e9af8997f3b14b6ddff8b1df46d"
+
+[[package]]
+name = "bilge"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc707ed8ebf81de5cd6c7f48f54b4c8621760926cdf35a57000747c512e67b57"
+dependencies = [
+ "arbitrary-int",
+ "bilge-impl",
+]
+
+[[package]]
+name = "bilge-impl"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "feb11e002038ad243af39c2068c8a72bcf147acf05025dcdb916fcc000adb2d8"
+dependencies = [
+ "itertools",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "either"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
+
+[[package]]
+name = "itertools"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "pl011"
+version = "0.1.0"
+dependencies = [
+ "arbitrary-int",
+ "bilge",
+ "bilge-impl",
+ "qemu_api",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "qemu_api"
+version = "0.1.0"
+
+[[package]]
+name = "quote"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml
new file mode 100644
index 0000000000..67a6973da6
--- /dev/null
+++ b/rust/hw/char/pl011/Cargo.toml
@@ -0,0 +1,26 @@
+[package]
+name = "pl011"
+version = "0.1.0"
+edition = "2021"
+authors = ["Manos Pitsidianakis <manos.pitsidianakis@linaro.org>"]
+license = "GPL-2.0 OR GPL-3.0-or-later"
+readme = "README.md"
+homepage = "https://www.qemu.org"
+description = "pl011 device model for QEMU"
+repository = "https://gitlab.com/epilys/rust-for-qemu"
+resolver = "2"
+publish = false
+keywords = []
+categories = []
+
+[lib]
+crate-type = ["staticlib"]
+
+[dependencies]
+arbitrary-int = { version = "1.2.7" }
+bilge = { version = "0.2.0" }
+bilge-impl = { version = "0.2.0" }
+qemu_api = { path = "../../../qemu-api" }
+
+# Do not include in any global workspace
+[workspace]
diff --git a/rust/hw/char/pl011/README.md b/rust/hw/char/pl011/README.md
new file mode 100644
index 0000000000..cd7dea3163
--- /dev/null
+++ b/rust/hw/char/pl011/README.md
@@ -0,0 +1,31 @@
+# PL011 QEMU Device Model
+
+This library implements a device model for the PrimeCell® UART (PL011)
+device in QEMU.
+
+## Build static lib
+
+Host build target must be explicitly specified:
+
+```sh
+cargo build --target x86_64-unknown-linux-gnu
+```
+
+Replace host target triplet if necessary.
+
+## Generate Rust documentation
+
+To generate docs for this crate, including private items:
+
+```sh
+cargo doc --no-deps --document-private-items --target x86_64-unknown-linux-gnu
+```
+
+To include direct dependencies like `bilge` (bitmaps for register types):
+
+```sh
+cargo tree --depth 1 -e normal --prefix none \
+ | cut -d' ' -f1 \
+ | xargs printf -- '-p %s\n' \
+ | xargs cargo doc --no-deps --document-private-items --target x86_64-unknown-linux-gnu
+```
diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build
new file mode 100644
index 0000000000..518d4924a9
--- /dev/null
+++ b/rust/hw/char/pl011/meson.build
@@ -0,0 +1,21 @@
+subproject('bilge-0.2-rs', required: true)
+subproject('bilge-impl-0.2-rs', required: true)
+
+bilge_dep = dependency('bilge-0.2-rs')
+bilge_impl_dep = dependency('bilge-impl-0.2-rs')
+
+_libpl011_rs = static_library(
+ 'pl011',
+ files('src/lib.rs'),
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'c',
+ dependencies: [
+ bilge_dep,
+ bilge_impl_dep,
+ qemu_api,
+ ],
+)
+
+specific_ss.add(when: 'CONFIG_X_PL011_RUST', if_true: [declare_dependency(
+ link_whole: [_libpl011_rs],
+)])
diff --git a/rust/hw/char/pl011/rustfmt.toml b/rust/hw/char/pl011/rustfmt.toml
new file mode 120000
index 0000000000..39f97b043b
--- /dev/null
+++ b/rust/hw/char/pl011/rustfmt.toml
@@ -0,0 +1 @@
+../rustfmt.toml
\ No newline at end of file
diff --git a/rust/hw/char/pl011/src/definitions.rs b/rust/hw/char/pl011/src/definitions.rs
new file mode 100644
index 0000000000..66070559d4
--- /dev/null
+++ b/rust/hw/char/pl011/src/definitions.rs
@@ -0,0 +1,26 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+
+//! Definitions required by QEMU when registering the device.
+
+use core::mem::MaybeUninit;
+
+use qemu_api::bindings::*;
+
+use crate::device::PL011State;
+use qemu_api::definitions::ObjectImpl;
+
+pub const TYPE_PL011: &std::ffi::CStr = c"pl011";
+
+#[used]
+pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
+ name: PL011State::TYPE_INFO.name,
+ unmigratable: true,
+ ..unsafe { MaybeUninit::<VMStateDescription>::zeroed().assume_init() }
+};
+
+qemu_api::module_init! {
+ qom: register_type => {
+ type_register_static(&PL011State::TYPE_INFO);
+ }
+}
diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs
new file mode 100644
index 0000000000..150787f70c
--- /dev/null
+++ b/rust/hw/char/pl011/src/device.rs
@@ -0,0 +1,586 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+
+use crate::{
+ memory_ops::PL011_OPS,
+ registers::{self, Interrupt},
+ RegisterOffset,
+};
+use core::{
+ ffi::{c_int, c_uchar, c_uint, c_void, CStr},
+ ptr::{addr_of, addr_of_mut, NonNull},
+};
+use qemu_api::bindings::{self, *};
+use qemu_api::definitions::ObjectImpl;
+
+static PL011_ID_ARM: [c_uchar; 8] = [0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
+
+const DATA_BREAK: u32 = 1 << 10;
+
+/// QEMU sourced constant.
+pub const PL011_FIFO_DEPTH: usize = 16_usize;
+
+#[repr(C)]
+#[derive(Debug)]
+/// PL011 Device Model in QEMU
+pub struct PL011State {
+ pub parent_obj: SysBusDevice,
+ pub iomem: MemoryRegion,
+ pub readbuff: u32,
+ #[doc(alias = "fr")]
+ pub flags: registers::Flags,
+ #[doc(alias = "lcr")]
+ pub line_control: registers::LineControl,
+ #[doc(alias = "rsr")]
+ pub receive_status_error_clear: registers::ReceiveStatusErrorClear,
+ #[doc(alias = "cr")]
+ pub control: registers::Control,
+ pub dmacr: u32,
+ pub int_enabled: u32,
+ pub int_level: u32,
+ pub read_fifo: [u32; PL011_FIFO_DEPTH],
+ pub ilpr: u32,
+ pub ibrd: u32,
+ pub fbrd: u32,
+ pub ifl: u32,
+ pub read_pos: usize,
+ pub read_count: usize,
+ pub read_trigger: usize,
+ #[doc(alias = "chr")]
+ pub char_backend: CharBackend,
+ /// QEMU interrupts
+ ///
+ /// ```text
+ /// * sysbus MMIO region 0: device registers
+ /// * sysbus IRQ 0: `UARTINTR` (combined interrupt line)
+ /// * sysbus IRQ 1: `UARTRXINTR` (receive FIFO interrupt line)
+ /// * sysbus IRQ 2: `UARTTXINTR` (transmit FIFO interrupt line)
+ /// * sysbus IRQ 3: `UARTRTINTR` (receive timeout interrupt line)
+ /// * sysbus IRQ 4: `UARTMSINTR` (momem status interrupt line)
+ /// * sysbus IRQ 5: `UARTEINTR` (error interrupt line)
+ /// ```
+ #[doc(alias = "irq")]
+ pub interrupts: [qemu_irq; 6usize],
+ #[doc(alias = "clk")]
+ pub clock: NonNull<Clock>,
+ #[doc(alias = "migrate_clk")]
+ pub migrate_clock: bool,
+}
+
+impl ObjectImpl for PL011State {
+ type Class = PL011Class;
+ const TYPE_INFO: qemu_api::bindings::TypeInfo = qemu_api::type_info! { PL011State };
+ const TYPE_NAME: &'static CStr = c"pl011";
+ const PARENT_TYPE_NAME: Option<&'static CStr> = Some(TYPE_SYS_BUS_DEVICE);
+ const ABSTRACT: bool = false;
+ const INSTANCE_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = Some(pl011_init);
+ const INSTANCE_POST_INIT: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
+ const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
+}
+
+#[repr(C)]
+pub struct PL011Class {
+ _inner: [u8; 0],
+}
+
+impl qemu_api::definitions::Class for PL011Class {
+ const CLASS_INIT: Option<
+ unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut core::ffi::c_void),
+ > = Some(crate::device_class::pl011_class_init);
+ const CLASS_BASE_INIT: Option<
+ unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut core::ffi::c_void),
+ > = None;
+}
+
+#[used]
+pub static CLK_NAME: &CStr = c"clk";
+
+impl PL011State {
+ pub fn init(&mut self) {
+ let dev = addr_of_mut!(*self).cast::<DeviceState>();
+ // SAFETY:
+ //
+ // self and self.iomem are guaranteed to be valid at this point since callers
+ // must make sure the `self` reference is valid.
+ unsafe {
+ memory_region_init_io(
+ addr_of_mut!(self.iomem),
+ addr_of_mut!(*self).cast::<Object>(),
+ &PL011_OPS,
+ addr_of_mut!(*self).cast::<c_void>(),
+ Self::TYPE_INFO.name,
+ 0x1000,
+ );
+ let sbd = addr_of_mut!(*self).cast::<SysBusDevice>();
+ sysbus_init_mmio(sbd, addr_of_mut!(self.iomem));
+ for irq in self.interrupts.iter_mut() {
+ sysbus_init_irq(sbd, irq);
+ }
+ }
+ // SAFETY:
+ //
+ // self.clock is not initialized at this point; but since `NonNull<_>` is Copy, we can
+ // overwrite the undefined value without side effects. This is safe since all PL011State
+ // instances are created by QOM code which calls this function to initialize the fields;
+ // therefore no code is able to access an invalid self.clock value.
+ unsafe {
+ self.clock = NonNull::new(qdev_init_clock_in(
+ dev,
+ CLK_NAME.as_ptr(),
+ None, /* pl011_clock_update */
+ addr_of_mut!(*self).cast::<c_void>(),
+ ClockEvent_ClockUpdate,
+ ))
+ .unwrap();
+ }
+ }
+
+ pub fn read(
+ &mut self,
+ offset: hwaddr,
+ _size: core::ffi::c_uint,
+ ) -> std::ops::ControlFlow<u64, u64> {
+ use RegisterOffset::*;
+
+ std::ops::ControlFlow::Break(match RegisterOffset::try_from(offset) {
+ Err(v) if (0x3f8..0x400).contains(&v) => {
+ u64::from(PL011_ID_ARM[((offset - 0xfe0) >> 2) as usize])
+ }
+ Err(_) => {
+ // qemu_log_mask(LOG_GUEST_ERROR, "pl011_read: Bad offset 0x%x\n", (int)offset);
+ 0
+ }
+ Ok(DR) => {
+ // s->flags &= ~PL011_FLAG_RXFF;
+ self.flags.set_receive_fifo_full(false);
+ let c = self.read_fifo[self.read_pos];
+ if self.read_count > 0 {
+ self.read_count -= 1;
+ self.read_pos = (self.read_pos + 1) & (self.fifo_depth() - 1);
+ }
+ if self.read_count == 0 {
+ // self.flags |= PL011_FLAG_RXFE;
+ self.flags.set_receive_fifo_empty(true);
+ }
+ if self.read_count + 1 == self.read_trigger {
+ //self.int_level &= ~ INT_RX;
+ self.int_level &= !registers::INT_RX;
+ }
+ // Update error bits.
+ self.receive_status_error_clear = c.to_be_bytes()[3].into();
+ self.update();
+ // Must call qemu_chr_fe_accept_input, so return Continue:
+ return std::ops::ControlFlow::Continue(c.into());
+ }
+ Ok(RSR) => u8::from(self.receive_status_error_clear).into(),
+ Ok(FR) => u16::from(self.flags).into(),
+ Ok(FBRD) => self.fbrd.into(),
+ Ok(ILPR) => self.ilpr.into(),
+ Ok(IBRD) => self.ibrd.into(),
+ Ok(LCR_H) => u16::from(self.line_control).into(),
+ Ok(CR) => {
+ // We exercise our self-control.
+ u16::from(self.control).into()
+ }
+ Ok(FLS) => self.ifl.into(),
+ Ok(IMSC) => self.int_enabled.into(),
+ Ok(RIS) => self.int_level.into(),
+ Ok(MIS) => u64::from(self.int_level & self.int_enabled),
+ Ok(ICR) => {
+ // "The UARTICR Register is the interrupt clear register and is write-only"
+ // Source: ARM DDI 0183G 3.3.13 Interrupt Clear Register, UARTICR
+ 0
+ }
+ Ok(DMACR) => self.dmacr.into(),
+ })
+ }
+
+ pub fn write(&mut self, offset: hwaddr, value: u64) {
+ // eprintln!("write offset {offset} value {value}");
+ use RegisterOffset::*;
+ let value: u32 = value as u32;
+ match RegisterOffset::try_from(offset) {
+ Err(_bad_offset) => {
+ eprintln!("write bad offset {offset} value {value}");
+ }
+ Ok(DR) => {
+ // ??? Check if transmitter is enabled.
+ let ch: u8 = value as u8;
+ // XXX this blocks entire thread. Rewrite to use
+ // qemu_chr_fe_write and background I/O callbacks
+
+ // SAFETY: self.char_backend is a valid CharBackend instance after it's been
+ // initialized in realize().
+ unsafe {
+ qemu_chr_fe_write_all(addr_of_mut!(self.char_backend), &ch, 1);
+ }
+ self.loopback_tx(value);
+ self.int_level |= registers::INT_TX;
+ self.update();
+ }
+ Ok(RSR) => {
+ self.receive_status_error_clear = 0.into();
+ }
+ Ok(FR) => {
+ // flag writes are ignored
+ }
+ Ok(ILPR) => {
+ self.ilpr = value;
+ }
+ Ok(IBRD) => {
+ self.ibrd = value;
+ }
+ Ok(FBRD) => {
+ self.fbrd = value;
+ }
+ Ok(LCR_H) => {
+ let value = value as u16;
+ let new_val: registers::LineControl = value.into();
+ // Reset the FIFO state on FIFO enable or disable
+ if bool::from(self.line_control.fifos_enabled())
+ ^ bool::from(new_val.fifos_enabled())
+ {
+ self.reset_fifo();
+ }
+ if self.line_control.send_break() ^ new_val.send_break() {
+ let mut break_enable: c_int = new_val.send_break().into();
+ // SAFETY: self.char_backend is a valid CharBackend instance after it's been
+ // initialized in realize().
+ unsafe {
+ qemu_chr_fe_ioctl(
+ addr_of_mut!(self.char_backend),
+ CHR_IOCTL_SERIAL_SET_BREAK as i32,
+ addr_of_mut!(break_enable).cast::<c_void>(),
+ );
+ }
+ self.loopback_break(break_enable > 0);
+ }
+ self.line_control = new_val;
+ self.set_read_trigger();
+ }
+ Ok(CR) => {
+ // ??? Need to implement the enable bit.
+ let value = value as u16;
+ self.control = value.into();
+ self.loopback_mdmctrl();
+ }
+ Ok(FLS) => {
+ self.ifl = value;
+ self.set_read_trigger();
+ }
+ Ok(IMSC) => {
+ self.int_enabled = value;
+ self.update();
+ }
+ Ok(RIS) => {}
+ Ok(MIS) => {}
+ Ok(ICR) => {
+ self.int_level &= !value;
+ self.update();
+ }
+ Ok(DMACR) => {
+ self.dmacr = value;
+ if value & 3 > 0 {
+ // qemu_log_mask(LOG_UNIMP, "pl011: DMA not implemented\n");
+ eprintln!("pl011: DMA not implemented");
+ }
+ }
+ }
+ }
+
+ #[inline]
+ fn loopback_tx(&mut self, value: u32) {
+ if !self.loopback_enabled() {
+ return;
+ }
+
+ // Caveat:
+ //
+ // In real hardware, TX loopback happens at the serial-bit level
+ // and then reassembled by the RX logics back into bytes and placed
+ // into the RX fifo. That is, loopback happens after TX fifo.
+ //
+ // Because the real hardware TX fifo is time-drained at the frame
+ // rate governed by the configured serial format, some loopback
+ // bytes in TX fifo may still be able to get into the RX fifo
+ // that could be full at times while being drained at software
+ // pace.
+ //
+ // In such scenario, the RX draining pace is the major factor
+ // deciding which loopback bytes get into the RX fifo, unless
+ // hardware flow-control is enabled.
+ //
+ // For simplicity, the above described is not emulated.
+ self.put_fifo(value);
+ }
+
+ fn loopback_mdmctrl(&mut self) {
+ if !self.loopback_enabled() {
+ return;
+ }
+
+ /*
+ * Loopback software-driven modem control outputs to modem status inputs:
+ * FR.RI <= CR.Out2
+ * FR.DCD <= CR.Out1
+ * FR.CTS <= CR.RTS
+ * FR.DSR <= CR.DTR
+ *
+ * The loopback happens immediately even if this call is triggered
+ * by setting only CR.LBE.
+ *
+ * CTS/RTS updates due to enabled hardware flow controls are not
+ * dealt with here.
+ */
+
+ //fr = s->flags & ~(PL011_FLAG_RI | PL011_FLAG_DCD |
+ // PL011_FLAG_DSR | PL011_FLAG_CTS);
+ //fr |= (cr & CR_OUT2) ? PL011_FLAG_RI : 0;
+ //fr |= (cr & CR_OUT1) ? PL011_FLAG_DCD : 0;
+ //fr |= (cr & CR_RTS) ? PL011_FLAG_CTS : 0;
+ //fr |= (cr & CR_DTR) ? PL011_FLAG_DSR : 0;
+ //
+ self.flags.set_ring_indicator(self.control.out_2());
+ self.flags.set_data_carrier_detect(self.control.out_1());
+ self.flags.set_clear_to_send(self.control.request_to_send());
+ self.flags
+ .set_data_set_ready(self.control.data_transmit_ready());
+
+ // Change interrupts based on updated FR
+ let mut il = self.int_level;
+
+ il &= !Interrupt::MS;
+ //il |= (fr & PL011_FLAG_DSR) ? INT_DSR : 0;
+ //il |= (fr & PL011_FLAG_DCD) ? INT_DCD : 0;
+ //il |= (fr & PL011_FLAG_CTS) ? INT_CTS : 0;
+ //il |= (fr & PL011_FLAG_RI) ? INT_RI : 0;
+
+ if self.flags.data_set_ready() {
+ il |= Interrupt::DSR as u32;
+ }
+ if self.flags.data_carrier_detect() {
+ il |= Interrupt::DCD as u32;
+ }
+ if self.flags.clear_to_send() {
+ il |= Interrupt::CTS as u32;
+ }
+ if self.flags.ring_indicator() {
+ il |= Interrupt::RI as u32;
+ }
+ self.int_level = il;
+ self.update();
+ }
+
+ fn loopback_break(&mut self, enable: bool) {
+ if enable {
+ self.loopback_tx(DATA_BREAK);
+ }
+ }
+
+ fn set_read_trigger(&mut self) {
+ //#if 0
+ // /* The docs say the RX interrupt is triggered when the FIFO exceeds
+ // the threshold. However linux only reads the FIFO in response to an
+ // interrupt. Triggering the interrupt when the FIFO is non-empty seems
+ // to make things work. */
+ // if (s->lcr & LCR_FEN)
+ // s->read_trigger = (s->ifl >> 1) & 0x1c;
+ // else
+ //#endif
+ self.read_trigger = 1;
+ }
+
+ pub fn realize(&mut self) {
+ // SAFETY: self.char_backend has the correct size and alignment for a
+ // CharBackend object, and its callbacks are of the correct types.
+ unsafe {
+ qemu_chr_fe_set_handlers(
+ addr_of_mut!(self.char_backend),
+ Some(pl011_can_receive),
+ Some(pl011_receive),
+ Some(pl011_event),
+ None,
+ addr_of_mut!(*self).cast::<c_void>(),
+ core::ptr::null_mut(),
+ true,
+ );
+ }
+ }
+
+ pub fn reset(&mut self) {
+ self.line_control.reset();
+ self.receive_status_error_clear.reset();
+ self.dmacr = 0;
+ self.int_enabled = 0;
+ self.int_level = 0;
+ self.ilpr = 0;
+ self.ibrd = 0;
+ self.fbrd = 0;
+ self.read_trigger = 1;
+ self.ifl = 0x12;
+ self.control.reset();
+ self.flags = 0.into();
+ self.reset_fifo();
+ }
+
+ pub fn reset_fifo(&mut self) {
+ self.read_count = 0;
+ self.read_pos = 0;
+
+ /* Reset FIFO flags */
+ self.flags.reset();
+ }
+
+ pub fn can_receive(&self) -> bool {
+ // trace_pl011_can_receive(s->lcr, s->read_count, r);
+ self.read_count < self.fifo_depth()
+ }
+
+ pub fn event(&mut self, event: QEMUChrEvent) {
+ if event == bindings::QEMUChrEvent_CHR_EVENT_BREAK && !self.fifo_enabled() {
+ self.put_fifo(DATA_BREAK);
+ self.receive_status_error_clear.set_break_error(true);
+ }
+ }
+
+ #[inline]
+ pub fn fifo_enabled(&self) -> bool {
+ matches!(self.line_control.fifos_enabled(), registers::Mode::FIFO)
+ }
+
+ #[inline]
+ pub fn loopback_enabled(&self) -> bool {
+ self.control.enable_loopback()
+ }
+
+ #[inline]
+ pub fn fifo_depth(&self) -> usize {
+ // Note: FIFO depth is expected to be power-of-2
+ if self.fifo_enabled() {
+ return PL011_FIFO_DEPTH;
+ }
+ 1
+ }
+
+ pub fn put_fifo(&mut self, value: c_uint) {
+ let depth = self.fifo_depth();
+ assert!(depth > 0);
+ let slot = (self.read_pos + self.read_count) & (depth - 1);
+ self.read_fifo[slot] = value;
+ self.read_count += 1;
+ // s->flags &= ~PL011_FLAG_RXFE;
+ self.flags.set_receive_fifo_empty(false);
+ if self.read_count == depth {
+ //s->flags |= PL011_FLAG_RXFF;
+ self.flags.set_receive_fifo_full(true);
+ }
+
+ if self.read_count == self.read_trigger {
+ self.int_level |= registers::INT_RX;
+ self.update();
+ }
+ }
+
+ pub fn update(&mut self) {
+ let flags = self.int_level & self.int_enabled;
+ for (irq, i) in self.interrupts.iter().zip(IRQMASK) {
+ // SAFETY: self.interrupts have been initialized in init().
+ unsafe { qemu_set_irq(*irq, i32::from(flags & i != 0)) };
+ }
+ }
+}
+
+/// Which bits in the interrupt status matter for each outbound IRQ line ?
+pub const IRQMASK: [u32; 6] = [
+ /* combined IRQ */
+ Interrupt::E
+ | Interrupt::MS
+ | Interrupt::RT as u32
+ | Interrupt::TX as u32
+ | Interrupt::RX as u32,
+ Interrupt::RX as u32,
+ Interrupt::TX as u32,
+ Interrupt::RT as u32,
+ Interrupt::MS,
+ Interrupt::E,
+];
+
+/// # Safety
+///
+/// We expect the FFI user of this function to pass a valid pointer, that has
+/// the same size as [`PL011State`]. We also expect the device is
+/// readable/writeable from one thread at any time.
+#[no_mangle]
+pub unsafe extern "C" fn pl011_can_receive(opaque: *mut c_void) -> c_int {
+ assert!(!opaque.is_null());
+ let state = NonNull::new_unchecked(opaque.cast::<PL011State>());
+ state.as_ref().can_receive().into()
+}
+
+/// # Safety
+///
+/// We expect the FFI user of this function to pass a valid pointer, that has
+/// the same size as [`PL011State`]. We also expect the device is
+/// readable/writeable from one thread at any time.
+///
+/// The buffer and size arguments must also be valid.
+#[no_mangle]
+pub unsafe extern "C" fn pl011_receive(
+ opaque: *mut core::ffi::c_void,
+ buf: *const u8,
+ size: core::ffi::c_int,
+) {
+ assert!(!opaque.is_null());
+ let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
+ if state.as_ref().loopback_enabled() {
+ return;
+ }
+ if size > 0 {
+ assert!(!buf.is_null());
+ state.as_mut().put_fifo(*buf.cast::<c_uint>())
+ }
+}
+
+/// # Safety
+///
+/// We expect the FFI user of this function to pass a valid pointer, that has
+/// the same size as [`PL011State`]. We also expect the device is
+/// readable/writeable from one thread at any time.
+#[no_mangle]
+pub unsafe extern "C" fn pl011_event(opaque: *mut core::ffi::c_void, event: QEMUChrEvent) {
+ assert!(!opaque.is_null());
+ let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
+ state.as_mut().event(event)
+}
+
+/// # Safety
+///
+/// We expect the FFI user of this function to pass a valid pointer for `chr`.
+#[no_mangle]
+pub unsafe extern "C" fn pl011_create(
+ addr: u64,
+ irq: qemu_irq,
+ chr: *mut Chardev,
+) -> *mut DeviceState {
+ let dev: *mut DeviceState = unsafe { qdev_new(PL011State::TYPE_INFO.name) };
+ assert!(!dev.is_null());
+ let sysbus: *mut SysBusDevice = dev as *mut SysBusDevice;
+
+ qdev_prop_set_chr(dev, bindings::TYPE_CHARDEV.as_ptr(), chr);
+ sysbus_realize_and_unref(sysbus, addr_of!(error_fatal) as *mut *mut Error);
+ sysbus_mmio_map(sysbus, 0, addr);
+ sysbus_connect_irq(sysbus, 0, irq);
+ dev
+}
+
+/// # Safety
+///
+/// We expect the FFI user of this function to pass a valid pointer, that has
+/// the same size as [`PL011State`]. We also expect the device is
+/// readable/writeable from one thread at any time.
+#[no_mangle]
+pub unsafe extern "C" fn pl011_init(obj: *mut Object) {
+ assert!(!obj.is_null());
+ let mut state = NonNull::new_unchecked(obj.cast::<PL011State>());
+ state.as_mut().init();
+}
diff --git a/rust/hw/char/pl011/src/device_class.rs b/rust/hw/char/pl011/src/device_class.rs
new file mode 100644
index 0000000000..6b99239133
--- /dev/null
+++ b/rust/hw/char/pl011/src/device_class.rs
@@ -0,0 +1,58 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+
+use core::ptr::NonNull;
+
+use qemu_api::bindings::*;
+
+use crate::{definitions::VMSTATE_PL011, device::PL011State};
+
+qemu_api::declare_properties! {
+ PL011_PROPERTIES,
+ qemu_api::define_property!(
+ c"chardev",
+ PL011State,
+ char_backend,
+ unsafe { &qdev_prop_chr },
+ CharBackend
+ ),
+ qemu_api::define_property!(
+ c"migrate-clk",
+ PL011State,
+ migrate_clock,
+ unsafe { &qdev_prop_bool },
+ bool
+ ),
+}
+
+qemu_api::device_class_init! {
+ pl011_class_init,
+ props => PL011_PROPERTIES,
+ realize_fn => Some(pl011_realize),
+ reset_fn => Some(pl011_reset),
+ vmsd => VMSTATE_PL011,
+}
+
+/// # Safety
+///
+/// We expect the FFI user of this function to pass a valid pointer, that has
+/// the same size as [`PL011State`]. We also expect the device is
+/// readable/writeable from one thread at any time.
+#[no_mangle]
+pub unsafe extern "C" fn pl011_realize(dev: *mut DeviceState, _errp: *mut *mut Error) {
+ assert!(!dev.is_null());
+ let mut state = NonNull::new_unchecked(dev.cast::<PL011State>());
+ state.as_mut().realize();
+}
+
+/// # Safety
+///
+/// We expect the FFI user of this function to pass a valid pointer, that has
+/// the same size as [`PL011State`]. We also expect the device is
+/// readable/writeable from one thread at any time.
+#[no_mangle]
+pub unsafe extern "C" fn pl011_reset(dev: *mut DeviceState) {
+ assert!(!dev.is_null());
+ let mut state = NonNull::new_unchecked(dev.cast::<PL011State>());
+ state.as_mut().reset();
+}
diff --git a/rust/hw/char/pl011/src/lib.rs b/rust/hw/char/pl011/src/lib.rs
new file mode 100644
index 0000000000..697d2ef5a6
--- /dev/null
+++ b/rust/hw/char/pl011/src/lib.rs
@@ -0,0 +1,584 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+//
+// PL011 QEMU Device Model
+//
+// This library implements a device model for the PrimeCell® UART (PL011)
+// device in QEMU.
+//
+#![doc = include_str!("../README.md")]
+//! # Library crate
+//!
+//! See [`PL011State`](crate::device::PL011State) for the device model type and
+//! the [`registers`] module for register types.
+
+#![deny(
+ rustdoc::broken_intra_doc_links,
+ rustdoc::redundant_explicit_links,
+ clippy::correctness,
+ clippy::suspicious,
+ clippy::complexity,
+ clippy::perf,
+ clippy::cargo,
+ clippy::nursery,
+ clippy::style,
+ // restriction group
+ clippy::dbg_macro,
+ clippy::as_underscore,
+ clippy::assertions_on_result_states,
+ // pedantic group
+ clippy::doc_markdown,
+ clippy::borrow_as_ptr,
+ clippy::cast_lossless,
+ clippy::option_if_let_else,
+ clippy::missing_const_for_fn,
+ clippy::cognitive_complexity,
+ clippy::missing_safety_doc,
+ )]
+
+extern crate bilge;
+extern crate bilge_impl;
+extern crate qemu_api;
+
+pub mod definitions;
+pub mod device;
+pub mod device_class;
+pub mod memory_ops;
+
+/// Offset of each register from the base memory address of the device.
+///
+/// # Source
+/// ARM DDI 0183G, Table 3-1 p.3-3
+#[doc(alias = "offset")]
+#[allow(non_camel_case_types)]
+#[repr(u64)]
+#[derive(Debug)]
+pub enum RegisterOffset {
+ /// Data Register
+ ///
+ /// A write to this register initiates the actual data transmission
+ #[doc(alias = "UARTDR")]
+ DR = 0x000,
+ /// Receive Status Register or Error Clear Register
+ #[doc(alias = "UARTRSR")]
+ #[doc(alias = "UARTECR")]
+ RSR = 0x004,
+ /// Flag Register
+ ///
+ /// A read of this register shows if transmission is complete
+ #[doc(alias = "UARTFR")]
+ FR = 0x018,
+ /// Fractional Baud Rate Register
+ ///
+ /// responsible for baud rate speed
+ #[doc(alias = "UARTFBRD")]
+ FBRD = 0x028,
+ /// `IrDA` Low-Power Counter Register
+ #[doc(alias = "UARTILPR")]
+ ILPR = 0x020,
+ /// Integer Baud Rate Register
+ ///
+ /// Responsible for baud rate speed
+ #[doc(alias = "UARTIBRD")]
+ IBRD = 0x024,
+ /// line control register (data frame format)
+ #[doc(alias = "UARTLCR_H")]
+ LCR_H = 0x02C,
+ /// Toggle UART, transmission or reception
+ #[doc(alias = "UARTCR")]
+ CR = 0x030,
+ /// Interrupt FIFO Level Select Register
+ #[doc(alias = "UARTIFLS")]
+ FLS = 0x034,
+ /// Interrupt Mask Set/Clear Register
+ #[doc(alias = "UARTIMSC")]
+ IMSC = 0x038,
+ /// Raw Interrupt Status Register
+ #[doc(alias = "UARTRIS")]
+ RIS = 0x03C,
+ /// Masked Interrupt Status Register
+ #[doc(alias = "UARTMIS")]
+ MIS = 0x040,
+ /// Interrupt Clear Register
+ #[doc(alias = "UARTICR")]
+ ICR = 0x044,
+ /// DMA control Register
+ #[doc(alias = "UARTDMACR")]
+ DMACR = 0x048,
+ ///// Reserved, offsets `0x04C` to `0x07C`.
+ //Reserved = 0x04C,
+}
+
+impl core::convert::TryFrom<u64> for RegisterOffset {
+ type Error = u64;
+
+ fn try_from(value: u64) -> Result<Self, Self::Error> {
+ macro_rules! case {
+ ($($discriminant:ident),*$(,)*) => {
+ /* check that matching on all macro arguments compiles, which means we are not
+ * missing any enum value; if the type definition ever changes this will stop
+ * compiling.
+ */
+ const fn _assert_exhaustive(val: RegisterOffset) {
+ match val {
+ $(RegisterOffset::$discriminant => (),)*
+ }
+ }
+
+ match value {
+ $(x if x == Self::$discriminant as u64 => Ok(Self::$discriminant),)*
+ _ => Err(value),
+ }
+ }
+ }
+ case! { DR, RSR, FR, FBRD, ILPR, IBRD, LCR_H, CR, FLS, IMSC, RIS, MIS, ICR, DMACR }
+ }
+}
+
+pub mod registers {
+ //! Device registers exposed as typed structs which are backed by arbitrary
+ //! integer bitmaps. [`Data`], [`Control`], [`LineControl`], etc.
+ //!
+ //! All PL011 registers are essentially 32-bit wide, but are typed here as
+ //! bitmaps with only the necessary width. That is, if a struct bitmap
+ //! in this module is for example 16 bits long, it should be conceived
+ //! as a 32-bit register where the unmentioned higher bits are always
+ //! unused thus treated as zero when read or written.
+ use bilge::prelude::*;
+
+ // TODO: FIFO Mode has different semantics
+ /// Data Register, `UARTDR`
+ ///
+ /// The `UARTDR` register is the data register.
+ ///
+ /// For words to be transmitted:
+ ///
+ /// - if the FIFOs are enabled, data written to this location is pushed onto
+ /// the transmit
+ /// FIFO
+ /// - if the FIFOs are not enabled, data is stored in the transmitter
+ /// holding register (the
+ /// bottom word of the transmit FIFO).
+ ///
+ /// The write operation initiates transmission from the UART. The data is
+ /// prefixed with a start bit, appended with the appropriate parity bit
+ /// (if parity is enabled), and a stop bit. The resultant word is then
+ /// transmitted.
+ ///
+ /// For received words:
+ ///
+ /// - if the FIFOs are enabled, the data byte and the 4-bit status (break,
+ /// frame, parity,
+ /// and overrun) is pushed onto the 12-bit wide receive FIFO
+ /// - if the FIFOs are not enabled, the data byte and status are stored in
+ /// the receiving
+ /// holding register (the bottom word of the receive FIFO).
+ ///
+ /// The received data byte is read by performing reads from the `UARTDR`
+ /// register along with the corresponding status information. The status
+ /// information can also be read by a read of the `UARTRSR/UARTECR`
+ /// register.
+ ///
+ /// # Note
+ ///
+ /// You must disable the UART before any of the control registers are
+ /// reprogrammed. When the UART is disabled in the middle of
+ /// transmission or reception, it completes the current character before
+ /// stopping.
+ ///
+ /// # Source
+ /// ARM DDI 0183G 3.3.1 Data Register, UARTDR
+ #[bitsize(16)]
+ #[derive(Clone, Copy, DebugBits, FromBits)]
+ #[doc(alias = "UARTDR")]
+ pub struct Data {
+ _reserved: u4,
+ pub data: u8,
+ pub framing_error: bool,
+ pub parity_error: bool,
+ pub break_error: bool,
+ pub overrun_error: bool,
+ }
+
+ // TODO: FIFO Mode has different semantics
+ /// Receive Status Register / Error Clear Register, `UARTRSR/UARTECR`
+ ///
+ /// The UARTRSR/UARTECR register is the receive status register/error clear
+ /// register. Receive status can also be read from the `UARTRSR`
+ /// register. If the status is read from this register, then the status
+ /// information for break, framing and parity corresponds to the
+ /// data character read from the [Data register](Data), `UARTDR` prior to
+ /// reading the UARTRSR register. The status information for overrun is
+ /// set immediately when an overrun condition occurs.
+ ///
+ ///
+ /// # Note
+ /// The received data character must be read first from the [Data
+ /// Register](Data), `UARTDR` before reading the error status associated
+ /// with that data character from the `UARTRSR` register. This read
+ /// sequence cannot be reversed, because the `UARTRSR` register is
+ /// updated only when a read occurs from the `UARTDR` register. However,
+ /// the status information can also be obtained by reading the `UARTDR`
+ /// register
+ ///
+ /// # Source
+ /// ARM DDI 0183G 3.3.2 Receive Status Register/Error Clear Register,
+ /// UARTRSR/UARTECR
+ #[bitsize(8)]
+ #[derive(Clone, Copy, DebugBits, FromBits)]
+ pub struct ReceiveStatusErrorClear {
+ pub framing_error: bool,
+ pub parity_error: bool,
+ pub break_error: bool,
+ pub overrun_error: bool,
+ _reserved_unpredictable: u4,
+ }
+
+ impl ReceiveStatusErrorClear {
+ pub fn reset(&mut self) {
+ // All the bits are cleared to 0 on reset.
+ *self = 0.into();
+ }
+ }
+
+ impl Default for ReceiveStatusErrorClear {
+ fn default() -> Self {
+ 0.into()
+ }
+ }
+
+ #[bitsize(16)]
+ #[derive(Clone, Copy, DebugBits, FromBits)]
+ /// Flag Register, `UARTFR`
+ #[doc(alias = "UARTFR")]
+ pub struct Flags {
+ /// CTS Clear to send. This bit is the complement of the UART clear to
+ /// send, `nUARTCTS`, modem status input. That is, the bit is 1
+ /// when `nUARTCTS` is LOW.
+ pub clear_to_send: bool,
+ /// DSR Data set ready. This bit is the complement of the UART data set
+ /// ready, `nUARTDSR`, modem status input. That is, the bit is 1 when
+ /// `nUARTDSR` is LOW.
+ pub data_set_ready: bool,
+ /// DCD Data carrier detect. This bit is the complement of the UART data
+ /// carrier detect, `nUARTDCD`, modem status input. That is, the bit is
+ /// 1 when `nUARTDCD` is LOW.
+ pub data_carrier_detect: bool,
+ /// BUSY UART busy. If this bit is set to 1, the UART is busy
+ /// transmitting data. This bit remains set until the complete
+ /// byte, including all the stop bits, has been sent from the
+ /// shift register. This bit is set as soon as the transmit FIFO
+ /// becomes non-empty, regardless of whether the UART is enabled
+ /// or not.
+ pub busy: bool,
+ /// RXFE Receive FIFO empty. The meaning of this bit depends on the
+ /// state of the FEN bit in the UARTLCR_H register. If the FIFO
+ /// is disabled, this bit is set when the receive holding
+ /// register is empty. If the FIFO is enabled, the RXFE bit is
+ /// set when the receive FIFO is empty.
+ pub receive_fifo_empty: bool,
+ /// TXFF Transmit FIFO full. The meaning of this bit depends on the
+ /// state of the FEN bit in the UARTLCR_H register. If the FIFO
+ /// is disabled, this bit is set when the transmit holding
+ /// register is full. If the FIFO is enabled, the TXFF bit is
+ /// set when the transmit FIFO is full.
+ pub transmit_fifo_full: bool,
+ /// RXFF Receive FIFO full. The meaning of this bit depends on the state
+ /// of the FEN bit in the UARTLCR_H register. If the FIFO is
+ /// disabled, this bit is set when the receive holding register
+ /// is full. If the FIFO is enabled, the RXFF bit is set when
+ /// the receive FIFO is full.
+ pub receive_fifo_full: bool,
+ /// Transmit FIFO empty. The meaning of this bit depends on the state of
+ /// the FEN bit in the [Line Control register](LineControl),
+ /// `UARTLCR_H`. If the FIFO is disabled, this bit is set when the
+ /// transmit holding register is empty. If the FIFO is enabled,
+ /// the TXFE bit is set when the transmit FIFO is empty. This
+ /// bit does not indicate if there is data in the transmit shift
+ /// register.
+ pub transmit_fifo_empty: bool,
+ /// `RI`, is `true` when `nUARTRI` is `LOW`.
+ pub ring_indicator: bool,
+ _reserved_zero_no_modify: u7,
+ }
+
+ impl Flags {
+ pub fn reset(&mut self) {
+ // After reset TXFF, RXFF, and BUSY are 0, and TXFE and RXFE are 1
+ self.set_receive_fifo_full(false);
+ self.set_transmit_fifo_full(false);
+ self.set_busy(false);
+ self.set_receive_fifo_empty(true);
+ self.set_transmit_fifo_empty(true);
+ }
+ }
+
+ impl Default for Flags {
+ fn default() -> Self {
+ let mut ret: Self = 0.into();
+ ret.reset();
+ ret
+ }
+ }
+
+ #[bitsize(16)]
+ #[derive(Clone, Copy, DebugBits, FromBits)]
+ /// Line Control Register, `UARTLCR_H`
+ #[doc(alias = "UARTLCR_H")]
+ pub struct LineControl {
+ /// 15:8 - Reserved, do not modify, read as zero.
+ _reserved_zero_no_modify: u8,
+ /// 7 SPS Stick parity select.
+ /// 0 = stick parity is disabled
+ /// 1 = either:
+ /// • if the EPS bit is 0 then the parity bit is transmitted and checked
+ /// as a 1 • if the EPS bit is 1 then the parity bit is
+ /// transmitted and checked as a 0. This bit has no effect when
+ /// the PEN bit disables parity checking and generation. See Table 3-11
+ /// on page 3-14 for the parity truth table.
+ pub sticky_parity: bool,
+ /// WLEN Word length. These bits indicate the number of data bits
+ /// transmitted or received in a frame as follows: b11 = 8 bits
+ /// b10 = 7 bits
+ /// b01 = 6 bits
+ /// b00 = 5 bits.
+ pub word_length: WordLength,
+ /// FEN Enable FIFOs:
+ /// 0 = FIFOs are disabled (character mode) that is, the FIFOs become
+ /// 1-byte-deep holding registers 1 = transmit and receive FIFO
+ /// buffers are enabled (FIFO mode).
+ pub fifos_enabled: Mode,
+ /// 3 STP2 Two stop bits select. If this bit is set to 1, two stop bits
+ /// are transmitted at the end of the frame. The receive
+ /// logic does not check for two stop bits being received.
+ pub two_stops_bits: bool,
+ /// EPS Even parity select. Controls the type of parity the UART uses
+ /// during transmission and reception:
+ /// - 0 = odd parity. The UART generates or checks for an odd number of
+ /// 1s in the data and parity bits.
+ /// - 1 = even parity. The UART generates or checks for an even number
+ /// of 1s in the data and parity bits.
+ /// This bit has no effect when the `PEN` bit disables parity checking
+ /// and generation. See Table 3-11 on page 3-14 for the parity
+ /// truth table.
+ pub parity: Parity,
+ /// 1 PEN Parity enable:
+ ///
+ /// - 0 = parity is disabled and no parity bit added to the data frame
+ /// - 1 = parity checking and generation is enabled.
+ ///
+ /// See Table 3-11 on page 3-14 for the parity truth table.
+ pub parity_enabled: bool,
+ /// BRK Send break.
+ ///
+ /// If this bit is set to `1`, a low-level is continually output on the
+ /// `UARTTXD` output, after completing transmission of the
+ /// current character. For the proper execution of the break command,
+ /// the software must set this bit for at least two complete
+ /// frames. For normal use, this bit must be cleared to `0`.
+ pub send_break: bool,
+ }
+
+ impl LineControl {
+ pub fn reset(&mut self) {
+ // All the bits are cleared to 0 when reset.
+ *self = 0.into();
+ }
+ }
+
+ impl Default for LineControl {
+ fn default() -> Self {
+ 0.into()
+ }
+ }
+
+ #[bitsize(1)]
+ #[derive(Clone, Copy, Debug, Eq, FromBits, PartialEq)]
+ /// `EPS` "Even parity select", field of [Line Control
+ /// register](LineControl).
+ pub enum Parity {
+ /// - 0 = odd parity. The UART generates or checks for an odd number of
+ /// 1s in the data and parity bits.
+ Odd = 0,
+ /// - 1 = even parity. The UART generates or checks for an even number
+ /// of 1s in the data and parity bits.
+ Even = 1,
+ }
+
+ #[bitsize(1)]
+ #[derive(Clone, Copy, Debug, Eq, FromBits, PartialEq)]
+ /// `FEN` "Enable FIFOs" or Device mode, field of [Line Control
+ /// register](LineControl).
+ pub enum Mode {
+ /// 0 = FIFOs are disabled (character mode) that is, the FIFOs become
+ /// 1-byte-deep holding registers
+ Character = 0,
+ /// 1 = transmit and receive FIFO buffers are enabled (FIFO mode).
+ FIFO = 1,
+ }
+
+ impl From<Mode> for bool {
+ fn from(val: Mode) -> Self {
+ matches!(val, Mode::FIFO)
+ }
+ }
+
+ #[bitsize(2)]
+ #[derive(Clone, Copy, Debug, Eq, FromBits, PartialEq)]
+ /// `WLEN` Word length, field of [Line Control register](LineControl).
+ ///
+ /// These bits indicate the number of data bits transmitted or received in a
+ /// frame as follows:
+ pub enum WordLength {
+ /// b11 = 8 bits
+ _8Bits = 0b11,
+ /// b10 = 7 bits
+ _7Bits = 0b10,
+ /// b01 = 6 bits
+ _6Bits = 0b01,
+ /// b00 = 5 bits.
+ _5Bits = 0b00,
+ }
+
+ /// Control Register, `UARTCR`
+ ///
+ /// The `UARTCR` register is the control register. All the bits are cleared
+ /// to `0` on reset except for bits `9` and `8` that are set to `1`.
+ ///
+ /// # Source
+ /// ARM DDI 0183G, 3.3.8 Control Register, `UARTCR`, Table 3-12
+ #[bitsize(16)]
+ #[doc(alias = "UARTCR")]
+ #[derive(Clone, Copy, DebugBits, FromBits)]
+ pub struct Control {
+ /// `UARTEN` UART enable: 0 = UART is disabled. If the UART is disabled
+ /// in the middle of transmission or reception, it completes the current
+ /// character before stopping. 1 = the UART is enabled. Data
+ /// transmission and reception occurs for either UART signals or SIR
+ /// signals depending on the setting of the SIREN bit.
+ pub enable_uart: bool,
+ /// `SIREN` `SIR` enable: 0 = IrDA SIR ENDEC is disabled. `nSIROUT`
+ /// remains LOW (no light pulse generated), and signal transitions on
+ /// SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is
+ /// transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH,
+ /// in the marking state. Signal transitions on UARTRXD or modem status
+ /// inputs have no effect. This bit has no effect if the UARTEN bit
+ /// disables the UART.
+ pub enable_sir: bool,
+ /// `SIRLP` SIR low-power IrDA mode. This bit selects the IrDA encoding
+ /// mode. If this bit is cleared to 0, low-level bits are transmitted as
+ /// an active high pulse with a width of 3/ 16th of the bit period. If
+ /// this bit is set to 1, low-level bits are transmitted with a pulse
+ /// width that is 3 times the period of the IrLPBaud16 input signal,
+ /// regardless of the selected bit rate. Setting this bit uses less
+ /// power, but might reduce transmission distances.
+ pub sir_lowpower_irda_mode: u1,
+ /// Reserved, do not modify, read as zero.
+ _reserved_zero_no_modify: u4,
+ /// `LBE` Loopback enable. If this bit is set to 1 and the SIREN bit is
+ /// set to 1 and the SIRTEST bit in the Test Control register, UARTTCR
+ /// on page 4-5 is set to 1, then the nSIROUT path is inverted, and fed
+ /// through to the SIRIN path. The SIRTEST bit in the test register must
+ /// be set to 1 to override the normal half-duplex SIR operation. This
+ /// must be the requirement for accessing the test registers during
+ /// normal operation, and SIRTEST must be cleared to 0 when loopback
+ /// testing is finished. This feature reduces the amount of external
+ /// coupling required during system test. If this bit is set to 1, and
+ /// the SIRTEST bit is set to 0, the UARTTXD path is fed through to the
+ /// UARTRXD path. In either SIR mode or UART mode, when this bit is set,
+ /// the modem outputs are also fed through to the modem inputs. This bit
+ /// is cleared to 0 on reset, to disable loopback.
+ pub enable_loopback: bool,
+ /// `TXE` Transmit enable. If this bit is set to 1, the transmit section
+ /// of the UART is enabled. Data transmission occurs for either UART
+ /// signals, or SIR signals depending on the setting of the SIREN bit.
+ /// When the UART is disabled in the middle of transmission, it
+ /// completes the current character before stopping.
+ pub enable_transmit: bool,
+ /// `RXE` Receive enable. If this bit is set to 1, the receive section
+ /// of the UART is enabled. Data reception occurs for either UART
+ /// signals or SIR signals depending on the setting of the SIREN bit.
+ /// When the UART is disabled in the middle of reception, it completes
+ /// the current character before stopping.
+ pub enable_receive: bool,
+ /// `DTR` Data transmit ready. This bit is the complement of the UART
+ /// data transmit ready, `nUARTDTR`, modem status output. That is, when
+ /// the bit is programmed to a 1 then `nUARTDTR` is LOW.
+ pub data_transmit_ready: bool,
+ /// `RTS` Request to send. This bit is the complement of the UART
+ /// request to send, `nUARTRTS`, modem status output. That is, when the
+ /// bit is programmed to a 1 then `nUARTRTS` is LOW.
+ pub request_to_send: bool,
+ /// `Out1` This bit is the complement of the UART Out1 (`nUARTOut1`)
+ /// modem status output. That is, when the bit is programmed to a 1 the
+ /// output is 0. For DTE this can be used as Data Carrier Detect (DCD).
+ pub out_1: bool,
+ /// `Out2` This bit is the complement of the UART Out2 (`nUARTOut2`)
+ /// modem status output. That is, when the bit is programmed to a 1, the
+ /// output is 0. For DTE this can be used as Ring Indicator (RI).
+ pub out_2: bool,
+ /// `RTSEn` RTS hardware flow control enable. If this bit is set to 1,
+ /// RTS hardware flow control is enabled. Data is only requested when
+ /// there is space in the receive FIFO for it to be received.
+ pub rts_hardware_flow_control_enable: bool,
+ /// `CTSEn` CTS hardware flow control enable. If this bit is set to 1,
+ /// CTS hardware flow control is enabled. Data is only transmitted when
+ /// the `nUARTCTS` signal is asserted.
+ pub cts_hardware_flow_control_enable: bool,
+ }
+
+ impl Control {
+ pub fn reset(&mut self) {
+ *self = 0.into();
+ self.set_enable_receive(true);
+ self.set_enable_transmit(true);
+ }
+ }
+
+ impl Default for Control {
+ fn default() -> Self {
+ let mut ret: Self = 0.into();
+ ret.reset();
+ ret
+ }
+ }
+
+ /// Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC
+ pub const INT_OE: u32 = 1 << 10;
+ pub const INT_BE: u32 = 1 << 9;
+ pub const INT_PE: u32 = 1 << 8;
+ pub const INT_FE: u32 = 1 << 7;
+ pub const INT_RT: u32 = 1 << 6;
+ pub const INT_TX: u32 = 1 << 5;
+ pub const INT_RX: u32 = 1 << 4;
+ pub const INT_DSR: u32 = 1 << 3;
+ pub const INT_DCD: u32 = 1 << 2;
+ pub const INT_CTS: u32 = 1 << 1;
+ pub const INT_RI: u32 = 1 << 0;
+ pub const INT_E: u32 = INT_OE | INT_BE | INT_PE | INT_FE;
+ pub const INT_MS: u32 = INT_RI | INT_DSR | INT_DCD | INT_CTS;
+
+ #[repr(u32)]
+ pub enum Interrupt {
+ OE = 1 << 10,
+ BE = 1 << 9,
+ PE = 1 << 8,
+ FE = 1 << 7,
+ RT = 1 << 6,
+ TX = 1 << 5,
+ RX = 1 << 4,
+ DSR = 1 << 3,
+ DCD = 1 << 2,
+ CTS = 1 << 1,
+ RI = 1 << 0,
+ }
+
+ impl Interrupt {
+ pub const E: u32 = INT_OE | INT_BE | INT_PE | INT_FE;
+ pub const MS: u32 = INT_RI | INT_DSR | INT_DCD | INT_CTS;
+ }
+}
+
+// TODO: You must disable the UART before any of the control registers are
+// reprogrammed. When the UART is disabled in the middle of transmission or
+// reception, it completes the current character before stopping
diff --git a/rust/hw/char/pl011/src/memory_ops.rs b/rust/hw/char/pl011/src/memory_ops.rs
new file mode 100644
index 0000000000..5e185b7cd7
--- /dev/null
+++ b/rust/hw/char/pl011/src/memory_ops.rs
@@ -0,0 +1,56 @@
+// Copyright 2024 Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+// SPDX-License-Identifier: GPL-2.0 OR GPL-3.0-or-later
+
+use core::{mem::MaybeUninit, ptr::NonNull};
+
+use qemu_api::bindings::*;
+
+use crate::device::PL011State;
+
+pub static PL011_OPS: MemoryRegionOps = MemoryRegionOps {
+ read: Some(pl011_read),
+ write: Some(pl011_write),
+ read_with_attrs: None,
+ write_with_attrs: None,
+ endianness: device_endian_DEVICE_NATIVE_ENDIAN,
+ valid: unsafe { MaybeUninit::<MemoryRegionOps__bindgen_ty_1>::zeroed().assume_init() },
+ impl_: MemoryRegionOps__bindgen_ty_2 {
+ min_access_size: 4,
+ max_access_size: 4,
+ ..unsafe { MaybeUninit::<MemoryRegionOps__bindgen_ty_2>::zeroed().assume_init() }
+ },
+};
+
+#[no_mangle]
+unsafe extern "C" fn pl011_read(
+ opaque: *mut core::ffi::c_void,
+ addr: hwaddr,
+ size: core::ffi::c_uint,
+) -> u64 {
+ assert!(!opaque.is_null());
+ let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
+ let val = state.as_mut().read(addr, size);
+ match val {
+ std::ops::ControlFlow::Break(val) => val,
+ std::ops::ControlFlow::Continue(val) => {
+ // SAFETY: self.char_backend is a valid CharBackend instance after it's been
+ // initialized in realize().
+ let cb_ptr = core::ptr::addr_of_mut!(state.as_mut().char_backend);
+ unsafe { qemu_chr_fe_accept_input(cb_ptr) };
+
+ val
+ }
+ }
+}
+
+#[no_mangle]
+unsafe extern "C" fn pl011_write(
+ opaque: *mut core::ffi::c_void,
+ addr: hwaddr,
+ data: u64,
+ _size: core::ffi::c_uint,
+) {
+ assert!(!opaque.is_null());
+ let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
+ state.as_mut().write(addr, data)
+}
diff --git a/rust/hw/meson.build b/rust/hw/meson.build
new file mode 100644
index 0000000000..860196645e
--- /dev/null
+++ b/rust/hw/meson.build
@@ -0,0 +1 @@
+subdir('char')
diff --git a/rust/meson.build b/rust/meson.build
index d5f32aed25..590e9397c3 100644
--- a/rust/meson.build
+++ b/rust/meson.build
@@ -7,3 +7,5 @@ _lib_bindings_rs = static_library(
)
subdir('qemu-api')
+
+subdir('hw')
diff --git a/scripts/archive-source.sh b/scripts/archive-source.sh
index 65af8063e4..eed67b3e67 100755
--- a/scripts/archive-source.sh
+++ b/scripts/archive-source.sh
@@ -26,7 +26,10 @@ sub_file="${sub_tdir}/submodule.tar"
# independent of what the developer currently has initialized
# in their checkout, because the build environment is completely
# different to the host OS.
-subprojects="keycodemapdb libvfio-user berkeley-softfloat-3 berkeley-testfloat-3"
+subprojects="keycodemapdb libvfio-user berkeley-softfloat-3 berkeley-testfloat-3
+ arbitrary-int-1.2.7 bilge-0.2.0 bilge-impl-0.2.0 either-1.12.0 itertools-0.11.0
+ proc-macro2-1.0.84 proc-macro-error-1.0.4 proc-macro-error-attr-1.0.4
+ quote-1.0.36 syn-2.0.66 unicode-ident-1.0.12"
sub_deinit=""
function cleanup() {
diff --git a/scripts/make-release b/scripts/make-release
index 6e0433de24..841404274b 100755
--- a/scripts/make-release
+++ b/scripts/make-release
@@ -17,7 +17,10 @@ if [ $# -ne 2 ]; then
fi
# Only include wraps that are invoked with subproject()
-SUBPROJECTS="libvfio-user keycodemapdb berkeley-softfloat-3 berkeley-testfloat-3"
+SUBPROJECTS="libvfio-user keycodemapdb berkeley-softfloat-3 berkeley-testfloat-3
+ arbitrary-int-1.2.7 bilge-0.2.0 bilge-impl-0.2.0 either-1.12.0 itertools-0.11.0
+ proc-macro2-1.0.84 proc-macro-error-1.0.4 proc-macro-error-attr-1.0.4
+ quote-1.0.36 syn-2.0.66 unicode-ident-1.0.12"
src="$1"
version="$2"
diff --git a/subprojects/.gitignore b/subprojects/.gitignore
index adca0266be..50f173f90d 100644
--- a/subprojects/.gitignore
+++ b/subprojects/.gitignore
@@ -6,3 +6,14 @@
/keycodemapdb
/libvfio-user
/slirp
+/arbitrary-int-1.2.7
+/bilge-0.2.0
+/bilge-impl-0.2.0
+/either-1.12.0
+/itertools-0.11.0
+/proc-macro-error-1.0.4
+/proc-macro-error-attr-1.0.4
+/proc-macro2-1.0.84
+/quote-1.0.36
+/syn-2.0.66
+/unicode-ident-1.0.12
diff --git a/subprojects/arbitrary-int-1-rs.wrap b/subprojects/arbitrary-int-1-rs.wrap
new file mode 100644
index 0000000000..e580538a87
--- /dev/null
+++ b/subprojects/arbitrary-int-1-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = arbitrary-int-1.2.7
+source_url = https://crates.io/api/v1/crates/arbitrary-int/1.2.7/download
+source_filename = arbitrary-int-1.2.7.tar.gz
+source_hash = c84fc003e338a6f69fbd4f7fe9f92b535ff13e9af8997f3b14b6ddff8b1df46d
+#method = cargo
+patch_directory = arbitrary-int-1-rs
diff --git a/subprojects/bilge-0.2-rs.wrap b/subprojects/bilge-0.2-rs.wrap
new file mode 100644
index 0000000000..7a4339d298
--- /dev/null
+++ b/subprojects/bilge-0.2-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = bilge-0.2.0
+source_url = https://crates.io/api/v1/crates/bilge/0.2.0/download
+source_filename = bilge-0.2.0.tar.gz
+source_hash = dc707ed8ebf81de5cd6c7f48f54b4c8621760926cdf35a57000747c512e67b57
+#method = cargo
+patch_directory = bilge-0.2-rs
diff --git a/subprojects/bilge-impl-0.2-rs.wrap b/subprojects/bilge-impl-0.2-rs.wrap
new file mode 100644
index 0000000000..eefb10c36c
--- /dev/null
+++ b/subprojects/bilge-impl-0.2-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = bilge-impl-0.2.0
+source_url = https://crates.io/api/v1/crates/bilge-impl/0.2.0/download
+source_filename = bilge-impl-0.2.0.tar.gz
+source_hash = feb11e002038ad243af39c2068c8a72bcf147acf05025dcdb916fcc000adb2d8
+#method = cargo
+patch_directory = bilge-impl-0.2-rs
diff --git a/subprojects/either-1-rs.wrap b/subprojects/either-1-rs.wrap
new file mode 100644
index 0000000000..6046712036
--- /dev/null
+++ b/subprojects/either-1-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = either-1.12.0
+source_url = https://crates.io/api/v1/crates/either/1.12.0/download
+source_filename = either-1.12.0.tar.gz
+source_hash = 3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b
+#method = cargo
+patch_directory = either-1-rs
diff --git a/subprojects/itertools-0.11-rs.wrap b/subprojects/itertools-0.11-rs.wrap
new file mode 100644
index 0000000000..66b05252cd
--- /dev/null
+++ b/subprojects/itertools-0.11-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = itertools-0.11.0
+source_url = https://crates.io/api/v1/crates/itertools/0.11.0/download
+source_filename = itertools-0.11.0.tar.gz
+source_hash = b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57
+#method = cargo
+patch_directory = itertools-0.11-rs
diff --git a/subprojects/packagefiles/arbitrary-int-1-rs/meson.build b/subprojects/packagefiles/arbitrary-int-1-rs/meson.build
new file mode 100644
index 0000000000..34a189cbae
--- /dev/null
+++ b/subprojects/packagefiles/arbitrary-int-1-rs/meson.build
@@ -0,0 +1,19 @@
+project('arbitrary-int-1-rs', 'rust',
+ version: '1.2.7',
+ license: 'MIT',
+ default_options: [])
+
+_arbitrary_int_rs = static_library(
+ 'arbitrary_int',
+ files('src/lib.rs'),
+ gnu_symbol_visibility: 'hidden',
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ dependencies: [],
+)
+
+arbitrary_int_dep = declare_dependency(
+ link_with: _arbitrary_int_rs,
+)
+
+meson.override_dependency('arbitrary-int-1-rs', arbitrary_int_dep)
diff --git a/subprojects/packagefiles/bilge-0.2-rs/meson.build b/subprojects/packagefiles/bilge-0.2-rs/meson.build
new file mode 100644
index 0000000000..a6ed4a8f0c
--- /dev/null
+++ b/subprojects/packagefiles/bilge-0.2-rs/meson.build
@@ -0,0 +1,29 @@
+project(
+ 'bilge-0.2-rs',
+ 'rust',
+ version : '0.2.0',
+ license : 'MIT or Apache-2.0',
+)
+
+subproject('arbitrary-int-1-rs', required: true)
+subproject('bilge-impl-0.2-rs', required: true)
+
+arbitrary_int_dep = dependency('arbitrary-int-1-rs')
+bilge_impl_dep = dependency('bilge-impl-0.2-rs')
+
+lib = static_library(
+ 'bilge',
+ 'src/lib.rs',
+ override_options : ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi : 'rust',
+ dependencies: [
+ arbitrary_int_dep,
+ bilge_impl_dep,
+ ],
+)
+
+bilge_dep = declare_dependency(
+ link_with : [lib],
+)
+
+meson.override_dependency('bilge-0.2-rs', bilge_dep)
diff --git a/subprojects/packagefiles/bilge-impl-0.2-rs/meson.build b/subprojects/packagefiles/bilge-impl-0.2-rs/meson.build
new file mode 100644
index 0000000000..80243c7024
--- /dev/null
+++ b/subprojects/packagefiles/bilge-impl-0.2-rs/meson.build
@@ -0,0 +1,45 @@
+project('bilge-impl-0.2-rs', 'rust',
+ version: '0.2.0',
+ license: 'MIT OR Apache-2.0',
+ default_options: [])
+
+subproject('itertools-0.11-rs', required: true)
+subproject('proc-macro-error-attr-1-rs', required: true)
+subproject('proc-macro-error-1-rs', required: true)
+subproject('quote-1-rs', required: true)
+subproject('syn-2-rs', required: true)
+subproject('proc-macro2-1-rs', required: true)
+
+itertools_dep = dependency('itertools-0.11-rs', native: true)
+proc_macro_error_attr_dep = dependency('proc-macro-error-attr-1-rs', native: true)
+proc_macro_error_dep = dependency('proc-macro-error-1-rs', native: true)
+quote_dep = dependency('quote-1-rs', native: true)
+syn_dep = dependency('syn-2-rs', native: true)
+proc_macro2_dep = dependency('proc-macro2-1-rs', native: true)
+
+rust = import('rust')
+
+_bilge_impl_rs = rust.proc_macro(
+ 'bilge_impl',
+ files('src/lib.rs'),
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_args: [
+ '--cfg', 'use_fallback',
+ '--cfg', 'feature="syn-error"',
+ '--cfg', 'feature="proc-macro"',
+ ],
+ dependencies: [
+ itertools_dep,
+ proc_macro_error_attr_dep,
+ proc_macro_error_dep,
+ quote_dep,
+ syn_dep,
+ proc_macro2_dep,
+ ],
+)
+
+bilge_impl_dep = declare_dependency(
+ link_with: _bilge_impl_rs,
+)
+
+meson.override_dependency('bilge-impl-0.2-rs', bilge_impl_dep)
diff --git a/subprojects/packagefiles/either-1-rs/meson.build b/subprojects/packagefiles/either-1-rs/meson.build
new file mode 100644
index 0000000000..a5842eb3a6
--- /dev/null
+++ b/subprojects/packagefiles/either-1-rs/meson.build
@@ -0,0 +1,24 @@
+project('either-1-rs', 'rust',
+ version: '1.12.0',
+ license: 'MIT OR Apache-2.0',
+ default_options: [])
+
+_either_rs = static_library(
+ 'either',
+ files('src/lib.rs'),
+ gnu_symbol_visibility: 'hidden',
+ override_options: ['rust_std=2018', 'build.rust_std=2018'],
+ rust_abi: 'rust',
+ rust_args: [
+ '--cfg', 'feature="use_std"',
+ '--cfg', 'feature="use_alloc"',
+ ],
+ dependencies: [],
+ native: true,
+)
+
+either_dep = declare_dependency(
+ link_with: _either_rs,
+)
+
+meson.override_dependency('either-1-rs', either_dep, native: true)
diff --git a/subprojects/packagefiles/itertools-0.11-rs/meson.build b/subprojects/packagefiles/itertools-0.11-rs/meson.build
new file mode 100644
index 0000000000..13d2d27019
--- /dev/null
+++ b/subprojects/packagefiles/itertools-0.11-rs/meson.build
@@ -0,0 +1,30 @@
+project('itertools-0.11-rs', 'rust',
+ version: '0.11.0',
+ license: 'MIT OR Apache-2.0',
+ default_options: [])
+
+subproject('either-1-rs', required: true)
+
+either_dep = dependency('either-1-rs', native: true)
+
+_itertools_rs = static_library(
+ 'itertools',
+ files('src/lib.rs'),
+ gnu_symbol_visibility: 'hidden',
+ override_options: ['rust_std=2018', 'build.rust_std=2018'],
+ rust_abi: 'rust',
+ rust_args: [
+ '--cfg', 'feature="use_std"',
+ '--cfg', 'feature="use_alloc"',
+ ],
+ dependencies: [
+ either_dep,
+ ],
+ native: true,
+)
+
+itertools_dep = declare_dependency(
+ link_with: _itertools_rs,
+)
+
+meson.override_dependency('itertools-0.11-rs', itertools_dep, native: true)
diff --git a/subprojects/packagefiles/proc-macro-error-1-rs/meson.build b/subprojects/packagefiles/proc-macro-error-1-rs/meson.build
new file mode 100644
index 0000000000..38ea7b89d3
--- /dev/null
+++ b/subprojects/packagefiles/proc-macro-error-1-rs/meson.build
@@ -0,0 +1,40 @@
+project('proc-macro-error-1-rs', 'rust',
+ version: '1.0.4',
+ license: 'MIT OR Apache-2.0',
+ default_options: [])
+
+subproject('proc-macro-error-attr-1-rs', required: true)
+subproject('quote-1-rs', required: true)
+subproject('syn-2-rs', required: true)
+subproject('proc-macro2-1-rs', required: true)
+
+proc_macro_error_attr_dep = dependency('proc-macro-error-attr-1-rs', native: true)
+proc_macro2_dep = dependency('proc-macro2-1-rs', native: true)
+quote_dep = dependency('quote-1-rs', native: true)
+syn_dep = dependency('syn-2-rs', native: true)
+
+_proc_macro_error_rs = static_library(
+ 'proc_macro_error',
+ files('src/lib.rs'),
+ override_options: ['rust_std=2018', 'build.rust_std=2018'],
+ rust_abi: 'rust',
+ rust_args: [
+ '--cfg', 'use_fallback',
+ '--cfg', 'feature="syn-error"',
+ '--cfg', 'feature="proc-macro"',
+ '-A', 'non_fmt_panics'
+ ],
+ dependencies: [
+ proc_macro_error_attr_dep,
+ proc_macro2_dep,
+ quote_dep,
+ syn_dep,
+ ],
+ native: true,
+)
+
+proc_macro_error_dep = declare_dependency(
+ link_with: _proc_macro_error_rs,
+)
+
+meson.override_dependency('proc-macro-error-1-rs', proc_macro_error_dep, native: true)
diff --git a/subprojects/packagefiles/proc-macro-error-attr-1-rs/meson.build b/subprojects/packagefiles/proc-macro-error-attr-1-rs/meson.build
new file mode 100644
index 0000000000..d900c54cfd
--- /dev/null
+++ b/subprojects/packagefiles/proc-macro-error-attr-1-rs/meson.build
@@ -0,0 +1,32 @@
+project('proc-macro-error-attr-1-rs', 'rust',
+ version: '1.12.0',
+ license: 'MIT OR Apache-2.0',
+ default_options: [])
+
+subproject('proc-macro2-1-rs', required: true)
+subproject('quote-1-rs', required: true)
+
+proc_macro2_dep = dependency('proc-macro2-1-rs', native: true)
+quote_dep = dependency('quote-1-rs', native: true)
+
+rust = import('rust')
+_proc_macro_error_attr_rs = rust.proc_macro(
+ 'proc_macro_error_attr',
+ files('src/lib.rs'),
+ override_options: ['rust_std=2018', 'build.rust_std=2018'],
+ rust_args: [
+ '--cfg', 'use_fallback',
+ '--cfg', 'feature="syn-error"',
+ '--cfg', 'feature="proc-macro"'
+ ],
+ dependencies: [
+ proc_macro2_dep,
+ quote_dep,
+ ],
+)
+
+proc_macro_error_attr_dep = declare_dependency(
+ link_with: _proc_macro_error_attr_rs,
+)
+
+meson.override_dependency('proc-macro-error-attr-1-rs', proc_macro_error_attr_dep, native: true)
diff --git a/subprojects/packagefiles/proc-macro2-1-rs/meson.build b/subprojects/packagefiles/proc-macro2-1-rs/meson.build
new file mode 100644
index 0000000000..818ec59336
--- /dev/null
+++ b/subprojects/packagefiles/proc-macro2-1-rs/meson.build
@@ -0,0 +1,31 @@
+project('proc-macro2-1-rs', 'rust',
+ version: '1.0.84',
+ license: 'MIT OR Apache-2.0',
+ default_options: [])
+
+subproject('unicode-ident-1-rs', required: true)
+
+unicode_ident_dep = dependency('unicode-ident-1-rs', native: true)
+
+_proc_macro2_rs = static_library(
+ 'proc_macro2',
+ files('src/lib.rs'),
+ gnu_symbol_visibility: 'hidden',
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ rust_args: [
+ '--cfg', 'feature="proc-macro"',
+ '--cfg', 'span_locations',
+ '--cfg', 'wrap_proc_macro',
+ ],
+ dependencies: [
+ unicode_ident_dep,
+ ],
+ native: true,
+)
+
+proc_macro2_dep = declare_dependency(
+ link_with: _proc_macro2_rs,
+)
+
+meson.override_dependency('proc-macro2-1-rs', proc_macro2_dep, native: true)
diff --git a/subprojects/packagefiles/quote-1-rs/meson.build b/subprojects/packagefiles/quote-1-rs/meson.build
new file mode 100644
index 0000000000..d36609bd3c
--- /dev/null
+++ b/subprojects/packagefiles/quote-1-rs/meson.build
@@ -0,0 +1,29 @@
+project('quote-1-rs', 'rust',
+ version: '1.12.0',
+ license: 'MIT OR Apache-2.0',
+ default_options: [])
+
+subproject('proc-macro2-1-rs', required: true)
+
+proc_macro2_dep = dependency('proc-macro2-1-rs', native: true)
+
+_quote_rs = static_library(
+ 'quote',
+ files('src/lib.rs'),
+ gnu_symbol_visibility: 'hidden',
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ rust_args: [
+ '--cfg', 'feature="proc-macro"',
+ ],
+ dependencies: [
+ proc_macro2_dep,
+ ],
+ native: true,
+)
+
+quote_dep = declare_dependency(
+ link_with: _quote_rs,
+)
+
+meson.override_dependency('quote-1-rs', quote_dep, native: true)
diff --git a/subprojects/packagefiles/syn-2-rs/meson.build b/subprojects/packagefiles/syn-2-rs/meson.build
new file mode 100644
index 0000000000..a53335f309
--- /dev/null
+++ b/subprojects/packagefiles/syn-2-rs/meson.build
@@ -0,0 +1,40 @@
+project('syn-2-rs', 'rust',
+ version: '2.0.66',
+ license: 'MIT OR Apache-2.0',
+ default_options: [])
+
+subproject('proc-macro2-1-rs', required: true)
+subproject('quote-1-rs', required: true)
+subproject('unicode-ident-1-rs', required: true)
+
+proc_macro2_dep = dependency('proc-macro2-1-rs', native: true)
+quote_dep = dependency('quote-1-rs', native: true)
+unicode_ident_dep = dependency('unicode-ident-1-rs', native: true)
+
+_syn_rs = static_library(
+ 'syn',
+ files('src/lib.rs'),
+ gnu_symbol_visibility: 'hidden',
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ rust_args: [
+ '--cfg', 'feature="full"',
+ '--cfg', 'feature="derive"',
+ '--cfg', 'feature="parsing"',
+ '--cfg', 'feature="printing"',
+ '--cfg', 'feature="clone-impls"',
+ '--cfg', 'feature="proc-macro"',
+ ],
+ dependencies: [
+ quote_dep,
+ proc_macro2_dep,
+ unicode_ident_dep,
+ ],
+ native: true,
+)
+
+syn_dep = declare_dependency(
+ link_with: _syn_rs,
+)
+
+meson.override_dependency('syn-2-rs', syn_dep, native: true)
diff --git a/subprojects/packagefiles/unicode-ident-1-rs/meson.build b/subprojects/packagefiles/unicode-ident-1-rs/meson.build
new file mode 100644
index 0000000000..54f2376854
--- /dev/null
+++ b/subprojects/packagefiles/unicode-ident-1-rs/meson.build
@@ -0,0 +1,20 @@
+project('unicode-ident-1-rs', 'rust',
+ version: '1.0.12',
+ license: '(MIT OR Apache-2.0) AND Unicode-DFS-2016',
+ default_options: [])
+
+_unicode_ident_rs = static_library(
+ 'unicode_ident',
+ files('src/lib.rs'),
+ gnu_symbol_visibility: 'hidden',
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ dependencies: [],
+ native: true,
+)
+
+unicode_ident_dep = declare_dependency(
+ link_with: _unicode_ident_rs,
+)
+
+meson.override_dependency('unicode-ident-1-rs', unicode_ident_dep, native: true)
diff --git a/subprojects/proc-macro-error-1-rs.wrap b/subprojects/proc-macro-error-1-rs.wrap
new file mode 100644
index 0000000000..b7db03b06a
--- /dev/null
+++ b/subprojects/proc-macro-error-1-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = proc-macro-error-1.0.4
+source_url = https://crates.io/api/v1/crates/proc-macro-error/1.0.4/download
+source_filename = proc-macro-error-1.0.4.tar.gz
+source_hash = da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c
+#method = cargo
+patch_directory = proc-macro-error-1-rs
diff --git a/subprojects/proc-macro-error-attr-1-rs.wrap b/subprojects/proc-macro-error-attr-1-rs.wrap
new file mode 100644
index 0000000000..d13d8a239a
--- /dev/null
+++ b/subprojects/proc-macro-error-attr-1-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = proc-macro-error-attr-1.0.4
+source_url = https://crates.io/api/v1/crates/proc-macro-error-attr/1.0.4/download
+source_filename = proc-macro-error-attr-1.0.4.tar.gz
+source_hash = a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869
+#method = cargo
+patch_directory = proc-macro-error-attr-1-rs
diff --git a/subprojects/proc-macro2-1-rs.wrap b/subprojects/proc-macro2-1-rs.wrap
new file mode 100644
index 0000000000..7053e2c013
--- /dev/null
+++ b/subprojects/proc-macro2-1-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = proc-macro2-1.0.84
+source_url = https://crates.io/api/v1/crates/proc-macro2/1.0.84/download
+source_filename = proc-macro2-1.0.84.0.tar.gz
+source_hash = ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6
+#method = cargo
+patch_directory = proc-macro2-1-rs
diff --git a/subprojects/quote-1-rs.wrap b/subprojects/quote-1-rs.wrap
new file mode 100644
index 0000000000..6e7ea69049
--- /dev/null
+++ b/subprojects/quote-1-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = quote-1.0.36
+source_url = https://crates.io/api/v1/crates/quote/1.0.36/download
+source_filename = quote-1.0.36.0.tar.gz
+source_hash = 0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7
+#method = cargo
+patch_directory = quote-1-rs
diff --git a/subprojects/syn-2-rs.wrap b/subprojects/syn-2-rs.wrap
new file mode 100644
index 0000000000..13ffdac3c3
--- /dev/null
+++ b/subprojects/syn-2-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = syn-2.0.66
+source_url = https://crates.io/api/v1/crates/syn/2.0.66/download
+source_filename = syn-2.0.66.0.tar.gz
+source_hash = c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5
+#method = cargo
+patch_directory = syn-2-rs
diff --git a/subprojects/unicode-ident-1-rs.wrap b/subprojects/unicode-ident-1-rs.wrap
new file mode 100644
index 0000000000..4609f96ed9
--- /dev/null
+++ b/subprojects/unicode-ident-1-rs.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = unicode-ident-1.0.12
+source_url = https://crates.io/api/v1/crates/unicode-ident/1.0.12/download
+source_filename = unicode-ident-1.0.12.tar.gz
+source_hash = 3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b
+#method = cargo
+patch_directory = unicode-ident-1-rs
--
2.44.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v7 6/7] rust: add crate to expose bindings and interfaces
2024-08-15 11:42 ` [PATCH v7 6/7] rust: add crate to expose bindings and interfaces Manos Pitsidianakis
@ 2024-08-15 14:01 ` Philippe Mathieu-Daudé
2024-08-15 14:50 ` Manos Pitsidianakis
2024-08-15 15:06 ` Daniel P. Berrangé
2024-08-16 8:26 ` Junjie Mao
1 sibling, 2 replies; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-08-15 14:01 UTC (permalink / raw)
To: Manos Pitsidianakis, qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, John Snow, Cleber Rosa, Beraldo Leal,
Alex Bennée, Wainer dos Santos Moschetta, Zhao Liu,
Peter Maydell, ARM TCG CPUs, Stefan Hajnoczi, Junjie Mao,
Pierrick Bouvier, Richard Henderson, Gustavo Romero, rowan.hart,
Mads Ynddal, Markus Armbruster
Hi Manos,
On 15/8/24 13:42, Manos Pitsidianakis wrote:
> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and
> provides some declaration macros for symbols visible to the rest of
> QEMU.
>
> Co-authored-by: Junjie Mao <junjie.mao@intel.com>
> Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Junjie Mao <junjie.mao@intel.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
> ---
> MAINTAINERS | 6 ++
> rust/meson.build | 9 +++
> rust/qemu-api/.gitignore | 2 +
> rust/qemu-api/Cargo.lock | 7 +++
> rust/qemu-api/Cargo.toml | 23 +++++++
> rust/qemu-api/README.md | 17 +++++
> rust/qemu-api/build.rs | 13 ++++
> rust/qemu-api/meson.build | 17 +++++
> rust/qemu-api/rustfmt.toml | 1 +
> rust/qemu-api/src/bindings.rs | 7 +++
> rust/qemu-api/src/definitions.rs | 108 ++++++++++++++++++++++++++++++++
> rust/qemu-api/src/device_class.rs | 128 ++++++++++++++++++++++++++++++++++++++
> rust/qemu-api/src/lib.rs | 100 +++++++++++++++++++++++++++++
> rust/qemu-api/src/tests.rs | 48 ++++++++++++++
> rust/rustfmt.toml | 7 +++
> 15 files changed, 493 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5464cb2b03..56a88048d2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3348,6 +3348,12 @@ F: hw/core/register.c
> F: include/hw/register.h
> F: include/hw/registerfields.h
>
> +Rust
> +M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
> +S: Maintained
> +F: rust/qemu-api
> +F: rust/rustfmt.toml
Few lines in docs/devel/rust.rst would be welcomed,
> diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml
> new file mode 100644
> index 0000000000..51260cbe42
> --- /dev/null
> +++ b/rust/qemu-api/Cargo.toml
> @@ -0,0 +1,23 @@
> +[package]
> +name = "qemu_api"
> +version = "0.1.0"
> +edition = "2021"
> +license = "GPL-2.0 OR GPL-3.0-or-later"
in particular explaining the license choice.
Should all rust code use it?
Thanks,
Phil.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 6/7] rust: add crate to expose bindings and interfaces
2024-08-15 14:01 ` Philippe Mathieu-Daudé
@ 2024-08-15 14:50 ` Manos Pitsidianakis
2024-08-15 15:06 ` Daniel P. Berrangé
1 sibling, 0 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-15 14:50 UTC (permalink / raw)
To: Philippe Mathieu-Daudé , qemu-devel
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé ,
Thomas Huth, John Snow, Cleber Rosa, Beraldo Leal,
Alex Benné e, Wainer dos Santos Moschetta, Zhao Liu,
Peter Maydell, ARM TCG CPUs, Stefan Hajnoczi, Junjie Mao,
Pierrick Bouvier, Richard Henderson, Gustavo Romero, rowan.hart,
Mads Ynddal, Markus Armbruster
On Thu, 15 Aug 2024 17:01, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>Hi Manos,
>
>On 15/8/24 13:42, Manos Pitsidianakis wrote:
>> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and
>> provides some declaration macros for symbols visible to the rest of
>> QEMU.
>>
>> Co-authored-by: Junjie Mao <junjie.mao@intel.com>
>> Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
>> Signed-off-by: Junjie Mao <junjie.mao@intel.com>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
>> ---
>> MAINTAINERS | 6 ++
>> rust/meson.build | 9 +++
>> rust/qemu-api/.gitignore | 2 +
>> rust/qemu-api/Cargo.lock | 7 +++
>> rust/qemu-api/Cargo.toml | 23 +++++++
>> rust/qemu-api/README.md | 17 +++++
>> rust/qemu-api/build.rs | 13 ++++
>> rust/qemu-api/meson.build | 17 +++++
>> rust/qemu-api/rustfmt.toml | 1 +
>> rust/qemu-api/src/bindings.rs | 7 +++
>> rust/qemu-api/src/definitions.rs | 108 ++++++++++++++++++++++++++++++++
>> rust/qemu-api/src/device_class.rs | 128 ++++++++++++++++++++++++++++++++++++++
>> rust/qemu-api/src/lib.rs | 100 +++++++++++++++++++++++++++++
>> rust/qemu-api/src/tests.rs | 48 ++++++++++++++
>> rust/rustfmt.toml | 7 +++
>> 15 files changed, 493 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 5464cb2b03..56a88048d2 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -3348,6 +3348,12 @@ F: hw/core/register.c
>> F: include/hw/register.h
>> F: include/hw/registerfields.h
>>
>> +Rust
>> +M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
>> +S: Maintained
>> +F: rust/qemu-api
>> +F: rust/rustfmt.toml
>
>Few lines in docs/devel/rust.rst would be welcomed,
In another patch. There's so much to do!
>
>> diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml
>> new file mode 100644
>> index 0000000000..51260cbe42
>> --- /dev/null
>> +++ b/rust/qemu-api/Cargo.toml
>> @@ -0,0 +1,23 @@
>> +[package]
>> +name = "qemu_api"
>> +version = "0.1.0"
>> +edition = "2021"
>
>> +license = "GPL-2.0 OR GPL-3.0-or-later"
>
>in particular explaining the license choice.
>
>Should all rust code use it?
It's an OR, so all rust code can use GPL-2.0 like the rest of QEMU.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 6/7] rust: add crate to expose bindings and interfaces
2024-08-15 14:01 ` Philippe Mathieu-Daudé
2024-08-15 14:50 ` Manos Pitsidianakis
@ 2024-08-15 15:06 ` Daniel P. Berrangé
2024-08-16 8:34 ` Philippe Mathieu-Daudé
1 sibling, 1 reply; 18+ messages in thread
From: Daniel P. Berrangé @ 2024-08-15 15:06 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: Manos Pitsidianakis, qemu-devel, Paolo Bonzini,
Marc-André Lureau, Thomas Huth, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Zhao Liu, Peter Maydell, ARM TCG CPUs, Stefan Hajnoczi,
Junjie Mao, Pierrick Bouvier, Richard Henderson, Gustavo Romero,
rowan.hart, Mads Ynddal, Markus Armbruster
On Thu, Aug 15, 2024 at 04:01:17PM +0200, Philippe Mathieu-Daudé wrote:
> Hi Manos,
>
> On 15/8/24 13:42, Manos Pitsidianakis wrote:
> > Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and
> > provides some declaration macros for symbols visible to the rest of
> > QEMU.
> >
> > Co-authored-by: Junjie Mao <junjie.mao@intel.com>
> > Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
> > Signed-off-by: Junjie Mao <junjie.mao@intel.com>
> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> > Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
> > ---
> > MAINTAINERS | 6 ++
> > rust/meson.build | 9 +++
> > rust/qemu-api/.gitignore | 2 +
> > rust/qemu-api/Cargo.lock | 7 +++
> > rust/qemu-api/Cargo.toml | 23 +++++++
> > rust/qemu-api/README.md | 17 +++++
> > rust/qemu-api/build.rs | 13 ++++
> > rust/qemu-api/meson.build | 17 +++++
> > rust/qemu-api/rustfmt.toml | 1 +
> > rust/qemu-api/src/bindings.rs | 7 +++
> > rust/qemu-api/src/definitions.rs | 108 ++++++++++++++++++++++++++++++++
> > rust/qemu-api/src/device_class.rs | 128 ++++++++++++++++++++++++++++++++++++++
> > rust/qemu-api/src/lib.rs | 100 +++++++++++++++++++++++++++++
> > rust/qemu-api/src/tests.rs | 48 ++++++++++++++
> > rust/rustfmt.toml | 7 +++
> > 15 files changed, 493 insertions(+)
> > diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml
> > new file mode 100644
> > index 0000000000..51260cbe42
> > --- /dev/null
> > +++ b/rust/qemu-api/Cargo.toml
> > @@ -0,0 +1,23 @@
> > +[package]
> > +name = "qemu_api"
> > +version = "0.1.0"
> > +edition = "2021"
>
> > +license = "GPL-2.0 OR GPL-3.0-or-later"
>
> in particular explaining the license choice.
Semantically this is an overly verbose way of saying
"GPL-2.0-or-later", so just simplify this.
> Should all rust code use it?
GPL-2.0-or-later is what we expect all new QEMU contributions to be
licensed as, regardless of language[1], so this looks desirable.
With regards,
Daniel
[1] unless they're derived from one of the few pieces of code under
different terms
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
` (6 preceding siblings ...)
2024-08-15 11:42 ` [PATCH v7 7/7] rust: add PL011 device model Manos Pitsidianakis
@ 2024-08-15 17:10 ` Peter Maydell
2024-08-16 8:06 ` Junjie Mao
8 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2024-08-15 17:10 UTC (permalink / raw)
To: Manos Pitsidianakis
Cc: qemu-devel, Paolo Bonzini, Marc-André Lureau,
Daniel P. Berrangé, Thomas Huth, Philippe Mathieu-Daudé,
John Snow, Cleber Rosa, Beraldo Leal, Alex Bennée,
Wainer dos Santos Moschetta, Zhao Liu, ARM TCG CPUs,
Stefan Hajnoczi, Junjie Mao, Pierrick Bouvier, Richard Henderson,
Gustavo Romero, rowan.hart, Mads Ynddal, Markus Armbruster
On Thu, 15 Aug 2024 at 12:42, Manos Pitsidianakis
<manos.pitsidianakis@linaro.org> wrote:
> Outstanding issues that are not blocking for merge are:
>
> - Cross-compilation for aarch64 is not possible out-of-the-box because of this bug:
> <https://github.com/rust-lang/rust/issues/125619> in llvm which when
> fixed, must be ported to upstream rust's llvm fork. Since the problem
> is an extraneous symbol we could strip it with objcopy -N|--strip-symbol
I asked around internally and found somebody willing to do
code review on the proposed LLVM compiler-rt pullreq that fixes
the root of this bug, so hopefully we can get that fixed (though
presumably we might want the workaround anyway given it'll take a
while to percolate through to a rust release).
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
` (7 preceding siblings ...)
2024-08-15 17:10 ` [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Peter Maydell
@ 2024-08-16 8:06 ` Junjie Mao
2024-08-16 8:17 ` Manos Pitsidianakis
8 siblings, 1 reply; 18+ messages in thread
From: Junjie Mao @ 2024-08-16 8:06 UTC (permalink / raw)
To: Manos Pitsidianakis, qemu-devel@nongnu.org
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Liu, Zhao1, Peter Maydell, ARM TCG CPUs, Stefan Hajnoczi,
Pierrick Bouvier, Richard Henderson, Gustavo Romero, Hart, Rowan,
Mads Ynddal, Markus Armbruster
On 8/15/2024 7:42 PM, Manos Pitsidianakis wrote:
> Outstanding issues
> ==================
>
> Outstanding issues that are not blocking for merge are:
>
> - Cross-compilation for aarch64 is not possible out-of-the-box because of this bug:
> <https://github.com/rust-lang/rust/issues/125619> in llvm which when
> fixed, must be ported to upstream rust's llvm fork. Since the problem
> is an extraneous symbol we could strip it with objcopy -N|--strip-symbol
> - Adding more than one Rust device ends up with duplicate symbols from
> rust std library because we are linking as whole archives because...
> constructors are stripped by the linker otherwise :( It can be worked
> around if a single Rust library is built with all the devices as
> dependencies which is then linked to qemu. The fix is a small change
> which I will add either in a next version or when a new Rust device is
> added.
>
Hi Manos,
I also noticed that when I tried adding a second device. Some other projects met
similar issues [1], but no clean solution seems to be available yet. The options
are:
1) Combining all crates into one staticlib which is linked to the final
executable. That requires generating one .rs with extern crate decls of all
enabled crates. In the context of QEMU, different targets may enable different
set of crates (e.g., some crates have arch constraints), thus one .rs for each
target will be needed in general.
2) Linking rlibs (or emitted objects) directly with other C objects using the C
linker. That somehow works (with some tricks) but is not officially supported
and may break in the future.
I'm working on (1), but would like to have your thoughts and preference on those
options.
[1] https://github.com/rust-lang/rust/issues/73632
---
Best Regards
Junjie Mao
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl
2024-08-16 8:06 ` Junjie Mao
@ 2024-08-16 8:17 ` Manos Pitsidianakis
2024-08-19 4:09 ` Junjie Mao
0 siblings, 1 reply; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-16 8:17 UTC (permalink / raw)
To: Junjie Mao
Cc: open list:ARM SMMU <qemu-arm@nongnu.org>, , Paolo Bonzini,
Marc-André Lureau, Daniel P. Berrangé, Thomas Huth,
Philippe Mathieu-Daudé, John Snow, Cleber Rosa, Beraldo Leal,
Alex Bennée, Wainer dos Santos Moschetta, Liu, Zhao1,
Peter Maydell, ARM TCG CPUs, Stefan Hajnoczi, Pierrick Bouvier,
Richard Henderson, Gustavo Romero, Hart, Rowan, Mads Ynddal,
Markus Armbruster
[-- Attachment #1: Type: text/plain, Size: 2377 bytes --]
On Fri, 16 Aug 2024, 11:06 Junjie Mao, <junjie.mao@intel.com> wrote:
> On 8/15/2024 7:42 PM, Manos Pitsidianakis wrote:
> > Outstanding issues
> > ==================
> >
> > Outstanding issues that are not blocking for merge are:
> >
> > - Cross-compilation for aarch64 is not possible out-of-the-box because
> of this bug:
> > <https://github.com/rust-lang/rust/issues/125619> in llvm which when
> > fixed, must be ported to upstream rust's llvm fork. Since the problem
> > is an extraneous symbol we could strip it with objcopy
> -N|--strip-symbol
> > - Adding more than one Rust device ends up with duplicate symbols from
> > rust std library because we are linking as whole archives because...
> > constructors are stripped by the linker otherwise :( It can be worked
> > around if a single Rust library is built with all the devices as
> > dependencies which is then linked to qemu. The fix is a small change
> > which I will add either in a next version or when a new Rust device is
> > added.
> >
>
> Hi Manos,
>
> I also noticed that when I tried adding a second device. Some other
> projects met
> similar issues [1], but no clean solution seems to be available yet. The
> options
> are:
>
> 1) Combining all crates into one staticlib which is linked to the final
> executable. That requires generating one .rs with extern crate decls of
> all
> enabled crates. In the context of QEMU, different targets may enable
> different
> set of crates (e.g., some crates have arch constraints), thus one .rs for
> each
> target will be needed in general.
>
> 2) Linking rlibs (or emitted objects) directly with other C objects using
> the C
> linker. That somehow works (with some tricks) but is not officially
> supported
> and may break in the future.
>
> I'm working on (1), but would like to have your thoughts and preference on
> those
> options.
>
Hello Junjie, I have also implemented (1) already (the fix I mentioned in
the cover letter). In general I'd like to do it on a standalone patch so
that it can be separated from the other changes instead of squashing it.
If you have something already too, please share here! I will send mine as a
reply to this thread when I am able. I am not familiar with meson so my
version could be lacking!
Manos
[1] https://github.com/rust-lang/rust/issues/73632
>
> ---
> Best Regards
> Junjie Mao
>
[-- Attachment #2: Type: text/html, Size: 3550 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 6/7] rust: add crate to expose bindings and interfaces
2024-08-15 11:42 ` [PATCH v7 6/7] rust: add crate to expose bindings and interfaces Manos Pitsidianakis
2024-08-15 14:01 ` Philippe Mathieu-Daudé
@ 2024-08-16 8:26 ` Junjie Mao
1 sibling, 0 replies; 18+ messages in thread
From: Junjie Mao @ 2024-08-16 8:26 UTC (permalink / raw)
To: Manos Pitsidianakis, qemu-devel@nongnu.org
Cc: Paolo Bonzini, Marc-André Lureau, Daniel P. Berrangé,
Thomas Huth, Philippe Mathieu-Daudé, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Liu, Zhao1, Peter Maydell, ARM TCG CPUs, Stefan Hajnoczi,
Pierrick Bouvier, Richard Henderson, Gustavo Romero, Hart, Rowan,
Mads Ynddal, Markus Armbruster
On 8/15/2024 7:42 PM, Manos Pitsidianakis wrote:
> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and
> provides some declaration macros for symbols visible to the rest of
> QEMU.
>
> Co-authored-by: Junjie Mao <junjie.mao@intel.com>
> Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Junjie Mao <junjie.mao@intel.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
> ---
[snip]
> +
> +#[macro_export]
> +macro_rules! declare_properties {
> + ($ident:ident, $($prop:expr),*$(,)*) => {
> +
> + const fn _calc_prop_len() -> usize {
> + let mut len = 1;
> + $({
> + _ = stringify!($prop);
> + len += 1;
> + })*
> + len
> + }
> + const PROP_LEN: usize = _calc_prop_len();
> +
> + #[no_mangle]
> + fn _make_properties() -> [$crate::bindings::Property; PROP_LEN] {
#[no_mangle] also makes _make_properties externally visible and thus will cause
duplicate-symbol-definition errors at link time when multiple devices are enabled.
Since it is only used in the definition of $ident below, shall we just remove
#[no_mangle] for _make_properties?
---
Best Regards
Junjie Mao
> + [
> + $($prop),*,
> + unsafe { ::core::mem::MaybeUninit::<$crate::bindings::Property>::zeroed().assume_init() },
> + ]
> + }
> +
> + #[no_mangle]
> + pub static mut $ident: $crate::device_class::Properties<PROP_LEN> = $crate::device_class::Properties(::std::sync::OnceLock::new(), _make_properties);
> + };
> +}
> +
> +#[macro_export]
> +macro_rules! vm_state_description {
> + ($(#[$outer:meta])*
> + $name:ident,
> + $(name: $vname:expr,)*
> + $(unmigratable: $um_val:expr,)*
> + ) => {
> + #[used]
> + $(#[$outer])*
> + pub static $name: $crate::bindings::VMStateDescription = $crate::bindings::VMStateDescription {
> + $(name: {
> + #[used]
> + static VMSTATE_NAME: &::core::ffi::CStr = $vname;
> + $vname.as_ptr()
> + },)*
> + unmigratable: true,
> + ..unsafe { ::core::mem::MaybeUninit::<$crate::bindings::VMStateDescription>::zeroed().assume_init() }
> + };
> + }
> +}
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 6/7] rust: add crate to expose bindings and interfaces
2024-08-15 15:06 ` Daniel P. Berrangé
@ 2024-08-16 8:34 ` Philippe Mathieu-Daudé
2024-08-21 7:24 ` Manos Pitsidianakis
0 siblings, 1 reply; 18+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-08-16 8:34 UTC (permalink / raw)
To: Daniel P. Berrangé
Cc: Manos Pitsidianakis, qemu-devel, Paolo Bonzini,
Marc-André Lureau, Thomas Huth, John Snow, Cleber Rosa,
Beraldo Leal, Alex Bennée, Wainer dos Santos Moschetta,
Zhao Liu, Peter Maydell, ARM TCG CPUs, Stefan Hajnoczi,
Junjie Mao, Pierrick Bouvier, Richard Henderson, Gustavo Romero,
rowan.hart, Mads Ynddal, Markus Armbruster
On 15/8/24 17:06, Daniel P. Berrangé wrote:
> On Thu, Aug 15, 2024 at 04:01:17PM +0200, Philippe Mathieu-Daudé wrote:
>> Hi Manos,
>>
>> On 15/8/24 13:42, Manos Pitsidianakis wrote:
>>> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and
>>> provides some declaration macros for symbols visible to the rest of
>>> QEMU.
>>>
>>> Co-authored-by: Junjie Mao <junjie.mao@intel.com>
>>> Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
>>> Signed-off-by: Junjie Mao <junjie.mao@intel.com>
>>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>>> Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
>>> ---
>>> MAINTAINERS | 6 ++
>>> rust/meson.build | 9 +++
>>> rust/qemu-api/.gitignore | 2 +
>>> rust/qemu-api/Cargo.lock | 7 +++
>>> rust/qemu-api/Cargo.toml | 23 +++++++
>>> rust/qemu-api/README.md | 17 +++++
>>> rust/qemu-api/build.rs | 13 ++++
>>> rust/qemu-api/meson.build | 17 +++++
>>> rust/qemu-api/rustfmt.toml | 1 +
>>> rust/qemu-api/src/bindings.rs | 7 +++
>>> rust/qemu-api/src/definitions.rs | 108 ++++++++++++++++++++++++++++++++
>>> rust/qemu-api/src/device_class.rs | 128 ++++++++++++++++++++++++++++++++++++++
>>> rust/qemu-api/src/lib.rs | 100 +++++++++++++++++++++++++++++
>>> rust/qemu-api/src/tests.rs | 48 ++++++++++++++
>>> rust/rustfmt.toml | 7 +++
>>> 15 files changed, 493 insertions(+)
>
>>> diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml
>>> new file mode 100644
>>> index 0000000000..51260cbe42
>>> --- /dev/null
>>> +++ b/rust/qemu-api/Cargo.toml
>>> @@ -0,0 +1,23 @@
>>> +[package]
>>> +name = "qemu_api"
>>> +version = "0.1.0"
>>> +edition = "2021"
>>
>>> +license = "GPL-2.0 OR GPL-3.0-or-later"
>>
>> in particular explaining the license choice.
>
> Semantically this is an overly verbose way of saying
> "GPL-2.0-or-later", so just simplify this.
Indeed. Manos, please use GPL-2.0-or-later to keep it simple.
>
>> Should all rust code use it?
>
> GPL-2.0-or-later is what we expect all new QEMU contributions to be
> licensed as, regardless of language[1], so this looks desirable.
Agreed.
>
> With regards,
> Daniel
>
> [1] unless they're derived from one of the few pieces of code under
> different terms
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl
2024-08-16 8:17 ` Manos Pitsidianakis
@ 2024-08-19 4:09 ` Junjie Mao
0 siblings, 0 replies; 18+ messages in thread
From: Junjie Mao @ 2024-08-19 4:09 UTC (permalink / raw)
To: Manos Pitsidianakis
Cc: open list:ARM SMMU, qemu-devel, Paolo Bonzini,
Marc-André Lureau, Daniel P. Berrangé, Thomas Huth,
Philippe Mathieu-Daudé, John Snow, Cleber Rosa, Beraldo Leal,
Alex Bennée, Wainer dos Santos Moschetta, Liu, Zhao1,
Peter Maydell, ARM TCG CPUs, Stefan Hajnoczi, Pierrick Bouvier,
Richard Henderson, Gustavo Romero, Hart, Rowan, Mads Ynddal,
Markus Armbruster
On 8/16/2024 4:17 PM, Manos Pitsidianakis wrote:
>
>
> On Fri, 16 Aug 2024, 11:06 Junjie Mao, <junjie.mao@intel.com
> <mailto:junjie.mao@intel.com>> wrote:
>
> On 8/15/2024 7:42 PM, Manos Pitsidianakis wrote:
> > Outstanding issues
> > ==================
> >
> > Outstanding issues that are not blocking for merge are:
> >
> > - Cross-compilation for aarch64 is not possible out-of-the-box because of
> this bug:
> > <https://github.com/rust-lang/rust/issues/125619
> <https://github.com/rust-lang/rust/issues/125619>> in llvm which when
> > fixed, must be ported to upstream rust's llvm fork. Since the problem
> > is an extraneous symbol we could strip it with objcopy -N|--strip-symbol
> > - Adding more than one Rust device ends up with duplicate symbols from
> > rust std library because we are linking as whole archives because...
> > constructors are stripped by the linker otherwise :( It can be worked
> > around if a single Rust library is built with all the devices as
> > dependencies which is then linked to qemu. The fix is a small change
> > which I will add either in a next version or when a new Rust device is
> > added.
> >
>
> Hi Manos,
>
> I also noticed that when I tried adding a second device. Some other projects
> met
> similar issues [1], but no clean solution seems to be available yet. The
> options
> are:
>
> 1) Combining all crates into one staticlib which is linked to the final
> executable. That requires generating one .rs with extern crate decls of all
> enabled crates. In the context of QEMU, different targets may enable different
> set of crates (e.g., some crates have arch constraints), thus one .rs for each
> target will be needed in general.
>
> 2) Linking rlibs (or emitted objects) directly with other C objects using the C
> linker. That somehow works (with some tricks) but is not officially supported
> and may break in the future.
>
> I'm working on (1), but would like to have your thoughts and preference on
> those
> options.
>
>
> Hello Junjie, I have also implemented (1) already (the fix I mentioned in the
> cover letter). In general I'd like to do it on a standalone patch so that it can
> be separated from the other changes instead of squashing it.
>
> If you have something already too, please share here! I will send mine as a
> reply to this thread when I am able. I am not familiar with meson so my version
> could be lacking!
Here's my version for your reference. There are still a few places yet to be
improved:
1. Each virtual device is required to write an additional `variables: {'crate':
'crate_name'}` in dep decl. It duplicates the crate name which is already given
in the static_libary() call, "abuses" the dep variables originally for cmake or
pkg-config, but is the only way I found to include the crate name in the dep.
2. Names of variables and scripts are tentative.
diff --git a/meson.build b/meson.build
index 97f90a9a60..07401b379a 100644
--- a/meson.build
+++ b/meson.build
@@ -3879,6 +3879,8 @@ common_all = static_library('common',
dependencies: common_ss.all_dependencies())
if have_rust and have_system
+ rust_root_crate = find_program('scripts/rust_root_crate.sh')
+
rust_args += run_command(
meson.global_source_root() / 'scripts/rustc_args.py',
'--config-headers', meson.project_build_root() / 'config-host.h',
@@ -3916,6 +3918,8 @@ if have_rust and have_system
'--allowlist-file', meson.project_build_root() + '/.*'
],
)
+
+ rust_ss = ss.source_set()
subdir('rust')
endif
@@ -4013,6 +4017,28 @@ foreach target : target_dirs
arch_srcs += target_specific.sources()
arch_deps += target_specific.dependencies()
+ if have_rust and have_system
+ target_rust = rust_ss.apply(config_target, strict: false)
+ crates = []
+ foreach dep : target_rust.dependencies()
+ crates += dep.get_variable('crate')
+ endforeach
+ if crates.length() > 0
+ root_crate = custom_target('rust-' + target + '.rs',
+ output: 'rust-' + target + '.rs',
+ command: [rust_root_crate] + crates,
+ capture: true,
+ build_by_default: true,
+ build_always_stale: true)
+ rust_lib = static_library('rust-' + target,
+ root_crate,
+ dependencies: target_rust.dependencies(),
+ rust_abi: 'c')
+ arch_deps += declare_dependency(link_whole: [rust_lib])
+ endif
+ endif
+
# allow using headers from the dependencies but do not include the sources,
# because this emulator only needs those in "objects". For external
# dependencies, the full dependency is included below in the executable.
diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build
index 518d4924a9..55d68ffb5c 100644
--- a/rust/hw/char/pl011/meson.build
+++ b/rust/hw/char/pl011/meson.build
@@ -8,7 +8,7 @@ _libpl011_rs = static_library(
'pl011',
files('src/lib.rs'),
override_options: ['rust_std=2021', 'build.rust_std=2021'],
- rust_abi: 'c',
+ rust_abi: 'rust',
dependencies: [
bilge_dep,
bilge_impl_dep,
@@ -16,6 +16,7 @@ _libpl011_rs = static_library(
],
)
-specific_ss.add(when: 'CONFIG_X_PL011_RUST', if_true: [declare_dependency(
+rust_ss.add(when: 'CONFIG_X_PL011_RUST', if_true: [declare_dependency(
link_whole: [_libpl011_rs],
+ variables: {'crate': 'pl011'},
)])
diff --git a/scripts/rust_root_crate.sh b/scripts/rust_root_crate.sh
new file mode 100755
index 0000000000..46d7e8728a
--- /dev/null
+++ b/scripts/rust_root_crate.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -eu
+
+cat <<EOF
+/* This file is autogenerated by scripts/rust_root_crate.sh. */
+
+EOF
+
+for crate in $*; do
+ echo "extern crate $crate;"
+done
---
Best Regards
Junjie Mao
>
> Manos
>
>
>
> [1] https://github.com/rust-lang/rust/issues/73632
> <https://github.com/rust-lang/rust/issues/73632>
>
> ---
> Best Regards
> Junjie Mao
>
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v7 6/7] rust: add crate to expose bindings and interfaces
2024-08-16 8:34 ` Philippe Mathieu-Daudé
@ 2024-08-21 7:24 ` Manos Pitsidianakis
0 siblings, 0 replies; 18+ messages in thread
From: Manos Pitsidianakis @ 2024-08-21 7:24 UTC (permalink / raw)
To: Philippe Mathieu-Daudé , Daniel P. Berrangé
Cc: Manos Pitsidianakis, qemu-devel, Paolo Bonzini,
Marc-André Lureau, Thomas Huth, John Snow, Cleber Rosa,
Beraldo Leal, Alex Benné e, Wainer dos Santos Moschetta,
Zhao Liu, Peter Maydell, ARM TCG CPUs, Stefan Hajnoczi,
Junjie Mao, Pierrick Bouvier, Richard Henderson, Gustavo Romero,
rowan.hart, Mads Ynddal, Markus Armbruster
On Fri, 16 Aug 2024 11:34, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>On 15/8/24 17:06, Daniel P. Berrangé wrote:
>> On Thu, Aug 15, 2024 at 04:01:17PM +0200, Philippe Mathieu-Daudé wrote:
>>> Hi Manos,
>>>
>>> On 15/8/24 13:42, Manos Pitsidianakis wrote:
>>>> Add rust/qemu-api, which exposes rust-bindgen generated FFI bindings and
>>>> provides some declaration macros for symbols visible to the rest of
>>>> QEMU.
>>>>
>>>> Co-authored-by: Junjie Mao <junjie.mao@intel.com>
>>>> Co-authored-by: Paolo Bonzini <pbonzini@redhat.com>
>>>> Signed-off-by: Junjie Mao <junjie.mao@intel.com>
>>>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>>>> Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
>>>> ---
>>>> MAINTAINERS | 6 ++
>>>> rust/meson.build | 9 +++
>>>> rust/qemu-api/.gitignore | 2 +
>>>> rust/qemu-api/Cargo.lock | 7 +++
>>>> rust/qemu-api/Cargo.toml | 23 +++++++
>>>> rust/qemu-api/README.md | 17 +++++
>>>> rust/qemu-api/build.rs | 13 ++++
>>>> rust/qemu-api/meson.build | 17 +++++
>>>> rust/qemu-api/rustfmt.toml | 1 +
>>>> rust/qemu-api/src/bindings.rs | 7 +++
>>>> rust/qemu-api/src/definitions.rs | 108 ++++++++++++++++++++++++++++++++
>>>> rust/qemu-api/src/device_class.rs | 128 ++++++++++++++++++++++++++++++++++++++
>>>> rust/qemu-api/src/lib.rs | 100 +++++++++++++++++++++++++++++
>>>> rust/qemu-api/src/tests.rs | 48 ++++++++++++++
>>>> rust/rustfmt.toml | 7 +++
>>>> 15 files changed, 493 insertions(+)
>>
>>>> diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml
>>>> new file mode 100644
>>>> index 0000000000..51260cbe42
>>>> --- /dev/null
>>>> +++ b/rust/qemu-api/Cargo.toml
>>>> @@ -0,0 +1,23 @@
>>>> +[package]
>>>> +name = "qemu_api"
>>>> +version = "0.1.0"
>>>> +edition = "2021"
>>>
>>>> +license = "GPL-2.0 OR GPL-3.0-or-later"
>>>
>>> in particular explaining the license choice.
>>
>> Semantically this is an overly verbose way of saying
>> "GPL-2.0-or-later", so just simplify this.
>
>Indeed. Manos, please use GPL-2.0-or-later to keep it simple.
>
>>
>>> Should all rust code use it?
>>
>> GPL-2.0-or-later is what we expect all new QEMU contributions to be
>> licensed as, regardless of language[1], so this looks desirable.
>
>Agreed.
Thanks, will replace it.
Manos
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2024-08-21 7:25 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-15 11:42 [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 1/7] Require meson version 1.5.0 Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 2/7] build-sys: Add rust feature option Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 3/7] configure, meson: detect Rust toolchain Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 4/7] rust: add bindgen step as a meson dependency Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 5/7] .gitattributes: add Rust diff and merge attributes Manos Pitsidianakis
2024-08-15 11:42 ` [PATCH v7 6/7] rust: add crate to expose bindings and interfaces Manos Pitsidianakis
2024-08-15 14:01 ` Philippe Mathieu-Daudé
2024-08-15 14:50 ` Manos Pitsidianakis
2024-08-15 15:06 ` Daniel P. Berrangé
2024-08-16 8:34 ` Philippe Mathieu-Daudé
2024-08-21 7:24 ` Manos Pitsidianakis
2024-08-16 8:26 ` Junjie Mao
2024-08-15 11:42 ` [PATCH v7 7/7] rust: add PL011 device model Manos Pitsidianakis
2024-08-15 17:10 ` [PATCH v7 0/7] Add Rust build support, ARM PL011 device impl Peter Maydell
2024-08-16 8:06 ` Junjie Mao
2024-08-16 8:17 ` Manos Pitsidianakis
2024-08-19 4:09 ` Junjie Mao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).