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);
 | 
			
		||||
    tb->pc = pc;
 | 
			
		||||
    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,8 +396,8 @@ static int cryptodev_builtin_create_session(
 | 
			
		||||
    case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
 | 
			
		||||
    case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
 | 
			
		||||
    default:
 | 
			
		||||
        error_report("Unsupported opcode :%" PRIu32 "",
 | 
			
		||||
                     sess_info->op_code);
 | 
			
		||||
        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,8 +552,8 @@ 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 "",
 | 
			
		||||
                     op_info->session_id);
 | 
			
		||||
        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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										135
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								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,
 | 
			
		||||
                                  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, 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,11 +4011,9 @@ 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;
 | 
			
		||||
        }
 | 
			
		||||
    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,10 +678,13 @@ 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) {
 | 
			
		||||
        blk_unref(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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								block/io.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								block/io.c
									
									
									
									
									
								
							@@ -1756,29 +1756,22 @@ 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);
 | 
			
		||||
    sliced_iov = qemu_iovec_slice(*qiov, *qiov_offset, *bytes,
 | 
			
		||||
                                  &sliced_head, &sliced_tail,
 | 
			
		||||
                                  &sliced_niov);
 | 
			
		||||
 | 
			
		||||
        /* Guaranteed by bdrv_check_request32() */
 | 
			
		||||
        assert(*bytes <= SIZE_MAX);
 | 
			
		||||
        ret = bdrv_create_padded_qiov(bs, pad, sliced_iov, sliced_niov,
 | 
			
		||||
                                      sliced_head, *bytes);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            bdrv_padding_finalize(pad);
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        *qiov = &pad->local_qiov;
 | 
			
		||||
        *qiov_offset = 0;
 | 
			
		||||
    /* Guaranteed by bdrv_check_request32() */
 | 
			
		||||
    assert(*bytes <= SIZE_MAX);
 | 
			
		||||
    ret = bdrv_create_padded_qiov(bs, pad, sliced_iov, sliced_niov,
 | 
			
		||||
                                  sliced_head, *bytes);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        bdrv_padding_finalize(pad);
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										64
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								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
 | 
			
		||||
  echo "WARNING: unrecognized host CPU, proceeding with 'uname -m' output '$cpu'"
 | 
			
		||||
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,19 +1391,16 @@ 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 | \
 | 
			
		||||
        i386:x86_64 | \
 | 
			
		||||
        mips*:mips64 | \
 | 
			
		||||
        ppc*:ppc64 | \
 | 
			
		||||
        sparc:sparc64 | \
 | 
			
		||||
        "$cpu:$cpu")
 | 
			
		||||
        try='native cross' ;;
 | 
			
		||||
      esac
 | 
			
		||||
  fi
 | 
			
		||||
  case "$target_arch:$cpu" in
 | 
			
		||||
    aarch64_be:aarch64 | \
 | 
			
		||||
    armeb:arm | \
 | 
			
		||||
    i386:x86_64 | \
 | 
			
		||||
    mips*:mips64 | \
 | 
			
		||||
    ppc*:ppc64 | \
 | 
			
		||||
    sparc:sparc64 | \
 | 
			
		||||
    "$cpu:$cpu")
 | 
			
		||||
      try='native cross' ;;
 | 
			
		||||
  esac
 | 
			
		||||
  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
 | 
			
		||||
~~~~~~~~~~~
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								docs/conf.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								docs/conf.py
									
									
									
									
									
								
							@@ -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 = {
 | 
			
		||||
    "style_nav_header_background": "#802400",
 | 
			
		||||
    "navigation_with_keys": True,
 | 
			
		||||
}
 | 
			
		||||
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,39 +1,34 @@
 | 
			
		||||
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
 | 
			
		||||
    swtpm socket --tpmstate dir=/tmp/vtpm2 \
 | 
			
		||||
      --ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock &
 | 
			
		||||
    --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 \
 | 
			
		||||
      -chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
 | 
			
		||||
      -mon chardev=libxl-cmd,mode=control \
 | 
			
		||||
      -chardev socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \
 | 
			
		||||
      -mon chardev=libxenstat-cmd,mode=control \
 | 
			
		||||
      -xen-attach -name guest0 -vnc none -display none -nographic \
 | 
			
		||||
      -machine xenpvh -m 1301 \
 | 
			
		||||
      -chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
 | 
			
		||||
      -tpmdev emulator,id=tpm0,chardev=chrtpm -machine tpm-base-addr=0x0C000000
 | 
			
		||||
    -chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
 | 
			
		||||
    -mon chardev=libxl-cmd,mode=control \
 | 
			
		||||
    -chardev socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \
 | 
			
		||||
    -mon chardev=libxenstat-cmd,mode=control \
 | 
			
		||||
    -xen-attach -name guest0 -vnc none -display none -nographic \
 | 
			
		||||
    -machine xenpvh -m 1301 \
 | 
			
		||||
    -chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
 | 
			
		||||
    -tpmdev emulator,id=tpm0,chardev=chrtpm -machine tpm-base-addr=0x0C000000
 | 
			
		||||
 | 
			
		||||
In above QEMU command, last two lines are for connecting xenpvh QEMU to swtpm
 | 
			
		||||
via chardev socket.
 | 
			
		||||
 
 | 
			
		||||
@@ -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,36 +826,47 @@ 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);
 | 
			
		||||
 | 
			
		||||
        resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
 | 
			
		||||
        iov_from_buf(buffer->elem->in_sg,
 | 
			
		||||
                     buffer->elem->in_num,
 | 
			
		||||
                     0,
 | 
			
		||||
                     &resp,
 | 
			
		||||
                     sizeof(virtio_snd_pcm_status));
 | 
			
		||||
        virtqueue_push(vq,
 | 
			
		||||
                       buffer->elem,
 | 
			
		||||
                       sizeof(virtio_snd_pcm_status));
 | 
			
		||||
        QSIMPLEQ_REMOVE_HEAD(&vsnd->invalid, entry);
 | 
			
		||||
        virtio_snd_pcm_buffer_free(buffer);
 | 
			
		||||
    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,
 | 
			
		||||
                                 0,
 | 
			
		||||
                                 &resp,
 | 
			
		||||
                                 sizeof(virtio_snd_pcm_status));
 | 
			
		||||
                    virtqueue_push(vq,
 | 
			
		||||
                                   buffer->elem,
 | 
			
		||||
                                   sizeof(virtio_snd_pcm_status));
 | 
			
		||||
                    QSIMPLEQ_REMOVE_HEAD(&stream->invalid, entry);
 | 
			
		||||
                    virtio_snd_pcm_buffer_free(buffer);
 | 
			
		||||
                }
 | 
			
		||||
                if (any) {
 | 
			
		||||
                    /*
 | 
			
		||||
                     * Notify vq about virtio_snd_pcm_status responses.
 | 
			
		||||
                     * Buffer responses must be notified separately later.
 | 
			
		||||
                     */
 | 
			
		||||
                    virtio_notify(vdev, vq);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /* Notify vq about virtio_snd_pcm_status responses. */
 | 
			
		||||
    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:
 | 
			
		||||
        must_empty_invalid_queue = true;
 | 
			
		||||
        buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
 | 
			
		||||
        buffer->elem = elem;
 | 
			
		||||
        buffer->vq = vq;
 | 
			
		||||
        QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
 | 
			
		||||
        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(&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:
 | 
			
		||||
        must_empty_invalid_queue = true;
 | 
			
		||||
        buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
 | 
			
		||||
        buffer->elem = elem;
 | 
			
		||||
        buffer->vq = vq;
 | 
			
		||||
        QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
 | 
			
		||||
        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(&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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
    if (be) {
 | 
			
		||||
        ret = ldn_be_p(p + offset, width);
 | 
			
		||||
    } else {
 | 
			
		||||
        ret = ldn_le_p(p + offset, width);
 | 
			
		||||
    switch (width) {
 | 
			
		||||
    case 1:
 | 
			
		||||
        ret = p[offset];
 | 
			
		||||
        break;
 | 
			
		||||
    case 2:
 | 
			
		||||
        if (be) {
 | 
			
		||||
            ret = p[offset] << 8;
 | 
			
		||||
            ret |= p[offset + 1];
 | 
			
		||||
        } else {
 | 
			
		||||
            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;
 | 
			
		||||
    uint8_t *p = pfl->storage;
 | 
			
		||||
 | 
			
		||||
    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(pfl->name, offset, width, value, pfl->counter);
 | 
			
		||||
    switch (width) {
 | 
			
		||||
    case 1:
 | 
			
		||||
        p[offset] = value;
 | 
			
		||||
        break;
 | 
			
		||||
    case 2:
 | 
			
		||||
        if (be) {
 | 
			
		||||
            p[offset] = value >> 8;
 | 
			
		||||
            p[offset + 1] = value;
 | 
			
		||||
        } else {
 | 
			
		||||
            p[offset] = value;
 | 
			
		||||
            p[offset + 1] = value >> 8;
 | 
			
		||||
        }
 | 
			
		||||
        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;
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (be) {
 | 
			
		||||
        stn_be_p(p, width, value);
 | 
			
		||||
    } else {
 | 
			
		||||
        stn_le_p(p, width, value);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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