Compare commits

..

12 Commits

Author SHA1 Message Date
Fabiano Rosas
eab13108cd tests/qtest: bios-tables-test: Skip if missing configs
If we build with --without-default-devices, CONFIG_HPET and
CONFIG_PARALLEL are set to N, which makes the respective devices go
missing from acpi tables.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
750400c56f tests/qemu-iotests: Require virtio-scsi-pci
Check that virtio-scsi-pci is present in the QEMU build before running
the tests.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
f5ef199312 tests/qtest: Do not include hexloader-test if loader device is not present
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
c789207417 tests/qtest: Check for devices in bios-tables-test
Do not include tests that require devices that are not available in
the QEMU build.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
3bf0b7dd7b tests/qtest: drive_del-test: Skip tests that require missing devices
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
3864d5e5c6 tests/qtest: Skip unplug tests that use missing devices
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
8a840ab4c2 tests/qtest: Fix coding style in device-plug-test.c
We should not mix declarations and statements in QEMU code.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
d32f29f651 tests/qtest: hd-geo-test: Check for missing devices
Don't include tests that require devices not available in the QEMU
binary.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
696cf0c1cd tests/qtest: Don't build virtio-serial-test.c if device not present
The virtconsole device might not be present in the QEMU build that is
being tested.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
ef92be0914 tests/qtest: Add dependence on PCIE_PORT for virtio-net-failover.c
This test depends on the presence of the pcie-root-port device. Add a
build time dependency.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
f85bfa0bcb tests/qtest: Do not run lsi53c895a test if device is not present
The tests are built once for all the targets, so as long as one QEMU
binary is built with CONFIG_LSI_SCSI_PCI=y, this test will
run. However some binaries might not include the device. So check this
again in runtime.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
Fabiano Rosas
ecbd3f095e tests/qtest: Skip PXE tests for missing devices
Check if the devices we're trying to add are present in the QEMU
binary. They could have been removed from the build via Kconfig or the
--without-default-devices option.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Thomas Huth <thuth@redhat.com>
2023-02-13 18:01:07 -03:00
1683 changed files with 45567 additions and 67854 deletions

109
.cirrus.yml Normal file
View File

@@ -0,0 +1,109 @@
env:
CIRRUS_CLONE_DEPTH: 1
windows_msys2_task:
timeout_in: 90m
windows_container:
image: cirrusci/windowsservercore:2019
os_version: 2019
cpu: 8
memory: 8G
env:
CIRRUS_SHELL: powershell
MSYS: winsymlinks:native
MSYSTEM: MINGW64
MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2022-06-03/msys2-base-x86_64-20220603.sfx.exe
MSYS2_FINGERPRINT: 0
MSYS2_PACKAGES: "
diffutils git grep make pkg-config sed
mingw-w64-x86_64-python
mingw-w64-x86_64-python-sphinx
mingw-w64-x86_64-toolchain
mingw-w64-x86_64-SDL2
mingw-w64-x86_64-SDL2_image
mingw-w64-x86_64-gtk3
mingw-w64-x86_64-glib2
mingw-w64-x86_64-ninja
mingw-w64-x86_64-jemalloc
mingw-w64-x86_64-lzo2
mingw-w64-x86_64-zstd
mingw-w64-x86_64-libjpeg-turbo
mingw-w64-x86_64-pixman
mingw-w64-x86_64-libgcrypt
mingw-w64-x86_64-libpng
mingw-w64-x86_64-libssh
mingw-w64-x86_64-snappy
mingw-w64-x86_64-libusb
mingw-w64-x86_64-usbredir
mingw-w64-x86_64-libtasn1
mingw-w64-x86_64-nettle
mingw-w64-x86_64-cyrus-sasl
mingw-w64-x86_64-curl
mingw-w64-x86_64-gnutls
mingw-w64-x86_64-libnfs
"
CHERE_INVOKING: 1
msys2_cache:
folder: C:\tools\archive
reupload_on_changes: false
# These env variables are used to generate fingerprint to trigger the cache procedure
# If wanna to force re-populate msys2, increase MSYS2_FINGERPRINT
fingerprint_script:
- |
echo $env:CIRRUS_TASK_NAME
echo $env:MSYS2_URL
echo $env:MSYS2_FINGERPRINT
echo $env:MSYS2_PACKAGES
populate_script:
- |
md -Force C:\tools\archive\pkg
$start_time = Get-Date
bitsadmin /transfer msys_download /dynamic /download /priority FOREGROUND $env:MSYS2_URL C:\tools\archive\base.exe
Write-Output "Download time taken: $((Get-Date).Subtract($start_time))"
cd C:\tools
C:\tools\archive\base.exe -y
del -Force C:\tools\archive\base.exe
Write-Output "Base install time taken: $((Get-Date).Subtract($start_time))"
$start_time = Get-Date
((Get-Content -path C:\tools\msys64\etc\\post-install\\07-pacman-key.post -Raw) -replace '--refresh-keys', '--version') | Set-Content -Path C:\tools\msys64\etc\\post-install\\07-pacman-key.post
C:\tools\msys64\usr\bin\bash.exe -lc "sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf"
C:\tools\msys64\usr\bin\bash.exe -lc "export"
C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Sy
echo Y | C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Suu --overwrite=*
taskkill /F /FI "MODULES eq msys-2.0.dll"
tasklist
C:\tools\msys64\usr\bin\bash.exe -lc "mv -f /etc/pacman.conf.pacnew /etc/pacman.conf || true"
C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -Syuu --overwrite=*"
Write-Output "Core install time taken: $((Get-Date).Subtract($start_time))"
$start_time = Get-Date
C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -S --needed $env:MSYS2_PACKAGES"
Write-Output "Package install time taken: $((Get-Date).Subtract($start_time))"
$start_time = Get-Date
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\etc\mtab
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\fd
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\stderr
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\stdin
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\stdout
del -Force -Recurse -ErrorAction SilentlyContinue C:\tools\msys64\var\cache\pacman\pkg
tar cf C:\tools\archive\msys64.tar -C C:\tools\ msys64
Write-Output "Package archive time taken: $((Get-Date).Subtract($start_time))"
del -Force -Recurse -ErrorAction SilentlyContinue c:\tools\msys64
install_script:
- |
$start_time = Get-Date
cd C:\tools
ls C:\tools\archive\msys64.tar
tar xf C:\tools\archive\msys64.tar
Write-Output "Extract msys2 time taken: $((Get-Date).Subtract($start_time))"
script:
- C:\tools\msys64\usr\bin\bash.exe -lc "mkdir build"
- C:\tools\msys64\usr\bin\bash.exe -lc "cd build && ../configure --python=python3"
- C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make -j8"
- exit $LastExitCode
test_script:
- C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make V=1 check"
- exit $LastExitCode

View File

@@ -1,21 +0,0 @@
#
# List of code-formatting clean ups the git blame can ignore
#
# git blame --ignore-revs-file .git-blame-ignore-revs
#
# or
#
# git config blame.ignoreRevsFile .git-blame-ignore-revs
#
# gdbstub: clean-up indents
ad9e4585b3c7425759d3eea697afbca71d2c2082
# e1000e: fix code style
0eadd56bf53ab196a16d492d7dd31c62e1c24c32
# target/riscv: coding style fixes
8c7feddddd9218b407792120bcfda0347ed16205
# replace TABs with spaces
48805df9c22a0700fba4b3b548fafaa21726ca68

View File

@@ -11,8 +11,6 @@
# and show the duration of each line. # and show the duration of each line.
FF_SCRIPT_SECTIONS: 1 FF_SCRIPT_SECTIONS: 1
interruptible: true
rules: rules:
############################################################# #############################################################
# Stage 1: exclude scenarios where we definitely don't # Stage 1: exclude scenarios where we definitely don't
@@ -75,5 +73,5 @@
- if: '$QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"' - if: '$QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
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 successfull
- when: on_success - when: on_success

View File

@@ -11,10 +11,12 @@
fi fi
- mkdir build - mkdir build
- cd build - cd build
- ../configure --enable-werror --disable-docs --enable-fdt=system - if test -n "$TARGETS";
${LD_JOBS:+--meson=git} ${TARGETS:+--target-list="$TARGETS"} then
$CONFIGURE_ARGS || ../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=git} $CONFIGURE_ARGS --target-list="$TARGETS" ;
{ cat config.log meson-logs/meson-log.txt && exit 1; } else
../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=git} $CONFIGURE_ARGS ;
fi || { cat config.log meson-logs/meson-log.txt && exit 1; }
- if test -n "$LD_JOBS"; - if test -n "$LD_JOBS";
then then
../meson/meson.py configure . -Dbackend_max_links="$LD_JOBS" ; ../meson/meson.py configure . -Dbackend_max_links="$LD_JOBS" ;
@@ -25,22 +27,6 @@
make -j"$JOBS" $MAKE_CHECK_ARGS ; make -j"$JOBS" $MAKE_CHECK_ARGS ;
fi fi
# We jump some hoops in common_test_job_template to avoid
# rebuilding all the object files we skip in the artifacts
.native_build_artifact_template:
artifacts:
expire_in: 2 days
paths:
- build
- .git-submodule-status
exclude:
- build/**/*.p
- build/**/*.a.p
- build/**/*.fa.p
- build/**/*.c.o
- build/**/*.c.o.d
- build/**/*.fa
.common_test_job_template: .common_test_job_template:
extends: .base_job_template extends: .base_job_template
stage: test stage: test

View File

@@ -2,16 +2,20 @@ include:
- local: '/.gitlab-ci.d/buildtest-template.yml' - local: '/.gitlab-ci.d/buildtest-template.yml'
build-system-alpine: build-system-alpine:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
- job: amd64-alpine-container - job: amd64-alpine-container
variables: variables:
IMAGE: alpine IMAGE: alpine
TARGETS: avr-softmmu loongarch64-softmmu mips64-softmmu mipsel-softmmu TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
microblazeel-softmmu mips64el-softmmu
MAKE_CHECK_ARGS: check-build MAKE_CHECK_ARGS: check-build
CONFIGURE_ARGS: --enable-docs --enable-trace-backends=log,simple,syslog CONFIGURE_ARGS: --enable-docs --enable-trace-backends=log,simple,syslog
artifacts:
expire_in: 2 days
paths:
- .git-submodule-status
- build
check-system-alpine: check-system-alpine:
extends: .native_test_job_template extends: .native_test_job_template
@@ -32,17 +36,19 @@ avocado-system-alpine:
MAKE_CHECK_ARGS: check-avocado MAKE_CHECK_ARGS: check-avocado
build-system-ubuntu: build-system-ubuntu:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
job: amd64-ubuntu2204-container job: amd64-ubuntu2004-container
variables: variables:
IMAGE: ubuntu2204 IMAGE: ubuntu2004
CONFIGURE_ARGS: --enable-docs CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-capstone
TARGETS: alpha-softmmu cris-softmmu hppa-softmmu TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
microblazeel-softmmu mips64el-softmmu microblazeel-softmmu mips64el-softmmu
MAKE_CHECK_ARGS: check-build MAKE_CHECK_ARGS: check-build
artifacts:
expire_in: 2 days
paths:
- build
check-system-ubuntu: check-system-ubuntu:
extends: .native_test_job_template extends: .native_test_job_template
@@ -50,7 +56,7 @@ check-system-ubuntu:
- job: build-system-ubuntu - job: build-system-ubuntu
artifacts: true artifacts: true
variables: variables:
IMAGE: ubuntu2204 IMAGE: ubuntu2004
MAKE_CHECK_ARGS: check MAKE_CHECK_ARGS: check
avocado-system-ubuntu: avocado-system-ubuntu:
@@ -59,21 +65,22 @@ avocado-system-ubuntu:
- job: build-system-ubuntu - job: build-system-ubuntu
artifacts: true artifacts: true
variables: variables:
IMAGE: ubuntu2204 IMAGE: ubuntu2004
MAKE_CHECK_ARGS: check-avocado MAKE_CHECK_ARGS: check-avocado
build-system-debian: build-system-debian:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
job: amd64-debian-container job: amd64-debian-container
variables: variables:
IMAGE: debian-amd64 IMAGE: debian-amd64
CONFIGURE_ARGS: --with-coroutine=sigaltstack TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
TARGETS: arm-softmmu i386-softmmu riscv64-softmmu sh4eb-softmmu riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
sparc-softmmu xtensaeb-softmmu
MAKE_CHECK_ARGS: check-build MAKE_CHECK_ARGS: check-build
artifacts:
expire_in: 2 days
paths:
- build
check-system-debian: check-system-debian:
extends: .native_test_job_template extends: .native_test_job_template
@@ -102,21 +109,24 @@ crash-test-debian:
IMAGE: debian-amd64 IMAGE: debian-amd64
script: script:
- cd build - cd build
- make NINJA=":" check-venv - make check-venv
- tests/venv/bin/python3 scripts/device-crash-test -q --tcg-only ./qemu-system-i386 - tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-i386
build-system-fedora: build-system-fedora:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
job: amd64-fedora-container job: amd64-fedora-container
variables: variables:
IMAGE: fedora IMAGE: fedora
CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
--enable-fdt=system --enable-slirp --enable-capstone
TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu
xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
MAKE_CHECK_ARGS: check-build MAKE_CHECK_ARGS: check-build
artifacts:
expire_in: 2 days
paths:
- build
check-system-fedora: check-system-fedora:
extends: .native_test_job_template extends: .native_test_job_template
@@ -145,23 +155,26 @@ crash-test-fedora:
IMAGE: fedora IMAGE: fedora
script: script:
- cd build - cd build
- make NINJA=":" check-venv - make check-venv
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc - tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32 - tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32
build-system-centos: build-system-centos:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
job: amd64-centos8-container job: amd64-centos8-container
variables: variables:
IMAGE: centos8 IMAGE: centos8
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system
--enable-modules --enable-trace-backends=dtrace --enable-docs --enable-modules --enable-trace-backends=dtrace --enable-docs
--enable-vfio-user-server
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 nios2-softmmu
MAKE_CHECK_ARGS: check-build MAKE_CHECK_ARGS: check-build
artifacts:
expire_in: 2 days
paths:
- build
check-system-centos: check-system-centos:
extends: .native_test_job_template extends: .native_test_job_template
@@ -182,15 +195,18 @@ avocado-system-centos:
MAKE_CHECK_ARGS: check-avocado MAKE_CHECK_ARGS: check-avocado
build-system-opensuse: build-system-opensuse:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
job: amd64-opensuse-leap-container job: amd64-opensuse-leap-container
variables: variables:
IMAGE: opensuse-leap IMAGE: opensuse-leap
CONFIGURE_ARGS: --enable-fdt=system
TARGETS: s390x-softmmu x86_64-softmmu aarch64-softmmu TARGETS: s390x-softmmu x86_64-softmmu aarch64-softmmu
MAKE_CHECK_ARGS: check-build MAKE_CHECK_ARGS: check-build
artifacts:
expire_in: 2 days
paths:
- build
check-system-opensuse: check-system-opensuse:
extends: .native_test_job_template extends: .native_test_job_template
@@ -325,9 +341,7 @@ clang-user:
# Split in three sets of build/check/avocado to limit the execution time of each # Split in three sets of build/check/avocado to limit the execution time of each
# job # job
build-cfi-aarch64: build-cfi-aarch64:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
- job: amd64-fedora-container - job: amd64-fedora-container
variables: variables:
@@ -343,6 +357,10 @@ build-cfi-aarch64:
# skipped until the situation has been solved. # skipped until the situation has been solved.
QEMU_JOB_SKIPPED: 1 QEMU_JOB_SKIPPED: 1
timeout: 90m timeout: 90m
artifacts:
expire_in: 2 days
paths:
- build
check-cfi-aarch64: check-cfi-aarch64:
extends: .native_test_job_template extends: .native_test_job_template
@@ -363,9 +381,7 @@ avocado-cfi-aarch64:
MAKE_CHECK_ARGS: check-avocado MAKE_CHECK_ARGS: check-avocado
build-cfi-ppc64-s390x: build-cfi-ppc64-s390x:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
- job: amd64-fedora-container - job: amd64-fedora-container
variables: variables:
@@ -381,6 +397,10 @@ build-cfi-ppc64-s390x:
# skipped until the situation has been solved. # skipped until the situation has been solved.
QEMU_JOB_SKIPPED: 1 QEMU_JOB_SKIPPED: 1
timeout: 80m timeout: 80m
artifacts:
expire_in: 2 days
paths:
- build
check-cfi-ppc64-s390x: check-cfi-ppc64-s390x:
extends: .native_test_job_template extends: .native_test_job_template
@@ -401,9 +421,7 @@ avocado-cfi-ppc64-s390x:
MAKE_CHECK_ARGS: check-avocado MAKE_CHECK_ARGS: check-avocado
build-cfi-x86_64: build-cfi-x86_64:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
- job: amd64-fedora-container - job: amd64-fedora-container
variables: variables:
@@ -415,6 +433,10 @@ build-cfi-x86_64:
TARGETS: x86_64-softmmu TARGETS: x86_64-softmmu
MAKE_CHECK_ARGS: check-build MAKE_CHECK_ARGS: check-build
timeout: 70m timeout: 70m
artifacts:
expire_in: 2 days
paths:
- build
check-cfi-x86_64: check-cfi-x86_64:
extends: .native_test_job_template extends: .native_test_job_template
@@ -437,23 +459,35 @@ avocado-cfi-x86_64:
tsan-build: tsan-build:
extends: .native_build_job_template extends: .native_build_job_template
needs: needs:
job: amd64-ubuntu2204-container job: amd64-ubuntu2004-container
variables: variables:
IMAGE: ubuntu2204 IMAGE: ubuntu2004
CONFIGURE_ARGS: --enable-tsan --cc=clang --cxx=clang++ CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10
--enable-trace-backends=ust --disable-slirp --enable-trace-backends=ust --enable-fdt=system --disable-slirp
TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
MAKE_CHECK_ARGS: bench V=1
# gcov is a GCC features # gprof/gcov are GCC features
gcov: build-gprof-gcov:
extends: .native_build_job_template extends: .native_build_job_template
needs: needs:
job: amd64-ubuntu2204-container job: amd64-ubuntu2004-container
timeout: 80m
variables: variables:
IMAGE: ubuntu2204 IMAGE: ubuntu2004
CONFIGURE_ARGS: --enable-gcov CONFIGURE_ARGS: --enable-gprof --enable-gcov
TARGETS: aarch64-softmmu ppc64-softmmu s390x-softmmu x86_64-softmmu TARGETS: aarch64-softmmu ppc64-softmmu s390x-softmmu x86_64-softmmu
artifacts:
expire_in: 1 days
paths:
- build
check-gprof-gcov:
extends: .native_test_job_template
needs:
- job: build-gprof-gcov
artifacts: true
variables:
IMAGE: ubuntu2004
MAKE_CHECK_ARGS: check MAKE_CHECK_ARGS: check
after_script: after_script:
- cd build - cd build
@@ -511,6 +545,18 @@ build-tci:
- QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow - QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow
- make check-tcg - make check-tcg
# Alternate coroutines implementations are only really of interest to KVM users
# However we can't test against KVM on Gitlab-CI so we can only run unit tests
build-coroutine-sigaltstack:
extends: .native_build_job_template
needs:
job: amd64-ubuntu2004-container
variables:
IMAGE: ubuntu2004
CONFIGURE_ARGS: --with-coroutine=sigaltstack --disable-tcg
--enable-trace-backends=ftrace
MAKE_CHECK_ARGS: check-unit
# Check our reduced build configurations # Check our reduced build configurations
build-without-defaults: build-without-defaults:
extends: .native_build_job_template extends: .native_build_job_template
@@ -544,9 +590,7 @@ build-libvhost-user:
# No targets are built here, just tools, docs, and unit tests. This # No targets are built here, just tools, docs, and unit tests. This
# also feeds into the eventual documentation deployment steps later # also feeds into the eventual documentation deployment steps later
build-tools-and-docs-debian: build-tools-and-docs-debian:
extends: extends: .native_build_job_template
- .native_build_job_template
- .native_build_artifact_template
needs: needs:
job: amd64-debian-container job: amd64-debian-container
# when running on 'master' we use pre-existing container # when running on 'master' we use pre-existing container
@@ -556,6 +600,10 @@ build-tools-and-docs-debian:
MAKE_CHECK_ARGS: check-unit ctags TAGS cscope MAKE_CHECK_ARGS: check-unit ctags TAGS cscope
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
QEMU_JOB_PUBLISH: 1 QEMU_JOB_PUBLISH: 1
artifacts:
expire_in: 2 days
paths:
- build
# Prepare for GitLab pages deployment. Anything copied into the # Prepare for GitLab pages deployment. Anything copied into the
# "public" directory will be deployed to $USER.gitlab.io/$PROJECT # "public" directory will be deployed to $USER.gitlab.io/$PROJECT

View File

@@ -32,9 +32,6 @@ build_task:
- $MAKE -j$(sysctl -n hw.ncpu) - $MAKE -j$(sysctl -n hw.ncpu)
- for TARGET in $TEST_TARGETS ; - for TARGET in $TEST_TARGETS ;
do do
$MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1 ; $MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1
|| { cat meson-logs/testlog.txt; exit 1; } ;
done done
always:
build_result_artifacts:
path: build/meson-logs/*log.txt
type: text/plain

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 cdrkit-genisoimage 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 ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 zstd' PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage 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 ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio spice-protocol tesseract usbredir virglrenderer vte3 zstd'
PYPI_PKGS='' PYPI_PKGS=''
PYTHON='/usr/local/bin/python3' PYTHON='/usr/local/bin/python3'

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 cdrkit-genisoimage 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 ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 zstd' PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage 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 ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio spice-protocol tesseract usbredir virglrenderer vte3 zstd'
PYPI_PKGS='' PYPI_PKGS=''
PYTHON='/usr/local/bin/python3' PYTHON='/usr/local/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 ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol tesseract usbredir vde vte3 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 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract usbredir vde vte3 zlib zstd'
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme' PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme'
PYTHON='/opt/homebrew/bin/python3' PYTHON='/opt/homebrew/bin/python3'

View File

@@ -6,16 +6,17 @@
- docker:dind - docker:dind
before_script: before_script:
- export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest" - export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
- export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/qemu/$NAME:latest" - export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/$NAME:latest"
- apk add python3 - apk add python3
- docker info - docker info
- docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" - docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
script: script:
- echo "TAG:$TAG" - echo "TAG:$TAG"
- echo "COMMON_TAG:$COMMON_TAG" - echo "COMMON_TAG:$COMMON_TAG"
- docker build --tag "$TAG" --cache-from "$TAG" --cache-from "$COMMON_TAG" - ./tests/docker/docker.py --engine docker build
--build-arg BUILDKIT_INLINE_CACHE=1 -t "qemu/$NAME" -f "tests/docker/dockerfiles/$NAME.docker"
-f "tests/docker/dockerfiles/$NAME.docker" "." -r $CI_REGISTRY/qemu-project/qemu
- docker tag "qemu/$NAME" "$TAG"
- docker push "$TAG" - docker push "$TAG"
after_script: after_script:
- docker logout - docker logout

View File

@@ -13,10 +13,10 @@ amd64-debian-container:
variables: variables:
NAME: debian-amd64 NAME: debian-amd64
amd64-ubuntu2204-container: amd64-ubuntu2004-container:
extends: .container_job_template extends: .container_job_template
variables: variables:
NAME: ubuntu2204 NAME: ubuntu2004
amd64-opensuse-leap-container: amd64-opensuse-leap-container:
extends: .container_job_template extends: .container_job_template

View File

@@ -6,9 +6,8 @@
script: script:
- mkdir build - mkdir build
- cd build - cd build
- ../configure --enable-werror --disable-docs --enable-fdt=system - ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
--disable-user $QEMU_CONFIGURE_OPTS $EXTRA_CONFIGURE_OPTS --disable-user --target-list-exclude="arm-softmmu cris-softmmu
--target-list-exclude="arm-softmmu cris-softmmu
i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu
mips64-softmmu ppc-softmmu riscv32-softmmu sh4-softmmu mips64-softmmu ppc-softmmu riscv32-softmmu sh4-softmmu
sparc-softmmu xtensa-softmmu $CROSS_SKIP_TARGETS" sparc-softmmu xtensa-softmmu $CROSS_SKIP_TARGETS"
@@ -49,14 +48,3 @@
nios2-linux-user or1k-linux-user ppc-linux-user sparc-linux-user nios2-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
# We can still run some tests on some of our cross build jobs. They can add this
# template to their extends to save the build logs and test results
.cross_test_artifacts:
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
expire_in: 7 days
paths:
- build/meson-logs/testlog.txt
reports:
junit: build/meson-logs/testlog.junit.xml

View File

@@ -1,6 +1,13 @@
include: include:
- local: '/.gitlab-ci.d/crossbuild-template.yml' - local: '/.gitlab-ci.d/crossbuild-template.yml'
cross-armel-system:
extends: .cross_system_build_job
needs:
job: armel-debian-cross-container
variables:
IMAGE: debian-armel-cross
cross-armel-user: cross-armel-user:
extends: .cross_user_build_job extends: .cross_user_build_job
needs: needs:
@@ -8,6 +15,13 @@ cross-armel-user:
variables: variables:
IMAGE: debian-armel-cross IMAGE: debian-armel-cross
cross-armhf-system:
extends: .cross_system_build_job
needs:
job: armhf-debian-cross-container
variables:
IMAGE: debian-armhf-cross
cross-armhf-user: cross-armhf-user:
extends: .cross_user_build_job extends: .cross_user_build_job
needs: needs:
@@ -29,10 +43,16 @@ cross-arm64-user:
variables: variables:
IMAGE: debian-arm64-cross IMAGE: debian-arm64-cross
cross-i386-system:
extends: .cross_system_build_job
needs:
job: i386-fedora-cross-container
variables:
IMAGE: fedora-i386-cross
MAKE_CHECK_ARGS: check-qtest
cross-i386-user: cross-i386-user:
extends: extends: .cross_user_build_job
- .cross_user_build_job
- .cross_test_artifacts
needs: needs:
job: i386-fedora-cross-container job: i386-fedora-cross-container
variables: variables:
@@ -40,9 +60,7 @@ cross-i386-user:
MAKE_CHECK_ARGS: check MAKE_CHECK_ARGS: check
cross-i386-tci: cross-i386-tci:
extends: extends: .cross_accel_build_job
- .cross_accel_build_job
- .cross_test_artifacts
timeout: 60m timeout: 60m
needs: needs:
job: i386-fedora-cross-container job: i386-fedora-cross-container
@@ -141,7 +159,7 @@ cross-s390x-kvm-only:
job: s390x-debian-cross-container job: s390x-debian-cross-container
variables: variables:
IMAGE: debian-s390x-cross IMAGE: debian-s390x-cross
EXTRA_CONFIGURE_OPTS: --disable-tcg --enable-trace-backends=ftrace EXTRA_CONFIGURE_OPTS: --disable-tcg
cross-mips64el-kvm-only: cross-mips64el-kvm-only:
extends: .cross_accel_build_job extends: .cross_accel_build_job
@@ -157,7 +175,6 @@ cross-win32-system:
job: win32-fedora-cross-container job: win32-fedora-cross-container
variables: variables:
IMAGE: fedora-win32-cross IMAGE: fedora-win32-cross
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
microblazeel-softmmu mips64el-softmmu nios2-softmmu microblazeel-softmmu mips64el-softmmu nios2-softmmu
artifacts: artifacts:
@@ -170,7 +187,6 @@ cross-win64-system:
job: win64-fedora-cross-container job: win64-fedora-cross-container
variables: variables:
IMAGE: fedora-win64-cross IMAGE: fedora-win64-cross
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal
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 nios2-softmmu
or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu

View File

@@ -15,8 +15,7 @@ variables:
# All custom runners can extend this template to upload the testlog # All custom runners can extend this template to upload the testlog
# data as an artifact and also feed the junit report # data as an artifact and also feed the junit report
.custom_runner_template: .custom_artifacts_template:
extends: .base_job_template
artifacts: artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
expire_in: 7 days expire_in: 7 days

View File

@@ -1,9 +1,4 @@
# 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: centos-stream-8-x86_64:
extends: .custom_runner_template
allow_failure: true allow_failure: true
needs: [] needs: []
stage: build stage: build
@@ -13,6 +8,15 @@ centos-stream-8-x86_64:
rules: rules:
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
- if: "$CENTOS_STREAM_8_x86_64_RUNNER_AVAILABLE" - if: "$CENTOS_STREAM_8_x86_64_RUNNER_AVAILABLE"
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
when: on_failure
expire_in: 7 days
paths:
- build/tests/results/latest/results.xml
- build/tests/results/latest/test-results
reports:
junit: build/tests/results/latest/results.xml
before_script: before_script:
- JOBS=$(expr $(nproc) + 1) - JOBS=$(expr $(nproc) + 1)
script: script:
@@ -21,4 +25,6 @@ centos-stream-8-x86_64:
- ../scripts/ci/org.centos/stream/8/x86_64/configure - ../scripts/ci/org.centos/stream/8/x86_64/configure
|| { 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"
- make NINJA=":" check check-avocado - make NINJA=":" check
|| { cat meson-logs/testlog.txt; exit 1; } ;
- ../scripts/ci/org.centos/stream/8/x86_64/test-avocado

View File

@@ -3,7 +3,7 @@
# "Install basic packages to build QEMU on Ubuntu 20.04/20.04" # "Install basic packages to build QEMU on Ubuntu 20.04/20.04"
ubuntu-20.04-s390x-all-linux-static: ubuntu-20.04-s390x-all-linux-static:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:
@@ -24,7 +24,7 @@ ubuntu-20.04-s390x-all-linux-static:
- make --output-sync -j`nproc` check - make --output-sync -j`nproc` check
ubuntu-20.04-s390x-all: ubuntu-20.04-s390x-all:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:
@@ -43,7 +43,7 @@ ubuntu-20.04-s390x-all:
- make --output-sync -j`nproc` check - make --output-sync -j`nproc` check
ubuntu-20.04-s390x-alldbg: ubuntu-20.04-s390x-alldbg:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:
@@ -66,7 +66,7 @@ ubuntu-20.04-s390x-alldbg:
- make --output-sync -j`nproc` check - make --output-sync -j`nproc` check
ubuntu-20.04-s390x-clang: ubuntu-20.04-s390x-clang:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:
@@ -108,7 +108,7 @@ ubuntu-20.04-s390x-tci:
- make --output-sync -j`nproc` - make --output-sync -j`nproc`
ubuntu-20.04-s390x-notcg: ubuntu-20.04-s390x-notcg:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:

View File

@@ -3,7 +3,7 @@
# "Install basic packages to build QEMU on Ubuntu 20.04" # "Install basic packages to build QEMU on Ubuntu 20.04"
ubuntu-22.04-aarch32-all: ubuntu-22.04-aarch32-all:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:

View File

@@ -3,7 +3,7 @@
# "Install basic packages to build QEMU on Ubuntu 20.04" # "Install basic packages to build QEMU on Ubuntu 20.04"
ubuntu-22.04-aarch64-all-linux-static: ubuntu-22.04-aarch64-all-linux-static:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:
@@ -24,7 +24,7 @@ ubuntu-22.04-aarch64-all-linux-static:
- make --output-sync -j`nproc --ignore=40` check - make --output-sync -j`nproc --ignore=40` check
ubuntu-22.04-aarch64-all: ubuntu-22.04-aarch64-all:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:
@@ -46,7 +46,7 @@ ubuntu-22.04-aarch64-all:
- make --output-sync -j`nproc --ignore=40` check - make --output-sync -j`nproc --ignore=40` check
ubuntu-22.04-aarch64-alldbg: ubuntu-22.04-aarch64-alldbg:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:
@@ -65,7 +65,7 @@ ubuntu-22.04-aarch64-alldbg:
- make --output-sync -j`nproc --ignore=40` check - make --output-sync -j`nproc --ignore=40` check
ubuntu-22.04-aarch64-clang: ubuntu-22.04-aarch64-clang:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:
@@ -107,7 +107,7 @@ ubuntu-22.04-aarch64-tci:
- make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40`
ubuntu-22.04-aarch64-notcg: ubuntu-22.04-aarch64-notcg:
extends: .custom_runner_template extends: .custom_artifacts_template
needs: [] needs: []
stage: build stage: build
tags: tags:

85
.gitlab-ci.d/edk2.yml Normal file
View File

@@ -0,0 +1,85 @@
# All jobs needing docker-edk2 must use the same rules it uses.
.edk2_job_rules:
rules:
# Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
when: never
# In forks, if QEMU_CI=1 is set, then create manual job
# if any of the files affecting the build are touched
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
changes:
- .gitlab-ci.d/edk2.yml
- .gitlab-ci.d/edk2/Dockerfile
- roms/edk2/*
when: manual
# In forks, if QEMU_CI=1 is set, then create manual job
# if the branch/tag starts with 'edk2'
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_REF_NAME =~ /^edk2/'
when: manual
# In forks, if QEMU_CI=1 is set, then create manual job
# if last commit msg contains 'EDK2' (case insensitive)
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_MESSAGE =~ /edk2/i'
when: manual
# Run if any files affecting the build output are touched
- changes:
- .gitlab-ci.d/edk2.yml
- .gitlab-ci.d/edk2/Dockerfile
- roms/edk2/*
when: on_success
# Run if the branch/tag starts with 'edk2'
- if: '$CI_COMMIT_REF_NAME =~ /^edk2/'
when: on_success
# Run if last commit msg contains 'EDK2' (case insensitive)
- if: '$CI_COMMIT_MESSAGE =~ /edk2/i'
when: on_success
docker-edk2:
extends: .edk2_job_rules
stage: containers
image: docker:19.03.1
services:
- docker:19.03.1-dind
variables:
GIT_DEPTH: 3
IMAGE_TAG: $CI_REGISTRY_IMAGE:edk2-cross-build
# We don't use TLS
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker pull $IMAGE_TAG || true
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
--tag $IMAGE_TAG .gitlab-ci.d/edk2
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $IMAGE_TAG
build-edk2:
extends: .edk2_job_rules
stage: build
needs: ['docker-edk2']
artifacts:
paths: # 'artifacts.zip' will contains the following files:
- pc-bios/edk2*bz2
- pc-bios/edk2-licenses.txt
- edk2-stdout.log
- edk2-stderr.log
image: $CI_REGISTRY_IMAGE:edk2-cross-build
variables:
GIT_DEPTH: 3
script: # Clone the required submodules and build EDK2
- git submodule update --init roms/edk2
- git -C roms/edk2 submodule update --init --
ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
BaseTools/Source/C/BrotliCompress/brotli
CryptoPkg/Library/OpensslLib/openssl
MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
- echo "=== Using ${JOBS} simultaneous jobs ==="
- make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2

View File

@@ -0,0 +1,27 @@
#
# Docker image to cross-compile EDK2 firmware binaries
#
FROM ubuntu:18.04
MAINTAINER Philippe Mathieu-Daudé <f4bug@amsat.org>
# Install packages required to build EDK2
RUN apt update \
&& \
\
DEBIAN_FRONTEND=noninteractive \
apt install --assume-yes --no-install-recommends \
build-essential \
ca-certificates \
dos2unix \
gcc-aarch64-linux-gnu \
gcc-arm-linux-gnueabi \
git \
iasl \
make \
nasm \
python3 \
uuid-dev \
&& \
\
rm -rf /var/lib/apt/lists/*

View File

@@ -42,9 +42,9 @@
docker-opensbi: docker-opensbi:
extends: .opensbi_job_rules extends: .opensbi_job_rules
stage: containers stage: containers
image: docker:stable image: docker:19.03.1
services: services:
- docker:stable-dind - docker:19.03.1-dind
variables: variables:
GIT_DEPTH: 3 GIT_DEPTH: 3
IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build

View File

@@ -15,7 +15,6 @@ RUN apt update \
ca-certificates \ ca-certificates \
git \ git \
make \ make \
python3 \
wget \ wget \
&& \ && \
\ \

View File

@@ -4,6 +4,7 @@
include: include:
- local: '/.gitlab-ci.d/base.yml' - local: '/.gitlab-ci.d/base.yml'
- local: '/.gitlab-ci.d/stages.yml' - local: '/.gitlab-ci.d/stages.yml'
- local: '/.gitlab-ci.d/edk2.yml'
- local: '/.gitlab-ci.d/opensbi.yml' - local: '/.gitlab-ci.d/opensbi.yml'
- local: '/.gitlab-ci.d/containers.yml' - local: '/.gitlab-ci.d/containers.yml'
- local: '/.gitlab-ci.d/crossbuilds.yml' - local: '/.gitlab-ci.d/crossbuilds.yml'

View File

@@ -23,12 +23,12 @@ check-dco:
before_script: before_script:
- apk -U add git - apk -U add git
check-python-minreqs: check-python-pipenv:
extends: .base_job_template extends: .base_job_template
stage: test stage: test
image: $CI_REGISTRY_IMAGE/qemu/python:latest image: $CI_REGISTRY_IMAGE/qemu/python:latest
script: script:
- make -C python check-minreqs - make -C python check-pipenv
variables: variables:
GIT_DEPTH: 1 GIT_DEPTH: 1
needs: needs:

View File

@@ -38,7 +38,6 @@ msys2-64bit:
mingw-w64-x86_64-capstone mingw-w64-x86_64-capstone
mingw-w64-x86_64-curl mingw-w64-x86_64-curl
mingw-w64-x86_64-cyrus-sasl 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-gnutls
@@ -59,7 +58,6 @@ msys2-64bit:
mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2
mingw-w64-x86_64-SDL2_image mingw-w64-x86_64-SDL2_image
mingw-w64-x86_64-snappy mingw-w64-x86_64-snappy
mingw-w64-x86_64-spice
mingw-w64-x86_64-usbredir mingw-w64-x86_64-usbredir
mingw-w64-x86_64-zstd " mingw-w64-x86_64-zstd "
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory - $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
@@ -73,7 +71,7 @@ msys2-64bit:
# for the msys2 64-bit job, due to the build could not complete within # for the msys2 64-bit job, due to the build could not complete within
# the project timeout. # the project timeout.
- ..\msys64\usr\bin\bash -lc '../configure --target-list=x86_64-softmmu - ..\msys64\usr\bin\bash -lc '../configure --target-list=x86_64-softmmu
--without-default-devices --enable-fdt=system' --without-default-devices'
- ..\msys64\usr\bin\bash -lc 'make' - ..\msys64\usr\bin\bash -lc 'make'
# qTests don't run successfully with "--without-default-devices", # qTests don't run successfully with "--without-default-devices",
# so let's exclude the qtests from CI for now. # so let's exclude the qtests from CI for now.
@@ -88,7 +86,6 @@ msys2-32bit:
mingw-w64-i686-capstone mingw-w64-i686-capstone
mingw-w64-i686-curl mingw-w64-i686-curl
mingw-w64-i686-cyrus-sasl mingw-w64-i686-cyrus-sasl
mingw-w64-i686-dtc
mingw-w64-i686-gcc mingw-w64-i686-gcc
mingw-w64-i686-glib2 mingw-w64-i686-glib2
mingw-w64-i686-gnutls mingw-w64-i686-gnutls
@@ -109,7 +106,6 @@ msys2-32bit:
mingw-w64-i686-SDL2 mingw-w64-i686-SDL2
mingw-w64-i686-SDL2_image mingw-w64-i686-SDL2_image
mingw-w64-i686-snappy mingw-w64-i686-snappy
mingw-w64-i686-spice
mingw-w64-i686-usbredir mingw-w64-i686-usbredir
mingw-w64-i686-zstd " mingw-w64-i686-zstd "
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory - $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
@@ -117,8 +113,7 @@ msys2-32bit:
- $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink - $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
- mkdir output - mkdir output
- cd output - cd output
- ..\msys64\usr\bin\bash -lc '../configure --target-list=ppc64-softmmu - ..\msys64\usr\bin\bash -lc '../configure --target-list=ppc64-softmmu'
--enable-fdt=system'
- ..\msys64\usr\bin\bash -lc 'make' - ..\msys64\usr\bin\bash -lc 'make'
- ..\msys64\usr\bin\bash -lc 'make check MTESTARGS=\"--no-suite qtest\" || - ..\msys64\usr\bin\bash -lc 'make check MTESTARGS=\"--no-suite qtest\" ||
{ cat meson-logs/testlog.txt; exit 1; }' { cat meson-logs/testlog.txt; exit 1; }'

3
.gitmodules vendored
View File

@@ -13,6 +13,9 @@
[submodule "roms/qemu-palcode"] [submodule "roms/qemu-palcode"]
path = roms/qemu-palcode path = roms/qemu-palcode
url = https://gitlab.com/qemu-project/qemu-palcode.git url = https://gitlab.com/qemu-project/qemu-palcode.git
[submodule "roms/sgabios"]
path = roms/sgabios
url = https://gitlab.com/qemu-project/sgabios.git
[submodule "dtc"] [submodule "dtc"]
path = dtc path = dtc
url = https://gitlab.com/qemu-project/dtc.git url = https://gitlab.com/qemu-project/dtc.git

View File

@@ -56,7 +56,6 @@ Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
Alexander Graf <agraf@csgraf.de> <agraf@suse.de> Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com> Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com> Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
Damien Hedde <damien.hedde@dahe.fr> <damien.hedde@greensocs.com>
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com> Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
Frederic Konrad <konrad.frederic@yahoo.fr> <fred.konrad@greensocs.com> Frederic Konrad <konrad.frederic@yahoo.fr> <fred.konrad@greensocs.com>
Frederic Konrad <konrad.frederic@yahoo.fr> <konrad@adacore.com> Frederic Konrad <konrad.frederic@yahoo.fr> <konrad@adacore.com>

View File

@@ -64,20 +64,6 @@ L: qemu-devel@nongnu.org
F: * F: *
F: */ F: */
Project policy and developer guides
R: Alex Bennée <alex.bennee@linaro.org>
R: Daniel P. Berrangé <berrange@redhat.com>
R: Thomas Huth <thuth@redhat.com>
R: Markus Armbruster <armbru@redhat.com>
R: Philippe Mathieu-Daudé <philmd@linaro.org>
W: https://www.qemu.org/docs/master/devel/index.html
S: Odd Fixes
F: docs/devel/style.rst
F: docs/devel/code-of-conduct.rst
F: docs/devel/conflict-resolution.rst
F: docs/devel/submitting-a-patch.rst
F: docs/devel/submitting-a-pull-request.rst
Responsible Disclosure, Reporting Security Issues Responsible Disclosure, Reporting Security Issues
------------------------------------------------- -------------------------------------------------
W: https://wiki.qemu.org/SecurityProcess W: https://wiki.qemu.org/SecurityProcess
@@ -137,7 +123,6 @@ M: Richard Henderson <richard.henderson@linaro.org>
R: Paolo Bonzini <pbonzini@redhat.com> R: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained S: Maintained
F: softmmu/cpus.c F: softmmu/cpus.c
F: softmmu/watchpoint.c
F: cpus-common.c F: cpus-common.c
F: page-vary.c F: page-vary.c
F: page-vary-common.c F: page-vary-common.c
@@ -150,8 +135,6 @@ F: docs/devel/decodetree.rst
F: docs/devel/tcg* F: docs/devel/tcg*
F: include/exec/cpu*.h F: include/exec/cpu*.h
F: include/exec/exec-all.h F: include/exec/exec-all.h
F: include/exec/tb-flush.h
F: include/exec/target_long.h
F: include/exec/helper*.h F: include/exec/helper*.h
F: include/sysemu/cpus.h F: include/sysemu/cpus.h
F: include/sysemu/tcg.h F: include/sysemu/tcg.h
@@ -178,7 +161,6 @@ M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org L: qemu-arm@nongnu.org
S: Maintained S: Maintained
F: target/arm/ F: target/arm/
F: target/arm/tcg/
F: tests/tcg/arm/ F: tests/tcg/arm/
F: tests/tcg/aarch64/ F: tests/tcg/aarch64/
F: tests/qtest/arm-cpu-features.c F: tests/qtest/arm-cpu-features.c
@@ -271,9 +253,9 @@ F: docs/system/cpu-models-mips.rst.inc
F: tests/tcg/mips/ F: tests/tcg/mips/
NiosII TCG CPUs NiosII TCG CPUs
R: Chris Wulff <crwulff@gmail.com> M: Chris Wulff <crwulff@gmail.com>
R: Marek Vasut <marex@denx.de> M: Marek Vasut <marex@denx.de>
S: Orphan S: Maintained
F: target/nios2/ F: target/nios2/
F: hw/nios2/ F: hw/nios2/
F: disas/nios2.c F: disas/nios2.c
@@ -305,9 +287,6 @@ 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 <bin.meng@windriver.com>
R: Weiwei Li <liweiwei@iscas.ac.cn>
R: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
R: Liu Zhiwei <zhiwei_liu@linux.alibaba.com>
L: qemu-riscv@nongnu.org L: qemu-riscv@nongnu.org
S: Supported S: Supported
F: target/riscv/ F: target/riscv/
@@ -385,7 +364,6 @@ S: Maintained
F: target/xtensa/ F: target/xtensa/
F: hw/xtensa/ F: hw/xtensa/
F: tests/tcg/xtensa/ F: tests/tcg/xtensa/
F: tests/tcg/xtensaeb/
F: disas/xtensa.c F: disas/xtensa.c
F: include/hw/xtensa/xtensa-isa.h F: include/hw/xtensa/xtensa-isa.h
F: configs/devices/xtensa*/default.mak F: configs/devices/xtensa*/default.mak
@@ -460,15 +438,6 @@ F: target/i386/kvm/
F: target/i386/sev* F: target/i386/sev*
F: scripts/kvm/vmxcap F: scripts/kvm/vmxcap
Xen emulation on X86 KVM CPUs
M: David Woodhouse <dwmw2@infradead.org>
M: Paul Durrant <paul@xen.org>
S: Supported
F: include/sysemu/kvm_xen.h
F: target/i386/kvm/xen*
F: hw/i386/kvm/xen*
F: tests/avocado/xen_guest.py
Guest CPU Cores (other accelerators) Guest CPU Cores (other accelerators)
------------------------------------ ------------------------------------
Overall Overall
@@ -838,13 +807,13 @@ F: include/hw/net/mv88w8618_eth.h
F: docs/system/arm/musicpal.rst F: docs/system/arm/musicpal.rst
Nuvoton NPCM7xx Nuvoton NPCM7xx
M: Havard Skinnemoen <hskinnemoen@google.com>
M: Tyrone Ting <kfting@nuvoton.com> M: Tyrone Ting <kfting@nuvoton.com>
M: Hao Wu <wuhaotsh@google.com>
L: qemu-arm@nongnu.org L: qemu-arm@nongnu.org
S: Supported S: Supported
F: hw/*/npcm* F: hw/*/npcm7xx*
F: include/hw/*/npcm* F: include/hw/*/npcm7xx*
F: tests/qtest/npcm* F: tests/qtest/npcm7xx*
F: pc-bios/npcm7xx_bootrom.bin F: pc-bios/npcm7xx_bootrom.bin
F: roms/vbootrom F: roms/vbootrom
F: docs/system/arm/nuvoton.rst F: docs/system/arm/nuvoton.rst
@@ -1025,6 +994,12 @@ S: Maintained
F: hw/ssi/xlnx-versal-ospi.c F: hw/ssi/xlnx-versal-ospi.c
F: include/hw/ssi/xlnx-versal-ospi.h F: include/hw/ssi/xlnx-versal-ospi.h
ARM ACPI Subsystem
M: Shannon Zhao <shannon.zhaosl@gmail.com>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/virt-acpi-build.c
STM32F100 STM32F100
M: Alexandre Iooss <erdnaxe@crans.org> M: Alexandre Iooss <erdnaxe@crans.org>
L: qemu-arm@nongnu.org L: qemu-arm@nongnu.org
@@ -1700,8 +1675,8 @@ F: hw/i2c/smbus_ich9.c
F: hw/acpi/piix4.c F: hw/acpi/piix4.c
F: hw/acpi/ich9*.c F: hw/acpi/ich9*.c
F: include/hw/acpi/ich9*.h F: include/hw/acpi/ich9*.h
F: include/hw/southbridge/ich9.h
F: include/hw/southbridge/piix.h F: include/hw/southbridge/piix.h
F: hw/misc/sga.c
F: hw/isa/apm.c F: hw/isa/apm.c
F: include/hw/isa/apm.h F: include/hw/isa/apm.h
F: tests/unit/test-x86-cpuid.c F: tests/unit/test-x86-cpuid.c
@@ -1733,7 +1708,6 @@ F: include/hw/char/parallel.h
F: include/hw/dma/i8257.h F: include/hw/dma/i8257.h
F: include/hw/i2c/pm_smbus.h F: include/hw/i2c/pm_smbus.h
F: include/hw/input/i8042.h F: include/hw/input/i8042.h
F: include/hw/intc/ioapic*
F: include/hw/isa/i8259_internal.h F: include/hw/isa/i8259_internal.h
F: include/hw/isa/superio.h F: include/hw/isa/superio.h
F: include/hw/timer/hpet.h F: include/hw/timer/hpet.h
@@ -1818,7 +1792,7 @@ F: hw/misc/edu.c
IDE IDE
M: John Snow <jsnow@redhat.com> M: John Snow <jsnow@redhat.com>
L: qemu-block@nongnu.org L: qemu-block@nongnu.org
S: Odd Fixes S: Supported
F: include/hw/ide.h F: include/hw/ide.h
F: include/hw/ide/ F: include/hw/ide/
F: hw/ide/ F: hw/ide/
@@ -1843,7 +1817,7 @@ T: git https://github.com/cminyard/qemu.git master-ipmi-rebase
Floppy Floppy
M: John Snow <jsnow@redhat.com> M: John Snow <jsnow@redhat.com>
L: qemu-block@nongnu.org L: qemu-block@nongnu.org
S: Odd Fixes S: Supported
F: hw/block/fdc.c F: hw/block/fdc.c
F: hw/block/fdc-internal.h F: hw/block/fdc-internal.h
F: hw/block/fdc-isa.c F: hw/block/fdc-isa.c
@@ -1912,18 +1886,6 @@ F: docs/specs/acpi_nvdimm.rst
F: docs/specs/acpi_pci_hotplug.rst F: docs/specs/acpi_pci_hotplug.rst
F: docs/specs/acpi_hw_reduced_hotplug.rst F: docs/specs/acpi_hw_reduced_hotplug.rst
ARM ACPI Subsystem
M: Shannon Zhao <shannon.zhaosl@gmail.com>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/virt-acpi-build.c
RISC-V ACPI Subsystem
M: Sunil V L <sunilvl@ventanamicro.com>
L: qemu-riscv@nongnu.org
S: Maintained
F: hw/riscv/virt-acpi-build.c
ACPI/VIOT ACPI/VIOT
M: Jean-Philippe Brucker <jean-philippe@linaro.org> M: Jean-Philippe Brucker <jean-philippe@linaro.org>
S: Supported S: Supported
@@ -2034,7 +1996,6 @@ F: hw/usb/dev-serial.c
VFIO VFIO
M: Alex Williamson <alex.williamson@redhat.com> M: Alex Williamson <alex.williamson@redhat.com>
R: Cédric Le Goater <clg@redhat.com>
S: Supported S: Supported
F: hw/vfio/* F: hw/vfio/*
F: include/hw/vfio/ F: include/hw/vfio/
@@ -2133,10 +2094,13 @@ T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org L: qemu-s390x@nongnu.org
virtiofs virtiofs
M: Dr. David Alan Gilbert <dgilbert@redhat.com>
M: Stefan Hajnoczi <stefanha@redhat.com> M: Stefan Hajnoczi <stefanha@redhat.com>
S: Supported S: Supported
F: tools/virtiofsd/*
F: hw/virtio/vhost-user-fs* F: hw/virtio/vhost-user-fs*
F: include/hw/virtio/vhost-user-fs.h F: include/hw/virtio/vhost-user-fs.h
F: docs/tools/virtiofsd.rst
L: virtio-fs@redhat.com L: virtio-fs@redhat.com
virtio-input virtio-input
@@ -2250,28 +2214,14 @@ F: docs/specs/rocker.txt
e1000x e1000x
M: Dmitry Fleytman <dmitry.fleytman@gmail.com> M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
R: Akihiko Odaki <akihiko.odaki@daynix.com>
S: Maintained S: Maintained
F: hw/net/e1000x* F: hw/net/e1000x*
e1000e e1000e
M: Dmitry Fleytman <dmitry.fleytman@gmail.com> M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
R: Akihiko Odaki <akihiko.odaki@daynix.com>
S: Maintained S: Maintained
F: hw/net/e1000e* F: hw/net/e1000e*
F: tests/qtest/fuzz-e1000e-test.c F: tests/qtest/fuzz-e1000e-test.c
F: tests/qtest/e1000e-test.c
F: tests/qtest/libqos/e1000e.*
igb
M: Akihiko Odaki <akihiko.odaki@daynix.com>
R: Sriram Yagnaraman <sriram.yagnaraman@est.tech>
S: Maintained
F: docs/system/devices/igb.rst
F: hw/net/igb*
F: tests/avocado/igb.py
F: tests/qtest/igb-test.c
F: tests/qtest/libqos/igb.c
eepro100 eepro100
M: Stefan Weil <sw@weilnetz.de> M: Stefan Weil <sw@weilnetz.de>
@@ -2325,6 +2275,7 @@ F: hw/acpi/vmgenid.c
F: include/hw/acpi/vmgenid.h F: include/hw/acpi/vmgenid.h
F: docs/specs/vmgenid.txt F: docs/specs/vmgenid.txt
F: tests/qtest/vmgenid-test.c F: tests/qtest/vmgenid-test.c
F: stubs/vmgenid.c
LED LED
M: Philippe Mathieu-Daudé <philmd@linaro.org> M: Philippe Mathieu-Daudé <philmd@linaro.org>
@@ -2535,7 +2486,6 @@ Subsystems
---------- ----------
Overall Audio backends Overall Audio backends
M: Gerd Hoffmann <kraxel@redhat.com> M: Gerd Hoffmann <kraxel@redhat.com>
M: Marc-André Lureau <marcandre.lureau@redhat.com>
S: Odd Fixes S: Odd Fixes
F: audio/ F: audio/
X: audio/alsaaudio.c X: audio/alsaaudio.c
@@ -2681,8 +2631,8 @@ T: git https://gitlab.com/jsnow/qemu.git jobs
T: git https://gitlab.com/vsementsov/qemu.git block T: git https://gitlab.com/vsementsov/qemu.git block
Compute Express Link Compute Express Link
M: Ben Widawsky <ben.widawsky@intel.com>
M: Jonathan Cameron <jonathan.cameron@huawei.com> M: Jonathan Cameron <jonathan.cameron@huawei.com>
R: Fan Ni <fan.ni@samsung.com>
S: Supported S: Supported
F: hw/cxl/ F: hw/cxl/
F: hw/mem/cxl_type3.c F: hw/mem/cxl_type3.c
@@ -2780,11 +2730,9 @@ S: Maintained
F: docs/system/gdb.rst F: docs/system/gdb.rst
F: gdbstub/* F: gdbstub/*
F: include/exec/gdbstub.h F: include/exec/gdbstub.h
F: include/gdbstub/*
F: gdb-xml/ F: gdb-xml/
F: tests/tcg/multiarch/gdbstub/ F: tests/tcg/multiarch/gdbstub/
F: scripts/feature_to_c.sh F: scripts/feature_to_c.sh
F: scripts/probe-gdb-support.py
Memory API Memory API
M: Paolo Bonzini <pbonzini@redhat.com> M: Paolo Bonzini <pbonzini@redhat.com>
@@ -2832,7 +2780,6 @@ F: docs/spice-port-fqdn.txt
Graphics Graphics
M: Gerd Hoffmann <kraxel@redhat.com> M: Gerd Hoffmann <kraxel@redhat.com>
M: Marc-André Lureau <marcandre.lureau@redhat.com>
S: Odd Fixes S: Odd Fixes
F: ui/ F: ui/
F: include/ui/ F: include/ui/
@@ -2868,15 +2815,13 @@ F: qapi/run-state.json
Read, Copy, Update (RCU) Read, Copy, Update (RCU)
M: Paolo Bonzini <pbonzini@redhat.com> M: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained S: Maintained
F: docs/devel/lockcnt.txt
F: docs/devel/rcu.txt
F: include/qemu/rcu*.h F: include/qemu/rcu*.h
F: tests/unit/rcutorture.c F: tests/unit/rcutorture.c
F: tests/unit/test-rcu-*.c F: tests/unit/test-rcu-*.c
F: util/rcu.c F: util/rcu.c
Human Monitor (HMP) Human Monitor (HMP)
M: Dr. David Alan Gilbert <dave@treblig.org> M: Dr. David Alan Gilbert <dgilbert@redhat.com>
S: Maintained S: Maintained
F: monitor/monitor-internal.h F: monitor/monitor-internal.h
F: monitor/misc.c F: monitor/misc.c
@@ -2916,11 +2861,9 @@ T: git https://gitlab.com/ehabkost/qemu.git machine-next
Cryptodev Backends Cryptodev Backends
M: Gonglei <arei.gonglei@huawei.com> M: Gonglei <arei.gonglei@huawei.com>
M: zhenwei pi <pizhenwei@bytedance.com>
S: Maintained S: Maintained
F: include/sysemu/cryptodev*.h F: include/sysemu/cryptodev*.h
F: backends/cryptodev*.c F: backends/cryptodev*.c
F: qapi/cryptodev.json
Python library Python library
M: John Snow <jsnow@redhat.com> M: John Snow <jsnow@redhat.com>
@@ -3149,6 +3092,7 @@ F: scripts/checkpatch.pl
Migration Migration
M: Juan Quintela <quintela@redhat.com> M: Juan Quintela <quintela@redhat.com>
M: Dr. David Alan Gilbert <dgilbert@redhat.com>
S: Maintained S: Maintained
F: hw/core/vmstate-if.c F: hw/core/vmstate-if.c
F: include/hw/vmstate-if.h F: include/hw/vmstate-if.h
@@ -3292,7 +3236,6 @@ S: Supported
F: replay/* F: replay/*
F: block/blkreplay.c F: block/blkreplay.c
F: net/filter-replay.c F: net/filter-replay.c
F: include/exec/replay-core.h
F: include/sysemu/replay.h F: include/sysemu/replay.h
F: docs/devel/replay.rst F: docs/devel/replay.rst
F: docs/system/replay.rst F: docs/system/replay.rst
@@ -3357,6 +3300,8 @@ F: roms/edk2
F: roms/edk2-* F: roms/edk2-*
F: tests/data/uefi-boot-images/ F: tests/data/uefi-boot-images/
F: tests/uefi-test-tools/ F: tests/uefi-test-tools/
F: .gitlab-ci.d/edk2.yml
F: .gitlab-ci.d/edk2/
VT-d Emulation VT-d Emulation
M: Michael S. Tsirkin <mst@redhat.com> M: Michael S. Tsirkin <mst@redhat.com>
@@ -3376,7 +3321,7 @@ F: .gitlab-ci.d/opensbi/
Clock framework Clock framework
M: Luc Michel <luc@lmichel.fr> M: Luc Michel <luc@lmichel.fr>
R: Damien Hedde <damien.hedde@dahe.fr> R: Damien Hedde <damien.hedde@greensocs.com>
S: Maintained S: Maintained
F: include/hw/clock.h F: include/hw/clock.h
F: include/hw/qdev-clock.h F: include/hw/qdev-clock.h
@@ -3635,11 +3580,13 @@ F: block/dmg.c
parallels parallels
M: Stefan Hajnoczi <stefanha@redhat.com> M: Stefan Hajnoczi <stefanha@redhat.com>
M: Denis V. Lunev <den@openvz.org> M: Denis V. Lunev <den@openvz.org>
M: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
L: qemu-block@nongnu.org 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.txt
T: git https://gitlab.com/vsementsov/qemu.git block
qed qed
M: Stefan Hajnoczi <stefanha@redhat.com> M: Stefan Hajnoczi <stefanha@redhat.com>
@@ -3814,7 +3761,6 @@ F: scripts/ci/
F: tests/docker/ F: tests/docker/
F: tests/vm/ F: tests/vm/
F: tests/lcitool/ F: tests/lcitool/
F: tests/avocado/tuxrun_baselines.py
F: scripts/archive-source.sh F: scripts/archive-source.sh
F: docs/devel/testing.rst F: docs/devel/testing.rst
W: https://gitlab.com/qemu-project/qemu/pipelines W: https://gitlab.com/qemu-project/qemu/pipelines
@@ -3831,7 +3777,8 @@ W: https://cirrus-ci.com/github/qemu/qemu
Windows Hosted Continuous Integration Windows Hosted Continuous Integration
M: Yonggang Luo <luoyonggang@gmail.com> M: Yonggang Luo <luoyonggang@gmail.com>
S: Maintained S: Maintained
F: .gitlab-ci.d/windows.yml F: .cirrus.yml
W: https://cirrus-ci.com/github/qemu/qemu
Guest Test Compilation Support Guest Test Compilation Support
M: Alex Bennée <alex.bennee@linaro.org> M: Alex Bennée <alex.bennee@linaro.org>
@@ -3920,8 +3867,3 @@ Performance Tools and Tests
M: Ahmed Karaman <ahmedkhaledkaraman@gmail.com> M: Ahmed Karaman <ahmedkhaledkaraman@gmail.com>
S: Maintained S: Maintained
F: scripts/performance/ F: scripts/performance/
Code Coverage Tools
M: Alex Bennée <alex.bennee@linaro.org>
S: Odd Fixes
F: scripts/coverage/

View File

@@ -220,7 +220,7 @@ qemu-%.tar.bz2:
distclean: clean recurse-distclean distclean: clean recurse-distclean
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || : -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || :
rm -f config-host.mak Makefile.prereqs rm -f config-host.mak Makefile.prereqs qemu-bundle
rm -f tests/tcg/*/config-target.mak tests/tcg/config-host.mak rm -f tests/tcg/*/config-target.mak tests/tcg/config-host.mak
rm -f config.status rm -f config.status
rm -f roms/seabios/config.mak rm -f roms/seabios/config.mak
@@ -230,7 +230,7 @@ distclean: clean recurse-distclean
rm -f Makefile.ninja Makefile.mtest build.ninja.stamp meson.stamp rm -f Makefile.ninja Makefile.mtest build.ninja.stamp meson.stamp
rm -f config.log rm -f config.log
rm -f linux-headers/asm rm -f linux-headers/asm
rm -Rf .sdk qemu-bundle rm -Rf .sdk
find-src-path = find "$(SRC_PATH)" -path "$(SRC_PATH)/meson" -prune -o \ find-src-path = find "$(SRC_PATH)" -path "$(SRC_PATH)/meson" -prune -o \
-type l -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \) -type l -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)

View File

@@ -1 +1 @@
8.0.5 7.2.50

View File

@@ -27,7 +27,7 @@
#include "qemu/accel.h" #include "qemu/accel.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
#include "qemu/error-report.h"
#include "accel-softmmu.h" #include "accel-softmmu.h"
int accel_init_machine(AccelState *accel, MachineState *ms) int accel_init_machine(AccelState *accel, MachineState *ms)

View File

@@ -86,13 +86,6 @@ static bool kvm_cpus_are_resettable(void)
return !kvm_enabled() || kvm_cpu_check_are_resettable(); return !kvm_enabled() || kvm_cpu_check_are_resettable();
} }
#ifdef KVM_CAP_SET_GUEST_DEBUG
static int kvm_update_guest_debug_ops(CPUState *cpu)
{
return kvm_update_guest_debug(cpu, 0);
}
#endif
static void kvm_accel_ops_class_init(ObjectClass *oc, void *data) static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
{ {
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
@@ -106,7 +99,6 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
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 KVM_CAP_SET_GUEST_DEBUG
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;
ops->remove_breakpoint = kvm_remove_breakpoint; ops->remove_breakpoint = kvm_remove_breakpoint;

View File

@@ -685,15 +685,6 @@ static uint32_t kvm_dirty_ring_reap_one(KVMState *s, CPUState *cpu)
uint32_t ring_size = s->kvm_dirty_ring_size; uint32_t ring_size = s->kvm_dirty_ring_size;
uint32_t count = 0, fetch = cpu->kvm_fetch_index; uint32_t count = 0, fetch = cpu->kvm_fetch_index;
/*
* It's possible that we race with vcpu creation code where the vcpu is
* put onto the vcpus list but not yet initialized the dirty ring
* structures. If so, skip it.
*/
if (!cpu->created) {
return 0;
}
assert(dirty_gfns && ring_size); assert(dirty_gfns && ring_size);
trace_kvm_dirty_ring_reap_vcpu(cpu->cpu_index); trace_kvm_dirty_ring_reap_vcpu(cpu->cpu_index);
@@ -2370,19 +2361,19 @@ static int kvm_init(MachineState *ms)
static const char upgrade_note[] = static const char upgrade_note[] =
"Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n" "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
"(see http://sourceforge.net/projects/kvm).\n"; "(see http://sourceforge.net/projects/kvm).\n";
const struct { struct {
const char *name; const char *name;
int num; int num;
} num_cpus[] = { } num_cpus[] = {
{ "SMP", ms->smp.cpus }, { "SMP", ms->smp.cpus },
{ "hotpluggable", ms->smp.max_cpus }, { "hotpluggable", ms->smp.max_cpus },
{ /* end of list */ } { NULL, }
}, *nc = num_cpus; }, *nc = num_cpus;
int soft_vcpus_limit, hard_vcpus_limit; int soft_vcpus_limit, hard_vcpus_limit;
KVMState *s; KVMState *s;
const KVMCapabilityInfo *missing_cap; const KVMCapabilityInfo *missing_cap;
int ret; int ret;
int type; int type = 0;
uint64_t dirty_log_manual_caps; uint64_t dirty_log_manual_caps;
qemu_mutex_init(&kml_slots_lock); qemu_mutex_init(&kml_slots_lock);
@@ -2447,8 +2438,6 @@ static int kvm_init(MachineState *ms)
type = mc->kvm_type(ms, kvm_type); type = mc->kvm_type(ms, kvm_type);
} else if (mc->kvm_type) { } else if (mc->kvm_type) {
type = mc->kvm_type(ms, NULL); type = mc->kvm_type(ms, NULL);
} else {
type = kvm_arch_get_default_type(ms);
} }
do { do {
@@ -3316,7 +3305,7 @@ bool kvm_supports_guest_debug(void)
return kvm_has_guest_debug; return kvm_has_guest_debug;
} }
int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) int kvm_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len)
{ {
struct kvm_sw_breakpoint *bp; struct kvm_sw_breakpoint *bp;
int err; int err;
@@ -3354,7 +3343,7 @@ int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len)
return 0; return 0;
} }
int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len) int kvm_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len)
{ {
struct kvm_sw_breakpoint *bp; struct kvm_sw_breakpoint *bp;
int err; int err;
@@ -3714,9 +3703,6 @@ static void kvm_accel_instance_init(Object *obj)
s->kvm_dirty_ring_size = 0; s->kvm_dirty_ring_size = 0;
s->notify_vmexit = NOTIFY_VMEXIT_OPTION_RUN; s->notify_vmexit = NOTIFY_VMEXIT_OPTION_RUN;
s->notify_window = 0; s->notify_window = 0;
s->xen_version = 0;
s->xen_gnttab_max_frames = 64;
s->xen_evtchn_max_pirq = 256;
} }
/** /**

View File

@@ -19,8 +19,8 @@ void kvm_cpu_synchronize_post_reset(CPUState *cpu);
void kvm_cpu_synchronize_post_init(CPUState *cpu); void kvm_cpu_synchronize_post_init(CPUState *cpu);
void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu); void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu);
bool kvm_supports_guest_debug(void); 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, hwaddr addr, hwaddr len);
int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len); int kvm_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr 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

@@ -11,7 +11,6 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "exec/tb-flush.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
void tb_flush(CPUState *cpu) void tb_flush(CPUState *cpu)
@@ -26,7 +25,7 @@ void tcg_flush_jmp_cache(CPUState *cpu)
{ {
} }
int probe_access_flags(CPUArchState *env, target_ulong addr, int size, int probe_access_flags(CPUArchState *env, target_ulong addr,
MMUAccessType access_type, int mmu_idx, MMUAccessType access_type, int mmu_idx,
bool nonfault, void **phost, uintptr_t retaddr) bool nonfault, void **phost, uintptr_t retaddr)
{ {

View File

@@ -21,7 +21,6 @@
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
#include "sysemu/tcg.h" #include "sysemu/tcg.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "qemu/plugin.h"
bool tcg_allowed; bool tcg_allowed;
@@ -66,8 +65,6 @@ void cpu_loop_exit(CPUState *cpu)
{ {
/* Undo the setting in cpu_tb_exec. */ /* Undo the setting in cpu_tb_exec. */
cpu->can_do_io = 1; cpu->can_do_io = 1;
/* Undo any setting in generated code. */
qemu_plugin_disable_mem_helpers(cpu);
siglongjmp(cpu->jmp_env, 1); siglongjmp(cpu->jmp_env, 1);
} }

View File

@@ -20,6 +20,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/qemu-print.h" #include "qemu/qemu-print.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qapi-commands-machine.h"
#include "qapi/type-helpers.h" #include "qapi/type-helpers.h"
#include "hw/core/tcg-cpu-ops.h" #include "hw/core/tcg-cpu-ops.h"
#include "trace.h" #include "trace.h"
@@ -27,6 +28,7 @@
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "tcg/tcg.h" #include "tcg/tcg.h"
#include "qemu/atomic.h" #include "qemu/atomic.h"
#include "qemu/timer.h"
#include "qemu/rcu.h" #include "qemu/rcu.h"
#include "exec/log.h" #include "exec/log.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
@@ -36,7 +38,7 @@
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
#include "exec/cpu-all.h" #include "exec/cpu-all.h"
#include "sysemu/cpu-timers.h" #include "sysemu/cpu-timers.h"
#include "exec/replay-core.h" #include "sysemu/replay.h"
#include "sysemu/tcg.h" #include "sysemu/tcg.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "tb-jmp-cache.h" #include "tb-jmp-cache.h"
@@ -62,8 +64,8 @@ typedef struct SyncClocks {
#define MAX_DELAY_PRINT_RATE 2000000000LL #define MAX_DELAY_PRINT_RATE 2000000000LL
#define MAX_NB_PRINTS 100 #define MAX_NB_PRINTS 100
int64_t max_delay; static int64_t max_delay;
int64_t max_advance; static int64_t max_advance;
static void align_clocks(SyncClocks *sc, CPUState *cpu) static void align_clocks(SyncClocks *sc, CPUState *cpu)
{ {
@@ -183,7 +185,7 @@ static bool tb_lookup_cmp(const void *p, const void *d)
const TranslationBlock *tb = p; const TranslationBlock *tb = p;
const struct tb_desc *desc = d; const struct tb_desc *desc = d;
if ((tb_cflags(tb) & CF_PCREL || tb->pc == desc->pc) && if ((TARGET_TB_PCREL || tb_pc(tb) == desc->pc) &&
tb_page_addr0(tb) == desc->page_addr0 && tb_page_addr0(tb) == desc->page_addr0 &&
tb->cs_base == desc->cs_base && tb->cs_base == desc->cs_base &&
tb->flags == desc->flags && tb->flags == desc->flags &&
@@ -235,7 +237,7 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
return NULL; return NULL;
} }
desc.page_addr0 = phys_pc; desc.page_addr0 = phys_pc;
h = tb_hash_func(phys_pc, (cflags & CF_PCREL ? 0 : pc), h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : pc),
flags, cflags, *cpu->trace_dstate); flags, cflags, *cpu->trace_dstate);
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp); return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
} }
@@ -254,13 +256,10 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
hash = tb_jmp_cache_hash_func(pc); hash = tb_jmp_cache_hash_func(pc);
jc = cpu->tb_jmp_cache; jc = cpu->tb_jmp_cache;
tb = tb_jmp_cache_get_tb(jc, hash);
if (cflags & CF_PCREL) {
/* Use acquire to ensure current load of pc from jc. */
tb = qatomic_load_acquire(&jc->array[hash].tb);
if (likely(tb && if (likely(tb &&
jc->array[hash].pc == pc && tb_jmp_cache_get_pc(jc, hash, tb) == pc &&
tb->cs_base == cs_base && tb->cs_base == cs_base &&
tb->flags == flags && tb->flags == flags &&
tb->trace_vcpu_dstate == *cpu->trace_dstate && tb->trace_vcpu_dstate == *cpu->trace_dstate &&
@@ -271,29 +270,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
if (tb == NULL) { if (tb == NULL) {
return NULL; return NULL;
} }
jc->array[hash].pc = pc; tb_jmp_cache_set(jc, hash, tb, pc);
/* Ensure pc is written first. */
qatomic_store_release(&jc->array[hash].tb, tb);
} else {
/* Use rcu_read to ensure current load of pc from *tb. */
tb = qatomic_rcu_read(&jc->array[hash].tb);
if (likely(tb &&
tb->pc == pc &&
tb->cs_base == cs_base &&
tb->flags == flags &&
tb->trace_vcpu_dstate == *cpu->trace_dstate &&
tb_cflags(tb) == cflags)) {
return tb;
}
tb = tb_htable_lookup(cpu, pc, cs_base, flags, cflags);
if (tb == NULL) {
return NULL;
}
/* Use the pc value already stored in tb->pc. */
qatomic_set(&jc->array[hash].tb, tb);
}
return tb; return tb;
} }
@@ -459,7 +436,6 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
qemu_thread_jit_execute(); qemu_thread_jit_execute();
ret = tcg_qemu_tb_exec(env, tb_ptr); ret = tcg_qemu_tb_exec(env, tb_ptr);
cpu->can_do_io = 1; cpu->can_do_io = 1;
qemu_plugin_disable_mem_helpers(cpu);
/* /*
* TODO: Delay swapping back to the read-write region of the TB * TODO: Delay swapping back to the read-write region of the TB
* until we actually need to modify the TB. The read-only copy, * until we actually need to modify the TB. The read-only copy,
@@ -483,9 +459,9 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
if (cc->tcg_ops->synchronize_from_tb) { if (cc->tcg_ops->synchronize_from_tb) {
cc->tcg_ops->synchronize_from_tb(cpu, last_tb); cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
} else { } else {
tcg_debug_assert(!(tb_cflags(last_tb) & CF_PCREL)); assert(!TARGET_TB_PCREL);
assert(cc->set_pc); assert(cc->set_pc);
cc->set_pc(cpu, last_tb->pc); cc->set_pc(cpu, tb_pc(last_tb));
} }
if (qemu_loglevel_mask(CPU_LOG_EXEC)) { if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
target_ulong pc = log_pc(cpu, last_tb); target_ulong pc = log_pc(cpu, last_tb);
@@ -527,6 +503,7 @@ static void cpu_exec_exit(CPUState *cpu)
if (cc->tcg_ops->cpu_exec_exit) { if (cc->tcg_ops->cpu_exec_exit) {
cc->tcg_ops->cpu_exec_exit(cpu); cc->tcg_ops->cpu_exec_exit(cpu);
} }
QEMU_PLUGIN_ASSERT(cpu->plugin_mem_cbs == NULL);
} }
void cpu_exec_step_atomic(CPUState *cpu) void cpu_exec_step_atomic(CPUState *cpu)
@@ -580,6 +557,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
qemu_mutex_unlock_iothread(); qemu_mutex_unlock_iothread();
} }
assert_no_pages_locked(); assert_no_pages_locked();
qemu_plugin_disable_mem_helpers(cpu);
} }
/* /*
@@ -971,27 +949,17 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
tb = tb_lookup(cpu, pc, cs_base, flags, cflags); tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
if (tb == NULL) { if (tb == NULL) {
CPUJumpCache *jc;
uint32_t h; uint32_t h;
mmap_lock(); mmap_lock();
tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
mmap_unlock(); mmap_unlock();
/* /*
* We add the TB in the virtual pc hash table * We add the TB in the virtual pc hash table
* for the fast lookup * for the fast lookup
*/ */
h = tb_jmp_cache_hash_func(pc); h = tb_jmp_cache_hash_func(pc);
jc = cpu->tb_jmp_cache; tb_jmp_cache_set(cpu->tb_jmp_cache, h, tb, pc);
if (cflags & CF_PCREL) {
jc->array[h].pc = pc;
/* Ensure pc is written first. */
qatomic_store_release(&jc->array[h].tb, tb);
} else {
/* Use the pc value already stored in tb->pc. */
qatomic_set(&jc->array[h].tb, tb);
}
} }
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
@@ -1012,6 +980,7 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
cpu_loop_exec_tb(cpu, tb, pc, &last_tb, &tb_exit); cpu_loop_exec_tb(cpu, tb, pc, &last_tb, &tb_exit);
QEMU_PLUGIN_ASSERT(cpu->plugin_mem_cbs == NULL);
/* Try to align the host and virtual clocks /* Try to align the host and virtual clocks
if the guest is in advance */ if the guest is in advance */
align_clocks(sc, cpu); align_clocks(sc, cpu);
@@ -1036,6 +1005,7 @@ static int cpu_exec_setjmp(CPUState *cpu, SyncClocks *sc)
if (qemu_mutex_iothread_locked()) { if (qemu_mutex_iothread_locked()) {
qemu_mutex_unlock_iothread(); qemu_mutex_unlock_iothread();
} }
qemu_plugin_disable_mem_helpers(cpu);
assert_no_pages_locked(); assert_no_pages_locked();
} }
@@ -1102,3 +1072,86 @@ void tcg_exec_unrealizefn(CPUState *cpu)
tlb_destroy(cpu); tlb_destroy(cpu);
g_free_rcu(cpu->tb_jmp_cache, rcu); g_free_rcu(cpu->tb_jmp_cache, rcu);
} }
#ifndef CONFIG_USER_ONLY
static void dump_drift_info(GString *buf)
{
if (!icount_enabled()) {
return;
}
g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n",
(cpu_get_clock() - icount_get()) / SCALE_MS);
if (icount_align_option) {
g_string_append_printf(buf, "Max guest delay %"PRIi64" ms\n",
-max_delay / SCALE_MS);
g_string_append_printf(buf, "Max guest advance %"PRIi64" ms\n",
max_advance / SCALE_MS);
} else {
g_string_append_printf(buf, "Max guest delay NA\n");
g_string_append_printf(buf, "Max guest advance NA\n");
}
}
HumanReadableText *qmp_x_query_jit(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
if (!tcg_enabled()) {
error_setg(errp, "JIT information is only available with accel=tcg");
return NULL;
}
dump_exec_info(buf);
dump_drift_info(buf);
return human_readable_text_from_str(buf);
}
HumanReadableText *qmp_x_query_opcount(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
if (!tcg_enabled()) {
error_setg(errp, "Opcode count information is only available with accel=tcg");
return NULL;
}
tcg_dump_op_count(buf);
return human_readable_text_from_str(buf);
}
#ifdef CONFIG_PROFILER
int64_t dev_time;
HumanReadableText *qmp_x_query_profile(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
static int64_t last_cpu_exec_time;
int64_t cpu_exec_time;
int64_t delta;
cpu_exec_time = tcg_cpu_exec_time();
delta = cpu_exec_time - last_cpu_exec_time;
g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n",
dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n",
delta, delta / (double)NANOSECONDS_PER_SECOND);
last_cpu_exec_time = cpu_exec_time;
dev_time = 0;
return human_readable_text_from_str(buf);
}
#else
HumanReadableText *qmp_x_query_profile(Error **errp)
{
error_setg(errp, "Internal profiler not compiled");
return NULL;
}
#endif
#endif /* !CONFIG_USER_ONLY */

View File

@@ -1250,6 +1250,7 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
desc->fulltlb[index] = *full; desc->fulltlb[index] = *full;
desc->fulltlb[index].xlat_section = iotlb - vaddr_page; desc->fulltlb[index].xlat_section = iotlb - vaddr_page;
desc->fulltlb[index].phys_addr = paddr_page; desc->fulltlb[index].phys_addr = paddr_page;
desc->fulltlb[index].prot = prot;
/* Now calculate the new entry */ /* Now calculate the new entry */
tn.addend = addend - vaddr_page; tn.addend = addend - vaddr_page;
@@ -1588,12 +1589,12 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
return flags; return flags;
} }
int probe_access_full(CPUArchState *env, target_ulong addr, int size, int probe_access_full(CPUArchState *env, target_ulong addr,
MMUAccessType access_type, int mmu_idx, MMUAccessType access_type, int mmu_idx,
bool nonfault, void **phost, CPUTLBEntryFull **pfull, bool nonfault, void **phost, CPUTLBEntryFull **pfull,
uintptr_t retaddr) uintptr_t retaddr)
{ {
int flags = probe_access_internal(env, addr, size, access_type, mmu_idx, int flags = probe_access_internal(env, addr, 0, access_type, mmu_idx,
nonfault, phost, pfull, retaddr); nonfault, phost, pfull, retaddr);
/* Handle clean RAM pages. */ /* Handle clean RAM pages. */
@@ -1605,25 +1606,14 @@ int probe_access_full(CPUArchState *env, target_ulong addr, int size,
return flags; return flags;
} }
int probe_access_flags(CPUArchState *env, target_ulong addr, int size, int probe_access_flags(CPUArchState *env, target_ulong addr,
MMUAccessType access_type, int mmu_idx, MMUAccessType access_type, int mmu_idx,
bool nonfault, void **phost, uintptr_t retaddr) bool nonfault, void **phost, uintptr_t retaddr)
{ {
CPUTLBEntryFull *full; CPUTLBEntryFull *full;
int flags;
g_assert(-(addr | TARGET_PAGE_MASK) >= size); return probe_access_full(env, addr, access_type, mmu_idx,
flags = probe_access_internal(env, addr, size, access_type, mmu_idx,
nonfault, phost, &full, retaddr); nonfault, phost, &full, retaddr);
/* Handle clean RAM pages. */
if (unlikely(flags & TLB_NOTDIRTY)) {
notdirty_write(env_cpu(env), addr, 1, full, retaddr);
flags &= ~TLB_NOTDIRTY;
}
return flags;
} }
void *probe_access(CPUArchState *env, target_ulong addr, int size, void *probe_access(CPUArchState *env, target_ulong addr, int size,
@@ -1767,7 +1757,6 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
CPUTLBEntry *tlbe; CPUTLBEntry *tlbe;
target_ulong tlb_addr; target_ulong tlb_addr;
void *hostaddr; void *hostaddr;
CPUTLBEntryFull *full;
tcg_debug_assert(mmu_idx < NB_MMU_MODES); tcg_debug_assert(mmu_idx < NB_MMU_MODES);
@@ -1806,31 +1795,22 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK; tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK;
} }
if (prot & PAGE_READ) { /* Let the guest notice RMW on a write-only page. */
/* if ((prot & PAGE_READ) &&
* Let the guest notice RMW on a write-only page. unlikely(tlbe->addr_read != (tlb_addr & ~TLB_NOTDIRTY))) {
* We have just verified that the page is writable.
* Subpage lookups may have left TLB_INVALID_MASK set,
* but addr_read will only be -1 if PAGE_READ was unset.
*/
if (unlikely(tlbe->addr_read == -1)) {
tlb_fill(env_cpu(env), addr, size, tlb_fill(env_cpu(env), addr, size,
MMU_DATA_LOAD, mmu_idx, retaddr); MMU_DATA_LOAD, mmu_idx, retaddr);
/* /*
* Since we don't support reads and writes to different * Since we don't support reads and writes to different addresses,
* addresses, and we do have the proper page loaded for * and we do have the proper page loaded for write, this shouldn't
* write, this shouldn't ever return. But just in case, * ever return. But just in case, handle via stop-the-world.
* handle via stop-the-world.
*/ */
goto stop_the_world; goto stop_the_world;
} }
/* Collect TLB_WATCHPOINT for read. */
tlb_addr |= tlbe->addr_read;
}
} else /* if (prot & PAGE_READ) */ { } else /* if (prot & PAGE_READ) */ {
tlb_addr = tlbe->addr_read; tlb_addr = tlbe->addr_read;
if (!tlb_hit(tlb_addr, addr)) { if (!tlb_hit(tlb_addr, addr)) {
if (!VICTIM_TLB_HIT(addr_read, addr)) { if (!VICTIM_TLB_HIT(addr_write, addr)) {
tlb_fill(env_cpu(env), addr, size, tlb_fill(env_cpu(env), addr, size,
MMU_DATA_LOAD, mmu_idx, retaddr); MMU_DATA_LOAD, mmu_idx, retaddr);
index = tlb_index(env, mmu_idx, addr); index = tlb_index(env, mmu_idx, addr);
@@ -1841,25 +1821,17 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
} }
/* Notice an IO access or a needs-MMU-lookup access */ /* Notice an IO access or a needs-MMU-lookup access */
if (unlikely(tlb_addr & (TLB_MMIO | TLB_DISCARD_WRITE))) { if (unlikely(tlb_addr & TLB_MMIO)) {
/* There's really nothing that can be done to /* There's really nothing that can be done to
support this apart from stop-the-world. */ support this apart from stop-the-world. */
goto stop_the_world; goto stop_the_world;
} }
hostaddr = (void *)((uintptr_t)addr + tlbe->addend); hostaddr = (void *)((uintptr_t)addr + tlbe->addend);
full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
if (unlikely(tlb_addr & TLB_NOTDIRTY)) { if (unlikely(tlb_addr & TLB_NOTDIRTY)) {
notdirty_write(env_cpu(env), addr, size, full, retaddr); notdirty_write(env_cpu(env), addr, size,
} &env_tlb(env)->d[mmu_idx].fulltlb[index], retaddr);
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
QEMU_BUILD_BUG_ON(PAGE_READ != BP_MEM_READ);
QEMU_BUILD_BUG_ON(PAGE_WRITE != BP_MEM_WRITE);
/* therefore prot == watchpoint bits */
cpu_check_watchpoint(env_cpu(env), addr, size,
full->attrs, prot, retaddr);
} }
return hostaddr; return hostaddr;

14
accel/tcg/hmp.c Normal file
View File

@@ -0,0 +1,14 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-machine.h"
#include "exec/exec-all.h"
#include "monitor/monitor.h"
static void hmp_tcg_register(void)
{
monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount);
}
type_init(hmp_tcg_register);

View File

@@ -57,14 +57,11 @@ void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
/* 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 target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb) static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
{ {
if (tb_cflags(tb) & CF_PCREL) { #if TARGET_TB_PCREL
return cpu->cc->get_pc(cpu); return cpu->cc->get_pc(cpu);
} else { #else
return tb->pc; return tb_pc(tb);
#endif
} }
}
extern int64_t max_delay;
extern int64_t max_advance;
#endif /* ACCEL_TCG_INTERNAL_H */ #endif /* ACCEL_TCG_INTERNAL_H */

View File

@@ -18,7 +18,7 @@ specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files( specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(
'cputlb.c', 'cputlb.c',
'monitor.c', 'hmp.c',
)) ))
tcg_module_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files( tcg_module_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(

View File

@@ -1,106 +0,0 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* QEMU TCG monitor
*
* Copyright (c) 2003-2005 Fabrice Bellard
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qapi/type-helpers.h"
#include "qapi/qapi-commands-machine.h"
#include "monitor/monitor.h"
#include "sysemu/cpus.h"
#include "sysemu/cpu-timers.h"
#include "sysemu/tcg.h"
#include "internal.h"
static void dump_drift_info(GString *buf)
{
if (!icount_enabled()) {
return;
}
g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n",
(cpu_get_clock() - icount_get()) / SCALE_MS);
if (icount_align_option) {
g_string_append_printf(buf, "Max guest delay %"PRIi64" ms\n",
-max_delay / SCALE_MS);
g_string_append_printf(buf, "Max guest advance %"PRIi64" ms\n",
max_advance / SCALE_MS);
} else {
g_string_append_printf(buf, "Max guest delay NA\n");
g_string_append_printf(buf, "Max guest advance NA\n");
}
}
HumanReadableText *qmp_x_query_jit(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
if (!tcg_enabled()) {
error_setg(errp, "JIT information is only available with accel=tcg");
return NULL;
}
dump_exec_info(buf);
dump_drift_info(buf);
return human_readable_text_from_str(buf);
}
HumanReadableText *qmp_x_query_opcount(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
if (!tcg_enabled()) {
error_setg(errp,
"Opcode count information is only available with accel=tcg");
return NULL;
}
tcg_dump_op_count(buf);
return human_readable_text_from_str(buf);
}
#ifdef CONFIG_PROFILER
int64_t dev_time;
HumanReadableText *qmp_x_query_profile(Error **errp)
{
g_autoptr(GString) buf = g_string_new("");
static int64_t last_cpu_exec_time;
int64_t cpu_exec_time;
int64_t delta;
cpu_exec_time = tcg_cpu_exec_time();
delta = cpu_exec_time - last_cpu_exec_time;
g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n",
dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n",
delta, delta / (double)NANOSECONDS_PER_SECOND);
last_cpu_exec_time = cpu_exec_time;
dev_time = 0;
return human_readable_text_from_str(buf);
}
#else
HumanReadableText *qmp_x_query_profile(Error **errp)
{
error_setg(errp, "Internal profiler not compiled");
return NULL;
}
#endif
static void hmp_tcg_register(void)
{
monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount);
}
type_init(hmp_tcg_register);

View File

@@ -328,7 +328,7 @@ void perf_report_code(uint64_t guest_pc, TranslationBlock *tb,
for (insn = 0; insn < tb->icount; insn++) { for (insn = 0; insn < tb->icount; insn++) {
/* FIXME: This replicates the restore_state_to_opc() logic. */ /* FIXME: This replicates the restore_state_to_opc() logic. */
q[insn].address = tcg_ctx->gen_insn_data[insn][0]; q[insn].address = tcg_ctx->gen_insn_data[insn][0];
if (tb_cflags(tb) & CF_PCREL) { if (TARGET_TB_PCREL) {
q[insn].address |= (guest_pc & TARGET_PAGE_MASK); q[insn].address |= (guest_pc & TARGET_PAGE_MASK);
} else { } else {
#if defined(TARGET_I386) #if defined(TARGET_I386)

View File

@@ -44,7 +44,6 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "tcg/tcg.h" #include "tcg/tcg.h"
#include "tcg/tcg-temp-internal.h"
#include "tcg/tcg-op.h" #include "tcg/tcg-op.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/plugin-gen.h" #include "exec/plugin-gen.h"
@@ -94,13 +93,11 @@ void HELPER(plugin_vcpu_mem_cb)(unsigned int vcpu_index,
static void do_gen_mem_cb(TCGv vaddr, uint32_t info) static void do_gen_mem_cb(TCGv vaddr, uint32_t info)
{ {
TCGv_i32 cpu_index = tcg_temp_ebb_new_i32(); TCGv_i32 cpu_index = tcg_temp_new_i32();
TCGv_i32 meminfo = tcg_temp_ebb_new_i32(); TCGv_i32 meminfo = tcg_const_i32(info);
TCGv_i64 vaddr64 = tcg_temp_ebb_new_i64(); TCGv_i64 vaddr64 = tcg_temp_new_i64();
TCGv_ptr udata = tcg_temp_ebb_new_ptr(); TCGv_ptr udata = tcg_const_ptr(NULL);
tcg_gen_movi_i32(meminfo, info);
tcg_gen_movi_ptr(udata, 0);
tcg_gen_ld_i32(cpu_index, cpu_env, tcg_gen_ld_i32(cpu_index, cpu_env,
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index)); -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
tcg_gen_extu_tl_i64(vaddr64, vaddr); tcg_gen_extu_tl_i64(vaddr64, vaddr);
@@ -115,10 +112,9 @@ static void do_gen_mem_cb(TCGv vaddr, uint32_t info)
static void gen_empty_udata_cb(void) static void gen_empty_udata_cb(void)
{ {
TCGv_i32 cpu_index = tcg_temp_ebb_new_i32(); TCGv_i32 cpu_index = tcg_temp_new_i32();
TCGv_ptr udata = tcg_temp_ebb_new_ptr(); TCGv_ptr udata = tcg_const_ptr(NULL); /* will be overwritten later */
tcg_gen_movi_ptr(udata, 0);
tcg_gen_ld_i32(cpu_index, cpu_env, tcg_gen_ld_i32(cpu_index, cpu_env,
-offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index)); -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
gen_helper_plugin_vcpu_udata_cb(cpu_index, udata); gen_helper_plugin_vcpu_udata_cb(cpu_index, udata);
@@ -133,10 +129,9 @@ static void gen_empty_udata_cb(void)
*/ */
static void gen_empty_inline_cb(void) static void gen_empty_inline_cb(void)
{ {
TCGv_i64 val = tcg_temp_ebb_new_i64(); TCGv_i64 val = tcg_temp_new_i64();
TCGv_ptr ptr = tcg_temp_ebb_new_ptr(); TCGv_ptr ptr = tcg_const_ptr(NULL); /* overwritten later */
tcg_gen_movi_ptr(ptr, 0);
tcg_gen_ld_i64(val, ptr, 0); tcg_gen_ld_i64(val, ptr, 0);
/* pass an immediate != 0 so that it doesn't get optimized away */ /* pass an immediate != 0 so that it doesn't get optimized away */
tcg_gen_addi_i64(val, val, 0xdeadface); tcg_gen_addi_i64(val, val, 0xdeadface);
@@ -156,9 +151,9 @@ static void gen_empty_mem_cb(TCGv addr, uint32_t info)
*/ */
static void gen_empty_mem_helper(void) static void gen_empty_mem_helper(void)
{ {
TCGv_ptr ptr = tcg_temp_ebb_new_ptr(); TCGv_ptr ptr;
tcg_gen_movi_ptr(ptr, 0); ptr = tcg_const_ptr(NULL);
tcg_gen_st_ptr(ptr, cpu_env, offsetof(CPUState, plugin_mem_cbs) - tcg_gen_st_ptr(ptr, cpu_env, offsetof(CPUState, plugin_mem_cbs) -
offsetof(ArchCPU, env)); offsetof(ArchCPU, env));
tcg_temp_free_ptr(ptr); tcg_temp_free_ptr(ptr);
@@ -631,6 +626,8 @@ static void inject_mem_disable_helper(struct qemu_plugin_insn *plugin_insn,
/* called before finishing a TB with exit_tb, goto_tb or goto_ptr */ /* called before finishing a TB with exit_tb, goto_tb or goto_ptr */
void plugin_gen_disable_mem_helpers(void) void plugin_gen_disable_mem_helpers(void)
{ {
TCGv_ptr ptr;
/* /*
* We could emit the clearing unconditionally and be done. However, this can * We could emit the clearing unconditionally and be done. However, this can
* be wasteful if for instance plugins don't track memory accesses, or if * be wasteful if for instance plugins don't track memory accesses, or if
@@ -643,8 +640,10 @@ void plugin_gen_disable_mem_helpers(void)
if (!tcg_ctx->plugin_tb->mem_helper) { if (!tcg_ctx->plugin_tb->mem_helper) {
return; return;
} }
tcg_gen_st_ptr(tcg_constant_ptr(NULL), cpu_env, ptr = tcg_const_ptr(NULL);
offsetof(CPUState, plugin_mem_cbs) - offsetof(ArchCPU, env)); tcg_gen_st_ptr(ptr, cpu_env, offsetof(CPUState, plugin_mem_cbs) -
offsetof(ArchCPU, env));
tcg_temp_free_ptr(ptr);
} }
static void plugin_gen_tb_udata(const struct qemu_plugin_tb *ptb, static void plugin_gen_tb_udata(const struct qemu_plugin_tb *ptb,

View File

@@ -14,15 +14,53 @@
/* /*
* Accessed in parallel; all accesses to 'tb' must be atomic. * Accessed in parallel; all accesses to 'tb' must be atomic.
* For CF_PCREL, accesses to 'pc' must be protected by a * For TARGET_TB_PCREL, accesses to 'pc' must be protected by
* load_acquire/store_release to 'tb'. * a load_acquire/store_release to 'tb'.
*/ */
struct CPUJumpCache { struct CPUJumpCache {
struct rcu_head rcu; struct rcu_head rcu;
struct { struct {
TranslationBlock *tb; TranslationBlock *tb;
#if TARGET_TB_PCREL
target_ulong pc; target_ulong pc;
#endif
} array[TB_JMP_CACHE_SIZE]; } array[TB_JMP_CACHE_SIZE];
}; };
static inline TranslationBlock *
tb_jmp_cache_get_tb(CPUJumpCache *jc, uint32_t hash)
{
#if TARGET_TB_PCREL
/* Use acquire to ensure current load of pc from jc. */
return qatomic_load_acquire(&jc->array[hash].tb);
#else
/* Use rcu_read to ensure current load of pc from *tb. */
return qatomic_rcu_read(&jc->array[hash].tb);
#endif
}
static inline target_ulong
tb_jmp_cache_get_pc(CPUJumpCache *jc, uint32_t hash, TranslationBlock *tb)
{
#if TARGET_TB_PCREL
return jc->array[hash].pc;
#else
return tb_pc(tb);
#endif
}
static inline void
tb_jmp_cache_set(CPUJumpCache *jc, uint32_t hash,
TranslationBlock *tb, target_ulong pc)
{
#if TARGET_TB_PCREL
jc->array[hash].pc = pc;
/* Use store_release on tb to ensure pc is written first. */
qatomic_store_release(&jc->array[hash].tb, tb);
#else
/* Use the pc value already stored in tb->pc. */
qatomic_set(&jc->array[hash].tb, tb);
#endif
}
#endif /* ACCEL_TCG_TB_JMP_CACHE_H */ #endif /* ACCEL_TCG_TB_JMP_CACHE_H */

View File

@@ -19,11 +19,9 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/interval-tree.h" #include "qemu/interval-tree.h"
#include "qemu/qtree.h"
#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/tb-flush.h"
#include "exec/translate-all.h" #include "exec/translate-all.h"
#include "sysemu/tcg.h" #include "sysemu/tcg.h"
#include "tcg/tcg.h" #include "tcg/tcg.h"
@@ -46,7 +44,7 @@ static bool tb_cmp(const void *ap, const void *bp)
const TranslationBlock *a = ap; const TranslationBlock *a = ap;
const TranslationBlock *b = bp; const TranslationBlock *b = bp;
return ((tb_cflags(a) & CF_PCREL || a->pc == b->pc) && return ((TARGET_TB_PCREL || tb_pc(a) == tb_pc(b)) &&
a->cs_base == b->cs_base && a->cs_base == b->cs_base &&
a->flags == b->flags && a->flags == b->flags &&
(tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) && (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
@@ -127,29 +125,29 @@ static void tb_remove(TranslationBlock *tb)
} }
/* TODO: For now, still shared with translate-all.c for system mode. */ /* TODO: For now, still shared with translate-all.c for system mode. */
#define PAGE_FOR_EACH_TB(start, last, pagedesc, T, N) \ #define PAGE_FOR_EACH_TB(start, end, pagedesc, T, N) \
for (T = foreach_tb_first(start, last), \ for (T = foreach_tb_first(start, end), \
N = foreach_tb_next(T, start, last); \ N = foreach_tb_next(T, start, end); \
T != NULL; \ T != NULL; \
T = N, N = foreach_tb_next(N, start, last)) T = N, N = foreach_tb_next(N, start, end))
typedef TranslationBlock *PageForEachNext; typedef TranslationBlock *PageForEachNext;
static PageForEachNext foreach_tb_first(tb_page_addr_t start, static PageForEachNext foreach_tb_first(tb_page_addr_t start,
tb_page_addr_t last) tb_page_addr_t end)
{ {
IntervalTreeNode *n = interval_tree_iter_first(&tb_root, start, last); IntervalTreeNode *n = interval_tree_iter_first(&tb_root, start, end - 1);
return n ? container_of(n, TranslationBlock, itree) : NULL; return n ? container_of(n, TranslationBlock, itree) : NULL;
} }
static PageForEachNext foreach_tb_next(PageForEachNext tb, static PageForEachNext foreach_tb_next(PageForEachNext tb,
tb_page_addr_t start, tb_page_addr_t start,
tb_page_addr_t last) tb_page_addr_t end)
{ {
IntervalTreeNode *n; IntervalTreeNode *n;
if (tb) { if (tb) {
n = interval_tree_iter_next(&tb->itree, start, last); n = interval_tree_iter_next(&tb->itree, start, end - 1);
if (n) { if (n) {
return container_of(n, TranslationBlock, itree); return container_of(n, TranslationBlock, itree);
} }
@@ -315,12 +313,12 @@ struct page_entry {
* See also: page_collection_lock(). * See also: page_collection_lock().
*/ */
struct page_collection { struct page_collection {
QTree *tree; GTree *tree;
struct page_entry *max; struct page_entry *max;
}; };
typedef int PageForEachNext; typedef int PageForEachNext;
#define PAGE_FOR_EACH_TB(start, last, pagedesc, tb, n) \ #define PAGE_FOR_EACH_TB(start, end, pagedesc, tb, n) \
TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next) TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next)
#ifdef CONFIG_DEBUG_TCG #ifdef CONFIG_DEBUG_TCG
@@ -468,7 +466,7 @@ static bool page_trylock_add(struct page_collection *set, tb_page_addr_t addr)
struct page_entry *pe; struct page_entry *pe;
PageDesc *pd; PageDesc *pd;
pe = q_tree_lookup(set->tree, &index); pe = g_tree_lookup(set->tree, &index);
if (pe) { if (pe) {
return false; return false;
} }
@@ -479,7 +477,7 @@ static bool page_trylock_add(struct page_collection *set, tb_page_addr_t addr)
} }
pe = page_entry_new(pd, index); pe = page_entry_new(pd, index);
q_tree_insert(set->tree, &pe->index, pe); g_tree_insert(set->tree, &pe->index, pe);
/* /*
* If this is either (1) the first insertion or (2) a page whose index * If this is either (1) the first insertion or (2) a page whose index
@@ -511,30 +509,30 @@ static gint tb_page_addr_cmp(gconstpointer ap, gconstpointer bp, gpointer udata)
} }
/* /*
* Lock a range of pages ([@start,@last]) as well as the pages of all * Lock a range of pages ([@start,@end[) as well as the pages of all
* intersecting TBs. * intersecting TBs.
* Locking order: acquire locks in ascending order of page index. * Locking order: acquire locks in ascending order of page index.
*/ */
static struct page_collection *page_collection_lock(tb_page_addr_t start, static struct page_collection *page_collection_lock(tb_page_addr_t start,
tb_page_addr_t last) tb_page_addr_t end)
{ {
struct page_collection *set = g_malloc(sizeof(*set)); struct page_collection *set = g_malloc(sizeof(*set));
tb_page_addr_t index; tb_page_addr_t index;
PageDesc *pd; PageDesc *pd;
start >>= TARGET_PAGE_BITS; start >>= TARGET_PAGE_BITS;
last >>= TARGET_PAGE_BITS; end >>= TARGET_PAGE_BITS;
g_assert(start <= last); g_assert(start <= end);
set->tree = q_tree_new_full(tb_page_addr_cmp, NULL, NULL, set->tree = g_tree_new_full(tb_page_addr_cmp, NULL, NULL,
page_entry_destroy); page_entry_destroy);
set->max = NULL; set->max = NULL;
assert_no_pages_locked(); assert_no_pages_locked();
retry: retry:
q_tree_foreach(set->tree, page_entry_lock, NULL); g_tree_foreach(set->tree, page_entry_lock, NULL);
for (index = start; index <= last; index++) { for (index = start; index <= end; index++) {
TranslationBlock *tb; TranslationBlock *tb;
PageForEachNext n; PageForEachNext n;
@@ -543,7 +541,7 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start,
continue; continue;
} }
if (page_trylock_add(set, index << TARGET_PAGE_BITS)) { if (page_trylock_add(set, index << TARGET_PAGE_BITS)) {
q_tree_foreach(set->tree, page_entry_unlock, NULL); g_tree_foreach(set->tree, page_entry_unlock, NULL);
goto retry; goto retry;
} }
assert_page_locked(pd); assert_page_locked(pd);
@@ -552,7 +550,7 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start,
(tb_page_addr1(tb) != -1 && (tb_page_addr1(tb) != -1 &&
page_trylock_add(set, tb_page_addr1(tb)))) { page_trylock_add(set, tb_page_addr1(tb)))) {
/* drop all locks, and reacquire in order */ /* drop all locks, and reacquire in order */
q_tree_foreach(set->tree, page_entry_unlock, NULL); g_tree_foreach(set->tree, page_entry_unlock, NULL);
goto retry; goto retry;
} }
} }
@@ -563,7 +561,7 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start,
static void page_collection_unlock(struct page_collection *set) static void page_collection_unlock(struct page_collection *set)
{ {
/* entries are unlocked and freed via page_entry_destroy */ /* entries are unlocked and freed via page_entry_destroy */
q_tree_destroy(set->tree); g_tree_destroy(set->tree);
g_free(set); g_free(set);
} }
@@ -849,13 +847,13 @@ static void tb_jmp_cache_inval_tb(TranslationBlock *tb)
{ {
CPUState *cpu; CPUState *cpu;
if (tb_cflags(tb) & CF_PCREL) { if (TARGET_TB_PCREL) {
/* A TB may be at any virtual address */ /* A TB may be at any virtual address */
CPU_FOREACH(cpu) { CPU_FOREACH(cpu) {
tcg_flush_jmp_cache(cpu); tcg_flush_jmp_cache(cpu);
} }
} else { } else {
uint32_t h = tb_jmp_cache_hash_func(tb->pc); uint32_t h = tb_jmp_cache_hash_func(tb_pc(tb));
CPU_FOREACH(cpu) { CPU_FOREACH(cpu) {
CPUJumpCache *jc = cpu->tb_jmp_cache; CPUJumpCache *jc = cpu->tb_jmp_cache;
@@ -887,7 +885,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
/* remove the TB from the hash list */ /* remove the TB from the hash list */
phys_pc = tb_page_addr0(tb); phys_pc = tb_page_addr0(tb);
h = tb_hash_func(phys_pc, (orig_cflags & CF_PCREL ? 0 : tb->pc), h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
tb->flags, orig_cflags, tb->trace_vcpu_dstate); tb->flags, orig_cflags, tb->trace_vcpu_dstate);
if (!qht_remove(&tb_ctx.htable, tb, h)) { if (!qht_remove(&tb_ctx.htable, tb, h)) {
return; return;
@@ -968,7 +966,7 @@ TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
tb_record(tb, p, p2); tb_record(tb, p, p2);
/* add in the hash table */ /* add in the hash table */
h = tb_hash_func(phys_pc, (tb->cflags & CF_PCREL ? 0 : tb->pc), h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
tb->flags, tb->cflags, tb->trace_vcpu_dstate); tb->flags, tb->cflags, tb->trace_vcpu_dstate);
qht_insert(&tb_ctx.htable, tb, h, &existing_tb); qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
@@ -991,14 +989,14 @@ TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
* Called with mmap_lock held for user-mode emulation. * Called with mmap_lock held for user-mode emulation.
* NOTE: this function must not be called while a TB is running. * NOTE: this function must not be called while a TB is running.
*/ */
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t last) void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
{ {
TranslationBlock *tb; TranslationBlock *tb;
PageForEachNext n; PageForEachNext n;
assert_memory_lock(); assert_memory_lock();
PAGE_FOR_EACH_TB(start, last, unused, tb, n) { PAGE_FOR_EACH_TB(start, end, unused, tb, n) {
tb_phys_invalidate__locked(tb); tb_phys_invalidate__locked(tb);
} }
} }
@@ -1010,11 +1008,11 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t last)
*/ */
void tb_invalidate_phys_page(tb_page_addr_t addr) void tb_invalidate_phys_page(tb_page_addr_t addr)
{ {
tb_page_addr_t start, last; tb_page_addr_t start, end;
start = addr & TARGET_PAGE_MASK; start = addr & TARGET_PAGE_MASK;
last = addr | ~TARGET_PAGE_MASK; end = start + TARGET_PAGE_SIZE;
tb_invalidate_phys_range(start, last); tb_invalidate_phys_range(start, end);
} }
/* /*
@@ -1030,7 +1028,6 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
bool current_tb_modified; bool current_tb_modified;
TranslationBlock *tb; TranslationBlock *tb;
PageForEachNext n; PageForEachNext n;
tb_page_addr_t last;
/* /*
* Without precise smc semantics, or when outside of a TB, * Without precise smc semantics, or when outside of a TB,
@@ -1047,11 +1044,10 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
assert_memory_lock(); assert_memory_lock();
current_tb = tcg_tb_lookup(pc); current_tb = tcg_tb_lookup(pc);
last = addr | ~TARGET_PAGE_MASK;
addr &= TARGET_PAGE_MASK; addr &= TARGET_PAGE_MASK;
current_tb_modified = false; current_tb_modified = false;
PAGE_FOR_EACH_TB(addr, last, unused, tb, n) { PAGE_FOR_EACH_TB(addr, addr + TARGET_PAGE_SIZE, unused, tb, n) {
if (current_tb == tb && if (current_tb == tb &&
(tb_cflags(current_tb) & CF_COUNT_MASK) != 1) { (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
/* /*
@@ -1083,36 +1079,34 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
static void static void
tb_invalidate_phys_page_range__locked(struct page_collection *pages, tb_invalidate_phys_page_range__locked(struct page_collection *pages,
PageDesc *p, tb_page_addr_t start, PageDesc *p, tb_page_addr_t start,
tb_page_addr_t last, tb_page_addr_t end,
uintptr_t retaddr) uintptr_t retaddr)
{ {
TranslationBlock *tb; TranslationBlock *tb;
tb_page_addr_t tb_start, tb_end;
PageForEachNext n; PageForEachNext n;
#ifdef TARGET_HAS_PRECISE_SMC #ifdef TARGET_HAS_PRECISE_SMC
bool current_tb_modified = false; bool current_tb_modified = false;
TranslationBlock *current_tb = retaddr ? tcg_tb_lookup(retaddr) : NULL; TranslationBlock *current_tb = retaddr ? tcg_tb_lookup(retaddr) : NULL;
#endif /* TARGET_HAS_PRECISE_SMC */ #endif /* TARGET_HAS_PRECISE_SMC */
/* Range may not cross a page. */
tcg_debug_assert(((start ^ last) & TARGET_PAGE_MASK) == 0);
/* /*
* We remove all the TBs in the range [start, last]. * We remove all the TBs in the range [start, end[.
* XXX: see if in some cases it could be faster to invalidate all the code * XXX: see if in some cases it could be faster to invalidate all the code
*/ */
PAGE_FOR_EACH_TB(start, last, p, tb, n) { PAGE_FOR_EACH_TB(start, end, p, tb, n) {
tb_page_addr_t tb_start, tb_last;
/* NOTE: this is subtle as a TB may span two physical pages */ /* NOTE: this is subtle as a TB may span two physical pages */
tb_start = tb_page_addr0(tb);
tb_last = tb_start + tb->size - 1;
if (n == 0) { if (n == 0) {
tb_last = MIN(tb_last, tb_start | ~TARGET_PAGE_MASK); /* NOTE: tb_end may be after the end of the page, but
it is not a problem */
tb_start = tb_page_addr0(tb);
tb_end = tb_start + tb->size;
} else { } else {
tb_start = tb_page_addr1(tb); tb_start = tb_page_addr1(tb);
tb_last = tb_start + (tb_last & ~TARGET_PAGE_MASK); tb_end = tb_start + ((tb_page_addr0(tb) + tb->size)
& ~TARGET_PAGE_MASK);
} }
if (!(tb_last < start || tb_start > last)) { if (!(tb_end <= start || tb_start >= end)) {
#ifdef TARGET_HAS_PRECISE_SMC #ifdef TARGET_HAS_PRECISE_SMC
if (current_tb == tb && if (current_tb == tb &&
(tb_cflags(current_tb) & CF_COUNT_MASK) != 1) { (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
@@ -1154,7 +1148,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
void tb_invalidate_phys_page(tb_page_addr_t addr) void tb_invalidate_phys_page(tb_page_addr_t addr)
{ {
struct page_collection *pages; struct page_collection *pages;
tb_page_addr_t start, last; tb_page_addr_t start, end;
PageDesc *p; PageDesc *p;
p = page_find(addr >> TARGET_PAGE_BITS); p = page_find(addr >> TARGET_PAGE_BITS);
@@ -1163,40 +1157,36 @@ void tb_invalidate_phys_page(tb_page_addr_t addr)
} }
start = addr & TARGET_PAGE_MASK; start = addr & TARGET_PAGE_MASK;
last = addr | ~TARGET_PAGE_MASK; end = start + TARGET_PAGE_SIZE;
pages = page_collection_lock(start, last); pages = page_collection_lock(start, end);
tb_invalidate_phys_page_range__locked(pages, p, start, last, 0); tb_invalidate_phys_page_range__locked(pages, p, start, end, 0);
page_collection_unlock(pages); page_collection_unlock(pages);
} }
/* /*
* Invalidate all TBs which intersect with the target physical address range * Invalidate all TBs which intersect with the target physical address range
* [start;last]. NOTE: start and end may refer to *different* physical pages. * [start;end[. NOTE: start and end may refer to *different* physical pages.
* 'is_cpu_write_access' should be true if called from a real cpu write * 'is_cpu_write_access' should be true if called from a real cpu write
* access: the virtual CPU will exit the current TB if code is modified inside * access: the virtual CPU will exit the current TB if code is modified inside
* this TB. * this TB.
*/ */
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t last) void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
{ {
struct page_collection *pages; struct page_collection *pages;
tb_page_addr_t index, index_last; tb_page_addr_t next;
pages = page_collection_lock(start, last); pages = page_collection_lock(start, end);
for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
index_last = last >> TARGET_PAGE_BITS; start < end;
for (index = start >> TARGET_PAGE_BITS; index <= index_last; index++) { start = next, next += TARGET_PAGE_SIZE) {
PageDesc *pd = page_find(index); PageDesc *pd = page_find(start >> TARGET_PAGE_BITS);
tb_page_addr_t page_start, page_last; tb_page_addr_t bound = MIN(next, end);
if (pd == NULL) { if (pd == NULL) {
continue; continue;
} }
assert_page_locked(pd); assert_page_locked(pd);
page_start = index << TARGET_PAGE_BITS; tb_invalidate_phys_page_range__locked(pages, pd, start, bound, 0);
page_last = page_start | ~TARGET_PAGE_MASK;
page_last = MIN(page_last, last);
tb_invalidate_phys_page_range__locked(pages, pd,
page_start, page_last, 0);
} }
page_collection_unlock(pages); page_collection_unlock(pages);
} }
@@ -1216,7 +1206,7 @@ static void tb_invalidate_phys_page_fast__locked(struct page_collection *pages,
} }
assert_page_locked(p); assert_page_locked(p);
tb_invalidate_phys_page_range__locked(pages, p, start, start + len - 1, ra); tb_invalidate_phys_page_range__locked(pages, p, start, start + len, ra);
} }
/* /*
@@ -1230,7 +1220,7 @@ void tb_invalidate_phys_range_fast(ram_addr_t ram_addr,
{ {
struct page_collection *pages; struct page_collection *pages;
pages = page_collection_lock(ram_addr, ram_addr + size - 1); pages = page_collection_lock(ram_addr, ram_addr + size);
tb_invalidate_phys_page_fast__locked(pages, ram_addr, size, retaddr); tb_invalidate_phys_page_fast__locked(pages, ram_addr, size, retaddr);
page_collection_unlock(pages); page_collection_unlock(pages);
} }

View File

@@ -31,7 +31,6 @@
#include "sysemu/cpu-timers.h" #include "sysemu/cpu-timers.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "qemu/guest-random.h" #include "qemu/guest-random.h"
#include "qemu/timer.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/hwaddr.h" #include "exec/hwaddr.h"
#include "exec/gdbstub.h" #include "exec/gdbstub.h"
@@ -45,21 +44,10 @@
void tcg_cpu_init_cflags(CPUState *cpu, bool parallel) void tcg_cpu_init_cflags(CPUState *cpu, bool parallel)
{ {
uint32_t cflags; uint32_t cflags = cpu->cluster_index << CF_CLUSTER_SHIFT;
/*
* Include the cluster number in the hash we use to look up TBs.
* This is important because a TB that is valid for one cluster at
* a given physical address and set of CPU flags is not necessarily
* valid for another:
* the two clusters may have different views of physical memory, or
* may have different CPU features (eg FPU present or absent).
*/
cflags = cpu->cluster_index << CF_CLUSTER_SHIFT;
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; cpu->tcg_cflags = cflags;
} }
void tcg_cpus_destroy(CPUState *cpu) void tcg_cpus_destroy(CPUState *cpu)
@@ -128,7 +116,7 @@ static inline int xlat_gdb_type(CPUState *cpu, int gdbtype)
return cputype; return cputype;
} }
static int tcg_insert_breakpoint(CPUState *cs, int type, vaddr addr, vaddr len) static int tcg_insert_breakpoint(CPUState *cs, int type, hwaddr addr, hwaddr len)
{ {
CPUState *cpu; CPUState *cpu;
int err = 0; int err = 0;
@@ -159,7 +147,7 @@ static int tcg_insert_breakpoint(CPUState *cs, int type, vaddr addr, vaddr len)
} }
} }
static int tcg_remove_breakpoint(CPUState *cs, int type, vaddr addr, vaddr len) static int tcg_remove_breakpoint(CPUState *cs, int type, hwaddr addr, hwaddr len)
{ {
CPUState *cpu; CPUState *cpu;
int err = 0; int err = 0;

View File

@@ -25,7 +25,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "sysemu/tcg.h" #include "sysemu/tcg.h"
#include "exec/replay-core.h" #include "sysemu/replay.h"
#include "sysemu/cpu-timers.h" #include "sysemu/cpu-timers.h"
#include "tcg/tcg.h" #include "tcg/tcg.h"
#include "qapi/error.h" #include "qapi/error.h"

View File

@@ -47,12 +47,11 @@
#include "exec/cputlb.h" #include "exec/cputlb.h"
#include "exec/translate-all.h" #include "exec/translate-all.h"
#include "exec/translator.h" #include "exec/translator.h"
#include "exec/tb-flush.h"
#include "qemu/bitmap.h" #include "qemu/bitmap.h"
#include "qemu/qemu-print.h" #include "qemu/qemu-print.h"
#include "qemu/timer.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "qemu/cacheinfo.h" #include "qemu/cacheinfo.h"
#include "qemu/timer.h"
#include "exec/log.h" #include "exec/log.h"
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
#include "sysemu/cpu-timers.h" #include "sysemu/cpu-timers.h"
@@ -136,7 +135,7 @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) { for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
if (i == 0) { if (i == 0) {
prev = (!(tb_cflags(tb) & CF_PCREL) && j == 0 ? tb->pc : 0); prev = (!TARGET_TB_PCREL && j == 0 ? tb_pc(tb) : 0);
} else { } else {
prev = tcg_ctx->gen_insn_data[i - 1][j]; prev = tcg_ctx->gen_insn_data[i - 1][j];
} }
@@ -171,8 +170,8 @@ static int cpu_unwind_data_from_tb(TranslationBlock *tb, uintptr_t host_pc,
} }
memset(data, 0, sizeof(uint64_t) * TARGET_INSN_START_WORDS); memset(data, 0, sizeof(uint64_t) * TARGET_INSN_START_WORDS);
if (!(tb_cflags(tb) & CF_PCREL)) { if (!TARGET_TB_PCREL) {
data[0] = tb->pc; data[0] = tb_pc(tb);
} }
/* /*
@@ -282,7 +281,7 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb,
tcg_func_start(tcg_ctx); tcg_func_start(tcg_ctx);
tcg_ctx->cpu = env_cpu(env); tcg_ctx->cpu = env_cpu(env);
gen_intermediate_code(env_cpu(env), tb, max_insns, pc, host_pc); gen_intermediate_code(env_cpu(env), tb, *max_insns, pc, host_pc);
assert(tb->size != 0); assert(tb->size != 0);
tcg_ctx->cpu = NULL; tcg_ctx->cpu = NULL;
*max_insns = tb->icount; *max_insns = tb->icount;
@@ -342,9 +341,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
gen_code_buf = tcg_ctx->code_gen_ptr; gen_code_buf = tcg_ctx->code_gen_ptr;
tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf); tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf);
if (!(cflags & CF_PCREL)) { #if !TARGET_TB_PCREL
tb->pc = pc; tb->pc = pc;
} #endif
tb->cs_base = cs_base; tb->cs_base = cs_base;
tb->flags = flags; tb->flags = flags;
tb->cflags = cflags; tb->cflags = cflags;
@@ -409,8 +408,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
tb->tc.size = gen_code_size; tb->tc.size = gen_code_size;
/* /*
* For CF_PCREL, attribute all executions of the generated code * For TARGET_TB_PCREL, attribute all executions of the generated
* to its first mapping. * code to its first mapping.
*/ */
perf_report_code(pc, tb, tcg_splitwx_to_rx(gen_code_buf)); perf_report_code(pc, tb, tcg_splitwx_to_rx(gen_code_buf));
@@ -572,7 +571,7 @@ void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
addr = get_page_addr_code(env, pc); addr = get_page_addr_code(env, pc);
if (addr != -1) { if (addr != -1) {
tb_invalidate_phys_range(addr, addr); tb_invalidate_phys_range(addr, addr + 1);
} }
} }
} }

View File

@@ -16,7 +16,20 @@
#include "exec/log.h" #include "exec/log.h"
#include "exec/translator.h" #include "exec/translator.h"
#include "exec/plugin-gen.h" #include "exec/plugin-gen.h"
#include "exec/replay-core.h" #include "sysemu/replay.h"
/* Pairs with tcg_clear_temp_count.
To be called by #TranslatorOps.{translate_insn,tb_stop} if
(1) the target is sufficiently clean to support reporting,
(2) as and when all temporaries are known to be consumed.
For most targets, (2) is at the end of translate_insn. */
void translator_loop_temp_check(DisasContextBase *db)
{
if (tcg_check_temp_count()) {
qemu_log("warning: TCG temporary leaks before "
TARGET_FMT_lx "\n", db->pc_next);
}
}
bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
{ {
@@ -29,7 +42,7 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0; return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
} }
void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
target_ulong pc, void *host_pc, target_ulong pc, void *host_pc,
const TranslatorOps *ops, DisasContextBase *db) const TranslatorOps *ops, DisasContextBase *db)
{ {
@@ -42,7 +55,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
db->pc_next = pc; db->pc_next = pc;
db->is_jmp = DISAS_NEXT; db->is_jmp = DISAS_NEXT;
db->num_insns = 0; db->num_insns = 0;
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->host_addr[0] = host_pc; db->host_addr[0] = host_pc;
db->host_addr[1] = NULL; db->host_addr[1] = NULL;
@@ -54,6 +67,9 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
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 */
/* Reset the temp count so that we can identify leaks */
tcg_clear_temp_count();
/* Start translating. */ /* Start translating. */
gen_tb_start(db->tb); gen_tb_start(db->tb);
ops->tb_start(db, cpu); ops->tb_start(db, cpu);
@@ -62,7 +78,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY); plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY);
while (true) { while (true) {
*max_insns = ++db->num_insns; db->num_insns++;
ops->insn_start(db, cpu); ops->insn_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 */
@@ -160,16 +176,8 @@ static void *translator_access(CPUArchState *env, DisasContextBase *db,
if (host == NULL) { if (host == NULL) {
tb_page_addr_t phys_page = tb_page_addr_t phys_page =
get_page_addr_code_hostp(env, base, &db->host_addr[1]); get_page_addr_code_hostp(env, base, &db->host_addr[1]);
/* We cannot handle MMIO as second page. */
/* assert(phys_page != -1);
* If the second page is MMIO, treat as if the first page
* was MMIO as well, so that we do not cache the TB.
*/
if (unlikely(phys_page == -1)) {
tb_set_page_addr0(tb, -1);
return NULL;
}
tb_set_page_addr1(tb, phys_page); tb_set_page_addr1(tb, phys_page);
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
page_protect(end); page_protect(end);

View File

@@ -1,6 +1,6 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "hw/core/cpu.h" #include "hw/core/cpu.h"
#include "exec/replay-core.h" #include "sysemu/replay.h"
bool enable_cpu_pm = false; bool enable_cpu_pm = false;

View File

@@ -480,22 +480,24 @@ static bool pageflags_set_clear(target_ulong start, target_ulong last,
* The flag PAGE_WRITE_ORG is positioned automatically depending * The flag PAGE_WRITE_ORG is positioned automatically depending
* on PAGE_WRITE. The mmap_lock should already be held. * on PAGE_WRITE. The mmap_lock should already be held.
*/ */
void page_set_flags(target_ulong start, target_ulong last, int flags) void page_set_flags(target_ulong start, target_ulong end, int flags)
{ {
target_ulong last;
bool reset = false; bool reset = false;
bool inval_tb = false; bool inval_tb = false;
/* This function should never be called with addresses outside the /* This function should never be called with addresses outside the
guest address space. If this assert fires, it probably indicates guest address space. If this assert fires, it probably indicates
a missing call to h2g_valid. */ a missing call to h2g_valid. */
assert(start <= last); assert(start < end);
assert(last <= GUEST_ADDR_MAX); assert(end - 1 <= GUEST_ADDR_MAX);
/* Only set PAGE_ANON with new mappings. */ /* Only set PAGE_ANON with new mappings. */
assert(!(flags & PAGE_ANON) || (flags & PAGE_RESET)); assert(!(flags & PAGE_ANON) || (flags & PAGE_RESET));
assert_memory_lock(); assert_memory_lock();
start &= TARGET_PAGE_MASK; start = start & TARGET_PAGE_MASK;
last |= ~TARGET_PAGE_MASK; end = TARGET_PAGE_ALIGN(end);
last = end - 1;
if (!(flags & PAGE_VALID)) { if (!(flags & PAGE_VALID)) {
flags = 0; flags = 0;
@@ -508,7 +510,7 @@ void page_set_flags(target_ulong start, target_ulong last, int flags)
} }
if (!flags || reset) { if (!flags || reset) {
page_reset_target_data(start, last); page_reset_target_data(start, end);
inval_tb |= pageflags_unset(start, last); inval_tb |= pageflags_unset(start, last);
} }
if (flags) { if (flags) {
@@ -516,7 +518,7 @@ void page_set_flags(target_ulong start, target_ulong last, int flags)
~(reset ? 0 : PAGE_STICKY)); ~(reset ? 0 : PAGE_STICKY));
} }
if (inval_tb) { if (inval_tb) {
tb_invalidate_phys_range(start, last); tb_invalidate_phys_range(start, end);
} }
} }
@@ -759,14 +761,13 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
cpu_loop_exit_sigsegv(env_cpu(env), addr, access_type, maperr, ra); cpu_loop_exit_sigsegv(env_cpu(env), addr, access_type, maperr, ra);
} }
int probe_access_flags(CPUArchState *env, target_ulong addr, int size, int probe_access_flags(CPUArchState *env, target_ulong addr,
MMUAccessType access_type, int mmu_idx, MMUAccessType access_type, int mmu_idx,
bool nonfault, void **phost, uintptr_t ra) bool nonfault, void **phost, uintptr_t ra)
{ {
int flags; int flags;
g_assert(-(addr | TARGET_PAGE_MASK) >= size); flags = probe_access_internal(env, addr, 0, access_type, nonfault, ra);
flags = probe_access_internal(env, addr, size, access_type, nonfault, ra);
*phost = flags ? NULL : g2h(env_cpu(env), addr); *phost = flags ? NULL : g2h(env_cpu(env), addr);
return flags; return flags;
} }
@@ -814,14 +815,15 @@ typedef struct TargetPageDataNode {
static IntervalTreeRoot targetdata_root; static IntervalTreeRoot targetdata_root;
void page_reset_target_data(target_ulong start, target_ulong last) void page_reset_target_data(target_ulong start, target_ulong end)
{ {
IntervalTreeNode *n, *next; IntervalTreeNode *n, *next;
target_ulong last;
assert_memory_lock(); assert_memory_lock();
start &= TARGET_PAGE_MASK; start = start & TARGET_PAGE_MASK;
last |= ~TARGET_PAGE_MASK; last = TARGET_PAGE_ALIGN(end) - 1;
for (n = interval_tree_iter_first(&targetdata_root, start, last), for (n = interval_tree_iter_first(&targetdata_root, start, last),
next = n ? interval_tree_iter_next(n, start, last) : NULL; next = n ? interval_tree_iter_next(n, start, last) : NULL;
@@ -884,7 +886,7 @@ void *page_get_target_data(target_ulong address)
return t->data[(page - region) >> TARGET_PAGE_BITS]; return t->data[(page - region) >> TARGET_PAGE_BITS];
} }
#else #else
void page_reset_target_data(target_ulong start, target_ulong last) { } void page_reset_target_data(target_ulong start, target_ulong end) { }
#endif /* TARGET_PAGE_DATA_SIZE */ #endif /* TARGET_PAGE_DATA_SIZE */
/* The softmmu versions of these helpers are in cputlb.c. */ /* The softmmu versions of these helpers are in cputlb.c. */

View File

@@ -12,7 +12,6 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "hw/xen/xen_native.h"
#include "hw/xen/xen-legacy-backend.h" #include "hw/xen/xen-legacy-backend.h"
#include "hw/xen/xen_pt.h" #include "hw/xen/xen_pt.h"
#include "chardev/char.h" #include "chardev/char.h"
@@ -24,18 +23,99 @@
#include "migration/global_state.h" #include "migration/global_state.h"
#include "hw/boards.h" #include "hw/boards.h"
//#define DEBUG_XEN
#ifdef DEBUG_XEN
#define DPRINTF(fmt, ...) \
do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
#else
#define DPRINTF(fmt, ...) \
do { } while (0)
#endif
bool xen_allowed; bool xen_allowed;
xc_interface *xen_xc; xc_interface *xen_xc;
xenforeignmemory_handle *xen_fmem; xenforeignmemory_handle *xen_fmem;
xendevicemodel_handle *xen_dmod; xendevicemodel_handle *xen_dmod;
static void xenstore_record_dm_state(const char *state) static int store_dev_info(int domid, Chardev *cs, const char *string)
{
struct xs_handle *xs = NULL;
char *path = NULL;
char *newpath = NULL;
char *pts = NULL;
int ret = -1;
/* Only continue if we're talking to a pty. */
if (!CHARDEV_IS_PTY(cs)) {
return 0;
}
pts = cs->filename + 4;
/* We now have everything we need to set the xenstore entry. */
xs = xs_open(0);
if (xs == NULL) {
fprintf(stderr, "Could not contact XenStore\n");
goto out;
}
path = xs_get_domain_path(xs, domid);
if (path == NULL) {
fprintf(stderr, "xs_get_domain_path() error\n");
goto out;
}
newpath = realloc(path, (strlen(path) + strlen(string) +
strlen("/tty") + 1));
if (newpath == NULL) {
fprintf(stderr, "realloc error\n");
goto out;
}
path = newpath;
strcat(path, string);
strcat(path, "/tty");
if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
fprintf(stderr, "xs_write for '%s' fail", string);
goto out;
}
ret = 0;
out:
free(path);
xs_close(xs);
return ret;
}
void xenstore_store_pv_console_info(int i, Chardev *chr)
{
if (i == 0) {
store_dev_info(xen_domid, chr, "/console");
} else {
char buf[32];
snprintf(buf, sizeof(buf), "/device/console/%d", i);
store_dev_info(xen_domid, chr, buf);
}
}
static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
{ {
char path[50]; char path[50];
if (xs == NULL) {
error_report("xenstore connection not initialized");
exit(1);
}
snprintf(path, sizeof (path), "device-model/%u/state", xen_domid); snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
if (!qemu_xen_xs_write(xenstore, XBT_NULL, path, state, strlen(state))) { /*
* This call may fail when running restricted so don't make it fatal in
* that case. Toolstacks should instead use QMP to listen for state changes.
*/
if (!xs_write(xs, XBT_NULL, path, state, strlen(state)) &&
!xen_domid_restrict) {
error_report("error recording dm state"); error_report("error recording dm state");
exit(1); exit(1);
} }
@@ -47,7 +127,7 @@ static void xen_change_state_handler(void *opaque, bool running,
{ {
if (running) { if (running) {
/* record state running */ /* record state running */
xenstore_record_dm_state("running"); xenstore_record_dm_state(xenstore, "running");
} }
} }
@@ -96,21 +176,11 @@ static int xen_init(MachineState *ms)
xc_interface_close(xen_xc); xc_interface_close(xen_xc);
return -1; return -1;
} }
/*
* The XenStore write would fail when running restricted so don't attempt
* it in that case. Toolstacks should instead use QMP to listen for state
* changes.
*/
if (!xen_domid_restrict) {
qemu_add_vm_change_state_handler(xen_change_state_handler, NULL); qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
}
/* /*
* opt out of system RAM being allocated by generic code * opt out of system RAM being allocated by generic code
*/ */
mc->default_ram_id = NULL; mc->default_ram_id = NULL;
xen_mode = XEN_ATTACH;
return 0; return 0;
} }

View File

@@ -222,7 +222,11 @@ static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask)
return -1; return -1;
} }
pfds = g_new0(struct pollfd, count); pfds = audio_calloc ("alsa_poll_helper", count, sizeof (*pfds));
if (!pfds) {
dolog ("Could not initialize poll mode\n");
return -1;
}
err = snd_pcm_poll_descriptors (handle, pfds, count); err = snd_pcm_poll_descriptors (handle, pfds, count);
if (err < 0) { if (err < 0) {
@@ -913,23 +917,28 @@ static void *alsa_audio_init(Audiodev *dev)
alsa_init_per_direction(aopts->in); alsa_init_per_direction(aopts->in);
alsa_init_per_direction(aopts->out); alsa_init_per_direction(aopts->out);
/* don't set has_* so alsa_open can identify it wasn't set by the user */ /*
* need to define them, as otherwise alsa produces no sound
* doesn't set has_* so alsa_open can identify it wasn't set by the user
*/
if (!dev->u.alsa.out->has_period_length) { if (!dev->u.alsa.out->has_period_length) {
/* 256 frames assuming 44100Hz */ /* 1024 frames assuming 44100Hz */
dev->u.alsa.out->period_length = 5805; dev->u.alsa.out->period_length = 1024 * 1000000 / 44100;
} }
if (!dev->u.alsa.out->has_buffer_length) { if (!dev->u.alsa.out->has_buffer_length) {
/* 4096 frames assuming 44100Hz */ /* 4096 frames assuming 44100Hz */
dev->u.alsa.out->buffer_length = 92880; dev->u.alsa.out->buffer_length = 4096ll * 1000000 / 44100;
} }
/*
* OptsVisitor sets unspecified optional fields to zero, but do not depend
* on it...
*/
if (!dev->u.alsa.in->has_period_length) { if (!dev->u.alsa.in->has_period_length) {
/* 256 frames assuming 44100Hz */ dev->u.alsa.in->period_length = 0;
dev->u.alsa.in->period_length = 5805;
} }
if (!dev->u.alsa.in->has_buffer_length) { if (!dev->u.alsa.in->has_buffer_length) {
/* 4096 frames assuming 44100Hz */ dev->u.alsa.in->buffer_length = 0;
dev->u.alsa.in->buffer_length = 92880;
} }
return dev; return dev;

View File

@@ -33,7 +33,6 @@
#include "qapi/qapi-visit-audio.h" #include "qapi/qapi-visit-audio.h"
#include "qapi/qapi-commands-audio.h" #include "qapi/qapi-commands-audio.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qemu/log.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/help_option.h" #include "qemu/help_option.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
@@ -149,6 +148,26 @@ static inline int audio_bits_to_index (int bits)
} }
} }
void *audio_calloc (const char *funcname, int nmemb, size_t size)
{
int cond;
size_t len;
len = nmemb * size;
cond = !nmemb || !size;
cond |= nmemb < 0;
cond |= len < size;
if (audio_bug ("audio_calloc", cond)) {
AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n",
funcname);
AUD_log (NULL, "nmemb=%d size=%zu (len=%zu)\n", nmemb, size, len);
return NULL;
}
return g_malloc0 (len);
}
void AUD_vlog (const char *cap, const char *fmt, va_list ap) void AUD_vlog (const char *cap, const char *fmt, va_list ap)
{ {
if (cap) { if (cap) {
@@ -381,6 +400,13 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
/* /*
* Capture * Capture
*/ */
static void noop_conv (struct st_sample *dst, const void *src, int samples)
{
(void) src;
(void) dst;
(void) samples;
}
static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioState *s, static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioState *s,
struct audsettings *as) struct audsettings *as)
{ {
@@ -478,8 +504,15 @@ static int audio_attach_capture (HWVoiceOut *hw)
sw->info = hw->info; sw->info = hw->info;
sw->empty = 1; sw->empty = 1;
sw->active = hw->enabled; sw->active = hw->enabled;
sw->conv = noop_conv;
sw->ratio = ((int64_t) hw_cap->info.freq << 32) / sw->info.freq;
sw->vol = nominal_volume; sw->vol = nominal_volume;
sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq); sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);
if (!sw->rate) {
dolog ("Could not start rate conversion for `%s'\n", SW_NAME (sw));
g_free (sw);
return -1;
}
QLIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries); QLIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries);
QLIST_INSERT_HEAD (&hw->cap_head, sc, entries); QLIST_INSERT_HEAD (&hw->cap_head, sc, entries);
#ifdef DEBUG_CAPTURE #ifdef DEBUG_CAPTURE
@@ -514,8 +547,8 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)
static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
{ {
size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
if (audio_bug(__func__, live > hw->conv_buf.size)) { if (audio_bug(__func__, live > hw->conv_buf->size)) {
dolog("live=%zu hw->conv_buf.size=%zu\n", live, hw->conv_buf.size); dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
return 0; return 0;
} }
return live; return live;
@@ -524,13 +557,13 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples) static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples)
{ {
size_t conv = 0; size_t conv = 0;
STSampleBuffer *conv_buf = &hw->conv_buf; STSampleBuffer *conv_buf = hw->conv_buf;
while (samples) { while (samples) {
uint8_t *src = advance(pcm_buf, conv * hw->info.bytes_per_frame); uint8_t *src = advance(pcm_buf, conv * hw->info.bytes_per_frame);
size_t proc = MIN(samples, conv_buf->size - conv_buf->pos); size_t proc = MIN(samples, conv_buf->size - conv_buf->pos);
hw->conv(conv_buf->buffer + conv_buf->pos, src, proc); hw->conv(conv_buf->samples + conv_buf->pos, src, proc);
conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size; conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
samples -= proc; samples -= proc;
conv += proc; conv += proc;
@@ -542,65 +575,56 @@ static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples)
/* /*
* Soft voice (capture) * Soft voice (capture)
*/ */
static void audio_pcm_sw_resample_in(SWVoiceIn *sw, static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
size_t frames_in_max, size_t frames_out_max,
size_t *total_in, size_t *total_out)
{ {
HWVoiceIn *hw = sw->hw; HWVoiceIn *hw = sw->hw;
struct st_sample *src, *dst; size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
size_t live, rpos, frames_in, frames_out; struct st_sample *src, *dst = sw->buf;
live = hw->total_samples_captured - sw->total_hw_samples_acquired;
rpos = audio_ring_posb(hw->conv_buf.pos, live, hw->conv_buf.size);
/* resample conv_buf from rpos to end of buffer */
src = hw->conv_buf.buffer + rpos;
frames_in = MIN(frames_in_max, hw->conv_buf.size - rpos);
dst = sw->resample_buf.buffer;
frames_out = frames_out_max;
st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out);
rpos += frames_in;
*total_in = frames_in;
*total_out = frames_out;
/* resample conv_buf from start of buffer if there are input frames left */
if (frames_in_max - frames_in && rpos == hw->conv_buf.size) {
src = hw->conv_buf.buffer;
frames_in = frames_in_max - frames_in;
dst += frames_out;
frames_out = frames_out_max - frames_out;
st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out);
*total_in += frames_in;
*total_out += frames_out;
}
}
static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t buf_len)
{
HWVoiceIn *hw = sw->hw;
size_t live, frames_out_max, total_in, total_out;
live = hw->total_samples_captured - sw->total_hw_samples_acquired; live = hw->total_samples_captured - sw->total_hw_samples_acquired;
if (!live) { if (!live) {
return 0; return 0;
} }
if (audio_bug(__func__, live > hw->conv_buf.size)) { if (audio_bug(__func__, live > hw->conv_buf->size)) {
dolog("live_in=%zu hw->conv_buf.size=%zu\n", live, hw->conv_buf.size); dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
return 0; return 0;
} }
frames_out_max = MIN(buf_len / sw->info.bytes_per_frame, rpos = audio_ring_posb(hw->conv_buf->pos, live, hw->conv_buf->size);
sw->resample_buf.size);
audio_pcm_sw_resample_in(sw, live, frames_out_max, &total_in, &total_out); samples = size / sw->info.bytes_per_frame;
swlim = (live * sw->ratio) >> 32;
swlim = MIN (swlim, samples);
while (swlim) {
src = hw->conv_buf->samples + rpos;
if (hw->conv_buf->pos > rpos) {
isamp = hw->conv_buf->pos - rpos;
} else {
isamp = hw->conv_buf->size - rpos;
}
if (!isamp) {
break;
}
osamp = swlim;
st_rate_flow (sw->rate, src, dst, &isamp, &osamp);
swlim -= osamp;
rpos = (rpos + isamp) % hw->conv_buf->size;
dst += osamp;
ret += osamp;
total += isamp;
}
if (!hw->pcm_ops->volume_in) { if (!hw->pcm_ops->volume_in) {
mixeng_volume(sw->resample_buf.buffer, total_out, &sw->vol); mixeng_volume (sw->buf, ret, &sw->vol);
} }
sw->clip(buf, sw->resample_buf.buffer, total_out);
sw->total_hw_samples_acquired += total_in; sw->clip (buf, sw->buf, ret);
return total_out * sw->info.bytes_per_frame; sw->total_hw_samples_acquired += total;
return ret * sw->info.bytes_per_frame;
} }
/* /*
@@ -636,8 +660,8 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live)
if (nb_live1) { if (nb_live1) {
size_t live = smin; size_t live = smin;
if (audio_bug(__func__, live > hw->mix_buf.size)) { if (audio_bug(__func__, live > hw->mix_buf->size)) {
dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size); dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size);
return 0; return 0;
} }
return live; return live;
@@ -654,17 +678,17 @@ static size_t audio_pcm_hw_get_free(HWVoiceOut *hw)
static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len) static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
{ {
size_t clipped = 0; size_t clipped = 0;
size_t pos = hw->mix_buf.pos; size_t pos = hw->mix_buf->pos;
while (len) { while (len) {
st_sample *src = hw->mix_buf.buffer + pos; st_sample *src = hw->mix_buf->samples + pos;
uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame); uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
size_t samples_till_end_of_buf = hw->mix_buf.size - pos; size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
size_t samples_to_clip = MIN(len, samples_till_end_of_buf); size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
hw->clip(dst, src, samples_to_clip); hw->clip(dst, src, samples_to_clip);
pos = (pos + samples_to_clip) % hw->mix_buf.size; pos = (pos + samples_to_clip) % hw->mix_buf->size;
len -= samples_to_clip; len -= samples_to_clip;
clipped += samples_to_clip; clipped += samples_to_clip;
} }
@@ -673,113 +697,84 @@ static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
/* /*
* Soft voice (playback) * Soft voice (playback)
*/ */
static void audio_pcm_sw_resample_out(SWVoiceOut *sw, static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
size_t frames_in_max, size_t frames_out_max,
size_t *total_in, size_t *total_out)
{ {
HWVoiceOut *hw = sw->hw; size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, blck;
struct st_sample *src, *dst; size_t hw_free;
size_t live, wpos, frames_in, frames_out; size_t ret = 0, pos = 0, total = 0;
live = sw->total_hw_samples_mixed; if (!sw) {
wpos = (hw->mix_buf.pos + live) % hw->mix_buf.size; return size;
/* write to mix_buf from wpos to end of buffer */
src = sw->resample_buf.buffer;
frames_in = frames_in_max;
dst = hw->mix_buf.buffer + wpos;
frames_out = MIN(frames_out_max, hw->mix_buf.size - wpos);
st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
wpos += frames_out;
*total_in = frames_in;
*total_out = frames_out;
/* write to mix_buf from start of buffer if there are input frames left */
if (frames_in_max - frames_in > 0 && wpos == hw->mix_buf.size) {
src += frames_in;
frames_in = frames_in_max - frames_in;
dst = hw->mix_buf.buffer;
frames_out = frames_out_max - frames_out;
st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
*total_in += frames_in;
*total_out += frames_out;
}
} }
static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len) hwsamples = sw->hw->mix_buf->size;
{
HWVoiceOut *hw = sw->hw;
size_t live, dead, hw_free, sw_max, fe_max;
size_t frames_in_max, frames_out_max, total_in, total_out;
live = sw->total_hw_samples_mixed; live = sw->total_hw_samples_mixed;
if (audio_bug(__func__, live > hw->mix_buf.size)) { if (audio_bug(__func__, live > hwsamples)) {
dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size); dolog("live=%zu hw->mix_buf->size=%zu\n", live, hwsamples);
return 0; return 0;
} }
if (live == hw->mix_buf.size) { if (live == hwsamples) {
#ifdef DEBUG_OUT #ifdef DEBUG_OUT
dolog ("%s is full %zu\n", sw->name, live); dolog ("%s is full %zu\n", sw->name, live);
#endif #endif
return 0; return 0;
} }
dead = hw->mix_buf.size - live; wpos = (sw->hw->mix_buf->pos + live) % hwsamples;
hw_free = audio_pcm_hw_get_free(hw);
dead = hwsamples - live;
hw_free = audio_pcm_hw_get_free(sw->hw);
hw_free = hw_free > live ? hw_free - live : 0; hw_free = hw_free > live ? hw_free - live : 0;
frames_out_max = MIN(dead, hw_free); samples = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
sw_max = st_rate_frames_in(sw->rate, frames_out_max); samples = MIN(samples, size / sw->info.bytes_per_frame);
fe_max = MIN(buf_len / sw->info.bytes_per_frame + sw->resample_buf.pos, if (samples) {
sw->resample_buf.size); sw->conv(sw->buf, buf, samples);
frames_in_max = MIN(sw_max, fe_max);
if (!frames_in_max) {
return 0;
}
if (frames_in_max > sw->resample_buf.pos) {
sw->conv(sw->resample_buf.buffer + sw->resample_buf.pos,
buf, frames_in_max - sw->resample_buf.pos);
if (!sw->hw->pcm_ops->volume_out) { if (!sw->hw->pcm_ops->volume_out) {
mixeng_volume(sw->resample_buf.buffer + sw->resample_buf.pos, mixeng_volume(sw->buf, samples, &sw->vol);
frames_in_max - sw->resample_buf.pos, &sw->vol);
} }
} }
audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max, while (samples) {
&total_in, &total_out); dead = hwsamples - live;
left = hwsamples - wpos;
blck = MIN (dead, left);
if (!blck) {
break;
}
isamp = samples;
osamp = blck;
st_rate_flow_mix (
sw->rate,
sw->buf + pos,
sw->hw->mix_buf->samples + wpos,
&isamp,
&osamp
);
ret += isamp;
samples -= isamp;
pos += isamp;
live += osamp;
wpos = (wpos + osamp) % hwsamples;
total += osamp;
}
sw->total_hw_samples_mixed += total_out; sw->total_hw_samples_mixed += total;
sw->empty = sw->total_hw_samples_mixed == 0; sw->empty = sw->total_hw_samples_mixed == 0;
/*
* Upsampling may leave one audio frame in the resample buffer. Decrement
* total_in by one if there was a leftover frame from the previous resample
* pass in the resample buffer. Increment total_in by one if the current
* resample pass left one frame in the resample buffer.
*/
if (frames_in_max - total_in == 1) {
/* copy one leftover audio frame to the beginning of the buffer */
*sw->resample_buf.buffer = *(sw->resample_buf.buffer + total_in);
total_in += 1 - sw->resample_buf.pos;
sw->resample_buf.pos = 1;
} else if (total_in >= sw->resample_buf.pos) {
total_in -= sw->resample_buf.pos;
sw->resample_buf.pos = 0;
}
#ifdef DEBUG_OUT #ifdef DEBUG_OUT
dolog ( dolog (
"%s: write size %zu written %zu total mixed %zu\n", "%s: write size %zu ret %zu total sw %zu\n",
SW_NAME (sw), SW_NAME (sw),
buf_len / sw->info.bytes_per_frame, size / sw->info.bytes_per_frame,
total_in, ret,
sw->total_hw_samples_mixed sw->total_hw_samples_mixed
); );
#endif #endif
return total_in * sw->info.bytes_per_frame; return ret * sw->info.bytes_per_frame;
} }
#ifdef DEBUG_AUDIO #ifdef DEBUG_AUDIO
@@ -997,6 +992,18 @@ void AUD_set_active_in (SWVoiceIn *sw, int on)
} }
} }
/**
* audio_frontend_frames_in() - returns the number of frames the resampling
* code generates from frames_in frames
*
* @sw: audio recording frontend
* @frames_in: number of frames
*/
static size_t audio_frontend_frames_in(SWVoiceIn *sw, size_t frames_in)
{
return (int64_t)frames_in * sw->ratio >> 32;
}
static size_t audio_get_avail (SWVoiceIn *sw) static size_t audio_get_avail (SWVoiceIn *sw)
{ {
size_t live; size_t live;
@@ -1006,21 +1013,33 @@ static size_t audio_get_avail (SWVoiceIn *sw)
} }
live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired; live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
if (audio_bug(__func__, live > sw->hw->conv_buf.size)) { if (audio_bug(__func__, live > sw->hw->conv_buf->size)) {
dolog("live=%zu sw->hw->conv_buf.size=%zu\n", live, dolog("live=%zu sw->hw->conv_buf->size=%zu\n", live,
sw->hw->conv_buf.size); sw->hw->conv_buf->size);
return 0; return 0;
} }
ldebug ( ldebug (
"%s: get_avail live %zu frontend frames %u\n", "%s: get_avail live %zu frontend frames %zu\n",
SW_NAME (sw), SW_NAME (sw),
live, st_rate_frames_out(sw->rate, live) live, audio_frontend_frames_in(sw, live)
); );
return live; return live;
} }
/**
* audio_frontend_frames_out() - returns the number of frames needed to
* get frames_out frames after resampling
*
* @sw: audio playback frontend
* @frames_out: number of frames
*/
static size_t audio_frontend_frames_out(SWVoiceOut *sw, size_t frames_out)
{
return ((int64_t)frames_out << 32) / sw->ratio;
}
static size_t audio_get_free(SWVoiceOut *sw) static size_t audio_get_free(SWVoiceOut *sw)
{ {
size_t live, dead; size_t live, dead;
@@ -1031,17 +1050,17 @@ static size_t audio_get_free(SWVoiceOut *sw)
live = sw->total_hw_samples_mixed; live = sw->total_hw_samples_mixed;
if (audio_bug(__func__, live > sw->hw->mix_buf.size)) { if (audio_bug(__func__, live > sw->hw->mix_buf->size)) {
dolog("live=%zu sw->hw->mix_buf.size=%zu\n", live, dolog("live=%zu sw->hw->mix_buf->size=%zu\n", live,
sw->hw->mix_buf.size); sw->hw->mix_buf->size);
return 0; return 0;
} }
dead = sw->hw->mix_buf.size - live; dead = sw->hw->mix_buf->size - live;
#ifdef DEBUG_OUT #ifdef DEBUG_OUT
dolog("%s: get_free live %zu dead %zu frontend frames %u\n", dolog("%s: get_free live %zu dead %zu frontend frames %zu\n",
SW_NAME(sw), live, dead, st_rate_frames_in(sw->rate, dead)); SW_NAME(sw), live, dead, audio_frontend_frames_out(sw, dead));
#endif #endif
return dead; return dead;
@@ -1057,40 +1076,32 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
SWVoiceOut *sw = &sc->sw; SWVoiceOut *sw = &sc->sw;
size_t rpos2 = rpos; int rpos2 = rpos;
n = samples; n = samples;
while (n) { while (n) {
size_t till_end_of_hw = hw->mix_buf.size - rpos2; size_t till_end_of_hw = hw->mix_buf->size - rpos2;
size_t to_read = MIN(till_end_of_hw, n); size_t to_write = MIN(till_end_of_hw, n);
size_t live, frames_in, frames_out; size_t bytes = to_write * hw->info.bytes_per_frame;
size_t written;
sw->resample_buf.buffer = hw->mix_buf.buffer + rpos2; sw->buf = hw->mix_buf->samples + rpos2;
sw->resample_buf.size = to_read; written = audio_pcm_sw_write (sw, NULL, bytes);
live = sw->total_hw_samples_mixed; if (written - bytes) {
dolog("Could not mix %zu bytes into a capture "
audio_pcm_sw_resample_out(sw,
to_read, sw->hw->mix_buf.size - live,
&frames_in, &frames_out);
sw->total_hw_samples_mixed += frames_out;
sw->empty = sw->total_hw_samples_mixed == 0;
if (to_read - frames_in) {
dolog("Could not mix %zu frames into a capture "
"buffer, mixed %zu\n", "buffer, mixed %zu\n",
to_read, frames_in); bytes, written);
break; break;
} }
n -= to_read; n -= to_write;
rpos2 = (rpos2 + to_read) % hw->mix_buf.size; rpos2 = (rpos2 + to_write) % hw->mix_buf->size;
} }
} }
} }
n = MIN(samples, hw->mix_buf.size - rpos); n = MIN(samples, hw->mix_buf->size - rpos);
mixeng_clear(hw->mix_buf.buffer + rpos, n); mixeng_clear(hw->mix_buf->samples + rpos, n);
mixeng_clear(hw->mix_buf.buffer, samples - n); mixeng_clear(hw->mix_buf->samples, samples - n);
} }
static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
@@ -1116,7 +1127,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
live -= proc; live -= proc;
clipped += proc; clipped += proc;
hw->mix_buf.pos = (hw->mix_buf.pos + proc) % hw->mix_buf.size; hw->mix_buf->pos = (hw->mix_buf->pos + proc) % hw->mix_buf->size;
if (proc == 0 || proc < decr) { if (proc == 0 || proc < decr) {
break; break;
@@ -1170,14 +1181,12 @@ static void audio_run_out (AudioState *s)
size_t free; size_t free;
if (hw_free > sw->total_hw_samples_mixed) { if (hw_free > sw->total_hw_samples_mixed) {
free = st_rate_frames_in(sw->rate, free = audio_frontend_frames_out(sw,
MIN(sw_free, hw_free - sw->total_hw_samples_mixed)); MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
} else { } else {
free = 0; free = 0;
} }
if (free > sw->resample_buf.pos) { if (free > 0) {
free = MIN(free, sw->resample_buf.size)
- sw->resample_buf.pos;
sw->callback.fn(sw->callback.opaque, sw->callback.fn(sw->callback.opaque,
free * sw->info.bytes_per_frame); free * sw->info.bytes_per_frame);
} }
@@ -1189,8 +1198,8 @@ static void audio_run_out (AudioState *s)
live = 0; live = 0;
} }
if (audio_bug(__func__, live > hw->mix_buf.size)) { if (audio_bug(__func__, live > hw->mix_buf->size)) {
dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size); dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size);
continue; continue;
} }
@@ -1218,13 +1227,13 @@ static void audio_run_out (AudioState *s)
continue; continue;
} }
prev_rpos = hw->mix_buf.pos; prev_rpos = hw->mix_buf->pos;
played = audio_pcm_hw_run_out(hw, live); played = audio_pcm_hw_run_out(hw, live);
replay_audio_out(&played); replay_audio_out(&played);
if (audio_bug(__func__, hw->mix_buf.pos >= hw->mix_buf.size)) { if (audio_bug(__func__, hw->mix_buf->pos >= hw->mix_buf->size)) {
dolog("hw->mix_buf.pos=%zu hw->mix_buf.size=%zu played=%zu\n", dolog("hw->mix_buf->pos=%zu hw->mix_buf->size=%zu played=%zu\n",
hw->mix_buf.pos, hw->mix_buf.size, played); hw->mix_buf->pos, hw->mix_buf->size, played);
hw->mix_buf.pos = 0; hw->mix_buf->pos = 0;
} }
#ifdef DEBUG_OUT #ifdef DEBUG_OUT
@@ -1305,10 +1314,10 @@ static void audio_run_in (AudioState *s)
if (replay_mode != REPLAY_MODE_PLAY) { if (replay_mode != REPLAY_MODE_PLAY) {
captured = audio_pcm_hw_run_in( captured = audio_pcm_hw_run_in(
hw, hw->conv_buf.size - audio_pcm_hw_get_live_in(hw)); hw, hw->conv_buf->size - audio_pcm_hw_get_live_in(hw));
} }
replay_audio_in(&captured, hw->conv_buf.buffer, &hw->conv_buf.pos, replay_audio_in(&captured, hw->conv_buf->samples, &hw->conv_buf->pos,
hw->conv_buf.size); hw->conv_buf->size);
min = audio_pcm_hw_find_min_in (hw); min = audio_pcm_hw_find_min_in (hw);
hw->total_samples_captured += captured - min; hw->total_samples_captured += captured - min;
@@ -1321,9 +1330,8 @@ static void audio_run_in (AudioState *s)
size_t sw_avail = audio_get_avail(sw); size_t sw_avail = audio_get_avail(sw);
size_t avail; size_t avail;
avail = st_rate_frames_out(sw->rate, sw_avail); avail = audio_frontend_frames_in(sw, sw_avail);
if (avail > 0) { if (avail > 0) {
avail = MIN(avail, sw->resample_buf.size);
sw->callback.fn(sw->callback.opaque, sw->callback.fn(sw->callback.opaque,
avail * sw->info.bytes_per_frame); avail * sw->info.bytes_per_frame);
} }
@@ -1342,14 +1350,14 @@ static void audio_run_capture (AudioState *s)
SWVoiceOut *sw; SWVoiceOut *sw;
captured = live = audio_pcm_hw_get_live_out (hw, NULL); captured = live = audio_pcm_hw_get_live_out (hw, NULL);
rpos = hw->mix_buf.pos; rpos = hw->mix_buf->pos;
while (live) { while (live) {
size_t left = hw->mix_buf.size - rpos; size_t left = hw->mix_buf->size - rpos;
size_t to_capture = MIN(live, left); size_t to_capture = MIN(live, left);
struct st_sample *src; struct st_sample *src;
struct capture_callback *cb; struct capture_callback *cb;
src = hw->mix_buf.buffer + rpos; src = hw->mix_buf->samples + rpos;
hw->clip (cap->buf, src, to_capture); hw->clip (cap->buf, src, to_capture);
mixeng_clear (src, to_capture); mixeng_clear (src, to_capture);
@@ -1357,10 +1365,10 @@ static void audio_run_capture (AudioState *s)
cb->ops.capture (cb->opaque, cap->buf, cb->ops.capture (cb->opaque, cap->buf,
to_capture * hw->info.bytes_per_frame); to_capture * hw->info.bytes_per_frame);
} }
rpos = (rpos + to_capture) % hw->mix_buf.size; rpos = (rpos + to_capture) % hw->mix_buf->size;
live -= to_capture; live -= to_capture;
} }
hw->mix_buf.pos = rpos; hw->mix_buf->pos = rpos;
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
if (!sw->active && sw->empty) { if (!sw->active && sw->empty) {
@@ -1919,7 +1927,7 @@ CaptureVoiceOut *AUD_add_capture(
audio_pcm_init_info (&hw->info, as); audio_pcm_init_info (&hw->info, as);
cap->buf = g_malloc0_n(hw->mix_buf.size, hw->info.bytes_per_frame); cap->buf = g_malloc0_n(hw->mix_buf->size, hw->info.bytes_per_frame);
if (hw->info.is_float) { if (hw->info.is_float) {
hw->clip = mixeng_clip_float[hw->info.nchannels == 2]; hw->clip = mixeng_clip_float[hw->info.nchannels == 2];
@@ -1971,7 +1979,7 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
sw = sw1; sw = sw1;
} }
QLIST_REMOVE (cap, entries); QLIST_REMOVE (cap, entries);
g_free(cap->hw.mix_buf.buffer); g_free (cap->hw.mix_buf);
g_free (cap->buf); g_free (cap->buf);
g_free (cap); g_free (cap);
} }

View File

@@ -58,7 +58,7 @@ typedef struct SWVoiceCap SWVoiceCap;
typedef struct STSampleBuffer { typedef struct STSampleBuffer {
size_t pos, size; size_t pos, size;
st_sample *buffer; st_sample samples[];
} STSampleBuffer; } STSampleBuffer;
typedef struct HWVoiceOut { typedef struct HWVoiceOut {
@@ -71,7 +71,7 @@ typedef struct HWVoiceOut {
f_sample *clip; f_sample *clip;
uint64_t ts_helper; uint64_t ts_helper;
STSampleBuffer mix_buf; STSampleBuffer *mix_buf;
void *buf_emul; void *buf_emul;
size_t pos_emul, pending_emul, size_emul; size_t pos_emul, pending_emul, size_emul;
@@ -93,7 +93,7 @@ typedef struct HWVoiceIn {
size_t total_samples_captured; size_t total_samples_captured;
uint64_t ts_helper; uint64_t ts_helper;
STSampleBuffer conv_buf; STSampleBuffer *conv_buf;
void *buf_emul; void *buf_emul;
size_t pos_emul, pending_emul, size_emul; size_t pos_emul, pending_emul, size_emul;
@@ -108,7 +108,8 @@ struct SWVoiceOut {
AudioState *s; AudioState *s;
struct audio_pcm_info info; struct audio_pcm_info info;
t_sample *conv; t_sample *conv;
STSampleBuffer resample_buf; int64_t ratio;
struct st_sample *buf;
void *rate; void *rate;
size_t total_hw_samples_mixed; size_t total_hw_samples_mixed;
int active; int active;
@@ -125,9 +126,10 @@ struct SWVoiceIn {
AudioState *s; AudioState *s;
int active; int active;
struct audio_pcm_info info; struct audio_pcm_info info;
int64_t ratio;
void *rate; void *rate;
size_t total_hw_samples_acquired; size_t total_hw_samples_acquired;
STSampleBuffer resample_buf; struct st_sample *buf;
f_sample *clip; f_sample *clip;
HWVoiceIn *hw; HWVoiceIn *hw;
char *name; char *name;
@@ -143,14 +145,14 @@ struct audio_driver {
void *(*init) (Audiodev *); void *(*init) (Audiodev *);
void (*fini) (void *); void (*fini) (void *);
#ifdef CONFIG_GIO #ifdef CONFIG_GIO
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p); void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager);
#endif #endif
struct audio_pcm_ops *pcm_ops; struct audio_pcm_ops *pcm_ops;
int can_be_default; int can_be_default;
int max_voices_out; int max_voices_out;
int max_voices_in; int max_voices_in;
size_t voice_size_out; int voice_size_out;
size_t voice_size_in; int voice_size_in;
QLIST_ENTRY(audio_driver) next; QLIST_ENTRY(audio_driver) next;
}; };
@@ -249,6 +251,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
int audio_bug (const char *funcname, int cond); int audio_bug (const char *funcname, int cond);
void *audio_calloc (const char *funcname, int nmemb, size_t size);
void audio_run(AudioState *s, const char *msg); void audio_run(AudioState *s, const char *msg);
@@ -291,6 +294,9 @@ static inline size_t audio_ring_posb(size_t pos, size_t dist, size_t len)
#define ldebug(fmt, ...) (void)0 #define ldebug(fmt, ...) (void)0
#endif #endif
#define AUDIO_STRINGIFY_(n) #n
#define AUDIO_STRINGIFY(n) AUDIO_STRINGIFY_(n)
typedef struct AudiodevListEntry { typedef struct AudiodevListEntry {
Audiodev *dev; Audiodev *dev;
QSIMPLEQ_ENTRY(AudiodevListEntry) next; QSIMPLEQ_ENTRY(AudiodevListEntry) next;

View File

@@ -40,7 +40,7 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
struct audio_driver *drv) struct audio_driver *drv)
{ {
int max_voices = glue (drv->max_voices_, TYPE); int max_voices = glue (drv->max_voices_, TYPE);
size_t voice_size = glue(drv->voice_size_, TYPE); int voice_size = glue (drv->voice_size_, TYPE);
if (glue (s->nb_hw_voices_, TYPE) > max_voices) { if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
if (!max_voices) { if (!max_voices) {
@@ -63,7 +63,7 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
} }
if (audio_bug(__func__, voice_size && !max_voices)) { if (audio_bug(__func__, voice_size && !max_voices)) {
dolog("drv=`%s' voice_size=%zu max_voices=0\n", dolog ("drv=`%s' voice_size=%d max_voices=0\n",
drv->name, voice_size); drv->name, voice_size);
} }
} }
@@ -71,9 +71,8 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
{ {
g_free(hw->buf_emul); g_free(hw->buf_emul);
g_free(HWBUF.buffer); g_free (HWBUF);
HWBUF.buffer = NULL; HWBUF = NULL;
HWBUF.size = 0;
} }
static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw) static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
@@ -84,67 +83,56 @@ static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
dolog("Attempted to allocate empty buffer\n"); dolog("Attempted to allocate empty buffer\n");
} }
HWBUF.buffer = g_new0(st_sample, samples); HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples);
HWBUF.size = samples; HWBUF->size = samples;
HWBUF.pos = 0;
} else { } else {
HWBUF.buffer = NULL; HWBUF = NULL;
HWBUF.size = 0;
} }
} }
static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw) static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
{ {
g_free(sw->resample_buf.buffer); g_free (sw->buf);
sw->resample_buf.buffer = NULL;
sw->resample_buf.size = 0;
if (sw->rate) { if (sw->rate) {
st_rate_stop (sw->rate); st_rate_stop (sw->rate);
} }
sw->buf = NULL;
sw->rate = NULL; sw->rate = NULL;
} }
static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw) static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
{ {
HW *hw = sw->hw; int samples;
uint64_t samples;
if (!glue(audio_get_pdo_, TYPE)(sw->s->dev)->mixing_engine) { if (!glue(audio_get_pdo_, TYPE)(sw->s->dev)->mixing_engine) {
return 0; return 0;
} }
samples = muldiv64(HWBUF.size, sw->info.freq, hw->info.freq); #ifdef DAC
if (samples == 0) { samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;
uint64_t f_fe_min; #else
uint64_t f_be = (uint32_t)hw->info.freq; samples = (int64_t)sw->HWBUF->size * sw->ratio >> 32;
#endif
/* f_fe_min = ceil(1 [frames] * f_be [Hz] / size_be [frames]) */ sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
f_fe_min = (f_be + HWBUF.size - 1) / HWBUF.size; if (!sw->buf) {
qemu_log_mask(LOG_UNIMP, dolog ("Could not allocate buffer for `%s' (%d samples)\n",
AUDIO_CAP ": The guest selected a " NAME " sample rate" SW_NAME (sw), samples);
" of %d Hz for %s. Only sample rates >= %" PRIu64 " Hz"
" are supported.\n",
sw->info.freq, sw->name, f_fe_min);
return -1; return -1;
} }
/*
* Allocate one additional audio frame that is needed for upsampling
* if the resample buffer size is small. For large buffer sizes take
* care of overflows and truncation.
*/
samples = samples < SIZE_MAX ? samples + 1 : SIZE_MAX;
sw->resample_buf.buffer = g_new0(st_sample, samples);
sw->resample_buf.size = samples;
sw->resample_buf.pos = 0;
#ifdef DAC #ifdef DAC
sw->rate = st_rate_start(sw->info.freq, hw->info.freq); sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
#else #else
sw->rate = st_rate_start(hw->info.freq, sw->info.freq); sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
#endif #endif
if (!sw->rate) {
g_free (sw->buf);
sw->buf = NULL;
return -1;
}
return 0; return 0;
} }
@@ -161,8 +149,11 @@ static int glue (audio_pcm_sw_init_, TYPE) (
sw->hw = hw; sw->hw = hw;
sw->active = 0; sw->active = 0;
#ifdef DAC #ifdef DAC
sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
sw->total_hw_samples_mixed = 0; sw->total_hw_samples_mixed = 0;
sw->empty = 1; sw->empty = 1;
#else
sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
#endif #endif
if (sw->info.is_float) { if (sw->info.is_float) {
@@ -273,11 +264,13 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
return NULL; return NULL;
} }
/* hw = audio_calloc(__func__, 1, glue(drv->voice_size_, TYPE));
* Since glue(s->nb_hw_voices_, TYPE) is != 0, glue(drv->voice_size_, TYPE) if (!hw) {
* is guaranteed to be != 0. See the audio_init_nb_voices_* functions. dolog ("Can not allocate voice `%s' size %d\n",
*/ drv->name, glue (drv->voice_size_, TYPE));
hw = g_malloc0(glue(drv->voice_size_, TYPE)); return NULL;
}
hw->s = s; hw->s = s;
hw->pcm_ops = drv->pcm_ops; hw->pcm_ops = drv->pcm_ops;
@@ -425,28 +418,33 @@ static SW *glue(audio_pcm_create_voice_pair_, TYPE)(
hw_as = *as; hw_as = *as;
} }
sw = g_new0(SW, 1); sw = audio_calloc(__func__, 1, sizeof(*sw));
if (!sw) {
dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
sw_name ? sw_name : "unknown", sizeof (*sw));
goto err1;
}
sw->s = s; sw->s = s;
hw = glue(audio_pcm_hw_add_, TYPE)(s, &hw_as); hw = glue(audio_pcm_hw_add_, TYPE)(s, &hw_as);
if (!hw) { if (!hw) {
dolog("Could not create a backend for voice `%s'\n", sw_name); goto err2;
goto err1;
} }
glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw); glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) { if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
goto err2; goto err3;
} }
return sw; return sw;
err2: err3:
glue (audio_pcm_hw_del_sw_, TYPE) (sw); glue (audio_pcm_hw_del_sw_, TYPE) (sw);
glue (audio_pcm_hw_gc_, TYPE) (&hw); glue (audio_pcm_hw_gc_, TYPE) (&hw);
err1: err2:
g_free (sw); g_free (sw);
err1:
return NULL; return NULL;
} }
@@ -517,7 +515,7 @@ SW *glue (AUD_open_, TYPE) (
HW *hw = sw->hw; HW *hw = sw->hw;
if (!hw) { if (!hw) {
dolog("Internal logic error: voice `%s' has no backend\n", dolog ("Internal logic error voice `%s' has no hardware store\n",
SW_NAME (sw)); SW_NAME (sw));
goto fail; goto fail;
} }
@@ -529,6 +527,7 @@ SW *glue (AUD_open_, TYPE) (
} else { } else {
sw = glue(audio_pcm_create_voice_pair_, TYPE)(s, name, as); sw = glue(audio_pcm_create_voice_pair_, TYPE)(s, name, as);
if (!sw) { if (!sw) {
dolog ("Failed to create voice `%s'\n", name);
return NULL; return NULL;
} }
} }

View File

@@ -43,7 +43,6 @@
typedef struct DBusAudio { typedef struct DBusAudio {
GDBusObjectManagerServer *server; GDBusObjectManagerServer *server;
bool p2p;
GDBusObjectSkeleton *audio; GDBusObjectSkeleton *audio;
QemuDBusDisplay1Audio *iface; QemuDBusDisplay1Audio *iface;
GHashTable *out_listeners; GHashTable *out_listeners;
@@ -449,8 +448,7 @@ dbus_audio_register_listener(AudioState *s,
bool out) bool out)
{ {
DBusAudio *da = s->drv_opaque; DBusAudio *da = s->drv_opaque;
const char *sender = const char *sender = g_dbus_method_invocation_get_sender(invocation);
da->p2p ? "p2p" : g_dbus_method_invocation_get_sender(invocation);
g_autoptr(GDBusConnection) listener_conn = NULL; g_autoptr(GDBusConnection) listener_conn = NULL;
g_autoptr(GError) err = NULL; g_autoptr(GError) err = NULL;
g_autoptr(GSocket) socket = NULL; g_autoptr(GSocket) socket = NULL;
@@ -593,7 +591,7 @@ dbus_audio_register_in_listener(AudioState *s,
} }
static void static void
dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p) dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server)
{ {
DBusAudio *da = s->drv_opaque; DBusAudio *da = s->drv_opaque;
@@ -601,7 +599,6 @@ dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p)
g_assert(!da->server); g_assert(!da->server);
da->server = g_object_ref(server); da->server = g_object_ref(server);
da->p2p = p2p;
da->audio = g_dbus_object_skeleton_new(DBUS_DISPLAY1_AUDIO_PATH); da->audio = g_dbus_object_skeleton_new(DBUS_DISPLAY1_AUDIO_PATH);
da->iface = qemu_dbus_display1_audio_skeleton_new(); da->iface = qemu_dbus_display1_audio_skeleton_new();

View File

@@ -414,7 +414,12 @@ struct rate {
*/ */
void *st_rate_start (int inrate, int outrate) void *st_rate_start (int inrate, int outrate)
{ {
struct rate *rate = g_new0(struct rate, 1); struct rate *rate = audio_calloc(__func__, 1, sizeof(*rate));
if (!rate) {
dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
return NULL;
}
rate->opos = 0; rate->opos = 0;
@@ -440,86 +445,6 @@ void st_rate_stop (void *opaque)
g_free (opaque); g_free (opaque);
} }
/**
* st_rate_frames_out() - returns the number of frames the resampling code
* generates from frames_in frames
*
* @opaque: pointer to struct rate
* @frames_in: number of frames
*
* When upsampling, there may be more than one correct result. In this case,
* the function returns the maximum number of output frames the resampling
* code can generate.
*/
uint32_t st_rate_frames_out(void *opaque, uint32_t frames_in)
{
struct rate *rate = opaque;
uint64_t opos_end, opos_delta;
uint32_t ipos_end;
uint32_t frames_out;
if (rate->opos_inc == 1ULL << 32) {
return frames_in;
}
/* no output frame without at least one input frame */
if (!frames_in) {
return 0;
}
/* last frame read was at rate->ipos - 1 */
ipos_end = rate->ipos - 1 + frames_in;
opos_end = (uint64_t)ipos_end << 32;
/* last frame written was at rate->opos - rate->opos_inc */
if (opos_end + rate->opos_inc <= rate->opos) {
return 0;
}
opos_delta = opos_end - rate->opos + rate->opos_inc;
frames_out = opos_delta / rate->opos_inc;
return opos_delta % rate->opos_inc ? frames_out : frames_out - 1;
}
/**
* st_rate_frames_in() - returns the number of frames needed to
* get frames_out frames after resampling
*
* @opaque: pointer to struct rate
* @frames_out: number of frames
*
* When downsampling, there may be more than one correct result. In this
* case, the function returns the maximum number of input frames needed.
*/
uint32_t st_rate_frames_in(void *opaque, uint32_t frames_out)
{
struct rate *rate = opaque;
uint64_t opos_start, opos_end;
uint32_t ipos_start, ipos_end;
if (rate->opos_inc == 1ULL << 32) {
return frames_out;
}
if (frames_out) {
opos_start = rate->opos;
ipos_start = rate->ipos;
} else {
uint64_t offset;
/* add offset = ceil(opos_inc) to opos and ipos to avoid an underflow */
offset = (rate->opos_inc + (1ULL << 32) - 1) & ~((1ULL << 32) - 1);
opos_start = rate->opos + offset;
ipos_start = rate->ipos + (offset >> 32);
}
/* last frame written was at opos_start - rate->opos_inc */
opos_end = opos_start - rate->opos_inc + rate->opos_inc * frames_out;
ipos_end = (opos_end >> 32) + 1;
/* last frame read was at ipos_start - 1 */
return ipos_end + 1 > ipos_start ? ipos_end + 1 - ipos_start : 0;
}
void mixeng_clear (struct st_sample *buf, int len) void mixeng_clear (struct st_sample *buf, int len)
{ {
memset (buf, 0, len * sizeof (struct st_sample)); memset (buf, 0, len * sizeof (struct st_sample));

View File

@@ -52,8 +52,6 @@ void st_rate_flow(void *opaque, st_sample *ibuf, st_sample *obuf,
void st_rate_flow_mix(void *opaque, st_sample *ibuf, st_sample *obuf, void st_rate_flow_mix(void *opaque, st_sample *ibuf, st_sample *obuf,
size_t *isamp, size_t *osamp); size_t *isamp, size_t *osamp);
void st_rate_stop (void *opaque); void st_rate_stop (void *opaque);
uint32_t st_rate_frames_out(void *opaque, uint32_t frames_in);
uint32_t st_rate_frames_in(void *opaque, uint32_t frames_out);
void mixeng_clear (struct st_sample *buf, int len); void mixeng_clear (struct st_sample *buf, int len);
void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol); void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol);

View File

@@ -40,6 +40,8 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
int64_t t; int64_t t;
#endif #endif
ilast = rate->ilast;
istart = ibuf; istart = ibuf;
iend = ibuf + *isamp; iend = ibuf + *isamp;
@@ -57,17 +59,15 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
return; return;
} }
/* without input samples, there's nothing to do */ while (obuf < oend) {
/* Safety catch to make sure we have input samples. */
if (ibuf >= iend) { if (ibuf >= iend) {
*osamp = 0; break;
return;
} }
ilast = rate->ilast;
while (true) {
/* read as many input samples so that ipos > opos */ /* read as many input samples so that ipos > opos */
while (rate->ipos <= (rate->opos >> 32)) { while (rate->ipos <= (rate->opos >> 32)) {
ilast = *ibuf++; ilast = *ibuf++;
rate->ipos++; rate->ipos++;
@@ -78,11 +78,6 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
} }
} }
/* make sure that the next output sample can be written */
if (obuf >= oend) {
break;
}
icur = *ibuf; icur = *ibuf;
/* wrap ipos and opos around long before they overflow */ /* wrap ipos and opos around long before they overflow */

View File

@@ -30,6 +30,7 @@
#include "qapi/qapi-visit-authz.h" #include "qapi/qapi-visit-authz.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qapi/qmp/qobject.h" #include "qapi/qmp/qobject.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qobject-input-visitor.h" #include "qapi/qobject-input-visitor.h"

View File

@@ -59,19 +59,6 @@ struct CryptoDevBackendBuiltin {
CryptoDevBackendBuiltinSession *sessions[MAX_NUM_SESSIONS]; CryptoDevBackendBuiltinSession *sessions[MAX_NUM_SESSIONS];
}; };
static void cryptodev_builtin_init_akcipher(CryptoDevBackend *backend)
{
QCryptoAkCipherOptions opts;
opts.alg = QCRYPTO_AKCIPHER_ALG_RSA;
opts.u.rsa.padding_alg = QCRYPTO_RSA_PADDING_ALG_RAW;
if (qcrypto_akcipher_supports(&opts)) {
backend->conf.crypto_services |=
(1u << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER);
backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
}
}
static void cryptodev_builtin_init( static void cryptodev_builtin_init(
CryptoDevBackend *backend, Error **errp) CryptoDevBackend *backend, Error **errp)
{ {
@@ -85,18 +72,21 @@ static void cryptodev_builtin_init(
return; return;
} }
cc = cryptodev_backend_new_client(); cc = cryptodev_backend_new_client(
"cryptodev-builtin", NULL);
cc->info_str = g_strdup_printf("cryptodev-builtin0"); cc->info_str = g_strdup_printf("cryptodev-builtin0");
cc->queue_index = 0; cc->queue_index = 0;
cc->type = QCRYPTODEV_BACKEND_TYPE_BUILTIN; cc->type = CRYPTODEV_BACKEND_TYPE_BUILTIN;
backend->conf.peers.ccs[0] = cc; backend->conf.peers.ccs[0] = cc;
backend->conf.crypto_services = backend->conf.crypto_services =
1u << QCRYPTODEV_BACKEND_SERVICE_CIPHER | 1u << VIRTIO_CRYPTO_SERVICE_CIPHER |
1u << QCRYPTODEV_BACKEND_SERVICE_HASH | 1u << VIRTIO_CRYPTO_SERVICE_HASH |
1u << QCRYPTODEV_BACKEND_SERVICE_MAC; 1u << VIRTIO_CRYPTO_SERVICE_MAC |
1u << VIRTIO_CRYPTO_SERVICE_AKCIPHER;
backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC; backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1; backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
/* /*
* Set the Maximum length of crypto request. * Set the Maximum length of crypto request.
* Why this value? Just avoid to overflow when * Why this value? Just avoid to overflow when
@@ -105,7 +95,6 @@ static void cryptodev_builtin_init(
backend->conf.max_size = LONG_MAX - sizeof(CryptoDevBackendOpInfo); backend->conf.max_size = LONG_MAX - sizeof(CryptoDevBackendOpInfo);
backend->conf.max_cipher_key_len = CRYPTODEV_BUITLIN_MAX_CIPHER_KEY_LEN; backend->conf.max_cipher_key_len = CRYPTODEV_BUITLIN_MAX_CIPHER_KEY_LEN;
backend->conf.max_auth_key_len = CRYPTODEV_BUITLIN_MAX_AUTH_KEY_LEN; backend->conf.max_auth_key_len = CRYPTODEV_BUITLIN_MAX_AUTH_KEY_LEN;
cryptodev_builtin_init_akcipher(backend);
cryptodev_backend_set_ready(backend, true); cryptodev_backend_set_ready(backend, true);
} }
@@ -539,14 +528,17 @@ static int cryptodev_builtin_asym_operation(
static int cryptodev_builtin_operation( static int cryptodev_builtin_operation(
CryptoDevBackend *backend, CryptoDevBackend *backend,
CryptoDevBackendOpInfo *op_info) CryptoDevBackendOpInfo *op_info,
uint32_t queue_index,
CryptoDevCompletionFunc cb,
void *opaque)
{ {
CryptoDevBackendBuiltin *builtin = CryptoDevBackendBuiltin *builtin =
CRYPTODEV_BACKEND_BUILTIN(backend); CRYPTODEV_BACKEND_BUILTIN(backend);
CryptoDevBackendBuiltinSession *sess; CryptoDevBackendBuiltinSession *sess;
CryptoDevBackendSymOpInfo *sym_op_info; CryptoDevBackendSymOpInfo *sym_op_info;
CryptoDevBackendAsymOpInfo *asym_op_info; CryptoDevBackendAsymOpInfo *asym_op_info;
QCryptodevBackendAlgType algtype = op_info->algtype; enum CryptoDevBackendAlgType algtype = op_info->algtype;
int status = -VIRTIO_CRYPTO_ERR; int status = -VIRTIO_CRYPTO_ERR;
Error *local_error = NULL; Error *local_error = NULL;
@@ -558,11 +550,11 @@ static int cryptodev_builtin_operation(
} }
sess = builtin->sessions[op_info->session_id]; sess = builtin->sessions[op_info->session_id];
if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) { if (algtype == CRYPTODEV_BACKEND_ALG_SYM) {
sym_op_info = op_info->u.sym_op_info; sym_op_info = op_info->u.sym_op_info;
status = cryptodev_builtin_sym_operation(sess, sym_op_info, status = cryptodev_builtin_sym_operation(sess, sym_op_info,
&local_error); &local_error);
} else if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) { } else if (algtype == CRYPTODEV_BACKEND_ALG_ASYM) {
asym_op_info = op_info->u.asym_op_info; asym_op_info = op_info->u.asym_op_info;
status = cryptodev_builtin_asym_operation(sess, op_info->op_code, status = cryptodev_builtin_asym_operation(sess, op_info->op_code,
asym_op_info, &local_error); asym_op_info, &local_error);
@@ -571,8 +563,8 @@ static int cryptodev_builtin_operation(
if (local_error) { if (local_error) {
error_report_err(local_error); error_report_err(local_error);
} }
if (op_info->cb) { if (cb) {
op_info->cb(op_info->opaque, status); cb(opaque, status);
} }
return 0; return 0;
} }

View File

@@ -1,54 +0,0 @@
/*
* HMP commands related to cryptodev
*
* Copyright (c) 2023 Bytedance.Inc
*
* Authors:
* zhenwei pi<pizhenwei@bytedance.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version.
*/
#include "qemu/osdep.h"
#include "monitor/hmp.h"
#include "monitor/monitor.h"
#include "qapi/qapi-commands-cryptodev.h"
#include "qapi/qmp/qdict.h"
void hmp_info_cryptodev(Monitor *mon, const QDict *qdict)
{
QCryptodevInfoList *il;
QCryptodevBackendServiceTypeList *sl;
QCryptodevBackendClientList *cl;
for (il = qmp_query_cryptodev(NULL); il; il = il->next) {
g_autofree char *services = NULL;
QCryptodevInfo *info = il->value;
char *tmp_services;
/* build a string like 'service=[akcipher|mac|hash|cipher]' */
for (sl = info->service; sl; sl = sl->next) {
const char *service = QCryptodevBackendServiceType_str(sl->value);
if (!services) {
services = g_strdup(service);
} else {
tmp_services = g_strjoin("|", services, service, NULL);
g_free(services);
services = tmp_services;
}
}
monitor_printf(mon, "%s: service=[%s]\n", info->id, services);
for (cl = info->client; cl; cl = cl->next) {
QCryptodevBackendClient *client = cl->value;
monitor_printf(mon, " queue %" PRIu32 ": type=%s\n",
client->queue,
QCryptodevBackendType_str(client->type));
}
}
qapi_free_QCryptodevInfoList(il);
}

View File

@@ -223,14 +223,14 @@ static void cryptodev_lkcf_init(CryptoDevBackend *backend, Error **errp)
return; return;
} }
cc = cryptodev_backend_new_client(); cc = cryptodev_backend_new_client("cryptodev-lkcf", NULL);
cc->info_str = g_strdup_printf("cryptodev-lkcf0"); cc->info_str = g_strdup_printf("cryptodev-lkcf0");
cc->queue_index = 0; cc->queue_index = 0;
cc->type = QCRYPTODEV_BACKEND_TYPE_LKCF; cc->type = CRYPTODEV_BACKEND_TYPE_LKCF;
backend->conf.peers.ccs[0] = cc; backend->conf.peers.ccs[0] = cc;
backend->conf.crypto_services = backend->conf.crypto_services =
1u << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER; 1u << VIRTIO_CRYPTO_SERVICE_AKCIPHER;
backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA; backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
lkcf->running = true; lkcf->running = true;
@@ -469,12 +469,15 @@ static void *cryptodev_lkcf_worker(void *arg)
static int cryptodev_lkcf_operation( static int cryptodev_lkcf_operation(
CryptoDevBackend *backend, CryptoDevBackend *backend,
CryptoDevBackendOpInfo *op_info) CryptoDevBackendOpInfo *op_info,
uint32_t queue_index,
CryptoDevCompletionFunc cb,
void *opaque)
{ {
CryptoDevBackendLKCF *lkcf = CryptoDevBackendLKCF *lkcf =
CRYPTODEV_BACKEND_LKCF(backend); CRYPTODEV_BACKEND_LKCF(backend);
CryptoDevBackendLKCFSession *sess; CryptoDevBackendLKCFSession *sess;
QCryptodevBackendAlgType algtype = op_info->algtype; enum CryptoDevBackendAlgType algtype = op_info->algtype;
CryptoDevLKCFTask *task; CryptoDevLKCFTask *task;
if (op_info->session_id >= MAX_SESSIONS || if (op_info->session_id >= MAX_SESSIONS ||
@@ -485,15 +488,15 @@ static int cryptodev_lkcf_operation(
} }
sess = lkcf->sess[op_info->session_id]; sess = lkcf->sess[op_info->session_id];
if (algtype != QCRYPTODEV_BACKEND_ALG_ASYM) { if (algtype != CRYPTODEV_BACKEND_ALG_ASYM) {
error_report("algtype not supported: %u", algtype); error_report("algtype not supported: %u", algtype);
return -VIRTIO_CRYPTO_NOTSUPP; return -VIRTIO_CRYPTO_NOTSUPP;
} }
task = g_new0(CryptoDevLKCFTask, 1); task = g_new0(CryptoDevLKCFTask, 1);
task->op_info = op_info; task->op_info = op_info;
task->cb = op_info->cb; task->cb = cb;
task->opaque = op_info->opaque; task->opaque = opaque;
task->sess = sess; task->sess = sess;
task->lkcf = lkcf; task->lkcf = lkcf;
task->status = -VIRTIO_CRYPTO_ERR; task->status = -VIRTIO_CRYPTO_ERR;

View File

@@ -67,7 +67,7 @@ cryptodev_vhost_user_get_vhost(
{ {
CryptoDevBackendVhostUser *s = CryptoDevBackendVhostUser *s =
CRYPTODEV_BACKEND_VHOST_USER(b); CRYPTODEV_BACKEND_VHOST_USER(b);
assert(cc->type == QCRYPTODEV_BACKEND_TYPE_VHOST_USER); assert(cc->type == CRYPTODEV_BACKEND_TYPE_VHOST_USER);
assert(queue < MAX_CRYPTO_QUEUE_NUM); assert(queue < MAX_CRYPTO_QUEUE_NUM);
return s->vhost_crypto[queue]; return s->vhost_crypto[queue];
@@ -198,11 +198,12 @@ static void cryptodev_vhost_user_init(
s->opened = true; s->opened = true;
for (i = 0; i < queues; i++) { for (i = 0; i < queues; i++) {
cc = cryptodev_backend_new_client(); cc = cryptodev_backend_new_client(
"cryptodev-vhost-user", NULL);
cc->info_str = g_strdup_printf("cryptodev-vhost-user%zu to %s ", cc->info_str = g_strdup_printf("cryptodev-vhost-user%zu to %s ",
i, chr->label); i, chr->label);
cc->queue_index = i; cc->queue_index = i;
cc->type = QCRYPTODEV_BACKEND_TYPE_VHOST_USER; cc->type = CRYPTODEV_BACKEND_TYPE_VHOST_USER;
backend->conf.peers.ccs[i] = cc; backend->conf.peers.ccs[i] = cc;
@@ -221,9 +222,9 @@ static void cryptodev_vhost_user_init(
cryptodev_vhost_user_event, NULL, s, NULL, true); cryptodev_vhost_user_event, NULL, s, NULL, true);
backend->conf.crypto_services = backend->conf.crypto_services =
1u << QCRYPTODEV_BACKEND_SERVICE_CIPHER | 1u << VIRTIO_CRYPTO_SERVICE_CIPHER |
1u << QCRYPTODEV_BACKEND_SERVICE_HASH | 1u << VIRTIO_CRYPTO_SERVICE_HASH |
1u << QCRYPTODEV_BACKEND_SERVICE_MAC; 1u << VIRTIO_CRYPTO_SERVICE_MAC;
backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC; backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1; backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;

View File

@@ -28,6 +28,7 @@
#ifdef CONFIG_VHOST_CRYPTO #ifdef CONFIG_VHOST_CRYPTO
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "hw/virtio/virtio-crypto.h" #include "hw/virtio/virtio-crypto.h"
#include "sysemu/cryptodev-vhost-user.h" #include "sysemu/cryptodev-vhost-user.h"
@@ -127,7 +128,7 @@ cryptodev_get_vhost(CryptoDevBackendClient *cc,
switch (cc->type) { switch (cc->type) {
#if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX) #if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX)
case QCRYPTODEV_BACKEND_TYPE_VHOST_USER: case CRYPTODEV_BACKEND_TYPE_VHOST_USER:
vhost_crypto = cryptodev_vhost_user_get_vhost(cc, b, queue); vhost_crypto = cryptodev_vhost_user_get_vhost(cc, b, queue);
break; break;
#endif #endif
@@ -195,7 +196,7 @@ int cryptodev_vhost_start(VirtIODevice *dev, int total_queues)
* because vhost user doesn't interrupt masking/unmasking * because vhost user doesn't interrupt masking/unmasking
* properly. * properly.
*/ */
if (cc->type == QCRYPTODEV_BACKEND_TYPE_VHOST_USER) { if (cc->type == CRYPTODEV_BACKEND_TYPE_VHOST_USER) {
dev->use_guest_notifier_mask = false; dev->use_guest_notifier_mask = false;
} }
} }

View File

@@ -23,92 +23,29 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "sysemu/cryptodev.h" #include "sysemu/cryptodev.h"
#include "sysemu/stats.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qapi-commands-cryptodev.h"
#include "qapi/qapi-types-stats.h"
#include "qapi/visitor.h" #include "qapi/visitor.h"
#include "qemu/config-file.h" #include "qemu/config-file.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/main-loop.h"
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
#include "hw/virtio/virtio-crypto.h" #include "hw/virtio/virtio-crypto.h"
#define SYM_ENCRYPT_OPS_STR "sym-encrypt-ops"
#define SYM_DECRYPT_OPS_STR "sym-decrypt-ops"
#define SYM_ENCRYPT_BYTES_STR "sym-encrypt-bytes"
#define SYM_DECRYPT_BYTES_STR "sym-decrypt-bytes"
#define ASYM_ENCRYPT_OPS_STR "asym-encrypt-ops"
#define ASYM_DECRYPT_OPS_STR "asym-decrypt-ops"
#define ASYM_SIGN_OPS_STR "asym-sign-ops"
#define ASYM_VERIFY_OPS_STR "asym-verify-ops"
#define ASYM_ENCRYPT_BYTES_STR "asym-encrypt-bytes"
#define ASYM_DECRYPT_BYTES_STR "asym-decrypt-bytes"
#define ASYM_SIGN_BYTES_STR "asym-sign-bytes"
#define ASYM_VERIFY_BYTES_STR "asym-verify-bytes"
typedef struct StatsArgs {
union StatsResultsType {
StatsResultList **stats;
StatsSchemaList **schema;
} result;
strList *names;
Error **errp;
} StatsArgs;
static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients; static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients;
static int qmp_query_cryptodev_foreach(Object *obj, void *data)
{
CryptoDevBackend *backend;
QCryptodevInfoList **infolist = data;
uint32_t services, i;
if (!object_dynamic_cast(obj, TYPE_CRYPTODEV_BACKEND)) { CryptoDevBackendClient *
return 0; cryptodev_backend_new_client(const char *model,
} const char *name)
QCryptodevInfo *info = g_new0(QCryptodevInfo, 1);
info->id = g_strdup(object_get_canonical_path_component(obj));
backend = CRYPTODEV_BACKEND(obj);
services = backend->conf.crypto_services;
for (i = 0; i < QCRYPTODEV_BACKEND_SERVICE__MAX; i++) {
if (services & (1 << i)) {
QAPI_LIST_PREPEND(info->service, i);
}
}
for (i = 0; i < backend->conf.peers.queues; i++) {
CryptoDevBackendClient *cc = backend->conf.peers.ccs[i];
QCryptodevBackendClient *client = g_new0(QCryptodevBackendClient, 1);
client->queue = cc->queue_index;
client->type = cc->type;
QAPI_LIST_PREPEND(info->client, client);
}
QAPI_LIST_PREPEND(*infolist, info);
return 0;
}
QCryptodevInfoList *qmp_query_cryptodev(Error **errp)
{
QCryptodevInfoList *list = NULL;
Object *objs = container_get(object_get_root(), "/objects");
object_child_foreach(objs, qmp_query_cryptodev_foreach, &list);
return list;
}
CryptoDevBackendClient *cryptodev_backend_new_client(void)
{ {
CryptoDevBackendClient *cc; CryptoDevBackendClient *cc;
cc = g_new0(CryptoDevBackendClient, 1); cc = g_new0(CryptoDevBackendClient, 1);
cc->model = g_strdup(model);
if (name) {
cc->name = g_strdup(name);
}
QTAILQ_INSERT_TAIL(&crypto_clients, cc, next); QTAILQ_INSERT_TAIL(&crypto_clients, cc, next);
return cc; return cc;
@@ -118,6 +55,8 @@ void cryptodev_backend_free_client(
CryptoDevBackendClient *cc) CryptoDevBackendClient *cc)
{ {
QTAILQ_REMOVE(&crypto_clients, cc, next); QTAILQ_REMOVE(&crypto_clients, cc, next);
g_free(cc->name);
g_free(cc->model);
g_free(cc->info_str); g_free(cc->info_str);
g_free(cc); g_free(cc);
} }
@@ -132,9 +71,6 @@ void cryptodev_backend_cleanup(
if (bc->cleanup) { if (bc->cleanup) {
bc->cleanup(backend, errp); bc->cleanup(backend, errp);
} }
g_free(backend->sym_stat);
g_free(backend->asym_stat);
} }
int cryptodev_backend_create_session( int cryptodev_backend_create_session(
@@ -171,121 +107,38 @@ int cryptodev_backend_close_session(
static int cryptodev_backend_operation( static int cryptodev_backend_operation(
CryptoDevBackend *backend, CryptoDevBackend *backend,
CryptoDevBackendOpInfo *op_info) CryptoDevBackendOpInfo *op_info,
uint32_t queue_index,
CryptoDevCompletionFunc cb,
void *opaque)
{ {
CryptoDevBackendClass *bc = CryptoDevBackendClass *bc =
CRYPTODEV_BACKEND_GET_CLASS(backend); CRYPTODEV_BACKEND_GET_CLASS(backend);
if (bc->do_op) { if (bc->do_op) {
return bc->do_op(backend, op_info); return bc->do_op(backend, op_info, queue_index, cb, opaque);
} }
return -VIRTIO_CRYPTO_NOTSUPP; return -VIRTIO_CRYPTO_NOTSUPP;
} }
static int cryptodev_backend_account(CryptoDevBackend *backend,
CryptoDevBackendOpInfo *op_info)
{
enum QCryptodevBackendAlgType algtype = op_info->algtype;
int len;
if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) {
CryptoDevBackendAsymOpInfo *asym_op_info = op_info->u.asym_op_info;
len = asym_op_info->src_len;
if (unlikely(!backend->asym_stat)) {
error_report("cryptodev: Unexpected asym operation");
return -VIRTIO_CRYPTO_NOTSUPP;
}
switch (op_info->op_code) {
case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT:
CryptodevAsymStatIncEncrypt(backend, len);
break;
case VIRTIO_CRYPTO_AKCIPHER_DECRYPT:
CryptodevAsymStatIncDecrypt(backend, len);
break;
case VIRTIO_CRYPTO_AKCIPHER_SIGN:
CryptodevAsymStatIncSign(backend, len);
break;
case VIRTIO_CRYPTO_AKCIPHER_VERIFY:
CryptodevAsymStatIncVerify(backend, len);
break;
default:
return -VIRTIO_CRYPTO_NOTSUPP;
}
} else if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) {
CryptoDevBackendSymOpInfo *sym_op_info = op_info->u.sym_op_info;
len = sym_op_info->src_len;
if (unlikely(!backend->sym_stat)) {
error_report("cryptodev: Unexpected sym operation");
return -VIRTIO_CRYPTO_NOTSUPP;
}
switch (op_info->op_code) {
case VIRTIO_CRYPTO_CIPHER_ENCRYPT:
CryptodevSymStatIncEncrypt(backend, len);
break;
case VIRTIO_CRYPTO_CIPHER_DECRYPT:
CryptodevSymStatIncDecrypt(backend, len);
break;
default:
return -VIRTIO_CRYPTO_NOTSUPP;
}
} else {
error_report("Unsupported cryptodev alg type: %" PRIu32 "", algtype);
return -VIRTIO_CRYPTO_NOTSUPP;
}
return len;
}
static void cryptodev_backend_throttle_timer_cb(void *opaque)
{
CryptoDevBackend *backend = (CryptoDevBackend *)opaque;
CryptoDevBackendOpInfo *op_info, *tmpop;
int ret;
QTAILQ_FOREACH_SAFE(op_info, &backend->opinfos, next, tmpop) {
QTAILQ_REMOVE(&backend->opinfos, op_info, next);
ret = cryptodev_backend_account(backend, op_info);
if (ret < 0) {
op_info->cb(op_info->opaque, ret);
continue;
}
throttle_account(&backend->ts, true, ret);
cryptodev_backend_operation(backend, op_info);
if (throttle_enabled(&backend->tc) &&
throttle_schedule_timer(&backend->ts, &backend->tt, true)) {
break;
}
}
}
int cryptodev_backend_crypto_operation( int cryptodev_backend_crypto_operation(
CryptoDevBackend *backend, CryptoDevBackend *backend,
CryptoDevBackendOpInfo *op_info) void *opaque1,
uint32_t queue_index,
CryptoDevCompletionFunc cb, void *opaque2)
{ {
int ret; VirtIOCryptoReq *req = opaque1;
CryptoDevBackendOpInfo *op_info = &req->op_info;
enum CryptoDevBackendAlgType algtype = req->flags;
if (!throttle_enabled(&backend->tc)) { if ((algtype != CRYPTODEV_BACKEND_ALG_SYM)
goto do_account; && (algtype != CRYPTODEV_BACKEND_ALG_ASYM)) {
error_report("Unsupported cryptodev alg type: %" PRIu32 "", algtype);
return -VIRTIO_CRYPTO_NOTSUPP;
} }
if (throttle_schedule_timer(&backend->ts, &backend->tt, true) || return cryptodev_backend_operation(backend, op_info, queue_index,
!QTAILQ_EMPTY(&backend->opinfos)) { cb, opaque2);
QTAILQ_INSERT_TAIL(&backend->opinfos, op_info, next);
return 0;
}
do_account:
ret = cryptodev_backend_account(backend, op_info);
if (ret < 0) {
return ret;
}
throttle_account(&backend->ts, true, ret);
return cryptodev_backend_operation(backend, op_info);
} }
static void static void
@@ -316,111 +169,15 @@ cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
backend->conf.peers.queues = value; backend->conf.peers.queues = value;
} }
static void cryptodev_backend_set_throttle(CryptoDevBackend *backend, int field,
uint64_t value, Error **errp)
{
uint64_t orig = backend->tc.buckets[field].avg;
bool enabled = throttle_enabled(&backend->tc);
if (orig == value) {
return;
}
backend->tc.buckets[field].avg = value;
if (!throttle_enabled(&backend->tc)) {
throttle_timers_destroy(&backend->tt);
cryptodev_backend_throttle_timer_cb(backend); /* drain opinfos */
return;
}
if (!throttle_is_valid(&backend->tc, errp)) {
backend->tc.buckets[field].avg = orig; /* revert change */
return;
}
if (!enabled) {
throttle_init(&backend->ts);
throttle_timers_init(&backend->tt, qemu_get_aio_context(),
QEMU_CLOCK_REALTIME,
cryptodev_backend_throttle_timer_cb, /* FIXME */
cryptodev_backend_throttle_timer_cb, backend);
}
throttle_config(&backend->ts, QEMU_CLOCK_REALTIME, &backend->tc);
}
static void cryptodev_backend_get_bps(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
uint64_t value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
visit_type_uint64(v, name, &value, errp);
}
static void cryptodev_backend_set_bps(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
uint64_t value;
if (!visit_type_uint64(v, name, &value, errp)) {
return;
}
cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
}
static void cryptodev_backend_get_ops(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
uint64_t value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
visit_type_uint64(v, name, &value, errp);
}
static void cryptodev_backend_set_ops(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
uint64_t value;
if (!visit_type_uint64(v, name, &value, errp)) {
return;
}
cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
}
static void static void
cryptodev_backend_complete(UserCreatable *uc, Error **errp) cryptodev_backend_complete(UserCreatable *uc, Error **errp)
{ {
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc); CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc); CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
uint32_t services;
uint64_t value;
QTAILQ_INIT(&backend->opinfos);
value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
if (bc->init) { if (bc->init) {
bc->init(backend, errp); bc->init(backend, errp);
} }
services = backend->conf.crypto_services;
if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_CIPHER)) {
backend->sym_stat = g_new0(CryptodevBackendSymStat, 1);
}
if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER)) {
backend->asym_stat = g_new0(CryptodevBackendAsymStat, 1);
}
} }
void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used) void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used)
@@ -451,12 +208,8 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc)
static void cryptodev_backend_instance_init(Object *obj) static void cryptodev_backend_instance_init(Object *obj)
{ {
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
/* Initialize devices' queues property to 1 */ /* Initialize devices' queues property to 1 */
object_property_set_int(obj, "queues", 1, NULL); object_property_set_int(obj, "queues", 1, NULL);
throttle_config_init(&backend->tc);
} }
static void cryptodev_backend_finalize(Object *obj) static void cryptodev_backend_finalize(Object *obj)
@@ -464,137 +217,6 @@ static void cryptodev_backend_finalize(Object *obj)
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
cryptodev_backend_cleanup(backend, NULL); cryptodev_backend_cleanup(backend, NULL);
if (throttle_enabled(&backend->tc)) {
throttle_timers_destroy(&backend->tt);
}
}
static StatsList *cryptodev_backend_stats_add(const char *name, int64_t *val,
StatsList *stats_list)
{
Stats *stats = g_new0(Stats, 1);
stats->name = g_strdup(name);
stats->value = g_new0(StatsValue, 1);
stats->value->type = QTYPE_QNUM;
stats->value->u.scalar = *val;
QAPI_LIST_PREPEND(stats_list, stats);
return stats_list;
}
static int cryptodev_backend_stats_query(Object *obj, void *data)
{
StatsArgs *stats_args = data;
StatsResultList **stats_results = stats_args->result.stats;
StatsList *stats_list = NULL;
StatsResult *entry;
CryptoDevBackend *backend;
CryptodevBackendSymStat *sym_stat;
CryptodevBackendAsymStat *asym_stat;
if (!object_dynamic_cast(obj, TYPE_CRYPTODEV_BACKEND)) {
return 0;
}
backend = CRYPTODEV_BACKEND(obj);
sym_stat = backend->sym_stat;
if (sym_stat) {
stats_list = cryptodev_backend_stats_add(SYM_ENCRYPT_OPS_STR,
&sym_stat->encrypt_ops, stats_list);
stats_list = cryptodev_backend_stats_add(SYM_DECRYPT_OPS_STR,
&sym_stat->decrypt_ops, stats_list);
stats_list = cryptodev_backend_stats_add(SYM_ENCRYPT_BYTES_STR,
&sym_stat->encrypt_bytes, stats_list);
stats_list = cryptodev_backend_stats_add(SYM_DECRYPT_BYTES_STR,
&sym_stat->decrypt_bytes, stats_list);
}
asym_stat = backend->asym_stat;
if (asym_stat) {
stats_list = cryptodev_backend_stats_add(ASYM_ENCRYPT_OPS_STR,
&asym_stat->encrypt_ops, stats_list);
stats_list = cryptodev_backend_stats_add(ASYM_DECRYPT_OPS_STR,
&asym_stat->decrypt_ops, stats_list);
stats_list = cryptodev_backend_stats_add(ASYM_SIGN_OPS_STR,
&asym_stat->sign_ops, stats_list);
stats_list = cryptodev_backend_stats_add(ASYM_VERIFY_OPS_STR,
&asym_stat->verify_ops, stats_list);
stats_list = cryptodev_backend_stats_add(ASYM_ENCRYPT_BYTES_STR,
&asym_stat->encrypt_bytes, stats_list);
stats_list = cryptodev_backend_stats_add(ASYM_DECRYPT_BYTES_STR,
&asym_stat->decrypt_bytes, stats_list);
stats_list = cryptodev_backend_stats_add(ASYM_SIGN_BYTES_STR,
&asym_stat->sign_bytes, stats_list);
stats_list = cryptodev_backend_stats_add(ASYM_VERIFY_BYTES_STR,
&asym_stat->verify_bytes, stats_list);
}
entry = g_new0(StatsResult, 1);
entry->provider = STATS_PROVIDER_CRYPTODEV;
entry->qom_path = g_strdup(object_get_canonical_path(obj));
entry->stats = stats_list;
QAPI_LIST_PREPEND(*stats_results, entry);
return 0;
}
static void cryptodev_backend_stats_cb(StatsResultList **result,
StatsTarget target,
strList *names, strList *targets,
Error **errp)
{
switch (target) {
case STATS_TARGET_CRYPTODEV:
{
Object *objs = container_get(object_get_root(), "/objects");
StatsArgs stats_args;
stats_args.result.stats = result;
stats_args.names = names;
stats_args.errp = errp;
object_child_foreach(objs, cryptodev_backend_stats_query, &stats_args);
break;
}
default:
break;
}
}
static StatsSchemaValueList *cryptodev_backend_schemas_add(const char *name,
StatsSchemaValueList *list)
{
StatsSchemaValueList *schema_entry = g_new0(StatsSchemaValueList, 1);
schema_entry->value = g_new0(StatsSchemaValue, 1);
schema_entry->value->type = STATS_TYPE_CUMULATIVE;
schema_entry->value->name = g_strdup(name);
schema_entry->next = list;
return schema_entry;
}
static void cryptodev_backend_schemas_cb(StatsSchemaList **result,
Error **errp)
{
StatsSchemaValueList *stats_list = NULL;
const char *sym_stats[] = { SYM_ENCRYPT_OPS_STR, SYM_DECRYPT_OPS_STR,
SYM_ENCRYPT_BYTES_STR, SYM_DECRYPT_BYTES_STR };
const char *asym_stats[] = { ASYM_ENCRYPT_OPS_STR, ASYM_DECRYPT_OPS_STR,
ASYM_SIGN_OPS_STR, ASYM_VERIFY_OPS_STR,
ASYM_ENCRYPT_BYTES_STR, ASYM_DECRYPT_BYTES_STR,
ASYM_SIGN_BYTES_STR, ASYM_VERIFY_BYTES_STR };
for (int i = 0; i < ARRAY_SIZE(sym_stats); i++) {
stats_list = cryptodev_backend_schemas_add(sym_stats[i], stats_list);
}
for (int i = 0; i < ARRAY_SIZE(asym_stats); i++) {
stats_list = cryptodev_backend_schemas_add(asym_stats[i], stats_list);
}
add_stats_schema(result, STATS_PROVIDER_CRYPTODEV, STATS_TARGET_CRYPTODEV,
stats_list);
} }
static void static void
@@ -610,17 +232,6 @@ cryptodev_backend_class_init(ObjectClass *oc, void *data)
cryptodev_backend_get_queues, cryptodev_backend_get_queues,
cryptodev_backend_set_queues, cryptodev_backend_set_queues,
NULL, NULL); NULL, NULL);
object_class_property_add(oc, "throttle-bps", "uint64",
cryptodev_backend_get_bps,
cryptodev_backend_set_bps,
NULL, NULL);
object_class_property_add(oc, "throttle-ops", "uint64",
cryptodev_backend_get_ops,
cryptodev_backend_set_ops,
NULL, NULL);
add_stats_callbacks(STATS_PROVIDER_CRYPTODEV, cryptodev_backend_stats_cb,
cryptodev_backend_schemas_cb);
} }
static const TypeInfo cryptodev_backend_info = { static const TypeInfo cryptodev_backend_info = {

View File

@@ -1,6 +1,5 @@
softmmu_ss.add([files( softmmu_ss.add([files(
'cryptodev-builtin.c', 'cryptodev-builtin.c',
'cryptodev-hmp-cmds.c',
'cryptodev.c', 'cryptodev.c',
'hostmem-ram.c', 'hostmem-ram.c',
'hostmem.c', 'hostmem.c',

View File

@@ -13,6 +13,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "sysemu/rng.h" #include "sysemu/rng.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"

View File

@@ -573,13 +573,13 @@ static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
goto err_exit; goto err_exit;
} }
close(fds[1]); closesocket(fds[1]);
return 0; return 0;
err_exit: err_exit:
close(fds[0]); closesocket(fds[0]);
close(fds[1]); closesocket(fds[1]);
return -1; return -1;
} }

View File

@@ -112,8 +112,12 @@ static int tpm_util_request(int fd,
void *response, void *response,
size_t responselen) size_t responselen)
{ {
GPollFD fds[1] = { {.fd = fd, .events = G_IO_IN } }; fd_set readfds;
int n; int n;
struct timeval tv = {
.tv_sec = 1,
.tv_usec = 0,
};
n = write(fd, request, requestlen); n = write(fd, request, requestlen);
if (n < 0) { if (n < 0) {
@@ -123,8 +127,11 @@ static int tpm_util_request(int fd,
return -EFAULT; return -EFAULT;
} }
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
/* wait for a second */ /* wait for a second */
n = RETRY_ON_EINTR(g_poll(fds, 1, 1000)); n = select(fd + 1, &readfds, NULL, NULL, &tv);
if (n != 1) { if (n != 1) {
return -errno; return -errno;
} }

View File

@@ -13,6 +13,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
#include "sysemu/vhost-user-backend.h" #include "sysemu/vhost-user-backend.h"
@@ -20,6 +21,12 @@
#include "io/channel-command.h" #include "io/channel-command.h"
#include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-bus.h"
static bool
ioeventfd_enabled(void)
{
return kvm_enabled() && kvm_eventfds_enabled();
}
int int
vhost_user_backend_dev_init(VhostUserBackend *b, VirtIODevice *vdev, vhost_user_backend_dev_init(VhostUserBackend *b, VirtIODevice *vdev,
unsigned nvqs, Error **errp) unsigned nvqs, Error **errp)
@@ -28,6 +35,11 @@ vhost_user_backend_dev_init(VhostUserBackend *b, VirtIODevice *vdev,
assert(!b->vdev && vdev); assert(!b->vdev && vdev);
if (!ioeventfd_enabled()) {
error_setg(errp, "vhost initialization failed: requires kvm");
return -1;
}
if (!vhost_user_init(&b->vhost_user, &b->chr, errp)) { if (!vhost_user_init(&b->vhost_user, &b->chr, errp)) {
return -1; return -1;
} }

82
block.c
View File

@@ -277,7 +277,7 @@ bool bdrv_is_read_only(BlockDriverState *bs)
return !(bs->open_flags & BDRV_O_RDWR); return !(bs->open_flags & BDRV_O_RDWR);
} }
static int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only, int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
bool ignore_allow_rdw, Error **errp) bool ignore_allow_rdw, Error **errp)
{ {
IO_CODE(); IO_CODE();
@@ -533,7 +533,6 @@ int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
int ret; int ret;
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
ERRP_GUARD(); ERRP_GUARD();
assert_bdrv_graph_readable();
if (!drv->bdrv_co_create_opts) { if (!drv->bdrv_co_create_opts) {
error_setg(errp, "Driver '%s' does not support image creation", error_setg(errp, "Driver '%s' does not support image creation",
@@ -658,7 +657,7 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv,
options = qdict_new(); options = qdict_new();
qdict_put_str(options, "driver", drv->format_name); qdict_put_str(options, "driver", drv->format_name);
blk = blk_co_new_open(filename, NULL, options, blk = blk_new_open(filename, NULL, options,
BDRV_O_RDWR | BDRV_O_RESIZE, errp); BDRV_O_RDWR | BDRV_O_RESIZE, errp);
if (!blk) { if (!blk) {
error_prepend(errp, "Protocol driver '%s' does not support image " error_prepend(errp, "Protocol driver '%s' does not support image "
@@ -680,7 +679,7 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv,
ret = 0; ret = 0;
out: out:
blk_co_unref(blk); blk_unref(blk);
return ret; return ret;
} }
@@ -740,7 +739,6 @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp)
IO_CODE(); IO_CODE();
assert(bs != NULL); assert(bs != NULL);
assert_bdrv_graph_readable();
if (!bs->drv) { if (!bs->drv) {
error_setg(errp, "Block node '%s' is not opened", bs->filename); error_setg(errp, "Block node '%s' is not opened", bs->filename);
@@ -1042,7 +1040,6 @@ int coroutine_fn bdrv_co_refresh_total_sectors(BlockDriverState *bs,
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
if (!drv) { if (!drv) {
return -ENOMEDIUM; return -ENOMEDIUM;
@@ -3810,10 +3807,12 @@ out:
* function eventually calls bdrv_refresh_total_sectors() which polls * function eventually calls bdrv_refresh_total_sectors() which polls
* when called from non-coroutine context. * when called from non-coroutine context.
*/ */
static BlockDriverState * no_coroutine_fn static BlockDriverState *bdrv_open_inherit(const char *filename,
bdrv_open_inherit(const char *filename, const char *reference, QDict *options, const char *reference,
int flags, BlockDriverState *parent, QDict *options, int flags,
const BdrvChildClass *child_class, BdrvChildRole child_role, BlockDriverState *parent,
const BdrvChildClass *child_class,
BdrvChildRole child_role,
Error **errp) Error **errp)
{ {
int ret; int ret;
@@ -3830,7 +3829,6 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
assert(!child_class || !flags); assert(!child_class || !flags);
assert(!child_class == !parent); assert(!child_class == !parent);
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
assert(!qemu_in_coroutine());
if (reference) { if (reference) {
bool options_non_empty = options ? qdict_size(options) : false; bool options_non_empty = options ? qdict_size(options) : false;
@@ -4918,7 +4916,6 @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
qdict_del(bs->options, "backing"); qdict_del(bs->options, "backing");
bdrv_refresh_limits(bs, NULL, NULL); bdrv_refresh_limits(bs, NULL, NULL);
bdrv_refresh_total_sectors(bs, bs->total_sectors);
} }
/* /*
@@ -5269,8 +5266,6 @@ int bdrv_drop_filter(BlockDriverState *bs, Error **errp)
* child. * child.
* *
* This function does not create any image files. * This function does not create any image files.
*
* The caller must hold the AioContext lock for @bs_top.
*/ */
int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
Error **errp) Error **errp)
@@ -5278,14 +5273,11 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
int ret; int ret;
BdrvChild *child; BdrvChild *child;
Transaction *tran = tran_new(); Transaction *tran = tran_new();
AioContext *old_context, *new_context = NULL;
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
assert(!bs_new->backing); assert(!bs_new->backing);
old_context = bdrv_get_aio_context(bs_top);
child = bdrv_attach_child_noperm(bs_new, bs_top, "backing", child = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
&child_of_bds, bdrv_backing_role(bs_new), &child_of_bds, bdrv_backing_role(bs_new),
tran, errp); tran, errp);
@@ -5294,19 +5286,6 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
goto out; goto out;
} }
/*
* bdrv_attach_child_noperm could change the AioContext of bs_top.
* bdrv_replace_node_noperm calls bdrv_drained_begin, so let's temporarily
* hold the new AioContext, since bdrv_drained_begin calls BDRV_POLL_WHILE
* that assumes the new lock is taken.
*/
new_context = bdrv_get_aio_context(bs_top);
if (old_context != new_context) {
aio_context_release(old_context);
aio_context_acquire(new_context);
}
ret = bdrv_replace_node_noperm(bs_top, bs_new, true, tran, errp); ret = bdrv_replace_node_noperm(bs_top, bs_new, true, tran, errp);
if (ret < 0) { if (ret < 0) {
goto out; goto out;
@@ -5318,11 +5297,6 @@ out:
bdrv_refresh_limits(bs_top, NULL, NULL); bdrv_refresh_limits(bs_top, NULL, NULL);
if (new_context && old_context != new_context) {
aio_context_release(new_context);
aio_context_acquire(old_context);
}
return ret; return ret;
} }
@@ -5845,12 +5819,11 @@ int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
if (!drv) if (!drv)
return -ENOMEDIUM; return -ENOMEDIUM;
if (bs->bl.has_variable_length) { if (drv->has_variable_length) {
int ret = bdrv_co_refresh_total_sectors(bs, bs->total_sectors); int ret = bdrv_co_refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
@@ -5859,28 +5832,6 @@ int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
return bs->total_sectors; return bs->total_sectors;
} }
/*
* This wrapper is written by hand because this function is in the hot I/O path,
* via blk_get_geometry.
*/
int64_t coroutine_mixed_fn bdrv_nb_sectors(BlockDriverState *bs)
{
BlockDriver *drv = bs->drv;
IO_CODE();
if (!drv)
return -ENOMEDIUM;
if (bs->bl.has_variable_length) {
int ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) {
return ret;
}
}
return bs->total_sectors;
}
/** /**
* Return length in bytes on success, -errno on error. * Return length in bytes on success, -errno on error.
* The length is always a multiple of BDRV_SECTOR_SIZE. * The length is always a multiple of BDRV_SECTOR_SIZE.
@@ -5889,7 +5840,6 @@ int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs)
{ {
int64_t ret; int64_t ret;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
ret = bdrv_co_nb_sectors(bs); ret = bdrv_co_nb_sectors(bs);
if (ret < 0) { if (ret < 0) {
@@ -5901,6 +5851,15 @@ int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs)
return ret * BDRV_SECTOR_SIZE; return ret * BDRV_SECTOR_SIZE;
} }
/* return 0 as number of sectors if no device present or error */
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
{
int64_t nb_sectors = bdrv_nb_sectors(bs);
IO_CODE();
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
}
bool bdrv_is_sg(BlockDriverState *bs) bool bdrv_is_sg(BlockDriverState *bs)
{ {
IO_CODE(); IO_CODE();
@@ -6844,7 +6803,6 @@ bool coroutine_fn bdrv_co_is_inserted(BlockDriverState *bs)
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
BdrvChild *child; BdrvChild *child;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
if (!drv) { if (!drv) {
return false; return false;
@@ -6867,7 +6825,6 @@ void coroutine_fn bdrv_co_eject(BlockDriverState *bs, bool eject_flag)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
if (drv && drv->bdrv_co_eject) { if (drv && drv->bdrv_co_eject) {
drv->bdrv_co_eject(bs, eject_flag); drv->bdrv_co_eject(bs, eject_flag);
@@ -6882,7 +6839,6 @@ void coroutine_fn bdrv_co_lock_medium(BlockDriverState *bs, bool locked)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
trace_bdrv_lock_medium(bs, locked); trace_bdrv_lock_medium(bs, locked);
if (drv && drv->bdrv_co_lock_medium) { if (drv && drv->bdrv_co_lock_medium) {

View File

@@ -22,6 +22,7 @@
#include "block/block-copy.h" #include "block/block-copy.h"
#include "block/dirty-bitmap.h" #include "block/dirty-bitmap.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
#include "qemu/bitmap.h" #include "qemu/bitmap.h"
@@ -269,10 +270,7 @@ static int coroutine_fn backup_run(Job *job, Error **errp)
return -ECANCELED; return -ECANCELED;
} }
/* rdlock protects the subsequent call to bdrv_is_allocated() */
bdrv_graph_co_rdlock();
ret = block_copy_reset_unallocated(s->bcs, offset, &count); ret = block_copy_reset_unallocated(s->bcs, offset, &count);
bdrv_graph_co_rdunlock();
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }

View File

@@ -626,7 +626,7 @@ static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
return -error; return -error;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags) QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
@@ -647,7 +647,7 @@ blkdebug_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags) QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
@@ -668,7 +668,7 @@ blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags); return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
} }
static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs) static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
{ {
int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH); int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
@@ -679,8 +679,8 @@ static int GRAPH_RDLOCK coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
return bdrv_co_flush(bs->file->bs); return bdrv_co_flush(bs->file->bs);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs,
blkdebug_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
BdrvRequestFlags flags) BdrvRequestFlags flags)
{ {
uint32_t align = MAX(bs->bl.request_alignment, uint32_t align = MAX(bs->bl.request_alignment,
@@ -712,8 +712,8 @@ blkdebug_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
blkdebug_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) int64_t offset, int64_t bytes)
{ {
uint32_t align = bs->bl.pdiscard_alignment; uint32_t align = bs->bl.pdiscard_alignment;
int err; int err;
@@ -967,8 +967,7 @@ static bool blkdebug_debug_is_suspended(BlockDriverState *bs, const char *tag)
return false; return false;
} }
static int64_t coroutine_fn GRAPH_RDLOCK static int64_t coroutine_fn blkdebug_co_getlength(BlockDriverState *bs)
blkdebug_co_getlength(BlockDriverState *bs)
{ {
return bdrv_co_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }

View File

@@ -267,8 +267,7 @@ static void blk_log_writes_close(BlockDriverState *bs)
s->log_file = NULL; s->log_file = NULL;
} }
static int64_t coroutine_fn GRAPH_RDLOCK static int64_t coroutine_fn blk_log_writes_co_getlength(BlockDriverState *bs)
blk_log_writes_co_getlength(BlockDriverState *bs)
{ {
return bdrv_co_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
@@ -295,7 +294,7 @@ static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp)
bs->bl.request_alignment = s->sectorsize; bs->bl.request_alignment = s->sectorsize;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blk_log_writes_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, blk_log_writes_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags) QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
@@ -308,7 +307,7 @@ typedef struct BlkLogWritesFileReq {
uint64_t bytes; uint64_t bytes;
int file_flags; int file_flags;
QEMUIOVector *qiov; QEMUIOVector *qiov;
int GRAPH_RDLOCK_PTR (*func)(struct BlkLogWritesFileReq *r); int (*func)(struct BlkLogWritesFileReq *r);
int file_ret; int file_ret;
} BlkLogWritesFileReq; } BlkLogWritesFileReq;
@@ -320,8 +319,7 @@ typedef struct {
int log_ret; int log_ret;
} BlkLogWritesLogReq; } BlkLogWritesLogReq;
static void coroutine_fn GRAPH_RDLOCK static void coroutine_fn blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
{ {
BDRVBlkLogWritesState *s = lr->bs->opaque; BDRVBlkLogWritesState *s = lr->bs->opaque;
uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits; uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits;
@@ -370,16 +368,15 @@ blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
} }
} }
static void coroutine_fn GRAPH_RDLOCK static void coroutine_fn blk_log_writes_co_do_file(BlkLogWritesFileReq *fr)
blk_log_writes_co_do_file(BlkLogWritesFileReq *fr)
{ {
fr->file_ret = fr->func(fr); fr->file_ret = fr->func(fr);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes, blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
QEMUIOVector *qiov, int flags, QEMUIOVector *qiov, int flags,
int /*GRAPH_RDLOCK*/ (*file_func)(BlkLogWritesFileReq *r), int (*file_func)(BlkLogWritesFileReq *r),
uint64_t entry_flags, bool is_zero_write) uint64_t entry_flags, bool is_zero_write)
{ {
QEMUIOVector log_qiov; QEMUIOVector log_qiov;
@@ -431,33 +428,32 @@ blk_log_writes_co_log(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
return fr.file_ret; return fr.file_ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr) blk_log_writes_co_do_file_pwritev(BlkLogWritesFileReq *fr)
{ {
return bdrv_co_pwritev(fr->bs->file, fr->offset, fr->bytes, return bdrv_co_pwritev(fr->bs->file, fr->offset, fr->bytes,
fr->qiov, fr->file_flags); fr->qiov, fr->file_flags);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr) blk_log_writes_co_do_file_pwrite_zeroes(BlkLogWritesFileReq *fr)
{ {
return bdrv_co_pwrite_zeroes(fr->bs->file, fr->offset, fr->bytes, return bdrv_co_pwrite_zeroes(fr->bs->file, fr->offset, fr->bytes,
fr->file_flags); fr->file_flags);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
blk_log_writes_co_do_file_flush(BlkLogWritesFileReq *fr)
{ {
return bdrv_co_flush(fr->bs->file->bs); return bdrv_co_flush(fr->bs->file->bs);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr) blk_log_writes_co_do_file_pdiscard(BlkLogWritesFileReq *fr)
{ {
return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes); return bdrv_co_pdiscard(fr->bs->file, fr->offset, fr->bytes);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags) QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
@@ -465,7 +461,7 @@ blk_log_writes_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
blk_log_writes_co_do_file_pwritev, 0, false); blk_log_writes_co_do_file_pwritev, 0, false);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
int64_t bytes, BdrvRequestFlags flags) int64_t bytes, BdrvRequestFlags flags)
{ {
@@ -474,15 +470,14 @@ blk_log_writes_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
true); true);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
blk_log_writes_co_flush_to_disk(BlockDriverState *bs)
{ {
return blk_log_writes_co_log(bs, 0, 0, NULL, 0, return blk_log_writes_co_log(bs, 0, 0, NULL, 0,
blk_log_writes_co_do_file_flush, blk_log_writes_co_do_file_flush,
LOG_FLUSH_FLAG, false); LOG_FLUSH_FLAG, false);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
{ {
return blk_log_writes_co_log(bs, offset, bytes, NULL, 0, return blk_log_writes_co_log(bs, offset, bytes, NULL, 0,

View File

@@ -40,8 +40,7 @@ fail:
return ret; return ret;
} }
static int64_t coroutine_fn GRAPH_RDLOCK static int64_t coroutine_fn blkreplay_co_getlength(BlockDriverState *bs)
blkreplay_co_getlength(BlockDriverState *bs)
{ {
return bdrv_co_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
@@ -70,9 +69,8 @@ static void block_request_create(uint64_t reqid, BlockDriverState *bs,
replay_block_event(req->bh, reqid); replay_block_event(req->bh, reqid);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn blkreplay_co_preadv(BlockDriverState *bs,
blkreplay_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
uint64_t reqid = blkreplay_next_id(); uint64_t reqid = blkreplay_next_id();
int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); int ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
@@ -82,9 +80,8 @@ blkreplay_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn blkreplay_co_pwritev(BlockDriverState *bs,
blkreplay_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
uint64_t reqid = blkreplay_next_id(); uint64_t reqid = blkreplay_next_id();
int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags); int ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
@@ -94,9 +91,8 @@ blkreplay_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
blkreplay_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes, BdrvRequestFlags flags)
BdrvRequestFlags flags)
{ {
uint64_t reqid = blkreplay_next_id(); uint64_t reqid = blkreplay_next_id();
int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); int ret = bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
@@ -106,8 +102,8 @@ blkreplay_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn blkreplay_co_pdiscard(BlockDriverState *bs,
blkreplay_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) int64_t offset, int64_t bytes)
{ {
uint64_t reqid = blkreplay_next_id(); uint64_t reqid = blkreplay_next_id();
int ret = bdrv_co_pdiscard(bs->file, offset, bytes); int ret = bdrv_co_pdiscard(bs->file, offset, bytes);
@@ -117,7 +113,7 @@ blkreplay_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK blkreplay_co_flush(BlockDriverState *bs) static int coroutine_fn blkreplay_co_flush(BlockDriverState *bs)
{ {
uint64_t reqid = blkreplay_next_id(); uint64_t reqid = blkreplay_next_id();
int ret = bdrv_co_flush(bs->file->bs); int ret = bdrv_co_flush(bs->file->bs);

View File

@@ -155,8 +155,7 @@ static void blkverify_close(BlockDriverState *bs)
s->test_file = NULL; s->test_file = NULL;
} }
static int64_t coroutine_fn GRAPH_RDLOCK static int64_t coroutine_fn blkverify_co_getlength(BlockDriverState *bs)
blkverify_co_getlength(BlockDriverState *bs)
{ {
BDRVBlkverifyState *s = bs->opaque; BDRVBlkverifyState *s = bs->opaque;
@@ -257,7 +256,7 @@ blkverify_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true); return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true);
} }
static int coroutine_fn GRAPH_RDLOCK blkverify_co_flush(BlockDriverState *bs) static int coroutine_fn blkverify_co_flush(BlockDriverState *bs)
{ {
BDRVBlkverifyState *s = bs->opaque; BDRVBlkverifyState *s = bs->opaque;

View File

@@ -1235,8 +1235,8 @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
blk->disable_request_queuing = disable; blk->disable_request_queuing = disable;
} }
static int coroutine_fn GRAPH_RDLOCK static coroutine_fn int blk_check_byte_request(BlockBackend *blk,
blk_check_byte_request(BlockBackend *blk, int64_t offset, int64_t bytes) int64_t offset, int64_t bytes)
{ {
int64_t len; int64_t len;
@@ -1244,7 +1244,7 @@ blk_check_byte_request(BlockBackend *blk, int64_t offset, int64_t bytes)
return -EIO; return -EIO;
} }
if (!blk_co_is_available(blk)) { if (!blk_is_available(blk)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
@@ -1289,7 +1289,6 @@ blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes,
IO_CODE(); IO_CODE();
blk_wait_while_drained(blk); blk_wait_while_drained(blk);
GRAPH_RDLOCK_GUARD();
/* Call blk_bs() only after waiting, the graph may have changed */ /* Call blk_bs() only after waiting, the graph may have changed */
bs = blk_bs(blk); bs = blk_bs(blk);
@@ -1364,7 +1363,6 @@ blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
IO_CODE(); IO_CODE();
blk_wait_while_drained(blk); blk_wait_while_drained(blk);
GRAPH_RDLOCK_GUARD();
/* Call blk_bs() only after waiting, the graph may have changed */ /* Call blk_bs() only after waiting, the graph may have changed */
bs = blk_bs(blk); bs = blk_bs(blk);
@@ -1433,7 +1431,6 @@ int coroutine_fn blk_co_block_status_above(BlockBackend *blk,
BlockDriverState **file) BlockDriverState **file)
{ {
IO_CODE(); IO_CODE();
GRAPH_RDLOCK_GUARD();
return bdrv_co_block_status_above(blk_bs(blk), base, offset, bytes, pnum, return bdrv_co_block_status_above(blk_bs(blk), base, offset, bytes, pnum,
map, file); map, file);
} }
@@ -1444,7 +1441,6 @@ int coroutine_fn blk_co_is_allocated_above(BlockBackend *blk,
int64_t bytes, int64_t *pnum) int64_t bytes, int64_t *pnum)
{ {
IO_CODE(); IO_CODE();
GRAPH_RDLOCK_GUARD();
return bdrv_co_is_allocated_above(blk_bs(blk), base, include_base, offset, return bdrv_co_is_allocated_above(blk_bs(blk), base, include_base, offset,
bytes, pnum); bytes, pnum);
} }
@@ -1606,62 +1602,33 @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
int64_t coroutine_fn blk_co_getlength(BlockBackend *blk) int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
{ {
IO_CODE(); IO_CODE();
GRAPH_RDLOCK_GUARD();
if (!blk_co_is_available(blk)) { if (!blk_is_available(blk)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
return bdrv_co_getlength(blk_bs(blk)); return bdrv_co_getlength(blk_bs(blk));
} }
void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
{
IO_CODE();
if (!blk_bs(blk)) {
*nb_sectors_ptr = 0;
} else {
bdrv_get_geometry(blk_bs(blk), nb_sectors_ptr);
}
}
int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk) int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
{ {
BlockDriverState *bs = blk_bs(blk);
IO_CODE();
GRAPH_RDLOCK_GUARD();
if (!bs) {
return -ENOMEDIUM;
} else {
return bdrv_co_nb_sectors(bs);
}
}
/*
* This wrapper is written by hand because this function is in the hot I/O path,
* via blk_get_geometry.
*/
int64_t coroutine_mixed_fn blk_nb_sectors(BlockBackend *blk)
{
BlockDriverState *bs = blk_bs(blk);
IO_CODE(); IO_CODE();
if (!bs) { if (!blk_is_available(blk)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} else {
return bdrv_nb_sectors(bs);
}
} }
/* return 0 as number of sectors if no device present or error */ return bdrv_co_nb_sectors(blk_bs(blk));
void coroutine_fn blk_co_get_geometry(BlockBackend *blk,
uint64_t *nb_sectors_ptr)
{
int64_t ret = blk_co_nb_sectors(blk);
*nb_sectors_ptr = ret < 0 ? 0 : ret;
}
/*
* This wrapper is written by hand because this function is in the hot I/O path.
*/
void coroutine_mixed_fn blk_get_geometry(BlockBackend *blk,
uint64_t *nb_sectors_ptr)
{
int64_t ret = blk_nb_sectors(blk);
*nb_sectors_ptr = ret < 0 ? 0 : ret;
} }
BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset, BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
@@ -1703,9 +1670,8 @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
IO_CODE(); IO_CODE();
blk_wait_while_drained(blk); blk_wait_while_drained(blk);
GRAPH_RDLOCK_GUARD();
if (!blk_co_is_available(blk)) { if (!blk_is_available(blk)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
@@ -1750,7 +1716,6 @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
IO_CODE(); IO_CODE();
blk_wait_while_drained(blk); blk_wait_while_drained(blk);
GRAPH_RDLOCK_GUARD();
ret = blk_check_byte_request(blk, offset, bytes); ret = blk_check_byte_request(blk, offset, bytes);
if (ret < 0) { if (ret < 0) {
@@ -1794,11 +1759,10 @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
/* To be called between exactly one pair of blk_inc/dec_in_flight() */ /* To be called between exactly one pair of blk_inc/dec_in_flight() */
static int coroutine_fn blk_co_do_flush(BlockBackend *blk) static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
{ {
IO_CODE();
blk_wait_while_drained(blk); blk_wait_while_drained(blk);
GRAPH_RDLOCK_GUARD(); IO_CODE();
if (!blk_co_is_available(blk)) { if (!blk_is_available(blk)) {
return -ENOMEDIUM; return -ENOMEDIUM;
} }
@@ -2018,37 +1982,27 @@ void blk_activate(BlockBackend *blk, Error **errp)
return; return;
} }
/*
* Migration code can call this function in coroutine context, so leave
* coroutine context if necessary.
*/
if (qemu_in_coroutine()) {
bdrv_co_activate(bs, errp);
} else {
bdrv_activate(bs, errp); bdrv_activate(bs, errp);
} }
}
bool coroutine_fn blk_co_is_inserted(BlockBackend *blk) bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
{ {
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
return bs && bdrv_co_is_inserted(bs); return bs && bdrv_co_is_inserted(bs);
} }
bool coroutine_fn blk_co_is_available(BlockBackend *blk) bool blk_is_available(BlockBackend *blk)
{ {
IO_CODE(); IO_CODE();
return blk_co_is_inserted(blk) && !blk_dev_is_tray_open(blk); return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
} }
void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked) void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
{ {
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
IO_CODE(); IO_CODE();
GRAPH_RDLOCK_GUARD();
if (bs) { if (bs) {
bdrv_co_lock_medium(bs, locked); bdrv_co_lock_medium(bs, locked);
@@ -2060,7 +2014,6 @@ void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag)
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
char *id; char *id;
IO_CODE(); IO_CODE();
GRAPH_RDLOCK_GUARD();
if (bs) { if (bs) {
bdrv_co_eject(bs, eject_flag); bdrv_co_eject(bs, eject_flag);
@@ -2368,7 +2321,6 @@ void coroutine_fn blk_co_io_plug(BlockBackend *blk)
{ {
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
IO_CODE(); IO_CODE();
GRAPH_RDLOCK_GUARD();
if (bs) { if (bs) {
bdrv_co_io_plug(bs); bdrv_co_io_plug(bs);
@@ -2379,7 +2331,6 @@ void coroutine_fn blk_co_io_unplug(BlockBackend *blk)
{ {
BlockDriverState *bs = blk_bs(blk); BlockDriverState *bs = blk_bs(blk);
IO_CODE(); IO_CODE();
GRAPH_RDLOCK_GUARD();
if (bs) { if (bs) {
bdrv_co_io_unplug(bs); bdrv_co_io_unplug(bs);
@@ -2421,8 +2372,7 @@ int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
Error **errp) Error **errp)
{ {
IO_OR_GS_CODE(); IO_OR_GS_CODE();
GRAPH_RDLOCK_GUARD(); if (!blk_is_available(blk)) {
if (!blk_co_is_available(blk)) {
error_setg(errp, "No medium inserted"); error_setg(errp, "No medium inserted");
return -ENOMEDIUM; return -ENOMEDIUM;
} }
@@ -2677,7 +2627,6 @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
{ {
int r; int r;
IO_CODE(); IO_CODE();
GRAPH_RDLOCK_GUARD();
r = blk_check_byte_request(blk_in, off_in, bytes); r = blk_check_byte_request(blk_in, off_in, bytes);
if (r) { if (r) {
@@ -2687,7 +2636,6 @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
if (r) { if (r) {
return r; return r;
} }
return bdrv_co_copy_range(blk_in->root, off_in, return bdrv_co_copy_range(blk_in->root, off_in,
blk_out->root, off_out, blk_out->root, off_out,
bytes, read_flags, write_flags); bytes, read_flags, write_flags);

View File

@@ -469,9 +469,10 @@ static coroutine_fn int block_copy_task_run(AioTaskPool *pool,
* value of @method should be used for subsequent tasks. * value of @method should be used for subsequent tasks.
* Returns 0 on success. * Returns 0 on success.
*/ */
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
block_copy_do_copy(BlockCopyState *s, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
BlockCopyMethod *method, bool *error_is_read) BlockCopyMethod *method,
bool *error_is_read)
{ {
int ret; int ret;
int64_t nbytes = MIN(offset + bytes, s->len) - offset; int64_t nbytes = MIN(offset + bytes, s->len) - offset;
@@ -557,10 +558,8 @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
BlockCopyMethod method = t->method; BlockCopyMethod method = t->method;
int ret; int ret;
WITH_GRAPH_RDLOCK_GUARD() {
ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method, ret = block_copy_do_copy(s, t->req.offset, t->req.bytes, &method,
&error_is_read); &error_is_read);
}
WITH_QEMU_LOCK_GUARD(&s->lock) { WITH_QEMU_LOCK_GUARD(&s->lock) {
if (s->method == t->method) { if (s->method == t->method) {
@@ -582,9 +581,9 @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
return ret; return ret;
} }
static coroutine_fn GRAPH_RDLOCK static coroutine_fn int block_copy_block_status(BlockCopyState *s,
int block_copy_block_status(BlockCopyState *s, int64_t offset, int64_t bytes, int64_t offset,
int64_t *pnum) int64_t bytes, int64_t *pnum)
{ {
int64_t num; int64_t num;
BlockDriverState *base; BlockDriverState *base;
@@ -619,8 +618,8 @@ int block_copy_block_status(BlockCopyState *s, int64_t offset, int64_t bytes,
* Check if the cluster starting at offset is allocated or not. * Check if the cluster starting at offset is allocated or not.
* return via pnum the number of contiguous clusters sharing this allocation. * return via pnum the number of contiguous clusters sharing this allocation.
*/ */
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn block_copy_is_cluster_allocated(BlockCopyState *s,
block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset, int64_t offset,
int64_t *pnum) int64_t *pnum)
{ {
BlockDriverState *bs = s->source->bs; BlockDriverState *bs = s->source->bs;
@@ -631,7 +630,6 @@ block_copy_is_cluster_allocated(BlockCopyState *s, int64_t offset,
assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
while (true) { while (true) {
/* protected in backup_run() */
ret = bdrv_co_is_allocated(bs, offset, bytes, &count); ret = bdrv_co_is_allocated(bs, offset, bytes, &count);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
@@ -706,7 +704,7 @@ int64_t coroutine_fn block_copy_reset_unallocated(BlockCopyState *s,
* Returns 1 if dirty clusters found and successfully copied, 0 if no dirty * Returns 1 if dirty clusters found and successfully copied, 0 if no dirty
* clusters found and -errno on failure. * clusters found and -errno on failure.
*/ */
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
block_copy_dirty_clusters(BlockCopyCallState *call_state) block_copy_dirty_clusters(BlockCopyCallState *call_state)
{ {
BlockCopyState *s = call_state->s; BlockCopyState *s = call_state->s;
@@ -829,8 +827,7 @@ void block_copy_kick(BlockCopyCallState *call_state)
* it means that some I/O operation failed in context of _this_ block_copy call, * it means that some I/O operation failed in context of _this_ block_copy call,
* not some parallel operation. * not some parallel operation.
*/ */
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn block_copy_common(BlockCopyCallState *call_state)
block_copy_common(BlockCopyCallState *call_state)
{ {
int ret; int ret;
BlockCopyState *s = call_state->s; BlockCopyState *s = call_state->s;
@@ -895,7 +892,6 @@ block_copy_common(BlockCopyCallState *call_state)
static void coroutine_fn block_copy_async_co_entry(void *opaque) static void coroutine_fn block_copy_async_co_entry(void *opaque)
{ {
GRAPH_RDLOCK_GUARD();
block_copy_common(opaque); block_copy_common(opaque);
} }

View File

@@ -237,7 +237,7 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset)); return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
bochs_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, bochs_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags) QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {

View File

@@ -18,6 +18,7 @@
#include "block/block_int.h" #include "block/block_int.h"
#include "block/blockjob_int.h" #include "block/blockjob_int.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qemu/ratelimit.h" #include "qemu/ratelimit.h"
#include "qemu/memalign.h" #include "qemu/memalign.h"
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
@@ -206,9 +207,8 @@ static const BlockJobDriver commit_job_driver = {
}, },
}; };
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
bdrv_commit_top_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags); return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
} }

View File

@@ -78,8 +78,8 @@ typedef struct BDRVCopyBeforeWriteState {
int snapshot_error; int snapshot_error;
} BDRVCopyBeforeWriteState; } BDRVCopyBeforeWriteState;
static int coroutine_fn GRAPH_RDLOCK static coroutine_fn int cbw_co_preadv(
cbw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags) QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
@@ -149,8 +149,8 @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
return 0; return 0;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs,
cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) int64_t offset, int64_t bytes)
{ {
int ret = cbw_do_copy_before_write(bs, offset, bytes, 0); int ret = cbw_do_copy_before_write(bs, offset, bytes, 0);
if (ret < 0) { if (ret < 0) {
@@ -160,9 +160,8 @@ cbw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
return bdrv_co_pdiscard(bs->file, offset, bytes); return bdrv_co_pdiscard(bs->file, offset, bytes);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes, BdrvRequestFlags flags)
BdrvRequestFlags flags)
{ {
int ret = cbw_do_copy_before_write(bs, offset, bytes, flags); int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
if (ret < 0) { if (ret < 0) {
@@ -172,9 +171,11 @@ cbw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
} }
static coroutine_fn GRAPH_RDLOCK static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
int cbw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset,
QEMUIOVector *qiov, BdrvRequestFlags flags) int64_t bytes,
QEMUIOVector *qiov,
BdrvRequestFlags flags)
{ {
int ret = cbw_do_copy_before_write(bs, offset, bytes, flags); int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
if (ret < 0) { if (ret < 0) {
@@ -184,7 +185,7 @@ int cbw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags); return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
} }
static int coroutine_fn GRAPH_RDLOCK cbw_co_flush(BlockDriverState *bs) static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
{ {
if (!bs->file) { if (!bs->file) {
return 0; return 0;
@@ -256,7 +257,7 @@ cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req)
g_free(req); g_free(req);
} }
static int coroutine_fn GRAPH_RDLOCK static coroutine_fn int
cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes, cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, size_t qiov_offset) QEMUIOVector *qiov, size_t qiov_offset)
{ {
@@ -288,7 +289,7 @@ cbw_co_preadv_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes,
return 0; return 0;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
cbw_co_snapshot_block_status(BlockDriverState *bs, cbw_co_snapshot_block_status(BlockDriverState *bs,
bool want_zero, int64_t offset, int64_t bytes, bool want_zero, int64_t offset, int64_t bytes,
int64_t *pnum, int64_t *map, int64_t *pnum, int64_t *map,
@@ -321,8 +322,8 @@ cbw_co_snapshot_block_status(BlockDriverState *bs,
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn cbw_co_pdiscard_snapshot(BlockDriverState *bs,
cbw_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes) int64_t offset, int64_t bytes)
{ {
BDRVCopyBeforeWriteState *s = bs->opaque; BDRVCopyBeforeWriteState *s = bs->opaque;

View File

@@ -121,15 +121,16 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
} }
static int64_t coroutine_fn GRAPH_RDLOCK cor_co_getlength(BlockDriverState *bs) static int64_t coroutine_fn cor_co_getlength(BlockDriverState *bs)
{ {
return bdrv_co_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn cor_co_preadv_part(BlockDriverState *bs,
cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, size_t qiov_offset, QEMUIOVector *qiov,
size_t qiov_offset,
BdrvRequestFlags flags) BdrvRequestFlags flags)
{ {
int64_t n; int64_t n;
@@ -179,9 +180,11 @@ cor_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn cor_co_pwritev_part(BlockDriverState *bs,
cor_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset,
QEMUIOVector *qiov, size_t qiov_offset, int64_t bytes,
QEMUIOVector *qiov,
size_t qiov_offset,
BdrvRequestFlags flags) BdrvRequestFlags flags)
{ {
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset, return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
@@ -189,23 +192,24 @@ cor_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
cor_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
BdrvRequestFlags flags) BdrvRequestFlags flags)
{ {
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs,
cor_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) int64_t offset, int64_t bytes)
{ {
return bdrv_co_pdiscard(bs->file, offset, bytes); return bdrv_co_pdiscard(bs->file, offset, bytes);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn cor_co_pwritev_compressed(BlockDriverState *bs,
cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset,
int64_t bytes,
QEMUIOVector *qiov) QEMUIOVector *qiov)
{ {
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, return bdrv_co_pwritev(bs->file, offset, bytes, qiov,
@@ -213,15 +217,13 @@ cor_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
} }
static void coroutine_fn GRAPH_RDLOCK static void coroutine_fn cor_co_eject(BlockDriverState *bs, bool eject_flag)
cor_co_eject(BlockDriverState *bs, bool eject_flag)
{ {
bdrv_co_eject(bs->file->bs, eject_flag); bdrv_co_eject(bs->file->bs, eject_flag);
} }
static void coroutine_fn GRAPH_RDLOCK static void coroutine_fn cor_co_lock_medium(BlockDriverState *bs, bool locked)
cor_co_lock_medium(BlockDriverState *bs, bool locked)
{ {
bdrv_co_lock_medium(bs->file->bs, locked); bdrv_co_lock_medium(bs->file->bs, locked);
} }
@@ -259,6 +261,7 @@ static BlockDriver bdrv_copy_on_read = {
.bdrv_co_eject = cor_co_eject, .bdrv_co_eject = cor_co_eject,
.bdrv_co_lock_medium = cor_co_lock_medium, .bdrv_co_lock_medium = cor_co_lock_medium,
.has_variable_length = true,
.is_filter = true, .is_filter = true,
}; };

View File

@@ -43,7 +43,7 @@ bdrv_co_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix);
int coroutine_fn GRAPH_RDLOCK int coroutine_fn GRAPH_RDLOCK
bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp); bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp);
int coroutine_fn GRAPH_RDLOCK int coroutine_fn
bdrv_co_common_block_status_above(BlockDriverState *bs, bdrv_co_common_block_status_above(BlockDriverState *bs,
BlockDriverState *base, BlockDriverState *base,
bool include_base, bool include_base,

View File

@@ -43,7 +43,6 @@ static int coroutine_fn blockdev_create_run(Job *job, Error **errp)
int ret; int ret;
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD();
job_progress_set_remaining(&s->common, 1); job_progress_set_remaining(&s->common, 1);
ret = s->drv->bdrv_co_create(s->opts, errp); ret = s->drv->bdrv_co_create(s->opts, errp);
@@ -60,12 +59,6 @@ static const JobDriver blockdev_create_job_driver = {
.run = blockdev_create_run, .run = blockdev_create_run,
}; };
/* Checking whether the function is present doesn't require the graph lock */
static inline bool TSA_NO_TSA has_bdrv_co_create(BlockDriver *drv)
{
return drv->bdrv_co_create;
}
void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options, void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
Error **errp) Error **errp)
{ {
@@ -86,7 +79,7 @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
} }
/* Error out if the driver doesn't support .bdrv_co_create */ /* Error out if the driver doesn't support .bdrv_co_create */
if (!has_bdrv_co_create(drv)) { if (!drv->bdrv_co_create) {
error_setg(errp, "Driver does not support blockdev-create"); error_setg(errp, "Driver does not support blockdev-create");
return; return;
} }

View File

@@ -314,17 +314,18 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
} }
static int coroutine_fn static int block_crypto_co_create_generic(BlockDriverState *bs,
block_crypto_co_create_generic(BlockDriverState *bs, int64_t size, int64_t size,
QCryptoBlockCreateOptions *opts, QCryptoBlockCreateOptions *opts,
PreallocMode prealloc, Error **errp) PreallocMode prealloc,
Error **errp)
{ {
int ret; int ret;
BlockBackend *blk; BlockBackend *blk;
QCryptoBlock *crypto = NULL; QCryptoBlock *crypto = NULL;
struct BlockCryptoCreateData data; struct BlockCryptoCreateData data;
blk = blk_co_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL, blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp); errp);
if (!blk) { if (!blk) {
ret = -EPERM; ret = -EPERM;
@@ -355,11 +356,11 @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
ret = 0; ret = 0;
cleanup: cleanup:
qcrypto_block_free(crypto); qcrypto_block_free(crypto);
blk_co_unref(blk); blk_unref(blk);
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact, block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
PreallocMode prealloc, BdrvRequestFlags flags, PreallocMode prealloc, BdrvRequestFlags flags,
Error **errp) Error **errp)
@@ -397,7 +398,7 @@ static int block_crypto_reopen_prepare(BDRVReopenState *state,
*/ */
#define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024) #define BLOCK_CRYPTO_MAX_IO_SIZE (1024 * 1024)
static int coroutine_fn GRAPH_RDLOCK static coroutine_fn int
block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags) QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
@@ -459,7 +460,7 @@ block_crypto_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
} }
static int coroutine_fn GRAPH_RDLOCK static coroutine_fn int
block_crypto_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, block_crypto_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, BdrvRequestFlags flags) QEMUIOVector *qiov, BdrvRequestFlags flags)
{ {
@@ -530,8 +531,7 @@ static void block_crypto_refresh_limits(BlockDriverState *bs, Error **errp)
} }
static int64_t coroutine_fn GRAPH_RDLOCK static int64_t coroutine_fn block_crypto_co_getlength(BlockDriverState *bs)
block_crypto_co_getlength(BlockDriverState *bs)
{ {
BlockCrypto *crypto = bs->opaque; BlockCrypto *crypto = bs->opaque;
int64_t len = bdrv_co_getlength(bs->file->bs); int64_t len = bdrv_co_getlength(bs->file->bs);
@@ -639,7 +639,7 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
assert(create_options->driver == BLOCKDEV_DRIVER_LUKS); assert(create_options->driver == BLOCKDEV_DRIVER_LUKS);
luks_opts = &create_options->u.luks; luks_opts = &create_options->u.luks;
bs = bdrv_co_open_blockdev_ref(luks_opts->file, errp); bs = bdrv_open_blockdev_ref(luks_opts->file, errp);
if (bs == NULL) { if (bs == NULL) {
return -EIO; return -EIO;
} }
@@ -661,13 +661,14 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
ret = 0; ret = 0;
fail: fail:
bdrv_co_unref(bs); bdrv_unref(bs);
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn block_crypto_co_create_opts_luks(BlockDriver *drv,
block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename, const char *filename,
QemuOpts *opts, Error **errp) QemuOpts *opts,
Error **errp)
{ {
QCryptoBlockCreateOptions *create_opts = NULL; QCryptoBlockCreateOptions *create_opts = NULL;
BlockDriverState *bs = NULL; BlockDriverState *bs = NULL;
@@ -707,7 +708,7 @@ block_crypto_co_create_opts_luks(BlockDriver *drv, const char *filename,
goto fail; goto fail;
} }
bs = bdrv_co_open(filename, NULL, NULL, bs = bdrv_open(filename, NULL, NULL,
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp); BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
if (!bs) { if (!bs) {
ret = -EINVAL; ret = -EINVAL;
@@ -730,7 +731,7 @@ fail:
bdrv_co_delete_file_noerr(bs); bdrv_co_delete_file_noerr(bs);
} }
bdrv_co_unref(bs); bdrv_unref(bs);
qapi_free_QCryptoBlockCreateOptions(create_opts); qapi_free_QCryptoBlockCreateOptions(create_opts);
qobject_unref(cryptoopts); qobject_unref(cryptoopts);
return ret; return ret;

View File

@@ -38,15 +38,8 @@
// #define DEBUG_VERBOSE // #define DEBUG_VERBOSE
/* CURL 7.85.0 switches to a string based API for specifying
* the desired protocols.
*/
#if LIBCURL_VERSION_NUM >= 0x075500
#define PROTOCOLS "HTTP,HTTPS,FTP,FTPS"
#else
#define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \ #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
CURLPROTO_FTP | CURLPROTO_FTPS) CURLPROTO_FTP | CURLPROTO_FTPS)
#endif
#define CURL_NUM_STATES 8 #define CURL_NUM_STATES 8
#define CURL_NUM_ACB 8 #define CURL_NUM_ACB 8
@@ -517,18 +510,9 @@ static int curl_init_state(BDRVCURLState *s, CURLState *state)
* obscure protocols. For example, do not allow POP3/SMTP/IMAP see * obscure protocols. For example, do not allow POP3/SMTP/IMAP see
* CVE-2013-0249. * CVE-2013-0249.
* *
* Restricting protocols is only supported from 7.19.4 upwards. Note: * Restricting protocols is only supported from 7.19.4 upwards.
* version 7.85.0 deprecates CURLOPT_*PROTOCOLS in favour of a string
* based CURLOPT_*PROTOCOLS_STR API.
*/ */
#if LIBCURL_VERSION_NUM >= 0x075500 #if LIBCURL_VERSION_NUM >= 0x071304
if (curl_easy_setopt(state->curl,
CURLOPT_PROTOCOLS_STR, PROTOCOLS) ||
curl_easy_setopt(state->curl,
CURLOPT_REDIR_PROTOCOLS_STR, PROTOCOLS)) {
goto err;
}
#elif LIBCURL_VERSION_NUM >= 0x071304
if (curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS) || if (curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS) ||
curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS)) { curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS)) {
goto err; goto err;
@@ -686,12 +670,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
const char *file; const char *file;
const char *cookie; const char *cookie;
const char *cookie_secret; const char *cookie_secret;
/* CURL >= 7.55.0 uses curl_off_t for content length instead of a double */ double d;
#if LIBCURL_VERSION_NUM >= 0x073700
curl_off_t cl;
#else
double cl;
#endif
const char *secretid; const char *secretid;
const char *protocol_delimiter; const char *protocol_delimiter;
int ret; int ret;
@@ -818,36 +797,27 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
} }
if (curl_easy_perform(state->curl)) if (curl_easy_perform(state->curl))
goto out; goto out;
/* CURL 7.55.0 deprecates CURLINFO_CONTENT_LENGTH_DOWNLOAD in favour of if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
* the *_T version which returns a more sensible type for content length.
*/
#if LIBCURL_VERSION_NUM >= 0x073700
if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl)) {
goto out; goto out;
} }
#else
if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl)) {
goto out;
}
#endif
/* Prior CURL 7.19.4 return value of 0 could mean that the file size is not /* Prior CURL 7.19.4 return value of 0 could mean that the file size is not
* know or the size is zero. From 7.19.4 CURL returns -1 if size is not * know or the size is zero. From 7.19.4 CURL returns -1 if size is not
* known and zero if it is really zero-length file. */ * known and zero if it is really zero-length file. */
#if LIBCURL_VERSION_NUM >= 0x071304 #if LIBCURL_VERSION_NUM >= 0x071304
if (cl < 0) { if (d < 0) {
pstrcpy(state->errmsg, CURL_ERROR_SIZE, pstrcpy(state->errmsg, CURL_ERROR_SIZE,
"Server didn't report file size."); "Server didn't report file size.");
goto out; goto out;
} }
#else #else
if (cl <= 0) { if (d <= 0) {
pstrcpy(state->errmsg, CURL_ERROR_SIZE, pstrcpy(state->errmsg, CURL_ERROR_SIZE,
"Unknown file size or zero-length file."); "Unknown file size or zero-length file.");
goto out; goto out;
} }
#endif #endif
s->len = cl; s->len = d;
if ((!strncasecmp(s->url, "http://", strlen("http://")) if ((!strncasecmp(s->url, "http://", strlen("http://"))
|| !strncasecmp(s->url, "https://", strlen("https://"))) || !strncasecmp(s->url, "https://", strlen("https://")))
@@ -880,10 +850,8 @@ out_noclean:
g_free(s->username); g_free(s->username);
g_free(s->proxyusername); g_free(s->proxyusername);
g_free(s->proxypassword); g_free(s->proxypassword);
if (s->sockets) {
curl_drop_all_sockets(s->sockets); curl_drop_all_sockets(s->sockets);
g_hash_table_destroy(s->sockets); g_hash_table_destroy(s->sockets);
}
qemu_opts_del(opts); qemu_opts_del(opts);
return -EINVAL; return -EINVAL;
} }

View File

@@ -394,7 +394,6 @@ int coroutine_fn
bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name,
Error **errp) Error **errp)
{ {
assert_bdrv_graph_readable();
if (bs->drv && bs->drv->bdrv_co_remove_persistent_dirty_bitmap) { if (bs->drv && bs->drv->bdrv_co_remove_persistent_dirty_bitmap) {
return bs->drv->bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp); return bs->drv->bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp);
} }
@@ -416,7 +415,6 @@ bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
uint32_t granularity, Error **errp) uint32_t granularity, Error **errp)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
assert_bdrv_graph_readable();
if (!drv) { if (!drv) {
error_setg_errno(errp, ENOMEDIUM, error_setg_errno(errp, ENOMEDIUM,

View File

@@ -23,12 +23,7 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "dmg.h" #include "dmg.h"
/* Work around a -Wstrict-prototypes warning in LZFSE headers */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#include <lzfse.h> #include <lzfse.h>
#pragma GCC diagnostic pop
static int dmg_uncompress_lzfse_do(char *next_in, unsigned int avail_in, static int dmg_uncompress_lzfse_do(char *next_in, unsigned int avail_in,
char *next_out, unsigned int avail_out) char *next_out, unsigned int avail_out)

View File

@@ -192,10 +192,7 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
return exp; return exp;
fail: fail:
if (blk) {
blk_set_dev_ops(blk, NULL, NULL);
blk_unref(blk); blk_unref(blk);
}
aio_context_release(ctx); aio_context_release(ctx);
if (exp) { if (exp) {
g_free(exp->id); g_free(exp->id);
@@ -222,7 +219,6 @@ static void blk_exp_delete_bh(void *opaque)
assert(exp->refcount == 0); assert(exp->refcount == 0);
QLIST_REMOVE(exp, next); QLIST_REMOVE(exp, next);
exp->drv->delete(exp); exp->drv->delete(exp);
blk_set_dev_ops(exp->blk, NULL, NULL);
blk_unref(exp->blk); blk_unref(exp->blk);
qapi_event_send_block_export_deleted(exp->id); qapi_event_send_block_export_deleted(exp->id);
g_free(exp->id); g_free(exp->id);

View File

@@ -673,16 +673,7 @@ static void fuse_fallocate(fuse_req_t req, fuse_ino_t inode, int mode,
do { do {
int size = MIN(length, BDRV_REQUEST_MAX_BYTES); int size = MIN(length, BDRV_REQUEST_MAX_BYTES);
ret = blk_pwrite_zeroes(exp->common.blk, offset, size, ret = blk_pdiscard(exp->common.blk, offset, size);
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK);
if (ret == -ENOTSUP) {
/*
* fallocate() specifies to return EOPNOTSUPP for unsupported
* operations
*/
ret = -EOPNOTSUPP;
}
offset += size; offset += size;
length -= size; length -= size;
} while (ret == 0 && length > 0); } while (ret == 0 && length > 0);

View File

@@ -346,6 +346,7 @@ static void vduse_blk_exp_delete(BlockExport *exp)
blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach, blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach,
vblk_exp); vblk_exp);
blk_set_dev_ops(exp->blk, NULL, NULL);
ret = vduse_dev_destroy(vblk_exp->dev); ret = vduse_dev_destroy(vblk_exp->dev);
if (ret != -EBUSY) { if (ret != -EBUSY) {
unlink(vblk_exp->recon_file); unlink(vblk_exp->recon_file);

View File

@@ -22,8 +22,7 @@ struct virtio_blk_inhdr {
unsigned char status; unsigned char status;
}; };
static bool coroutine_fn static bool virtio_blk_sect_range_ok(BlockBackend *blk, uint32_t block_size,
virtio_blk_sect_range_ok(BlockBackend *blk, uint32_t block_size,
uint64_t sector, size_t size) uint64_t sector, size_t size)
{ {
uint64_t nb_sectors; uint64_t nb_sectors;
@@ -42,7 +41,7 @@ virtio_blk_sect_range_ok(BlockBackend *blk, uint32_t block_size,
if ((sector << VIRTIO_BLK_SECTOR_BITS) % block_size) { if ((sector << VIRTIO_BLK_SECTOR_BITS) % block_size) {
return false; return false;
} }
blk_co_get_geometry(blk, &total_sectors); blk_get_geometry(blk, &total_sectors);
if (sector > total_sectors || nb_sectors > total_sectors - sector) { if (sector > total_sectors || nb_sectors > total_sectors - sector) {
return false; return false;
} }

View File

@@ -1738,7 +1738,7 @@ static int handle_aiocb_write_zeroes(void *opaque)
#ifdef CONFIG_FALLOCATE #ifdef CONFIG_FALLOCATE
/* Last resort: we are trying to extend the file with zeroed data. This /* Last resort: we are trying to extend the file with zeroed data. This
* can be done via fallocate(fd, 0) */ * can be done via fallocate(fd, 0) */
len = raw_co_getlength(aiocb->bs); len = bdrv_getlength(aiocb->bs);
if (s->has_fallocate && len >= 0 && aiocb->aio_offset >= len) { if (s->has_fallocate && len >= 0 && aiocb->aio_offset >= len) {
int ret = do_fallocate(s->fd, 0, aiocb->aio_offset, aiocb->aio_nbytes); int ret = do_fallocate(s->fd, 0, aiocb->aio_offset, aiocb->aio_nbytes);
if (ret == 0 || ret != -ENOTSUP) { if (ret == 0 || ret != -ENOTSUP) {
@@ -2607,9 +2607,10 @@ out:
return result; return result;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
raw_co_create_opts(BlockDriver *drv, const char *filename, const char *filename,
QemuOpts *opts, Error **errp) QemuOpts *opts,
Error **errp)
{ {
BlockdevCreateOptions options; BlockdevCreateOptions options;
int64_t total_size = 0; int64_t total_size = 0;
@@ -2919,8 +2920,8 @@ static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp)
} }
#endif /* __linux__ */ #endif /* __linux__ */
static void coroutine_fn GRAPH_RDLOCK static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
raw_co_invalidate_cache(BlockDriverState *bs, Error **errp) Error **errp)
{ {
BDRVRawState *s = bs->opaque; BDRVRawState *s = bs->opaque;
int ret; int ret;
@@ -3271,7 +3272,7 @@ static void raw_abort_perm_update(BlockDriverState *bs)
raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL); raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
} }
static int coroutine_fn GRAPH_RDLOCK raw_co_copy_range_from( static int coroutine_fn raw_co_copy_range_from(
BlockDriverState *bs, BdrvChild *src, int64_t src_offset, BlockDriverState *bs, BdrvChild *src, int64_t src_offset,
BdrvChild *dst, int64_t dst_offset, int64_t bytes, BdrvChild *dst, int64_t dst_offset, int64_t bytes,
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags) BdrvRequestFlags read_flags, BdrvRequestFlags write_flags)
@@ -3280,11 +3281,13 @@ static int coroutine_fn GRAPH_RDLOCK raw_co_copy_range_from(
read_flags, write_flags); read_flags, write_flags);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
raw_co_copy_range_to(BlockDriverState *bs, BdrvChild *src,
BdrvChild *src, int64_t src_offset, int64_t src_offset,
BdrvChild *dst, int64_t dst_offset, BdrvChild *dst,
int64_t bytes, BdrvRequestFlags read_flags, int64_t dst_offset,
int64_t bytes,
BdrvRequestFlags read_flags,
BdrvRequestFlags write_flags) BdrvRequestFlags write_flags)
{ {
RawPosixAIOData acb; RawPosixAIOData acb;
@@ -3743,12 +3746,6 @@ static void cdrom_parse_filename(const char *filename, QDict *options,
{ {
bdrv_parse_filename_strip_prefix(filename, "host_cdrom:", options); bdrv_parse_filename_strip_prefix(filename, "host_cdrom:", options);
} }
static void cdrom_refresh_limits(BlockDriverState *bs, Error **errp)
{
bs->bl.has_variable_length = true;
raw_refresh_limits(bs, errp);
}
#endif #endif
#ifdef __linux__ #ifdef __linux__
@@ -3844,13 +3841,14 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_co_preadv = raw_co_preadv, .bdrv_co_preadv = raw_co_preadv,
.bdrv_co_pwritev = raw_co_pwritev, .bdrv_co_pwritev = raw_co_pwritev,
.bdrv_co_flush_to_disk = raw_co_flush_to_disk, .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
.bdrv_refresh_limits = cdrom_refresh_limits, .bdrv_refresh_limits = raw_refresh_limits,
.bdrv_co_io_plug = raw_co_io_plug, .bdrv_co_io_plug = raw_co_io_plug,
.bdrv_co_io_unplug = raw_co_io_unplug, .bdrv_co_io_unplug = raw_co_io_unplug,
.bdrv_attach_aio_context = raw_aio_attach_aio_context, .bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate, .bdrv_co_truncate = raw_co_truncate,
.bdrv_co_getlength = raw_co_getlength, .bdrv_co_getlength = raw_co_getlength,
.has_variable_length = true,
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size, .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
/* removable device support */ /* removable device support */
@@ -3972,13 +3970,14 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_co_preadv = raw_co_preadv, .bdrv_co_preadv = raw_co_preadv,
.bdrv_co_pwritev = raw_co_pwritev, .bdrv_co_pwritev = raw_co_pwritev,
.bdrv_co_flush_to_disk = raw_co_flush_to_disk, .bdrv_co_flush_to_disk = raw_co_flush_to_disk,
.bdrv_refresh_limits = cdrom_refresh_limits, .bdrv_refresh_limits = raw_refresh_limits,
.bdrv_co_io_plug = raw_co_io_plug, .bdrv_co_io_plug = raw_co_io_plug,
.bdrv_co_io_unplug = raw_co_io_unplug, .bdrv_co_io_unplug = raw_co_io_unplug,
.bdrv_attach_aio_context = raw_aio_attach_aio_context, .bdrv_attach_aio_context = raw_aio_attach_aio_context,
.bdrv_co_truncate = raw_co_truncate, .bdrv_co_truncate = raw_co_truncate,
.bdrv_co_getlength = raw_co_getlength, .bdrv_co_getlength = raw_co_getlength,
.has_variable_length = true,
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size, .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
/* removable device support */ /* removable device support */

View File

@@ -613,9 +613,10 @@ static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
return 0; return 0;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
raw_co_create_opts(BlockDriver *drv, const char *filename, const char *filename,
QemuOpts *opts, Error **errp) QemuOpts *opts,
Error **errp)
{ {
BlockdevCreateOptions options; BlockdevCreateOptions options;
int64_t total_size = 0; int64_t total_size = 0;
@@ -838,7 +839,6 @@ static void hdev_refresh_limits(BlockDriverState *bs, Error **errp)
{ {
/* XXX Does Windows support AIO on less than 512-byte alignment? */ /* XXX Does Windows support AIO on less than 512-byte alignment? */
bs->bl.request_alignment = 512; bs->bl.request_alignment = 512;
bs->bl.has_variable_length = true;
} }
static int hdev_open(BlockDriverState *bs, QDict *options, int flags, static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
@@ -934,6 +934,7 @@ static BlockDriver bdrv_host_device = {
.bdrv_attach_aio_context = raw_attach_aio_context, .bdrv_attach_aio_context = raw_attach_aio_context,
.bdrv_co_getlength = raw_co_getlength, .bdrv_co_getlength = raw_co_getlength,
.has_variable_length = true,
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size, .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
}; };

View File

@@ -55,16 +55,16 @@ static int compress_open(BlockDriverState *bs, QDict *options, int flags,
} }
static int64_t coroutine_fn GRAPH_RDLOCK static int64_t coroutine_fn compress_co_getlength(BlockDriverState *bs)
compress_co_getlength(BlockDriverState *bs)
{ {
return bdrv_co_getlength(bs->file->bs); return bdrv_co_getlength(bs->file->bs);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn compress_co_preadv_part(BlockDriverState *bs,
compress_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, size_t qiov_offset, QEMUIOVector *qiov,
size_t qiov_offset,
BdrvRequestFlags flags) BdrvRequestFlags flags)
{ {
return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset, return bdrv_co_preadv_part(bs->file, offset, bytes, qiov, qiov_offset,
@@ -72,9 +72,11 @@ compress_co_preadv_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn compress_co_pwritev_part(BlockDriverState *bs,
compress_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset,
QEMUIOVector *qiov, size_t qiov_offset, int64_t bytes,
QEMUIOVector *qiov,
size_t qiov_offset,
BdrvRequestFlags flags) BdrvRequestFlags flags)
{ {
return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset, return bdrv_co_pwritev_part(bs->file, offset, bytes, qiov, qiov_offset,
@@ -82,16 +84,16 @@ compress_co_pwritev_part(BlockDriverState *bs, int64_t offset, int64_t bytes,
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn compress_co_pwrite_zeroes(BlockDriverState *bs,
compress_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
BdrvRequestFlags flags) BdrvRequestFlags flags)
{ {
return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn compress_co_pdiscard(BlockDriverState *bs,
compress_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes) int64_t offset, int64_t bytes)
{ {
return bdrv_co_pdiscard(bs->file, offset, bytes); return bdrv_co_pdiscard(bs->file, offset, bytes);
} }
@@ -115,14 +117,14 @@ static void compress_refresh_limits(BlockDriverState *bs, Error **errp)
} }
static void coroutine_fn GRAPH_RDLOCK static void coroutine_fn
compress_co_eject(BlockDriverState *bs, bool eject_flag) compress_co_eject(BlockDriverState *bs, bool eject_flag)
{ {
bdrv_co_eject(bs->file->bs, eject_flag); bdrv_co_eject(bs->file->bs, eject_flag);
} }
static void coroutine_fn GRAPH_RDLOCK static void coroutine_fn
compress_co_lock_medium(BlockDriverState *bs, bool locked) compress_co_lock_medium(BlockDriverState *bs, bool locked)
{ {
bdrv_co_lock_medium(bs->file->bs, locked); bdrv_co_lock_medium(bs->file->bs, locked);
@@ -146,6 +148,7 @@ static BlockDriver bdrv_compress = {
.bdrv_co_eject = compress_co_eject, .bdrv_co_eject = compress_co_eject,
.bdrv_co_lock_medium = compress_co_lock_medium, .bdrv_co_lock_medium = compress_co_lock_medium,
.has_variable_length = true,
.is_filter = true, .is_filter = true,
}; };

View File

@@ -30,10 +30,8 @@ BdrvGraphLock graph_lock;
/* Protects the list of aiocontext and orphaned_reader_count */ /* Protects the list of aiocontext and orphaned_reader_count */
static QemuMutex aio_context_list_lock; static QemuMutex aio_context_list_lock;
#if 0
/* Written and read with atomic operations. */ /* Written and read with atomic operations. */
static int has_writer; static int has_writer;
#endif
/* /*
* A reader coroutine could move from an AioContext to another. * A reader coroutine could move from an AioContext to another.
@@ -90,7 +88,6 @@ void unregister_aiocontext(AioContext *ctx)
g_free(ctx->bdrv_graph); g_free(ctx->bdrv_graph);
} }
#if 0
static uint32_t reader_count(void) static uint32_t reader_count(void)
{ {
BdrvGraphRWlock *brdv_graph; BdrvGraphRWlock *brdv_graph;
@@ -108,17 +105,10 @@ static uint32_t reader_count(void)
assert((int32_t)rd >= 0); assert((int32_t)rd >= 0);
return rd; return rd;
} }
#endif
void bdrv_graph_wrlock(void) void bdrv_graph_wrlock(void)
{ {
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
/*
* TODO Some callers hold an AioContext lock when this is called, which
* causes deadlocks. Reenable once the AioContext locking is cleaned up (or
* AioContext locks are gone).
*/
#if 0
assert(!qatomic_read(&has_writer)); assert(!qatomic_read(&has_writer));
/* Make sure that constantly arriving new I/O doesn't cause starvation */ /* Make sure that constantly arriving new I/O doesn't cause starvation */
@@ -149,13 +139,11 @@ void bdrv_graph_wrlock(void)
} while (reader_count() >= 1); } while (reader_count() >= 1);
bdrv_drain_all_end(); bdrv_drain_all_end();
#endif
} }
void bdrv_graph_wrunlock(void) void bdrv_graph_wrunlock(void)
{ {
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
#if 0
QEMU_LOCK_GUARD(&aio_context_list_lock); QEMU_LOCK_GUARD(&aio_context_list_lock);
assert(qatomic_read(&has_writer)); assert(qatomic_read(&has_writer));
@@ -167,13 +155,10 @@ void bdrv_graph_wrunlock(void)
/* Wake up all coroutine that are waiting to read the graph */ /* Wake up all coroutine that are waiting to read the graph */
qemu_co_enter_all(&reader_queue, &aio_context_list_lock); qemu_co_enter_all(&reader_queue, &aio_context_list_lock);
#endif
} }
void coroutine_fn bdrv_graph_co_rdlock(void) void coroutine_fn bdrv_graph_co_rdlock(void)
{ {
/* TODO Reenable when wrlock is reenabled */
#if 0
BdrvGraphRWlock *bdrv_graph; BdrvGraphRWlock *bdrv_graph;
bdrv_graph = qemu_get_current_aio_context()->bdrv_graph; bdrv_graph = qemu_get_current_aio_context()->bdrv_graph;
@@ -238,12 +223,10 @@ void coroutine_fn bdrv_graph_co_rdlock(void)
qemu_co_queue_wait(&reader_queue, &aio_context_list_lock); qemu_co_queue_wait(&reader_queue, &aio_context_list_lock);
} }
} }
#endif
} }
void coroutine_fn bdrv_graph_co_rdunlock(void) void coroutine_fn bdrv_graph_co_rdunlock(void)
{ {
#if 0
BdrvGraphRWlock *bdrv_graph; BdrvGraphRWlock *bdrv_graph;
bdrv_graph = qemu_get_current_aio_context()->bdrv_graph; bdrv_graph = qemu_get_current_aio_context()->bdrv_graph;
@@ -266,7 +249,6 @@ void coroutine_fn bdrv_graph_co_rdunlock(void)
if (qatomic_read(&has_writer)) { if (qatomic_read(&has_writer)) {
aio_wait_kick(); aio_wait_kick();
} }
#endif
} }
void bdrv_graph_rdlock_main_loop(void) void bdrv_graph_rdlock_main_loop(void)
@@ -283,20 +265,11 @@ void bdrv_graph_rdunlock_main_loop(void)
void assert_bdrv_graph_readable(void) void assert_bdrv_graph_readable(void)
{ {
/* reader_count() is slow due to aio_context_list_lock lock contention */
/* TODO Reenable when wrlock is reenabled */
#if 0
#ifdef CONFIG_DEBUG_GRAPH_LOCK
assert(qemu_in_main_thread() || reader_count()); assert(qemu_in_main_thread() || reader_count());
#endif
#endif
} }
void assert_bdrv_graph_writable(void) void assert_bdrv_graph_writable(void)
{ {
assert(qemu_in_main_thread()); assert(qemu_in_main_thread());
/* TODO Reenable when wrlock is reenabled */
#if 0
assert(qatomic_read(&has_writer)); assert(qatomic_read(&has_writer));
#endif
} }

View File

@@ -160,7 +160,6 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
bool have_limits; bool have_limits;
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
assume_graph_lock(); /* FIXME */
if (tran) { if (tran) {
BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1); BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1);
@@ -190,10 +189,6 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
bdrv_merge_limits(&bs->bl, &c->bs->bl); bdrv_merge_limits(&bs->bl, &c->bs->bl);
have_limits = true; have_limits = true;
} }
if (c->role & BDRV_CHILD_FILTERED) {
bs->bl.has_variable_length |= c->bs->bl.has_variable_length;
}
} }
if (!have_limits) { if (!have_limits) {
@@ -937,7 +932,6 @@ int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
{ {
int ret; int ret;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
ret = bdrv_co_pwrite(child, offset, bytes, buf, flags); ret = bdrv_co_pwrite(child, offset, bytes, buf, flags);
if (ret < 0) { if (ret < 0) {
@@ -965,16 +959,16 @@ static void bdrv_co_io_em_complete(void *opaque, int ret)
aio_co_wake(co->coroutine); aio_co_wake(co->coroutine);
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
bdrv_driver_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, size_t qiov_offset, int flags) QEMUIOVector *qiov,
size_t qiov_offset, int flags)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
int64_t sector_num; int64_t sector_num;
unsigned int nb_sectors; unsigned int nb_sectors;
QEMUIOVector local_qiov; QEMUIOVector local_qiov;
int ret; int ret;
assert_bdrv_graph_readable();
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
assert(!(flags & ~bs->supported_read_flags)); assert(!(flags & ~bs->supported_read_flags));
@@ -1034,9 +1028,10 @@ out:
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
QEMUIOVector *qiov, size_t qiov_offset, QEMUIOVector *qiov,
size_t qiov_offset,
BdrvRequestFlags flags) BdrvRequestFlags flags)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
@@ -1045,7 +1040,6 @@ bdrv_driver_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
unsigned int nb_sectors; unsigned int nb_sectors;
QEMUIOVector local_qiov; QEMUIOVector local_qiov;
int ret; int ret;
assert_bdrv_graph_readable();
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
@@ -1116,7 +1110,7 @@ emulate_flags:
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn
bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset, bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
int64_t bytes, QEMUIOVector *qiov, int64_t bytes, QEMUIOVector *qiov,
size_t qiov_offset) size_t qiov_offset)
@@ -1124,7 +1118,6 @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
QEMUIOVector local_qiov; QEMUIOVector local_qiov;
int ret; int ret;
assert_bdrv_graph_readable();
bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort); bdrv_check_qiov_request(offset, bytes, qiov, qiov_offset, &error_abort);
@@ -1152,9 +1145,9 @@ bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes, QEMUIOVector *qiov,
QEMUIOVector *qiov, size_t qiov_offset, int flags) size_t qiov_offset, int flags)
{ {
BlockDriverState *bs = child->bs; BlockDriverState *bs = child->bs;
@@ -1316,10 +1309,9 @@ err:
* handles copy on read, zeroing after EOF, and fragmentation of large * handles copy on read, zeroing after EOF, and fragmentation of large
* reads; any other features must be implemented by the caller. * reads; any other features must be implemented by the caller.
*/ */
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req, BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
int64_t offset, int64_t bytes, int64_t align, int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
QEMUIOVector *qiov, size_t qiov_offset, int flags)
{ {
BlockDriverState *bs = child->bs; BlockDriverState *bs = child->bs;
int64_t total_bytes, max_bytes; int64_t total_bytes, max_bytes;
@@ -1486,9 +1478,10 @@ static bool bdrv_init_padding(BlockDriverState *bs,
return true; return true;
} }
static int coroutine_fn GRAPH_RDLOCK static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
bdrv_padding_rmw_read(BdrvChild *child, BdrvTrackedRequest *req, BdrvTrackedRequest *req,
BdrvRequestPadding *pad, bool zero_middle) BdrvRequestPadding *pad,
bool zero_middle)
{ {
QEMUIOVector local_qiov; QEMUIOVector local_qiov;
BlockDriverState *bs = child->bs; BlockDriverState *bs = child->bs;
@@ -1676,9 +1669,8 @@ fail:
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, int64_t offset, int64_t bytes, BdrvRequestFlags flags)
BdrvRequestFlags flags)
{ {
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
QEMUIOVector qiov; QEMUIOVector qiov;
@@ -1694,7 +1686,6 @@ bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
bs->bl.request_alignment); bs->bl.request_alignment);
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER); int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, MAX_BOUNCE_BUFFER);
assert_bdrv_graph_readable();
bdrv_check_request(offset, bytes, &error_abort); bdrv_check_request(offset, bytes, &error_abort);
if (!drv) { if (!drv) {
@@ -1898,10 +1889,9 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
* Forwards an already correctly aligned write request to the BlockDriver, * Forwards an already correctly aligned write request to the BlockDriver,
* after possibly fragmenting it. * after possibly fragmenting it.
*/ */
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
bdrv_aligned_pwritev(BdrvChild *child, BdrvTrackedRequest *req, BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
int64_t offset, int64_t bytes, int64_t align, int64_t align, QEMUIOVector *qiov, size_t qiov_offset,
QEMUIOVector *qiov, size_t qiov_offset,
BdrvRequestFlags flags) BdrvRequestFlags flags)
{ {
BlockDriverState *bs = child->bs; BlockDriverState *bs = child->bs;
@@ -1986,9 +1976,11 @@ bdrv_aligned_pwritev(BdrvChild *child, BdrvTrackedRequest *req,
return ret; return ret;
} }
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes, int64_t offset,
BdrvRequestFlags flags, BdrvTrackedRequest *req) int64_t bytes,
BdrvRequestFlags flags,
BdrvTrackedRequest *req)
{ {
BlockDriverState *bs = child->bs; BlockDriverState *bs = child->bs;
QEMUIOVector local_qiov; QEMUIOVector local_qiov;
@@ -2161,7 +2153,6 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
{ {
IO_CODE(); IO_CODE();
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags); trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
assert_bdrv_graph_readable();
if (!(child->bs->open_flags & BDRV_O_UNMAP)) { if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
flags &= ~BDRV_REQ_MAY_UNMAP; flags &= ~BDRV_REQ_MAY_UNMAP;
@@ -2233,10 +2224,11 @@ int bdrv_flush_all(void)
* BDRV_BLOCK_OFFSET_VALID bit is set, 'map' and 'file' (if non-NULL) are * BDRV_BLOCK_OFFSET_VALID bit is set, 'map' and 'file' (if non-NULL) are
* set to the host mapping and BDS corresponding to the guest offset. * set to the host mapping and BDS corresponding to the guest offset.
*/ */
static int coroutine_fn GRAPH_RDLOCK static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
bdrv_co_block_status(BlockDriverState *bs, bool want_zero, bool want_zero,
int64_t offset, int64_t bytes, int64_t offset, int64_t bytes,
int64_t *pnum, int64_t *map, BlockDriverState **file) int64_t *pnum, int64_t *map,
BlockDriverState **file)
{ {
int64_t total_size; int64_t total_size;
int64_t n; /* bytes */ int64_t n; /* bytes */
@@ -2248,7 +2240,6 @@ bdrv_co_block_status(BlockDriverState *bs, bool want_zero,
bool has_filtered_child; bool has_filtered_child;
assert(pnum); assert(pnum);
assert_bdrv_graph_readable();
*pnum = 0; *pnum = 0;
total_size = bdrv_getlength(bs); total_size = bdrv_getlength(bs);
if (total_size < 0) { if (total_size < 0) {
@@ -2479,7 +2470,6 @@ bdrv_co_common_block_status_above(BlockDriverState *bs,
IO_CODE(); IO_CODE();
assert(!include_base || base); /* Can't include NULL base */ assert(!include_base || base); /* Can't include NULL base */
assert_bdrv_graph_readable();
if (!depth) { if (!depth) {
depth = &dummy; depth = &dummy;
@@ -2846,7 +2836,6 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
int ret = 0; int ret = 0;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
bdrv_inc_in_flight(bs); bdrv_inc_in_flight(bs);
if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) || if (!bdrv_co_is_inserted(bs) || bdrv_is_read_only(bs) ||
@@ -2972,7 +2961,6 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
int head, tail, align; int head, tail, align;
BlockDriverState *bs = child->bs; BlockDriverState *bs = child->bs;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) { if (!bs || !bs->drv || !bdrv_co_is_inserted(bs)) {
return -ENOMEDIUM; return -ENOMEDIUM;
@@ -3092,7 +3080,6 @@ int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf)
}; };
BlockAIOCB *acb; BlockAIOCB *acb;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
bdrv_inc_in_flight(bs); bdrv_inc_in_flight(bs);
if (!drv || (!drv->bdrv_aio_ioctl && !drv->bdrv_co_ioctl)) { if (!drv || (!drv->bdrv_aio_ioctl && !drv->bdrv_co_ioctl)) {
@@ -3157,7 +3144,6 @@ void coroutine_fn bdrv_co_io_plug(BlockDriverState *bs)
{ {
BdrvChild *child; BdrvChild *child;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
QLIST_FOREACH(child, &bs->children, next) { QLIST_FOREACH(child, &bs->children, next) {
bdrv_co_io_plug(child->bs); bdrv_co_io_plug(child->bs);
@@ -3175,7 +3161,6 @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
{ {
BdrvChild *child; BdrvChild *child;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
assert(bs->io_plugged); assert(bs->io_plugged);
if (qatomic_fetch_dec(&bs->io_plugged) == 1) { if (qatomic_fetch_dec(&bs->io_plugged) == 1) {
@@ -3191,15 +3176,13 @@ void coroutine_fn bdrv_co_io_unplug(BlockDriverState *bs)
} }
/* Helper that undoes bdrv_register_buf() when it fails partway through */ /* Helper that undoes bdrv_register_buf() when it fails partway through */
static void GRAPH_RDLOCK static void bdrv_register_buf_rollback(BlockDriverState *bs,
bdrv_register_buf_rollback(BlockDriverState *bs, void *host, size_t size, void *host,
size_t size,
BdrvChild *final_child) BdrvChild *final_child)
{ {
BdrvChild *child; BdrvChild *child;
GLOBAL_STATE_CODE();
assert_bdrv_graph_readable();
QLIST_FOREACH(child, &bs->children, next) { QLIST_FOREACH(child, &bs->children, next) {
if (child == final_child) { if (child == final_child) {
break; break;
@@ -3219,8 +3202,6 @@ bool bdrv_register_buf(BlockDriverState *bs, void *host, size_t size,
BdrvChild *child; BdrvChild *child;
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
if (bs->drv && bs->drv->bdrv_register_buf) { if (bs->drv && bs->drv->bdrv_register_buf) {
if (!bs->drv->bdrv_register_buf(bs, host, size, errp)) { if (!bs->drv->bdrv_register_buf(bs, host, size, errp)) {
return false; return false;
@@ -3240,8 +3221,6 @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
BdrvChild *child; BdrvChild *child;
GLOBAL_STATE_CODE(); GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
if (bs->drv && bs->drv->bdrv_unregister_buf) { if (bs->drv && bs->drv->bdrv_unregister_buf) {
bs->drv->bdrv_unregister_buf(bs, host, size); bs->drv->bdrv_unregister_buf(bs, host, size);
} }
@@ -3250,7 +3229,7 @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host, size_t size)
} }
} }
static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal( static int coroutine_fn bdrv_co_copy_range_internal(
BdrvChild *src, int64_t src_offset, BdrvChild *dst, BdrvChild *src, int64_t src_offset, BdrvChild *dst,
int64_t dst_offset, int64_t bytes, int64_t dst_offset, int64_t bytes,
BdrvRequestFlags read_flags, BdrvRequestFlags write_flags, BdrvRequestFlags read_flags, BdrvRequestFlags write_flags,
@@ -3258,7 +3237,6 @@ static int coroutine_fn GRAPH_RDLOCK bdrv_co_copy_range_internal(
{ {
BdrvTrackedRequest req; BdrvTrackedRequest req;
int ret; int ret;
assert_bdrv_graph_readable();
/* TODO We can support BDRV_REQ_NO_FALLBACK here */ /* TODO We can support BDRV_REQ_NO_FALLBACK here */
assert(!(read_flags & BDRV_REQ_NO_FALLBACK)); assert(!(read_flags & BDRV_REQ_NO_FALLBACK));
@@ -3340,7 +3318,6 @@ int coroutine_fn bdrv_co_copy_range_from(BdrvChild *src, int64_t src_offset,
BdrvRequestFlags write_flags) BdrvRequestFlags write_flags)
{ {
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes, trace_bdrv_co_copy_range_from(src, src_offset, dst, dst_offset, bytes,
read_flags, write_flags); read_flags, write_flags);
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset, return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
@@ -3358,7 +3335,6 @@ int coroutine_fn bdrv_co_copy_range_to(BdrvChild *src, int64_t src_offset,
BdrvRequestFlags write_flags) BdrvRequestFlags write_flags)
{ {
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, trace_bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes,
read_flags, write_flags); read_flags, write_flags);
return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset, return bdrv_co_copy_range_internal(src, src_offset, dst, dst_offset,
@@ -3371,8 +3347,6 @@ int coroutine_fn bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
BdrvRequestFlags write_flags) BdrvRequestFlags write_flags)
{ {
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
return bdrv_co_copy_range_from(src, src_offset, return bdrv_co_copy_range_from(src, src_offset,
dst, dst_offset, dst, dst_offset,
bytes, read_flags, write_flags); bytes, read_flags, write_flags);
@@ -3406,7 +3380,6 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
int64_t old_size, new_bytes; int64_t old_size, new_bytes;
int ret; int ret;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
/* if bs->drv == NULL, bs is closed, so there's nothing to do here */ /* if bs->drv == NULL, bs is closed, so there's nothing to do here */
if (!drv) { if (!drv) {
@@ -3544,7 +3517,6 @@ bdrv_co_preadv_snapshot(BdrvChild *child, int64_t offset, int64_t bytes,
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
int ret; int ret;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
if (!drv) { if (!drv) {
return -ENOMEDIUM; return -ENOMEDIUM;
@@ -3570,7 +3542,6 @@ bdrv_co_snapshot_block_status(BlockDriverState *bs,
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
int ret; int ret;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
if (!drv) { if (!drv) {
return -ENOMEDIUM; return -ENOMEDIUM;
@@ -3594,7 +3565,6 @@ bdrv_co_pdiscard_snapshot(BlockDriverState *bs, int64_t offset, int64_t bytes)
BlockDriver *drv = bs->drv; BlockDriver *drv = bs->drv;
int ret; int ret;
IO_CODE(); IO_CODE();
assert_bdrv_graph_readable();
if (!drv) { if (!drv) {
return -ENOMEDIUM; return -ENOMEDIUM;

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