release
-----BEGIN PGP SIGNATURE----- iQFDBAABCAAtFiEEe3O61ovnosKJMUsicBtPaxppPlkFAmW3ieYPHG1qdEB0bHMu bXNrLnJ1AAoJEHAbT2saaT5ZZoQH/3W/nem8F8SvhsBJSYxe6PBgWzoNNgkPRalq x/HshsYDg7DOuA3qutmnnoUH7jlxubhtzQaiM/mTAKX4YQZ+ysubvu6Nh5A8iEWb zTHUFY8fpn+oPs8snuHcbu9GltgN2K750w7PXasCkctmJF0TfxmGnAlF5+KPLott 7Wl9IldiDuOFGCH/Oyz+YVvz48D7cNLeSz06LrQZ5XWLaKnJHXj80VydX0qSUf6I begK/pMISBpJX+CSTcLuH/eA3sFxbgze8puWqU6XOZ6QSOhrI2l5t0a0JFY2KQUp pz7QvBLhgM3/gbBhwzf5dU2Ym8scZwAR2bmL6feKDBu1aRmX8Lo= =UPmI -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQSq9xYmtep25y1RrMYC5KE/dBVGigUCZcCn6wAKCRAC5KE/dBVG ihCjAQCMfVzZ0NI8dci+aO5nJYqtvJ62FHExxNMEavyTT42M9QEApMF7DrnNb7yi 1zAYBOB7liOGNq0RMJqq0c9onkaOOQk= =804i -----END PGP SIGNATURE----- Merge tag 'v8.2.1' release
This commit is contained in:
commit
75d15d54f4
@ -41,7 +41,7 @@ build-system-ubuntu:
|
|||||||
variables:
|
variables:
|
||||||
IMAGE: ubuntu2204
|
IMAGE: ubuntu2204
|
||||||
CONFIGURE_ARGS: --enable-docs
|
CONFIGURE_ARGS: --enable-docs
|
||||||
TARGETS: alpha-softmmu microblazeel-softmmu mips64el-softmmu
|
TARGETS: alpha-softmmu microblaze-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-amd64
|
IMAGE: debian
|
||||||
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-amd64
|
IMAGE: debian
|
||||||
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-amd64
|
IMAGE: debian
|
||||||
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-amd64
|
IMAGE: debian
|
||||||
script:
|
script:
|
||||||
- cd build
|
- cd build
|
||||||
- make NINJA=":" check-venv
|
- make NINJA=":" check-venv
|
||||||
@ -217,6 +217,36 @@ 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
|
||||||
@ -589,7 +619,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-amd64
|
IMAGE: debian
|
||||||
MAKE_CHECK_ARGS: check-unit ctags TAGS cscope
|
MAKE_CHECK_ARGS: check-unit ctags TAGS cscope
|
||||||
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
|
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
|
||||||
QEMU_JOB_PUBLISH: 1
|
QEMU_JOB_PUBLISH: 1
|
||||||
@ -609,7 +639,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-amd64:$QEMU_CI_CONTAINER_TAG
|
image: $CI_REGISTRY_IMAGE/qemu/debian:$QEMU_CI_CONTAINER_TAG
|
||||||
stage: test
|
stage: test
|
||||||
needs:
|
needs:
|
||||||
- job: build-tools-and-docs-debian
|
- job: build-tools-and-docs-debian
|
||||||
@ -617,7 +647,10 @@ pages:
|
|||||||
- mkdir -p public
|
- mkdir -p public
|
||||||
# HTML-ised source tree
|
# HTML-ised source tree
|
||||||
- make gtags
|
- make gtags
|
||||||
- htags -anT --tree-view=filetree -m qemu_init
|
# We unset variables to work around a bug in some htags versions
|
||||||
|
# which causes it to fail when the environment is large
|
||||||
|
- CI_COMMIT_MESSAGE= CI_COMMIT_TAG_MESSAGE= htags
|
||||||
|
-anT --tree-view=filetree -m qemu_init
|
||||||
-t "Welcome to the QEMU sourcecode"
|
-t "Welcome to the QEMU sourcecode"
|
||||||
- mv HTML public/src
|
- mv HTML public/src
|
||||||
# Project documentation
|
# Project documentation
|
||||||
|
@ -59,13 +59,13 @@ x64-freebsd-13-build:
|
|||||||
INSTALL_COMMAND: pkg install -y
|
INSTALL_COMMAND: pkg install -y
|
||||||
TEST_TARGETS: check
|
TEST_TARGETS: check
|
||||||
|
|
||||||
aarch64-macos-12-base-build:
|
aarch64-macos-13-base-build:
|
||||||
extends: .cirrus_build_job
|
extends: .cirrus_build_job
|
||||||
variables:
|
variables:
|
||||||
NAME: macos-12
|
NAME: macos-13
|
||||||
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-monterey-base:latest
|
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-ventura-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
|
||||||
@ -74,6 +74,22 @@ aarch64-macos-12-base-build:
|
|||||||
PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
|
PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
|
||||||
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
||||||
|
|
||||||
|
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_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
|
||||||
|
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
|
||||||
.cirrus_kvm_job:
|
.cirrus_kvm_job:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# THIS FILE WAS AUTO-GENERATED
|
# THIS FILE WAS AUTO-GENERATED
|
||||||
#
|
#
|
||||||
# $ lcitool variables macos-12 qemu
|
# $ lcitool variables macos-13 qemu
|
||||||
#
|
#
|
||||||
# https://gitlab.com/libvirt/libvirt-ci
|
# https://gitlab.com/libvirt/libvirt-ci
|
||||||
|
|
16
.gitlab-ci.d/cirrus/macos-14.vars
Normal file
16
.gitlab-ci.d/cirrus/macos-14.vars
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# 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'
|
@ -46,6 +46,12 @@ 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
|
||||||
@ -95,11 +101,6 @@ 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-amd64
|
NAME: debian
|
||||||
|
|
||||||
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-i386-user:
|
cross-i686-user:
|
||||||
extends:
|
extends:
|
||||||
- .cross_user_build_job
|
- .cross_user_build_job
|
||||||
- .cross_test_artifacts
|
- .cross_test_artifacts
|
||||||
needs:
|
needs:
|
||||||
job: i386-fedora-cross-container
|
job: i686-debian-cross-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora-i386-cross
|
IMAGE: debian-i686-cross
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
cross-i386-tci:
|
cross-i686-tci:
|
||||||
extends:
|
extends:
|
||||||
- .cross_accel_build_job
|
- .cross_accel_build_job
|
||||||
- .cross_test_artifacts
|
- .cross_test_artifacts
|
||||||
timeout: 60m
|
timeout: 60m
|
||||||
needs:
|
needs:
|
||||||
job: i386-fedora-cross-container
|
job: i686-debian-cross-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora-i386-cross
|
IMAGE: debian-i686-cross
|
||||||
ACCEL: tcg-interpreter
|
ACCEL: tcg-interpreter
|
||||||
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins
|
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins
|
||||||
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 --disable-plugins
|
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal
|
||||||
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
|
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
|
||||||
microblazeel-softmmu mips64el-softmmu nios2-softmmu
|
microblazeel-softmmu mips64el-softmmu nios2-softmmu
|
||||||
artifacts:
|
artifacts:
|
||||||
|
@ -5,16 +5,21 @@
|
|||||||
# 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
|
|
||||||
|
@ -174,6 +174,7 @@ 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>
|
||||||
|
@ -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_cflags(tb) & CF_PCREL || tb->pc == desc->pc) &&
|
if (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, (cflags & CF_PCREL ? 0 : pc),
|
h = tb_hash_func(phys_pc, 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);
|
||||||
}
|
}
|
||||||
|
@ -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 ((tb_cflags(a) & CF_PCREL || a->pc == b->pc) &&
|
return (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) &&
|
||||||
@ -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, (orig_cflags & CF_PCREL ? 0 : tb->pc),
|
h = tb_hash_func(phys_pc, 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->cflags & CF_PCREL ? 0 : tb->pc),
|
h = tb_hash_func(tb_page_addr0(tb), 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);
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb,
|
|||||||
}
|
}
|
||||||
hook = hook->next;
|
hook = hook->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
gen_intermediate_code(env_cpu(env), tb, max_insns, pc, host_pc);
|
gen_intermediate_code(env_cpu(env), tb, max_insns, pc, host_pc);
|
||||||
@ -320,11 +320,11 @@ static target_ulong reverse_bits(target_ulong num)
|
|||||||
{
|
{
|
||||||
unsigned int count = sizeof(num) * 8 - 1;
|
unsigned int count = sizeof(num) * 8 - 1;
|
||||||
target_ulong reverse_num = num;
|
target_ulong reverse_num = num;
|
||||||
|
|
||||||
num >>= 1;
|
num >>= 1;
|
||||||
while(num)
|
while(num)
|
||||||
{
|
{
|
||||||
reverse_num <<= 1;
|
reverse_num <<= 1;
|
||||||
reverse_num |= num & 1;
|
reverse_num |= num & 1;
|
||||||
num >>= 1;
|
num >>= 1;
|
||||||
count--;
|
count--;
|
||||||
@ -358,7 +358,7 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
|||||||
(void)existing_tb;
|
(void)existing_tb;
|
||||||
|
|
||||||
assert_memory_lock();
|
assert_memory_lock();
|
||||||
|
|
||||||
struct libafl_edge_hook* hook = libafl_edge_hooks;
|
struct libafl_edge_hook* hook = libafl_edge_hooks;
|
||||||
int no_exec_hook = 1;
|
int no_exec_hook = 1;
|
||||||
while (hook) {
|
while (hook) {
|
||||||
|
@ -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'\n", drvname);
|
error_setg(errp, "Unknown audio driver `%s'", drvname);
|
||||||
}
|
}
|
||||||
if (!done) {
|
if (!done) {
|
||||||
goto out;
|
goto out;
|
||||||
@ -1758,12 +1758,15 @@ 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;
|
||||||
}
|
}
|
||||||
QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next);
|
qapi_free_Audiodev(dev);
|
||||||
|
s->dev = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,6 +398,7 @@ 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;
|
||||||
@ -406,11 +407,20 @@ 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;
|
||||||
|
39
block.c
39
block.c
@ -1713,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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
|
|
||||||
g_free(bs->opaque);
|
g_free(bs->opaque);
|
||||||
bs->opaque = NULL;
|
bs->opaque = NULL;
|
||||||
@ -3577,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();
|
bdrv_graph_wrunlock(backing_hd);
|
||||||
bdrv_drained_end(drain_bs);
|
bdrv_drained_end(drain_bs);
|
||||||
bdrv_unref(drain_bs);
|
bdrv_unref(drain_bs);
|
||||||
|
|
||||||
@ -3796,7 +3796,7 @@ BdrvChild *bdrv_open_child(const char *filename,
|
|||||||
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||||
errp);
|
errp);
|
||||||
aio_context_release(ctx);
|
aio_context_release(ctx);
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock(NULL);
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
@ -4652,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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
|
|
||||||
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;
|
||||||
@ -4671,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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
|
|
||||||
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) {
|
||||||
@ -4857,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();
|
bdrv_graph_wrunlock_ctx(ctx);
|
||||||
|
|
||||||
if (old_ctx != ctx) {
|
if (old_ctx != ctx) {
|
||||||
aio_context_release(ctx);
|
aio_context_release(ctx);
|
||||||
@ -5216,7 +5216,7 @@ static void bdrv_close(BlockDriverState *bs)
|
|||||||
|
|
||||||
assert(!bs->backing);
|
assert(!bs->backing);
|
||||||
assert(!bs->file);
|
assert(!bs->file);
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock(bs);
|
||||||
|
|
||||||
g_free(bs->opaque);
|
g_free(bs->opaque);
|
||||||
bs->opaque = NULL;
|
bs->opaque = NULL;
|
||||||
@ -5511,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();
|
bdrv_graph_wrunlock(bs);
|
||||||
bdrv_drained_end(child_bs);
|
bdrv_drained_end(child_bs);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -5593,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();
|
bdrv_graph_wrunlock(bs_top);
|
||||||
|
|
||||||
bdrv_drained_end(bs_top);
|
bdrv_drained_end(bs_top);
|
||||||
bdrv_drained_end(bs_new);
|
bdrv_drained_end(bs_new);
|
||||||
@ -5631,7 +5631,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
|
|||||||
|
|
||||||
tran_finalize(tran, ret);
|
tran_finalize(tran, ret);
|
||||||
|
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock(new_bs);
|
||||||
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);
|
||||||
@ -5720,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();
|
bdrv_graph_wrunlock(new_node_bs);
|
||||||
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);
|
||||||
@ -6015,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();
|
bdrv_graph_wrunlock(base);
|
||||||
|
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_report_err(local_err);
|
error_report_err(local_err);
|
||||||
@ -6052,7 +6052,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
exit_wrlock:
|
exit_wrlock:
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock(base);
|
||||||
exit:
|
exit:
|
||||||
bdrv_drained_end(base);
|
bdrv_drained_end(base);
|
||||||
bdrv_unref(top);
|
bdrv_unref(top);
|
||||||
@ -7254,6 +7254,16 @@ 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.
|
||||||
*
|
*
|
||||||
@ -7267,8 +7277,7 @@ void bdrv_schedule_unref(BlockDriverState *bs)
|
|||||||
if (!bs) {
|
if (!bs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
aio_bh_schedule_oneshot(qemu_get_aio_context(),
|
aio_bh_schedule_oneshot(qemu_get_aio_context(), bdrv_schedule_unref_bh, bs);
|
||||||
(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();
|
bdrv_graph_wrunlock(target);
|
||||||
|
|
||||||
return &job->common;
|
return &job->common;
|
||||||
|
|
||||||
|
@ -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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t coroutine_fn GRAPH_RDLOCK
|
static int64_t coroutine_fn GRAPH_RDLOCK
|
||||||
@ -328,22 +328,39 @@ 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 +=
|
s->cur_log_sector += entry_nr_sectors;
|
||||||
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) {
|
||||||
cur_log_offset = s->cur_log_sector << s->sectorbits;
|
const uint64_t zeroes_offset = entry_offset + qiov_aligned_size;
|
||||||
s->cur_log_sector +=
|
|
||||||
ROUND_UP(lr->zero_size, s->sectorsize) >> s->sectorbits;
|
|
||||||
|
|
||||||
lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, cur_log_offset,
|
lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, zeroes_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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t coroutine_fn GRAPH_RDLOCK
|
static int64_t coroutine_fn GRAPH_RDLOCK
|
||||||
|
@ -924,11 +924,14 @@ 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();
|
||||||
|
|
||||||
@ -958,9 +961,10 @@ void blk_remove_bs(BlockBackend *blk)
|
|||||||
root = blk->root;
|
root = blk->root;
|
||||||
blk->root = NULL;
|
blk->root = NULL;
|
||||||
|
|
||||||
bdrv_graph_wrlock(NULL);
|
ctx = bdrv_get_aio_context(root->bs);
|
||||||
|
bdrv_graph_wrlock(root->bs);
|
||||||
bdrv_root_unref_child(root);
|
bdrv_root_unref_child(root);
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock_ctx(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -971,6 +975,8 @@ 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);
|
||||||
@ -978,7 +984,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();
|
bdrv_graph_wrunlock_ctx(ctx);
|
||||||
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();
|
bdrv_graph_wrunlock(commit_top_backing_bs);
|
||||||
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();
|
bdrv_graph_wrunlock(top);
|
||||||
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();
|
bdrv_graph_wrunlock(top);
|
||||||
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();
|
bdrv_graph_wrunlock(top);
|
||||||
|
|
||||||
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();
|
bdrv_graph_wrunlock(top);
|
||||||
bdrv_drained_end(top);
|
bdrv_drained_end(top);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,6 +283,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,19 +292,23 @@ 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 vhost_user_server_has_in_flight(&vexp->vu_server);
|
return server->co_trip || vhost_user_server_has_in_flight(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const BlockDevOps vu_blk_dev_ops = {
|
static const BlockDevOps vu_blk_dev_ops = {
|
||||||
|
@ -161,11 +161,21 @@ void no_coroutine_fn bdrv_graph_wrlock(BlockDriverState *bs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bdrv_graph_wrunlock(void)
|
void no_coroutine_fn bdrv_graph_wrunlock_ctx(AioContext *ctx)
|
||||||
{
|
{
|
||||||
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
|
||||||
@ -187,6 +197,17 @@ void bdrv_graph_wrunlock(void)
|
|||||||
* 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)
|
||||||
|
10
block/io.c
10
block/io.c
@ -2619,6 +2619,16 @@ 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:
|
||||||
|
@ -773,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();
|
bdrv_graph_wrunlock(target_bs);
|
||||||
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);
|
||||||
@ -798,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();
|
bdrv_graph_wrunlock(mirror_top_bs);
|
||||||
|
|
||||||
bdrv_drained_end(target_bs);
|
bdrv_drained_end(target_bs);
|
||||||
bdrv_unref(target_bs);
|
bdrv_unref(target_bs);
|
||||||
@ -1920,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();
|
bdrv_graph_wrunlock(bs);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1965,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();
|
bdrv_graph_wrunlock(bs);
|
||||||
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();
|
bdrv_graph_wrunlock(bs);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock(bs);
|
||||||
|
|
||||||
QTAILQ_INIT(&s->ops_in_flight);
|
QTAILQ_INIT(&s->ops_in_flight);
|
||||||
|
|
||||||
@ -2006,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();
|
bdrv_graph_wrunlock(bs);
|
||||||
bdrv_drained_end(bs);
|
bdrv_drained_end(bs);
|
||||||
|
|
||||||
bdrv_unref(mirror_top_bs);
|
bdrv_unref(mirror_top_bs);
|
||||||
|
@ -2809,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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
|
|
||||||
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();
|
bdrv_graph_wrunlock(bs);
|
||||||
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();
|
bdrv_graph_wrunlock(bs);
|
||||||
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();
|
bdrv_graph_wrunlock(bs);
|
||||||
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();
|
bdrv_graph_wrunlock(bs);
|
||||||
|
|
||||||
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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
|
|
||||||
s->error = 0;
|
s->error = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -196,8 +196,10 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +294,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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -99,9 +99,9 @@ static int stream_prepare(Job *job)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bdrv_graph_wrlock(base);
|
bdrv_graph_wrlock(s->target_bs);
|
||||||
bdrv_set_backing_hd_drained(unfiltered_bs, base, &local_err);
|
bdrv_set_backing_hd_drained(unfiltered_bs, base, &local_err);
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock(s->target_bs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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();
|
bdrv_graph_wrunlock(bs);
|
||||||
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();
|
bdrv_graph_wrunlock(bs);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock(bs);
|
||||||
|
|
||||||
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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
|
|
||||||
g_free(s->extents);
|
g_free(s->extents);
|
||||||
}
|
}
|
||||||
@ -351,29 +351,41 @@ vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
|
|||||||
BDRVVmdkState *s = bs->opaque;
|
BDRVVmdkState *s = bs->opaque;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
desc = g_malloc0(DESC_SIZE);
|
size_t desc_buf_size;
|
||||||
tmp_desc = g_malloc0(DESC_SIZE);
|
|
||||||
ret = bdrv_co_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
|
if (s->desc_offset == 0) {
|
||||||
|
desc_buf_size = bdrv_getlength(bs->file->bs);
|
||||||
|
if (desc_buf_size > 16ULL << 20) {
|
||||||
|
error_report("VMDK description file too big");
|
||||||
|
return -EFBIG;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
desc_buf_size = DESC_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc = g_malloc0(desc_buf_size);
|
||||||
|
tmp_desc = g_malloc0(desc_buf_size);
|
||||||
|
ret = bdrv_co_pread(bs->file, s->desc_offset, desc_buf_size, desc, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc[DESC_SIZE - 1] = '\0';
|
desc[desc_buf_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_SIZE, tmp_str);
|
pstrcpy(tmp_desc, desc_buf_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_SIZE - (p_name - desc), "%" PRIx32 "\n", cid);
|
snprintf(p_name, desc_buf_size - (p_name - desc), "%" PRIx32 "\n", cid);
|
||||||
pstrcat(desc, DESC_SIZE, tmp_desc);
|
pstrcat(desc, desc_buf_size, tmp_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
|
ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, desc_buf_size, desc, 0);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
g_free(desc);
|
g_free(desc);
|
||||||
@ -1237,7 +1249,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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
bdrv_graph_rdlock_main_loop();
|
bdrv_graph_rdlock_main_loop();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1256,7 +1268,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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
bdrv_graph_rdlock_main_loop();
|
bdrv_graph_rdlock_main_loop();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1267,7 +1279,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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
bdrv_graph_rdlock_main_loop();
|
bdrv_graph_rdlock_main_loop();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1277,7 +1289,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();
|
bdrv_graph_wrunlock(NULL);
|
||||||
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();
|
bdrv_graph_wrunlock(state->old_bs);
|
||||||
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,8 +2400,9 @@ 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);
|
||||||
blk_co_unref(blk);
|
|
||||||
bdrv_co_unlock(bs);
|
bdrv_co_unlock(bs);
|
||||||
|
|
||||||
|
blk_co_unref(blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_block_stream(const char *job_id, const char *device,
|
void qmp_block_stream(const char *job_id, const char *device,
|
||||||
@ -3692,7 +3693,7 @@ void qmp_x_blockdev_change(const char *parent, const char *child,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
bdrv_graph_wrunlock_ctx(job->job.aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
bdrv_graph_wrunlock(bs);
|
||||||
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();
|
bdrv_graph_wrunlock(bs);
|
||||||
return job;
|
return job;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
bdrv_graph_wrunlock();
|
bdrv_graph_wrunlock(bs);
|
||||||
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 necesary */
|
/* Release heap if necessary */
|
||||||
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 agrument for the emulator */
|
/* save the first argument 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undocummented nstat(char *path, struct nstat *ub) syscall */
|
/* undocumented 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undocummented nfstat(int fd, struct nstat *sb) syscall */
|
/* undocumented 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undocummented nlstat(char *path, struct nstat *ub) syscall */
|
/* undocumented 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;
|
||||||
|
@ -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",
|
||||||
"an abstract device type");
|
"a non-abstract device type");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
48
configure
vendored
48
configure
vendored
@ -41,12 +41,7 @@ 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
|
||||||
|
|
||||||
ifeq ($(MAKECMDGOALS),)
|
build:
|
||||||
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" && \
|
||||||
@ -54,8 +49,9 @@ endif
|
|||||||
then \
|
then \
|
||||||
rm -rf build GNUmakefile ; \
|
rm -rf build GNUmakefile ; \
|
||||||
fi
|
fi
|
||||||
force: ;
|
%: build
|
||||||
.PHONY: force
|
@
|
||||||
|
.PHONY: build
|
||||||
GNUmakefile: ;
|
GNUmakefile: ;
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
@ -981,14 +977,14 @@ meson="$(cd pyvenv/bin; pwd)/meson"
|
|||||||
|
|
||||||
# Conditionally ensure Sphinx is installed.
|
# Conditionally ensure Sphinx is installed.
|
||||||
|
|
||||||
mkvenv_flags=""
|
mkvenv_online_flag=""
|
||||||
if test "$download" = "enabled" -a "$docs" = "enabled" ; then
|
if test "$download" = "enabled" ; then
|
||||||
mkvenv_flags="--online"
|
mkvenv_online_flag=" --online"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$docs" != "disabled" ; then
|
if test "$docs" != "disabled" ; then
|
||||||
if ! $mkvenv ensuregroup \
|
if ! $mkvenv ensuregroup \
|
||||||
$mkvenv_flags \
|
$(test "$docs" = "enabled" && echo "$mkvenv_online_flag") \
|
||||||
${source_path}/pythondeps.toml docs;
|
${source_path}/pythondeps.toml docs;
|
||||||
then
|
then
|
||||||
if test "$docs" = "enabled" ; then
|
if test "$docs" = "enabled" ; then
|
||||||
@ -1320,8 +1316,8 @@ probe_target_compiler() {
|
|||||||
container_cross_cc=${container_cross_prefix}gcc
|
container_cross_cc=${container_cross_prefix}gcc
|
||||||
;;
|
;;
|
||||||
i386)
|
i386)
|
||||||
container_image=fedora-i386-cross
|
container_image=debian-i686-cross
|
||||||
container_cross_prefix=
|
container_cross_prefix=i686-linux-gnu-
|
||||||
;;
|
;;
|
||||||
loongarch64)
|
loongarch64)
|
||||||
container_image=debian-loongarch-cross
|
container_image=debian-loongarch-cross
|
||||||
@ -1404,16 +1400,19 @@ probe_target_compiler() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
try=cross
|
try=cross
|
||||||
case "$target_arch:$cpu" in
|
# For softmmu/roms also look for a bi-endian or multilib-enabled host compiler
|
||||||
aarch64_be:aarch64 | \
|
if [ "${1%softmmu}" != "$1" ] || test "$target_arch" = "$cpu"; then
|
||||||
armeb:arm | \
|
case "$target_arch:$cpu" in
|
||||||
i386:x86_64 | \
|
aarch64_be:aarch64 | \
|
||||||
mips*:mips64 | \
|
armeb:arm | \
|
||||||
ppc*:ppc64 | \
|
i386:x86_64 | \
|
||||||
sparc:sparc64 | \
|
mips*:mips64 | \
|
||||||
"$cpu:$cpu")
|
ppc*:ppc64 | \
|
||||||
try='native cross' ;;
|
sparc:sparc64 | \
|
||||||
esac
|
"$cpu:$cpu")
|
||||||
|
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
|
||||||
@ -1645,6 +1644,7 @@ 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
|
||||||
|
@ -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/qemu_plugin_api.lib
|
lib%$(SO_SUFFIX): %.o win32_linker.o ../../plugins/libqemu_plugin_api.a
|
||||||
$(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
|
||||||
|
@ -401,7 +401,7 @@ virgl_cmd_set_scanout(VuGpu *g,
|
|||||||
|
|
||||||
if (g->use_modifiers) {
|
if (g->use_modifiers) {
|
||||||
/*
|
/*
|
||||||
* The mesage uses all the fields set in dmabuf_scanout plus
|
* The message 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, int signedp)
|
format_dec (long number, char *outbuffer, size_t outsize, int signedp)
|
||||||
{
|
{
|
||||||
last_immediate = number;
|
last_immediate = number;
|
||||||
sprintf (outbuffer, signedp ? "%ld" : "%lu", number);
|
snprintf (outbuffer, outsize, signedp ? "%ld" : "%lu", number);
|
||||||
|
|
||||||
return outbuffer + strlen (outbuffer);
|
return outbuffer + strlen (outbuffer);
|
||||||
}
|
}
|
||||||
@ -1876,6 +1876,12 @@ 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. */
|
||||||
@ -2105,7 +2111,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;
|
||||||
@ -2241,7 +2247,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;
|
||||||
@ -2340,7 +2346,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
|
||||||
@ -2397,7 +2403,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':
|
||||||
@ -2426,11 +2432,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':
|
||||||
@ -2463,7 +2469,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);
|
||||||
}
|
}
|
||||||
@ -2474,7 +2480,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,6 +1968,10 @@ 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];
|
||||||
@ -2826,6 +2830,6 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info)
|
|||||||
return sizeof (insn);
|
return sizeof (insn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(*info->fprintf_func) (info->stream, "#%8x", insn);
|
info->fprintf_func(info->stream, "<unknown>");
|
||||||
return sizeof (insn);
|
return sizeof (insn);
|
||||||
}
|
}
|
||||||
|
@ -236,6 +236,16 @@ 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
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
@ -254,6 +264,11 @@ 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
|
||||||
---------------
|
---------------
|
||||||
@ -514,5 +529,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 becase they fail randomly. If you need
|
compression tests are disabled because they fail randomly. If you need
|
||||||
compression, use multifd compression methods.
|
compression, use multifd compression methods.
|
||||||
|
@ -129,8 +129,9 @@ 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. You should only ever run trusted
|
happily trash your host system. Some semihosting calls (e.g.
|
||||||
code with semihosting enabled.
|
``SYS_READC``) can block execution indefinitely. You should only
|
||||||
|
ever run trusted code with semihosting enabled.
|
||||||
|
|
||||||
Redirection
|
Redirection
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
@ -122,10 +122,78 @@ functioning. These are performed using a few more helper functions:
|
|||||||
indicated by $TMPC.
|
indicated by $TMPC.
|
||||||
|
|
||||||
|
|
||||||
Python virtual environments and the QEMU build system
|
Python virtual environments and the build process
|
||||||
-----------------------------------------------------
|
-------------------------------------------------
|
||||||
|
|
||||||
|
An important step in ``configure`` is to create a Python virtual
|
||||||
|
environment (venv) during the configuration phase. The Python interpreter
|
||||||
|
comes from the ``--python`` command line option, the ``$PYTHON`` variable
|
||||||
|
from the environment, or the system PATH, in this order. The venv resides
|
||||||
|
in the ``pyvenv`` directory in the build tree, and provides consistency
|
||||||
|
in how the build process runs Python code.
|
||||||
|
|
||||||
|
At this stage, ``configure`` also queries the chosen Python interpreter
|
||||||
|
about QEMU's build dependencies. Note that the build process does *not*
|
||||||
|
look for ``meson``, ``sphinx-build`` or ``avocado`` binaries in the PATH;
|
||||||
|
likewise, there are no options such as ``--meson`` or ``--sphinx-build``.
|
||||||
|
This avoids a potential mismatch, where Meson and Sphinx binaries on the
|
||||||
|
PATH might operate in a different Python environment than the one chosen
|
||||||
|
by the user during the build process. On the other hand, it introduces
|
||||||
|
a potential source of confusion where the user installs a dependency but
|
||||||
|
``configure`` is not able to find it. When this happens, the dependency
|
||||||
|
was installed in the ``site-packages`` directory of another interpreter,
|
||||||
|
or with the wrong ``pip`` program.
|
||||||
|
|
||||||
|
If a package is available for the chosen interpreter, ``configure``
|
||||||
|
prepares a small script that invokes it from the venv itself[#distlib]_.
|
||||||
|
If not, ``configure`` can also optionally install dependencies in the
|
||||||
|
virtual environment with ``pip``, either from wheels in ``python/wheels``
|
||||||
|
or by downloading the package with PyPI. Downloading can be disabled with
|
||||||
|
``--disable-download``; and anyway, it only happens when a ``configure``
|
||||||
|
option (currently, only ``--enable-docs``) is explicitly enabled but
|
||||||
|
the dependencies are not present[#pip]_.
|
||||||
|
|
||||||
|
.. [#distlib] The scripts are created based on the package's metadata,
|
||||||
|
specifically the ``console_script`` entry points. This is the
|
||||||
|
same mechanism that ``pip`` uses when installing a package.
|
||||||
|
Currently, in all cases it would be possible to use ``python -m``
|
||||||
|
instead of an entry point script, which makes this approach a
|
||||||
|
bit overkill. On the other hand, creating the scripts is
|
||||||
|
future proof and it makes the contents of the ``pyvenv/bin``
|
||||||
|
directory more informative. Portability is also not an issue,
|
||||||
|
because the Python Packaging Authority provides a package
|
||||||
|
``distlib.scripts`` to perform this task.
|
||||||
|
|
||||||
|
.. [#pip] ``pip`` might also be used when running ``make check-avocado``
|
||||||
|
if downloading is enabled, to ensure that Avocado is
|
||||||
|
available.
|
||||||
|
|
||||||
|
The required versions of the packages are stored in a configuration file
|
||||||
|
``pythondeps.toml``. The format is custom to QEMU, but it is documented
|
||||||
|
at the top of the file itself and it should be easy to understand. The
|
||||||
|
requirements should make it possible to use the version that is packaged
|
||||||
|
that is provided by supported distros.
|
||||||
|
|
||||||
|
When dependencies are downloaded, instead, ``configure`` uses a "known
|
||||||
|
good" version that is also listed in ``pythondeps.toml``. In this
|
||||||
|
scenario, ``pythondeps.toml`` behaves like the "lock file" used by
|
||||||
|
``cargo``, ``poetry`` or other dependency management systems.
|
||||||
|
|
||||||
|
|
||||||
|
Bundled Python packages
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Python packages that are **mandatory** dependencies to build QEMU,
|
||||||
|
but are not available in all supported distros, are bundled with the
|
||||||
|
QEMU sources. Currently this includes Meson (outdated in CentOS 8
|
||||||
|
and derivatives, Ubuntu 20.04 and 22.04, and openSUSE Leap) and tomli
|
||||||
|
(absent in Ubuntu 20.04).
|
||||||
|
|
||||||
|
If you need to update these, please do so by modifying and rerunning
|
||||||
|
``python/scripts/vendor.py``. This script embeds the sha256 hash of
|
||||||
|
package sources and checks it. The pypi.org web site provides an easy
|
||||||
|
way to retrieve the sha256 hash of the sources.
|
||||||
|
|
||||||
TBD
|
|
||||||
|
|
||||||
Stage 2: Meson
|
Stage 2: Meson
|
||||||
==============
|
==============
|
||||||
@ -376,6 +444,15 @@ 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
|
||||||
=============
|
=============
|
||||||
@ -434,6 +511,11 @@ 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.
|
||||||
|
@ -1061,7 +1061,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 doen't understand
|
This combination is not possible as the qemu-5.1 doesn'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 +1214,8 @@ machine types to have the right value::
|
|||||||
...
|
...
|
||||||
};
|
};
|
||||||
|
|
||||||
A device with diferent features on both sides
|
A device with different 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 +1294,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 responsability
|
And you would be able to migrate between them. It is responsibility
|
||||||
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 recomend to use -cpu host for migration. It is
|
Notice that we don't recommend 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=112,entitlement=high \
|
-device z14-s390x-cpu,core-id=12,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": 112,
|
"core-id": 12,
|
||||||
"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": 112,
|
"cpu-index": 12,
|
||||||
"target": "s390x"
|
"target": "s390x"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -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.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)')
|
self.assertRegex(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.assertEquals(first_res, second_res, third_res)
|
self.assertEqual(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,23 +1371,33 @@ 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.
|
||||||
|
|
||||||
GITLAB_CI
|
|
||||||
^^^^^^^^^
|
|
||||||
A number of tests are flagged to not run on the GitLab CI. Usually because
|
|
||||||
they proved to the flaky or there are constraints on the CI environment which
|
|
||||||
would make them fail. If you encounter a similar situation then use that
|
|
||||||
variable as shown on the code snippet below to skip the test:
|
|
||||||
|
|
||||||
.. code::
|
|
||||||
|
|
||||||
@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
|
|
||||||
def test(self):
|
|
||||||
do_something()
|
|
||||||
|
|
||||||
QEMU_TEST_FLAKY_TESTS
|
QEMU_TEST_FLAKY_TESTS
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
Some tests are not working reliably and thus are disabled by default.
|
Some tests are not working reliably and thus are disabled by default.
|
||||||
Set this environment variable to enable them.
|
This includes tests that don't run reliably on GitLab's CI which
|
||||||
|
usually expose real issues that are rarely seen on developer machines
|
||||||
|
due to the constraints of the CI environment. If you encounter a
|
||||||
|
similar situation then raise a bug and then mark the test as shown on
|
||||||
|
the code snippet below:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
# See https://gitlab.com/qemu-project/qemu/-/issues/nnnn
|
||||||
|
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
|
||||||
|
def test(self):
|
||||||
|
do_something()
|
||||||
|
|
||||||
|
You can also add ``:avocado: tags=flaky`` to the test meta-data so
|
||||||
|
only the flaky tests can be run as a group:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
env QEMU_TEST_FLAKY_TESTS=1 ./pyvenv/bin/avocado \
|
||||||
|
run tests/avocado -filter-by-tags=flaky
|
||||||
|
|
||||||
|
Tests should not live in this state forever and should either be fixed
|
||||||
|
or eventually removed.
|
||||||
|
|
||||||
|
|
||||||
Uninstalling Avocado
|
Uninstalling Avocado
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
2
docs/requirements.txt
Normal file
2
docs/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
sphinx==5.3.0
|
||||||
|
sphinx_rtd_theme==1.1.1
|
@ -1,3 +1,5 @@
|
|||||||
|
.. _tpm-device:
|
||||||
|
|
||||||
===============
|
===============
|
||||||
QEMU TPM Device
|
QEMU TPM Device
|
||||||
===============
|
===============
|
||||||
|
@ -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 (Enhacements to pointer authentication)
|
- FEAT_PAuth2 (Enhancements 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,34 +1,39 @@
|
|||||||
XENPVH (``xenpvh``)
|
Xen Device Emulation Backend (``xenpvh``)
|
||||||
=========================================
|
=========================================
|
||||||
This machine creates a IOREQ server to register/connect with Xen Hypervisor.
|
|
||||||
|
|
||||||
When TPM is enabled, this machine also creates a tpm-tis-device at a user input
|
This machine is a little unusual compared to others as QEMU just acts
|
||||||
tpm base address, adds a TPM emulator and connects to a swtpm application
|
as an IOREQ server to register/connect with Xen Hypervisor. Control of
|
||||||
running on host machine via chardev socket. This enables xenpvh to support TPM
|
the VMs themselves is left to the Xen tooling.
|
||||||
functionalities for a guest domain.
|
|
||||||
|
|
||||||
More information about TPM use and installing swtpm linux application can be
|
When TPM is enabled, this machine also creates a tpm-tis-device at a
|
||||||
found at: docs/specs/tpm.rst.
|
user input tpm base address, adds a TPM emulator and connects to a
|
||||||
|
swtpm application running on host machine via chardev socket. This
|
||||||
|
enables xenpvh to support TPM functionalities for a guest domain.
|
||||||
|
|
||||||
|
More information about TPM use and installing swtpm linux application
|
||||||
|
can be found in the :ref:`tpm-device` section.
|
||||||
|
|
||||||
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,6 +68,17 @@ 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
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
@ -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,
|
||||||
* respectivelly
|
* respectively
|
||||||
*/
|
*/
|
||||||
int target_count = 0;
|
int target_count = 0;
|
||||||
CPUState *last_target = NULL;
|
CPUState *last_target = NULL;
|
||||||
|
@ -24,6 +24,7 @@ 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_IO;
|
ret = GDB_SIGNAL_STOP;
|
||||||
break;
|
break;
|
||||||
case RUN_STATE_WATCHDOG:
|
case RUN_STATE_WATCHDOG:
|
||||||
trace_gdbstub_hit_watchdog();
|
trace_gdbstub_hit_watchdog();
|
||||||
|
@ -947,6 +947,7 @@ 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();
|
||||||
@ -964,9 +965,15 @@ 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,
|
||||||
@ -977,6 +984,9 @@ 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);
|
||||||
|
|
||||||
|
@ -169,7 +169,8 @@ 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, &err);
|
object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num,
|
||||||
|
&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,7 +379,8 @@ 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, &err);
|
object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num,
|
||||||
|
&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,7 +44,6 @@ 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);
|
||||||
|
|
||||||
@ -54,8 +53,14 @@ 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,7 +44,6 @@ 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);
|
||||||
|
|
||||||
@ -55,8 +54,14 @@ 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)
|
||||||
|
@ -47,7 +47,6 @@ 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);
|
||||||
|
|
||||||
@ -58,9 +57,14 @@ 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->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
|
mc->valid_cpu_types = valid_cpu_types;
|
||||||
|
|
||||||
/* 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;
|
||||||
|
@ -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", s->cpu_type);
|
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
|
||||||
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,17 +180,12 @@ 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;
|
||||||
device_class_set_props(dc, stm32f100_soc_properties);
|
/* No vmstate or reset required: device has no internal state */
|
||||||
}
|
}
|
||||||
|
|
||||||
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", s->cpu_type);
|
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
|
||||||
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,17 +201,12 @@ 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;
|
||||||
device_class_set_props(dc, stm32f205_soc_properties);
|
/* No vmstate or reset required: device has no internal state */
|
||||||
}
|
}
|
||||||
|
|
||||||
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", s->cpu_type);
|
qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
|
||||||
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,17 +287,11 @@ 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,7 +47,6 @@ 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);
|
||||||
|
|
||||||
@ -58,8 +57,14 @@ 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)
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#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"
|
||||||
@ -189,9 +190,9 @@ struct HDAAudioState {
|
|||||||
bool use_timer;
|
bool use_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int64_t hda_bytes_per_second(HDAAudioStream *st)
|
static inline uint32_t hda_bytes_per_second(HDAAudioStream *st)
|
||||||
{
|
{
|
||||||
return 2LL * st->as.nchannels * st->as.freq;
|
return 2 * (uint32_t)st->as.nchannels * (uint32_t)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)
|
||||||
@ -222,12 +223,18 @@ 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 buft_start = st->buft_start;
|
int64_t uptime = now - 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;
|
||||||
|
|
||||||
int64_t wanted_rpos = hda_bytes_per_second(st) * (now - buft_start)
|
if (uptime <= 0) {
|
||||||
/ NANOSECONDS_PER_SECOND;
|
/* wanted_rpos <= 0 */
|
||||||
|
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) {
|
||||||
@ -286,12 +293,18 @@ 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 buft_start = st->buft_start;
|
int64_t uptime = now - 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;
|
||||||
|
|
||||||
int64_t wanted_wpos = hda_bytes_per_second(st) * (now - buft_start)
|
if (uptime <= 0) {
|
||||||
/ NANOSECONDS_PER_SECOND;
|
/* wanted_wpos <= 0 */
|
||||||
|
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) {
|
||||||
@ -855,10 +868,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_nomixemu;
|
const struct desc_codec *desc = &output_mixemu;
|
||||||
|
|
||||||
if (!a->mixer) {
|
if (!a->mixer) {
|
||||||
desc = &output_mixemu;
|
desc = &output_nomixemu;
|
||||||
}
|
}
|
||||||
|
|
||||||
hda_audio_init(hda, desc, errp);
|
hda_audio_init(hda, desc, errp);
|
||||||
@ -867,10 +880,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_nomixemu;
|
const struct desc_codec *desc = &duplex_mixemu;
|
||||||
|
|
||||||
if (!a->mixer) {
|
if (!a->mixer) {
|
||||||
desc = &duplex_mixemu;
|
desc = &duplex_nomixemu;
|
||||||
}
|
}
|
||||||
|
|
||||||
hda_audio_init(hda, desc, errp);
|
hda_audio_init(hda, desc, errp);
|
||||||
@ -879,10 +892,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 = µ_nomixemu;
|
const struct desc_codec *desc = µ_mixemu;
|
||||||
|
|
||||||
if (!a->mixer) {
|
if (!a->mixer) {
|
||||||
desc = µ_mixemu;
|
desc = µ_nomixemu;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
pci_set_irq(&s->dev, 1);
|
via_isa_set_irq(&s->dev, 0, 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) {
|
||||||
pci_set_irq(&s->dev, 1);
|
via_isa_set_irq(&s->dev, 0, 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) {
|
||||||
pci_set_irq(&s->dev, 0);
|
via_isa_set_irq(&s->dev, 0, 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) {
|
||||||
pci_set_irq(&s->dev, 0);
|
via_isa_set_irq(&s->dev, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -47,12 +47,14 @@ 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,6 +36,7 @@ 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)
|
||||||
@ -68,6 +69,7 @@ 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[]) {
|
||||||
@ -1065,23 +1067,9 @@ 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);
|
||||||
|
|
||||||
vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
|
/* check number of jacks and streams */
|
||||||
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,
|
||||||
@ -1102,7 +1090,22 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AUD_register_card("virtio-sound", &vsnd->card, errp);
|
if (!AUD_register_card("virtio-sound", &vsnd->card, errp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vsnd->vmstate =
|
||||||
|
qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
|
||||||
|
|
||||||
|
vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
|
||||||
|
vsnd->pcm->snd = vsnd;
|
||||||
|
vsnd->pcm->streams =
|
||||||
|
g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams);
|
||||||
|
vsnd->pcm->pcm_params =
|
||||||
|
g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams);
|
||||||
|
|
||||||
|
virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
|
||||||
|
virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1);
|
||||||
|
|
||||||
/* set default params for all streams */
|
/* set default params for all streams */
|
||||||
default_params.features = 0;
|
default_params.features = 0;
|
||||||
@ -1126,18 +1129,23 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
|
|||||||
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 initalize stream params, device responded with %s.",
|
"Can't initialize stream params, device responded with %s.",
|
||||||
print_code(status));
|
print_code(status));
|
||||||
return;
|
goto error_cleanup;
|
||||||
}
|
}
|
||||||
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));
|
||||||
return;
|
goto error_cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
error_cleanup:
|
||||||
|
virtio_snd_unrealize(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void return_tx_buffer(VirtIOSoundPCMStream *stream,
|
static inline void return_tx_buffer(VirtIOSoundPCMStream *stream,
|
||||||
|
@ -233,6 +233,10 @@ 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);
|
||||||
|
|
||||||
|
@ -80,16 +80,39 @@ struct PFlashCFI01 {
|
|||||||
uint16_t ident3;
|
uint16_t ident3;
|
||||||
uint8_t cfi_table[0x52];
|
uint8_t cfi_table[0x52];
|
||||||
uint64_t counter;
|
uint64_t counter;
|
||||||
unsigned int writeblock_size;
|
uint32_t 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,
|
||||||
@ -101,6 +124,10 @@ 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
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -225,34 +252,10 @@ static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset,
|
|||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
|
|
||||||
p = pfl->storage;
|
p = pfl->storage;
|
||||||
switch (width) {
|
if (be) {
|
||||||
case 1:
|
ret = ldn_be_p(p + offset, width);
|
||||||
ret = p[offset];
|
} else {
|
||||||
break;
|
ret = ldn_le_p(p + offset, width);
|
||||||
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;
|
||||||
@ -400,40 +403,61 @@ 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 = pfl->storage;
|
uint8_t *p;
|
||||||
|
|
||||||
trace_pflash_data_write(pfl->name, offset, width, value, pfl->counter);
|
if (pfl->blk_offset != -1) {
|
||||||
switch (width) {
|
/* block write: redirect writes to block update buffer */
|
||||||
case 1:
|
if ((offset < pfl->blk_offset) ||
|
||||||
p[offset] = value;
|
(offset + width > pfl->blk_offset + pfl->writeblock_size)) {
|
||||||
break;
|
pfl->status |= 0x10; /* Programming error */
|
||||||
case 2:
|
return;
|
||||||
if (be) {
|
|
||||||
p[offset] = value >> 8;
|
|
||||||
p[offset + 1] = value;
|
|
||||||
} else {
|
|
||||||
p[offset] = value;
|
|
||||||
p[offset + 1] = value >> 8;
|
|
||||||
}
|
}
|
||||||
break;
|
trace_pflash_data_write_block(pfl->name, offset, width, value,
|
||||||
case 4:
|
pfl->counter);
|
||||||
if (be) {
|
p = pfl->blk_bytes + (offset - pfl->blk_offset);
|
||||||
p[offset] = value >> 24;
|
} else {
|
||||||
p[offset + 1] = value >> 16;
|
/* write directly to storage */
|
||||||
p[offset + 2] = value >> 8;
|
trace_pflash_data_write(pfl->name, offset, width, value);
|
||||||
p[offset + 3] = value;
|
p = pfl->storage + offset;
|
||||||
} 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,
|
||||||
@ -548,9 +572,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) {
|
||||||
@ -581,12 +605,7 @@ 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) {
|
if (!pfl->ro && (pfl->blk_offset != -1)) {
|
||||||
/*
|
|
||||||
* 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 */
|
||||||
@ -595,18 +614,8 @@ 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--;
|
||||||
@ -618,20 +627,17 @@ 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) {
|
if ((cmd == 0xd0) && !(pfl->status & 0x10)) {
|
||||||
/* FIXME this is where we should write out the buffer */
|
pflash_blk_write_flush(pfl);
|
||||||
pfl->wcycle = 0;
|
pfl->wcycle = 0;
|
||||||
pfl->status |= 0x80;
|
pfl->status |= 0x80;
|
||||||
} else {
|
} else {
|
||||||
qemu_log_mask(LOG_UNIMP,
|
pflash_blk_write_abort(pfl);
|
||||||
"%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;
|
||||||
@ -865,6 +871,9 @@ 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)
|
||||||
@ -884,6 +893,8 @@ 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, 0);
|
trace_pflash_data_write(pfl->name, offset, width, value);
|
||||||
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,7 +12,8 @@ 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, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
|
pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x"
|
||||||
|
pflash_data_write_block(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64
|
||||||
pflash_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"
|
||||||
@ -32,7 +33,9 @@ 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(const char *name, uint32_t value) "%s: block write: bytes:0x%x"
|
pflash_write_block_start(const char *name, uint32_t value) "%s: block write start: bytes:0x%x"
|
||||||
|
pflash_write_block_flush(const char *name) "%s: block write flush"
|
||||||
|
pflash_write_block_abort(const char *name) "%s: block write abort"
|
||||||
pflash_write_block_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,7 +326,6 @@ 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;
|
||||||
@ -343,15 +342,14 @@ 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 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vhost_user_blk_disconnect(DeviceState *dev)
|
static void vhost_user_blk_disconnect(DeviceState *dev)
|
||||||
|
@ -91,9 +91,27 @@ static bool xen_block_find_free_vdev(XenBlockDevice *blockdev, Error **errp)
|
|||||||
|
|
||||||
existing_frontends = qemu_xen_xs_directory(xenbus->xsh, XBT_NULL, fe_path,
|
existing_frontends = qemu_xen_xs_directory(xenbus->xsh, XBT_NULL, fe_path,
|
||||||
&nr_existing);
|
&nr_existing);
|
||||||
if (!existing_frontends && errno != ENOENT) {
|
if (!existing_frontends) {
|
||||||
error_setg_errno(errp, errno, "cannot read %s", fe_path);
|
if (errno == ENOENT) {
|
||||||
return false;
|
/*
|
||||||
|
* If the frontend directory doesn't exist because there are
|
||||||
|
* no existing vbd devices, that's fine. Just ensure that we
|
||||||
|
* don't dereference the NULL existing_frontends pointer, by
|
||||||
|
* checking that nr_existing is zero so the loop below is not
|
||||||
|
* entered.
|
||||||
|
*
|
||||||
|
* In fact this is redundant since nr_existing is initialized
|
||||||
|
* to zero, but setting it again here makes it abundantly clear
|
||||||
|
* to Coverity, and to the human reader who doesn't know the
|
||||||
|
* semantics of qemu_xen_xs_directory() off the top of their
|
||||||
|
* head.
|
||||||
|
*/
|
||||||
|
nr_existing = 0;
|
||||||
|
} else {
|
||||||
|
/* All other errors accessing the frontend directory are fatal. */
|
||||||
|
error_setg_errno(errp, errno, "cannot read %s", fe_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(used_devs, 0, sizeof(used_devs));
|
memset(used_devs, 0, sizeof(used_devs));
|
||||||
|
@ -505,7 +505,7 @@ ssize_t load_elf_ram_sym(const char *filename,
|
|||||||
clear_lsb, data_swab, as, load_rom, sym_cb);
|
clear_lsb, data_swab, as, load_rom, sym_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != ELF_LOAD_FAILED) {
|
if (ret > 0) {
|
||||||
debuginfo_report_elf(filename, fd, 0);
|
debuginfo_report_elf(filename, fd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,23 +689,36 @@ static void get_prop_array(Object *obj, Visitor *v, const char *name,
|
|||||||
Property *prop = opaque;
|
Property *prop = opaque;
|
||||||
uint32_t *alenptr = object_field_prop_ptr(obj, prop);
|
uint32_t *alenptr = object_field_prop_ptr(obj, prop);
|
||||||
void **arrayptr = (void *)obj + prop->arrayoffset;
|
void **arrayptr = (void *)obj + prop->arrayoffset;
|
||||||
char *elem = *arrayptr;
|
char *elemptr = *arrayptr;
|
||||||
GenericList *list;
|
ArrayElementList *list = NULL, *elem;
|
||||||
const size_t list_elem_size = sizeof(*list) + prop->arrayfieldsize;
|
ArrayElementList **tail = &list;
|
||||||
|
const size_t size = sizeof(*list);
|
||||||
int i;
|
int i;
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
if (!visit_start_list(v, name, &list, list_elem_size, errp)) {
|
/* At least the string output visitor needs a real list */
|
||||||
|
for (i = 0; i < *alenptr; i++) {
|
||||||
|
elem = g_new0(ArrayElementList, 1);
|
||||||
|
elem->value = elemptr;
|
||||||
|
elemptr += prop->arrayfieldsize;
|
||||||
|
|
||||||
|
*tail = elem;
|
||||||
|
tail = &elem->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < *alenptr; i++) {
|
elem = list;
|
||||||
Property elem_prop = array_elem_prop(obj, prop, name, elem);
|
while (elem) {
|
||||||
|
Property elem_prop = array_elem_prop(obj, prop, name, elem->value);
|
||||||
prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp);
|
prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp);
|
||||||
if (*errp) {
|
if (*errp) {
|
||||||
goto out_obj;
|
goto out_obj;
|
||||||
}
|
}
|
||||||
elem += prop->arrayfieldsize;
|
elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem,
|
||||||
|
size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* visit_check_list() can only fail for input visitors */
|
/* visit_check_list() can only fail for input visitors */
|
||||||
@ -714,6 +727,12 @@ static void get_prop_array(Object *obj, Visitor *v, const char *name,
|
|||||||
|
|
||||||
out_obj:
|
out_obj:
|
||||||
visit_end_list(v, (void**) &list);
|
visit_end_list(v, (void**) &list);
|
||||||
|
|
||||||
|
while (list) {
|
||||||
|
elem = list;
|
||||||
|
list = elem->next;
|
||||||
|
g_free(elem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void default_prop_array(ObjectProperty *op, const Property *prop)
|
static void default_prop_array(ObjectProperty *op, const Property *prop)
|
||||||
|
@ -81,7 +81,7 @@ static uint64_t cxl_cache_mem_read_reg(void *opaque, hwaddr offset,
|
|||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* In line with specifiction limitaions on access sizes, this
|
* In line with specification limitaions on access sizes, this
|
||||||
* routine is not called with other sizes.
|
* routine is not called with other sizes.
|
||||||
*/
|
*/
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
@ -152,7 +152,7 @@ static void cxl_cache_mem_write_reg(void *opaque, hwaddr offset, uint64_t value,
|
|||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* In line with specifiction limitaions on access sizes, this
|
* In line with specification limitaions on access sizes, this
|
||||||
* routine is not called with other sizes.
|
* routine is not called with other sizes.
|
||||||
*/
|
*/
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
|
@ -431,7 +431,7 @@ static CXLRetCode cmd_identify_switch_device(const struct cxl_cmd *cmd,
|
|||||||
out = (struct cxl_fmapi_ident_switch_dev_resp_pl *)payload_out;
|
out = (struct cxl_fmapi_ident_switch_dev_resp_pl *)payload_out;
|
||||||
*out = (struct cxl_fmapi_ident_switch_dev_resp_pl) {
|
*out = (struct cxl_fmapi_ident_switch_dev_resp_pl) {
|
||||||
.num_physical_ports = num_phys_ports + 1, /* 1 USP */
|
.num_physical_ports = num_phys_ports + 1, /* 1 USP */
|
||||||
.num_vcss = 1, /* Not yet support multiple VCS - potentialy tricky */
|
.num_vcss = 1, /* Not yet support multiple VCS - potentially tricky */
|
||||||
.active_vcs_bitmask[0] = 0x1,
|
.active_vcs_bitmask[0] = 0x1,
|
||||||
.total_vppbs = num_phys_ports + 1,
|
.total_vppbs = num_phys_ports + 1,
|
||||||
.bound_vppbs = num_phys_ports + 1,
|
.bound_vppbs = num_phys_ports + 1,
|
||||||
|
@ -33,13 +33,13 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Ref: UG1087 (v1.7) February 8, 2019
|
* Ref: UG1087 (v1.7) February 8, 2019
|
||||||
* https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
|
* https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers
|
||||||
* CSUDMA Module section
|
* CSUDMA Module section
|
||||||
*/
|
*/
|
||||||
REG32(ADDR, 0x0)
|
REG32(ADDR, 0x0)
|
||||||
FIELD(ADDR, ADDR, 2, 30) /* wo */
|
FIELD(ADDR, ADDR, 2, 30) /* wo */
|
||||||
REG32(SIZE, 0x4)
|
REG32(SIZE, 0x4)
|
||||||
FIELD(SIZE, SIZE, 2, 27) /* wo */
|
FIELD(SIZE, SIZE, 2, 27)
|
||||||
FIELD(SIZE, LAST_WORD, 0, 1) /* rw, only exists in SRC */
|
FIELD(SIZE, LAST_WORD, 0, 1) /* rw, only exists in SRC */
|
||||||
REG32(STATUS, 0x8)
|
REG32(STATUS, 0x8)
|
||||||
FIELD(STATUS, DONE_CNT, 13, 3) /* wtc */
|
FIELD(STATUS, DONE_CNT, 13, 3) /* wtc */
|
||||||
@ -335,10 +335,14 @@ static uint64_t addr_pre_write(RegisterInfo *reg, uint64_t val)
|
|||||||
static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val)
|
static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val)
|
||||||
{
|
{
|
||||||
XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
|
XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
|
||||||
|
uint64_t size = val & R_SIZE_SIZE_MASK;
|
||||||
|
|
||||||
if (s->regs[R_SIZE] != 0) {
|
if (s->regs[R_SIZE] != 0) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
if (size || s->is_dst) {
|
||||||
"%s: Starting DMA while already running.\n", __func__);
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: Starting DMA while already running.\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->is_dst) {
|
if (!s->is_dst) {
|
||||||
@ -346,7 +350,7 @@ static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Size is word aligned */
|
/* Size is word aligned */
|
||||||
return val & R_SIZE_SIZE_MASK;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t size_post_read(RegisterInfo *reg, uint64_t val)
|
static uint64_t size_post_read(RegisterInfo *reg, uint64_t val)
|
||||||
|
@ -36,8 +36,8 @@
|
|||||||
|
|
||||||
#define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
|
#define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
|
||||||
|
|
||||||
/* Power button address at &PAGE0->pad[4] */
|
#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
|
||||||
#define HPA_POWER_BUTTON (0x40 + 4 * sizeof(uint32_t))
|
static hwaddr soft_power_reg;
|
||||||
|
|
||||||
#define enable_lasi_lan() 0
|
#define enable_lasi_lan() 0
|
||||||
|
|
||||||
@ -45,7 +45,6 @@ static DeviceState *lasi_dev;
|
|||||||
|
|
||||||
static void hppa_powerdown_req(Notifier *n, void *opaque)
|
static void hppa_powerdown_req(Notifier *n, void *opaque)
|
||||||
{
|
{
|
||||||
hwaddr soft_power_reg = HPA_POWER_BUTTON;
|
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
|
||||||
val = ldl_be_phys(&address_space_memory, soft_power_reg);
|
val = ldl_be_phys(&address_space_memory, soft_power_reg);
|
||||||
@ -221,7 +220,7 @@ static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
|
|||||||
fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
|
fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
|
||||||
g_memdup(mc->name, len), len);
|
g_memdup(mc->name, len), len);
|
||||||
|
|
||||||
val = cpu_to_le64(HPA_POWER_BUTTON);
|
val = cpu_to_le64(soft_power_reg);
|
||||||
fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
|
fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
|
||||||
g_memdup(&val, sizeof(val)), sizeof(val));
|
g_memdup(&val, sizeof(val)), sizeof(val));
|
||||||
|
|
||||||
@ -276,6 +275,7 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
|
|||||||
unsigned int smp_cpus = machine->smp.cpus;
|
unsigned int smp_cpus = machine->smp.cpus;
|
||||||
TranslateFn *translate;
|
TranslateFn *translate;
|
||||||
MemoryRegion *cpu_region;
|
MemoryRegion *cpu_region;
|
||||||
|
uint64_t ram_max;
|
||||||
|
|
||||||
/* Create CPUs. */
|
/* Create CPUs. */
|
||||||
for (unsigned int i = 0; i < smp_cpus; i++) {
|
for (unsigned int i = 0; i < smp_cpus; i++) {
|
||||||
@ -288,10 +288,14 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
|
|||||||
*/
|
*/
|
||||||
if (hppa_is_pa20(&cpu[0]->env)) {
|
if (hppa_is_pa20(&cpu[0]->env)) {
|
||||||
translate = translate_pa20;
|
translate = translate_pa20;
|
||||||
|
ram_max = 0xf0000000; /* 3.75 GB (limited by 32-bit firmware) */
|
||||||
} else {
|
} else {
|
||||||
translate = translate_pa10;
|
translate = translate_pa10;
|
||||||
|
ram_max = 0xf0000000; /* 3.75 GB (32-bit CPU) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
soft_power_reg = translate(NULL, HPA_POWER_BUTTON);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < smp_cpus; i++) {
|
for (unsigned int i = 0; i < smp_cpus; i++) {
|
||||||
g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
|
g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
|
||||||
|
|
||||||
@ -311,9 +315,9 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
|
|||||||
cpu_region);
|
cpu_region);
|
||||||
|
|
||||||
/* Main memory region. */
|
/* Main memory region. */
|
||||||
if (machine->ram_size > 3 * GiB) {
|
if (machine->ram_size > ram_max) {
|
||||||
error_report("RAM size is currently restricted to 3GB");
|
info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB);
|
||||||
exit(EXIT_FAILURE);
|
machine->ram_size = ram_max;
|
||||||
}
|
}
|
||||||
memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
|
memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
|
||||||
|
|
||||||
@ -343,8 +347,10 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
|
|||||||
SysBusDevice *s;
|
SysBusDevice *s;
|
||||||
|
|
||||||
/* SCSI disk setup. */
|
/* SCSI disk setup. */
|
||||||
dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
|
if (drive_get_max_bus(IF_SCSI) >= 0) {
|
||||||
lsi53c8xx_handle_legacy_cmdline(dev);
|
dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
|
||||||
|
lsi53c8xx_handle_legacy_cmdline(dev);
|
||||||
|
}
|
||||||
|
|
||||||
/* Graphics setup. */
|
/* Graphics setup. */
|
||||||
if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
|
if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
|
||||||
@ -357,7 +363,7 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Network setup. */
|
/* Network setup. */
|
||||||
if (enable_lasi_lan()) {
|
if (nd_table[0].used && enable_lasi_lan()) {
|
||||||
lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
|
lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
|
||||||
qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
|
qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
|
||||||
}
|
}
|
||||||
@ -382,7 +388,7 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
|
|||||||
pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_ID], 0x1227); /* Powerbar */
|
pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_ID], 0x1227); /* Powerbar */
|
||||||
|
|
||||||
/* create a second serial PCI card when running Astro */
|
/* create a second serial PCI card when running Astro */
|
||||||
if (!lasi_dev) {
|
if (serial_hd(1) && !lasi_dev) {
|
||||||
pci_dev = pci_new(-1, "pci-serial-4x");
|
pci_dev = pci_new(-1, "pci-serial-4x");
|
||||||
qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(1));
|
qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(1));
|
||||||
qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(2));
|
qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(2));
|
||||||
@ -672,19 +678,18 @@ static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *HP_B160L_machine_valid_cpu_types[] = {
|
|
||||||
TYPE_HPPA_CPU,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data)
|
static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
|
static const char * const valid_cpu_types[] = {
|
||||||
|
TYPE_HPPA_CPU,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
NMIClass *nc = NMI_CLASS(oc);
|
NMIClass *nc = NMI_CLASS(oc);
|
||||||
|
|
||||||
mc->desc = "HP B160L workstation";
|
mc->desc = "HP B160L workstation";
|
||||||
mc->default_cpu_type = TYPE_HPPA_CPU;
|
mc->default_cpu_type = TYPE_HPPA_CPU;
|
||||||
mc->valid_cpu_types = HP_B160L_machine_valid_cpu_types;
|
mc->valid_cpu_types = valid_cpu_types;
|
||||||
mc->init = machine_HP_B160L_init;
|
mc->init = machine_HP_B160L_init;
|
||||||
mc->reset = hppa_machine_reset;
|
mc->reset = hppa_machine_reset;
|
||||||
mc->block_default_type = IF_SCSI;
|
mc->block_default_type = IF_SCSI;
|
||||||
@ -709,19 +714,18 @@ static const TypeInfo HP_B160L_machine_init_typeinfo = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *HP_C3700_machine_valid_cpu_types[] = {
|
|
||||||
TYPE_HPPA64_CPU,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static void HP_C3700_machine_init_class_init(ObjectClass *oc, void *data)
|
static void HP_C3700_machine_init_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
|
static const char * const valid_cpu_types[] = {
|
||||||
|
TYPE_HPPA64_CPU,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
NMIClass *nc = NMI_CLASS(oc);
|
NMIClass *nc = NMI_CLASS(oc);
|
||||||
|
|
||||||
mc->desc = "HP C3700 workstation";
|
mc->desc = "HP C3700 workstation";
|
||||||
mc->default_cpu_type = TYPE_HPPA64_CPU;
|
mc->default_cpu_type = TYPE_HPPA64_CPU;
|
||||||
mc->valid_cpu_types = HP_C3700_machine_valid_cpu_types;
|
mc->valid_cpu_types = valid_cpu_types;
|
||||||
mc->init = machine_HP_C3700_init;
|
mc->init = machine_HP_C3700_init;
|
||||||
mc->reset = hppa_machine_reset;
|
mc->reset = hppa_machine_reset;
|
||||||
mc->block_default_type = IF_SCSI;
|
mc->block_default_type = IF_SCSI;
|
||||||
|
@ -34,5 +34,5 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms)
|
|||||||
|
|
||||||
bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
|
bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
|
||||||
{
|
{
|
||||||
g_assert_not_reached();
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -131,8 +131,12 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version)
|
|||||||
/*
|
/*
|
||||||
* Can we support APIC ID 255 or higher? With KVM, that requires
|
* Can we support APIC ID 255 or higher? With KVM, that requires
|
||||||
* both in-kernel lapic and X2APIC userspace API.
|
* both in-kernel lapic and X2APIC userspace API.
|
||||||
|
*
|
||||||
|
* kvm_enabled() must go first to ensure that kvm_* references are
|
||||||
|
* not emitted for the linker to consume (kvm_enabled() is
|
||||||
|
* a literal `0` in configurations where kvm_* aren't defined)
|
||||||
*/
|
*/
|
||||||
if (x86ms->apic_id_limit > 255 && kvm_enabled() &&
|
if (kvm_enabled() && x86ms->apic_id_limit > 255 &&
|
||||||
(!kvm_irqchip_in_kernel() || !kvm_enable_x2apic())) {
|
(!kvm_irqchip_in_kernel() || !kvm_enable_x2apic())) {
|
||||||
error_report("current -smp configuration requires kernel "
|
error_report("current -smp configuration requires kernel "
|
||||||
"irqchip and X2APIC API support.");
|
"irqchip and X2APIC API support.");
|
||||||
@ -418,8 +422,13 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
|||||||
}
|
}
|
||||||
cpu->thread_id = topo_ids.smt_id;
|
cpu->thread_id = topo_ids.smt_id;
|
||||||
|
|
||||||
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) &&
|
/*
|
||||||
kvm_enabled() && !kvm_hv_vpindex_settable()) {
|
* kvm_enabled() must go first to ensure that kvm_* references are
|
||||||
|
* not emitted for the linker to consume (kvm_enabled() is
|
||||||
|
* a literal `0` in configurations where kvm_* aren't defined)
|
||||||
|
*/
|
||||||
|
if (kvm_enabled() && hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) &&
|
||||||
|
!kvm_hv_vpindex_settable()) {
|
||||||
error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX");
|
error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -623,9 +623,13 @@ static void ahci_init_d2h(AHCIDevice *ad)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For simplicity, do not call ahci_clear_cmd_issue() for this
|
||||||
|
* ahci_write_fis_d2h(). (The reset value for PxCI is 0.)
|
||||||
|
*/
|
||||||
if (ahci_write_fis_d2h(ad, true)) {
|
if (ahci_write_fis_d2h(ad, true)) {
|
||||||
ad->init_d2h_sent = true;
|
ad->init_d2h_sent = true;
|
||||||
/* We're emulating receiving the first Reg H2D Fis from the device;
|
/* We're emulating receiving the first Reg D2H FIS from the device;
|
||||||
* Update the SIG register, but otherwise proceed as normal. */
|
* Update the SIG register, but otherwise proceed as normal. */
|
||||||
pr->sig = ((uint32_t)ide_state->hcyl << 24) |
|
pr->sig = ((uint32_t)ide_state->hcyl << 24) |
|
||||||
(ide_state->lcyl << 16) |
|
(ide_state->lcyl << 16) |
|
||||||
@ -663,6 +667,7 @@ static void ahci_reset_port(AHCIState *s, int port)
|
|||||||
pr->scr_act = 0;
|
pr->scr_act = 0;
|
||||||
pr->tfdata = 0x7F;
|
pr->tfdata = 0x7F;
|
||||||
pr->sig = 0xFFFFFFFF;
|
pr->sig = 0xFFFFFFFF;
|
||||||
|
pr->cmd_issue = 0;
|
||||||
d->busy_slot = -1;
|
d->busy_slot = -1;
|
||||||
d->init_d2h_sent = false;
|
d->init_d2h_sent = false;
|
||||||
|
|
||||||
@ -1242,10 +1247,30 @@ static void handle_reg_h2d_fis(AHCIState *s, int port,
|
|||||||
case STATE_RUN:
|
case STATE_RUN:
|
||||||
if (cmd_fis[15] & ATA_SRST) {
|
if (cmd_fis[15] & ATA_SRST) {
|
||||||
s->dev[port].port_state = STATE_RESET;
|
s->dev[port].port_state = STATE_RESET;
|
||||||
|
/*
|
||||||
|
* When setting SRST in the first H2D FIS in the reset sequence,
|
||||||
|
* the device does not send a D2H FIS. Host software thus has to
|
||||||
|
* set the "Clear Busy upon R_OK" bit such that PxCI (and BUSY)
|
||||||
|
* gets cleared. See AHCI 1.3.1, section 10.4.1 Software Reset.
|
||||||
|
*/
|
||||||
|
if (opts & AHCI_CMD_CLR_BUSY) {
|
||||||
|
ahci_clear_cmd_issue(ad, slot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATE_RESET:
|
case STATE_RESET:
|
||||||
if (!(cmd_fis[15] & ATA_SRST)) {
|
if (!(cmd_fis[15] & ATA_SRST)) {
|
||||||
|
/*
|
||||||
|
* When clearing SRST in the second H2D FIS in the reset
|
||||||
|
* sequence, the device will execute diagnostics. When this is
|
||||||
|
* done, the device will send a D2H FIS with the good status.
|
||||||
|
* See SATA 3.5a Gold, section 11.4 Software reset protocol.
|
||||||
|
*
|
||||||
|
* This D2H FIS is the first D2H FIS received from the device,
|
||||||
|
* and is received regardless if the reset was performed by a
|
||||||
|
* COMRESET or by setting and clearing the SRST bit. Therefore,
|
||||||
|
* the logic for this is found in ahci_init_d2h() and not here.
|
||||||
|
*/
|
||||||
ahci_reset_port(s, port);
|
ahci_reset_port(s, port);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -81,6 +81,18 @@ static const char *IDE_DMA_CMD_str(enum ide_dma_cmd enval)
|
|||||||
|
|
||||||
static void ide_dummy_transfer_stop(IDEState *s);
|
static void ide_dummy_transfer_stop(IDEState *s);
|
||||||
|
|
||||||
|
const MemoryRegionPortio ide_portio_list[] = {
|
||||||
|
{ 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write },
|
||||||
|
{ 0, 1, 2, .read = ide_data_readw, .write = ide_data_writew },
|
||||||
|
{ 0, 1, 4, .read = ide_data_readl, .write = ide_data_writel },
|
||||||
|
PORTIO_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const MemoryRegionPortio ide_portio2_list[] = {
|
||||||
|
{ 0, 1, 1, .read = ide_status_read, .write = ide_ctrl_write },
|
||||||
|
PORTIO_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void padstr(char *str, const char *src, int len)
|
static void padstr(char *str, const char *src, int len)
|
||||||
{
|
{
|
||||||
int i, v;
|
int i, v;
|
||||||
|
@ -28,18 +28,6 @@
|
|||||||
#include "hw/ide/internal.h"
|
#include "hw/ide/internal.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
static const MemoryRegionPortio ide_portio_list[] = {
|
|
||||||
{ 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write },
|
|
||||||
{ 0, 1, 2, .read = ide_data_readw, .write = ide_data_writew },
|
|
||||||
{ 0, 1, 4, .read = ide_data_readl, .write = ide_data_writel },
|
|
||||||
PORTIO_END_OF_LIST(),
|
|
||||||
};
|
|
||||||
|
|
||||||
static const MemoryRegionPortio ide_portio2_list[] = {
|
|
||||||
{ 0, 1, 1, .read = ide_status_read, .write = ide_ctrl_write },
|
|
||||||
PORTIO_END_OF_LIST(),
|
|
||||||
};
|
|
||||||
|
|
||||||
int ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
|
int ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
84
hw/ide/pci.c
84
hw/ide/pci.c
@ -104,6 +104,90 @@ const MemoryRegionOps pci_ide_data_le_ops = {
|
|||||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void pci_ide_update_mode(PCIIDEState *s)
|
||||||
|
{
|
||||||
|
PCIDevice *d = PCI_DEVICE(s);
|
||||||
|
uint8_t mode = d->config[PCI_CLASS_PROG];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function only configures the BARs/ioports for now: PCI IDE
|
||||||
|
* controllers must manage their own IRQ routing
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (mode & 0xf) {
|
||||||
|
case 0xa:
|
||||||
|
/* Both channels legacy mode */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: according to the PCI IDE specification the BARs should
|
||||||
|
* be completely disabled, however Linux for the pegasos2
|
||||||
|
* machine stil accesses the BAR addresses after switching to legacy
|
||||||
|
* mode. Hence we leave them active for now.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Clear interrupt pin */
|
||||||
|
pci_config_set_interrupt_pin(d->config, 0);
|
||||||
|
|
||||||
|
/* Add legacy IDE ports */
|
||||||
|
if (!s->bus[0].portio_list.owner) {
|
||||||
|
portio_list_init(&s->bus[0].portio_list, OBJECT(d),
|
||||||
|
ide_portio_list, &s->bus[0], "ide");
|
||||||
|
portio_list_add(&s->bus[0].portio_list,
|
||||||
|
pci_address_space_io(d), 0x1f0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s->bus[0].portio2_list.owner) {
|
||||||
|
portio_list_init(&s->bus[0].portio2_list, OBJECT(d),
|
||||||
|
ide_portio2_list, &s->bus[0], "ide");
|
||||||
|
portio_list_add(&s->bus[0].portio2_list,
|
||||||
|
pci_address_space_io(d), 0x3f6);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s->bus[1].portio_list.owner) {
|
||||||
|
portio_list_init(&s->bus[1].portio_list, OBJECT(d),
|
||||||
|
ide_portio_list, &s->bus[1], "ide");
|
||||||
|
portio_list_add(&s->bus[1].portio_list,
|
||||||
|
pci_address_space_io(d), 0x170);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s->bus[1].portio2_list.owner) {
|
||||||
|
portio_list_init(&s->bus[1].portio2_list, OBJECT(d),
|
||||||
|
ide_portio2_list, &s->bus[1], "ide");
|
||||||
|
portio_list_add(&s->bus[1].portio2_list,
|
||||||
|
pci_address_space_io(d), 0x376);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xf:
|
||||||
|
/* Both channels native mode */
|
||||||
|
|
||||||
|
/* Set interrupt pin */
|
||||||
|
pci_config_set_interrupt_pin(d->config, 1);
|
||||||
|
|
||||||
|
/* Remove legacy IDE ports */
|
||||||
|
if (s->bus[0].portio_list.owner) {
|
||||||
|
portio_list_del(&s->bus[0].portio_list);
|
||||||
|
portio_list_destroy(&s->bus[0].portio_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->bus[0].portio2_list.owner) {
|
||||||
|
portio_list_del(&s->bus[0].portio2_list);
|
||||||
|
portio_list_destroy(&s->bus[0].portio2_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->bus[1].portio_list.owner) {
|
||||||
|
portio_list_del(&s->bus[1].portio_list);
|
||||||
|
portio_list_destroy(&s->bus[1].portio_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->bus[1].portio2_list.owner) {
|
||||||
|
portio_list_del(&s->bus[1].portio2_list);
|
||||||
|
portio_list_destroy(&s->bus[1].portio2_list);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static IDEState *bmdma_active_if(BMDMAState *bmdma)
|
static IDEState *bmdma_active_if(BMDMAState *bmdma)
|
||||||
{
|
{
|
||||||
assert(bmdma->bus->retry_unit != (uint8_t)-1);
|
assert(bmdma->bus->retry_unit != (uint8_t)-1);
|
||||||
|
49
hw/ide/via.c
49
hw/ide/via.c
@ -28,6 +28,7 @@
|
|||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
|
#include "qemu/range.h"
|
||||||
#include "sysemu/dma.h"
|
#include "sysemu/dma.h"
|
||||||
#include "hw/isa/vt82c686.h"
|
#include "hw/isa/vt82c686.h"
|
||||||
#include "hw/ide/pci.h"
|
#include "hw/ide/pci.h"
|
||||||
@ -128,16 +129,14 @@ static void via_ide_reset(DeviceState *dev)
|
|||||||
ide_bus_reset(&d->bus[i]);
|
ide_bus_reset(&d->bus[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy mode */
|
||||||
|
pci_ide_update_mode(d);
|
||||||
|
|
||||||
pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_WAIT);
|
pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_WAIT);
|
||||||
pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK |
|
pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK |
|
||||||
PCI_STATUS_DEVSEL_MEDIUM);
|
PCI_STATUS_DEVSEL_MEDIUM);
|
||||||
|
|
||||||
pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x000001f0);
|
pci_set_byte(pci_conf + PCI_INTERRUPT_LINE, 0xe);
|
||||||
pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x000003f4);
|
|
||||||
pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x00000170);
|
|
||||||
pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x00000374);
|
|
||||||
pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0x0000cc01); /* BMIBA: 20-23h */
|
|
||||||
pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x0000010e);
|
|
||||||
|
|
||||||
/* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/
|
/* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/
|
||||||
pci_set_long(pci_conf + 0x40, 0x0a090600);
|
pci_set_long(pci_conf + 0x40, 0x0a090600);
|
||||||
@ -159,6 +158,41 @@ static void via_ide_reset(DeviceState *dev)
|
|||||||
pci_set_long(pci_conf + 0xc0, 0x00020001);
|
pci_set_long(pci_conf + 0xc0, 0x00020001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t via_ide_cfg_read(PCIDevice *pd, uint32_t addr, int len)
|
||||||
|
{
|
||||||
|
uint32_t val = pci_default_read_config(pd, addr, len);
|
||||||
|
uint8_t mode = pd->config[PCI_CLASS_PROG];
|
||||||
|
|
||||||
|
if ((mode & 0xf) == 0xa) {
|
||||||
|
if (ranges_overlap(addr, len, PCI_BASE_ADDRESS_0, 16)) {
|
||||||
|
/* BARs 0-3 always read back zero in legacy mode */
|
||||||
|
for (int i = addr; i < addr + len; i++) {
|
||||||
|
if (i >= PCI_BASE_ADDRESS_0 && i < PCI_BASE_ADDRESS_0 + 16) {
|
||||||
|
val &= ~(0xffULL << ((i - addr) << 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (addr == PCI_BASE_ADDRESS_4 && val == PCI_BASE_ADDRESS_SPACE_IO) {
|
||||||
|
/* BAR4 default value if unset */
|
||||||
|
val = 0xcc00 | PCI_BASE_ADDRESS_SPACE_IO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void via_ide_cfg_write(PCIDevice *pd, uint32_t addr,
|
||||||
|
uint32_t val, int len)
|
||||||
|
{
|
||||||
|
PCIIDEState *d = PCI_IDE(pd);
|
||||||
|
|
||||||
|
pci_default_write_config(pd, addr, val, len);
|
||||||
|
|
||||||
|
if (range_covers_byte(addr, len, PCI_CLASS_PROG)) {
|
||||||
|
pci_ide_update_mode(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void via_ide_realize(PCIDevice *dev, Error **errp)
|
static void via_ide_realize(PCIDevice *dev, Error **errp)
|
||||||
{
|
{
|
||||||
PCIIDEState *d = PCI_IDE(dev);
|
PCIIDEState *d = PCI_IDE(dev);
|
||||||
@ -166,7 +200,6 @@ static void via_ide_realize(PCIDevice *dev, Error **errp)
|
|||||||
uint8_t *pci_conf = dev->config;
|
uint8_t *pci_conf = dev->config;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy mode */
|
|
||||||
pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
|
pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
|
||||||
dev->wmask[PCI_INTERRUPT_LINE] = 0;
|
dev->wmask[PCI_INTERRUPT_LINE] = 0;
|
||||||
dev->wmask[PCI_CLASS_PROG] = 5;
|
dev->wmask[PCI_CLASS_PROG] = 5;
|
||||||
@ -221,6 +254,8 @@ static void via_ide_class_init(ObjectClass *klass, void *data)
|
|||||||
/* Reason: only works as function of VIA southbridge */
|
/* Reason: only works as function of VIA southbridge */
|
||||||
dc->user_creatable = false;
|
dc->user_creatable = false;
|
||||||
|
|
||||||
|
k->config_read = via_ide_cfg_read;
|
||||||
|
k->config_write = via_ide_cfg_write;
|
||||||
k->realize = via_ide_realize;
|
k->realize = via_ide_realize;
|
||||||
k->exit = via_ide_exitfn;
|
k->exit = via_ide_exitfn;
|
||||||
k->vendor_id = PCI_VENDOR_ID_VIA;
|
k->vendor_id = PCI_VENDOR_ID_VIA;
|
||||||
|
@ -63,6 +63,13 @@ static void stellaris_gamepad_realize(DeviceState *dev, Error **errp)
|
|||||||
qemu_input_handler_register(dev, &stellaris_gamepad_handler);
|
qemu_input_handler_register(dev, &stellaris_gamepad_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stellaris_gamepad_finalize(Object *obj)
|
||||||
|
{
|
||||||
|
StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
|
||||||
|
|
||||||
|
g_free(s->keycodes);
|
||||||
|
}
|
||||||
|
|
||||||
static void stellaris_gamepad_reset_enter(Object *obj, ResetType type)
|
static void stellaris_gamepad_reset_enter(Object *obj, ResetType type)
|
||||||
{
|
{
|
||||||
StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
|
StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
|
||||||
@ -92,6 +99,7 @@ static const TypeInfo stellaris_gamepad_info[] = {
|
|||||||
.name = TYPE_STELLARIS_GAMEPAD,
|
.name = TYPE_STELLARIS_GAMEPAD,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
.instance_size = sizeof(StellarisGamepad),
|
.instance_size = sizeof(StellarisGamepad),
|
||||||
|
.instance_finalize = stellaris_gamepad_finalize,
|
||||||
.class_init = stellaris_gamepad_class_init,
|
.class_init = stellaris_gamepad_class_init,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -146,7 +146,7 @@ static uint32_t icv_fullprio_mask(GICv3CPUState *cs)
|
|||||||
* with the group priority, whose mask depends on the value of VBPR
|
* with the group priority, whose mask depends on the value of VBPR
|
||||||
* for the interrupt group.)
|
* for the interrupt group.)
|
||||||
*/
|
*/
|
||||||
return ~0U << (8 - cs->vpribits);
|
return (~0U << (8 - cs->vpribits)) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ich_highest_active_virt_prio(GICv3CPUState *cs)
|
static int ich_highest_active_virt_prio(GICv3CPUState *cs)
|
||||||
@ -803,7 +803,7 @@ static uint32_t icc_fullprio_mask(GICv3CPUState *cs)
|
|||||||
* with the group priority, whose mask depends on the value of BPR
|
* with the group priority, whose mask depends on the value of BPR
|
||||||
* for the interrupt group.)
|
* for the interrupt group.)
|
||||||
*/
|
*/
|
||||||
return ~0U << (8 - cs->pribits);
|
return (~0U << (8 - cs->pribits)) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int icc_min_bpr(GICv3CPUState *cs)
|
static inline int icc_min_bpr(GICv3CPUState *cs)
|
||||||
@ -1434,16 +1434,25 @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||||||
idx = icv_find_active(cs, irq);
|
idx = icv_find_active(cs, irq);
|
||||||
|
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
/* No valid list register corresponding to EOI ID */
|
/*
|
||||||
icv_increment_eoicount(cs);
|
* No valid list register corresponding to EOI ID; if this is a vLPI
|
||||||
|
* not in the list regs then do nothing; otherwise increment EOI count
|
||||||
|
*/
|
||||||
|
if (irq < GICV3_LPI_INTID_START) {
|
||||||
|
icv_increment_eoicount(cs);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uint64_t lr = cs->ich_lr_el2[idx];
|
uint64_t lr = cs->ich_lr_el2[idx];
|
||||||
int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
|
int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
|
||||||
int lr_gprio = ich_lr_prio(lr) & icv_gprio_mask(cs, grp);
|
int lr_gprio = ich_lr_prio(lr) & icv_gprio_mask(cs, grp);
|
||||||
|
|
||||||
if (thisgrp == grp && lr_gprio == dropprio) {
|
if (thisgrp == grp && lr_gprio == dropprio) {
|
||||||
if (!icv_eoi_split(env, cs)) {
|
if (!icv_eoi_split(env, cs) || irq >= GICV3_LPI_INTID_START) {
|
||||||
/* Priority drop and deactivate not split: deactivate irq now */
|
/*
|
||||||
|
* Priority drop and deactivate not split: deactivate irq now.
|
||||||
|
* LPIs always get their active state cleared immediately
|
||||||
|
* because no separate deactivate is expected.
|
||||||
|
*/
|
||||||
icv_deactivate_irq(cs, idx);
|
icv_deactivate_irq(cs, idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -549,6 +549,7 @@ struct ViaISAState {
|
|||||||
PCIDevice dev;
|
PCIDevice dev;
|
||||||
qemu_irq cpu_intr;
|
qemu_irq cpu_intr;
|
||||||
qemu_irq *isa_irqs_in;
|
qemu_irq *isa_irqs_in;
|
||||||
|
uint16_t irq_state[ISA_NUM_IRQS];
|
||||||
ViaSuperIOState via_sio;
|
ViaSuperIOState via_sio;
|
||||||
MC146818RtcState rtc;
|
MC146818RtcState rtc;
|
||||||
PCIIDEState ide;
|
PCIIDEState ide;
|
||||||
@ -592,15 +593,9 @@ static const TypeInfo via_isa_info = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void via_isa_request_i8259_irq(void *opaque, int irq, int level)
|
static int via_isa_get_pci_irq(const ViaISAState *s, int pin)
|
||||||
{
|
{
|
||||||
ViaISAState *s = opaque;
|
switch (pin) {
|
||||||
qemu_set_irq(s->cpu_intr, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int via_isa_get_pci_irq(const ViaISAState *s, int irq_num)
|
|
||||||
{
|
|
||||||
switch (irq_num) {
|
|
||||||
case 0:
|
case 0:
|
||||||
return s->dev.config[0x55] >> 4;
|
return s->dev.config[0x55] >> 4;
|
||||||
case 1:
|
case 1:
|
||||||
@ -613,29 +608,60 @@ static int via_isa_get_pci_irq(const ViaISAState *s, int irq_num)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void via_isa_set_pci_irq(void *opaque, int irq_num, int level)
|
void via_isa_set_irq(PCIDevice *d, int pin, int level)
|
||||||
{
|
{
|
||||||
ViaISAState *s = opaque;
|
ViaISAState *s = VIA_ISA(pci_get_function_0(d));
|
||||||
PCIBus *bus = pci_get_bus(&s->dev);
|
uint8_t irq = d->config[PCI_INTERRUPT_LINE], max_irq = 15;
|
||||||
int i, pic_level, pic_irq = via_isa_get_pci_irq(s, irq_num);
|
int f = PCI_FUNC(d->devfn);
|
||||||
|
uint16_t mask = BIT(f);
|
||||||
|
|
||||||
/* IRQ 0: disabled, IRQ 2,8,13: reserved */
|
switch (f) {
|
||||||
if (!pic_irq) {
|
case 0: /* PIRQ/PINT inputs */
|
||||||
|
irq = via_isa_get_pci_irq(s, pin);
|
||||||
|
f = 8 + pin; /* Use function 8-11 for PCI interrupt inputs */
|
||||||
|
break;
|
||||||
|
case 2: /* USB ports 0-1 */
|
||||||
|
case 3: /* USB ports 2-3 */
|
||||||
|
case 5: /* AC97 audio */
|
||||||
|
max_irq = 14;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep track of the state of all sources */
|
||||||
|
if (level) {
|
||||||
|
s->irq_state[0] |= mask;
|
||||||
|
} else {
|
||||||
|
s->irq_state[0] &= ~mask;
|
||||||
|
}
|
||||||
|
if (irq == 0 || irq == 0xff) {
|
||||||
|
return; /* disabled */
|
||||||
|
}
|
||||||
|
if (unlikely(irq > max_irq || irq == 2)) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "Invalid ISA IRQ routing %d for %d",
|
||||||
|
irq, f);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (unlikely(pic_irq == 2 || pic_irq == 8 || pic_irq == 13)) {
|
/* Record source state at mapped IRQ */
|
||||||
qemu_log_mask(LOG_GUEST_ERROR, "Invalid ISA IRQ routing");
|
if (level) {
|
||||||
|
s->irq_state[irq] |= mask;
|
||||||
|
} else {
|
||||||
|
s->irq_state[irq] &= ~mask;
|
||||||
}
|
}
|
||||||
|
/* Make sure there are no stuck bits if mapping has changed */
|
||||||
|
s->irq_state[irq] &= s->irq_state[0];
|
||||||
|
/* ISA IRQ level is the OR of all sources routed to it */
|
||||||
|
qemu_set_irq(s->isa_irqs_in[irq], !!s->irq_state[irq]);
|
||||||
|
}
|
||||||
|
|
||||||
/* The pic level is the logical OR of all the PCI irqs mapped to it. */
|
static void via_isa_pirq(void *opaque, int pin, int level)
|
||||||
pic_level = 0;
|
{
|
||||||
for (i = 0; i < PCI_NUM_PINS; i++) {
|
via_isa_set_irq(opaque, pin, level);
|
||||||
if (pic_irq == via_isa_get_pci_irq(s, i)) {
|
}
|
||||||
pic_level |= pci_bus_get_irq_level(bus, i);
|
|
||||||
}
|
static void via_isa_request_i8259_irq(void *opaque, int irq, int level)
|
||||||
}
|
{
|
||||||
/* Now we change the pic irq level according to the via irq mappings. */
|
ViaISAState *s = opaque;
|
||||||
qemu_set_irq(s->isa_irqs_in[pic_irq], pic_level);
|
qemu_set_irq(s->cpu_intr, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void via_isa_realize(PCIDevice *d, Error **errp)
|
static void via_isa_realize(PCIDevice *d, Error **errp)
|
||||||
@ -648,6 +674,7 @@ static void via_isa_realize(PCIDevice *d, Error **errp)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
qdev_init_gpio_out(dev, &s->cpu_intr, 1);
|
qdev_init_gpio_out(dev, &s->cpu_intr, 1);
|
||||||
|
qdev_init_gpio_in_named(dev, via_isa_pirq, "pirq", PCI_NUM_PINS);
|
||||||
isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1);
|
isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1);
|
||||||
isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(d),
|
isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(d),
|
||||||
errp);
|
errp);
|
||||||
@ -661,8 +688,6 @@ static void via_isa_realize(PCIDevice *d, Error **errp)
|
|||||||
i8254_pit_init(isa_bus, 0x40, 0, NULL);
|
i8254_pit_init(isa_bus, 0x40, 0, NULL);
|
||||||
i8257_dma_init(isa_bus, 0);
|
i8257_dma_init(isa_bus, 0);
|
||||||
|
|
||||||
qdev_init_gpio_in_named(dev, via_isa_set_pci_irq, "pirq", PCI_NUM_PINS);
|
|
||||||
|
|
||||||
/* RTC */
|
/* RTC */
|
||||||
qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000);
|
qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000);
|
||||||
if (!qdev_realize(DEVICE(&s->rtc), BUS(isa_bus), errp)) {
|
if (!qdev_realize(DEVICE(&s->rtc), BUS(isa_bus), errp)) {
|
||||||
|
@ -726,19 +726,18 @@ static GlobalProperty hw_compat_q800[] = {
|
|||||||
};
|
};
|
||||||
static const size_t hw_compat_q800_len = G_N_ELEMENTS(hw_compat_q800);
|
static const size_t hw_compat_q800_len = G_N_ELEMENTS(hw_compat_q800);
|
||||||
|
|
||||||
static const char *q800_machine_valid_cpu_types[] = {
|
|
||||||
M68K_CPU_TYPE_NAME("m68040"),
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static void q800_machine_class_init(ObjectClass *oc, void *data)
|
static void q800_machine_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
|
static const char * const valid_cpu_types[] = {
|
||||||
|
M68K_CPU_TYPE_NAME("m68040"),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
|
||||||
mc->desc = "Macintosh Quadra 800";
|
mc->desc = "Macintosh Quadra 800";
|
||||||
mc->init = q800_machine_init;
|
mc->init = q800_machine_init;
|
||||||
mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
|
mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
|
||||||
mc->valid_cpu_types = q800_machine_valid_cpu_types;
|
mc->valid_cpu_types = valid_cpu_types;
|
||||||
mc->max_cpus = 1;
|
mc->max_cpus = 1;
|
||||||
mc->block_default_type = IF_SCSI;
|
mc->block_default_type = IF_SCSI;
|
||||||
mc->default_ram_id = "m68k_mac.ram";
|
mc->default_ram_id = "m68k_mac.ram";
|
||||||
|
@ -29,7 +29,7 @@ static bool memory_device_is_empty(const MemoryDeviceState *md)
|
|||||||
/* dropping const here is fine as we don't touch the memory region */
|
/* dropping const here is fine as we don't touch the memory region */
|
||||||
mr = mdc->get_memory_region((MemoryDeviceState *)md, &local_err);
|
mr = mdc->get_memory_region((MemoryDeviceState *)md, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
/* Not empty, we'll report errors later when ontaining the MR again. */
|
/* Not empty, we'll report errors later when containing the MR again. */
|
||||||
error_free(local_err);
|
error_free(local_err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ static void edu_check_range(uint64_t addr, uint64_t size1, uint64_t start,
|
|||||||
uint64_t end2 = start + size2;
|
uint64_t end2 = start + size2;
|
||||||
|
|
||||||
if (within(addr, start, end2) &&
|
if (within(addr, start, end2) &&
|
||||||
end1 > addr && within(end1, start, end2)) {
|
end1 > addr && end1 <= end2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,6 +329,13 @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
|
|||||||
s->oscclk = g_new0(uint32_t, s->num_oscclk);
|
s->oscclk = g_new0(uint32_t, s->num_oscclk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mps2_scc_finalize(Object *obj)
|
||||||
|
{
|
||||||
|
MPS2SCC *s = MPS2_SCC(obj);
|
||||||
|
|
||||||
|
g_free(s->oscclk_reset);
|
||||||
|
}
|
||||||
|
|
||||||
static const VMStateDescription mps2_scc_vmstate = {
|
static const VMStateDescription mps2_scc_vmstate = {
|
||||||
.name = "mps2-scc",
|
.name = "mps2-scc",
|
||||||
.version_id = 3,
|
.version_id = 3,
|
||||||
@ -385,6 +392,7 @@ static const TypeInfo mps2_scc_info = {
|
|||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
.instance_size = sizeof(MPS2SCC),
|
.instance_size = sizeof(MPS2SCC),
|
||||||
.instance_init = mps2_scc_init,
|
.instance_init = mps2_scc_init,
|
||||||
|
.instance_finalize = mps2_scc_finalize,
|
||||||
.class_init = mps2_scc_class_init,
|
.class_init = mps2_scc_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -824,7 +824,8 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
qemu_macaddr_default_if_unset(&s->conf.macaddr);
|
qemu_macaddr_default_if_unset(&s->conf.macaddr);
|
||||||
s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf,
|
s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf,
|
||||||
object_get_typename(OBJECT(dev)), dev->id, s);
|
object_get_typename(OBJECT(dev)), dev->id,
|
||||||
|
&dev->mem_reentrancy_guard, s);
|
||||||
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
|
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +453,8 @@ static void aw_emac_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
qemu_macaddr_default_if_unset(&s->conf.macaddr);
|
qemu_macaddr_default_if_unset(&s->conf.macaddr);
|
||||||
s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf,
|
s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf,
|
||||||
object_get_typename(OBJECT(dev)), dev->id, s);
|
object_get_typename(OBJECT(dev)), dev->id,
|
||||||
|
&dev->mem_reentrancy_guard, s);
|
||||||
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
|
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
|
||||||
|
|
||||||
fifo8_create(&s->rx_fifo, RX_FIFO_SIZE);
|
fifo8_create(&s->rx_fifo, RX_FIFO_SIZE);
|
||||||
|
@ -199,8 +199,8 @@ REG32(PHYMNTNC, 0x34) /* Phy Maintenance reg */
|
|||||||
FIELD(PHYMNTNC, PHY_ADDR, 23, 5)
|
FIELD(PHYMNTNC, PHY_ADDR, 23, 5)
|
||||||
FIELD(PHYMNTNC, OP, 28, 2)
|
FIELD(PHYMNTNC, OP, 28, 2)
|
||||||
FIELD(PHYMNTNC, ST, 30, 2)
|
FIELD(PHYMNTNC, ST, 30, 2)
|
||||||
#define MDIO_OP_READ 0x3
|
#define MDIO_OP_READ 0x2
|
||||||
#define MDIO_OP_WRITE 0x2
|
#define MDIO_OP_WRITE 0x1
|
||||||
|
|
||||||
REG32(RXPAUSE, 0x38) /* RX Pause Time reg */
|
REG32(RXPAUSE, 0x38) /* RX Pause Time reg */
|
||||||
REG32(TXPAUSE, 0x3c) /* TX Pause Time reg */
|
REG32(TXPAUSE, 0x3c) /* TX Pause Time reg */
|
||||||
@ -225,8 +225,8 @@ REG32(WOLAN, 0xb8) /* Wake on LAN reg */
|
|||||||
REG32(IPGSTRETCH, 0xbc) /* IPG Stretch reg */
|
REG32(IPGSTRETCH, 0xbc) /* IPG Stretch reg */
|
||||||
REG32(SVLAN, 0xc0) /* Stacked VLAN reg */
|
REG32(SVLAN, 0xc0) /* Stacked VLAN reg */
|
||||||
REG32(MODID, 0xfc) /* Module ID reg */
|
REG32(MODID, 0xfc) /* Module ID reg */
|
||||||
REG32(OCTTXLO, 0x100) /* Octects transmitted Low reg */
|
REG32(OCTTXLO, 0x100) /* Octets transmitted Low reg */
|
||||||
REG32(OCTTXHI, 0x104) /* Octects transmitted High reg */
|
REG32(OCTTXHI, 0x104) /* Octets transmitted High reg */
|
||||||
REG32(TXCNT, 0x108) /* Error-free Frames transmitted */
|
REG32(TXCNT, 0x108) /* Error-free Frames transmitted */
|
||||||
REG32(TXBCNT, 0x10c) /* Error-free Broadcast Frames */
|
REG32(TXBCNT, 0x10c) /* Error-free Broadcast Frames */
|
||||||
REG32(TXMCNT, 0x110) /* Error-free Multicast Frame */
|
REG32(TXMCNT, 0x110) /* Error-free Multicast Frame */
|
||||||
@ -245,8 +245,8 @@ REG32(EXCESSCOLLCNT, 0x140) /* Excessive Collision Frames */
|
|||||||
REG32(LATECOLLCNT, 0x144) /* Late Collision Frames */
|
REG32(LATECOLLCNT, 0x144) /* Late Collision Frames */
|
||||||
REG32(DEFERTXCNT, 0x148) /* Deferred Transmission Frames */
|
REG32(DEFERTXCNT, 0x148) /* Deferred Transmission Frames */
|
||||||
REG32(CSENSECNT, 0x14c) /* Carrier Sense Error Counter */
|
REG32(CSENSECNT, 0x14c) /* Carrier Sense Error Counter */
|
||||||
REG32(OCTRXLO, 0x150) /* Octects Received register Low */
|
REG32(OCTRXLO, 0x150) /* Octets Received register Low */
|
||||||
REG32(OCTRXHI, 0x154) /* Octects Received register High */
|
REG32(OCTRXHI, 0x154) /* Octets Received register High */
|
||||||
REG32(RXCNT, 0x158) /* Error-free Frames Received */
|
REG32(RXCNT, 0x158) /* Error-free Frames Received */
|
||||||
REG32(RXBROADCNT, 0x15c) /* Error-free Broadcast Frames RX */
|
REG32(RXBROADCNT, 0x15c) /* Error-free Broadcast Frames RX */
|
||||||
REG32(RXMULTICNT, 0x160) /* Error-free Multicast Frames RX */
|
REG32(RXMULTICNT, 0x160) /* Error-free Multicast Frames RX */
|
||||||
@ -1743,7 +1743,8 @@ static void gem_realize(DeviceState *dev, Error **errp)
|
|||||||
qemu_macaddr_default_if_unset(&s->conf.macaddr);
|
qemu_macaddr_default_if_unset(&s->conf.macaddr);
|
||||||
|
|
||||||
s->nic = qemu_new_nic(&net_gem_info, &s->conf,
|
s->nic = qemu_new_nic(&net_gem_info, &s->conf,
|
||||||
object_get_typename(OBJECT(dev)), dev->id, s);
|
object_get_typename(OBJECT(dev)), dev->id,
|
||||||
|
&dev->mem_reentrancy_guard, s);
|
||||||
|
|
||||||
if (s->jumbo_max_len > MAX_FRAME_SIZE) {
|
if (s->jumbo_max_len > MAX_FRAME_SIZE) {
|
||||||
error_setg(errp, "jumbo-max-len is greater than %d",
|
error_setg(errp, "jumbo-max-len is greater than %d",
|
||||||
|
@ -108,7 +108,7 @@ void can_sja_single_filter(struct qemu_can_filter *filter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
filter->can_mask = (uint32_t)amr[0] << 3;
|
filter->can_mask = (uint32_t)amr[0] << 3;
|
||||||
filter->can_mask |= (uint32_t)amr[1] << 5;
|
filter->can_mask |= (uint32_t)amr[1] >> 5;
|
||||||
filter->can_mask = ~filter->can_mask & QEMU_CAN_SFF_MASK;
|
filter->can_mask = ~filter->can_mask & QEMU_CAN_SFF_MASK;
|
||||||
if (!(amr[1] & 0x10)) {
|
if (!(amr[1] & 0x10)) {
|
||||||
filter->can_mask |= QEMU_CAN_RTR_FLAG;
|
filter->can_mask |= QEMU_CAN_RTR_FLAG;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user