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
|
then
|
||||||
pyvenv/bin/meson configure . -Dbackend_max_links="$LD_JOBS" ;
|
pyvenv/bin/meson configure . -Dbackend_max_links="$LD_JOBS" ;
|
||||||
fi || exit 1;
|
fi || exit 1;
|
||||||
- $MAKE -j"$JOBS"
|
- make -j"$JOBS"
|
||||||
- if test -n "$MAKE_CHECK_ARGS";
|
- if test -n "$MAKE_CHECK_ARGS";
|
||||||
then
|
then
|
||||||
$MAKE -j"$JOBS" $MAKE_CHECK_ARGS ;
|
make -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||||
fi
|
fi
|
||||||
- ccache --show-stats
|
- ccache --show-stats
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
- cd build
|
- cd build
|
||||||
- find . -type f -exec touch {} +
|
- find . -type f -exec touch {} +
|
||||||
# Avoid recompiling by hiding ninja with NINJA=":"
|
# Avoid recompiling by hiding ninja with NINJA=":"
|
||||||
- $MAKE NINJA=":" $MAKE_CHECK_ARGS
|
- make NINJA=":" $MAKE_CHECK_ARGS
|
||||||
|
|
||||||
.native_test_job_template:
|
.native_test_job_template:
|
||||||
extends: .common_test_job_template
|
extends: .common_test_job_template
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ build-system-ubuntu:
|
|||||||
variables:
|
variables:
|
||||||
IMAGE: ubuntu2204
|
IMAGE: ubuntu2204
|
||||||
CONFIGURE_ARGS: --enable-docs
|
CONFIGURE_ARGS: --enable-docs
|
||||||
TARGETS: alpha-softmmu microblaze-softmmu mips64el-softmmu
|
TARGETS: alpha-softmmu microblazeel-softmmu mips64el-softmmu
|
||||||
MAKE_CHECK_ARGS: check-build
|
MAKE_CHECK_ARGS: check-build
|
||||||
|
|
||||||
check-system-ubuntu:
|
check-system-ubuntu:
|
||||||
@@ -70,7 +70,7 @@ build-system-debian:
|
|||||||
needs:
|
needs:
|
||||||
job: amd64-debian-container
|
job: amd64-debian-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian
|
IMAGE: debian-amd64
|
||||||
CONFIGURE_ARGS: --with-coroutine=sigaltstack
|
CONFIGURE_ARGS: --with-coroutine=sigaltstack
|
||||||
TARGETS: arm-softmmu i386-softmmu riscv64-softmmu sh4eb-softmmu
|
TARGETS: arm-softmmu i386-softmmu riscv64-softmmu sh4eb-softmmu
|
||||||
sparc-softmmu xtensa-softmmu
|
sparc-softmmu xtensa-softmmu
|
||||||
@@ -82,7 +82,7 @@ check-system-debian:
|
|||||||
- job: build-system-debian
|
- job: build-system-debian
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian
|
IMAGE: debian-amd64
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-system-debian:
|
avocado-system-debian:
|
||||||
@@ -91,7 +91,7 @@ avocado-system-debian:
|
|||||||
- job: build-system-debian
|
- job: build-system-debian
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian
|
IMAGE: debian-amd64
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-avocado
|
||||||
AVOCADO_TAGS: arch:arm arch:i386 arch:riscv64 arch:sh4 arch:sparc arch:xtensa
|
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
|
- job: build-system-debian
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian
|
IMAGE: debian-amd64
|
||||||
script:
|
script:
|
||||||
- cd build
|
- cd build
|
||||||
- make NINJA=":" check-venv
|
- make NINJA=":" check-venv
|
||||||
@@ -158,9 +158,9 @@ build-system-centos:
|
|||||||
- .native_build_job_template
|
- .native_build_job_template
|
||||||
- .native_build_artifact_template
|
- .native_build_artifact_template
|
||||||
needs:
|
needs:
|
||||||
job: amd64-centos9-container
|
job: amd64-centos8-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: centos9
|
IMAGE: centos8
|
||||||
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
|
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
|
||||||
--enable-modules --enable-trace-backends=dtrace --enable-docs
|
--enable-modules --enable-trace-backends=dtrace --enable-docs
|
||||||
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
|
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
|
||||||
@@ -173,7 +173,7 @@ check-system-centos:
|
|||||||
- job: build-system-centos
|
- job: build-system-centos
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: centos9
|
IMAGE: centos8
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-system-centos:
|
avocado-system-centos:
|
||||||
@@ -182,7 +182,7 @@ avocado-system-centos:
|
|||||||
- job: build-system-centos
|
- job: build-system-centos
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: centos9
|
IMAGE: centos8
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-avocado
|
||||||
AVOCADO_TAGS: arch:ppc64 arch:or1k arch:390x arch:x86_64 arch:rx
|
AVOCADO_TAGS: arch:ppc64 arch:or1k arch:390x arch:x86_64 arch:rx
|
||||||
arch:sh4 arch:nios2
|
arch:sh4 arch:nios2
|
||||||
@@ -217,36 +217,6 @@ avocado-system-opensuse:
|
|||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-avocado
|
||||||
AVOCADO_TAGS: arch:s390x arch:x86_64 arch:aarch64
|
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
|
# This jobs explicitly disable TCG (--disable-tcg), KVM is detected by
|
||||||
# the configure script. The container doesn't contain Xen headers so
|
# the configure script. The container doesn't contain Xen headers so
|
||||||
@@ -258,9 +228,9 @@ avocado-system-flaky:
|
|||||||
build-tcg-disabled:
|
build-tcg-disabled:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
needs:
|
needs:
|
||||||
job: amd64-centos9-container
|
job: amd64-centos8-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: centos9
|
IMAGE: centos8
|
||||||
script:
|
script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
@@ -506,9 +476,6 @@ tsan-build:
|
|||||||
CONFIGURE_ARGS: --enable-tsan --cc=clang --cxx=clang++
|
CONFIGURE_ARGS: --enable-tsan --cc=clang --cxx=clang++
|
||||||
--enable-trace-backends=ust --disable-slirp
|
--enable-trace-backends=ust --disable-slirp
|
||||||
TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
|
TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
|
||||||
# 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 is a GCC features
|
||||||
gcov:
|
gcov:
|
||||||
@@ -585,9 +552,9 @@ build-tci:
|
|||||||
build-without-defaults:
|
build-without-defaults:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
needs:
|
needs:
|
||||||
job: amd64-centos9-container
|
job: amd64-centos8-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: centos9
|
IMAGE: centos8
|
||||||
CONFIGURE_ARGS:
|
CONFIGURE_ARGS:
|
||||||
--without-default-devices
|
--without-default-devices
|
||||||
--without-default-features
|
--without-default-features
|
||||||
@@ -622,7 +589,7 @@ build-tools-and-docs-debian:
|
|||||||
# when running on 'master' we use pre-existing container
|
# when running on 'master' we use pre-existing container
|
||||||
optional: true
|
optional: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian
|
IMAGE: debian-amd64
|
||||||
MAKE_CHECK_ARGS: check-unit ctags TAGS cscope
|
MAKE_CHECK_ARGS: check-unit ctags TAGS cscope
|
||||||
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
|
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
|
||||||
QEMU_JOB_PUBLISH: 1
|
QEMU_JOB_PUBLISH: 1
|
||||||
@@ -642,7 +609,7 @@ build-tools-and-docs-debian:
|
|||||||
# of what topic branch they're currently using
|
# of what topic branch they're currently using
|
||||||
pages:
|
pages:
|
||||||
extends: .base_job_template
|
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
|
stage: test
|
||||||
needs:
|
needs:
|
||||||
- job: build-tools-and-docs-debian
|
- job: build-tools-and-docs-debian
|
||||||
@@ -650,10 +617,7 @@ pages:
|
|||||||
- mkdir -p public
|
- mkdir -p public
|
||||||
# HTML-ised source tree
|
# HTML-ised source tree
|
||||||
- make gtags
|
- make gtags
|
||||||
# We unset variables to work around a bug in some htags versions
|
- htags -anT --tree-view=filetree -m qemu_init
|
||||||
# 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
|
|
||||||
-t "Welcome to the QEMU sourcecode"
|
-t "Welcome to the QEMU sourcecode"
|
||||||
- mv HTML public/src
|
- mv HTML public/src
|
||||||
# Project documentation
|
# Project documentation
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
.cirrus_build_job:
|
.cirrus_build_job:
|
||||||
extends: .base_job_template
|
extends: .base_job_template
|
||||||
stage: build
|
stage: build
|
||||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:latest
|
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
||||||
needs: []
|
needs: []
|
||||||
# 20 mins larger than "timeout_in" in cirrus/build.yml
|
# 20 mins larger than "timeout_in" in cirrus/build.yml
|
||||||
# as there's often a 5-10 minute delay before Cirrus CI
|
# as there's often a 5-10 minute delay before Cirrus CI
|
||||||
@@ -52,37 +52,20 @@ x64-freebsd-13-build:
|
|||||||
NAME: freebsd-13
|
NAME: freebsd-13
|
||||||
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
||||||
CIRRUS_VM_IMAGE_SELECTOR: image_family
|
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_CPUS: 8
|
||||||
CIRRUS_VM_RAM: 8G
|
CIRRUS_VM_RAM: 8G
|
||||||
UPDATE_COMMAND: pkg update; pkg upgrade -y
|
UPDATE_COMMAND: pkg update; pkg upgrade -y
|
||||||
INSTALL_COMMAND: pkg install -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
|
TEST_TARGETS: check
|
||||||
|
|
||||||
aarch64-macos-13-base-build:
|
aarch64-macos-12-base-build:
|
||||||
extends: .cirrus_build_job
|
extends: .cirrus_build_job
|
||||||
variables:
|
variables:
|
||||||
NAME: macos-13
|
NAME: macos-12
|
||||||
CIRRUS_VM_INSTANCE_TYPE: macos_instance
|
CIRRUS_VM_INSTANCE_TYPE: macos_instance
|
||||||
CIRRUS_VM_IMAGE_SELECTOR: image
|
CIRRUS_VM_IMAGE_SELECTOR: image
|
||||||
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-ventura-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
|
|
||||||
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_CPUS: 12
|
CIRRUS_VM_CPUS: 12
|
||||||
CIRRUS_VM_RAM: 24G
|
CIRRUS_VM_RAM: 24G
|
||||||
UPDATE_COMMAND: brew update
|
UPDATE_COMMAND: brew update
|
||||||
@@ -90,7 +73,6 @@ aarch64-macos-14-base-build:
|
|||||||
PATH_EXTRA: /opt/homebrew/ccache/libexec:/opt/homebrew/gettext/bin
|
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
|
PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
|
||||||
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
||||||
QEMU_JOB_OPTIONAL: 1
|
|
||||||
|
|
||||||
|
|
||||||
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
|
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ build_task:
|
|||||||
install_script:
|
install_script:
|
||||||
- @UPDATE_COMMAND@
|
- @UPDATE_COMMAND@
|
||||||
- @INSTALL_COMMAND@ @PKGS@
|
- @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:
|
clone_script:
|
||||||
- git clone --depth 100 "$CI_REPOSITORY_URL" .
|
- git clone --depth 100 "$CI_REPOSITORY_URL" .
|
||||||
- git fetch origin "$CI_COMMIT_REF_NAME"
|
- git fetch origin "$CI_COMMIT_REF_NAME"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# THIS FILE WAS AUTO-GENERATED
|
# THIS FILE WAS AUTO-GENERATED
|
||||||
#
|
#
|
||||||
# $ lcitool variables macos-13 qemu
|
# $ lcitool variables macos-12 qemu
|
||||||
#
|
#
|
||||||
# https://gitlab.com/libvirt/libvirt-ci
|
# 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:
|
include:
|
||||||
- local: '/.gitlab-ci.d/container-template.yml'
|
- local: '/.gitlab-ci.d/container-template.yml'
|
||||||
|
|
||||||
amd64-centos9-container:
|
amd64-centos8-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
variables:
|
variables:
|
||||||
NAME: centos9
|
NAME: centos8
|
||||||
|
|
||||||
amd64-fedora-container:
|
amd64-fedora-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
|
|||||||
@@ -46,12 +46,6 @@ loongarch-debian-cross-container:
|
|||||||
variables:
|
variables:
|
||||||
NAME: debian-loongarch-cross
|
NAME: debian-loongarch-cross
|
||||||
|
|
||||||
i686-debian-cross-container:
|
|
||||||
extends: .container_job_template
|
|
||||||
stage: containers
|
|
||||||
variables:
|
|
||||||
NAME: debian-i686-cross
|
|
||||||
|
|
||||||
mips64el-debian-cross-container:
|
mips64el-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers
|
||||||
@@ -101,6 +95,11 @@ cris-fedora-cross-container:
|
|||||||
variables:
|
variables:
|
||||||
NAME: fedora-cris-cross
|
NAME: fedora-cris-cross
|
||||||
|
|
||||||
|
i386-fedora-cross-container:
|
||||||
|
extends: .container_job_template
|
||||||
|
variables:
|
||||||
|
NAME: fedora-i386-cross
|
||||||
|
|
||||||
win32-fedora-cross-container:
|
win32-fedora-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
variables:
|
variables:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ amd64-debian-container:
|
|||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers
|
||||||
variables:
|
variables:
|
||||||
NAME: debian
|
NAME: debian-amd64
|
||||||
|
|
||||||
amd64-ubuntu2204-container:
|
amd64-ubuntu2204-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
|
|||||||
@@ -37,25 +37,25 @@ cross-arm64-kvm-only:
|
|||||||
IMAGE: debian-arm64-cross
|
IMAGE: debian-arm64-cross
|
||||||
EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features
|
EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features
|
||||||
|
|
||||||
cross-i686-user:
|
cross-i386-user:
|
||||||
extends:
|
extends:
|
||||||
- .cross_user_build_job
|
- .cross_user_build_job
|
||||||
- .cross_test_artifacts
|
- .cross_test_artifacts
|
||||||
needs:
|
needs:
|
||||||
job: i686-debian-cross-container
|
job: i386-fedora-cross-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian-i686-cross
|
IMAGE: fedora-i386-cross
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
cross-i686-tci:
|
cross-i386-tci:
|
||||||
extends:
|
extends:
|
||||||
- .cross_accel_build_job
|
- .cross_accel_build_job
|
||||||
- .cross_test_artifacts
|
- .cross_test_artifacts
|
||||||
timeout: 60m
|
timeout: 60m
|
||||||
needs:
|
needs:
|
||||||
job: i686-debian-cross-container
|
job: i386-fedora-cross-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian-i686-cross
|
IMAGE: fedora-i386-cross
|
||||||
ACCEL: tcg-interpreter
|
ACCEL: tcg-interpreter
|
||||||
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins
|
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins
|
||||||
MAKE_CHECK_ARGS: check check-tcg
|
MAKE_CHECK_ARGS: check check-tcg
|
||||||
@@ -165,7 +165,7 @@ cross-win32-system:
|
|||||||
job: win32-fedora-cross-container
|
job: win32-fedora-cross-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora-win32-cross
|
IMAGE: fedora-win32-cross
|
||||||
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal
|
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal --disable-plugins
|
||||||
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
|
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
|
||||||
microblazeel-softmmu mips64el-softmmu nios2-softmmu
|
microblazeel-softmmu mips64el-softmmu nios2-softmmu
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
.shared_msys2_builder:
|
.shared_msys2_builder:
|
||||||
extends: .base_job_template
|
extends: .base_job_template
|
||||||
tags:
|
tags:
|
||||||
- saas-windows-medium-amd64
|
- shared-windows
|
||||||
|
- windows
|
||||||
|
- windows-1809
|
||||||
cache:
|
cache:
|
||||||
key: "$CI_JOB_NAME"
|
key: "$CI_JOB_NAME"
|
||||||
paths:
|
paths:
|
||||||
@@ -86,6 +88,7 @@
|
|||||||
$MINGW_TARGET-libpng
|
$MINGW_TARGET-libpng
|
||||||
$MINGW_TARGET-libssh
|
$MINGW_TARGET-libssh
|
||||||
$MINGW_TARGET-libtasn1
|
$MINGW_TARGET-libtasn1
|
||||||
|
$MINGW_TARGET-libusb
|
||||||
$MINGW_TARGET-lzo2
|
$MINGW_TARGET-lzo2
|
||||||
$MINGW_TARGET-nettle
|
$MINGW_TARGET-nettle
|
||||||
$MINGW_TARGET-ninja
|
$MINGW_TARGET-ninja
|
||||||
@@ -95,8 +98,9 @@
|
|||||||
$MINGW_TARGET-SDL2
|
$MINGW_TARGET-SDL2
|
||||||
$MINGW_TARGET-SDL2_image
|
$MINGW_TARGET-SDL2_image
|
||||||
$MINGW_TARGET-snappy
|
$MINGW_TARGET-snappy
|
||||||
$MINGW_TARGET-zstd
|
$MINGW_TARGET-spice
|
||||||
$EXTRA_PACKAGES "
|
$MINGW_TARGET-usbredir
|
||||||
|
$MINGW_TARGET-zstd "
|
||||||
- Write-Output "Running build at $(Get-Date -Format u)"
|
- Write-Output "Running build at $(Get-Date -Format u)"
|
||||||
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||||
- $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
|
- $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
|
||||||
@@ -119,8 +123,6 @@ msys2-64bit:
|
|||||||
variables:
|
variables:
|
||||||
MINGW_TARGET: mingw-w64-x86_64
|
MINGW_TARGET: mingw-w64-x86_64
|
||||||
MSYSTEM: MINGW64
|
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"!
|
# do not remove "--without-default-devices"!
|
||||||
# commit 9f8e6cad65a6 ("gitlab-ci: Speed up the msys2-64bit job by using --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
|
# 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",
|
# qTests don't run successfully with "--without-default-devices",
|
||||||
# so let's exclude the qtests from CI for now.
|
# so let's exclude the qtests from CI for now.
|
||||||
TEST_ARGS: --no-suite qtest
|
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
|
# Required
|
||||||
version: 2
|
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
|
# Build documentation in the docs/ directory with Sphinx
|
||||||
sphinx:
|
sphinx:
|
||||||
configuration: docs/conf.py
|
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
|
# We want all the document formats
|
||||||
formats: all
|
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: docs/system/target-mips.rst
|
||||||
F: configs/targets/mips*
|
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)
|
Guest CPU cores (TCG)
|
||||||
---------------------
|
---------------------
|
||||||
Overall TCG CPUs
|
Overall TCG CPUs
|
||||||
@@ -174,7 +163,6 @@ F: include/hw/core/tcg-cpu-ops.h
|
|||||||
F: host/include/*/host/cpuinfo.h
|
F: host/include/*/host/cpuinfo.h
|
||||||
F: util/cpuinfo-*.c
|
F: util/cpuinfo-*.c
|
||||||
F: include/tcg/
|
F: include/tcg/
|
||||||
F: tests/decode/
|
|
||||||
|
|
||||||
FPU emulation
|
FPU emulation
|
||||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||||
@@ -669,7 +657,6 @@ F: include/hw/dma/pl080.h
|
|||||||
F: hw/dma/pl330.c
|
F: hw/dma/pl330.c
|
||||||
F: hw/gpio/pl061.c
|
F: hw/gpio/pl061.c
|
||||||
F: hw/input/pl050.c
|
F: hw/input/pl050.c
|
||||||
F: include/hw/input/pl050.h
|
|
||||||
F: hw/intc/pl190.c
|
F: hw/intc/pl190.c
|
||||||
F: hw/sd/pl181.c
|
F: hw/sd/pl181.c
|
||||||
F: hw/ssi/pl022.c
|
F: hw/ssi/pl022.c
|
||||||
@@ -940,7 +927,6 @@ F: hw/*/pxa2xx*
|
|||||||
F: hw/display/tc6393xb.c
|
F: hw/display/tc6393xb.c
|
||||||
F: hw/gpio/max7310.c
|
F: hw/gpio/max7310.c
|
||||||
F: hw/gpio/zaurus.c
|
F: hw/gpio/zaurus.c
|
||||||
F: hw/input/ads7846.c
|
|
||||||
F: hw/misc/mst_fpga.c
|
F: hw/misc/mst_fpga.c
|
||||||
F: hw/adc/max111x.c
|
F: hw/adc/max111x.c
|
||||||
F: include/hw/adc/max111x.h
|
F: include/hw/adc/max111x.h
|
||||||
@@ -993,9 +979,7 @@ M: Peter Maydell <peter.maydell@linaro.org>
|
|||||||
L: qemu-arm@nongnu.org
|
L: qemu-arm@nongnu.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: hw/*/stellaris*
|
F: hw/*/stellaris*
|
||||||
F: hw/display/ssd03*
|
|
||||||
F: include/hw/input/gamepad.h
|
F: include/hw/input/gamepad.h
|
||||||
F: include/hw/timer/stellaris-gptm.h
|
|
||||||
F: docs/system/arm/stellaris.rst
|
F: docs/system/arm/stellaris.rst
|
||||||
|
|
||||||
STM32VLDISCOVERY
|
STM32VLDISCOVERY
|
||||||
@@ -1010,7 +994,6 @@ M: Peter Maydell <peter.maydell@linaro.org>
|
|||||||
L: qemu-arm@nongnu.org
|
L: qemu-arm@nongnu.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: hw/arm/vexpress.c
|
F: hw/arm/vexpress.c
|
||||||
F: hw/display/sii9022.c
|
|
||||||
F: docs/system/arm/vexpress.rst
|
F: docs/system/arm/vexpress.rst
|
||||||
|
|
||||||
Versatile PB
|
Versatile PB
|
||||||
@@ -2258,7 +2241,7 @@ M: Stefan Hajnoczi <stefanha@redhat.com>
|
|||||||
S: Supported
|
S: Supported
|
||||||
F: hw/virtio/vhost-user-fs*
|
F: hw/virtio/vhost-user-fs*
|
||||||
F: include/hw/virtio/vhost-user-fs.h
|
F: include/hw/virtio/vhost-user-fs.h
|
||||||
L: virtio-fs@lists.linux.dev
|
L: virtio-fs@redhat.com
|
||||||
|
|
||||||
virtio-input
|
virtio-input
|
||||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
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 TranslationBlock *tb = p;
|
||||||
const struct tb_desc *desc = d;
|
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_page_addr0(tb) == desc->page_addr0 &&
|
||||||
tb->cs_base == desc->cs_base &&
|
tb->cs_base == desc->cs_base &&
|
||||||
tb->flags == desc->flags &&
|
tb->flags == desc->flags &&
|
||||||
@@ -233,7 +233,7 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, vaddr pc,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
desc.page_addr0 = phys_pc;
|
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);
|
flags, cs_base, cflags);
|
||||||
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
|
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) {
|
&& cpu->neg.icount_decr.u16.low + cpu->icount_extra == 0) {
|
||||||
/* Execute just one insn to trigger exception pending in the log */
|
/* Execute just one insn to trigger exception pending in the log */
|
||||||
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
|
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
|
||||||
| CF_NOIRQ | 1;
|
| CF_LAST_IO | CF_NOIRQ | 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1479,8 +1479,7 @@ int probe_access_full(CPUArchState *env, vaddr addr, int size,
|
|||||||
|
|
||||||
/* Handle clean RAM pages. */
|
/* Handle clean RAM pages. */
|
||||||
if (unlikely(flags & TLB_NOTDIRTY)) {
|
if (unlikely(flags & TLB_NOTDIRTY)) {
|
||||||
int dirtysize = size == 0 ? 1 : size;
|
notdirty_write(env_cpu(env), addr, 1, *pfull, retaddr);
|
||||||
notdirty_write(env_cpu(env), addr, dirtysize, *pfull, retaddr);
|
|
||||||
flags &= ~TLB_NOTDIRTY;
|
flags &= ~TLB_NOTDIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1503,8 +1502,7 @@ int probe_access_full_mmu(CPUArchState *env, vaddr addr, int size,
|
|||||||
|
|
||||||
/* Handle clean RAM pages. */
|
/* Handle clean RAM pages. */
|
||||||
if (unlikely(flags & TLB_NOTDIRTY)) {
|
if (unlikely(flags & TLB_NOTDIRTY)) {
|
||||||
int dirtysize = size == 0 ? 1 : size;
|
notdirty_write(env_cpu(env), addr, 1, *pfull, 0);
|
||||||
notdirty_write(env_cpu(env), addr, dirtysize, *pfull, 0);
|
|
||||||
flags &= ~TLB_NOTDIRTY;
|
flags &= ~TLB_NOTDIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1526,8 +1524,7 @@ int probe_access_flags(CPUArchState *env, vaddr addr, int size,
|
|||||||
|
|
||||||
/* Handle clean RAM pages. */
|
/* Handle clean RAM pages. */
|
||||||
if (unlikely(flags & TLB_NOTDIRTY)) {
|
if (unlikely(flags & TLB_NOTDIRTY)) {
|
||||||
int dirtysize = size == 0 ? 1 : size;
|
notdirty_write(env_cpu(env), addr, 1, full, retaddr);
|
||||||
notdirty_write(env_cpu(env), addr, dirtysize, full, retaddr);
|
|
||||||
flags &= ~TLB_NOTDIRTY;
|
flags &= ~TLB_NOTDIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1563,7 +1560,7 @@ void *probe_access(CPUArchState *env, vaddr addr, int size,
|
|||||||
|
|
||||||
/* Handle clean RAM pages. */
|
/* Handle clean RAM pages. */
|
||||||
if (flags & TLB_NOTDIRTY) {
|
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 *a = ap;
|
||||||
const TranslationBlock *b = bp;
|
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->cs_base == b->cs_base &&
|
||||||
a->flags == b->flags &&
|
a->flags == b->flags &&
|
||||||
(tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
|
(tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
|
||||||
@@ -712,7 +712,7 @@ static void tb_record(TranslationBlock *tb)
|
|||||||
tb_page_addr_t paddr0 = tb_page_addr0(tb);
|
tb_page_addr_t paddr0 = tb_page_addr0(tb);
|
||||||
tb_page_addr_t paddr1 = tb_page_addr1(tb);
|
tb_page_addr_t paddr1 = tb_page_addr1(tb);
|
||||||
tb_page_addr_t pindex0 = paddr0 >> TARGET_PAGE_BITS;
|
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);
|
assert(paddr0 != -1);
|
||||||
if (unlikely(paddr1 != -1) && pindex0 != pindex1) {
|
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 paddr0 = tb_page_addr0(tb);
|
||||||
tb_page_addr_t paddr1 = tb_page_addr1(tb);
|
tb_page_addr_t paddr1 = tb_page_addr1(tb);
|
||||||
tb_page_addr_t pindex0 = paddr0 >> TARGET_PAGE_BITS;
|
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);
|
assert(paddr0 != -1);
|
||||||
if (unlikely(paddr1 != -1) && pindex0 != pindex1) {
|
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 */
|
/* remove the TB from the hash list */
|
||||||
phys_pc = tb_page_addr0(tb);
|
phys_pc = tb_page_addr0(tb);
|
||||||
h = tb_hash_func(phys_pc, tb->pc,
|
h = tb_hash_func(phys_pc, (orig_cflags & CF_PCREL ? 0 : tb->pc),
|
||||||
tb->flags, tb->cs_base, orig_cflags);
|
tb->flags, tb->cs_base, orig_cflags);
|
||||||
if (!qht_remove(&tb_ctx.htable, tb, h)) {
|
if (!qht_remove(&tb_ctx.htable, tb, h)) {
|
||||||
return;
|
return;
|
||||||
@@ -983,7 +983,7 @@ TranslationBlock *tb_link_page(TranslationBlock *tb)
|
|||||||
tb_record(tb);
|
tb_record(tb);
|
||||||
|
|
||||||
/* add in the hash table */
|
/* 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);
|
tb->flags, tb->cs_base, tb->cflags);
|
||||||
qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
|
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) {
|
if (current_tb_modified) {
|
||||||
/* Force execution of one insn next time. */
|
/* Force execution of one insn next time. */
|
||||||
CPUState *cpu = current_cpu;
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -1153,7 +1154,8 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
|
|||||||
if (current_tb_modified) {
|
if (current_tb_modified) {
|
||||||
page_collection_unlock(pages);
|
page_collection_unlock(pages);
|
||||||
/* Force execution of one insn next time. */
|
/* 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();
|
mmap_unlock();
|
||||||
cpu_loop_exit_noexc(current_cpu);
|
cpu_loop_exit_noexc(current_cpu);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||||||
|
|
||||||
if (phys_pc == -1) {
|
if (phys_pc == -1) {
|
||||||
/* Generate a one-shot TB with 1 insn in it */
|
/* 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;
|
max_insns = cflags & CF_COUNT_MASK;
|
||||||
@@ -327,7 +327,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||||||
|
|
||||||
gen_code_buf = tcg_ctx->code_gen_ptr;
|
gen_code_buf = tcg_ctx->code_gen_ptr;
|
||||||
tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf);
|
tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf);
|
||||||
tb->pc = pc;
|
if (!(cflags & CF_PCREL)) {
|
||||||
|
tb->pc = pc;
|
||||||
|
}
|
||||||
tb->cs_base = cs_base;
|
tb->cs_base = cs_base;
|
||||||
tb->flags = flags;
|
tb->flags = flags;
|
||||||
tb->cflags = cflags;
|
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
|
* operations only (which execute after completion) so we don't
|
||||||
* double instrument the instruction.
|
* 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)) {
|
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
|
||||||
vaddr pc = log_pc(cpu, tb);
|
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
|
* each translation block. The cost is minimal, plus it would be
|
||||||
* very easy to forget doing it in the translator.
|
* 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;
|
return icount_start_insn;
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,13 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
|||||||
ops->tb_start(db, cpu);
|
ops->tb_start(db, cpu);
|
||||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||||
|
|
||||||
plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY);
|
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;
|
db->plugin_enabled = plugin_enabled;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -163,13 +169,11 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
|||||||
plugin_gen_insn_start(cpu, db);
|
plugin_gen_insn_start(cpu, db);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Disassemble one instruction. The translate_insn hook should
|
||||||
* Disassemble one instruction. The translate_insn hook should
|
update db->pc_next and db->is_jmp to indicate what should be
|
||||||
* update db->pc_next and db->is_jmp to indicate what should be
|
done next -- either exiting this loop or locate the start of
|
||||||
* done next -- either exiting this loop or locate the start of
|
the next instruction. */
|
||||||
* the next instruction.
|
if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
|
||||||
*/
|
|
||||||
if (db->num_insns == db->max_insns) {
|
|
||||||
/* Accept I/O on the last instruction. */
|
/* Accept I/O on the last instruction. */
|
||||||
set_can_do_io(db, true);
|
set_can_do_io(db, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1744,7 +1744,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp)
|
|||||||
if (driver) {
|
if (driver) {
|
||||||
done = !audio_driver_init(s, driver, dev, errp);
|
done = !audio_driver_init(s, driver, dev, errp);
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "Unknown audio driver `%s'", drvname);
|
error_setg(errp, "Unknown audio driver `%s'\n", drvname);
|
||||||
}
|
}
|
||||||
if (!done) {
|
if (!done) {
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1758,15 +1758,12 @@ static AudioState *audio_init(Audiodev *dev, Error **errp)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
s->dev = dev = e->dev;
|
s->dev = dev = e->dev;
|
||||||
QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next);
|
|
||||||
g_free(e);
|
|
||||||
drvname = AudiodevDriver_str(dev->driver);
|
drvname = AudiodevDriver_str(dev->driver);
|
||||||
driver = audio_driver_lookup(drvname);
|
driver = audio_driver_lookup(drvname);
|
||||||
if (!audio_driver_init(s, driver, dev, NULL)) {
|
if (!audio_driver_init(s, driver, dev, NULL)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
qapi_free_Audiodev(dev);
|
QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next);
|
||||||
s->dev = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ endforeach
|
|||||||
|
|
||||||
if dbus_display
|
if dbus_display
|
||||||
module_ss = ss.source_set()
|
module_ss = ss.source_set()
|
||||||
module_ss.add(when: [gio, dbus_display1_dep, pixman],
|
module_ss.add(when: [gio, pixman], if_true: files('dbusaudio.c'))
|
||||||
if_true: files('dbusaudio.c'))
|
|
||||||
audio_modules += {'dbus': module_ss}
|
audio_modules += {'dbus': module_ss}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "sysemu/cryptodev.h"
|
#include "sysemu/cryptodev.h"
|
||||||
#include "qemu/error-report.h"
|
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "standard-headers/linux/virtio_crypto.h"
|
#include "standard-headers/linux/virtio_crypto.h"
|
||||||
#include "crypto/cipher.h"
|
#include "crypto/cipher.h"
|
||||||
@@ -397,8 +396,8 @@ static int cryptodev_builtin_create_session(
|
|||||||
case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
|
case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
|
||||||
case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
|
case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
|
||||||
default:
|
default:
|
||||||
error_report("Unsupported opcode :%" PRIu32 "",
|
error_setg(&local_error, "Unsupported opcode :%" PRIu32 "",
|
||||||
sess_info->op_code);
|
sess_info->op_code);
|
||||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,9 +427,7 @@ static int cryptodev_builtin_close_session(
|
|||||||
CRYPTODEV_BACKEND_BUILTIN(backend);
|
CRYPTODEV_BACKEND_BUILTIN(backend);
|
||||||
CryptoDevBackendBuiltinSession *session;
|
CryptoDevBackendBuiltinSession *session;
|
||||||
|
|
||||||
if (session_id >= MAX_NUM_SESSIONS || !builtin->sessions[session_id]) {
|
assert(session_id < MAX_NUM_SESSIONS && builtin->sessions[session_id]);
|
||||||
return -VIRTIO_CRYPTO_INVSESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
session = builtin->sessions[session_id];
|
session = builtin->sessions[session_id];
|
||||||
if (session->cipher) {
|
if (session->cipher) {
|
||||||
@@ -555,8 +552,8 @@ static int cryptodev_builtin_operation(
|
|||||||
|
|
||||||
if (op_info->session_id >= MAX_NUM_SESSIONS ||
|
if (op_info->session_id >= MAX_NUM_SESSIONS ||
|
||||||
builtin->sessions[op_info->session_id] == NULL) {
|
builtin->sessions[op_info->session_id] == NULL) {
|
||||||
error_report("Cannot find a valid session id: %" PRIu64 "",
|
error_setg(&local_error, "Cannot find a valid session id: %" PRIu64 "",
|
||||||
op_info->session_id);
|
op_info->session_id);
|
||||||
return -VIRTIO_CRYPTO_INVSESS;
|
return -VIRTIO_CRYPTO_INVSESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -398,7 +398,6 @@ static void cryptodev_backend_set_ops(Object *obj, Visitor *v,
|
|||||||
static void
|
static void
|
||||||
cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
||||||
{
|
{
|
||||||
ERRP_GUARD();
|
|
||||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
|
||||||
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
|
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
|
||||||
uint32_t services;
|
uint32_t services;
|
||||||
@@ -407,20 +406,11 @@ cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
|||||||
QTAILQ_INIT(&backend->opinfos);
|
QTAILQ_INIT(&backend->opinfos);
|
||||||
value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
|
value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
|
||||||
cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
|
cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
|
||||||
if (*errp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
|
value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
|
||||||
cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
|
cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
|
||||||
if (*errp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bc->init) {
|
if (bc->init) {
|
||||||
bc->init(backend, errp);
|
bc->init(backend, errp);
|
||||||
if (*errp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
services = backend->conf.crypto_services;
|
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,
|
BlockDriverState *parent,
|
||||||
const BdrvChildClass *child_class,
|
const BdrvChildClass *child_class,
|
||||||
BdrvChildRole child_role,
|
BdrvChildRole child_role,
|
||||||
bool parse_filename,
|
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
static bool bdrv_recurse_has_child(BlockDriverState *bs,
|
static bool bdrv_recurse_has_child(BlockDriverState *bs,
|
||||||
@@ -1714,7 +1713,7 @@ open_failed:
|
|||||||
bdrv_unref_child(bs, bs->file);
|
bdrv_unref_child(bs, bs->file);
|
||||||
assert(!bs->file);
|
assert(!bs->file);
|
||||||
}
|
}
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
g_free(bs->opaque);
|
g_free(bs->opaque);
|
||||||
bs->opaque = NULL;
|
bs->opaque = NULL;
|
||||||
@@ -2048,8 +2047,7 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
|
|||||||
* block driver has been specified explicitly.
|
* block driver has been specified explicitly.
|
||||||
*/
|
*/
|
||||||
static int bdrv_fill_options(QDict **options, const char *filename,
|
static int bdrv_fill_options(QDict **options, const char *filename,
|
||||||
int *flags, bool allow_parse_filename,
|
int *flags, Error **errp)
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
const char *drvname;
|
const char *drvname;
|
||||||
bool protocol = *flags & BDRV_O_PROTOCOL;
|
bool protocol = *flags & BDRV_O_PROTOCOL;
|
||||||
@@ -2091,7 +2089,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
|||||||
if (protocol && filename) {
|
if (protocol && filename) {
|
||||||
if (!qdict_haskey(*options, "filename")) {
|
if (!qdict_haskey(*options, "filename")) {
|
||||||
qdict_put_str(*options, "filename", filename);
|
qdict_put_str(*options, "filename", filename);
|
||||||
parse_filename = allow_parse_filename;
|
parse_filename = true;
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "Can't specify 'file' and 'filename' options at "
|
error_setg(errp, "Can't specify 'file' and 'filename' options at "
|
||||||
"the same time");
|
"the same time");
|
||||||
@@ -3579,7 +3577,7 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
|||||||
bdrv_drained_begin(drain_bs);
|
bdrv_drained_begin(drain_bs);
|
||||||
bdrv_graph_wrlock(backing_hd);
|
bdrv_graph_wrlock(backing_hd);
|
||||||
ret = bdrv_set_backing_hd_drained(bs, backing_hd, errp);
|
ret = bdrv_set_backing_hd_drained(bs, backing_hd, errp);
|
||||||
bdrv_graph_wrunlock(backing_hd);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_drained_end(drain_bs);
|
bdrv_drained_end(drain_bs);
|
||||||
bdrv_unref(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,
|
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
|
||||||
&child_of_bds, bdrv_backing_role(bs), true,
|
&child_of_bds, bdrv_backing_role(bs), errp);
|
||||||
errp);
|
|
||||||
if (!backing_hd) {
|
if (!backing_hd) {
|
||||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||||
error_prepend(errp, "Could not open backing file: ");
|
error_prepend(errp, "Could not open backing file: ");
|
||||||
@@ -3715,8 +3712,7 @@ free_exit:
|
|||||||
static BlockDriverState *
|
static BlockDriverState *
|
||||||
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||||
BlockDriverState *parent, const BdrvChildClass *child_class,
|
BlockDriverState *parent, const BdrvChildClass *child_class,
|
||||||
BdrvChildRole child_role, bool allow_none,
|
BdrvChildRole child_role, bool allow_none, Error **errp)
|
||||||
bool parse_filename, Error **errp)
|
|
||||||
{
|
{
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
QDict *image_options;
|
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,
|
bs = bdrv_open_inherit(filename, reference, image_options, 0,
|
||||||
parent, child_class, child_role, parse_filename,
|
parent, child_class, child_role, errp);
|
||||||
errp);
|
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@@ -3758,37 +3753,6 @@ done:
|
|||||||
return bs;
|
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
|
* Opens a disk image whose options are given as BlockdevRef in another block
|
||||||
* device's options.
|
* device's options.
|
||||||
@@ -3814,15 +3778,31 @@ BdrvChild *bdrv_open_child(const char *filename,
|
|||||||
BdrvChildRole child_role,
|
BdrvChildRole child_role,
|
||||||
bool allow_none, Error **errp)
|
bool allow_none, Error **errp)
|
||||||
{
|
{
|
||||||
return bdrv_open_child_common(filename, options, bdref_key, parent,
|
BlockDriverState *bs;
|
||||||
child_class, child_role, allow_none, false,
|
BdrvChild *child;
|
||||||
errp);
|
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
|
* Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
|
||||||
* child of a node. A notable difference from bdrv_open_child() is that it
|
|
||||||
* enables filename parsing for protocol names (including json:).
|
|
||||||
*
|
*
|
||||||
* The caller must hold the lock of the main AioContext and no other AioContext.
|
* 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
|
* @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 ?
|
role = parent->drv->is_filter ?
|
||||||
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
|
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
|
||||||
|
|
||||||
if (!bdrv_open_child_common(filename, options, bdref_key, parent,
|
if (!bdrv_open_child(filename, options, bdref_key, parent,
|
||||||
&child_of_bds, role, false, true, errp))
|
&child_of_bds, role, false, errp))
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
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,
|
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
|
||||||
errp);
|
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
qobject_unref(obj);
|
qobject_unref(obj);
|
||||||
visit_free(v);
|
visit_free(v);
|
||||||
@@ -3983,7 +3962,7 @@ static BlockDriverState * no_coroutine_fn
|
|||||||
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||||
int flags, BlockDriverState *parent,
|
int flags, BlockDriverState *parent,
|
||||||
const BdrvChildClass *child_class, BdrvChildRole child_role,
|
const BdrvChildClass *child_class, BdrvChildRole child_role,
|
||||||
bool parse_filename, Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
BlockBackend *file = NULL;
|
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 */
|
/* json: syntax counts as explicit options, as if in the QDict */
|
||||||
if (parse_filename) {
|
parse_json_protocol(options, &filename, &local_err);
|
||||||
parse_json_protocol(options, &filename, &local_err);
|
if (local_err) {
|
||||||
if (local_err) {
|
goto fail;
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bs->explicit_options = qdict_clone_shallow(options);
|
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);
|
parent->open_flags, parent->options);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
|
ret = bdrv_fill_options(&options, filename, &flags, &local_err);
|
||||||
&local_err);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
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,
|
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
|
||||||
&child_of_bds, BDRV_CHILD_IMAGE,
|
&child_of_bds, BDRV_CHILD_IMAGE,
|
||||||
true, true, &local_err);
|
true, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -4294,7 +4270,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
|
|||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
|
|
||||||
return bdrv_open_inherit(filename, reference, options, flags, NULL,
|
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 */
|
/* 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);
|
bdrv_graph_wrlock(NULL);
|
||||||
tran_commit(tran);
|
tran_commit(tran);
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) {
|
QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) {
|
||||||
BlockDriverState *bs = bs_entry->state.bs;
|
BlockDriverState *bs = bs_entry->state.bs;
|
||||||
@@ -4695,7 +4671,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
|
|||||||
abort:
|
abort:
|
||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
tran_abort(tran);
|
tran_abort(tran);
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
|
QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
|
||||||
if (bs_entry->prepared) {
|
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,
|
ret = bdrv_set_file_or_backing_noperm(bs, new_child_bs, is_backing,
|
||||||
tran, errp);
|
tran, errp);
|
||||||
|
|
||||||
bdrv_graph_wrunlock_ctx(ctx);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
if (old_ctx != ctx) {
|
if (old_ctx != ctx) {
|
||||||
aio_context_release(ctx);
|
aio_context_release(ctx);
|
||||||
@@ -5240,7 +5216,7 @@ static void bdrv_close(BlockDriverState *bs)
|
|||||||
|
|
||||||
assert(!bs->backing);
|
assert(!bs->backing);
|
||||||
assert(!bs->file);
|
assert(!bs->file);
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
g_free(bs->opaque);
|
g_free(bs->opaque);
|
||||||
bs->opaque = NULL;
|
bs->opaque = NULL;
|
||||||
@@ -5535,7 +5511,7 @@ int bdrv_drop_filter(BlockDriverState *bs, Error **errp)
|
|||||||
bdrv_drained_begin(child_bs);
|
bdrv_drained_begin(child_bs);
|
||||||
bdrv_graph_wrlock(bs);
|
bdrv_graph_wrlock(bs);
|
||||||
ret = bdrv_replace_node_common(bs, child_bs, true, true, errp);
|
ret = bdrv_replace_node_common(bs, child_bs, true, true, errp);
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_drained_end(child_bs);
|
bdrv_drained_end(child_bs);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -5617,7 +5593,7 @@ out:
|
|||||||
tran_finalize(tran, ret);
|
tran_finalize(tran, ret);
|
||||||
|
|
||||||
bdrv_refresh_limits(bs_top, NULL, NULL);
|
bdrv_refresh_limits(bs_top, NULL, NULL);
|
||||||
bdrv_graph_wrunlock(bs_top);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
bdrv_drained_end(bs_top);
|
bdrv_drained_end(bs_top);
|
||||||
bdrv_drained_end(bs_new);
|
bdrv_drained_end(bs_new);
|
||||||
@@ -5655,7 +5631,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
|
|||||||
|
|
||||||
tran_finalize(tran, ret);
|
tran_finalize(tran, ret);
|
||||||
|
|
||||||
bdrv_graph_wrunlock(new_bs);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_drained_end(old_bs);
|
bdrv_drained_end(old_bs);
|
||||||
bdrv_drained_end(new_bs);
|
bdrv_drained_end(new_bs);
|
||||||
bdrv_unref(old_bs);
|
bdrv_unref(old_bs);
|
||||||
@@ -5744,7 +5720,7 @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
|
|||||||
bdrv_drained_begin(new_node_bs);
|
bdrv_drained_begin(new_node_bs);
|
||||||
bdrv_graph_wrlock(new_node_bs);
|
bdrv_graph_wrlock(new_node_bs);
|
||||||
ret = bdrv_replace_node(bs, new_node_bs, errp);
|
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(new_node_bs);
|
||||||
bdrv_drained_end(bs);
|
bdrv_drained_end(bs);
|
||||||
bdrv_unref(bs);
|
bdrv_unref(bs);
|
||||||
@@ -6039,7 +6015,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
|||||||
* That's a FIXME.
|
* That's a FIXME.
|
||||||
*/
|
*/
|
||||||
bdrv_replace_node_common(top, base, false, false, &local_err);
|
bdrv_replace_node_common(top, base, false, false, &local_err);
|
||||||
bdrv_graph_wrunlock(base);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_report_err(local_err);
|
error_report_err(local_err);
|
||||||
@@ -6076,7 +6052,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
exit_wrlock:
|
exit_wrlock:
|
||||||
bdrv_graph_wrunlock(base);
|
bdrv_graph_wrunlock();
|
||||||
exit:
|
exit:
|
||||||
bdrv_drained_end(base);
|
bdrv_drained_end(base);
|
||||||
bdrv_unref(top);
|
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.
|
* Release a BlockDriverState reference while holding the graph write lock.
|
||||||
*
|
*
|
||||||
@@ -7301,7 +7267,8 @@ void bdrv_schedule_unref(BlockDriverState *bs)
|
|||||||
if (!bs) {
|
if (!bs) {
|
||||||
return;
|
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 {
|
struct BdrvOpBlocker {
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|||||||
bdrv_graph_wrlock(target);
|
bdrv_graph_wrlock(target);
|
||||||
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
bdrv_graph_wrunlock(target);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
return &job->common;
|
return &job->common;
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ typedef struct {
|
|||||||
CoQueue bounce_available;
|
CoQueue bounce_available;
|
||||||
|
|
||||||
/* The value of the "mem-region-alignment" property */
|
/* 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? */
|
/* Can we skip adding/deleting blkio_mem_regions? */
|
||||||
bool needs_mem_regions;
|
bool needs_mem_regions;
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ fail_log:
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_unref_child(bs, s->log_file);
|
bdrv_unref_child(bs, s->log_file);
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
s->log_file = NULL;
|
s->log_file = NULL;
|
||||||
}
|
}
|
||||||
fail:
|
fail:
|
||||||
@@ -268,7 +268,7 @@ static void blk_log_writes_close(BlockDriverState *bs)
|
|||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_unref_child(bs, s->log_file);
|
bdrv_unref_child(bs, s->log_file);
|
||||||
s->log_file = NULL;
|
s->log_file = NULL;
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t coroutine_fn GRAPH_RDLOCK
|
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)
|
blk_log_writes_co_do_log(BlkLogWritesLogReq *lr)
|
||||||
{
|
{
|
||||||
BDRVBlkLogWritesState *s = lr->bs->opaque;
|
BDRVBlkLogWritesState *s = lr->bs->opaque;
|
||||||
|
uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits;
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
s->nr_entries++;
|
s->nr_entries++;
|
||||||
s->cur_log_sector += entry_nr_sectors;
|
s->cur_log_sector +=
|
||||||
|
ROUND_UP(lr->qiov->size, s->sectorsize) >> s->sectorbits;
|
||||||
|
|
||||||
/*
|
lr->log_ret = bdrv_co_pwritev(s->log_file, cur_log_offset, lr->qiov->size,
|
||||||
* 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->qiov, 0);
|
lr->qiov, 0);
|
||||||
|
|
||||||
/* Logging for the "write zeroes" operation */
|
/* Logging for the "write zeroes" operation */
|
||||||
if (lr->log_ret == 0 && lr->zero_size) {
|
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);
|
lr->zero_size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ static void blkverify_close(BlockDriverState *bs)
|
|||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_unref_child(bs, s->test_file);
|
bdrv_unref_child(bs, s->test_file);
|
||||||
s->test_file = NULL;
|
s->test_file = NULL;
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t coroutine_fn GRAPH_RDLOCK
|
static int64_t coroutine_fn GRAPH_RDLOCK
|
||||||
|
|||||||
@@ -613,14 +613,14 @@ BlockDriverState *bdrv_next(BdrvNextIterator *it)
|
|||||||
/* Must be called from the main loop */
|
/* Must be called from the main loop */
|
||||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
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
|
/* 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
|
* 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 the BB is the first one in the parent list of the BDS. */
|
||||||
if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
|
if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
|
||||||
BlockBackend *old_blk = it->blk;
|
BlockBackend *old_blk = it->blk;
|
||||||
|
|
||||||
|
old_bs = old_blk ? blk_bs(old_blk) : NULL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
it->blk = blk_all_next(it->blk);
|
it->blk = blk_all_next(it->blk);
|
||||||
bs = it->blk ? blk_bs(it->blk) : NULL;
|
bs = it->blk ? blk_bs(it->blk) : NULL;
|
||||||
@@ -634,10 +634,11 @@ BlockDriverState *bdrv_next(BdrvNextIterator *it)
|
|||||||
if (bs) {
|
if (bs) {
|
||||||
bdrv_ref(bs);
|
bdrv_ref(bs);
|
||||||
bdrv_unref(old_bs);
|
bdrv_unref(old_bs);
|
||||||
it->bs = bs;
|
|
||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
it->phase = BDRV_NEXT_MONITOR_OWNED;
|
it->phase = BDRV_NEXT_MONITOR_OWNED;
|
||||||
|
} else {
|
||||||
|
old_bs = it->bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then return the monitor-owned BDSes without a BB attached. Ignore all
|
/* 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 */
|
/* Must be called from the main loop */
|
||||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||||
|
|
||||||
bdrv_unref(it->bs);
|
if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
|
||||||
|
if (it->blk) {
|
||||||
if (it->phase == BDRV_NEXT_BACKEND_ROOTS && it->blk) {
|
bdrv_unref(blk_bs(it->blk));
|
||||||
blk_unref(it->blk);
|
blk_unref(it->blk);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bdrv_unref(it->bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_next_reset(it);
|
bdrv_next_reset(it);
|
||||||
@@ -878,14 +882,11 @@ BlockBackend *blk_by_public(BlockBackendPublic *public)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Disassociates the currently associated BlockDriverState from @blk.
|
* Disassociates the currently associated BlockDriverState from @blk.
|
||||||
*
|
|
||||||
* The caller must hold the AioContext lock for the BlockBackend.
|
|
||||||
*/
|
*/
|
||||||
void blk_remove_bs(BlockBackend *blk)
|
void blk_remove_bs(BlockBackend *blk)
|
||||||
{
|
{
|
||||||
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
||||||
BdrvChild *root;
|
BdrvChild *root;
|
||||||
AioContext *ctx;
|
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
|
|
||||||
@@ -915,10 +916,9 @@ void blk_remove_bs(BlockBackend *blk)
|
|||||||
root = blk->root;
|
root = blk->root;
|
||||||
blk->root = NULL;
|
blk->root = NULL;
|
||||||
|
|
||||||
ctx = bdrv_get_aio_context(root->bs);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_graph_wrlock(root->bs);
|
|
||||||
bdrv_root_unref_child(root);
|
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)
|
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
|
||||||
{
|
{
|
||||||
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
||||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
bdrv_ref(bs);
|
bdrv_ref(bs);
|
||||||
bdrv_graph_wrlock(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,
|
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
|
||||||
blk->perm, blk->shared_perm,
|
blk->perm, blk->shared_perm,
|
||||||
blk, errp);
|
blk, errp);
|
||||||
bdrv_graph_wrunlock_ctx(ctx);
|
bdrv_graph_wrunlock();
|
||||||
if (blk->root == NULL) {
|
if (blk->root == NULL) {
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ static void commit_abort(Job *job)
|
|||||||
bdrv_drained_begin(commit_top_backing_bs);
|
bdrv_drained_begin(commit_top_backing_bs);
|
||||||
bdrv_graph_wrlock(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_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_drained_end(commit_top_backing_bs);
|
||||||
|
|
||||||
bdrv_unref(s->commit_top_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,
|
ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
||||||
iter_shared_perms, errp);
|
iter_shared_perms, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_graph_wrunlock(top);
|
bdrv_graph_wrunlock();
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
|
if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
|
||||||
bdrv_graph_wrunlock(top);
|
bdrv_graph_wrunlock();
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
s->chain_frozen = true;
|
s->chain_frozen = true;
|
||||||
|
|
||||||
ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp);
|
ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp);
|
||||||
bdrv_graph_wrunlock(top);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -436,7 +436,7 @@ fail:
|
|||||||
bdrv_drained_begin(top);
|
bdrv_drained_begin(top);
|
||||||
bdrv_graph_wrlock(top);
|
bdrv_graph_wrlock(top);
|
||||||
bdrv_replace_node(commit_top_bs, top, &error_abort);
|
bdrv_replace_node(commit_top_bs, top, &error_abort);
|
||||||
bdrv_graph_wrunlock(top);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_drained_end(top);
|
bdrv_drained_end(top);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -283,7 +283,6 @@ static void vu_blk_drained_begin(void *opaque)
|
|||||||
{
|
{
|
||||||
VuBlkExport *vexp = opaque;
|
VuBlkExport *vexp = opaque;
|
||||||
|
|
||||||
vexp->vu_server.quiescing = true;
|
|
||||||
vhost_user_server_detach_aio_context(&vexp->vu_server);
|
vhost_user_server_detach_aio_context(&vexp->vu_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,23 +291,19 @@ static void vu_blk_drained_end(void *opaque)
|
|||||||
{
|
{
|
||||||
VuBlkExport *vexp = opaque;
|
VuBlkExport *vexp = opaque;
|
||||||
|
|
||||||
vexp->vu_server.quiescing = false;
|
|
||||||
vhost_user_server_attach_aio_context(&vexp->vu_server, vexp->export.ctx);
|
vhost_user_server_attach_aio_context(&vexp->vu_server, vexp->export.ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensures that bdrv_drained_begin() waits until in-flight requests complete
|
* 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().
|
|
||||||
*
|
*
|
||||||
* Called with vexp->export.ctx acquired.
|
* Called with vexp->export.ctx acquired.
|
||||||
*/
|
*/
|
||||||
static bool vu_blk_drained_poll(void *opaque)
|
static bool vu_blk_drained_poll(void *opaque)
|
||||||
{
|
{
|
||||||
VuBlkExport *vexp = 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 = {
|
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();
|
GLOBAL_STATE_CODE();
|
||||||
assert(qatomic_read(&has_writer));
|
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) {
|
WITH_QEMU_LOCK_GUARD(&aio_context_list_lock) {
|
||||||
/*
|
/*
|
||||||
* No need for memory barriers, this works in pair with
|
* 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.
|
* progress.
|
||||||
*/
|
*/
|
||||||
aio_bh_poll(qemu_get_aio_context());
|
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)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
sliced_iov = qemu_iovec_slice(*qiov, *qiov_offset, *bytes,
|
||||||
* For prefetching in stream_populate(), no qiov is passed along, because
|
&sliced_head, &sliced_tail,
|
||||||
* only copy-on-read matters.
|
&sliced_niov);
|
||||||
*/
|
|
||||||
if (qiov && *qiov) {
|
|
||||||
sliced_iov = qemu_iovec_slice(*qiov, *qiov_offset, *bytes,
|
|
||||||
&sliced_head, &sliced_tail,
|
|
||||||
&sliced_niov);
|
|
||||||
|
|
||||||
/* Guaranteed by bdrv_check_request32() */
|
/* Guaranteed by bdrv_check_request32() */
|
||||||
assert(*bytes <= SIZE_MAX);
|
assert(*bytes <= SIZE_MAX);
|
||||||
ret = bdrv_create_padded_qiov(bs, pad, sliced_iov, sliced_niov,
|
ret = bdrv_create_padded_qiov(bs, pad, sliced_iov, sliced_niov,
|
||||||
sliced_head, *bytes);
|
sliced_head, *bytes);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_padding_finalize(pad);
|
bdrv_padding_finalize(pad);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
|
||||||
*qiov = &pad->local_qiov;
|
|
||||||
*qiov_offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*bytes += pad->head + pad->tail;
|
*bytes += pad->head + pad->tail;
|
||||||
*offset -= pad->head;
|
*offset -= pad->head;
|
||||||
|
*qiov = &pad->local_qiov;
|
||||||
|
*qiov_offset = 0;
|
||||||
if (padded) {
|
if (padded) {
|
||||||
*padded = true;
|
*padded = true;
|
||||||
}
|
}
|
||||||
@@ -2626,16 +2619,6 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero,
|
|||||||
ret |= (ret2 & BDRV_BLOCK_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:
|
out:
|
||||||
|
|||||||
@@ -479,9 +479,9 @@ static unsigned mirror_perform(MirrorBlockJob *s, int64_t offset,
|
|||||||
return bytes_handled;
|
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;
|
MirrorOp *pseudo_op;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
/* At least the first dirty chunk is mirrored in one iteration. */
|
/* 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));
|
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);
|
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);
|
bdrv_dirty_bitmap_lock(s->dirty_bitmap);
|
||||||
offset = bdrv_dirty_iter_next(s->dbi);
|
offset = bdrv_dirty_iter_next(s->dbi);
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
@@ -777,7 +773,7 @@ static int mirror_exit_common(Job *job)
|
|||||||
"would not lead to an abrupt change of visible data",
|
"would not lead to an abrupt change of visible data",
|
||||||
to_replace->node_name, target_bs->node_name);
|
to_replace->node_name, target_bs->node_name);
|
||||||
}
|
}
|
||||||
bdrv_graph_wrunlock(target_bs);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_drained_end(to_replace);
|
bdrv_drained_end(to_replace);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_report_err(local_err);
|
error_report_err(local_err);
|
||||||
@@ -802,7 +798,7 @@ static int mirror_exit_common(Job *job)
|
|||||||
block_job_remove_all_bdrv(bjob);
|
block_job_remove_all_bdrv(bjob);
|
||||||
bdrv_graph_wrlock(mirror_top_bs);
|
bdrv_graph_wrlock(mirror_top_bs);
|
||||||
bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort);
|
bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort);
|
||||||
bdrv_graph_wrunlock(mirror_top_bs);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
bdrv_drained_end(target_bs);
|
bdrv_drained_end(target_bs);
|
||||||
bdrv_unref(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);
|
mirror_wait_for_free_in_flight_slot(s);
|
||||||
continue;
|
continue;
|
||||||
} else if (cnt != 0) {
|
} else if (cnt != 0) {
|
||||||
|
bdrv_graph_co_rdlock();
|
||||||
mirror_iteration(s);
|
mirror_iteration(s);
|
||||||
|
bdrv_graph_co_rdunlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1922,7 +1920,7 @@ static BlockJob *mirror_start_job(
|
|||||||
BLK_PERM_CONSISTENT_READ,
|
BLK_PERM_CONSISTENT_READ,
|
||||||
errp);
|
errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1967,17 +1965,17 @@ static BlockJob *mirror_start_job(
|
|||||||
ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
||||||
iter_shared_perms, errp);
|
iter_shared_perms, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_freeze_backing_chain(mirror_top_bs, target, errp) < 0) {
|
if (bdrv_freeze_backing_chain(mirror_top_bs, target, errp) < 0) {
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
QTAILQ_INIT(&s->ops_in_flight);
|
QTAILQ_INIT(&s->ops_in_flight);
|
||||||
|
|
||||||
@@ -2008,7 +2006,7 @@ fail:
|
|||||||
bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing,
|
bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing,
|
||||||
&error_abort);
|
&error_abort);
|
||||||
bdrv_replace_node(mirror_top_bs, bs, &error_abort);
|
bdrv_replace_node(mirror_top_bs, bs, &error_abort);
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_drained_end(bs);
|
bdrv_drained_end(bs);
|
||||||
|
|
||||||
bdrv_unref(mirror_top_bs);
|
bdrv_unref(mirror_top_bs);
|
||||||
|
|||||||
@@ -1636,22 +1636,7 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open_data_file && (flags & BDRV_O_NO_IO)) {
|
if (open_data_file) {
|
||||||
/*
|
|
||||||
* 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) {
|
|
||||||
/* Open external data file */
|
/* Open external data file */
|
||||||
bdrv_graph_co_rdunlock();
|
bdrv_graph_co_rdunlock();
|
||||||
s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs,
|
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_rdunlock_main_loop();
|
||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_unref_child(bs, s->data_file);
|
bdrv_unref_child(bs, s->data_file);
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
s->data_file = NULL;
|
s->data_file = NULL;
|
||||||
bdrv_graph_rdlock_main_loop();
|
bdrv_graph_rdlock_main_loop();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1044,7 +1044,7 @@ close_exit:
|
|||||||
}
|
}
|
||||||
bdrv_unref_child(bs, s->children[i]);
|
bdrv_unref_child(bs, s->children[i]);
|
||||||
}
|
}
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
g_free(s->children);
|
g_free(s->children);
|
||||||
g_free(opened);
|
g_free(opened);
|
||||||
exit:
|
exit:
|
||||||
@@ -1061,7 +1061,7 @@ static void quorum_close(BlockDriverState *bs)
|
|||||||
for (i = 0; i < s->num_children; i++) {
|
for (i = 0; i < s->num_children; i++) {
|
||||||
bdrv_unref_child(bs, s->children[i]);
|
bdrv_unref_child(bs, s->children[i]);
|
||||||
}
|
}
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
g_free(s->children);
|
g_free(s->children);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -568,7 +568,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
|||||||
&local_err);
|
&local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -579,7 +579,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
|||||||
BDRV_CHILD_DATA, &local_err);
|
BDRV_CHILD_DATA, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -592,7 +592,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
|||||||
if (!top_bs || !bdrv_is_root_node(top_bs) ||
|
if (!top_bs || !bdrv_is_root_node(top_bs) ||
|
||||||
!check_top_bs(top_bs, bs)) {
|
!check_top_bs(top_bs, bs)) {
|
||||||
error_setg(errp, "No top_bs or it is invalid");
|
error_setg(errp, "No top_bs or it is invalid");
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
reopen_backing_file(bs, false, NULL);
|
reopen_backing_file(bs, false, NULL);
|
||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
return;
|
return;
|
||||||
@@ -600,7 +600,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
|||||||
bdrv_op_block_all(top_bs, s->blocker);
|
bdrv_op_block_all(top_bs, s->blocker);
|
||||||
bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, 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(
|
s->backup_job = backup_job_create(
|
||||||
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
|
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;
|
s->secondary_disk = NULL;
|
||||||
bdrv_unref_child(bs, s->hidden_disk);
|
bdrv_unref_child(bs, s->hidden_disk);
|
||||||
s->hidden_disk = NULL;
|
s->hidden_disk = NULL;
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
s->error = 0;
|
s->error = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -196,10 +196,8 @@ bdrv_snapshot_fallback(BlockDriverState *bs)
|
|||||||
int bdrv_can_snapshot(BlockDriverState *bs)
|
int bdrv_can_snapshot(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
|
if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
|
||||||
if (!drv || !bdrv_is_inserted(bs) || !bdrv_is_writable(bs)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +292,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
|
|||||||
/* .bdrv_open() will re-attach it */
|
/* .bdrv_open() will re-attach it */
|
||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_unref_child(bs, fallback);
|
bdrv_unref_child(bs, fallback);
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
|
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
|
||||||
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
|
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) {
|
while (iterbdrvs) {
|
||||||
BlockDriverState *bs = iterbdrvs->data;
|
BlockDriverState *bs = iterbdrvs->data;
|
||||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||||
|
int ret = 0;
|
||||||
bool all_snapshots_includes_bs;
|
bool all_snapshots_includes_bs;
|
||||||
|
|
||||||
aio_context_acquire(ctx);
|
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);
|
all_snapshots_includes_bs = bdrv_all_snapshots_includes_bs(bs);
|
||||||
bdrv_graph_rdunlock_main_loop();
|
bdrv_graph_rdunlock_main_loop();
|
||||||
|
|
||||||
ret = (devices || all_snapshots_includes_bs) ?
|
if (devices || all_snapshots_includes_bs) {
|
||||||
bdrv_snapshot_goto(bs, name, errp) : 0;
|
ret = bdrv_snapshot_goto(bs, name, errp);
|
||||||
|
}
|
||||||
aio_context_release(ctx);
|
aio_context_release(ctx);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_graph_rdlock_main_loop();
|
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_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.
|
* 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);
|
bdrv_graph_wrlock(bs);
|
||||||
if (block_job_add_bdrv(&s->common, "active node", bs, 0,
|
if (block_job_add_bdrv(&s->common, "active node", bs, 0,
|
||||||
basic_flags | BLK_PERM_WRITE, errp)) {
|
basic_flags | BLK_PERM_WRITE, errp)) {
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
goto fail;
|
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,
|
ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0,
|
||||||
basic_flags, errp);
|
basic_flags, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
s->base_overlay = base_overlay;
|
s->base_overlay = base_overlay;
|
||||||
s->above_base = above_base;
|
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_unref_child(bs, e->file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
|
|
||||||
g_free(s->extents);
|
g_free(s->extents);
|
||||||
}
|
}
|
||||||
@@ -351,41 +351,29 @@ vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
|
|||||||
BDRVVmdkState *s = bs->opaque;
|
BDRVVmdkState *s = bs->opaque;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
size_t desc_buf_size;
|
desc = g_malloc0(DESC_SIZE);
|
||||||
|
tmp_desc = g_malloc0(DESC_SIZE);
|
||||||
if (s->desc_offset == 0) {
|
ret = bdrv_co_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 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);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc[desc_buf_size - 1] = '\0';
|
desc[DESC_SIZE - 1] = '\0';
|
||||||
tmp_str = strstr(desc, "parentCID");
|
tmp_str = strstr(desc, "parentCID");
|
||||||
if (tmp_str == NULL) {
|
if (tmp_str == NULL) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pstrcpy(tmp_desc, desc_buf_size, tmp_str);
|
pstrcpy(tmp_desc, DESC_SIZE, tmp_str);
|
||||||
p_name = strstr(desc, "CID");
|
p_name = strstr(desc, "CID");
|
||||||
if (p_name != NULL) {
|
if (p_name != NULL) {
|
||||||
p_name += sizeof("CID");
|
p_name += sizeof("CID");
|
||||||
snprintf(p_name, desc_buf_size - (p_name - desc), "%" PRIx32 "\n", cid);
|
snprintf(p_name, DESC_SIZE - (p_name - desc), "%" PRIx32 "\n", cid);
|
||||||
pstrcat(desc, desc_buf_size, tmp_desc);
|
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:
|
out:
|
||||||
g_free(desc);
|
g_free(desc);
|
||||||
@@ -1249,7 +1237,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
|||||||
bdrv_graph_rdunlock_main_loop();
|
bdrv_graph_rdunlock_main_loop();
|
||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_unref_child(bs, extent_file);
|
bdrv_unref_child(bs, extent_file);
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_graph_rdlock_main_loop();
|
bdrv_graph_rdlock_main_loop();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1268,7 +1256,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
|||||||
bdrv_graph_rdunlock_main_loop();
|
bdrv_graph_rdunlock_main_loop();
|
||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_unref_child(bs, extent_file);
|
bdrv_unref_child(bs, extent_file);
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_graph_rdlock_main_loop();
|
bdrv_graph_rdlock_main_loop();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1279,7 +1267,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
|||||||
bdrv_graph_rdunlock_main_loop();
|
bdrv_graph_rdunlock_main_loop();
|
||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_unref_child(bs, extent_file);
|
bdrv_unref_child(bs, extent_file);
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_graph_rdlock_main_loop();
|
bdrv_graph_rdlock_main_loop();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1289,7 +1277,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
|||||||
bdrv_graph_rdunlock_main_loop();
|
bdrv_graph_rdunlock_main_loop();
|
||||||
bdrv_graph_wrlock(NULL);
|
bdrv_graph_wrlock(NULL);
|
||||||
bdrv_unref_child(bs, extent_file);
|
bdrv_unref_child(bs, extent_file);
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
bdrv_graph_rdlock_main_loop();
|
bdrv_graph_rdlock_main_loop();
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
@@ -1613,7 +1613,7 @@ static void external_snapshot_abort(void *opaque)
|
|||||||
bdrv_drained_begin(state->new_bs);
|
bdrv_drained_begin(state->new_bs);
|
||||||
bdrv_graph_wrlock(state->old_bs);
|
bdrv_graph_wrlock(state->old_bs);
|
||||||
bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
|
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_drained_end(state->new_bs);
|
||||||
|
|
||||||
bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_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_co_lock(bs);
|
||||||
bdrv_drained_end(bs);
|
bdrv_drained_end(bs);
|
||||||
bdrv_co_unlock(bs);
|
|
||||||
|
|
||||||
blk_co_unref(blk);
|
blk_co_unref(blk);
|
||||||
|
bdrv_co_unlock(bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_block_stream(const char *job_id, const char *device,
|
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:
|
out:
|
||||||
bdrv_graph_wrunlock(NULL);
|
bdrv_graph_wrunlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockJobInfoList *qmp_query_block_jobs(Error **errp)
|
BlockJobInfoList *qmp_query_block_jobs(Error **errp)
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ void block_job_remove_all_bdrv(BlockJob *job)
|
|||||||
|
|
||||||
g_slist_free_1(l);
|
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)
|
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),
|
job = job_create(job_id, &driver->job_driver, txn, bdrv_get_aio_context(bs),
|
||||||
flags, cb, opaque, errp);
|
flags, cb, opaque, errp);
|
||||||
if (job == NULL) {
|
if (job == NULL) {
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,11 +563,11 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
return job;
|
return job;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
bdrv_graph_wrunlock(bs);
|
bdrv_graph_wrunlock();
|
||||||
job_early_fail(&job->job);
|
job_early_fail(&job->job);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ static inline abi_long do_obreak(abi_ulong brk_val)
|
|||||||
return target_brk;
|
return target_brk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release heap if necessary */
|
/* Release heap if necesary */
|
||||||
if (new_brk < old_brk) {
|
if (new_brk < old_brk) {
|
||||||
target_munmap(new_brk, old_brk - new_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);
|
qarg0 = argp = g_new0(char *, argc + 9);
|
||||||
/* save the first argument for the emulator */
|
/* save the first agrument for the emulator */
|
||||||
*argp++ = (char *)getprogname();
|
*argp++ = (char *)getprogname();
|
||||||
qargp = argp;
|
qargp = argp;
|
||||||
*argp++ = (char *)getprogname();
|
*argp++ = (char *)getprogname();
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2,
|
|||||||
return ret;
|
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)
|
static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2)
|
||||||
{
|
{
|
||||||
abi_long ret;
|
abi_long ret;
|
||||||
@@ -162,7 +162,7 @@ static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2)
|
|||||||
return ret;
|
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)
|
static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2)
|
||||||
{
|
{
|
||||||
abi_long ret;
|
abi_long ret;
|
||||||
@@ -175,7 +175,7 @@ static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2)
|
|||||||
return ret;
|
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)
|
static abi_long do_freebsd11_nlstat(abi_long arg1, abi_long arg2)
|
||||||
{
|
{
|
||||||
abi_long ret;
|
abi_long ret;
|
||||||
|
|||||||
@@ -41,7 +41,6 @@
|
|||||||
/* init terminal so that we can grab keys */
|
/* init terminal so that we can grab keys */
|
||||||
static struct termios oldtty;
|
static struct termios oldtty;
|
||||||
static int old_fd0_flags;
|
static int old_fd0_flags;
|
||||||
static int old_fd1_flags;
|
|
||||||
static bool stdio_in_use;
|
static bool stdio_in_use;
|
||||||
static bool stdio_allow_signal;
|
static bool stdio_allow_signal;
|
||||||
static bool stdio_echo_state;
|
static bool stdio_echo_state;
|
||||||
@@ -51,8 +50,6 @@ static void term_exit(void)
|
|||||||
if (stdio_in_use) {
|
if (stdio_in_use) {
|
||||||
tcsetattr(0, TCSANOW, &oldtty);
|
tcsetattr(0, TCSANOW, &oldtty);
|
||||||
fcntl(0, F_SETFL, old_fd0_flags);
|
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;
|
stdio_in_use = true;
|
||||||
old_fd0_flags = fcntl(0, F_GETFL);
|
old_fd0_flags = fcntl(0, F_GETFL);
|
||||||
old_fd1_flags = fcntl(1, F_GETFL);
|
|
||||||
tcgetattr(0, &oldtty);
|
tcgetattr(0, &oldtty);
|
||||||
if (!g_unix_set_fd_nonblocking(0, true, NULL)) {
|
if (!g_unix_set_fd_nonblocking(0, true, NULL)) {
|
||||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
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)) {
|
if (object_class_is_abstract(oc)) {
|
||||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
|
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
|
||||||
"a non-abstract device type");
|
"an abstract device type");
|
||||||
return NULL;
|
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
|
# This file is auto-generated by configure to support in-source tree
|
||||||
# 'make' command invocation
|
# 'make' command invocation
|
||||||
|
|
||||||
build:
|
ifeq ($(MAKECMDGOALS),)
|
||||||
|
recurse: all
|
||||||
|
endif
|
||||||
|
|
||||||
|
.NOTPARALLEL: %
|
||||||
|
%: force
|
||||||
@echo 'changing dir to build for $(MAKE) "$(MAKECMDGOALS)"...'
|
@echo 'changing dir to build for $(MAKE) "$(MAKECMDGOALS)"...'
|
||||||
@$(MAKE) -C build -f Makefile $(MAKECMDGOALS)
|
@$(MAKE) -C build -f Makefile $(MAKECMDGOALS)
|
||||||
@if test "$(MAKECMDGOALS)" = "distclean" && \
|
@if test "$(MAKECMDGOALS)" = "distclean" && \
|
||||||
@@ -49,9 +54,8 @@ build:
|
|||||||
then \
|
then \
|
||||||
rm -rf build GNUmakefile ; \
|
rm -rf build GNUmakefile ; \
|
||||||
fi
|
fi
|
||||||
%: build
|
force: ;
|
||||||
@
|
.PHONY: force
|
||||||
.PHONY: build
|
|
||||||
GNUmakefile: ;
|
GNUmakefile: ;
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
@@ -411,9 +415,7 @@ else
|
|||||||
# Using uname is really broken, but it is just a fallback for architectures
|
# Using uname is really broken, but it is just a fallback for architectures
|
||||||
# that are going to use TCI anyway
|
# that are going to use TCI anyway
|
||||||
cpu=$(uname -m)
|
cpu=$(uname -m)
|
||||||
if test "$host_os" != "bogus"; then
|
echo "WARNING: unrecognized host CPU, proceeding with 'uname -m' output '$cpu'"
|
||||||
echo "WARNING: unrecognized host CPU, proceeding with 'uname -m' output '$cpu'"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Normalise host CPU name to the values used by Meson cross files and in source
|
# 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"
|
--*) meson_option_parse "$opt" "$optarg"
|
||||||
;;
|
;;
|
||||||
# Pass through -Dxxxx options to meson
|
# Pass through -Dxxxx options to meson
|
||||||
-D*) meson_option_add "$opt"
|
-D*) meson_options="$meson_options $opt"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@@ -895,13 +897,6 @@ EOF
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
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
|
# Remove old dependency files to make sure that they get properly regenerated
|
||||||
rm -f ./*/config-devices.mak.d
|
rm -f ./*/config-devices.mak.d
|
||||||
|
|
||||||
@@ -973,14 +968,14 @@ meson="$(cd pyvenv/bin; pwd)/meson"
|
|||||||
|
|
||||||
# Conditionally ensure Sphinx is installed.
|
# Conditionally ensure Sphinx is installed.
|
||||||
|
|
||||||
mkvenv_online_flag=""
|
mkvenv_flags=""
|
||||||
if test "$download" = "enabled" ; then
|
if test "$download" = "enabled" -a "$docs" = "enabled" ; then
|
||||||
mkvenv_online_flag=" --online"
|
mkvenv_flags="--online"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$docs" != "disabled" ; then
|
if test "$docs" != "disabled" ; then
|
||||||
if ! $mkvenv ensuregroup \
|
if ! $mkvenv ensuregroup \
|
||||||
$(test "$docs" = "enabled" && echo "$mkvenv_online_flag") \
|
$mkvenv_flags \
|
||||||
${source_path}/pythondeps.toml docs;
|
${source_path}/pythondeps.toml docs;
|
||||||
then
|
then
|
||||||
if test "$docs" = "enabled" ; then
|
if test "$docs" = "enabled" ; then
|
||||||
@@ -1312,8 +1307,8 @@ probe_target_compiler() {
|
|||||||
container_cross_cc=${container_cross_prefix}gcc
|
container_cross_cc=${container_cross_prefix}gcc
|
||||||
;;
|
;;
|
||||||
i386)
|
i386)
|
||||||
container_image=debian-i686-cross
|
container_image=fedora-i386-cross
|
||||||
container_cross_prefix=i686-linux-gnu-
|
container_cross_prefix=
|
||||||
;;
|
;;
|
||||||
loongarch64)
|
loongarch64)
|
||||||
container_image=debian-loongarch-cross
|
container_image=debian-loongarch-cross
|
||||||
@@ -1396,19 +1391,16 @@ probe_target_compiler() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
try=cross
|
try=cross
|
||||||
# For softmmu/roms also look for a bi-endian or multilib-enabled host compiler
|
case "$target_arch:$cpu" in
|
||||||
if [ "${1%softmmu}" != "$1" ] || test "$target_arch" = "$cpu"; then
|
aarch64_be:aarch64 | \
|
||||||
case "$target_arch:$cpu" in
|
armeb:arm | \
|
||||||
aarch64_be:aarch64 | \
|
i386:x86_64 | \
|
||||||
armeb:arm | \
|
mips*:mips64 | \
|
||||||
i386:x86_64 | \
|
ppc*:ppc64 | \
|
||||||
mips*:mips64 | \
|
sparc:sparc64 | \
|
||||||
ppc*:ppc64 | \
|
"$cpu:$cpu")
|
||||||
sparc:sparc64 | \
|
try='native cross' ;;
|
||||||
"$cpu:$cpu")
|
esac
|
||||||
try='native cross' ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
eval "target_cflags=\${cross_cc_cflags_$target_arch}"
|
eval "target_cflags=\${cross_cc_cflags_$target_arch}"
|
||||||
for thistry in $try; do
|
for thistry in $try; do
|
||||||
case $thistry in
|
case $thistry in
|
||||||
@@ -1639,7 +1631,6 @@ if test "$container" != no; then
|
|||||||
fi
|
fi
|
||||||
echo "SUBDIRS=$subdirs" >> $config_host_mak
|
echo "SUBDIRS=$subdirs" >> $config_host_mak
|
||||||
echo "PYTHON=$python" >> $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 "GENISOIMAGE=$genisoimage" >> $config_host_mak
|
||||||
echo "MESON=$meson" >> $config_host_mak
|
echo "MESON=$meson" >> $config_host_mak
|
||||||
echo "NINJA=$ninja" >> $config_host_mak
|
echo "NINJA=$ninja" >> $config_host_mak
|
||||||
@@ -1684,9 +1675,6 @@ fi
|
|||||||
mkdir -p tests/tcg
|
mkdir -p tests/tcg
|
||||||
echo "# Automatically generated by configure - do not modify" > $config_host_mak
|
echo "# Automatically generated by configure - do not modify" > $config_host_mak
|
||||||
echo "SRC_PATH=$source_path" >> $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=
|
tcg_tests_targets=
|
||||||
for target in $target_list; do
|
for target in $target_list; do
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ all: $(SONAMES)
|
|||||||
$(CC) $(CFLAGS) $(PLUGIN_CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) $(PLUGIN_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
ifeq ($(CONFIG_WIN32),y)
|
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)
|
$(CC) -shared -o $@ $^ $(LDLIBS)
|
||||||
else ifeq ($(CONFIG_DARWIN),y)
|
else ifeq ($(CONFIG_DARWIN),y)
|
||||||
lib%$(SO_SUFFIX): %.o
|
lib%$(SO_SUFFIX): %.o
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ virgl_get_resource_info_modifiers(uint32_t resource_id,
|
|||||||
#ifdef VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION
|
#ifdef VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION
|
||||||
struct virgl_renderer_resource_info_ext info_ext;
|
struct virgl_renderer_resource_info_ext info_ext;
|
||||||
ret = virgl_renderer_resource_get_info_ext(resource_id, &info_ext);
|
ret = virgl_renderer_resource_get_info_ext(resource_id, &info_ext);
|
||||||
if (ret) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +335,7 @@ virgl_get_resource_info_modifiers(uint32_t resource_id,
|
|||||||
*modifiers = info_ext.modifiers;
|
*modifiers = info_ext.modifiers;
|
||||||
#else
|
#else
|
||||||
ret = virgl_renderer_resource_get_info(resource_id, info);
|
ret = virgl_renderer_resource_get_info(resource_id, info);
|
||||||
if (ret) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ virgl_cmd_set_scanout(VuGpu *g,
|
|||||||
uint64_t modifiers = 0;
|
uint64_t modifiers = 0;
|
||||||
ret = virgl_get_resource_info_modifiers(ss.resource_id, &info,
|
ret = virgl_get_resource_info_modifiers(ss.resource_id, &info,
|
||||||
&modifiers);
|
&modifiers);
|
||||||
if (ret) {
|
if (ret == -1) {
|
||||||
g_critical("%s: illegal resource specified %d\n",
|
g_critical("%s: illegal resource specified %d\n",
|
||||||
__func__, ss.resource_id);
|
__func__, ss.resource_id);
|
||||||
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_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) {
|
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.
|
* modifiers which is appended after VhostUserGpuDMABUFScanout.
|
||||||
*/
|
*/
|
||||||
msg.request = VHOST_USER_GPU_DMABUF_SCANOUT2;
|
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). */
|
unsigned (== 0). */
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
format_dec (long number, char *outbuffer, size_t outsize, int signedp)
|
format_dec (long number, char *outbuffer, int signedp)
|
||||||
{
|
{
|
||||||
last_immediate = number;
|
last_immediate = number;
|
||||||
snprintf (outbuffer, outsize, signedp ? "%ld" : "%lu", number);
|
sprintf (outbuffer, signedp ? "%ld" : "%lu", number);
|
||||||
|
|
||||||
return outbuffer + strlen (outbuffer);
|
return outbuffer + strlen (outbuffer);
|
||||||
}
|
}
|
||||||
@@ -1876,12 +1876,6 @@ print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp)
|
|||||||
return 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
|
/* 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
|
fields. The prefix_opcodep and the rest hold a prefix insn that is
|
||||||
supposed to be output as an address mode. */
|
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))
|
if ((*cs == 'z' && (insn & 0x20))
|
||||||
|| (opcodep->match == BDAP_QUICK_OPCODE
|
|| (opcodep->match == BDAP_QUICK_OPCODE
|
||||||
&& (nbytes <= 2 || buffer[1 + nbytes] == 0)))
|
&& (nbytes <= 2 || buffer[1 + nbytes] == 0)))
|
||||||
tp = FORMAT_DEC (number, tp, signedp);
|
tp = format_dec (number, tp, signedp);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int highbyte = (number >> 24) & 0xff;
|
unsigned int highbyte = (number >> 24) & 0xff;
|
||||||
@@ -2247,7 +2241,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
|||||||
with_reg_prefix);
|
with_reg_prefix);
|
||||||
if (number >= 0)
|
if (number >= 0)
|
||||||
*tp++ = '+';
|
*tp++ = '+';
|
||||||
tp = FORMAT_DEC (number, tp, 1);
|
tp = format_dec (number, tp, 1);
|
||||||
|
|
||||||
info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
|
info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
|
||||||
info->target = (prefix_insn >> 12) & 15;
|
info->target = (prefix_insn >> 12) & 15;
|
||||||
@@ -2346,7 +2340,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
|||||||
{
|
{
|
||||||
if (number >= 0)
|
if (number >= 0)
|
||||||
*tp++ = '+';
|
*tp++ = '+';
|
||||||
tp = FORMAT_DEC (number, tp, 1);
|
tp = format_dec (number, tp, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2403,7 +2397,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
tp = FORMAT_DEC (insn & 63, tp, 0);
|
tp = format_dec (insn & 63, tp, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
@@ -2432,11 +2426,11 @@ print_with_operands (const struct cris_opcode *opcodep,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
tp = FORMAT_DEC (insn & 31, tp, 0);
|
tp = format_dec (insn & 31, tp, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'C':
|
case 'C':
|
||||||
tp = FORMAT_DEC (insn & 15, tp, 0);
|
tp = format_dec (insn & 15, tp, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
@@ -2469,7 +2463,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
|||||||
if (number > 127)
|
if (number > 127)
|
||||||
number = number - 256;
|
number = number - 256;
|
||||||
|
|
||||||
tp = FORMAT_DEC (number, tp, 1);
|
tp = format_dec (number, tp, 1);
|
||||||
*tp++ = ',';
|
*tp++ = ',';
|
||||||
tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
|
tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
|
||||||
}
|
}
|
||||||
@@ -2480,7 +2474,7 @@ print_with_operands (const struct cris_opcode *opcodep,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
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;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
|
|||||||
@@ -1968,10 +1968,6 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info)
|
|||||||
|
|
||||||
insn = bfd_getb32 (buffer);
|
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)
|
for (i = 0; i < NUMOPCODES; ++i)
|
||||||
{
|
{
|
||||||
const struct pa_opcode *opcode = &pa_opcodes[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);
|
return sizeof (insn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info->fprintf_func(info->stream, "<unknown>");
|
(*info->fprintf_func) (info->stream, "#%8x", insn);
|
||||||
return sizeof (insn);
|
return sizeof (insn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2184,22 +2184,7 @@ static const char *csr_name(int csrno)
|
|||||||
case 0x0383: return "mibound";
|
case 0x0383: return "mibound";
|
||||||
case 0x0384: return "mdbase";
|
case 0x0384: return "mdbase";
|
||||||
case 0x0385: return "mdbound";
|
case 0x0385: return "mdbound";
|
||||||
case 0x03a0: return "pmpcfg0";
|
case 0x03a0: return "pmpcfg3";
|
||||||
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 0x03b0: return "pmpaddr0";
|
case 0x03b0: return "pmpaddr0";
|
||||||
case 0x03b1: return "pmpaddr1";
|
case 0x03b1: return "pmpaddr1";
|
||||||
case 0x03b2: return "pmpaddr2";
|
case 0x03b2: return "pmpaddr2";
|
||||||
@@ -2216,54 +2201,6 @@ static const char *csr_name(int csrno)
|
|||||||
case 0x03bd: return "pmpaddr13";
|
case 0x03bd: return "pmpaddr13";
|
||||||
case 0x03be: return "pmpaddr14";
|
case 0x03be: return "pmpaddr14";
|
||||||
case 0x03bf: return "pmpaddr15";
|
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 0x0780: return "mtohost";
|
||||||
case 0x0781: return "mfromhost";
|
case 0x0781: return "mfromhost";
|
||||||
case 0x0782: return "mreset";
|
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.
|
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
|
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
|
various pitfalls with regards to live migration. Use a newer machine type
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
Nios II ``10m50-ghrd`` and ``nios2-generic-nommu`` machines (since 8.2)
|
|
||||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
|
||||||
|
|
||||||
The Nios II architecture is orphan.
|
|
||||||
|
|
||||||
|
|
||||||
Backend options
|
Backend options
|
||||||
---------------
|
---------------
|
||||||
@@ -529,5 +514,5 @@ old compression method (since 8.2)
|
|||||||
|
|
||||||
Compression method fails too much. Too many races. We are going to
|
Compression method fails too much. Too many races. We are going to
|
||||||
remove it if nobody fixes it. For starters, migration-test
|
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.
|
compression, use multifd compression methods.
|
||||||
|
|||||||
@@ -129,9 +129,8 @@ causing most hypervisors to trap and fault on them.
|
|||||||
.. warning::
|
.. warning::
|
||||||
Semihosting inherently bypasses any isolation there may be between
|
Semihosting inherently bypasses any isolation there may be between
|
||||||
the guest and the host. As a result a program using semihosting can
|
the guest and the host. As a result a program using semihosting can
|
||||||
happily trash your host system. Some semihosting calls (e.g.
|
happily trash your host system. You should only ever run trusted
|
||||||
``SYS_READC``) can block execution indefinitely. You should only
|
code with semihosting enabled.
|
||||||
ever run trusted code with semihosting enabled.
|
|
||||||
|
|
||||||
Redirection
|
Redirection
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|||||||
10
docs/conf.py
10
docs/conf.py
@@ -29,6 +29,7 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import sphinx
|
import sphinx
|
||||||
|
from distutils.version import LooseVersion
|
||||||
from sphinx.errors import ConfigError
|
from sphinx.errors import ConfigError
|
||||||
|
|
||||||
# The per-manual conf.py will set qemu_docdir for a single-manual build;
|
# 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
|
# 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
|
# further. For a list of options available for each theme, see the
|
||||||
# documentation.
|
# documentation.
|
||||||
html_theme_options = {
|
if LooseVersion(sphinx_rtd_theme.__version__) >= LooseVersion("0.4.3"):
|
||||||
"style_nav_header_background": "#802400",
|
html_theme_options = {
|
||||||
"navigation_with_keys": True,
|
"style_nav_header_background": "#802400",
|
||||||
}
|
"navigation_with_keys": True,
|
||||||
|
}
|
||||||
|
|
||||||
html_logo = os.path.join(qemu_docdir, "../ui/icons/qemu_128x128.png")
|
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.
|
indicated by $TMPC.
|
||||||
|
|
||||||
|
|
||||||
Python virtual environments and the build process
|
Python virtual environments and the QEMU build system
|
||||||
-------------------------------------------------
|
-----------------------------------------------------
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
Stage 2: Meson
|
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
|
script, which may point to something other than the first python3
|
||||||
binary on the path.
|
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
|
Stage 3: Make
|
||||||
=============
|
=============
|
||||||
@@ -511,11 +434,6 @@ number of dynamically created files listed later.
|
|||||||
executables. Build rules for various subdirectories are included in
|
executables. Build rules for various subdirectories are included in
|
||||||
other meson.build files spread throughout the QEMU source tree.
|
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``
|
``tests/Makefile.include``
|
||||||
Rules for external test harnesses. These include the TCG tests
|
Rules for external test harnesses. These include the TCG tests
|
||||||
and the Avocado-based integration 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``
|
some reason don't have a bus concept) make use of the ``instance id``
|
||||||
for otherwise identically named devices.
|
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
|
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
|
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.
|
pc-5.2 machine type. So nothing to worry here.
|
||||||
|
|
||||||
Now it comes the interesting ones, when both QEMU processes are
|
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,
|
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
|
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
|
$ 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
|
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
|
configuration is correct. QEMU doesn't know how to look at this kind
|
||||||
of features in general.
|
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.
|
used in this example because it makes the example simpler.
|
||||||
|
|
||||||
Other devices have worse control about individual features. If they
|
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 \
|
-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=19,entitlement=high \
|
||||||
-device z14-s390x-cpu,core-id=11,entitlement=low \
|
-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
|
Additions to query-cpus-fast
|
||||||
@@ -78,7 +78,7 @@ modifiers for all configured vCPUs.
|
|||||||
"dedicated": true,
|
"dedicated": true,
|
||||||
"thread-id": 537005,
|
"thread-id": 537005,
|
||||||
"props": {
|
"props": {
|
||||||
"core-id": 12,
|
"core-id": 112,
|
||||||
"socket-id": 0,
|
"socket-id": 0,
|
||||||
"drawer-id": 3,
|
"drawer-id": 3,
|
||||||
"book-id": 2
|
"book-id": 2
|
||||||
@@ -86,7 +86,7 @@ modifiers for all configured vCPUs.
|
|||||||
"cpu-state": "operating",
|
"cpu-state": "operating",
|
||||||
"entitlement": "high",
|
"entitlement": "high",
|
||||||
"qom-path": "/machine/peripheral-anon/device[2]",
|
"qom-path": "/machine/peripheral-anon/device[2]",
|
||||||
"cpu-index": 12,
|
"cpu-index": 112,
|
||||||
"target": "s390x"
|
"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
|
- re-compile a single [1]_ instruction block for the current PC
|
||||||
- exit the cpu loop and execute the re-compiled block
|
- 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
|
.. [1] sometimes two instructions if dealing with delay slots
|
||||||
|
|
||||||
Other I/O operations
|
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
|
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.
|
at compile time for test or debug.
|
||||||
Add flags to configure to enable:
|
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":
|
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()
|
self.vm.launch()
|
||||||
res = self.vm.cmd('human-monitor-command',
|
res = self.vm.cmd('human-monitor-command',
|
||||||
command_line='info version')
|
command_line='info version')
|
||||||
self.assertRegex(res, r'^(\d+\.\d+\.\d)')
|
self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
|
||||||
|
|
||||||
To execute your test, run:
|
To execute your test, run:
|
||||||
|
|
||||||
@@ -1077,7 +1077,7 @@ and hypothetical example follows:
|
|||||||
'human-monitor-command',
|
'human-monitor-command',
|
||||||
command_line='info version')
|
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
|
At test "tear down", ``avocado_qemu.Test`` handles all the QEMUMachines
|
||||||
shutdown.
|
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
|
compiled with debug flags. Therefore, the ``AVOCADO_TIMEOUT_EXPECTED`` variable
|
||||||
has been used to determine whether those tests should run or not.
|
has been used to determine whether those tests should run or not.
|
||||||
|
|
||||||
QEMU_TEST_FLAKY_TESTS
|
GITLAB_CI
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^
|
||||||
Some tests are not working reliably and thus are disabled by default.
|
A number of tests are flagged to not run on the GitLab CI. Usually because
|
||||||
This includes tests that don't run reliably on GitLab's CI which
|
they proved to the flaky or there are constraints on the CI environment which
|
||||||
usually expose real issues that are rarely seen on developer machines
|
would make them fail. If you encounter a similar situation then use that
|
||||||
due to the constraints of the CI environment. If you encounter a
|
variable as shown on the code snippet below to skip the test:
|
||||||
similar situation then raise a bug and then mark the test as shown on
|
|
||||||
the code snippet below:
|
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
# See https://gitlab.com/qemu-project/qemu/-/issues/nnnn
|
@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
|
||||||
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
|
|
||||||
def test(self):
|
def test(self):
|
||||||
do_something()
|
do_something()
|
||||||
|
|
||||||
You can also add ``:avocado: tags=flaky`` to the test meta-data so
|
QEMU_TEST_FLAKY_TESTS
|
||||||
only the flaky tests can be run as a group:
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
Some tests are not working reliably and thus are disabled by default.
|
||||||
.. code::
|
Set this environment variable to enable them.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Uninstalling Avocado
|
Uninstalling Avocado
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|||||||
@@ -148,9 +148,9 @@ Vring descriptor indices for packed virtqueues
|
|||||||
A vring address description
|
A vring address description
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
+-------+-------+------------+------+-----------+-----+
|
+-------+-------+------+------------+------+-----------+-----+
|
||||||
| index | flags | descriptor | used | available | log |
|
| index | flags | size | descriptor | used | available | log |
|
||||||
+-------+-------+------------+------+-----------+-----+
|
+-------+-------+------+------------+------+-----------+-----+
|
||||||
|
|
||||||
:index: a 32-bit vring index
|
: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
|
QEMU TPM Device
|
||||||
===============
|
===============
|
||||||
|
|||||||
@@ -229,15 +229,15 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
|||||||
section += dlnode
|
section += dlnode
|
||||||
return [section]
|
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"""
|
"""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
|
assert not doc.args
|
||||||
section = self._make_section('Arguments')
|
section = self._make_section('Arguments')
|
||||||
dlnode = nodes.definition_list()
|
dlnode = nodes.definition_list()
|
||||||
dlnode += self._make_dlitem(
|
dlnode += self._make_dlitem(
|
||||||
[nodes.Text('The members of '),
|
[nodes.Text('The members of '),
|
||||||
nodes.literal('', arg_type.name)],
|
nodes.literal('', boxed_arg_type.name)],
|
||||||
None)
|
None)
|
||||||
section += dlnode
|
section += dlnode
|
||||||
return [section]
|
return [section]
|
||||||
@@ -341,7 +341,8 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
|||||||
allow_preconfig, coroutine):
|
allow_preconfig, coroutine):
|
||||||
doc = self._cur_doc
|
doc = self._cur_doc
|
||||||
self._add_doc('Command',
|
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_features(doc)
|
||||||
+ self._nodes_for_sections(doc)
|
+ self._nodes_for_sections(doc)
|
||||||
+ self._nodes_for_if_section(ifcond))
|
+ self._nodes_for_if_section(ifcond))
|
||||||
@@ -349,7 +350,8 @@ class QAPISchemaGenRSTVisitor(QAPISchemaVisitor):
|
|||||||
def visit_event(self, name, info, ifcond, features, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, features, arg_type, boxed):
|
||||||
doc = self._cur_doc
|
doc = self._cur_doc
|
||||||
self._add_doc('Event',
|
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_features(doc)
|
||||||
+ self._nodes_for_sections(doc)
|
+ self._nodes_for_sections(doc)
|
||||||
+ self._nodes_for_if_section(ifcond))
|
+ self._nodes_for_if_section(ifcond))
|
||||||
@@ -513,7 +515,7 @@ class QAPIDocDirective(Directive):
|
|||||||
except QAPIError as err:
|
except QAPIError as err:
|
||||||
# Launder QAPI parse errors into Sphinx extension errors
|
# Launder QAPI parse errors into Sphinx extension errors
|
||||||
# so they are displayed nicely to the user
|
# so they are displayed nicely to the user
|
||||||
raise ExtensionError(str(err)) from err
|
raise ExtensionError(str(err))
|
||||||
|
|
||||||
def do_parse(self, rstlist, node):
|
def do_parse(self, rstlist, node):
|
||||||
"""Parse rST source lines and add them to the specified 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_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
|
||||||
- FEAT_PAN3 (Support for SCTLR_ELx.EPAN)
|
- FEAT_PAN3 (Support for SCTLR_ELx.EPAN)
|
||||||
- FEAT_PAuth (Pointer authentication)
|
- FEAT_PAuth (Pointer authentication)
|
||||||
- FEAT_PAuth2 (Enhancements to pointer authentication)
|
- FEAT_PAuth2 (Enhacements to pointer authentication)
|
||||||
- FEAT_PMULL (PMULL, PMULL2 instructions)
|
- FEAT_PMULL (PMULL, PMULL2 instructions)
|
||||||
- FEAT_PMUv3p1 (PMU Extensions v3.1)
|
- FEAT_PMUv3p1 (PMU Extensions v3.1)
|
||||||
- FEAT_PMUv3p4 (PMU Extensions v3.4)
|
- 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
|
When TPM is enabled, this machine also creates a tpm-tis-device at a user input
|
||||||
as an IOREQ server to register/connect with Xen Hypervisor. Control of
|
tpm base address, adds a TPM emulator and connects to a swtpm application
|
||||||
the VMs themselves is left to the Xen tooling.
|
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
|
More information about TPM use and installing swtpm linux application can be
|
||||||
user input tpm base address, adds a TPM emulator and connects to a
|
found at: docs/specs/tpm.rst.
|
||||||
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.
|
|
||||||
|
|
||||||
Example for starting swtpm on host machine:
|
Example for starting swtpm on host machine:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
mkdir /tmp/vtpm2
|
mkdir /tmp/vtpm2
|
||||||
swtpm socket --tpmstate dir=/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:
|
Sample QEMU xenpvh commands for running and connecting with Xen:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
qemu-system-aarch64 -xen-domid 1 \
|
qemu-system-aarch64 -xen-domid 1 \
|
||||||
-chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
|
-chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \
|
||||||
-mon chardev=libxl-cmd,mode=control \
|
-mon chardev=libxl-cmd,mode=control \
|
||||||
-chardev socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \
|
-chardev socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \
|
||||||
-mon chardev=libxenstat-cmd,mode=control \
|
-mon chardev=libxenstat-cmd,mode=control \
|
||||||
-xen-attach -name guest0 -vnc none -display none -nographic \
|
-xen-attach -name guest0 -vnc none -display none -nographic \
|
||||||
-machine xenpvh -m 1301 \
|
-machine xenpvh -m 1301 \
|
||||||
-chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
|
-chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \
|
||||||
-tpmdev emulator,id=tpm0,chardev=chrtpm -machine tpm-base-addr=0x0C000000
|
-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
|
In above QEMU command, last two lines are for connecting xenpvh QEMU to swtpm
|
||||||
via chardev socket.
|
via chardev socket.
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ As TCG cannot track all memory accesses in user-mode there is no
|
|||||||
support for watchpoints.
|
support for watchpoints.
|
||||||
|
|
||||||
Relocating code
|
Relocating code
|
||||||
===============
|
---------------
|
||||||
|
|
||||||
On modern kernels confusion can be caused by code being relocated by
|
On modern kernels confusion can be caused by code being relocated by
|
||||||
features such as address space layout randomisation. To avoid
|
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
|
view of where things are in memory or perhaps more trivially disable
|
||||||
ASLR when booting the system.
|
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
|
Debugging multicore machines
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
During the graphical emulation, you can use special key combinations from
|
During the graphical emulation, you can use special key combinations to
|
||||||
the following table to change modes. By default the modifier is Ctrl-Alt
|
change modes. The default key mappings are shown below, but if you use
|
||||||
(used in the table below) which can be changed with ``-display`` suboption
|
``-alt-grab`` then the modifier is Ctrl-Alt-Shift (instead of Ctrl-Alt)
|
||||||
``mod=`` where appropriate. For example, ``-display sdl,
|
and if you use ``-ctrl-grab`` then the modifier is the right Ctrl key
|
||||||
grab-mod=lshift-lctrl-lalt`` changes the modifier key to Ctrl-Alt-Shift,
|
(instead of Ctrl-Alt):
|
||||||
while ``-display sdl,grab-mod=rctrl`` changes it to the right Ctrl key.
|
|
||||||
|
|
||||||
Ctrl-Alt-f
|
Ctrl-Alt-f
|
||||||
Toggle full screen
|
Toggle full screen
|
||||||
@@ -29,7 +28,7 @@ Ctrl-Alt-n
|
|||||||
*3*
|
*3*
|
||||||
Serial port
|
Serial port
|
||||||
|
|
||||||
Ctrl-Alt-g
|
Ctrl-Alt
|
||||||
Toggle mouse and keyboard grab.
|
Toggle mouse and keyboard grab.
|
||||||
|
|
||||||
In the virtual consoles, you can use Ctrl-Up, Ctrl-Down, Ctrl-PageUp and
|
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)
|
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);
|
guest_phys_blocks_free(&s->guest_phys_blocks);
|
||||||
memory_mapping_list_free(&s->list);
|
memory_mapping_list_free(&s->list);
|
||||||
close(s->fd);
|
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
|
* 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,
|
* step or resume, and a pointer to the state structure of one of them,
|
||||||
* respectively
|
* respectivelly
|
||||||
*/
|
*/
|
||||||
int target_count = 0;
|
int target_count = 0;
|
||||||
CPUState *last_target = NULL;
|
CPUState *last_target = NULL;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ enum {
|
|||||||
GDB_SIGNAL_TRAP = 5,
|
GDB_SIGNAL_TRAP = 5,
|
||||||
GDB_SIGNAL_ABRT = 6,
|
GDB_SIGNAL_ABRT = 6,
|
||||||
GDB_SIGNAL_ALRM = 14,
|
GDB_SIGNAL_ALRM = 14,
|
||||||
GDB_SIGNAL_STOP = 17,
|
|
||||||
GDB_SIGNAL_IO = 23,
|
GDB_SIGNAL_IO = 23,
|
||||||
GDB_SIGNAL_XCPU = 24,
|
GDB_SIGNAL_XCPU = 24,
|
||||||
GDB_SIGNAL_UNKNOWN = 143
|
GDB_SIGNAL_UNKNOWN = 143
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
|
|||||||
break;
|
break;
|
||||||
case RUN_STATE_IO_ERROR:
|
case RUN_STATE_IO_ERROR:
|
||||||
trace_gdbstub_hit_io_error();
|
trace_gdbstub_hit_io_error();
|
||||||
ret = GDB_SIGNAL_STOP;
|
ret = GDB_SIGNAL_IO;
|
||||||
break;
|
break;
|
||||||
case RUN_STATE_WATCHDOG:
|
case RUN_STATE_WATCHDOG:
|
||||||
trace_gdbstub_hit_watchdog();
|
trace_gdbstub_hit_watchdog();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
|
|||||||
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
||||||
atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
|
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;
|
Int128Alias r, c, n;
|
||||||
|
|
||||||
c.s = cmp;
|
c.s = cmp;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ atomic16_read_rw(Int128 *ptr)
|
|||||||
static inline void ATTRIBUTE_ATOMIC128_OPT
|
static inline void ATTRIBUTE_ATOMIC128_OPT
|
||||||
atomic16_set(Int128 *ptr, Int128 val)
|
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;
|
__int128_t old;
|
||||||
Int128Alias new;
|
Int128Alias new;
|
||||||
|
|
||||||
|
|||||||
@@ -947,7 +947,6 @@ static const VMStateDescription erst_vmstate = {
|
|||||||
|
|
||||||
static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
|
static void erst_realizefn(PCIDevice *pci_dev, Error **errp)
|
||||||
{
|
{
|
||||||
ERRP_GUARD();
|
|
||||||
ERSTDeviceState *s = ACPIERST(pci_dev);
|
ERSTDeviceState *s = ACPIERST(pci_dev);
|
||||||
|
|
||||||
trace_acpi_erst_realizefn_in();
|
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 */
|
/* HostMemoryBackend size will be multiple of PAGE_SIZE */
|
||||||
s->storage_size = object_property_get_int(OBJECT(s->hostmem), "size", errp);
|
s->storage_size = object_property_get_int(OBJECT(s->hostmem), "size", errp);
|
||||||
if (*errp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize backend storage and record_count */
|
/* Initialize backend storage and record_count */
|
||||||
check_erst_backend_storage(s, errp);
|
check_erst_backend_storage(s, errp);
|
||||||
if (*errp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BAR 0: Programming registers */
|
/* BAR 0: Programming registers */
|
||||||
memory_region_init_io(&s->iomem_mr, OBJECT(pci_dev), &erst_reg_ops, s,
|
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),
|
memory_region_init_ram(&s->exchange_mr, OBJECT(pci_dev),
|
||||||
"erst.exchange",
|
"erst.exchange",
|
||||||
le32_to_cpu(s->header->record_size), errp);
|
le32_to_cpu(s->header->record_size), errp);
|
||||||
if (*errp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
|
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
|
||||||
&s->exchange_mr);
|
&s->exchange_mr);
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
|
|||||||
uint32_t *initiator_list)
|
uint32_t *initiator_list)
|
||||||
{
|
{
|
||||||
int i, index;
|
int i, index;
|
||||||
uint32_t initiator_to_index[MAX_NODES] = {};
|
|
||||||
HMAT_LB_Data *lb_data;
|
HMAT_LB_Data *lb_data;
|
||||||
uint16_t *entry_list;
|
uint16_t *entry_list;
|
||||||
uint32_t base;
|
uint32_t base;
|
||||||
@@ -122,8 +121,6 @@ static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
|
|||||||
/* Initiator Proximity Domain List */
|
/* Initiator Proximity Domain List */
|
||||||
for (i = 0; i < num_initiator; i++) {
|
for (i = 0; i < num_initiator; i++) {
|
||||||
build_append_int_noprefix(table_data, initiator_list[i], 4);
|
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 */
|
/* 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);
|
entry_list = g_new0(uint16_t, num_initiator * num_target);
|
||||||
for (i = 0; i < hmat_lb->list->len; i++) {
|
for (i = 0; i < hmat_lb->list->len; i++) {
|
||||||
lb_data = &g_array_index(hmat_lb->list, HMAT_LB_Data, i);
|
lb_data = &g_array_index(hmat_lb->list, HMAT_LB_Data, i);
|
||||||
index = initiator_to_index[lb_data->initiator] * num_target +
|
index = lb_data->initiator * num_target + lb_data->target;
|
||||||
lb_data->target;
|
|
||||||
|
|
||||||
entry_list[index] = (uint16_t)(lb_data->data / hmat_lb->base);
|
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));
|
epit_table[i].irq));
|
||||||
}
|
}
|
||||||
|
|
||||||
object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num,
|
object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num, &err);
|
||||||
&error_abort);
|
|
||||||
qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
|
qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
|
||||||
|
|
||||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->fec), errp)) {
|
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));
|
spi_table[i].irq));
|
||||||
}
|
}
|
||||||
|
|
||||||
object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num,
|
object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num, &err);
|
||||||
&error_abort);
|
|
||||||
qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]);
|
qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]);
|
||||||
if (!sysbus_realize(SYS_BUS_DEVICE(&s->eth), errp)) {
|
if (!sysbus_realize(SYS_BUS_DEVICE(&s->eth), errp)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ static void netduino2_init(MachineState *machine)
|
|||||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||||
|
|
||||||
dev = qdev_new(TYPE_STM32F205_SOC);
|
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);
|
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
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 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->desc = "Netduino 2 Machine (Cortex-M3)";
|
||||||
mc->init = netduino2_init;
|
mc->init = netduino2_init;
|
||||||
mc->valid_cpu_types = valid_cpu_types;
|
|
||||||
mc->ignore_memory_transaction_failures = true;
|
mc->ignore_memory_transaction_failures = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ static void netduinoplus2_init(MachineState *machine)
|
|||||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||||
|
|
||||||
dev = qdev_new(TYPE_STM32F405_SOC);
|
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);
|
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
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 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->desc = "Netduino Plus 2 Machine (Cortex-M4)";
|
||||||
mc->init = netduinoplus2_init;
|
mc->init = netduinoplus2_init;
|
||||||
mc->valid_cpu_types = valid_cpu_types;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_MACHINE("netduinoplus2", netduinoplus2_machine_init)
|
DEFINE_MACHINE("netduinoplus2", netduinoplus2_machine_init)
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include "hw/qdev-clock.h"
|
#include "hw/qdev-clock.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/bswap.h"
|
|
||||||
#include "qemu/units.h"
|
#include "qemu/units.h"
|
||||||
#include "sysemu/sysemu.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.
|
* The initial mask of disabled modules indicates the chip derivative (e.g.
|
||||||
* NPCM750 or NPCM730).
|
* 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,
|
npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
|
||||||
sizeof(value));
|
sizeof(value));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ static void olimex_stm32_h405_init(MachineState *machine)
|
|||||||
clock_set_hz(sysclk, SYSCLK_FRQ);
|
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||||
|
|
||||||
dev = qdev_new(TYPE_STM32F405_SOC);
|
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);
|
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
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 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->desc = "Olimex STM32-H405 (Cortex-M4)";
|
||||||
mc->init = olimex_stm32_h405_init;
|
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 */
|
/* SRAM pre-allocated as part of the SoC instantiation */
|
||||||
mc->default_ram_size = 0;
|
mc->default_ram_size = 0;
|
||||||
|
|||||||
@@ -675,8 +675,6 @@ static void smmu_base_reset_hold(Object *obj)
|
|||||||
{
|
{
|
||||||
SMMUState *s = ARM_SMMU(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->configs);
|
||||||
g_hash_table_remove_all(s->iotlb);
|
g_hash_table_remove_all(s->iotlb);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
|
|||||||
/* Init ARMv7m */
|
/* Init ARMv7m */
|
||||||
armv7m = DEVICE(&s->armv7m);
|
armv7m = DEVICE(&s->armv7m);
|
||||||
qdev_prop_set_uint32(armv7m, "num-irq", 61);
|
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_prop_set_bit(armv7m, "enable-bitband", true);
|
||||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||||
qdev_connect_clock_in(armv7m, "refclk", s->refclk);
|
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);
|
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)
|
static void stm32f100_soc_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->realize = stm32f100_soc_realize;
|
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 = {
|
static const TypeInfo stm32f100_soc_info = {
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
|||||||
|
|
||||||
armv7m = DEVICE(&s->armv7m);
|
armv7m = DEVICE(&s->armv7m);
|
||||||
qdev_prop_set_uint32(armv7m, "num-irq", 96);
|
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_prop_set_bit(armv7m, "enable-bitband", true);
|
||||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||||
qdev_connect_clock_in(armv7m, "refclk", s->refclk);
|
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)
|
static void stm32f205_soc_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->realize = stm32f205_soc_realize;
|
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 = {
|
static const TypeInfo stm32f205_soc_info = {
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
|
|||||||
|
|
||||||
armv7m = DEVICE(&s->armv7m);
|
armv7m = DEVICE(&s->armv7m);
|
||||||
qdev_prop_set_uint32(armv7m, "num-irq", 96);
|
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_prop_set_bit(armv7m, "enable-bitband", true);
|
||||||
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
|
||||||
qdev_connect_clock_in(armv7m, "refclk", s->refclk);
|
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);
|
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)
|
static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->realize = stm32f405_soc_realize;
|
dc->realize = stm32f405_soc_realize;
|
||||||
|
device_class_set_props(dc, stm32f405_soc_properties);
|
||||||
/* No vmstate or reset required: device has no internal state */
|
/* 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);
|
clock_set_hz(sysclk, SYSCLK_FRQ);
|
||||||
|
|
||||||
dev = qdev_new(TYPE_STM32F100_SOC);
|
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);
|
qdev_connect_clock_in(dev, "sysclk", sysclk);
|
||||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
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 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->desc = "ST STM32VLDISCOVERY (Cortex-M3)";
|
||||||
mc->init = stm32vldiscovery_init;
|
mc->init = stm32vldiscovery_init;
|
||||||
mc->valid_cpu_types = valid_cpu_types;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init)
|
DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init)
|
||||||
|
|||||||
@@ -576,8 +576,7 @@ static void fdt_add_gic_node(VirtMachineState *vms)
|
|||||||
|
|
||||||
if (vms->virt) {
|
if (vms->virt) {
|
||||||
qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
||||||
GIC_FDT_IRQ_TYPE_PPI,
|
GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
|
||||||
INTID_TO_PPI(ARCH_GIC_MAINT_IRQ),
|
|
||||||
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
|
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
|
||||||
}
|
}
|
||||||
} else {
|
} 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].base,
|
||||||
2, vms->memmap[VIRT_GIC_VCPU].size);
|
2, vms->memmap[VIRT_GIC_VCPU].size);
|
||||||
qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
||||||
GIC_FDT_IRQ_TYPE_PPI,
|
GIC_FDT_IRQ_TYPE_PPI, ARCH_GIC_MAINT_IRQ,
|
||||||
INTID_TO_PPI(ARCH_GIC_MAINT_IRQ),
|
|
||||||
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
|
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;
|
cnt += (transferred + d->leftover) >> 2;
|
||||||
|
|
||||||
if (s->sctl & loop_sel) {
|
if (s->sctl & loop_sel) {
|
||||||
/*
|
/* Bah, how stupid is that having a 0 represent true value?
|
||||||
* loop_sel tells us which bit in the SCTL register to look at
|
i just spent few hours on this shit */
|
||||||
* (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).
|
|
||||||
*/
|
|
||||||
AUD_log ("es1370: warning", "non looping mode\n");
|
AUD_log ("es1370: warning", "non looping mode\n");
|
||||||
} else {
|
} else {
|
||||||
d->frame_cnt = size;
|
d->frame_cnt = size;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "intel-hda.h"
|
#include "intel-hda.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
#include "qemu/host-utils.h"
|
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "intel-hda-defs.h"
|
#include "intel-hda-defs.h"
|
||||||
#include "audio/audio.h"
|
#include "audio/audio.h"
|
||||||
@@ -190,9 +189,9 @@ struct HDAAudioState {
|
|||||||
bool use_timer;
|
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)
|
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 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 wpos = st->wpos;
|
||||||
int64_t rpos = st->rpos;
|
int64_t rpos = st->rpos;
|
||||||
int64_t wanted_rpos;
|
|
||||||
|
|
||||||
if (uptime <= 0) {
|
int64_t wanted_rpos = hda_bytes_per_second(st) * (now - buft_start)
|
||||||
/* wanted_rpos <= 0 */
|
/ NANOSECONDS_PER_SECOND;
|
||||||
goto out_timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
wanted_rpos = muldiv64(uptime, hda_bytes_per_second(st),
|
|
||||||
NANOSECONDS_PER_SECOND);
|
|
||||||
wanted_rpos &= -4; /* IMPORTANT! clip to frames */
|
wanted_rpos &= -4; /* IMPORTANT! clip to frames */
|
||||||
|
|
||||||
if (wanted_rpos <= rpos) {
|
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 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 wpos = st->wpos;
|
||||||
int64_t rpos = st->rpos;
|
int64_t rpos = st->rpos;
|
||||||
int64_t wanted_wpos;
|
|
||||||
|
|
||||||
if (uptime <= 0) {
|
int64_t wanted_wpos = hda_bytes_per_second(st) * (now - buft_start)
|
||||||
/* wanted_wpos <= 0 */
|
/ NANOSECONDS_PER_SECOND;
|
||||||
goto out_timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
wanted_wpos = muldiv64(uptime, hda_bytes_per_second(st),
|
|
||||||
NANOSECONDS_PER_SECOND);
|
|
||||||
wanted_wpos &= -4; /* IMPORTANT! clip to frames */
|
wanted_wpos &= -4; /* IMPORTANT! clip to frames */
|
||||||
|
|
||||||
if (wanted_wpos <= wpos) {
|
if (wanted_wpos <= wpos) {
|
||||||
@@ -868,10 +855,10 @@ static Property hda_audio_properties[] = {
|
|||||||
static void hda_audio_init_output(HDACodecDevice *hda, Error **errp)
|
static void hda_audio_init_output(HDACodecDevice *hda, Error **errp)
|
||||||
{
|
{
|
||||||
HDAAudioState *a = HDA_AUDIO(hda);
|
HDAAudioState *a = HDA_AUDIO(hda);
|
||||||
const struct desc_codec *desc = &output_mixemu;
|
const struct desc_codec *desc = &output_nomixemu;
|
||||||
|
|
||||||
if (!a->mixer) {
|
if (!a->mixer) {
|
||||||
desc = &output_nomixemu;
|
desc = &output_mixemu;
|
||||||
}
|
}
|
||||||
|
|
||||||
hda_audio_init(hda, desc, errp);
|
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)
|
static void hda_audio_init_duplex(HDACodecDevice *hda, Error **errp)
|
||||||
{
|
{
|
||||||
HDAAudioState *a = HDA_AUDIO(hda);
|
HDAAudioState *a = HDA_AUDIO(hda);
|
||||||
const struct desc_codec *desc = &duplex_mixemu;
|
const struct desc_codec *desc = &duplex_nomixemu;
|
||||||
|
|
||||||
if (!a->mixer) {
|
if (!a->mixer) {
|
||||||
desc = &duplex_nomixemu;
|
desc = &duplex_mixemu;
|
||||||
}
|
}
|
||||||
|
|
||||||
hda_audio_init(hda, desc, errp);
|
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)
|
static void hda_audio_init_micro(HDACodecDevice *hda, Error **errp)
|
||||||
{
|
{
|
||||||
HDAAudioState *a = HDA_AUDIO(hda);
|
HDAAudioState *a = HDA_AUDIO(hda);
|
||||||
const struct desc_codec *desc = µ_mixemu;
|
const struct desc_codec *desc = µ_nomixemu;
|
||||||
|
|
||||||
if (!a->mixer) {
|
if (!a->mixer) {
|
||||||
desc = µ_nomixemu;
|
desc = µ_mixemu;
|
||||||
}
|
}
|
||||||
|
|
||||||
hda_audio_init(hda, desc, errp);
|
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);
|
AUD_set_active_out(s->vo, 0);
|
||||||
}
|
}
|
||||||
if (c->type & STAT_EOL) {
|
if (c->type & STAT_EOL) {
|
||||||
via_isa_set_irq(&s->dev, 0, 1);
|
pci_set_irq(&s->dev, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CLEN_IS_FLAG(c)) {
|
if (CLEN_IS_FLAG(c)) {
|
||||||
c->stat |= STAT_FLAG;
|
c->stat |= STAT_FLAG;
|
||||||
c->stat |= STAT_PAUSED;
|
c->stat |= STAT_PAUSED;
|
||||||
if (c->type & STAT_FLAG) {
|
if (c->type & STAT_FLAG) {
|
||||||
via_isa_set_irq(&s->dev, 0, 1);
|
pci_set_irq(&s->dev, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CLEN_IS_STOP(c)) {
|
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) {
|
if (val & STAT_EOL) {
|
||||||
s->aur.stat &= ~(STAT_EOL | STAT_PAUSED);
|
s->aur.stat &= ~(STAT_EOL | STAT_PAUSED);
|
||||||
if (s->aur.type & STAT_EOL) {
|
if (s->aur.type & STAT_EOL) {
|
||||||
via_isa_set_irq(&s->dev, 0, 0);
|
pci_set_irq(&s->dev, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (val & STAT_FLAG) {
|
if (val & STAT_FLAG) {
|
||||||
s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED);
|
s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED);
|
||||||
if (s->aur.type & STAT_FLAG) {
|
if (s->aur.type & STAT_FLAG) {
|
||||||
via_isa_set_irq(&s->dev, 0, 0);
|
pci_set_irq(&s->dev, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -47,14 +47,12 @@ static void virtio_snd_pci_class_init(ObjectClass *klass, void *data)
|
|||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
|
VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
|
||||||
PCIDeviceClass *pcidevklass = PCI_DEVICE_CLASS(klass);
|
|
||||||
|
|
||||||
device_class_set_props(dc, virtio_snd_pci_properties);
|
device_class_set_props(dc, virtio_snd_pci_properties);
|
||||||
dc->desc = "Virtio Sound";
|
dc->desc = "Virtio Sound";
|
||||||
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
|
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
|
||||||
|
|
||||||
vpciklass->realize = virtio_snd_pci_realize;
|
vpciklass->realize = virtio_snd_pci_realize;
|
||||||
pcidevklass->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_snd_pci_instance_init(Object *obj)
|
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_process_cmdq(VirtIOSound *s);
|
||||||
static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream);
|
static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream);
|
||||||
static void virtio_snd_pcm_in_cb(void *data, int available);
|
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)
|
static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
|
||||||
| BIT(VIRTIO_SND_PCM_FMT_U8)
|
| BIT(VIRTIO_SND_PCM_FMT_U8)
|
||||||
@@ -69,7 +68,6 @@ static const VMStateDescription vmstate_virtio_snd_device = {
|
|||||||
|
|
||||||
static const VMStateDescription vmstate_virtio_snd = {
|
static const VMStateDescription vmstate_virtio_snd = {
|
||||||
.name = TYPE_VIRTIO_SND,
|
.name = TYPE_VIRTIO_SND,
|
||||||
.unmigratable = 1,
|
|
||||||
.minimum_version_id = VIRTIO_SOUND_VM_VERSION,
|
.minimum_version_id = VIRTIO_SOUND_VM_VERSION,
|
||||||
.version_id = VIRTIO_SOUND_VM_VERSION,
|
.version_id = VIRTIO_SOUND_VM_VERSION,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
@@ -243,13 +241,12 @@ static void virtio_snd_handle_pcm_info(VirtIOSound *s,
|
|||||||
memset(&pcm_info[i].padding, 0, 5);
|
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);
|
cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
|
||||||
iov_from_buf(cmd->elem->in_sg,
|
iov_from_buf(cmd->elem->in_sg,
|
||||||
cmd->elem->in_num,
|
cmd->elem->in_num,
|
||||||
sizeof(virtio_snd_hdr),
|
sizeof(virtio_snd_hdr),
|
||||||
pcm_info,
|
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->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels);
|
||||||
as->fmt = virtio_snd_get_qemu_format(params->format);
|
as->fmt = virtio_snd_get_qemu_format(params->format);
|
||||||
as->freq = virtio_snd_get_qemu_freq(params->rate);
|
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;
|
stream->s = s;
|
||||||
qemu_mutex_init(&stream->queue_mutex);
|
qemu_mutex_init(&stream->queue_mutex);
|
||||||
QSIMPLEQ_INIT(&stream->queue);
|
QSIMPLEQ_INIT(&stream->queue);
|
||||||
|
QSIMPLEQ_INIT(&stream->invalid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* stream_id >= s->snd_conf.streams was checked before so this is
|
* 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) {
|
QSIMPLEQ_FOREACH_SAFE(buffer, &stream->queue, entry, next) {
|
||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
QSIMPLEQ_FOREACH_SAFE(buffer, &stream->invalid, entry, next) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@@ -746,8 +747,7 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
|
|||||||
0,
|
0,
|
||||||
&cmd->resp,
|
&cmd->resp,
|
||||||
sizeof(virtio_snd_hdr));
|
sizeof(virtio_snd_hdr));
|
||||||
virtqueue_push(cmd->vq, cmd->elem,
|
virtqueue_push(cmd->vq, cmd->elem, sizeof(virtio_snd_hdr));
|
||||||
sizeof(virtio_snd_hdr) + cmd->payload_size);
|
|
||||||
virtio_notify(VIRTIO_DEVICE(s), cmd->vq);
|
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->elem = elem;
|
||||||
cmd->vq = vq;
|
cmd->vq = vq;
|
||||||
cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
|
cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
|
||||||
/* implicit cmd->payload_size = 0; */
|
|
||||||
QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next);
|
QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next);
|
||||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
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();
|
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)
|
static inline void empty_invalid_queue(VirtIODevice *vdev, VirtQueue *vq)
|
||||||
{
|
{
|
||||||
VirtIOSoundPCMBuffer *buffer = NULL;
|
VirtIOSoundPCMBuffer *buffer = NULL;
|
||||||
|
VirtIOSoundPCMStream *stream = NULL;
|
||||||
virtio_snd_pcm_status resp = { 0 };
|
virtio_snd_pcm_status resp = { 0 };
|
||||||
VirtIOSound *vsnd = VIRTIO_SND(vdev);
|
VirtIOSound *vsnd = VIRTIO_SND(vdev);
|
||||||
|
bool any = false;
|
||||||
|
|
||||||
g_assert(!QSIMPLEQ_EMPTY(&vsnd->invalid));
|
for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
|
||||||
|
stream = vsnd->pcm->streams[i];
|
||||||
while (!QSIMPLEQ_EMPTY(&vsnd->invalid)) {
|
if (stream) {
|
||||||
buffer = QSIMPLEQ_FIRST(&vsnd->invalid);
|
any = false;
|
||||||
/* If buffer->vq != vq, our logic is fundamentally wrong, so bail out */
|
WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
|
||||||
g_assert(buffer->vq == vq);
|
while (!QSIMPLEQ_EMPTY(&stream->invalid)) {
|
||||||
|
buffer = QSIMPLEQ_FIRST(&stream->invalid);
|
||||||
resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
|
if (buffer->vq != vq) {
|
||||||
iov_from_buf(buffer->elem->in_sg,
|
break;
|
||||||
buffer->elem->in_num,
|
}
|
||||||
0,
|
any = true;
|
||||||
&resp,
|
resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
|
||||||
sizeof(virtio_snd_pcm_status));
|
iov_from_buf(buffer->elem->in_sg,
|
||||||
virtqueue_push(vq,
|
buffer->elem->in_num,
|
||||||
buffer->elem,
|
0,
|
||||||
sizeof(virtio_snd_pcm_status));
|
&resp,
|
||||||
QSIMPLEQ_REMOVE_HEAD(&vsnd->invalid, entry);
|
sizeof(virtio_snd_pcm_status));
|
||||||
virtio_snd_pcm_buffer_free(buffer);
|
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)
|
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;
|
VirtIOSoundPCMBuffer *buffer;
|
||||||
VirtQueueElement *elem;
|
VirtQueueElement *elem;
|
||||||
size_t msg_sz, size;
|
size_t msg_sz, size;
|
||||||
virtio_snd_pcm_xfer hdr;
|
virtio_snd_pcm_xfer hdr;
|
||||||
uint32_t stream_id;
|
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.
|
* return them after the for loop.
|
||||||
*/
|
*/
|
||||||
bool must_empty_invalid_queue = false;
|
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();
|
trace_virtio_snd_handle_tx_xfer();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
VirtIOSoundPCMStream *stream;
|
|
||||||
|
|
||||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||||
if (!elem) {
|
if (!elem) {
|
||||||
break;
|
break;
|
||||||
@@ -903,12 +912,12 @@ static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
}
|
}
|
||||||
stream_id = le32_to_cpu(hdr.stream_id);
|
stream_id = le32_to_cpu(hdr.stream_id);
|
||||||
|
|
||||||
if (stream_id >= vsnd->snd_conf.streams
|
if (stream_id >= s->snd_conf.streams
|
||||||
|| vsnd->pcm->streams[stream_id] == NULL) {
|
|| s->pcm->streams[stream_id] == NULL) {
|
||||||
goto tx_err;
|
goto tx_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream = vsnd->pcm->streams[stream_id];
|
stream = s->pcm->streams[stream_id];
|
||||||
if (stream->info.direction != VIRTIO_SND_D_OUTPUT) {
|
if (stream->info.direction != VIRTIO_SND_D_OUTPUT) {
|
||||||
goto tx_err;
|
goto tx_err;
|
||||||
}
|
}
|
||||||
@@ -928,11 +937,13 @@ static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
tx_err:
|
tx_err:
|
||||||
must_empty_invalid_queue = true;
|
WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
|
||||||
buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
|
must_empty_invalid_queue = true;
|
||||||
buffer->elem = elem;
|
buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
|
||||||
buffer->vq = vq;
|
buffer->elem = elem;
|
||||||
QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
|
buffer->vq = vq;
|
||||||
|
QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (must_empty_invalid_queue) {
|
if (must_empty_invalid_queue) {
|
||||||
@@ -949,14 +960,15 @@ tx_err:
|
|||||||
*/
|
*/
|
||||||
static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
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;
|
VirtIOSoundPCMBuffer *buffer;
|
||||||
VirtQueueElement *elem;
|
VirtQueueElement *elem;
|
||||||
size_t msg_sz, size;
|
size_t msg_sz, size;
|
||||||
virtio_snd_pcm_xfer hdr;
|
virtio_snd_pcm_xfer hdr;
|
||||||
uint32_t stream_id;
|
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.
|
* return them after the for loop.
|
||||||
*/
|
*/
|
||||||
bool must_empty_invalid_queue = false;
|
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();
|
trace_virtio_snd_handle_rx_xfer();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
VirtIOSoundPCMStream *stream;
|
|
||||||
|
|
||||||
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
|
||||||
if (!elem) {
|
if (!elem) {
|
||||||
break;
|
break;
|
||||||
@@ -984,12 +994,12 @@ static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
}
|
}
|
||||||
stream_id = le32_to_cpu(hdr.stream_id);
|
stream_id = le32_to_cpu(hdr.stream_id);
|
||||||
|
|
||||||
if (stream_id >= vsnd->snd_conf.streams
|
if (stream_id >= s->snd_conf.streams
|
||||||
|| !vsnd->pcm->streams[stream_id]) {
|
|| !s->pcm->streams[stream_id]) {
|
||||||
goto rx_err;
|
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) {
|
if (stream == NULL || stream->info.direction != VIRTIO_SND_D_INPUT) {
|
||||||
goto rx_err;
|
goto rx_err;
|
||||||
}
|
}
|
||||||
@@ -1006,11 +1016,13 @@ static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
rx_err:
|
rx_err:
|
||||||
must_empty_invalid_queue = true;
|
WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
|
||||||
buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
|
must_empty_invalid_queue = true;
|
||||||
buffer->elem = elem;
|
buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
|
||||||
buffer->vq = vq;
|
buffer->elem = elem;
|
||||||
QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
|
buffer->vq = vq;
|
||||||
|
QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (must_empty_invalid_queue) {
|
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 };
|
virtio_snd_pcm_set_params default_params = { 0 };
|
||||||
uint32_t status;
|
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);
|
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) {
|
if (vsnd->snd_conf.jacks > 8) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Invalid number of jacks: %"PRIu32,
|
"Invalid number of jacks: %"PRIu32,
|
||||||
@@ -1076,22 +1102,7 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AUD_register_card("virtio-sound", &vsnd->card, errp)) {
|
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);
|
|
||||||
|
|
||||||
/* set default params for all streams */
|
/* set default params for all streams */
|
||||||
default_params.features = 0;
|
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);
|
virtio_add_queue(vdev, 64, virtio_snd_handle_rx_xfer);
|
||||||
qemu_mutex_init(&vsnd->cmdq_mutex);
|
qemu_mutex_init(&vsnd->cmdq_mutex);
|
||||||
QTAILQ_INIT(&vsnd->cmdq);
|
QTAILQ_INIT(&vsnd->cmdq);
|
||||||
QSIMPLEQ_INIT(&vsnd->invalid);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
|
for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
|
||||||
status = virtio_snd_set_pcm_params(vsnd, i, &default_params);
|
status = virtio_snd_set_pcm_params(vsnd, i, &default_params);
|
||||||
if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
|
if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Can't initialize stream params, device responded with %s.",
|
"Can't initalize stream params, device responded with %s.",
|
||||||
print_code(status));
|
print_code(status));
|
||||||
goto error_cleanup;
|
return;
|
||||||
}
|
}
|
||||||
status = virtio_snd_pcm_prepare(vsnd, i);
|
status = virtio_snd_pcm_prepare(vsnd, i);
|
||||||
if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
|
if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Can't prepare streams, device responded with %s.",
|
"Can't prepare streams, device responded with %s.",
|
||||||
print_code(status));
|
print_code(status));
|
||||||
goto error_cleanup;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
error_cleanup:
|
|
||||||
virtio_snd_unrealize(dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void return_tx_buffer(VirtIOSoundPCMStream *stream,
|
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)
|
static void virtio_snd_reset(VirtIODevice *vdev)
|
||||||
{
|
{
|
||||||
VirtIOSound *vsnd = VIRTIO_SND(vdev);
|
VirtIOSound *s = VIRTIO_SND(vdev);
|
||||||
virtio_snd_ctrl_command *cmd;
|
virtio_snd_ctrl_command *cmd;
|
||||||
|
|
||||||
/*
|
WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
|
||||||
* Sanity check that the invalid buffer message queue is emptied at the end
|
while (!QTAILQ_EMPTY(&s->cmdq)) {
|
||||||
* of every virtio_snd_handle_tx_xfer/virtio_snd_handle_rx_xfer call, and
|
cmd = QTAILQ_FIRST(&s->cmdq);
|
||||||
* must be empty otherwise.
|
QTAILQ_REMOVE(&s->cmdq, cmd, next);
|
||||||
*/
|
|
||||||
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);
|
|
||||||
virtio_snd_ctrl_cmd_free(cmd);
|
virtio_snd_ctrl_cmd_free(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,10 +233,6 @@ static void atmega_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
/* CPU */
|
/* CPU */
|
||||||
object_initialize_child(OBJECT(dev), "cpu", &s->cpu, mc->cpu_type);
|
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);
|
qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
|
||||||
cpudev = DEVICE(&s->cpu);
|
cpudev = DEVICE(&s->cpu);
|
||||||
|
|
||||||
|
|||||||
@@ -84,11 +84,7 @@ struct NANDFlashState {
|
|||||||
|
|
||||||
void (*blk_write)(NANDFlashState *s);
|
void (*blk_write)(NANDFlashState *s);
|
||||||
void (*blk_erase)(NANDFlashState *s);
|
void (*blk_erase)(NANDFlashState *s);
|
||||||
/*
|
void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
|
||||||
* Returns %true when block containing (@addr + @offset) is
|
|
||||||
* successfully loaded, otherwise %false.
|
|
||||||
*/
|
|
||||||
bool (*blk_load)(NANDFlashState *s, uint64_t addr, unsigned offset);
|
|
||||||
|
|
||||||
uint32_t ioaddr_vmstate;
|
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)
|
static void nand_command(NANDFlashState *s)
|
||||||
{
|
{
|
||||||
|
unsigned int offset;
|
||||||
switch (s->cmd) {
|
switch (s->cmd) {
|
||||||
case NAND_CMD_READ0:
|
case NAND_CMD_READ0:
|
||||||
s->iolen = 0;
|
s->iolen = 0;
|
||||||
@@ -296,7 +271,12 @@ static void nand_command(NANDFlashState *s)
|
|||||||
case NAND_CMD_NOSERIALREAD2:
|
case NAND_CMD_NOSERIALREAD2:
|
||||||
if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP))
|
if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP))
|
||||||
break;
|
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;
|
break;
|
||||||
|
|
||||||
case NAND_CMD_RESET:
|
case NAND_CMD_RESET:
|
||||||
@@ -617,7 +597,12 @@ uint32_t nand_getio(DeviceState *dev)
|
|||||||
if (!s->iolen && s->cmd == NAND_CMD_READ0) {
|
if (!s->iolen && s->cmd == NAND_CMD_READ0) {
|
||||||
offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
|
offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
|
||||||
s->offset = 0;
|
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) {
|
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,
|
static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
|
||||||
uint64_t addr, unsigned offset)
|
uint64_t addr, int offset)
|
||||||
{
|
{
|
||||||
if (PAGE(addr) >= s->pages) {
|
if (PAGE(addr) >= s->pages) {
|
||||||
return false;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (offset > NAND_PAGE_SIZE + OOB_SIZE) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->blk) {
|
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);
|
offset, NAND_PAGE_SIZE + OOB_SIZE - offset);
|
||||||
s->ioaddr = s->io;
|
s->ioaddr = s->io;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void glue(nand_init_, NAND_PAGE_SIZE)(NANDFlashState *s)
|
static void glue(nand_init_, NAND_PAGE_SIZE)(NANDFlashState *s)
|
||||||
|
|||||||
@@ -80,39 +80,16 @@ struct PFlashCFI01 {
|
|||||||
uint16_t ident3;
|
uint16_t ident3;
|
||||||
uint8_t cfi_table[0x52];
|
uint8_t cfi_table[0x52];
|
||||||
uint64_t counter;
|
uint64_t counter;
|
||||||
uint32_t writeblock_size;
|
unsigned int writeblock_size;
|
||||||
MemoryRegion mem;
|
MemoryRegion mem;
|
||||||
char *name;
|
char *name;
|
||||||
void *storage;
|
void *storage;
|
||||||
VMChangeStateEntry *vmstate;
|
VMChangeStateEntry *vmstate;
|
||||||
bool old_multiple_chip_handling;
|
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 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 = {
|
static const VMStateDescription vmstate_pflash = {
|
||||||
.name = "pflash_cfi01",
|
.name = "pflash_cfi01",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
@@ -124,10 +101,6 @@ static const VMStateDescription vmstate_pflash = {
|
|||||||
VMSTATE_UINT8(status, PFlashCFI01),
|
VMSTATE_UINT8(status, PFlashCFI01),
|
||||||
VMSTATE_UINT64(counter, PFlashCFI01),
|
VMSTATE_UINT64(counter, PFlashCFI01),
|
||||||
VMSTATE_END_OF_LIST()
|
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;
|
uint32_t ret;
|
||||||
|
|
||||||
p = pfl->storage;
|
p = pfl->storage;
|
||||||
if (be) {
|
switch (width) {
|
||||||
ret = ldn_be_p(p + offset, width);
|
case 1:
|
||||||
} else {
|
ret = p[offset];
|
||||||
ret = ldn_le_p(p + offset, width);
|
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);
|
trace_pflash_data_read(pfl->name, offset, width, ret);
|
||||||
return 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,
|
static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||||
uint32_t value, int width, int be)
|
uint32_t value, int width, int be)
|
||||||
{
|
{
|
||||||
uint8_t *p;
|
uint8_t *p = pfl->storage;
|
||||||
|
|
||||||
if (pfl->blk_offset != -1) {
|
trace_pflash_data_write(pfl->name, offset, width, value, pfl->counter);
|
||||||
/* block write: redirect writes to block update buffer */
|
switch (width) {
|
||||||
if ((offset < pfl->blk_offset) ||
|
case 1:
|
||||||
(offset + width > pfl->blk_offset + pfl->writeblock_size)) {
|
p[offset] = value;
|
||||||
pfl->status |= 0x10; /* Programming error */
|
break;
|
||||||
return;
|
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,
|
break;
|
||||||
pfl->counter);
|
case 4:
|
||||||
p = pfl->blk_bytes + (offset - pfl->blk_offset);
|
if (be) {
|
||||||
} else {
|
p[offset] = value >> 24;
|
||||||
/* write directly to storage */
|
p[offset + 1] = value >> 16;
|
||||||
trace_pflash_data_write(pfl->name, offset, width, value);
|
p[offset + 2] = value >> 8;
|
||||||
p = pfl->storage + offset;
|
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,
|
static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
||||||
@@ -572,9 +548,9 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
|||||||
} else {
|
} else {
|
||||||
value = extract32(value, 0, pfl->bank_width * 8);
|
value = extract32(value, 0, pfl->bank_width * 8);
|
||||||
}
|
}
|
||||||
|
trace_pflash_write_block(pfl->name, value);
|
||||||
pfl->counter = value;
|
pfl->counter = value;
|
||||||
pfl->wcycle++;
|
pfl->wcycle++;
|
||||||
pflash_blk_write_start(pfl, offset);
|
|
||||||
break;
|
break;
|
||||||
case 0x60:
|
case 0x60:
|
||||||
if (cmd == 0xd0) {
|
if (cmd == 0xd0) {
|
||||||
@@ -605,7 +581,12 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
|||||||
switch (pfl->cmd) {
|
switch (pfl->cmd) {
|
||||||
case 0xe8: /* Block write */
|
case 0xe8: /* Block write */
|
||||||
/* FIXME check @offset, @width */
|
/* 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);
|
pflash_data_write(pfl, offset, value, width, be);
|
||||||
} else {
|
} else {
|
||||||
pfl->status |= 0x10; /* Programming error */
|
pfl->status |= 0x10; /* Programming error */
|
||||||
@@ -614,8 +595,18 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
|||||||
pfl->status |= 0x80;
|
pfl->status |= 0x80;
|
||||||
|
|
||||||
if (!pfl->counter) {
|
if (!pfl->counter) {
|
||||||
|
hwaddr mask = pfl->writeblock_size - 1;
|
||||||
|
mask = ~mask;
|
||||||
|
|
||||||
trace_pflash_write(pfl->name, "block write finished");
|
trace_pflash_write(pfl->name, "block write finished");
|
||||||
pfl->wcycle++;
|
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--;
|
pfl->counter--;
|
||||||
@@ -627,17 +618,20 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset,
|
|||||||
case 3: /* Confirm mode */
|
case 3: /* Confirm mode */
|
||||||
switch (pfl->cmd) {
|
switch (pfl->cmd) {
|
||||||
case 0xe8: /* Block write */
|
case 0xe8: /* Block write */
|
||||||
if ((cmd == 0xd0) && !(pfl->status & 0x10)) {
|
if (cmd == 0xd0) {
|
||||||
pflash_blk_write_flush(pfl);
|
/* FIXME this is where we should write out the buffer */
|
||||||
pfl->wcycle = 0;
|
pfl->wcycle = 0;
|
||||||
pfl->status |= 0x80;
|
pfl->status |= 0x80;
|
||||||
} else {
|
} 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;
|
goto mode_read_array;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pflash_blk_write_abort(pfl);
|
|
||||||
goto error_flash;
|
goto error_flash;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -871,9 +865,6 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
|||||||
pfl->cmd = 0x00;
|
pfl->cmd = 0x00;
|
||||||
pfl->status = 0x80; /* WSM ready */
|
pfl->status = 0x80; /* WSM ready */
|
||||||
pflash_cfi01_fill_cfi_table(pfl);
|
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)
|
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.
|
* This model deliberately ignores this delay.
|
||||||
*/
|
*/
|
||||||
pfl->status = 0x80;
|
pfl->status = 0x80;
|
||||||
|
|
||||||
pfl->blk_offset = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property pflash_cfi01_properties[] = {
|
static Property pflash_cfi01_properties[] = {
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ static void pflash_write(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
}
|
}
|
||||||
goto reset_flash;
|
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) {
|
if (!pfl->ro) {
|
||||||
p = (uint8_t *)pfl->storage + offset;
|
p = (uint8_t *)pfl->storage + offset;
|
||||||
if (pfl->be) {
|
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_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_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_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(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_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_device_id(const char *name, uint16_t id) "%s: read device ID: 0x%04x"
|
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_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"
|
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_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_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(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(const char *name, uint32_t value) "%s: block write: 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_erase(const char *name, uint64_t offset, uint64_t len) "%s: block erase offset:0x%" PRIx64 " bytes:0x%" PRIx64
|
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_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"
|
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) {
|
if (s->connected) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
s->connected = true;
|
||||||
|
|
||||||
s->dev.num_queues = s->num_queues;
|
s->dev.num_queues = s->num_queues;
|
||||||
s->dev.nvqs = 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->connected = true;
|
|
||||||
|
|
||||||
/* restore vhost state */
|
/* restore vhost state */
|
||||||
if (virtio_device_started(vdev, vdev->status)) {
|
if (virtio_device_started(vdev, vdev->status)) {
|
||||||
ret = vhost_user_blk_start(vdev, errp);
|
ret = vhost_user_blk_start(vdev, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vhost_user_blk_disconnect(DeviceState *dev)
|
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