-----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:
Romain Malmain 2024-02-05 10:18:33 +01:00
commit 75d15d54f4
406 changed files with 5310 additions and 2899 deletions

View File

@ -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

View File

@ -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:

View File

@ -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

View 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'

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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>

View File

@ -1 +1 @@
8.1.90 8.2.1

View File

@ -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);
} }

View File

@ -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);

View File

@ -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;
} }
} }

View File

@ -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
View File

@ -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 {

View File

@ -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;

View File

@ -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);
} }

View File

@ -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

View File

@ -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;
} }

View File

@ -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);
} }
} }

View File

@ -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 = {

View File

@ -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)

View File

@ -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:

View File

@ -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);

View File

@ -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();
} }

View File

@ -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);
} }

View File

@ -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 {

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;
} }

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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':

View File

@ -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);
} }

View File

@ -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.

View File

@ -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
~~~~~~~~~~~ ~~~~~~~~~~~

View File

@ -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.

View File

@ -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

View File

@ -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"
} }
] ]

View File

@ -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
View File

@ -0,0 +1,2 @@
sphinx==5.3.0
sphinx_rtd_theme==1.1.1

View File

@ -1,3 +1,5 @@
.. _tpm-device:
=============== ===============
QEMU TPM Device QEMU TPM Device
=============== ===============

View File

@ -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)

View File

@ -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.

View File

@ -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
============================ ============================

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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)) {

View File

@ -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;

View File

@ -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;
} }

View File

@ -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)

View File

@ -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;

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 */
} }

View File

@ -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)

View File

@ -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 = &micro_nomixemu; const struct desc_codec *desc = &micro_mixemu;
if (!a->mixer) { if (!a->mixer) {
desc = &micro_mixemu; desc = &micro_nomixemu;
} }
hda_audio_init(hda, desc, errp); hda_audio_init(hda, desc, errp);

View File

@ -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;

View File

@ -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)

View File

@ -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,

View File

@ -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);

View File

@ -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[] = {

View File

@ -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) {

View File

@ -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"

View File

@ -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)

View File

@ -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));

View File

@ -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);
} }

View File

@ -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)

View File

@ -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();

View File

@ -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,

View File

@ -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)

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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,
}, },
}; };

View File

@ -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);
} }
} }

View File

@ -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)) {

View File

@ -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";

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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,
}; };

View File

@ -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);
} }

View File

@ -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);

View File

@ -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",

View File

@ -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;

View File

@ -434,6 +434,52 @@ static bool tx_ready_check(XlnxZynqMPCANState *s)
return true; return true;
} }
static void read_tx_frame(XlnxZynqMPCANState *s, Fifo32 *fifo, uint32_t *data)
{
unsigned used = fifo32_num_used(fifo);
bool is_txhpb = fifo == &s->txhpb_fifo;
assert(used > 0);
used %= CAN_FRAME_SIZE;
/*
* Frame Message Format
*
* Each frame includes four words (16 bytes). Software must read and write
* all four words regardless of the actual number of data bytes and valid
* fields in the message.
* If software misbehave (not writing all four words), we use the previous
* registers content to initialize each missing word.
*
* If used is 1 then ID, DLC and DATA1 are missing.
* if used is 2 then ID and DLC are missing.
* if used is 3 then only ID is missing.
*/
if (used > 0) {
data[0] = s->regs[is_txhpb ? R_TXHPB_ID : R_TXFIFO_ID];
} else {
data[0] = fifo32_pop(fifo);
}
if (used == 1 || used == 2) {
data[1] = s->regs[is_txhpb ? R_TXHPB_DLC : R_TXFIFO_DLC];
} else {
data[1] = fifo32_pop(fifo);
}
if (used == 1) {
data[2] = s->regs[is_txhpb ? R_TXHPB_DATA1 : R_TXFIFO_DATA1];
} else {
data[2] = fifo32_pop(fifo);
}
/* DATA2 triggered the transfer thus is always available */
data[3] = fifo32_pop(fifo);
if (used) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Incomplete CAN frame (only %u/%u slots used)\n",
TYPE_XLNX_ZYNQMP_CAN, used, CAN_FRAME_SIZE);
}
}
static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo) static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
{ {
qemu_can_frame frame; qemu_can_frame frame;
@ -451,9 +497,7 @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
} }
while (!fifo32_is_empty(fifo)) { while (!fifo32_is_empty(fifo)) {
for (i = 0; i < CAN_FRAME_SIZE; i++) { read_tx_frame(s, fifo, data);
data[i] = fifo32_pop(fifo);
}
if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) { if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
/* /*
@ -734,14 +778,18 @@ static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
} }
} }
static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val) static uint64_t can_rxfifo_post_read_id(RegisterInfo *reg, uint64_t val)
{ {
XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque); XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
unsigned used = fifo32_num_used(&s->rx_fifo);
if (!fifo32_is_empty(&s->rx_fifo)) { if (used < CAN_FRAME_SIZE) {
val = fifo32_pop(&s->rx_fifo);
} else {
ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1); ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
} else {
val = s->regs[R_RXFIFO_ID] = fifo32_pop(&s->rx_fifo);
s->regs[R_RXFIFO_DLC] = fifo32_pop(&s->rx_fifo);
s->regs[R_RXFIFO_DATA1] = fifo32_pop(&s->rx_fifo);
s->regs[R_RXFIFO_DATA2] = fifo32_pop(&s->rx_fifo);
} }
can_update_irq(s); can_update_irq(s);
@ -902,14 +950,11 @@ static const RegisterAccessInfo can_regs_info[] = {
.post_write = can_tx_post_write, .post_write = can_tx_post_write,
},{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID, },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
.ro = 0xffffffff, .ro = 0xffffffff,
.post_read = can_rxfifo_pre_read, .post_read = can_rxfifo_post_read_id,
},{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC, },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
.rsvd = 0xfff0000, .rsvd = 0xfff0000,
.post_read = can_rxfifo_pre_read,
},{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1, },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
.post_read = can_rxfifo_pre_read,
},{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2, },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
.post_read = can_rxfifo_pre_read,
},{ .name = "AFR", .addr = A_AFR, },{ .name = "AFR", .addr = A_AFR,
.rsvd = 0xfffffff0, .rsvd = 0xfffffff0,
.post_write = can_filter_enable_post_write, .post_write = can_filter_enable_post_write,

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