Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bac900779 |
No files matched your search
@@ -0,0 +1,34 @@
|
||||
# Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown
|
||||
|
||||
# Close issues and pull requests
|
||||
close: true
|
||||
|
||||
# Lock issues and pull requests
|
||||
lock: true
|
||||
|
||||
issues:
|
||||
comment: |
|
||||
Thank you for your interest in the QEMU project.
|
||||
|
||||
This repository is a read-only mirror of the project's repostories hosted
|
||||
at https://gitlab.com/qemu-project/qemu.git.
|
||||
The project does not process issues filed on GitHub.
|
||||
|
||||
The project issues are tracked on GitLab:
|
||||
https://gitlab.com/qemu-project/qemu/-/issues
|
||||
|
||||
QEMU welcomes bug report contributions. You can file new ones on:
|
||||
https://gitlab.com/qemu-project/qemu/-/issues/new
|
||||
|
||||
pulls:
|
||||
comment: |
|
||||
Thank you for your interest in the QEMU project.
|
||||
|
||||
This repository is a read-only mirror of the project's repostories hosted
|
||||
on https://gitlab.com/qemu-project/qemu.git.
|
||||
The project does not process merge requests filed on GitHub.
|
||||
|
||||
QEMU welcomes contributions of code (either fixing bugs or adding new
|
||||
functionality). However, we get a lot of patches, and so we have some
|
||||
guidelines about contributing on the project website:
|
||||
https://www.qemu.org/contribute/
|
||||
@@ -1,30 +0,0 @@
|
||||
# Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown
|
||||
|
||||
name: 'Repo Lockdown'
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: opened
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/repo-lockdown@v2
|
||||
with:
|
||||
pull-comment: |
|
||||
Thank you for your interest in the QEMU project.
|
||||
|
||||
This repository is a read-only mirror of the project's repostories hosted
|
||||
on https://gitlab.com/qemu-project/qemu.git.
|
||||
The project does not process merge requests filed on GitHub.
|
||||
|
||||
QEMU welcomes contributions of code (either fixing bugs or adding new
|
||||
functionality). However, we get a lot of patches, and so we have some
|
||||
guidelines about contributing on the project website:
|
||||
https://www.qemu.org/contribute/
|
||||
lock-pull: true
|
||||
close-pull: true
|
||||
@@ -37,7 +37,7 @@
|
||||
# Avoid recompiling by hiding ninja with NINJA=":"
|
||||
- make NINJA=":" $MAKE_CHECK_ARGS
|
||||
|
||||
.avocado_test_job_template:
|
||||
.acceptance_test_job_template:
|
||||
extends: .native_test_job_template
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}-cache"
|
||||
|
||||
+29
-51
@@ -26,14 +26,14 @@ check-system-alpine:
|
||||
IMAGE: alpine
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-alpine:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-alpine:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-alpine
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: alpine
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-ubuntu:
|
||||
extends: .native_build_job_template
|
||||
@@ -59,14 +59,14 @@ check-system-ubuntu:
|
||||
IMAGE: ubuntu2004
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-ubuntu:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-ubuntu:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-ubuntu
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-debian:
|
||||
extends: .native_build_job_template
|
||||
@@ -91,25 +91,14 @@ check-system-debian:
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-debian:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-debian:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
|
||||
crash-test-debian:
|
||||
extends: .native_test_job_template
|
||||
needs:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
script:
|
||||
- cd build
|
||||
- scripts/device-crash-test -q ./qemu-system-i386
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-fedora:
|
||||
extends: .native_build_job_template
|
||||
@@ -136,26 +125,14 @@ check-system-fedora:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-fedora:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-fedora:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-fedora
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
|
||||
crash-test-fedora:
|
||||
extends: .native_test_job_template
|
||||
needs:
|
||||
- job: build-system-fedora
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
script:
|
||||
- cd build
|
||||
- scripts/device-crash-test -q ./qemu-system-ppc
|
||||
- scripts/device-crash-test -q ./qemu-system-riscv32
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-centos:
|
||||
extends: .native_build_job_template
|
||||
@@ -182,14 +159,14 @@ check-system-centos:
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-centos:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-centos:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-centos
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-opensuse:
|
||||
extends: .native_build_job_template
|
||||
@@ -214,14 +191,14 @@ check-system-opensuse:
|
||||
IMAGE: opensuse-leap
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-opensuse:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-opensuse:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-opensuse
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: opensuse-leap
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
|
||||
# This jobs explicitly disable TCG (--disable-tcg), KVM is detected by
|
||||
@@ -340,7 +317,7 @@ clang-user:
|
||||
# This can be accomplished by using -enable-slirp=git, which avoids the use of
|
||||
# a system-wide version of the library
|
||||
#
|
||||
# Split in three sets of build/check/avocado to limit the execution time of each
|
||||
# Split in three sets of build/check/acceptance to limit the execution time of each
|
||||
# job
|
||||
build-cfi-aarch64:
|
||||
extends: .native_build_job_template
|
||||
@@ -375,14 +352,14 @@ check-cfi-aarch64:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-cfi-aarch64:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-cfi-aarch64:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-cfi-aarch64
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-cfi-ppc64-s390x:
|
||||
extends: .native_build_job_template
|
||||
@@ -417,14 +394,14 @@ check-cfi-ppc64-s390x:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-cfi-ppc64-s390x:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-cfi-ppc64-s390x:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-cfi-ppc64-s390x
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-cfi-x86_64:
|
||||
extends: .native_build_job_template
|
||||
@@ -453,14 +430,14 @@ check-cfi-x86_64:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-cfi-x86_64:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-cfi-x86_64:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-cfi-x86_64
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
tsan-build:
|
||||
extends: .native_build_job_template
|
||||
@@ -598,6 +575,7 @@ build-without-default-features:
|
||||
CONFIGURE_ARGS:
|
||||
--without-default-features
|
||||
--disable-capstone
|
||||
--disable-fdt
|
||||
--disable-pie
|
||||
--disable-qom-cast-debug
|
||||
--disable-slirp
|
||||
|
||||
+1
-40
@@ -14,7 +14,6 @@
|
||||
stage: build
|
||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
||||
needs: []
|
||||
timeout: 80m
|
||||
allow_failure: true
|
||||
script:
|
||||
- source .gitlab-ci.d/cirrus/$NAME.vars
|
||||
@@ -36,14 +35,11 @@
|
||||
-e "s|[@]PIP3@|$PIP3|g"
|
||||
-e "s|[@]PYPI_PKGS@|$PYPI_PKGS|g"
|
||||
-e "s|[@]CONFIGURE_ARGS@|$CONFIGURE_ARGS|g"
|
||||
-e "s|[@]TEST_TARGETS@|$TEST_TARGETS|g"
|
||||
-e "s|[@]TEST_TARGETSS@|$TEST_TARGETSS|g"
|
||||
<.gitlab-ci.d/cirrus/build.yml >.gitlab-ci.d/cirrus/$NAME.yml
|
||||
- cat .gitlab-ci.d/cirrus/$NAME.yml
|
||||
- cirrus-run -v --show-build-log always .gitlab-ci.d/cirrus/$NAME.yml
|
||||
rules:
|
||||
# Allow on 'staging' branch and 'stable-X.Y-staging' branches only
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH !~ /staging/'
|
||||
when: never
|
||||
- if: "$CIRRUS_GITHUB_REPO && $CIRRUS_API_TOKEN"
|
||||
|
||||
x64-freebsd-12-build:
|
||||
@@ -89,38 +85,3 @@ x64-macos-11-base-build:
|
||||
PATH_EXTRA: /usr/local/opt/ccache/libexec:/usr/local/opt/gettext/bin
|
||||
PKG_CONFIG_PATH: /usr/local/opt/curl/lib/pkgconfig:/usr/local/opt/ncurses/lib/pkgconfig:/usr/local/opt/readline/lib/pkgconfig
|
||||
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
||||
|
||||
|
||||
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
|
||||
.cirrus_kvm_job:
|
||||
stage: build
|
||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
||||
needs: []
|
||||
timeout: 80m
|
||||
allow_failure: true
|
||||
script:
|
||||
- sed -e "s|[@]CI_REPOSITORY_URL@|$CI_REPOSITORY_URL|g"
|
||||
-e "s|[@]CI_COMMIT_REF_NAME@|$CI_COMMIT_REF_NAME|g"
|
||||
-e "s|[@]CI_COMMIT_SHA@|$CI_COMMIT_SHA|g"
|
||||
-e "s|[@]NAME@|$NAME|g"
|
||||
-e "s|[@]CONFIGURE_ARGS@|$CONFIGURE_ARGS|g"
|
||||
-e "s|[@]TEST_TARGETS@|$TEST_TARGETS|g"
|
||||
<.gitlab-ci.d/cirrus/kvm-build.yml >.gitlab-ci.d/cirrus/$NAME.yml
|
||||
- cat .gitlab-ci.d/cirrus/$NAME.yml
|
||||
- cirrus-run -v --show-build-log always .gitlab-ci.d/cirrus/$NAME.yml
|
||||
rules:
|
||||
- when: manual
|
||||
|
||||
x86-netbsd:
|
||||
extends: .cirrus_kvm_job
|
||||
variables:
|
||||
NAME: netbsd
|
||||
CONFIGURE_ARGS: --target-list=x86_64-softmmu,ppc64-softmmu,aarch64-softmmu
|
||||
TEST_TARGETS: check
|
||||
|
||||
x86-openbsd:
|
||||
extends: .cirrus_kvm_job
|
||||
variables:
|
||||
NAME: openbsd
|
||||
CONFIGURE_ARGS: --target-list=i386-softmmu,riscv64-softmmu,mips64-softmmu
|
||||
TEST_TARGETS: check
|
||||
@@ -13,7 +13,6 @@ env:
|
||||
PYTHON: "@PYTHON@"
|
||||
MAKE: "@MAKE@"
|
||||
CONFIGURE_ARGS: "@CONFIGURE_ARGS@"
|
||||
TEST_TARGETS: "@TEST_TARGETS@"
|
||||
|
||||
build_task:
|
||||
install_script:
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
container:
|
||||
image: fedora:35
|
||||
cpu: 4
|
||||
memory: 8Gb
|
||||
kvm: true
|
||||
|
||||
env:
|
||||
CIRRUS_CLONE_DEPTH: 1
|
||||
CI_REPOSITORY_URL: "@CI_REPOSITORY_URL@"
|
||||
CI_COMMIT_REF_NAME: "@CI_COMMIT_REF_NAME@"
|
||||
CI_COMMIT_SHA: "@CI_COMMIT_SHA@"
|
||||
|
||||
@NAME@_task:
|
||||
@NAME@_vm_cache:
|
||||
folder: $HOME/.cache/qemu-vm
|
||||
install_script:
|
||||
- dnf update -y
|
||||
- dnf install -y git make openssh-clients qemu-img qemu-system-x86 wget
|
||||
clone_script:
|
||||
- git clone --depth 100 "$CI_REPOSITORY_URL" .
|
||||
- git fetch origin "$CI_COMMIT_REF_NAME"
|
||||
- git reset --hard "$CI_COMMIT_SHA"
|
||||
build_script:
|
||||
- if [ -f $HOME/.cache/qemu-vm/images/@NAME@.img ]; then
|
||||
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN)
|
||||
EXTRA_CONFIGURE_OPTS="@CONFIGURE_ARGS@"
|
||||
BUILD_TARGET="@TEST_TARGETS@" ;
|
||||
else
|
||||
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN) BUILD_TARGET=help
|
||||
EXTRA_CONFIGURE_OPTS="--disable-system --disable-user --disable-tools" ;
|
||||
fi
|
||||
@@ -134,8 +134,7 @@ ppc64el-debian-cross-container:
|
||||
riscv64-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers-layer2
|
||||
# as we are currently based on 'sid/unstable' we may break so...
|
||||
allow_failure: true
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-riscv64-cross
|
||||
|
||||
|
||||
@@ -124,25 +124,6 @@ cross-ppc64el-user:
|
||||
variables:
|
||||
IMAGE: debian-ppc64el-cross
|
||||
|
||||
# The riscv64 cross-builds currently use a 'sid' container to get
|
||||
# compilers and libraries. Until something more stable is found we
|
||||
# allow_failure so as not to block CI.
|
||||
cross-riscv64-system:
|
||||
extends: .cross_system_build_job
|
||||
allow_failure: true
|
||||
needs:
|
||||
job: riscv64-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-riscv64-cross
|
||||
|
||||
cross-riscv64-user:
|
||||
extends: .cross_user_build_job
|
||||
allow_failure: true
|
||||
needs:
|
||||
job: riscv64-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-riscv64-cross
|
||||
|
||||
cross-s390x-system:
|
||||
extends: .cross_system_build_job
|
||||
needs:
|
||||
|
||||
@@ -13,7 +13,238 @@
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
|
||||
include:
|
||||
- local: '/.gitlab-ci.d/custom-runners/ubuntu-18.04-s390x.yml'
|
||||
- local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml'
|
||||
- local: '/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml'
|
||||
# All ubuntu-18.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
|
||||
ubuntu-18.04-s390x-all-linux-static:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
|
||||
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
- make --output-sync -j`nproc` check-tcg V=1
|
||||
|
||||
ubuntu-18.04-s390x-all:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-18.04-s390x-alldbg:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --disable-libssh
|
||||
- make clean
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-18.04-s390x-clang:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-18.04-s390x-tci:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --enable-tcg-interpreter
|
||||
- make --output-sync -j`nproc`
|
||||
|
||||
ubuntu-18.04-s390x-notcg:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --disable-tcg
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
# All ubuntu-20.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/qemu/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
|
||||
ubuntu-20.04-aarch64-all-linux-static:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
script:
|
||||
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
|
||||
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
- make --output-sync -j`nproc` check-tcg V=1
|
||||
|
||||
ubuntu-20.04-aarch64-all:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-20.04-aarch64-alldbg:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --disable-libssh
|
||||
- make clean
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-20.04-aarch64-clang:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --cc=clang-10 --cxx=clang++-10 --enable-sanitizers
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-20.04-aarch64-tci:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --enable-tcg-interpreter
|
||||
- make --output-sync -j`nproc`
|
||||
|
||||
ubuntu-20.04-aarch64-notcg:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --disable-tcg
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
@@ -1,28 +0,0 @@
|
||||
centos-stream-8-x86_64:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- centos_stream_8
|
||||
- x86_64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$CENTOS_STREAM_8_x86_64_RUNNER_AVAILABLE"
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
when: on_failure
|
||||
expire_in: 7 days
|
||||
paths:
|
||||
- build/tests/results/latest/results.xml
|
||||
- build/tests/results/latest/test-results
|
||||
reports:
|
||||
junit: build/tests/results/latest/results.xml
|
||||
before_script:
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../scripts/ci/org.centos/stream/8/x86_64/configure
|
||||
- make -j"$JOBS"
|
||||
- make NINJA=":" check
|
||||
- ../scripts/ci/org.centos/stream/8/x86_64/test-avocado
|
||||
@@ -1,118 +0,0 @@
|
||||
# All ubuntu-18.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
|
||||
|
||||
ubuntu-18.04-s390x-all-linux-static:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
|
||||
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
- make --output-sync -j`nproc` check-tcg V=1
|
||||
|
||||
ubuntu-18.04-s390x-all:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-18.04-s390x-alldbg:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --disable-libssh
|
||||
- make clean
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-18.04-s390x-clang:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-18.04-s390x-tci:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --enable-tcg-interpreter
|
||||
- make --output-sync -j`nproc`
|
||||
|
||||
ubuntu-18.04-s390x-notcg:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --disable-tcg
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
@@ -1,118 +0,0 @@
|
||||
# All ubuntu-20.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/qemu/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
|
||||
|
||||
ubuntu-20.04-aarch64-all-linux-static:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
script:
|
||||
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
|
||||
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
- make --output-sync -j`nproc` check-tcg V=1
|
||||
|
||||
ubuntu-20.04-aarch64-all:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-20.04-aarch64-alldbg:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --disable-libssh
|
||||
- make clean
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-20.04-aarch64-clang:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --cc=clang-10 --cxx=clang++-10 --enable-sanitizers
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-20.04-aarch64-tci:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --enable-tcg-interpreter
|
||||
- make --output-sync -j`nproc`
|
||||
|
||||
ubuntu-20.04-aarch64-notcg:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --disable-tcg
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
@@ -50,11 +50,7 @@ build-edk2:
|
||||
GIT_DEPTH: 3
|
||||
script: # Clone the required submodules and build EDK2
|
||||
- git submodule update --init roms/edk2
|
||||
- git -C roms/edk2 submodule update --init --
|
||||
ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
|
||||
BaseTools/Source/C/BrotliCompress/brotli
|
||||
CryptoPkg/Library/OpensslLib/openssl
|
||||
MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
|
||||
- git -C roms/edk2 submodule update --init
|
||||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
- make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2
|
||||
@@ -11,4 +11,3 @@ include:
|
||||
- local: '/.gitlab-ci.d/static_checks.yml'
|
||||
- local: '/.gitlab-ci.d/custom-runners.yml'
|
||||
- local: '/.gitlab-ci.d/cirrus.yml'
|
||||
- local: '/.gitlab-ci.d/windows.yml'
|
||||
@@ -8,7 +8,7 @@ check-patch:
|
||||
variables:
|
||||
GIT_DEPTH: 1000
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
when: never
|
||||
- when: on_success
|
||||
allow_failure: true
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
.shared_msys2_builder:
|
||||
tags:
|
||||
- shared-windows
|
||||
- windows
|
||||
- windows-1809
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}-cache"
|
||||
paths:
|
||||
- ${CI_PROJECT_DIR}/msys64/var/cache
|
||||
needs: []
|
||||
stage: build
|
||||
timeout: 70m
|
||||
before_script:
|
||||
- If ( !(Test-Path -Path msys64\var\cache ) ) {
|
||||
mkdir msys64\var\cache
|
||||
}
|
||||
- If ( !(Test-Path -Path msys64\var\cache\msys2.exe ) ) {
|
||||
Invoke-WebRequest
|
||||
"https://github.com/msys2/msys2-installer/releases/download/2021-07-25/msys2-base-x86_64-20210725.sfx.exe"
|
||||
-outfile "msys64\var\cache\msys2.exe"
|
||||
}
|
||||
- msys64\var\cache\msys2.exe -y
|
||||
- ((Get-Content -path .\msys64\etc\\post-install\\07-pacman-key.post -Raw)
|
||||
-replace '--refresh-keys', '--version') |
|
||||
Set-Content -Path ${CI_PROJECT_DIR}\msys64\etc\\post-install\\07-pacman-key.post
|
||||
- .\msys64\usr\bin\bash -lc "sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf"
|
||||
- .\msys64\usr\bin\bash -lc 'pacman --noconfirm -Syuu' # Core update
|
||||
- .\msys64\usr\bin\bash -lc 'pacman --noconfirm -Syuu' # Normal update
|
||||
- taskkill /F /FI "MODULES eq msys-2.0.dll"
|
||||
|
||||
msys2-64bit:
|
||||
extends: .shared_msys2_builder
|
||||
script:
|
||||
- .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed
|
||||
diffutils git grep make sed
|
||||
mingw-w64-x86_64-capstone
|
||||
mingw-w64-x86_64-curl
|
||||
mingw-w64-x86_64-cyrus-sasl
|
||||
mingw-w64-x86_64-gcc
|
||||
mingw-w64-x86_64-glib2
|
||||
mingw-w64-x86_64-gnutls
|
||||
mingw-w64-x86_64-libnfs
|
||||
mingw-w64-x86_64-libpng
|
||||
mingw-w64-x86_64-libssh
|
||||
mingw-w64-x86_64-libtasn1
|
||||
mingw-w64-x86_64-libusb
|
||||
mingw-w64-x86_64-libxml2
|
||||
mingw-w64-x86_64-nettle
|
||||
mingw-w64-x86_64-ninja
|
||||
mingw-w64-x86_64-pixman
|
||||
mingw-w64-x86_64-pkgconf
|
||||
mingw-w64-x86_64-python
|
||||
mingw-w64-x86_64-SDL2
|
||||
mingw-w64-x86_64-SDL2_image
|
||||
mingw-w64-x86_64-snappy
|
||||
mingw-w64-x86_64-usbredir
|
||||
mingw-w64-x86_64-zstd "
|
||||
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||
- $env:MSYSTEM = 'MINGW64' # Start a 64 bit Mingw environment
|
||||
- .\msys64\usr\bin\bash -lc './configure --target-list=x86_64-softmmu
|
||||
--enable-capstone=system --without-default-devices'
|
||||
- .\msys64\usr\bin\bash -lc "sed -i '/^ROMS=/d' build/config-host.mak"
|
||||
- .\msys64\usr\bin\bash -lc 'make -j2'
|
||||
- .\msys64\usr\bin\bash -lc 'make check'
|
||||
|
||||
msys2-32bit:
|
||||
extends: .shared_msys2_builder
|
||||
script:
|
||||
- .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed
|
||||
diffutils git grep make sed
|
||||
mingw-w64-i686-capstone
|
||||
mingw-w64-i686-curl
|
||||
mingw-w64-i686-cyrus-sasl
|
||||
mingw-w64-i686-gcc
|
||||
mingw-w64-i686-glib2
|
||||
mingw-w64-i686-gnutls
|
||||
mingw-w64-i686-gtk3
|
||||
mingw-w64-i686-libgcrypt
|
||||
mingw-w64-i686-libjpeg-turbo
|
||||
mingw-w64-i686-libssh
|
||||
mingw-w64-i686-libtasn1
|
||||
mingw-w64-i686-libusb
|
||||
mingw-w64-i686-libxml2
|
||||
mingw-w64-i686-lzo2
|
||||
mingw-w64-i686-ninja
|
||||
mingw-w64-i686-pixman
|
||||
mingw-w64-i686-pkgconf
|
||||
mingw-w64-i686-python
|
||||
mingw-w64-i686-snappy
|
||||
mingw-w64-i686-usbredir "
|
||||
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||
- $env:MSYSTEM = 'MINGW32' # Start a 32-bit MinG environment
|
||||
- mkdir output
|
||||
- cd output
|
||||
- ..\msys64\usr\bin\bash -lc "../configure --target-list=ppc64-softmmu
|
||||
--enable-capstone=system"
|
||||
- ..\msys64\usr\bin\bash -lc 'make -j2'
|
||||
- ..\msys64\usr\bin\bash -lc 'make check'
|
||||
@@ -50,7 +50,6 @@ Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <arikalo@wavecomp.com>
|
||||
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
|
||||
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
|
||||
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
|
||||
Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
|
||||
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
|
||||
Frederic Konrad <konrad@adacore.com> <fred.konrad@greensocs.com>
|
||||
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
|
||||
@@ -70,7 +69,6 @@ Yongbok Kim <yongbok.kim@mips.com> <yongbok.kim@imgtec.com>
|
||||
# git author config, or had utf8/latin1 encoding issues.
|
||||
Aaron Lindsay <aaron@os.amperecomputing.com>
|
||||
Alexey Gerasimenko <x1917x@gmail.com>
|
||||
Alex Chen <alex.chen@huawei.com>
|
||||
Alex Ivanov <void@aleksoft.net>
|
||||
Andreas Färber <afaerber@suse.de>
|
||||
Bandan Das <bsd@redhat.com>
|
||||
@@ -101,11 +99,9 @@ Gautham R. Shenoy <ego@in.ibm.com>
|
||||
Gautham R. Shenoy <ego@linux.vnet.ibm.com>
|
||||
Gonglei (Arei) <arei.gonglei@huawei.com>
|
||||
Guang Wang <wang.guang55@zte.com.cn>
|
||||
Haibin Zhang <haibinzhang@tencent.com>
|
||||
Hailiang Zhang <zhang.zhanghailiang@huawei.com>
|
||||
Hanna Reitz <hreitz@redhat.com> <mreitz@redhat.com>
|
||||
Hervé Poussineau <hpoussin@reactos.org>
|
||||
Hyman Huang <huangy81@chinatelecom.cn>
|
||||
Jakub Jermář <jakub@jermar.eu>
|
||||
Jakub Jermář <jakub.jermar@kernkonzept.com>
|
||||
Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
@@ -139,7 +135,6 @@ Nicholas Thomas <nick@bytemark.co.uk>
|
||||
Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
|
||||
Orit Wasserman <owasserm@redhat.com>
|
||||
Paolo Bonzini <pbonzini@redhat.com>
|
||||
Pan Nengyuan <pannengyuan@huawei.com>
|
||||
Pavel Dovgaluk <dovgaluk@ispras.ru>
|
||||
Pavel Dovgaluk <pavel.dovgaluk@gmail.com>
|
||||
Pavel Dovgaluk <Pavel.Dovgaluk@ispras.ru>
|
||||
|
||||
+23
@@ -305,3 +305,26 @@ jobs:
|
||||
- CONFIG="--disable-containers --disable-tcg --enable-kvm
|
||||
--disable-tools --host-cc=clang --cxx=clang++"
|
||||
- UNRELIABLE=true
|
||||
|
||||
# Release builds
|
||||
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
|
||||
# This is the case when release candidate tags are created.
|
||||
- name: "Release tarball"
|
||||
if: tag IS present AND tag =~ /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
env:
|
||||
# We want to build from the release tarball
|
||||
- BUILD_DIR="release/build/dir" SRC_DIR="../../.."
|
||||
- BASE_CONFIG="--prefix=$PWD/dist"
|
||||
- CONFIG="--target-list=x86_64-softmmu,aarch64-softmmu,armeb-linux-user,ppc-linux-user"
|
||||
- TEST_CMD="make install -j${JOBS}"
|
||||
- QEMU_VERSION="${TRAVIS_TAG:1}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
script:
|
||||
- make -C ${SRC_DIR} qemu-${QEMU_VERSION}.tar.bz2
|
||||
- ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2
|
||||
- tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION}
|
||||
- mkdir -p release-build && cd release-build
|
||||
- ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- make install
|
||||
allow_failures:
|
||||
- env: UNRELIABLE=true
|
||||
@@ -41,7 +41,3 @@ config PVRDMA
|
||||
config MULTIPROCESS_ALLOWED
|
||||
bool
|
||||
imply MULTIPROCESS
|
||||
|
||||
config FUZZ
|
||||
bool
|
||||
select SPARSE_MEM
|
||||
+66
-117
@@ -109,12 +109,6 @@ K: ^Subject:.*(?i)s390x?
|
||||
T: git https://gitlab.com/cohuck/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
MIPS general architecture support
|
||||
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
R: Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
S: Odd Fixes
|
||||
K: ^Subject:.*(?i)mips
|
||||
|
||||
Guest CPU cores (TCG)
|
||||
---------------------
|
||||
Overall TCG CPUs
|
||||
@@ -177,7 +171,7 @@ L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/smmu*
|
||||
F: include/hw/arm/smmu*
|
||||
F: tests/avocado/smmu.py
|
||||
F: tests/acceptance/smmu.py
|
||||
|
||||
AVR TCG CPUs
|
||||
M: Michael Rolnik <mrolnik@gmail.com>
|
||||
@@ -185,7 +179,7 @@ S: Maintained
|
||||
F: docs/system/target-avr.rst
|
||||
F: gdb-xml/avr-cpu.xml
|
||||
F: target/avr/
|
||||
F: tests/avocado/machine_avr6.py
|
||||
F: tests/acceptance/machine_avr6.py
|
||||
|
||||
CRIS TCG CPUs
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
@@ -211,7 +205,10 @@ HPPA (PA-RISC) TCG CPUs
|
||||
M: Richard Henderson <richard.henderson@linaro.org>
|
||||
S: Maintained
|
||||
F: target/hppa/
|
||||
F: hw/hppa/
|
||||
F: disas/hppa.c
|
||||
F: hw/net/*i82596*
|
||||
F: include/hw/net/lasi_82596.h
|
||||
|
||||
M68K TCG CPUs
|
||||
M: Laurent Vivier <laurent@vivier.eu>
|
||||
@@ -225,8 +222,6 @@ S: Maintained
|
||||
F: target/microblaze/
|
||||
F: hw/microblaze/
|
||||
F: disas/microblaze.c
|
||||
F: tests/docker/dockerfiles/debian-microblaze-cross.d/build-toolchain.sh
|
||||
F: tests/tcg/nios2/Makefile.target
|
||||
|
||||
MIPS TCG CPUs
|
||||
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
@@ -235,9 +230,19 @@ R: Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
|
||||
S: Odd Fixes
|
||||
F: target/mips/
|
||||
F: configs/devices/mips*/*
|
||||
F: disas/mips.c
|
||||
F: docs/system/cpu-models-mips.rst.inc
|
||||
F: hw/intc/mips_gic.c
|
||||
F: hw/mips/
|
||||
F: hw/misc/mips_*
|
||||
F: hw/timer/mips_gictimer.c
|
||||
F: include/hw/intc/mips_gic.h
|
||||
F: include/hw/mips/
|
||||
F: include/hw/misc/mips_*
|
||||
F: include/hw/timer/mips_gictimer.h
|
||||
F: tests/tcg/mips/
|
||||
K: ^Subject:.*(?i)mips
|
||||
|
||||
MIPS TCG CPUs (nanoMIPS ISA)
|
||||
S: Orphan
|
||||
@@ -252,7 +257,6 @@ F: target/nios2/
|
||||
F: hw/nios2/
|
||||
F: disas/nios2.c
|
||||
F: configs/devices/nios2-softmmu/default.mak
|
||||
F: tests/docker/dockerfiles/debian-nios2-cross.d/build-toolchain.sh
|
||||
|
||||
OpenRISC TCG CPUs
|
||||
M: Stafford Horne <shorne@gmail.com>
|
||||
@@ -262,10 +266,8 @@ F: hw/openrisc/
|
||||
F: tests/tcg/openrisc/
|
||||
|
||||
PowerPC TCG CPUs
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
M: Daniel Henrique Barboza <danielhb413@gmail.com>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Maintained
|
||||
F: target/ppc/
|
||||
@@ -324,7 +326,7 @@ F: disas/sparc.c
|
||||
X86 TCG CPUs
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
M: Richard Henderson <richard.henderson@linaro.org>
|
||||
M: Eduardo Habkost <eduardo@habkost.net>
|
||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||
S: Maintained
|
||||
F: target/i386/tcg/
|
||||
F: tests/tcg/i386/
|
||||
@@ -384,16 +386,15 @@ F: target/mips/kvm*
|
||||
F: target/mips/sysemu/
|
||||
|
||||
PPC KVM CPUs
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
M: Daniel Henrique Barboza <danielhb413@gmail.com>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
S: Maintained
|
||||
F: target/ppc/kvm.c
|
||||
|
||||
S390 KVM CPUs
|
||||
M: Halil Pasic <pasic@linux.ibm.com>
|
||||
M: Christian Borntraeger <borntraeger@linux.ibm.com>
|
||||
M: Cornelia Huck <cohuck@redhat.com>
|
||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
S: Supported
|
||||
F: target/s390x/kvm/
|
||||
F: target/s390x/ioinst.[ch]
|
||||
@@ -407,6 +408,7 @@ F: hw/intc/s390_flic.c
|
||||
F: hw/intc/s390_flic_kvm.c
|
||||
F: include/hw/s390x/s390_flic.h
|
||||
F: gdb-xml/s390*.xml
|
||||
T: git https://gitlab.com/cohuck/qemu.git s390-next
|
||||
T: git https://github.com/borntraeger/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
@@ -415,10 +417,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
M: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
L: kvm@vger.kernel.org
|
||||
S: Supported
|
||||
F: docs/amd-memory-encryption.txt
|
||||
F: docs/system/i386/sgx.rst
|
||||
F: target/i386/kvm/
|
||||
F: target/i386/sev*
|
||||
F: scripts/kvm/vmxcap
|
||||
|
||||
Guest CPU Cores (other accelerators)
|
||||
@@ -661,7 +660,7 @@ S: Odd Fixes
|
||||
F: include/hw/arm/digic.h
|
||||
F: hw/*/digic*
|
||||
F: include/hw/*/digic*
|
||||
F: tests/avocado/machine_arm_canona1100.py
|
||||
F: tests/acceptance/machine_arm_canona1100.py
|
||||
F: docs/system/arm/digic.rst
|
||||
|
||||
Goldfish RTC
|
||||
@@ -712,7 +711,7 @@ S: Maintained
|
||||
F: hw/arm/integratorcp.c
|
||||
F: hw/misc/arm_integrator_debug.c
|
||||
F: include/hw/misc/arm_integrator_debug.h
|
||||
F: tests/avocado/machine_arm_integratorcp.py
|
||||
F: tests/acceptance/machine_arm_integratorcp.py
|
||||
F: docs/system/arm/integratorcp.rst
|
||||
|
||||
MCIMX6UL EVK / i.MX6ul
|
||||
@@ -809,7 +808,7 @@ F: include/hw/display/blizzard.h
|
||||
F: include/hw/input/lm832x.h
|
||||
F: include/hw/input/tsc2xxx.h
|
||||
F: include/hw/misc/cbus.h
|
||||
F: tests/avocado/machine_arm_n8x0.py
|
||||
F: tests/acceptance/machine_arm_n8x0.py
|
||||
F: docs/system/arm/nseries.rst
|
||||
|
||||
Palm
|
||||
@@ -1099,8 +1098,6 @@ R: Helge Deller <deller@gmx.de>
|
||||
S: Odd Fixes
|
||||
F: configs/devices/hppa-softmmu/default.mak
|
||||
F: hw/hppa/
|
||||
F: hw/net/*i82596*
|
||||
F: include/hw/net/lasi_82596.h
|
||||
F: pc-bios/hppa-firmware.img
|
||||
|
||||
M68K Machines
|
||||
@@ -1163,7 +1160,7 @@ M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
S: Maintained
|
||||
F: hw/microblaze/petalogix_s3adsp1800_mmu.c
|
||||
F: include/hw/char/xilinx_uartlite.h
|
||||
F: tests/avocado/machine_microblaze.py
|
||||
F: tests/acceptance/machine_microblaze.py
|
||||
|
||||
petalogix_ml605
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
@@ -1172,13 +1169,6 @@ F: hw/microblaze/petalogix_ml605_mmu.c
|
||||
|
||||
MIPS Machines
|
||||
-------------
|
||||
Overall MIPS Machines
|
||||
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
S: Odd Fixes
|
||||
F: configs/devices/mips*/*
|
||||
F: hw/mips/
|
||||
F: include/hw/mips/
|
||||
|
||||
Jazz
|
||||
M: Hervé Poussineau <hpoussin@reactos.org>
|
||||
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
|
||||
@@ -1196,8 +1186,8 @@ F: hw/acpi/piix4.c
|
||||
F: hw/mips/malta.c
|
||||
F: hw/mips/gt64xxx_pci.c
|
||||
F: include/hw/southbridge/piix.h
|
||||
F: tests/avocado/linux_ssh_mips_malta.py
|
||||
F: tests/avocado/machine_mips_malta.py
|
||||
F: tests/acceptance/linux_ssh_mips_malta.py
|
||||
F: tests/acceptance/machine_mips_malta.py
|
||||
|
||||
Mipssim
|
||||
R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
|
||||
@@ -1215,7 +1205,7 @@ F: hw/isa/vt82c686.c
|
||||
F: hw/pci-host/bonito.c
|
||||
F: hw/usb/vt82c686-uhci-pci.c
|
||||
F: include/hw/isa/vt82c686.h
|
||||
F: tests/avocado/machine_mips_fuloong2e.py
|
||||
F: tests/acceptance/machine_mips_fuloong2e.py
|
||||
|
||||
Loongson-3 virtual platforms
|
||||
M: Huacai Chen <chenhuacai@kernel.org>
|
||||
@@ -1225,7 +1215,7 @@ F: hw/intc/loongson_liointc.c
|
||||
F: hw/mips/loongson3_bootp.c
|
||||
F: hw/mips/loongson3_bootp.h
|
||||
F: hw/mips/loongson3_virt.c
|
||||
F: tests/avocado/machine_mips_loongson3v.py
|
||||
F: tests/acceptance/machine_mips_loongson3v.py
|
||||
|
||||
Boston
|
||||
M: Paul Burton <paulburton@kernel.org>
|
||||
@@ -1254,7 +1244,6 @@ Bamboo
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Orphan
|
||||
F: hw/ppc/ppc440_bamboo.c
|
||||
F: tests/avocado/ppc_bamboo.py
|
||||
|
||||
e500
|
||||
L: qemu-ppc@nongnu.org
|
||||
@@ -1275,7 +1264,7 @@ L: qemu-ppc@nongnu.org
|
||||
S: Orphan
|
||||
F: hw/ppc/mpc8544ds.c
|
||||
F: hw/ppc/mpc8544_guts.c
|
||||
F: tests/avocado/ppc_mpc8544ds.py
|
||||
F: tests/acceptance/ppc_mpc8544ds.py
|
||||
|
||||
New World (mac99)
|
||||
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
|
||||
@@ -1322,13 +1311,11 @@ F: hw/dma/i82374.c
|
||||
F: hw/rtc/m48t59-isa.c
|
||||
F: include/hw/isa/pc87312.h
|
||||
F: include/hw/rtc/m48t59.h
|
||||
F: tests/avocado/ppc_prep_40p.py
|
||||
F: tests/acceptance/ppc_prep_40p.py
|
||||
|
||||
sPAPR
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
M: Daniel Henrique Barboza <danielhb413@gmail.com>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/*/spapr*
|
||||
@@ -1342,7 +1329,7 @@ F: tests/qtest/spapr*
|
||||
F: tests/qtest/libqos/*spapr*
|
||||
F: tests/qtest/rtas*
|
||||
F: tests/qtest/libqos/rtas*
|
||||
F: tests/avocado/ppc_pseries.py
|
||||
F: tests/acceptance/ppc_pseries.py
|
||||
|
||||
PowerNV (Non-Virtualized)
|
||||
M: Cédric Le Goater <clg@kaod.org>
|
||||
@@ -1362,7 +1349,7 @@ M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/ppc/virtex_ml507.c
|
||||
F: tests/avocado/ppc_virtex_ml507.py
|
||||
F: tests/acceptance/ppc_virtex_ml507.py
|
||||
|
||||
sam460ex
|
||||
M: BALATON Zoltan <balaton@eik.bme.hu>
|
||||
@@ -1388,8 +1375,6 @@ F: include/hw/pci-host/mv64361.h
|
||||
|
||||
Virtual Open Firmware (VOF)
|
||||
M: Alexey Kardashevskiy <aik@ozlabs.ru>
|
||||
R: Cédric Le Goater <clg@kaod.org>
|
||||
R: Daniel Henrique Barboza <danielhb413@gmail.com>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
R: Greg Kurz <groug@kaod.org>
|
||||
L: qemu-ppc@nongnu.org
|
||||
@@ -1451,7 +1436,7 @@ R: Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
S: Orphan
|
||||
F: docs/system/target-rx.rst
|
||||
F: hw/rx/rx-gdbsim.c
|
||||
F: tests/avocado/machine_rx_gdbsim.py
|
||||
F: tests/acceptance/machine_rx_gdbsim.py
|
||||
|
||||
SH4 Machines
|
||||
------------
|
||||
@@ -1505,7 +1490,7 @@ F: include/hw/pci-host/sabre.h
|
||||
F: hw/pci-bridge/simba.c
|
||||
F: include/hw/pci-bridge/simba.h
|
||||
F: pc-bios/openbios-sparc64
|
||||
F: tests/avocado/machine_sparc64_sun4u.py
|
||||
F: tests/acceptance/machine_sparc64_sun4u.py
|
||||
|
||||
Sun4v
|
||||
M: Artyom Tarasenko <atar4qemu@gmail.com>
|
||||
@@ -1521,13 +1506,14 @@ S: Maintained
|
||||
F: hw/sparc/leon3.c
|
||||
F: hw/*/grlib*
|
||||
F: include/hw/*/grlib*
|
||||
F: tests/avocado/machine_sparc_leon3.py
|
||||
F: tests/acceptance/machine_sparc_leon3.py
|
||||
|
||||
S390 Machines
|
||||
-------------
|
||||
S390 Virtio-ccw
|
||||
M: Cornelia Huck <cohuck@redhat.com>
|
||||
M: Halil Pasic <pasic@linux.ibm.com>
|
||||
M: Christian Borntraeger <borntraeger@linux.ibm.com>
|
||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
S: Supported
|
||||
F: hw/char/sclp*.[hc]
|
||||
F: hw/char/terminal3270.c
|
||||
@@ -1536,12 +1522,13 @@ F: include/hw/s390x/
|
||||
F: hw/watchdog/wdt_diag288.c
|
||||
F: include/hw/watchdog/wdt_diag288.h
|
||||
F: configs/devices/s390x-softmmu/default.mak
|
||||
F: tests/avocado/machine_s390_ccw_virtio.py
|
||||
F: tests/acceptance/machine_s390_ccw_virtio.py
|
||||
T: git https://gitlab.com/cohuck/qemu.git s390-next
|
||||
T: git https://github.com/borntraeger/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
S390-ccw boot
|
||||
M: Christian Borntraeger <borntraeger@linux.ibm.com>
|
||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
M: Thomas Huth <thuth@redhat.com>
|
||||
S: Supported
|
||||
F: hw/s390x/ipl.*
|
||||
@@ -1622,21 +1609,19 @@ microvm
|
||||
M: Sergio Lopez <slp@redhat.com>
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Maintained
|
||||
F: docs/system/i386/microvm.rst
|
||||
F: docs/microvm.rst
|
||||
F: hw/i386/microvm.c
|
||||
F: include/hw/i386/microvm.h
|
||||
F: pc-bios/bios-microvm.bin
|
||||
|
||||
Machine core
|
||||
M: Eduardo Habkost <eduardo@habkost.net>
|
||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||
M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
|
||||
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
S: Supported
|
||||
F: cpu.c
|
||||
F: hw/core/cpu.c
|
||||
F: hw/core/machine-qmp-cmds.c
|
||||
F: hw/core/machine.c
|
||||
F: hw/core/machine-smp.c
|
||||
F: hw/core/null-machine.c
|
||||
F: hw/core/numa.c
|
||||
F: hw/cpu/cluster.c
|
||||
@@ -1646,7 +1631,6 @@ F: include/hw/boards.h
|
||||
F: include/hw/core/cpu.h
|
||||
F: include/hw/cpu/cluster.h
|
||||
F: include/sysemu/numa.h
|
||||
F: tests/unit/test-smp-parse.c
|
||||
T: git https://gitlab.com/ehabkost/qemu.git machine-next
|
||||
|
||||
Xtensa Machines
|
||||
@@ -1825,7 +1809,6 @@ F: hw/scsi/*
|
||||
F: tests/qtest/virtio-scsi-test.c
|
||||
F: tests/qtest/fuzz-virtio-scsi-test.c
|
||||
F: tests/qtest/am53c974-test.c
|
||||
F: tests/qtest/fuzz-lsi53c895a-test.c
|
||||
T: git https://github.com/bonzini/qemu.git scsi-next
|
||||
|
||||
SSI
|
||||
@@ -1879,6 +1862,7 @@ F: docs/igd-assign.txt
|
||||
F: docs/devel/vfio-migration.rst
|
||||
|
||||
vfio-ccw
|
||||
M: Cornelia Huck <cohuck@redhat.com>
|
||||
M: Eric Farman <farman@linux.ibm.com>
|
||||
M: Matthew Rosato <mjrosato@linux.ibm.com>
|
||||
S: Supported
|
||||
@@ -1886,6 +1870,7 @@ F: hw/vfio/ccw.c
|
||||
F: hw/s390x/s390-ccw.c
|
||||
F: include/hw/s390x/s390-ccw.h
|
||||
F: include/hw/s390x/vfio-ccw.h
|
||||
T: git https://gitlab.com/cohuck/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
vfio-ap
|
||||
@@ -2121,7 +2106,7 @@ M: Alex Bennée <alex.bennee@linaro.org>
|
||||
S: Maintained
|
||||
F: hw/core/guest-loader.c
|
||||
F: docs/system/guest-loader.rst
|
||||
F: tests/avocado/boot_xen.py
|
||||
F: tests/acceptance/boot_xen.py
|
||||
|
||||
Intel Hexadecimal Object File Loader
|
||||
M: Su Hang <suhang16@mails.ucas.ac.cn>
|
||||
@@ -2281,20 +2266,6 @@ S: Odd Fixes
|
||||
F: hw/intc/openpic.c
|
||||
F: include/hw/ppc/openpic.h
|
||||
|
||||
MIPS CPS
|
||||
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
S: Odd Fixes
|
||||
F: hw/misc/mips_*
|
||||
F: include/hw/misc/mips_*
|
||||
|
||||
MIPS GIC
|
||||
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
S: Odd Fixes
|
||||
F: hw/intc/mips_gic.c
|
||||
F: hw/timer/mips_gictimer.c
|
||||
F: include/hw/intc/mips_gic.h
|
||||
F: include/hw/timer/mips_gictimer.h
|
||||
|
||||
Subsystems
|
||||
----------
|
||||
Overall Audio backends
|
||||
@@ -2313,13 +2284,11 @@ F: qapi/audio.json
|
||||
|
||||
ALSA Audio backend
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
R: Christian Schoenebeck <qemu_oss@crudebyte.com>
|
||||
S: Odd Fixes
|
||||
F: audio/alsaaudio.c
|
||||
|
||||
Core Audio framework backend
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
R: Christian Schoenebeck <qemu_oss@crudebyte.com>
|
||||
S: Odd Fixes
|
||||
F: audio/coreaudio.c
|
||||
|
||||
@@ -2330,7 +2299,6 @@ F: audio/dsound*
|
||||
|
||||
JACK Audio Connection Kit backend
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
R: Christian Schoenebeck <qemu_oss@crudebyte.com>
|
||||
S: Odd Fixes
|
||||
F: audio/jackaudio.c
|
||||
|
||||
@@ -2346,7 +2314,6 @@ F: audio/paaudio.c
|
||||
|
||||
SDL Audio backend
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
R: Thomas Huth <huth@tuxfamily.org>
|
||||
S: Odd Fixes
|
||||
F: audio/sdlaudio.c
|
||||
|
||||
@@ -2535,7 +2502,6 @@ Memory API
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
M: Peter Xu <peterx@redhat.com>
|
||||
M: David Hildenbrand <david@redhat.com>
|
||||
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
S: Supported
|
||||
F: include/exec/ioport.h
|
||||
F: include/exec/memop.h
|
||||
@@ -2649,13 +2615,13 @@ F: backends/cryptodev*.c
|
||||
Python library
|
||||
M: John Snow <jsnow@redhat.com>
|
||||
M: Cleber Rosa <crosa@redhat.com>
|
||||
R: Eduardo Habkost <eduardo@habkost.net>
|
||||
R: Eduardo Habkost <ehabkost@redhat.com>
|
||||
S: Maintained
|
||||
F: python/
|
||||
T: git https://gitlab.com/jsnow/qemu.git python
|
||||
|
||||
Python scripts
|
||||
M: Eduardo Habkost <eduardo@habkost.net>
|
||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||
M: Cleber Rosa <crosa@redhat.com>
|
||||
S: Odd Fixes
|
||||
F: scripts/*.py
|
||||
@@ -2731,7 +2697,7 @@ T: git https://github.com/mdroth/qemu.git qga
|
||||
QOM
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
R: Daniel P. Berrange <berrange@redhat.com>
|
||||
R: Eduardo Habkost <eduardo@habkost.net>
|
||||
R: Eduardo Habkost <ehabkost@redhat.com>
|
||||
S: Supported
|
||||
F: docs/qdev-device-use.txt
|
||||
F: hw/core/qdev*
|
||||
@@ -2751,7 +2717,7 @@ F: tests/unit/check-qom-proplist.c
|
||||
F: tests/unit/test-qdev-global-props.c
|
||||
|
||||
QOM boilerplate conversion script
|
||||
M: Eduardo Habkost <eduardo@habkost.net>
|
||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||
S: Maintained
|
||||
F: scripts/codeconverter/
|
||||
|
||||
@@ -2873,15 +2839,11 @@ D-Bus
|
||||
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
S: Maintained
|
||||
F: backends/dbus-vmstate.c
|
||||
F: ui/dbus*
|
||||
F: audio/dbus*
|
||||
F: tests/dbus-vmstate*
|
||||
F: util/dbus.c
|
||||
F: include/ui/dbus*
|
||||
F: include/qemu/dbus.h
|
||||
F: docs/interop/dbus*
|
||||
F: docs/sphinx/dbus*
|
||||
F: docs/sphinx/fakedbusdoc.py
|
||||
F: tests/qtest/dbus*
|
||||
F: docs/interop/dbus.rst
|
||||
F: docs/interop/dbus-vmstate.rst
|
||||
|
||||
Seccomp
|
||||
M: Eduardo Otubo <otubo@redhat.com>
|
||||
@@ -2987,7 +2949,6 @@ F: docs/colo-proxy.txt
|
||||
F: net/colo*
|
||||
F: net/filter-rewriter.c
|
||||
F: net/filter-mirror.c
|
||||
F: tests/qtest/test-filter*
|
||||
|
||||
Record/replay
|
||||
M: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
|
||||
@@ -3000,9 +2961,9 @@ F: net/filter-replay.c
|
||||
F: include/sysemu/replay.h
|
||||
F: docs/replay.txt
|
||||
F: stubs/replay.c
|
||||
F: tests/avocado/replay_kernel.py
|
||||
F: tests/avocado/replay_linux.py
|
||||
F: tests/avocado/reverse_debugging.py
|
||||
F: tests/acceptance/replay_kernel.py
|
||||
F: tests/acceptance/replay_linux.py
|
||||
F: tests/acceptance/reverse_debugging.py
|
||||
F: qapi/replay.json
|
||||
|
||||
IOVA Tree
|
||||
@@ -3082,9 +3043,8 @@ Usermode Emulation
|
||||
Overall usermode emulation
|
||||
M: Riku Voipio <riku.voipio@iki.fi>
|
||||
S: Maintained
|
||||
F: thunk.c
|
||||
F: accel/tcg/user-exec*.c
|
||||
F: include/user/
|
||||
F: common-user/
|
||||
|
||||
BSD user
|
||||
M: Warner Losh <imp@bsdimp.com>
|
||||
@@ -3120,7 +3080,7 @@ S: Maintained
|
||||
F: docs/devel/tcg-plugins.rst
|
||||
F: plugins/
|
||||
F: tests/plugin/
|
||||
F: tests/avocado/tcg_plugins.py
|
||||
F: tests/acceptance/tcg_plugins.py
|
||||
F: contrib/plugins/
|
||||
|
||||
AArch64 TCG target
|
||||
@@ -3144,11 +3104,6 @@ S: Maintained
|
||||
F: tcg/i386/
|
||||
F: disas/i386.c
|
||||
|
||||
LoongArch64 TCG target
|
||||
M: WANG Xuerui <git@xen0n.name>
|
||||
S: Maintained
|
||||
F: tcg/loongarch64/
|
||||
|
||||
MIPS TCG target
|
||||
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
R: Aurelien Jarno <aurelien@aurel32.net>
|
||||
@@ -3481,7 +3436,7 @@ M: Alex Bennée <alex.bennee@linaro.org>
|
||||
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
M: Thomas Huth <thuth@redhat.com>
|
||||
R: Wainer dos Santos Moschetta <wainersm@redhat.com>
|
||||
R: Beraldo Leal <bleal@redhat.com>
|
||||
R: Willian Rampazzo <willianr@redhat.com>
|
||||
S: Maintained
|
||||
F: .github/lockdown.yml
|
||||
F: .gitlab-ci.yml
|
||||
@@ -3514,20 +3469,14 @@ S: Maintained
|
||||
F: tests/tcg/Makefile
|
||||
F: tests/tcg/Makefile.include
|
||||
|
||||
Integration Testing with the Avocado framework
|
||||
Acceptance (Integration) Testing with the Avocado framework
|
||||
W: https://trello.com/b/6Qi1pxVn/avocado-qemu
|
||||
R: Cleber Rosa <crosa@redhat.com>
|
||||
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
R: Wainer dos Santos Moschetta <wainersm@redhat.com>
|
||||
R: Beraldo Leal <bleal@redhat.com>
|
||||
R: Willian Rampazzo <willianr@redhat.com>
|
||||
S: Odd Fixes
|
||||
F: tests/avocado/
|
||||
|
||||
GitLab custom runner (Works On Arm Sponsored)
|
||||
M: Alex Bennée <alex.bennee@linaro.org>
|
||||
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
S: Maintained
|
||||
F: .gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml
|
||||
F: tests/acceptance/
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
@@ -87,7 +87,7 @@ x := $(shell rm -rf meson-private meson-info meson-logs)
|
||||
endif
|
||||
|
||||
# 1. ensure config-host.mak is up-to-date
|
||||
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/scripts/meson-buildoptions.sh $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION
|
||||
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION
|
||||
@echo config-host.mak is out-of-date, running configure
|
||||
@if test -f meson-private/coredata.dat; then \
|
||||
./config.status --skip-meson; \
|
||||
@@ -124,12 +124,6 @@ ifneq ($(MESON),)
|
||||
Makefile.mtest: build.ninja scripts/mtest2make.py
|
||||
$(MESON) introspect --targets --tests --benchmarks | $(PYTHON) scripts/mtest2make.py > $@
|
||||
-include Makefile.mtest
|
||||
|
||||
.PHONY: update-buildoptions
|
||||
all update-buildoptions: $(SRC_PATH)/scripts/meson-buildoptions.sh
|
||||
$(SRC_PATH)/scripts/meson-buildoptions.sh: $(SRC_PATH)/meson_options.txt
|
||||
$(MESON) introspect --buildoptions $(SRC_PATH)/meson.build | $(PYTHON) \
|
||||
scripts/meson-buildoptions.py > $@.tmp && mv $@.tmp $@
|
||||
endif
|
||||
|
||||
# 4. Rules to bridge to other makefiles
|
||||
@@ -145,8 +139,7 @@ NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \
|
||||
$(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \
|
||||
|
||||
ninja-cmd-goals = $(or $(MAKECMDGOALS), all)
|
||||
ninja-cmd-goals += $(foreach t, $(.check.build-suites), $(.check-$t.deps))
|
||||
ninja-cmd-goals += $(foreach t, $(.bench.build-suites), $(.bench-$t.deps))
|
||||
ninja-cmd-goals += $(foreach t, $(.tests), $(.test.deps.$t))
|
||||
|
||||
makefile-targets := build.ninja ctags TAGS cscope dist clean uninstall
|
||||
# "ninja -t targets" also lists all prerequisites. If build system
|
||||
@@ -236,8 +229,7 @@ distclean: clean
|
||||
rm -f linux-headers/asm
|
||||
rm -Rf .sdk
|
||||
|
||||
find-src-path = find "$(SRC_PATH)" -path "$(SRC_PATH)/meson" -prune -o \
|
||||
-type l -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
|
||||
find-src-path = find "$(SRC_PATH)/" -path "$(SRC_PATH)/meson" -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
|
||||
|
||||
.PHONY: ctags
|
||||
ctags:
|
||||
@@ -258,7 +250,7 @@ gtags:
|
||||
"GTAGS", "Remove old $@ files")
|
||||
$(call quiet-command, \
|
||||
(cd $(SRC_PATH) && \
|
||||
$(find-src-path) -print | gtags -f -), \
|
||||
$(find-src-path) | gtags -f -), \
|
||||
"GTAGS", "Re-index $(SRC_PATH)")
|
||||
|
||||
.PHONY: TAGS
|
||||
|
||||
+7
-7
@@ -59,9 +59,9 @@ of other UNIX targets. The simple steps to build QEMU are:
|
||||
|
||||
Additional information can also be found online via the QEMU website:
|
||||
|
||||
* `<https://wiki.qemu.org/Hosts/Linux>`_
|
||||
* `<https://wiki.qemu.org/Hosts/Mac>`_
|
||||
* `<https://wiki.qemu.org/Hosts/W32>`_
|
||||
* `<https://qemu.org/Hosts/Linux>`_
|
||||
* `<https://qemu.org/Hosts/Mac>`_
|
||||
* `<https://qemu.org/Hosts/W32>`_
|
||||
|
||||
|
||||
Submitting patches
|
||||
@@ -84,8 +84,8 @@ the Developers Guide.
|
||||
Additional information on submitting patches can be found online via
|
||||
the QEMU website
|
||||
|
||||
* `<https://wiki.qemu.org/Contribute/SubmitAPatch>`_
|
||||
* `<https://wiki.qemu.org/Contribute/TrivialPatches>`_
|
||||
* `<https://qemu.org/Contribute/SubmitAPatch>`_
|
||||
* `<https://qemu.org/Contribute/TrivialPatches>`_
|
||||
|
||||
The QEMU website is also maintained under source control.
|
||||
|
||||
@@ -144,7 +144,7 @@ reported via GitLab.
|
||||
|
||||
For additional information on bug reporting consult:
|
||||
|
||||
* `<https://wiki.qemu.org/Contribute/ReportABug>`_
|
||||
* `<https://qemu.org/Contribute/ReportABug>`_
|
||||
|
||||
|
||||
ChangeLog
|
||||
@@ -168,4 +168,4 @@ main methods being email and IRC
|
||||
Information on additional methods of contacting the community can be
|
||||
found online via the QEMU website:
|
||||
|
||||
* `<https://wiki.qemu.org/Contribute/StartHere>`_
|
||||
* `<https://qemu.org/Contribute/StartHere>`_
|
||||
@@ -122,7 +122,6 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||
MemoryRegion *area = section->mr;
|
||||
bool writeable = !area->readonly && !area->rom_device;
|
||||
hv_memory_flags_t flags;
|
||||
uint64_t page_size = qemu_real_host_page_size;
|
||||
|
||||
if (!memory_region_is_ram(area)) {
|
||||
if (writeable) {
|
||||
@@ -136,12 +135,6 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||
}
|
||||
}
|
||||
|
||||
if (!QEMU_IS_ALIGNED(int128_get64(section->size), page_size) ||
|
||||
!QEMU_IS_ALIGNED(section->offset_within_address_space, page_size)) {
|
||||
/* Not page aligned, so we can not map as RAM */
|
||||
add = false;
|
||||
}
|
||||
|
||||
mem = hvf_find_overlap_slot(
|
||||
section->offset_within_address_space,
|
||||
int128_get64(section->size));
|
||||
@@ -328,7 +321,7 @@ static int hvf_accel_init(MachineState *ms)
|
||||
|
||||
s = g_new0(HVFState, 1);
|
||||
|
||||
s->num_slots = ARRAY_SIZE(s->slots);
|
||||
s->num_slots = 32;
|
||||
for (x = 0; x < s->num_slots; ++x) {
|
||||
s->slots[x].size = 0;
|
||||
s->slots[x].slot_id = x;
|
||||
|
||||
@@ -61,10 +61,6 @@
|
||||
#endif
|
||||
#define PAGE_SIZE qemu_real_host_page_size
|
||||
|
||||
#ifndef KVM_GUESTDBG_BLOCKIRQ
|
||||
#define KVM_GUESTDBG_BLOCKIRQ 0
|
||||
#endif
|
||||
|
||||
//#define DEBUG_KVM
|
||||
|
||||
#ifdef DEBUG_KVM
|
||||
@@ -172,8 +168,6 @@ bool kvm_vm_attributes_allowed;
|
||||
bool kvm_direct_msi_allowed;
|
||||
bool kvm_ioeventfd_any_length_allowed;
|
||||
bool kvm_msi_use_devid;
|
||||
bool kvm_has_guest_debug;
|
||||
int kvm_sstep_flags;
|
||||
static bool kvm_immediate_exit;
|
||||
static hwaddr kvm_max_slot_size = ~0;
|
||||
|
||||
@@ -475,7 +469,6 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
||||
cpu->kvm_fd = ret;
|
||||
cpu->kvm_state = s;
|
||||
cpu->vcpu_dirty = true;
|
||||
cpu->dirty_pages = 0;
|
||||
|
||||
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
|
||||
if (mmap_size < 0) {
|
||||
@@ -750,7 +743,6 @@ static uint32_t kvm_dirty_ring_reap_one(KVMState *s, CPUState *cpu)
|
||||
count++;
|
||||
}
|
||||
cpu->kvm_fetch_index = fetch;
|
||||
cpu->dirty_pages += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -2304,11 +2296,6 @@ bool kvm_vcpu_id_is_valid(int vcpu_id)
|
||||
return vcpu_id >= 0 && vcpu_id < kvm_max_vcpu_id(s);
|
||||
}
|
||||
|
||||
bool kvm_dirty_ring_enabled(void)
|
||||
{
|
||||
return kvm_state->kvm_dirty_ring_size ? true : false;
|
||||
}
|
||||
|
||||
static int kvm_init(MachineState *ms)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
@@ -2570,25 +2557,6 @@ static int kvm_init(MachineState *ms)
|
||||
kvm_ioeventfd_any_length_allowed =
|
||||
(kvm_check_extension(s, KVM_CAP_IOEVENTFD_ANY_LENGTH) > 0);
|
||||
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
kvm_has_guest_debug =
|
||||
(kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0);
|
||||
#endif
|
||||
|
||||
kvm_sstep_flags = 0;
|
||||
if (kvm_has_guest_debug) {
|
||||
kvm_sstep_flags = SSTEP_ENABLE;
|
||||
|
||||
#if defined KVM_CAP_SET_GUEST_DEBUG2
|
||||
int guest_debug_flags =
|
||||
kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG2);
|
||||
|
||||
if (guest_debug_flags & KVM_GUESTDBG_BLOCKIRQ) {
|
||||
kvm_sstep_flags |= SSTEP_NOIRQ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
kvm_state = s;
|
||||
|
||||
ret = kvm_arch_init(ms, s);
|
||||
@@ -3218,10 +3186,6 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
|
||||
|
||||
if (cpu->singlestep_enabled) {
|
||||
data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
|
||||
|
||||
if (cpu->singlestep_enabled & SSTEP_NOIRQ) {
|
||||
data.dbg.control |= KVM_GUESTDBG_BLOCKIRQ;
|
||||
}
|
||||
}
|
||||
kvm_arch_update_guest_debug(cpu, &data.dbg);
|
||||
|
||||
|
||||
@@ -3,5 +3,6 @@ kvm_ss.add(files(
|
||||
'kvm-all.c',
|
||||
'kvm-accel-ops.c',
|
||||
))
|
||||
kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
|
||||
|
||||
specific_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sev.h"
|
||||
#include "sysemu/sev.h"
|
||||
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
{
|
||||
@@ -147,9 +147,4 @@ bool kvm_arm_supports_user_irq(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool kvm_dirty_ring_enabled(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -13,43 +13,56 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
static void atomic_trace_rmw_pre(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi)
|
||||
static uint16_t atomic_trace_rmw_pre(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi)
|
||||
{
|
||||
CPUState *cpu = env_cpu(env);
|
||||
uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), false);
|
||||
|
||||
trace_guest_rmw_before_exec(cpu, addr, oi);
|
||||
trace_guest_mem_before_exec(cpu, addr, info);
|
||||
trace_guest_mem_before_exec(cpu, addr, info | TRACE_MEM_ST);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi)
|
||||
uint16_t info)
|
||||
{
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_RW);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info | TRACE_MEM_ST);
|
||||
}
|
||||
|
||||
#if HAVE_ATOMIC128
|
||||
static void atomic_trace_ld_pre(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi)
|
||||
static uint16_t atomic_trace_ld_pre(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi)
|
||||
{
|
||||
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
|
||||
uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void atomic_trace_ld_post(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi)
|
||||
uint16_t info)
|
||||
{
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info);
|
||||
}
|
||||
|
||||
static void atomic_trace_st_pre(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi)
|
||||
static uint16_t atomic_trace_st_pre(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi)
|
||||
{
|
||||
trace_guest_st_before_exec(env_cpu(env), addr, oi);
|
||||
uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void atomic_trace_st_post(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi)
|
||||
uint16_t info)
|
||||
{
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+37
-36
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/plugin.h"
|
||||
#include "trace/mem.h"
|
||||
|
||||
#if DATA_SIZE == 16
|
||||
# define SUFFIX o
|
||||
@@ -71,77 +72,77 @@
|
||||
|
||||
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
ABI_TYPE cmpv, ABI_TYPE newv,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ | PAGE_WRITE, retaddr);
|
||||
DATA_TYPE ret;
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||
|
||||
atomic_trace_rmw_pre(env, addr, oi);
|
||||
#if DATA_SIZE == 16
|
||||
ret = atomic16_cmpxchg(haddr, cmpv, newv);
|
||||
#else
|
||||
ret = qatomic_cmpxchg__nocheck(haddr, cmpv, newv);
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if DATA_SIZE >= 16
|
||||
#if HAVE_ATOMIC128
|
||||
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ, retaddr);
|
||||
DATA_TYPE val;
|
||||
uint16_t info = atomic_trace_ld_pre(env, addr, oi);
|
||||
|
||||
atomic_trace_ld_pre(env, addr, oi);
|
||||
val = atomic16_read(haddr);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_ld_post(env, addr, oi);
|
||||
atomic_trace_ld_post(env, addr, info);
|
||||
return val;
|
||||
}
|
||||
|
||||
void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_WRITE, retaddr);
|
||||
uint16_t info = atomic_trace_st_pre(env, addr, oi);
|
||||
|
||||
atomic_trace_st_pre(env, addr, oi);
|
||||
atomic16_set(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_st_post(env, addr, oi);
|
||||
atomic_trace_st_post(env, addr, info);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ | PAGE_WRITE, retaddr);
|
||||
DATA_TYPE ret;
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||
|
||||
atomic_trace_rmw_pre(env, addr, oi);
|
||||
ret = qatomic_xchg__nocheck(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define GEN_ATOMIC_HELPER(X) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
|
||||
ABI_TYPE val, TCGMemOpIdx oi, uintptr_t retaddr) \
|
||||
{ \
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||
DATA_TYPE ret; \
|
||||
atomic_trace_rmw_pre(env, addr, oi); \
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||
ret = qatomic_##X(haddr, val); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
@@ -166,12 +167,12 @@ GEN_ATOMIC_HELPER(xor_fetch)
|
||||
*/
|
||||
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
|
||||
ABI_TYPE xval, TCGMemOpIdx oi, uintptr_t retaddr) \
|
||||
{ \
|
||||
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||
XDATA_TYPE cmp, old, new, val = xval; \
|
||||
atomic_trace_rmw_pre(env, addr, oi); \
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||
smp_mb(); \
|
||||
cmp = qatomic_read__nocheck(haddr); \
|
||||
do { \
|
||||
@@ -179,7 +180,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
cmp = qatomic_cmpxchg__nocheck(haddr, old, new); \
|
||||
} while (cmp != old); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return RET; \
|
||||
}
|
||||
|
||||
@@ -210,78 +211,78 @@ GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
|
||||
|
||||
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
ABI_TYPE cmpv, ABI_TYPE newv,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ | PAGE_WRITE, retaddr);
|
||||
DATA_TYPE ret;
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||
|
||||
atomic_trace_rmw_pre(env, addr, oi);
|
||||
#if DATA_SIZE == 16
|
||||
ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||
#else
|
||||
ret = qatomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return BSWAP(ret);
|
||||
}
|
||||
|
||||
#if DATA_SIZE >= 16
|
||||
#if HAVE_ATOMIC128
|
||||
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ, retaddr);
|
||||
DATA_TYPE val;
|
||||
uint16_t info = atomic_trace_ld_pre(env, addr, oi);
|
||||
|
||||
atomic_trace_ld_pre(env, addr, oi);
|
||||
val = atomic16_read(haddr);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_ld_post(env, addr, oi);
|
||||
atomic_trace_ld_post(env, addr, info);
|
||||
return BSWAP(val);
|
||||
}
|
||||
|
||||
void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_WRITE, retaddr);
|
||||
uint16_t info = atomic_trace_st_pre(env, addr, oi);
|
||||
|
||||
atomic_trace_st_pre(env, addr, oi);
|
||||
val = BSWAP(val);
|
||||
atomic16_set(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_st_post(env, addr, oi);
|
||||
atomic_trace_st_post(env, addr, info);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ | PAGE_WRITE, retaddr);
|
||||
ABI_TYPE ret;
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||
|
||||
atomic_trace_rmw_pre(env, addr, oi);
|
||||
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return BSWAP(ret);
|
||||
}
|
||||
|
||||
#define GEN_ATOMIC_HELPER(X) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
|
||||
ABI_TYPE val, TCGMemOpIdx oi, uintptr_t retaddr) \
|
||||
{ \
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||
DATA_TYPE ret; \
|
||||
atomic_trace_rmw_pre(env, addr, oi); \
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||
ret = qatomic_##X(haddr, BSWAP(val)); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return BSWAP(ret); \
|
||||
}
|
||||
|
||||
@@ -303,12 +304,12 @@ GEN_ATOMIC_HELPER(xor_fetch)
|
||||
*/
|
||||
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
|
||||
ABI_TYPE xval, TCGMemOpIdx oi, uintptr_t retaddr) \
|
||||
{ \
|
||||
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||
XDATA_TYPE ldo, ldn, old, new, val = xval; \
|
||||
atomic_trace_rmw_pre(env, addr, oi); \
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||
smp_mb(); \
|
||||
ldn = qatomic_read__nocheck(haddr); \
|
||||
do { \
|
||||
@@ -316,7 +317,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ldn = qatomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \
|
||||
} while (ldo != ldn); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return RET; \
|
||||
}
|
||||
|
||||
|
||||
+10
-64
@@ -20,9 +20,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-machine.h"
|
||||
#include "qapi/type-helpers.h"
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
#include "trace.h"
|
||||
#include "disas/disas.h"
|
||||
@@ -41,7 +38,6 @@
|
||||
#include "exec/cpu-all.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "tb-hash.h"
|
||||
#include "tb-context.h"
|
||||
@@ -387,17 +383,6 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
|
||||
cc->set_pc(cpu, last_tb->pc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If gdb single-step, and we haven't raised another exception,
|
||||
* raise a debug exception. Single-step with another exception
|
||||
* is handled in cpu_handle_exception.
|
||||
*/
|
||||
if (unlikely(cpu->singlestep_enabled) && cpu->exception_index == -1) {
|
||||
cpu->exception_index = EXCP_DEBUG;
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
|
||||
return last_tb;
|
||||
}
|
||||
|
||||
@@ -466,7 +451,6 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
* memory.
|
||||
*/
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
clear_helper_retaddr();
|
||||
tcg_debug_assert(!have_mmap_lock());
|
||||
#endif
|
||||
if (qemu_mutex_iothread_locked()) {
|
||||
@@ -476,6 +460,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* As we start the exclusive region before codegen we must still
|
||||
* be in the region if we longjump out of either the codegen or
|
||||
@@ -721,15 +706,6 @@ static inline bool need_replay_interrupt(int interrupt_request)
|
||||
static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
TranslationBlock **last_tb)
|
||||
{
|
||||
/*
|
||||
* If we have requested custom cflags with CF_NOIRQ we should
|
||||
* skip checking here. Any pending interrupts will get picked up
|
||||
* by the next TB we execute under normal cflags.
|
||||
*/
|
||||
if (cpu->cflags_next_tb != -1 && cpu->cflags_next_tb & CF_NOIRQ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clear the interrupt flag now since we're processing
|
||||
* cpu->interrupt_request and cpu->exit_request.
|
||||
* Ensure zeroing happens before reading cpu->exit_request or
|
||||
@@ -929,7 +905,6 @@ int cpu_exec(CPUState *cpu)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
clear_helper_retaddr();
|
||||
tcg_debug_assert(!have_mmap_lock());
|
||||
#endif
|
||||
if (qemu_mutex_iothread_locked()) {
|
||||
@@ -1042,52 +1017,23 @@ void tcg_exec_unrealizefn(CPUState *cpu)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
void dump_drift_info(GString *buf)
|
||||
void dump_drift_info(void)
|
||||
{
|
||||
if (!icount_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n",
|
||||
(cpu_get_clock() - icount_get()) / SCALE_MS);
|
||||
qemu_printf("Host - Guest clock %"PRIi64" ms\n",
|
||||
(cpu_get_clock() - icount_get()) / SCALE_MS);
|
||||
if (icount_align_option) {
|
||||
g_string_append_printf(buf, "Max guest delay %"PRIi64" ms\n",
|
||||
-max_delay / SCALE_MS);
|
||||
g_string_append_printf(buf, "Max guest advance %"PRIi64" ms\n",
|
||||
max_advance / SCALE_MS);
|
||||
qemu_printf("Max guest delay %"PRIi64" ms\n",
|
||||
-max_delay / SCALE_MS);
|
||||
qemu_printf("Max guest advance %"PRIi64" ms\n",
|
||||
max_advance / SCALE_MS);
|
||||
} else {
|
||||
g_string_append_printf(buf, "Max guest delay NA\n");
|
||||
g_string_append_printf(buf, "Max guest advance NA\n");
|
||||
qemu_printf("Max guest delay NA\n");
|
||||
qemu_printf("Max guest advance NA\n");
|
||||
}
|
||||
}
|
||||
|
||||
HumanReadableText *qmp_x_query_jit(Error **errp)
|
||||
{
|
||||
g_autoptr(GString) buf = g_string_new("");
|
||||
|
||||
if (!tcg_enabled()) {
|
||||
error_setg(errp, "JIT information is only available with accel=tcg");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dump_exec_info(buf);
|
||||
dump_drift_info(buf);
|
||||
|
||||
return human_readable_text_from_str(buf);
|
||||
}
|
||||
|
||||
HumanReadableText *qmp_x_query_opcount(Error **errp)
|
||||
{
|
||||
g_autoptr(GString) buf = g_string_new("");
|
||||
|
||||
if (!tcg_enabled()) {
|
||||
error_setg(errp, "Opcode count information is only available with accel=tcg");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dump_opcount_info(buf);
|
||||
|
||||
return human_readable_text_from_str(buf);
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
+317
-167
@@ -34,12 +34,12 @@
|
||||
#include "qemu/atomic128.h"
|
||||
#include "exec/translate-all.h"
|
||||
#include "trace/trace-root.h"
|
||||
#include "trace/mem.h"
|
||||
#include "tb-hash.h"
|
||||
#include "internal.h"
|
||||
#ifdef CONFIG_PLUGIN
|
||||
#include "qemu/plugin-memory.h"
|
||||
#endif
|
||||
#include "tcg/tcg-ldst.h"
|
||||
|
||||
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
|
||||
/* #define DEBUG_TLB */
|
||||
@@ -1749,7 +1749,7 @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx,
|
||||
* @prot may be PAGE_READ, PAGE_WRITE, or PAGE_READ|PAGE_WRITE.
|
||||
*/
|
||||
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, int size, int prot,
|
||||
TCGMemOpIdx oi, int size, int prot,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
size_t mmu_idx = get_mmuidx(oi);
|
||||
@@ -1840,25 +1840,6 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||
cpu_loop_exit_atomic(env_cpu(env), retaddr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that we have passed the correct MemOp to the correct function.
|
||||
*
|
||||
* In the case of the helper_*_mmu functions, we will have done this by
|
||||
* using the MemOp to look up the helper during code generation.
|
||||
*
|
||||
* In the case of the cpu_*_mmu functions, this is up to the caller.
|
||||
* We could present one function to target code, and dispatch based on
|
||||
* the MemOp, but so far we have worked hard to avoid an indirect function
|
||||
* call along the memory path.
|
||||
*/
|
||||
static void validate_memop(MemOpIdx oi, MemOp expected)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
MemOp have = get_memop(oi) & (MO_SIZE | MO_BSWAP);
|
||||
assert(have == expected);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Load Helpers
|
||||
*
|
||||
@@ -1869,7 +1850,7 @@ static void validate_memop(MemOpIdx oi, MemOp expected)
|
||||
*/
|
||||
|
||||
typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
TCGMemOpIdx oi, uintptr_t retaddr);
|
||||
|
||||
static inline uint64_t QEMU_ALWAYS_INLINE
|
||||
load_memop(const void *haddr, MemOp op)
|
||||
@@ -1895,7 +1876,7 @@ load_memop(const void *haddr, MemOp op)
|
||||
}
|
||||
|
||||
static inline uint64_t QEMU_ALWAYS_INLINE
|
||||
load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
|
||||
load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
|
||||
uintptr_t retaddr, MemOp op, bool code_read,
|
||||
FullLoadHelper *full_load)
|
||||
{
|
||||
@@ -2010,86 +1991,79 @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
|
||||
*/
|
||||
|
||||
static uint64_t full_ldub_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_UB);
|
||||
return load_helper(env, addr, oi, retaddr, MO_UB, false, full_ldub_mmu);
|
||||
}
|
||||
|
||||
tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return full_ldub_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
static uint64_t full_le_lduw_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_LEUW);
|
||||
return load_helper(env, addr, oi, retaddr, MO_LEUW, false,
|
||||
full_le_lduw_mmu);
|
||||
}
|
||||
|
||||
tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return full_le_lduw_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
static uint64_t full_be_lduw_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_BEUW);
|
||||
return load_helper(env, addr, oi, retaddr, MO_BEUW, false,
|
||||
full_be_lduw_mmu);
|
||||
}
|
||||
|
||||
tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return full_be_lduw_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
static uint64_t full_le_ldul_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_LEUL);
|
||||
return load_helper(env, addr, oi, retaddr, MO_LEUL, false,
|
||||
full_le_ldul_mmu);
|
||||
}
|
||||
|
||||
tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return full_le_ldul_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
static uint64_t full_be_ldul_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_BEUL);
|
||||
return load_helper(env, addr, oi, retaddr, MO_BEUL, false,
|
||||
full_be_ldul_mmu);
|
||||
}
|
||||
|
||||
tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return full_be_ldul_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_LEQ);
|
||||
return load_helper(env, addr, oi, retaddr, MO_LEQ, false,
|
||||
helper_le_ldq_mmu);
|
||||
}
|
||||
|
||||
uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_BEQ);
|
||||
return load_helper(env, addr, oi, retaddr, MO_BEQ, false,
|
||||
helper_be_ldq_mmu);
|
||||
}
|
||||
@@ -2101,31 +2075,31 @@ uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
|
||||
|
||||
|
||||
tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return (int8_t)helper_ret_ldub_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return (int16_t)helper_le_lduw_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return (int16_t)helper_be_lduw_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return (int32_t)helper_le_ldul_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return (int32_t)helper_be_ldul_mmu(env, addr, oi, retaddr);
|
||||
}
|
||||
@@ -2135,56 +2109,193 @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
|
||||
*/
|
||||
|
||||
static inline uint64_t cpu_load_helper(CPUArchState *env, abi_ptr addr,
|
||||
MemOpIdx oi, uintptr_t retaddr,
|
||||
FullLoadHelper *full_load)
|
||||
int mmu_idx, uintptr_t retaddr,
|
||||
MemOp op, FullLoadHelper *full_load)
|
||||
{
|
||||
uint16_t meminfo;
|
||||
TCGMemOpIdx oi;
|
||||
uint64_t ret;
|
||||
|
||||
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
|
||||
meminfo = trace_mem_get_info(op, mmu_idx, false);
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, meminfo);
|
||||
|
||||
op &= ~MO_SIGN;
|
||||
oi = make_memop_idx(op, mmu_idx);
|
||||
ret = full_load(env, addr, oi, retaddr);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
|
||||
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, meminfo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra)
|
||||
uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_load_helper(env, addr, oi, ra, full_ldub_mmu);
|
||||
return cpu_load_helper(env, addr, mmu_idx, ra, MO_UB, full_ldub_mmu);
|
||||
}
|
||||
|
||||
uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr addr,
|
||||
MemOpIdx oi, uintptr_t ra)
|
||||
int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_load_helper(env, addr, oi, ra, full_be_lduw_mmu);
|
||||
return (int8_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_SB,
|
||||
full_ldub_mmu);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
|
||||
MemOpIdx oi, uintptr_t ra)
|
||||
uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_load_helper(env, addr, oi, ra, full_be_ldul_mmu);
|
||||
return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEUW, full_be_lduw_mmu);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
|
||||
MemOpIdx oi, uintptr_t ra)
|
||||
int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_load_helper(env, addr, oi, MO_BEQ, helper_be_ldq_mmu);
|
||||
return (int16_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_BESW,
|
||||
full_be_lduw_mmu);
|
||||
}
|
||||
|
||||
uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
|
||||
MemOpIdx oi, uintptr_t ra)
|
||||
uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_load_helper(env, addr, oi, ra, full_le_lduw_mmu);
|
||||
return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEUL, full_be_ldul_mmu);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr addr,
|
||||
MemOpIdx oi, uintptr_t ra)
|
||||
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_load_helper(env, addr, oi, ra, full_le_ldul_mmu);
|
||||
return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEQ, helper_be_ldq_mmu);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
|
||||
MemOpIdx oi, uintptr_t ra)
|
||||
uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_load_helper(env, addr, oi, ra, helper_le_ldq_mmu);
|
||||
return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEUW, full_le_lduw_mmu);
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return (int16_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_LESW,
|
||||
full_le_lduw_mmu);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEUL, full_le_ldul_mmu);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEQ, helper_le_ldq_mmu);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldub_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
return cpu_ldub_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
int cpu_ldsb_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr)
|
||||
{
|
||||
return cpu_ldsb_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
return cpu_lduw_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr)
|
||||
{
|
||||
return cpu_ldsw_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
return cpu_ldl_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
return cpu_ldq_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
return cpu_lduw_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr)
|
||||
{
|
||||
return cpu_ldsw_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
return cpu_ldl_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
return cpu_ldq_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldub_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_ldub_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
int cpu_ldsb_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_ldsb_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_lduw_be_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_ldsw_be_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_ldl_be_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_ldq_be_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_lduw_le_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_ldsw_le_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_ldl_le_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_data(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
return cpu_ldq_le_data_ra(env, ptr, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2221,9 +2332,6 @@ store_memop(void *haddr, uint64_t val, MemOp op)
|
||||
}
|
||||
}
|
||||
|
||||
static void full_stb_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
|
||||
static void __attribute__((noinline))
|
||||
store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
uintptr_t retaddr, size_t size, uintptr_t mmu_idx,
|
||||
@@ -2233,7 +2341,7 @@ store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
uintptr_t index, index2;
|
||||
CPUTLBEntry *entry, *entry2;
|
||||
target_ulong page2, tlb_addr, tlb_addr2;
|
||||
MemOpIdx oi;
|
||||
TCGMemOpIdx oi;
|
||||
size_t size2;
|
||||
int i;
|
||||
|
||||
@@ -2287,20 +2395,20 @@ store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
for (i = 0; i < size; ++i) {
|
||||
/* Big-endian extract. */
|
||||
uint8_t val8 = val >> (((size - 1) * 8) - (i * 8));
|
||||
full_stb_mmu(env, addr + i, val8, oi, retaddr);
|
||||
helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < size; ++i) {
|
||||
/* Little-endian extract. */
|
||||
uint8_t val8 = val >> (i * 8);
|
||||
full_stb_mmu(env, addr + i, val8, oi, retaddr);
|
||||
helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void QEMU_ALWAYS_INLINE
|
||||
store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr, MemOp op)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr, MemOp op)
|
||||
{
|
||||
uintptr_t mmu_idx = get_mmuidx(oi);
|
||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
||||
@@ -2396,83 +2504,46 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
store_memop(haddr, val, op);
|
||||
}
|
||||
|
||||
static void __attribute__((noinline))
|
||||
full_stb_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void __attribute__((noinline))
|
||||
helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_UB);
|
||||
store_helper(env, addr, val, oi, retaddr, MO_UB);
|
||||
}
|
||||
|
||||
void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
full_stb_mmu(env, addr, val, oi, retaddr);
|
||||
}
|
||||
|
||||
static void full_le_stw_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_LEUW);
|
||||
store_helper(env, addr, val, oi, retaddr, MO_LEUW);
|
||||
}
|
||||
|
||||
void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
full_le_stw_mmu(env, addr, val, oi, retaddr);
|
||||
}
|
||||
|
||||
static void full_be_stw_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_BEUW);
|
||||
store_helper(env, addr, val, oi, retaddr, MO_BEUW);
|
||||
}
|
||||
|
||||
void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
full_be_stw_mmu(env, addr, val, oi, retaddr);
|
||||
}
|
||||
|
||||
static void full_le_stl_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_LEUL);
|
||||
store_helper(env, addr, val, oi, retaddr, MO_LEUL);
|
||||
}
|
||||
|
||||
void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
full_le_stl_mmu(env, addr, val, oi, retaddr);
|
||||
}
|
||||
|
||||
static void full_be_stl_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_BEUL);
|
||||
store_helper(env, addr, val, oi, retaddr, MO_BEUL);
|
||||
}
|
||||
|
||||
void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
full_be_stl_mmu(env, addr, val, oi, retaddr);
|
||||
}
|
||||
|
||||
void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_LEQ);
|
||||
store_helper(env, addr, val, oi, retaddr, MO_LEQ);
|
||||
}
|
||||
|
||||
void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
validate_memop(oi, MO_BEQ);
|
||||
store_helper(env, addr, val, oi, retaddr, MO_BEQ);
|
||||
}
|
||||
|
||||
@@ -2480,61 +2551,140 @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
* Store Helpers for cpu_ldst.h
|
||||
*/
|
||||
|
||||
typedef void FullStoreHelper(CPUArchState *env, target_ulong addr,
|
||||
uint64_t val, MemOpIdx oi, uintptr_t retaddr);
|
||||
|
||||
static inline void cpu_store_helper(CPUArchState *env, target_ulong addr,
|
||||
uint64_t val, MemOpIdx oi, uintptr_t ra,
|
||||
FullStoreHelper *full_store)
|
||||
static inline void QEMU_ALWAYS_INLINE
|
||||
cpu_store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
int mmu_idx, uintptr_t retaddr, MemOp op)
|
||||
{
|
||||
trace_guest_st_before_exec(env_cpu(env), addr, oi);
|
||||
full_store(env, addr, val, oi, ra);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
|
||||
TCGMemOpIdx oi;
|
||||
uint16_t meminfo;
|
||||
|
||||
meminfo = trace_mem_get_info(op, mmu_idx, true);
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, meminfo);
|
||||
|
||||
oi = make_memop_idx(op, mmu_idx);
|
||||
store_helper(env, addr, val, oi, retaddr, op);
|
||||
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, meminfo);
|
||||
}
|
||||
|
||||
void cpu_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void cpu_stb_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
cpu_store_helper(env, addr, val, oi, retaddr, full_stb_mmu);
|
||||
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_UB);
|
||||
}
|
||||
|
||||
void cpu_stw_be_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void cpu_stw_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
cpu_store_helper(env, addr, val, oi, retaddr, full_be_stw_mmu);
|
||||
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEUW);
|
||||
}
|
||||
|
||||
void cpu_stl_be_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void cpu_stl_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
cpu_store_helper(env, addr, val, oi, retaddr, full_be_stl_mmu);
|
||||
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEUL);
|
||||
}
|
||||
|
||||
void cpu_stq_be_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void cpu_stq_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
cpu_store_helper(env, addr, val, oi, retaddr, helper_be_stq_mmu);
|
||||
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEQ);
|
||||
}
|
||||
|
||||
void cpu_stw_le_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void cpu_stw_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
cpu_store_helper(env, addr, val, oi, retaddr, full_le_stw_mmu);
|
||||
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEUW);
|
||||
}
|
||||
|
||||
void cpu_stl_le_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void cpu_stl_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
cpu_store_helper(env, addr, val, oi, retaddr, full_le_stl_mmu);
|
||||
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEUL);
|
||||
}
|
||||
|
||||
void cpu_stq_le_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
void cpu_stq_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
cpu_store_helper(env, addr, val, oi, retaddr, helper_le_stq_mmu);
|
||||
cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEQ);
|
||||
}
|
||||
|
||||
#include "ldst_common.c.inc"
|
||||
void cpu_stb_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
cpu_stb_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
void cpu_stw_be_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
cpu_stw_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
void cpu_stl_be_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
cpu_stl_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
void cpu_stq_be_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uint64_t val, uintptr_t retaddr)
|
||||
{
|
||||
cpu_stq_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
void cpu_stw_le_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
cpu_stw_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
void cpu_stl_le_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
cpu_stl_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
void cpu_stq_le_data_ra(CPUArchState *env, target_ulong ptr,
|
||||
uint64_t val, uintptr_t retaddr)
|
||||
{
|
||||
cpu_stq_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
|
||||
}
|
||||
|
||||
void cpu_stb_data(CPUArchState *env, target_ulong ptr, uint32_t val)
|
||||
{
|
||||
cpu_stb_data_ra(env, ptr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stw_be_data(CPUArchState *env, target_ulong ptr, uint32_t val)
|
||||
{
|
||||
cpu_stw_be_data_ra(env, ptr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stl_be_data(CPUArchState *env, target_ulong ptr, uint32_t val)
|
||||
{
|
||||
cpu_stl_be_data_ra(env, ptr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stq_be_data(CPUArchState *env, target_ulong ptr, uint64_t val)
|
||||
{
|
||||
cpu_stq_be_data_ra(env, ptr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stw_le_data(CPUArchState *env, target_ulong ptr, uint32_t val)
|
||||
{
|
||||
cpu_stw_le_data_ra(env, ptr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stl_le_data(CPUArchState *env, target_ulong ptr, uint32_t val)
|
||||
{
|
||||
cpu_stl_le_data_ra(env, ptr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stq_le_data(CPUArchState *env, target_ulong ptr, uint64_t val)
|
||||
{
|
||||
cpu_stq_le_data_ra(env, ptr, val, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* First set of functions passes in OI and RETADDR.
|
||||
@@ -2571,49 +2721,49 @@ void cpu_stq_le_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||
/* Code access functions. */
|
||||
|
||||
static uint64_t full_ldub_code(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return load_helper(env, addr, oi, retaddr, MO_8, true, full_ldub_code);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_UB, cpu_mmu_index(env, true));
|
||||
TCGMemOpIdx oi = make_memop_idx(MO_UB, cpu_mmu_index(env, true));
|
||||
return full_ldub_code(env, addr, oi, 0);
|
||||
}
|
||||
|
||||
static uint64_t full_lduw_code(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return load_helper(env, addr, oi, retaddr, MO_TEUW, true, full_lduw_code);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUW, cpu_mmu_index(env, true));
|
||||
TCGMemOpIdx oi = make_memop_idx(MO_TEUW, cpu_mmu_index(env, true));
|
||||
return full_lduw_code(env, addr, oi, 0);
|
||||
}
|
||||
|
||||
static uint64_t full_ldl_code(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return load_helper(env, addr, oi, retaddr, MO_TEUL, true, full_ldl_code);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUL, cpu_mmu_index(env, true));
|
||||
TCGMemOpIdx oi = make_memop_idx(MO_TEUL, cpu_mmu_index(env, true));
|
||||
return full_ldl_code(env, addr, oi, 0);
|
||||
}
|
||||
|
||||
static uint64_t full_ldq_code(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return load_helper(env, addr, oi, retaddr, MO_TEQ, true, full_ldq_code);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_TEQ, cpu_mmu_index(env, true));
|
||||
TCGMemOpIdx oi = make_memop_idx(MO_TEQ, cpu_mmu_index(env, true));
|
||||
return full_ldq_code(env, addr, oi, 0);
|
||||
}
|
||||
+18
-4
@@ -1,15 +1,29 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-machine.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "sysemu/tcg.h"
|
||||
|
||||
static void hmp_info_jit(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
if (!tcg_enabled()) {
|
||||
error_report("JIT information is only available with accel=tcg");
|
||||
return;
|
||||
}
|
||||
|
||||
dump_exec_info();
|
||||
dump_drift_info();
|
||||
}
|
||||
|
||||
static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
dump_opcount_info();
|
||||
}
|
||||
|
||||
static void hmp_tcg_register(void)
|
||||
{
|
||||
monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
|
||||
monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount);
|
||||
monitor_register_hmp("jit", true, hmp_info_jit);
|
||||
monitor_register_hmp("opcount", true, hmp_info_opcount);
|
||||
}
|
||||
|
||||
type_init(hmp_tcg_register);
|
||||
@@ -1,307 +0,0 @@
|
||||
/*
|
||||
* Routines common to user and system emulation of load/store.
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
||||
return cpu_ldb_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return (int8_t)cpu_ldub_mmuidx_ra(env, addr, mmu_idx, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
|
||||
return cpu_ldw_be_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return (int16_t)cpu_lduw_be_mmuidx_ra(env, addr, mmu_idx, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
|
||||
return cpu_ldl_be_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx);
|
||||
return cpu_ldq_be_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
|
||||
return cpu_ldw_le_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return (int16_t)cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
|
||||
return cpu_ldl_le_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx);
|
||||
return cpu_ldq_le_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
||||
cpu_stb_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
|
||||
cpu_stw_be_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
|
||||
cpu_stl_be_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx);
|
||||
cpu_stq_be_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
|
||||
cpu_stw_le_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
|
||||
cpu_stl_le_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx);
|
||||
cpu_stq_le_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
|
||||
uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldub_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return (int8_t)cpu_ldub_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_lduw_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return (int16_t)cpu_lduw_be_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldl_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldq_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_lduw_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return (int16_t)cpu_lduw_le_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldl_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldq_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stb_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stb_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stw_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stl_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint64_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stq_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stw_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stl_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint64_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stq_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
|
||||
uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldub_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
int cpu_ldsb_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return (int8_t)cpu_ldub_data(env, addr);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_lduw_be_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return (int16_t)cpu_lduw_be_data(env, addr);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldl_be_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldq_be_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_lduw_le_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return (int16_t)cpu_lduw_le_data(env, addr);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldl_le_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldq_le_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
void cpu_stb_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stb_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stw_be_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stw_be_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stl_be_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stl_be_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stq_be_data(CPUArchState *env, abi_ptr addr, uint64_t val)
|
||||
{
|
||||
cpu_stq_be_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stw_le_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stw_le_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stl_le_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stl_le_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stq_le_data(CPUArchState *env, abi_ptr addr, uint64_t val)
|
||||
{
|
||||
cpu_stq_le_data_ra(env, addr, val, 0);
|
||||
}
|
||||
@@ -10,7 +10,7 @@ tcg_ss.add(files(
|
||||
))
|
||||
tcg_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user-exec.c'))
|
||||
tcg_ss.add(when: 'CONFIG_SOFTMMU', if_false: files('user-exec-stub.c'))
|
||||
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c')])
|
||||
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c'), libdl])
|
||||
specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
|
||||
|
||||
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(
|
||||
|
||||
+76
-87
@@ -45,6 +45,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "trace/mem.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/plugin-gen.h"
|
||||
#include "exec/translator.h"
|
||||
@@ -162,7 +163,11 @@ static void gen_empty_mem_helper(void)
|
||||
static void gen_plugin_cb_start(enum plugin_gen_from from,
|
||||
enum plugin_gen_cb type, unsigned wr)
|
||||
{
|
||||
TCGOp *op;
|
||||
|
||||
tcg_gen_plugin_cb_start(from, type, wr);
|
||||
op = tcg_last_op();
|
||||
QSIMPLEQ_INSERT_TAIL(&tcg_ctx->plugin_ops, op, plugin_link);
|
||||
}
|
||||
|
||||
static void gen_wrapped(enum plugin_gen_from from,
|
||||
@@ -206,9 +211,9 @@ static void gen_mem_wrapped(enum plugin_gen_cb type,
|
||||
const union mem_gen_fn *f, TCGv addr,
|
||||
uint32_t info, bool is_mem)
|
||||
{
|
||||
enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info);
|
||||
int wr = !!(info & TRACE_MEM_ST);
|
||||
|
||||
gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, type, rw);
|
||||
gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, type, wr);
|
||||
if (is_mem) {
|
||||
f->mem_fn(addr, info);
|
||||
} else {
|
||||
@@ -702,6 +707,62 @@ static void plugin_gen_disable_mem_helper(const struct qemu_plugin_tb *ptb,
|
||||
inject_mem_disable_helper(insn, begin_op);
|
||||
}
|
||||
|
||||
static void plugin_inject_cb(const struct qemu_plugin_tb *ptb, TCGOp *begin_op,
|
||||
int insn_idx)
|
||||
{
|
||||
enum plugin_gen_from from = begin_op->args[0];
|
||||
enum plugin_gen_cb type = begin_op->args[1];
|
||||
|
||||
switch (from) {
|
||||
case PLUGIN_GEN_FROM_TB:
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_UDATA:
|
||||
plugin_gen_tb_udata(ptb, begin_op);
|
||||
return;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_tb_inline(ptb, begin_op);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
case PLUGIN_GEN_FROM_INSN:
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_UDATA:
|
||||
plugin_gen_insn_udata(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_insn_inline(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
case PLUGIN_GEN_ENABLE_MEM_HELPER:
|
||||
plugin_gen_enable_mem_helper(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
case PLUGIN_GEN_FROM_MEM:
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_MEM:
|
||||
plugin_gen_mem_regular(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_mem_inline(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
case PLUGIN_GEN_AFTER_INSN:
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_DISABLE_MEM_HELPER:
|
||||
plugin_gen_disable_mem_helper(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
/* #define DEBUG_PLUGIN_GEN_OPS */
|
||||
static void pr_ops(void)
|
||||
{
|
||||
@@ -759,95 +820,21 @@ static void pr_ops(void)
|
||||
static void plugin_gen_inject(const struct qemu_plugin_tb *plugin_tb)
|
||||
{
|
||||
TCGOp *op;
|
||||
int insn_idx = -1;
|
||||
int insn_idx;
|
||||
|
||||
pr_ops();
|
||||
insn_idx = -1;
|
||||
QSIMPLEQ_FOREACH(op, &tcg_ctx->plugin_ops, plugin_link) {
|
||||
enum plugin_gen_from from = op->args[0];
|
||||
enum plugin_gen_cb type = op->args[1];
|
||||
|
||||
QTAILQ_FOREACH(op, &tcg_ctx->ops, link) {
|
||||
switch (op->opc) {
|
||||
case INDEX_op_insn_start:
|
||||
tcg_debug_assert(op->opc == INDEX_op_plugin_cb_start);
|
||||
/* ENABLE_MEM_HELPER is the first callback of an instruction */
|
||||
if (from == PLUGIN_GEN_FROM_INSN &&
|
||||
type == PLUGIN_GEN_ENABLE_MEM_HELPER) {
|
||||
insn_idx++;
|
||||
break;
|
||||
case INDEX_op_plugin_cb_start:
|
||||
{
|
||||
enum plugin_gen_from from = op->args[0];
|
||||
enum plugin_gen_cb type = op->args[1];
|
||||
|
||||
switch (from) {
|
||||
case PLUGIN_GEN_FROM_TB:
|
||||
{
|
||||
g_assert(insn_idx == -1);
|
||||
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_UDATA:
|
||||
plugin_gen_tb_udata(plugin_tb, op);
|
||||
break;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_tb_inline(plugin_tb, op);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PLUGIN_GEN_FROM_INSN:
|
||||
{
|
||||
g_assert(insn_idx >= 0);
|
||||
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_UDATA:
|
||||
plugin_gen_insn_udata(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_insn_inline(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
case PLUGIN_GEN_ENABLE_MEM_HELPER:
|
||||
plugin_gen_enable_mem_helper(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PLUGIN_GEN_FROM_MEM:
|
||||
{
|
||||
g_assert(insn_idx >= 0);
|
||||
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_MEM:
|
||||
plugin_gen_mem_regular(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_mem_inline(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PLUGIN_GEN_AFTER_INSN:
|
||||
{
|
||||
g_assert(insn_idx >= 0);
|
||||
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_DISABLE_MEM_HELPER:
|
||||
plugin_gen_disable_mem_helper(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* plugins don't care about any other ops */
|
||||
break;
|
||||
}
|
||||
plugin_inject_cb(plugin_tb, op, insn_idx);
|
||||
}
|
||||
pr_ops();
|
||||
}
|
||||
@@ -860,6 +847,7 @@ bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_onl
|
||||
if (test_bit(QEMU_PLUGIN_EV_VCPU_TB_TRANS, cpu->plugin_mask)) {
|
||||
ret = true;
|
||||
|
||||
QSIMPLEQ_INIT(&tcg_ctx->plugin_ops);
|
||||
ptb->vaddr = tb->pc;
|
||||
ptb->vaddr2 = -1;
|
||||
get_page_addr_code_hostp(cpu->env_ptr, tb->pc, &ptb->haddr1);
|
||||
@@ -876,8 +864,9 @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
|
||||
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
||||
struct qemu_plugin_insn *pinsn;
|
||||
|
||||
pinsn = qemu_plugin_tb_insn_get(ptb, db->pc_next);
|
||||
pinsn = qemu_plugin_tb_insn_get(ptb);
|
||||
tcg_ctx->plugin_insn = pinsn;
|
||||
pinsn->vaddr = db->pc_next;
|
||||
plugin_gen_empty_callback(PLUGIN_GEN_FROM_INSN);
|
||||
|
||||
/*
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "hw/boards.h"
|
||||
@@ -36,26 +35,6 @@
|
||||
#include "tcg-accel-ops.h"
|
||||
#include "tcg-accel-ops-mttcg.h"
|
||||
|
||||
typedef struct MttcgForceRcuNotifier {
|
||||
Notifier notifier;
|
||||
CPUState *cpu;
|
||||
} MttcgForceRcuNotifier;
|
||||
|
||||
static void do_nothing(CPUState *cpu, run_on_cpu_data d)
|
||||
{
|
||||
}
|
||||
|
||||
static void mttcg_force_rcu(Notifier *notify, void *data)
|
||||
{
|
||||
CPUState *cpu = container_of(notify, MttcgForceRcuNotifier, notifier)->cpu;
|
||||
|
||||
/*
|
||||
* Called with rcu_registry_lock held, using async_run_on_cpu() ensures
|
||||
* that there are no deadlocks.
|
||||
*/
|
||||
async_run_on_cpu(cpu, do_nothing, RUN_ON_CPU_NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* In the multi-threaded case each vCPU has its own thread. The TLS
|
||||
* variable current_cpu can be used deep in the code to find the
|
||||
@@ -64,16 +43,12 @@ static void mttcg_force_rcu(Notifier *notify, void *data)
|
||||
|
||||
static void *mttcg_cpu_thread_fn(void *arg)
|
||||
{
|
||||
MttcgForceRcuNotifier force_rcu;
|
||||
CPUState *cpu = arg;
|
||||
|
||||
assert(tcg_enabled());
|
||||
g_assert(!icount_enabled());
|
||||
|
||||
rcu_register_thread();
|
||||
force_rcu.notifier.notify = mttcg_force_rcu;
|
||||
force_rcu.cpu = cpu;
|
||||
rcu_add_force_rcu_notifier(&force_rcu.notifier);
|
||||
tcg_register_thread();
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
@@ -125,7 +100,6 @@ static void *mttcg_cpu_thread_fn(void *arg)
|
||||
|
||||
tcg_cpus_destroy(cpu);
|
||||
qemu_mutex_unlock_iothread();
|
||||
rcu_remove_force_rcu_notifier(&force_rcu.notifier);
|
||||
rcu_unregister_thread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
@@ -134,11 +133,6 @@ static void rr_deal_with_unplugged_cpus(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void rr_force_rcu(Notifier *notify, void *data)
|
||||
{
|
||||
rr_kick_next_cpu();
|
||||
}
|
||||
|
||||
/*
|
||||
* In the single-threaded case each vCPU is simulated in turn. If
|
||||
* there is more than a single vCPU we create a simple timer to kick
|
||||
@@ -149,13 +143,10 @@ static void rr_force_rcu(Notifier *notify, void *data)
|
||||
|
||||
static void *rr_cpu_thread_fn(void *arg)
|
||||
{
|
||||
Notifier force_rcu;
|
||||
CPUState *cpu = arg;
|
||||
|
||||
assert(tcg_enabled());
|
||||
rcu_register_thread();
|
||||
force_rcu.notify = rr_force_rcu;
|
||||
rcu_add_force_rcu_notifier(&force_rcu);
|
||||
tcg_register_thread();
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
@@ -264,7 +255,6 @@ static void *rr_cpu_thread_fn(void *arg)
|
||||
rr_deal_with_unplugged_cpus();
|
||||
}
|
||||
|
||||
rcu_remove_force_rcu_notifier(&force_rcu);
|
||||
rcu_unregister_thread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+40
-48
@@ -1738,7 +1738,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
|
||||
if (current_tb_modified) {
|
||||
page_collection_unlock(pages);
|
||||
/* Force execution of one insn next time. */
|
||||
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
|
||||
cpu->cflags_next_tb = 1 | curr_cflags(cpu);
|
||||
mmap_unlock();
|
||||
cpu_loop_exit_noexc(cpu);
|
||||
}
|
||||
@@ -1906,7 +1906,7 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
|
||||
#ifdef TARGET_HAS_PRECISE_SMC
|
||||
if (current_tb_modified) {
|
||||
/* Force execution of one insn next time. */
|
||||
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
|
||||
cpu->cflags_next_tb = 1 | curr_cflags(cpu);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -1991,7 +1991,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
cpu_loop_exit_noexc(cpu);
|
||||
}
|
||||
|
||||
static void print_qht_statistics(struct qht_stats hst, GString *buf)
|
||||
static void print_qht_statistics(struct qht_stats hst)
|
||||
{
|
||||
uint32_t hgram_opts;
|
||||
size_t hgram_bins;
|
||||
@@ -2000,11 +2000,9 @@ static void print_qht_statistics(struct qht_stats hst, GString *buf)
|
||||
if (!hst.head_buckets) {
|
||||
return;
|
||||
}
|
||||
g_string_append_printf(buf, "TB hash buckets %zu/%zu "
|
||||
"(%0.2f%% head buckets used)\n",
|
||||
hst.used_head_buckets, hst.head_buckets,
|
||||
(double)hst.used_head_buckets /
|
||||
hst.head_buckets * 100);
|
||||
qemu_printf("TB hash buckets %zu/%zu (%0.2f%% head buckets used)\n",
|
||||
hst.used_head_buckets, hst.head_buckets,
|
||||
(double)hst.used_head_buckets / hst.head_buckets * 100);
|
||||
|
||||
hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
|
||||
hgram_opts |= QDIST_PR_100X | QDIST_PR_PERCENT;
|
||||
@@ -2012,9 +2010,8 @@ static void print_qht_statistics(struct qht_stats hst, GString *buf)
|
||||
hgram_opts |= QDIST_PR_NODECIMAL;
|
||||
}
|
||||
hgram = qdist_pr(&hst.occupancy, 10, hgram_opts);
|
||||
g_string_append_printf(buf, "TB hash occupancy %0.2f%% avg chain occ. "
|
||||
"Histogram: %s\n",
|
||||
qdist_avg(&hst.occupancy) * 100, hgram);
|
||||
qemu_printf("TB hash occupancy %0.2f%% avg chain occ. Histogram: %s\n",
|
||||
qdist_avg(&hst.occupancy) * 100, hgram);
|
||||
g_free(hgram);
|
||||
|
||||
hgram_opts = QDIST_PR_BORDER | QDIST_PR_LABELS;
|
||||
@@ -2026,9 +2023,8 @@ static void print_qht_statistics(struct qht_stats hst, GString *buf)
|
||||
hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE;
|
||||
}
|
||||
hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts);
|
||||
g_string_append_printf(buf, "TB hash avg chain %0.3f buckets. "
|
||||
"Histogram: %s\n",
|
||||
qdist_avg(&hst.chain), hgram);
|
||||
qemu_printf("TB hash avg chain %0.3f buckets. Histogram: %s\n",
|
||||
qdist_avg(&hst.chain), hgram);
|
||||
g_free(hgram);
|
||||
}
|
||||
|
||||
@@ -2065,7 +2061,7 @@ static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
|
||||
return false;
|
||||
}
|
||||
|
||||
void dump_exec_info(GString *buf)
|
||||
void dump_exec_info(void)
|
||||
{
|
||||
struct tb_tree_stats tst = {};
|
||||
struct qht_stats hst;
|
||||
@@ -2074,53 +2070,49 @@ void dump_exec_info(GString *buf)
|
||||
tcg_tb_foreach(tb_tree_stats_iter, &tst);
|
||||
nb_tbs = tst.nb_tbs;
|
||||
/* XXX: avoid using doubles ? */
|
||||
g_string_append_printf(buf, "Translation buffer state:\n");
|
||||
qemu_printf("Translation buffer state:\n");
|
||||
/*
|
||||
* Report total code size including the padding and TB structs;
|
||||
* otherwise users might think "-accel tcg,tb-size" is not honoured.
|
||||
* For avg host size we use the precise numbers from tb_tree_stats though.
|
||||
*/
|
||||
g_string_append_printf(buf, "gen code size %zu/%zu\n",
|
||||
tcg_code_size(), tcg_code_capacity());
|
||||
g_string_append_printf(buf, "TB count %zu\n", nb_tbs);
|
||||
g_string_append_printf(buf, "TB avg target size %zu max=%zu bytes\n",
|
||||
nb_tbs ? tst.target_size / nb_tbs : 0,
|
||||
tst.max_target_size);
|
||||
g_string_append_printf(buf, "TB avg host size %zu bytes "
|
||||
"(expansion ratio: %0.1f)\n",
|
||||
nb_tbs ? tst.host_size / nb_tbs : 0,
|
||||
tst.target_size ?
|
||||
(double)tst.host_size / tst.target_size : 0);
|
||||
g_string_append_printf(buf, "cross page TB count %zu (%zu%%)\n",
|
||||
tst.cross_page,
|
||||
nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
|
||||
g_string_append_printf(buf, "direct jump count %zu (%zu%%) "
|
||||
"(2 jumps=%zu %zu%%)\n",
|
||||
tst.direct_jmp_count,
|
||||
nb_tbs ? (tst.direct_jmp_count * 100) / nb_tbs : 0,
|
||||
tst.direct_jmp2_count,
|
||||
nb_tbs ? (tst.direct_jmp2_count * 100) / nb_tbs : 0);
|
||||
qemu_printf("gen code size %zu/%zu\n",
|
||||
tcg_code_size(), tcg_code_capacity());
|
||||
qemu_printf("TB count %zu\n", nb_tbs);
|
||||
qemu_printf("TB avg target size %zu max=%zu bytes\n",
|
||||
nb_tbs ? tst.target_size / nb_tbs : 0,
|
||||
tst.max_target_size);
|
||||
qemu_printf("TB avg host size %zu bytes (expansion ratio: %0.1f)\n",
|
||||
nb_tbs ? tst.host_size / nb_tbs : 0,
|
||||
tst.target_size ? (double)tst.host_size / tst.target_size : 0);
|
||||
qemu_printf("cross page TB count %zu (%zu%%)\n", tst.cross_page,
|
||||
nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
|
||||
qemu_printf("direct jump count %zu (%zu%%) (2 jumps=%zu %zu%%)\n",
|
||||
tst.direct_jmp_count,
|
||||
nb_tbs ? (tst.direct_jmp_count * 100) / nb_tbs : 0,
|
||||
tst.direct_jmp2_count,
|
||||
nb_tbs ? (tst.direct_jmp2_count * 100) / nb_tbs : 0);
|
||||
|
||||
qht_statistics_init(&tb_ctx.htable, &hst);
|
||||
print_qht_statistics(hst, buf);
|
||||
print_qht_statistics(hst);
|
||||
qht_statistics_destroy(&hst);
|
||||
|
||||
g_string_append_printf(buf, "\nStatistics:\n");
|
||||
g_string_append_printf(buf, "TB flush count %u\n",
|
||||
qatomic_read(&tb_ctx.tb_flush_count));
|
||||
g_string_append_printf(buf, "TB invalidate count %u\n",
|
||||
qatomic_read(&tb_ctx.tb_phys_invalidate_count));
|
||||
qemu_printf("\nStatistics:\n");
|
||||
qemu_printf("TB flush count %u\n",
|
||||
qatomic_read(&tb_ctx.tb_flush_count));
|
||||
qemu_printf("TB invalidate count %u\n",
|
||||
qatomic_read(&tb_ctx.tb_phys_invalidate_count));
|
||||
|
||||
tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
|
||||
g_string_append_printf(buf, "TLB full flushes %zu\n", flush_full);
|
||||
g_string_append_printf(buf, "TLB partial flushes %zu\n", flush_part);
|
||||
g_string_append_printf(buf, "TLB elided flushes %zu\n", flush_elide);
|
||||
tcg_dump_info(buf);
|
||||
qemu_printf("TLB full flushes %zu\n", flush_full);
|
||||
qemu_printf("TLB partial flushes %zu\n", flush_part);
|
||||
qemu_printf("TLB elided flushes %zu\n", flush_elide);
|
||||
tcg_dump_info();
|
||||
}
|
||||
|
||||
void dump_opcount_info(GString *buf)
|
||||
void dump_opcount_info(void)
|
||||
{
|
||||
tcg_dump_op_count(buf);
|
||||
tcg_dump_op_count();
|
||||
}
|
||||
|
||||
#else /* CONFIG_USER_ONLY */
|
||||
|
||||
@@ -169,7 +169,7 @@ static inline void translator_maybe_page_protect(DisasContextBase *dcbase,
|
||||
if (do_swap) { \
|
||||
ret = swap_fn(ret); \
|
||||
} \
|
||||
plugin_insn_append(pc, &ret, sizeof(ret)); \
|
||||
plugin_insn_append(&ret, sizeof(ret)); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
|
||||
+1006
-243
File diff suppressed because it is too large.
Load diff
@@ -2000,7 +2000,6 @@ void audio_create_pdos(Audiodev *dev)
|
||||
CASE(NONE, none, );
|
||||
CASE(ALSA, alsa, Alsa);
|
||||
CASE(COREAUDIO, coreaudio, Coreaudio);
|
||||
CASE(DBUS, dbus, );
|
||||
CASE(DSOUND, dsound, );
|
||||
CASE(JACK, jack, Jack);
|
||||
CASE(OSS, oss, Oss);
|
||||
|
||||
@@ -31,10 +31,6 @@
|
||||
#endif
|
||||
#include "mixeng.h"
|
||||
|
||||
#ifdef CONFIG_GIO
|
||||
#include <gio/gio.h>
|
||||
#endif
|
||||
|
||||
struct audio_pcm_ops;
|
||||
|
||||
struct audio_callback {
|
||||
@@ -144,9 +140,6 @@ struct audio_driver {
|
||||
const char *descr;
|
||||
void *(*init) (Audiodev *);
|
||||
void (*fini) (void *);
|
||||
#ifdef CONFIG_GIO
|
||||
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager);
|
||||
#endif
|
||||
struct audio_pcm_ops *pcm_ops;
|
||||
int can_be_default;
|
||||
int max_voices_out;
|
||||
|
||||
@@ -327,8 +327,6 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
|
||||
case AUDIODEV_DRIVER_COREAUDIO:
|
||||
return qapi_AudiodevCoreaudioPerDirectionOptions_base(
|
||||
dev->u.coreaudio.TYPE);
|
||||
case AUDIODEV_DRIVER_DBUS:
|
||||
return dev->u.dbus.TYPE;
|
||||
case AUDIODEV_DRIVER_DSOUND:
|
||||
return dev->u.dsound.TYPE;
|
||||
case AUDIODEV_DRIVER_JACK:
|
||||
|
||||
@@ -1,654 +0,0 @@
|
||||
/*
|
||||
* QEMU DBus audio
|
||||
*
|
||||
* Copyright (c) 2021 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/dbus.h"
|
||||
|
||||
#include <gio/gunixfdlist.h>
|
||||
#include "ui/dbus-display1.h"
|
||||
|
||||
#define AUDIO_CAP "dbus"
|
||||
#include "audio.h"
|
||||
#include "audio_int.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define DBUS_DISPLAY1_AUDIO_PATH DBUS_DISPLAY1_ROOT "/Audio"
|
||||
|
||||
#define DBUS_AUDIO_NSAMPLES 1024 /* could be configured? */
|
||||
|
||||
typedef struct DBusAudio {
|
||||
GDBusObjectManagerServer *server;
|
||||
GDBusObjectSkeleton *audio;
|
||||
QemuDBusDisplay1Audio *iface;
|
||||
GHashTable *out_listeners;
|
||||
GHashTable *in_listeners;
|
||||
} DBusAudio;
|
||||
|
||||
typedef struct DBusVoiceOut {
|
||||
HWVoiceOut hw;
|
||||
bool enabled;
|
||||
RateCtl rate;
|
||||
|
||||
void *buf;
|
||||
size_t buf_pos;
|
||||
size_t buf_size;
|
||||
|
||||
bool has_volume;
|
||||
Volume volume;
|
||||
} DBusVoiceOut;
|
||||
|
||||
typedef struct DBusVoiceIn {
|
||||
HWVoiceIn hw;
|
||||
bool enabled;
|
||||
RateCtl rate;
|
||||
|
||||
bool has_volume;
|
||||
Volume volume;
|
||||
} DBusVoiceIn;
|
||||
|
||||
static void *dbus_get_buffer_out(HWVoiceOut *hw, size_t *size)
|
||||
{
|
||||
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
|
||||
|
||||
if (!vo->buf) {
|
||||
vo->buf_size = hw->samples * hw->info.bytes_per_frame;
|
||||
vo->buf = g_malloc(vo->buf_size);
|
||||
vo->buf_pos = 0;
|
||||
}
|
||||
|
||||
*size = MIN(vo->buf_size - vo->buf_pos, *size);
|
||||
*size = audio_rate_get_bytes(&hw->info, &vo->rate, *size);
|
||||
|
||||
return vo->buf + vo->buf_pos;
|
||||
|
||||
}
|
||||
|
||||
static size_t dbus_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioOutListener *listener = NULL;
|
||||
g_autoptr(GBytes) bytes = NULL;
|
||||
g_autoptr(GVariant) v_data = NULL;
|
||||
|
||||
assert(buf == vo->buf + vo->buf_pos && vo->buf_pos + size <= vo->buf_size);
|
||||
vo->buf_pos += size;
|
||||
|
||||
trace_dbus_audio_put_buffer_out(size);
|
||||
|
||||
if (vo->buf_pos < vo->buf_size) {
|
||||
return size;
|
||||
}
|
||||
|
||||
bytes = g_bytes_new_take(g_steal_pointer(&vo->buf), vo->buf_size);
|
||||
v_data = g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), bytes, TRUE);
|
||||
g_variant_ref_sink(v_data);
|
||||
|
||||
g_hash_table_iter_init(&iter, da->out_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
qemu_dbus_display1_audio_out_listener_call_write(
|
||||
listener,
|
||||
(uintptr_t)hw,
|
||||
v_data,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
#define AUDIO_HOST_BE TRUE
|
||||
#else
|
||||
#define AUDIO_HOST_BE FALSE
|
||||
#endif
|
||||
|
||||
static void
|
||||
dbus_init_out_listener(QemuDBusDisplay1AudioOutListener *listener,
|
||||
HWVoiceOut *hw)
|
||||
{
|
||||
qemu_dbus_display1_audio_out_listener_call_init(
|
||||
listener,
|
||||
(uintptr_t)hw,
|
||||
hw->info.bits,
|
||||
hw->info.is_signed,
|
||||
hw->info.is_float,
|
||||
hw->info.freq,
|
||||
hw->info.nchannels,
|
||||
hw->info.bytes_per_frame,
|
||||
hw->info.bytes_per_second,
|
||||
hw->info.swap_endianness ? !AUDIO_HOST_BE : AUDIO_HOST_BE,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
dbus_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioOutListener *listener = NULL;
|
||||
|
||||
audio_pcm_init_info(&hw->info, as);
|
||||
hw->samples = DBUS_AUDIO_NSAMPLES;
|
||||
audio_rate_start(&vo->rate);
|
||||
|
||||
g_hash_table_iter_init(&iter, da->out_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
dbus_init_out_listener(listener, hw);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_fini_out(HWVoiceOut *hw)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioOutListener *listener = NULL;
|
||||
|
||||
g_hash_table_iter_init(&iter, da->out_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
qemu_dbus_display1_audio_out_listener_call_fini(
|
||||
listener,
|
||||
(uintptr_t)hw,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
g_clear_pointer(&vo->buf, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_enable_out(HWVoiceOut *hw, bool enable)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioOutListener *listener = NULL;
|
||||
|
||||
vo->enabled = enable;
|
||||
if (enable) {
|
||||
audio_rate_start(&vo->rate);
|
||||
}
|
||||
|
||||
g_hash_table_iter_init(&iter, da->out_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
qemu_dbus_display1_audio_out_listener_call_set_enabled(
|
||||
listener, (uintptr_t)hw, enable,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_volume_out_listener(HWVoiceOut *hw,
|
||||
QemuDBusDisplay1AudioOutListener *listener)
|
||||
{
|
||||
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
|
||||
Volume *vol = &vo->volume;
|
||||
g_autoptr(GBytes) bytes = NULL;
|
||||
GVariant *v_vol = NULL;
|
||||
|
||||
if (!vo->has_volume) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(vol->channels < sizeof(vol->vol));
|
||||
bytes = g_bytes_new(vol->vol, vol->channels);
|
||||
v_vol = g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), bytes, TRUE);
|
||||
qemu_dbus_display1_audio_out_listener_call_set_volume(
|
||||
listener, (uintptr_t)hw, vol->mute, v_vol,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_volume_out(HWVoiceOut *hw, Volume *vol)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioOutListener *listener = NULL;
|
||||
|
||||
vo->has_volume = true;
|
||||
vo->volume = *vol;
|
||||
|
||||
g_hash_table_iter_init(&iter, da->out_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
dbus_volume_out_listener(hw, listener);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_init_in_listener(QemuDBusDisplay1AudioInListener *listener, HWVoiceIn *hw)
|
||||
{
|
||||
qemu_dbus_display1_audio_in_listener_call_init(
|
||||
listener,
|
||||
(uintptr_t)hw,
|
||||
hw->info.bits,
|
||||
hw->info.is_signed,
|
||||
hw->info.is_float,
|
||||
hw->info.freq,
|
||||
hw->info.nchannels,
|
||||
hw->info.bytes_per_frame,
|
||||
hw->info.bytes_per_second,
|
||||
hw->info.swap_endianness ? !AUDIO_HOST_BE : AUDIO_HOST_BE,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
dbus_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioInListener *listener = NULL;
|
||||
|
||||
audio_pcm_init_info(&hw->info, as);
|
||||
hw->samples = DBUS_AUDIO_NSAMPLES;
|
||||
audio_rate_start(&vo->rate);
|
||||
|
||||
g_hash_table_iter_init(&iter, da->in_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
dbus_init_in_listener(listener, hw);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_fini_in(HWVoiceIn *hw)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioInListener *listener = NULL;
|
||||
|
||||
g_hash_table_iter_init(&iter, da->in_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
qemu_dbus_display1_audio_in_listener_call_fini(
|
||||
listener,
|
||||
(uintptr_t)hw,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_volume_in_listener(HWVoiceIn *hw,
|
||||
QemuDBusDisplay1AudioInListener *listener)
|
||||
{
|
||||
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
|
||||
Volume *vol = &vo->volume;
|
||||
g_autoptr(GBytes) bytes = NULL;
|
||||
GVariant *v_vol = NULL;
|
||||
|
||||
if (!vo->has_volume) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(vol->channels < sizeof(vol->vol));
|
||||
bytes = g_bytes_new(vol->vol, vol->channels);
|
||||
v_vol = g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), bytes, TRUE);
|
||||
qemu_dbus_display1_audio_in_listener_call_set_volume(
|
||||
listener, (uintptr_t)hw, vol->mute, v_vol,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_volume_in(HWVoiceIn *hw, Volume *vol)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioInListener *listener = NULL;
|
||||
|
||||
vo->has_volume = true;
|
||||
vo->volume = *vol;
|
||||
|
||||
g_hash_table_iter_init(&iter, da->in_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
dbus_volume_in_listener(hw, listener);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
dbus_read(HWVoiceIn *hw, void *buf, size_t size)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
/* DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw); */
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioInListener *listener = NULL;
|
||||
|
||||
trace_dbus_audio_read(size);
|
||||
|
||||
/* size = audio_rate_get_bytes(&hw->info, &vo->rate, size); */
|
||||
|
||||
g_hash_table_iter_init(&iter, da->in_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
g_autoptr(GVariant) v_data = NULL;
|
||||
const char *data;
|
||||
gsize n = 0;
|
||||
|
||||
if (qemu_dbus_display1_audio_in_listener_call_read_sync(
|
||||
listener,
|
||||
(uintptr_t)hw,
|
||||
size,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
||||
&v_data, NULL, NULL)) {
|
||||
data = g_variant_get_fixed_array(v_data, &n, 1);
|
||||
g_warn_if_fail(n <= size);
|
||||
size = MIN(n, size);
|
||||
memcpy(buf, data, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_enable_in(HWVoiceIn *hw, bool enable)
|
||||
{
|
||||
DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
|
||||
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
|
||||
GHashTableIter iter;
|
||||
QemuDBusDisplay1AudioInListener *listener = NULL;
|
||||
|
||||
vo->enabled = enable;
|
||||
if (enable) {
|
||||
audio_rate_start(&vo->rate);
|
||||
}
|
||||
|
||||
g_hash_table_iter_init(&iter, da->in_listeners);
|
||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||
qemu_dbus_display1_audio_in_listener_call_set_enabled(
|
||||
listener, (uintptr_t)hw, enable,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
dbus_audio_init(Audiodev *dev)
|
||||
{
|
||||
DBusAudio *da = g_new0(DBusAudio, 1);
|
||||
|
||||
da->out_listeners = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
da->in_listeners = g_hash_table_new_full(g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
return da;
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_audio_fini(void *opaque)
|
||||
{
|
||||
DBusAudio *da = opaque;
|
||||
|
||||
if (da->server) {
|
||||
g_dbus_object_manager_server_unexport(da->server,
|
||||
DBUS_DISPLAY1_AUDIO_PATH);
|
||||
}
|
||||
g_clear_object(&da->audio);
|
||||
g_clear_object(&da->iface);
|
||||
g_clear_pointer(&da->in_listeners, g_hash_table_unref);
|
||||
g_clear_pointer(&da->out_listeners, g_hash_table_unref);
|
||||
g_clear_object(&da->server);
|
||||
g_free(da);
|
||||
}
|
||||
|
||||
static void
|
||||
listener_out_vanished_cb(GDBusConnection *connection,
|
||||
gboolean remote_peer_vanished,
|
||||
GError *error,
|
||||
DBusAudio *da)
|
||||
{
|
||||
char *name = g_object_get_data(G_OBJECT(connection), "name");
|
||||
|
||||
g_hash_table_remove(da->out_listeners, name);
|
||||
}
|
||||
|
||||
static void
|
||||
listener_in_vanished_cb(GDBusConnection *connection,
|
||||
gboolean remote_peer_vanished,
|
||||
GError *error,
|
||||
DBusAudio *da)
|
||||
{
|
||||
char *name = g_object_get_data(G_OBJECT(connection), "name");
|
||||
|
||||
g_hash_table_remove(da->in_listeners, name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dbus_audio_register_listener(AudioState *s,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GUnixFDList *fd_list,
|
||||
GVariant *arg_listener,
|
||||
bool out)
|
||||
{
|
||||
DBusAudio *da = s->drv_opaque;
|
||||
const char *sender = g_dbus_method_invocation_get_sender(invocation);
|
||||
g_autoptr(GDBusConnection) listener_conn = NULL;
|
||||
g_autoptr(GError) err = NULL;
|
||||
g_autoptr(GSocket) socket = NULL;
|
||||
g_autoptr(GSocketConnection) socket_conn = NULL;
|
||||
g_autofree char *guid = g_dbus_generate_guid();
|
||||
GHashTable *listeners = out ? da->out_listeners : da->in_listeners;
|
||||
GObject *listener;
|
||||
int fd;
|
||||
|
||||
trace_dbus_audio_register(sender, out ? "out" : "in");
|
||||
|
||||
if (g_hash_table_contains(listeners, sender)) {
|
||||
g_dbus_method_invocation_return_error(invocation,
|
||||
DBUS_DISPLAY_ERROR,
|
||||
DBUS_DISPLAY_ERROR_INVALID,
|
||||
"`%s` is already registered!",
|
||||
sender);
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
fd = g_unix_fd_list_get(fd_list, g_variant_get_handle(arg_listener), &err);
|
||||
if (err) {
|
||||
g_dbus_method_invocation_return_error(invocation,
|
||||
DBUS_DISPLAY_ERROR,
|
||||
DBUS_DISPLAY_ERROR_FAILED,
|
||||
"Couldn't get peer fd: %s",
|
||||
err->message);
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
socket = g_socket_new_from_fd(fd, &err);
|
||||
if (err) {
|
||||
g_dbus_method_invocation_return_error(invocation,
|
||||
DBUS_DISPLAY_ERROR,
|
||||
DBUS_DISPLAY_ERROR_FAILED,
|
||||
"Couldn't make a socket: %s",
|
||||
err->message);
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
socket_conn = g_socket_connection_factory_create_connection(socket);
|
||||
if (out) {
|
||||
qemu_dbus_display1_audio_complete_register_out_listener(
|
||||
da->iface, invocation, NULL);
|
||||
} else {
|
||||
qemu_dbus_display1_audio_complete_register_in_listener(
|
||||
da->iface, invocation, NULL);
|
||||
}
|
||||
|
||||
listener_conn =
|
||||
g_dbus_connection_new_sync(
|
||||
G_IO_STREAM(socket_conn),
|
||||
guid,
|
||||
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
|
||||
NULL, NULL, &err);
|
||||
if (err) {
|
||||
error_report("Failed to setup peer connection: %s", err->message);
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
listener = out ?
|
||||
G_OBJECT(qemu_dbus_display1_audio_out_listener_proxy_new_sync(
|
||||
listener_conn,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL,
|
||||
"/org/qemu/Display1/AudioOutListener",
|
||||
NULL,
|
||||
&err)) :
|
||||
G_OBJECT(qemu_dbus_display1_audio_in_listener_proxy_new_sync(
|
||||
listener_conn,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL,
|
||||
"/org/qemu/Display1/AudioInListener",
|
||||
NULL,
|
||||
&err));
|
||||
if (!listener) {
|
||||
error_report("Failed to setup proxy: %s", err->message);
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
if (out) {
|
||||
HWVoiceOut *hw;
|
||||
|
||||
QLIST_FOREACH(hw, &s->hw_head_out, entries) {
|
||||
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
|
||||
QemuDBusDisplay1AudioOutListener *l =
|
||||
QEMU_DBUS_DISPLAY1_AUDIO_OUT_LISTENER(listener);
|
||||
|
||||
dbus_init_out_listener(l, hw);
|
||||
qemu_dbus_display1_audio_out_listener_call_set_enabled(
|
||||
l, (uintptr_t)hw, vo->enabled,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
} else {
|
||||
HWVoiceIn *hw;
|
||||
|
||||
QLIST_FOREACH(hw, &s->hw_head_in, entries) {
|
||||
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
|
||||
QemuDBusDisplay1AudioInListener *l =
|
||||
QEMU_DBUS_DISPLAY1_AUDIO_IN_LISTENER(listener);
|
||||
|
||||
dbus_init_in_listener(
|
||||
QEMU_DBUS_DISPLAY1_AUDIO_IN_LISTENER(listener), hw);
|
||||
qemu_dbus_display1_audio_in_listener_call_set_enabled(
|
||||
l, (uintptr_t)hw, vo->enabled,
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_set_data_full(G_OBJECT(listener_conn), "name",
|
||||
g_strdup(sender), g_free);
|
||||
g_hash_table_insert(listeners, g_strdup(sender), listener);
|
||||
g_object_connect(listener_conn,
|
||||
"signal::closed",
|
||||
out ? listener_out_vanished_cb : listener_in_vanished_cb,
|
||||
da,
|
||||
NULL);
|
||||
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dbus_audio_register_out_listener(AudioState *s,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GUnixFDList *fd_list,
|
||||
GVariant *arg_listener)
|
||||
{
|
||||
return dbus_audio_register_listener(s, invocation,
|
||||
fd_list, arg_listener, true);
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dbus_audio_register_in_listener(AudioState *s,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GUnixFDList *fd_list,
|
||||
GVariant *arg_listener)
|
||||
{
|
||||
return dbus_audio_register_listener(s, invocation,
|
||||
fd_list, arg_listener, false);
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server)
|
||||
{
|
||||
DBusAudio *da = s->drv_opaque;
|
||||
|
||||
g_assert(da);
|
||||
g_assert(!da->server);
|
||||
|
||||
da->server = g_object_ref(server);
|
||||
|
||||
da->audio = g_dbus_object_skeleton_new(DBUS_DISPLAY1_AUDIO_PATH);
|
||||
da->iface = qemu_dbus_display1_audio_skeleton_new();
|
||||
g_object_connect(da->iface,
|
||||
"swapped-signal::handle-register-in-listener",
|
||||
dbus_audio_register_in_listener, s,
|
||||
"swapped-signal::handle-register-out-listener",
|
||||
dbus_audio_register_out_listener, s,
|
||||
NULL);
|
||||
|
||||
g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(da->audio),
|
||||
G_DBUS_INTERFACE_SKELETON(da->iface));
|
||||
g_dbus_object_manager_server_export(da->server, da->audio);
|
||||
}
|
||||
|
||||
static struct audio_pcm_ops dbus_pcm_ops = {
|
||||
.init_out = dbus_init_out,
|
||||
.fini_out = dbus_fini_out,
|
||||
.write = audio_generic_write,
|
||||
.get_buffer_out = dbus_get_buffer_out,
|
||||
.put_buffer_out = dbus_put_buffer_out,
|
||||
.enable_out = dbus_enable_out,
|
||||
.volume_out = dbus_volume_out,
|
||||
|
||||
.init_in = dbus_init_in,
|
||||
.fini_in = dbus_fini_in,
|
||||
.read = dbus_read,
|
||||
.run_buffer_in = audio_generic_run_buffer_in,
|
||||
.enable_in = dbus_enable_in,
|
||||
.volume_in = dbus_volume_in,
|
||||
};
|
||||
|
||||
static struct audio_driver dbus_audio_driver = {
|
||||
.name = "dbus",
|
||||
.descr = "Timer based audio exposed with DBus interface",
|
||||
.init = dbus_audio_init,
|
||||
.fini = dbus_audio_fini,
|
||||
.set_dbus_server = dbus_audio_set_server,
|
||||
.pcm_ops = &dbus_pcm_ops,
|
||||
.can_be_default = 1,
|
||||
.max_voices_out = INT_MAX,
|
||||
.max_voices_in = INT_MAX,
|
||||
.voice_size_out = sizeof(DBusVoiceOut),
|
||||
.voice_size_in = sizeof(DBusVoiceIn)
|
||||
};
|
||||
|
||||
static void register_audio_dbus(void)
|
||||
{
|
||||
audio_driver_register(&dbus_audio_driver);
|
||||
}
|
||||
type_init(register_audio_dbus);
|
||||
|
||||
module_dep("ui-dbus")
|
||||
+12
-17
@@ -7,29 +7,24 @@ softmmu_ss.add(files(
|
||||
'wavcapture.c',
|
||||
))
|
||||
|
||||
softmmu_ss.add(when: coreaudio, if_true: files('coreaudio.c'))
|
||||
softmmu_ss.add(when: dsound, if_true: files('dsoundaudio.c', 'audio_win_int.c'))
|
||||
softmmu_ss.add(when: [coreaudio, 'CONFIG_AUDIO_COREAUDIO'], if_true: files('coreaudio.c'))
|
||||
softmmu_ss.add(when: [dsound, 'CONFIG_AUDIO_DSOUND'], if_true: files('dsoundaudio.c'))
|
||||
softmmu_ss.add(when: ['CONFIG_AUDIO_WIN_INT'], if_true: files('audio_win_int.c'))
|
||||
|
||||
audio_modules = {}
|
||||
foreach m : [
|
||||
['alsa', alsa, files('alsaaudio.c')],
|
||||
['oss', oss, files('ossaudio.c')],
|
||||
['pa', pulse, files('paaudio.c')],
|
||||
['sdl', sdl, files('sdlaudio.c')],
|
||||
['jack', jack, files('jackaudio.c')],
|
||||
['spice', spice, files('spiceaudio.c')]
|
||||
['CONFIG_AUDIO_ALSA', 'alsa', alsa, 'alsaaudio.c'],
|
||||
['CONFIG_AUDIO_OSS', 'oss', oss, 'ossaudio.c'],
|
||||
['CONFIG_AUDIO_PA', 'pa', pulse, 'paaudio.c'],
|
||||
['CONFIG_AUDIO_SDL', 'sdl', sdl, 'sdlaudio.c'],
|
||||
['CONFIG_AUDIO_JACK', 'jack', jack, 'jackaudio.c'],
|
||||
['CONFIG_SPICE', 'spice', spice, 'spiceaudio.c']
|
||||
]
|
||||
if m[1].found()
|
||||
if config_host.has_key(m[0])
|
||||
module_ss = ss.source_set()
|
||||
module_ss.add(m[1], m[2])
|
||||
audio_modules += {m[0] : module_ss}
|
||||
module_ss.add(when: m[2], if_true: files(m[3]))
|
||||
audio_modules += {m[1] : module_ss}
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if dbus_display
|
||||
module_ss = ss.source_set()
|
||||
module_ss.add(when: gio, if_true: files('dbusaudio.c'))
|
||||
audio_modules += {'dbus': module_ss}
|
||||
endif
|
||||
|
||||
modules += {'audio': audio_modules}
|
||||
@@ -13,11 +13,6 @@ alsa_resume_out(void) "Resuming suspended output stream"
|
||||
# ossaudio.c
|
||||
oss_version(int version) "OSS version = 0x%x"
|
||||
|
||||
# dbusaudio.c
|
||||
dbus_audio_register(const char *s, const char *dir) "sender = %s, dir = %s"
|
||||
dbus_audio_put_buffer_out(size_t len) "len = %zu"
|
||||
dbus_audio_read(size_t len) "len = %zu"
|
||||
|
||||
# audio.c
|
||||
audio_timer_start(int interval) "interval %d ms"
|
||||
audio_timer_stop(void) ""
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
|
||||
<!--
|
||||
org.qemu.VMState1:
|
||||
|
||||
This interface must be implemented at the object path
|
||||
``/org/qemu/VMState1`` to support helper migration.
|
||||
-->
|
||||
<interface name="org.qemu.VMState1">
|
||||
|
||||
<!--
|
||||
Id:
|
||||
|
||||
A string that identifies the helper uniquely. (maximum 256 bytes
|
||||
including terminating NUL byte)
|
||||
|
||||
.. note::
|
||||
|
||||
The VMState helper ID namespace is its own namespace. In particular,
|
||||
it is not related to QEMU "id" used in -object/-device objects.
|
||||
-->
|
||||
<property name="Id" type="s" access="read"/>
|
||||
|
||||
<!--
|
||||
Load:
|
||||
@data: data to restore the state.
|
||||
|
||||
The method called on destination with the state to restore.
|
||||
|
||||
The helper may be initially started in a waiting state (with an
|
||||
``-incoming`` argument for example), and it may resume on success.
|
||||
|
||||
An error may be returned to the caller.
|
||||
-->
|
||||
<method name="Load">
|
||||
<arg type="ay" name="data" direction="in"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Save:
|
||||
@data: state data to save for later resume.
|
||||
|
||||
The method called on the source to get the current state to be
|
||||
migrated. The helper should continue to run normally.
|
||||
|
||||
An error may be returned to the caller.
|
||||
-->
|
||||
<method name="Save">
|
||||
<arg type="ay" name="data" direction="out"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
@@ -84,13 +84,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
BdrvChildRole child_role,
|
||||
Error **errp);
|
||||
|
||||
static bool bdrv_recurse_has_child(BlockDriverState *bs,
|
||||
BlockDriverState *child);
|
||||
|
||||
static void bdrv_child_free(BdrvChild *child);
|
||||
static void bdrv_replace_child_noperm(BdrvChild **child,
|
||||
BlockDriverState *new_bs,
|
||||
bool free_empty_child);
|
||||
static void bdrv_replace_child_noperm(BdrvChild *child,
|
||||
BlockDriverState *new_bs);
|
||||
static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
|
||||
BdrvChild *child,
|
||||
Transaction *tran);
|
||||
@@ -1389,8 +1384,6 @@ static void bdrv_child_cb_attach(BdrvChild *child)
|
||||
{
|
||||
BlockDriverState *bs = child->opaque;
|
||||
|
||||
QLIST_INSERT_HEAD(&bs->children, child, next);
|
||||
|
||||
if (child->role & BDRV_CHILD_COW) {
|
||||
bdrv_backing_attach(child);
|
||||
}
|
||||
@@ -1407,8 +1400,6 @@ static void bdrv_child_cb_detach(BdrvChild *child)
|
||||
}
|
||||
|
||||
bdrv_unapply_subtree_drain(child, bs);
|
||||
|
||||
QLIST_REMOVE(child, next);
|
||||
}
|
||||
|
||||
static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
|
||||
@@ -1613,26 +1604,16 @@ open_failed:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create and open a block node.
|
||||
*
|
||||
* @options is a QDict of options to pass to the block drivers, or NULL for an
|
||||
* empty set of options. The reference to the QDict belongs to the block layer
|
||||
* after the call (even on failure), so if the caller intends to reuse the
|
||||
* dictionary, it needs to use qobject_ref() before calling bdrv_open.
|
||||
*/
|
||||
BlockDriverState *bdrv_new_open_driver_opts(BlockDriver *drv,
|
||||
const char *node_name,
|
||||
QDict *options, int flags,
|
||||
Error **errp)
|
||||
BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
|
||||
int flags, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
int ret;
|
||||
|
||||
bs = bdrv_new();
|
||||
bs->open_flags = flags;
|
||||
bs->options = options ?: qdict_new();
|
||||
bs->explicit_options = qdict_clone_shallow(bs->options);
|
||||
bs->explicit_options = qdict_new();
|
||||
bs->options = qdict_new();
|
||||
bs->opaque = NULL;
|
||||
|
||||
update_options_from_flags(bs->options, flags);
|
||||
@@ -1650,13 +1631,6 @@ BlockDriverState *bdrv_new_open_driver_opts(BlockDriver *drv,
|
||||
return bs;
|
||||
}
|
||||
|
||||
/* Create and open a block node. */
|
||||
BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
|
||||
int flags, Error **errp)
|
||||
{
|
||||
return bdrv_new_open_driver_opts(drv, node_name, NULL, flags, errp);
|
||||
}
|
||||
|
||||
QemuOptsList bdrv_runtime_opts = {
|
||||
.name = "bdrv_common",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(bdrv_runtime_opts.head),
|
||||
@@ -2256,18 +2230,13 @@ static int bdrv_drv_set_perm(BlockDriverState *bs, uint64_t perm,
|
||||
|
||||
typedef struct BdrvReplaceChildState {
|
||||
BdrvChild *child;
|
||||
BdrvChild **childp;
|
||||
BlockDriverState *old_bs;
|
||||
bool free_empty_child;
|
||||
} BdrvReplaceChildState;
|
||||
|
||||
static void bdrv_replace_child_commit(void *opaque)
|
||||
{
|
||||
BdrvReplaceChildState *s = opaque;
|
||||
|
||||
if (s->free_empty_child && !s->child->bs) {
|
||||
bdrv_child_free(s->child);
|
||||
}
|
||||
bdrv_unref(s->old_bs);
|
||||
}
|
||||
|
||||
@@ -2276,34 +2245,8 @@ static void bdrv_replace_child_abort(void *opaque)
|
||||
BdrvReplaceChildState *s = opaque;
|
||||
BlockDriverState *new_bs = s->child->bs;
|
||||
|
||||
/*
|
||||
* old_bs reference is transparently moved from @s to s->child.
|
||||
*
|
||||
* Pass &s->child here instead of s->childp, because:
|
||||
* (1) s->old_bs must be non-NULL, so bdrv_replace_child_noperm() will not
|
||||
* modify the BdrvChild * pointer we indirectly pass to it, i.e. it
|
||||
* will not modify s->child. From that perspective, it does not matter
|
||||
* whether we pass s->childp or &s->child.
|
||||
* (2) If new_bs is not NULL, s->childp will be NULL. We then cannot use
|
||||
* it here.
|
||||
* (3) If new_bs is NULL, *s->childp will have been NULLed by
|
||||
* bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
|
||||
* must not pass a NULL *s->childp here.
|
||||
*
|
||||
* So whether new_bs was NULL or not, we cannot pass s->childp here; and in
|
||||
* any case, there is no reason to pass it anyway.
|
||||
*/
|
||||
bdrv_replace_child_noperm(&s->child, s->old_bs, true);
|
||||
/*
|
||||
* The child was pre-existing, so s->old_bs must be non-NULL, and
|
||||
* s->child thus must not have been freed
|
||||
*/
|
||||
assert(s->child != NULL);
|
||||
if (!new_bs) {
|
||||
/* As described above, *s->childp was cleared, so restore it */
|
||||
assert(s->childp != NULL);
|
||||
*s->childp = s->child;
|
||||
}
|
||||
/* old_bs reference is transparently moved from @s to @s->child */
|
||||
bdrv_replace_child_noperm(s->child, s->old_bs);
|
||||
bdrv_unref(new_bs);
|
||||
}
|
||||
|
||||
@@ -2319,46 +2262,22 @@ static TransactionActionDrv bdrv_replace_child_drv = {
|
||||
* Note: real unref of old_bs is done only on commit.
|
||||
*
|
||||
* The function doesn't update permissions, caller is responsible for this.
|
||||
*
|
||||
* (*childp)->bs must not be NULL.
|
||||
*
|
||||
* Note that if new_bs == NULL, @childp is stored in a state object attached
|
||||
* to @tran, so that the old child can be reinstated in the abort handler.
|
||||
* Therefore, if @new_bs can be NULL, @childp must stay valid until the
|
||||
* transaction is committed or aborted.
|
||||
*
|
||||
* If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
|
||||
* freed (on commit). @free_empty_child should only be false if the
|
||||
* caller will free the BDrvChild themselves (which may be important
|
||||
* if this is in turn called in another transactional context).
|
||||
*/
|
||||
static void bdrv_replace_child_tran(BdrvChild **childp,
|
||||
BlockDriverState *new_bs,
|
||||
Transaction *tran,
|
||||
bool free_empty_child)
|
||||
static void bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
|
||||
Transaction *tran)
|
||||
{
|
||||
BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
|
||||
*s = (BdrvReplaceChildState) {
|
||||
.child = *childp,
|
||||
.childp = new_bs == NULL ? childp : NULL,
|
||||
.old_bs = (*childp)->bs,
|
||||
.free_empty_child = free_empty_child,
|
||||
.child = child,
|
||||
.old_bs = child->bs,
|
||||
};
|
||||
tran_add(tran, &bdrv_replace_child_drv, s);
|
||||
|
||||
/* The abort handler relies on this */
|
||||
assert(s->old_bs != NULL);
|
||||
|
||||
if (new_bs) {
|
||||
bdrv_ref(new_bs);
|
||||
}
|
||||
/*
|
||||
* Pass free_empty_child=false, we will free the child (if
|
||||
* necessary) in bdrv_replace_child_commit() (if our
|
||||
* @free_empty_child parameter was true).
|
||||
*/
|
||||
bdrv_replace_child_noperm(childp, new_bs, false);
|
||||
/* old_bs reference is transparently moved from *childp to @s */
|
||||
bdrv_replace_child_noperm(child, new_bs);
|
||||
/* old_bs reference is transparently moved from @child to @s */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2729,30 +2648,14 @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
|
||||
return permissions[qapi_perm];
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace (*childp)->bs by @new_bs.
|
||||
*
|
||||
* If @new_bs is NULL, *childp will be set to NULL, too: BDS parents
|
||||
* generally cannot handle a BdrvChild with .bs == NULL, so clearing
|
||||
* BdrvChild.bs should generally immediately be followed by the
|
||||
* BdrvChild pointer being cleared as well.
|
||||
*
|
||||
* If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
|
||||
* freed. @free_empty_child should only be false if the caller will
|
||||
* free the BdrvChild themselves (this may be important in a
|
||||
* transactional context, where it may only be freed on commit).
|
||||
*/
|
||||
static void bdrv_replace_child_noperm(BdrvChild **childp,
|
||||
BlockDriverState *new_bs,
|
||||
bool free_empty_child)
|
||||
static void bdrv_replace_child_noperm(BdrvChild *child,
|
||||
BlockDriverState *new_bs)
|
||||
{
|
||||
BdrvChild *child = *childp;
|
||||
BlockDriverState *old_bs = child->bs;
|
||||
int new_bs_quiesce_counter;
|
||||
int drain_saldo;
|
||||
|
||||
assert(!child->frozen);
|
||||
assert(old_bs != new_bs);
|
||||
|
||||
if (old_bs && new_bs) {
|
||||
assert(bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs));
|
||||
@@ -2781,9 +2684,6 @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
|
||||
}
|
||||
|
||||
child->bs = new_bs;
|
||||
if (!new_bs) {
|
||||
*childp = NULL;
|
||||
}
|
||||
|
||||
if (new_bs) {
|
||||
QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent);
|
||||
@@ -2813,25 +2713,21 @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
|
||||
bdrv_parent_drained_end_single(child);
|
||||
drain_saldo++;
|
||||
}
|
||||
|
||||
if (free_empty_child && !child->bs) {
|
||||
bdrv_child_free(child);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the given @child.
|
||||
*
|
||||
* The child must be empty (i.e. `child->bs == NULL`) and it must be
|
||||
* unused (i.e. not in a children list).
|
||||
*/
|
||||
static void bdrv_child_free(BdrvChild *child)
|
||||
static void bdrv_child_free(void *opaque)
|
||||
{
|
||||
BdrvChild *c = opaque;
|
||||
|
||||
g_free(c->name);
|
||||
g_free(c);
|
||||
}
|
||||
|
||||
static void bdrv_remove_empty_child(BdrvChild *child)
|
||||
{
|
||||
assert(!child->bs);
|
||||
assert(!child->next.le_prev); /* not in children list */
|
||||
|
||||
g_free(child->name);
|
||||
g_free(child);
|
||||
QLIST_SAFE_REMOVE(child, next);
|
||||
bdrv_child_free(child);
|
||||
}
|
||||
|
||||
typedef struct BdrvAttachChildCommonState {
|
||||
@@ -2846,35 +2742,27 @@ static void bdrv_attach_child_common_abort(void *opaque)
|
||||
BdrvChild *child = *s->child;
|
||||
BlockDriverState *bs = child->bs;
|
||||
|
||||
/*
|
||||
* Pass free_empty_child=false, because we still need the child
|
||||
* for the AioContext operations on the parent below; those
|
||||
* BdrvChildClass methods all work on a BdrvChild object, so we
|
||||
* need to keep it as an empty shell (after this function, it will
|
||||
* not be attached to any parent, and it will not have a .bs).
|
||||
*/
|
||||
bdrv_replace_child_noperm(s->child, NULL, false);
|
||||
bdrv_replace_child_noperm(child, NULL);
|
||||
|
||||
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
|
||||
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
|
||||
}
|
||||
|
||||
if (bdrv_child_get_parent_aio_context(child) != s->old_parent_ctx) {
|
||||
GSList *ignore;
|
||||
GSList *ignore = g_slist_prepend(NULL, child);
|
||||
|
||||
/* No need to ignore `child`, because it has been detached already */
|
||||
ignore = NULL;
|
||||
child->klass->can_set_aio_ctx(child, s->old_parent_ctx, &ignore,
|
||||
&error_abort);
|
||||
g_slist_free(ignore);
|
||||
|
||||
ignore = NULL;
|
||||
ignore = g_slist_prepend(NULL, child);
|
||||
child->klass->set_aio_ctx(child, s->old_parent_ctx, &ignore);
|
||||
|
||||
g_slist_free(ignore);
|
||||
}
|
||||
|
||||
bdrv_unref(bs);
|
||||
bdrv_child_free(child);
|
||||
bdrv_remove_empty_child(child);
|
||||
*s->child = NULL;
|
||||
}
|
||||
|
||||
static TransactionActionDrv bdrv_attach_child_common_drv = {
|
||||
@@ -2946,15 +2834,13 @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
|
||||
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
bdrv_child_free(new_child);
|
||||
bdrv_remove_empty_child(new_child);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bdrv_ref(child_bs);
|
||||
bdrv_replace_child_noperm(&new_child, child_bs, true);
|
||||
/* child_bs was non-NULL, so new_child must not have been freed */
|
||||
assert(new_child != NULL);
|
||||
bdrv_replace_child_noperm(new_child, child_bs);
|
||||
|
||||
*child = new_child;
|
||||
|
||||
@@ -2989,12 +2875,6 @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
|
||||
|
||||
assert(parent_bs->drv);
|
||||
|
||||
if (bdrv_recurse_has_child(child_bs, parent_bs)) {
|
||||
error_setg(errp, "Making '%s' a %s child of '%s' would create a cycle",
|
||||
child_bs->node_name, child_name, parent_bs->node_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
|
||||
bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
|
||||
perm, shared_perm, &perm, &shared_perm);
|
||||
@@ -3006,14 +2886,21 @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
|
||||
return ret;
|
||||
}
|
||||
|
||||
QLIST_INSERT_HEAD(&parent_bs->children, *child, next);
|
||||
/*
|
||||
* child is removed in bdrv_attach_child_common_abort(), so don't care to
|
||||
* abort this change separately.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bdrv_detach_child(BdrvChild **childp)
|
||||
static void bdrv_detach_child(BdrvChild *child)
|
||||
{
|
||||
BlockDriverState *old_bs = (*childp)->bs;
|
||||
BlockDriverState *old_bs = child->bs;
|
||||
|
||||
bdrv_replace_child_noperm(childp, NULL, true);
|
||||
bdrv_replace_child_noperm(child, NULL);
|
||||
bdrv_remove_empty_child(child);
|
||||
|
||||
if (old_bs) {
|
||||
/*
|
||||
@@ -3119,7 +3006,7 @@ void bdrv_root_unref_child(BdrvChild *child)
|
||||
BlockDriverState *child_bs;
|
||||
|
||||
child_bs = child->bs;
|
||||
bdrv_detach_child(&child);
|
||||
bdrv_detach_child(child);
|
||||
bdrv_unref(child_bs);
|
||||
}
|
||||
|
||||
@@ -4929,7 +4816,6 @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
|
||||
|
||||
typedef struct BdrvRemoveFilterOrCowChild {
|
||||
BdrvChild *child;
|
||||
BlockDriverState *bs;
|
||||
bool is_backing;
|
||||
} BdrvRemoveFilterOrCowChild;
|
||||
|
||||
@@ -4938,6 +4824,7 @@ static void bdrv_remove_filter_or_cow_child_abort(void *opaque)
|
||||
BdrvRemoveFilterOrCowChild *s = opaque;
|
||||
BlockDriverState *parent_bs = s->child->opaque;
|
||||
|
||||
QLIST_INSERT_HEAD(&parent_bs->children, s->child, next);
|
||||
if (s->is_backing) {
|
||||
parent_bs->backing = s->child;
|
||||
} else {
|
||||
@@ -4959,19 +4846,10 @@ static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
|
||||
bdrv_child_free(s->child);
|
||||
}
|
||||
|
||||
static void bdrv_remove_filter_or_cow_child_clean(void *opaque)
|
||||
{
|
||||
BdrvRemoveFilterOrCowChild *s = opaque;
|
||||
|
||||
/* Drop the bs reference after the transaction is done */
|
||||
bdrv_unref(s->bs);
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
|
||||
.abort = bdrv_remove_filter_or_cow_child_abort,
|
||||
.commit = bdrv_remove_filter_or_cow_child_commit,
|
||||
.clean = bdrv_remove_filter_or_cow_child_clean,
|
||||
.clean = g_free,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -4982,41 +4860,31 @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
|
||||
BdrvChild *child,
|
||||
Transaction *tran)
|
||||
{
|
||||
BdrvChild **childp;
|
||||
BdrvRemoveFilterOrCowChild *s;
|
||||
|
||||
assert(child == bs->backing || child == bs->file);
|
||||
|
||||
if (!child) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep a reference to @bs so @childp will stay valid throughout the
|
||||
* transaction (required by bdrv_replace_child_tran())
|
||||
*/
|
||||
bdrv_ref(bs);
|
||||
if (child == bs->backing) {
|
||||
childp = &bs->backing;
|
||||
} else if (child == bs->file) {
|
||||
childp = &bs->file;
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (child->bs) {
|
||||
/*
|
||||
* Pass free_empty_child=false, we will free the child in
|
||||
* bdrv_remove_filter_or_cow_child_commit()
|
||||
*/
|
||||
bdrv_replace_child_tran(childp, NULL, tran, false);
|
||||
bdrv_replace_child_tran(child, NULL, tran);
|
||||
}
|
||||
|
||||
s = g_new(BdrvRemoveFilterOrCowChild, 1);
|
||||
*s = (BdrvRemoveFilterOrCowChild) {
|
||||
.child = child,
|
||||
.bs = bs,
|
||||
.is_backing = (childp == &bs->backing),
|
||||
.is_backing = (child == bs->backing),
|
||||
};
|
||||
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
|
||||
|
||||
QLIST_SAFE_REMOVE(child, next);
|
||||
if (s->is_backing) {
|
||||
bs->backing = NULL;
|
||||
} else {
|
||||
bs->file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5037,8 +4905,6 @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
|
||||
{
|
||||
BdrvChild *c, *next;
|
||||
|
||||
assert(to != NULL);
|
||||
|
||||
QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) {
|
||||
assert(c->bs == from);
|
||||
if (!should_update_child(c, to)) {
|
||||
@@ -5054,12 +4920,7 @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
|
||||
c->name, from->node_name);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Passing a pointer to the local variable @c is fine here, because
|
||||
* @to is not NULL, and so &c will not be attached to the transaction.
|
||||
*/
|
||||
bdrv_replace_child_tran(&c, to, tran, true);
|
||||
bdrv_replace_child_tran(c, to, tran);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -5074,8 +4935,6 @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
|
||||
*
|
||||
* With @detach_subchain=true @to must be in a backing chain of @from. In this
|
||||
* case backing link of the cow-parent of @to is removed.
|
||||
*
|
||||
* @to must not be NULL.
|
||||
*/
|
||||
static int bdrv_replace_node_common(BlockDriverState *from,
|
||||
BlockDriverState *to,
|
||||
@@ -5088,8 +4947,6 @@ static int bdrv_replace_node_common(BlockDriverState *from,
|
||||
BlockDriverState *to_cow_parent = NULL;
|
||||
int ret;
|
||||
|
||||
assert(to != NULL);
|
||||
|
||||
if (detach_subchain) {
|
||||
assert(bdrv_chain_contains(from, to));
|
||||
assert(from != to);
|
||||
@@ -5145,9 +5002,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace node @from by @to (where neither may be NULL).
|
||||
*/
|
||||
int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
|
||||
Error **errp)
|
||||
{
|
||||
@@ -5215,9 +5069,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
|
||||
bdrv_drained_begin(old_bs);
|
||||
bdrv_drained_begin(new_bs);
|
||||
|
||||
bdrv_replace_child_tran(&child, new_bs, tran, true);
|
||||
/* @new_bs must have been non-NULL, so @child must not have been freed */
|
||||
assert(child != NULL);
|
||||
bdrv_replace_child_tran(child, new_bs, tran);
|
||||
|
||||
found = g_hash_table_new(NULL, NULL);
|
||||
refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
|
||||
@@ -5250,61 +5102,29 @@ static void bdrv_delete(BlockDriverState *bs)
|
||||
g_free(bs);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Replace @bs by newly created block node.
|
||||
*
|
||||
* @options is a QDict of options to pass to the block drivers, or NULL for an
|
||||
* empty set of options. The reference to the QDict belongs to the block layer
|
||||
* after the call (even on failure), so if the caller intends to reuse the
|
||||
* dictionary, it needs to use qobject_ref() before calling bdrv_open.
|
||||
*/
|
||||
BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
|
||||
BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
|
||||
int flags, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
int ret;
|
||||
BlockDriverState *new_node_bs = NULL;
|
||||
const char *drvname, *node_name;
|
||||
BlockDriver *drv;
|
||||
BlockDriverState *new_node_bs;
|
||||
Error *local_err = NULL;
|
||||
|
||||
drvname = qdict_get_try_str(options, "driver");
|
||||
if (!drvname) {
|
||||
error_setg(errp, "driver is not specified");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
drv = bdrv_find_format(drvname);
|
||||
if (!drv) {
|
||||
error_setg(errp, "Unknown driver: '%s'", drvname);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
node_name = qdict_get_try_str(options, "node-name");
|
||||
|
||||
new_node_bs = bdrv_new_open_driver_opts(drv, node_name, options, flags,
|
||||
errp);
|
||||
options = NULL; /* bdrv_new_open_driver() eats options */
|
||||
if (!new_node_bs) {
|
||||
new_node_bs = bdrv_open(NULL, NULL, node_options, flags, errp);
|
||||
if (new_node_bs == NULL) {
|
||||
error_prepend(errp, "Could not create node: ");
|
||||
goto fail;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdrv_drained_begin(bs);
|
||||
ret = bdrv_replace_node(bs, new_node_bs, errp);
|
||||
bdrv_replace_node(bs, new_node_bs, &local_err);
|
||||
bdrv_drained_end(bs);
|
||||
|
||||
if (ret < 0) {
|
||||
error_prepend(errp, "Could not replace node: ");
|
||||
goto fail;
|
||||
if (local_err) {
|
||||
bdrv_unref(new_node_bs);
|
||||
error_propagate(errp, local_err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new_node_bs;
|
||||
|
||||
fail:
|
||||
qobject_unref(options);
|
||||
bdrv_unref(new_node_bs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -98,8 +98,6 @@ AioTaskPool *coroutine_fn aio_task_pool_new(int max_busy_tasks)
|
||||
{
|
||||
AioTaskPool *pool = g_new0(AioTaskPool, 1);
|
||||
|
||||
assert(max_busy_tasks > 0);
|
||||
|
||||
pool->main_co = qemu_coroutine_self();
|
||||
pool->max_busy_tasks = max_busy_tasks;
|
||||
|
||||
|
||||
+3
-4
@@ -327,12 +327,11 @@ static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
|
||||
}
|
||||
}
|
||||
|
||||
static bool backup_cancel(Job *job, bool force)
|
||||
static void backup_cancel(Job *job, bool force)
|
||||
{
|
||||
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
|
||||
|
||||
bdrv_cancel_in_flight(s->target_bs);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const BlockJobDriver backup_job_driver = {
|
||||
@@ -408,8 +407,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (perf->max_workers < 1 || perf->max_workers > INT_MAX) {
|
||||
error_setg(errp, "max-workers must be between 1 and %d", INT_MAX);
|
||||
if (perf->max_workers < 1) {
|
||||
error_setg(errp, "max-workers must be greater than zero");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+140
-115
@@ -14,7 +14,6 @@
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/blockjob.h"
|
||||
#include "block/coroutines.h"
|
||||
#include "block/throttle-groups.h"
|
||||
#include "hw/qdev-core.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
@@ -1162,11 +1161,11 @@ void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
|
||||
}
|
||||
|
||||
static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes)
|
||||
size_t size)
|
||||
{
|
||||
int64_t len;
|
||||
|
||||
if (bytes < 0) {
|
||||
if (size > INT_MAX) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -1184,7 +1183,7 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
|
||||
return len;
|
||||
}
|
||||
|
||||
if (offset > len || len - offset < bytes) {
|
||||
if (offset > len || len - offset < size) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
@@ -1205,9 +1204,9 @@ static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
|
||||
}
|
||||
|
||||
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
||||
int coroutine_fn
|
||||
blk_co_do_preadv(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, BdrvRequestFlags flags)
|
||||
static int coroutine_fn
|
||||
blk_do_preadv(BlockBackend *blk, int64_t offset, unsigned int bytes,
|
||||
QEMUIOVector *qiov, BdrvRequestFlags flags)
|
||||
{
|
||||
int ret;
|
||||
BlockDriverState *bs;
|
||||
@@ -1237,23 +1236,23 @@ blk_co_do_preadv(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
}
|
||||
|
||||
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes, QEMUIOVector *qiov,
|
||||
unsigned int bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
ret = blk_co_do_preadv(blk, offset, bytes, qiov, flags);
|
||||
ret = blk_do_preadv(blk, offset, bytes, qiov, flags);
|
||||
blk_dec_in_flight(blk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
||||
int coroutine_fn
|
||||
blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, size_t qiov_offset,
|
||||
BdrvRequestFlags flags)
|
||||
static int coroutine_fn
|
||||
blk_do_pwritev_part(BlockBackend *blk, int64_t offset, unsigned int bytes,
|
||||
QEMUIOVector *qiov, size_t qiov_offset,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
int ret;
|
||||
BlockDriverState *bs;
|
||||
@@ -1287,33 +1286,12 @@ blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
}
|
||||
|
||||
int coroutine_fn blk_co_pwritev_part(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes,
|
||||
unsigned int bytes,
|
||||
QEMUIOVector *qiov, size_t qiov_offset,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
ret = blk_co_do_pwritev_part(blk, offset, bytes, qiov, qiov_offset, flags);
|
||||
blk_dec_in_flight(blk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
return blk_co_pwritev_part(blk, offset, bytes, qiov, 0, flags);
|
||||
}
|
||||
|
||||
static int coroutine_fn blk_pwritev_part(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes,
|
||||
QEMUIOVector *qiov, size_t qiov_offset,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
ret = blk_do_pwritev_part(blk, offset, bytes, qiov, qiov_offset, flags);
|
||||
blk_dec_in_flight(blk);
|
||||
@@ -1321,6 +1299,13 @@ static int coroutine_fn blk_pwritev_part(BlockBackend *blk, int64_t offset,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
|
||||
unsigned int bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
return blk_co_pwritev_part(blk, offset, bytes, qiov, 0, flags);
|
||||
}
|
||||
|
||||
typedef struct BlkRwCo {
|
||||
BlockBackend *blk;
|
||||
int64_t offset;
|
||||
@@ -1329,11 +1314,58 @@ typedef struct BlkRwCo {
|
||||
BdrvRequestFlags flags;
|
||||
} BlkRwCo;
|
||||
|
||||
int blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes, BdrvRequestFlags flags)
|
||||
static void blk_read_entry(void *opaque)
|
||||
{
|
||||
return blk_pwritev_part(blk, offset, bytes, NULL, 0,
|
||||
flags | BDRV_REQ_ZERO_WRITE);
|
||||
BlkRwCo *rwco = opaque;
|
||||
QEMUIOVector *qiov = rwco->iobuf;
|
||||
|
||||
rwco->ret = blk_do_preadv(rwco->blk, rwco->offset, qiov->size,
|
||||
qiov, rwco->flags);
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
static void blk_write_entry(void *opaque)
|
||||
{
|
||||
BlkRwCo *rwco = opaque;
|
||||
QEMUIOVector *qiov = rwco->iobuf;
|
||||
|
||||
rwco->ret = blk_do_pwritev_part(rwco->blk, rwco->offset, qiov->size,
|
||||
qiov, 0, rwco->flags);
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
|
||||
int64_t bytes, CoroutineEntry co_entry,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||
BlkRwCo rwco = {
|
||||
.blk = blk,
|
||||
.offset = offset,
|
||||
.iobuf = &qiov,
|
||||
.flags = flags,
|
||||
.ret = NOT_DONE,
|
||||
};
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
if (qemu_in_coroutine()) {
|
||||
/* Fast-path if already in coroutine context */
|
||||
co_entry(&rwco);
|
||||
} else {
|
||||
Coroutine *co = qemu_coroutine_create(co_entry, &rwco);
|
||||
bdrv_coroutine_enter(blk_bs(blk), co);
|
||||
BDRV_POLL_WHILE(blk_bs(blk), rwco.ret == NOT_DONE);
|
||||
}
|
||||
blk_dec_in_flight(blk);
|
||||
|
||||
return rwco.ret;
|
||||
}
|
||||
|
||||
int blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
||||
int bytes, BdrvRequestFlags flags)
|
||||
{
|
||||
return blk_prw(blk, offset, NULL, bytes, blk_write_entry,
|
||||
flags | BDRV_REQ_ZERO_WRITE);
|
||||
}
|
||||
|
||||
int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
|
||||
@@ -1380,7 +1412,7 @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
|
||||
typedef struct BlkAioEmAIOCB {
|
||||
BlockAIOCB common;
|
||||
BlkRwCo rwco;
|
||||
int64_t bytes;
|
||||
int bytes;
|
||||
bool has_returned;
|
||||
} BlkAioEmAIOCB;
|
||||
|
||||
@@ -1412,8 +1444,7 @@ static void blk_aio_complete_bh(void *opaque)
|
||||
blk_aio_complete(acb);
|
||||
}
|
||||
|
||||
static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes,
|
||||
static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
|
||||
void *iobuf, CoroutineEntry co_entry,
|
||||
BdrvRequestFlags flags,
|
||||
BlockCompletionFunc *cb, void *opaque)
|
||||
@@ -1452,8 +1483,8 @@ static void blk_aio_read_entry(void *opaque)
|
||||
QEMUIOVector *qiov = rwco->iobuf;
|
||||
|
||||
assert(qiov->size == acb->bytes);
|
||||
rwco->ret = blk_co_do_preadv(rwco->blk, rwco->offset, acb->bytes,
|
||||
qiov, rwco->flags);
|
||||
rwco->ret = blk_do_preadv(rwco->blk, rwco->offset, acb->bytes,
|
||||
qiov, rwco->flags);
|
||||
blk_aio_complete(acb);
|
||||
}
|
||||
|
||||
@@ -1464,40 +1495,37 @@ static void blk_aio_write_entry(void *opaque)
|
||||
QEMUIOVector *qiov = rwco->iobuf;
|
||||
|
||||
assert(!qiov || qiov->size == acb->bytes);
|
||||
rwco->ret = blk_co_do_pwritev_part(rwco->blk, rwco->offset, acb->bytes,
|
||||
qiov, 0, rwco->flags);
|
||||
rwco->ret = blk_do_pwritev_part(rwco->blk, rwco->offset, acb->bytes,
|
||||
qiov, 0, rwco->flags);
|
||||
blk_aio_complete(acb);
|
||||
}
|
||||
|
||||
BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes, BdrvRequestFlags flags,
|
||||
int count, BdrvRequestFlags flags,
|
||||
BlockCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
return blk_aio_prwv(blk, offset, bytes, NULL, blk_aio_write_entry,
|
||||
return blk_aio_prwv(blk, offset, count, NULL, blk_aio_write_entry,
|
||||
flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
|
||||
}
|
||||
|
||||
int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int bytes)
|
||||
int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count)
|
||||
{
|
||||
int ret;
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
ret = blk_do_preadv(blk, offset, bytes, &qiov, 0);
|
||||
blk_dec_in_flight(blk);
|
||||
|
||||
return ret < 0 ? ret : bytes;
|
||||
int ret = blk_prw(blk, offset, buf, count, blk_read_entry, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int bytes,
|
||||
int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count,
|
||||
BdrvRequestFlags flags)
|
||||
{
|
||||
int ret;
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||
|
||||
ret = blk_pwritev_part(blk, offset, bytes, &qiov, 0, flags);
|
||||
|
||||
return ret < 0 ? ret : bytes;
|
||||
int ret = blk_prw(blk, offset, (void *) buf, count, blk_write_entry,
|
||||
flags);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int64_t blk_getlength(BlockBackend *blk)
|
||||
@@ -1531,7 +1559,6 @@ BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
|
||||
QEMUIOVector *qiov, BdrvRequestFlags flags,
|
||||
BlockCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
assert((uint64_t)qiov->size <= INT64_MAX);
|
||||
return blk_aio_prwv(blk, offset, qiov->size, qiov,
|
||||
blk_aio_read_entry, flags, cb, opaque);
|
||||
}
|
||||
@@ -1540,7 +1567,6 @@ BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset,
|
||||
QEMUIOVector *qiov, BdrvRequestFlags flags,
|
||||
BlockCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
assert((uint64_t)qiov->size <= INT64_MAX);
|
||||
return blk_aio_prwv(blk, offset, qiov->size, qiov,
|
||||
blk_aio_write_entry, flags, cb, opaque);
|
||||
}
|
||||
@@ -1556,8 +1582,8 @@ void blk_aio_cancel_async(BlockAIOCB *acb)
|
||||
}
|
||||
|
||||
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
||||
int coroutine_fn
|
||||
blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
|
||||
static int coroutine_fn
|
||||
blk_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
|
||||
{
|
||||
blk_wait_while_drained(blk);
|
||||
|
||||
@@ -1568,15 +1594,18 @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
|
||||
return bdrv_co_ioctl(blk_bs(blk), req, buf);
|
||||
}
|
||||
|
||||
static void blk_ioctl_entry(void *opaque)
|
||||
{
|
||||
BlkRwCo *rwco = opaque;
|
||||
QEMUIOVector *qiov = rwco->iobuf;
|
||||
|
||||
rwco->ret = blk_do_ioctl(rwco->blk, rwco->offset, qiov->iov[0].iov_base);
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
ret = blk_do_ioctl(blk, req, buf);
|
||||
blk_dec_in_flight(blk);
|
||||
|
||||
return ret;
|
||||
return blk_prw(blk, req, buf, 0, blk_ioctl_entry, 0);
|
||||
}
|
||||
|
||||
static void blk_aio_ioctl_entry(void *opaque)
|
||||
@@ -1584,7 +1613,7 @@ static void blk_aio_ioctl_entry(void *opaque)
|
||||
BlkAioEmAIOCB *acb = opaque;
|
||||
BlkRwCo *rwco = &acb->rwco;
|
||||
|
||||
rwco->ret = blk_co_do_ioctl(rwco->blk, rwco->offset, rwco->iobuf);
|
||||
rwco->ret = blk_do_ioctl(rwco->blk, rwco->offset, rwco->iobuf);
|
||||
|
||||
blk_aio_complete(acb);
|
||||
}
|
||||
@@ -1596,8 +1625,8 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
|
||||
}
|
||||
|
||||
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
||||
int coroutine_fn
|
||||
blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
|
||||
static int coroutine_fn
|
||||
blk_do_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -1616,31 +1645,19 @@ static void blk_aio_pdiscard_entry(void *opaque)
|
||||
BlkAioEmAIOCB *acb = opaque;
|
||||
BlkRwCo *rwco = &acb->rwco;
|
||||
|
||||
rwco->ret = blk_co_do_pdiscard(rwco->blk, rwco->offset, acb->bytes);
|
||||
rwco->ret = blk_do_pdiscard(rwco->blk, rwco->offset, acb->bytes);
|
||||
blk_aio_complete(acb);
|
||||
}
|
||||
|
||||
BlockAIOCB *blk_aio_pdiscard(BlockBackend *blk,
|
||||
int64_t offset, int64_t bytes,
|
||||
int64_t offset, int bytes,
|
||||
BlockCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
return blk_aio_prwv(blk, offset, bytes, NULL, blk_aio_pdiscard_entry, 0,
|
||||
cb, opaque);
|
||||
}
|
||||
|
||||
int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
ret = blk_co_do_pdiscard(blk, offset, bytes);
|
||||
blk_dec_in_flight(blk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int blk_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
|
||||
int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -1651,8 +1668,22 @@ int blk_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void blk_pdiscard_entry(void *opaque)
|
||||
{
|
||||
BlkRwCo *rwco = opaque;
|
||||
QEMUIOVector *qiov = rwco->iobuf;
|
||||
|
||||
rwco->ret = blk_do_pdiscard(rwco->blk, rwco->offset, qiov->size);
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes)
|
||||
{
|
||||
return blk_prw(blk, offset, NULL, bytes, blk_pdiscard_entry, 0);
|
||||
}
|
||||
|
||||
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
||||
int coroutine_fn blk_co_do_flush(BlockBackend *blk)
|
||||
static int coroutine_fn blk_do_flush(BlockBackend *blk)
|
||||
{
|
||||
blk_wait_while_drained(blk);
|
||||
|
||||
@@ -1668,7 +1699,7 @@ static void blk_aio_flush_entry(void *opaque)
|
||||
BlkAioEmAIOCB *acb = opaque;
|
||||
BlkRwCo *rwco = &acb->rwco;
|
||||
|
||||
rwco->ret = blk_co_do_flush(rwco->blk);
|
||||
rwco->ret = blk_do_flush(rwco->blk);
|
||||
blk_aio_complete(acb);
|
||||
}
|
||||
|
||||
@@ -1683,21 +1714,22 @@ int coroutine_fn blk_co_flush(BlockBackend *blk)
|
||||
int ret;
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
ret = blk_co_do_flush(blk);
|
||||
ret = blk_do_flush(blk);
|
||||
blk_dec_in_flight(blk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void blk_flush_entry(void *opaque)
|
||||
{
|
||||
BlkRwCo *rwco = opaque;
|
||||
rwco->ret = blk_do_flush(rwco->blk);
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
int blk_flush(BlockBackend *blk)
|
||||
{
|
||||
int ret;
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
ret = blk_do_flush(blk);
|
||||
blk_dec_in_flight(blk);
|
||||
|
||||
return ret;
|
||||
return blk_prw(blk, 0, NULL, 0, blk_flush_entry, 0);
|
||||
}
|
||||
|
||||
void blk_drain(BlockBackend *blk)
|
||||
@@ -1954,12 +1986,6 @@ uint32_t blk_get_max_transfer(BlockBackend *blk)
|
||||
return ROUND_DOWN(max, blk_get_request_alignment(blk));
|
||||
}
|
||||
|
||||
int blk_get_max_hw_iov(BlockBackend *blk)
|
||||
{
|
||||
return MIN_NON_ZERO(blk->root->bs->bl.max_hw_iov,
|
||||
blk->root->bs->bl.max_iov);
|
||||
}
|
||||
|
||||
int blk_get_max_iov(BlockBackend *blk)
|
||||
{
|
||||
return blk->root->bs->bl.max_iov;
|
||||
@@ -2182,18 +2208,17 @@ void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
|
||||
}
|
||||
|
||||
int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
||||
int64_t bytes, BdrvRequestFlags flags)
|
||||
int bytes, BdrvRequestFlags flags)
|
||||
{
|
||||
return blk_co_pwritev(blk, offset, bytes, NULL,
|
||||
flags | BDRV_REQ_ZERO_WRITE);
|
||||
}
|
||||
|
||||
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
|
||||
int64_t bytes)
|
||||
int count)
|
||||
{
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||
return blk_pwritev_part(blk, offset, bytes, &qiov, 0,
|
||||
BDRV_REQ_WRITE_COMPRESSED);
|
||||
return blk_prw(blk, offset, (void *) buf, count, blk_write_entry,
|
||||
BDRV_REQ_WRITE_COMPRESSED);
|
||||
}
|
||||
|
||||
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
|
||||
@@ -2421,7 +2446,7 @@ void blk_unregister_buf(BlockBackend *blk, void *host)
|
||||
|
||||
int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
|
||||
BlockBackend *blk_out, int64_t off_out,
|
||||
int64_t bytes, BdrvRequestFlags read_flags,
|
||||
int bytes, BdrvRequestFlags read_flags,
|
||||
BdrvRequestFlags write_flags)
|
||||
{
|
||||
int r;
|
||||
|
||||
@@ -27,9 +27,6 @@
|
||||
|
||||
#include "block/block_int.h"
|
||||
|
||||
/* For blk_bs() in generated block/block-gen.c */
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
int coroutine_fn bdrv_co_check(BlockDriverState *bs,
|
||||
BdrvCheckResult *res, BdrvCheckMode fix);
|
||||
int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp);
|
||||
@@ -75,34 +72,4 @@ int coroutine_fn
|
||||
nbd_co_do_establish_connection(BlockDriverState *bs, Error **errp);
|
||||
|
||||
|
||||
int generated_co_wrapper
|
||||
blk_do_preadv(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, BdrvRequestFlags flags);
|
||||
int coroutine_fn
|
||||
blk_co_do_preadv(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, BdrvRequestFlags flags);
|
||||
|
||||
|
||||
int generated_co_wrapper
|
||||
blk_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, size_t qiov_offset,
|
||||
BdrvRequestFlags flags);
|
||||
int coroutine_fn
|
||||
blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, size_t qiov_offset,
|
||||
BdrvRequestFlags flags);
|
||||
|
||||
int generated_co_wrapper
|
||||
blk_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
|
||||
int coroutine_fn
|
||||
blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
|
||||
|
||||
int generated_co_wrapper
|
||||
blk_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
|
||||
int coroutine_fn
|
||||
blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
|
||||
|
||||
int generated_co_wrapper blk_do_flush(BlockBackend *blk);
|
||||
int coroutine_fn blk_co_do_flush(BlockBackend *blk);
|
||||
|
||||
#endif /* BLOCK_COROUTINES_INT_H */
|
||||
@@ -31,10 +31,6 @@
|
||||
#include <fuse.h>
|
||||
#include <fuse_lowlevel.h>
|
||||
|
||||
#if defined(CONFIG_FALLOCATE_ZERO_RANGE)
|
||||
#include <linux/falloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/fs.h>
|
||||
#endif
|
||||
|
||||
+9
-31
@@ -150,8 +150,6 @@ typedef struct BDRVRawState {
|
||||
uint64_t locked_perm;
|
||||
uint64_t locked_shared_perm;
|
||||
|
||||
uint64_t aio_max_batch;
|
||||
|
||||
int perm_change_fd;
|
||||
int perm_change_flags;
|
||||
BDRVReopenState *reopen_state;
|
||||
@@ -167,7 +165,6 @@ typedef struct BDRVRawState {
|
||||
int page_cache_inconsistent; /* errno from fdatasync failure */
|
||||
bool has_fallocate;
|
||||
bool needs_alignment;
|
||||
bool force_alignment;
|
||||
bool drop_cache;
|
||||
bool check_cache_dropped;
|
||||
struct {
|
||||
@@ -352,17 +349,6 @@ static bool dio_byte_aligned(int fd)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool raw_needs_alignment(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return s->force_alignment;
|
||||
}
|
||||
|
||||
/* Check if read is allowed with given memory buffer and length.
|
||||
*
|
||||
* This function is used to check O_DIRECT memory buffer and request alignment.
|
||||
@@ -544,11 +530,6 @@ static QemuOptsList raw_runtime_opts = {
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "host AIO implementation (threads, native, io_uring)",
|
||||
},
|
||||
{
|
||||
.name = "aio-max-batch",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "AIO max batch size (0 = auto handled by AIO backend, default: 0)",
|
||||
},
|
||||
{
|
||||
.name = "locking",
|
||||
.type = QEMU_OPT_STRING,
|
||||
@@ -628,8 +609,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
s->use_linux_io_uring = (aio == BLOCKDEV_AIO_OPTIONS_IO_URING);
|
||||
#endif
|
||||
|
||||
s->aio_max_batch = qemu_opt_get_number(opts, "aio-max-batch", 0);
|
||||
|
||||
locking = qapi_enum_parse(&OnOffAuto_lookup,
|
||||
qemu_opt_get(opts, "locking"),
|
||||
ON_OFF_AUTO_AUTO, &local_err);
|
||||
@@ -740,6 +719,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
|
||||
s->has_discard = true;
|
||||
s->has_write_zeroes = true;
|
||||
if ((bs->open_flags & BDRV_O_NOCACHE) != 0 && !dio_byte_aligned(s->fd)) {
|
||||
s->needs_alignment = true;
|
||||
}
|
||||
|
||||
if (fstat(s->fd, &st) < 0) {
|
||||
ret = -errno;
|
||||
@@ -793,10 +775,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
* so QEMU makes sure all IO operations on the device are aligned
|
||||
* to sector size, or else FreeBSD will reject them with EINVAL.
|
||||
*/
|
||||
s->force_alignment = true;
|
||||
s->needs_alignment = true;
|
||||
}
|
||||
#endif
|
||||
s->needs_alignment = raw_needs_alignment(bs);
|
||||
|
||||
#ifdef CONFIG_XFS
|
||||
if (platform_test_xfs_fd(s->fd)) {
|
||||
@@ -1261,9 +1242,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
BDRVRawState *s = bs->opaque;
|
||||
struct stat st;
|
||||
|
||||
s->needs_alignment = raw_needs_alignment(bs);
|
||||
raw_probe_alignment(bs, s->fd, errp);
|
||||
|
||||
bs->bl.min_mem_alignment = s->buf_align;
|
||||
bs->bl.opt_mem_alignment = MAX(s->buf_align, qemu_real_host_page_size);
|
||||
|
||||
@@ -1294,7 +1273,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
|
||||
ret = hdev_get_max_segments(s->fd, &st);
|
||||
if (ret > 0) {
|
||||
bs->bl.max_hw_iov = ret;
|
||||
bs->bl.max_iov = ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1828,7 +1807,7 @@ static int handle_aiocb_copy_range(void *opaque)
|
||||
static int handle_aiocb_discard(void *opaque)
|
||||
{
|
||||
RawPosixAIOData *aiocb = opaque;
|
||||
int ret = -ENOTSUP;
|
||||
int ret = -EOPNOTSUPP;
|
||||
BDRVRawState *s = aiocb->bs->opaque;
|
||||
|
||||
if (!s->has_discard) {
|
||||
@@ -1850,7 +1829,7 @@ static int handle_aiocb_discard(void *opaque)
|
||||
#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
|
||||
ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
||||
aiocb->aio_offset, aiocb->aio_nbytes);
|
||||
ret = translate_err(ret);
|
||||
ret = translate_err(-errno);
|
||||
#elif defined(__APPLE__) && (__MACH__)
|
||||
fpunchhole_t fpunchhole;
|
||||
fpunchhole.fp_flags = 0;
|
||||
@@ -2078,8 +2057,7 @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
|
||||
} else if (s->use_linux_aio) {
|
||||
LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
|
||||
assert(qiov->size == bytes);
|
||||
return laio_co_submit(bs, aio, s->fd, offset, qiov, type,
|
||||
s->aio_max_batch);
|
||||
return laio_co_submit(bs, aio, s->fd, offset, qiov, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2137,7 +2115,7 @@ static void raw_aio_unplug(BlockDriverState *bs)
|
||||
#ifdef CONFIG_LINUX_AIO
|
||||
if (s->use_linux_aio) {
|
||||
LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
|
||||
laio_io_unplug(bs, aio, s->aio_max_batch);
|
||||
laio_io_unplug(bs, aio);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_LINUX_IO_URING
|
||||
|
||||
@@ -136,7 +136,6 @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src)
|
||||
dst->min_mem_alignment = MAX(dst->min_mem_alignment,
|
||||
src->min_mem_alignment);
|
||||
dst->max_iov = MIN_NON_ZERO(dst->max_iov, src->max_iov);
|
||||
dst->max_hw_iov = MIN_NON_ZERO(dst->max_hw_iov, src->max_hw_iov);
|
||||
}
|
||||
|
||||
typedef struct BdrvRefreshLimitsState {
|
||||
|
||||
+11
-27
@@ -334,45 +334,30 @@ static void ioq_submit(LinuxAioState *s)
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t laio_max_batch(LinuxAioState *s, uint64_t dev_max_batch)
|
||||
{
|
||||
uint64_t max_batch = s->aio_context->aio_max_batch ?: DEFAULT_MAX_BATCH;
|
||||
|
||||
/*
|
||||
* AIO context can be shared between multiple block devices, so
|
||||
* `dev_max_batch` allows reducing the batch size for latency-sensitive
|
||||
* devices.
|
||||
*/
|
||||
max_batch = MIN_NON_ZERO(dev_max_batch, max_batch);
|
||||
|
||||
/* limit the batch with the number of available events */
|
||||
max_batch = MIN_NON_ZERO(MAX_EVENTS - s->io_q.in_flight, max_batch);
|
||||
|
||||
return max_batch;
|
||||
}
|
||||
|
||||
void laio_io_plug(BlockDriverState *bs, LinuxAioState *s)
|
||||
{
|
||||
s->io_q.plugged++;
|
||||
}
|
||||
|
||||
void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s,
|
||||
uint64_t dev_max_batch)
|
||||
void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s)
|
||||
{
|
||||
assert(s->io_q.plugged);
|
||||
if (s->io_q.in_queue >= laio_max_batch(s, dev_max_batch) ||
|
||||
(--s->io_q.plugged == 0 &&
|
||||
!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending))) {
|
||||
if (--s->io_q.plugged == 0 &&
|
||||
!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
|
||||
ioq_submit(s);
|
||||
}
|
||||
}
|
||||
|
||||
static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
|
||||
int type, uint64_t dev_max_batch)
|
||||
int type)
|
||||
{
|
||||
LinuxAioState *s = laiocb->ctx;
|
||||
struct iocb *iocbs = &laiocb->iocb;
|
||||
QEMUIOVector *qiov = laiocb->qiov;
|
||||
int64_t max_batch = s->aio_context->aio_max_batch ?: DEFAULT_MAX_BATCH;
|
||||
|
||||
/* limit the batch with the number of available events */
|
||||
max_batch = MIN_NON_ZERO(MAX_EVENTS - s->io_q.in_flight, max_batch);
|
||||
|
||||
switch (type) {
|
||||
case QEMU_AIO_WRITE:
|
||||
@@ -393,7 +378,7 @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
|
||||
s->io_q.in_queue++;
|
||||
if (!s->io_q.blocked &&
|
||||
(!s->io_q.plugged ||
|
||||
s->io_q.in_queue >= laio_max_batch(s, dev_max_batch))) {
|
||||
s->io_q.in_queue >= max_batch)) {
|
||||
ioq_submit(s);
|
||||
}
|
||||
|
||||
@@ -401,8 +386,7 @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
|
||||
}
|
||||
|
||||
int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
|
||||
uint64_t offset, QEMUIOVector *qiov, int type,
|
||||
uint64_t dev_max_batch)
|
||||
uint64_t offset, QEMUIOVector *qiov, int type)
|
||||
{
|
||||
int ret;
|
||||
struct qemu_laiocb laiocb = {
|
||||
@@ -414,7 +398,7 @@ int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
|
||||
.qiov = qiov,
|
||||
};
|
||||
|
||||
ret = laio_do_submit(fd, &laiocb, offset, type, dev_max_batch);
|
||||
ret = laio_do_submit(fd, &laiocb, offset, type);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ block_ss.add(when: 'CONFIG_POSIX', if_true: [files('file-posix.c'), coref, iokit
|
||||
block_ss.add(when: libiscsi, if_true: files('iscsi-opts.c'))
|
||||
block_ss.add(when: 'CONFIG_LINUX', if_true: files('nvme.c'))
|
||||
block_ss.add(when: 'CONFIG_REPLICATION', if_true: files('replication.c'))
|
||||
block_ss.add(when: libaio, if_true: files('linux-aio.c'))
|
||||
block_ss.add(when: ['CONFIG_LINUX_AIO', libaio], if_true: files('linux-aio.c'))
|
||||
block_ss.add(when: linux_io_uring, if_true: files('io_uring.c'))
|
||||
|
||||
block_modules = {}
|
||||
|
||||
+24
-32
@@ -56,6 +56,7 @@ typedef struct MirrorBlockJob {
|
||||
bool zero_target;
|
||||
MirrorCopyMode copy_mode;
|
||||
BlockdevOnError on_source_error, on_target_error;
|
||||
bool synced;
|
||||
/* Set when the target is synced (dirty bitmap is clean, nothing
|
||||
* in flight) and the job is running in active mode */
|
||||
bool actively_synced;
|
||||
@@ -120,6 +121,7 @@ typedef enum MirrorMethod {
|
||||
static BlockErrorAction mirror_error_action(MirrorBlockJob *s, bool read,
|
||||
int error)
|
||||
{
|
||||
s->synced = false;
|
||||
s->actively_synced = false;
|
||||
if (read) {
|
||||
return block_job_error_action(&s->common, s->on_source_error,
|
||||
@@ -942,10 +944,12 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
|
||||
if (s->bdev_length == 0) {
|
||||
/* Transition to the READY state and wait for complete. */
|
||||
job_transition_to_ready(&s->common.job);
|
||||
s->synced = true;
|
||||
s->actively_synced = true;
|
||||
while (!job_cancel_requested(&s->common.job) && !s->should_complete) {
|
||||
while (!job_is_cancelled(&s->common.job) && !s->should_complete) {
|
||||
job_yield(&s->common.job);
|
||||
}
|
||||
s->common.job.cancelled = false;
|
||||
goto immediate_exit;
|
||||
}
|
||||
|
||||
@@ -1006,11 +1010,6 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
|
||||
|
||||
job_pause_point(&s->common.job);
|
||||
|
||||
if (job_is_cancelled(&s->common.job)) {
|
||||
ret = 0;
|
||||
goto immediate_exit;
|
||||
}
|
||||
|
||||
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
|
||||
/* cnt is the number of dirty bytes remaining and s->bytes_in_flight is
|
||||
* the number of bytes currently being processed; together those are
|
||||
@@ -1037,7 +1036,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
|
||||
should_complete = false;
|
||||
if (s->in_flight == 0 && cnt == 0) {
|
||||
trace_mirror_before_flush(s);
|
||||
if (!job_is_ready(&s->common.job)) {
|
||||
if (!s->synced) {
|
||||
if (mirror_flush(s) < 0) {
|
||||
/* Go check s->ret. */
|
||||
continue;
|
||||
@@ -1048,13 +1047,14 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
|
||||
* the target in a consistent state.
|
||||
*/
|
||||
job_transition_to_ready(&s->common.job);
|
||||
s->synced = true;
|
||||
if (s->copy_mode != MIRROR_COPY_MODE_BACKGROUND) {
|
||||
s->actively_synced = true;
|
||||
}
|
||||
}
|
||||
|
||||
should_complete = s->should_complete ||
|
||||
job_cancel_requested(&s->common.job);
|
||||
job_is_cancelled(&s->common.job);
|
||||
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
|
||||
}
|
||||
|
||||
@@ -1084,17 +1084,24 @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
|
||||
* completion.
|
||||
*/
|
||||
assert(QLIST_EMPTY(&bs->tracked_requests));
|
||||
s->common.job.cancelled = false;
|
||||
need_drain = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (job_is_ready(&s->common.job) && !should_complete) {
|
||||
ret = 0;
|
||||
|
||||
if (s->synced && !should_complete) {
|
||||
delay_ns = (s->in_flight == 0 &&
|
||||
cnt == 0 ? BLOCK_JOB_SLICE_TIME : 0);
|
||||
}
|
||||
trace_mirror_before_sleep(s, cnt, job_is_ready(&s->common.job),
|
||||
delay_ns);
|
||||
trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
|
||||
job_sleep_ns(&s->common.job, delay_ns);
|
||||
if (job_is_cancelled(&s->common.job) &&
|
||||
(!s->synced || s->common.job.force_cancel))
|
||||
{
|
||||
break;
|
||||
}
|
||||
s->last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||
}
|
||||
|
||||
@@ -1104,7 +1111,8 @@ immediate_exit:
|
||||
* or it was cancelled prematurely so that we do not guarantee that
|
||||
* the target is a copy of the source.
|
||||
*/
|
||||
assert(ret < 0 || job_is_cancelled(&s->common.job));
|
||||
assert(ret < 0 || ((s->common.job.force_cancel || !s->synced) &&
|
||||
job_is_cancelled(&s->common.job)));
|
||||
assert(need_drain);
|
||||
mirror_wait_for_all_io(s);
|
||||
}
|
||||
@@ -1127,7 +1135,7 @@ static void mirror_complete(Job *job, Error **errp)
|
||||
{
|
||||
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
|
||||
|
||||
if (!job_is_ready(job)) {
|
||||
if (!s->synced) {
|
||||
error_setg(errp, "The active block job '%s' cannot be completed",
|
||||
job->id);
|
||||
return;
|
||||
@@ -1182,34 +1190,21 @@ static bool mirror_drained_poll(BlockJob *job)
|
||||
* from one of our own drain sections, to avoid a deadlock waiting for
|
||||
* ourselves.
|
||||
*/
|
||||
if (!s->common.job.paused && !job_is_cancelled(&job->job) && !s->in_drain) {
|
||||
if (!s->common.job.paused && !s->common.job.cancelled && !s->in_drain) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !!s->in_flight;
|
||||
}
|
||||
|
||||
static bool mirror_cancel(Job *job, bool force)
|
||||
static void mirror_cancel(Job *job, bool force)
|
||||
{
|
||||
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job);
|
||||
BlockDriverState *target = blk_bs(s->target);
|
||||
|
||||
/*
|
||||
* Before the job is READY, we treat any cancellation like a
|
||||
* force-cancellation.
|
||||
*/
|
||||
force = force || !job_is_ready(job);
|
||||
|
||||
if (force) {
|
||||
if (force || !job_is_ready(job)) {
|
||||
bdrv_cancel_in_flight(target);
|
||||
}
|
||||
return force;
|
||||
}
|
||||
|
||||
static bool commit_active_cancel(Job *job, bool force)
|
||||
{
|
||||
/* Same as above in mirror_cancel() */
|
||||
return force || !job_is_ready(job);
|
||||
}
|
||||
|
||||
static const BlockJobDriver mirror_job_driver = {
|
||||
@@ -1239,7 +1234,6 @@ static const BlockJobDriver commit_active_job_driver = {
|
||||
.abort = mirror_abort,
|
||||
.pause = mirror_pause,
|
||||
.complete = mirror_complete,
|
||||
.cancel = commit_active_cancel,
|
||||
},
|
||||
.drained_poll = mirror_drained_poll,
|
||||
};
|
||||
@@ -1423,7 +1417,6 @@ static int coroutine_fn bdrv_mirror_top_do_write(BlockDriverState *bs,
|
||||
bool copy_to_target;
|
||||
|
||||
copy_to_target = s->job->ret >= 0 &&
|
||||
!job_is_cancelled(&s->job->common.job) &&
|
||||
s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING;
|
||||
|
||||
if (copy_to_target) {
|
||||
@@ -1472,7 +1465,6 @@ static int coroutine_fn bdrv_mirror_top_pwritev(BlockDriverState *bs,
|
||||
bool copy_to_target;
|
||||
|
||||
copy_to_target = s->job->ret >= 0 &&
|
||||
!job_is_cancelled(&s->job->common.job) &&
|
||||
s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING;
|
||||
|
||||
if (copy_to_target) {
|
||||
|
||||
+1
-44
@@ -80,7 +80,6 @@ typedef struct BDRVNBDState {
|
||||
NBDClientState state;
|
||||
|
||||
QEMUTimer *reconnect_delay_timer;
|
||||
QEMUTimer *open_timer;
|
||||
|
||||
NBDClientRequest requests[MAX_NBD_REQUESTS];
|
||||
NBDReply reply;
|
||||
@@ -88,7 +87,6 @@ typedef struct BDRVNBDState {
|
||||
|
||||
/* Connection parameters */
|
||||
uint32_t reconnect_delay;
|
||||
uint32_t open_timeout;
|
||||
SocketAddress *saddr;
|
||||
char *export, *tlscredsid;
|
||||
QCryptoTLSCreds *tlscreds;
|
||||
@@ -220,32 +218,6 @@ static void nbd_teardown_connection(BlockDriverState *bs)
|
||||
s->state = NBD_CLIENT_QUIT;
|
||||
}
|
||||
|
||||
static void open_timer_del(BDRVNBDState *s)
|
||||
{
|
||||
if (s->open_timer) {
|
||||
timer_free(s->open_timer);
|
||||
s->open_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void open_timer_cb(void *opaque)
|
||||
{
|
||||
BDRVNBDState *s = opaque;
|
||||
|
||||
nbd_co_establish_connection_cancel(s->conn);
|
||||
open_timer_del(s);
|
||||
}
|
||||
|
||||
static void open_timer_init(BDRVNBDState *s, uint64_t expire_time_ns)
|
||||
{
|
||||
assert(!s->open_timer);
|
||||
s->open_timer = aio_timer_new(bdrv_get_aio_context(s->bs),
|
||||
QEMU_CLOCK_REALTIME,
|
||||
SCALE_NS,
|
||||
open_timer_cb, s);
|
||||
timer_mod(s->open_timer, expire_time_ns);
|
||||
}
|
||||
|
||||
static bool nbd_client_connecting(BDRVNBDState *s)
|
||||
{
|
||||
NBDClientState state = qatomic_load_acquire(&s->state);
|
||||
@@ -1770,15 +1742,6 @@ static QemuOptsList nbd_runtime_opts = {
|
||||
"future requests before a successful reconnect will "
|
||||
"immediately fail. Default 0",
|
||||
},
|
||||
{
|
||||
.name = "open-timeout",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "In seconds. If zero, the nbd driver tries the connection "
|
||||
"only once, and fails to open if the connection fails. "
|
||||
"If non-zero, the nbd driver will repeat connection "
|
||||
"attempts until successful or until @open-timeout seconds "
|
||||
"have elapsed. Default 0",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
@@ -1834,7 +1797,6 @@ static int nbd_process_options(BlockDriverState *bs, QDict *options,
|
||||
}
|
||||
|
||||
s->reconnect_delay = qemu_opt_get_number(opts, "reconnect-delay", 0);
|
||||
s->open_timeout = qemu_opt_get_number(opts, "open-timeout", 0);
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -1866,12 +1828,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->conn = nbd_client_connection_new(s->saddr, true, s->export,
|
||||
s->x_dirty_bitmap, s->tlscreds);
|
||||
|
||||
if (s->open_timeout) {
|
||||
nbd_client_connection_enable_retry(s->conn);
|
||||
open_timer_init(s, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) +
|
||||
s->open_timeout * NANOSECONDS_PER_SECOND);
|
||||
}
|
||||
|
||||
/* TODO: Configurable retry-until-timeout behaviour. */
|
||||
s->state = NBD_CLIENT_CONNECTING_WAIT;
|
||||
ret = nbd_do_establish_connection(bs, errp);
|
||||
if (ret < 0) {
|
||||
|
||||
+12
-15
@@ -183,20 +183,15 @@ static bool nvme_init_queue(BDRVNVMeState *s, NVMeQueue *q,
|
||||
return r == 0;
|
||||
}
|
||||
|
||||
static void nvme_free_queue(NVMeQueue *q)
|
||||
{
|
||||
qemu_vfree(q->queue);
|
||||
}
|
||||
|
||||
static void nvme_free_queue_pair(NVMeQueuePair *q)
|
||||
{
|
||||
trace_nvme_free_queue_pair(q->index, q, &q->cq, &q->sq);
|
||||
trace_nvme_free_queue_pair(q->index, q);
|
||||
if (q->completion_bh) {
|
||||
qemu_bh_delete(q->completion_bh);
|
||||
}
|
||||
nvme_free_queue(&q->sq);
|
||||
nvme_free_queue(&q->cq);
|
||||
qemu_vfree(q->prp_list_pages);
|
||||
qemu_vfree(q->sq.queue);
|
||||
qemu_vfree(q->cq.queue);
|
||||
qemu_mutex_destroy(&q->lock);
|
||||
g_free(q);
|
||||
}
|
||||
@@ -206,9 +201,8 @@ static void nvme_free_req_queue_cb(void *opaque)
|
||||
NVMeQueuePair *q = opaque;
|
||||
|
||||
qemu_mutex_lock(&q->lock);
|
||||
while (q->free_req_head != -1 &&
|
||||
qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
|
||||
/* Retry waiting requests */
|
||||
while (qemu_co_enter_next(&q->free_req_queue, &q->lock)) {
|
||||
/* Retry all pending requests */
|
||||
}
|
||||
qemu_mutex_unlock(&q->lock);
|
||||
}
|
||||
@@ -520,10 +514,10 @@ static bool nvme_identify(BlockDriverState *bs, int namespace, Error **errp)
|
||||
{
|
||||
BDRVNVMeState *s = bs->opaque;
|
||||
bool ret = false;
|
||||
QEMU_AUTO_VFREE union {
|
||||
union {
|
||||
NvmeIdCtrl ctrl;
|
||||
NvmeIdNs ns;
|
||||
} *id = NULL;
|
||||
} *id;
|
||||
NvmeLBAF *lbaf;
|
||||
uint16_t oncs;
|
||||
int r;
|
||||
@@ -601,6 +595,7 @@ static bool nvme_identify(BlockDriverState *bs, int namespace, Error **errp)
|
||||
s->blkshift = lbaf->ds;
|
||||
out:
|
||||
qemu_vfio_dma_unmap(s->vfio, id);
|
||||
qemu_vfree(id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1224,7 +1219,7 @@ static int nvme_co_prw(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
{
|
||||
BDRVNVMeState *s = bs->opaque;
|
||||
int r;
|
||||
QEMU_AUTO_VFREE uint8_t *buf = NULL;
|
||||
uint8_t *buf = NULL;
|
||||
QEMUIOVector local_qiov;
|
||||
size_t len = QEMU_ALIGN_UP(bytes, qemu_real_host_page_size);
|
||||
assert(QEMU_IS_ALIGNED(offset, s->page_size));
|
||||
@@ -1251,6 +1246,7 @@ static int nvme_co_prw(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
if (!r && !is_write) {
|
||||
qemu_iovec_from_buf(qiov, 0, buf, bytes);
|
||||
}
|
||||
qemu_vfree(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1369,7 +1365,7 @@ static int coroutine_fn nvme_co_pdiscard(BlockDriverState *bs,
|
||||
BDRVNVMeState *s = bs->opaque;
|
||||
NVMeQueuePair *ioq = s->queues[INDEX_IO(0)];
|
||||
NVMeRequest *req;
|
||||
QEMU_AUTO_VFREE NvmeDsmRange *buf = NULL;
|
||||
NvmeDsmRange *buf;
|
||||
QEMUIOVector local_qiov;
|
||||
int ret;
|
||||
|
||||
@@ -1444,6 +1440,7 @@ static int coroutine_fn nvme_co_pdiscard(BlockDriverState *bs,
|
||||
trace_nvme_dsm_done(s, offset, bytes, ret);
|
||||
out:
|
||||
qemu_iovec_destroy(&local_qiov);
|
||||
qemu_vfree(buf);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@@ -513,8 +513,7 @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
|
||||
*/
|
||||
assert(src_cluster_offset <= INT64_MAX);
|
||||
assert(src_cluster_offset + offset_in_cluster <= INT64_MAX);
|
||||
/* Cast qiov->size to uint64_t to silence a compiler warning on -m32 */
|
||||
assert((uint64_t)qiov->size <= INT64_MAX);
|
||||
assert(qiov->size <= INT64_MAX);
|
||||
bdrv_check_qiov_request(src_cluster_offset + offset_in_cluster, qiov->size,
|
||||
qiov, 0, &error_abort);
|
||||
/*
|
||||
|
||||
-112
@@ -97,12 +97,6 @@ typedef struct RBDTask {
|
||||
int64_t ret;
|
||||
} RBDTask;
|
||||
|
||||
typedef struct RBDDiffIterateReq {
|
||||
uint64_t offs;
|
||||
uint64_t bytes;
|
||||
bool exists;
|
||||
} RBDDiffIterateReq;
|
||||
|
||||
static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
|
||||
BlockdevOptionsRbd *opts, bool cache,
|
||||
const char *keypairs, const char *secretid,
|
||||
@@ -1265,111 +1259,6 @@ static ImageInfoSpecific *qemu_rbd_get_specific_info(BlockDriverState *bs,
|
||||
return spec_info;
|
||||
}
|
||||
|
||||
/*
|
||||
* rbd_diff_iterate2 allows to interrupt the exection by returning a negative
|
||||
* value in the callback routine. Choose a value that does not conflict with
|
||||
* an existing exitcode and return it if we want to prematurely stop the
|
||||
* execution because we detected a change in the allocation status.
|
||||
*/
|
||||
#define QEMU_RBD_EXIT_DIFF_ITERATE2 -9000
|
||||
|
||||
static int qemu_rbd_diff_iterate_cb(uint64_t offs, size_t len,
|
||||
int exists, void *opaque)
|
||||
{
|
||||
RBDDiffIterateReq *req = opaque;
|
||||
|
||||
assert(req->offs + req->bytes <= offs);
|
||||
/*
|
||||
* we do not diff against a snapshot so we should never receive a callback
|
||||
* for a hole.
|
||||
*/
|
||||
assert(exists);
|
||||
|
||||
if (!req->exists && offs > req->offs) {
|
||||
/*
|
||||
* we started in an unallocated area and hit the first allocated
|
||||
* block. req->bytes must be set to the length of the unallocated area
|
||||
* before the allocated area. stop further processing.
|
||||
*/
|
||||
req->bytes = offs - req->offs;
|
||||
return QEMU_RBD_EXIT_DIFF_ITERATE2;
|
||||
}
|
||||
|
||||
if (req->exists && offs > req->offs + req->bytes) {
|
||||
/*
|
||||
* we started in an allocated area and jumped over an unallocated area,
|
||||
* req->bytes contains the length of the allocated area before the
|
||||
* unallocated area. stop further processing.
|
||||
*/
|
||||
return QEMU_RBD_EXIT_DIFF_ITERATE2;
|
||||
}
|
||||
|
||||
req->bytes += len;
|
||||
req->exists = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
|
||||
bool want_zero, int64_t offset,
|
||||
int64_t bytes, int64_t *pnum,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
BDRVRBDState *s = bs->opaque;
|
||||
int status, r;
|
||||
RBDDiffIterateReq req = { .offs = offset };
|
||||
uint64_t features, flags;
|
||||
|
||||
assert(offset + bytes <= s->image_size);
|
||||
|
||||
/* default to all sectors allocated */
|
||||
status = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
|
||||
*map = offset;
|
||||
*file = bs;
|
||||
*pnum = bytes;
|
||||
|
||||
/* check if RBD image supports fast-diff */
|
||||
r = rbd_get_features(s->image, &features);
|
||||
if (r < 0) {
|
||||
return status;
|
||||
}
|
||||
if (!(features & RBD_FEATURE_FAST_DIFF)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* check if RBD fast-diff result is valid */
|
||||
r = rbd_get_flags(s->image, &flags);
|
||||
if (r < 0) {
|
||||
return status;
|
||||
}
|
||||
if (flags & RBD_FLAG_FAST_DIFF_INVALID) {
|
||||
return status;
|
||||
}
|
||||
|
||||
r = rbd_diff_iterate2(s->image, NULL, offset, bytes, true, true,
|
||||
qemu_rbd_diff_iterate_cb, &req);
|
||||
if (r < 0 && r != QEMU_RBD_EXIT_DIFF_ITERATE2) {
|
||||
return status;
|
||||
}
|
||||
assert(req.bytes <= bytes);
|
||||
if (!req.exists) {
|
||||
if (r == 0) {
|
||||
/*
|
||||
* rbd_diff_iterate2 does not invoke callbacks for unallocated
|
||||
* areas. This here catches the case where no callback was
|
||||
* invoked at all (req.bytes == 0).
|
||||
*/
|
||||
assert(req.bytes == 0);
|
||||
req.bytes = bytes;
|
||||
}
|
||||
status = BDRV_BLOCK_ZERO | BDRV_BLOCK_OFFSET_VALID;
|
||||
}
|
||||
|
||||
*pnum = req.bytes;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int64_t qemu_rbd_getlength(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRBDState *s = bs->opaque;
|
||||
@@ -1605,7 +1494,6 @@ static BlockDriver bdrv_rbd = {
|
||||
#ifdef LIBRBD_SUPPORTS_WRITE_ZEROES
|
||||
.bdrv_co_pwrite_zeroes = qemu_rbd_co_pwrite_zeroes,
|
||||
#endif
|
||||
.bdrv_co_block_status = qemu_rbd_co_block_status,
|
||||
|
||||
.bdrv_snapshot_create = qemu_rbd_snap_create,
|
||||
.bdrv_snapshot_delete = qemu_rbd_snap_remove,
|
||||
|
||||
+2
-2
@@ -149,7 +149,7 @@ static void replication_close(BlockDriverState *bs)
|
||||
if (s->stage == BLOCK_REPLICATION_FAILOVER) {
|
||||
commit_job = &s->commit_job->job;
|
||||
assert(commit_job->aio_context == qemu_get_current_aio_context());
|
||||
job_cancel_sync(commit_job, false);
|
||||
job_cancel_sync(commit_job);
|
||||
}
|
||||
|
||||
if (s->mode == REPLICATION_MODE_SECONDARY) {
|
||||
@@ -726,7 +726,7 @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
|
||||
* disk, secondary disk in backup_job_completed().
|
||||
*/
|
||||
if (s->backup_job) {
|
||||
job_cancel_sync(&s->backup_job->job, true);
|
||||
job_cancel_sync(&s->backup_job->job);
|
||||
}
|
||||
|
||||
if (!failover) {
|
||||
|
||||
+2
-5
@@ -54,8 +54,8 @@ static int stream_prepare(Job *job)
|
||||
{
|
||||
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
|
||||
BlockDriverState *unfiltered_bs = bdrv_skip_filters(s->target_bs);
|
||||
BlockDriverState *base;
|
||||
BlockDriverState *unfiltered_base;
|
||||
BlockDriverState *base = bdrv_filter_or_cow_bs(s->above_base);
|
||||
BlockDriverState *unfiltered_base = bdrv_skip_filters(base);
|
||||
Error *local_err = NULL;
|
||||
int ret = 0;
|
||||
|
||||
@@ -63,9 +63,6 @@ static int stream_prepare(Job *job)
|
||||
bdrv_cor_filter_drop(s->cor_filter_bs);
|
||||
s->cor_filter_bs = NULL;
|
||||
|
||||
base = bdrv_filter_or_cow_bs(s->above_base);
|
||||
unfiltered_base = bdrv_skip_filters(base);
|
||||
|
||||
if (bdrv_cow_child(unfiltered_bs)) {
|
||||
const char *base_id = NULL, *base_fmt = NULL;
|
||||
if (unfiltered_base) {
|
||||
|
||||
+3
-3
@@ -5,8 +5,8 @@ bdrv_open_common(void *bs, const char *filename, int flags, const char *format_n
|
||||
bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d"
|
||||
|
||||
# block-backend.c
|
||||
blk_co_preadv(void *blk, void *bs, int64_t offset, int64_t bytes, int flags) "blk %p bs %p offset %"PRId64" bytes %" PRId64 " flags 0x%x"
|
||||
blk_co_pwritev(void *blk, void *bs, int64_t offset, int64_t bytes, int flags) "blk %p bs %p offset %"PRId64" bytes %" PRId64 " flags 0x%x"
|
||||
blk_co_preadv(void *blk, void *bs, int64_t offset, unsigned int bytes, int flags) "blk %p bs %p offset %"PRId64" bytes %u flags 0x%x"
|
||||
blk_co_pwritev(void *blk, void *bs, int64_t offset, unsigned int bytes, int flags) "blk %p bs %p offset %"PRId64" bytes %u flags 0x%x"
|
||||
blk_root_attach(void *child, void *blk, void *bs) "child %p blk %p bs %p"
|
||||
blk_root_detach(void *child, void *blk, void *bs) "child %p blk %p bs %p"
|
||||
|
||||
@@ -157,7 +157,7 @@ nvme_dsm_done(void *s, int64_t offset, int64_t bytes, int ret) "s %p offset 0x%"
|
||||
nvme_dma_map_flush(void *s) "s %p"
|
||||
nvme_free_req_queue_wait(void *s, unsigned q_index) "s %p q #%u"
|
||||
nvme_create_queue_pair(unsigned q_index, void *q, size_t size, void *aio_context, int fd) "index %u q %p size %zu aioctx %p fd %d"
|
||||
nvme_free_queue_pair(unsigned q_index, void *q, void *cq, void *sq) "index %u q %p cq %p sq %p"
|
||||
nvme_free_queue_pair(unsigned q_index, void *q) "index %u q %p"
|
||||
nvme_cmd_map_qiov(void *s, void *cmd, void *req, void *qiov, int entries) "s %p cmd %p req %p qiov %p entries %d"
|
||||
nvme_cmd_map_qiov_pages(void *s, int i, uint64_t page) "s %p page[%d] 0x%"PRIx64
|
||||
nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pages %d"
|
||||
|
||||
+4
-20
@@ -60,7 +60,6 @@
|
||||
#define VMDK_ZEROED (-3)
|
||||
|
||||
#define BLOCK_OPT_ZEROED_GRAIN "zeroed_grain"
|
||||
#define BLOCK_OPT_TOOLSVERSION "toolsversion"
|
||||
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
@@ -2345,7 +2344,6 @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
|
||||
BlockdevVmdkAdapterType adapter_type,
|
||||
const char *backing_file,
|
||||
const char *hw_version,
|
||||
const char *toolsversion,
|
||||
bool compat6,
|
||||
bool zeroed_grain,
|
||||
vmdk_create_extent_fn extent_fn,
|
||||
@@ -2386,8 +2384,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
|
||||
"ddb.geometry.cylinders = \"%" PRId64 "\"\n"
|
||||
"ddb.geometry.heads = \"%" PRIu32 "\"\n"
|
||||
"ddb.geometry.sectors = \"63\"\n"
|
||||
"ddb.adapterType = \"%s\"\n"
|
||||
"ddb.toolsVersion = \"%s\"\n";
|
||||
"ddb.adapterType = \"%s\"\n";
|
||||
|
||||
ext_desc_lines = g_string_new(NULL);
|
||||
|
||||
@@ -2404,9 +2401,6 @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
|
||||
if (!hw_version) {
|
||||
hw_version = "4";
|
||||
}
|
||||
if (!toolsversion) {
|
||||
toolsversion = "2147483647";
|
||||
}
|
||||
|
||||
if (adapter_type != BLOCKDEV_VMDK_ADAPTER_TYPE_IDE) {
|
||||
/* that's the number of heads with which vmware operates when
|
||||
@@ -2531,8 +2525,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
|
||||
size /
|
||||
(int64_t)(63 * number_heads * BDRV_SECTOR_SIZE),
|
||||
number_heads,
|
||||
BlockdevVmdkAdapterType_str(adapter_type),
|
||||
toolsversion);
|
||||
BlockdevVmdkAdapterType_str(adapter_type));
|
||||
desc_len = strlen(desc);
|
||||
/* the descriptor offset = 0x200 */
|
||||
if (!split && !flat) {
|
||||
@@ -2624,7 +2617,6 @@ static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv,
|
||||
BlockdevVmdkAdapterType adapter_type_enum;
|
||||
char *backing_file = NULL;
|
||||
char *hw_version = NULL;
|
||||
char *toolsversion = NULL;
|
||||
char *fmt = NULL;
|
||||
BlockdevVmdkSubformat subformat;
|
||||
int ret = 0;
|
||||
@@ -2657,7 +2649,6 @@ static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv,
|
||||
adapter_type = qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE);
|
||||
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
|
||||
hw_version = qemu_opt_get_del(opts, BLOCK_OPT_HWVERSION);
|
||||
toolsversion = qemu_opt_get_del(opts, BLOCK_OPT_TOOLSVERSION);
|
||||
compat6 = qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false);
|
||||
if (strcmp(hw_version, "undefined") == 0) {
|
||||
g_free(hw_version);
|
||||
@@ -2701,15 +2692,14 @@ static int coroutine_fn vmdk_co_create_opts(BlockDriver *drv,
|
||||
.opts = opts,
|
||||
};
|
||||
ret = vmdk_co_do_create(total_size, subformat, adapter_type_enum,
|
||||
backing_file, hw_version, toolsversion, compat6,
|
||||
zeroed_grain, vmdk_co_create_opts_cb, &data, errp);
|
||||
backing_file, hw_version, compat6, zeroed_grain,
|
||||
vmdk_co_create_opts_cb, &data, errp);
|
||||
|
||||
exit:
|
||||
g_free(backing_fmt);
|
||||
g_free(adapter_type);
|
||||
g_free(backing_file);
|
||||
g_free(hw_version);
|
||||
g_free(toolsversion);
|
||||
g_free(fmt);
|
||||
g_free(desc);
|
||||
g_free(path);
|
||||
@@ -2792,7 +2782,6 @@ static int coroutine_fn vmdk_co_create(BlockdevCreateOptions *create_options,
|
||||
opts->adapter_type,
|
||||
opts->backing_file,
|
||||
opts->hwversion,
|
||||
opts->toolsversion,
|
||||
false,
|
||||
opts->zeroed_grain,
|
||||
vmdk_co_create_cb,
|
||||
@@ -3042,11 +3031,6 @@ static QemuOptsList vmdk_create_opts = {
|
||||
.help = "VMDK hardware version",
|
||||
.def_value_str = "undefined"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_TOOLSVERSION,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "VMware guest tools version",
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_SUBFMT,
|
||||
.type = QEMU_OPT_STRING,
|
||||
|
||||
+1
-2
@@ -276,8 +276,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if (strncmp(footer->creator, "conectix", 8) ||
|
||||
be32_to_cpu(footer->type) != VHD_FIXED) {
|
||||
if (strncmp(footer->creator, "conectix", 8)) {
|
||||
error_setg(errp, "invalid VPC image");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
|
||||
+4
-12
@@ -1279,18 +1279,8 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
|
||||
qemu_opts_del(opts);
|
||||
|
||||
return 0;
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
g_free(s->qcow_filename);
|
||||
s->qcow_filename = NULL;
|
||||
g_free(s->cluster_buffer);
|
||||
s->cluster_buffer = NULL;
|
||||
g_free(s->used_clusters);
|
||||
s->used_clusters = NULL;
|
||||
|
||||
qemu_opts_del(opts);
|
||||
return ret;
|
||||
}
|
||||
@@ -3128,7 +3118,7 @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
|
||||
int size = sector2cluster(s, s->sector_count);
|
||||
QDict *options;
|
||||
|
||||
s->used_clusters = g_malloc0(size);
|
||||
s->used_clusters = calloc(size, 1);
|
||||
|
||||
array_init(&(s->commits), sizeof(commit_t));
|
||||
|
||||
@@ -3176,6 +3166,8 @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
|
||||
return 0;
|
||||
|
||||
err:
|
||||
g_free(s->qcow_filename);
|
||||
s->qcow_filename = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+12
-2
@@ -303,6 +303,16 @@ int drive_get_max_bus(BlockInterfaceType type)
|
||||
return max_bus;
|
||||
}
|
||||
|
||||
/* Get a block device. This should only be used for single-drive devices
|
||||
(e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
|
||||
appropriate bus. */
|
||||
DriveInfo *drive_get_next(BlockInterfaceType type)
|
||||
{
|
||||
static int next_block_unit[IF_COUNT];
|
||||
|
||||
return drive_get(type, 0, next_block_unit[type]++);
|
||||
}
|
||||
|
||||
static void bdrv_format_print(void *opaque, const char *name)
|
||||
{
|
||||
qemu_printf(" %s", name);
|
||||
@@ -1837,7 +1847,7 @@ static void drive_backup_abort(BlkActionState *common)
|
||||
aio_context = bdrv_get_aio_context(state->bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
job_cancel_sync(&state->job->job, true);
|
||||
job_cancel_sync(&state->job->job);
|
||||
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
@@ -1938,7 +1948,7 @@ static void blockdev_backup_abort(BlkActionState *common)
|
||||
aio_context = bdrv_get_aio_context(state->bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
job_cancel_sync(&state->job->job, true);
|
||||
job_cancel_sync(&state->job->job);
|
||||
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
+3
-14
@@ -1,3 +1,6 @@
|
||||
/* $OpenBSD: errno.h,v 1.20 2007/09/03 14:37:52 millert Exp $ */
|
||||
/* $NetBSD: errno.h,v 1.10 1996/01/20 01:33:53 jtc Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
@@ -34,9 +37,6 @@
|
||||
* @(#)errno.h 8.5 (Berkeley) 1/21/94
|
||||
*/
|
||||
|
||||
#ifndef _ERRNO_DEFS_H_
|
||||
#define _ERRNO_DEFS_H_
|
||||
|
||||
#define TARGET_EPERM 1 /* Operation not permitted */
|
||||
#define TARGET_ENOENT 2 /* No such file or directory */
|
||||
#define TARGET_ESRCH 3 /* No such process */
|
||||
@@ -147,14 +147,3 @@
|
||||
#define TARGET_EIDRM 89 /* Identifier removed */
|
||||
#define TARGET_ENOMSG 90 /* No message of desired type */
|
||||
#define TARGET_ELAST 90 /* Must be equal largest errno */
|
||||
|
||||
/* Internal errors: */
|
||||
#define TARGET_EJUSTRETURN 254 /* Just return without modifing regs */
|
||||
#define TARGET_ERESTART 255 /* Restart syscall */
|
||||
|
||||
#include "special-errno.h"
|
||||
|
||||
_Static_assert(TARGET_ERESTART == QEMU_ERESTARTSYS,
|
||||
"TARGET_ERESTART and QEMU_ERESTARTSYS expected to match");
|
||||
|
||||
#endif /* ! _ERRNO_DEFS_H_ */
|
||||
@@ -1,3 +0,0 @@
|
||||
bsd_user_ss.add(files(
|
||||
'os-sys.c',
|
||||
))
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* FreeBSD sysctl() and sysarch() system call emulation
|
||||
*
|
||||
* Copyright (c) 2013-15 Stacey D. Son
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu.h"
|
||||
#include "target_arch_sysarch.h"
|
||||
|
||||
/* sysarch() is architecture dependent. */
|
||||
abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2)
|
||||
{
|
||||
return do_freebsd_arch_sysarch(cpu_env, arg1, arg2);
|
||||
}
|
||||
@@ -33,6 +33,10 @@
|
||||
{ TARGET_FREEBSD_NR___syscall, "__syscall", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, print_sysctl, NULL },
|
||||
{ TARGET_FREEBSD_NR__umtx_op, "_umtx_op", "%s(%#x, %d, %d, %#x, %#x)", NULL, NULL },
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version < 1000000
|
||||
{ TARGET_FREEBSD_NR__umtx_lock, "__umtx_lock", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR__umtx_unlock, "__umtx_unlock", NULL, NULL, NULL },
|
||||
#endif
|
||||
{ TARGET_FREEBSD_NR_accept, "accept", "%s(%d,%#x,%#x)", NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_accept4, "accept4", "%s(%d,%d,%#x,%#x)", NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_access, "access", "%s(\"%s\",%#o)", NULL, NULL },
|
||||
@@ -45,6 +49,10 @@
|
||||
{ TARGET_FREEBSD_NR_cap_fcntls_get, "cap_fcntls_get", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_cap_fcntls_limit, "cap_fcntls_limit", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_cap_getmode, "cap_getmode", NULL, NULL, NULL },
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version < 1000000
|
||||
{ TARGET_FREEBSD_NR_cap_getrights, "cap_getrights", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_cap_new, "cap_new", NULL, NULL, NULL },
|
||||
#endif
|
||||
{ TARGET_FREEBSD_NR_cap_ioctls_get, "cap_ioctls_get", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_cap_ioctls_limit, "cap_ioctls_limit", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_cap_rights_limit, "cap_rights_limit", NULL, NULL, NULL },
|
||||
@@ -138,6 +146,9 @@
|
||||
{ TARGET_FREEBSD_NR_freebsd11_kevent, "freebsd11_kevent", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_kevent, "kevent", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_kill, "kill", NULL, NULL, NULL },
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version < 1000000
|
||||
{ TARGET_FREEBSD_NR_killpg, "killpg", NULL, NULL, NULL },
|
||||
#endif
|
||||
{ TARGET_FREEBSD_NR_kqueue, "kqueue", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_ktrace, "ktrace", NULL, NULL, NULL },
|
||||
{ TARGET_FREEBSD_NR_lchown, "lchown", NULL, NULL, NULL },
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#define ELF_PLATFORM (NULL)
|
||||
#endif
|
||||
|
||||
#ifndef ELF_HWCAP
|
||||
#define ELF_HWCAP 0
|
||||
#endif
|
||||
|
||||
/* XXX Look at the other conflicting AT_* values. */
|
||||
#define FREEBSD_AT_NCPUS 19
|
||||
#define FREEBSD_AT_HWCAP 25
|
||||
@@ -110,16 +114,12 @@ static abi_ulong target_create_elf_tables(abi_ulong p, int argc, int envc,
|
||||
NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
|
||||
NEW_AUX_ENT(FREEBSD_AT_NCPUS, (abi_ulong)bsd_get_ncpu());
|
||||
NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
|
||||
features = ELF_HWCAP;
|
||||
NEW_AUX_ENT(FREEBSD_AT_HWCAP, features);
|
||||
#ifdef ELF_HWCAP2
|
||||
features = ELF_HWCAP2;
|
||||
NEW_AUX_ENT(FREEBSD_AT_HWCAP2, features);
|
||||
#endif
|
||||
NEW_AUX_ENT(AT_UID, (abi_ulong)getuid());
|
||||
NEW_AUX_ENT(AT_EUID, (abi_ulong)geteuid());
|
||||
NEW_AUX_ENT(AT_GID, (abi_ulong)getgid());
|
||||
NEW_AUX_ENT(AT_EGID, (abi_ulong)getegid());
|
||||
features = ELF_HWCAP;
|
||||
NEW_AUX_ENT(FREEBSD_AT_HWCAP, features);
|
||||
target_auxents = sp; /* Note where the aux entries are in the target */
|
||||
#ifdef ARCH_DLINFO
|
||||
/*
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#ifndef _TARGET_OS_SIGNAL_H_
|
||||
#define _TARGET_OS_SIGNAL_H_
|
||||
|
||||
/* FreeBSD's sys/ucontext.h defines this */
|
||||
#define TARGET_MC_GET_CLEAR_RET 0x0001
|
||||
|
||||
#include "target_os_siginfo.h"
|
||||
#include "target_arch_signal.h"
|
||||
|
||||
|
||||
@@ -61,7 +61,15 @@ struct target_sockaddr_storage {
|
||||
/*
|
||||
* from sys/user.h
|
||||
*/
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
#define TARGET_KI_NSPARE_INT 2
|
||||
#elif defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
|
||||
#define TARGET_KI_NSPARE_INT 4
|
||||
#elif defined(__FreeBSD_version) && __FreeBSD_version >= 1000000
|
||||
#define TARGET_KI_NSPARE_INT 7
|
||||
#else
|
||||
#define TARGET_KI_NSPARE_INT 9
|
||||
#endif /* ! __FreeBSD_version >= 1000000 */
|
||||
#define TARGET_KI_NSPARE_LONG 12
|
||||
#define TARGET_KI_NSPARE_PTR 6
|
||||
|
||||
@@ -108,7 +116,11 @@ struct target_kinfo_proc {
|
||||
int32_t ki_tsid; /* Terminal session ID */
|
||||
int16_t ki_jobc; /* job control counter */
|
||||
int16_t ki_spare_short1; /* unused (just here for alignment) */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
int32_t ki_tdev__freebsd11; /* controlling tty dev */
|
||||
#else
|
||||
int32_t ki_tdev; /* controlling tty dev */
|
||||
#endif
|
||||
target_sigset_t ki_siglist; /* Signals arrived but not delivered */
|
||||
target_sigset_t ki_sigmask; /* Current signal mask */
|
||||
target_sigset_t ki_sigignore; /* Signals being ignored */
|
||||
@@ -152,24 +164,45 @@ struct target_kinfo_proc {
|
||||
int8_t ki_nice; /* Process "nice" value */
|
||||
char ki_lock; /* Process lock (prevent swap) count */
|
||||
char ki_rqindex; /* Run queue index */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
|
||||
u_char ki_oncpu_old; /* Which cpu we are on (legacy) */
|
||||
u_char ki_lastcpu_old; /* Last cpu we were on (legacy) */
|
||||
#else
|
||||
u_char ki_oncpu; /* Which cpu we are on */
|
||||
u_char ki_lastcpu; /* Last cpu we were on */
|
||||
#endif /* ! __FreeBSD_version >= 1100000 */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
|
||||
char ki_tdname[TARGET_TDNAMLEN + 1]; /* thread name */
|
||||
#else
|
||||
char ki_ocomm[TARGET_TDNAMLEN + 1]; /* thread name */
|
||||
#endif /* ! __FreeBSD_version >= 900000 */
|
||||
char ki_wmesg[TARGET_WMESGLEN + 1]; /* wchan message */
|
||||
char ki_login[TARGET_LOGNAMELEN + 1]; /* setlogin name */
|
||||
char ki_lockname[TARGET_LOCKNAMELEN + 1]; /* lock name */
|
||||
char ki_comm[TARGET_COMMLEN + 1]; /* command name */
|
||||
char ki_emul[TARGET_KI_EMULNAMELEN + 1]; /* emulation name */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
|
||||
char ki_loginclass[TARGET_LOGINCLASSLEN + 1]; /* login class */
|
||||
#endif /* ! __FreeBSD_version >= 900000 */
|
||||
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
|
||||
char ki_sparestrings[50]; /* spare string space */
|
||||
#else
|
||||
char ki_sparestrings[68]; /* spare string space */
|
||||
#endif /* ! __FreeBSD_version >= 900000 */
|
||||
int32_t ki_spareints[TARGET_KI_NSPARE_INT]; /* spare room for growth */
|
||||
uint64_t ki_tdev; /* controlling tty dev */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
uint64_t ki_tdev; /* controlling tty dev */
|
||||
#endif
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
|
||||
int32_t ki_oncpu; /* Which cpu we are on */
|
||||
int32_t ki_lastcpu; /* Last cpu we were on */
|
||||
int32_t ki_tracer; /* Pid of tracing process */
|
||||
#endif /* __FreeBSD_version >= 1100000 */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
|
||||
int32_t ki_flag2; /* P2_* flags */
|
||||
int32_t ki_fibnum; /* Default FIB number */
|
||||
#endif /* ! __FreeBSD_version >= 900000 */
|
||||
uint32_t ki_cr_flags; /* Credential flags */
|
||||
int32_t ki_jid; /* Process jail ID */
|
||||
int32_t ki_numthreads; /* XXXKSE number of threads in total */
|
||||
@@ -201,8 +234,18 @@ struct target_kinfo_file {
|
||||
int32_t kf_flags; /* Flags. */
|
||||
int32_t kf_pad0; /* Round to 64 bit alignment. */
|
||||
int64_t kf_offset; /* Seek location. */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version < 1200031
|
||||
int32_t kf_vnode_type; /* Vnode type. */
|
||||
int32_t kf_sock_domain; /* Socket domain. */
|
||||
int32_t kf_sock_type; /* Socket type. */
|
||||
int32_t kf_sock_protocol; /* Socket protocol. */
|
||||
struct target_sockaddr_storage kf_sa_local; /* Socket address. */
|
||||
struct target_sockaddr_storage kf_sa_peer; /* Peer address. */
|
||||
#endif
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
|
||||
union {
|
||||
struct {
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
uint32_t kf_spareint;
|
||||
/* Socket domain. */
|
||||
int kf_sock_domain0;
|
||||
@@ -214,6 +257,7 @@ struct target_kinfo_file {
|
||||
struct sockaddr_storage kf_sa_local;
|
||||
/* Peer address. */
|
||||
struct sockaddr_storage kf_sa_peer;
|
||||
#endif
|
||||
/* Address of so_pcb. */
|
||||
uint64_t kf_sock_pcb;
|
||||
/* Address of inp_ppcb. */
|
||||
@@ -228,6 +272,7 @@ struct target_kinfo_file {
|
||||
uint32_t kf_sock_pad0;
|
||||
} kf_sock;
|
||||
struct {
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
/* Vnode type. */
|
||||
int kf_file_type;
|
||||
/* Space for future use */
|
||||
@@ -245,6 +290,16 @@ struct target_kinfo_file {
|
||||
uint32_t kf_file_fsid_freebsd11;
|
||||
/* File device, FreeBSD 11 compat. */
|
||||
uint32_t kf_file_rdev_freebsd11;
|
||||
#else
|
||||
/* Global file id. */
|
||||
uint64_t kf_file_fileid;
|
||||
/* File size. */
|
||||
uint64_t kf_file_size;
|
||||
/* Vnode filesystem id. */
|
||||
uint32_t kf_file_fsid;
|
||||
/* File device. */
|
||||
uint32_t kf_file_rdev;
|
||||
#endif
|
||||
/* File mode. */
|
||||
uint16_t kf_file_mode;
|
||||
/* Round to 64 bit alignment. */
|
||||
@@ -252,14 +307,18 @@ struct target_kinfo_file {
|
||||
uint32_t kf_file_pad1;
|
||||
} kf_file;
|
||||
struct {
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
uint32_t kf_spareint[4];
|
||||
uint64_t kf_spareint64[32];
|
||||
#endif
|
||||
uint32_t kf_sem_value;
|
||||
uint16_t kf_sem_mode;
|
||||
} kf_sem;
|
||||
struct {
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
uint32_t kf_spareint[4];
|
||||
uint64_t kf_spareint64[32];
|
||||
#endif
|
||||
uint64_t kf_pipe_addr;
|
||||
uint64_t kf_pipe_peer;
|
||||
uint32_t kf_pipe_buffer_cnt;
|
||||
@@ -267,6 +326,7 @@ struct target_kinfo_file {
|
||||
uint32_t kf_pipe_pad0[3];
|
||||
} kf_pipe;
|
||||
struct {
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
uint32_t kf_spareint[4];
|
||||
uint64_t kf_spareint64[32];
|
||||
uint32_t kf_pts_dev_freebsd11;
|
||||
@@ -274,18 +334,34 @@ struct target_kinfo_file {
|
||||
uint64_t kf_pts_dev;
|
||||
/* Round to 64 bit alignment. */
|
||||
uint32_t kf_pts_pad1[4];
|
||||
#else
|
||||
uint32_t kf_pts_dev;
|
||||
/* Round to 64 bit alignment. */
|
||||
uint32_t kf_pts_pad0[7];
|
||||
#endif
|
||||
} kf_pts;
|
||||
struct {
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
uint32_t kf_spareint[4];
|
||||
uint64_t kf_spareint64[32];
|
||||
#endif
|
||||
int32_t kf_pid;
|
||||
} kf_proc;
|
||||
} kf_un;
|
||||
uint16_t kf_status; /* Status flags. */
|
||||
uint16_t kf_pad1; /* Round to 32 bit alignment. */
|
||||
int32_t _kf_ispare0; /* Space for more stuff. */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1000000
|
||||
target_cap_rights_t kf_cap_rights; /* Capability rights. */
|
||||
uint64_t _kf_cap_spare; /* Space for future cap_rights_t. */
|
||||
#else /* ! __FreeBSD_version >= 1000000 */
|
||||
uint64_t kf_cap_rights;
|
||||
int _kf_ispare[4];
|
||||
#endif /* ! __FreeBSD_version >= 1000000 */
|
||||
|
||||
#else /* ! __FreeBSD_version >= 900000 */
|
||||
int _kf_ispare[16];
|
||||
#endif /* ! __FreeBSD_version >= 900000 */
|
||||
/* Truncated before copyout in sysctl */
|
||||
char kf_path[PATH_MAX]; /* Path to file, if any. */
|
||||
};
|
||||
@@ -296,19 +372,34 @@ struct target_kinfo_vmentry {
|
||||
uint64_t kve_start; /* Starting address. */
|
||||
uint64_t kve_end; /* Finishing address. */
|
||||
uint64_t kve_offset; /* Mapping offset in object */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
|
||||
uint64_t kve_vn_fileid; /* inode number if vnode */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
uint32_t kve_vn_fsid_freebsd11; /* dev_t of vnode location */
|
||||
#else
|
||||
uint32_t kve_vn_fsid; /* dev_t of vnode location */
|
||||
#endif
|
||||
#else /* ! __FreeBSD_version >= 900000 */
|
||||
uint64_t kve_fileid; /* inode number if vnode */
|
||||
uint32_t kve_fsid; /* dev_t of vnode location */
|
||||
#endif /* ! __FreeBSD_version >= 900000 */
|
||||
int32_t kve_flags; /* Flags on map entry. */
|
||||
int32_t kve_resident; /* Number of resident pages. */
|
||||
int32_t kve_private_resident; /* Number of private pages. */
|
||||
int32_t kve_protection; /* Protection bitmask. */
|
||||
int32_t kve_ref_count; /* VM obj ref count. */
|
||||
int32_t kve_shadow_count; /* VM obj shadow count. */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
|
||||
int32_t kve_vn_type; /* Vnode type. */
|
||||
uint64_t kve_vn_size; /* File size. */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
uint32_t kve_vn_rdev_freebsd11; /* Device id if device. */
|
||||
#else
|
||||
uint32_t kve_vn_rdev; /* Device id if device. */
|
||||
#endif
|
||||
uint16_t kve_vn_mode; /* File mode. */
|
||||
uint16_t kve_status; /* Status flags. */
|
||||
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
|
||||
#if (__FreeBSD_version >= 1300501 && __FreeBSD_version < 1400000) || \
|
||||
__FreeBSD_version >= 1400009
|
||||
union {
|
||||
@@ -322,6 +413,13 @@ struct target_kinfo_vmentry {
|
||||
#endif
|
||||
uint64_t kve_vn_rdev; /* Device id if device. */
|
||||
int _kve_ispare[8]; /* Space for more stuff. */
|
||||
#else
|
||||
int32_t _kve_ispare[12]; /* Space for more stuff. */
|
||||
#endif
|
||||
#else /* ! __FreeBSD_version >= 900000 */
|
||||
int _kve_pad0;
|
||||
int32_t _kve_ispare[16]; /* Space for more stuff. */
|
||||
#endif /* ! __FreeBSD_version >= 900000 */
|
||||
/* Truncated before copyout in sysctl */
|
||||
char kve_path[PATH_MAX]; /* Path to VM obj, if any. */
|
||||
};
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#define TARGET_DEFAULT_CPU_MODEL "qemu32"
|
||||
|
||||
#define TARGET_CPU_RESET(cpu)
|
||||
|
||||
static inline void target_cpu_init(CPUX86State *env,
|
||||
struct target_pt_regs *regs)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
|
||||
#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
|
||||
|
||||
#define TARGET_MC_GET_CLEAR_RET 0x0001
|
||||
|
||||
struct target_sigcontext {
|
||||
/* to be added */
|
||||
};
|
||||
|
||||
+1
-9
@@ -195,15 +195,6 @@ static void usage(void)
|
||||
|
||||
__thread CPUState *thread_cpu;
|
||||
|
||||
void stop_all_tasks(void)
|
||||
{
|
||||
/*
|
||||
* We trust when using NPTL (pthreads) start_exclusive() handles thread
|
||||
* stopping correctly.
|
||||
*/
|
||||
start_exclusive();
|
||||
}
|
||||
|
||||
bool qemu_cpu_is_self(CPUState *cpu)
|
||||
{
|
||||
return thread_cpu == cpu;
|
||||
@@ -219,6 +210,7 @@ void init_task_state(TaskState *ts)
|
||||
{
|
||||
int i;
|
||||
|
||||
ts->used = 1;
|
||||
ts->first_free = ts->sigqueue_table;
|
||||
for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
|
||||
ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
if not have_bsd_user
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
bsd_user_ss = ss.source_set()
|
||||
|
||||
common_user_inc += include_directories('.')
|
||||
|
||||
bsd_user_ss.add(files(
|
||||
'bsdload.c',
|
||||
'elfload.c',
|
||||
@@ -16,8 +8,3 @@ bsd_user_ss.add(files(
|
||||
'syscall.c',
|
||||
'uaccess.c',
|
||||
))
|
||||
|
||||
# Pull in the OS-specific build glue, if any
|
||||
subdir(targetos)
|
||||
|
||||
specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
|
||||
+66
-78
@@ -21,6 +21,8 @@
|
||||
#include "qemu.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
//#define DEBUG_MMAP
|
||||
|
||||
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static __thread int mmap_lock_count;
|
||||
|
||||
@@ -65,11 +67,14 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
|
||||
abi_ulong end, host_start, host_end, addr;
|
||||
int prot1, ret;
|
||||
|
||||
qemu_log_mask(CPU_LOG_PAGE, "mprotect: start=0x" TARGET_ABI_FMT_lx
|
||||
" len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
|
||||
prot & PROT_READ ? 'r' : '-',
|
||||
prot & PROT_WRITE ? 'w' : '-',
|
||||
prot & PROT_EXEC ? 'x' : '-');
|
||||
#ifdef DEBUG_MMAP
|
||||
printf("mprotect: start=0x" TARGET_ABI_FMT_lx
|
||||
"len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
|
||||
prot & PROT_READ ? 'r' : '-',
|
||||
prot & PROT_WRITE ? 'w' : '-',
|
||||
prot & PROT_EXEC ? 'x' : '-');
|
||||
#endif
|
||||
|
||||
if ((start & ~TARGET_PAGE_MASK) != 0)
|
||||
return -EINVAL;
|
||||
len = TARGET_PAGE_ALIGN(len);
|
||||
@@ -127,27 +132,7 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* map an incomplete host page
|
||||
*
|
||||
* mmap_frag can be called with a valid fd, if flags doesn't contain one of
|
||||
* MAP_ANON, MAP_STACK, MAP_GUARD. If we need to map a page in those cases, we
|
||||
* pass fd == -1. However, if flags contains MAP_GUARD then MAP_ANON cannot be
|
||||
* added.
|
||||
*
|
||||
* * If fd is valid (not -1) we want to map the pages with MAP_ANON.
|
||||
* * If flags contains MAP_GUARD we don't want to add MAP_ANON because it
|
||||
* will be rejected. See kern_mmap's enforcing of constraints for MAP_GUARD
|
||||
* in sys/vm/vm_mmap.c.
|
||||
* * If flags contains MAP_ANON it doesn't matter if we add it or not.
|
||||
* * If flags contains MAP_STACK, mmap adds MAP_ANON when called so doesn't
|
||||
* matter if we add it or not either. See enforcing of constraints for
|
||||
* MAP_STACK in kern_mmap.
|
||||
*
|
||||
* Don't add MAP_ANON for the flags that use fd == -1 without specifying the
|
||||
* flags directly, with the assumption that future flags that require fd == -1
|
||||
* will also not require MAP_ANON.
|
||||
*/
|
||||
/* map an incomplete host page */
|
||||
static int mmap_frag(abi_ulong real_start,
|
||||
abi_ulong start, abi_ulong end,
|
||||
int prot, int flags, int fd, abi_ulong offset)
|
||||
@@ -167,9 +152,9 @@ static int mmap_frag(abi_ulong real_start,
|
||||
}
|
||||
|
||||
if (prot1 == 0) {
|
||||
/* no page was there, so we allocate one. See also above. */
|
||||
/* no page was there, so we allocate one */
|
||||
void *p = mmap(host_start, qemu_host_page_size, prot,
|
||||
flags | ((fd != -1) ? MAP_ANON : 0), -1, 0);
|
||||
flags | MAP_ANON, -1, 0);
|
||||
if (p == MAP_FAILED)
|
||||
return -1;
|
||||
prot1 = prot;
|
||||
@@ -177,7 +162,7 @@ static int mmap_frag(abi_ulong real_start,
|
||||
prot1 &= PAGE_BITS;
|
||||
|
||||
prot_new = prot | prot1;
|
||||
if (fd != -1) {
|
||||
if (!(flags & MAP_ANON)) {
|
||||
/* msync() won't work here, so we return an error if write is
|
||||
possible while it is a shared mapping */
|
||||
if ((flags & TARGET_BSD_MAP_FLAGMASK) == MAP_SHARED &&
|
||||
@@ -189,20 +174,16 @@ static int mmap_frag(abi_ulong real_start,
|
||||
mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE);
|
||||
|
||||
/* read the corresponding file data */
|
||||
if (pread(fd, g2h_untagged(start), end - start, offset) == -1) {
|
||||
return -1;
|
||||
}
|
||||
pread(fd, g2h_untagged(start), end - start, offset);
|
||||
|
||||
/* put final protection */
|
||||
if (prot_new != (prot1 | PROT_WRITE))
|
||||
mprotect(host_start, qemu_host_page_size, prot_new);
|
||||
} else {
|
||||
/* just update the protection */
|
||||
if (prot_new != prot1) {
|
||||
mprotect(host_start, qemu_host_page_size, prot_new);
|
||||
}
|
||||
if (prot_new & PROT_WRITE) {
|
||||
memset(g2h_untagged(start), 0, end - start);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -300,10 +281,14 @@ static abi_ulong mmap_find_vma_aligned(abi_ulong start, abi_ulong size,
|
||||
addr = start;
|
||||
wrapped = repeat = 0;
|
||||
prev = 0;
|
||||
flags = MAP_ANON | MAP_PRIVATE;
|
||||
flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
#ifdef MAP_ALIGNED
|
||||
if (alignment != 0) {
|
||||
flags |= MAP_ALIGNED(alignment);
|
||||
}
|
||||
#else
|
||||
/* XXX TODO */
|
||||
#endif
|
||||
|
||||
for (;; prev = ptr) {
|
||||
/*
|
||||
@@ -406,48 +391,57 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
|
||||
|
||||
mmap_lock();
|
||||
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
|
||||
qemu_log("mmap: start=0x" TARGET_ABI_FMT_lx
|
||||
" len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
|
||||
start, len,
|
||||
prot & PROT_READ ? 'r' : '-',
|
||||
prot & PROT_WRITE ? 'w' : '-',
|
||||
prot & PROT_EXEC ? 'x' : '-');
|
||||
#ifdef DEBUG_MMAP
|
||||
{
|
||||
printf("mmap: start=0x" TARGET_ABI_FMT_lx
|
||||
" len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
|
||||
start, len,
|
||||
prot & PROT_READ ? 'r' : '-',
|
||||
prot & PROT_WRITE ? 'w' : '-',
|
||||
prot & PROT_EXEC ? 'x' : '-');
|
||||
if (flags & MAP_ALIGNMENT_MASK) {
|
||||
qemu_log("MAP_ALIGNED(%u) ",
|
||||
(flags & MAP_ALIGNMENT_MASK) >> MAP_ALIGNMENT_SHIFT);
|
||||
printf("MAP_ALIGNED(%u) ", (flags & MAP_ALIGNMENT_MASK)
|
||||
>> MAP_ALIGNMENT_SHIFT);
|
||||
}
|
||||
#if MAP_GUARD
|
||||
if (flags & MAP_GUARD) {
|
||||
qemu_log("MAP_GUARD ");
|
||||
printf("MAP_GUARD ");
|
||||
}
|
||||
#endif
|
||||
if (flags & MAP_FIXED) {
|
||||
qemu_log("MAP_FIXED ");
|
||||
printf("MAP_FIXED ");
|
||||
}
|
||||
if (flags & MAP_ANON) {
|
||||
qemu_log("MAP_ANON ");
|
||||
if (flags & MAP_ANONYMOUS) {
|
||||
printf("MAP_ANON ");
|
||||
}
|
||||
#ifdef MAP_EXCL
|
||||
if (flags & MAP_EXCL) {
|
||||
qemu_log("MAP_EXCL ");
|
||||
printf("MAP_EXCL ");
|
||||
}
|
||||
#endif
|
||||
if (flags & MAP_PRIVATE) {
|
||||
qemu_log("MAP_PRIVATE ");
|
||||
printf("MAP_PRIVATE ");
|
||||
}
|
||||
if (flags & MAP_SHARED) {
|
||||
qemu_log("MAP_SHARED ");
|
||||
printf("MAP_SHARED ");
|
||||
}
|
||||
if (flags & MAP_NOCORE) {
|
||||
qemu_log("MAP_NOCORE ");
|
||||
printf("MAP_NOCORE ");
|
||||
}
|
||||
#ifdef MAP_STACK
|
||||
if (flags & MAP_STACK) {
|
||||
qemu_log("MAP_STACK ");
|
||||
printf("MAP_STACK ");
|
||||
}
|
||||
qemu_log("fd=%d offset=0x%lx\n", fd, offset);
|
||||
#endif
|
||||
printf("fd=%d offset=0x%llx\n", fd, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((flags & MAP_ANON) && fd != -1) {
|
||||
if ((flags & MAP_ANONYMOUS) && fd != -1) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
#ifdef MAP_STACK
|
||||
if (flags & MAP_STACK) {
|
||||
if ((fd != -1) || ((prot & (PROT_READ | PROT_WRITE)) !=
|
||||
(PROT_READ | PROT_WRITE))) {
|
||||
@@ -455,6 +449,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif /* MAP_STACK */
|
||||
#ifdef MAP_GUARD
|
||||
if ((flags & MAP_GUARD) && (prot != PROT_NONE || fd != -1 ||
|
||||
offset != 0 || (flags & (MAP_SHARED | MAP_PRIVATE |
|
||||
/* MAP_PREFAULT | */ /* MAP_PREFAULT not in mman.h */
|
||||
@@ -462,24 +458,18 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (offset & ~TARGET_PAGE_MASK) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
len = TARGET_PAGE_ALIGN(len);
|
||||
if (len == 0) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check for overflows */
|
||||
len = TARGET_PAGE_ALIGN(len);
|
||||
if (len == 0) {
|
||||
errno = ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
real_start = start & qemu_host_page_mask;
|
||||
host_offset = offset & qemu_host_page_mask;
|
||||
|
||||
@@ -546,7 +536,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
* qemu_real_host_page_size
|
||||
*/
|
||||
p = mmap(g2h_untagged(start), host_len, prot,
|
||||
flags | MAP_FIXED | ((fd != -1) ? MAP_ANON : 0), -1, 0);
|
||||
flags | MAP_FIXED | ((fd != -1) ? MAP_ANONYMOUS : 0), -1, 0);
|
||||
if (p == MAP_FAILED)
|
||||
goto fail;
|
||||
/* update start so that it points to the file position at 'offset' */
|
||||
@@ -574,16 +564,18 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
* It can fail only on 64-bit host with 32-bit target.
|
||||
* On any other target/host host mmap() handles this error correctly.
|
||||
*/
|
||||
if (!guest_range_valid_untagged(start, len)) {
|
||||
#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
|
||||
if ((unsigned long)start + len - 1 > (abi_ulong) -1) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* worst case: we cannot map the file because the offset is not
|
||||
* aligned, so we read it
|
||||
*/
|
||||
if (fd != -1 &&
|
||||
if (!(flags & MAP_ANON) &&
|
||||
(offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
|
||||
/*
|
||||
* msync() won't work here, so we return an error if write is
|
||||
@@ -599,22 +591,17 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
-1, 0);
|
||||
if (retaddr == -1)
|
||||
goto fail;
|
||||
if (pread(fd, g2h_untagged(start), len, offset) == -1) {
|
||||
goto fail;
|
||||
}
|
||||
pread(fd, g2h_untagged(start), len, offset);
|
||||
if (!(prot & PROT_WRITE)) {
|
||||
ret = target_mprotect(start, len, prot);
|
||||
assert(ret == 0);
|
||||
if (ret != 0) {
|
||||
start = ret;
|
||||
goto the_end;
|
||||
}
|
||||
}
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
/* Reject the mapping if any page within the range is mapped */
|
||||
if ((flags & MAP_EXCL) && page_check_range(start, len, 0) < 0) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* handle the start of the mapping */
|
||||
if (start > real_start) {
|
||||
if (real_end == real_start + qemu_host_page_size) {
|
||||
@@ -710,7 +697,8 @@ static void mmap_reserve(abi_ulong start, abi_ulong size)
|
||||
}
|
||||
if (real_start != real_end) {
|
||||
mmap(g2h_untagged(real_start), real_end - real_start, PROT_NONE,
|
||||
MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE,
|
||||
-1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-16
@@ -17,6 +17,7 @@
|
||||
#ifndef QEMU_H
|
||||
#define QEMU_H
|
||||
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/units.h"
|
||||
@@ -72,15 +73,15 @@ struct image_info {
|
||||
|
||||
#define MAX_SIGQUEUE_SIZE 1024
|
||||
|
||||
struct qemu_sigqueue {
|
||||
struct qemu_sigqueue *next;
|
||||
target_siginfo_t info;
|
||||
struct sigqueue {
|
||||
struct sigqueue *next;
|
||||
};
|
||||
|
||||
struct emulated_sigtable {
|
||||
int pending; /* true if signal is pending */
|
||||
struct qemu_sigqueue *first;
|
||||
struct qemu_sigqueue info; /* Put first signal info here */
|
||||
struct sigqueue *first;
|
||||
/* in order to always have memory for the first signal, we put it here */
|
||||
struct sigqueue info;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -91,18 +92,18 @@ typedef struct TaskState {
|
||||
|
||||
struct TaskState *next;
|
||||
struct bsd_binprm *bprm;
|
||||
int used; /* non zero if used */
|
||||
struct image_info *info;
|
||||
|
||||
struct emulated_sigtable sigtab[TARGET_NSIG];
|
||||
struct qemu_sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
|
||||
struct qemu_sigqueue *first_free; /* first free siginfo queue entry */
|
||||
struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
|
||||
struct sigqueue *first_free; /* first free siginfo queue entry */
|
||||
int signal_pending; /* non zero if a signal may be pending */
|
||||
|
||||
uint8_t stack[];
|
||||
} __attribute__((aligned(16))) TaskState;
|
||||
|
||||
void init_task_state(TaskState *ts);
|
||||
void stop_all_tasks(void);
|
||||
extern const char *qemu_uname_release;
|
||||
|
||||
/*
|
||||
@@ -208,7 +209,6 @@ void process_pending_signals(CPUArchState *cpu_env);
|
||||
void signal_init(void);
|
||||
long do_sigreturn(CPUArchState *env);
|
||||
long do_rt_sigreturn(CPUArchState *env);
|
||||
void queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
|
||||
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
|
||||
|
||||
/* mmap.c */
|
||||
@@ -235,13 +235,6 @@ extern unsigned long target_dflssiz;
|
||||
extern unsigned long target_maxssiz;
|
||||
extern unsigned long target_sgrowsiz;
|
||||
|
||||
/* syscall.c */
|
||||
abi_long get_errno(abi_long ret);
|
||||
bool is_error(abi_long ret);
|
||||
|
||||
/* os-sys.c */
|
||||
abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2);
|
||||
|
||||
/* user access */
|
||||
|
||||
#define VERIFY_READ PAGE_READ
|
||||
|
||||
+1
-31
@@ -16,24 +16,10 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "qemu.h"
|
||||
|
||||
/*
|
||||
* Stubbed out routines until we merge signal support from bsd-user
|
||||
* fork.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Queue a signal so that it will be send to the virtual CPU as soon as
|
||||
* possible.
|
||||
*/
|
||||
void queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "No signal queueing, dropping signal %d\n", sig);
|
||||
}
|
||||
|
||||
void signal_init(void)
|
||||
{
|
||||
}
|
||||
@@ -41,19 +27,3 @@ void signal_init(void)
|
||||
void process_pending_signals(CPUArchState *cpu_env)
|
||||
{
|
||||
}
|
||||
|
||||
void cpu_loop_exit_sigsegv(CPUState *cpu, target_ulong addr,
|
||||
MMUAccessType access_type, bool maperr, uintptr_t ra)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "No signal support for SIGSEGV\n");
|
||||
/* unreachable */
|
||||
abort();
|
||||
}
|
||||
|
||||
void cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr,
|
||||
MMUAccessType access_type, uintptr_t ra)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "No signal support for SIGBUS\n");
|
||||
/* unreachable */
|
||||
abort();
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* QEMU internal errno values for implementing user-only POSIX.
|
||||
*
|
||||
* Copyright (c) 2021 Linaro, Ltd.
|
||||
*/
|
||||
|
||||
#ifndef SPECIAL_ERRNO_H
|
||||
#define SPECIAL_ERRNO_H
|
||||
|
||||
/*
|
||||
* All of these are QEMU internal, not visible to the guest.
|
||||
* They should be chosen so as to not overlap with any host
|
||||
* or guest errno.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is returned when a system call should be restarted, to tell the
|
||||
* main loop that it should wind the guest PC backwards so it will
|
||||
* re-execute the syscall after handling any pending signals.
|
||||
*/
|
||||
#define QEMU_ERESTARTSYS 255
|
||||
|
||||
#endif /* SPECIAL_ERRNO_H */
|
||||
+55
-5
@@ -33,18 +33,18 @@
|
||||
static abi_ulong target_brk;
|
||||
static abi_ulong target_original_brk;
|
||||
|
||||
abi_long get_errno(abi_long ret)
|
||||
static inline abi_long get_errno(abi_long ret)
|
||||
{
|
||||
if (ret == -1) {
|
||||
if (ret == -1)
|
||||
/* XXX need to translate host -> target errnos here */
|
||||
return -(errno);
|
||||
}
|
||||
return ret;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define target_to_host_bitmask(x, tbl) (x)
|
||||
|
||||
bool is_error(abi_long ret)
|
||||
static inline int is_error(abi_long ret)
|
||||
{
|
||||
return (abi_ulong)ret >= (abi_ulong)(-4096);
|
||||
}
|
||||
@@ -88,6 +88,56 @@ static abi_long do_obreak(abi_ulong new_brk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(TARGET_I386)
|
||||
static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
|
||||
{
|
||||
abi_long ret = 0;
|
||||
abi_ulong val;
|
||||
int idx;
|
||||
|
||||
switch (op) {
|
||||
#ifdef TARGET_ABI32
|
||||
case TARGET_FREEBSD_I386_SET_GSBASE:
|
||||
case TARGET_FREEBSD_I386_SET_FSBASE:
|
||||
if (op == TARGET_FREEBSD_I386_SET_GSBASE)
|
||||
#else
|
||||
case TARGET_FREEBSD_AMD64_SET_GSBASE:
|
||||
case TARGET_FREEBSD_AMD64_SET_FSBASE:
|
||||
if (op == TARGET_FREEBSD_AMD64_SET_GSBASE)
|
||||
#endif
|
||||
idx = R_GS;
|
||||
else
|
||||
idx = R_FS;
|
||||
if (get_user(val, parms, abi_ulong))
|
||||
return -TARGET_EFAULT;
|
||||
cpu_x86_load_seg(env, idx, 0);
|
||||
env->segs[idx].base = val;
|
||||
break;
|
||||
#ifdef TARGET_ABI32
|
||||
case TARGET_FREEBSD_I386_GET_GSBASE:
|
||||
case TARGET_FREEBSD_I386_GET_FSBASE:
|
||||
if (op == TARGET_FREEBSD_I386_GET_GSBASE)
|
||||
#else
|
||||
case TARGET_FREEBSD_AMD64_GET_GSBASE:
|
||||
case TARGET_FREEBSD_AMD64_GET_FSBASE:
|
||||
if (op == TARGET_FREEBSD_AMD64_GET_GSBASE)
|
||||
#endif
|
||||
idx = R_GS;
|
||||
else
|
||||
idx = R_FS;
|
||||
val = env->segs[idx].base;
|
||||
if (put_user(val, parms, abi_ulong))
|
||||
return -TARGET_EFAULT;
|
||||
break;
|
||||
/* XXX handle the others... */
|
||||
default:
|
||||
ret = -TARGET_EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/*
|
||||
* XXX this uses the undocumented oidfmt interface to find the kind of
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#define TARGET_DEFAULT_CPU_MODEL "qemu64"
|
||||
|
||||
#define TARGET_CPU_RESET(cpu)
|
||||
|
||||
static inline void target_cpu_init(CPUX86State *env,
|
||||
struct target_pt_regs *regs)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
|
||||
#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
|
||||
|
||||
#define TARGET_MC_GET_CLEAR_RET 0x0001
|
||||
|
||||
struct target_sigcontext {
|
||||
/* to be added */
|
||||
};
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@
|
||||
#include "qemu/option.h"
|
||||
#include "chardev/char.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qapi/qapi-commands-control.h"
|
||||
#include "chardev-internal.h"
|
||||
|
||||
/* MUX driver for serial I/O splitting */
|
||||
@@ -158,7 +157,7 @@ static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch)
|
||||
{
|
||||
const char *term = "QEMU: Terminated\n\r";
|
||||
qemu_chr_write_all(chr, (uint8_t *)term, strlen(term));
|
||||
qmp_quit(NULL);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
|
||||
+62
-10
@@ -25,7 +25,9 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "chardev/char.h"
|
||||
#include "io/channel-socket.h"
|
||||
#include "io/channel-tls.h"
|
||||
#include "io/channel-websock.h"
|
||||
#include "io/net-listener.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
@@ -35,7 +37,61 @@
|
||||
#include "qemu/yank.h"
|
||||
|
||||
#include "chardev/char-io.h"
|
||||
#include "chardev/char-socket.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
/***********************************************************/
|
||||
/* TCP Net console */
|
||||
|
||||
#define TCP_MAX_FDS 16
|
||||
|
||||
typedef struct {
|
||||
char buf[21];
|
||||
size_t buflen;
|
||||
} TCPChardevTelnetInit;
|
||||
|
||||
typedef enum {
|
||||
TCP_CHARDEV_STATE_DISCONNECTED,
|
||||
TCP_CHARDEV_STATE_CONNECTING,
|
||||
TCP_CHARDEV_STATE_CONNECTED,
|
||||
} TCPChardevState;
|
||||
|
||||
struct SocketChardev {
|
||||
Chardev parent;
|
||||
QIOChannel *ioc; /* Client I/O channel */
|
||||
QIOChannelSocket *sioc; /* Client master channel */
|
||||
QIONetListener *listener;
|
||||
GSource *hup_source;
|
||||
QCryptoTLSCreds *tls_creds;
|
||||
char *tls_authz;
|
||||
TCPChardevState state;
|
||||
int max_size;
|
||||
int do_telnetopt;
|
||||
int do_nodelay;
|
||||
int *read_msgfds;
|
||||
size_t read_msgfds_num;
|
||||
int *write_msgfds;
|
||||
size_t write_msgfds_num;
|
||||
bool registered_yank;
|
||||
|
||||
SocketAddress *addr;
|
||||
bool is_listen;
|
||||
bool is_telnet;
|
||||
bool is_tn3270;
|
||||
GSource *telnet_source;
|
||||
TCPChardevTelnetInit *telnet_init;
|
||||
|
||||
bool is_websock;
|
||||
|
||||
GSource *reconnect_timer;
|
||||
int64_t reconnect_time;
|
||||
bool connect_err_reported;
|
||||
|
||||
QIOTask *connect_task;
|
||||
};
|
||||
typedef struct SocketChardev SocketChardev;
|
||||
|
||||
DECLARE_INSTANCE_CHECKER(SocketChardev, SOCKET_CHARDEV,
|
||||
TYPE_CHARDEV_SOCKET)
|
||||
|
||||
static gboolean socket_reconnect_timeout(gpointer opaque);
|
||||
static void tcp_chr_telnet_init(Chardev *chr);
|
||||
@@ -1192,10 +1248,6 @@ static int qmp_chardev_open_socket_server(Chardev *chr,
|
||||
qio_net_listener_set_name(s->listener, name);
|
||||
g_free(name);
|
||||
|
||||
if (s->addr->type == SOCKET_ADDRESS_TYPE_FD && !*s->addr->u.fd.str) {
|
||||
goto skip_listen;
|
||||
}
|
||||
|
||||
if (qio_net_listener_open_sync(s->listener, s->addr, 1, errp) < 0) {
|
||||
object_unref(OBJECT(s->listener));
|
||||
s->listener = NULL;
|
||||
@@ -1204,8 +1256,6 @@ static int qmp_chardev_open_socket_server(Chardev *chr,
|
||||
|
||||
qapi_free_SocketAddress(s->addr);
|
||||
s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
|
||||
|
||||
skip_listen:
|
||||
update_disconnected_filename(s);
|
||||
|
||||
if (is_waitconnect) {
|
||||
@@ -1416,9 +1466,9 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
|
||||
SocketAddressLegacy *addr;
|
||||
ChardevSocket *sock;
|
||||
|
||||
if ((!!path + !!fd + !!host) > 1) {
|
||||
if ((!!path + !!fd + !!host) != 1) {
|
||||
error_setg(errp,
|
||||
"None or one of 'path', 'fd' or 'host' option required.");
|
||||
"Exactly one of 'path', 'fd' or 'host' required");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1492,10 +1542,12 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
|
||||
.has_ipv6 = qemu_opt_get(opts, "ipv6"),
|
||||
.ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
|
||||
};
|
||||
} else {
|
||||
} else if (fd) {
|
||||
addr->type = SOCKET_ADDRESS_TYPE_FD;
|
||||
addr->u.fd.data = g_new(String, 1);
|
||||
addr->u.fd.data->str = g_strdup(fd);
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
sock->addr = addr;
|
||||
}
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ if brlapi.found()
|
||||
chardev_modules += { 'baum': module_ss }
|
||||
endif
|
||||
|
||||
if spice.found()
|
||||
if config_host.has_key('CONFIG_SPICE')
|
||||
module_ss = ss.source_set()
|
||||
module_ss.add(when: [spice], if_true: files('spice.c'))
|
||||
chardev_modules += { 'spice': module_ss }
|
||||
|
||||
@@ -320,6 +320,7 @@ static void wctablet_chr_finalize(Object *obj)
|
||||
TabletChardev *tablet = WCTABLET_CHARDEV(obj);
|
||||
|
||||
qemu_input_handler_unregister(tablet->hs);
|
||||
g_free(tablet);
|
||||
}
|
||||
|
||||
static void wctablet_chr_open(Chardev *chr,
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* safe-syscall.inc.S : host-specific assembly fragment
|
||||
* to handle signals occurring at the same time as system calls.
|
||||
* This is intended to be included by common-user/safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <rth@twiddle.net>
|
||||
* Copyright (C) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
.global safe_syscall_base
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_base, #function
|
||||
.type safe_syscall_start, #function
|
||||
.type safe_syscall_end, #function
|
||||
|
||||
/* This is the entry point for making a system call. The calling
|
||||
* convention here is that of a C varargs function with the
|
||||
* first argument an 'int *' to the signal_pending flag, the
|
||||
* second one the system call number (as a 'long'), and all further
|
||||
* arguments being syscall arguments (also 'long').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
/* The syscall calling convention isn't the same as the
|
||||
* C one:
|
||||
* we enter with x0 == &signal_pending
|
||||
* x1 == syscall number
|
||||
* x2 ... x7, (stack) == syscall arguments
|
||||
* and return the result in x0
|
||||
* and the syscall instruction needs
|
||||
* x8 == syscall number
|
||||
* x0 ... x6 == syscall arguments
|
||||
* and returns the result in x0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
mov x9, x0 /* signal_pending pointer */
|
||||
mov x8, x1 /* syscall number */
|
||||
mov x0, x2 /* syscall arguments */
|
||||
mov x1, x3
|
||||
mov x2, x4
|
||||
mov x3, x5
|
||||
mov x4, x6
|
||||
mov x5, x7
|
||||
ldr x6, [sp]
|
||||
|
||||
/* This next sequence of code works in conjunction with the
|
||||
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||
* The code sequence must therefore be able to cope with this, and
|
||||
* the syscall instruction must be the final one in the sequence.
|
||||
*/
|
||||
safe_syscall_start:
|
||||
/* if signal_pending is non-zero, don't do the call */
|
||||
ldr w10, [x9]
|
||||
cbnz w10, 2f
|
||||
svc 0x0
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
#if defined(__linux__)
|
||||
/* Linux kernel returns (small) negative errno. */
|
||||
cmp x0, #-4096
|
||||
b.hi 0f
|
||||
#elif defined(__FreeBSD__)
|
||||
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||
b.cs 1f
|
||||
#else
|
||||
#error "unsupported os"
|
||||
#endif
|
||||
ret
|
||||
|
||||
#if defined(__linux__)
|
||||
/* code path setting errno */
|
||||
0: neg w0, w0
|
||||
b safe_syscall_set_errno_tail
|
||||
#endif
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: mov w0, #QEMU_ERESTARTSYS
|
||||
1: b safe_syscall_set_errno_tail
|
||||
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* safe-syscall.inc.S : host-specific assembly fragment
|
||||
* to handle signals occurring at the same time as system calls.
|
||||
* This is intended to be included by common-user/safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <rth@twiddle.net>
|
||||
* Copyright (C) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
.global safe_syscall_base
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_base, %function
|
||||
|
||||
.cfi_sections .debug_frame
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
.arm
|
||||
.align 2
|
||||
|
||||
/* This is the entry point for making a system call. The calling
|
||||
* convention here is that of a C varargs function with the
|
||||
* first argument an 'int *' to the signal_pending flag, the
|
||||
* second one the system call number (as a 'long'), and all further
|
||||
* arguments being syscall arguments (also 'long').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.fnstart
|
||||
.cfi_startproc
|
||||
mov r12, sp /* save entry stack */
|
||||
push { r4, r5, r6, r7, r8, lr }
|
||||
.save { r4, r5, r6, r7, r8, lr }
|
||||
.cfi_adjust_cfa_offset 24
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
.cfi_rel_offset r6, 8
|
||||
.cfi_rel_offset r7, 12
|
||||
.cfi_rel_offset r8, 16
|
||||
.cfi_rel_offset lr, 20
|
||||
|
||||
/* The syscall calling convention isn't the same as the C one:
|
||||
* we enter with r0 == &signal_pending
|
||||
* r1 == syscall number
|
||||
* r2, r3, [sp+0] ... [sp+12] == syscall arguments
|
||||
* and return the result in r0
|
||||
* and the syscall instruction needs
|
||||
* r7 == syscall number
|
||||
* r0 ... r6 == syscall arguments
|
||||
* and returns the result in r0
|
||||
* Shuffle everything around appropriately.
|
||||
* Note the 16 bytes that we pushed to save registers.
|
||||
*/
|
||||
mov r8, r0 /* copy signal_pending */
|
||||
mov r7, r1 /* syscall number */
|
||||
mov r0, r2 /* syscall args */
|
||||
mov r1, r3
|
||||
ldm r12, { r2, r3, r4, r5, r6 }
|
||||
|
||||
/* This next sequence of code works in conjunction with the
|
||||
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||
* The code sequence must therefore be able to cope with this, and
|
||||
* the syscall instruction must be the final one in the sequence.
|
||||
*/
|
||||
safe_syscall_start:
|
||||
/* if signal_pending is non-zero, don't do the call */
|
||||
ldr r12, [r8] /* signal_pending */
|
||||
tst r12, r12
|
||||
bne 2f
|
||||
swi 0
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
#if defined(__linux__)
|
||||
/* Linux kernel returns (small) negative errno. */
|
||||
cmp r0, #-4096
|
||||
neghi r0, r0
|
||||
bhi 1f
|
||||
#elif defined(__FreeBSD__)
|
||||
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||
bcs 1f
|
||||
#else
|
||||
#error "unsupported os"
|
||||
#endif
|
||||
pop { r4, r5, r6, r7, r8, pc }
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: mov r0, #QEMU_ERESTARTSYS
|
||||
|
||||
/* code path setting errno */
|
||||
1: pop { r4, r5, r6, r7, r8, lr }
|
||||
.cfi_adjust_cfa_offset -24
|
||||
.cfi_restore r4
|
||||
.cfi_restore r5
|
||||
.cfi_restore r6
|
||||
.cfi_restore r7
|
||||
.cfi_restore r8
|
||||
.cfi_restore lr
|
||||
b safe_syscall_set_errno_tail
|
||||
|
||||
.fnend
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* safe-syscall.inc.S : host-specific assembly fragment
|
||||
* to handle signals occurring at the same time as system calls.
|
||||
* This is intended to be included by common-user/safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <rth@twiddle.net>
|
||||
* Copyright (C) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
.global safe_syscall_base
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_base, @function
|
||||
|
||||
/* This is the entry point for making a system call. The calling
|
||||
* convention here is that of a C varargs function with the
|
||||
* first argument an 'int *' to the signal_pending flag, the
|
||||
* second one the system call number (as a 'long'), and all further
|
||||
* arguments being syscall arguments (also 'long').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
push %ebp
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ebp, 0
|
||||
push %esi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset esi, 0
|
||||
push %edi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edi, 0
|
||||
push %ebx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ebx, 0
|
||||
|
||||
/* The syscall calling convention isn't the same as the C one:
|
||||
* we enter with 0(%esp) == return address
|
||||
* 4(%esp) == &signal_pending
|
||||
* 8(%esp) == syscall number
|
||||
* 12(%esp) ... 32(%esp) == syscall arguments
|
||||
* and return the result in eax
|
||||
* and the syscall instruction needs
|
||||
* eax == syscall number
|
||||
* ebx, ecx, edx, esi, edi, ebp == syscall arguments
|
||||
* and returns the result in eax
|
||||
* Shuffle everything around appropriately.
|
||||
* Note the 16 bytes that we pushed to save registers.
|
||||
*/
|
||||
mov 12+16(%esp), %ebx /* the syscall arguments */
|
||||
mov 16+16(%esp), %ecx
|
||||
mov 20+16(%esp), %edx
|
||||
mov 24+16(%esp), %esi
|
||||
mov 28+16(%esp), %edi
|
||||
mov 32+16(%esp), %ebp
|
||||
|
||||
/* This next sequence of code works in conjunction with the
|
||||
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||
* The code sequence must therefore be able to cope with this, and
|
||||
* the syscall instruction must be the final one in the sequence.
|
||||
*/
|
||||
safe_syscall_start:
|
||||
/* if signal_pending is non-zero, don't do the call */
|
||||
mov 4+16(%esp), %eax /* signal_pending */
|
||||
cmpl $0, (%eax)
|
||||
jnz 2f
|
||||
mov 8+16(%esp), %eax /* syscall number */
|
||||
int $0x80
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
#if defined(__linux__)
|
||||
/* Linux kernel returns (small) negative errno. */
|
||||
cmp $-4095, %eax
|
||||
jae 0f
|
||||
#elif defined(__FreeBSD__)
|
||||
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||
jc 1f
|
||||
#else
|
||||
#error "unsupported os"
|
||||
#endif
|
||||
pop %ebx
|
||||
.cfi_remember_state
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebx
|
||||
pop %edi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore edi
|
||||
pop %esi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore esi
|
||||
pop %ebp
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebp
|
||||
ret
|
||||
.cfi_restore_state
|
||||
|
||||
#if defined(__linux__)
|
||||
0: neg %eax
|
||||
jmp 1f
|
||||
#endif
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: mov $QEMU_ERESTARTSYS, %eax
|
||||
|
||||
/* code path setting errno */
|
||||
1: pop %ebx
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebx
|
||||
pop %edi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore edi
|
||||
pop %esi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore esi
|
||||
pop %ebp
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebp
|
||||
jmp safe_syscall_set_errno_tail
|
||||
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* safe-syscall.inc.S : host-specific assembly fragment
|
||||
* to handle signals occurring at the same time as system calls.
|
||||
* This is intended to be included by common-user/safe-syscall.S
|
||||
*
|
||||
* Ported to LoongArch by WANG Xuerui <git@xen0n.name>
|
||||
*
|
||||
* Based on safe-syscall.inc.S code for RISC-V,
|
||||
* originally written by Richard Henderson <rth@twiddle.net>
|
||||
* Copyright (C) 2018 Linaro, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
.global safe_syscall_base
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_base, @function
|
||||
.type safe_syscall_start, @function
|
||||
.type safe_syscall_end, @function
|
||||
|
||||
/*
|
||||
* This is the entry point for making a system call. The calling
|
||||
* convention here is that of a C varargs function with the
|
||||
* first argument an 'int *' to the signal_pending flag, the
|
||||
* second one the system call number (as a 'long'), and all further
|
||||
* arguments being syscall arguments (also 'long').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
/*
|
||||
* The syscall calling convention is nearly the same as C:
|
||||
* we enter with a0 == &signal_pending
|
||||
* a1 == syscall number
|
||||
* a2 ... a7 == syscall arguments
|
||||
* and return the result in a0
|
||||
* and the syscall instruction needs
|
||||
* a7 == syscall number
|
||||
* a0 ... a5 == syscall arguments
|
||||
* and returns the result in a0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
move $t0, $a0 /* signal_pending pointer */
|
||||
move $t1, $a1 /* syscall number */
|
||||
move $a0, $a2 /* syscall arguments */
|
||||
move $a1, $a3
|
||||
move $a2, $a4
|
||||
move $a3, $a5
|
||||
move $a4, $a6
|
||||
move $a5, $a7
|
||||
move $a7, $t1
|
||||
|
||||
/*
|
||||
* We need to preserve the signal_pending pointer but t0 is
|
||||
* clobbered by syscalls on LoongArch, so we need to move it
|
||||
* somewhere else, ideally both preserved across syscalls and
|
||||
* clobbered by procedure calls so we don't have to allocate a
|
||||
* stack frame; a6 is just the register we want here.
|
||||
*/
|
||||
move $a6, $t0
|
||||
|
||||
/*
|
||||
* This next sequence of code works in conjunction with the
|
||||
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||
* The code sequence must therefore be able to cope with this, and
|
||||
* the syscall instruction must be the final one in the sequence.
|
||||
*/
|
||||
safe_syscall_start:
|
||||
/* If signal_pending is non-zero, don't do the call */
|
||||
ld.w $t1, $a6, 0
|
||||
bnez $t1, 2f
|
||||
syscall 0
|
||||
safe_syscall_end:
|
||||
/* code path for having successfully executed the syscall */
|
||||
li.w $t2, -4096
|
||||
bgtu $a0, $t2, 0f
|
||||
jr $ra
|
||||
|
||||
/* code path setting errno */
|
||||
0: sub.d $a0, $zero, $a0
|
||||
b safe_syscall_set_errno_tail
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: li.w $a0, QEMU_ERESTARTSYS
|
||||
b safe_syscall_set_errno_tail
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* safe-syscall.inc.S : host-specific assembly fragment
|
||||
* to handle signals occurring at the same time as system calls.
|
||||
* This is intended to be included by common-user/safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <richard.henderson@linaro.org>
|
||||
* Copyright (C) 2021 Linaro, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "sys/regdef.h"
|
||||
#include "sys/asm.h"
|
||||
|
||||
.text
|
||||
.set nomips16
|
||||
.set reorder
|
||||
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_start, @function
|
||||
.type safe_syscall_end, @function
|
||||
|
||||
/*
|
||||
* This is the entry point for making a system call. The calling
|
||||
* convention here is that of a C varargs function with the
|
||||
* first argument an 'int *' to the signal_pending flag, the
|
||||
* second one the system call number (as a 'long'), and all further
|
||||
* arguments being syscall arguments (also 'long').
|
||||
*/
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
/* 8 * 4 = 32 for outgoing parameters; 1 * 4 for s0 save; 1 * 4 for align. */
|
||||
#define FRAME 40
|
||||
#define OFS_S0 32
|
||||
#else
|
||||
/* 1 * 8 for s0 save; 1 * 8 for align. */
|
||||
#define FRAME 16
|
||||
#define OFS_S0 0
|
||||
#endif
|
||||
|
||||
|
||||
NESTED(safe_syscall_base, FRAME, ra)
|
||||
.cfi_startproc
|
||||
PTR_ADDIU sp, sp, -FRAME
|
||||
.cfi_adjust_cfa_offset FRAME
|
||||
REG_S s0, OFS_S0(sp)
|
||||
.cfi_rel_offset s0, OFS_S0
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
/*
|
||||
* The syscall calling convention is nearly the same as C:
|
||||
* we enter with a0 == &signal_pending
|
||||
* a1 == syscall number
|
||||
* a2, a3, stack == syscall arguments
|
||||
* and return the result in a0
|
||||
* and the syscall instruction needs
|
||||
* v0 == syscall number
|
||||
* a0 ... a3, stack == syscall arguments
|
||||
* and returns the result in v0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
move s0, a0 /* signal_pending pointer */
|
||||
move v0, a1 /* syscall number */
|
||||
move a0, a2 /* syscall arguments */
|
||||
move a1, a3
|
||||
lw a2, FRAME+16(sp)
|
||||
lw a3, FRAME+20(sp)
|
||||
lw t4, FRAME+24(sp)
|
||||
lw t5, FRAME+28(sp)
|
||||
lw t6, FRAME+32(sp)
|
||||
lw t7, FRAME+40(sp)
|
||||
sw t4, 16(sp)
|
||||
sw t5, 20(sp)
|
||||
sw t6, 24(sp)
|
||||
sw t7, 28(sp)
|
||||
#else
|
||||
/*
|
||||
* The syscall calling convention is nearly the same as C:
|
||||
* we enter with a0 == &signal_pending
|
||||
* a1 == syscall number
|
||||
* a2 ... a7 == syscall arguments
|
||||
* and return the result in a0
|
||||
* and the syscall instruction needs
|
||||
* v0 == syscall number
|
||||
* a0 ... a5 == syscall arguments
|
||||
* and returns the result in v0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
move s0, a0 /* signal_pending pointer */
|
||||
move v0, a1 /* syscall number */
|
||||
move a0, a2 /* syscall arguments */
|
||||
move a1, a3
|
||||
move a2, a4
|
||||
move a3, a5
|
||||
move a4, a6
|
||||
move a5, a7
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This next sequence of code works in conjunction with the
|
||||
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||
* The code sequence must therefore be able to cope with this, and
|
||||
* the syscall instruction must be the final one in the sequence.
|
||||
*/
|
||||
safe_syscall_start:
|
||||
/* If signal_pending is non-zero, don't do the call */
|
||||
lw t1, 0(s0)
|
||||
bnez t1, 2f
|
||||
syscall
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
REG_L s0, OFS_S0(sp)
|
||||
PTR_ADDIU sp, sp, FRAME
|
||||
.cfi_remember_state
|
||||
.cfi_adjust_cfa_offset -FRAME
|
||||
.cfi_restore s0
|
||||
bnez a3, 1f
|
||||
jr ra
|
||||
.cfi_restore_state
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: REG_L s0, OFS_S0(sp)
|
||||
PTR_ADDIU sp, sp, FRAME
|
||||
.cfi_adjust_cfa_offset -FRAME
|
||||
.cfi_restore s0
|
||||
li v0, QEMU_ERESTARTSYS
|
||||
|
||||
/* code path setting errno */
|
||||
/*
|
||||
* We didn't setup GP on entry, optimistic of the syscall success.
|
||||
* We must do so now to load the address of the helper, as required
|
||||
* by the ABI, into t9.
|
||||
*
|
||||
* Note that SETUP_GPX and SETUP_GPX64 are themselves conditional,
|
||||
* so we can simply let the one that's not empty succeed.
|
||||
*/
|
||||
1: USE_ALT_CP(t0)
|
||||
SETUP_GPX(t1)
|
||||
SETUP_GPX64(t0, t1)
|
||||
PTR_LA t9, safe_syscall_set_errno_tail
|
||||
jr t9
|
||||
|
||||
.cfi_endproc
|
||||
END(safe_syscall_base)
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* safe-syscall.inc.S : host-specific assembly fragment
|
||||
* to handle signals occurring at the same time as system calls.
|
||||
* This is intended to be included by common-user/safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <rth@twiddle.net>
|
||||
* Copyright (C) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
.global safe_syscall_base
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_base, @function
|
||||
|
||||
.text
|
||||
|
||||
/* This is the entry point for making a system call. The calling
|
||||
* convention here is that of a C varargs function with the
|
||||
* first argument an 'int *' to the signal_pending flag, the
|
||||
* second one the system call number (as a 'long'), and all further
|
||||
* arguments being syscall arguments (also 'long').
|
||||
*/
|
||||
#if _CALL_ELF == 2
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
.localentry safe_syscall_base,0
|
||||
#else
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
safe_syscall_base:
|
||||
.quad .L.safe_syscall_base,.TOC.@tocbase,0
|
||||
.previous
|
||||
.L.safe_syscall_base:
|
||||
.cfi_startproc
|
||||
#endif
|
||||
/* We enter with r3 == &signal_pending
|
||||
* r4 == syscall number
|
||||
* r5 ... r10 == syscall arguments
|
||||
* and return the result in r3
|
||||
* and the syscall instruction needs
|
||||
* r0 == syscall number
|
||||
* r3 ... r8 == syscall arguments
|
||||
* and returns the result in r3
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
std 14, 16(1) /* Preserve r14 in SP+16 */
|
||||
.cfi_offset 14, 16
|
||||
mr 14, 3 /* signal_pending */
|
||||
mr 0, 4 /* syscall number */
|
||||
mr 3, 5 /* syscall arguments */
|
||||
mr 4, 6
|
||||
mr 5, 7
|
||||
mr 6, 8
|
||||
mr 7, 9
|
||||
mr 8, 10
|
||||
|
||||
/* This next sequence of code works in conjunction with the
|
||||
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||
* The code sequence must therefore be able to cope with this, and
|
||||
* the syscall instruction must be the final one in the sequence.
|
||||
*/
|
||||
safe_syscall_start:
|
||||
/* if signal_pending is non-zero, don't do the call */
|
||||
lwz 12, 0(14)
|
||||
cmpwi 0, 12, 0
|
||||
bne- 2f
|
||||
sc
|
||||
safe_syscall_end:
|
||||
/* code path when we did execute the syscall */
|
||||
ld 14, 16(1) /* restore r14 */
|
||||
bso- 1f
|
||||
blr
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: ld 14, 16(1) /* restore r14 */
|
||||
addi 3, 0, QEMU_ERESTARTSYS
|
||||
|
||||
/* code path setting errno */
|
||||
1: b safe_syscall_set_errno_tail
|
||||
nop /* per abi, for the linker to modify */
|
||||
|
||||
.cfi_endproc
|
||||
|
||||
#if _CALL_ELF == 2
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
||||
#else
|
||||
.size safe_syscall_base, .-.L.safe_syscall_base
|
||||
.size .L.safe_syscall_base, .-.L.safe_syscall_base
|
||||
#endif
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* safe-syscall.inc.S : host-specific assembly fragment
|
||||
* to handle signals occurring at the same time as system calls.
|
||||
* This is intended to be included by common-user/safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <rth@twiddle.net>
|
||||
* Copyright (C) 2018 Linaro, Inc.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
.global safe_syscall_base
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_base, @function
|
||||
.type safe_syscall_start, @function
|
||||
.type safe_syscall_end, @function
|
||||
|
||||
/*
|
||||
* This is the entry point for making a system call. The calling
|
||||
* convention here is that of a C varargs function with the
|
||||
* first argument an 'int *' to the signal_pending flag, the
|
||||
* second one the system call number (as a 'long'), and all further
|
||||
* arguments being syscall arguments (also 'long').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
/*
|
||||
* The syscall calling convention is nearly the same as C:
|
||||
* we enter with a0 == &signal_pending
|
||||
* a1 == syscall number
|
||||
* a2 ... a7 == syscall arguments
|
||||
* and return the result in a0
|
||||
* and the syscall instruction needs
|
||||
* a7 == syscall number
|
||||
* a0 ... a5 == syscall arguments
|
||||
* and returns the result in a0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
mv t0, a0 /* signal_pending pointer */
|
||||
mv t1, a1 /* syscall number */
|
||||
mv a0, a2 /* syscall arguments */
|
||||
mv a1, a3
|
||||
mv a2, a4
|
||||
mv a3, a5
|
||||
mv a4, a6
|
||||
mv a5, a7
|
||||
mv a7, t1
|
||||
|
||||
/*
|
||||
* This next sequence of code works in conjunction with the
|
||||
* rewind_if_safe_syscall_function(). If a signal is taken
|
||||
* and the interrupted PC is anywhere between 'safe_syscall_start'
|
||||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
|
||||
* The code sequence must therefore be able to cope with this, and
|
||||
* the syscall instruction must be the final one in the sequence.
|
||||
*/
|
||||
safe_syscall_start:
|
||||
/* If signal_pending is non-zero, don't do the call */
|
||||
lw t1, 0(t0)
|
||||
bnez t1, 2f
|
||||
scall
|
||||
safe_syscall_end:
|
||||
/* code path for having successfully executed the syscall */
|
||||
li t2, -4096
|
||||
bgtu a0, t2, 0f
|
||||
ret
|
||||
|
||||
/* code path setting errno */
|
||||
0: neg a0, a0
|
||||
j safe_syscall_set_errno_tail
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: li a0, QEMU_ERESTARTSYS
|
||||
j safe_syscall_set_errno_tail
|
||||
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
||||
Loaded 100 of 1472 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user