Compare commits
39 Commits
v8.2.6
...
multifd-fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f1a8f4e85 | ||
|
|
47b2c3d4f6 | ||
|
|
086d8dc142 | ||
|
|
4b6eeb2335 | ||
|
|
2cb56cb34e | ||
|
|
5deb383d1a | ||
|
|
4478aef543 | ||
|
|
a8adda79e7 | ||
|
|
cf07faa04a | ||
|
|
b0839f1600 | ||
|
|
db401f5302 | ||
|
|
ed95cd0446 | ||
|
|
d5bce67e17 | ||
|
|
b00e0415ed | ||
|
|
6822813ae9 | ||
|
|
23e7e3fc41 | ||
|
|
a071d2f34e | ||
|
|
ab194ba308 | ||
|
|
9954a41782 | ||
|
|
76798336e4 | ||
|
|
ffd3e56398 | ||
|
|
1c036fa56a | ||
|
|
3eb7f2ab75 | ||
|
|
43ad5422c9 | ||
|
|
909f4a40f6 | ||
|
|
07acf019b1 | ||
|
|
b018f49a5b | ||
|
|
f9c6197b58 | ||
|
|
1b1da54c69 | ||
|
|
d636220e69 | ||
|
|
5e25355c4b | ||
|
|
f978a45734 | ||
|
|
d969e2d0ff | ||
|
|
87dcefce00 | ||
|
|
2b12bbcfed | ||
|
|
fd92544b1a | ||
|
|
19b0f579aa | ||
|
|
ae1ea5b13e | ||
|
|
f6a85fa7a4 |
@@ -25,10 +25,10 @@
|
||||
then
|
||||
pyvenv/bin/meson configure . -Dbackend_max_links="$LD_JOBS" ;
|
||||
fi || exit 1;
|
||||
- $MAKE -j"$JOBS"
|
||||
- make -j"$JOBS"
|
||||
- if test -n "$MAKE_CHECK_ARGS";
|
||||
then
|
||||
$MAKE -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||
make -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||
fi
|
||||
- ccache --show-stats
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
- cd build
|
||||
- find . -type f -exec touch {} +
|
||||
# Avoid recompiling by hiding ninja with NINJA=":"
|
||||
- $MAKE NINJA=":" $MAKE_CHECK_ARGS
|
||||
- make NINJA=":" $MAKE_CHECK_ARGS
|
||||
|
||||
.native_test_job_template:
|
||||
extends: .common_test_job_template
|
||||
|
||||
@@ -41,7 +41,7 @@ build-system-ubuntu:
|
||||
variables:
|
||||
IMAGE: ubuntu2204
|
||||
CONFIGURE_ARGS: --enable-docs
|
||||
TARGETS: alpha-softmmu microblaze-softmmu mips64el-softmmu
|
||||
TARGETS: alpha-softmmu microblazeel-softmmu mips64el-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
|
||||
check-system-ubuntu:
|
||||
@@ -70,7 +70,7 @@ build-system-debian:
|
||||
needs:
|
||||
job: amd64-debian-container
|
||||
variables:
|
||||
IMAGE: debian
|
||||
IMAGE: debian-amd64
|
||||
CONFIGURE_ARGS: --with-coroutine=sigaltstack
|
||||
TARGETS: arm-softmmu i386-softmmu riscv64-softmmu sh4eb-softmmu
|
||||
sparc-softmmu xtensa-softmmu
|
||||
@@ -82,7 +82,7 @@ check-system-debian:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-debian:
|
||||
@@ -91,7 +91,7 @@ avocado-system-debian:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:arm arch:i386 arch:riscv64 arch:sh4 arch:sparc arch:xtensa
|
||||
|
||||
@@ -101,7 +101,7 @@ crash-test-debian:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian
|
||||
IMAGE: debian-amd64
|
||||
script:
|
||||
- cd build
|
||||
- make NINJA=":" check-venv
|
||||
@@ -158,9 +158,9 @@ build-system-centos:
|
||||
- .native_build_job_template
|
||||
- .native_build_artifact_template
|
||||
needs:
|
||||
job: amd64-centos9-container
|
||||
job: amd64-centos8-container
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
IMAGE: centos8
|
||||
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
|
||||
--enable-modules --enable-trace-backends=dtrace --enable-docs
|
||||
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
|
||||
@@ -173,7 +173,7 @@ check-system-centos:
|
||||
- job: build-system-centos
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-centos:
|
||||
@@ -182,7 +182,7 @@ avocado-system-centos:
|
||||
- job: build-system-centos
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:ppc64 arch:or1k arch:390x arch:x86_64 arch:rx
|
||||
arch:sh4 arch:nios2
|
||||
@@ -217,36 +217,6 @@ avocado-system-opensuse:
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:s390x arch:x86_64 arch:aarch64
|
||||
|
||||
#
|
||||
# Flaky tests. We don't run these by default and they are allow fail
|
||||
# but often the CI system is the only way to trigger the failures.
|
||||
#
|
||||
|
||||
build-system-flaky:
|
||||
extends:
|
||||
- .native_build_job_template
|
||||
- .native_build_artifact_template
|
||||
needs:
|
||||
job: amd64-debian-container
|
||||
variables:
|
||||
IMAGE: debian
|
||||
QEMU_JOB_OPTIONAL: 1
|
||||
TARGETS: aarch64-softmmu arm-softmmu mips64el-softmmu
|
||||
ppc64-softmmu rx-softmmu s390x-softmmu sh4-softmmu x86_64-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
|
||||
avocado-system-flaky:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-system-flaky
|
||||
artifacts: true
|
||||
allow_failure: true
|
||||
variables:
|
||||
IMAGE: debian
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
QEMU_JOB_OPTIONAL: 1
|
||||
QEMU_TEST_FLAKY_TESTS: 1
|
||||
AVOCADO_TAGS: flaky
|
||||
|
||||
# This jobs explicitly disable TCG (--disable-tcg), KVM is detected by
|
||||
# the configure script. The container doesn't contain Xen headers so
|
||||
@@ -258,9 +228,9 @@ avocado-system-flaky:
|
||||
build-tcg-disabled:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-centos9-container
|
||||
job: amd64-centos8-container
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
IMAGE: centos8
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
@@ -506,9 +476,6 @@ tsan-build:
|
||||
CONFIGURE_ARGS: --enable-tsan --cc=clang --cxx=clang++
|
||||
--enable-trace-backends=ust --disable-slirp
|
||||
TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
|
||||
# Remove when we switch to a distro with clang >= 18
|
||||
# https://github.com/google/sanitizers/issues/1716
|
||||
MAKE: setarch -R make
|
||||
|
||||
# gcov is a GCC features
|
||||
gcov:
|
||||
@@ -585,9 +552,9 @@ build-tci:
|
||||
build-without-defaults:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-centos9-container
|
||||
job: amd64-centos8-container
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
IMAGE: centos8
|
||||
CONFIGURE_ARGS:
|
||||
--without-default-devices
|
||||
--without-default-features
|
||||
@@ -622,7 +589,7 @@ build-tools-and-docs-debian:
|
||||
# when running on 'master' we use pre-existing container
|
||||
optional: true
|
||||
variables:
|
||||
IMAGE: debian
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check-unit ctags TAGS cscope
|
||||
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
|
||||
QEMU_JOB_PUBLISH: 1
|
||||
@@ -642,7 +609,7 @@ build-tools-and-docs-debian:
|
||||
# of what topic branch they're currently using
|
||||
pages:
|
||||
extends: .base_job_template
|
||||
image: $CI_REGISTRY_IMAGE/qemu/debian:$QEMU_CI_CONTAINER_TAG
|
||||
image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:$QEMU_CI_CONTAINER_TAG
|
||||
stage: test
|
||||
needs:
|
||||
- job: build-tools-and-docs-debian
|
||||
@@ -650,10 +617,7 @@ pages:
|
||||
- mkdir -p public
|
||||
# HTML-ised source tree
|
||||
- make gtags
|
||||
# We unset variables to work around a bug in some htags versions
|
||||
# which causes it to fail when the environment is large
|
||||
- CI_COMMIT_MESSAGE= CI_COMMIT_TAG_MESSAGE= htags
|
||||
-anT --tree-view=filetree -m qemu_init
|
||||
- htags -anT --tree-view=filetree -m qemu_init
|
||||
-t "Welcome to the QEMU sourcecode"
|
||||
- mv HTML public/src
|
||||
# Project documentation
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
.cirrus_build_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:latest
|
||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
||||
needs: []
|
||||
# 20 mins larger than "timeout_in" in cirrus/build.yml
|
||||
# as there's often a 5-10 minute delay before Cirrus CI
|
||||
@@ -52,37 +52,20 @@ x64-freebsd-13-build:
|
||||
NAME: freebsd-13
|
||||
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
||||
CIRRUS_VM_IMAGE_SELECTOR: image_family
|
||||
CIRRUS_VM_IMAGE_NAME: freebsd-13-3
|
||||
CIRRUS_VM_IMAGE_NAME: freebsd-13-2
|
||||
CIRRUS_VM_CPUS: 8
|
||||
CIRRUS_VM_RAM: 8G
|
||||
UPDATE_COMMAND: pkg update; pkg upgrade -y
|
||||
INSTALL_COMMAND: pkg install -y
|
||||
CONFIGURE_ARGS: --target-list-exclude=arm-softmmu,i386-softmmu,microblaze-softmmu,mips64el-softmmu,mipsel-softmmu,mips-softmmu,ppc-softmmu,sh4eb-softmmu,xtensa-softmmu
|
||||
TEST_TARGETS: check
|
||||
|
||||
aarch64-macos-13-base-build:
|
||||
aarch64-macos-12-base-build:
|
||||
extends: .cirrus_build_job
|
||||
variables:
|
||||
NAME: macos-13
|
||||
NAME: macos-12
|
||||
CIRRUS_VM_INSTANCE_TYPE: macos_instance
|
||||
CIRRUS_VM_IMAGE_SELECTOR: image
|
||||
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-ventura-base:latest
|
||||
CIRRUS_VM_CPUS: 12
|
||||
CIRRUS_VM_RAM: 24G
|
||||
UPDATE_COMMAND: brew update
|
||||
INSTALL_COMMAND: brew install
|
||||
PATH_EXTRA: /opt/homebrew/ccache/libexec:/opt/homebrew/gettext/bin
|
||||
PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
|
||||
CONFIGURE_ARGS: --target-list-exclude=arm-softmmu,i386-softmmu,microblazeel-softmmu,mips64-softmmu,mipsel-softmmu,mips-softmmu,ppc-softmmu,sh4-softmmu,xtensaeb-softmmu
|
||||
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
||||
|
||||
aarch64-macos-14-base-build:
|
||||
extends: .cirrus_build_job
|
||||
variables:
|
||||
NAME: macos-14
|
||||
CIRRUS_VM_INSTANCE_TYPE: macos_instance
|
||||
CIRRUS_VM_IMAGE_SELECTOR: image
|
||||
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-sonoma-base:latest
|
||||
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-monterey-base:latest
|
||||
CIRRUS_VM_CPUS: 12
|
||||
CIRRUS_VM_RAM: 24G
|
||||
UPDATE_COMMAND: brew update
|
||||
@@ -90,7 +73,6 @@ aarch64-macos-14-base-build:
|
||||
PATH_EXTRA: /opt/homebrew/ccache/libexec:/opt/homebrew/gettext/bin
|
||||
PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
|
||||
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
||||
QEMU_JOB_OPTIONAL: 1
|
||||
|
||||
|
||||
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
|
||||
|
||||
@@ -21,7 +21,7 @@ build_task:
|
||||
install_script:
|
||||
- @UPDATE_COMMAND@
|
||||
- @INSTALL_COMMAND@ @PKGS@
|
||||
- if test -n "@PYPI_PKGS@" ; then PYLIB=$(@PYTHON@ -c 'import sysconfig; print(sysconfig.get_path("stdlib"))'); rm -f $PYLIB/EXTERNALLY-MANAGED; @PIP3@ install @PYPI_PKGS@ ; fi
|
||||
- if test -n "@PYPI_PKGS@" ; then @PIP3@ install @PYPI_PKGS@ ; fi
|
||||
clone_script:
|
||||
- git clone --depth 100 "$CI_REPOSITORY_URL" .
|
||||
- git fetch origin "$CI_COMMIT_REF_NAME"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# THIS FILE WAS AUTO-GENERATED
|
||||
#
|
||||
# $ lcitool variables macos-13 qemu
|
||||
# $ lcitool variables macos-12 qemu
|
||||
#
|
||||
# https://gitlab.com/libvirt/libvirt-ci
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# THIS FILE WAS AUTO-GENERATED
|
||||
#
|
||||
# $ lcitool variables macos-14 qemu
|
||||
#
|
||||
# https://gitlab.com/libvirt/libvirt-ci
|
||||
|
||||
CCACHE='/opt/homebrew/bin/ccache'
|
||||
CPAN_PKGS=''
|
||||
CROSS_PKGS=''
|
||||
MAKE='/opt/homebrew/bin/gmake'
|
||||
NINJA='/opt/homebrew/bin/ninja'
|
||||
PACKAGING_COMMAND='brew'
|
||||
PIP3='/opt/homebrew/bin/pip3'
|
||||
PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd'
|
||||
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli'
|
||||
PYTHON='/opt/homebrew/bin/python3'
|
||||
@@ -1,10 +1,10 @@
|
||||
include:
|
||||
- local: '/.gitlab-ci.d/container-template.yml'
|
||||
|
||||
amd64-centos9-container:
|
||||
amd64-centos8-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: centos9
|
||||
NAME: centos8
|
||||
|
||||
amd64-fedora-container:
|
||||
extends: .container_job_template
|
||||
|
||||
@@ -46,12 +46,6 @@ loongarch-debian-cross-container:
|
||||
variables:
|
||||
NAME: debian-loongarch-cross
|
||||
|
||||
i686-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
variables:
|
||||
NAME: debian-i686-cross
|
||||
|
||||
mips64el-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
@@ -101,6 +95,11 @@ cris-fedora-cross-container:
|
||||
variables:
|
||||
NAME: fedora-cris-cross
|
||||
|
||||
i386-fedora-cross-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: fedora-i386-cross
|
||||
|
||||
win32-fedora-cross-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
|
||||
@@ -11,7 +11,7 @@ amd64-debian-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
variables:
|
||||
NAME: debian
|
||||
NAME: debian-amd64
|
||||
|
||||
amd64-ubuntu2204-container:
|
||||
extends: .container_job_template
|
||||
|
||||
@@ -37,25 +37,25 @@ cross-arm64-kvm-only:
|
||||
IMAGE: debian-arm64-cross
|
||||
EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features
|
||||
|
||||
cross-i686-user:
|
||||
cross-i386-user:
|
||||
extends:
|
||||
- .cross_user_build_job
|
||||
- .cross_test_artifacts
|
||||
needs:
|
||||
job: i686-debian-cross-container
|
||||
job: i386-fedora-cross-container
|
||||
variables:
|
||||
IMAGE: debian-i686-cross
|
||||
IMAGE: fedora-i386-cross
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
cross-i686-tci:
|
||||
cross-i386-tci:
|
||||
extends:
|
||||
- .cross_accel_build_job
|
||||
- .cross_test_artifacts
|
||||
timeout: 60m
|
||||
needs:
|
||||
job: i686-debian-cross-container
|
||||
job: i386-fedora-cross-container
|
||||
variables:
|
||||
IMAGE: debian-i686-cross
|
||||
IMAGE: fedora-i386-cross
|
||||
ACCEL: tcg-interpreter
|
||||
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins
|
||||
MAKE_CHECK_ARGS: check check-tcg
|
||||
@@ -165,7 +165,7 @@ cross-win32-system:
|
||||
job: win32-fedora-cross-container
|
||||
variables:
|
||||
IMAGE: fedora-win32-cross
|
||||
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal
|
||||
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal --disable-plugins
|
||||
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
|
||||
microblazeel-softmmu mips64el-softmmu nios2-softmmu
|
||||
artifacts:
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
.shared_msys2_builder:
|
||||
extends: .base_job_template
|
||||
tags:
|
||||
- saas-windows-medium-amd64
|
||||
- shared-windows
|
||||
- windows
|
||||
- windows-1809
|
||||
cache:
|
||||
key: "$CI_JOB_NAME"
|
||||
paths:
|
||||
@@ -86,6 +88,7 @@
|
||||
$MINGW_TARGET-libpng
|
||||
$MINGW_TARGET-libssh
|
||||
$MINGW_TARGET-libtasn1
|
||||
$MINGW_TARGET-libusb
|
||||
$MINGW_TARGET-lzo2
|
||||
$MINGW_TARGET-nettle
|
||||
$MINGW_TARGET-ninja
|
||||
@@ -95,8 +98,9 @@
|
||||
$MINGW_TARGET-SDL2
|
||||
$MINGW_TARGET-SDL2_image
|
||||
$MINGW_TARGET-snappy
|
||||
$MINGW_TARGET-zstd
|
||||
$EXTRA_PACKAGES "
|
||||
$MINGW_TARGET-spice
|
||||
$MINGW_TARGET-usbredir
|
||||
$MINGW_TARGET-zstd "
|
||||
- Write-Output "Running build at $(Get-Date -Format u)"
|
||||
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||
- $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
|
||||
@@ -119,8 +123,6 @@ msys2-64bit:
|
||||
variables:
|
||||
MINGW_TARGET: mingw-w64-x86_64
|
||||
MSYSTEM: MINGW64
|
||||
# msys2 only ship these packages for 64-bit, not 32-bit
|
||||
EXTRA_PACKAGES: $MINGW_TARGET-libusb $MINGW_TARGET-usbredir $MINGW_TARGET-spice
|
||||
# do not remove "--without-default-devices"!
|
||||
# commit 9f8e6cad65a6 ("gitlab-ci: Speed up the msys2-64bit job by using --without-default-devices"
|
||||
# changed to compile QEMU with the --without-default-devices switch
|
||||
@@ -129,3 +131,11 @@ msys2-64bit:
|
||||
# qTests don't run successfully with "--without-default-devices",
|
||||
# so let's exclude the qtests from CI for now.
|
||||
TEST_ARGS: --no-suite qtest
|
||||
|
||||
msys2-32bit:
|
||||
extends: .shared_msys2_builder
|
||||
variables:
|
||||
MINGW_TARGET: mingw-w64-i686
|
||||
MSYSTEM: MINGW32
|
||||
CONFIGURE_ARGS: --target-list=ppc64-softmmu -Ddebug=false -Doptimization=0
|
||||
TEST_ARGS: --no-suite qtest
|
||||
|
||||
@@ -5,21 +5,16 @@
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the version of Python and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
# We recommend specifying your dependencies to enable reproducible builds:
|
||||
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
# We want all the document formats
|
||||
formats: all
|
||||
|
||||
# For consistency, we require that QEMU's Sphinx extensions
|
||||
# run with at least the same minimum version of Python that
|
||||
# we require for other Python in our codebase (our conf.py
|
||||
# enforces this, and some code needs it.)
|
||||
python:
|
||||
version: 3.6
|
||||
|
||||
19
MAINTAINERS
19
MAINTAINERS
@@ -131,17 +131,6 @@ K: ^Subject:.*(?i)mips
|
||||
F: docs/system/target-mips.rst
|
||||
F: configs/targets/mips*
|
||||
|
||||
X86 general architecture support
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Maintained
|
||||
F: configs/devices/i386-softmmu/default.mak
|
||||
F: configs/targets/i386-softmmu.mak
|
||||
F: configs/targets/x86_64-softmmu.mak
|
||||
F: docs/system/target-i386*
|
||||
F: target/i386/*.[ch]
|
||||
F: target/i386/Kconfig
|
||||
F: target/i386/meson.build
|
||||
|
||||
Guest CPU cores (TCG)
|
||||
---------------------
|
||||
Overall TCG CPUs
|
||||
@@ -174,7 +163,6 @@ F: include/hw/core/tcg-cpu-ops.h
|
||||
F: host/include/*/host/cpuinfo.h
|
||||
F: util/cpuinfo-*.c
|
||||
F: include/tcg/
|
||||
F: tests/decode/
|
||||
|
||||
FPU emulation
|
||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||
@@ -669,7 +657,6 @@ F: include/hw/dma/pl080.h
|
||||
F: hw/dma/pl330.c
|
||||
F: hw/gpio/pl061.c
|
||||
F: hw/input/pl050.c
|
||||
F: include/hw/input/pl050.h
|
||||
F: hw/intc/pl190.c
|
||||
F: hw/sd/pl181.c
|
||||
F: hw/ssi/pl022.c
|
||||
@@ -940,7 +927,6 @@ F: hw/*/pxa2xx*
|
||||
F: hw/display/tc6393xb.c
|
||||
F: hw/gpio/max7310.c
|
||||
F: hw/gpio/zaurus.c
|
||||
F: hw/input/ads7846.c
|
||||
F: hw/misc/mst_fpga.c
|
||||
F: hw/adc/max111x.c
|
||||
F: include/hw/adc/max111x.h
|
||||
@@ -993,9 +979,7 @@ M: Peter Maydell <peter.maydell@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/*/stellaris*
|
||||
F: hw/display/ssd03*
|
||||
F: include/hw/input/gamepad.h
|
||||
F: include/hw/timer/stellaris-gptm.h
|
||||
F: docs/system/arm/stellaris.rst
|
||||
|
||||
STM32VLDISCOVERY
|
||||
@@ -1010,7 +994,6 @@ M: Peter Maydell <peter.maydell@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/vexpress.c
|
||||
F: hw/display/sii9022.c
|
||||
F: docs/system/arm/vexpress.rst
|
||||
|
||||
Versatile PB
|
||||
@@ -2258,7 +2241,7 @@ M: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
S: Supported
|
||||
F: hw/virtio/vhost-user-fs*
|
||||
F: include/hw/virtio/vhost-user-fs.h
|
||||
L: virtio-fs@lists.linux.dev
|
||||
L: virtio-fs@redhat.com
|
||||
|
||||
virtio-input
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
|
||||
@@ -183,7 +183,7 @@ static bool tb_lookup_cmp(const void *p, const void *d)
|
||||
const TranslationBlock *tb = p;
|
||||
const struct tb_desc *desc = d;
|
||||
|
||||
if (tb->pc == desc->pc &&
|
||||
if ((tb_cflags(tb) & CF_PCREL || tb->pc == desc->pc) &&
|
||||
tb_page_addr0(tb) == desc->page_addr0 &&
|
||||
tb->cs_base == desc->cs_base &&
|
||||
tb->flags == desc->flags &&
|
||||
@@ -233,7 +233,7 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, vaddr pc,
|
||||
return NULL;
|
||||
}
|
||||
desc.page_addr0 = phys_pc;
|
||||
h = tb_hash_func(phys_pc, pc,
|
||||
h = tb_hash_func(phys_pc, (cflags & CF_PCREL ? 0 : pc),
|
||||
flags, cs_base, cflags);
|
||||
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
|
||||
}
|
||||
@@ -721,7 +721,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
&& cpu->neg.icount_decr.u16.low + cpu->icount_extra == 0) {
|
||||
/* Execute just one insn to trigger exception pending in the log */
|
||||
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
|
||||
| CF_NOIRQ | 1;
|
||||
| CF_LAST_IO | CF_NOIRQ | 1;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
|
||||
@@ -1479,8 +1479,7 @@ int probe_access_full(CPUArchState *env, vaddr addr, int size,
|
||||
|
||||
/* Handle clean RAM pages. */
|
||||
if (unlikely(flags & TLB_NOTDIRTY)) {
|
||||
int dirtysize = size == 0 ? 1 : size;
|
||||
notdirty_write(env_cpu(env), addr, dirtysize, *pfull, retaddr);
|
||||
notdirty_write(env_cpu(env), addr, 1, *pfull, retaddr);
|
||||
flags &= ~TLB_NOTDIRTY;
|
||||
}
|
||||
|
||||
@@ -1503,8 +1502,7 @@ int probe_access_full_mmu(CPUArchState *env, vaddr addr, int size,
|
||||
|
||||
/* Handle clean RAM pages. */
|
||||
if (unlikely(flags & TLB_NOTDIRTY)) {
|
||||
int dirtysize = size == 0 ? 1 : size;
|
||||
notdirty_write(env_cpu(env), addr, dirtysize, *pfull, 0);
|
||||
notdirty_write(env_cpu(env), addr, 1, *pfull, 0);
|
||||
flags &= ~TLB_NOTDIRTY;
|
||||
}
|
||||
|
||||
@@ -1526,8 +1524,7 @@ int probe_access_flags(CPUArchState *env, vaddr addr, int size,
|
||||
|
||||
/* Handle clean RAM pages. */
|
||||
if (unlikely(flags & TLB_NOTDIRTY)) {
|
||||
int dirtysize = size == 0 ? 1 : size;
|
||||
notdirty_write(env_cpu(env), addr, dirtysize, full, retaddr);
|
||||
notdirty_write(env_cpu(env), addr, 1, full, retaddr);
|
||||
flags &= ~TLB_NOTDIRTY;
|
||||
}
|
||||
|
||||
@@ -1563,7 +1560,7 @@ void *probe_access(CPUArchState *env, vaddr addr, int size,
|
||||
|
||||
/* Handle clean RAM pages. */
|
||||
if (flags & TLB_NOTDIRTY) {
|
||||
notdirty_write(env_cpu(env), addr, size, full, retaddr);
|
||||
notdirty_write(env_cpu(env), addr, 1, full, retaddr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ static bool tb_cmp(const void *ap, const void *bp)
|
||||
const TranslationBlock *a = ap;
|
||||
const TranslationBlock *b = bp;
|
||||
|
||||
return (a->pc == b->pc &&
|
||||
return ((tb_cflags(a) & CF_PCREL || a->pc == b->pc) &&
|
||||
a->cs_base == b->cs_base &&
|
||||
a->flags == b->flags &&
|
||||
(tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
|
||||
@@ -712,7 +712,7 @@ static void tb_record(TranslationBlock *tb)
|
||||
tb_page_addr_t paddr0 = tb_page_addr0(tb);
|
||||
tb_page_addr_t paddr1 = tb_page_addr1(tb);
|
||||
tb_page_addr_t pindex0 = paddr0 >> TARGET_PAGE_BITS;
|
||||
tb_page_addr_t pindex1 = paddr1 >> TARGET_PAGE_BITS;
|
||||
tb_page_addr_t pindex1 = paddr0 >> TARGET_PAGE_BITS;
|
||||
|
||||
assert(paddr0 != -1);
|
||||
if (unlikely(paddr1 != -1) && pindex0 != pindex1) {
|
||||
@@ -744,7 +744,7 @@ static void tb_remove(TranslationBlock *tb)
|
||||
tb_page_addr_t paddr0 = tb_page_addr0(tb);
|
||||
tb_page_addr_t paddr1 = tb_page_addr1(tb);
|
||||
tb_page_addr_t pindex0 = paddr0 >> TARGET_PAGE_BITS;
|
||||
tb_page_addr_t pindex1 = paddr1 >> TARGET_PAGE_BITS;
|
||||
tb_page_addr_t pindex1 = paddr0 >> TARGET_PAGE_BITS;
|
||||
|
||||
assert(paddr0 != -1);
|
||||
if (unlikely(paddr1 != -1) && pindex0 != pindex1) {
|
||||
@@ -916,7 +916,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
|
||||
|
||||
/* remove the TB from the hash list */
|
||||
phys_pc = tb_page_addr0(tb);
|
||||
h = tb_hash_func(phys_pc, tb->pc,
|
||||
h = tb_hash_func(phys_pc, (orig_cflags & CF_PCREL ? 0 : tb->pc),
|
||||
tb->flags, tb->cs_base, orig_cflags);
|
||||
if (!qht_remove(&tb_ctx.htable, tb, h)) {
|
||||
return;
|
||||
@@ -983,7 +983,7 @@ TranslationBlock *tb_link_page(TranslationBlock *tb)
|
||||
tb_record(tb);
|
||||
|
||||
/* add in the hash table */
|
||||
h = tb_hash_func(tb_page_addr0(tb), tb->pc,
|
||||
h = tb_hash_func(tb_page_addr0(tb), (tb->cflags & CF_PCREL ? 0 : tb->pc),
|
||||
tb->flags, tb->cs_base, tb->cflags);
|
||||
qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
|
||||
|
||||
@@ -1083,7 +1083,8 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
|
||||
if (current_tb_modified) {
|
||||
/* Force execution of one insn next time. */
|
||||
CPUState *cpu = current_cpu;
|
||||
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu);
|
||||
cpu->cflags_next_tb =
|
||||
1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1153,7 +1154,8 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
|
||||
if (current_tb_modified) {
|
||||
page_collection_unlock(pages);
|
||||
/* Force execution of one insn next time. */
|
||||
current_cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu);
|
||||
current_cpu->cflags_next_tb =
|
||||
1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu);
|
||||
mmap_unlock();
|
||||
cpu_loop_exit_noexc(current_cpu);
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
|
||||
if (phys_pc == -1) {
|
||||
/* Generate a one-shot TB with 1 insn in it */
|
||||
cflags = (cflags & ~CF_COUNT_MASK) | 1;
|
||||
cflags = (cflags & ~CF_COUNT_MASK) | CF_LAST_IO | 1;
|
||||
}
|
||||
|
||||
max_insns = cflags & CF_COUNT_MASK;
|
||||
@@ -327,7 +327,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
|
||||
gen_code_buf = tcg_ctx->code_gen_ptr;
|
||||
tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf);
|
||||
if (!(cflags & CF_PCREL)) {
|
||||
tb->pc = pc;
|
||||
}
|
||||
tb->cs_base = cs_base;
|
||||
tb->flags = flags;
|
||||
tb->cflags = cflags;
|
||||
@@ -630,7 +632,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
* operations only (which execute after completion) so we don't
|
||||
* double instrument the instruction.
|
||||
*/
|
||||
cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | n;
|
||||
cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | CF_LAST_IO | n;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
|
||||
vaddr pc = log_pc(cpu, tb);
|
||||
|
||||
@@ -89,7 +89,7 @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags)
|
||||
* each translation block. The cost is minimal, plus it would be
|
||||
* very easy to forget doing it in the translator.
|
||||
*/
|
||||
set_can_do_io(db, db->max_insns == 1);
|
||||
set_can_do_io(db, db->max_insns == 1 && (cflags & CF_LAST_IO));
|
||||
|
||||
return icount_start_insn;
|
||||
}
|
||||
@@ -151,7 +151,13 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
ops->tb_start(db, cpu);
|
||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||
|
||||
plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY);
|
||||
if (cflags & CF_MEMI_ONLY) {
|
||||
/* We should only see CF_MEMI_ONLY for io_recompile. */
|
||||
assert(cflags & CF_LAST_IO);
|
||||
plugin_enabled = plugin_gen_tb_start(cpu, db, true);
|
||||
} else {
|
||||
plugin_enabled = plugin_gen_tb_start(cpu, db, false);
|
||||
}
|
||||
db->plugin_enabled = plugin_enabled;
|
||||
|
||||
while (true) {
|
||||
@@ -163,13 +169,11 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
plugin_gen_insn_start(cpu, db);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disassemble one instruction. The translate_insn hook should
|
||||
* update db->pc_next and db->is_jmp to indicate what should be
|
||||
* done next -- either exiting this loop or locate the start of
|
||||
* the next instruction.
|
||||
*/
|
||||
if (db->num_insns == db->max_insns) {
|
||||
/* Disassemble one instruction. The translate_insn hook should
|
||||
update db->pc_next and db->is_jmp to indicate what should be
|
||||
done next -- either exiting this loop or locate the start of
|
||||
the next instruction. */
|
||||
if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
|
||||
/* Accept I/O on the last instruction. */
|
||||
set_can_do_io(db, true);
|
||||
}
|
||||
|
||||
@@ -1744,7 +1744,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp)
|
||||
if (driver) {
|
||||
done = !audio_driver_init(s, driver, dev, errp);
|
||||
} else {
|
||||
error_setg(errp, "Unknown audio driver `%s'", drvname);
|
||||
error_setg(errp, "Unknown audio driver `%s'\n", drvname);
|
||||
}
|
||||
if (!done) {
|
||||
goto out;
|
||||
@@ -1758,15 +1758,12 @@ static AudioState *audio_init(Audiodev *dev, Error **errp)
|
||||
goto out;
|
||||
}
|
||||
s->dev = dev = e->dev;
|
||||
QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next);
|
||||
g_free(e);
|
||||
drvname = AudiodevDriver_str(dev->driver);
|
||||
driver = audio_driver_lookup(drvname);
|
||||
if (!audio_driver_init(s, driver, dev, NULL)) {
|
||||
break;
|
||||
}
|
||||
qapi_free_Audiodev(dev);
|
||||
s->dev = NULL;
|
||||
QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,7 @@ endforeach
|
||||
|
||||
if dbus_display
|
||||
module_ss = ss.source_set()
|
||||
module_ss.add(when: [gio, dbus_display1_dep, pixman],
|
||||
if_true: files('dbusaudio.c'))
|
||||
module_ss.add(when: [gio, pixman], if_true: files('dbusaudio.c'))
|
||||
audio_modules += {'dbus': module_ss}
|
||||
endif
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/cryptodev.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "standard-headers/linux/virtio_crypto.h"
|
||||
#include "crypto/cipher.h"
|
||||
@@ -397,7 +396,7 @@ static int cryptodev_builtin_create_session(
|
||||
case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
|
||||
case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
|
||||
default:
|
||||
error_report("Unsupported opcode :%" PRIu32 "",
|
||||
error_setg(&local_error, "Unsupported opcode :%" PRIu32 "",
|
||||
sess_info->op_code);
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
@@ -428,9 +427,7 @@ static int cryptodev_builtin_close_session(
|
||||
CRYPTODEV_BACKEND_BUILTIN(backend);
|
||||
CryptoDevBackendBuiltinSession *session;
|
||||
|
||||
if (session_id >= MAX_NUM_SESSIONS || !builtin->sessions[session_id]) {
|
||||
return -VIRTIO_CRYPTO_INVSESS;
|
||||
}
|
||||
assert(session_id < MAX_NUM_SESSIONS && builtin->sessions[session_id]);
|
||||
|
||||
session = builtin->sessions[session_id];
|
||||
if (session->cipher) {
|
||||
@@ -555,7 +552,7 @@ static int cryptodev_builtin_operation(
|
||||
|
||||
if (op_info->session_id >= MAX_NUM_SESSIONS ||
|
||||
builtin->sessions[op_info->session_id] == NULL) {
|
||||
error_report("Cannot find a valid session id: %" PRIu64 "",
|
||||
error_setg(&local_error, "Cannot find a valid session id: %" PRIu64 "",
|
||||
op_info->session_id);
|
||||
return -VIRTIO_CRYPTO_INVSESS;
|
||||
}
|
||||
|
||||
@@ -398,7 +398,6 @@ static void cryptodev_backend_set_ops(Object *obj, Visitor *v,
|
||||
static void
|
||||
cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
|
||||
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
|
||||
uint32_t services;
|
||||
@@ -407,20 +406,11 @@ cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
||||
QTAILQ_INIT(&backend->opinfos);
|
||||
value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
|
||||
cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
|
||||
cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bc->init) {
|
||||
bc->init(backend, errp);
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
services = backend->conf.crypto_services;
|
||||
|
||||
127
block.c
127
block.c
@@ -86,7 +86,6 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role,
|
||||
bool parse_filename,
|
||||
Error **errp);
|
||||
|
||||
static bool bdrv_recurse_has_child(BlockDriverState *bs,
|
||||
@@ -1714,7 +1713,7 @@ open_failed:
|
||||
bdrv_unref_child(bs, bs->file);
|
||||
assert(!bs->file);
|
||||
}
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
g_free(bs->opaque);
|
||||
bs->opaque = NULL;
|
||||
@@ -2048,8 +2047,7 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
|
||||
* block driver has been specified explicitly.
|
||||
*/
|
||||
static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
int *flags, bool allow_parse_filename,
|
||||
Error **errp)
|
||||
int *flags, Error **errp)
|
||||
{
|
||||
const char *drvname;
|
||||
bool protocol = *flags & BDRV_O_PROTOCOL;
|
||||
@@ -2091,7 +2089,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
if (protocol && filename) {
|
||||
if (!qdict_haskey(*options, "filename")) {
|
||||
qdict_put_str(*options, "filename", filename);
|
||||
parse_filename = allow_parse_filename;
|
||||
parse_filename = true;
|
||||
} else {
|
||||
error_setg(errp, "Can't specify 'file' and 'filename' options at "
|
||||
"the same time");
|
||||
@@ -3579,7 +3577,7 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||
bdrv_drained_begin(drain_bs);
|
||||
bdrv_graph_wrlock(backing_hd);
|
||||
ret = bdrv_set_backing_hd_drained(bs, backing_hd, errp);
|
||||
bdrv_graph_wrunlock(backing_hd);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(drain_bs);
|
||||
bdrv_unref(drain_bs);
|
||||
|
||||
@@ -3677,8 +3675,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
}
|
||||
|
||||
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
|
||||
&child_of_bds, bdrv_backing_role(bs), true,
|
||||
errp);
|
||||
&child_of_bds, bdrv_backing_role(bs), errp);
|
||||
if (!backing_hd) {
|
||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||
error_prepend(errp, "Could not open backing file: ");
|
||||
@@ -3715,8 +3712,7 @@ free_exit:
|
||||
static BlockDriverState *
|
||||
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||
BlockDriverState *parent, const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role, bool allow_none,
|
||||
bool parse_filename, Error **errp)
|
||||
BdrvChildRole child_role, bool allow_none, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
QDict *image_options;
|
||||
@@ -3747,8 +3743,7 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||
}
|
||||
|
||||
bs = bdrv_open_inherit(filename, reference, image_options, 0,
|
||||
parent, child_class, child_role, parse_filename,
|
||||
errp);
|
||||
parent, child_class, child_role, errp);
|
||||
if (!bs) {
|
||||
goto done;
|
||||
}
|
||||
@@ -3758,37 +3753,6 @@ done:
|
||||
return bs;
|
||||
}
|
||||
|
||||
static BdrvChild *bdrv_open_child_common(const char *filename,
|
||||
QDict *options, const char *bdref_key,
|
||||
BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role,
|
||||
bool allow_none, bool parse_filename,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BdrvChild *child;
|
||||
AioContext *ctx;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
||||
child_role, allow_none, parse_filename, errp);
|
||||
if (bs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdrv_graph_wrlock(NULL);
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(ctx);
|
||||
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
errp);
|
||||
aio_context_release(ctx);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens a disk image whose options are given as BlockdevRef in another block
|
||||
* device's options.
|
||||
@@ -3814,15 +3778,31 @@ BdrvChild *bdrv_open_child(const char *filename,
|
||||
BdrvChildRole child_role,
|
||||
bool allow_none, Error **errp)
|
||||
{
|
||||
return bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||
child_class, child_role, allow_none, false,
|
||||
BlockDriverState *bs;
|
||||
BdrvChild *child;
|
||||
AioContext *ctx;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
||||
child_role, allow_none, errp);
|
||||
if (bs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdrv_graph_wrlock(NULL);
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(ctx);
|
||||
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
errp);
|
||||
aio_context_release(ctx);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* This does mostly the same as bdrv_open_child(), but for opening the primary
|
||||
* child of a node. A notable difference from bdrv_open_child() is that it
|
||||
* enables filename parsing for protocol names (including json:).
|
||||
* Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
|
||||
*
|
||||
* The caller must hold the lock of the main AioContext and no other AioContext.
|
||||
* @parent can move to a different AioContext in this function. Callers must
|
||||
@@ -3839,8 +3819,8 @@ int bdrv_open_file_child(const char *filename,
|
||||
role = parent->drv->is_filter ?
|
||||
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
|
||||
|
||||
if (!bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||
&child_of_bds, role, false, true, errp))
|
||||
if (!bdrv_open_child(filename, options, bdref_key, parent,
|
||||
&child_of_bds, role, false, errp))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -3885,8 +3865,7 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
|
||||
|
||||
}
|
||||
|
||||
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
|
||||
errp);
|
||||
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
|
||||
obj = NULL;
|
||||
qobject_unref(obj);
|
||||
visit_free(v);
|
||||
@@ -3983,7 +3962,7 @@ static BlockDriverState * no_coroutine_fn
|
||||
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
int flags, BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class, BdrvChildRole child_role,
|
||||
bool parse_filename, Error **errp)
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
BlockBackend *file = NULL;
|
||||
@@ -4032,12 +4011,10 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
}
|
||||
|
||||
/* json: syntax counts as explicit options, as if in the QDict */
|
||||
if (parse_filename) {
|
||||
parse_json_protocol(options, &filename, &local_err);
|
||||
if (local_err) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
bs->explicit_options = qdict_clone_shallow(options);
|
||||
|
||||
@@ -4061,8 +4038,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
parent->open_flags, parent->options);
|
||||
}
|
||||
|
||||
ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
|
||||
&local_err);
|
||||
ret = bdrv_fill_options(&options, filename, &flags, &local_err);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -4131,7 +4107,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
|
||||
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
|
||||
&child_of_bds, BDRV_CHILD_IMAGE,
|
||||
true, true, &local_err);
|
||||
true, &local_err);
|
||||
if (local_err) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -4294,7 +4270,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
return bdrv_open_inherit(filename, reference, options, flags, NULL,
|
||||
NULL, 0, true, errp);
|
||||
NULL, 0, errp);
|
||||
}
|
||||
|
||||
/* Return true if the NULL-terminated @list contains @str */
|
||||
@@ -4676,7 +4652,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
|
||||
|
||||
bdrv_graph_wrlock(NULL);
|
||||
tran_commit(tran);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) {
|
||||
BlockDriverState *bs = bs_entry->state.bs;
|
||||
@@ -4695,7 +4671,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
|
||||
abort:
|
||||
bdrv_graph_wrlock(NULL);
|
||||
tran_abort(tran);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
|
||||
if (bs_entry->prepared) {
|
||||
@@ -4881,7 +4857,7 @@ bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
|
||||
ret = bdrv_set_file_or_backing_noperm(bs, new_child_bs, is_backing,
|
||||
tran, errp);
|
||||
|
||||
bdrv_graph_wrunlock_ctx(ctx);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
if (old_ctx != ctx) {
|
||||
aio_context_release(ctx);
|
||||
@@ -5240,7 +5216,7 @@ static void bdrv_close(BlockDriverState *bs)
|
||||
|
||||
assert(!bs->backing);
|
||||
assert(!bs->file);
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
g_free(bs->opaque);
|
||||
bs->opaque = NULL;
|
||||
@@ -5535,7 +5511,7 @@ int bdrv_drop_filter(BlockDriverState *bs, Error **errp)
|
||||
bdrv_drained_begin(child_bs);
|
||||
bdrv_graph_wrlock(bs);
|
||||
ret = bdrv_replace_node_common(bs, child_bs, true, true, errp);
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(child_bs);
|
||||
|
||||
return ret;
|
||||
@@ -5617,7 +5593,7 @@ out:
|
||||
tran_finalize(tran, ret);
|
||||
|
||||
bdrv_refresh_limits(bs_top, NULL, NULL);
|
||||
bdrv_graph_wrunlock(bs_top);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
bdrv_drained_end(bs_top);
|
||||
bdrv_drained_end(bs_new);
|
||||
@@ -5655,7 +5631,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
|
||||
|
||||
tran_finalize(tran, ret);
|
||||
|
||||
bdrv_graph_wrunlock(new_bs);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(old_bs);
|
||||
bdrv_drained_end(new_bs);
|
||||
bdrv_unref(old_bs);
|
||||
@@ -5744,7 +5720,7 @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
|
||||
bdrv_drained_begin(new_node_bs);
|
||||
bdrv_graph_wrlock(new_node_bs);
|
||||
ret = bdrv_replace_node(bs, new_node_bs, errp);
|
||||
bdrv_graph_wrunlock(new_node_bs);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(new_node_bs);
|
||||
bdrv_drained_end(bs);
|
||||
bdrv_unref(bs);
|
||||
@@ -6039,7 +6015,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||
* That's a FIXME.
|
||||
*/
|
||||
bdrv_replace_node_common(top, base, false, false, &local_err);
|
||||
bdrv_graph_wrunlock(base);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
@@ -6076,7 +6052,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||
goto exit;
|
||||
|
||||
exit_wrlock:
|
||||
bdrv_graph_wrunlock(base);
|
||||
bdrv_graph_wrunlock();
|
||||
exit:
|
||||
bdrv_drained_end(base);
|
||||
bdrv_unref(top);
|
||||
@@ -7278,16 +7254,6 @@ void bdrv_unref(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
static void bdrv_schedule_unref_bh(void *opaque)
|
||||
{
|
||||
BlockDriverState *bs = opaque;
|
||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(ctx);
|
||||
bdrv_unref(bs);
|
||||
aio_context_release(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release a BlockDriverState reference while holding the graph write lock.
|
||||
*
|
||||
@@ -7301,7 +7267,8 @@ void bdrv_schedule_unref(BlockDriverState *bs)
|
||||
if (!bs) {
|
||||
return;
|
||||
}
|
||||
aio_bh_schedule_oneshot(qemu_get_aio_context(), bdrv_schedule_unref_bh, bs);
|
||||
aio_bh_schedule_oneshot(qemu_get_aio_context(),
|
||||
(QEMUBHFunc *) bdrv_unref, bs);
|
||||
}
|
||||
|
||||
struct BdrvOpBlocker {
|
||||
|
||||
@@ -499,7 +499,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
bdrv_graph_wrlock(target);
|
||||
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
||||
&error_abort);
|
||||
bdrv_graph_wrunlock(target);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
return &job->common;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ typedef struct {
|
||||
CoQueue bounce_available;
|
||||
|
||||
/* The value of the "mem-region-alignment" property */
|
||||
uint64_t mem_region_alignment;
|
||||
size_t mem_region_alignment;
|
||||
|
||||
/* Can we skip adding/deleting blkio_mem_regions? */
|
||||
bool needs_mem_regions;
|
||||
|
||||
@@ -253,7 +253,7 @@ fail_log:
|
||||
if (ret < 0) {
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_unref_child(bs, s->log_file);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
s->log_file = NULL;
|
||||
}
|
||||
fail:
|
||||
@@ -268,7 +268,7 @@ static void blk_log_writes_close(BlockDriverState *bs)
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_unref_child(bs, s->log_file);
|
||||
s->log_file = NULL;
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn GRAPH_RDLOCK
|
||||
@@ -328,39 +328,22 @@ static void coroutine_fn GRAPH_RDLOCK
|
||||
blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
|
||||
{
|
||||
BDRVBlkLogWritesState *s = lr->bs->opaque;
|
||||
|
||||
/*
|
||||
* Determine the offsets and sizes of different parts of the entry, and
|
||||
* update the state of the driver.
|
||||
*
|
||||
* This needs to be done in one go, before any actual I/O is done, as the
|
||||
* log entry may have to be written in two parts, and the state of the
|
||||
* driver may be modified by other driver operations while waiting for the
|
||||
* I/O to complete.
|
||||
*/
|
||||
const uint64_t entry_start_sector = s->cur_log_sector;
|
||||
const uint64_t entry_offset = entry_start_sector << s->sectorbits;
|
||||
const uint64_t qiov_aligned_size = ROUND_UP(lr->qiov->size, s->sectorsize);
|
||||
const uint64_t entry_aligned_size = qiov_aligned_size +
|
||||
ROUND_UP(lr->zero_size, s->sectorsize);
|
||||
const uint64_t entry_nr_sectors = entry_aligned_size >> s->sectorbits;
|
||||
uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits;
|
||||
|
||||
s->nr_entries++;
|
||||
s->cur_log_sector += entry_nr_sectors;
|
||||
s->cur_log_sector +=
|
||||
ROUND_UP(lr->qiov->size, s->sectorsize) >> s->sectorbits;
|
||||
|
||||
/*
|
||||
* Write the log entry. Note that if this is a "write zeroes" operation,
|
||||
* only the entry header is written here, with the zeroing being done
|
||||
* separately below.
|
||||
*/
|
||||
lr->log_ret = bdrv_co_pwritev(s->log_file, entry_offset, lr->qiov->size,
|
||||
lr->log_ret = bdrv_co_pwritev(s->log_file, cur_log_offset, lr->qiov->size,
|
||||
lr->qiov, 0);
|
||||
|
||||
/* Logging for the "write zeroes" operation */
|
||||
if (lr->log_ret == 0 && lr->zero_size) {
|
||||
const uint64_t zeroes_offset = entry_offset + qiov_aligned_size;
|
||||
cur_log_offset = s->cur_log_sector << s->sectorbits;
|
||||
s->cur_log_sector +=
|
||||
ROUND_UP(lr->zero_size, s->sectorsize) >> s->sectorbits;
|
||||
|
||||
lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, zeroes_offset,
|
||||
lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, cur_log_offset,
|
||||
lr->zero_size, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ static void blkverify_close(BlockDriverState *bs)
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_unref_child(bs, s->test_file);
|
||||
s->test_file = NULL;
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn GRAPH_RDLOCK
|
||||
|
||||
@@ -613,14 +613,14 @@ BlockDriverState *bdrv_next(BdrvNextIterator *it)
|
||||
/* Must be called from the main loop */
|
||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||
|
||||
old_bs = it->bs;
|
||||
|
||||
/* First, return all root nodes of BlockBackends. In order to avoid
|
||||
* returning a BDS twice when multiple BBs refer to it, we only return it
|
||||
* if the BB is the first one in the parent list of the BDS. */
|
||||
if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
|
||||
BlockBackend *old_blk = it->blk;
|
||||
|
||||
old_bs = old_blk ? blk_bs(old_blk) : NULL;
|
||||
|
||||
do {
|
||||
it->blk = blk_all_next(it->blk);
|
||||
bs = it->blk ? blk_bs(it->blk) : NULL;
|
||||
@@ -634,10 +634,11 @@ BlockDriverState *bdrv_next(BdrvNextIterator *it)
|
||||
if (bs) {
|
||||
bdrv_ref(bs);
|
||||
bdrv_unref(old_bs);
|
||||
it->bs = bs;
|
||||
return bs;
|
||||
}
|
||||
it->phase = BDRV_NEXT_MONITOR_OWNED;
|
||||
} else {
|
||||
old_bs = it->bs;
|
||||
}
|
||||
|
||||
/* Then return the monitor-owned BDSes without a BB attached. Ignore all
|
||||
@@ -677,11 +678,14 @@ void bdrv_next_cleanup(BdrvNextIterator *it)
|
||||
/* Must be called from the main loop */
|
||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||
|
||||
bdrv_unref(it->bs);
|
||||
|
||||
if (it->phase == BDRV_NEXT_BACKEND_ROOTS && it->blk) {
|
||||
if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
|
||||
if (it->blk) {
|
||||
bdrv_unref(blk_bs(it->blk));
|
||||
blk_unref(it->blk);
|
||||
}
|
||||
} else {
|
||||
bdrv_unref(it->bs);
|
||||
}
|
||||
|
||||
bdrv_next_reset(it);
|
||||
}
|
||||
@@ -878,14 +882,11 @@ BlockBackend *blk_by_public(BlockBackendPublic *public)
|
||||
|
||||
/*
|
||||
* Disassociates the currently associated BlockDriverState from @blk.
|
||||
*
|
||||
* The caller must hold the AioContext lock for the BlockBackend.
|
||||
*/
|
||||
void blk_remove_bs(BlockBackend *blk)
|
||||
{
|
||||
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
||||
BdrvChild *root;
|
||||
AioContext *ctx;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
@@ -915,10 +916,9 @@ void blk_remove_bs(BlockBackend *blk)
|
||||
root = blk->root;
|
||||
blk->root = NULL;
|
||||
|
||||
ctx = bdrv_get_aio_context(root->bs);
|
||||
bdrv_graph_wrlock(root->bs);
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_root_unref_child(root);
|
||||
bdrv_graph_wrunlock_ctx(ctx);
|
||||
bdrv_graph_wrunlock();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -929,8 +929,6 @@ void blk_remove_bs(BlockBackend *blk)
|
||||
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
bdrv_ref(bs);
|
||||
bdrv_graph_wrlock(bs);
|
||||
@@ -938,7 +936,7 @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
|
||||
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
|
||||
blk->perm, blk->shared_perm,
|
||||
blk, errp);
|
||||
bdrv_graph_wrunlock_ctx(ctx);
|
||||
bdrv_graph_wrunlock();
|
||||
if (blk->root == NULL) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ static void commit_abort(Job *job)
|
||||
bdrv_drained_begin(commit_top_backing_bs);
|
||||
bdrv_graph_wrlock(commit_top_backing_bs);
|
||||
bdrv_replace_node(s->commit_top_bs, commit_top_backing_bs, &error_abort);
|
||||
bdrv_graph_wrunlock(commit_top_backing_bs);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(commit_top_backing_bs);
|
||||
|
||||
bdrv_unref(s->commit_top_bs);
|
||||
@@ -370,19 +370,19 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||
ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
||||
iter_shared_perms, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_wrunlock(top);
|
||||
bdrv_graph_wrunlock();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
|
||||
bdrv_graph_wrunlock(top);
|
||||
bdrv_graph_wrunlock();
|
||||
goto fail;
|
||||
}
|
||||
s->chain_frozen = true;
|
||||
|
||||
ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp);
|
||||
bdrv_graph_wrunlock(top);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -436,7 +436,7 @@ fail:
|
||||
bdrv_drained_begin(top);
|
||||
bdrv_graph_wrlock(top);
|
||||
bdrv_replace_node(commit_top_bs, top, &error_abort);
|
||||
bdrv_graph_wrunlock(top);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(top);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +283,6 @@ static void vu_blk_drained_begin(void *opaque)
|
||||
{
|
||||
VuBlkExport *vexp = opaque;
|
||||
|
||||
vexp->vu_server.quiescing = true;
|
||||
vhost_user_server_detach_aio_context(&vexp->vu_server);
|
||||
}
|
||||
|
||||
@@ -292,23 +291,19 @@ static void vu_blk_drained_end(void *opaque)
|
||||
{
|
||||
VuBlkExport *vexp = opaque;
|
||||
|
||||
vexp->vu_server.quiescing = false;
|
||||
vhost_user_server_attach_aio_context(&vexp->vu_server, vexp->export.ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensures that bdrv_drained_begin() waits until in-flight requests complete
|
||||
* and the server->co_trip coroutine has terminated. It will be restarted in
|
||||
* vhost_user_server_attach_aio_context().
|
||||
* Ensures that bdrv_drained_begin() waits until in-flight requests complete.
|
||||
*
|
||||
* Called with vexp->export.ctx acquired.
|
||||
*/
|
||||
static bool vu_blk_drained_poll(void *opaque)
|
||||
{
|
||||
VuBlkExport *vexp = opaque;
|
||||
VuServer *server = &vexp->vu_server;
|
||||
|
||||
return server->co_trip || vhost_user_server_has_in_flight(server);
|
||||
return vhost_user_server_has_in_flight(&vexp->vu_server);
|
||||
}
|
||||
|
||||
static const BlockDevOps vu_blk_dev_ops = {
|
||||
|
||||
@@ -161,21 +161,11 @@ void no_coroutine_fn bdrv_graph_wrlock(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
void no_coroutine_fn bdrv_graph_wrunlock_ctx(AioContext *ctx)
|
||||
void bdrv_graph_wrunlock(void)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
assert(qatomic_read(&has_writer));
|
||||
|
||||
/*
|
||||
* Release only non-mainloop AioContext. The mainloop often relies on the
|
||||
* BQL and doesn't lock the main AioContext before doing things.
|
||||
*/
|
||||
if (ctx && ctx != qemu_get_aio_context()) {
|
||||
aio_context_release(ctx);
|
||||
} else {
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&aio_context_list_lock) {
|
||||
/*
|
||||
* No need for memory barriers, this works in pair with
|
||||
@@ -197,17 +187,6 @@ void no_coroutine_fn bdrv_graph_wrunlock_ctx(AioContext *ctx)
|
||||
* progress.
|
||||
*/
|
||||
aio_bh_poll(qemu_get_aio_context());
|
||||
|
||||
if (ctx) {
|
||||
aio_context_acquire(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void no_coroutine_fn bdrv_graph_wrunlock(BlockDriverState *bs)
|
||||
{
|
||||
AioContext *ctx = bs ? bdrv_get_aio_context(bs) : NULL;
|
||||
|
||||
bdrv_graph_wrunlock_ctx(ctx);
|
||||
}
|
||||
|
||||
void coroutine_fn bdrv_graph_co_rdlock(void)
|
||||
|
||||
21
block/io.c
21
block/io.c
@@ -1756,11 +1756,6 @@ static int bdrv_pad_request(BlockDriverState *bs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For prefetching in stream_populate(), no qiov is passed along, because
|
||||
* only copy-on-read matters.
|
||||
*/
|
||||
if (qiov && *qiov) {
|
||||
sliced_iov = qemu_iovec_slice(*qiov, *qiov_offset, *bytes,
|
||||
&sliced_head, &sliced_tail,
|
||||
&sliced_niov);
|
||||
@@ -1773,12 +1768,10 @@ static int bdrv_pad_request(BlockDriverState *bs,
|
||||
bdrv_padding_finalize(pad);
|
||||
return ret;
|
||||
}
|
||||
*qiov = &pad->local_qiov;
|
||||
*qiov_offset = 0;
|
||||
}
|
||||
|
||||
*bytes += pad->head + pad->tail;
|
||||
*offset -= pad->head;
|
||||
*qiov = &pad->local_qiov;
|
||||
*qiov_offset = 0;
|
||||
if (padded) {
|
||||
*padded = true;
|
||||
}
|
||||
@@ -2626,16 +2619,6 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero,
|
||||
ret |= (ret2 & BDRV_BLOCK_ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that the recursive search was done, clear the flag. Otherwise,
|
||||
* with more complicated block graphs like snapshot-access ->
|
||||
* copy-before-write -> qcow2, where the return value will be propagated
|
||||
* further up to a parent bdrv_co_do_block_status() call, both the
|
||||
* BDRV_BLOCK_RECURSE and BDRV_BLOCK_ZERO flags would be set, which is
|
||||
* not allowed.
|
||||
*/
|
||||
ret &= ~BDRV_BLOCK_RECURSE;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
@@ -479,9 +479,9 @@ static unsigned mirror_perform(MirrorBlockJob *s, int64_t offset,
|
||||
return bytes_handled;
|
||||
}
|
||||
|
||||
static void coroutine_fn GRAPH_UNLOCKED mirror_iteration(MirrorBlockJob *s)
|
||||
static void coroutine_fn GRAPH_RDLOCK mirror_iteration(MirrorBlockJob *s)
|
||||
{
|
||||
BlockDriverState *source;
|
||||
BlockDriverState *source = s->mirror_top_bs->backing->bs;
|
||||
MirrorOp *pseudo_op;
|
||||
int64_t offset;
|
||||
/* At least the first dirty chunk is mirrored in one iteration. */
|
||||
@@ -489,10 +489,6 @@ static void coroutine_fn GRAPH_UNLOCKED mirror_iteration(MirrorBlockJob *s)
|
||||
bool write_zeroes_ok = bdrv_can_write_zeroes_with_unmap(blk_bs(s->target));
|
||||
int max_io_bytes = MAX(s->buf_size / MAX_IN_FLIGHT, MAX_IO_BYTES);
|
||||
|
||||
bdrv_graph_co_rdlock();
|
||||
source = s->mirror_top_bs->backing->bs;
|
||||
bdrv_graph_co_rdunlock();
|
||||
|
||||
bdrv_dirty_bitmap_lock(s->dirty_bitmap);
|
||||
offset = bdrv_dirty_iter_next(s->dbi);
|
||||
if (offset < 0) {
|
||||
@@ -777,7 +773,7 @@ static int mirror_exit_common(Job *job)
|
||||
"would not lead to an abrupt change of visible data",
|
||||
to_replace->node_name, target_bs->node_name);
|
||||
}
|
||||
bdrv_graph_wrunlock(target_bs);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(to_replace);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
@@ -802,7 +798,7 @@ static int mirror_exit_common(Job *job)
|
||||
block_job_remove_all_bdrv(bjob);
|
||||
bdrv_graph_wrlock(mirror_top_bs);
|
||||
bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort);
|
||||
bdrv_graph_wrunlock(mirror_top_bs);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
bdrv_drained_end(target_bs);
|
||||
bdrv_unref(target_bs);
|
||||
@@ -1082,7 +1078,9 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
|
||||
mirror_wait_for_free_in_flight_slot(s);
|
||||
continue;
|
||||
} else if (cnt != 0) {
|
||||
bdrv_graph_co_rdlock();
|
||||
mirror_iteration(s);
|
||||
bdrv_graph_co_rdunlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1922,7 +1920,7 @@ static BlockJob *mirror_start_job(
|
||||
BLK_PERM_CONSISTENT_READ,
|
||||
errp);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -1967,17 +1965,17 @@ static BlockJob *mirror_start_job(
|
||||
ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
||||
iter_shared_perms, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (bdrv_freeze_backing_chain(mirror_top_bs, target, errp) < 0) {
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
QTAILQ_INIT(&s->ops_in_flight);
|
||||
|
||||
@@ -2008,7 +2006,7 @@ fail:
|
||||
bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing,
|
||||
&error_abort);
|
||||
bdrv_replace_node(mirror_top_bs, bs, &error_abort);
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(bs);
|
||||
|
||||
bdrv_unref(mirror_top_bs);
|
||||
|
||||
@@ -1636,22 +1636,7 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (open_data_file && (flags & BDRV_O_NO_IO)) {
|
||||
/*
|
||||
* Don't open the data file for 'qemu-img info' so that it can be used
|
||||
* to verify that an untrusted qcow2 image doesn't refer to external
|
||||
* files.
|
||||
*
|
||||
* Note: This still makes has_data_file() return true.
|
||||
*/
|
||||
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
|
||||
s->data_file = NULL;
|
||||
} else {
|
||||
s->data_file = bs->file;
|
||||
}
|
||||
qdict_extract_subqdict(options, NULL, "data-file.");
|
||||
qdict_del(options, "data-file");
|
||||
} else if (open_data_file) {
|
||||
if (open_data_file) {
|
||||
/* Open external data file */
|
||||
bdrv_graph_co_rdunlock();
|
||||
s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs,
|
||||
@@ -2824,7 +2809,7 @@ qcow2_do_close(BlockDriverState *bs, bool close_data_file)
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_unref_child(bs, s->data_file);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
s->data_file = NULL;
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
}
|
||||
|
||||
@@ -1044,7 +1044,7 @@ close_exit:
|
||||
}
|
||||
bdrv_unref_child(bs, s->children[i]);
|
||||
}
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
g_free(s->children);
|
||||
g_free(opened);
|
||||
exit:
|
||||
@@ -1061,7 +1061,7 @@ static void quorum_close(BlockDriverState *bs)
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
bdrv_unref_child(bs, s->children[i]);
|
||||
}
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
g_free(s->children);
|
||||
}
|
||||
|
||||
@@ -568,7 +568,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
aio_context_release(aio_context);
|
||||
return;
|
||||
}
|
||||
@@ -579,7 +579,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
BDRV_CHILD_DATA, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
aio_context_release(aio_context);
|
||||
return;
|
||||
}
|
||||
@@ -592,7 +592,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
if (!top_bs || !bdrv_is_root_node(top_bs) ||
|
||||
!check_top_bs(top_bs, bs)) {
|
||||
error_setg(errp, "No top_bs or it is invalid");
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
reopen_backing_file(bs, false, NULL);
|
||||
aio_context_release(aio_context);
|
||||
return;
|
||||
@@ -600,7 +600,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
bdrv_op_block_all(top_bs, s->blocker);
|
||||
bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker);
|
||||
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
s->backup_job = backup_job_create(
|
||||
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
|
||||
@@ -696,7 +696,7 @@ static void replication_done(void *opaque, int ret)
|
||||
s->secondary_disk = NULL;
|
||||
bdrv_unref_child(bs, s->hidden_disk);
|
||||
s->hidden_disk = NULL;
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
s->error = 0;
|
||||
} else {
|
||||
|
||||
@@ -196,10 +196,8 @@ bdrv_snapshot_fallback(BlockDriverState *bs)
|
||||
int bdrv_can_snapshot(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
if (!drv || !bdrv_is_inserted(bs) || !bdrv_is_writable(bs)) {
|
||||
if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -294,7 +292,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
|
||||
/* .bdrv_open() will re-attach it */
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_unref_child(bs, fallback);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
|
||||
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
|
||||
@@ -631,6 +629,7 @@ int bdrv_all_goto_snapshot(const char *name,
|
||||
while (iterbdrvs) {
|
||||
BlockDriverState *bs = iterbdrvs->data;
|
||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||
int ret = 0;
|
||||
bool all_snapshots_includes_bs;
|
||||
|
||||
aio_context_acquire(ctx);
|
||||
@@ -638,8 +637,9 @@ int bdrv_all_goto_snapshot(const char *name,
|
||||
all_snapshots_includes_bs = bdrv_all_snapshots_includes_bs(bs);
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
ret = (devices || all_snapshots_includes_bs) ?
|
||||
bdrv_snapshot_goto(bs, name, errp) : 0;
|
||||
if (devices || all_snapshots_includes_bs) {
|
||||
ret = bdrv_snapshot_goto(bs, name, errp);
|
||||
}
|
||||
aio_context_release(ctx);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
|
||||
@@ -99,9 +99,9 @@ static int stream_prepare(Job *job)
|
||||
}
|
||||
}
|
||||
|
||||
bdrv_graph_wrlock(s->target_bs);
|
||||
bdrv_graph_wrlock(base);
|
||||
bdrv_set_backing_hd_drained(unfiltered_bs, base, &local_err);
|
||||
bdrv_graph_wrunlock(s->target_bs);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
/*
|
||||
* This call will do I/O, so the graph can change again from here on.
|
||||
@@ -369,7 +369,7 @@ void stream_start(const char *job_id, BlockDriverState *bs,
|
||||
bdrv_graph_wrlock(bs);
|
||||
if (block_job_add_bdrv(&s->common, "active node", bs, 0,
|
||||
basic_flags | BLK_PERM_WRITE, errp)) {
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -389,11 +389,11 @@ void stream_start(const char *job_id, BlockDriverState *bs,
|
||||
ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
||||
basic_flags, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
s->base_overlay = base_overlay;
|
||||
s->above_base = above_base;
|
||||
|
||||
38
block/vmdk.c
38
block/vmdk.c
@@ -283,7 +283,7 @@ static void vmdk_free_extents(BlockDriverState *bs)
|
||||
bdrv_unref_child(bs, e->file);
|
||||
}
|
||||
}
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
g_free(s->extents);
|
||||
}
|
||||
@@ -351,41 +351,29 @@ vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
int ret = 0;
|
||||
|
||||
size_t desc_buf_size;
|
||||
|
||||
if (s->desc_offset == 0) {
|
||||
desc_buf_size = bdrv_getlength(bs->file->bs);
|
||||
if (desc_buf_size > 16ULL << 20) {
|
||||
error_report("VMDK description file too big");
|
||||
return -EFBIG;
|
||||
}
|
||||
} else {
|
||||
desc_buf_size = DESC_SIZE;
|
||||
}
|
||||
|
||||
desc = g_malloc0(desc_buf_size);
|
||||
tmp_desc = g_malloc0(desc_buf_size);
|
||||
ret = bdrv_co_pread(bs->file, s->desc_offset, desc_buf_size, desc, 0);
|
||||
desc = g_malloc0(DESC_SIZE);
|
||||
tmp_desc = g_malloc0(DESC_SIZE);
|
||||
ret = bdrv_co_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
desc[desc_buf_size - 1] = '\0';
|
||||
desc[DESC_SIZE - 1] = '\0';
|
||||
tmp_str = strstr(desc, "parentCID");
|
||||
if (tmp_str == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pstrcpy(tmp_desc, desc_buf_size, tmp_str);
|
||||
pstrcpy(tmp_desc, DESC_SIZE, tmp_str);
|
||||
p_name = strstr(desc, "CID");
|
||||
if (p_name != NULL) {
|
||||
p_name += sizeof("CID");
|
||||
snprintf(p_name, desc_buf_size - (p_name - desc), "%" PRIx32 "\n", cid);
|
||||
pstrcat(desc, desc_buf_size, tmp_desc);
|
||||
snprintf(p_name, DESC_SIZE - (p_name - desc), "%" PRIx32 "\n", cid);
|
||||
pstrcat(desc, DESC_SIZE, tmp_desc);
|
||||
}
|
||||
|
||||
ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, desc_buf_size, desc, 0);
|
||||
ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
|
||||
|
||||
out:
|
||||
g_free(desc);
|
||||
@@ -1249,7 +1237,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_unref_child(bs, extent_file);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
goto out;
|
||||
}
|
||||
@@ -1268,7 +1256,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_unref_child(bs, extent_file);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
goto out;
|
||||
}
|
||||
@@ -1279,7 +1267,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_unref_child(bs, extent_file);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
goto out;
|
||||
}
|
||||
@@ -1289,7 +1277,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_graph_wrlock(NULL);
|
||||
bdrv_unref_child(bs, extent_file);
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
ret = -ENOTSUP;
|
||||
goto out;
|
||||
|
||||
@@ -1613,7 +1613,7 @@ static void external_snapshot_abort(void *opaque)
|
||||
bdrv_drained_begin(state->new_bs);
|
||||
bdrv_graph_wrlock(state->old_bs);
|
||||
bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
|
||||
bdrv_graph_wrunlock(state->old_bs);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(state->new_bs);
|
||||
|
||||
bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */
|
||||
@@ -2400,9 +2400,8 @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
|
||||
|
||||
bdrv_co_lock(bs);
|
||||
bdrv_drained_end(bs);
|
||||
bdrv_co_unlock(bs);
|
||||
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unlock(bs);
|
||||
}
|
||||
|
||||
void qmp_block_stream(const char *job_id, const char *device,
|
||||
@@ -3693,7 +3692,7 @@ void qmp_x_blockdev_change(const char *parent, const char *child,
|
||||
}
|
||||
|
||||
out:
|
||||
bdrv_graph_wrunlock(NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
}
|
||||
|
||||
BlockJobInfoList *qmp_query_block_jobs(Error **errp)
|
||||
|
||||
@@ -212,7 +212,7 @@ void block_job_remove_all_bdrv(BlockJob *job)
|
||||
|
||||
g_slist_free_1(l);
|
||||
}
|
||||
bdrv_graph_wrunlock_ctx(job->job.aio_context);
|
||||
bdrv_graph_wrunlock();
|
||||
}
|
||||
|
||||
bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs)
|
||||
@@ -523,7 +523,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||
job = job_create(job_id, &driver->job_driver, txn, bdrv_get_aio_context(bs),
|
||||
flags, cb, opaque, errp);
|
||||
if (job == NULL) {
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -563,11 +563,11 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
return job;
|
||||
|
||||
fail:
|
||||
bdrv_graph_wrunlock(bs);
|
||||
bdrv_graph_wrunlock();
|
||||
job_early_fail(&job->job);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ static inline abi_long do_obreak(abi_ulong brk_val)
|
||||
return target_brk;
|
||||
}
|
||||
|
||||
/* Release heap if necessary */
|
||||
/* Release heap if necesary */
|
||||
if (new_brk < old_brk) {
|
||||
target_munmap(new_brk, old_brk - new_brk);
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
|
||||
}
|
||||
|
||||
qarg0 = argp = g_new0(char *, argc + 9);
|
||||
/* save the first argument for the emulator */
|
||||
/* save the first agrument for the emulator */
|
||||
*argp++ = (char *)getprogname();
|
||||
qargp = argp;
|
||||
*argp++ = (char *)getprogname();
|
||||
|
||||
@@ -146,7 +146,7 @@ static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* undocumented nstat(char *path, struct nstat *ub) syscall */
|
||||
/* undocummented nstat(char *path, struct nstat *ub) syscall */
|
||||
static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2)
|
||||
{
|
||||
abi_long ret;
|
||||
@@ -162,7 +162,7 @@ static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* undocumented nfstat(int fd, struct nstat *sb) syscall */
|
||||
/* undocummented nfstat(int fd, struct nstat *sb) syscall */
|
||||
static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2)
|
||||
{
|
||||
abi_long ret;
|
||||
@@ -175,7 +175,7 @@ static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* undocumented nlstat(char *path, struct nstat *ub) syscall */
|
||||
/* undocummented nlstat(char *path, struct nstat *ub) syscall */
|
||||
static abi_long do_freebsd11_nlstat(abi_long arg1, abi_long arg2)
|
||||
{
|
||||
abi_long ret;
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
/* init terminal so that we can grab keys */
|
||||
static struct termios oldtty;
|
||||
static int old_fd0_flags;
|
||||
static int old_fd1_flags;
|
||||
static bool stdio_in_use;
|
||||
static bool stdio_allow_signal;
|
||||
static bool stdio_echo_state;
|
||||
@@ -51,8 +50,6 @@ static void term_exit(void)
|
||||
if (stdio_in_use) {
|
||||
tcsetattr(0, TCSANOW, &oldtty);
|
||||
fcntl(0, F_SETFL, old_fd0_flags);
|
||||
fcntl(1, F_SETFL, old_fd1_flags);
|
||||
stdio_in_use = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +102,6 @@ static void qemu_chr_open_stdio(Chardev *chr,
|
||||
|
||||
stdio_in_use = true;
|
||||
old_fd0_flags = fcntl(0, F_GETFL);
|
||||
old_fd1_flags = fcntl(1, F_GETFL);
|
||||
tcgetattr(0, &oldtty);
|
||||
if (!g_unix_set_fd_nonblocking(0, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
|
||||
@@ -518,7 +518,7 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp)
|
||||
|
||||
if (object_class_is_abstract(oc)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
|
||||
"a non-abstract device type");
|
||||
"an abstract device type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
42
configure
vendored
42
configure
vendored
@@ -41,7 +41,12 @@ then
|
||||
# This file is auto-generated by configure to support in-source tree
|
||||
# 'make' command invocation
|
||||
|
||||
build:
|
||||
ifeq ($(MAKECMDGOALS),)
|
||||
recurse: all
|
||||
endif
|
||||
|
||||
.NOTPARALLEL: %
|
||||
%: force
|
||||
@echo 'changing dir to build for $(MAKE) "$(MAKECMDGOALS)"...'
|
||||
@$(MAKE) -C build -f Makefile $(MAKECMDGOALS)
|
||||
@if test "$(MAKECMDGOALS)" = "distclean" && \
|
||||
@@ -49,9 +54,8 @@ build:
|
||||
then \
|
||||
rm -rf build GNUmakefile ; \
|
||||
fi
|
||||
%: build
|
||||
@
|
||||
.PHONY: build
|
||||
force: ;
|
||||
.PHONY: force
|
||||
GNUmakefile: ;
|
||||
|
||||
EOF
|
||||
@@ -411,9 +415,7 @@ else
|
||||
# Using uname is really broken, but it is just a fallback for architectures
|
||||
# that are going to use TCI anyway
|
||||
cpu=$(uname -m)
|
||||
if test "$host_os" != "bogus"; then
|
||||
echo "WARNING: unrecognized host CPU, proceeding with 'uname -m' output '$cpu'"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Normalise host CPU name to the values used by Meson cross files and in source
|
||||
@@ -763,7 +765,7 @@ for opt do
|
||||
--*) meson_option_parse "$opt" "$optarg"
|
||||
;;
|
||||
# Pass through -Dxxxx options to meson
|
||||
-D*) meson_option_add "$opt"
|
||||
-D*) meson_options="$meson_options $opt"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -895,13 +897,6 @@ EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Now that we are sure that the user did not only want to print the --help
|
||||
# information, we should double-check that the C compiler really works:
|
||||
write_c_skeleton
|
||||
if ! compile_object ; then
|
||||
error_exit "C compiler \"$cc\" either does not exist or does not work."
|
||||
fi
|
||||
|
||||
# Remove old dependency files to make sure that they get properly regenerated
|
||||
rm -f ./*/config-devices.mak.d
|
||||
|
||||
@@ -973,14 +968,14 @@ meson="$(cd pyvenv/bin; pwd)/meson"
|
||||
|
||||
# Conditionally ensure Sphinx is installed.
|
||||
|
||||
mkvenv_online_flag=""
|
||||
if test "$download" = "enabled" ; then
|
||||
mkvenv_online_flag=" --online"
|
||||
mkvenv_flags=""
|
||||
if test "$download" = "enabled" -a "$docs" = "enabled" ; then
|
||||
mkvenv_flags="--online"
|
||||
fi
|
||||
|
||||
if test "$docs" != "disabled" ; then
|
||||
if ! $mkvenv ensuregroup \
|
||||
$(test "$docs" = "enabled" && echo "$mkvenv_online_flag") \
|
||||
$mkvenv_flags \
|
||||
${source_path}/pythondeps.toml docs;
|
||||
then
|
||||
if test "$docs" = "enabled" ; then
|
||||
@@ -1312,8 +1307,8 @@ probe_target_compiler() {
|
||||
container_cross_cc=${container_cross_prefix}gcc
|
||||
;;
|
||||
i386)
|
||||
container_image=debian-i686-cross
|
||||
container_cross_prefix=i686-linux-gnu-
|
||||
container_image=fedora-i386-cross
|
||||
container_cross_prefix=
|
||||
;;
|
||||
loongarch64)
|
||||
container_image=debian-loongarch-cross
|
||||
@@ -1396,8 +1391,6 @@ probe_target_compiler() {
|
||||
done
|
||||
|
||||
try=cross
|
||||
# For softmmu/roms also look for a bi-endian or multilib-enabled host compiler
|
||||
if [ "${1%softmmu}" != "$1" ] || test "$target_arch" = "$cpu"; then
|
||||
case "$target_arch:$cpu" in
|
||||
aarch64_be:aarch64 | \
|
||||
armeb:arm | \
|
||||
@@ -1408,7 +1401,6 @@ probe_target_compiler() {
|
||||
"$cpu:$cpu")
|
||||
try='native cross' ;;
|
||||
esac
|
||||
fi
|
||||
eval "target_cflags=\${cross_cc_cflags_$target_arch}"
|
||||
for thistry in $try; do
|
||||
case $thistry in
|
||||
@@ -1639,7 +1631,6 @@ if test "$container" != no; then
|
||||
fi
|
||||
echo "SUBDIRS=$subdirs" >> $config_host_mak
|
||||
echo "PYTHON=$python" >> $config_host_mak
|
||||
echo "MKVENV_ENSUREGROUP=$mkvenv ensuregroup $mkvenv_online_flag" >> $config_host_mak
|
||||
echo "GENISOIMAGE=$genisoimage" >> $config_host_mak
|
||||
echo "MESON=$meson" >> $config_host_mak
|
||||
echo "NINJA=$ninja" >> $config_host_mak
|
||||
@@ -1684,9 +1675,6 @@ fi
|
||||
mkdir -p tests/tcg
|
||||
echo "# Automatically generated by configure - do not modify" > $config_host_mak
|
||||
echo "SRC_PATH=$source_path" >> $config_host_mak
|
||||
if test "$plugins" = "yes" ; then
|
||||
echo "CONFIG_PLUGIN=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
tcg_tests_targets=
|
||||
for target in $target_list; do
|
||||
|
||||
@@ -49,7 +49,7 @@ all: $(SONAMES)
|
||||
$(CC) $(CFLAGS) $(PLUGIN_CFLAGS) -c -o $@ $<
|
||||
|
||||
ifeq ($(CONFIG_WIN32),y)
|
||||
lib%$(SO_SUFFIX): %.o win32_linker.o ../../plugins/libqemu_plugin_api.a
|
||||
lib%$(SO_SUFFIX): %.o win32_linker.o ../../plugins/qemu_plugin_api.lib
|
||||
$(CC) -shared -o $@ $^ $(LDLIBS)
|
||||
else ifeq ($(CONFIG_DARWIN),y)
|
||||
lib%$(SO_SUFFIX): %.o
|
||||
|
||||
@@ -327,7 +327,7 @@ virgl_get_resource_info_modifiers(uint32_t resource_id,
|
||||
#ifdef VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION
|
||||
struct virgl_renderer_resource_info_ext info_ext;
|
||||
ret = virgl_renderer_resource_get_info_ext(resource_id, &info_ext);
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ virgl_get_resource_info_modifiers(uint32_t resource_id,
|
||||
*modifiers = info_ext.modifiers;
|
||||
#else
|
||||
ret = virgl_renderer_resource_get_info(resource_id, info);
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ virgl_cmd_set_scanout(VuGpu *g,
|
||||
uint64_t modifiers = 0;
|
||||
ret = virgl_get_resource_info_modifiers(ss.resource_id, &info,
|
||||
&modifiers);
|
||||
if (ret) {
|
||||
if (ret == -1) {
|
||||
g_critical("%s: illegal resource specified %d\n",
|
||||
__func__, ss.resource_id);
|
||||
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
|
||||
@@ -401,7 +401,7 @@ virgl_cmd_set_scanout(VuGpu *g,
|
||||
|
||||
if (g->use_modifiers) {
|
||||
/*
|
||||
* The message uses all the fields set in dmabuf_scanout plus
|
||||
* The mesage uses all the fields set in dmabuf_scanout plus
|
||||
* modifiers which is appended after VhostUserGpuDMABUFScanout.
|
||||
*/
|
||||
msg.request = VHOST_USER_GPU_DMABUF_SCANOUT2;
|
||||
|
||||
26
disas/cris.c
26
disas/cris.c
@@ -1731,10 +1731,10 @@ format_hex (unsigned long number,
|
||||
unsigned (== 0). */
|
||||
|
||||
static char *
|
||||
format_dec (long number, char *outbuffer, size_t outsize, int signedp)
|
||||
format_dec (long number, char *outbuffer, int signedp)
|
||||
{
|
||||
last_immediate = number;
|
||||
snprintf (outbuffer, outsize, signedp ? "%ld" : "%lu", number);
|
||||
sprintf (outbuffer, signedp ? "%ld" : "%lu", number);
|
||||
|
||||
return outbuffer + strlen (outbuffer);
|
||||
}
|
||||
@@ -1876,12 +1876,6 @@ print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp)
|
||||
return cp;
|
||||
}
|
||||
|
||||
#define FORMAT_DEC(number, tp, signedp) \
|
||||
format_dec (number, tp, ({ \
|
||||
assert(tp >= temp && tp <= temp + sizeof(temp)); \
|
||||
temp + sizeof(temp) - tp; \
|
||||
}), signedp)
|
||||
|
||||
/* Print out an insn with its operands, and update the info->insn_type
|
||||
fields. The prefix_opcodep and the rest hold a prefix insn that is
|
||||
supposed to be output as an address mode. */
|
||||
@@ -2111,7 +2105,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
||||
if ((*cs == 'z' && (insn & 0x20))
|
||||
|| (opcodep->match == BDAP_QUICK_OPCODE
|
||||
&& (nbytes <= 2 || buffer[1 + nbytes] == 0)))
|
||||
tp = FORMAT_DEC (number, tp, signedp);
|
||||
tp = format_dec (number, tp, signedp);
|
||||
else
|
||||
{
|
||||
unsigned int highbyte = (number >> 24) & 0xff;
|
||||
@@ -2247,7 +2241,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
||||
with_reg_prefix);
|
||||
if (number >= 0)
|
||||
*tp++ = '+';
|
||||
tp = FORMAT_DEC (number, tp, 1);
|
||||
tp = format_dec (number, tp, 1);
|
||||
|
||||
info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
|
||||
info->target = (prefix_insn >> 12) & 15;
|
||||
@@ -2346,7 +2340,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
||||
{
|
||||
if (number >= 0)
|
||||
*tp++ = '+';
|
||||
tp = FORMAT_DEC (number, tp, 1);
|
||||
tp = format_dec (number, tp, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2403,7 +2397,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
tp = FORMAT_DEC (insn & 63, tp, 0);
|
||||
tp = format_dec (insn & 63, tp, 0);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
@@ -2432,11 +2426,11 @@ print_with_operands (const struct cris_opcode *opcodep,
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
tp = FORMAT_DEC (insn & 31, tp, 0);
|
||||
tp = format_dec (insn & 31, tp, 0);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
tp = FORMAT_DEC (insn & 15, tp, 0);
|
||||
tp = format_dec (insn & 15, tp, 0);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
@@ -2469,7 +2463,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
||||
if (number > 127)
|
||||
number = number - 256;
|
||||
|
||||
tp = FORMAT_DEC (number, tp, 1);
|
||||
tp = format_dec (number, tp, 1);
|
||||
*tp++ = ',';
|
||||
tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
|
||||
}
|
||||
@@ -2480,7 +2474,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
tp = FORMAT_DEC ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1);
|
||||
tp = format_dec ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1);
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
|
||||
@@ -1968,10 +1968,6 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info)
|
||||
|
||||
insn = bfd_getb32 (buffer);
|
||||
|
||||
info->fprintf_func(info->stream, " %02x %02x %02x %02x ",
|
||||
(insn >> 24) & 0xff, (insn >> 16) & 0xff,
|
||||
(insn >> 8) & 0xff, insn & 0xff);
|
||||
|
||||
for (i = 0; i < NUMOPCODES; ++i)
|
||||
{
|
||||
const struct pa_opcode *opcode = &pa_opcodes[i];
|
||||
@@ -2830,6 +2826,6 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info)
|
||||
return sizeof (insn);
|
||||
}
|
||||
}
|
||||
info->fprintf_func(info->stream, "<unknown>");
|
||||
(*info->fprintf_func) (info->stream, "#%8x", insn);
|
||||
return sizeof (insn);
|
||||
}
|
||||
|
||||
@@ -2184,22 +2184,7 @@ static const char *csr_name(int csrno)
|
||||
case 0x0383: return "mibound";
|
||||
case 0x0384: return "mdbase";
|
||||
case 0x0385: return "mdbound";
|
||||
case 0x03a0: return "pmpcfg0";
|
||||
case 0x03a1: return "pmpcfg1";
|
||||
case 0x03a2: return "pmpcfg2";
|
||||
case 0x03a3: return "pmpcfg3";
|
||||
case 0x03a4: return "pmpcfg4";
|
||||
case 0x03a5: return "pmpcfg5";
|
||||
case 0x03a6: return "pmpcfg6";
|
||||
case 0x03a7: return "pmpcfg7";
|
||||
case 0x03a8: return "pmpcfg8";
|
||||
case 0x03a9: return "pmpcfg9";
|
||||
case 0x03aa: return "pmpcfg10";
|
||||
case 0x03ab: return "pmpcfg11";
|
||||
case 0x03ac: return "pmpcfg12";
|
||||
case 0x03ad: return "pmpcfg13";
|
||||
case 0x03ae: return "pmpcfg14";
|
||||
case 0x03af: return "pmpcfg15";
|
||||
case 0x03a0: return "pmpcfg3";
|
||||
case 0x03b0: return "pmpaddr0";
|
||||
case 0x03b1: return "pmpaddr1";
|
||||
case 0x03b2: return "pmpaddr2";
|
||||
@@ -2216,54 +2201,6 @@ static const char *csr_name(int csrno)
|
||||
case 0x03bd: return "pmpaddr13";
|
||||
case 0x03be: return "pmpaddr14";
|
||||
case 0x03bf: return "pmpaddr15";
|
||||
case 0x03c0: return "pmpaddr16";
|
||||
case 0x03c1: return "pmpaddr17";
|
||||
case 0x03c2: return "pmpaddr18";
|
||||
case 0x03c3: return "pmpaddr19";
|
||||
case 0x03c4: return "pmpaddr20";
|
||||
case 0x03c5: return "pmpaddr21";
|
||||
case 0x03c6: return "pmpaddr22";
|
||||
case 0x03c7: return "pmpaddr23";
|
||||
case 0x03c8: return "pmpaddr24";
|
||||
case 0x03c9: return "pmpaddr25";
|
||||
case 0x03ca: return "pmpaddr26";
|
||||
case 0x03cb: return "pmpaddr27";
|
||||
case 0x03cc: return "pmpaddr28";
|
||||
case 0x03cd: return "pmpaddr29";
|
||||
case 0x03ce: return "pmpaddr30";
|
||||
case 0x03cf: return "pmpaddr31";
|
||||
case 0x03d0: return "pmpaddr32";
|
||||
case 0x03d1: return "pmpaddr33";
|
||||
case 0x03d2: return "pmpaddr34";
|
||||
case 0x03d3: return "pmpaddr35";
|
||||
case 0x03d4: return "pmpaddr36";
|
||||
case 0x03d5: return "pmpaddr37";
|
||||
case 0x03d6: return "pmpaddr38";
|
||||
case 0x03d7: return "pmpaddr39";
|
||||
case 0x03d8: return "pmpaddr40";
|
||||
case 0x03d9: return "pmpaddr41";
|
||||
case 0x03da: return "pmpaddr42";
|
||||
case 0x03db: return "pmpaddr43";
|
||||
case 0x03dc: return "pmpaddr44";
|
||||
case 0x03dd: return "pmpaddr45";
|
||||
case 0x03de: return "pmpaddr46";
|
||||
case 0x03df: return "pmpaddr47";
|
||||
case 0x03e0: return "pmpaddr48";
|
||||
case 0x03e1: return "pmpaddr49";
|
||||
case 0x03e2: return "pmpaddr50";
|
||||
case 0x03e3: return "pmpaddr51";
|
||||
case 0x03e4: return "pmpaddr52";
|
||||
case 0x03e5: return "pmpaddr53";
|
||||
case 0x03e6: return "pmpaddr54";
|
||||
case 0x03e7: return "pmpaddr55";
|
||||
case 0x03e8: return "pmpaddr56";
|
||||
case 0x03e9: return "pmpaddr57";
|
||||
case 0x03ea: return "pmpaddr58";
|
||||
case 0x03eb: return "pmpaddr59";
|
||||
case 0x03ec: return "pmpaddr60";
|
||||
case 0x03ed: return "pmpaddr61";
|
||||
case 0x03ee: return "pmpaddr62";
|
||||
case 0x03ef: return "pmpaddr63";
|
||||
case 0x0780: return "mtohost";
|
||||
case 0x0781: return "mfromhost";
|
||||
case 0x0782: return "mreset";
|
||||
|
||||
@@ -236,16 +236,6 @@ it. Since all recent x86 hardware from the past >10 years is capable of the
|
||||
64-bit x86 extensions, a corresponding 64-bit OS should be used instead.
|
||||
|
||||
|
||||
System emulator CPUs
|
||||
--------------------
|
||||
|
||||
Nios II CPU (since 8.2)
|
||||
'''''''''''''''''''''''
|
||||
|
||||
The Nios II architecture is orphan. The ``nios2`` guest CPU support is
|
||||
deprecated and will be removed in a future version of QEMU.
|
||||
|
||||
|
||||
System emulator machines
|
||||
------------------------
|
||||
|
||||
@@ -264,11 +254,6 @@ These old machine types are quite neglected nowadays and thus might have
|
||||
various pitfalls with regards to live migration. Use a newer machine type
|
||||
instead.
|
||||
|
||||
Nios II ``10m50-ghrd`` and ``nios2-generic-nommu`` machines (since 8.2)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The Nios II architecture is orphan.
|
||||
|
||||
|
||||
Backend options
|
||||
---------------
|
||||
@@ -529,5 +514,5 @@ old compression method (since 8.2)
|
||||
|
||||
Compression method fails too much. Too many races. We are going to
|
||||
remove it if nobody fixes it. For starters, migration-test
|
||||
compression tests are disabled because they fail randomly. If you need
|
||||
compression tests are disabled becase they fail randomly. If you need
|
||||
compression, use multifd compression methods.
|
||||
|
||||
@@ -129,9 +129,8 @@ causing most hypervisors to trap and fault on them.
|
||||
.. warning::
|
||||
Semihosting inherently bypasses any isolation there may be between
|
||||
the guest and the host. As a result a program using semihosting can
|
||||
happily trash your host system. Some semihosting calls (e.g.
|
||||
``SYS_READC``) can block execution indefinitely. You should only
|
||||
ever run trusted code with semihosting enabled.
|
||||
happily trash your host system. You should only ever run trusted
|
||||
code with semihosting enabled.
|
||||
|
||||
Redirection
|
||||
~~~~~~~~~~~
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
import os
|
||||
import sys
|
||||
import sphinx
|
||||
from distutils.version import LooseVersion
|
||||
from sphinx.errors import ConfigError
|
||||
|
||||
# The per-manual conf.py will set qemu_docdir for a single-manual build;
|
||||
@@ -164,10 +165,11 @@ html_theme = 'sphinx_rtd_theme'
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
html_theme_options = {
|
||||
if LooseVersion(sphinx_rtd_theme.__version__) >= LooseVersion("0.4.3"):
|
||||
html_theme_options = {
|
||||
"style_nav_header_background": "#802400",
|
||||
"navigation_with_keys": True,
|
||||
}
|
||||
}
|
||||
|
||||
html_logo = os.path.join(qemu_docdir, "../ui/icons/qemu_128x128.png")
|
||||
|
||||
|
||||
@@ -122,78 +122,10 @@ functioning. These are performed using a few more helper functions:
|
||||
indicated by $TMPC.
|
||||
|
||||
|
||||
Python virtual environments and the build process
|
||||
-------------------------------------------------
|
||||
|
||||
An important step in ``configure`` is to create a Python virtual
|
||||
environment (venv) during the configuration phase. The Python interpreter
|
||||
comes from the ``--python`` command line option, the ``$PYTHON`` variable
|
||||
from the environment, or the system PATH, in this order. The venv resides
|
||||
in the ``pyvenv`` directory in the build tree, and provides consistency
|
||||
in how the build process runs Python code.
|
||||
|
||||
At this stage, ``configure`` also queries the chosen Python interpreter
|
||||
about QEMU's build dependencies. Note that the build process does *not*
|
||||
look for ``meson``, ``sphinx-build`` or ``avocado`` binaries in the PATH;
|
||||
likewise, there are no options such as ``--meson`` or ``--sphinx-build``.
|
||||
This avoids a potential mismatch, where Meson and Sphinx binaries on the
|
||||
PATH might operate in a different Python environment than the one chosen
|
||||
by the user during the build process. On the other hand, it introduces
|
||||
a potential source of confusion where the user installs a dependency but
|
||||
``configure`` is not able to find it. When this happens, the dependency
|
||||
was installed in the ``site-packages`` directory of another interpreter,
|
||||
or with the wrong ``pip`` program.
|
||||
|
||||
If a package is available for the chosen interpreter, ``configure``
|
||||
prepares a small script that invokes it from the venv itself[#distlib]_.
|
||||
If not, ``configure`` can also optionally install dependencies in the
|
||||
virtual environment with ``pip``, either from wheels in ``python/wheels``
|
||||
or by downloading the package with PyPI. Downloading can be disabled with
|
||||
``--disable-download``; and anyway, it only happens when a ``configure``
|
||||
option (currently, only ``--enable-docs``) is explicitly enabled but
|
||||
the dependencies are not present[#pip]_.
|
||||
|
||||
.. [#distlib] The scripts are created based on the package's metadata,
|
||||
specifically the ``console_script`` entry points. This is the
|
||||
same mechanism that ``pip`` uses when installing a package.
|
||||
Currently, in all cases it would be possible to use ``python -m``
|
||||
instead of an entry point script, which makes this approach a
|
||||
bit overkill. On the other hand, creating the scripts is
|
||||
future proof and it makes the contents of the ``pyvenv/bin``
|
||||
directory more informative. Portability is also not an issue,
|
||||
because the Python Packaging Authority provides a package
|
||||
``distlib.scripts`` to perform this task.
|
||||
|
||||
.. [#pip] ``pip`` might also be used when running ``make check-avocado``
|
||||
if downloading is enabled, to ensure that Avocado is
|
||||
available.
|
||||
|
||||
The required versions of the packages are stored in a configuration file
|
||||
``pythondeps.toml``. The format is custom to QEMU, but it is documented
|
||||
at the top of the file itself and it should be easy to understand. The
|
||||
requirements should make it possible to use the version that is packaged
|
||||
that is provided by supported distros.
|
||||
|
||||
When dependencies are downloaded, instead, ``configure`` uses a "known
|
||||
good" version that is also listed in ``pythondeps.toml``. In this
|
||||
scenario, ``pythondeps.toml`` behaves like the "lock file" used by
|
||||
``cargo``, ``poetry`` or other dependency management systems.
|
||||
|
||||
|
||||
Bundled Python packages
|
||||
-----------------------
|
||||
|
||||
Python packages that are **mandatory** dependencies to build QEMU,
|
||||
but are not available in all supported distros, are bundled with the
|
||||
QEMU sources. Currently this includes Meson (outdated in CentOS 8
|
||||
and derivatives, Ubuntu 20.04 and 22.04, and openSUSE Leap) and tomli
|
||||
(absent in Ubuntu 20.04).
|
||||
|
||||
If you need to update these, please do so by modifying and rerunning
|
||||
``python/scripts/vendor.py``. This script embeds the sha256 hash of
|
||||
package sources and checks it. The pypi.org web site provides an easy
|
||||
way to retrieve the sha256 hash of the sources.
|
||||
Python virtual environments and the QEMU build system
|
||||
-----------------------------------------------------
|
||||
|
||||
TBD
|
||||
|
||||
Stage 2: Meson
|
||||
==============
|
||||
@@ -444,15 +376,6 @@ This is needed to obey the --python= option passed to the configure
|
||||
script, which may point to something other than the first python3
|
||||
binary on the path.
|
||||
|
||||
By the time Meson runs, Python dependencies are available in the virtual
|
||||
environment and should be invoked through the scripts that ``configure``
|
||||
places under ``pyvenv``. One way to do so is as follows, using Meson's
|
||||
``find_program`` function::
|
||||
|
||||
sphinx_build = find_program(
|
||||
fs.parent(python.full_path()) / 'sphinx-build',
|
||||
required: get_option('docs'))
|
||||
|
||||
|
||||
Stage 3: Make
|
||||
=============
|
||||
@@ -511,11 +434,6 @@ number of dynamically created files listed later.
|
||||
executables. Build rules for various subdirectories are included in
|
||||
other meson.build files spread throughout the QEMU source tree.
|
||||
|
||||
``python/scripts/mkvenv.py``
|
||||
A wrapper for the Python ``venv`` and ``distlib.scripts`` packages.
|
||||
It handles creating the virtual environment, creating scripts in
|
||||
``pyvenv/bin``, and calling ``pip`` to install dependencies.
|
||||
|
||||
``tests/Makefile.include``
|
||||
Rules for external test harnesses. These include the TCG tests
|
||||
and the Avocado-based integration tests.
|
||||
|
||||
@@ -572,6 +572,27 @@ Others (especially either older devices or system devices which for
|
||||
some reason don't have a bus concept) make use of the ``instance id``
|
||||
for otherwise identically named devices.
|
||||
|
||||
Fixed-ram format
|
||||
----------------
|
||||
|
||||
When the ``fixed-ram`` capability is enabled, a slightly different
|
||||
stream format is used for the RAM section. Instead of having a
|
||||
sequential stream of pages that follow the RAMBlock headers, the dirty
|
||||
pages for a RAMBlock follow its header. This ensures that each RAM
|
||||
page has a fixed offset in the resulting migration file.
|
||||
|
||||
The ``fixed-ram`` capability must be enabled in both source and
|
||||
destination with:
|
||||
|
||||
``migrate_set_capability fixed-ram on``
|
||||
|
||||
Since pages are written to their relatives offsets and out of order
|
||||
(due to the memory dirtying patterns), streaming channels such as
|
||||
sockets are not supported. A seekable channel such as a file is
|
||||
required. This can be verified in the QIOChannel by the presence of
|
||||
the QIO_CHANNEL_FEATURE_SEEKABLE. In more practical terms, this
|
||||
migration format requires the ``file:`` URI when migrating.
|
||||
|
||||
Return path
|
||||
-----------
|
||||
|
||||
@@ -1061,7 +1082,7 @@ QEMU version, in this case pc-5.1.
|
||||
|
||||
4 - qemu-5.1 -M pc-5.2 -> migrates to -> qemu-5.1 -M pc-5.2
|
||||
|
||||
This combination is not possible as the qemu-5.1 doesn't understand
|
||||
This combination is not possible as the qemu-5.1 doen't understand
|
||||
pc-5.2 machine type. So nothing to worry here.
|
||||
|
||||
Now it comes the interesting ones, when both QEMU processes are
|
||||
@@ -1214,8 +1235,8 @@ machine types to have the right value::
|
||||
...
|
||||
};
|
||||
|
||||
A device with different features on both sides
|
||||
----------------------------------------------
|
||||
A device with diferent features on both sides
|
||||
---------------------------------------------
|
||||
|
||||
Let's assume that we are using the same QEMU binary on both sides,
|
||||
just to make the things easier. But we have a device that has
|
||||
@@ -1294,12 +1315,12 @@ Host B:
|
||||
|
||||
$ qemu-system-x86_64 -cpu host,taa-no=off
|
||||
|
||||
And you would be able to migrate between them. It is responsibility
|
||||
And you would be able to migrate between them. It is responsability
|
||||
of the management application or of the user to make sure that the
|
||||
configuration is correct. QEMU doesn't know how to look at this kind
|
||||
of features in general.
|
||||
|
||||
Notice that we don't recommend to use -cpu host for migration. It is
|
||||
Notice that we don't recomend to use -cpu host for migration. It is
|
||||
used in this example because it makes the example simpler.
|
||||
|
||||
Other devices have worse control about individual features. If they
|
||||
|
||||
@@ -15,7 +15,7 @@ have default values:
|
||||
-smp 1,drawers=3,books=3,sockets=2,cores=2,maxcpus=36 \
|
||||
-device z14-s390x-cpu,core-id=19,entitlement=high \
|
||||
-device z14-s390x-cpu,core-id=11,entitlement=low \
|
||||
-device z14-s390x-cpu,core-id=12,entitlement=high \
|
||||
-device z14-s390x-cpu,core-id=112,entitlement=high \
|
||||
...
|
||||
|
||||
Additions to query-cpus-fast
|
||||
@@ -78,7 +78,7 @@ modifiers for all configured vCPUs.
|
||||
"dedicated": true,
|
||||
"thread-id": 537005,
|
||||
"props": {
|
||||
"core-id": 12,
|
||||
"core-id": 112,
|
||||
"socket-id": 0,
|
||||
"drawer-id": 3,
|
||||
"book-id": 2
|
||||
@@ -86,7 +86,7 @@ modifiers for all configured vCPUs.
|
||||
"cpu-state": "operating",
|
||||
"entitlement": "high",
|
||||
"qom-path": "/machine/peripheral-anon/device[2]",
|
||||
"cpu-index": 12,
|
||||
"cpu-index": 112,
|
||||
"target": "s390x"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -62,6 +62,12 @@ To deal with this case, when an I/O access is made we:
|
||||
- re-compile a single [1]_ instruction block for the current PC
|
||||
- exit the cpu loop and execute the re-compiled block
|
||||
|
||||
The new block is created with the CF_LAST_IO compile flag which
|
||||
ensures the final instruction translation starts with a call to
|
||||
gen_io_start() so we don't enter a perpetual loop constantly
|
||||
recompiling a single instruction block. For translators using the
|
||||
common translator_loop this is done automatically.
|
||||
|
||||
.. [1] sometimes two instructions if dealing with delay slots
|
||||
|
||||
Other I/O operations
|
||||
|
||||
@@ -668,11 +668,11 @@ suppressing it. More information on the file format can be found here:
|
||||
|
||||
https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions
|
||||
|
||||
tests/tsan/ignore.tsan - Has TSan warnings we wish to disable
|
||||
tests/tsan/blacklist.tsan - Has TSan warnings we wish to disable
|
||||
at compile time for test or debug.
|
||||
Add flags to configure to enable:
|
||||
|
||||
"--extra-cflags=-fsanitize-blacklist=<src path>/tests/tsan/ignore.tsan"
|
||||
"--extra-cflags=-fsanitize-blacklist=<src path>/tests/tsan/blacklist.tsan"
|
||||
|
||||
More information on the file format can be found here under "Blacklist Format":
|
||||
|
||||
@@ -1016,7 +1016,7 @@ class. Here's a simple usage example:
|
||||
self.vm.launch()
|
||||
res = self.vm.cmd('human-monitor-command',
|
||||
command_line='info version')
|
||||
self.assertRegex(res, r'^(\d+\.\d+\.\d)')
|
||||
self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
|
||||
|
||||
To execute your test, run:
|
||||
|
||||
@@ -1077,7 +1077,7 @@ and hypothetical example follows:
|
||||
'human-monitor-command',
|
||||
command_line='info version')
|
||||
|
||||
self.assertEqual(first_res, second_res, third_res)
|
||||
self.assertEquals(first_res, second_res, third_res)
|
||||
|
||||
At test "tear down", ``avocado_qemu.Test`` handles all the QEMUMachines
|
||||
shutdown.
|
||||
@@ -1371,33 +1371,23 @@ conditions. For example, tests that take longer to execute when QEMU is
|
||||
compiled with debug flags. Therefore, the ``AVOCADO_TIMEOUT_EXPECTED`` variable
|
||||
has been used to determine whether those tests should run or not.
|
||||
|
||||
QEMU_TEST_FLAKY_TESTS
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
Some tests are not working reliably and thus are disabled by default.
|
||||
This includes tests that don't run reliably on GitLab's CI which
|
||||
usually expose real issues that are rarely seen on developer machines
|
||||
due to the constraints of the CI environment. If you encounter a
|
||||
similar situation then raise a bug and then mark the test as shown on
|
||||
the code snippet below:
|
||||
GITLAB_CI
|
||||
^^^^^^^^^
|
||||
A number of tests are flagged to not run on the GitLab CI. Usually because
|
||||
they proved to the flaky or there are constraints on the CI environment which
|
||||
would make them fail. If you encounter a similar situation then use that
|
||||
variable as shown on the code snippet below to skip the test:
|
||||
|
||||
.. code::
|
||||
|
||||
# See https://gitlab.com/qemu-project/qemu/-/issues/nnnn
|
||||
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
|
||||
@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
|
||||
def test(self):
|
||||
do_something()
|
||||
|
||||
You can also add ``:avocado: tags=flaky`` to the test meta-data so
|
||||
only the flaky tests can be run as a group:
|
||||
|
||||
.. code::
|
||||
|
||||
env QEMU_TEST_FLAKY_TESTS=1 ./pyvenv/bin/avocado \
|
||||
run tests/avocado -filter-by-tags=flaky
|
||||
|
||||
Tests should not live in this state forever and should either be fixed
|
||||
or eventually removed.
|
||||
|
||||
QEMU_TEST_FLAKY_TESTS
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
Some tests are not working reliably and thus are disabled by default.
|
||||
Set this environment variable to enable them.
|
||||
|
||||
Uninstalling Avocado
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -148,9 +148,9 @@ Vring descriptor indices for packed virtqueues
|
||||
A vring address description
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
+-------+-------+------------+------+-----------+-----+
|
||||
| index | flags | descriptor | used | available | log |
|
||||
+-------+-------+------------+------+-----------+-----+
|
||||
+-------+-------+------+------------+------+-----------+-----+
|
||||
| index | flags | size | descriptor | used | available | log |
|
||||
+-------+-------+------+------------+------+-----------+-----+
|
||||
|
||||
:index: a 32-bit vring index
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
sphinx==5.3.0
|
||||
sphinx_rtd_theme==1.1.1
|
||||
@@ -1,5 +1,3 @@
|
||||
.. _tpm-device:
|
||||
|
||||
===============
|
||||
QEMU TPM Device
|
||||
===============
|
||||
|
||||
@@ -229,15 +229,15 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
||||
section += dlnode
|
||||
return [section]
|
||||
|
||||
def _nodes_for_arguments(self, doc, arg_type):
|
||||
def _nodes_for_arguments(self, doc, boxed_arg_type):
|
||||
"""Return list of doctree nodes for the arguments section"""
|
||||
if arg_type and not arg_type.is_implicit():
|
||||
if boxed_arg_type:
|
||||
assert not doc.args
|
||||
section = self._make_section('Arguments')
|
||||
dlnode = nodes.definition_list()
|
||||
dlnode += self._make_dlitem(
|
||||
[nodes.Text('The members of '),
|
||||
nodes.literal('', arg_type.name)],
|
||||
nodes.literal('', boxed_arg_type.name)],
|
||||
None)
|
||||
section += dlnode
|
||||
return [section]
|
||||
@@ -341,7 +341,8 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
||||
allow_preconfig, coroutine):
|
||||
doc = self._cur_doc
|
||||
self._add_doc('Command',
|
||||
self._nodes_for_arguments(doc, arg_type)
|
||||
self._nodes_for_arguments(doc,
|
||||
arg_type if boxed else None)
|
||||
+ self._nodes_for_features(doc)
|
||||
+ self._nodes_for_sections(doc)
|
||||
+ self._nodes_for_if_section(ifcond))
|
||||
@@ -349,7 +350,8 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
||||
def visit_event(self, name, info, ifcond, features, arg_type, boxed):
|
||||
doc = self._cur_doc
|
||||
self._add_doc('Event',
|
||||
self._nodes_for_arguments(doc, arg_type)
|
||||
self._nodes_for_arguments(doc,
|
||||
arg_type if boxed else None)
|
||||
+ self._nodes_for_features(doc)
|
||||
+ self._nodes_for_sections(doc)
|
||||
+ self._nodes_for_if_section(ifcond))
|
||||
@@ -513,7 +515,7 @@ class QAPIDocDirective(Directive):
|
||||
except QAPIError as err:
|
||||
# Launder QAPI parse errors into Sphinx extension errors
|
||||
# so they are displayed nicely to the user
|
||||
raise ExtensionError(str(err)) from err
|
||||
raise ExtensionError(str(err))
|
||||
|
||||
def do_parse(self, rstlist, node):
|
||||
"""Parse rST source lines and add them to the specified node
|
||||
|
||||
@@ -70,7 +70,7 @@ the following architecture extensions:
|
||||
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
|
||||
- FEAT_PAN3 (Support for SCTLR_ELx.EPAN)
|
||||
- FEAT_PAuth (Pointer authentication)
|
||||
- FEAT_PAuth2 (Enhancements to pointer authentication)
|
||||
- FEAT_PAuth2 (Enhacements to pointer authentication)
|
||||
- FEAT_PMULL (PMULL, PMULL2 instructions)
|
||||
- FEAT_PMUv3p1 (PMU Extensions v3.1)
|
||||
- FEAT_PMUv3p4 (PMU Extensions v3.4)
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
Xen Device Emulation Backend (``xenpvh``)
|
||||
XENPVH (``xenpvh``)
|
||||
=========================================
|
||||
This machine creates a IOREQ server to register/connect with Xen Hypervisor.
|
||||
|
||||
This machine is a little unusual compared to others as QEMU just acts
|
||||
as an IOREQ server to register/connect with Xen Hypervisor. Control of
|
||||
the VMs themselves is left to the Xen tooling.
|
||||
When TPM is enabled, this machine also creates a tpm-tis-device at a user input
|
||||
tpm base address, adds a TPM emulator and connects to a swtpm application
|
||||
running on host machine via chardev socket. This enables xenpvh to support TPM
|
||||
functionalities for a guest domain.
|
||||
|
||||
When TPM is enabled, this machine also creates a tpm-tis-device at a
|
||||
user input tpm base address, adds a TPM emulator and connects to a
|
||||
swtpm application running on host machine via chardev socket. This
|
||||
enables xenpvh to support TPM functionalities for a guest domain.
|
||||
|
||||
More information about TPM use and installing swtpm linux application
|
||||
can be found in the :ref:`tpm-device` section.
|
||||
More information about TPM use and installing swtpm linux application can be
|
||||
found at: docs/specs/tpm.rst.
|
||||
|
||||
Example for starting swtpm on host machine:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
mkdir /tmp/vtpm2
|
||||
@@ -22,7 +18,6 @@ Example for starting swtpm on host machine:
|
||||
--ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &
|
||||
|
||||
Sample QEMU xenpvh commands for running and connecting with Xen:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
qemu-system-aarch64 -xen-domid 1 \
|
||||
|
||||
@@ -60,7 +60,7 @@ As TCG cannot track all memory accesses in user-mode there is no
|
||||
support for watchpoints.
|
||||
|
||||
Relocating code
|
||||
===============
|
||||
---------------
|
||||
|
||||
On modern kernels confusion can be caused by code being relocated by
|
||||
features such as address space layout randomisation. To avoid
|
||||
@@ -68,17 +68,6 @@ confusion when debugging such things you either need to update gdb's
|
||||
view of where things are in memory or perhaps more trivially disable
|
||||
ASLR when booting the system.
|
||||
|
||||
Debugging user-space in system emulation
|
||||
========================================
|
||||
|
||||
While it is technically possible to debug a user-space program running
|
||||
inside a system image, it does present challenges. Kernel preemption
|
||||
and execution mode changes between kernel and user mode can make it
|
||||
hard to follow what's going on. Unless you are specifically trying to
|
||||
debug some interaction between kernel and user-space you are better
|
||||
off running your guest program with gdb either in the guest or using
|
||||
a gdbserver exposed via a port to the outside world.
|
||||
|
||||
Debugging multicore machines
|
||||
============================
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
During the graphical emulation, you can use special key combinations from
|
||||
the following table to change modes. By default the modifier is Ctrl-Alt
|
||||
(used in the table below) which can be changed with ``-display`` suboption
|
||||
``mod=`` where appropriate. For example, ``-display sdl,
|
||||
grab-mod=lshift-lctrl-lalt`` changes the modifier key to Ctrl-Alt-Shift,
|
||||
while ``-display sdl,grab-mod=rctrl`` changes it to the right Ctrl key.
|
||||
During the graphical emulation, you can use special key combinations to
|
||||
change modes. The default key mappings are shown below, but if you use
|
||||
``-alt-grab`` then the modifier is Ctrl-Alt-Shift (instead of Ctrl-Alt)
|
||||
and if you use ``-ctrl-grab`` then the modifier is the right Ctrl key
|
||||
(instead of Ctrl-Alt):
|
||||
|
||||
Ctrl-Alt-f
|
||||
Toggle full screen
|
||||
@@ -29,7 +28,7 @@ Ctrl-Alt-n
|
||||
*3*
|
||||
Serial port
|
||||
|
||||
Ctrl-Alt-g
|
||||
Ctrl-Alt
|
||||
Toggle mouse and keyboard grab.
|
||||
|
||||
In the virtual consoles, you can use Ctrl-Up, Ctrl-Down, Ctrl-PageUp and
|
||||
|
||||
@@ -96,10 +96,6 @@ uint64_t cpu_to_dump64(DumpState *s, uint64_t val)
|
||||
|
||||
static int dump_cleanup(DumpState *s)
|
||||
{
|
||||
if (s->dump_info.arch_cleanup_fn) {
|
||||
s->dump_info.arch_cleanup_fn(s);
|
||||
}
|
||||
|
||||
guest_phys_blocks_free(&s->guest_phys_blocks);
|
||||
memory_mapping_list_free(&s->list);
|
||||
close(s->fd);
|
||||
|
||||
@@ -692,7 +692,7 @@ static int gdb_handle_vcont(const char *p)
|
||||
/*
|
||||
* target_count and last_target keep track of how many CPUs we are going to
|
||||
* step or resume, and a pointer to the state structure of one of them,
|
||||
* respectively
|
||||
* respectivelly
|
||||
*/
|
||||
int target_count = 0;
|
||||
CPUState *last_target = NULL;
|
||||
|
||||
@@ -24,7 +24,6 @@ enum {
|
||||
GDB_SIGNAL_TRAP = 5,
|
||||
GDB_SIGNAL_ABRT = 6,
|
||||
GDB_SIGNAL_ALRM = 14,
|
||||
GDB_SIGNAL_STOP = 17,
|
||||
GDB_SIGNAL_IO = 23,
|
||||
GDB_SIGNAL_XCPU = 24,
|
||||
GDB_SIGNAL_UNKNOWN = 143
|
||||
|
||||
@@ -183,7 +183,7 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
|
||||
break;
|
||||
case RUN_STATE_IO_ERROR:
|
||||
trace_gdbstub_hit_io_error();
|
||||
ret = GDB_SIGNAL_STOP;
|
||||
ret = GDB_SIGNAL_IO;
|
||||
break;
|
||||
case RUN_STATE_WATCHDOG:
|
||||
trace_gdbstub_hit_watchdog();
|
||||
|
||||
@@ -28,7 +28,7 @@ atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
|
||||
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
||||
atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
|
||||
{
|
||||
Int128Aligned *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
__int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
Int128Alias r, c, n;
|
||||
|
||||
c.s = cmp;
|
||||
|
||||
@@ -58,7 +58,7 @@ atomic16_read_rw(Int128 *ptr)
|
||||
static inline void ATTRIBUTE_ATOMIC128_OPT
|
||||
atomic16_set(Int128 *ptr, Int128 val)
|
||||
{
|
||||
Int128Aligned *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
__int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
__int128_t old;
|
||||
Int128Alias new;
|
||||
|
||||
|
||||
@@ -947,7 +947,6 @@ static const VMStateDescription erst_vmstate = {
|
||||
|
||||
static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
ERSTDeviceState *s = ACPIERST(pci_dev);
|
||||
|
||||
trace_acpi_erst_realizefn_in();
|
||||
@@ -965,15 +964,9 @@ static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
|
||||
|
||||
/* HostMemoryBackend size will be multiple of PAGE_SIZE */
|
||||
s->storage_size = object_property_get_int(OBJECT(s->hostmem), "size", errp);
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize backend storage and record_count */
|
||||
check_erst_backend_storage(s, errp);
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* BAR 0: Programming registers */
|
||||
memory_region_init_io(&s->iomem_mr, OBJECT(pci_dev), &erst_reg_ops, s,
|
||||
@@ -984,9 +977,6 @@ static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
|
||||
memory_region_init_ram(&s->exchange_mr, OBJECT(pci_dev),
|
||||
"erst.exchange",
|
||||
le32_to_cpu(s->header->record_size), errp);
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
|
||||
&s->exchange_mr);
|
||||
|
||||
|
||||
@@ -78,7 +78,6 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
|
||||
uint32_t *initiator_list)
|
||||
{
|
||||
int i, index;
|
||||
uint32_t initiator_to_index[MAX_NODES] = {};
|
||||
HMAT_LB_Data *lb_data;
|
||||
uint16_t *entry_list;
|
||||
uint32_t base;
|
||||
@@ -122,8 +121,6 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
|
||||
/* Initiator Proximity Domain List */
|
||||
for (i = 0; i < num_initiator; i++) {
|
||||
build_append_int_noprefix(table_data, initiator_list[i], 4);
|
||||
/* Reverse mapping for array possitions */
|
||||
initiator_to_index[initiator_list[i]] = i;
|
||||
}
|
||||
|
||||
/* Target Proximity Domain List */
|
||||
@@ -135,8 +132,7 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
|
||||
entry_list = g_new0(uint16_t, num_initiator * num_target);
|
||||
for (i = 0; i < hmat_lb->list->len; i++) {
|
||||
lb_data = &g_array_index(hmat_lb->list, HMAT_LB_Data, i);
|
||||
index = initiator_to_index[lb_data->initiator] * num_target +
|
||||
lb_data->target;
|
||||
index = lb_data->initiator * num_target + lb_data->target;
|
||||
|
||||
entry_list[index] = (uint16_t)(lb_data->data / hmat_lb->base);
|
||||
}
|
||||
|
||||
@@ -169,8 +169,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
|
||||
epit_table[i].irq));
|
||||
}
|
||||
|
||||
object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num,
|
||||
&error_abort);
|
||||
object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num, &err);
|
||||
qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
|
||||
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->fec), errp)) {
|
||||
|
||||
@@ -379,8 +379,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
|
||||
spi_table[i].irq));
|
||||
}
|
||||
|
||||
object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num,
|
||||
&error_abort);
|
||||
object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num, &err);
|
||||
qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]);
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->eth), errp)) {
|
||||
return;
|
||||
|
||||
@@ -44,6 +44,7 @@ static void netduino2_init(MachineState *machine)
|
||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||
|
||||
dev = qdev_new(TYPE_STM32F205_SOC);
|
||||
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
|
||||
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
@@ -53,14 +54,8 @@ static void netduino2_init(MachineState *machine)
|
||||
|
||||
static void netduino2_machine_init(MachineClass *mc)
|
||||
{
|
||||
static const char * const valid_cpu_types[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-m3"),
|
||||
NULL
|
||||
};
|
||||
|
||||
mc->desc = "Netduino 2 Machine (Cortex-M3)";
|
||||
mc->init = netduino2_init;
|
||||
mc->valid_cpu_types = valid_cpu_types;
|
||||
mc->ignore_memory_transaction_failures = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ static void netduinoplus2_init(MachineState *machine)
|
||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||
|
||||
dev = qdev_new(TYPE_STM32F405_SOC);
|
||||
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
|
||||
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
@@ -54,14 +55,8 @@ static void netduinoplus2_init(MachineState *machine)
|
||||
|
||||
static void netduinoplus2_machine_init(MachineClass *mc)
|
||||
{
|
||||
static const char * const valid_cpu_types[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-m4"),
|
||||
NULL
|
||||
};
|
||||
|
||||
mc->desc = "Netduino Plus 2 Machine (Cortex-M4)";
|
||||
mc->init = netduinoplus2_init;
|
||||
mc->valid_cpu_types = valid_cpu_types;
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("netduinoplus2", netduinoplus2_machine_init)
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/units.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
@@ -378,7 +377,7 @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
|
||||
* The initial mask of disabled modules indicates the chip derivative (e.g.
|
||||
* NPCM750 or NPCM730).
|
||||
*/
|
||||
value = cpu_to_le32(nc->disabled_modules);
|
||||
value = tswap32(nc->disabled_modules);
|
||||
npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
|
||||
sizeof(value));
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ static void olimex_stm32_h405_init(MachineState *machine)
|
||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||
|
||||
dev = qdev_new(TYPE_STM32F405_SOC);
|
||||
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
|
||||
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
@@ -57,14 +58,9 @@ static void olimex_stm32_h405_init(MachineState *machine)
|
||||
|
||||
static void olimex_stm32_h405_machine_init(MachineClass *mc)
|
||||
{
|
||||
static const char * const valid_cpu_types[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-m4"),
|
||||
NULL
|
||||
};
|
||||
|
||||
mc->desc = "Olimex STM32-H405 (Cortex-M4)";
|
||||
mc->init = olimex_stm32_h405_init;
|
||||
mc->valid_cpu_types = valid_cpu_types;
|
||||
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
|
||||
|
||||
/* SRAM pre-allocated as part of the SoC instantiation */
|
||||
mc->default_ram_size = 0;
|
||||
|
||||
@@ -675,8 +675,6 @@ static void smmu_base_reset_hold(Object *obj)
|
||||
{
|
||||
SMMUState *s = ARM_SMMU(obj);
|
||||
|
||||
memset(s->smmu_pcibus_by_bus_num, 0, sizeof(s->smmu_pcibus_by_bus_num));
|
||||
|
||||
g_hash_table_remove_all(s->configs);
|
||||
g_hash_table_remove_all(s->iotlb);
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
/* Init ARMv7m */
|
||||
armv7m = DEVICE(&s->armv7m);
|
||||
qdev_prop_set_uint32(armv7m, "num-irq", 61);
|
||||
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
|
||||
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
|
||||
qdev_prop_set_bit(armv7m, "enable-bitband", true);
|
||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||
qdev_connect_clock_in(armv7m, "refclk", s->refclk);
|
||||
@@ -180,12 +180,17 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
create_unimplemented_device("CRC", 0x40023000, 0x400);
|
||||
}
|
||||
|
||||
static Property stm32f100_soc_properties[] = {
|
||||
DEFINE_PROP_STRING("cpu-type", STM32F100State, cpu_type),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void stm32f100_soc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = stm32f100_soc_realize;
|
||||
/* No vmstate or reset required: device has no internal state */
|
||||
device_class_set_props(dc, stm32f100_soc_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo stm32f100_soc_info = {
|
||||
|
||||
@@ -127,7 +127,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
|
||||
armv7m = DEVICE(&s->armv7m);
|
||||
qdev_prop_set_uint32(armv7m, "num-irq", 96);
|
||||
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
|
||||
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
|
||||
qdev_prop_set_bit(armv7m, "enable-bitband", true);
|
||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||
qdev_connect_clock_in(armv7m, "refclk", s->refclk);
|
||||
@@ -201,12 +201,17 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static Property stm32f205_soc_properties[] = {
|
||||
DEFINE_PROP_STRING("cpu-type", STM32F205State, cpu_type),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void stm32f205_soc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = stm32f205_soc_realize;
|
||||
/* No vmstate or reset required: device has no internal state */
|
||||
device_class_set_props(dc, stm32f205_soc_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo stm32f205_soc_info = {
|
||||
|
||||
@@ -149,7 +149,7 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
|
||||
armv7m = DEVICE(&s->armv7m);
|
||||
qdev_prop_set_uint32(armv7m, "num-irq", 96);
|
||||
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
|
||||
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
|
||||
qdev_prop_set_bit(armv7m, "enable-bitband", true);
|
||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||
qdev_connect_clock_in(armv7m, "refclk", s->refclk);
|
||||
@@ -287,11 +287,17 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
create_unimplemented_device("RNG", 0x50060800, 0x400);
|
||||
}
|
||||
|
||||
static Property stm32f405_soc_properties[] = {
|
||||
DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = stm32f405_soc_realize;
|
||||
device_class_set_props(dc, stm32f405_soc_properties);
|
||||
/* No vmstate or reset required: device has no internal state */
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ static void stm32vldiscovery_init(MachineState *machine)
|
||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||
|
||||
dev = qdev_new(TYPE_STM32F100_SOC);
|
||||
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
|
||||
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
@@ -57,14 +58,8 @@ static void stm32vldiscovery_init(MachineState *machine)
|
||||
|
||||
static void stm32vldiscovery_machine_init(MachineClass *mc)
|
||||
{
|
||||
static const char * const valid_cpu_types[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-m3"),
|
||||
NULL
|
||||
};
|
||||
|
||||
mc->desc = "ST STM32VLDISCOVERY (Cortex-M3)";
|
||||
mc->init = stm32vldiscovery_init;
|
||||
mc->valid_cpu_types = valid_cpu_types;
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init)
|
||||
|
||||
@@ -576,8 +576,7 @@ static void fdt_add_gic_node(VirtMachineState *vms)
|
||||
|
||||
if (vms->virt) {
|
||||
qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
||||
GIC_FDT_IRQ_TYPE_PPI,
|
||||
INTID_TO_PPI(ARCH_GIC_MAINT_IRQ),
|
||||
GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
|
||||
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
|
||||
}
|
||||
} else {
|
||||
@@ -601,8 +600,7 @@ static void fdt_add_gic_node(VirtMachineState *vms)
|
||||
2, vms->memmap[VIRT_GIC_VCPU].base,
|
||||
2, vms->memmap[VIRT_GIC_VCPU].size);
|
||||
qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
||||
GIC_FDT_IRQ_TYPE_PPI,
|
||||
INTID_TO_PPI(ARCH_GIC_MAINT_IRQ),
|
||||
GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
|
||||
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -670,13 +670,8 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
|
||||
cnt += (transferred + d->leftover) >> 2;
|
||||
|
||||
if (s->sctl & loop_sel) {
|
||||
/*
|
||||
* loop_sel tells us which bit in the SCTL register to look at
|
||||
* (either P1_LOOP_SEL, P2_LOOP_SEL or R1_LOOP_SEL). The sense
|
||||
* of these bits is 0 for loop mode (set interrupt and keep recording
|
||||
* when the sample count reaches zero) or 1 for stop mode (set
|
||||
* interrupt and stop recording).
|
||||
*/
|
||||
/* Bah, how stupid is that having a 0 represent true value?
|
||||
i just spent few hours on this shit */
|
||||
AUD_log ("es1370: warning", "non looping mode\n");
|
||||
} else {
|
||||
d->frame_cnt = size;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "intel-hda.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "intel-hda-defs.h"
|
||||
#include "audio/audio.h"
|
||||
@@ -190,9 +189,9 @@ struct HDAAudioState {
|
||||
bool use_timer;
|
||||
};
|
||||
|
||||
static inline uint32_t hda_bytes_per_second(HDAAudioStream *st)
|
||||
static inline int64_t hda_bytes_per_second(HDAAudioStream *st)
|
||||
{
|
||||
return 2 * (uint32_t)st->as.nchannels * (uint32_t)st->as.freq;
|
||||
return 2LL * st->as.nchannels * st->as.freq;
|
||||
}
|
||||
|
||||
static inline void hda_timer_sync_adjust(HDAAudioStream *st, int64_t target_pos)
|
||||
@@ -223,18 +222,12 @@ static void hda_audio_input_timer(void *opaque)
|
||||
|
||||
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
|
||||
int64_t uptime = now - st->buft_start;
|
||||
int64_t buft_start = st->buft_start;
|
||||
int64_t wpos = st->wpos;
|
||||
int64_t rpos = st->rpos;
|
||||
int64_t wanted_rpos;
|
||||
|
||||
if (uptime <= 0) {
|
||||
/* wanted_rpos <= 0 */
|
||||
goto out_timer;
|
||||
}
|
||||
|
||||
wanted_rpos = muldiv64(uptime, hda_bytes_per_second(st),
|
||||
NANOSECONDS_PER_SECOND);
|
||||
int64_t wanted_rpos = hda_bytes_per_second(st) * (now - buft_start)
|
||||
/ NANOSECONDS_PER_SECOND;
|
||||
wanted_rpos &= -4; /* IMPORTANT! clip to frames */
|
||||
|
||||
if (wanted_rpos <= rpos) {
|
||||
@@ -293,18 +286,12 @@ static void hda_audio_output_timer(void *opaque)
|
||||
|
||||
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
|
||||
int64_t uptime = now - st->buft_start;
|
||||
int64_t buft_start = st->buft_start;
|
||||
int64_t wpos = st->wpos;
|
||||
int64_t rpos = st->rpos;
|
||||
int64_t wanted_wpos;
|
||||
|
||||
if (uptime <= 0) {
|
||||
/* wanted_wpos <= 0 */
|
||||
goto out_timer;
|
||||
}
|
||||
|
||||
wanted_wpos = muldiv64(uptime, hda_bytes_per_second(st),
|
||||
NANOSECONDS_PER_SECOND);
|
||||
int64_t wanted_wpos = hda_bytes_per_second(st) * (now - buft_start)
|
||||
/ NANOSECONDS_PER_SECOND;
|
||||
wanted_wpos &= -4; /* IMPORTANT! clip to frames */
|
||||
|
||||
if (wanted_wpos <= wpos) {
|
||||
@@ -868,10 +855,10 @@ static Property hda_audio_properties[] = {
|
||||
static void hda_audio_init_output(HDACodecDevice *hda, Error **errp)
|
||||
{
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
const struct desc_codec *desc = &output_mixemu;
|
||||
const struct desc_codec *desc = &output_nomixemu;
|
||||
|
||||
if (!a->mixer) {
|
||||
desc = &output_nomixemu;
|
||||
desc = &output_mixemu;
|
||||
}
|
||||
|
||||
hda_audio_init(hda, desc, errp);
|
||||
@@ -880,10 +867,10 @@ static void hda_audio_init_output(HDACodecDevice *hda, Error **errp)
|
||||
static void hda_audio_init_duplex(HDACodecDevice *hda, Error **errp)
|
||||
{
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
const struct desc_codec *desc = &duplex_mixemu;
|
||||
const struct desc_codec *desc = &duplex_nomixemu;
|
||||
|
||||
if (!a->mixer) {
|
||||
desc = &duplex_nomixemu;
|
||||
desc = &duplex_mixemu;
|
||||
}
|
||||
|
||||
hda_audio_init(hda, desc, errp);
|
||||
@@ -892,10 +879,10 @@ static void hda_audio_init_duplex(HDACodecDevice *hda, Error **errp)
|
||||
static void hda_audio_init_micro(HDACodecDevice *hda, Error **errp)
|
||||
{
|
||||
HDAAudioState *a = HDA_AUDIO(hda);
|
||||
const struct desc_codec *desc = µ_mixemu;
|
||||
const struct desc_codec *desc = µ_nomixemu;
|
||||
|
||||
if (!a->mixer) {
|
||||
desc = µ_nomixemu;
|
||||
desc = µ_mixemu;
|
||||
}
|
||||
|
||||
hda_audio_init(hda, desc, errp);
|
||||
|
||||
@@ -211,14 +211,14 @@ static void out_cb(void *opaque, int avail)
|
||||
AUD_set_active_out(s->vo, 0);
|
||||
}
|
||||
if (c->type & STAT_EOL) {
|
||||
via_isa_set_irq(&s->dev, 0, 1);
|
||||
pci_set_irq(&s->dev, 1);
|
||||
}
|
||||
}
|
||||
if (CLEN_IS_FLAG(c)) {
|
||||
c->stat |= STAT_FLAG;
|
||||
c->stat |= STAT_PAUSED;
|
||||
if (c->type & STAT_FLAG) {
|
||||
via_isa_set_irq(&s->dev, 0, 1);
|
||||
pci_set_irq(&s->dev, 1);
|
||||
}
|
||||
}
|
||||
if (CLEN_IS_STOP(c)) {
|
||||
@@ -305,13 +305,13 @@ static void sgd_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
||||
if (val & STAT_EOL) {
|
||||
s->aur.stat &= ~(STAT_EOL | STAT_PAUSED);
|
||||
if (s->aur.type & STAT_EOL) {
|
||||
via_isa_set_irq(&s->dev, 0, 0);
|
||||
pci_set_irq(&s->dev, 0);
|
||||
}
|
||||
}
|
||||
if (val & STAT_FLAG) {
|
||||
s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED);
|
||||
if (s->aur.type & STAT_FLAG) {
|
||||
via_isa_set_irq(&s->dev, 0, 0);
|
||||
pci_set_irq(&s->dev, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -47,14 +47,12 @@ static void virtio_snd_pci_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
|
||||
PCIDeviceClass *pcidevklass = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
device_class_set_props(dc, virtio_snd_pci_properties);
|
||||
dc->desc = "Virtio Sound";
|
||||
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
|
||||
|
||||
vpciklass->realize = virtio_snd_pci_realize;
|
||||
pcidevklass->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
|
||||
}
|
||||
|
||||
static void virtio_snd_pci_instance_init(Object *obj)
|
||||
|
||||
@@ -36,7 +36,6 @@ static void virtio_snd_pcm_out_cb(void *data, int available);
|
||||
static void virtio_snd_process_cmdq(VirtIOSound *s);
|
||||
static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream);
|
||||
static void virtio_snd_pcm_in_cb(void *data, int available);
|
||||
static void virtio_snd_unrealize(DeviceState *dev);
|
||||
|
||||
static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
|
||||
| BIT(VIRTIO_SND_PCM_FMT_U8)
|
||||
@@ -69,7 +68,6 @@ static const VMStateDescription vmstate_virtio_snd_device = {
|
||||
|
||||
static const VMStateDescription vmstate_virtio_snd = {
|
||||
.name = TYPE_VIRTIO_SND,
|
||||
.unmigratable = 1,
|
||||
.minimum_version_id = VIRTIO_SOUND_VM_VERSION,
|
||||
.version_id = VIRTIO_SOUND_VM_VERSION,
|
||||
.fields = (VMStateField[]) {
|
||||
@@ -243,13 +241,12 @@ static void virtio_snd_handle_pcm_info(VirtIOSound *s,
|
||||
memset(&pcm_info[i].padding, 0, 5);
|
||||
}
|
||||
|
||||
cmd->payload_size = sizeof(virtio_snd_pcm_info) * count;
|
||||
cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
|
||||
iov_from_buf(cmd->elem->in_sg,
|
||||
cmd->elem->in_num,
|
||||
sizeof(virtio_snd_hdr),
|
||||
pcm_info,
|
||||
cmd->payload_size);
|
||||
sizeof(virtio_snd_pcm_info) * count);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -401,7 +398,7 @@ static void virtio_snd_get_qemu_audsettings(audsettings *as,
|
||||
as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels);
|
||||
as->fmt = virtio_snd_get_qemu_format(params->format);
|
||||
as->freq = virtio_snd_get_qemu_freq(params->rate);
|
||||
as->endianness = 0; /* Conforming to VIRTIO 1.0: always little endian. */
|
||||
as->endianness = target_words_bigendian() ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -456,6 +453,7 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id)
|
||||
stream->s = s;
|
||||
qemu_mutex_init(&stream->queue_mutex);
|
||||
QSIMPLEQ_INIT(&stream->queue);
|
||||
QSIMPLEQ_INIT(&stream->invalid);
|
||||
|
||||
/*
|
||||
* stream_id >= s->snd_conf.streams was checked before so this is
|
||||
@@ -610,6 +608,9 @@ static size_t virtio_snd_pcm_get_io_msgs_count(VirtIOSoundPCMStream *stream)
|
||||
QSIMPLEQ_FOREACH_SAFE(buffer, &stream->queue, entry, next) {
|
||||
count += 1;
|
||||
}
|
||||
QSIMPLEQ_FOREACH_SAFE(buffer, &stream->invalid, entry, next) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -746,8 +747,7 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
|
||||
0,
|
||||
&cmd->resp,
|
||||
sizeof(virtio_snd_hdr));
|
||||
virtqueue_push(cmd->vq, cmd->elem,
|
||||
sizeof(virtio_snd_hdr) + cmd->payload_size);
|
||||
virtqueue_push(cmd->vq, cmd->elem, sizeof(virtio_snd_hdr));
|
||||
virtio_notify(VIRTIO_DEVICE(s), cmd->vq);
|
||||
}
|
||||
|
||||
@@ -806,7 +806,6 @@ static void virtio_snd_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
|
||||
cmd->elem = elem;
|
||||
cmd->vq = vq;
|
||||
cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
|
||||
/* implicit cmd->payload_size = 0; */
|
||||
QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next);
|
||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||
}
|
||||
@@ -827,22 +826,25 @@ static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq)
|
||||
trace_virtio_snd_handle_event();
|
||||
}
|
||||
|
||||
/*
|
||||
* Must only be called if vsnd->invalid is not empty.
|
||||
*/
|
||||
static inline void empty_invalid_queue(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOSoundPCMBuffer *buffer = NULL;
|
||||
VirtIOSoundPCMStream *stream = NULL;
|
||||
virtio_snd_pcm_status resp = { 0 };
|
||||
VirtIOSound *vsnd = VIRTIO_SND(vdev);
|
||||
bool any = false;
|
||||
|
||||
g_assert(!QSIMPLEQ_EMPTY(&vsnd->invalid));
|
||||
|
||||
while (!QSIMPLEQ_EMPTY(&vsnd->invalid)) {
|
||||
buffer = QSIMPLEQ_FIRST(&vsnd->invalid);
|
||||
/* If buffer->vq != vq, our logic is fundamentally wrong, so bail out */
|
||||
g_assert(buffer->vq == vq);
|
||||
|
||||
for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
|
||||
stream = vsnd->pcm->streams[i];
|
||||
if (stream) {
|
||||
any = false;
|
||||
WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
|
||||
while (!QSIMPLEQ_EMPTY(&stream->invalid)) {
|
||||
buffer = QSIMPLEQ_FIRST(&stream->invalid);
|
||||
if (buffer->vq != vq) {
|
||||
break;
|
||||
}
|
||||
any = true;
|
||||
resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
|
||||
iov_from_buf(buffer->elem->in_sg,
|
||||
buffer->elem->in_num,
|
||||
@@ -852,11 +854,19 @@ static inline void empty_invalid_queue(VirtIODevice *vdev, VirtQueue *vq)
|
||||
virtqueue_push(vq,
|
||||
buffer->elem,
|
||||
sizeof(virtio_snd_pcm_status));
|
||||
QSIMPLEQ_REMOVE_HEAD(&vsnd->invalid, entry);
|
||||
QSIMPLEQ_REMOVE_HEAD(&stream->invalid, entry);
|
||||
virtio_snd_pcm_buffer_free(buffer);
|
||||
}
|
||||
/* Notify vq about virtio_snd_pcm_status responses. */
|
||||
if (any) {
|
||||
/*
|
||||
* Notify vq about virtio_snd_pcm_status responses.
|
||||
* Buffer responses must be notified separately later.
|
||||
*/
|
||||
virtio_notify(vdev, vq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -868,14 +878,15 @@ static inline void empty_invalid_queue(VirtIODevice *vdev, VirtQueue *vq)
|
||||
*/
|
||||
static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOSound *vsnd = VIRTIO_SND(vdev);
|
||||
VirtIOSound *s = VIRTIO_SND(vdev);
|
||||
VirtIOSoundPCMStream *stream = NULL;
|
||||
VirtIOSoundPCMBuffer *buffer;
|
||||
VirtQueueElement *elem;
|
||||
size_t msg_sz, size;
|
||||
virtio_snd_pcm_xfer hdr;
|
||||
uint32_t stream_id;
|
||||
/*
|
||||
* If any of the I/O messages are invalid, put them in vsnd->invalid and
|
||||
* If any of the I/O messages are invalid, put them in stream->invalid and
|
||||
* return them after the for loop.
|
||||
*/
|
||||
bool must_empty_invalid_queue = false;
|
||||
@@ -886,8 +897,6 @@ static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
||||
trace_virtio_snd_handle_tx_xfer();
|
||||
|
||||
for (;;) {
|
||||
VirtIOSoundPCMStream *stream;
|
||||
|
||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||
if (!elem) {
|
||||
break;
|
||||
@@ -903,12 +912,12 @@ static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
||||
}
|
||||
stream_id = le32_to_cpu(hdr.stream_id);
|
||||
|
||||
if (stream_id >= vsnd->snd_conf.streams
|
||||
|| vsnd->pcm->streams[stream_id] == NULL) {
|
||||
if (stream_id >= s->snd_conf.streams
|
||||
|| s->pcm->streams[stream_id] == NULL) {
|
||||
goto tx_err;
|
||||
}
|
||||
|
||||
stream = vsnd->pcm->streams[stream_id];
|
||||
stream = s->pcm->streams[stream_id];
|
||||
if (stream->info.direction != VIRTIO_SND_D_OUTPUT) {
|
||||
goto tx_err;
|
||||
}
|
||||
@@ -928,11 +937,13 @@ static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
||||
continue;
|
||||
|
||||
tx_err:
|
||||
WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
|
||||
must_empty_invalid_queue = true;
|
||||
buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
|
||||
buffer->elem = elem;
|
||||
buffer->vq = vq;
|
||||
QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
|
||||
QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (must_empty_invalid_queue) {
|
||||
@@ -949,14 +960,15 @@ tx_err:
|
||||
*/
|
||||
static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VirtIOSound *vsnd = VIRTIO_SND(vdev);
|
||||
VirtIOSound *s = VIRTIO_SND(vdev);
|
||||
VirtIOSoundPCMStream *stream = NULL;
|
||||
VirtIOSoundPCMBuffer *buffer;
|
||||
VirtQueueElement *elem;
|
||||
size_t msg_sz, size;
|
||||
virtio_snd_pcm_xfer hdr;
|
||||
uint32_t stream_id;
|
||||
/*
|
||||
* if any of the I/O messages are invalid, put them in vsnd->invalid and
|
||||
* if any of the I/O messages are invalid, put them in stream->invalid and
|
||||
* return them after the for loop.
|
||||
*/
|
||||
bool must_empty_invalid_queue = false;
|
||||
@@ -967,8 +979,6 @@ static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
||||
trace_virtio_snd_handle_rx_xfer();
|
||||
|
||||
for (;;) {
|
||||
VirtIOSoundPCMStream *stream;
|
||||
|
||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||
if (!elem) {
|
||||
break;
|
||||
@@ -984,12 +994,12 @@ static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
||||
}
|
||||
stream_id = le32_to_cpu(hdr.stream_id);
|
||||
|
||||
if (stream_id >= vsnd->snd_conf.streams
|
||||
|| !vsnd->pcm->streams[stream_id]) {
|
||||
if (stream_id >= s->snd_conf.streams
|
||||
|| !s->pcm->streams[stream_id]) {
|
||||
goto rx_err;
|
||||
}
|
||||
|
||||
stream = vsnd->pcm->streams[stream_id];
|
||||
stream = s->pcm->streams[stream_id];
|
||||
if (stream == NULL || stream->info.direction != VIRTIO_SND_D_INPUT) {
|
||||
goto rx_err;
|
||||
}
|
||||
@@ -1006,11 +1016,13 @@ static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
||||
continue;
|
||||
|
||||
rx_err:
|
||||
WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
|
||||
must_empty_invalid_queue = true;
|
||||
buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
|
||||
buffer->elem = elem;
|
||||
buffer->vq = vq;
|
||||
QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
|
||||
QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (must_empty_invalid_queue) {
|
||||
@@ -1053,9 +1065,23 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
|
||||
virtio_snd_pcm_set_params default_params = { 0 };
|
||||
uint32_t status;
|
||||
|
||||
vsnd->pcm = NULL;
|
||||
vsnd->vmstate =
|
||||
qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
|
||||
|
||||
trace_virtio_snd_realize(vsnd);
|
||||
|
||||
/* check number of jacks and streams */
|
||||
vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
|
||||
vsnd->pcm->snd = vsnd;
|
||||
vsnd->pcm->streams =
|
||||
g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams);
|
||||
vsnd->pcm->pcm_params =
|
||||
g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams);
|
||||
|
||||
virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
|
||||
virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1);
|
||||
|
||||
/* set number of jacks and streams */
|
||||
if (vsnd->snd_conf.jacks > 8) {
|
||||
error_setg(errp,
|
||||
"Invalid number of jacks: %"PRIu32,
|
||||
@@ -1076,22 +1102,7 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AUD_register_card("virtio-sound", &vsnd->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vsnd->vmstate =
|
||||
qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
|
||||
|
||||
vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
|
||||
vsnd->pcm->snd = vsnd;
|
||||
vsnd->pcm->streams =
|
||||
g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams);
|
||||
vsnd->pcm->pcm_params =
|
||||
g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams);
|
||||
|
||||
virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
|
||||
virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1);
|
||||
AUD_register_card("virtio-sound", &vsnd->card, errp);
|
||||
|
||||
/* set default params for all streams */
|
||||
default_params.features = 0;
|
||||
@@ -1110,29 +1121,23 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
|
||||
virtio_add_queue(vdev, 64, virtio_snd_handle_rx_xfer);
|
||||
qemu_mutex_init(&vsnd->cmdq_mutex);
|
||||
QTAILQ_INIT(&vsnd->cmdq);
|
||||
QSIMPLEQ_INIT(&vsnd->invalid);
|
||||
|
||||
for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
|
||||
status = virtio_snd_set_pcm_params(vsnd, i, &default_params);
|
||||
if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
|
||||
error_setg(errp,
|
||||
"Can't initialize stream params, device responded with %s.",
|
||||
"Can't initalize stream params, device responded with %s.",
|
||||
print_code(status));
|
||||
goto error_cleanup;
|
||||
return;
|
||||
}
|
||||
status = virtio_snd_pcm_prepare(vsnd, i);
|
||||
if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
|
||||
error_setg(errp,
|
||||
"Can't prepare streams, device responded with %s.",
|
||||
print_code(status));
|
||||
goto error_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error_cleanup:
|
||||
virtio_snd_unrealize(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void return_tx_buffer(VirtIOSoundPCMStream *stream,
|
||||
@@ -1360,20 +1365,13 @@ static void virtio_snd_unrealize(DeviceState *dev)
|
||||
|
||||
static void virtio_snd_reset(VirtIODevice *vdev)
|
||||
{
|
||||
VirtIOSound *vsnd = VIRTIO_SND(vdev);
|
||||
VirtIOSound *s = VIRTIO_SND(vdev);
|
||||
virtio_snd_ctrl_command *cmd;
|
||||
|
||||
/*
|
||||
* Sanity check that the invalid buffer message queue is emptied at the end
|
||||
* of every virtio_snd_handle_tx_xfer/virtio_snd_handle_rx_xfer call, and
|
||||
* must be empty otherwise.
|
||||
*/
|
||||
g_assert(QSIMPLEQ_EMPTY(&vsnd->invalid));
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&vsnd->cmdq_mutex) {
|
||||
while (!QTAILQ_EMPTY(&vsnd->cmdq)) {
|
||||
cmd = QTAILQ_FIRST(&vsnd->cmdq);
|
||||
QTAILQ_REMOVE(&vsnd->cmdq, cmd, next);
|
||||
WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
|
||||
while (!QTAILQ_EMPTY(&s->cmdq)) {
|
||||
cmd = QTAILQ_FIRST(&s->cmdq);
|
||||
QTAILQ_REMOVE(&s->cmdq, cmd, next);
|
||||
virtio_snd_ctrl_cmd_free(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,10 +233,6 @@ static void atmega_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
/* CPU */
|
||||
object_initialize_child(OBJECT(dev), "cpu", &s->cpu, mc->cpu_type);
|
||||
|
||||
object_property_set_uint(OBJECT(&s->cpu), "init-sp",
|
||||
mc->io_size + mc->sram_size - 1, &error_abort);
|
||||
|
||||
qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
|
||||
cpudev = DEVICE(&s->cpu);
|
||||
|
||||
|
||||
@@ -84,11 +84,7 @@ struct NANDFlashState {
|
||||
|
||||
void (*blk_write)(NANDFlashState *s);
|
||||
void (*blk_erase)(NANDFlashState *s);
|
||||
/*
|
||||
* Returns %true when block containing (@addr + @offset) is
|
||||
* successfully loaded, otherwise %false.
|
||||
*/
|
||||
bool (*blk_load)(NANDFlashState *s, uint64_t addr, unsigned offset);
|
||||
void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
|
||||
|
||||
uint32_t ioaddr_vmstate;
|
||||
};
|
||||
@@ -247,30 +243,9 @@ static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nand_load_block: Load block containing (s->addr + @offset).
|
||||
* Returns length of data available at @offset in this block.
|
||||
*/
|
||||
static unsigned nand_load_block(NANDFlashState *s, unsigned offset)
|
||||
{
|
||||
unsigned iolen;
|
||||
|
||||
if (!s->blk_load(s, s->addr, offset)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
iolen = (1 << s->page_shift);
|
||||
if (s->gnd) {
|
||||
iolen += 1 << s->oob_shift;
|
||||
}
|
||||
assert(offset <= iolen);
|
||||
iolen -= offset;
|
||||
|
||||
return iolen;
|
||||
}
|
||||
|
||||
static void nand_command(NANDFlashState *s)
|
||||
{
|
||||
unsigned int offset;
|
||||
switch (s->cmd) {
|
||||
case NAND_CMD_READ0:
|
||||
s->iolen = 0;
|
||||
@@ -296,7 +271,12 @@ static void nand_command(NANDFlashState *s)
|
||||
case NAND_CMD_NOSERIALREAD2:
|
||||
if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP))
|
||||
break;
|
||||
s->iolen = nand_load_block(s, s->addr & ((1 << s->addr_shift) - 1));
|
||||
offset = s->addr & ((1 << s->addr_shift) - 1);
|
||||
s->blk_load(s, s->addr, offset);
|
||||
if (s->gnd)
|
||||
s->iolen = (1 << s->page_shift) - offset;
|
||||
else
|
||||
s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
|
||||
break;
|
||||
|
||||
case NAND_CMD_RESET:
|
||||
@@ -617,7 +597,12 @@ uint32_t nand_getio(DeviceState *dev)
|
||||
if (!s->iolen && s->cmd == NAND_CMD_READ0) {
|
||||
offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
|
||||
s->offset = 0;
|
||||
s->iolen = nand_load_block(s, offset);
|
||||
|
||||
s->blk_load(s, s->addr, offset);
|
||||
if (s->gnd)
|
||||
s->iolen = (1 << s->page_shift) - offset;
|
||||
else
|
||||
s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
|
||||
}
|
||||
|
||||
if (s->ce || s->iolen <= 0) {
|
||||
@@ -778,15 +763,11 @@ static void glue(nand_blk_erase_, NAND_PAGE_SIZE)(NANDFlashState *s)
|
||||
}
|
||||
}
|
||||
|
||||
static bool glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
|
||||
uint64_t addr, unsigned offset)
|
||||
static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
|
||||
uint64_t addr, int offset)
|
||||
{
|
||||
if (PAGE(addr) >= s->pages) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offset > NAND_PAGE_SIZE + OOB_SIZE) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->blk) {
|
||||
@@ -814,8 +795,6 @@ static bool glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
|
||||
offset, NAND_PAGE_SIZE + OOB_SIZE - offset);
|
||||
s->ioaddr = s->io;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void glue(nand_init_, NAND_PAGE_SIZE)(NANDFlashState *s)
|
||||
|
||||
@@ -80,39 +80,16 @@ struct PFlashCFI01 {
|
||||
uint16_t ident3;
|
||||
uint8_t cfi_table[0x52];
|
||||
uint64_t counter;
|
||||
uint32_t writeblock_size;
|
||||
unsigned int writeblock_size;
|
||||
MemoryRegion mem;
|
||||
char *name;
|
||||
void *storage;
|
||||
VMChangeStateEntry *vmstate;
|
||||
bool old_multiple_chip_handling;
|
||||
|
||||
/* block update buffer */
|
||||
unsigned char *blk_bytes;
|
||||
uint32_t blk_offset;
|
||||
};
|
||||
|
||||
static int pflash_post_load(void *opaque, int version_id);
|
||||
|
||||
static bool pflash_blk_write_state_needed(void *opaque)
|
||||
{
|
||||
PFlashCFI01 *pfl = opaque;
|
||||
|
||||
return (pfl->blk_offset != -1);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pflash_blk_write = {
|
||||
.name = "pflash_cfi01_blk_write",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = pflash_blk_write_state_needed,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_VBUFFER_UINT32(blk_bytes, PFlashCFI01, 0, NULL, writeblock_size),
|
||||
VMSTATE_UINT32(blk_offset, PFlashCFI01),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_pflash = {
|
||||
.name = "pflash_cfi01",
|
||||
.version_id = 1,
|
||||
@@ -124,10 +101,6 @@ static const VMStateDescription vmstate_pflash = {
|
||||
VMSTATE_UINT8(status, PFlashCFI01),
|
||||
VMSTATE_UINT64(counter, PFlashCFI01),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (const VMStateDescription * []) {
|
||||
&vmstate_pflash_blk_write,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
@@ -252,10 +225,34 @@ static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset,
|
||||
uint32_t ret;
|
||||
|
||||
p = pfl->storage;
|
||||
switch (width) {
|
||||
case 1:
|
||||
ret = p[offset];
|
||||
break;
|
||||
case 2:
|
||||
if (be) {
|
||||
ret = ldn_be_p(p + offset, width);
|
||||
ret = p[offset] << 8;
|
||||
ret |= p[offset + 1];
|
||||
} else {
|
||||
ret = ldn_le_p(p + offset, width);
|
||||
ret = p[offset];
|
||||
ret |= p[offset + 1] << 8;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (be) {
|
||||
ret = p[offset] << 24;
|
||||
ret |= p[offset + 1] << 16;
|
||||
ret |= p[offset + 2] << 8;
|
||||
ret |= p[offset + 3];
|
||||
} else {
|
||||
ret = p[offset];
|
||||
ret |= p[offset + 1] << 8;
|
||||
ret |= p[offset + 2] << 16;
|
||||
ret |= p[offset + 3] << 24;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
trace_pflash_data_read(pfl->name, offset, width, ret);
|
||||
return ret;
|
||||
@@ -403,61 +400,40 @@ static void pflash_update(PFlashCFI01 *pfl, int offset,
|
||||
}
|
||||
}
|
||||
|
||||
/* copy current flash content to block update buffer */
|
||||
static void pflash_blk_write_start(PFlashCFI01 *pfl, hwaddr offset)
|
||||
{
|
||||
hwaddr mask = ~(pfl->writeblock_size - 1);
|
||||
|
||||
trace_pflash_write_block_start(pfl->name, pfl->counter);
|
||||
pfl->blk_offset = offset & mask;
|
||||
memcpy(pfl->blk_bytes, pfl->storage + pfl->blk_offset,
|
||||
pfl->writeblock_size);
|
||||
}
|
||||
|
||||
/* commit block update buffer changes */
|
||||
static void pflash_blk_write_flush(PFlashCFI01 *pfl)
|
||||
{
|
||||
g_assert(pfl->blk_offset != -1);
|
||||
trace_pflash_write_block_flush(pfl->name);
|
||||
memcpy(pfl->storage + pfl->blk_offset, pfl->blk_bytes,
|
||||
pfl->writeblock_size);
|
||||
pflash_update(pfl, pfl->blk_offset, pfl->writeblock_size);
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
/* discard block update buffer changes */
|
||||
static void pflash_blk_write_abort(PFlashCFI01 *pfl)
|
||||
{
|
||||
trace_pflash_write_block_abort(pfl->name);
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
uint32_t value, int width, int be)
|
||||
{
|
||||
uint8_t *p;
|
||||
|
||||
if (pfl->blk_offset != -1) {
|
||||
/* block write: redirect writes to block update buffer */
|
||||
if ((offset < pfl->blk_offset) ||
|
||||
(offset + width > pfl->blk_offset + pfl->writeblock_size)) {
|
||||
pfl->status |= 0x10; /* Programming error */
|
||||
return;
|
||||
}
|
||||
trace_pflash_data_write_block(pfl->name, offset, width, value,
|
||||
pfl->counter);
|
||||
p = pfl->blk_bytes + (offset - pfl->blk_offset);
|
||||
} else {
|
||||
/* write directly to storage */
|
||||
trace_pflash_data_write(pfl->name, offset, width, value);
|
||||
p = pfl->storage + offset;
|
||||
}
|
||||
uint8_t *p = pfl->storage;
|
||||
|
||||
trace_pflash_data_write(pfl->name, offset, width, value, pfl->counter);
|
||||
switch (width) {
|
||||
case 1:
|
||||
p[offset] = value;
|
||||
break;
|
||||
case 2:
|
||||
if (be) {
|
||||
stn_be_p(p, width, value);
|
||||
p[offset] = value >> 8;
|
||||
p[offset + 1] = value;
|
||||
} else {
|
||||
stn_le_p(p, width, value);
|
||||
p[offset] = value;
|
||||
p[offset + 1] = value >> 8;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (be) {
|
||||
p[offset] = value >> 24;
|
||||
p[offset + 1] = value >> 16;
|
||||
p[offset + 2] = value >> 8;
|
||||
p[offset + 3] = value;
|
||||
} else {
|
||||
p[offset] = value;
|
||||
p[offset + 1] = value >> 8;
|
||||
p[offset + 2] = value >> 16;
|
||||
p[offset + 3] = value >> 24;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
@@ -572,9 +548,9 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
} else {
|
||||
value = extract32(value, 0, pfl->bank_width * 8);
|
||||
}
|
||||
trace_pflash_write_block(pfl->name, value);
|
||||
pfl->counter = value;
|
||||
pfl->wcycle++;
|
||||
pflash_blk_write_start(pfl, offset);
|
||||
break;
|
||||
case 0x60:
|
||||
if (cmd == 0xd0) {
|
||||
@@ -605,7 +581,12 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
switch (pfl->cmd) {
|
||||
case 0xe8: /* Block write */
|
||||
/* FIXME check @offset, @width */
|
||||
if (!pfl->ro && (pfl->blk_offset != -1)) {
|
||||
if (!pfl->ro) {
|
||||
/*
|
||||
* FIXME writing straight to memory is *wrong*. We
|
||||
* should write to a buffer, and flush it to memory
|
||||
* only on confirm command (see below).
|
||||
*/
|
||||
pflash_data_write(pfl, offset, value, width, be);
|
||||
} else {
|
||||
pfl->status |= 0x10; /* Programming error */
|
||||
@@ -614,8 +595,18 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
pfl->status |= 0x80;
|
||||
|
||||
if (!pfl->counter) {
|
||||
hwaddr mask = pfl->writeblock_size - 1;
|
||||
mask = ~mask;
|
||||
|
||||
trace_pflash_write(pfl->name, "block write finished");
|
||||
pfl->wcycle++;
|
||||
if (!pfl->ro) {
|
||||
/* Flush the entire write buffer onto backing storage. */
|
||||
/* FIXME premature! */
|
||||
pflash_update(pfl, offset & mask, pfl->writeblock_size);
|
||||
} else {
|
||||
pfl->status |= 0x10; /* Programming error */
|
||||
}
|
||||
}
|
||||
|
||||
pfl->counter--;
|
||||
@@ -627,17 +618,20 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||
case 3: /* Confirm mode */
|
||||
switch (pfl->cmd) {
|
||||
case 0xe8: /* Block write */
|
||||
if ((cmd == 0xd0) && !(pfl->status & 0x10)) {
|
||||
pflash_blk_write_flush(pfl);
|
||||
if (cmd == 0xd0) {
|
||||
/* FIXME this is where we should write out the buffer */
|
||||
pfl->wcycle = 0;
|
||||
pfl->status |= 0x80;
|
||||
} else {
|
||||
pflash_blk_write_abort(pfl);
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"%s: Aborting write to buffer not implemented,"
|
||||
" the data is already written to storage!\n"
|
||||
"Flash device reset into READ mode.\n",
|
||||
__func__);
|
||||
goto mode_read_array;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pflash_blk_write_abort(pfl);
|
||||
goto error_flash;
|
||||
}
|
||||
break;
|
||||
@@ -871,9 +865,6 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
||||
pfl->cmd = 0x00;
|
||||
pfl->status = 0x80; /* WSM ready */
|
||||
pflash_cfi01_fill_cfi_table(pfl);
|
||||
|
||||
pfl->blk_bytes = g_malloc(pfl->writeblock_size);
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
static void pflash_cfi01_system_reset(DeviceState *dev)
|
||||
@@ -893,8 +884,6 @@ static void pflash_cfi01_system_reset(DeviceState *dev)
|
||||
* This model deliberately ignores this delay.
|
||||
*/
|
||||
pfl->status = 0x80;
|
||||
|
||||
pfl->blk_offset = -1;
|
||||
}
|
||||
|
||||
static Property pflash_cfi01_properties[] = {
|
||||
|
||||
@@ -546,7 +546,7 @@ static void pflash_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
}
|
||||
goto reset_flash;
|
||||
}
|
||||
trace_pflash_data_write(pfl->name, offset, width, value);
|
||||
trace_pflash_data_write(pfl->name, offset, width, value, 0);
|
||||
if (!pfl->ro) {
|
||||
p = (uint8_t *)pfl->storage + offset;
|
||||
if (pfl->be) {
|
||||
|
||||
@@ -12,8 +12,7 @@ fdctrl_tc_pulse(int level) "TC pulse: %u"
|
||||
pflash_chip_erase_invalid(const char *name, uint64_t offset) "%s: chip erase: invalid address 0x%" PRIx64
|
||||
pflash_chip_erase_start(const char *name) "%s: start chip erase"
|
||||
pflash_data_read(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x"
|
||||
pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x"
|
||||
pflash_data_write_block(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
|
||||
pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
|
||||
pflash_device_id(const char *name, uint16_t id) "%s: read device ID: 0x%04x"
|
||||
pflash_device_info(const char *name, uint64_t offset) "%s: read device information offset:0x%04" PRIx64
|
||||
pflash_erase_complete(const char *name) "%s: sector erase complete"
|
||||
@@ -33,9 +32,7 @@ pflash_unlock0_failed(const char *name, uint64_t offset, uint8_t cmd, uint16_t a
|
||||
pflash_unlock1_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: unlock0 failed 0x%" PRIx64 " 0x%02x"
|
||||
pflash_unsupported_device_configuration(const char *name, uint8_t width, uint8_t max) "%s: unsupported device configuration: device_width:%d max_device_width:%d"
|
||||
pflash_write(const char *name, const char *str) "%s: %s"
|
||||
pflash_write_block_start(const char *name, uint32_t value) "%s: block write start: bytes:0x%x"
|
||||
pflash_write_block_flush(const char *name) "%s: block write flush"
|
||||
pflash_write_block_abort(const char *name) "%s: block write abort"
|
||||
pflash_write_block(const char *name, uint32_t value) "%s: block write: bytes:0x%x"
|
||||
pflash_write_block_erase(const char *name, uint64_t offset, uint64_t len) "%s: block erase offset:0x%" PRIx64 " bytes:0x%" PRIx64
|
||||
pflash_write_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: command failed 0x%" PRIx64 " 0x%02x"
|
||||
pflash_write_invalid(const char *name, uint8_t cmd) "%s: invalid write for command 0x%02x"
|
||||
|
||||
@@ -326,6 +326,7 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
|
||||
if (s->connected) {
|
||||
return 0;
|
||||
}
|
||||
s->connected = true;
|
||||
|
||||
s->dev.num_queues = s->num_queues;
|
||||
s->dev.nvqs = s->num_queues;
|
||||
@@ -342,14 +343,15 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
s->connected = true;
|
||||
|
||||
/* restore vhost state */
|
||||
if (virtio_device_started(vdev, vdev->status)) {
|
||||
ret = vhost_user_blk_start(vdev, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vhost_user_blk_disconnect(DeviceState *dev)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user