v9.1.1 release

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEZKoqtTHVaQM2a/75gqpKJDselHgFAmcScB0ACgkQgqpKJDse
 lHgQ7g/7BIWV/LC7MqFmHlXl9S0S7ZHVsDc2x6Bx97Sk4sKAUKLvRsLFMa5F40Fn
 xY8v/aLsqOTmzWz38hdtgJR0rrv8DykWw9ft9nta2tFg20tilL/LaakT8TLKmjK2
 StZFzk7iijnY78Z3RcVliBTStLoPbOx9WCUs2evCV/qTxQDec1A7u4ukG9cAztGn
 ea8pNnKNgk+BN805w1uMMZ1wnh3FTVs9kdXVh7CzXlRAHHkVHQ47C9ZN6vh6N3xs
 3qj/Obi4k1N81NNRJFA4gR02t82LdPhg/WV33/q9TxSmHyZEmNXg0lRlDyIeSbpw
 bqYY+dsBbGyMJgN/LUZMNjPAfQL4S5VicFJcfKTXr6xYtkhqtlCun1kmI7O+ZIY5
 kGQYbAAhyPkFIOU6XedyKxM+0eUDqrr9fyzyn5NfISzETQiGFccYjfk/4fsHGfS8
 nOBTNtYBpnEXFeUk/jvv6OPOsh2L+K0PKbGefFbCjNng9Ix3Kz5zEY8xhtlv7C6m
 9YyGGAS1zwcWapwq8URy01GWkiKT2Ia/gD7c89oGY1bJmQKYf9lrLX5YtP+d/NYs
 UqWmk046ViapiKDF7VXWtF0f5axYpeaMMhkNM5RtkOq57nez4LuKPaKs1emRC6W9
 LE2om+28dyGJqHeJp5fqigM+wPxRJlecR57sDIuq4n0bJcvzLEA=
 =240n
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQSq9xYmtep25y1RrMYC5KE/dBVGigUCZxv7TAAKCRAC5KE/dBVG
 isCPAP43SCLPw/W/su5jPShfNn4fvHHiY1f0a6t3Kf6414aqvQD/XKmYGFGl4V5k
 XYnW/9D6Bp/k8gBSjKzYeIt0+Mt/AAQ=
 =cRil
 -----END PGP SIGNATURE-----

Merge tag 'v9.1.1' into update_qemu_9_1_0

v9.1.1 release
This commit is contained in:
Romain Malmain 2024-10-25 22:10:51 +02:00
commit 67dabac1ed
2172 changed files with 87536 additions and 72801 deletions

View File

@ -128,7 +128,7 @@ variables:
when: manual when: manual
# Jobs can run if any jobs they depend on were successful # Jobs can run if any jobs they depend on were successful
- if: '$QEMU_JOB_SKIPPED && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH =~ /staging-[[:digit:]]+\.[[:digit:]]/' - if: '$CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH =~ /staging-[[:digit:]]+\.[[:digit:]]/'
when: on_success when: on_success
variables: variables:
QEMU_CI_CONTAINER_TAG: $CI_COMMIT_REF_SLUG QEMU_CI_CONTAINER_TAG: $CI_COMMIT_REF_SLUG

View File

@ -9,6 +9,7 @@
when: always when: always
before_script: before_script:
- JOBS=$(expr $(nproc) + 1) - JOBS=$(expr $(nproc) + 1)
- cat /packages.txt
script: script:
- export CCACHE_BASEDIR="$(pwd)" - export CCACHE_BASEDIR="$(pwd)"
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache" - export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
@ -45,10 +46,8 @@
exclude: exclude:
- build/**/*.p - build/**/*.p
- build/**/*.a.p - build/**/*.a.p
- build/**/*.fa.p
- build/**/*.c.o - build/**/*.c.o
- build/**/*.c.o.d - build/**/*.c.o.d
- build/**/*.fa
.common_test_job_template: .common_test_job_template:
extends: .base_job_template extends: .base_job_template

View File

@ -164,7 +164,7 @@ build-system-centos:
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
--enable-modules --enable-trace-backends=dtrace --enable-docs --enable-modules --enable-trace-backends=dtrace --enable-docs
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu x86_64-softmmu rx-softmmu sh4-softmmu
MAKE_CHECK_ARGS: check-build MAKE_CHECK_ARGS: check-build
# Previous QEMU release. Used for cross-version migration tests. # Previous QEMU release. Used for cross-version migration tests.
@ -178,10 +178,8 @@ build-previous-qemu:
exclude: exclude:
- build-previous/**/*.p - build-previous/**/*.p
- build-previous/**/*.a.p - build-previous/**/*.a.p
- build-previous/**/*.fa.p
- build-previous/**/*.c.o - build-previous/**/*.c.o
- build-previous/**/*.c.o.d - build-previous/**/*.c.o.d
- build-previous/**/*.fa
needs: needs:
job: amd64-opensuse-leap-container job: amd64-opensuse-leap-container
variables: variables:
@ -254,7 +252,7 @@ avocado-system-centos:
IMAGE: centos9 IMAGE: centos9
MAKE_CHECK_ARGS: check-avocado MAKE_CHECK_ARGS: check-avocado
AVOCADO_TAGS: arch:ppc64 arch:or1k arch:s390x arch:x86_64 arch:rx AVOCADO_TAGS: arch:ppc64 arch:or1k arch:s390x arch:x86_64 arch:rx
arch:sh4 arch:nios2 arch:sh4
build-system-opensuse: build-system-opensuse:
extends: extends:
@ -342,11 +340,13 @@ build-tcg-disabled:
- cd tests/qemu-iotests/ - cd tests/qemu-iotests/
- ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048 - ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163 052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163
170 171 183 184 192 194 208 221 226 227 236 253 277 image-fleecing 170 171 184 192 194 208 221 226 227 236 253 277 image-fleecing
- ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122 - ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122
124 132 139 142 144 145 151 152 155 157 165 194 196 200 202 124 132 139 142 144 145 151 152 155 157 165 194 196 200 202
208 209 216 218 227 234 246 247 248 250 254 255 257 258 208 209 216 218 227 234 246 247 248 250 254 255 257 258
260 261 262 263 264 270 272 273 277 279 image-fleecing 260 261 262 263 264 270 272 273 277 279 image-fleecing
- cd ../..
- make distclean
build-user: build-user:
extends: .native_build_job_template extends: .native_build_job_template
@ -432,6 +432,7 @@ clang-system:
IMAGE: fedora IMAGE: fedora
CONFIGURE_ARGS: --cc=clang --cxx=clang++ CONFIGURE_ARGS: --cc=clang --cxx=clang++
--extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined --extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined
--extra-cflags=-fno-sanitize=function
TARGETS: alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu s390x-softmmu TARGETS: alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu s390x-softmmu
MAKE_CHECK_ARGS: check-qtest check-tcg MAKE_CHECK_ARGS: check-qtest check-tcg
@ -445,6 +446,7 @@ clang-user:
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --disable-system CONFIGURE_ARGS: --cc=clang --cxx=clang++ --disable-system
--target-list-exclude=alpha-linux-user,microblazeel-linux-user,aarch64_be-linux-user,i386-linux-user,m68k-linux-user,mipsn32el-linux-user,xtensaeb-linux-user --target-list-exclude=alpha-linux-user,microblazeel-linux-user,aarch64_be-linux-user,i386-linux-user,m68k-linux-user,mipsn32el-linux-user,xtensaeb-linux-user
--extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined --extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined
--extra-cflags=-fno-sanitize=function
MAKE_CHECK_ARGS: check-unit check-tcg MAKE_CHECK_ARGS: check-unit check-tcg
# Set LD_JOBS=1 because this requires LTO and ld consumes a large amount of memory. # Set LD_JOBS=1 because this requires LTO and ld consumes a large amount of memory.
@ -636,7 +638,7 @@ build-tci:
- TARGETS="aarch64 arm hppa m68k microblaze ppc64 s390x x86_64" - TARGETS="aarch64 arm hppa m68k microblaze ppc64 s390x x86_64"
- mkdir build - mkdir build
- cd build - cd build
- ../configure --enable-tcg-interpreter --disable-docs --disable-gtk --disable-vnc - ../configure --enable-tcg-interpreter --disable-kvm --disable-docs --disable-gtk --disable-vnc
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)" --target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
|| { cat config.log meson-logs/meson-log.txt && exit 1; } || { cat config.log meson-logs/meson-log.txt && exit 1; }
- make -j"$JOBS" - make -j"$JOBS"
@ -651,6 +653,9 @@ build-tci:
- make check-tcg - make check-tcg
# Check our reduced build configurations # Check our reduced build configurations
# requires libfdt: aarch64, arm, loongarch64, microblaze, microblazeel,
# or1k, ppc64, riscv32, riscv64, rx
# fails qtest without boards: i386, x86_64
build-without-defaults: build-without-defaults:
extends: .native_build_job_template extends: .native_build_job_template
needs: needs:
@ -664,8 +669,11 @@ build-without-defaults:
--disable-pie --disable-pie
--disable-qom-cast-debug --disable-qom-cast-debug
--disable-strip --disable-strip
TARGETS: avr-softmmu s390x-softmmu sh4-softmmu TARGETS: alpha-softmmu avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
sparc64-softmmu hexagon-linux-user i386-linux-user s390x-linux-user mips-softmmu mips64-softmmu mipsel-softmmu mips64el-softmmu
ppc-softmmu s390x-softmmu sh4-softmmu sh4eb-softmmu sparc-softmmu
sparc64-softmmu tricore-softmmu xtensa-softmmu xtensaeb-softmmu
hexagon-linux-user i386-linux-user s390x-linux-user
MAKE_CHECK_ARGS: check MAKE_CHECK_ARGS: check
build-libvhost-user: build-libvhost-user:

View File

@ -91,40 +91,3 @@ aarch64-macos-14-base-build:
PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64 TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
QEMU_JOB_OPTIONAL: 1 QEMU_JOB_OPTIONAL: 1
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
.cirrus_kvm_job:
extends: .base_job_template
stage: build
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
needs: []
timeout: 80m
script:
- sed -e "s|[@]CI_REPOSITORY_URL@|$CI_REPOSITORY_URL|g"
-e "s|[@]CI_COMMIT_REF_NAME@|$CI_COMMIT_REF_NAME|g"
-e "s|[@]CI_COMMIT_SHA@|$CI_COMMIT_SHA|g"
-e "s|[@]NAME@|$NAME|g"
-e "s|[@]CONFIGURE_ARGS@|$CONFIGURE_ARGS|g"
-e "s|[@]TEST_TARGETS@|$TEST_TARGETS|g"
<.gitlab-ci.d/cirrus/kvm-build.yml >.gitlab-ci.d/cirrus/$NAME.yml
- cat .gitlab-ci.d/cirrus/$NAME.yml
- cirrus-run -v --show-build-log always .gitlab-ci.d/cirrus/$NAME.yml
variables:
QEMU_JOB_CIRRUS: 1
QEMU_JOB_OPTIONAL: 1
x86-netbsd:
extends: .cirrus_kvm_job
variables:
NAME: netbsd
CONFIGURE_ARGS: --target-list=x86_64-softmmu,ppc64-softmmu,aarch64-softmmu
TEST_TARGETS: check
x86-openbsd:
extends: .cirrus_kvm_job
variables:
NAME: openbsd
CONFIGURE_ARGS: --target-list=i386-softmmu,riscv64-softmmu,mips64-softmmu
TEST_TARGETS: check

View File

@ -26,7 +26,7 @@ build_task:
- git clone --depth 100 "$CI_REPOSITORY_URL" . - git clone --depth 100 "$CI_REPOSITORY_URL" .
- git fetch origin "$CI_COMMIT_REF_NAME" - git fetch origin "$CI_COMMIT_REF_NAME"
- git reset --hard "$CI_COMMIT_SHA" - git reset --hard "$CI_COMMIT_SHA"
build_script: step_script:
- mkdir build - mkdir build
- cd build - cd build
- ../configure --enable-werror $CONFIGURE_ARGS - ../configure --enable-werror $CONFIGURE_ARGS

View File

@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake'
NINJA='/usr/local/bin/ninja' NINJA='/usr/local/bin/ninja'
PACKAGING_COMMAND='pkg' PACKAGING_COMMAND='pkg'
PIP3='/usr/local/bin/pip-3.8' PIP3='/usr/local/bin/pip-3.8'
PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-tomli py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd' PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk-vnc gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py311-numpy py311-pillow py311-pip py311-sphinx py311-sphinx_rtd_theme py311-tomli py311-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd'
PYPI_PKGS='' PYPI_PKGS=''
PYTHON='/usr/local/bin/python3' PYTHON='/usr/local/bin/python3'

View File

@ -1,31 +0,0 @@
container:
image: fedora:35
cpu: 4
memory: 8Gb
kvm: true
env:
CIRRUS_CLONE_DEPTH: 1
CI_REPOSITORY_URL: "@CI_REPOSITORY_URL@"
CI_COMMIT_REF_NAME: "@CI_COMMIT_REF_NAME@"
CI_COMMIT_SHA: "@CI_COMMIT_SHA@"
@NAME@_task:
@NAME@_vm_cache:
folder: $HOME/.cache/qemu-vm
install_script:
- dnf update -y
- dnf install -y git make openssh-clients qemu-img qemu-system-x86 wget meson
clone_script:
- git clone --depth 100 "$CI_REPOSITORY_URL" .
- git fetch origin "$CI_COMMIT_REF_NAME"
- git reset --hard "$CI_COMMIT_SHA"
build_script:
- if [ -f $HOME/.cache/qemu-vm/images/@NAME@.img ]; then
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN)
EXTRA_CONFIGURE_OPTS="@CONFIGURE_ARGS@"
BUILD_TARGET="@TEST_TARGETS@" ;
else
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN) BUILD_TARGET=help
EXTRA_CONFIGURE_OPTS="--disable-system --disable-user --disable-tools" ;
fi

View File

@ -11,6 +11,6 @@ MAKE='/opt/homebrew/bin/gmake'
NINJA='/opt/homebrew/bin/ninja' NINJA='/opt/homebrew/bin/ninja'
PACKAGING_COMMAND='brew' PACKAGING_COMMAND='brew'
PIP3='/opt/homebrew/bin/pip3' PIP3='/opt/homebrew/bin/pip3'
PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd' PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 gtk-vnc jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd'
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli' PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli'
PYTHON='/opt/homebrew/bin/python3' PYTHON='/opt/homebrew/bin/python3'

View File

@ -11,6 +11,6 @@ MAKE='/opt/homebrew/bin/gmake'
NINJA='/opt/homebrew/bin/ninja' NINJA='/opt/homebrew/bin/ninja'
PACKAGING_COMMAND='brew' PACKAGING_COMMAND='brew'
PIP3='/opt/homebrew/bin/pip3' PIP3='/opt/homebrew/bin/pip3'
PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd' PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 gtk-vnc jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd'
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli' PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli'
PYTHON='/opt/homebrew/bin/python3' PYTHON='/opt/homebrew/bin/python3'

View File

@ -22,12 +22,6 @@ arm64-debian-cross-container:
variables: variables:
NAME: debian-arm64-cross NAME: debian-arm64-cross
armel-debian-cross-container:
extends: .container_job_template
stage: containers
variables:
NAME: debian-armel-cross
armhf-debian-cross-container: armhf-debian-cross-container:
extends: .container_job_template extends: .container_job_template
stage: containers stage: containers

View File

@ -8,6 +8,8 @@
key: "$CI_JOB_NAME" key: "$CI_JOB_NAME"
when: always when: always
timeout: 80m timeout: 80m
before_script:
- cat /packages.txt
script: script:
- export CCACHE_BASEDIR="$(pwd)" - export CCACHE_BASEDIR="$(pwd)"
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache" - export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
@ -72,7 +74,7 @@
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS - ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
--disable-system --target-list-exclude="aarch64_be-linux-user --disable-system --target-list-exclude="aarch64_be-linux-user
alpha-linux-user cris-linux-user m68k-linux-user microblazeel-linux-user alpha-linux-user cris-linux-user m68k-linux-user microblazeel-linux-user
nios2-linux-user or1k-linux-user ppc-linux-user sparc-linux-user or1k-linux-user ppc-linux-user sparc-linux-user
xtensa-linux-user $CROSS_SKIP_TARGETS" xtensa-linux-user $CROSS_SKIP_TARGETS"
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS - make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS

View File

@ -1,13 +1,6 @@
include: include:
- local: '/.gitlab-ci.d/crossbuild-template.yml' - local: '/.gitlab-ci.d/crossbuild-template.yml'
cross-armel-user:
extends: .cross_user_build_job
needs:
job: armel-debian-cross-container
variables:
IMAGE: debian-armel-cross
cross-armhf-user: cross-armhf-user:
extends: .cross_user_build_job extends: .cross_user_build_job
needs: needs:
@ -37,6 +30,17 @@ cross-arm64-kvm-only:
IMAGE: debian-arm64-cross IMAGE: debian-arm64-cross
EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features
cross-i686-system:
extends:
- .cross_system_build_job
- .cross_test_artifacts
needs:
job: i686-debian-cross-container
variables:
IMAGE: debian-i686-cross
EXTRA_CONFIGURE_OPTS: --disable-kvm
MAKE_CHECK_ARGS: check-qtest
cross-i686-user: cross-i686-user:
extends: extends:
- .cross_user_build_job - .cross_user_build_job
@ -57,7 +61,7 @@ cross-i686-tci:
variables: variables:
IMAGE: debian-i686-cross IMAGE: debian-i686-cross
ACCEL: tcg-interpreter ACCEL: tcg-interpreter
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins --disable-kvm
MAKE_CHECK_ARGS: check check-tcg MAKE_CHECK_ARGS: check check-tcg
cross-mipsel-system: cross-mipsel-system:
@ -167,7 +171,7 @@ cross-win64-system:
IMAGE: fedora-win64-cross IMAGE: fedora-win64-cross
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal --disable-plugins EXTRA_CONFIGURE_OPTS: --enable-fdt=internal --disable-plugins
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu
m68k-softmmu microblazeel-softmmu nios2-softmmu m68k-softmmu microblazeel-softmmu
or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu
tricore-softmmu xtensaeb-softmmu tricore-softmmu xtensaeb-softmmu
artifacts: artifacts:

View File

@ -29,7 +29,6 @@
junit: build/meson-logs/testlog.junit.xml junit: build/meson-logs/testlog.junit.xml
include: include:
- local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml' - local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-s390x.yml'
- local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml' - local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml'
- local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml' - local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml'
- local: '/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml'

View File

@ -1,24 +0,0 @@
# All centos-stream-8 jobs should run successfully in an environment
# setup by the scripts/ci/setup/stream/8/build-environment.yml task
# "Installation of extra packages to build QEMU"
centos-stream-8-x86_64:
extends: .custom_runner_template
allow_failure: true
needs: []
stage: build
tags:
- centos_stream_8
- x86_64
rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$CENTOS_STREAM_8_x86_64_RUNNER_AVAILABLE"
before_script:
- JOBS=$(expr $(nproc) + 1)
script:
- mkdir build
- cd build
- ../scripts/ci/org.centos/stream/8/x86_64/configure
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- make -j"$JOBS"
- make NINJA=":" check check-avocado

View File

@ -1,5 +1,5 @@
# All ubuntu-22.04 jobs should run successfully in an environment # All ubuntu-22.04 jobs should run successfully in an environment
# setup by the scripts/ci/setup/qemu/build-environment.yml task # setup by the scripts/ci/setup/ubuntu/build-environment.yml task
# "Install basic packages to build QEMU on Ubuntu 22.04" # "Install basic packages to build QEMU on Ubuntu 22.04"
ubuntu-22.04-aarch32-all: ubuntu-22.04-aarch32-all:

View File

@ -1,5 +1,5 @@
# All ubuntu-22.04 jobs should run successfully in an environment # All ubuntu-22.04 jobs should run successfully in an environment
# setup by the scripts/ci/setup/qemu/build-environment.yml task # setup by the scripts/ci/setup/ubuntu/build-environment.yml task
# "Install basic packages to build QEMU on Ubuntu 22.04" # "Install basic packages to build QEMU on Ubuntu 22.04"
ubuntu-22.04-aarch64-all-linux-static: ubuntu-22.04-aarch64-all-linux-static:

View File

@ -1,34 +1,32 @@
# All ubuntu-20.04 jobs should run successfully in an environment # All ubuntu-22.04 jobs should run successfully in an environment
# setup by the scripts/ci/setup/build-environment.yml task # setup by the scripts/ci/setup/ubuntu/build-environment.yml task
# "Install basic packages to build QEMU on Ubuntu 20.04/20.04" # "Install basic packages to build QEMU on Ubuntu 22.04"
ubuntu-20.04-s390x-all-linux-static: ubuntu-22.04-s390x-all-linux:
extends: .custom_runner_template extends: .custom_runner_template
needs: [] needs: []
stage: build stage: build
tags: tags:
- ubuntu_20.04 - ubuntu_22.04
- s390x - s390x
rules: rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$S390X_RUNNER_AVAILABLE" - if: "$S390X_RUNNER_AVAILABLE"
script: script:
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
- mkdir build - mkdir build
- cd build - cd build
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh - ../configure --enable-debug --disable-system --disable-tools --disable-docs
|| { cat config.log meson-logs/meson-log.txt; exit 1; } || { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc` - make --output-sync -j`nproc`
- make --output-sync check-tcg - make --output-sync check-tcg
- make --output-sync -j`nproc` check - make --output-sync -j`nproc` check
ubuntu-20.04-s390x-all: ubuntu-22.04-s390x-all-system:
extends: .custom_runner_template extends: .custom_runner_template
needs: [] needs: []
stage: build stage: build
tags: tags:
- ubuntu_20.04 - ubuntu_22.04
- s390x - s390x
timeout: 75m timeout: 75m
rules: rules:
@ -37,17 +35,17 @@ ubuntu-20.04-s390x-all:
script: script:
- mkdir build - mkdir build
- cd build - cd build
- ../configure --disable-libssh - ../configure --disable-user
|| { cat config.log meson-logs/meson-log.txt; exit 1; } || { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc` - make --output-sync -j`nproc`
- make --output-sync -j`nproc` check - make --output-sync -j`nproc` check
ubuntu-20.04-s390x-alldbg: ubuntu-22.04-s390x-alldbg:
extends: .custom_runner_template extends: .custom_runner_template
needs: [] needs: []
stage: build stage: build
tags: tags:
- ubuntu_20.04 - ubuntu_22.04
- s390x - s390x
rules: rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
@ -59,18 +57,18 @@ ubuntu-20.04-s390x-alldbg:
script: script:
- mkdir build - mkdir build
- cd build - cd build
- ../configure --enable-debug --disable-libssh - ../configure --enable-debug
|| { cat config.log meson-logs/meson-log.txt; exit 1; } || { cat config.log meson-logs/meson-log.txt; exit 1; }
- make clean - make clean
- make --output-sync -j`nproc` - make --output-sync -j`nproc`
- make --output-sync -j`nproc` check - make --output-sync -j`nproc` check
ubuntu-20.04-s390x-clang: ubuntu-22.04-s390x-clang:
extends: .custom_runner_template extends: .custom_runner_template
needs: [] needs: []
stage: build stage: build
tags: tags:
- ubuntu_20.04 - ubuntu_22.04
- s390x - s390x
rules: rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
@ -82,16 +80,16 @@ ubuntu-20.04-s390x-clang:
script: script:
- mkdir build - mkdir build
- cd build - cd build
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers - ../configure --cc=clang --cxx=clang++ --enable-sanitizers
|| { cat config.log meson-logs/meson-log.txt; exit 1; } || { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc` - make --output-sync -j`nproc`
- make --output-sync -j`nproc` check - make --output-sync -j`nproc` check
ubuntu-20.04-s390x-tci: ubuntu-22.04-s390x-tci:
needs: [] needs: []
stage: build stage: build
tags: tags:
- ubuntu_20.04 - ubuntu_22.04
- s390x - s390x
rules: rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
@ -103,16 +101,16 @@ ubuntu-20.04-s390x-tci:
script: script:
- mkdir build - mkdir build
- cd build - cd build
- ../configure --disable-libssh --enable-tcg-interpreter - ../configure --enable-tcg-interpreter
|| { cat config.log meson-logs/meson-log.txt; exit 1; } || { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc` - make --output-sync -j`nproc`
ubuntu-20.04-s390x-notcg: ubuntu-22.04-s390x-notcg:
extends: .custom_runner_template extends: .custom_runner_template
needs: [] needs: []
stage: build stage: build
tags: tags:
- ubuntu_20.04 - ubuntu_22.04
- s390x - s390x
rules: rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
@ -124,7 +122,7 @@ ubuntu-20.04-s390x-notcg:
script: script:
- mkdir build - mkdir build
- cd build - cd build
- ../configure --disable-libssh --disable-tcg - ../configure --disable-tcg
|| { cat config.log meson-logs/meson-log.txt; exit 1; } || { cat config.log meson-logs/meson-log.txt; exit 1; }
- make --output-sync -j`nproc` - make --output-sync -j`nproc`
- make --output-sync -j`nproc` check - make --output-sync -j`nproc` check

View File

@ -17,15 +17,7 @@ msys2-64bit:
# This feature doesn't (currently) work with PowerShell, it stops # This feature doesn't (currently) work with PowerShell, it stops
# the echo'ing of commands being run and doesn't show any timing # the echo'ing of commands being run and doesn't show any timing
FF_SCRIPT_SECTIONS: 0 FF_SCRIPT_SECTIONS: 0
# do not remove "--without-default-devices"! CONFIGURE_ARGS: --disable-system --enable-tools -Ddebug=false -Doptimization=0
# commit 9f8e6cad65a6 ("gitlab-ci: Speed up the msys2-64bit job by using --without-default-devices"
# changed to compile QEMU with the --without-default-devices switch
# for this job, because otherwise the build could not complete within
# the project timeout.
CONFIGURE_ARGS: --target-list=x86_64-softmmu --without-default-devices -Ddebug=false -Doptimization=0
# qTests don't run successfully with "--without-default-devices",
# so let's exclude the qtests from CI for now.
TEST_ARGS: --no-suite qtest
# The Windows git is a bit older so override the default # The Windows git is a bit older so override the default
GIT_FETCH_EXTRA_FLAGS: --no-tags --prune --quiet GIT_FETCH_EXTRA_FLAGS: --no-tags --prune --quiet
artifacts: artifacts:
@ -84,33 +76,16 @@ msys2-64bit:
bison diffutils flex bison diffutils flex
git grep make sed git grep make sed
mingw-w64-x86_64-binutils mingw-w64-x86_64-binutils
mingw-w64-x86_64-capstone
mingw-w64-x86_64-ccache mingw-w64-x86_64-ccache
mingw-w64-x86_64-curl mingw-w64-x86_64-curl
mingw-w64-x86_64-cyrus-sasl
mingw-w64-x86_64-dtc
mingw-w64-x86_64-gcc mingw-w64-x86_64-gcc
mingw-w64-x86_64-glib2 mingw-w64-x86_64-glib2
mingw-w64-x86_64-gnutls
mingw-w64-x86_64-gtk3
mingw-w64-x86_64-libgcrypt
mingw-w64-x86_64-libjpeg-turbo
mingw-w64-x86_64-libnfs mingw-w64-x86_64-libnfs
mingw-w64-x86_64-libpng
mingw-w64-x86_64-libssh mingw-w64-x86_64-libssh
mingw-w64-x86_64-libtasn1
mingw-w64-x86_64-libusb
mingw-w64-x86_64-lzo2
mingw-w64-x86_64-nettle
mingw-w64-x86_64-ninja mingw-w64-x86_64-ninja
mingw-w64-x86_64-pixman mingw-w64-x86_64-pixman
mingw-w64-x86_64-pkgconf mingw-w64-x86_64-pkgconf
mingw-w64-x86_64-python mingw-w64-x86_64-python
mingw-w64-x86_64-SDL2
mingw-w64-x86_64-SDL2_image
mingw-w64-x86_64-snappy
mingw-w64-x86_64-spice
mingw-w64-x86_64-usbredir
mingw-w64-x86_64-zstd" mingw-w64-x86_64-zstd"
- Write-Output "Running build at $(Get-Date -Format u)" - Write-Output "Running build at $(Get-Date -Format u)"
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory - $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
@ -123,7 +98,7 @@ msys2-64bit:
- mkdir build - mkdir build
- cd build - cd build
- ..\msys64\usr\bin\bash -lc "ccache --zero-stats" - ..\msys64\usr\bin\bash -lc "ccache --zero-stats"
- ..\msys64\usr\bin\bash -lc "../configure --enable-fdt=system $CONFIGURE_ARGS" - ..\msys64\usr\bin\bash -lc "../configure $CONFIGURE_ARGS"
- ..\msys64\usr\bin\bash -lc "make" - ..\msys64\usr\bin\bash -lc "make"
- ..\msys64\usr\bin\bash -lc "make check MTESTARGS='$TEST_ARGS' || { cat meson-logs/testlog.txt; exit 1; } ;" - ..\msys64\usr\bin\bash -lc "make check MTESTARGS='$TEST_ARGS' || { cat meson-logs/testlog.txt; exit 1; } ;"
- ..\msys64\usr\bin\bash -lc "ccache --show-stats" - ..\msys64\usr\bin\bash -lc "ccache --show-stats"

View File

@ -100,6 +100,7 @@ Philippe Mathieu-Daudé <philmd@linaro.org> <f4bug@amsat.org>
Philippe Mathieu-Daudé <philmd@linaro.org> <philmd@redhat.com> Philippe Mathieu-Daudé <philmd@linaro.org> <philmd@redhat.com>
Philippe Mathieu-Daudé <philmd@linaro.org> <philmd@fungible.com> Philippe Mathieu-Daudé <philmd@linaro.org> <philmd@fungible.com>
Roman Bolshakov <rbolshakov@ddn.com> <r.bolshakov@yadro.com> Roman Bolshakov <rbolshakov@ddn.com> <r.bolshakov@yadro.com>
Sriram Yagnaraman <sriram.yagnaraman@ericsson.com> <sriram.yagnaraman@est.tech>
Stefan Brankovic <stefan.brankovic@syrmia.com> <stefan.brankovic@rt-rk.com.com> Stefan Brankovic <stefan.brankovic@syrmia.com> <stefan.brankovic@rt-rk.com.com>
Stefan Weil <sw@weilnetz.de> Stefan Weil <stefan@weilnetz.de> Stefan Weil <sw@weilnetz.de> Stefan Weil <stefan@weilnetz.de>
Taylor Simpson <ltaylorsimpson@gmail.com> <tsimpson@quicinc.com> Taylor Simpson <ltaylorsimpson@gmail.com> <tsimpson@quicinc.com>

View File

@ -1,5 +1,5 @@
os: linux os: linux
dist: focal dist: jammy
language: c language: c
compiler: compiler:
- gcc - gcc
@ -7,13 +7,11 @@ cache:
# There is one cache per branch and compiler version. # There is one cache per branch and compiler version.
# characteristics of each job are used to identify the cache: # characteristics of each job are used to identify the cache:
# - OS name (currently only linux) # - OS name (currently only linux)
# - OS distribution (for Linux, bionic or focal) # - OS distribution (e.g. "jammy" for Linux)
# - Names and values of visible environment variables set in .travis.yml or Settings panel # - Names and values of visible environment variables set in .travis.yml or Settings panel
timeout: 1200 timeout: 1200
ccache: true ccache: true
pip: true pip: true
directories:
- $HOME/avocado/data/cache
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu # The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
@ -83,7 +81,6 @@ jobs:
- name: "[aarch64] GCC check-tcg" - name: "[aarch64] GCC check-tcg"
arch: arm64 arch: arm64
dist: focal
addons: addons:
apt_packages: apt_packages:
- libaio-dev - libaio-dev
@ -109,17 +106,17 @@ jobs:
- libvdeplug-dev - libvdeplug-dev
- libvte-2.91-dev - libvte-2.91-dev
- ninja-build - ninja-build
- python3-tomli
# Tests dependencies # Tests dependencies
- genisoimage - genisoimage
env: env:
- TEST_CMD="make check check-tcg V=1" - TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers --enable-fdt=system - CONFIG="--disable-containers --enable-fdt=system
--target-list=${MAIN_SYSTEM_TARGETS} --cxx=/bin/false" --target-list=${MAIN_SYSTEM_TARGETS} --cxx=/bin/false"
- UNRELIABLE=true
- name: "[ppc64] GCC check-tcg" - name: "[ppc64] Clang check-tcg"
arch: ppc64le arch: ppc64le
dist: focal compiler: clang
addons: addons:
apt_packages: apt_packages:
- libaio-dev - libaio-dev
@ -145,6 +142,7 @@ jobs:
- libvdeplug-dev - libvdeplug-dev
- libvte-2.91-dev - libvte-2.91-dev
- ninja-build - ninja-build
- python3-tomli
# Tests dependencies # Tests dependencies
- genisoimage - genisoimage
env: env:
@ -154,7 +152,6 @@ jobs:
- name: "[s390x] GCC check-tcg" - name: "[s390x] GCC check-tcg"
arch: s390x arch: s390x
dist: focal
addons: addons:
apt_packages: apt_packages:
- libaio-dev - libaio-dev
@ -180,13 +177,13 @@ jobs:
- libvdeplug-dev - libvdeplug-dev
- libvte-2.91-dev - libvte-2.91-dev
- ninja-build - ninja-build
- python3-tomli
# Tests dependencies # Tests dependencies
- genisoimage - genisoimage
env: env:
- TEST_CMD="make check check-tcg V=1" - TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers - CONFIG="--disable-containers
--target-list=hppa-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu" --target-list=hppa-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
- UNRELIABLE=true
script: script:
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$? - BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
- | - |
@ -197,9 +194,9 @@ jobs:
$(exit $BUILD_RC); $(exit $BUILD_RC);
fi fi
- name: "[s390x] GCC (other-system)" - name: "[s390x] Clang (other-system)"
arch: s390x arch: s390x
dist: focal compiler: clang
addons: addons:
apt_packages: apt_packages:
- libaio-dev - libaio-dev
@ -221,6 +218,7 @@ jobs:
- libzstd-dev - libzstd-dev
- nettle-dev - nettle-dev
- ninja-build - ninja-build
- python3-tomli
# Tests dependencies # Tests dependencies
- genisoimage - genisoimage
env: env:
@ -229,7 +227,6 @@ jobs:
- name: "[s390x] GCC (user)" - name: "[s390x] GCC (user)"
arch: s390x arch: s390x
dist: focal
addons: addons:
apt_packages: apt_packages:
- libgcrypt20-dev - libgcrypt20-dev
@ -238,14 +235,14 @@ jobs:
- ninja-build - ninja-build
- flex - flex
- bison - bison
- python3-tomli
env: env:
- TEST_CMD="make check check-tcg V=1" - TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers --disable-system" - CONFIG="--disable-containers --disable-system"
- name: "[s390x] Clang (disable-tcg)" - name: "[s390x] Clang (disable-tcg)"
arch: s390x arch: s390x
dist: focal compiler: clang
compiler: clang-10
addons: addons:
apt_packages: apt_packages:
- libaio-dev - libaio-dev
@ -271,9 +268,8 @@ jobs:
- libvdeplug-dev - libvdeplug-dev
- libvte-2.91-dev - libvte-2.91-dev
- ninja-build - ninja-build
- clang-10 - python3-tomli
env: env:
- TEST_CMD="make check-unit" - TEST_CMD="make check-unit"
- CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools - CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools
--enable-fdt=system --host-cc=clang --cxx=clang++" --enable-fdt=system --host-cc=clang --cxx=clang++"
- UNRELIABLE=true

View File

@ -23,6 +23,9 @@ config IVSHMEM
config TPM config TPM
bool bool
config FDT
bool
config VHOST_USER config VHOST_USER
bool bool
@ -35,9 +38,6 @@ config VHOST_KERNEL
config VIRTFS config VIRTFS
bool bool
config PVRDMA
bool
config MULTIPROCESS_ALLOWED config MULTIPROCESS_ALLOWED
bool bool
imply MULTIPROCESS imply MULTIPROCESS

View File

@ -140,6 +140,7 @@ F: docs/system/target-i386*
F: target/i386/*.[ch] F: target/i386/*.[ch]
F: target/i386/Kconfig F: target/i386/Kconfig
F: target/i386/meson.build F: target/i386/meson.build
F: tools/i386/
Guest CPU cores (TCG) Guest CPU cores (TCG)
--------------------- ---------------------
@ -167,6 +168,7 @@ F: include/exec/target_long.h
F: include/exec/helper*.h F: include/exec/helper*.h
F: include/exec/helper*.h.inc F: include/exec/helper*.h.inc
F: include/exec/helper-info.c.inc F: include/exec/helper-info.c.inc
F: include/exec/page-protection.h
F: include/sysemu/cpus.h F: include/sysemu/cpus.h
F: include/sysemu/tcg.h F: include/sysemu/tcg.h
F: include/hw/core/tcg-cpu-ops.h F: include/hw/core/tcg-cpu-ops.h
@ -243,6 +245,7 @@ F: disas/hexagon.c
F: configs/targets/hexagon-linux-user/default.mak F: configs/targets/hexagon-linux-user/default.mak
F: docker/dockerfiles/debian-hexagon-cross.docker F: docker/dockerfiles/debian-hexagon-cross.docker
F: gdb-xml/hexagon*.xml F: gdb-xml/hexagon*.xml
T: git https://github.com/quic/qemu.git hex-next
Hexagon idef-parser Hexagon idef-parser
M: Alessandro Di Federico <ale@rev.ng> M: Alessandro Di Federico <ale@rev.ng>
@ -284,26 +287,13 @@ MIPS TCG CPUs
M: Philippe Mathieu-Daudé <philmd@linaro.org> M: Philippe Mathieu-Daudé <philmd@linaro.org>
R: Aurelien Jarno <aurelien@aurel32.net> R: Aurelien Jarno <aurelien@aurel32.net>
R: Jiaxun Yang <jiaxun.yang@flygoat.com> R: Jiaxun Yang <jiaxun.yang@flygoat.com>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> R: Aleksandar Rikalo <arikalo@gmail.com>
S: Odd Fixes S: Odd Fixes
F: target/mips/ F: target/mips/
F: disas/*mips.c F: disas/*mips.c
F: docs/system/cpu-models-mips.rst.inc F: docs/system/cpu-models-mips.rst.inc
F: tests/tcg/mips/ F: tests/tcg/mips/
NiosII TCG CPUs
R: Chris Wulff <crwulff@gmail.com>
R: Marek Vasut <marex@denx.de>
S: Orphan
F: target/nios2/
F: hw/nios2/
F: hw/intc/nios2_vic.c
F: disas/nios2.c
F: include/hw/intc/nios2_vic.h
F: configs/devices/nios2-softmmu/default.mak
F: tests/docker/dockerfiles/debian-nios2-cross.d/build-toolchain.sh
F: tests/tcg/nios2/
OpenRISC TCG CPUs OpenRISC TCG CPUs
M: Stafford Horne <shorne@gmail.com> M: Stafford Horne <shorne@gmail.com>
S: Odd Fixes S: Odd Fixes
@ -332,7 +322,7 @@ F: tests/tcg/ppc*/*
RISC-V TCG CPUs RISC-V TCG CPUs
M: Palmer Dabbelt <palmer@dabbelt.com> M: Palmer Dabbelt <palmer@dabbelt.com>
M: Alistair Francis <alistair.francis@wdc.com> M: Alistair Francis <alistair.francis@wdc.com>
M: Bin Meng <bin.meng@windriver.com> M: Bin Meng <bmeng.cn@gmail.com>
R: Weiwei Li <liwei1518@gmail.com> R: Weiwei Li <liwei1518@gmail.com>
R: Daniel Henrique Barboza <dbarboza@ventanamicro.com> R: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
R: Liu Zhiwei <zhiwei_liu@linux.alibaba.com> R: Liu Zhiwei <zhiwei_liu@linux.alibaba.com>
@ -355,6 +345,7 @@ L: qemu-riscv@nongnu.org
S: Supported S: Supported
F: target/riscv/insn_trans/trans_xthead.c.inc F: target/riscv/insn_trans/trans_xthead.c.inc
F: target/riscv/xthead*.decode F: target/riscv/xthead*.decode
F: target/riscv/th_*
F: disas/riscv-xthead* F: disas/riscv-xthead*
RISC-V XVentanaCondOps extension RISC-V XVentanaCondOps extension
@ -545,8 +536,9 @@ Guest CPU Cores (Xen)
--------------------- ---------------------
X86 Xen CPUs X86 Xen CPUs
M: Stefano Stabellini <sstabellini@kernel.org> M: Stefano Stabellini <sstabellini@kernel.org>
M: Anthony Perard <anthony.perard@citrix.com> M: Anthony PERARD <anthony@xenproject.org>
M: Paul Durrant <paul@xen.org> M: Paul Durrant <paul@xen.org>
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
L: xen-devel@lists.xenproject.org L: xen-devel@lists.xenproject.org
S: Supported S: Supported
F: */xen* F: */xen*
@ -1044,6 +1036,7 @@ F: hw/adc/zynq-xadc.c
F: include/hw/misc/zynq_slcr.h F: include/hw/misc/zynq_slcr.h
F: include/hw/adc/zynq-xadc.h F: include/hw/adc/zynq-xadc.h
X: hw/ssi/xilinx_* X: hw/ssi/xilinx_*
F: docs/system/arm/xlnx-zynq.rst
Xilinx ZynqMP and Versal Xilinx ZynqMP and Versal
M: Alistair Francis <alistair@alistair23.me> M: Alistair Francis <alistair@alistair23.me>
@ -1128,6 +1121,7 @@ M: Inès Varhol <ines.varhol@telecom-paris.fr>
L: qemu-arm@nongnu.org L: qemu-arm@nongnu.org
S: Maintained S: Maintained
F: hw/arm/stm32l4x5_soc.c F: hw/arm/stm32l4x5_soc.c
F: hw/char/stm32l4x5_usart.c
F: hw/misc/stm32l4x5_exti.c F: hw/misc/stm32l4x5_exti.c
F: hw/misc/stm32l4x5_syscfg.c F: hw/misc/stm32l4x5_syscfg.c
F: hw/misc/stm32l4x5_rcc.c F: hw/misc/stm32l4x5_rcc.c
@ -1168,6 +1162,9 @@ F: docs/system/arm/emcraft-sf2.rst
ASPEED BMCs ASPEED BMCs
M: Cédric Le Goater <clg@kaod.org> M: Cédric Le Goater <clg@kaod.org>
M: Peter Maydell <peter.maydell@linaro.org> M: Peter Maydell <peter.maydell@linaro.org>
R: Steven Lee <steven_lee@aspeedtech.com>
R: Troy Lee <leetroy@gmail.com>
R: Jamin Lin <jamin_lin@aspeedtech.com>
R: Andrew Jeffery <andrew@codeconstruct.com.au> R: Andrew Jeffery <andrew@codeconstruct.com.au>
R: Joel Stanley <joel@jms.id.au> R: Joel Stanley <joel@jms.id.au>
L: qemu-arm@nongnu.org L: qemu-arm@nongnu.org
@ -1246,6 +1243,7 @@ LoongArch Machines
------------------ ------------------
Virt Virt
M: Song Gao <gaosong@loongson.cn> M: Song Gao <gaosong@loongson.cn>
R: Jiaxun Yang <jiaxun.yang@flygoat.com>
S: Maintained S: Maintained
F: docs/system/loongarch/virt.rst F: docs/system/loongarch/virt.rst
F: configs/targets/loongarch64-softmmu.mak F: configs/targets/loongarch64-softmmu.mak
@ -1253,7 +1251,9 @@ F: configs/devices/loongarch64-softmmu/default.mak
F: hw/loongarch/ F: hw/loongarch/
F: include/hw/loongarch/virt.h F: include/hw/loongarch/virt.h
F: include/hw/intc/loongarch_*.h F: include/hw/intc/loongarch_*.h
F: include/hw/intc/loongson_ipi_common.h
F: hw/intc/loongarch_*.c F: hw/intc/loongarch_*.c
F: hw/intc/loongson_ipi_common.c
F: include/hw/pci-host/ls7a.h F: include/hw/pci-host/ls7a.h
F: hw/rtc/ls7a_rtc.c F: hw/rtc/ls7a_rtc.c
F: gdb-xml/loongarch*.xml F: gdb-xml/loongarch*.xml
@ -1346,7 +1346,7 @@ F: include/hw/mips/
Jazz Jazz
M: Hervé Poussineau <hpoussin@reactos.org> M: Hervé Poussineau <hpoussin@reactos.org>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> R: Aleksandar Rikalo <arikalo@gmail.com>
S: Maintained S: Maintained
F: hw/mips/jazz.c F: hw/mips/jazz.c
F: hw/display/g364fb.c F: hw/display/g364fb.c
@ -1368,7 +1368,7 @@ F: tests/avocado/linux_ssh_mips_malta.py
F: tests/avocado/machine_mips_malta.py F: tests/avocado/machine_mips_malta.py
Mipssim Mipssim
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> R: Aleksandar Rikalo <arikalo@gmail.com>
S: Orphan S: Orphan
F: hw/mips/mipssim.c F: hw/mips/mipssim.c
F: hw/net/mipsnet.c F: hw/net/mipsnet.c
@ -1387,16 +1387,20 @@ Loongson-3 virtual platforms
M: Huacai Chen <chenhuacai@kernel.org> M: Huacai Chen <chenhuacai@kernel.org>
R: Jiaxun Yang <jiaxun.yang@flygoat.com> R: Jiaxun Yang <jiaxun.yang@flygoat.com>
S: Maintained S: Maintained
F: hw/intc/loongson_ipi_common.c
F: hw/intc/loongson_ipi.c
F: hw/intc/loongson_liointc.c F: hw/intc/loongson_liointc.c
F: hw/mips/loongson3_bootp.c F: hw/mips/loongson3_bootp.c
F: hw/mips/loongson3_bootp.h F: hw/mips/loongson3_bootp.h
F: hw/mips/loongson3_virt.c F: hw/mips/loongson3_virt.c
F: include/hw/intc/loongson_ipi_common.h
F: include/hw/intc/loongson_ipi.h
F: include/hw/intc/loongson_liointc.h F: include/hw/intc/loongson_liointc.h
F: tests/avocado/machine_mips_loongson3v.py F: tests/avocado/machine_mips_loongson3v.py
Boston Boston
M: Paul Burton <paulburton@kernel.org> M: Paul Burton <paulburton@kernel.org>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> R: Aleksandar Rikalo <arikalo@gmail.com>
S: Odd Fixes S: Odd Fixes
F: hw/core/loader-fit.c F: hw/core/loader-fit.c
F: hw/mips/boston.c F: hw/mips/boston.c
@ -1614,7 +1618,7 @@ F: include/hw/riscv/opentitan.h
F: include/hw/*/ibex_*.h F: include/hw/*/ibex_*.h
Microchip PolarFire SoC Icicle Kit Microchip PolarFire SoC Icicle Kit
M: Bin Meng <bin.meng@windriver.com> M: Bin Meng <bmeng.cn@gmail.com>
L: qemu-riscv@nongnu.org L: qemu-riscv@nongnu.org
S: Supported S: Supported
F: docs/system/riscv/microchip-icicle-kit.rst F: docs/system/riscv/microchip-icicle-kit.rst
@ -1641,7 +1645,7 @@ F: include/hw/char/shakti_uart.h
SiFive Machines SiFive Machines
M: Alistair Francis <Alistair.Francis@wdc.com> M: Alistair Francis <Alistair.Francis@wdc.com>
M: Bin Meng <bin.meng@windriver.com> M: Bin Meng <bmeng.cn@gmail.com>
M: Palmer Dabbelt <palmer@dabbelt.com> M: Palmer Dabbelt <palmer@dabbelt.com>
L: qemu-riscv@nongnu.org L: qemu-riscv@nongnu.org
S: Supported S: Supported
@ -1727,7 +1731,6 @@ S: Maintained
F: hw/sparc/leon3.c F: hw/sparc/leon3.c
F: hw/*/grlib* F: hw/*/grlib*
F: include/hw/*/grlib* F: include/hw/*/grlib*
F: tests/avocado/machine_sparc_leon3.py
S390 Machines S390 Machines
------------- -------------
@ -1879,6 +1882,7 @@ M: Eduardo Habkost <eduardo@habkost.net>
M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
R: Philippe Mathieu-Daudé <philmd@linaro.org> R: Philippe Mathieu-Daudé <philmd@linaro.org>
R: Yanan Wang <wangyanan55@huawei.com> R: Yanan Wang <wangyanan55@huawei.com>
R: Zhao Liu <zhao1.liu@intel.com>
S: Supported S: Supported
F: hw/core/cpu-common.c F: hw/core/cpu-common.c
F: hw/core/cpu-sysemu.c F: hw/core/cpu-sysemu.c
@ -2137,7 +2141,7 @@ F: hw/ssi/xilinx_*
SD (Secure Card) SD (Secure Card)
M: Philippe Mathieu-Daudé <philmd@linaro.org> M: Philippe Mathieu-Daudé <philmd@linaro.org>
M: Bin Meng <bin.meng@windriver.com> M: Bin Meng <bmeng.cn@gmail.com>
L: qemu-block@nongnu.org L: qemu-block@nongnu.org
S: Odd Fixes S: Odd Fixes
F: include/hw/sd/sd* F: include/hw/sd/sd*
@ -2148,8 +2152,7 @@ F: tests/qtest/fuzz-sdcard-test.c
F: tests/qtest/sdhci-test.c F: tests/qtest/sdhci-test.c
USB USB
M: Gerd Hoffmann <kraxel@redhat.com> S: Orphan
S: Odd Fixes
F: hw/usb/* F: hw/usb/*
F: stubs/usb-dev-stub.c F: stubs/usb-dev-stub.c
F: tests/qtest/usb-*-test.c F: tests/qtest/usb-*-test.c
@ -2158,7 +2161,6 @@ F: include/hw/usb.h
F: include/hw/usb/ F: include/hw/usb/
USB (serial adapter) USB (serial adapter)
R: Gerd Hoffmann <kraxel@redhat.com>
M: Samuel Thibault <samuel.thibault@ens-lyon.org> M: Samuel Thibault <samuel.thibault@ens-lyon.org>
S: Maintained S: Maintained
F: hw/usb/dev-serial.c F: hw/usb/dev-serial.c
@ -2171,6 +2173,7 @@ F: hw/vfio/*
F: include/hw/vfio/ F: include/hw/vfio/
F: docs/igd-assign.txt F: docs/igd-assign.txt
F: docs/devel/migration/vfio.rst F: docs/devel/migration/vfio.rst
F: qapi/vfio.json
vfio-ccw vfio-ccw
M: Eric Farman <farman@linux.ibm.com> M: Eric Farman <farman@linux.ibm.com>
@ -2202,12 +2205,15 @@ M: Zhenzhong Duan <zhenzhong.duan@intel.com>
S: Supported S: Supported
F: backends/iommufd.c F: backends/iommufd.c
F: include/sysemu/iommufd.h F: include/sysemu/iommufd.h
F: backends/host_iommu_device.c
F: include/sysemu/host_iommu_device.h
F: include/qemu/chardev_open.h F: include/qemu/chardev_open.h
F: util/chardev_open.c F: util/chardev_open.c
F: docs/devel/vfio-iommufd.rst F: docs/devel/vfio-iommufd.rst
vhost vhost
M: Michael S. Tsirkin <mst@redhat.com> M: Michael S. Tsirkin <mst@redhat.com>
R: Stefano Garzarella <sgarzare@redhat.com>
S: Supported S: Supported
F: hw/*/*vhost* F: hw/*/*vhost*
F: docs/interop/vhost-user.json F: docs/interop/vhost-user.json
@ -2459,7 +2465,7 @@ S: Maintained
F: hw/net/rocker/ F: hw/net/rocker/
F: qapi/rocker.json F: qapi/rocker.json
F: tests/rocker/ F: tests/rocker/
F: docs/specs/rocker.txt F: docs/specs/rocker.rst
e1000x e1000x
M: Dmitry Fleytman <dmitry.fleytman@gmail.com> M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
@ -2478,7 +2484,7 @@ F: tests/qtest/libqos/e1000e.*
igb igb
M: Akihiko Odaki <akihiko.odaki@daynix.com> M: Akihiko Odaki <akihiko.odaki@daynix.com>
R: Sriram Yagnaraman <sriram.yagnaraman@est.tech> R: Sriram Yagnaraman <sriram.yagnaraman@ericsson.com>
S: Maintained S: Maintained
F: docs/system/devices/igb.rst F: docs/system/devices/igb.rst
F: hw/net/igb* F: hw/net/igb*
@ -2498,7 +2504,7 @@ F: hw/net/tulip.c
F: hw/net/tulip.h F: hw/net/tulip.h
pca954x pca954x
M: Patrick Venture <venture@google.com> M: Patrick Leis <venture@google.com>
S: Maintained S: Maintained
F: hw/i2c/i2c_mux_pca954x.c F: hw/i2c/i2c_mux_pca954x.c
F: include/hw/i2c/i2c_mux_pca954x.h F: include/hw/i2c/i2c_mux_pca954x.h
@ -2583,8 +2589,7 @@ F: hw/display/ramfb*.c
F: include/hw/display/ramfb.h F: include/hw/display/ramfb.h
virtio-gpu virtio-gpu
M: Gerd Hoffmann <kraxel@redhat.com> S: Orphan
S: Odd Fixes
F: hw/display/virtio-gpu* F: hw/display/virtio-gpu*
F: hw/display/virtio-vga.* F: hw/display/virtio-vga.*
F: include/hw/virtio/virtio-gpu.h F: include/hw/virtio/virtio-gpu.h
@ -2606,7 +2611,6 @@ F: include/hw/virtio/virtio-blk-common.h
vhost-user-gpu vhost-user-gpu
M: Marc-André Lureau <marcandre.lureau@redhat.com> M: Marc-André Lureau <marcandre.lureau@redhat.com>
R: Gerd Hoffmann <kraxel@redhat.com>
S: Maintained S: Maintained
F: docs/interop/vhost-user-gpu.rst F: docs/interop/vhost-user-gpu.rst
F: contrib/vhost-user-gpu F: contrib/vhost-user-gpu
@ -2877,7 +2881,6 @@ F: util/aio-*.h
F: util/defer-call.c F: util/defer-call.c
F: util/fdmon-*.c F: util/fdmon-*.c
F: block/io.c F: block/io.c
F: migration/block*
F: include/block/aio.h F: include/block/aio.h
F: include/block/aio-wait.h F: include/block/aio-wait.h
F: include/qemu/defer-call.h F: include/qemu/defer-call.h
@ -3065,8 +3068,7 @@ F: stubs/memory_device.c
F: docs/nvdimm.txt F: docs/nvdimm.txt
SPICE SPICE
M: Gerd Hoffmann <kraxel@redhat.com> S: Orphan
S: Odd Fixes
F: include/ui/qemu-spice.h F: include/ui/qemu-spice.h
F: include/ui/spice-display.h F: include/ui/spice-display.h
F: ui/spice-*.c F: ui/spice-*.c
@ -3076,7 +3078,6 @@ F: qapi/ui.json
F: docs/spice-port-fqdn.txt F: docs/spice-port-fqdn.txt
Graphics Graphics
M: Gerd Hoffmann <kraxel@redhat.com>
M: Marc-André Lureau <marcandre.lureau@redhat.com> M: Marc-André Lureau <marcandre.lureau@redhat.com>
S: Odd Fixes S: Odd Fixes
F: ui/ F: ui/
@ -3223,6 +3224,7 @@ M: Eric Blake <eblake@redhat.com>
M: Markus Armbruster <armbru@redhat.com> M: Markus Armbruster <armbru@redhat.com>
S: Supported S: Supported
F: qapi/*.json F: qapi/*.json
F: qga/qapi-schema.json
T: git https://repo.or.cz/qemu/armbru.git qapi-next T: git https://repo.or.cz/qemu/armbru.git qapi-next
QObject QObject
@ -3321,6 +3323,7 @@ F: tests/qtest/
F: docs/devel/qgraph.rst F: docs/devel/qgraph.rst
F: docs/devel/qtest.rst F: docs/devel/qtest.rst
X: tests/qtest/bios-tables-test* X: tests/qtest/bios-tables-test*
X: tests/qtest/migration-*
Device Fuzzing Device Fuzzing
M: Alexander Bulekov <alxndr@bu.edu> M: Alexander Bulekov <alxndr@bu.edu>
@ -3402,6 +3405,12 @@ F: tests/qtest/*tpm*
F: docs/specs/tpm.rst F: docs/specs/tpm.rst
T: git https://github.com/stefanberger/qemu-tpm.git tpm-next T: git https://github.com/stefanberger/qemu-tpm.git tpm-next
SPDM
M: Alistair Francis <alistair.francis@wdc.com>
S: Maintained
F: backends/spdm-socket.c
F: include/sysemu/spdm-socket.h
Checkpatch Checkpatch
S: Odd Fixes S: Odd Fixes
F: scripts/checkpatch.pl F: scripts/checkpatch.pl
@ -3417,7 +3426,7 @@ F: include/qemu/userfaultfd.h
F: migration/ F: migration/
F: scripts/vmstate-static-checker.py F: scripts/vmstate-static-checker.py
F: tests/vmstate-static-checker-data/ F: tests/vmstate-static-checker-data/
F: tests/qtest/migration-test.c F: tests/qtest/migration-*
F: docs/devel/migration/ F: docs/devel/migration/
F: qapi/migration.json F: qapi/migration.json
F: tests/migration/ F: tests/migration/
@ -3444,6 +3453,7 @@ Detached LUKS header
M: Hyman Huang <yong.huang@smartx.com> M: Hyman Huang <yong.huang@smartx.com>
S: Maintained S: Maintained
F: tests/qemu-iotests/tests/luks-detached-header F: tests/qemu-iotests/tests/luks-detached-header
F: docs/devel/luks-detached-header.rst
D-Bus D-Bus
M: Marc-André Lureau <marcandre.lureau@redhat.com> M: Marc-André Lureau <marcandre.lureau@redhat.com>
@ -3477,7 +3487,7 @@ F: qapi/crypto.json
F: tests/unit/test-crypto-* F: tests/unit/test-crypto-*
F: tests/bench/benchmark-crypto-* F: tests/bench/benchmark-crypto-*
F: tests/unit/crypto-tls-* F: tests/unit/crypto-tls-*
F: tests/unit/pkix_asn1_tab.c F: tests/unit/pkix_asn1_tab.c.inc
F: qemu.sasl F: qemu.sasl
Coroutines Coroutines
@ -3661,6 +3671,7 @@ F: tests/uefi-test-tools/
VT-d Emulation VT-d Emulation
M: Michael S. Tsirkin <mst@redhat.com> M: Michael S. Tsirkin <mst@redhat.com>
R: Jason Wang <jasowang@redhat.com> R: Jason Wang <jasowang@redhat.com>
R: Yi Liu <yi.l.liu@intel.com>
S: Supported S: Supported
F: hw/i386/intel_iommu.c F: hw/i386/intel_iommu.c
F: hw/i386/intel_iommu_internal.h F: hw/i386/intel_iommu_internal.h
@ -3742,7 +3753,7 @@ R: Pierrick Bouvier <pierrick.bouvier@linaro.org>
S: Maintained S: Maintained
F: docs/devel/tcg-plugins.rst F: docs/devel/tcg-plugins.rst
F: plugins/ F: plugins/
F: tests/plugin/ F: tests/tcg/plugins/
F: tests/avocado/tcg_plugins.py F: tests/avocado/tcg_plugins.py
F: contrib/plugins/ F: contrib/plugins/
@ -3773,7 +3784,7 @@ M: Philippe Mathieu-Daudé <philmd@linaro.org>
R: Aurelien Jarno <aurelien@aurel32.net> R: Aurelien Jarno <aurelien@aurel32.net>
R: Huacai Chen <chenhuacai@kernel.org> R: Huacai Chen <chenhuacai@kernel.org>
R: Jiaxun Yang <jiaxun.yang@flygoat.com> R: Jiaxun Yang <jiaxun.yang@flygoat.com>
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> R: Aleksandar Rikalo <arikalo@gmail.com>
S: Odd Fixes S: Odd Fixes
F: tcg/mips/ F: tcg/mips/
@ -3818,7 +3829,7 @@ F: block/vmdk.c
RBD RBD
M: Ilya Dryomov <idryomov@gmail.com> M: Ilya Dryomov <idryomov@gmail.com>
R: Peter Lieven <pl@kamp.de> R: Peter Lieven <pl@dlhnet.de>
L: qemu-block@nongnu.org L: qemu-block@nongnu.org
S: Supported S: Supported
F: block/rbd.c F: block/rbd.c
@ -3844,7 +3855,7 @@ F: block/blkio.c
iSCSI iSCSI
M: Ronnie Sahlberg <ronniesahlberg@gmail.com> M: Ronnie Sahlberg <ronniesahlberg@gmail.com>
M: Paolo Bonzini <pbonzini@redhat.com> M: Paolo Bonzini <pbonzini@redhat.com>
M: Peter Lieven <pl@kamp.de> M: Peter Lieven <pl@dlhnet.de>
L: qemu-block@nongnu.org L: qemu-block@nongnu.org
S: Odd Fixes S: Odd Fixes
F: block/iscsi.c F: block/iscsi.c
@ -3860,14 +3871,14 @@ F: nbd/
F: include/block/nbd* F: include/block/nbd*
F: qemu-nbd.* F: qemu-nbd.*
F: blockdev-nbd.c F: blockdev-nbd.c
F: docs/interop/nbd.txt F: docs/interop/nbd.rst
F: docs/tools/qemu-nbd.rst F: docs/tools/qemu-nbd.rst
F: tests/qemu-iotests/tests/*nbd* F: tests/qemu-iotests/tests/*nbd*
T: git https://repo.or.cz/qemu/ericb.git nbd T: git https://repo.or.cz/qemu/ericb.git nbd
T: git https://gitlab.com/vsementsov/qemu.git block T: git https://gitlab.com/vsementsov/qemu.git block
NFS NFS
M: Peter Lieven <pl@kamp.de> M: Peter Lieven <pl@dlhnet.de>
L: qemu-block@nongnu.org L: qemu-block@nongnu.org
S: Maintained S: Maintained
F: block/nfs.c F: block/nfs.c
@ -3953,7 +3964,8 @@ L: qemu-block@nongnu.org
S: Supported S: Supported
F: block/parallels.c F: block/parallels.c
F: block/parallels-ext.c F: block/parallels-ext.c
F: docs/interop/parallels.txt F: docs/interop/parallels.rst
F: docs/interop/prl-xml.rst
T: git https://src.openvz.org/scm/~den/qemu.git parallels T: git https://src.openvz.org/scm/~den/qemu.git parallels
qed qed
@ -4057,16 +4069,6 @@ F: block/replication.c
F: tests/unit/test-replication.c F: tests/unit/test-replication.c
F: docs/block-replication.txt F: docs/block-replication.txt
PVRDMA
M: Yuval Shaia <yuval.shaia.ml@gmail.com>
M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
S: Odd Fixes
F: hw/rdma/*
F: hw/rdma/vmw/*
F: docs/pvrdma.txt
F: contrib/rdmacm-mux/*
F: qapi/rdma.json
Semihosting Semihosting
M: Alex Bennée <alex.bennee@linaro.org> M: Alex Bennée <alex.bennee@linaro.org>
S: Maintained S: Maintained
@ -4252,3 +4254,8 @@ Code Coverage Tools
M: Alex Bennée <alex.bennee@linaro.org> M: Alex Bennée <alex.bennee@linaro.org>
S: Odd Fixes S: Odd Fixes
F: scripts/coverage/ F: scripts/coverage/
Machine development tool
M: Maksim Davydov <davydov-max@yandex-team.ru>
S: Supported
F: scripts/compare-machine-types.py

View File

@ -78,7 +78,8 @@ x := $(shell rm -rf meson-private meson-info meson-logs)
endif endif
# 1. ensure config-host.mak is up-to-date # 1. ensure config-host.mak is up-to-date
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/scripts/meson-buildoptions.sh $(SRC_PATH)/VERSION config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/scripts/meson-buildoptions.sh \
$(SRC_PATH)/pythondeps.toml $(SRC_PATH)/VERSION
@echo config-host.mak is out-of-date, running configure @echo config-host.mak is out-of-date, running configure
@if test -f meson-private/coredata.dat; then \ @if test -f meson-private/coredata.dat; then \
./config.status --skip-meson; \ ./config.status --skip-meson; \

View File

@ -82,7 +82,7 @@ guidelines set out in the `style section
the Developers Guide. the Developers Guide.
Additional information on submitting patches can be found online via Additional information on submitting patches can be found online via
the QEMU website the QEMU website:
* `<https://wiki.qemu.org/Contribute/SubmitAPatch>`_ * `<https://wiki.qemu.org/Contribute/SubmitAPatch>`_
* `<https://wiki.qemu.org/Contribute/TrivialPatches>`_ * `<https://wiki.qemu.org/Contribute/TrivialPatches>`_
@ -102,7 +102,7 @@ requires a working 'git send-email' setup, and by default doesn't
automate everything, so you may want to go through the above steps automate everything, so you may want to go through the above steps
manually for once. manually for once.
For installation instructions, please go to For installation instructions, please go to:
* `<https://github.com/stefanha/git-publish>`_ * `<https://github.com/stefanha/git-publish>`_
@ -159,7 +159,7 @@ Contact
======= =======
The QEMU community can be contacted in a number of ways, with the two The QEMU community can be contacted in a number of ways, with the two
main methods being email and IRC main methods being email and IRC:
* `<mailto:qemu-devel@nongnu.org>`_ * `<mailto:qemu-devel@nongnu.org>`_
* `<https://lists.nongnu.org/mailman/listinfo/qemu-devel>`_ * `<https://lists.nongnu.org/mailman/listinfo/qemu-devel>`_

View File

@ -1 +1 @@
9.0.2 9.1.1

View File

@ -68,9 +68,6 @@ void dummy_start_vcpu_thread(CPUState *cpu)
{ {
char thread_name[VCPU_THREAD_NAME_SIZE]; char thread_name[VCPU_THREAD_NAME_SIZE];
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY", snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY",
cpu->cpu_index); cpu->cpu_index);
qemu_thread_create(cpu->thread, thread_name, dummy_cpu_thread_fn, cpu, qemu_thread_create(cpu->thread, thread_name, dummy_cpu_thread_fn, cpu,

View File

@ -52,7 +52,7 @@
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/gdbstub.h" #include "gdbstub/enums.h"
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
#include "sysemu/hvf.h" #include "sysemu/hvf.h"
#include "sysemu/hvf_int.h" #include "sysemu/hvf_int.h"
@ -204,15 +204,15 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
{ {
if (!cpu->vcpu_dirty) { if (!cpu->accel->dirty) {
hvf_get_registers(cpu); hvf_get_registers(cpu);
cpu->vcpu_dirty = true; cpu->accel->dirty = true;
} }
} }
static void hvf_cpu_synchronize_state(CPUState *cpu) static void hvf_cpu_synchronize_state(CPUState *cpu)
{ {
if (!cpu->vcpu_dirty) { if (!cpu->accel->dirty) {
run_on_cpu(cpu, do_hvf_cpu_synchronize_state, RUN_ON_CPU_NULL); run_on_cpu(cpu, do_hvf_cpu_synchronize_state, RUN_ON_CPU_NULL);
} }
} }
@ -221,7 +221,7 @@ static void do_hvf_cpu_synchronize_set_dirty(CPUState *cpu,
run_on_cpu_data arg) run_on_cpu_data arg)
{ {
/* QEMU state is the reference, push it to HVF now and on next entry */ /* QEMU state is the reference, push it to HVF now and on next entry */
cpu->vcpu_dirty = true; cpu->accel->dirty = true;
} }
static void hvf_cpu_synchronize_post_reset(CPUState *cpu) static void hvf_cpu_synchronize_post_reset(CPUState *cpu)
@ -400,9 +400,9 @@ static int hvf_init_vcpu(CPUState *cpu)
r = hv_vcpu_create(&cpu->accel->fd, r = hv_vcpu_create(&cpu->accel->fd,
(hv_vcpu_exit_t **)&cpu->accel->exit, NULL); (hv_vcpu_exit_t **)&cpu->accel->exit, NULL);
#else #else
r = hv_vcpu_create((hv_vcpuid_t *)&cpu->accel->fd, HV_VCPU_DEFAULT); r = hv_vcpu_create(&cpu->accel->fd, HV_VCPU_DEFAULT);
#endif #endif
cpu->vcpu_dirty = 1; cpu->accel->dirty = true;
assert_hvf_ok(r); assert_hvf_ok(r);
cpu->accel->guest_debug_enabled = false; cpu->accel->guest_debug_enabled = false;
@ -463,10 +463,6 @@ static void hvf_start_vcpu_thread(CPUState *cpu)
*/ */
assert(hvf_enabled()); assert(hvf_enabled());
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF", snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF",
cpu->cpu_index); cpu->cpu_index);
qemu_thread_create(cpu->thread, thread_name, hvf_cpu_thread_fn, qemu_thread_create(cpu->thread, thread_name, hvf_cpu_thread_fn,

View File

@ -13,40 +13,30 @@
#include "sysemu/hvf.h" #include "sysemu/hvf.h"
#include "sysemu/hvf_int.h" #include "sysemu/hvf_int.h"
void assert_hvf_ok(hv_return_t ret) const char *hvf_return_string(hv_return_t ret)
{
switch (ret) {
case HV_SUCCESS: return "HV_SUCCESS";
case HV_ERROR: return "HV_ERROR";
case HV_BUSY: return "HV_BUSY";
case HV_BAD_ARGUMENT: return "HV_BAD_ARGUMENT";
case HV_NO_RESOURCES: return "HV_NO_RESOURCES";
case HV_NO_DEVICE: return "HV_NO_DEVICE";
case HV_UNSUPPORTED: return "HV_UNSUPPORTED";
case HV_DENIED: return "HV_DENIED";
default: return "[unknown hv_return value]";
}
}
void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line,
const char *exp)
{ {
if (ret == HV_SUCCESS) { if (ret == HV_SUCCESS) {
return; return;
} }
switch (ret) { error_report("Error: %s = %s (0x%x, at %s:%u)",
case HV_ERROR: exp, hvf_return_string(ret), ret, file, line);
error_report("Error: HV_ERROR");
break;
case HV_BUSY:
error_report("Error: HV_BUSY");
break;
case HV_BAD_ARGUMENT:
error_report("Error: HV_BAD_ARGUMENT");
break;
case HV_NO_RESOURCES:
error_report("Error: HV_NO_RESOURCES");
break;
case HV_NO_DEVICE:
error_report("Error: HV_NO_DEVICE");
break;
case HV_UNSUPPORTED:
error_report("Error: HV_UNSUPPORTED");
break;
#if defined(MAC_OS_VERSION_11_0) && \
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
case HV_DENIED:
error_report("Error: HV_DENIED");
break;
#endif
default:
error_report("Unknown Error");
}
abort(); abort();
} }

View File

@ -78,9 +78,6 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
{ {
char thread_name[VCPU_THREAD_NAME_SIZE]; char thread_name[VCPU_THREAD_NAME_SIZE];
cpu->thread = g_malloc0(sizeof(QemuThread));
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM", snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
cpu->cpu_index); cpu->cpu_index);
qemu_thread_create(cpu->thread, thread_name, kvm_vcpu_thread_fn, qemu_thread_create(cpu->thread, thread_name, kvm_vcpu_thread_fn,
@ -94,10 +91,10 @@ static bool kvm_vcpu_thread_is_idle(CPUState *cpu)
static bool kvm_cpus_are_resettable(void) static bool kvm_cpus_are_resettable(void)
{ {
return !kvm_enabled() || kvm_cpu_check_are_resettable(); return !kvm_enabled() || !kvm_state->guest_state_protected;
} }
#ifdef KVM_CAP_SET_GUEST_DEBUG #ifdef TARGET_KVM_HAVE_GUEST_DEBUG
static int kvm_update_guest_debug_ops(CPUState *cpu) static int kvm_update_guest_debug_ops(CPUState *cpu)
{ {
return kvm_update_guest_debug(cpu, 0); return kvm_update_guest_debug(cpu, 0);
@ -116,7 +113,7 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
ops->synchronize_state = kvm_cpu_synchronize_state; ops->synchronize_state = kvm_cpu_synchronize_state;
ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm; ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;
#ifdef KVM_CAP_SET_GUEST_DEBUG #ifdef TARGET_KVM_HAVE_GUEST_DEBUG
ops->update_guest_debug = kvm_update_guest_debug_ops; ops->update_guest_debug = kvm_update_guest_debug_ops;
ops->supports_guest_debug = kvm_supports_guest_debug; ops->supports_guest_debug = kvm_supports_guest_debug;
ops->insert_breakpoint = kvm_insert_breakpoint; ops->insert_breakpoint = kvm_insert_breakpoint;

View File

@ -27,7 +27,7 @@
#include "hw/pci/msi.h" #include "hw/pci/msi.h"
#include "hw/pci/msix.h" #include "hw/pci/msix.h"
#include "hw/s390x/adapter.h" #include "hw/s390x/adapter.h"
#include "exec/gdbstub.h" #include "gdbstub/enums.h"
#include "sysemu/kvm_int.h" #include "sysemu/kvm_int.h"
#include "sysemu/runstate.h" #include "sysemu/runstate.h"
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
@ -97,6 +97,8 @@ bool kvm_msi_use_devid;
static bool kvm_has_guest_debug; static bool kvm_has_guest_debug;
static int kvm_sstep_flags; static int kvm_sstep_flags;
static bool kvm_immediate_exit; static bool kvm_immediate_exit;
static uint64_t kvm_supported_memory_attributes;
static bool kvm_guest_memfd_supported;
static hwaddr kvm_max_slot_size = ~0; static hwaddr kvm_max_slot_size = ~0;
static const KVMCapabilityInfo kvm_required_capabilites[] = { static const KVMCapabilityInfo kvm_required_capabilites[] = {
@ -288,35 +290,130 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot, bool new) static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot, bool new)
{ {
KVMState *s = kvm_state; KVMState *s = kvm_state;
struct kvm_userspace_memory_region mem; struct kvm_userspace_memory_region2 mem;
int ret; int ret;
mem.slot = slot->slot | (kml->as_id << 16); mem.slot = slot->slot | (kml->as_id << 16);
mem.guest_phys_addr = slot->start_addr; mem.guest_phys_addr = slot->start_addr;
mem.userspace_addr = (unsigned long)slot->ram; mem.userspace_addr = (unsigned long)slot->ram;
mem.flags = slot->flags; mem.flags = slot->flags;
mem.guest_memfd = slot->guest_memfd;
mem.guest_memfd_offset = slot->guest_memfd_offset;
if (slot->memory_size && !new && (mem.flags ^ slot->old_flags) & KVM_MEM_READONLY) { if (slot->memory_size && !new && (mem.flags ^ slot->old_flags) & KVM_MEM_READONLY) {
/* Set the slot size to 0 before setting the slot to the desired /* Set the slot size to 0 before setting the slot to the desired
* value. This is needed based on KVM commit 75d61fbc. */ * value. This is needed based on KVM commit 75d61fbc. */
mem.memory_size = 0; mem.memory_size = 0;
if (kvm_guest_memfd_supported) {
ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION2, &mem);
} else {
ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
}
if (ret < 0) { if (ret < 0) {
goto err; goto err;
} }
} }
mem.memory_size = slot->memory_size; mem.memory_size = slot->memory_size;
if (kvm_guest_memfd_supported) {
ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION2, &mem);
} else {
ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem); ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
}
slot->old_flags = mem.flags; slot->old_flags = mem.flags;
err: err:
trace_kvm_set_user_memory(mem.slot, mem.flags, mem.guest_phys_addr, trace_kvm_set_user_memory(mem.slot >> 16, (uint16_t)mem.slot, mem.flags,
mem.memory_size, mem.userspace_addr, ret); mem.guest_phys_addr, mem.memory_size,
mem.userspace_addr, mem.guest_memfd,
mem.guest_memfd_offset, ret);
if (ret < 0) { if (ret < 0) {
if (kvm_guest_memfd_supported) {
error_report("%s: KVM_SET_USER_MEMORY_REGION2 failed, slot=%d,"
" start=0x%" PRIx64 ", size=0x%" PRIx64 ","
" flags=0x%" PRIx32 ", guest_memfd=%" PRId32 ","
" guest_memfd_offset=0x%" PRIx64 ": %s",
__func__, mem.slot, slot->start_addr,
(uint64_t)mem.memory_size, mem.flags,
mem.guest_memfd, (uint64_t)mem.guest_memfd_offset,
strerror(errno));
} else {
error_report("%s: KVM_SET_USER_MEMORY_REGION failed, slot=%d," error_report("%s: KVM_SET_USER_MEMORY_REGION failed, slot=%d,"
" start=0x%" PRIx64 ", size=0x%" PRIx64 ": %s", " start=0x%" PRIx64 ", size=0x%" PRIx64 ": %s",
__func__, mem.slot, slot->start_addr, __func__, mem.slot, slot->start_addr,
(uint64_t)mem.memory_size, strerror(errno)); (uint64_t)mem.memory_size, strerror(errno));
} }
}
return ret;
}
void kvm_park_vcpu(CPUState *cpu)
{
struct KVMParkedVcpu *vcpu;
trace_kvm_park_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu));
vcpu = g_malloc0(sizeof(*vcpu));
vcpu->vcpu_id = kvm_arch_vcpu_id(cpu);
vcpu->kvm_fd = cpu->kvm_fd;
QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node);
}
int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id)
{
struct KVMParkedVcpu *cpu;
int kvm_fd = -ENOENT;
QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) {
if (cpu->vcpu_id == vcpu_id) {
QLIST_REMOVE(cpu, node);
kvm_fd = cpu->kvm_fd;
g_free(cpu);
break;
}
}
trace_kvm_unpark_vcpu(vcpu_id, kvm_fd > 0 ? "unparked" : "!found parked");
return kvm_fd;
}
int kvm_create_vcpu(CPUState *cpu)
{
unsigned long vcpu_id = kvm_arch_vcpu_id(cpu);
KVMState *s = kvm_state;
int kvm_fd;
/* check if the KVM vCPU already exist but is parked */
kvm_fd = kvm_unpark_vcpu(s, vcpu_id);
if (kvm_fd < 0) {
/* vCPU not parked: create a new KVM vCPU */
kvm_fd = kvm_vm_ioctl(s, KVM_CREATE_VCPU, vcpu_id);
if (kvm_fd < 0) {
error_report("KVM_CREATE_VCPU IOCTL failed for vCPU %lu", vcpu_id);
return kvm_fd;
}
}
cpu->kvm_fd = kvm_fd;
cpu->kvm_state = s;
cpu->vcpu_dirty = true;
cpu->dirty_pages = 0;
cpu->throttle_us_per_full = 0;
trace_kvm_create_vcpu(cpu->cpu_index, vcpu_id, kvm_fd);
return 0;
}
int kvm_create_and_park_vcpu(CPUState *cpu)
{
int ret = 0;
ret = kvm_create_vcpu(cpu);
if (!ret) {
kvm_park_vcpu(cpu);
}
return ret; return ret;
} }
@ -324,10 +421,9 @@ static int do_kvm_destroy_vcpu(CPUState *cpu)
{ {
KVMState *s = kvm_state; KVMState *s = kvm_state;
long mmap_size; long mmap_size;
struct KVMParkedVcpu *vcpu = NULL;
int ret = 0; int ret = 0;
trace_kvm_destroy_vcpu(); trace_kvm_destroy_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu));
ret = kvm_arch_destroy_vcpu(cpu); ret = kvm_arch_destroy_vcpu(cpu);
if (ret < 0) { if (ret < 0) {
@ -353,10 +449,7 @@ static int do_kvm_destroy_vcpu(CPUState *cpu)
} }
} }
vcpu = g_malloc0(sizeof(*vcpu)); kvm_park_vcpu(cpu);
vcpu->vcpu_id = kvm_arch_vcpu_id(cpu);
vcpu->kvm_fd = cpu->kvm_fd;
QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node);
err: err:
return ret; return ret;
} }
@ -369,24 +462,6 @@ void kvm_destroy_vcpu(CPUState *cpu)
} }
} }
static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id)
{
struct KVMParkedVcpu *cpu;
QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) {
if (cpu->vcpu_id == vcpu_id) {
int kvm_fd;
QLIST_REMOVE(cpu, node);
kvm_fd = cpu->kvm_fd;
g_free(cpu);
return kvm_fd;
}
}
return kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id);
}
int kvm_init_vcpu(CPUState *cpu, Error **errp) int kvm_init_vcpu(CPUState *cpu, Error **errp)
{ {
KVMState *s = kvm_state; KVMState *s = kvm_state;
@ -395,19 +470,14 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu));
ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu)); ret = kvm_create_vcpu(cpu);
if (ret < 0) { if (ret < 0) {
error_setg_errno(errp, -ret, "kvm_init_vcpu: kvm_get_vcpu failed (%lu)", error_setg_errno(errp, -ret,
"kvm_init_vcpu: kvm_create_vcpu failed (%lu)",
kvm_arch_vcpu_id(cpu)); kvm_arch_vcpu_id(cpu));
goto err; goto err;
} }
cpu->kvm_fd = ret;
cpu->kvm_state = s;
cpu->vcpu_dirty = true;
cpu->dirty_pages = 0;
cpu->throttle_us_per_full = 0;
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
if (mmap_size < 0) { if (mmap_size < 0) {
ret = mmap_size; ret = mmap_size;
@ -470,6 +540,10 @@ static int kvm_mem_flags(MemoryRegion *mr)
if (readonly && kvm_readonly_mem_allowed) { if (readonly && kvm_readonly_mem_allowed) {
flags |= KVM_MEM_READONLY; flags |= KVM_MEM_READONLY;
} }
if (memory_region_has_guest_memfd(mr)) {
assert(kvm_guest_memfd_supported);
flags |= KVM_MEM_GUEST_MEMFD;
}
return flags; return flags;
} }
@ -1271,6 +1345,36 @@ void kvm_set_max_memslot_size(hwaddr max_slot_size)
kvm_max_slot_size = max_slot_size; kvm_max_slot_size = max_slot_size;
} }
static int kvm_set_memory_attributes(hwaddr start, uint64_t size, uint64_t attr)
{
struct kvm_memory_attributes attrs;
int r;
assert((attr & kvm_supported_memory_attributes) == attr);
attrs.attributes = attr;
attrs.address = start;
attrs.size = size;
attrs.flags = 0;
r = kvm_vm_ioctl(kvm_state, KVM_SET_MEMORY_ATTRIBUTES, &attrs);
if (r) {
error_report("failed to set memory (0x%" HWADDR_PRIx "+0x%" PRIx64 ") "
"with attr 0x%" PRIx64 " error '%s'",
start, size, attr, strerror(errno));
}
return r;
}
int kvm_set_memory_attributes_private(hwaddr start, uint64_t size)
{
return kvm_set_memory_attributes(start, size, KVM_MEMORY_ATTRIBUTE_PRIVATE);
}
int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size)
{
return kvm_set_memory_attributes(start, size, 0);
}
/* Called with KVMMemoryListener.slots_lock held */ /* Called with KVMMemoryListener.slots_lock held */
static void kvm_set_phys_mem(KVMMemoryListener *kml, static void kvm_set_phys_mem(KVMMemoryListener *kml,
MemoryRegionSection *section, bool add) MemoryRegionSection *section, bool add)
@ -1367,6 +1471,9 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
mem->ram_start_offset = ram_start_offset; mem->ram_start_offset = ram_start_offset;
mem->ram = ram; mem->ram = ram;
mem->flags = kvm_mem_flags(mr); mem->flags = kvm_mem_flags(mr);
mem->guest_memfd = mr->ram_block->guest_memfd;
mem->guest_memfd_offset = (uint8_t*)ram - mr->ram_block->host;
kvm_slot_init_dirty_bitmap(mem); kvm_slot_init_dirty_bitmap(mem);
err = kvm_set_user_memory_region(kml, mem, true); err = kvm_set_user_memory_region(kml, mem, true);
if (err) { if (err) {
@ -1374,6 +1481,16 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
strerror(-err)); strerror(-err));
abort(); abort();
} }
if (memory_region_has_guest_memfd(mr)) {
err = kvm_set_memory_attributes_private(start_addr, slot_size);
if (err) {
error_report("%s: failed to set memory attribute private: %s",
__func__, strerror(-err));
exit(1);
}
}
start_addr += slot_size; start_addr += slot_size;
ram_start_offset += slot_size; ram_start_offset += slot_size;
ram += slot_size; ram += slot_size;
@ -1842,7 +1959,7 @@ void kvm_irqchip_commit_routes(KVMState *s)
assert(ret == 0); assert(ret == 0);
} }
static void kvm_add_routing_entry(KVMState *s, void kvm_add_routing_entry(KVMState *s,
struct kvm_irq_routing_entry *entry) struct kvm_irq_routing_entry *entry)
{ {
struct kvm_irq_routing_entry *new; struct kvm_irq_routing_entry *new;
@ -1940,7 +2057,7 @@ void kvm_irqchip_change_notify(void)
notifier_list_notify(&kvm_irqchip_change_notifiers, NULL); notifier_list_notify(&kvm_irqchip_change_notifiers, NULL);
} }
static int kvm_irqchip_get_virq(KVMState *s) int kvm_irqchip_get_virq(KVMState *s)
{ {
int next_virq; int next_virq;
@ -2098,62 +2215,6 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, EventNotifier *event,
return kvm_vm_ioctl(s, KVM_IRQFD, &irqfd); return kvm_vm_ioctl(s, KVM_IRQFD, &irqfd);
} }
int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
{
struct kvm_irq_routing_entry kroute = {};
int virq;
if (!kvm_gsi_routing_enabled()) {
return -ENOSYS;
}
virq = kvm_irqchip_get_virq(s);
if (virq < 0) {
return virq;
}
kroute.gsi = virq;
kroute.type = KVM_IRQ_ROUTING_S390_ADAPTER;
kroute.flags = 0;
kroute.u.adapter.summary_addr = adapter->summary_addr;
kroute.u.adapter.ind_addr = adapter->ind_addr;
kroute.u.adapter.summary_offset = adapter->summary_offset;
kroute.u.adapter.ind_offset = adapter->ind_offset;
kroute.u.adapter.adapter_id = adapter->adapter_id;
kvm_add_routing_entry(s, &kroute);
return virq;
}
int kvm_irqchip_add_hv_sint_route(KVMState *s, uint32_t vcpu, uint32_t sint)
{
struct kvm_irq_routing_entry kroute = {};
int virq;
if (!kvm_gsi_routing_enabled()) {
return -ENOSYS;
}
if (!kvm_check_extension(s, KVM_CAP_HYPERV_SYNIC)) {
return -ENOSYS;
}
virq = kvm_irqchip_get_virq(s);
if (virq < 0) {
return virq;
}
kroute.gsi = virq;
kroute.type = KVM_IRQ_ROUTING_HV_SINT;
kroute.flags = 0;
kroute.u.hv_sint.vcpu = vcpu;
kroute.u.hv_sint.sint = sint;
kvm_add_routing_entry(s, &kroute);
kvm_irqchip_commit_routes(s);
return virq;
}
#else /* !KVM_CAP_IRQ_ROUTING */ #else /* !KVM_CAP_IRQ_ROUTING */
void kvm_init_irq_routing(KVMState *s) void kvm_init_irq_routing(KVMState *s)
@ -2318,7 +2379,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id)
bool kvm_dirty_ring_enabled(void) bool kvm_dirty_ring_enabled(void)
{ {
return kvm_state->kvm_dirty_ring_size ? true : false; return kvm_state && kvm_state->kvm_dirty_ring_size;
} }
static void query_stats_cb(StatsResultList **result, StatsTarget target, static void query_stats_cb(StatsResultList **result, StatsTarget target,
@ -2366,7 +2427,7 @@ static int kvm_init(MachineState *ms)
s->sigmask_len = 8; s->sigmask_len = 8;
accel_blocker_init(); accel_blocker_init();
#ifdef KVM_CAP_SET_GUEST_DEBUG #ifdef TARGET_KVM_HAVE_GUEST_DEBUG
QTAILQ_INIT(&s->kvm_sw_breakpoints); QTAILQ_INIT(&s->kvm_sw_breakpoints);
#endif #endif
QLIST_INIT(&s->kvm_parked_vcpus); QLIST_INIT(&s->kvm_parked_vcpus);
@ -2392,6 +2453,12 @@ static int kvm_init(MachineState *ms)
goto err; goto err;
} }
kvm_supported_memory_attributes = kvm_check_extension(s, KVM_CAP_MEMORY_ATTRIBUTES);
kvm_guest_memfd_supported =
kvm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
kvm_check_extension(s, KVM_CAP_USER_MEMORY2) &&
(kvm_supported_memory_attributes & KVM_MEMORY_ATTRIBUTE_PRIVATE);
kvm_immediate_exit = kvm_check_extension(s, KVM_CAP_IMMEDIATE_EXIT); kvm_immediate_exit = kvm_check_extension(s, KVM_CAP_IMMEDIATE_EXIT);
s->nr_slots = kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS); s->nr_slots = kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
@ -2550,7 +2617,7 @@ static int kvm_init(MachineState *ms)
kvm_vm_attributes_allowed = kvm_vm_attributes_allowed =
(kvm_check_extension(s, KVM_CAP_VM_ATTRIBUTES) > 0); (kvm_check_extension(s, KVM_CAP_VM_ATTRIBUTES) > 0);
#ifdef KVM_CAP_SET_GUEST_DEBUG #ifdef TARGET_KVM_HAVE_GUEST_DEBUG
kvm_has_guest_debug = kvm_has_guest_debug =
(kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0); (kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0);
#endif #endif
@ -2559,7 +2626,7 @@ static int kvm_init(MachineState *ms)
if (kvm_has_guest_debug) { if (kvm_has_guest_debug) {
kvm_sstep_flags = SSTEP_ENABLE; kvm_sstep_flags = SSTEP_ENABLE;
#if defined KVM_CAP_SET_GUEST_DEBUG2 #if defined TARGET_KVM_HAVE_GUEST_DEBUG
int guest_debug_flags = int guest_debug_flags =
kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG2); kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG2);
@ -2702,14 +2769,9 @@ void kvm_flush_coalesced_mmio_buffer(void)
s->coalesced_flush_in_progress = false; s->coalesced_flush_in_progress = false;
} }
bool kvm_cpu_check_are_resettable(void)
{
return kvm_arch_cpu_check_are_resettable();
}
static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
{ {
if (!cpu->vcpu_dirty) { if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) {
int ret = kvm_arch_get_registers(cpu); int ret = kvm_arch_get_registers(cpu);
if (ret) { if (ret) {
error_report("Failed to get registers: %s", strerror(-ret)); error_report("Failed to get registers: %s", strerror(-ret));
@ -2723,7 +2785,7 @@ static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
void kvm_cpu_synchronize_state(CPUState *cpu) void kvm_cpu_synchronize_state(CPUState *cpu)
{ {
if (!cpu->vcpu_dirty) { if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) {
run_on_cpu(cpu, do_kvm_cpu_synchronize_state, RUN_ON_CPU_NULL); run_on_cpu(cpu, do_kvm_cpu_synchronize_state, RUN_ON_CPU_NULL);
} }
} }
@ -2758,8 +2820,14 @@ static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg)
void kvm_cpu_synchronize_post_init(CPUState *cpu) void kvm_cpu_synchronize_post_init(CPUState *cpu)
{ {
if (!kvm_state->guest_state_protected) {
/*
* This runs before the machine_init_done notifiers, and is the last
* opportunity to synchronize the state of confidential guests.
*/
run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, RUN_ON_CPU_NULL); run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
} }
}
static void do_kvm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg) static void do_kvm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg)
{ {
@ -2826,6 +2894,94 @@ static void kvm_eat_signals(CPUState *cpu)
} while (sigismember(&chkset, SIG_IPI)); } while (sigismember(&chkset, SIG_IPI));
} }
int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private)
{
MemoryRegionSection section;
ram_addr_t offset;
MemoryRegion *mr;
RAMBlock *rb;
void *addr;
int ret = -1;
trace_kvm_convert_memory(start, size, to_private ? "shared_to_private" : "private_to_shared");
if (!QEMU_PTR_IS_ALIGNED(start, qemu_real_host_page_size()) ||
!QEMU_PTR_IS_ALIGNED(size, qemu_real_host_page_size())) {
return -1;
}
if (!size) {
return -1;
}
section = memory_region_find(get_system_memory(), start, size);
mr = section.mr;
if (!mr) {
/*
* Ignore converting non-assigned region to shared.
*
* TDX requires vMMIO region to be shared to inject #VE to guest.
* OVMF issues conservatively MapGPA(shared) on 32bit PCI MMIO region,
* and vIO-APIC 0xFEC00000 4K page.
* OVMF assigns 32bit PCI MMIO region to
* [top of low memory: typically 2GB=0xC000000, 0xFC00000)
*/
if (!to_private) {
return 0;
}
return -1;
}
if (!memory_region_has_guest_memfd(mr)) {
/*
* Because vMMIO region must be shared, guest TD may convert vMMIO
* region to shared explicitly. Don't complain such case. See
* memory_region_type() for checking if the region is MMIO region.
*/
if (!to_private &&
!memory_region_is_ram(mr) &&
!memory_region_is_ram_device(mr) &&
!memory_region_is_rom(mr) &&
!memory_region_is_romd(mr)) {
ret = 0;
} else {
error_report("Convert non guest_memfd backed memory region "
"(0x%"HWADDR_PRIx" ,+ 0x%"HWADDR_PRIx") to %s",
start, size, to_private ? "private" : "shared");
}
goto out_unref;
}
if (to_private) {
ret = kvm_set_memory_attributes_private(start, size);
} else {
ret = kvm_set_memory_attributes_shared(start, size);
}
if (ret) {
goto out_unref;
}
addr = memory_region_get_ram_ptr(mr) + section.offset_within_region;
rb = qemu_ram_block_from_host(addr, false, &offset);
if (to_private) {
if (rb->page_size != qemu_real_host_page_size()) {
/*
* shared memory is backed by hugetlb, which is supposed to be
* pre-allocated and doesn't need to be discarded
*/
goto out_unref;
}
ret = ram_block_discard_range(rb, offset, size);
} else {
ret = ram_block_discard_guest_memfd_range(rb, offset, size);
}
out_unref:
memory_region_unref(mr);
return ret;
}
int kvm_cpu_exec(CPUState *cpu) int kvm_cpu_exec(CPUState *cpu)
{ {
struct kvm_run *run = cpu->kvm_run; struct kvm_run *run = cpu->kvm_run;
@ -2905,6 +3061,7 @@ int kvm_cpu_exec(CPUState *cpu)
ret = EXCP_INTERRUPT; ret = EXCP_INTERRUPT;
break; break;
} }
if (!(run_ret == -EFAULT && run->exit_reason == KVM_EXIT_MEMORY_FAULT)) {
fprintf(stderr, "error: kvm run failed %s\n", fprintf(stderr, "error: kvm run failed %s\n",
strerror(-run_ret)); strerror(-run_ret));
#ifdef TARGET_PPC #ifdef TARGET_PPC
@ -2918,6 +3075,7 @@ int kvm_cpu_exec(CPUState *cpu)
ret = -1; ret = -1;
break; break;
} }
}
trace_kvm_run_exit(cpu->cpu_index, run->exit_reason); trace_kvm_run_exit(cpu->cpu_index, run->exit_reason);
switch (run->exit_reason) { switch (run->exit_reason) {
@ -2999,6 +3157,19 @@ int kvm_cpu_exec(CPUState *cpu)
break; break;
} }
break; break;
case KVM_EXIT_MEMORY_FAULT:
trace_kvm_memory_fault(run->memory_fault.gpa,
run->memory_fault.size,
run->memory_fault.flags);
if (run->memory_fault.flags & ~KVM_MEMORY_EXIT_FLAG_PRIVATE) {
error_report("KVM_EXIT_MEMORY_FAULT: Unknown flag 0x%" PRIx64,
(uint64_t)run->memory_fault.flags);
ret = -1;
break;
}
ret = kvm_convert_memory(run->memory_fault.gpa, run->memory_fault.size,
run->memory_fault.flags & KVM_MEMORY_EXIT_FLAG_PRIVATE);
break;
default: default:
ret = kvm_arch_handle_exit(cpu, run); ret = kvm_arch_handle_exit(cpu, run);
break; break;
@ -3175,7 +3346,7 @@ bool kvm_arm_supports_user_irq(void)
return kvm_check_extension(kvm_state, KVM_CAP_ARM_USER_IRQ); return kvm_check_extension(kvm_state, KVM_CAP_ARM_USER_IRQ);
} }
#ifdef KVM_CAP_SET_GUEST_DEBUG #ifdef TARGET_KVM_HAVE_GUEST_DEBUG
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, vaddr pc) struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, vaddr pc)
{ {
struct kvm_sw_breakpoint *bp; struct kvm_sw_breakpoint *bp;
@ -3335,7 +3506,7 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
} }
} }
#endif /* !KVM_CAP_SET_GUEST_DEBUG */ #endif /* !TARGET_KVM_HAVE_GUEST_DEBUG */
static int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) static int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset)
{ {
@ -3636,6 +3807,21 @@ static void kvm_set_device(Object *obj,
s->device = g_strdup(value); s->device = g_strdup(value);
} }
static void kvm_set_kvm_rapl(Object *obj, bool value, Error **errp)
{
KVMState *s = KVM_STATE(obj);
s->msr_energy.enable = value;
}
static void kvm_set_kvm_rapl_socket_path(Object *obj,
const char *str,
Error **errp)
{
KVMState *s = KVM_STATE(obj);
g_free(s->msr_energy.socket_path);
s->msr_energy.socket_path = g_strdup(str);
}
static void kvm_accel_instance_init(Object *obj) static void kvm_accel_instance_init(Object *obj)
{ {
KVMState *s = KVM_STATE(obj); KVMState *s = KVM_STATE(obj);
@ -3655,6 +3841,7 @@ static void kvm_accel_instance_init(Object *obj)
s->xen_gnttab_max_frames = 64; s->xen_gnttab_max_frames = 64;
s->xen_evtchn_max_pirq = 256; s->xen_evtchn_max_pirq = 256;
s->device = NULL; s->device = NULL;
s->msr_energy.enable = false;
} }
/** /**
@ -3699,6 +3886,17 @@ static void kvm_accel_class_init(ObjectClass *oc, void *data)
object_class_property_set_description(oc, "device", object_class_property_set_description(oc, "device",
"Path to the device node to use (default: /dev/kvm)"); "Path to the device node to use (default: /dev/kvm)");
object_class_property_add_bool(oc, "rapl",
NULL,
kvm_set_kvm_rapl);
object_class_property_set_description(oc, "rapl",
"Allow energy related MSRs for RAPL interface in Guest");
object_class_property_add_str(oc, "rapl-helper-socket", NULL,
kvm_set_kvm_rapl_socket_path);
object_class_property_set_description(oc, "rapl-helper-socket",
"Socket Path for comminucating with the Virtual MSR helper daemon");
kvm_arch_accel_class_init(oc); kvm_arch_accel_class_init(oc);
} }
@ -3769,7 +3967,7 @@ static StatsList *add_kvmstat_entry(struct kvm_stats_desc *pdesc,
/* Alloc and populate data list */ /* Alloc and populate data list */
stats = g_new0(Stats, 1); stats = g_new0(Stats, 1);
stats->name = g_strdup(pdesc->name); stats->name = g_strdup(pdesc->name);
stats->value = g_new0(StatsValue, 1);; stats->value = g_new0(StatsValue, 1);
if ((pdesc->flags & KVM_STATS_UNIT_MASK) == KVM_STATS_UNIT_BOOLEAN) { if ((pdesc->flags & KVM_STATS_UNIT_MASK) == KVM_STATS_UNIT_BOOLEAN) {
stats->value->u.boolean = *stats_data; stats->value->u.boolean = *stats_data;
@ -4117,3 +4315,30 @@ void query_stats_schemas_cb(StatsSchemaList **result, Error **errp)
query_stats_schema_vcpu(first_cpu, &stats_args); query_stats_schema_vcpu(first_cpu, &stats_args);
} }
} }
void kvm_mark_guest_state_protected(void)
{
kvm_state->guest_state_protected = true;
}
int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
{
int fd;
struct kvm_create_guest_memfd guest_memfd = {
.size = size,
.flags = flags,
};
if (!kvm_guest_memfd_supported) {
error_setg(errp, "KVM does not support guest_memfd");
return -1;
}
fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_GUEST_MEMFD, &guest_memfd);
if (fd < 0) {
error_setg_errno(errp, errno, "Error creating KVM guest_memfd");
return -1;
}
return fd;
}

View File

@ -22,5 +22,4 @@ bool kvm_supports_guest_debug(void);
int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len); int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len);
int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len); int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len);
void kvm_remove_all_breakpoints(CPUState *cpu); void kvm_remove_all_breakpoints(CPUState *cpu);
#endif /* KVM_CPUS_H */ #endif /* KVM_CPUS_H */

View File

@ -9,13 +9,17 @@ kvm_device_ioctl(int fd, int type, void *arg) "dev fd %d, type 0x%x, arg %p"
kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s" kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s"
kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s" kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s"
kvm_init_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu" kvm_init_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
kvm_create_vcpu(int cpu_index, unsigned long arch_cpu_id, int kvm_fd) "index: %d, id: %lu, kvm fd: %d"
kvm_destroy_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
kvm_park_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
kvm_unpark_vcpu(unsigned long arch_cpu_id, const char *msg) "id: %lu %s"
kvm_irqchip_commit_routes(void) "" kvm_irqchip_commit_routes(void) ""
kvm_irqchip_add_msi_route(char *name, int vector, int virq) "dev %s vector %d virq %d" kvm_irqchip_add_msi_route(char *name, int vector, int virq) "dev %s vector %d virq %d"
kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d" kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d"
kvm_irqchip_release_virq(int virq) "virq %d" kvm_irqchip_release_virq(int virq) "virq %d"
kvm_set_ioeventfd_mmio(int fd, uint64_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%" PRIx64 " val=0x%x assign: %d size: %d match: %d" kvm_set_ioeventfd_mmio(int fd, uint64_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%" PRIx64 " val=0x%x assign: %d size: %d match: %d"
kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%x val=0x%x assign: %d size: %d match: %d" kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%x val=0x%x assign: %d size: %d match: %d"
kvm_set_user_memory(uint32_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, int ret) "Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " ret=%d" kvm_set_user_memory(uint16_t as, uint16_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, uint32_t fd, uint64_t fd_offset, int ret) "AddrSpace#%d Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " guest_memfd=%d" " guest_memfd_offset=0x%" PRIx64 " ret=%d"
kvm_clear_dirty_log(uint32_t slot, uint64_t start, uint32_t size) "slot#%"PRId32" start 0x%"PRIx64" size 0x%"PRIx32 kvm_clear_dirty_log(uint32_t slot, uint64_t start, uint32_t size) "slot#%"PRId32" start 0x%"PRIx64" size 0x%"PRIx32
kvm_resample_fd_notify(int gsi) "gsi %d" kvm_resample_fd_notify(int gsi) "gsi %d"
kvm_dirty_ring_full(int id) "vcpu %d" kvm_dirty_ring_full(int id) "vcpu %d"
@ -25,9 +29,10 @@ kvm_dirty_ring_reaper(const char *s) "%s"
kvm_dirty_ring_reap(uint64_t count, int64_t t) "reaped %"PRIu64" pages (took %"PRIi64" us)" kvm_dirty_ring_reap(uint64_t count, int64_t t) "reaped %"PRIu64" pages (took %"PRIi64" us)"
kvm_dirty_ring_reaper_kick(const char *reason) "%s" kvm_dirty_ring_reaper_kick(const char *reason) "%s"
kvm_dirty_ring_flush(int finished) "%d" kvm_dirty_ring_flush(int finished) "%d"
kvm_destroy_vcpu(void) ""
kvm_failed_get_vcpu_mmap_size(void) "" kvm_failed_get_vcpu_mmap_size(void) ""
kvm_cpu_exec(void) "" kvm_cpu_exec(void) ""
kvm_interrupt_exit_request(void) "" kvm_interrupt_exit_request(void) ""
kvm_io_window_exit(void) "" kvm_io_window_exit(void) ""
kvm_run_exit_system_event(int cpu_index, uint32_t event_type) "cpu_index %d, system_even_type %"PRIu32 kvm_run_exit_system_event(int cpu_index, uint32_t event_type) "cpu_index %d, system_even_type %"PRIu32
kvm_convert_memory(uint64_t start, uint64_t size, const char *msg) "start 0x%" PRIx64 " size 0x%" PRIx64 " %s"
kvm_memory_fault(uint64_t start, uint64_t size, uint64_t flags) "start 0x%" PRIx64 " size 0x%" PRIx64 " flags 0x%" PRIx64

View File

@ -24,6 +24,18 @@
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "hw/core/cpu.h" #include "hw/core/cpu.h"
static int64_t qtest_clock_counter;
static int64_t qtest_get_virtual_clock(void)
{
return qatomic_read_i64(&qtest_clock_counter);
}
static void qtest_set_virtual_clock(int64_t count)
{
qatomic_set_i64(&qtest_clock_counter, count);
}
static int qtest_init_accel(MachineState *ms) static int qtest_init_accel(MachineState *ms)
{ {
return 0; return 0;
@ -52,6 +64,7 @@ static void qtest_accel_ops_class_init(ObjectClass *oc, void *data)
ops->create_vcpu_thread = dummy_start_vcpu_thread; ops->create_vcpu_thread = dummy_start_vcpu_thread;
ops->get_virtual_clock = qtest_get_virtual_clock; ops->get_virtual_clock = qtest_get_virtual_clock;
ops->set_virtual_clock = qtest_set_virtual_clock;
}; };
static const TypeInfo qtest_accel_ops_type = { static const TypeInfo qtest_accel_ops_type = {

View File

@ -129,3 +129,8 @@ bool kvm_hwpoisoned_mem(void)
{ {
return false; return false;
} }
int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
{
return -ENOSYS;
}

View File

@ -18,24 +18,6 @@ void tb_flush(CPUState *cpu)
{ {
} }
void tlb_set_dirty(CPUState *cpu, vaddr vaddr)
{
}
int probe_access_flags(CPUArchState *env, vaddr addr, int size,
MMUAccessType access_type, int mmu_idx,
bool nonfault, void **phost, uintptr_t retaddr)
{
g_assert_not_reached();
}
void *probe_access(CPUArchState *env, vaddr addr, int size,
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
{
/* Handled by hardware accelerator. */
g_assert_not_reached();
}
G_NORETURN void cpu_loop_exit(CPUState *cpu) G_NORETURN void cpu_loop_exit(CPUState *cpu)
{ {
g_assert_not_reached(); g_assert_not_reached();

View File

@ -144,6 +144,16 @@ static void init_delay_params(SyncClocks *sc, const CPUState *cpu)
} }
#endif /* CONFIG USER ONLY */ #endif /* CONFIG USER ONLY */
bool tcg_cflags_has(CPUState *cpu, uint32_t flags)
{
return cpu->tcg_cflags & flags;
}
void tcg_cflags_set(CPUState *cpu, uint32_t flags)
{
cpu->tcg_cflags |= flags;
}
uint32_t curr_cflags(CPUState *cpu) uint32_t curr_cflags(CPUState *cpu)
{ {
uint32_t cflags = cpu->tcg_cflags; uint32_t cflags = cpu->tcg_cflags;
@ -368,7 +378,7 @@ static bool check_for_breakpoints_slow(CPUState *cpu, vaddr pc,
* breakpoints are removed. * breakpoints are removed.
*/ */
if (match_page) { if (match_page) {
*cflags = (*cflags & ~CF_COUNT_MASK) | CF_NO_GOTO_TB | 1; *cflags = (*cflags & ~CF_COUNT_MASK) | CF_NO_GOTO_TB | CF_BP_PAGE | 1;
} }
return false; return false;
} }
@ -669,11 +679,9 @@ static inline bool cpu_handle_halt(CPUState *cpu)
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
if (cpu->halted) { if (cpu->halted) {
const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops;
bool leave_halt = tcg_ops->cpu_exec_halt(cpu);
if (tcg_ops->cpu_exec_halt) { if (!leave_halt) {
tcg_ops->cpu_exec_halt(cpu);
}
if (!cpu_has_work(cpu)) {
return true; return true;
} }
@ -864,8 +872,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
else { else {
const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops;
if (tcg_ops->cpu_exec_interrupt && if (tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
if (!tcg_ops->need_replay_interrupt || if (!tcg_ops->need_replay_interrupt ||
tcg_ops->need_replay_interrupt(interrupt_request)) { tcg_ops->need_replay_interrupt(interrupt_request)) {
replay_interrupt(); replay_interrupt();
@ -915,8 +922,6 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
vaddr pc, TranslationBlock **last_tb, vaddr pc, TranslationBlock **last_tb,
int *tb_exit) int *tb_exit)
{ {
int32_t insns_left;
trace_exec_tb(tb, pc); trace_exec_tb(tb, pc);
tb = cpu_tb_exec(cpu, tb, tb_exit); tb = cpu_tb_exec(cpu, tb, tb_exit);
if (*tb_exit != TB_EXIT_REQUESTED) { if (*tb_exit != TB_EXIT_REQUESTED) {
@ -925,8 +930,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
} }
*last_tb = NULL; *last_tb = NULL;
insns_left = qatomic_read(&cpu->neg.icount_decr.u32); if (cpu_loop_exit_requested(cpu)) {
if (insns_left < 0) {
/* Something asked us to stop executing chained TBs; just /* Something asked us to stop executing chained TBs; just
* continue round the main loop. Whatever requested the exit * continue round the main loop. Whatever requested the exit
* will also have set something else (eg exit_request or * will also have set something else (eg exit_request or
@ -943,7 +947,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
/* Ensure global icount has gone forward */ /* Ensure global icount has gone forward */
icount_update(cpu); icount_update(cpu);
/* Refill decrementer and continue execution. */ /* Refill decrementer and continue execution. */
insns_left = MIN(0xffff, cpu->icount_budget); int32_t insns_left = MIN(0xffff, cpu->icount_budget);
cpu->neg.icount_decr.u16.low = insns_left; cpu->neg.icount_decr.u16.low = insns_left;
cpu->icount_extra = cpu->icount_budget - insns_left; cpu->icount_extra = cpu->icount_budget - insns_left;
@ -1125,6 +1129,11 @@ bool tcg_exec_realizefn(CPUState *cpu, Error **errp)
static bool tcg_target_initialized; static bool tcg_target_initialized;
if (!tcg_target_initialized) { if (!tcg_target_initialized) {
/* Check mandatory TCGCPUOps handlers */
#ifndef CONFIG_USER_ONLY
assert(cpu->cc->tcg_ops->cpu_exec_halt);
assert(cpu->cc->tcg_ops->cpu_exec_interrupt);
#endif /* !CONFIG_USER_ONLY */
cpu->cc->tcg_ops->initialize(); cpu->cc->tcg_ops->initialize();
tcg_target_initialized = true; tcg_target_initialized = true;
} }

View File

@ -21,12 +21,16 @@
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "hw/core/tcg-cpu-ops.h" #include "hw/core/tcg-cpu-ops.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/page-protection.h"
#include "exec/memory.h" #include "exec/memory.h"
#include "exec/cpu_ldst.h" #include "exec/cpu_ldst.h"
#include "exec/cputlb.h" #include "exec/cputlb.h"
#include "exec/tb-flush.h" #include "exec/tb-flush.h"
#include "exec/memory-internal.h" #include "exec/memory-internal.h"
#include "exec/ram_addr.h" #include "exec/ram_addr.h"
#include "exec/mmu-access-type.h"
#include "exec/tlb-common.h"
#include "exec/vaddr.h"
#include "tcg/tcg.h" #include "tcg/tcg.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "exec/log.h" #include "exec/log.h"
@ -102,6 +106,54 @@ static inline size_t sizeof_tlb(CPUTLBDescFast *fast)
return fast->mask + (1 << CPU_TLB_ENTRY_BITS); return fast->mask + (1 << CPU_TLB_ENTRY_BITS);
} }
static inline uint64_t tlb_read_idx(const CPUTLBEntry *entry,
MMUAccessType access_type)
{
/* Do not rearrange the CPUTLBEntry structure members. */
QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_read) !=
MMU_DATA_LOAD * sizeof(uint64_t));
QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_write) !=
MMU_DATA_STORE * sizeof(uint64_t));
QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_code) !=
MMU_INST_FETCH * sizeof(uint64_t));
#if TARGET_LONG_BITS == 32
/* Use qatomic_read, in case of addr_write; only care about low bits. */
const uint32_t *ptr = (uint32_t *)&entry->addr_idx[access_type];
ptr += HOST_BIG_ENDIAN;
return qatomic_read(ptr);
#else
const uint64_t *ptr = &entry->addr_idx[access_type];
# if TCG_OVERSIZED_GUEST
return *ptr;
# else
/* ofs might correspond to .addr_write, so use qatomic_read */
return qatomic_read(ptr);
# endif
#endif
}
static inline uint64_t tlb_addr_write(const CPUTLBEntry *entry)
{
return tlb_read_idx(entry, MMU_DATA_STORE);
}
/* Find the TLB index corresponding to the mmu_idx + address pair. */
static inline uintptr_t tlb_index(CPUState *cpu, uintptr_t mmu_idx,
vaddr addr)
{
uintptr_t size_mask = cpu->neg.tlb.f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS;
return (addr >> TARGET_PAGE_BITS) & size_mask;
}
/* Find the TLB entry corresponding to the mmu_idx + address pair. */
static inline CPUTLBEntry *tlb_entry(CPUState *cpu, uintptr_t mmu_idx,
vaddr addr)
{
return &cpu->neg.tlb.f[mmu_idx].table[tlb_index(cpu, mmu_idx, addr)];
}
static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns, static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
size_t max_entries) size_t max_entries)
{ {
@ -373,34 +425,16 @@ void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap)
{ {
tlb_debug("mmu_idx: 0x%" PRIx16 "\n", idxmap); tlb_debug("mmu_idx: 0x%" PRIx16 "\n", idxmap);
if (cpu->created && !qemu_cpu_is_self(cpu)) { assert_cpu_is_self(cpu);
async_run_on_cpu(cpu, tlb_flush_by_mmuidx_async_work,
RUN_ON_CPU_HOST_INT(idxmap));
} else {
tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(idxmap)); tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(idxmap));
} }
}
void tlb_flush(CPUState *cpu) void tlb_flush(CPUState *cpu)
{ {
tlb_flush_by_mmuidx(cpu, ALL_MMUIDX_BITS); tlb_flush_by_mmuidx(cpu, ALL_MMUIDX_BITS);
} }
void tlb_flush_by_mmuidx_all_cpus(CPUState *src_cpu, uint16_t idxmap)
{
const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work;
tlb_debug("mmu_idx: 0x%"PRIx16"\n", idxmap);
flush_all_helper(src_cpu, fn, RUN_ON_CPU_HOST_INT(idxmap));
fn(src_cpu, RUN_ON_CPU_HOST_INT(idxmap));
}
void tlb_flush_all_cpus(CPUState *src_cpu)
{
tlb_flush_by_mmuidx_all_cpus(src_cpu, ALL_MMUIDX_BITS);
}
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, uint16_t idxmap) void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, uint16_t idxmap)
{ {
const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work; const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work;
@ -582,28 +616,12 @@ void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr, uint16_t idxmap)
{ {
tlb_debug("addr: %016" VADDR_PRIx " mmu_idx:%" PRIx16 "\n", addr, idxmap); tlb_debug("addr: %016" VADDR_PRIx " mmu_idx:%" PRIx16 "\n", addr, idxmap);
assert_cpu_is_self(cpu);
/* This should already be page aligned */ /* This should already be page aligned */
addr &= TARGET_PAGE_MASK; addr &= TARGET_PAGE_MASK;
if (qemu_cpu_is_self(cpu)) {
tlb_flush_page_by_mmuidx_async_0(cpu, addr, idxmap); tlb_flush_page_by_mmuidx_async_0(cpu, addr, idxmap);
} else if (idxmap < TARGET_PAGE_SIZE) {
/*
* Most targets have only a few mmu_idx. In the case where
* we can stuff idxmap into the low TARGET_PAGE_BITS, avoid
* allocating memory for this operation.
*/
async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_1,
RUN_ON_CPU_TARGET_PTR(addr | idxmap));
} else {
TLBFlushPageByMMUIdxData *d = g_new(TLBFlushPageByMMUIdxData, 1);
/* Otherwise allocate a structure, freed by the worker. */
d->addr = addr;
d->idxmap = idxmap;
async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_2,
RUN_ON_CPU_HOST_PTR(d));
}
} }
void tlb_flush_page(CPUState *cpu, vaddr addr) void tlb_flush_page(CPUState *cpu, vaddr addr)
@ -611,46 +629,6 @@ void tlb_flush_page(CPUState *cpu, vaddr addr)
tlb_flush_page_by_mmuidx(cpu, addr, ALL_MMUIDX_BITS); tlb_flush_page_by_mmuidx(cpu, addr, ALL_MMUIDX_BITS);
} }
void tlb_flush_page_by_mmuidx_all_cpus(CPUState *src_cpu, vaddr addr,
uint16_t idxmap)
{
tlb_debug("addr: %016" VADDR_PRIx " mmu_idx:%"PRIx16"\n", addr, idxmap);
/* This should already be page aligned */
addr &= TARGET_PAGE_MASK;
/*
* Allocate memory to hold addr+idxmap only when needed.
* See tlb_flush_page_by_mmuidx for details.
*/
if (idxmap < TARGET_PAGE_SIZE) {
flush_all_helper(src_cpu, tlb_flush_page_by_mmuidx_async_1,
RUN_ON_CPU_TARGET_PTR(addr | idxmap));
} else {
CPUState *dst_cpu;
/* Allocate a separate data block for each destination cpu. */
CPU_FOREACH(dst_cpu) {
if (dst_cpu != src_cpu) {
TLBFlushPageByMMUIdxData *d
= g_new(TLBFlushPageByMMUIdxData, 1);
d->addr = addr;
d->idxmap = idxmap;
async_run_on_cpu(dst_cpu, tlb_flush_page_by_mmuidx_async_2,
RUN_ON_CPU_HOST_PTR(d));
}
}
}
tlb_flush_page_by_mmuidx_async_0(src_cpu, addr, idxmap);
}
void tlb_flush_page_all_cpus(CPUState *src, vaddr addr)
{
tlb_flush_page_by_mmuidx_all_cpus(src, addr, ALL_MMUIDX_BITS);
}
void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu, void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
vaddr addr, vaddr addr,
uint16_t idxmap) uint16_t idxmap)
@ -806,6 +784,8 @@ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
{ {
TLBFlushRangeData d; TLBFlushRangeData d;
assert_cpu_is_self(cpu);
/* /*
* If all bits are significant, and len is small, * If all bits are significant, and len is small,
* this devolves to tlb_flush_page. * this devolves to tlb_flush_page.
@ -826,14 +806,7 @@ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
d.idxmap = idxmap; d.idxmap = idxmap;
d.bits = bits; d.bits = bits;
if (qemu_cpu_is_self(cpu)) {
tlb_flush_range_by_mmuidx_async_0(cpu, d); tlb_flush_range_by_mmuidx_async_0(cpu, d);
} else {
/* Otherwise allocate a structure, freed by the worker. */
TLBFlushRangeData *p = g_memdup(&d, sizeof(d));
async_run_on_cpu(cpu, tlb_flush_range_by_mmuidx_async_1,
RUN_ON_CPU_HOST_PTR(p));
}
} }
void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr, void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr,
@ -842,54 +815,6 @@ void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr,
tlb_flush_range_by_mmuidx(cpu, addr, TARGET_PAGE_SIZE, idxmap, bits); tlb_flush_range_by_mmuidx(cpu, addr, TARGET_PAGE_SIZE, idxmap, bits);
} }
void tlb_flush_range_by_mmuidx_all_cpus(CPUState *src_cpu,
vaddr addr, vaddr len,
uint16_t idxmap, unsigned bits)
{
TLBFlushRangeData d;
CPUState *dst_cpu;
/*
* If all bits are significant, and len is small,
* this devolves to tlb_flush_page.
*/
if (bits >= TARGET_LONG_BITS && len <= TARGET_PAGE_SIZE) {
tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap);
return;
}
/* If no page bits are significant, this devolves to tlb_flush. */
if (bits < TARGET_PAGE_BITS) {
tlb_flush_by_mmuidx_all_cpus(src_cpu, idxmap);
return;
}
/* This should already be page aligned */
d.addr = addr & TARGET_PAGE_MASK;
d.len = len;
d.idxmap = idxmap;
d.bits = bits;
/* Allocate a separate data block for each destination cpu. */
CPU_FOREACH(dst_cpu) {
if (dst_cpu != src_cpu) {
TLBFlushRangeData *p = g_memdup(&d, sizeof(d));
async_run_on_cpu(dst_cpu,
tlb_flush_range_by_mmuidx_async_1,
RUN_ON_CPU_HOST_PTR(p));
}
}
tlb_flush_range_by_mmuidx_async_0(src_cpu, d);
}
void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
vaddr addr, uint16_t idxmap,
unsigned bits)
{
tlb_flush_range_by_mmuidx_all_cpus(src_cpu, addr, TARGET_PAGE_SIZE,
idxmap, bits);
}
void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *src_cpu, void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
vaddr addr, vaddr addr,
vaddr len, vaddr len,
@ -1046,7 +971,7 @@ static inline void tlb_set_dirty1_locked(CPUTLBEntry *tlb_entry,
/* update the TLB corresponding to virtual page vaddr /* update the TLB corresponding to virtual page vaddr
so that it is no longer dirty */ so that it is no longer dirty */
void tlb_set_dirty(CPUState *cpu, vaddr addr) static void tlb_set_dirty(CPUState *cpu, vaddr addr)
{ {
int mmu_idx; int mmu_idx;

View File

@ -336,10 +336,8 @@ void icount_start_warp_timer(void)
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
~QEMU_TIMER_ATTR_EXTERNAL); ~QEMU_TIMER_ATTR_EXTERNAL);
if (deadline < 0) { if (deadline < 0) {
static bool notified; if (!icount_sleep) {
if (!icount_sleep && !notified) { warn_report_once("icount sleep disabled and no active timers");
warn_report("icount sleep disabled and no active timers");
notified = true;
} }
return; return;
} }

View File

@ -9,18 +9,51 @@
#ifndef ACCEL_TCG_INTERNAL_COMMON_H #ifndef ACCEL_TCG_INTERNAL_COMMON_H
#define ACCEL_TCG_INTERNAL_COMMON_H #define ACCEL_TCG_INTERNAL_COMMON_H
#include "exec/cpu-common.h"
#include "exec/translation-block.h" #include "exec/translation-block.h"
extern int64_t max_delay; extern int64_t max_delay;
extern int64_t max_advance; extern int64_t max_advance;
extern bool one_insn_per_tb;
/* /*
* Return true if CS is not running in parallel with other cpus, either * Return true if CS is not running in parallel with other cpus, either
* because there are no other cpus or we are within an exclusive context. * because there are no other cpus or we are within an exclusive context.
*/ */
static inline bool cpu_in_serial_context(CPUState *cs) static inline bool cpu_in_serial_context(CPUState *cs)
{ {
return !(cs->tcg_cflags & CF_PARALLEL) || cpu_in_exclusive_context(cs); return !tcg_cflags_has(cs, CF_PARALLEL) || cpu_in_exclusive_context(cs);
} }
/**
* cpu_plugin_mem_cbs_enabled() - are plugin memory callbacks enabled?
* @cs: CPUState pointer
*
* The memory callbacks are installed if a plugin has instrumented an
* instruction for memory. This can be useful to know if you want to
* force a slow path for a series of memory accesses.
*/
static inline bool cpu_plugin_mem_cbs_enabled(const CPUState *cpu)
{
#ifdef CONFIG_PLUGIN
return !!cpu->neg.plugin_mem_cbs;
#else
return false;
#endif
}
TranslationBlock *tb_gen_code(CPUState *cpu, vaddr pc,
uint64_t cs_base, uint32_t flags,
int cflags);
void page_init(void);
void tb_htable_init(void);
void tb_reset_jump(TranslationBlock *tb, int n);
TranslationBlock *tb_link_page(TranslationBlock *tb);
void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
uintptr_t host_pc);
bool tcg_exec_realizefn(CPUState *cpu, Error **errp);
void tcg_exec_unrealizefn(CPUState *cpu);
#endif #endif

View File

@ -69,19 +69,7 @@ void tb_invalidate_phys_range_fast(ram_addr_t ram_addr,
G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr); G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
#endif /* CONFIG_SOFTMMU */ #endif /* CONFIG_SOFTMMU */
TranslationBlock *tb_gen_code(CPUState *cpu, vaddr pc,
uint64_t cs_base, uint32_t flags,
int cflags);
void page_init(void);
void tb_htable_init(void);
void tb_reset_jump(TranslationBlock *tb, int n);
TranslationBlock *tb_link_page(TranslationBlock *tb);
bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc); bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc);
void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
uintptr_t host_pc);
bool tcg_exec_realizefn(CPUState *cpu, Error **errp);
void tcg_exec_unrealizefn(CPUState *cpu);
/* Return the current PC from CPU, which may be cached in TB. */ /* Return the current PC from CPU, which may be cached in TB. */
static inline vaddr log_pc(CPUState *cpu, const TranslationBlock *tb) static inline vaddr log_pc(CPUState *cpu, const TranslationBlock *tb)
@ -93,8 +81,6 @@ static inline vaddr log_pc(CPUState *cpu, const TranslationBlock *tb)
} }
} }
extern bool one_insn_per_tb;
/** /**
* tcg_req_mo: * tcg_req_mo:
* @type: TCGBar * @type: TCGBar

View File

@ -9,8 +9,8 @@
* See the COPYING file in the top-level directory. * See the COPYING file in the top-level directory.
*/ */
#include "host/load-extract-al16-al8.h" #include "host/load-extract-al16-al8.h.inc"
#include "host/store-insert-al16.h" #include "host/store-insert-al16.h.inc"
#ifdef CONFIG_ATOMIC64 #ifdef CONFIG_ATOMIC64
# define HAVE_al8 true # define HAVE_al8 true

View File

@ -125,8 +125,10 @@ void helper_st_i128(CPUArchState *env, uint64_t addr, Int128 val, MemOpIdx oi)
static void plugin_load_cb(CPUArchState *env, abi_ptr addr, MemOpIdx oi) static void plugin_load_cb(CPUArchState *env, abi_ptr addr, MemOpIdx oi)
{ {
if (cpu_plugin_mem_cbs_enabled(env_cpu(env))) {
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R); qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
} }
}
uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra) uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra)
{ {
@ -188,8 +190,10 @@ Int128 cpu_ld16_mmu(CPUArchState *env, abi_ptr addr,
static void plugin_store_cb(CPUArchState *env, abi_ptr addr, MemOpIdx oi) static void plugin_store_cb(CPUArchState *env, abi_ptr addr, MemOpIdx oi)
{ {
if (cpu_plugin_mem_cbs_enabled(env_cpu(env))) {
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W); qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
} }
}
void cpu_stb_mmu(CPUArchState *env, abi_ptr addr, uint8_t val, void cpu_stb_mmu(CPUArchState *env, abi_ptr addr, uint8_t val,
MemOpIdx oi, uintptr_t retaddr) MemOpIdx oi, uintptr_t retaddr)

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +0,0 @@
#ifdef CONFIG_PLUGIN
DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_wg, TCG_CALL_NO_WG | TCG_CALL_PLUGIN, void, i32, ptr)
DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_rwg, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, void, i32, ptr)
DEF_HELPER_FLAGS_4(plugin_vcpu_mem_cb, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, void, i32, i32, i64, ptr)
#endif

View File

@ -9,6 +9,9 @@
#ifndef ACCEL_TCG_TB_JMP_CACHE_H #ifndef ACCEL_TCG_TB_JMP_CACHE_H
#define ACCEL_TCG_TB_JMP_CACHE_H #define ACCEL_TCG_TB_JMP_CACHE_H
#include "qemu/rcu.h"
#include "exec/cpu-common.h"
#define TB_JMP_CACHE_BITS 12 #define TB_JMP_CACHE_BITS 12
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
@ -19,12 +22,12 @@
* non-NULL value of 'tb'. Strictly speaking pc is only needed for * non-NULL value of 'tb'. Strictly speaking pc is only needed for
* CF_PCREL, but it's used always for simplicity. * CF_PCREL, but it's used always for simplicity.
*/ */
struct CPUJumpCache { typedef struct CPUJumpCache {
struct rcu_head rcu; struct rcu_head rcu;
struct { struct {
TranslationBlock *tb; TranslationBlock *tb;
vaddr pc; vaddr pc;
} array[TB_JMP_CACHE_SIZE]; } array[TB_JMP_CACHE_SIZE];
}; } CPUJumpCache;
#endif /* ACCEL_TCG_TB_JMP_CACHE_H */ #endif /* ACCEL_TCG_TB_JMP_CACHE_H */

View File

@ -23,6 +23,7 @@
#include "exec/cputlb.h" #include "exec/cputlb.h"
#include "exec/log.h" #include "exec/log.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/page-protection.h"
#include "exec/tb-flush.h" #include "exec/tb-flush.h"
#include "exec/translate-all.h" #include "exec/translate-all.h"
#include "sysemu/tcg.h" #include "sysemu/tcg.h"

View File

@ -137,10 +137,6 @@ void mttcg_start_vcpu_thread(CPUState *cpu)
g_assert(tcg_enabled()); g_assert(tcg_enabled());
tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1); tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1);
cpu->thread = g_new0(QemuThread, 1);
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
qemu_cond_init(cpu->halt_cond);
/* create a thread per vCPU with TCG (MTTCG) */ /* create a thread per vCPU with TCG (MTTCG) */
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG", snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
cpu->cpu_index); cpu->cpu_index);

View File

@ -109,7 +109,7 @@ static void rr_wait_io_event(void)
{ {
CPUState *cpu; CPUState *cpu;
while (all_cpu_threads_idle() && replay_can_wait()) { while (all_cpu_threads_idle()) {
rr_stop_kick_timer(); rr_stop_kick_timer();
qemu_cond_wait_bql(first_cpu->halt_cond); qemu_cond_wait_bql(first_cpu->halt_cond);
} }
@ -317,22 +317,23 @@ void rr_start_vcpu_thread(CPUState *cpu)
tcg_cpu_init_cflags(cpu, false); tcg_cpu_init_cflags(cpu, false);
if (!single_tcg_cpu_thread) { if (!single_tcg_cpu_thread) {
cpu->thread = g_new0(QemuThread, 1); single_tcg_halt_cond = cpu->halt_cond;
cpu->halt_cond = g_new0(QemuCond, 1); single_tcg_cpu_thread = cpu->thread;
qemu_cond_init(cpu->halt_cond);
/* share a single thread for all cpus with TCG */ /* share a single thread for all cpus with TCG */
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG"); snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG");
qemu_thread_create(cpu->thread, thread_name, qemu_thread_create(cpu->thread, thread_name,
rr_cpu_thread_fn, rr_cpu_thread_fn,
cpu, QEMU_THREAD_JOINABLE); cpu, QEMU_THREAD_JOINABLE);
single_tcg_halt_cond = cpu->halt_cond;
single_tcg_cpu_thread = cpu->thread;
} else { } else {
/* we share the thread */ /* we share the thread, dump spare data */
g_free(cpu->thread);
qemu_cond_destroy(cpu->halt_cond);
g_free(cpu->halt_cond);
cpu->thread = single_tcg_cpu_thread; cpu->thread = single_tcg_cpu_thread;
cpu->halt_cond = single_tcg_halt_cond; cpu->halt_cond = single_tcg_halt_cond;
/* copy the stuff done at start of rr_cpu_thread_fn */
cpu->thread_id = first_cpu->thread_id; cpu->thread_id = first_cpu->thread_id;
cpu->neg.can_do_io = 1; cpu->neg.can_do_io = 1;
cpu->created = true; cpu->created = true;

View File

@ -35,7 +35,9 @@
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/hwaddr.h" #include "exec/hwaddr.h"
#include "exec/tb-flush.h" #include "exec/tb-flush.h"
#include "exec/gdbstub.h" #include "gdbstub/enums.h"
#include "hw/core/cpu.h"
#include "tcg-accel-ops.h" #include "tcg-accel-ops.h"
#include "tcg-accel-ops-mttcg.h" #include "tcg-accel-ops-mttcg.h"
@ -60,7 +62,7 @@ void tcg_cpu_init_cflags(CPUState *cpu, bool parallel)
cflags |= parallel ? CF_PARALLEL : 0; cflags |= parallel ? CF_PARALLEL : 0;
cflags |= icount_enabled() ? CF_USE_ICOUNT : 0; cflags |= icount_enabled() ? CF_USE_ICOUNT : 0;
cpu->tcg_cflags |= cflags; tcg_cflags_set(cpu, cflags);
} }
void tcg_cpu_destroy(CPUState *cpu) void tcg_cpu_destroy(CPUState *cpu)

View File

@ -38,7 +38,7 @@
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
#include "hw/boards.h" #include "hw/boards.h"
#endif #endif
#include "internal-target.h" #include "internal-common.h"
struct TCGState { struct TCGState {
AccelState parent_obj; AccelState parent_obj;

View File

@ -937,15 +937,6 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
cpu_loop_exit_noexc(cpu); cpu_loop_exit_noexc(cpu);
} }
#else /* CONFIG_USER_ONLY */
void cpu_interrupt(CPUState *cpu, int mask)
{
g_assert(bql_locked());
cpu->interrupt_request |= mask;
qatomic_set(&cpu->neg.icount_decr.u16.high, -1);
}
#endif /* CONFIG_USER_ONLY */ #endif /* CONFIG_USER_ONLY */
/* /*

View File

@ -12,9 +12,12 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/translator.h" #include "exec/translator.h"
#include "exec/cpu_ldst.h"
#include "exec/plugin-gen.h" #include "exec/plugin-gen.h"
#include "exec/cpu_ldst.h"
#include "tcg/tcg-op-common.h" #include "tcg/tcg-op-common.h"
#include "internal-target.h" #include "internal-target.h"
#include "disas/disas.h"
static void set_can_do_io(DisasContextBase *db, bool val) static void set_can_do_io(DisasContextBase *db, bool val)
{ {
@ -142,8 +145,11 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
db->max_insns = *max_insns; db->max_insns = *max_insns;
db->singlestep_enabled = cflags & CF_SINGLE_STEP; db->singlestep_enabled = cflags & CF_SINGLE_STEP;
db->insn_start = NULL; db->insn_start = NULL;
db->fake_insn = false;
db->host_addr[0] = host_pc; db->host_addr[0] = host_pc;
db->host_addr[1] = NULL; db->host_addr[1] = NULL;
db->record_start = 0;
db->record_len = 0;
ops->init_disas_context(db, cpu); ops->init_disas_context(db, cpu);
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
@ -153,7 +159,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
ops->tb_start(db, cpu); ops->tb_start(db, cpu);
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY); plugin_enabled = plugin_gen_tb_start(cpu, db);
db->plugin_enabled = plugin_enabled; db->plugin_enabled = plugin_enabled;
while (true) { while (true) {
@ -259,47 +265,79 @@ post_translate_insn:
set_can_do_io(db, true); set_can_do_io(db, true);
tcg_ctx->emit_before_op = NULL; tcg_ctx->emit_before_op = NULL;
/* May be used by disas_log or plugin callbacks. */
tb->size = db->pc_next - db->pc_first;
tb->icount = db->num_insns;
if (plugin_enabled) { if (plugin_enabled) {
plugin_gen_tb_end(cpu, db->num_insns); plugin_gen_tb_end(cpu, db->num_insns);
} }
/* The disas_log hook may use these values rather than recompute. */
tb->size = db->pc_next - db->pc_first;
tb->icount = db->num_insns;
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(db->pc_first)) { && qemu_log_in_addr_range(db->pc_first)) {
FILE *logfile = qemu_log_trylock(); FILE *logfile = qemu_log_trylock();
if (logfile) { if (logfile) {
fprintf(logfile, "----------------\n"); fprintf(logfile, "----------------\n");
ops->disas_log(db, cpu, logfile);
if (!ops->disas_log ||
!ops->disas_log(db, cpu, logfile)) {
fprintf(logfile, "IN: %s\n", lookup_symbol(db->pc_first));
target_disas(logfile, cpu, db);
}
fprintf(logfile, "\n"); fprintf(logfile, "\n");
qemu_log_unlock(logfile); qemu_log_unlock(logfile);
} }
} }
} }
static void *translator_access(CPUArchState *env, DisasContextBase *db, static bool translator_ld(CPUArchState *env, DisasContextBase *db,
vaddr pc, size_t len) void *dest, vaddr pc, size_t len)
{ {
TranslationBlock *tb = db->tb;
vaddr last = pc + len - 1;
void *host; void *host;
vaddr base, end; vaddr base;
TranslationBlock *tb;
tb = db->tb;
/* Use slow path if first page is MMIO. */ /* Use slow path if first page is MMIO. */
if (unlikely(tb_page_addr0(tb) == -1)) { if (unlikely(tb_page_addr0(tb) == -1)) {
return NULL; /* We capped translation with first page MMIO in tb_gen_code. */
tcg_debug_assert(db->max_insns == 1);
return false;
} }
end = pc + len - 1;
if (likely(is_same_page(db, end))) {
host = db->host_addr[0]; host = db->host_addr[0];
base = db->pc_first; base = db->pc_first;
} else {
if (likely(((base ^ last) & TARGET_PAGE_MASK) == 0)) {
/* Entire read is from the first page. */
memcpy(dest, host + (pc - base), len);
return true;
}
if (unlikely(((base ^ pc) & TARGET_PAGE_MASK) == 0)) {
/* Read begins on the first page and extends to the second. */
size_t len0 = -(pc | TARGET_PAGE_MASK);
memcpy(dest, host + (pc - base), len0);
pc += len0;
dest += len0;
len -= len0;
}
/*
* The read must conclude on the second page and not extend to a third.
*
* TODO: We could allow the two pages to be virtually discontiguous,
* since we already allow the two pages to be physically discontiguous.
* The only reasonable use case would be executing an insn at the end
* of the address space wrapping around to the beginning. For that,
* we would need to know the current width of the address space.
* In the meantime, assert.
*/
base = (base & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
assert(((base ^ pc) & TARGET_PAGE_MASK) == 0);
assert(((base ^ last) & TARGET_PAGE_MASK) == 0);
host = db->host_addr[1]; host = db->host_addr[1];
base = TARGET_PAGE_ALIGN(db->pc_first);
if (host == NULL) { if (host == NULL) {
tb_page_addr_t page0, old_page1, new_page1; tb_page_addr_t page0, old_page1, new_page1;
@ -312,7 +350,9 @@ static void *translator_access(CPUArchState *env, DisasContextBase *db,
if (unlikely(new_page1 == -1)) { if (unlikely(new_page1 == -1)) {
tb_unlock_pages(tb); tb_unlock_pages(tb);
tb_set_page_addr0(tb, -1); tb_set_page_addr0(tb, -1);
return NULL; /* Require that this be the final insn. */
db->max_insns = db->num_insns;
return false;
} }
/* /*
@ -334,97 +374,153 @@ static void *translator_access(CPUArchState *env, DisasContextBase *db,
host = db->host_addr[1]; host = db->host_addr[1];
} }
/* Use slow path when crossing pages. */ memcpy(dest, host + (pc - base), len);
if (is_same_page(db, pc)) { return true;
return NULL;
}
} }
tcg_debug_assert(pc >= base); static void record_save(DisasContextBase *db, vaddr pc,
return host + (pc - base); const void *from, int size)
}
static void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
{ {
#ifdef CONFIG_PLUGIN int offset;
struct qemu_plugin_insn *insn = tcg_ctx->plugin_insn;
abi_ptr off;
if (insn == NULL) { /* Do not record probes before the start of TB. */
if (pc < db->pc_first) {
return; return;
} }
off = pc - insn->vaddr;
if (off < insn->data->len) { /*
g_byte_array_set_size(insn->data, off); * In translator_access, we verified that pc is within 2 pages
} else if (off > insn->data->len) { * of pc_first, thus this will never overflow.
/* we have an unexpected gap */ */
g_assert_not_reached(); offset = pc - db->pc_first;
/*
* Either the first or second page may be I/O. If it is the second,
* then the first byte we need to record will be at a non-zero offset.
* In either case, we should not need to record but a single insn.
*/
if (db->record_len == 0) {
db->record_start = offset;
db->record_len = size;
} else {
assert(offset == db->record_start + db->record_len);
assert(db->record_len + size <= sizeof(db->record));
db->record_len += size;
} }
insn->data = g_byte_array_append(insn->data, from, size); memcpy(db->record + (offset - db->record_start), from, size);
#endif
} }
uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc) size_t translator_st_len(const DisasContextBase *db)
{ {
uint8_t ret; return db->fake_insn ? db->record_len : db->tb->size;
void *p = translator_access(env, db, pc, sizeof(ret));
if (p) {
plugin_insn_append(pc, p, sizeof(ret));
return ldub_p(p);
}
ret = cpu_ldub_code(env, pc);
plugin_insn_append(pc, &ret, sizeof(ret));
return ret;
} }
uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc) bool translator_st(const DisasContextBase *db, void *dest,
vaddr addr, size_t len)
{ {
uint16_t ret, plug; size_t offset, offset_end;
void *p = translator_access(env, db, pc, sizeof(ret));
if (p) { if (addr < db->pc_first) {
plugin_insn_append(pc, p, sizeof(ret)); return false;
return lduw_p(p);
} }
ret = cpu_lduw_code(env, pc); offset = addr - db->pc_first;
plug = tswap16(ret); offset_end = offset + len;
plugin_insn_append(pc, &plug, sizeof(ret)); if (offset_end > translator_st_len(db)) {
return ret; return false;
} }
uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc) if (!db->fake_insn) {
size_t offset_page1 = -(db->pc_first | TARGET_PAGE_MASK);
/* Get all the bytes from the first page. */
if (db->host_addr[0]) {
if (offset_end <= offset_page1) {
memcpy(dest, db->host_addr[0] + offset, len);
return true;
}
if (offset < offset_page1) {
size_t len0 = offset_page1 - offset;
memcpy(dest, db->host_addr[0] + offset, len0);
offset += len0;
dest += len0;
}
}
/* Get any bytes from the second page. */
if (db->host_addr[1] && offset >= offset_page1) {
memcpy(dest, db->host_addr[1] + (offset - offset_page1),
offset_end - offset);
return true;
}
}
/* Else get recorded bytes. */
if (db->record_len != 0 &&
offset >= db->record_start &&
offset_end <= db->record_start + db->record_len) {
memcpy(dest, db->record + (offset - db->record_start),
offset_end - offset);
return true;
}
return false;
}
uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, vaddr pc)
{ {
uint32_t ret, plug; uint8_t raw;
void *p = translator_access(env, db, pc, sizeof(ret));
if (p) { if (!translator_ld(env, db, &raw, pc, sizeof(raw))) {
plugin_insn_append(pc, p, sizeof(ret)); raw = cpu_ldub_code(env, pc);
return ldl_p(p); record_save(db, pc, &raw, sizeof(raw));
} }
ret = cpu_ldl_code(env, pc); return raw;
plug = tswap32(ret);
plugin_insn_append(pc, &plug, sizeof(ret));
return ret;
} }
uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc) uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, vaddr pc)
{ {
uint64_t ret, plug; uint16_t raw, tgt;
void *p = translator_access(env, db, pc, sizeof(ret));
if (p) { if (translator_ld(env, db, &raw, pc, sizeof(raw))) {
plugin_insn_append(pc, p, sizeof(ret)); tgt = tswap16(raw);
return ldq_p(p); } else {
tgt = cpu_lduw_code(env, pc);
raw = tswap16(tgt);
record_save(db, pc, &raw, sizeof(raw));
} }
ret = cpu_ldq_code(env, pc); return tgt;
plug = tswap64(ret);
plugin_insn_append(pc, &plug, sizeof(ret));
return ret;
} }
void translator_fake_ldb(uint8_t insn8, abi_ptr pc) uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, vaddr pc)
{ {
plugin_insn_append(pc, &insn8, sizeof(insn8)); uint32_t raw, tgt;
if (translator_ld(env, db, &raw, pc, sizeof(raw))) {
tgt = tswap32(raw);
} else {
tgt = cpu_ldl_code(env, pc);
raw = tswap32(tgt);
record_save(db, pc, &raw, sizeof(raw));
}
return tgt;
}
uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, vaddr pc)
{
uint64_t raw, tgt;
if (translator_ld(env, db, &raw, pc, sizeof(raw))) {
tgt = tswap64(raw);
} else {
tgt = cpu_ldq_code(env, pc);
raw = tswap64(tgt);
record_save(db, pc, &raw, sizeof(raw));
}
return tgt;
}
void translator_fake_ld(DisasContextBase *db, const void *data, size_t len)
{
db->fake_insn = true;
record_save(db, db->pc_first, data, len);
} }

View File

@ -24,7 +24,9 @@
#include "qemu/bitops.h" #include "qemu/bitops.h"
#include "qemu/rcu.h" #include "qemu/rcu.h"
#include "exec/cpu_ldst.h" #include "exec/cpu_ldst.h"
#include "qemu/main-loop.h"
#include "exec/translate-all.h" #include "exec/translate-all.h"
#include "exec/page-protection.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "qemu/atomic128.h" #include "qemu/atomic128.h"
#include "trace/trace-root.h" #include "trace/trace-root.h"
@ -36,6 +38,13 @@ __thread uintptr_t helper_retaddr;
//#define DEBUG_SIGNAL //#define DEBUG_SIGNAL
void cpu_interrupt(CPUState *cpu, int mask)
{
g_assert(bql_locked());
cpu->interrupt_request |= mask;
qatomic_set(&cpu->neg.icount_decr.u16.high, -1);
}
/* /*
* Adjust the pc to pass to cpu_restore_state; return the memop type. * Adjust the pc to pass to cpu_restore_state; return the memop type.
*/ */
@ -770,7 +779,7 @@ int page_unprotect(target_ulong address, uintptr_t pc)
if (prot & PAGE_EXEC) { if (prot & PAGE_EXEC) {
prot = (prot & ~PAGE_EXEC) | PAGE_READ; prot = (prot & ~PAGE_EXEC) | PAGE_READ;
} }
mprotect((void *)g2h_untagged(start), len, prot & PAGE_BITS); mprotect((void *)g2h_untagged(start), len, prot & PAGE_RWX);
} }
mmap_unlock(); mmap_unlock();

18
accel/tcg/vcpu-state.h Normal file
View File

@ -0,0 +1,18 @@
/*
* SPDX-FileContributor: Philippe Mathieu-Daudé <philmd@linaro.org>
* SPDX-FileCopyrightText: 2023 Linaro Ltd.
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef ACCEL_TCG_VCPU_STATE_H
#define ACCEL_TCG_VCPU_STATE_H
#include "hw/core/cpu.h"
#ifdef CONFIG_USER_ONLY
static inline TaskState *get_task_state(const CPUState *cs)
{
return cs->opaque;
}
#endif
#endif

View File

@ -44,11 +44,6 @@ typedef struct coreaudioVoiceOut {
bool enabled; bool enabled;
} coreaudioVoiceOut; } coreaudioVoiceOut;
#if !defined(MAC_OS_VERSION_12_0) \
|| (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0)
#define kAudioObjectPropertyElementMain kAudioObjectPropertyElementMaster
#endif
static const AudioObjectPropertyAddress voice_addr = { static const AudioObjectPropertyAddress voice_addr = {
kAudioHardwarePropertyDefaultOutputDevice, kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyScopeGlobal,

View File

@ -105,7 +105,7 @@ static size_t dbus_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
assert(buf == vo->buf + vo->buf_pos && vo->buf_pos + size <= vo->buf_size); assert(buf == vo->buf + vo->buf_pos && vo->buf_pos + size <= vo->buf_size);
vo->buf_pos += size; vo->buf_pos += size;
trace_dbus_audio_put_buffer_out(size); trace_dbus_audio_put_buffer_out(vo->buf_pos, vo->buf_size);
if (vo->buf_pos < vo->buf_size) { if (vo->buf_pos < vo->buf_size) {
return size; return size;

View File

@ -30,8 +30,8 @@ endforeach
if dbus_display if dbus_display
module_ss = ss.source_set() module_ss = ss.source_set()
module_ss.add(when: [gio, dbus_display1_dep, pixman], module_ss.add(when: [gio, pixman],
if_true: files('dbusaudio.c')) if_true: [dbus_display1, files('dbusaudio.c')])
audio_modules += {'dbus': module_ss} audio_modules += {'dbus': module_ss}
endif endif

View File

@ -15,7 +15,7 @@ oss_version(int version) "OSS version = 0x%x"
# dbusaudio.c # dbusaudio.c
dbus_audio_register(const char *s, const char *dir) "sender = %s, dir = %s" dbus_audio_register(const char *s, const char *dir) "sender = %s, dir = %s"
dbus_audio_put_buffer_out(size_t len) "len = %zu" dbus_audio_put_buffer_out(size_t pos, size_t size) "buf_pos = %zu, buf_size = %zu"
dbus_audio_read(size_t len) "len = %zu" dbus_audio_read(size_t len) "len = %zu"
# pwaudio.c # pwaudio.c

View File

@ -3,3 +3,7 @@ source tpm/Kconfig
config IOMMUFD config IOMMUFD
bool bool
depends on VFIO depends on VFIO
config SPDM_SOCKET
bool
default y

View File

@ -0,0 +1,33 @@
/*
* Host IOMMU device abstract
*
* Copyright (C) 2024 Intel Corporation.
*
* Authors: Zhenzhong Duan <zhenzhong.duan@intel.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "sysemu/host_iommu_device.h"
OBJECT_DEFINE_ABSTRACT_TYPE(HostIOMMUDevice,
host_iommu_device,
HOST_IOMMU_DEVICE,
OBJECT)
static void host_iommu_device_class_init(ObjectClass *oc, void *data)
{
}
static void host_iommu_device_init(Object *obj)
{
}
static void host_iommu_device_finalize(Object *obj)
{
HostIOMMUDevice *hiod = HOST_IOMMU_DEVICE(obj);
g_free(hiod->name);
}

View File

@ -29,13 +29,12 @@ sgx_epc_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
return false; return false;
} }
fd = qemu_open_old("/dev/sgx_vepc", O_RDWR); fd = qemu_open("/dev/sgx_vepc", O_RDWR, errp);
if (fd < 0) { if (fd < 0) {
error_setg_errno(errp, errno,
"failed to open /dev/sgx_vepc to alloc SGX EPC");
return false; return false;
} }
backend->aligned = true;
name = object_get_canonical_path(OBJECT(backend)); name = object_get_canonical_path(OBJECT(backend));
ram_flags = (backend->share ? RAM_SHARED : 0) | RAM_PROTECTED; ram_flags = (backend->share ? RAM_SHARED : 0) | RAM_PROTECTED;
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name, return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,

View File

@ -80,11 +80,13 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
g_assert_not_reached(); g_assert_not_reached();
} }
backend->aligned = true;
name = host_memory_backend_get_name(backend); name = host_memory_backend_get_name(backend);
ram_flags = backend->share ? RAM_SHARED : 0; ram_flags = backend->share ? RAM_SHARED : 0;
ram_flags |= fb->readonly ? RAM_READONLY_FD : 0; ram_flags |= fb->readonly ? RAM_READONLY_FD : 0;
ram_flags |= fb->rom == ON_OFF_AUTO_ON ? RAM_READONLY : 0; ram_flags |= fb->rom == ON_OFF_AUTO_ON ? RAM_READONLY : 0;
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE; ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
ram_flags |= fb->is_pmem ? RAM_PMEM : 0; ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
ram_flags |= RAM_NAMED_FILE; ram_flags |= RAM_NAMED_FILE;
return memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name, return memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,

View File

@ -52,9 +52,11 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
return false; return false;
} }
backend->aligned = true;
name = host_memory_backend_get_name(backend); name = host_memory_backend_get_name(backend);
ram_flags = backend->share ? RAM_SHARED : 0; ram_flags = backend->share ? RAM_SHARED : 0;
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE; ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name, return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
backend->size, ram_flags, fd, 0, errp); backend->size, ram_flags, fd, 0, errp);
} }

View File

@ -30,6 +30,7 @@ ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
name = host_memory_backend_get_name(backend); name = host_memory_backend_get_name(backend);
ram_flags = backend->share ? RAM_SHARED : 0; ram_flags = backend->share ? RAM_SHARED : 0;
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE; ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
return memory_region_init_ram_flags_nomigrate(&backend->mr, OBJECT(backend), return memory_region_init_ram_flags_nomigrate(&backend->mr, OBJECT(backend),
name, backend->size, name, backend->size,
ram_flags, errp); ram_flags, errp);

123
backends/hostmem-shm.c Normal file
View File

@ -0,0 +1,123 @@
/*
* QEMU host POSIX shared memory object backend
*
* Copyright (C) 2024 Red Hat Inc
*
* Authors:
* Stefano Garzarella <sgarzare@redhat.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "sysemu/hostmem.h"
#include "qapi/error.h"
#define TYPE_MEMORY_BACKEND_SHM "memory-backend-shm"
OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendShm, MEMORY_BACKEND_SHM)
struct HostMemoryBackendShm {
HostMemoryBackend parent_obj;
};
static bool
shm_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
{
g_autoptr(GString) shm_name = g_string_new(NULL);
g_autofree char *backend_name = NULL;
uint32_t ram_flags;
int fd, oflag;
mode_t mode;
if (!backend->size) {
error_setg(errp, "can't create shm backend with size 0");
return false;
}
if (!backend->share) {
error_setg(errp, "can't create shm backend with `share=off`");
return false;
}
/*
* Let's use `mode = 0` because we don't want other processes to open our
* memory unless we share the file descriptor with them.
*/
mode = 0;
oflag = O_RDWR | O_CREAT | O_EXCL;
backend_name = host_memory_backend_get_name(backend);
/*
* Some operating systems allow creating anonymous POSIX shared memory
* objects (e.g. FreeBSD provides the SHM_ANON constant), but this is not
* defined by POSIX, so let's create a unique name.
*
* From Linux's shm_open(3) man-page:
* For portable use, a shared memory object should be identified
* by a name of the form /somename;"
*/
g_string_printf(shm_name, "/qemu-" FMT_pid "-shm-%s", getpid(),
backend_name);
fd = shm_open(shm_name->str, oflag, mode);
if (fd < 0) {
error_setg_errno(errp, errno,
"failed to create POSIX shared memory");
return false;
}
/*
* We have the file descriptor, so we no longer need to expose the
* POSIX shared memory object. However it will remain allocated as long as
* there are file descriptors pointing to it.
*/
shm_unlink(shm_name->str);
if (ftruncate(fd, backend->size) == -1) {
error_setg_errno(errp, errno,
"failed to resize POSIX shared memory to %" PRIu64,
backend->size);
close(fd);
return false;
}
ram_flags = RAM_SHARED;
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
backend_name, backend->size,
ram_flags, fd, 0, errp);
}
static void
shm_backend_instance_init(Object *obj)
{
HostMemoryBackendShm *m = MEMORY_BACKEND_SHM(obj);
MEMORY_BACKEND(m)->share = true;
}
static void
shm_backend_class_init(ObjectClass *oc, void *data)
{
HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
bc->alloc = shm_backend_memory_alloc;
}
static const TypeInfo shm_backend_info = {
.name = TYPE_MEMORY_BACKEND_SHM,
.parent = TYPE_MEMORY_BACKEND,
.instance_init = shm_backend_instance_init,
.class_init = shm_backend_class_init,
.instance_size = sizeof(HostMemoryBackendShm),
};
static void register_types(void)
{
type_register_static(&shm_backend_info);
}
type_init(register_types);

View File

@ -20,6 +20,7 @@
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
#include "qemu/mmap-alloc.h" #include "qemu/mmap-alloc.h"
#include "qemu/madvise.h" #include "qemu/madvise.h"
#include "qemu/cutils.h"
#include "hw/qdev-core.h" #include "hw/qdev-core.h"
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
@ -169,19 +170,24 @@ static void host_memory_backend_set_merge(Object *obj, bool value, Error **errp)
{ {
HostMemoryBackend *backend = MEMORY_BACKEND(obj); HostMemoryBackend *backend = MEMORY_BACKEND(obj);
if (!host_memory_backend_mr_inited(backend)) { if (QEMU_MADV_MERGEABLE == QEMU_MADV_INVALID) {
backend->merge = value; if (value) {
error_setg(errp, "Memory merging is not supported on this host");
}
assert(!backend->merge);
return; return;
} }
if (value != backend->merge) { if (!host_memory_backend_mr_inited(backend) &&
value != backend->merge) {
void *ptr = memory_region_get_ram_ptr(&backend->mr); void *ptr = memory_region_get_ram_ptr(&backend->mr);
uint64_t sz = memory_region_size(&backend->mr); uint64_t sz = memory_region_size(&backend->mr);
qemu_madvise(ptr, sz, qemu_madvise(ptr, sz,
value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE); value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE);
backend->merge = value;
} }
backend->merge = value;
} }
static bool host_memory_backend_get_dump(Object *obj, Error **errp) static bool host_memory_backend_get_dump(Object *obj, Error **errp)
@ -195,19 +201,24 @@ static void host_memory_backend_set_dump(Object *obj, bool value, Error **errp)
{ {
HostMemoryBackend *backend = MEMORY_BACKEND(obj); HostMemoryBackend *backend = MEMORY_BACKEND(obj);
if (!host_memory_backend_mr_inited(backend)) { if (QEMU_MADV_DONTDUMP == QEMU_MADV_INVALID) {
backend->dump = value; if (!value) {
error_setg(errp, "Dumping guest memory cannot be disabled on this host");
}
assert(backend->dump);
return; return;
} }
if (value != backend->dump) { if (host_memory_backend_mr_inited(backend) &&
value != backend->dump) {
void *ptr = memory_region_get_ram_ptr(&backend->mr); void *ptr = memory_region_get_ram_ptr(&backend->mr);
uint64_t sz = memory_region_size(&backend->mr); uint64_t sz = memory_region_size(&backend->mr);
qemu_madvise(ptr, sz, qemu_madvise(ptr, sz,
value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP); value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP);
backend->dump = value;
} }
backend->dump = value;
} }
static bool host_memory_backend_get_prealloc(Object *obj, Error **errp) static bool host_memory_backend_get_prealloc(Object *obj, Error **errp)
@ -277,6 +288,7 @@ static void host_memory_backend_init(Object *obj)
/* TODO: convert access to globals to compat properties */ /* TODO: convert access to globals to compat properties */
backend->merge = machine_mem_merge(machine); backend->merge = machine_mem_merge(machine);
backend->dump = machine_dump_guest_core(machine); backend->dump = machine_dump_guest_core(machine);
backend->guest_memfd = machine_require_guest_memfd(machine);
backend->reserve = true; backend->reserve = true;
backend->prealloc_threads = machine->smp.cpus; backend->prealloc_threads = machine->smp.cpus;
} }
@ -324,6 +336,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc); HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
void *ptr; void *ptr;
uint64_t sz; uint64_t sz;
size_t pagesize;
bool async = !phase_check(PHASE_LATE_BACKENDS_CREATED); bool async = !phase_check(PHASE_LATE_BACKENDS_CREATED);
if (!bc->alloc) { if (!bc->alloc) {
@ -335,6 +348,14 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
ptr = memory_region_get_ram_ptr(&backend->mr); ptr = memory_region_get_ram_ptr(&backend->mr);
sz = memory_region_size(&backend->mr); sz = memory_region_size(&backend->mr);
pagesize = qemu_ram_pagesize(backend->mr.ram_block);
if (backend->aligned && !QEMU_IS_ALIGNED(sz, pagesize)) {
g_autofree char *pagesize_str = size_to_str(pagesize);
error_setg(errp, "backend '%s' memory size must be multiple of %s",
object_get_typename(OBJECT(uc)), pagesize_str);
return;
}
if (backend->merge) { if (backend->merge) {
qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE); qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE);

View File

@ -13,12 +13,12 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "sysemu/iommufd.h" #include "sysemu/iommufd.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "trace.h" #include "trace.h"
#include "hw/vfio/vfio-common.h"
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/iommufd.h> #include <linux/iommufd.h>
@ -73,24 +73,21 @@ static void iommufd_backend_class_init(ObjectClass *oc, void *data)
object_class_property_add_str(oc, "fd", NULL, iommufd_backend_set_fd); object_class_property_add_str(oc, "fd", NULL, iommufd_backend_set_fd);
} }
int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp) bool iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
{ {
int fd, ret = 0; int fd;
if (be->owned && !be->users) { if (be->owned && !be->users) {
fd = qemu_open_old("/dev/iommu", O_RDWR); fd = qemu_open("/dev/iommu", O_RDWR, errp);
if (fd < 0) { if (fd < 0) {
error_setg_errno(errp, errno, "/dev/iommu opening failed"); return false;
ret = fd;
goto out;
} }
be->fd = fd; be->fd = fd;
} }
be->users++; be->users++;
out:
trace_iommufd_backend_connect(be->fd, be->owned, trace_iommufd_backend_connect(be->fd, be->owned, be->users);
be->users, ret); return true;
return ret;
} }
void iommufd_backend_disconnect(IOMMUFDBackend *be) void iommufd_backend_disconnect(IOMMUFDBackend *be)
@ -107,25 +104,24 @@ out:
trace_iommufd_backend_disconnect(be->fd, be->users); trace_iommufd_backend_disconnect(be->fd, be->users);
} }
int iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id, bool iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id,
Error **errp) Error **errp)
{ {
int ret, fd = be->fd; int fd = be->fd;
struct iommu_ioas_alloc alloc_data = { struct iommu_ioas_alloc alloc_data = {
.size = sizeof(alloc_data), .size = sizeof(alloc_data),
.flags = 0, .flags = 0,
}; };
ret = ioctl(fd, IOMMU_IOAS_ALLOC, &alloc_data); if (ioctl(fd, IOMMU_IOAS_ALLOC, &alloc_data)) {
if (ret) {
error_setg_errno(errp, errno, "Failed to allocate ioas"); error_setg_errno(errp, errno, "Failed to allocate ioas");
return ret; return false;
} }
*ioas_id = alloc_data.out_ioas_id; *ioas_id = alloc_data.out_ioas_id;
trace_iommufd_backend_alloc_ioas(fd, *ioas_id, ret); trace_iommufd_backend_alloc_ioas(fd, *ioas_id);
return ret; return true;
} }
void iommufd_backend_free_id(IOMMUFDBackend *be, uint32_t id) void iommufd_backend_free_id(IOMMUFDBackend *be, uint32_t id)
@ -212,7 +208,136 @@ int iommufd_backend_unmap_dma(IOMMUFDBackend *be, uint32_t ioas_id,
return ret; return ret;
} }
static const TypeInfo iommufd_backend_info = { bool iommufd_backend_alloc_hwpt(IOMMUFDBackend *be, uint32_t dev_id,
uint32_t pt_id, uint32_t flags,
uint32_t data_type, uint32_t data_len,
void *data_ptr, uint32_t *out_hwpt,
Error **errp)
{
int ret, fd = be->fd;
struct iommu_hwpt_alloc alloc_hwpt = {
.size = sizeof(struct iommu_hwpt_alloc),
.flags = flags,
.dev_id = dev_id,
.pt_id = pt_id,
.data_type = data_type,
.data_len = data_len,
.data_uptr = (uintptr_t)data_ptr,
};
ret = ioctl(fd, IOMMU_HWPT_ALLOC, &alloc_hwpt);
trace_iommufd_backend_alloc_hwpt(fd, dev_id, pt_id, flags, data_type,
data_len, (uintptr_t)data_ptr,
alloc_hwpt.out_hwpt_id, ret);
if (ret) {
error_setg_errno(errp, errno, "Failed to allocate hwpt");
return false;
}
*out_hwpt = alloc_hwpt.out_hwpt_id;
return true;
}
bool iommufd_backend_set_dirty_tracking(IOMMUFDBackend *be,
uint32_t hwpt_id, bool start,
Error **errp)
{
int ret;
struct iommu_hwpt_set_dirty_tracking set_dirty = {
.size = sizeof(set_dirty),
.hwpt_id = hwpt_id,
.flags = start ? IOMMU_HWPT_DIRTY_TRACKING_ENABLE : 0,
};
ret = ioctl(be->fd, IOMMU_HWPT_SET_DIRTY_TRACKING, &set_dirty);
trace_iommufd_backend_set_dirty(be->fd, hwpt_id, start, ret ? errno : 0);
if (ret) {
error_setg_errno(errp, errno,
"IOMMU_HWPT_SET_DIRTY_TRACKING(hwpt_id %u) failed",
hwpt_id);
return false;
}
return true;
}
bool iommufd_backend_get_dirty_bitmap(IOMMUFDBackend *be,
uint32_t hwpt_id,
uint64_t iova, ram_addr_t size,
uint64_t page_size, uint64_t *data,
Error **errp)
{
int ret;
struct iommu_hwpt_get_dirty_bitmap get_dirty_bitmap = {
.size = sizeof(get_dirty_bitmap),
.hwpt_id = hwpt_id,
.iova = iova,
.length = size,
.page_size = page_size,
.data = (uintptr_t)data,
};
ret = ioctl(be->fd, IOMMU_HWPT_GET_DIRTY_BITMAP, &get_dirty_bitmap);
trace_iommufd_backend_get_dirty_bitmap(be->fd, hwpt_id, iova, size,
page_size, ret ? errno : 0);
if (ret) {
error_setg_errno(errp, errno,
"IOMMU_HWPT_GET_DIRTY_BITMAP (iova: 0x%"HWADDR_PRIx
" size: 0x"RAM_ADDR_FMT") failed", iova, size);
return false;
}
return true;
}
bool iommufd_backend_get_device_info(IOMMUFDBackend *be, uint32_t devid,
uint32_t *type, void *data, uint32_t len,
uint64_t *caps, Error **errp)
{
struct iommu_hw_info info = {
.size = sizeof(info),
.dev_id = devid,
.data_len = len,
.data_uptr = (uintptr_t)data,
};
if (ioctl(be->fd, IOMMU_GET_HW_INFO, &info)) {
error_setg_errno(errp, errno, "Failed to get hardware info");
return false;
}
g_assert(type);
*type = info.out_data_type;
g_assert(caps);
*caps = info.out_capabilities;
return true;
}
static int hiod_iommufd_get_cap(HostIOMMUDevice *hiod, int cap, Error **errp)
{
HostIOMMUDeviceCaps *caps = &hiod->caps;
switch (cap) {
case HOST_IOMMU_DEVICE_CAP_IOMMU_TYPE:
return caps->type;
case HOST_IOMMU_DEVICE_CAP_AW_BITS:
return vfio_device_get_aw_bits(hiod->agent);
default:
error_setg(errp, "%s: unsupported capability %x", hiod->name, cap);
return -EINVAL;
}
}
static void hiod_iommufd_class_init(ObjectClass *oc, void *data)
{
HostIOMMUDeviceClass *hioc = HOST_IOMMU_DEVICE_CLASS(oc);
hioc->get_cap = hiod_iommufd_get_cap;
};
static const TypeInfo types[] = {
{
.name = TYPE_IOMMUFD_BACKEND, .name = TYPE_IOMMUFD_BACKEND,
.parent = TYPE_OBJECT, .parent = TYPE_OBJECT,
.instance_size = sizeof(IOMMUFDBackend), .instance_size = sizeof(IOMMUFDBackend),
@ -224,11 +349,12 @@ static const TypeInfo iommufd_backend_info = {
{ TYPE_USER_CREATABLE }, { TYPE_USER_CREATABLE },
{ } { }
} }
}, {
.name = TYPE_HOST_IOMMU_DEVICE_IOMMUFD,
.parent = TYPE_HOST_IOMMU_DEVICE,
.class_init = hiod_iommufd_class_init,
.abstract = true,
}
}; };
static void register_types(void) DEFINE_TYPES(types)
{
type_register_static(&iommufd_backend_info);
}
type_init(register_types);

View File

@ -13,9 +13,11 @@ system_ss.add([files(
if host_os != 'windows' if host_os != 'windows'
system_ss.add(files('rng-random.c')) system_ss.add(files('rng-random.c'))
system_ss.add(files('hostmem-file.c')) system_ss.add(files('hostmem-file.c'))
system_ss.add([files('hostmem-shm.c'), rt])
endif endif
if host_os == 'linux' if host_os == 'linux'
system_ss.add(files('hostmem-memfd.c')) system_ss.add(files('hostmem-memfd.c'))
system_ss.add(files('host_iommu_device.c'))
endif endif
if keyutils.found() if keyutils.found()
system_ss.add(keyutils, files('cryptodev-lkcf.c')) system_ss.add(keyutils, files('cryptodev-lkcf.c'))
@ -31,4 +33,6 @@ endif
system_ss.add(when: gio, if_true: files('dbus-vmstate.c')) system_ss.add(when: gio, if_true: files('dbus-vmstate.c'))
system_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c')) system_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c'))
system_ss.add(when: 'CONFIG_SPDM_SOCKET', if_true: files('spdm-socket.c'))
subdir('tpm') subdir('tpm')

View File

@ -75,10 +75,7 @@ static void rng_random_opened(RngBackend *b, Error **errp)
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
"filename", "a valid filename"); "filename", "a valid filename");
} else { } else {
s->fd = qemu_open_old(s->filename, O_RDONLY | O_NONBLOCK); s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK, errp);
if (s->fd == -1) {
error_setg_file_open(errp, errno, s->filename);
}
} }
} }

216
backends/spdm-socket.c Normal file
View File

@ -0,0 +1,216 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
* QEMU SPDM socket support
*
* This is based on:
* https://github.com/DMTF/spdm-emu/blob/07c0a838bcc1c6207c656ac75885c0603e344b6f/spdm_emu/spdm_emu_common/command.c
* but has been re-written to match QEMU style
*
* Copyright (c) 2021, DMTF. All rights reserved.
* Copyright (c) 2023. Western Digital Corporation or its affiliates.
*/
#include "qemu/osdep.h"
#include "sysemu/spdm-socket.h"
#include "qapi/error.h"
static bool read_bytes(const int socket, uint8_t *buffer,
size_t number_of_bytes)
{
ssize_t number_received = 0;
ssize_t result;
while (number_received < number_of_bytes) {
result = recv(socket, buffer + number_received,
number_of_bytes - number_received, 0);
if (result <= 0) {
return false;
}
number_received += result;
}
return true;
}
static bool read_data32(const int socket, uint32_t *data)
{
bool result;
result = read_bytes(socket, (uint8_t *)data, sizeof(uint32_t));
if (!result) {
return result;
}
*data = ntohl(*data);
return true;
}
static bool read_multiple_bytes(const int socket, uint8_t *buffer,
uint32_t *bytes_received,
uint32_t max_buffer_length)
{
uint32_t length;
bool result;
result = read_data32(socket, &length);
if (!result) {
return result;
}
if (length > max_buffer_length) {
return false;
}
if (bytes_received) {
*bytes_received = length;
}
if (length == 0) {
return true;
}
return read_bytes(socket, buffer, length);
}
static bool receive_platform_data(const int socket,
uint32_t transport_type,
uint32_t *command,
uint8_t *receive_buffer,
uint32_t *bytes_to_receive)
{
bool result;
uint32_t response;
uint32_t bytes_received;
result = read_data32(socket, &response);
if (!result) {
return result;
}
*command = response;
result = read_data32(socket, &transport_type);
if (!result) {
return result;
}
bytes_received = 0;
result = read_multiple_bytes(socket, receive_buffer, &bytes_received,
*bytes_to_receive);
if (!result) {
return result;
}
*bytes_to_receive = bytes_received;
return result;
}
static bool write_bytes(const int socket, const uint8_t *buffer,
uint32_t number_of_bytes)
{
ssize_t number_sent = 0;
ssize_t result;
while (number_sent < number_of_bytes) {
result = send(socket, buffer + number_sent,
number_of_bytes - number_sent, 0);
if (result == -1) {
return false;
}
number_sent += result;
}
return true;
}
static bool write_data32(const int socket, uint32_t data)
{
data = htonl(data);
return write_bytes(socket, (uint8_t *)&data, sizeof(uint32_t));
}
static bool write_multiple_bytes(const int socket, const uint8_t *buffer,
uint32_t bytes_to_send)
{
bool result;
result = write_data32(socket, bytes_to_send);
if (!result) {
return result;
}
return write_bytes(socket, buffer, bytes_to_send);
}
static bool send_platform_data(const int socket,
uint32_t transport_type, uint32_t command,
const uint8_t *send_buffer, size_t bytes_to_send)
{
bool result;
result = write_data32(socket, command);
if (!result) {
return result;
}
result = write_data32(socket, transport_type);
if (!result) {
return result;
}
return write_multiple_bytes(socket, send_buffer, bytes_to_send);
}
int spdm_socket_connect(uint16_t port, Error **errp)
{
int client_socket;
struct sockaddr_in server_addr;
client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client_socket < 0) {
error_setg(errp, "cannot create socket: %s", strerror(errno));
return -1;
}
memset((char *)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
server_addr.sin_port = htons(port);
if (connect(client_socket, (struct sockaddr *)&server_addr,
sizeof(server_addr)) < 0) {
error_setg(errp, "cannot connect: %s", strerror(errno));
close(client_socket);
return -1;
}
return client_socket;
}
uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type,
void *req, uint32_t req_len,
void *rsp, uint32_t rsp_len)
{
uint32_t command;
bool result;
result = send_platform_data(socket, transport_type,
SPDM_SOCKET_COMMAND_NORMAL,
req, req_len);
if (!result) {
return 0;
}
result = receive_platform_data(socket, transport_type, &command,
(uint8_t *)rsp, &rsp_len);
if (!result) {
return 0;
}
assert(command != 0);
return rsp_len;
}
void spdm_socket_close(const int socket, uint32_t transport_type)
{
send_platform_data(socket, transport_type,
SPDM_SOCKET_COMMAND_SHUTDOWN, NULL, 0);
}

View File

@ -339,10 +339,11 @@ void tpm_util_show_buffer(const unsigned char *buffer,
size_t len, i; size_t len, i;
char *line_buffer, *p; char *line_buffer, *p;
if (!trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) { if (!trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER_CONTENT)) {
return; return;
} }
len = MIN(tpm_cmd_get_size(buffer), buffer_size); len = MIN(tpm_cmd_get_size(buffer), buffer_size);
trace_tpm_util_show_buffer_header(string, len);
/* /*
* allocate enough room for 3 chars per buffer entry plus a * allocate enough room for 3 chars per buffer entry plus a
@ -356,7 +357,7 @@ void tpm_util_show_buffer(const unsigned char *buffer,
} }
p += sprintf(p, "%.2X ", buffer[i]); p += sprintf(p, "%.2X ", buffer[i]);
} }
trace_tpm_util_show_buffer(string, len, line_buffer); trace_tpm_util_show_buffer_content(line_buffer);
g_free(line_buffer); g_free(line_buffer);
} }

View File

@ -10,7 +10,8 @@ tpm_util_get_buffer_size_len(uint32_t len, size_t expected) "tpm_resp->len = %u,
tpm_util_get_buffer_size_hdr_len2(uint32_t len, size_t expected) "tpm2_resp->hdr.len = %u, expected = %zu" tpm_util_get_buffer_size_hdr_len2(uint32_t len, size_t expected) "tpm2_resp->hdr.len = %u, expected = %zu"
tpm_util_get_buffer_size_len2(uint32_t len, size_t expected) "tpm2_resp->len = %u, expected = %zu" tpm_util_get_buffer_size_len2(uint32_t len, size_t expected) "tpm2_resp->len = %u, expected = %zu"
tpm_util_get_buffer_size(size_t len) "buffersize of device: %zu" tpm_util_get_buffer_size(size_t len) "buffersize of device: %zu"
tpm_util_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s" tpm_util_show_buffer_header(const char *direction, size_t len) "direction: %s len: %zu"
tpm_util_show_buffer_content(const char *buf) "%s"
# tpm_emulator.c # tpm_emulator.c
tpm_emulator_set_locality(uint8_t locty) "setting locality to %d" tpm_emulator_set_locality(uint8_t locty) "setting locality to %d"

View File

@ -7,11 +7,14 @@ dbus_vmstate_loading(const char *id) "id: %s"
dbus_vmstate_saving(const char *id) "id: %s" dbus_vmstate_saving(const char *id) "id: %s"
# iommufd.c # iommufd.c
iommufd_backend_connect(int fd, bool owned, uint32_t users, int ret) "fd=%d owned=%d users=%d (%d)" iommufd_backend_connect(int fd, bool owned, uint32_t users) "fd=%d owned=%d users=%d"
iommufd_backend_disconnect(int fd, uint32_t users) "fd=%d users=%d" iommufd_backend_disconnect(int fd, uint32_t users) "fd=%d users=%d"
iommu_backend_set_fd(int fd) "pre-opened /dev/iommu fd=%d" iommu_backend_set_fd(int fd) "pre-opened /dev/iommu fd=%d"
iommufd_backend_map_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, void *vaddr, bool readonly, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" addr=%p readonly=%d (%d)" iommufd_backend_map_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, void *vaddr, bool readonly, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" addr=%p readonly=%d (%d)"
iommufd_backend_unmap_dma_non_exist(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " Unmap nonexistent mapping: iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)" iommufd_backend_unmap_dma_non_exist(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " Unmap nonexistent mapping: iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)"
iommufd_backend_unmap_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)" iommufd_backend_unmap_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)"
iommufd_backend_alloc_ioas(int iommufd, uint32_t ioas, int ret) " iommufd=%d ioas=%d (%d)" iommufd_backend_alloc_ioas(int iommufd, uint32_t ioas) " iommufd=%d ioas=%d"
iommufd_backend_alloc_hwpt(int iommufd, uint32_t dev_id, uint32_t pt_id, uint32_t flags, uint32_t hwpt_type, uint32_t len, uint64_t data_ptr, uint32_t out_hwpt_id, int ret) " iommufd=%d dev_id=%u pt_id=%u flags=0x%x hwpt_type=%u len=%u data_ptr=0x%"PRIx64" out_hwpt=%u (%d)"
iommufd_backend_free_id(int iommufd, uint32_t id, int ret) " iommufd=%d id=%d (%d)" iommufd_backend_free_id(int iommufd, uint32_t id, int ret) " iommufd=%d id=%d (%d)"
iommufd_backend_set_dirty(int iommufd, uint32_t hwpt_id, bool start, int ret) " iommufd=%d hwpt=%u enable=%d (%d)"
iommufd_backend_get_dirty_bitmap(int iommufd, uint32_t hwpt_id, uint64_t iova, uint64_t size, uint64_t page_size, int ret) " iommufd=%d hwpt=%u iova=0x%"PRIx64" size=0x%"PRIx64" page_size=0x%"PRIx64" (%d)"

15
block.c
View File

@ -927,7 +927,6 @@ BlockDriver *bdrv_find_protocol(const char *filename,
int i; int i;
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
/* TODO Drivers without bdrv_file_open must be specified explicitly */
/* /*
* XXX(hch): we really should not let host device detection * XXX(hch): we really should not let host device detection
@ -1656,10 +1655,8 @@ bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name,
bs->drv = drv; bs->drv = drv;
bs->opaque = g_malloc0(drv->instance_size); bs->opaque = g_malloc0(drv->instance_size);
if (drv->bdrv_file_open) {
assert(!drv->bdrv_needs_filename || bs->filename[0]); assert(!drv->bdrv_needs_filename || bs->filename[0]);
ret = drv->bdrv_file_open(bs, options, open_flags, &local_err); if (drv->bdrv_open) {
} else if (drv->bdrv_open) {
ret = drv->bdrv_open(bs, options, open_flags, &local_err); ret = drv->bdrv_open(bs, options, open_flags, &local_err);
} else { } else {
ret = 0; ret = 0;
@ -1984,7 +1981,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
open_flags = bdrv_open_flags(bs, bs->open_flags); open_flags = bdrv_open_flags(bs, bs->open_flags);
node_name = qemu_opt_get(opts, "node-name"); node_name = qemu_opt_get(opts, "node-name");
assert(!drv->bdrv_file_open || file == NULL); assert(!drv->protocol_name || file == NULL);
ret = bdrv_open_driver(bs, drv, node_name, options, open_flags, errp); ret = bdrv_open_driver(bs, drv, node_name, options, open_flags, errp);
if (ret < 0) { if (ret < 0) {
goto fail_opts; goto fail_opts;
@ -2086,7 +2083,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
} }
/* If the user has explicitly specified the driver, this choice should /* If the user has explicitly specified the driver, this choice should
* override the BDRV_O_PROTOCOL flag */ * override the BDRV_O_PROTOCOL flag */
protocol = drv->bdrv_file_open; protocol = drv->protocol_name;
} }
if (protocol) { if (protocol) {
@ -4147,7 +4144,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
} }
/* BDRV_O_PROTOCOL must be set iff a protocol BDS is about to be created */ /* BDRV_O_PROTOCOL must be set iff a protocol BDS is about to be created */
assert(!!(flags & BDRV_O_PROTOCOL) == !!drv->bdrv_file_open); assert(!!(flags & BDRV_O_PROTOCOL) == !!drv->protocol_name);
/* file must be NULL if a protocol BDS is about to be created /* file must be NULL if a protocol BDS is about to be created
* (the inverse results in an error message from bdrv_open_common()) */ * (the inverse results in an error message from bdrv_open_common()) */
assert(!(flags & BDRV_O_PROTOCOL) || !file); assert(!(flags & BDRV_O_PROTOCOL) || !file);
@ -5995,7 +5992,7 @@ int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs)
return drv->bdrv_co_get_allocated_file_size(bs); return drv->bdrv_co_get_allocated_file_size(bs);
} }
if (drv->bdrv_file_open) { if (drv->protocol_name) {
/* /*
* Protocol drivers default to -ENOTSUP (most of their data is * Protocol drivers default to -ENOTSUP (most of their data is
* not stored in any of their children (if they even have any), * not stored in any of their children (if they even have any),
@ -8054,7 +8051,7 @@ void bdrv_refresh_filename(BlockDriverState *bs)
* Both of these conditions are represented by generate_json_filename. * Both of these conditions are represented by generate_json_filename.
*/ */
if (primary_child_bs->exact_filename[0] && if (primary_child_bs->exact_filename[0] &&
primary_child_bs->drv->bdrv_file_open && primary_child_bs->drv->protocol_name &&
!drv->is_filter && !generate_json_filename) !drv->is_filter && !generate_json_filename)
{ {
strcpy(bs->exact_filename, primary_child_bs->exact_filename); strcpy(bs->exact_filename, primary_child_bs->exact_filename);

View File

@ -356,7 +356,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
BlockDriverState *target, int64_t speed, BlockDriverState *target, int64_t speed,
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap, MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
BitmapSyncMode bitmap_mode, BitmapSyncMode bitmap_mode,
bool compress, bool compress, bool discard_source,
const char *filter_node_name, const char *filter_node_name,
BackupPerf *perf, BackupPerf *perf,
BlockdevOnError on_source_error, BlockdevOnError on_source_error,
@ -457,7 +457,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
goto error; goto error;
} }
cbw = bdrv_cbw_append(bs, target, filter_node_name, &bcs, errp); cbw = bdrv_cbw_append(bs, target, filter_node_name, discard_source,
&bcs, errp);
if (!cbw) { if (!cbw) {
goto error; goto error;
} }

View File

@ -1073,7 +1073,7 @@ static BlockDriver bdrv_blkdebug = {
.is_filter = true, .is_filter = true,
.bdrv_parse_filename = blkdebug_parse_filename, .bdrv_parse_filename = blkdebug_parse_filename,
.bdrv_file_open = blkdebug_open, .bdrv_open = blkdebug_open,
.bdrv_close = blkdebug_close, .bdrv_close = blkdebug_close,
.bdrv_reopen_prepare = blkdebug_reopen_prepare, .bdrv_reopen_prepare = blkdebug_reopen_prepare,
.bdrv_child_perm = blkdebug_child_perm, .bdrv_child_perm = blkdebug_child_perm,

View File

@ -713,7 +713,7 @@ static int blkio_virtio_blk_connect(BlockDriverState *bs, QDict *options,
* for example will fail. * for example will fail.
* *
* In order to open the device read-only, we are using the `read-only` * In order to open the device read-only, we are using the `read-only`
* property of the libblkio driver in blkio_file_open(). * property of the libblkio driver in blkio_open().
*/ */
fd = qemu_open(path, O_RDWR, NULL); fd = qemu_open(path, O_RDWR, NULL);
if (fd < 0) { if (fd < 0) {
@ -791,7 +791,7 @@ static int blkio_virtio_blk_connect(BlockDriverState *bs, QDict *options,
return 0; return 0;
} }
static int blkio_file_open(BlockDriverState *bs, QDict *options, int flags, static int blkio_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp) Error **errp)
{ {
const char *blkio_driver = bs->drv->protocol_name; const char *blkio_driver = bs->drv->protocol_name;
@ -899,8 +899,10 @@ static int blkio_file_open(BlockDriverState *bs, QDict *options, int flags,
} }
bs->supported_write_flags = BDRV_REQ_FUA | BDRV_REQ_REGISTERED_BUF; bs->supported_write_flags = BDRV_REQ_FUA | BDRV_REQ_REGISTERED_BUF;
bs->supported_zero_flags = BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
BDRV_REQ_NO_FALLBACK; #ifdef CONFIG_BLKIO_WRITE_ZEROS_FUA
bs->supported_zero_flags |= BDRV_REQ_FUA;
#endif
qemu_mutex_init(&s->blkio_lock); qemu_mutex_init(&s->blkio_lock);
qemu_co_mutex_init(&s->bounce_lock); qemu_co_mutex_init(&s->bounce_lock);
@ -1088,7 +1090,7 @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
*/ */
#define BLKIO_DRIVER_COMMON \ #define BLKIO_DRIVER_COMMON \
.instance_size = sizeof(BDRVBlkioState), \ .instance_size = sizeof(BDRVBlkioState), \
.bdrv_file_open = blkio_file_open, \ .bdrv_open = blkio_open, \
.bdrv_close = blkio_close, \ .bdrv_close = blkio_close, \
.bdrv_co_getlength = blkio_co_getlength, \ .bdrv_co_getlength = blkio_co_getlength, \
.bdrv_co_truncate = blkio_truncate, \ .bdrv_co_truncate = blkio_truncate, \

View File

@ -321,7 +321,7 @@ static BlockDriver bdrv_blkverify = {
.instance_size = sizeof(BDRVBlkverifyState), .instance_size = sizeof(BDRVBlkverifyState),
.bdrv_parse_filename = blkverify_parse_filename, .bdrv_parse_filename = blkverify_parse_filename,
.bdrv_file_open = blkverify_open, .bdrv_open = blkverify_open,
.bdrv_close = blkverify_close, .bdrv_close = blkverify_close,
.bdrv_child_perm = bdrv_default_perms, .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_getlength = blkverify_co_getlength, .bdrv_co_getlength = blkverify_co_getlength,

View File

@ -137,6 +137,7 @@ typedef struct BlockCopyState {
CoMutex lock; CoMutex lock;
int64_t in_flight_bytes; int64_t in_flight_bytes;
BlockCopyMethod method; BlockCopyMethod method;
bool discard_source;
BlockReqList reqs; BlockReqList reqs;
QLIST_HEAD(, BlockCopyCallState) calls; QLIST_HEAD(, BlockCopyCallState) calls;
/* /*
@ -351,7 +352,9 @@ static int64_t block_copy_calculate_cluster_size(BlockDriverState *target,
} }
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target, BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
BlockDriverState *copy_bitmap_bs,
const BdrvDirtyBitmap *bitmap, const BdrvDirtyBitmap *bitmap,
bool discard_source,
Error **errp) Error **errp)
{ {
ERRP_GUARD(); ERRP_GUARD();
@ -367,7 +370,7 @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
return NULL; return NULL;
} }
copy_bitmap = bdrv_create_dirty_bitmap(source->bs, cluster_size, NULL, copy_bitmap = bdrv_create_dirty_bitmap(copy_bitmap_bs, cluster_size, NULL,
errp); errp);
if (!copy_bitmap) { if (!copy_bitmap) {
return NULL; return NULL;
@ -417,6 +420,7 @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
cluster_size), cluster_size),
}; };
s->discard_source = discard_source;
block_copy_set_copy_opts(s, false, false); block_copy_set_copy_opts(s, false, false);
ratelimit_init(&s->rate_limit); ratelimit_init(&s->rate_limit);
@ -588,6 +592,14 @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
co_put_to_shres(s->mem, t->req.bytes); co_put_to_shres(s->mem, t->req.bytes);
block_copy_task_end(t, ret); block_copy_task_end(t, ret);
if (s->discard_source && ret == 0) {
int64_t nbytes =
MIN(t->req.offset + t->req.bytes, s->len) - t->req.offset;
WITH_GRAPH_RDLOCK_GUARD() {
bdrv_co_pdiscard(s->source, t->req.offset, nbytes);
}
}
return ret; return ret;
} }

View File

@ -43,7 +43,8 @@ typedef struct BDRVCopyBeforeWriteState {
BlockCopyState *bcs; BlockCopyState *bcs;
BdrvChild *target; BdrvChild *target;
OnCbwError on_cbw_error; OnCbwError on_cbw_error;
uint32_t cbw_timeout_ns; uint64_t cbw_timeout_ns;
bool discard_source;
/* /*
* @lock: protects access to @access_bitmap, @done_bitmap and * @lock: protects access to @access_bitmap, @done_bitmap and
@ -65,7 +66,8 @@ typedef struct BDRVCopyBeforeWriteState {
/* /*
* @frozen_read_reqs: current read requests for fleecing user in bs->file * @frozen_read_reqs: current read requests for fleecing user in bs->file
* node. These areas must not be rewritten by guest. * node. These areas must not be rewritten by guest. There can be multiple
* overlapping read requests.
*/ */
BlockReqList frozen_read_reqs; BlockReqList frozen_read_reqs;
@ -325,14 +327,24 @@ static int coroutine_fn GRAPH_RDLOCK
cbw_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes) cbw_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes)
{ {
BDRVCopyBeforeWriteState *s = bs->opaque; BDRVCopyBeforeWriteState *s = bs->opaque;
uint32_t cluster_size = block_copy_cluster_size(s->bcs);
int64_t aligned_offset = QEMU_ALIGN_UP(offset, cluster_size);
int64_t aligned_end = QEMU_ALIGN_DOWN(offset + bytes, cluster_size);
int64_t aligned_bytes;
if (aligned_end <= aligned_offset) {
return 0;
}
aligned_bytes = aligned_end - aligned_offset;
WITH_QEMU_LOCK_GUARD(&s->lock) { WITH_QEMU_LOCK_GUARD(&s->lock) {
bdrv_reset_dirty_bitmap(s->access_bitmap, offset, bytes); bdrv_reset_dirty_bitmap(s->access_bitmap, aligned_offset,
aligned_bytes);
} }
block_copy_reset(s->bcs, offset, bytes); block_copy_reset(s->bcs, aligned_offset, aligned_bytes);
return bdrv_co_pdiscard(s->target, offset, bytes); return bdrv_co_pdiscard(s->target, aligned_offset, aligned_bytes);
} }
static void GRAPH_RDLOCK cbw_refresh_filename(BlockDriverState *bs) static void GRAPH_RDLOCK cbw_refresh_filename(BlockDriverState *bs)
@ -347,6 +359,8 @@ cbw_child_perm(BlockDriverState *bs, BdrvChild *c, BdrvChildRole role,
uint64_t perm, uint64_t shared, uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared) uint64_t *nperm, uint64_t *nshared)
{ {
BDRVCopyBeforeWriteState *s = bs->opaque;
if (!(role & BDRV_CHILD_FILTERED)) { if (!(role & BDRV_CHILD_FILTERED)) {
/* /*
* Target child * Target child
@ -364,9 +378,17 @@ cbw_child_perm(BlockDriverState *bs, BdrvChild *c, BdrvChildRole role,
perm, shared, nperm, nshared); perm, shared, nperm, nshared);
if (!QLIST_EMPTY(&bs->parents)) { if (!QLIST_EMPTY(&bs->parents)) {
if (perm & BLK_PERM_WRITE) { /*
* Note, that source child may be shared with backup job. Backup job
* does create own blk parent on copy-before-write node, so this
* works even if source node does not have any parents before backup
* start
*/
*nperm = *nperm | BLK_PERM_CONSISTENT_READ; *nperm = *nperm | BLK_PERM_CONSISTENT_READ;
if (s->discard_source) {
*nperm = *nperm | BLK_PERM_WRITE;
} }
*nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
} }
} }
@ -454,7 +476,9 @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
bs->file->bs->supported_zero_flags); bs->file->bs->supported_zero_flags);
s->bcs = block_copy_state_new(bs->file, s->target, bitmap, errp); s->discard_source = flags & BDRV_O_CBW_DISCARD_SOURCE;
s->bcs = block_copy_state_new(bs->file, s->target, bs, bitmap,
flags & BDRV_O_CBW_DISCARD_SOURCE, errp);
if (!s->bcs) { if (!s->bcs) {
error_prepend(errp, "Cannot create block-copy-state: "); error_prepend(errp, "Cannot create block-copy-state: ");
return -EINVAL; return -EINVAL;
@ -521,12 +545,14 @@ static BlockDriver bdrv_cbw_filter = {
BlockDriverState *bdrv_cbw_append(BlockDriverState *source, BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
BlockDriverState *target, BlockDriverState *target,
const char *filter_node_name, const char *filter_node_name,
bool discard_source,
BlockCopyState **bcs, BlockCopyState **bcs,
Error **errp) Error **errp)
{ {
BDRVCopyBeforeWriteState *state; BDRVCopyBeforeWriteState *state;
BlockDriverState *top; BlockDriverState *top;
QDict *opts; QDict *opts;
int flags = BDRV_O_RDWR | (discard_source ? BDRV_O_CBW_DISCARD_SOURCE : 0);
assert(source->total_sectors == target->total_sectors); assert(source->total_sectors == target->total_sectors);
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
@ -539,7 +565,7 @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
qdict_put_str(opts, "file", bdrv_get_node_name(source)); qdict_put_str(opts, "file", bdrv_get_node_name(source));
qdict_put_str(opts, "target", bdrv_get_node_name(target)); qdict_put_str(opts, "target", bdrv_get_node_name(target));
top = bdrv_insert_node(source, opts, BDRV_O_RDWR, errp); top = bdrv_insert_node(source, opts, flags, errp);
if (!top) { if (!top) {
return NULL; return NULL;
} }

View File

@ -39,6 +39,7 @@
BlockDriverState *bdrv_cbw_append(BlockDriverState *source, BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
BlockDriverState *target, BlockDriverState *target,
const char *filter_node_name, const char *filter_node_name,
bool discard_source,
BlockCopyState **bcs, BlockCopyState **bcs,
Error **errp); Error **errp);
void bdrv_cbw_drop(BlockDriverState *bs); void bdrv_cbw_drop(BlockDriverState *bs);

View File

@ -363,7 +363,6 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
block_crypto_read_func, block_crypto_read_func,
bs, bs,
cflags, cflags,
1,
errp); errp);
if (!crypto->block) { if (!crypto->block) {

View File

@ -210,36 +210,28 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
{ {
BDRVCURLState *s = opaque; BDRVCURLState *s = opaque;
size_t realsize = size * nmemb; size_t realsize = size * nmemb;
const char *header = (char *)ptr; const char *p = ptr;
const char *end = header + realsize; const char *end = p + realsize;
const char *accept_ranges = "accept-ranges:"; const char *t = "accept-ranges : bytes "; /* A lowercase template */
const char *bytes = "bytes";
if (realsize >= strlen(accept_ranges) /* check if header matches the "t" template */
&& g_ascii_strncasecmp(header, accept_ranges, for (;;) {
strlen(accept_ranges)) == 0) { if (*t == ' ') { /* space in t matches any amount of isspace in p */
if (p < end && g_ascii_isspace(*p)) {
char *p = strchr(header, ':') + 1; ++p;
} else {
/* Skip whitespace between the header name and value. */ ++t;
while (p < end && *p && g_ascii_isspace(*p)) { }
p++; } else if (*t && p < end && *t == g_ascii_tolower(*p)) {
++p, ++t;
} else {
break;
}
} }
if (end - p >= strlen(bytes) if (!*t && p == end) { /* if we managed to reach ends of both strings */
&& strncmp(p, bytes, strlen(bytes)) == 0) {
/* Check that there is nothing but whitespace after the value. */
p += strlen(bytes);
while (p < end && *p && g_ascii_isspace(*p)) {
p++;
}
if (p == end || !*p) {
s->accept_range = true; s->accept_range = true;
} }
}
}
return realsize; return realsize;
} }
@ -1034,7 +1026,7 @@ static BlockDriver bdrv_http = {
.instance_size = sizeof(BDRVCURLState), .instance_size = sizeof(BDRVCURLState),
.bdrv_parse_filename = curl_parse_filename, .bdrv_parse_filename = curl_parse_filename,
.bdrv_file_open = curl_open, .bdrv_open = curl_open,
.bdrv_close = curl_close, .bdrv_close = curl_close,
.bdrv_co_getlength = curl_co_getlength, .bdrv_co_getlength = curl_co_getlength,
@ -1053,7 +1045,7 @@ static BlockDriver bdrv_https = {
.instance_size = sizeof(BDRVCURLState), .instance_size = sizeof(BDRVCURLState),
.bdrv_parse_filename = curl_parse_filename, .bdrv_parse_filename = curl_parse_filename,
.bdrv_file_open = curl_open, .bdrv_open = curl_open,
.bdrv_close = curl_close, .bdrv_close = curl_close,
.bdrv_co_getlength = curl_co_getlength, .bdrv_co_getlength = curl_co_getlength,
@ -1072,7 +1064,7 @@ static BlockDriver bdrv_ftp = {
.instance_size = sizeof(BDRVCURLState), .instance_size = sizeof(BDRVCURLState),
.bdrv_parse_filename = curl_parse_filename, .bdrv_parse_filename = curl_parse_filename,
.bdrv_file_open = curl_open, .bdrv_open = curl_open,
.bdrv_close = curl_close, .bdrv_close = curl_close,
.bdrv_co_getlength = curl_co_getlength, .bdrv_co_getlength = curl_co_getlength,
@ -1091,7 +1083,7 @@ static BlockDriver bdrv_ftps = {
.instance_size = sizeof(BDRVCURLState), .instance_size = sizeof(BDRVCURLState),
.bdrv_parse_filename = curl_parse_filename, .bdrv_parse_filename = curl_parse_filename,
.bdrv_file_open = curl_open, .bdrv_open = curl_open,
.bdrv_close = curl_close, .bdrv_close = curl_close,
.bdrv_co_getlength = curl_co_getlength, .bdrv_co_getlength = curl_co_getlength,

View File

@ -159,6 +159,7 @@ typedef struct BDRVRawState {
bool has_discard:1; bool has_discard:1;
bool has_write_zeroes:1; bool has_write_zeroes:1;
bool use_linux_aio:1; bool use_linux_aio:1;
bool has_laio_fdsync:1;
bool use_linux_io_uring:1; bool use_linux_io_uring:1;
int page_cache_inconsistent; /* errno from fdatasync failure */ int page_cache_inconsistent; /* errno from fdatasync failure */
bool has_fallocate; bool has_fallocate;
@ -718,6 +719,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
if (s->use_linux_aio) {
s->has_laio_fdsync = laio_has_fdsync(s->fd);
}
#else #else
if (s->use_linux_aio) { if (s->use_linux_aio) {
error_setg(errp, "aio=native was specified, but is not supported " error_setg(errp, "aio=native was specified, but is not supported "
@ -1039,8 +1043,7 @@ static int fcntl_setfl(int fd, int flag)
} }
static int raw_reconfigure_getfd(BlockDriverState *bs, int flags, static int raw_reconfigure_getfd(BlockDriverState *bs, int flags,
int *open_flags, uint64_t perm, bool force_dup, int *open_flags, uint64_t perm, Error **errp)
Error **errp)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
int fd = -1; int fd = -1;
@ -1068,7 +1071,7 @@ static int raw_reconfigure_getfd(BlockDriverState *bs, int flags,
assert((s->open_flags & O_ASYNC) == 0); assert((s->open_flags & O_ASYNC) == 0);
#endif #endif
if (!force_dup && *open_flags == s->open_flags) { if (*open_flags == s->open_flags) {
/* We're lucky, the existing fd is fine */ /* We're lucky, the existing fd is fine */
return s->fd; return s->fd;
} }
@ -2599,6 +2602,11 @@ static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
if (raw_check_linux_io_uring(s)) { if (raw_check_linux_io_uring(s)) {
return luring_co_submit(bs, s->fd, 0, NULL, QEMU_AIO_FLUSH); return luring_co_submit(bs, s->fd, 0, NULL, QEMU_AIO_FLUSH);
} }
#endif
#ifdef CONFIG_LINUX_AIO
if (s->has_laio_fdsync && raw_check_linux_aio(s)) {
return laio_co_submit(s->fd, 0, NULL, QEMU_AIO_FLUSH, 0);
}
#endif #endif
return raw_thread_pool_submit(handle_aiocb_flush, &acb); return raw_thread_pool_submit(handle_aiocb_flush, &acb);
} }
@ -3748,8 +3756,7 @@ static int raw_check_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared,
int ret; int ret;
/* We may need a new fd if auto-read-only switches the mode */ /* We may need a new fd if auto-read-only switches the mode */
ret = raw_reconfigure_getfd(bs, input_flags, &open_flags, perm, ret = raw_reconfigure_getfd(bs, input_flags, &open_flags, perm, errp);
false, errp);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} else if (ret != s->fd) { } else if (ret != s->fd) {
@ -3879,7 +3886,7 @@ BlockDriver bdrv_file = {
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_probe = NULL, /* no probe for protocols */ .bdrv_probe = NULL, /* no probe for protocols */
.bdrv_parse_filename = raw_parse_filename, .bdrv_parse_filename = raw_parse_filename,
.bdrv_file_open = raw_open, .bdrv_open = raw_open,
.bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort, .bdrv_reopen_abort = raw_reopen_abort,
@ -3922,11 +3929,6 @@ BlockDriver bdrv_file = {
static kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath, static kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath,
CFIndex maxPathSize, int flags); CFIndex maxPathSize, int flags);
#if !defined(MAC_OS_VERSION_12_0) \
|| (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0)
#define IOMainPort IOMasterPort
#endif
static char *FindEjectableOpticalMedia(io_iterator_t *mediaIterator) static char *FindEjectableOpticalMedia(io_iterator_t *mediaIterator)
{ {
kern_return_t kernResult = KERN_FAILURE; kern_return_t kernResult = KERN_FAILURE;
@ -4250,7 +4252,7 @@ static BlockDriver bdrv_host_device = {
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_probe_device = hdev_probe_device, .bdrv_probe_device = hdev_probe_device,
.bdrv_parse_filename = hdev_parse_filename, .bdrv_parse_filename = hdev_parse_filename,
.bdrv_file_open = hdev_open, .bdrv_open = hdev_open,
.bdrv_close = raw_close, .bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_commit = raw_reopen_commit,
@ -4389,7 +4391,7 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_probe_device = cdrom_probe_device, .bdrv_probe_device = cdrom_probe_device,
.bdrv_parse_filename = cdrom_parse_filename, .bdrv_parse_filename = cdrom_parse_filename,
.bdrv_file_open = cdrom_open, .bdrv_open = cdrom_open,
.bdrv_close = raw_close, .bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_commit = raw_reopen_commit,
@ -4515,7 +4517,7 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_probe_device = cdrom_probe_device, .bdrv_probe_device = cdrom_probe_device,
.bdrv_parse_filename = cdrom_parse_filename, .bdrv_parse_filename = cdrom_parse_filename,
.bdrv_file_open = cdrom_open, .bdrv_open = cdrom_open,
.bdrv_close = raw_close, .bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare, .bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit, .bdrv_reopen_commit = raw_reopen_commit,

View File

@ -746,7 +746,7 @@ BlockDriver bdrv_file = {
.instance_size = sizeof(BDRVRawState), .instance_size = sizeof(BDRVRawState),
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_parse_filename = raw_parse_filename, .bdrv_parse_filename = raw_parse_filename,
.bdrv_file_open = raw_open, .bdrv_open = raw_open,
.bdrv_refresh_limits = raw_probe_alignment, .bdrv_refresh_limits = raw_probe_alignment,
.bdrv_close = raw_close, .bdrv_close = raw_close,
.bdrv_co_create_opts = raw_co_create_opts, .bdrv_co_create_opts = raw_co_create_opts,
@ -920,7 +920,7 @@ static BlockDriver bdrv_host_device = {
.bdrv_needs_filename = true, .bdrv_needs_filename = true,
.bdrv_parse_filename = hdev_parse_filename, .bdrv_parse_filename = hdev_parse_filename,
.bdrv_probe_device = hdev_probe_device, .bdrv_probe_device = hdev_probe_device,
.bdrv_file_open = hdev_open, .bdrv_open = hdev_open,
.bdrv_close = raw_close, .bdrv_close = raw_close,
.bdrv_refresh_limits = hdev_refresh_limits, .bdrv_refresh_limits = hdev_refresh_limits,

View File

@ -17,7 +17,6 @@
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qemu/uri.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/option.h" #include "qemu/option.h"
@ -289,9 +288,9 @@ static void glfs_clear_preopened(glfs_t *fs)
} }
} }
static int parse_volume_options(BlockdevOptionsGluster *gconf, char *path) static int parse_volume_options(BlockdevOptionsGluster *gconf, const char *path)
{ {
char *p, *q; const char *p, *q;
if (!path) { if (!path) {
return -EINVAL; return -EINVAL;
@ -349,13 +348,13 @@ static int parse_volume_options(BlockdevOptionsGluster *gconf, char *path)
static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf, static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
const char *filename) const char *filename)
{ {
g_autoptr(GUri) uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
g_autoptr(GHashTable) qp = NULL;
SocketAddress *gsconf; SocketAddress *gsconf;
URI *uri;
QueryParams *qp = NULL;
bool is_unix = false; bool is_unix = false;
int ret = 0; const char *uri_scheme, *uri_query, *uri_server;
int uri_port, ret;
uri = uri_parse(filename);
if (!uri) { if (!uri) {
return -EINVAL; return -EINVAL;
} }
@ -364,57 +363,54 @@ static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
QAPI_LIST_PREPEND(gconf->server, gsconf); QAPI_LIST_PREPEND(gconf->server, gsconf);
/* transport */ /* transport */
if (!uri->scheme || !strcmp(uri->scheme, "gluster")) { uri_scheme = g_uri_get_scheme(uri);
if (!uri_scheme || !strcmp(uri_scheme, "gluster")) {
gsconf->type = SOCKET_ADDRESS_TYPE_INET; gsconf->type = SOCKET_ADDRESS_TYPE_INET;
} else if (!strcmp(uri->scheme, "gluster+tcp")) { } else if (!strcmp(uri_scheme, "gluster+tcp")) {
gsconf->type = SOCKET_ADDRESS_TYPE_INET; gsconf->type = SOCKET_ADDRESS_TYPE_INET;
} else if (!strcmp(uri->scheme, "gluster+unix")) { } else if (!strcmp(uri_scheme, "gluster+unix")) {
gsconf->type = SOCKET_ADDRESS_TYPE_UNIX; gsconf->type = SOCKET_ADDRESS_TYPE_UNIX;
is_unix = true; is_unix = true;
} else if (!strcmp(uri->scheme, "gluster+rdma")) {
gsconf->type = SOCKET_ADDRESS_TYPE_INET;
warn_report("rdma feature is not supported, falling back to tcp");
} else { } else {
ret = -EINVAL; return -EINVAL;
goto out;
} }
ret = parse_volume_options(gconf, uri->path); ret = parse_volume_options(gconf, g_uri_get_path(uri));
if (ret < 0) { if (ret < 0) {
goto out; return ret;
} }
qp = query_params_parse(uri->query); uri_query = g_uri_get_query(uri);
if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) { if (uri_query) {
ret = -EINVAL; qp = g_uri_parse_params(uri_query, -1, "&", G_URI_PARAMS_NONE, NULL);
goto out; if (!qp) {
return -EINVAL;
} }
ret = g_hash_table_size(qp);
if (ret > 1 || (is_unix && !ret) || (!is_unix && ret)) {
return -EINVAL;
}
}
uri_server = g_uri_get_host(uri);
uri_port = g_uri_get_port(uri);
if (is_unix) { if (is_unix) {
if (uri->server || uri->port) { char *uri_socket = g_hash_table_lookup(qp, "socket");
ret = -EINVAL; if (uri_server || uri_port != -1 || !uri_socket) {
goto out; return -EINVAL;
} }
if (strcmp(qp->p[0].name, "socket")) { gsconf->u.q_unix.path = g_strdup(uri_socket);
ret = -EINVAL;
goto out;
}
gsconf->u.q_unix.path = g_strdup(qp->p[0].value);
} else { } else {
gsconf->u.inet.host = g_strdup(uri->server ? uri->server : "localhost"); gsconf->u.inet.host = g_strdup(uri_server ? uri_server : "localhost");
if (uri->port) { if (uri_port > 0) {
gsconf->u.inet.port = g_strdup_printf("%d", uri->port); gsconf->u.inet.port = g_strdup_printf("%d", uri_port);
} else { } else {
gsconf->u.inet.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT); gsconf->u.inet.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT);
} }
} }
out: return 0;
if (qp) {
query_params_free(qp);
}
uri_free(uri);
return ret;
} }
static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf, static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
@ -1555,7 +1551,7 @@ static BlockDriver bdrv_gluster = {
.format_name = "gluster", .format_name = "gluster",
.protocol_name = "gluster", .protocol_name = "gluster",
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_file_open = qemu_gluster_open, .bdrv_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit, .bdrv_reopen_commit = qemu_gluster_reopen_commit,
.bdrv_reopen_abort = qemu_gluster_reopen_abort, .bdrv_reopen_abort = qemu_gluster_reopen_abort,
@ -1584,7 +1580,7 @@ static BlockDriver bdrv_gluster_tcp = {
.format_name = "gluster", .format_name = "gluster",
.protocol_name = "gluster+tcp", .protocol_name = "gluster+tcp",
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_file_open = qemu_gluster_open, .bdrv_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit, .bdrv_reopen_commit = qemu_gluster_reopen_commit,
.bdrv_reopen_abort = qemu_gluster_reopen_abort, .bdrv_reopen_abort = qemu_gluster_reopen_abort,
@ -1613,42 +1609,7 @@ static BlockDriver bdrv_gluster_unix = {
.format_name = "gluster", .format_name = "gluster",
.protocol_name = "gluster+unix", .protocol_name = "gluster+unix",
.instance_size = sizeof(BDRVGlusterState), .instance_size = sizeof(BDRVGlusterState),
.bdrv_file_open = qemu_gluster_open, .bdrv_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
.bdrv_close = qemu_gluster_close,
.bdrv_co_create = qemu_gluster_co_create,
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
.bdrv_co_getlength = qemu_gluster_co_getlength,
.bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
.bdrv_co_truncate = qemu_gluster_co_truncate,
.bdrv_co_readv = qemu_gluster_co_readv,
.bdrv_co_writev = qemu_gluster_co_writev,
.bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
#ifdef CONFIG_GLUSTERFS_DISCARD
.bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
#endif
#ifdef CONFIG_GLUSTERFS_ZEROFILL
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
#endif
.bdrv_co_block_status = qemu_gluster_co_block_status,
.bdrv_refresh_limits = qemu_gluster_refresh_limits,
.create_opts = &qemu_gluster_create_opts,
.strong_runtime_opts = gluster_strong_open_opts,
};
/* rdma is deprecated (actually never supported for volfile fetch).
* Let's maintain it for the protocol compatibility, to make sure things
* won't break immediately. For now, gluster+rdma will fall back to gluster+tcp
* protocol with a warning.
* TODO: remove gluster+rdma interface support
*/
static BlockDriver bdrv_gluster_rdma = {
.format_name = "gluster",
.protocol_name = "gluster+rdma",
.instance_size = sizeof(BDRVGlusterState),
.bdrv_file_open = qemu_gluster_open,
.bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
.bdrv_reopen_commit = qemu_gluster_reopen_commit, .bdrv_reopen_commit = qemu_gluster_reopen_commit,
.bdrv_reopen_abort = qemu_gluster_reopen_abort, .bdrv_reopen_abort = qemu_gluster_reopen_abort,
@ -1675,7 +1636,6 @@ static BlockDriver bdrv_gluster_rdma = {
static void bdrv_gluster_init(void) static void bdrv_gluster_init(void)
{ {
bdrv_register(&bdrv_gluster_rdma);
bdrv_register(&bdrv_gluster_unix); bdrv_register(&bdrv_gluster_unix);
bdrv_register(&bdrv_gluster_tcp); bdrv_register(&bdrv_gluster_tcp);
bdrv_register(&bdrv_gluster); bdrv_register(&bdrv_gluster);

View File

@ -1862,6 +1862,11 @@ bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
return -EINVAL; return -EINVAL;
} }
/* If opened with discard=off we should never unmap. */
if (!(bs->open_flags & BDRV_O_UNMAP)) {
flags &= ~BDRV_REQ_MAY_UNMAP;
}
/* Invalidate the cached block-status data range if this write overlaps */ /* Invalidate the cached block-status data range if this write overlaps */
bdrv_bsc_invalidate_range(bs, offset, bytes); bdrv_bsc_invalidate_range(bs, offset, bytes);
@ -2315,10 +2320,6 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags); trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
assert_bdrv_graph_readable(); assert_bdrv_graph_readable();
if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
flags &= ~BDRV_REQ_MAY_UNMAP;
}
return bdrv_co_pwritev(child, offset, bytes, NULL, return bdrv_co_pwritev(child, offset, bytes, NULL,
BDRV_REQ_ZERO_WRITE | flags); BDRV_REQ_ZERO_WRITE | flags);
} }

View File

@ -2429,7 +2429,7 @@ static BlockDriver bdrv_iscsi = {
.instance_size = sizeof(IscsiLun), .instance_size = sizeof(IscsiLun),
.bdrv_parse_filename = iscsi_parse_filename, .bdrv_parse_filename = iscsi_parse_filename,
.bdrv_file_open = iscsi_open, .bdrv_open = iscsi_open,
.bdrv_close = iscsi_close, .bdrv_close = iscsi_close,
.bdrv_co_create_opts = bdrv_co_create_opts_simple, .bdrv_co_create_opts = bdrv_co_create_opts_simple,
.create_opts = &bdrv_create_opts_simple, .create_opts = &bdrv_create_opts_simple,
@ -2468,7 +2468,7 @@ static BlockDriver bdrv_iser = {
.instance_size = sizeof(IscsiLun), .instance_size = sizeof(IscsiLun),
.bdrv_parse_filename = iscsi_parse_filename, .bdrv_parse_filename = iscsi_parse_filename,
.bdrv_file_open = iscsi_open, .bdrv_open = iscsi_open,
.bdrv_close = iscsi_close, .bdrv_close = iscsi_close,
.bdrv_co_create_opts = bdrv_co_create_opts_simple, .bdrv_co_create_opts = bdrv_co_create_opts_simple,
.create_opts = &bdrv_create_opts_simple, .create_opts = &bdrv_create_opts_simple,

View File

@ -384,6 +384,9 @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
case QEMU_AIO_READ: case QEMU_AIO_READ:
io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset); io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset);
break; break;
case QEMU_AIO_FLUSH:
io_prep_fdsync(iocbs, fd);
break;
/* Currently Linux kernel does not support other operations */ /* Currently Linux kernel does not support other operations */
default: default:
fprintf(stderr, "%s: invalid AIO request type 0x%x.\n", fprintf(stderr, "%s: invalid AIO request type 0x%x.\n",
@ -412,7 +415,7 @@ int coroutine_fn laio_co_submit(int fd, uint64_t offset, QEMUIOVector *qiov,
AioContext *ctx = qemu_get_current_aio_context(); AioContext *ctx = qemu_get_current_aio_context();
struct qemu_laiocb laiocb = { struct qemu_laiocb laiocb = {
.co = qemu_coroutine_self(), .co = qemu_coroutine_self(),
.nbytes = qiov->size, .nbytes = qiov ? qiov->size : 0,
.ctx = aio_get_linux_aio(ctx), .ctx = aio_get_linux_aio(ctx),
.ret = -EINPROGRESS, .ret = -EINPROGRESS,
.is_read = (type == QEMU_AIO_READ), .is_read = (type == QEMU_AIO_READ),
@ -486,3 +489,19 @@ void laio_cleanup(LinuxAioState *s)
} }
g_free(s); g_free(s);
} }
bool laio_has_fdsync(int fd)
{
struct iocb cb;
struct iocb *cbs[] = {&cb, NULL};
io_context_t ctx = 0;
io_setup(1, &ctx);
/* check if host kernel supports IO_CMD_FDSYNC */
io_prep_fdsync(&cb, fd);
int ret = io_submit(ctx, 1, cbs);
io_destroy(ctx);
return (ret == -EINVAL) ? false : true;
}

View File

@ -39,7 +39,7 @@ block_ss.add(files(
'throttle.c', 'throttle.c',
'throttle-groups.c', 'throttle-groups.c',
'write-threshold.c', 'write-threshold.c',
), zstd, zlib, gnutls) ), zstd, zlib)
system_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c')) system_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c'))
system_ss.add(files('block-ram-registrar.c')) system_ss.add(files('block-ram-registrar.c'))
@ -110,7 +110,7 @@ foreach m : [
[blkio, 'blkio', files('blkio.c')], [blkio, 'blkio', files('blkio.c')],
[curl, 'curl', files('curl.c')], [curl, 'curl', files('curl.c')],
[glusterfs, 'gluster', files('gluster.c')], [glusterfs, 'gluster', files('gluster.c')],
[libiscsi, 'iscsi', [files('iscsi.c'), libm]], [libiscsi, 'iscsi', files('iscsi.c')],
[libnfs, 'nfs', files('nfs.c')], [libnfs, 'nfs', files('nfs.c')],
[libssh, 'ssh', files('ssh.c')], [libssh, 'ssh', files('ssh.c')],
[rbd, 'rbd', files('rbd.c')], [rbd, 'rbd', files('rbd.c')],
@ -119,7 +119,7 @@ foreach m : [
module_ss = ss.source_set() module_ss = ss.source_set()
module_ss.add(when: m[0], if_true: m[2]) module_ss.add(when: m[0], if_true: m[2])
if enable_modules if enable_modules
modsrc += module_ss.all_sources() modsrc += m[2]
endif endif
block_modules += {m[1] : module_ss} block_modules += {m[1] : module_ss}
endif endif

View File

@ -93,6 +93,7 @@ typedef struct MirrorBlockJob {
int64_t active_write_bytes_in_flight; int64_t active_write_bytes_in_flight;
bool prepared; bool prepared;
bool in_drain; bool in_drain;
bool base_ro;
} MirrorBlockJob; } MirrorBlockJob;
typedef struct MirrorBDSOpaque { typedef struct MirrorBDSOpaque {
@ -794,6 +795,10 @@ static int mirror_exit_common(Job *job)
bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort); bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort);
bdrv_graph_wrunlock(); bdrv_graph_wrunlock();
if (abort && s->base_ro && !bdrv_is_read_only(target_bs)) {
bdrv_reopen_set_read_only(target_bs, true, NULL);
}
bdrv_drained_end(target_bs); bdrv_drained_end(target_bs);
bdrv_unref(target_bs); bdrv_unref(target_bs);
@ -1717,6 +1722,7 @@ static BlockJob *mirror_start_job(
bool is_none_mode, BlockDriverState *base, bool is_none_mode, BlockDriverState *base,
bool auto_complete, const char *filter_node_name, bool auto_complete, const char *filter_node_name,
bool is_mirror, MirrorCopyMode copy_mode, bool is_mirror, MirrorCopyMode copy_mode,
bool base_ro,
Error **errp) Error **errp)
{ {
MirrorBlockJob *s; MirrorBlockJob *s;
@ -1800,6 +1806,7 @@ static BlockJob *mirror_start_job(
bdrv_unref(mirror_top_bs); bdrv_unref(mirror_top_bs);
s->mirror_top_bs = mirror_top_bs; s->mirror_top_bs = mirror_top_bs;
s->base_ro = base_ro;
/* No resize for the target either; while the mirror is still running, a /* No resize for the target either; while the mirror is still running, a
* consistent read isn't necessarily possible. We could possibly allow * consistent read isn't necessarily possible. We could possibly allow
@ -2029,7 +2036,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
speed, granularity, buf_size, backing_mode, zero_target, speed, granularity, buf_size, backing_mode, zero_target,
on_source_error, on_target_error, unmap, NULL, NULL, on_source_error, on_target_error, unmap, NULL, NULL,
&mirror_job_driver, is_none_mode, base, false, &mirror_job_driver, is_none_mode, base, false,
filter_node_name, true, copy_mode, errp); filter_node_name, true, copy_mode, false, errp);
} }
BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs, BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
@ -2058,7 +2065,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
on_error, on_error, true, cb, opaque, on_error, on_error, true, cb, opaque,
&commit_active_job_driver, false, base, auto_complete, &commit_active_job_driver, false, base, auto_complete,
filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND, filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND,
errp); base_read_only, errp);
if (!job) { if (!job) {
goto error_restore_flags; goto error_restore_flags;
} }

View File

@ -402,7 +402,8 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
goto exit; goto exit;
} }
nbd_server_start(addr, NULL, NULL, 0, &local_err); nbd_server_start(addr, NULL, NULL, NBD_DEFAULT_MAX_CONNECTIONS,
&local_err);
qapi_free_SocketAddress(addr); qapi_free_SocketAddress(addr);
if (local_err != NULL) { if (local_err != NULL) {
goto exit; goto exit;

View File

@ -31,7 +31,6 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "trace.h" #include "trace.h"
#include "qemu/uri.h"
#include "qemu/option.h" #include "qemu/option.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
@ -1514,30 +1513,31 @@ static void nbd_client_close(BlockDriverState *bs)
static int nbd_parse_uri(const char *filename, QDict *options) static int nbd_parse_uri(const char *filename, QDict *options)
{ {
URI *uri; g_autoptr(GUri) uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
g_autoptr(GHashTable) qp = NULL;
const char *p; const char *p;
QueryParams *qp = NULL; int qp_n;
int ret = 0;
bool is_unix; bool is_unix;
const char *uri_scheme, *uri_query, *uri_server;
int uri_port;
uri = uri_parse(filename);
if (!uri) { if (!uri) {
return -EINVAL; return -EINVAL;
} }
/* transport */ /* transport */
if (!g_strcmp0(uri->scheme, "nbd")) { uri_scheme = g_uri_get_scheme(uri);
if (!g_strcmp0(uri_scheme, "nbd")) {
is_unix = false; is_unix = false;
} else if (!g_strcmp0(uri->scheme, "nbd+tcp")) { } else if (!g_strcmp0(uri_scheme, "nbd+tcp")) {
is_unix = false; is_unix = false;
} else if (!g_strcmp0(uri->scheme, "nbd+unix")) { } else if (!g_strcmp0(uri_scheme, "nbd+unix")) {
is_unix = true; is_unix = true;
} else { } else {
ret = -EINVAL; return -EINVAL;
goto out;
} }
p = uri->path ? uri->path : ""; p = g_uri_get_path(uri) ?: "";
if (p[0] == '/') { if (p[0] == '/') {
p++; p++;
} }
@ -1545,52 +1545,50 @@ static int nbd_parse_uri(const char *filename, QDict *options)
qdict_put_str(options, "export", p); qdict_put_str(options, "export", p);
} }
qp = query_params_parse(uri->query); uri_query = g_uri_get_query(uri);
if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) { if (uri_query) {
ret = -EINVAL; qp = g_uri_parse_params(uri_query, -1, "&", G_URI_PARAMS_NONE, NULL);
goto out; if (!qp) {
return -EINVAL;
} }
qp_n = g_hash_table_size(qp);
if (qp_n > 1 || (is_unix && !qp_n) || (!is_unix && qp_n)) {
return -EINVAL;
}
}
uri_server = g_uri_get_host(uri);
if (uri_server && !uri_server[0]) {
uri_server = NULL;
}
uri_port = g_uri_get_port(uri);
if (is_unix) { if (is_unix) {
/* nbd+unix:///export?socket=path */ /* nbd+unix:///export?socket=path */
if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) { const char *uri_socket = g_hash_table_lookup(qp, "socket");
ret = -EINVAL; if (uri_server || uri_port != -1 || !uri_socket) {
goto out; return -EINVAL;
} }
qdict_put_str(options, "server.type", "unix"); qdict_put_str(options, "server.type", "unix");
qdict_put_str(options, "server.path", qp->p[0].value); qdict_put_str(options, "server.path", uri_socket);
} else { } else {
QString *host;
char *port_str; char *port_str;
/* nbd[+tcp]://host[:port]/export */ /* nbd[+tcp]://host[:port]/export */
if (!uri->server) { if (!uri_server) {
ret = -EINVAL; return -EINVAL;
goto out;
}
/* strip braces from literal IPv6 address */
if (uri->server[0] == '[') {
host = qstring_from_substr(uri->server, 1,
strlen(uri->server) - 1);
} else {
host = qstring_from_str(uri->server);
} }
qdict_put_str(options, "server.type", "inet"); qdict_put_str(options, "server.type", "inet");
qdict_put(options, "server.host", host); qdict_put_str(options, "server.host", uri_server);
port_str = g_strdup_printf("%d", uri->port ?: NBD_DEFAULT_PORT); port_str = g_strdup_printf("%d", uri_port > 0 ? uri_port
: NBD_DEFAULT_PORT);
qdict_put_str(options, "server.port", port_str); qdict_put_str(options, "server.port", port_str);
g_free(port_str); g_free(port_str);
} }
out: return 0;
if (qp) {
query_params_free(qp);
}
uri_free(uri);
return ret;
} }
static bool nbd_has_filename_options_conflict(QDict *options, Error **errp) static bool nbd_has_filename_options_conflict(QDict *options, Error **errp)
@ -2148,7 +2146,7 @@ static BlockDriver bdrv_nbd = {
.bdrv_parse_filename = nbd_parse_filename, .bdrv_parse_filename = nbd_parse_filename,
.bdrv_co_create_opts = bdrv_co_create_opts_simple, .bdrv_co_create_opts = bdrv_co_create_opts_simple,
.create_opts = &bdrv_create_opts_simple, .create_opts = &bdrv_create_opts_simple,
.bdrv_file_open = nbd_open, .bdrv_open = nbd_open,
.bdrv_reopen_prepare = nbd_client_reopen_prepare, .bdrv_reopen_prepare = nbd_client_reopen_prepare,
.bdrv_co_preadv = nbd_client_co_preadv, .bdrv_co_preadv = nbd_client_co_preadv,
.bdrv_co_pwritev = nbd_client_co_pwritev, .bdrv_co_pwritev = nbd_client_co_pwritev,
@ -2176,7 +2174,7 @@ static BlockDriver bdrv_nbd_tcp = {
.bdrv_parse_filename = nbd_parse_filename, .bdrv_parse_filename = nbd_parse_filename,
.bdrv_co_create_opts = bdrv_co_create_opts_simple, .bdrv_co_create_opts = bdrv_co_create_opts_simple,
.create_opts = &bdrv_create_opts_simple, .create_opts = &bdrv_create_opts_simple,
.bdrv_file_open = nbd_open, .bdrv_open = nbd_open,
.bdrv_reopen_prepare = nbd_client_reopen_prepare, .bdrv_reopen_prepare = nbd_client_reopen_prepare,
.bdrv_co_preadv = nbd_client_co_preadv, .bdrv_co_preadv = nbd_client_co_preadv,
.bdrv_co_pwritev = nbd_client_co_pwritev, .bdrv_co_pwritev = nbd_client_co_pwritev,
@ -2204,7 +2202,7 @@ static BlockDriver bdrv_nbd_unix = {
.bdrv_parse_filename = nbd_parse_filename, .bdrv_parse_filename = nbd_parse_filename,
.bdrv_co_create_opts = bdrv_co_create_opts_simple, .bdrv_co_create_opts = bdrv_co_create_opts_simple,
.create_opts = &bdrv_create_opts_simple, .create_opts = &bdrv_create_opts_simple,
.bdrv_file_open = nbd_open, .bdrv_open = nbd_open,
.bdrv_reopen_prepare = nbd_client_reopen_prepare, .bdrv_reopen_prepare = nbd_client_reopen_prepare,
.bdrv_co_preadv = nbd_client_co_preadv, .bdrv_co_preadv = nbd_client_co_preadv,
.bdrv_co_pwritev = nbd_client_co_pwritev, .bdrv_co_pwritev = nbd_client_co_pwritev,

View File

@ -38,7 +38,6 @@
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/option.h" #include "qemu/option.h"
#include "qemu/uri.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "sysemu/replay.h" #include "sysemu/replay.h"
#include "qapi/qapi-visit-block-core.h" #include "qapi/qapi-visit-block-core.h"
@ -79,77 +78,76 @@ typedef struct NFSRPC {
static int nfs_parse_uri(const char *filename, QDict *options, Error **errp) static int nfs_parse_uri(const char *filename, QDict *options, Error **errp)
{ {
URI *uri = NULL; g_autoptr(GUri) uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
QueryParams *qp = NULL; GUriParamsIter qp;
int ret = -EINVAL, i; const char *uri_server, *uri_path, *uri_query;
char *qp_name, *qp_value;
GError *gerror = NULL;
uri = uri_parse(filename);
if (!uri) { if (!uri) {
error_setg(errp, "Invalid URI specified"); error_setg(errp, "Invalid URI specified");
goto out; return -EINVAL;
} }
if (g_strcmp0(uri->scheme, "nfs") != 0) { if (!g_str_equal(g_uri_get_scheme(uri), "nfs")) {
error_setg(errp, "URI scheme must be 'nfs'"); error_setg(errp, "URI scheme must be 'nfs'");
goto out; return -EINVAL;
} }
if (!uri->server) { uri_server = g_uri_get_host(uri);
if (!uri_server || !uri_server[0]) {
error_setg(errp, "missing hostname in URI"); error_setg(errp, "missing hostname in URI");
goto out; return -EINVAL;
} }
if (!uri->path) { uri_path = g_uri_get_path(uri);
if (!uri_path || !uri_path[0]) {
error_setg(errp, "missing file path in URI"); error_setg(errp, "missing file path in URI");
goto out; return -EINVAL;
} }
qp = query_params_parse(uri->query); qdict_put_str(options, "server.host", uri_server);
if (!qp) {
error_setg(errp, "could not parse query parameters");
goto out;
}
qdict_put_str(options, "server.host", uri->server);
qdict_put_str(options, "server.type", "inet"); qdict_put_str(options, "server.type", "inet");
qdict_put_str(options, "path", uri->path); qdict_put_str(options, "path", uri_path);
for (i = 0; i < qp->n; i++) { uri_query = g_uri_get_query(uri);
if (uri_query) {
g_uri_params_iter_init(&qp, uri_query, -1, "&", G_URI_PARAMS_NONE);
while (g_uri_params_iter_next(&qp, &qp_name, &qp_value, &gerror)) {
uint64_t val; uint64_t val;
if (!qp->p[i].value) { if (!qp_name || gerror) {
error_setg(errp, "Failed to parse NFS parameter");
return -EINVAL;
}
if (!qp_value) {
error_setg(errp, "Value for NFS parameter expected: %s", error_setg(errp, "Value for NFS parameter expected: %s",
qp->p[i].name); qp_name);
goto out; return -EINVAL;
} }
if (parse_uint_full(qp->p[i].value, 0, &val)) { if (parse_uint_full(qp_value, 0, &val)) {
error_setg(errp, "Illegal value for NFS parameter: %s", error_setg(errp, "Invalid value for NFS parameter: %s",
qp->p[i].name); qp_name);
goto out; return -EINVAL;
} }
if (!strcmp(qp->p[i].name, "uid")) { if (g_str_equal(qp_name, "uid")) {
qdict_put_str(options, "user", qp->p[i].value); qdict_put_str(options, "user", qp_value);
} else if (!strcmp(qp->p[i].name, "gid")) { } else if (g_str_equal(qp_name, "gid")) {
qdict_put_str(options, "group", qp->p[i].value); qdict_put_str(options, "group", qp_value);
} else if (!strcmp(qp->p[i].name, "tcp-syncnt")) { } else if (g_str_equal(qp_name, "tcp-syncnt")) {
qdict_put_str(options, "tcp-syn-count", qp->p[i].value); qdict_put_str(options, "tcp-syn-count", qp_value);
} else if (!strcmp(qp->p[i].name, "readahead")) { } else if (g_str_equal(qp_name, "readahead")) {
qdict_put_str(options, "readahead-size", qp->p[i].value); qdict_put_str(options, "readahead-size", qp_value);
} else if (!strcmp(qp->p[i].name, "pagecache")) { } else if (g_str_equal(qp_name, "pagecache")) {
qdict_put_str(options, "page-cache-size", qp->p[i].value); qdict_put_str(options, "page-cache-size", qp_value);
} else if (!strcmp(qp->p[i].name, "debug")) { } else if (g_str_equal(qp_name, "debug")) {
qdict_put_str(options, "debug", qp->p[i].value); qdict_put_str(options, "debug", qp_value);
} else { } else {
error_setg(errp, "Unknown NFS parameter name: %s", error_setg(errp, "Unknown NFS parameter name: %s", qp_name);
qp->p[i].name); return -EINVAL;
goto out;
} }
} }
ret = 0;
out:
if (qp) {
query_params_free(qp);
} }
uri_free(uri);
return ret; return 0;
} }
static bool nfs_has_filename_options_conflict(QDict *options, Error **errp) static bool nfs_has_filename_options_conflict(QDict *options, Error **errp)
@ -890,7 +888,7 @@ static BlockDriver bdrv_nfs = {
#endif #endif
.bdrv_co_truncate = nfs_file_co_truncate, .bdrv_co_truncate = nfs_file_co_truncate,
.bdrv_file_open = nfs_file_open, .bdrv_open = nfs_file_open,
.bdrv_close = nfs_file_close, .bdrv_close = nfs_file_close,
.bdrv_co_create = nfs_file_co_create, .bdrv_co_create = nfs_file_co_create,
.bdrv_co_create_opts = nfs_file_co_create_opts, .bdrv_co_create_opts = nfs_file_co_create_opts,

View File

@ -77,7 +77,7 @@ static void null_aio_parse_filename(const char *filename, QDict *options,
} }
} }
static int null_file_open(BlockDriverState *bs, QDict *options, int flags, static int null_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp) Error **errp)
{ {
QemuOpts *opts; QemuOpts *opts;
@ -283,7 +283,7 @@ static BlockDriver bdrv_null_co = {
.protocol_name = "null-co", .protocol_name = "null-co",
.instance_size = sizeof(BDRVNullState), .instance_size = sizeof(BDRVNullState),
.bdrv_file_open = null_file_open, .bdrv_open = null_open,
.bdrv_parse_filename = null_co_parse_filename, .bdrv_parse_filename = null_co_parse_filename,
.bdrv_co_getlength = null_co_getlength, .bdrv_co_getlength = null_co_getlength,
.bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size, .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,
@ -304,7 +304,7 @@ static BlockDriver bdrv_null_aio = {
.protocol_name = "null-aio", .protocol_name = "null-aio",
.instance_size = sizeof(BDRVNullState), .instance_size = sizeof(BDRVNullState),
.bdrv_file_open = null_file_open, .bdrv_open = null_open,
.bdrv_parse_filename = null_aio_parse_filename, .bdrv_parse_filename = null_aio_parse_filename,
.bdrv_co_getlength = null_co_getlength, .bdrv_co_getlength = null_co_getlength,
.bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size, .bdrv_co_get_allocated_file_size = null_co_get_allocated_file_size,

View File

@ -889,7 +889,7 @@ out:
qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)regs, 0, sizeof(NvmeBar)); qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)regs, 0, sizeof(NvmeBar));
} }
/* Cleaning up is done in nvme_file_open() upon error. */ /* Cleaning up is done in nvme_open() upon error. */
return ret; return ret;
} }
@ -967,7 +967,7 @@ static void nvme_close(BlockDriverState *bs)
g_free(s->device); g_free(s->device);
} }
static int nvme_file_open(BlockDriverState *bs, QDict *options, int flags, static int nvme_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp) Error **errp)
{ {
const char *device; const char *device;
@ -1630,7 +1630,7 @@ static BlockDriver bdrv_nvme = {
.create_opts = &bdrv_create_opts_simple, .create_opts = &bdrv_create_opts_simple,
.bdrv_parse_filename = nvme_parse_filename, .bdrv_parse_filename = nvme_parse_filename,
.bdrv_file_open = nvme_file_open, .bdrv_open = nvme_open,
.bdrv_close = nvme_close, .bdrv_close = nvme_close,
.bdrv_co_getlength = nvme_co_getlength, .bdrv_co_getlength = nvme_co_getlength,
.bdrv_probe_blocksizes = nvme_probe_blocksizes, .bdrv_probe_blocksizes = nvme_probe_blocksizes,

View File

@ -211,7 +211,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
} }
s->crypto = qcrypto_block_open(crypto_opts, "encrypt.", s->crypto = qcrypto_block_open(crypto_opts, "encrypt.",
NULL, NULL, cflags, 1, errp); NULL, NULL, cflags, errp);
if (!s->crypto) { if (!s->crypto) {
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;

View File

@ -1609,7 +1609,7 @@ bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
name); name);
goto fail; goto fail;
} }
tb = g_memdup(&bm->table, sizeof(bm->table)); tb = g_memdup2(&bm->table, sizeof(bm->table));
bm->table.offset = 0; bm->table.offset = 0;
bm->table.size = 0; bm->table.size = 0;
QSIMPLEQ_INSERT_TAIL(&drop_tables, tb, entry); QSIMPLEQ_INSERT_TAIL(&drop_tables, tb, entry);

View File

@ -321,7 +321,7 @@ qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
} }
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
qcow2_crypto_hdr_read_func, qcow2_crypto_hdr_read_func,
bs, cflags, QCOW2_MAX_THREADS, errp); bs, cflags, errp);
if (!s->crypto) { if (!s->crypto) {
return -EINVAL; return -EINVAL;
} }
@ -1716,8 +1716,7 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO; cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
} }
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.", s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
NULL, NULL, cflags, NULL, NULL, cflags, errp);
QCOW2_MAX_THREADS, errp);
if (!s->crypto) { if (!s->crypto) {
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;

View File

@ -1815,8 +1815,9 @@ static const char *const qemu_rbd_strong_runtime_opts[] = {
static BlockDriver bdrv_rbd = { static BlockDriver bdrv_rbd = {
.format_name = "rbd", .format_name = "rbd",
.instance_size = sizeof(BDRVRBDState), .instance_size = sizeof(BDRVRBDState),
.bdrv_parse_filename = qemu_rbd_parse_filename, .bdrv_parse_filename = qemu_rbd_parse_filename,
.bdrv_file_open = qemu_rbd_open, .bdrv_open = qemu_rbd_open,
.bdrv_close = qemu_rbd_close, .bdrv_close = qemu_rbd_close,
.bdrv_reopen_prepare = qemu_rbd_reopen_prepare, .bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
.bdrv_co_create = qemu_rbd_co_create, .bdrv_co_create = qemu_rbd_co_create,

Some files were not shown because too many files have changed in this diff Show More