Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9173d5d084 | ||
|
|
d8f4a7a80e | ||
|
|
c80a048f38 | ||
|
|
af87044127 | ||
|
|
395d5d09c7 | ||
|
|
ac056cbb54 | ||
|
|
f0060d4691 | ||
|
|
0170f3ea3d | ||
|
|
9ae56d2e46 | ||
|
|
6ed0b8431c | ||
|
|
50a715c77c | ||
|
|
efb1c1d294 |
@@ -2,8 +2,3 @@
|
||||
*.h.inc diff=c
|
||||
*.m diff=objc
|
||||
*.py diff=python
|
||||
*.rs diff=rust
|
||||
*.rs.inc diff=rust
|
||||
Cargo.lock diff=toml merge=binary
|
||||
|
||||
*.patch -text -whitespace
|
||||
|
||||
@@ -24,10 +24,6 @@ variables:
|
||||
# Each script line from will be in a collapsible section in the job output
|
||||
# and show the duration of each line.
|
||||
FF_SCRIPT_SECTIONS: 1
|
||||
# The project has a fairly fat GIT repo so we try and avoid bringing in things
|
||||
# we don't need. The --filter options avoid blobs and tree references we aren't going to use
|
||||
# and we also avoid fetching tags.
|
||||
GIT_FETCH_EXTRA_FLAGS: --filter=blob:none --filter=tree:0 --no-tags --prune --quiet
|
||||
|
||||
interruptible: true
|
||||
|
||||
@@ -128,7 +124,7 @@ variables:
|
||||
when: manual
|
||||
|
||||
# Jobs can run if any jobs they depend on were successful
|
||||
- if: '$CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH =~ /staging-[[:digit:]]+\.[[:digit:]]/'
|
||||
- if: '$QEMU_JOB_SKIPPED && $CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_COMMIT_BRANCH =~ /staging-[[:digit:]]+\.[[:digit:]]/'
|
||||
when: on_success
|
||||
variables:
|
||||
QEMU_CI_CONTAINER_TAG: $CI_COMMIT_REF_SLUG
|
||||
|
||||
@@ -8,21 +8,15 @@
|
||||
key: "$CI_JOB_NAME"
|
||||
when: always
|
||||
before_script:
|
||||
- source scripts/ci/gitlab-ci-section
|
||||
- section_start setup "Pre-script setup"
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
- cat /packages.txt
|
||||
- section_end setup
|
||||
script:
|
||||
- export CCACHE_BASEDIR="$(pwd)"
|
||||
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
|
||||
- export CCACHE_MAXSIZE="500M"
|
||||
- export PATH="$CCACHE_WRAPPERSDIR:$PATH"
|
||||
- du -sh .git
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ccache --zero-stats
|
||||
- section_start configure "Running configure"
|
||||
- ../configure --enable-werror --disable-docs --enable-fdt=system
|
||||
${TARGETS:+--target-list="$TARGETS"}
|
||||
$CONFIGURE_ARGS ||
|
||||
@@ -31,16 +25,11 @@
|
||||
then
|
||||
pyvenv/bin/meson configure . -Dbackend_max_links="$LD_JOBS" ;
|
||||
fi || exit 1;
|
||||
- section_end configure
|
||||
- section_start build "Building QEMU"
|
||||
- $MAKE -j"$JOBS"
|
||||
- section_end build
|
||||
- section_start test "Running tests"
|
||||
- make -j"$JOBS"
|
||||
- if test -n "$MAKE_CHECK_ARGS";
|
||||
then
|
||||
$MAKE -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||
make -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||
fi
|
||||
- section_end test
|
||||
- ccache --show-stats
|
||||
|
||||
# We jump some hoops in common_test_job_template to avoid
|
||||
@@ -55,29 +44,22 @@
|
||||
exclude:
|
||||
- build/**/*.p
|
||||
- build/**/*.a.p
|
||||
- build/**/*.fa.p
|
||||
- build/**/*.c.o
|
||||
- build/**/*.c.o.d
|
||||
- build/**/*.fa
|
||||
|
||||
.common_test_job_template:
|
||||
extends: .base_job_template
|
||||
stage: test
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:$QEMU_CI_CONTAINER_TAG
|
||||
script:
|
||||
- source scripts/ci/gitlab-ci-section
|
||||
- section_start buildenv "Setting up to run tests"
|
||||
- scripts/git-submodule.sh update roms/SLOF
|
||||
- build/pyvenv/bin/meson subprojects download $(cd build/subprojects && echo *)
|
||||
- meson subprojects download $(cd build/subprojects && echo *)
|
||||
- cd build
|
||||
- find . -type f -exec touch {} +
|
||||
# Avoid recompiling by hiding ninja with NINJA=":"
|
||||
# We also have to pre-cache the functional tests manually in this case
|
||||
- if [ "x${QEMU_TEST_CACHE_DIR}" != "x" ]; then
|
||||
$MAKE precache-functional ;
|
||||
fi
|
||||
- section_end buildenv
|
||||
- section_start test "Running tests"
|
||||
- $MAKE NINJA=":" $MAKE_CHECK_ARGS
|
||||
- section_end test
|
||||
- make NINJA=":" $MAKE_CHECK_ARGS
|
||||
|
||||
.native_test_job_template:
|
||||
extends: .common_test_job_template
|
||||
@@ -90,13 +72,12 @@
|
||||
reports:
|
||||
junit: build/meson-logs/testlog.junit.xml
|
||||
|
||||
.functional_test_job_template:
|
||||
.avocado_test_job_template:
|
||||
extends: .common_test_job_template
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}-cache"
|
||||
paths:
|
||||
- ${CI_PROJECT_DIR}/avocado-cache
|
||||
- ${CI_PROJECT_DIR}/functional-cache
|
||||
policy: pull-push
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
@@ -105,7 +86,6 @@
|
||||
paths:
|
||||
- build/tests/results/latest/results.xml
|
||||
- build/tests/results/latest/test-results
|
||||
- build/tests/functional/*/*/*.log
|
||||
reports:
|
||||
junit: build/tests/results/latest/results.xml
|
||||
before_script:
|
||||
@@ -116,13 +96,11 @@
|
||||
- echo -e '[job.output.testlogs]\nstatuses = ["FAIL", "INTERRUPT"]'
|
||||
>> ~/.config/avocado/avocado.conf
|
||||
- if [ -d ${CI_PROJECT_DIR}/avocado-cache ]; then
|
||||
du -chs ${CI_PROJECT_DIR}/*-cache ;
|
||||
du -chs ${CI_PROJECT_DIR}/avocado-cache ;
|
||||
fi
|
||||
- export AVOCADO_ALLOW_UNTRUSTED_CODE=1
|
||||
- export QEMU_TEST_ALLOW_UNTRUSTED_CODE=1
|
||||
- export QEMU_TEST_CACHE_DIR=${CI_PROJECT_DIR}/functional-cache
|
||||
after_script:
|
||||
- cd build
|
||||
- du -chs ${CI_PROJECT_DIR}/*-cache
|
||||
- du -chs ${CI_PROJECT_DIR}/avocado-cache
|
||||
variables:
|
||||
QEMU_JOB_AVOCADO: 1
|
||||
|
||||
+52
-81
@@ -22,14 +22,14 @@ check-system-alpine:
|
||||
IMAGE: alpine
|
||||
MAKE_CHECK_ARGS: check-unit check-qtest
|
||||
|
||||
functional-system-alpine:
|
||||
extends: .functional_test_job_template
|
||||
avocado-system-alpine:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-system-alpine
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: alpine
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:avr arch:loongarch64 arch:mips64 arch:mipsel
|
||||
|
||||
build-system-ubuntu:
|
||||
@@ -53,14 +53,14 @@ check-system-ubuntu:
|
||||
IMAGE: ubuntu2204
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
functional-system-ubuntu:
|
||||
extends: .functional_test_job_template
|
||||
avocado-system-ubuntu:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-system-ubuntu
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: ubuntu2204
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:alpha arch:microblazeel arch:mips64el
|
||||
|
||||
build-system-debian:
|
||||
@@ -85,14 +85,14 @@ check-system-debian:
|
||||
IMAGE: debian
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
functional-system-debian:
|
||||
extends: .functional_test_job_template
|
||||
avocado-system-debian:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:arm arch:i386 arch:riscv64 arch:sh4 arch:sparc arch:xtensa
|
||||
|
||||
crash-test-debian:
|
||||
@@ -115,24 +115,11 @@ build-system-fedora:
|
||||
job: amd64-fedora-container
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs --enable-crypto-afalg --enable-rust
|
||||
CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
|
||||
TARGETS: microblaze-softmmu mips-softmmu
|
||||
xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
|
||||
build-system-fedora-rust-nightly:
|
||||
extends:
|
||||
- .native_build_job_template
|
||||
- .native_build_artifact_template
|
||||
needs:
|
||||
job: amd64-fedora-rust-nightly-container
|
||||
variables:
|
||||
IMAGE: fedora-rust-nightly
|
||||
CONFIGURE_ARGS: --disable-docs --enable-rust --enable-strict-rust-lints
|
||||
TARGETS: aarch64-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
allow_failure: true
|
||||
|
||||
check-system-fedora:
|
||||
extends: .native_test_job_template
|
||||
needs:
|
||||
@@ -142,14 +129,14 @@ check-system-fedora:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
functional-system-fedora:
|
||||
extends: .functional_test_job_template
|
||||
avocado-system-fedora:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-system-fedora
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:microblaze arch:mips arch:xtensa arch:m68k
|
||||
arch:riscv32 arch:ppc arch:sparc64
|
||||
|
||||
@@ -171,13 +158,13 @@ build-system-centos:
|
||||
- .native_build_job_template
|
||||
- .native_build_artifact_template
|
||||
needs:
|
||||
job: amd64-centos9-container
|
||||
job: amd64-centos8-container
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
IMAGE: centos8
|
||||
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
|
||||
--enable-modules --enable-trace-backends=dtrace --enable-docs
|
||||
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
|
||||
x86_64-softmmu rx-softmmu sh4-softmmu
|
||||
x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
|
||||
# Previous QEMU release. Used for cross-version migration tests.
|
||||
@@ -191,17 +178,16 @@ build-previous-qemu:
|
||||
exclude:
|
||||
- build-previous/**/*.p
|
||||
- build-previous/**/*.a.p
|
||||
- build-previous/**/*.fa.p
|
||||
- build-previous/**/*.c.o
|
||||
- build-previous/**/*.c.o.d
|
||||
- build-previous/**/*.fa
|
||||
needs:
|
||||
job: amd64-opensuse-leap-container
|
||||
variables:
|
||||
IMAGE: opensuse-leap
|
||||
TARGETS: x86_64-softmmu aarch64-softmmu
|
||||
# Override the default flags as we need more to grab the old version
|
||||
GIT_FETCH_EXTRA_FLAGS: --prune --quiet
|
||||
before_script:
|
||||
- source scripts/ci/gitlab-ci-section
|
||||
- export QEMU_PREV_VERSION="$(sed 's/\([0-9.]*\)\.[0-9]*/v\1.0/' VERSION)"
|
||||
- git remote add upstream https://gitlab.com/qemu-project/qemu
|
||||
- git fetch upstream refs/tags/$QEMU_PREV_VERSION:refs/tags/$QEMU_PREV_VERSION
|
||||
@@ -226,14 +212,6 @@ build-previous-qemu:
|
||||
# testing an old QEMU against new features/tests that it is not
|
||||
# compatible with.
|
||||
- cd build-previous
|
||||
# Don't allow python-based tests to run. The
|
||||
# vmstate-checker-script test has a race that causes it to fail
|
||||
# sometimes. It cannot be fixed it because this job runs the test
|
||||
# from the old QEMU version. The test will be removed on master,
|
||||
# but this job will only see the change in the next release.
|
||||
#
|
||||
# TODO: remove this line after 9.2 release
|
||||
- unset PYTHON
|
||||
# old to new
|
||||
- QTEST_QEMU_BINARY_SRC=./qemu-system-${TARGET}
|
||||
QTEST_QEMU_BINARY=../build/qemu-system-${TARGET} ./tests/qtest/migration-test
|
||||
@@ -262,19 +240,19 @@ check-system-centos:
|
||||
- job: build-system-centos
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
functional-system-centos:
|
||||
extends: .functional_test_job_template
|
||||
avocado-system-centos:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-system-centos
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:ppc64 arch:or1k arch:s390x arch:x86_64 arch:rx
|
||||
arch:sh4
|
||||
arch:sh4 arch:nios2
|
||||
|
||||
build-system-opensuse:
|
||||
extends:
|
||||
@@ -296,14 +274,14 @@ check-system-opensuse:
|
||||
IMAGE: opensuse-leap
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
functional-system-opensuse:
|
||||
extends: .functional_test_job_template
|
||||
avocado-system-opensuse:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-system-opensuse
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: opensuse-leap
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:s390x arch:x86_64 arch:aarch64
|
||||
|
||||
#
|
||||
@@ -324,15 +302,15 @@ build-system-flaky:
|
||||
ppc64-softmmu rx-softmmu s390x-softmmu sh4-softmmu x86_64-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
|
||||
functional-system-flaky:
|
||||
extends: .functional_test_job_template
|
||||
avocado-system-flaky:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-system-flaky
|
||||
artifacts: true
|
||||
allow_failure: true
|
||||
variables:
|
||||
IMAGE: debian
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
QEMU_JOB_OPTIONAL: 1
|
||||
QEMU_TEST_FLAKY_TESTS: 1
|
||||
AVOCADO_TAGS: flaky
|
||||
@@ -347,9 +325,9 @@ functional-system-flaky:
|
||||
build-tcg-disabled:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-centos9-container
|
||||
job: amd64-centos8-container
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
IMAGE: centos8
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
@@ -362,13 +340,11 @@ build-tcg-disabled:
|
||||
- cd tests/qemu-iotests/
|
||||
- ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
|
||||
052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163
|
||||
170 171 184 192 194 208 221 226 227 236 253 277 image-fleecing
|
||||
170 171 183 184 192 194 208 221 226 227 236 253 277 image-fleecing
|
||||
- ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122
|
||||
124 132 139 142 144 145 151 152 155 157 165 194 196 200 202
|
||||
208 209 216 218 227 234 246 247 248 250 254 255 257 258
|
||||
260 261 262 263 264 270 272 273 277 279 image-fleecing
|
||||
- cd ../..
|
||||
- make distclean
|
||||
|
||||
build-user:
|
||||
extends: .native_build_job_template
|
||||
@@ -452,8 +428,8 @@ clang-system:
|
||||
job: amd64-fedora-container
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-ubsan
|
||||
--extra-cflags=-fno-sanitize-recover=undefined
|
||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++
|
||||
--extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined
|
||||
TARGETS: alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu s390x-softmmu
|
||||
MAKE_CHECK_ARGS: check-qtest check-tcg
|
||||
|
||||
@@ -464,9 +440,9 @@ clang-user:
|
||||
timeout: 70m
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --disable-system --enable-ubsan
|
||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --disable-system
|
||||
--target-list-exclude=alpha-linux-user,microblazeel-linux-user,aarch64_be-linux-user,i386-linux-user,m68k-linux-user,mipsn32el-linux-user,xtensaeb-linux-user
|
||||
--extra-cflags=-fno-sanitize-recover=undefined
|
||||
--extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined
|
||||
MAKE_CHECK_ARGS: check-unit check-tcg
|
||||
|
||||
# Set LD_JOBS=1 because this requires LTO and ld consumes a large amount of memory.
|
||||
@@ -507,14 +483,14 @@ check-cfi-aarch64:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
functional-cfi-aarch64:
|
||||
extends: .functional_test_job_template
|
||||
avocado-cfi-aarch64:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-cfi-aarch64
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
|
||||
build-cfi-ppc64-s390x:
|
||||
extends:
|
||||
@@ -545,14 +521,14 @@ check-cfi-ppc64-s390x:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
functional-cfi-ppc64-s390x:
|
||||
extends: .functional_test_job_template
|
||||
avocado-cfi-ppc64-s390x:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-cfi-ppc64-s390x
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
|
||||
build-cfi-x86_64:
|
||||
extends:
|
||||
@@ -579,14 +555,14 @@ check-cfi-x86_64:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
functional-cfi-x86_64:
|
||||
extends: .functional_test_job_template
|
||||
avocado-cfi-x86_64:
|
||||
extends: .avocado_test_job_template
|
||||
needs:
|
||||
- job: build-cfi-x86_64
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado check-functional
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
|
||||
tsan-build:
|
||||
extends: .native_build_job_template
|
||||
@@ -597,9 +573,6 @@ tsan-build:
|
||||
CONFIGURE_ARGS: --enable-tsan --cc=clang --cxx=clang++
|
||||
--enable-trace-backends=ust --disable-slirp
|
||||
TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
|
||||
# Remove when we switch to a distro with clang >= 18
|
||||
# https://github.com/google/sanitizers/issues/1716
|
||||
MAKE: setarch -R make
|
||||
|
||||
# gcov is a GCC features
|
||||
gcov:
|
||||
@@ -641,15 +614,12 @@ build-oss-fuzz:
|
||||
- CC="clang" CXX="clang++" CFLAGS="-fsanitize=address"
|
||||
./scripts/oss-fuzz/build.sh
|
||||
- export ASAN_OPTIONS="fast_unwind_on_malloc=0"
|
||||
- failures=0
|
||||
- for fuzzer in $(find ./build-oss-fuzz/DEST_DIR/ -executable -type f
|
||||
| grep -v slirp); do
|
||||
grep "LLVMFuzzerTestOneInput" ${fuzzer} > /dev/null 2>&1 || continue ;
|
||||
echo Testing ${fuzzer} ... ;
|
||||
"${fuzzer}" -runs=1 -seed=1 || { echo "FAILED:"" ${fuzzer} exit code is $?"; failures=$(($failures+1)); };
|
||||
"${fuzzer}" -runs=1 -seed=1 || exit 1 ;
|
||||
done
|
||||
- echo "Number of failures:"" $failures"
|
||||
- test $failures = 0
|
||||
|
||||
build-tci:
|
||||
extends: .native_build_job_template
|
||||
@@ -661,7 +631,7 @@ build-tci:
|
||||
- TARGETS="aarch64 arm hppa m68k microblaze ppc64 s390x x86_64"
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-tcg-interpreter --disable-kvm --disable-docs --disable-gtk --disable-vnc
|
||||
- ../configure --enable-tcg-interpreter --disable-docs --disable-gtk --disable-vnc
|
||||
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
|
||||
|| { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- make -j"$JOBS"
|
||||
@@ -679,9 +649,9 @@ build-tci:
|
||||
build-without-defaults:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-centos9-container
|
||||
job: amd64-centos8-container
|
||||
variables:
|
||||
IMAGE: centos9
|
||||
IMAGE: centos8
|
||||
CONFIGURE_ARGS:
|
||||
--without-default-devices
|
||||
--without-default-features
|
||||
@@ -689,7 +659,8 @@ build-without-defaults:
|
||||
--disable-pie
|
||||
--disable-qom-cast-debug
|
||||
--disable-strip
|
||||
--target-list-exclude=aarch64-softmmu,microblaze-softmmu,mips64-softmmu,mipsel-softmmu,ppc64-softmmu,sh4el-softmmu,xtensa-softmmu,x86_64-softmmu
|
||||
TARGETS: avr-softmmu s390x-softmmu sh4-softmmu
|
||||
sparc64-softmmu hexagon-linux-user i386-linux-user s390x-linux-user
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
build-libvhost-user:
|
||||
|
||||
@@ -19,9 +19,10 @@ cwd = os.getcwd()
|
||||
reponame = os.path.basename(cwd)
|
||||
repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
|
||||
|
||||
print(f"adding upstream git repo @ {repourl}")
|
||||
subprocess.check_call(["git", "remote", "add", "check-dco", repourl])
|
||||
subprocess.check_call(["git", "fetch", "check-dco", "master"])
|
||||
subprocess.check_call(["git", "fetch", "check-dco", "master"],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
ancestor = subprocess.check_output(["git", "merge-base",
|
||||
"check-dco/master", "HEAD"],
|
||||
@@ -78,10 +79,7 @@ of Origin 1.1 (DCO):
|
||||
|
||||
To indicate acceptance of the DCO every commit must have a tag
|
||||
|
||||
Signed-off-by: YOUR NAME <EMAIL>
|
||||
|
||||
where "YOUR NAME" is your commonly known identity in the context
|
||||
of the community.
|
||||
Signed-off-by: REAL NAME <EMAIL>
|
||||
|
||||
This can be achieved by passing the "-s" flag to the "git commit" command.
|
||||
|
||||
|
||||
@@ -19,12 +19,13 @@ cwd = os.getcwd()
|
||||
reponame = os.path.basename(cwd)
|
||||
repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
|
||||
|
||||
print(f"adding upstream git repo @ {repourl}")
|
||||
# GitLab CI environment does not give us any direct info about the
|
||||
# base for the user's branch. We thus need to figure out a common
|
||||
# ancestor between the user's branch and current git master.
|
||||
subprocess.check_call(["git", "remote", "add", "check-patch", repourl])
|
||||
subprocess.check_call(["git", "fetch", "check-patch", "master"])
|
||||
subprocess.check_call(["git", "fetch", "check-patch", "master"],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
ancestor = subprocess.check_output(["git", "merge-base",
|
||||
"check-patch/master", "HEAD"],
|
||||
|
||||
+61
-8
@@ -13,7 +13,7 @@
|
||||
.cirrus_build_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:latest
|
||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
||||
needs: []
|
||||
# 20 mins larger than "timeout_in" in cirrus/build.yml
|
||||
# as there's often a 5-10 minute delay before Cirrus CI
|
||||
@@ -46,30 +46,83 @@
|
||||
variables:
|
||||
QEMU_JOB_CIRRUS: 1
|
||||
|
||||
x64-freebsd-14-build:
|
||||
x64-freebsd-13-build:
|
||||
extends: .cirrus_build_job
|
||||
variables:
|
||||
NAME: freebsd-14
|
||||
NAME: freebsd-13
|
||||
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
||||
CIRRUS_VM_IMAGE_SELECTOR: image_family
|
||||
CIRRUS_VM_IMAGE_NAME: freebsd-14-2
|
||||
CIRRUS_VM_IMAGE_NAME: freebsd-13-3
|
||||
CIRRUS_VM_CPUS: 8
|
||||
CIRRUS_VM_RAM: 8G
|
||||
UPDATE_COMMAND: pkg update; pkg upgrade -y
|
||||
INSTALL_COMMAND: pkg install -y
|
||||
CONFIGURE_ARGS: --target-list-exclude=arm-softmmu,i386-softmmu,microblaze-softmmu,mips64el-softmmu,mipsel-softmmu,mips-softmmu,ppc-softmmu,sh4eb-softmmu,xtensa-softmmu
|
||||
TEST_TARGETS: check
|
||||
|
||||
aarch64-macos-build:
|
||||
aarch64-macos-13-base-build:
|
||||
extends: .cirrus_build_job
|
||||
variables:
|
||||
NAME: macos-13
|
||||
CIRRUS_VM_INSTANCE_TYPE: macos_instance
|
||||
CIRRUS_VM_IMAGE_SELECTOR: image
|
||||
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-ventura-base:latest
|
||||
CIRRUS_VM_CPUS: 12
|
||||
CIRRUS_VM_RAM: 24G
|
||||
UPDATE_COMMAND: brew update
|
||||
INSTALL_COMMAND: brew install
|
||||
PATH_EXTRA: /opt/homebrew/ccache/libexec:/opt/homebrew/gettext/bin
|
||||
PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
|
||||
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
||||
|
||||
aarch64-macos-14-base-build:
|
||||
extends: .cirrus_build_job
|
||||
variables:
|
||||
NAME: macos-14
|
||||
CIRRUS_VM_INSTANCE_TYPE: macos_instance
|
||||
CIRRUS_VM_IMAGE_SELECTOR: image
|
||||
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-runner:sonoma
|
||||
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-sonoma-base:latest
|
||||
CIRRUS_VM_CPUS: 12
|
||||
CIRRUS_VM_RAM: 24G
|
||||
UPDATE_COMMAND: brew update
|
||||
INSTALL_COMMAND: brew install
|
||||
PATH_EXTRA: /opt/homebrew/ccache/libexec:/opt/homebrew/gettext/bin
|
||||
PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
|
||||
CONFIGURE_ARGS: --target-list-exclude=arm-softmmu,i386-softmmu,microblazeel-softmmu,mips64-softmmu,mipsel-softmmu,mips-softmmu,ppc-softmmu,sh4-softmmu,xtensaeb-softmmu
|
||||
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
||||
QEMU_JOB_OPTIONAL: 1
|
||||
|
||||
|
||||
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
|
||||
.cirrus_kvm_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
||||
needs: []
|
||||
timeout: 80m
|
||||
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
|
||||
variables:
|
||||
QEMU_JOB_CIRRUS: 1
|
||||
QEMU_JOB_OPTIONAL: 1
|
||||
|
||||
|
||||
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
|
||||
|
||||
@@ -26,7 +26,7 @@ build_task:
|
||||
- git clone --depth 100 "$CI_REPOSITORY_URL" .
|
||||
- git fetch origin "$CI_COMMIT_REF_NAME"
|
||||
- git reset --hard "$CI_COMMIT_SHA"
|
||||
step_script:
|
||||
build_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror $CONFIGURE_ARGS
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# THIS FILE WAS AUTO-GENERATED
|
||||
#
|
||||
# $ lcitool variables freebsd-13 qemu
|
||||
#
|
||||
# https://gitlab.com/libvirt/libvirt-ci
|
||||
|
||||
CCACHE='/usr/local/bin/ccache'
|
||||
CPAN_PKGS=''
|
||||
CROSS_PKGS=''
|
||||
MAKE='/usr/local/bin/gmake'
|
||||
NINJA='/usr/local/bin/ninja'
|
||||
PACKAGING_COMMAND='pkg'
|
||||
PIP3='/usr/local/bin/pip-3.8'
|
||||
PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-tomli py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd'
|
||||
PYPI_PKGS=''
|
||||
PYTHON='/usr/local/bin/python3'
|
||||
@@ -1,16 +0,0 @@
|
||||
# THIS FILE WAS AUTO-GENERATED
|
||||
#
|
||||
# $ lcitool variables freebsd-14 qemu
|
||||
#
|
||||
# https://gitlab.com/libvirt/libvirt-ci
|
||||
|
||||
CCACHE='/usr/local/bin/ccache'
|
||||
CPAN_PKGS=''
|
||||
CROSS_PKGS=''
|
||||
MAKE='/usr/local/bin/gmake'
|
||||
NINJA='/usr/local/bin/ninja'
|
||||
PACKAGING_COMMAND='pkg'
|
||||
PIP3='/usr/local/bin/pip'
|
||||
PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk-vnc gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py311-numpy py311-pillow py311-pip py311-pyyaml py311-sphinx py311-sphinx_rtd_theme py311-tomli python3 rpm2cpio rust rust-bindgen-cli sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd'
|
||||
PYPI_PKGS=''
|
||||
PYTHON='/usr/local/bin/python3'
|
||||
@@ -0,0 +1,31 @@
|
||||
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 meson
|
||||
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
|
||||
@@ -0,0 +1,16 @@
|
||||
# THIS FILE WAS AUTO-GENERATED
|
||||
#
|
||||
# $ lcitool variables macos-13 qemu
|
||||
#
|
||||
# https://gitlab.com/libvirt/libvirt-ci
|
||||
|
||||
CCACHE='/opt/homebrew/bin/ccache'
|
||||
CPAN_PKGS=''
|
||||
CROSS_PKGS=''
|
||||
MAKE='/opt/homebrew/bin/gmake'
|
||||
NINJA='/opt/homebrew/bin/ninja'
|
||||
PACKAGING_COMMAND='brew'
|
||||
PIP3='/opt/homebrew/bin/pip3'
|
||||
PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd'
|
||||
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli'
|
||||
PYTHON='/opt/homebrew/bin/python3'
|
||||
@@ -11,6 +11,6 @@ MAKE='/opt/homebrew/bin/gmake'
|
||||
NINJA='/opt/homebrew/bin/ninja'
|
||||
PACKAGING_COMMAND='brew'
|
||||
PIP3='/opt/homebrew/bin/pip3'
|
||||
PKGS='bash bc bindgen bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 gtk-vnc jemalloc jpeg-turbo json-c libcbor libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio rust sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd'
|
||||
PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd'
|
||||
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli'
|
||||
PYTHON='/opt/homebrew/bin/python3'
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
include:
|
||||
- local: '/.gitlab-ci.d/container-template.yml'
|
||||
|
||||
amd64-centos9-container:
|
||||
amd64-centos8-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: centos9
|
||||
NAME: centos8
|
||||
|
||||
amd64-fedora-container:
|
||||
extends: .container_job_template
|
||||
|
||||
@@ -22,6 +22,12 @@ arm64-debian-cross-container:
|
||||
variables:
|
||||
NAME: debian-arm64-cross
|
||||
|
||||
armel-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
variables:
|
||||
NAME: debian-armel-cross
|
||||
|
||||
armhf-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
@@ -90,6 +96,11 @@ xtensa-debian-cross-container:
|
||||
variables:
|
||||
NAME: debian-xtensa-cross
|
||||
|
||||
cris-fedora-cross-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: fedora-cris-cross
|
||||
|
||||
win64-fedora-cross-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
|
||||
@@ -27,9 +27,3 @@ python-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: python
|
||||
|
||||
amd64-fedora-rust-nightly-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: fedora-rust-nightly
|
||||
allow_failure: true
|
||||
|
||||
@@ -8,12 +8,6 @@
|
||||
key: "$CI_JOB_NAME"
|
||||
when: always
|
||||
timeout: 80m
|
||||
before_script:
|
||||
- source scripts/ci/gitlab-ci-section
|
||||
- section_start setup "Pre-script setup"
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
- cat /packages.txt
|
||||
- section_end setup
|
||||
script:
|
||||
- export CCACHE_BASEDIR="$(pwd)"
|
||||
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
|
||||
@@ -22,30 +16,18 @@
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ccache --zero-stats
|
||||
- section_start configure "Running configure"
|
||||
- ../configure --enable-werror --disable-docs --enable-fdt=system
|
||||
--disable-user $QEMU_CONFIGURE_OPTS $EXTRA_CONFIGURE_OPTS
|
||||
--target-list-exclude="arm-softmmu
|
||||
--target-list-exclude="arm-softmmu cris-softmmu
|
||||
i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu
|
||||
mips64-softmmu ppc-softmmu riscv32-softmmu sh4-softmmu
|
||||
sparc-softmmu xtensa-softmmu $CROSS_SKIP_TARGETS"
|
||||
- section_end configure
|
||||
- section_start build "Building QEMU"
|
||||
- make -j"$JOBS" all check-build
|
||||
- section_end build
|
||||
- section_start test "Running tests"
|
||||
- if test -n "$MAKE_CHECK_ARGS";
|
||||
then
|
||||
$MAKE -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||
fi
|
||||
- section_end test
|
||||
- section_start installer "Building the installer"
|
||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||
- if grep -q "EXESUF=.exe" config-host.mak;
|
||||
then make installer;
|
||||
version="$(git describe --match v[0-9]* 2>/dev/null || git rev-parse --short HEAD)";
|
||||
mv -v qemu-setup*.exe qemu-setup-${version}.exe;
|
||||
fi
|
||||
- section_end installer
|
||||
- ccache --show-stats
|
||||
|
||||
# Job to cross-build specific accelerators.
|
||||
@@ -57,14 +39,11 @@
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:$QEMU_CI_CONTAINER_TAG
|
||||
timeout: 60m
|
||||
timeout: 30m
|
||||
cache:
|
||||
paths:
|
||||
- ccache/
|
||||
key: "$CI_JOB_NAME"
|
||||
before_script:
|
||||
- source scripts/ci/gitlab-ci-section
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
script:
|
||||
- export CCACHE_BASEDIR="$(pwd)"
|
||||
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
|
||||
@@ -72,19 +51,9 @@
|
||||
- export PATH="$CCACHE_WRAPPERSDIR:$PATH"
|
||||
- mkdir build
|
||||
- cd build
|
||||
- section_start configure "Running configure"
|
||||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-tools --enable-${ACCEL:-kvm} $EXTRA_CONFIGURE_OPTS
|
||||
- section_end configure
|
||||
- section_start build "Building QEMU"
|
||||
- make -j"$JOBS" all check-build
|
||||
- section_end build
|
||||
- section_start test "Running tests"
|
||||
- if test -n "$MAKE_CHECK_ARGS";
|
||||
then
|
||||
$MAKE -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||
fi
|
||||
- section_end test
|
||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||
|
||||
.cross_user_build_job:
|
||||
extends: .base_job_template
|
||||
@@ -94,31 +63,18 @@
|
||||
paths:
|
||||
- ccache/
|
||||
key: "$CI_JOB_NAME"
|
||||
before_script:
|
||||
- source scripts/ci/gitlab-ci-section
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
script:
|
||||
- export CCACHE_BASEDIR="$(pwd)"
|
||||
- export CCACHE_DIR="$CCACHE_BASEDIR/ccache"
|
||||
- export CCACHE_MAXSIZE="500M"
|
||||
- mkdir build
|
||||
- cd build
|
||||
- section_start configure "Running configure"
|
||||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-system --target-list-exclude="aarch64_be-linux-user
|
||||
alpha-linux-user m68k-linux-user microblazeel-linux-user
|
||||
or1k-linux-user ppc-linux-user sparc-linux-user
|
||||
alpha-linux-user cris-linux-user m68k-linux-user microblazeel-linux-user
|
||||
nios2-linux-user or1k-linux-user ppc-linux-user sparc-linux-user
|
||||
xtensa-linux-user $CROSS_SKIP_TARGETS"
|
||||
- section_end configure
|
||||
- section_start build "Building QEMU"
|
||||
- make -j"$JOBS" all check-build
|
||||
- section_end build
|
||||
- section_start test "Running tests"
|
||||
- if test -n "$MAKE_CHECK_ARGS";
|
||||
then
|
||||
$MAKE -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||
fi
|
||||
- section_end test
|
||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||
|
||||
# We can still run some tests on some of our cross build jobs. They can add this
|
||||
# template to their extends to save the build logs and test results
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
include:
|
||||
- local: '/.gitlab-ci.d/crossbuild-template.yml'
|
||||
|
||||
cross-armel-user:
|
||||
extends: .cross_user_build_job
|
||||
needs:
|
||||
job: armel-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-armel-cross
|
||||
|
||||
cross-armhf-user:
|
||||
extends: .cross_user_build_job
|
||||
needs:
|
||||
@@ -30,17 +37,6 @@ cross-arm64-kvm-only:
|
||||
IMAGE: debian-arm64-cross
|
||||
EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features
|
||||
|
||||
cross-i686-system:
|
||||
extends:
|
||||
- .cross_system_build_job
|
||||
- .cross_test_artifacts
|
||||
needs:
|
||||
job: i686-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-i686-cross
|
||||
EXTRA_CONFIGURE_OPTS: --disable-kvm
|
||||
MAKE_CHECK_ARGS: check-qtest
|
||||
|
||||
cross-i686-user:
|
||||
extends:
|
||||
- .cross_user_build_job
|
||||
@@ -61,12 +57,8 @@ cross-i686-tci:
|
||||
variables:
|
||||
IMAGE: debian-i686-cross
|
||||
ACCEL: tcg-interpreter
|
||||
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins --disable-kvm
|
||||
# Force tests to run with reduced parallelism, to see whether this
|
||||
# reduces the flakiness of this CI job. The CI
|
||||
# environment by default shows us 8 CPUs and so we
|
||||
# would otherwise be using a parallelism of 9.
|
||||
MAKE_CHECK_ARGS: check check-tcg -j2
|
||||
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins
|
||||
MAKE_CHECK_ARGS: check check-tcg
|
||||
|
||||
cross-mipsel-system:
|
||||
extends: .cross_system_build_job
|
||||
@@ -175,7 +167,7 @@ cross-win64-system:
|
||||
IMAGE: fedora-win64-cross
|
||||
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal --disable-plugins
|
||||
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu
|
||||
m68k-softmmu microblazeel-softmmu
|
||||
m68k-softmmu microblazeel-softmmu nios2-softmmu
|
||||
or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu
|
||||
tricore-softmmu xtensaeb-softmmu
|
||||
artifacts:
|
||||
|
||||
@@ -10,14 +10,13 @@
|
||||
# gitlab-runner. To avoid problems that gitlab-runner can cause while
|
||||
# reusing the GIT repository, let's enable the clone strategy, which
|
||||
# guarantees a fresh repository on each job run.
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
|
||||
# All custom runners can extend this template to upload the testlog
|
||||
# data as an artifact and also feed the junit report
|
||||
.custom_runner_template:
|
||||
extends: .base_job_template
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
GIT_FETCH_EXTRA_FLAGS: --no-tags --prune --quiet
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
expire_in: 7 days
|
||||
@@ -29,6 +28,7 @@
|
||||
junit: build/meson-logs/testlog.junit.xml
|
||||
|
||||
include:
|
||||
- local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-s390x.yml'
|
||||
- local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml'
|
||||
- local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml'
|
||||
- local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml'
|
||||
- local: '/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml'
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# All centos-stream-8 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/stream/8/build-environment.yml task
|
||||
# "Installation of extra packages to build QEMU"
|
||||
|
||||
centos-stream-8-x86_64:
|
||||
extends: .custom_runner_template
|
||||
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"
|
||||
before_script:
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../scripts/ci/org.centos/stream/8/x86_64/configure
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make -j"$JOBS"
|
||||
- make NINJA=":" check check-avocado
|
||||
+23
-21
@@ -1,32 +1,34 @@
|
||||
# All ubuntu-22.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/ubuntu/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 22.04"
|
||||
# All ubuntu-20.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 20.04/20.04"
|
||||
|
||||
ubuntu-22.04-s390x-all-linux:
|
||||
ubuntu-20.04-s390x-all-linux-static:
|
||||
extends: .custom_runner_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- ubuntu_20.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 --disable-system --disable-tools --disable-docs
|
||||
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync check-tcg
|
||||
- make --output-sync -j`nproc` check
|
||||
|
||||
ubuntu-22.04-s390x-all-system:
|
||||
ubuntu-20.04-s390x-all:
|
||||
extends: .custom_runner_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
timeout: 75m
|
||||
rules:
|
||||
@@ -35,17 +37,17 @@ ubuntu-22.04-s390x-all-system:
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-user
|
||||
- ../configure --disable-libssh
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check
|
||||
|
||||
ubuntu-22.04-s390x-alldbg:
|
||||
ubuntu-20.04-s390x-alldbg:
|
||||
extends: .custom_runner_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
@@ -57,18 +59,18 @@ ubuntu-22.04-s390x-alldbg:
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug
|
||||
- ../configure --enable-debug --disable-libssh
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make clean
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check
|
||||
|
||||
ubuntu-22.04-s390x-clang:
|
||||
ubuntu-20.04-s390x-clang:
|
||||
extends: .custom_runner_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
@@ -80,16 +82,16 @@ ubuntu-22.04-s390x-clang:
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --cc=clang --cxx=clang++ --enable-ubsan
|
||||
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check
|
||||
|
||||
ubuntu-22.04-s390x-tci:
|
||||
ubuntu-20.04-s390x-tci:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
@@ -101,16 +103,16 @@ ubuntu-22.04-s390x-tci:
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-tcg-interpreter
|
||||
- ../configure --disable-libssh --enable-tcg-interpreter
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc`
|
||||
|
||||
ubuntu-22.04-s390x-notcg:
|
||||
ubuntu-20.04-s390x-notcg:
|
||||
extends: .custom_runner_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
@@ -122,7 +124,7 @@ ubuntu-22.04-s390x-notcg:
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-tcg
|
||||
- ../configure --disable-libssh --disable-tcg
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check
|
||||
@@ -1,5 +1,5 @@
|
||||
# All ubuntu-22.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/ubuntu/build-environment.yml task
|
||||
# setup by the scripts/ci/setup/qemu/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 22.04"
|
||||
|
||||
ubuntu-22.04-aarch32-all:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# All ubuntu-22.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/ubuntu/build-environment.yml task
|
||||
# setup by the scripts/ci/setup/qemu/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 22.04"
|
||||
|
||||
ubuntu-22.04-aarch64-all-linux-static:
|
||||
@@ -103,7 +103,7 @@ ubuntu-22.04-aarch64-clang:
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-ubsan
|
||||
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc --ignore=40`
|
||||
- make --output-sync -j`nproc --ignore=40` check
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
msys2-64bit:
|
||||
extends: .base_job_template
|
||||
tags:
|
||||
- saas-windows-medium-amd64
|
||||
- shared-windows
|
||||
- windows
|
||||
- windows-1809
|
||||
cache:
|
||||
key: "$CI_JOB_NAME"
|
||||
paths:
|
||||
@@ -17,9 +19,15 @@ msys2-64bit:
|
||||
# This feature doesn't (currently) work with PowerShell, it stops
|
||||
# the echo'ing of commands being run and doesn't show any timing
|
||||
FF_SCRIPT_SECTIONS: 0
|
||||
CONFIGURE_ARGS: --disable-system --enable-tools -Ddebug=false -Doptimization=0
|
||||
# The Windows git is a bit older so override the default
|
||||
GIT_FETCH_EXTRA_FLAGS: --no-tags --prune --quiet
|
||||
# do not remove "--without-default-devices"!
|
||||
# commit 9f8e6cad65a6 ("gitlab-ci: Speed up the msys2-64bit job by using --without-default-devices"
|
||||
# changed to compile QEMU with the --without-default-devices switch
|
||||
# for this job, because otherwise the build could not complete within
|
||||
# the project timeout.
|
||||
CONFIGURE_ARGS: --target-list=x86_64-softmmu --without-default-devices -Ddebug=false -Doptimization=0
|
||||
# qTests don't run successfully with "--without-default-devices",
|
||||
# so let's exclude the qtests from CI for now.
|
||||
TEST_ARGS: --no-suite qtest
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
expire_in: 7 days
|
||||
@@ -76,19 +84,35 @@ msys2-64bit:
|
||||
bison diffutils flex
|
||||
git grep make sed
|
||||
mingw-w64-x86_64-binutils
|
||||
mingw-w64-x86_64-capstone
|
||||
mingw-w64-x86_64-ccache
|
||||
mingw-w64-x86_64-curl
|
||||
mingw-w64-x86_64-cyrus-sasl
|
||||
mingw-w64-x86_64-dtc
|
||||
mingw-w64-x86_64-gcc
|
||||
mingw-w64-x86_64-glib2
|
||||
mingw-w64-x86_64-gnutls
|
||||
mingw-w64-x86_64-gtk3
|
||||
mingw-w64-x86_64-libgcrypt
|
||||
mingw-w64-x86_64-libjpeg-turbo
|
||||
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-lzo2
|
||||
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-spice
|
||||
mingw-w64-x86_64-usbredir
|
||||
mingw-w64-x86_64-zstd"
|
||||
- Write-Output "Running build at $(Get-Date -Format u)"
|
||||
- $env:JOBS = $(.\msys64\usr\bin\bash -lc nproc)
|
||||
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||
- $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
|
||||
- $env:CCACHE_BASEDIR = "$env:CI_PROJECT_DIR"
|
||||
@@ -99,8 +123,8 @@ msys2-64bit:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ..\msys64\usr\bin\bash -lc "ccache --zero-stats"
|
||||
- ..\msys64\usr\bin\bash -lc "../configure $CONFIGURE_ARGS"
|
||||
- ..\msys64\usr\bin\bash -lc "make -j$env:JOBS"
|
||||
- ..\msys64\usr\bin\bash -lc "../configure --enable-fdt=system $CONFIGURE_ARGS"
|
||||
- ..\msys64\usr\bin\bash -lc "make"
|
||||
- ..\msys64\usr\bin\bash -lc "make check MTESTARGS='$TEST_ARGS' || { cat meson-logs/testlog.txt; exit 1; } ;"
|
||||
- ..\msys64\usr\bin\bash -lc "ccache --show-stats"
|
||||
- Write-Output "Finished build at $(Get-Date -Format u)"
|
||||
|
||||
@@ -75,8 +75,6 @@ Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
|
||||
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
|
||||
Ani Sinha <anisinha@redhat.com> <ani@anisinha.ca>
|
||||
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
|
||||
Brian Cain <brian.cain@oss.qualcomm.com> <bcain@quicinc.com>
|
||||
Brian Cain <brian.cain@oss.qualcomm.com> <quic_bcain@quicinc.com>
|
||||
Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
|
||||
Damien Hedde <damien.hedde@dahe.fr> <damien.hedde@greensocs.com>
|
||||
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
|
||||
@@ -102,7 +100,6 @@ Philippe Mathieu-Daudé <philmd@linaro.org> <f4bug@amsat.org>
|
||||
Philippe Mathieu-Daudé <philmd@linaro.org> <philmd@redhat.com>
|
||||
Philippe Mathieu-Daudé <philmd@linaro.org> <philmd@fungible.com>
|
||||
Roman Bolshakov <rbolshakov@ddn.com> <r.bolshakov@yadro.com>
|
||||
Sriram Yagnaraman <sriram.yagnaraman@ericsson.com> <sriram.yagnaraman@est.tech>
|
||||
Stefan Brankovic <stefan.brankovic@syrmia.com> <stefan.brankovic@rt-rk.com.com>
|
||||
Stefan Weil <sw@weilnetz.de> Stefan Weil <stefan@weilnetz.de>
|
||||
Taylor Simpson <ltaylorsimpson@gmail.com> <tsimpson@quicinc.com>
|
||||
|
||||
+24
-20
@@ -1,5 +1,5 @@
|
||||
os: linux
|
||||
dist: jammy
|
||||
dist: focal
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
@@ -7,11 +7,13 @@ cache:
|
||||
# There is one cache per branch and compiler version.
|
||||
# characteristics of each job are used to identify the cache:
|
||||
# - OS name (currently only linux)
|
||||
# - OS distribution (e.g. "jammy" for Linux)
|
||||
# - OS distribution (for Linux, bionic or focal)
|
||||
# - Names and values of visible environment variables set in .travis.yml or Settings panel
|
||||
timeout: 1200
|
||||
ccache: true
|
||||
pip: true
|
||||
directories:
|
||||
- $HOME/avocado/data/cache
|
||||
|
||||
|
||||
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
|
||||
@@ -33,7 +35,7 @@ env:
|
||||
- TEST_BUILD_CMD=""
|
||||
- TEST_CMD="make check V=1"
|
||||
# This is broadly a list of "mainline" system targets which have support across the major distros
|
||||
- MAIN_SYSTEM_TARGETS="aarch64-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
|
||||
- MAIN_SOFTMMU_TARGETS="aarch64-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
|
||||
- CCACHE_SLOPPINESS="include_file_ctime,include_file_mtime"
|
||||
- CCACHE_MAXSIZE=1G
|
||||
- G_MESSAGES_DEBUG=error
|
||||
@@ -81,6 +83,7 @@ jobs:
|
||||
|
||||
- name: "[aarch64] GCC check-tcg"
|
||||
arch: arm64
|
||||
dist: focal
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
@@ -106,17 +109,17 @@ jobs:
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- ninja-build
|
||||
- python3-tomli
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --enable-fdt=system
|
||||
--target-list=${MAIN_SYSTEM_TARGETS} --cxx=/bin/false"
|
||||
--target-list=${MAIN_SOFTMMU_TARGETS} --cxx=/bin/false"
|
||||
- UNRELIABLE=true
|
||||
|
||||
- name: "[ppc64] Clang check-tcg"
|
||||
- name: "[ppc64] GCC check-tcg"
|
||||
arch: ppc64le
|
||||
compiler: clang
|
||||
dist: focal
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
@@ -142,7 +145,6 @@ jobs:
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- ninja-build
|
||||
- python3-tomli
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
env:
|
||||
@@ -152,6 +154,7 @@ jobs:
|
||||
|
||||
- name: "[s390x] GCC check-tcg"
|
||||
arch: s390x
|
||||
dist: focal
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
@@ -177,13 +180,13 @@ jobs:
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- ninja-build
|
||||
- python3-tomli
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers
|
||||
--target-list=hppa-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
|
||||
- CONFIG="--disable-containers --enable-fdt=system
|
||||
--target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
|
||||
- UNRELIABLE=true
|
||||
script:
|
||||
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
|
||||
- |
|
||||
@@ -194,9 +197,9 @@ jobs:
|
||||
$(exit $BUILD_RC);
|
||||
fi
|
||||
|
||||
- name: "[s390x] Clang (other-system)"
|
||||
- name: "[s390x] GCC (other-system)"
|
||||
arch: s390x
|
||||
compiler: clang
|
||||
dist: focal
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
@@ -217,16 +220,17 @@ jobs:
|
||||
- libsnappy-dev
|
||||
- libzstd-dev
|
||||
- nettle-dev
|
||||
- xfslibs-dev
|
||||
- ninja-build
|
||||
- python3-tomli
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
env:
|
||||
- CONFIG="--disable-containers --audio-drv-list=sdl --disable-user
|
||||
--target-list=arm-softmmu,avr-softmmu,microblaze-softmmu,sh4eb-softmmu,sparc64-softmmu,xtensaeb-softmmu"
|
||||
- CONFIG="--disable-containers --enable-fdt=system --audio-drv-list=sdl
|
||||
--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
|
||||
|
||||
- name: "[s390x] GCC (user)"
|
||||
arch: s390x
|
||||
dist: focal
|
||||
addons:
|
||||
apt_packages:
|
||||
- libgcrypt20-dev
|
||||
@@ -235,14 +239,13 @@ jobs:
|
||||
- ninja-build
|
||||
- flex
|
||||
- bison
|
||||
- python3-tomli
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --disable-system"
|
||||
|
||||
- name: "[s390x] Clang (disable-tcg)"
|
||||
arch: s390x
|
||||
compiler: clang
|
||||
dist: focal
|
||||
compiler: clang-10
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
@@ -268,8 +271,9 @@ jobs:
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- ninja-build
|
||||
- python3-tomli
|
||||
- clang-10
|
||||
env:
|
||||
- TEST_CMD="make check-unit"
|
||||
- CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools
|
||||
--enable-fdt=system --host-cc=clang --cxx=clang++"
|
||||
- UNRELIABLE=true
|
||||
|
||||
@@ -4,4 +4,3 @@ source accel/Kconfig
|
||||
source target/Kconfig
|
||||
source hw/Kconfig
|
||||
source semihosting/Kconfig
|
||||
source rust/Kconfig
|
||||
|
||||
+3
-12
@@ -5,12 +5,6 @@
|
||||
config LINUX
|
||||
bool
|
||||
|
||||
config LIBCBOR
|
||||
bool
|
||||
|
||||
config GNUTLS
|
||||
bool
|
||||
|
||||
config OPENGL
|
||||
bool
|
||||
|
||||
@@ -29,9 +23,6 @@ config IVSHMEM
|
||||
config TPM
|
||||
bool
|
||||
|
||||
config FDT
|
||||
bool
|
||||
|
||||
config VHOST_USER
|
||||
bool
|
||||
|
||||
@@ -44,6 +35,9 @@ config VHOST_KERNEL
|
||||
config VIRTFS
|
||||
bool
|
||||
|
||||
config PVRDMA
|
||||
bool
|
||||
|
||||
config MULTIPROCESS_ALLOWED
|
||||
bool
|
||||
imply MULTIPROCESS
|
||||
@@ -58,6 +52,3 @@ config VFIO_USER_SERVER_ALLOWED
|
||||
|
||||
config HV_BALLOON_POSSIBLE
|
||||
bool
|
||||
|
||||
config HAVE_RUST
|
||||
bool
|
||||
|
||||
+217
-250
File diff suppressed because it is too large
Load Diff
@@ -78,8 +78,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)/pythondeps.toml $(SRC_PATH)/VERSION
|
||||
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/scripts/meson-buildoptions.sh $(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; \
|
||||
@@ -142,13 +141,8 @@ MAKE.n = $(findstring n,$(firstword $(filter-out --%,$(MAKEFLAGS))))
|
||||
MAKE.k = $(findstring k,$(firstword $(filter-out --%,$(MAKEFLAGS))))
|
||||
MAKE.q = $(findstring q,$(firstword $(filter-out --%,$(MAKEFLAGS))))
|
||||
MAKE.nq = $(if $(word 2, $(MAKE.n) $(MAKE.q)),nq)
|
||||
NINJAFLAGS = \
|
||||
$(if $V,-v) \
|
||||
$(if $(MAKE.n), -n) \
|
||||
$(if $(MAKE.k), -k0) \
|
||||
$(filter-out -j, \
|
||||
$(or $(filter -l% -j%, $(MAKEFLAGS)), \
|
||||
$(if $(filter --jobserver-auth=%, $(MAKEFLAGS)),, -j1))) \
|
||||
NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \
|
||||
$(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \
|
||||
-d keepdepfile
|
||||
ninja-cmd-goals = $(or $(MAKECMDGOALS), all)
|
||||
ninja-cmd-goals += $(foreach g, $(MAKECMDGOALS), $(.ninja-goals.$g))
|
||||
@@ -187,6 +181,11 @@ SUBDIR_RULES=$(foreach t, all clean distclean, $(addsuffix /$(t), $(SUBDIRS)))
|
||||
$(SUBDIR_RULES):
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" $(notdir $@),)
|
||||
|
||||
ifneq ($(filter contrib/plugins, $(SUBDIRS)),)
|
||||
.PHONY: plugins
|
||||
plugins: contrib/plugins/all
|
||||
endif
|
||||
|
||||
.PHONY: recurse-all recurse-clean
|
||||
recurse-all: $(addsuffix /all, $(SUBDIRS))
|
||||
recurse-clean: $(addsuffix /clean, $(SUBDIRS))
|
||||
@@ -302,6 +301,11 @@ help:
|
||||
$(call print-help,cscope,Generate cscope index)
|
||||
$(call print-help,sparse,Run sparse on the QEMU source)
|
||||
@echo ''
|
||||
ifneq ($(filter contrib/plugins, $(SUBDIRS)),)
|
||||
@echo 'Plugin targets:'
|
||||
$(call print-help,plugins,Build the example TCG plugins)
|
||||
@echo ''
|
||||
endif
|
||||
@echo 'Cleaning targets:'
|
||||
$(call print-help,clean,Remove most generated files but keep the config)
|
||||
$(call print-help,distclean,Remove all generated files)
|
||||
|
||||
+3
-3
@@ -82,7 +82,7 @@ guidelines set out in the `style section
|
||||
the Developers Guide.
|
||||
|
||||
Additional information on submitting patches can be found online via
|
||||
the QEMU website:
|
||||
the QEMU website
|
||||
|
||||
* `<https://wiki.qemu.org/Contribute/SubmitAPatch>`_
|
||||
* `<https://wiki.qemu.org/Contribute/TrivialPatches>`_
|
||||
@@ -102,7 +102,7 @@ requires a working 'git send-email' setup, and by default doesn't
|
||||
automate everything, so you may want to go through the above steps
|
||||
manually for once.
|
||||
|
||||
For installation instructions, please go to:
|
||||
For installation instructions, please go to
|
||||
|
||||
* `<https://github.com/stefanha/git-publish>`_
|
||||
|
||||
@@ -159,7 +159,7 @@ Contact
|
||||
=======
|
||||
|
||||
The QEMU community can be contacted in a number of ways, with the two
|
||||
main methods being email and IRC:
|
||||
main methods being email and IRC
|
||||
|
||||
* `<mailto:qemu-devel@nongnu.org>`_
|
||||
* `<https://lists.nongnu.org/mailman/listinfo/qemu-devel>`_
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/lockcnt.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
@@ -73,17 +73,19 @@ void accel_system_init_ops_interfaces(AccelClass *ac)
|
||||
g_assert(ac_name != NULL);
|
||||
|
||||
ops_name = g_strdup_printf("%s" ACCEL_OPS_SUFFIX, ac_name);
|
||||
ops = ACCEL_OPS_CLASS(module_object_class_by_name(ops_name));
|
||||
oc = module_object_class_by_name(ops_name);
|
||||
if (!oc) {
|
||||
error_report("fatal: could not load module for type '%s'", ops_name);
|
||||
exit(1);
|
||||
}
|
||||
g_free(ops_name);
|
||||
ops = ACCEL_OPS_CLASS(oc);
|
||||
/*
|
||||
* all accelerators need to define ops, providing at least a mandatory
|
||||
* non-NULL create_vcpu_thread operation.
|
||||
*/
|
||||
ops = ACCEL_OPS_CLASS(oc);
|
||||
g_assert(ops != NULL);
|
||||
if (ops->ops_init) {
|
||||
ops->ops_init(ops);
|
||||
}
|
||||
|
||||
@@ -68,6 +68,9 @@ void dummy_start_vcpu_thread(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY",
|
||||
cpu->cpu_index);
|
||||
qemu_thread_create(cpu->thread, thread_name, dummy_cpu_thread_fn, cpu,
|
||||
|
||||
+16
-18
@@ -52,8 +52,7 @@
|
||||
#include "qemu/main-loop.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "gdbstub/enums.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/hvf.h"
|
||||
#include "sysemu/hvf_int.h"
|
||||
@@ -62,6 +61,10 @@
|
||||
|
||||
HVFState *hvf_state;
|
||||
|
||||
#ifdef __aarch64__
|
||||
#define HV_VM_DEFAULT NULL
|
||||
#endif
|
||||
|
||||
/* Memory slots */
|
||||
|
||||
hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size)
|
||||
@@ -201,15 +204,15 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||
|
||||
static void do_hvf_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
|
||||
{
|
||||
if (!cpu->accel->dirty) {
|
||||
if (!cpu->vcpu_dirty) {
|
||||
hvf_get_registers(cpu);
|
||||
cpu->accel->dirty = true;
|
||||
cpu->vcpu_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void hvf_cpu_synchronize_state(CPUState *cpu)
|
||||
{
|
||||
if (!cpu->accel->dirty) {
|
||||
if (!cpu->vcpu_dirty) {
|
||||
run_on_cpu(cpu, do_hvf_cpu_synchronize_state, RUN_ON_CPU_NULL);
|
||||
}
|
||||
}
|
||||
@@ -218,7 +221,7 @@ static void do_hvf_cpu_synchronize_set_dirty(CPUState *cpu,
|
||||
run_on_cpu_data arg)
|
||||
{
|
||||
/* QEMU state is the reference, push it to HVF now and on next entry */
|
||||
cpu->accel->dirty = true;
|
||||
cpu->vcpu_dirty = true;
|
||||
}
|
||||
|
||||
static void hvf_cpu_synchronize_post_reset(CPUState *cpu)
|
||||
@@ -320,17 +323,8 @@ static int hvf_accel_init(MachineState *ms)
|
||||
int x;
|
||||
hv_return_t ret;
|
||||
HVFState *s;
|
||||
int pa_range = 36;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
|
||||
if (mc->hvf_get_physical_address_range) {
|
||||
pa_range = mc->hvf_get_physical_address_range(ms);
|
||||
if (pa_range < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = hvf_arch_vm_create(ms, (uint32_t)pa_range);
|
||||
ret = hv_vm_create(HV_VM_DEFAULT);
|
||||
assert_hvf_ok(ret);
|
||||
|
||||
s = g_new0(HVFState, 1);
|
||||
@@ -406,9 +400,9 @@ static int hvf_init_vcpu(CPUState *cpu)
|
||||
r = hv_vcpu_create(&cpu->accel->fd,
|
||||
(hv_vcpu_exit_t **)&cpu->accel->exit, NULL);
|
||||
#else
|
||||
r = hv_vcpu_create(&cpu->accel->fd, HV_VCPU_DEFAULT);
|
||||
r = hv_vcpu_create((hv_vcpuid_t *)&cpu->accel->fd, HV_VCPU_DEFAULT);
|
||||
#endif
|
||||
cpu->accel->dirty = true;
|
||||
cpu->vcpu_dirty = 1;
|
||||
assert_hvf_ok(r);
|
||||
|
||||
cpu->accel->guest_debug_enabled = false;
|
||||
@@ -469,6 +463,10 @@ static void hvf_start_vcpu_thread(CPUState *cpu)
|
||||
*/
|
||||
assert(hvf_enabled());
|
||||
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF",
|
||||
cpu->cpu_index);
|
||||
qemu_thread_create(cpu->thread, thread_name, hvf_cpu_thread_fn,
|
||||
|
||||
+29
-19
@@ -13,30 +13,40 @@
|
||||
#include "sysemu/hvf.h"
|
||||
#include "sysemu/hvf_int.h"
|
||||
|
||||
const char *hvf_return_string(hv_return_t ret)
|
||||
{
|
||||
switch (ret) {
|
||||
case HV_SUCCESS: return "HV_SUCCESS";
|
||||
case HV_ERROR: return "HV_ERROR";
|
||||
case HV_BUSY: return "HV_BUSY";
|
||||
case HV_BAD_ARGUMENT: return "HV_BAD_ARGUMENT";
|
||||
case HV_NO_RESOURCES: return "HV_NO_RESOURCES";
|
||||
case HV_NO_DEVICE: return "HV_NO_DEVICE";
|
||||
case HV_UNSUPPORTED: return "HV_UNSUPPORTED";
|
||||
case HV_DENIED: return "HV_DENIED";
|
||||
default: return "[unknown hv_return value]";
|
||||
}
|
||||
}
|
||||
|
||||
void assert_hvf_ok_impl(hv_return_t ret, const char *file, unsigned int line,
|
||||
const char *exp)
|
||||
void assert_hvf_ok(hv_return_t ret)
|
||||
{
|
||||
if (ret == HV_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
error_report("Error: %s = %s (0x%x, at %s:%u)",
|
||||
exp, hvf_return_string(ret), ret, file, line);
|
||||
switch (ret) {
|
||||
case HV_ERROR:
|
||||
error_report("Error: HV_ERROR");
|
||||
break;
|
||||
case HV_BUSY:
|
||||
error_report("Error: HV_BUSY");
|
||||
break;
|
||||
case HV_BAD_ARGUMENT:
|
||||
error_report("Error: HV_BAD_ARGUMENT");
|
||||
break;
|
||||
case HV_NO_RESOURCES:
|
||||
error_report("Error: HV_NO_RESOURCES");
|
||||
break;
|
||||
case HV_NO_DEVICE:
|
||||
error_report("Error: HV_NO_DEVICE");
|
||||
break;
|
||||
case HV_UNSUPPORTED:
|
||||
error_report("Error: HV_UNSUPPORTED");
|
||||
break;
|
||||
#if defined(MAC_OS_VERSION_11_0) && \
|
||||
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
|
||||
case HV_DENIED:
|
||||
error_report("Error: HV_DENIED");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error_report("Unknown Error");
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
|
||||
cpu->cpu_index);
|
||||
qemu_thread_create(cpu->thread, thread_name, kvm_vcpu_thread_fn,
|
||||
@@ -79,10 +82,10 @@ static bool kvm_vcpu_thread_is_idle(CPUState *cpu)
|
||||
|
||||
static bool kvm_cpus_are_resettable(void)
|
||||
{
|
||||
return !kvm_enabled() || !kvm_state->guest_state_protected;
|
||||
return !kvm_enabled() || kvm_cpu_check_are_resettable();
|
||||
}
|
||||
|
||||
#ifdef TARGET_KVM_HAVE_GUEST_DEBUG
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
static int kvm_update_guest_debug_ops(CPUState *cpu)
|
||||
{
|
||||
return kvm_update_guest_debug(cpu, 0);
|
||||
@@ -101,7 +104,7 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
ops->synchronize_state = kvm_cpu_synchronize_state;
|
||||
ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;
|
||||
|
||||
#ifdef TARGET_KVM_HAVE_GUEST_DEBUG
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
ops->update_guest_debug = kvm_update_guest_debug_ops;
|
||||
ops->supports_guest_debug = kvm_supports_guest_debug;
|
||||
ops->insert_breakpoint = kvm_insert_breakpoint;
|
||||
|
||||
+311
-661
File diff suppressed because it is too large
Load Diff
@@ -22,4 +22,5 @@ bool kvm_supports_guest_debug(void);
|
||||
int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len);
|
||||
int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len);
|
||||
void kvm_remove_all_breakpoints(CPUState *cpu);
|
||||
|
||||
#endif /* KVM_CPUS_H */
|
||||
|
||||
+6
-12
@@ -1,25 +1,21 @@
|
||||
# See docs/devel/tracing.rst for syntax documentation.
|
||||
|
||||
# kvm-all.c
|
||||
kvm_ioctl(unsigned long type, void *arg) "type 0x%lx, arg %p"
|
||||
kvm_vm_ioctl(unsigned long type, void *arg) "type 0x%lx, arg %p"
|
||||
kvm_vcpu_ioctl(int cpu_index, unsigned long type, void *arg) "cpu_index %d, type 0x%lx, arg %p"
|
||||
kvm_ioctl(int type, void *arg) "type 0x%x, arg %p"
|
||||
kvm_vm_ioctl(int type, void *arg) "type 0x%x, arg %p"
|
||||
kvm_vcpu_ioctl(int cpu_index, int type, void *arg) "cpu_index %d, type 0x%x, arg %p"
|
||||
kvm_run_exit(int cpu_index, uint32_t reason) "cpu_index %d, reason %d"
|
||||
kvm_device_ioctl(int fd, unsigned long type, void *arg) "dev fd %d, type 0x%lx, arg %p"
|
||||
kvm_device_ioctl(int fd, int type, void *arg) "dev fd %d, type 0x%x, arg %p"
|
||||
kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s"
|
||||
kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s"
|
||||
kvm_init_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
|
||||
kvm_create_vcpu(int cpu_index, unsigned long arch_cpu_id, int kvm_fd) "index: %d, id: %lu, kvm fd: %d"
|
||||
kvm_destroy_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
|
||||
kvm_park_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
|
||||
kvm_unpark_vcpu(unsigned long arch_cpu_id, const char *msg) "id: %lu %s"
|
||||
kvm_irqchip_commit_routes(void) ""
|
||||
kvm_irqchip_add_msi_route(char *name, int vector, int virq) "dev %s vector %d virq %d"
|
||||
kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d"
|
||||
kvm_irqchip_release_virq(int virq) "virq %d"
|
||||
kvm_set_ioeventfd_mmio(int fd, uint64_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%" PRIx64 " val=0x%x assign: %d size: %d match: %d"
|
||||
kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%x val=0x%x assign: %d size: %d match: %d"
|
||||
kvm_set_user_memory(uint16_t as, uint16_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, uint32_t fd, uint64_t fd_offset, int ret) "AddrSpace#%d Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " guest_memfd=%d" " guest_memfd_offset=0x%" PRIx64 " ret=%d"
|
||||
kvm_set_user_memory(uint32_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, int ret) "Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " ret=%d"
|
||||
kvm_clear_dirty_log(uint32_t slot, uint64_t start, uint32_t size) "slot#%"PRId32" start 0x%"PRIx64" size 0x%"PRIx32
|
||||
kvm_resample_fd_notify(int gsi) "gsi %d"
|
||||
kvm_dirty_ring_full(int id) "vcpu %d"
|
||||
@@ -29,11 +25,9 @@ kvm_dirty_ring_reaper(const char *s) "%s"
|
||||
kvm_dirty_ring_reap(uint64_t count, int64_t t) "reaped %"PRIu64" pages (took %"PRIi64" us)"
|
||||
kvm_dirty_ring_reaper_kick(const char *reason) "%s"
|
||||
kvm_dirty_ring_flush(int finished) "%d"
|
||||
kvm_destroy_vcpu(void) ""
|
||||
kvm_failed_get_vcpu_mmap_size(void) ""
|
||||
kvm_cpu_exec(void) ""
|
||||
kvm_interrupt_exit_request(void) ""
|
||||
kvm_io_window_exit(void) ""
|
||||
kvm_run_exit_system_event(int cpu_index, uint32_t event_type) "cpu_index %d, system_even_type %"PRIu32
|
||||
kvm_convert_memory(uint64_t start, uint64_t size, const char *msg) "start 0x%" PRIx64 " size 0x%" PRIx64 " %s"
|
||||
kvm_memory_fault(uint64_t start, uint64_t size, uint64_t flags) "start 0x%" PRIx64 " size 0x%" PRIx64 " flags 0x%" PRIx64
|
||||
kvm_slots_grow(unsigned int old, unsigned int new) "%u -> %u"
|
||||
|
||||
@@ -24,18 +24,6 @@
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
static int64_t qtest_clock_counter;
|
||||
|
||||
static int64_t qtest_get_virtual_clock(void)
|
||||
{
|
||||
return qatomic_read_i64(&qtest_clock_counter);
|
||||
}
|
||||
|
||||
static void qtest_set_virtual_clock(int64_t count)
|
||||
{
|
||||
qatomic_set_i64(&qtest_clock_counter, count);
|
||||
}
|
||||
|
||||
static int qtest_init_accel(MachineState *ms)
|
||||
{
|
||||
return 0;
|
||||
@@ -64,7 +52,6 @@ static void qtest_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
ops->create_vcpu_thread = dummy_start_vcpu_thread;
|
||||
ops->get_virtual_clock = qtest_get_virtual_clock;
|
||||
ops->set_virtual_clock = qtest_set_virtual_clock;
|
||||
};
|
||||
|
||||
static const TypeInfo qtest_accel_ops_type = {
|
||||
|
||||
@@ -129,8 +129,3 @@ bool kvm_hwpoisoned_mem(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,24 @@ void tb_flush(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void tlb_set_dirty(CPUState *cpu, vaddr vaddr)
|
||||
{
|
||||
}
|
||||
|
||||
int probe_access_flags(CPUArchState *env, vaddr addr, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool nonfault, void **phost, uintptr_t retaddr)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void *probe_access(CPUArchState *env, vaddr addr, int size,
|
||||
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
/* Handled by hardware accelerator. */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
G_NORETURN void cpu_loop_exit(CPUState *cpu)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
|
||||
@@ -14,20 +14,9 @@
|
||||
*/
|
||||
|
||||
static void atomic_trace_rmw_post(CPUArchState *env, uint64_t addr,
|
||||
uint64_t read_value_low,
|
||||
uint64_t read_value_high,
|
||||
uint64_t write_value_low,
|
||||
uint64_t write_value_high,
|
||||
MemOpIdx oi)
|
||||
{
|
||||
if (cpu_plugin_mem_cbs_enabled(env_cpu(env))) {
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr,
|
||||
read_value_low, read_value_high,
|
||||
oi, QEMU_PLUGIN_MEM_R);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr,
|
||||
write_value_low, write_value_high,
|
||||
oi, QEMU_PLUGIN_MEM_W);
|
||||
}
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_RW);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -53,14 +53,6 @@
|
||||
# error unsupported data size
|
||||
#endif
|
||||
|
||||
#if DATA_SIZE == 16
|
||||
# define VALUE_LOW(val) int128_getlo(val)
|
||||
# define VALUE_HIGH(val) int128_gethi(val)
|
||||
#else
|
||||
# define VALUE_LOW(val) val
|
||||
# define VALUE_HIGH(val) 0
|
||||
#endif
|
||||
|
||||
#if DATA_SIZE >= 4
|
||||
# define ABI_TYPE DATA_TYPE
|
||||
#else
|
||||
@@ -91,12 +83,7 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, abi_ptr addr,
|
||||
ret = qatomic_cmpxchg__nocheck(haddr, cmpv, newv);
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
VALUE_HIGH(ret),
|
||||
VALUE_LOW(newv),
|
||||
VALUE_HIGH(newv),
|
||||
oi);
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -110,12 +97,7 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, abi_ptr addr, ABI_TYPE val,
|
||||
|
||||
ret = qatomic_xchg__nocheck(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
VALUE_HIGH(ret),
|
||||
VALUE_LOW(val),
|
||||
VALUE_HIGH(val),
|
||||
oi);
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -127,12 +109,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr, \
|
||||
haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, DATA_SIZE, retaddr); \
|
||||
ret = qatomic_##X(haddr, val); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, \
|
||||
VALUE_LOW(ret), \
|
||||
VALUE_HIGH(ret), \
|
||||
VALUE_LOW(val), \
|
||||
VALUE_HIGH(val), \
|
||||
oi); \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
@@ -168,12 +145,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr, \
|
||||
cmp = qatomic_cmpxchg__nocheck(haddr, old, new); \
|
||||
} while (cmp != old); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, \
|
||||
VALUE_LOW(old), \
|
||||
VALUE_HIGH(old), \
|
||||
VALUE_LOW(xval), \
|
||||
VALUE_HIGH(xval), \
|
||||
oi); \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
return RET; \
|
||||
}
|
||||
|
||||
@@ -216,12 +188,7 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, abi_ptr addr,
|
||||
ret = qatomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
VALUE_HIGH(ret),
|
||||
VALUE_LOW(newv),
|
||||
VALUE_HIGH(newv),
|
||||
oi);
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
return BSWAP(ret);
|
||||
}
|
||||
|
||||
@@ -235,12 +202,7 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, abi_ptr addr, ABI_TYPE val,
|
||||
|
||||
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
VALUE_HIGH(ret),
|
||||
VALUE_LOW(val),
|
||||
VALUE_HIGH(val),
|
||||
oi);
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
return BSWAP(ret);
|
||||
}
|
||||
|
||||
@@ -252,12 +214,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr, \
|
||||
haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, DATA_SIZE, retaddr); \
|
||||
ret = qatomic_##X(haddr, BSWAP(val)); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, \
|
||||
VALUE_LOW(ret), \
|
||||
VALUE_HIGH(ret), \
|
||||
VALUE_LOW(val), \
|
||||
VALUE_HIGH(val), \
|
||||
oi); \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
return BSWAP(ret); \
|
||||
}
|
||||
|
||||
@@ -290,12 +247,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr, \
|
||||
ldn = qatomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \
|
||||
} while (ldo != ldn); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, \
|
||||
VALUE_LOW(old), \
|
||||
VALUE_HIGH(old), \
|
||||
VALUE_LOW(xval), \
|
||||
VALUE_HIGH(xval), \
|
||||
oi); \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
return RET; \
|
||||
}
|
||||
|
||||
@@ -329,5 +281,3 @@ GEN_ATOMIC_HELPER_FN(add_fetch, ADD, DATA_TYPE, new)
|
||||
#undef SUFFIX
|
||||
#undef DATA_SIZE
|
||||
#undef SHIFT
|
||||
#undef VALUE_LOW
|
||||
#undef VALUE_HIGH
|
||||
|
||||
+14
-22
@@ -144,16 +144,6 @@ static void init_delay_params(SyncClocks *sc, const CPUState *cpu)
|
||||
}
|
||||
#endif /* CONFIG USER ONLY */
|
||||
|
||||
bool tcg_cflags_has(CPUState *cpu, uint32_t flags)
|
||||
{
|
||||
return cpu->tcg_cflags & flags;
|
||||
}
|
||||
|
||||
void tcg_cflags_set(CPUState *cpu, uint32_t flags)
|
||||
{
|
||||
cpu->tcg_cflags |= flags;
|
||||
}
|
||||
|
||||
uint32_t curr_cflags(CPUState *cpu)
|
||||
{
|
||||
uint32_t cflags = cpu->tcg_cflags;
|
||||
@@ -378,7 +368,7 @@ static bool check_for_breakpoints_slow(CPUState *cpu, vaddr pc,
|
||||
* breakpoints are removed.
|
||||
*/
|
||||
if (match_page) {
|
||||
*cflags = (*cflags & ~CF_COUNT_MASK) | CF_NO_GOTO_TB | CF_BP_PAGE | 1;
|
||||
*cflags = (*cflags & ~CF_COUNT_MASK) | CF_NO_GOTO_TB | 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -446,6 +436,7 @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
|
||||
static inline TranslationBlock * QEMU_DISABLE_CFI
|
||||
cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
|
||||
{
|
||||
CPUArchState *env = cpu_env(cpu);
|
||||
uintptr_t ret;
|
||||
TranslationBlock *last_tb;
|
||||
const void *tb_ptr = itb->tc.ptr;
|
||||
@@ -455,7 +446,7 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
|
||||
}
|
||||
|
||||
qemu_thread_jit_execute();
|
||||
ret = tcg_qemu_tb_exec(cpu_env(cpu), tb_ptr);
|
||||
ret = tcg_qemu_tb_exec(env, tb_ptr);
|
||||
cpu->neg.can_do_io = true;
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
/*
|
||||
@@ -679,9 +670,11 @@ static inline bool cpu_handle_halt(CPUState *cpu)
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (cpu->halted) {
|
||||
const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops;
|
||||
bool leave_halt = tcg_ops->cpu_exec_halt(cpu);
|
||||
|
||||
if (!leave_halt) {
|
||||
if (tcg_ops->cpu_exec_halt) {
|
||||
tcg_ops->cpu_exec_halt(cpu);
|
||||
}
|
||||
if (!cpu_has_work(cpu)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -854,7 +847,8 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
else {
|
||||
const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops;
|
||||
|
||||
if (tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||
if (tcg_ops->cpu_exec_interrupt &&
|
||||
tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||
if (!tcg_ops->need_replay_interrupt ||
|
||||
tcg_ops->need_replay_interrupt(interrupt_request)) {
|
||||
replay_interrupt();
|
||||
@@ -904,6 +898,8 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
vaddr pc, TranslationBlock **last_tb,
|
||||
int *tb_exit)
|
||||
{
|
||||
int32_t insns_left;
|
||||
|
||||
trace_exec_tb(tb, pc);
|
||||
tb = cpu_tb_exec(cpu, tb, tb_exit);
|
||||
if (*tb_exit != TB_EXIT_REQUESTED) {
|
||||
@@ -912,7 +908,8 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
}
|
||||
|
||||
*last_tb = NULL;
|
||||
if (cpu_loop_exit_requested(cpu)) {
|
||||
insns_left = qatomic_read(&cpu->neg.icount_decr.u32);
|
||||
if (insns_left < 0) {
|
||||
/* Something asked us to stop executing chained TBs; just
|
||||
* continue round the main loop. Whatever requested the exit
|
||||
* will also have set something else (eg exit_request or
|
||||
@@ -929,7 +926,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
/* Ensure global icount has gone forward */
|
||||
icount_update(cpu);
|
||||
/* Refill decrementer and continue execution. */
|
||||
int32_t insns_left = MIN(0xffff, cpu->icount_budget);
|
||||
insns_left = MIN(0xffff, cpu->icount_budget);
|
||||
cpu->neg.icount_decr.u16.low = insns_left;
|
||||
cpu->icount_extra = cpu->icount_budget - insns_left;
|
||||
|
||||
@@ -1073,11 +1070,6 @@ bool tcg_exec_realizefn(CPUState *cpu, Error **errp)
|
||||
static bool tcg_target_initialized;
|
||||
|
||||
if (!tcg_target_initialized) {
|
||||
/* Check mandatory TCGCPUOps handlers */
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
assert(cpu->cc->tcg_ops->cpu_exec_halt);
|
||||
assert(cpu->cc->tcg_ops->cpu_exec_interrupt);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
cpu->cc->tcg_ops->initialize();
|
||||
tcg_target_initialized = true;
|
||||
}
|
||||
|
||||
+197
-147
@@ -21,16 +21,12 @@
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/page-protection.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/cputlb.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "exec/memory-internal.h"
|
||||
#include "exec/ram_addr.h"
|
||||
#include "exec/mmu-access-type.h"
|
||||
#include "exec/tlb-common.h"
|
||||
#include "exec/vaddr.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "exec/log.h"
|
||||
@@ -99,54 +95,6 @@ static inline size_t sizeof_tlb(CPUTLBDescFast *fast)
|
||||
return fast->mask + (1 << CPU_TLB_ENTRY_BITS);
|
||||
}
|
||||
|
||||
static inline uint64_t tlb_read_idx(const CPUTLBEntry *entry,
|
||||
MMUAccessType access_type)
|
||||
{
|
||||
/* Do not rearrange the CPUTLBEntry structure members. */
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_read) !=
|
||||
MMU_DATA_LOAD * sizeof(uint64_t));
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_write) !=
|
||||
MMU_DATA_STORE * sizeof(uint64_t));
|
||||
QEMU_BUILD_BUG_ON(offsetof(CPUTLBEntry, addr_code) !=
|
||||
MMU_INST_FETCH * sizeof(uint64_t));
|
||||
|
||||
#if TARGET_LONG_BITS == 32
|
||||
/* Use qatomic_read, in case of addr_write; only care about low bits. */
|
||||
const uint32_t *ptr = (uint32_t *)&entry->addr_idx[access_type];
|
||||
ptr += HOST_BIG_ENDIAN;
|
||||
return qatomic_read(ptr);
|
||||
#else
|
||||
const uint64_t *ptr = &entry->addr_idx[access_type];
|
||||
# if TCG_OVERSIZED_GUEST
|
||||
return *ptr;
|
||||
# else
|
||||
/* ofs might correspond to .addr_write, so use qatomic_read */
|
||||
return qatomic_read(ptr);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint64_t tlb_addr_write(const CPUTLBEntry *entry)
|
||||
{
|
||||
return tlb_read_idx(entry, MMU_DATA_STORE);
|
||||
}
|
||||
|
||||
/* Find the TLB index corresponding to the mmu_idx + address pair. */
|
||||
static inline uintptr_t tlb_index(CPUState *cpu, uintptr_t mmu_idx,
|
||||
vaddr addr)
|
||||
{
|
||||
uintptr_t size_mask = cpu->neg.tlb.f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS;
|
||||
|
||||
return (addr >> TARGET_PAGE_BITS) & size_mask;
|
||||
}
|
||||
|
||||
/* Find the TLB entry corresponding to the mmu_idx + address pair. */
|
||||
static inline CPUTLBEntry *tlb_entry(CPUState *cpu, uintptr_t mmu_idx,
|
||||
vaddr addr)
|
||||
{
|
||||
return &cpu->neg.tlb.f[mmu_idx].table[tlb_index(cpu, mmu_idx, addr)];
|
||||
}
|
||||
|
||||
static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
|
||||
size_t max_entries)
|
||||
{
|
||||
@@ -418,9 +366,12 @@ void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap)
|
||||
{
|
||||
tlb_debug("mmu_idx: 0x%" PRIx16 "\n", idxmap);
|
||||
|
||||
assert_cpu_is_self(cpu);
|
||||
|
||||
tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(idxmap));
|
||||
if (cpu->created && !qemu_cpu_is_self(cpu)) {
|
||||
async_run_on_cpu(cpu, tlb_flush_by_mmuidx_async_work,
|
||||
RUN_ON_CPU_HOST_INT(idxmap));
|
||||
} else {
|
||||
tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(idxmap));
|
||||
}
|
||||
}
|
||||
|
||||
void tlb_flush(CPUState *cpu)
|
||||
@@ -428,6 +379,21 @@ void tlb_flush(CPUState *cpu)
|
||||
tlb_flush_by_mmuidx(cpu, ALL_MMUIDX_BITS);
|
||||
}
|
||||
|
||||
void tlb_flush_by_mmuidx_all_cpus(CPUState *src_cpu, uint16_t idxmap)
|
||||
{
|
||||
const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work;
|
||||
|
||||
tlb_debug("mmu_idx: 0x%"PRIx16"\n", idxmap);
|
||||
|
||||
flush_all_helper(src_cpu, fn, RUN_ON_CPU_HOST_INT(idxmap));
|
||||
fn(src_cpu, RUN_ON_CPU_HOST_INT(idxmap));
|
||||
}
|
||||
|
||||
void tlb_flush_all_cpus(CPUState *src_cpu)
|
||||
{
|
||||
tlb_flush_by_mmuidx_all_cpus(src_cpu, ALL_MMUIDX_BITS);
|
||||
}
|
||||
|
||||
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, uint16_t idxmap)
|
||||
{
|
||||
const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work;
|
||||
@@ -609,12 +575,28 @@ void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr, uint16_t idxmap)
|
||||
{
|
||||
tlb_debug("addr: %016" VADDR_PRIx " mmu_idx:%" PRIx16 "\n", addr, idxmap);
|
||||
|
||||
assert_cpu_is_self(cpu);
|
||||
|
||||
/* This should already be page aligned */
|
||||
addr &= TARGET_PAGE_MASK;
|
||||
|
||||
tlb_flush_page_by_mmuidx_async_0(cpu, addr, idxmap);
|
||||
if (qemu_cpu_is_self(cpu)) {
|
||||
tlb_flush_page_by_mmuidx_async_0(cpu, addr, idxmap);
|
||||
} else if (idxmap < TARGET_PAGE_SIZE) {
|
||||
/*
|
||||
* Most targets have only a few mmu_idx. In the case where
|
||||
* we can stuff idxmap into the low TARGET_PAGE_BITS, avoid
|
||||
* allocating memory for this operation.
|
||||
*/
|
||||
async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_1,
|
||||
RUN_ON_CPU_TARGET_PTR(addr | idxmap));
|
||||
} else {
|
||||
TLBFlushPageByMMUIdxData *d = g_new(TLBFlushPageByMMUIdxData, 1);
|
||||
|
||||
/* Otherwise allocate a structure, freed by the worker. */
|
||||
d->addr = addr;
|
||||
d->idxmap = idxmap;
|
||||
async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_2,
|
||||
RUN_ON_CPU_HOST_PTR(d));
|
||||
}
|
||||
}
|
||||
|
||||
void tlb_flush_page(CPUState *cpu, vaddr addr)
|
||||
@@ -622,6 +604,46 @@ void tlb_flush_page(CPUState *cpu, vaddr addr)
|
||||
tlb_flush_page_by_mmuidx(cpu, addr, ALL_MMUIDX_BITS);
|
||||
}
|
||||
|
||||
void tlb_flush_page_by_mmuidx_all_cpus(CPUState *src_cpu, vaddr addr,
|
||||
uint16_t idxmap)
|
||||
{
|
||||
tlb_debug("addr: %016" VADDR_PRIx " mmu_idx:%"PRIx16"\n", addr, idxmap);
|
||||
|
||||
/* This should already be page aligned */
|
||||
addr &= TARGET_PAGE_MASK;
|
||||
|
||||
/*
|
||||
* Allocate memory to hold addr+idxmap only when needed.
|
||||
* See tlb_flush_page_by_mmuidx for details.
|
||||
*/
|
||||
if (idxmap < TARGET_PAGE_SIZE) {
|
||||
flush_all_helper(src_cpu, tlb_flush_page_by_mmuidx_async_1,
|
||||
RUN_ON_CPU_TARGET_PTR(addr | idxmap));
|
||||
} else {
|
||||
CPUState *dst_cpu;
|
||||
|
||||
/* Allocate a separate data block for each destination cpu. */
|
||||
CPU_FOREACH(dst_cpu) {
|
||||
if (dst_cpu != src_cpu) {
|
||||
TLBFlushPageByMMUIdxData *d
|
||||
= g_new(TLBFlushPageByMMUIdxData, 1);
|
||||
|
||||
d->addr = addr;
|
||||
d->idxmap = idxmap;
|
||||
async_run_on_cpu(dst_cpu, tlb_flush_page_by_mmuidx_async_2,
|
||||
RUN_ON_CPU_HOST_PTR(d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tlb_flush_page_by_mmuidx_async_0(src_cpu, addr, idxmap);
|
||||
}
|
||||
|
||||
void tlb_flush_page_all_cpus(CPUState *src, vaddr addr)
|
||||
{
|
||||
tlb_flush_page_by_mmuidx_all_cpus(src, addr, ALL_MMUIDX_BITS);
|
||||
}
|
||||
|
||||
void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
|
||||
vaddr addr,
|
||||
uint16_t idxmap)
|
||||
@@ -777,8 +799,6 @@ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
|
||||
{
|
||||
TLBFlushRangeData d;
|
||||
|
||||
assert_cpu_is_self(cpu);
|
||||
|
||||
/*
|
||||
* If all bits are significant, and len is small,
|
||||
* this devolves to tlb_flush_page.
|
||||
@@ -799,7 +819,14 @@ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
|
||||
d.idxmap = idxmap;
|
||||
d.bits = bits;
|
||||
|
||||
tlb_flush_range_by_mmuidx_async_0(cpu, d);
|
||||
if (qemu_cpu_is_self(cpu)) {
|
||||
tlb_flush_range_by_mmuidx_async_0(cpu, d);
|
||||
} else {
|
||||
/* Otherwise allocate a structure, freed by the worker. */
|
||||
TLBFlushRangeData *p = g_memdup(&d, sizeof(d));
|
||||
async_run_on_cpu(cpu, tlb_flush_range_by_mmuidx_async_1,
|
||||
RUN_ON_CPU_HOST_PTR(p));
|
||||
}
|
||||
}
|
||||
|
||||
void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr,
|
||||
@@ -808,6 +835,54 @@ void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr,
|
||||
tlb_flush_range_by_mmuidx(cpu, addr, TARGET_PAGE_SIZE, idxmap, bits);
|
||||
}
|
||||
|
||||
void tlb_flush_range_by_mmuidx_all_cpus(CPUState *src_cpu,
|
||||
vaddr addr, vaddr len,
|
||||
uint16_t idxmap, unsigned bits)
|
||||
{
|
||||
TLBFlushRangeData d;
|
||||
CPUState *dst_cpu;
|
||||
|
||||
/*
|
||||
* If all bits are significant, and len is small,
|
||||
* this devolves to tlb_flush_page.
|
||||
*/
|
||||
if (bits >= TARGET_LONG_BITS && len <= TARGET_PAGE_SIZE) {
|
||||
tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap);
|
||||
return;
|
||||
}
|
||||
/* If no page bits are significant, this devolves to tlb_flush. */
|
||||
if (bits < TARGET_PAGE_BITS) {
|
||||
tlb_flush_by_mmuidx_all_cpus(src_cpu, idxmap);
|
||||
return;
|
||||
}
|
||||
|
||||
/* This should already be page aligned */
|
||||
d.addr = addr & TARGET_PAGE_MASK;
|
||||
d.len = len;
|
||||
d.idxmap = idxmap;
|
||||
d.bits = bits;
|
||||
|
||||
/* Allocate a separate data block for each destination cpu. */
|
||||
CPU_FOREACH(dst_cpu) {
|
||||
if (dst_cpu != src_cpu) {
|
||||
TLBFlushRangeData *p = g_memdup(&d, sizeof(d));
|
||||
async_run_on_cpu(dst_cpu,
|
||||
tlb_flush_range_by_mmuidx_async_1,
|
||||
RUN_ON_CPU_HOST_PTR(p));
|
||||
}
|
||||
}
|
||||
|
||||
tlb_flush_range_by_mmuidx_async_0(src_cpu, d);
|
||||
}
|
||||
|
||||
void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
|
||||
vaddr addr, uint16_t idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
tlb_flush_range_by_mmuidx_all_cpus(src_cpu, addr, TARGET_PAGE_SIZE,
|
||||
idxmap, bits);
|
||||
}
|
||||
|
||||
void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
|
||||
vaddr addr,
|
||||
vaddr len,
|
||||
@@ -964,7 +1039,7 @@ static inline void tlb_set_dirty1_locked(CPUTLBEntry *tlb_entry,
|
||||
|
||||
/* update the TLB corresponding to virtual page vaddr
|
||||
so that it is no longer dirty */
|
||||
static void tlb_set_dirty(CPUState *cpu, vaddr addr)
|
||||
void tlb_set_dirty(CPUState *cpu, vaddr addr)
|
||||
{
|
||||
int mmu_idx;
|
||||
|
||||
@@ -1070,11 +1145,14 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
|
||||
" prot=%x idx=%d\n",
|
||||
addr, full->phys_addr, prot, mmu_idx);
|
||||
|
||||
read_flags = full->tlb_fill_flags;
|
||||
read_flags = 0;
|
||||
if (full->lg_page_size < TARGET_PAGE_BITS) {
|
||||
/* Repeat the MMU check and TLB fill on every access. */
|
||||
read_flags |= TLB_INVALID_MASK;
|
||||
}
|
||||
if (full->attrs.byte_swap) {
|
||||
read_flags |= TLB_BSWAP;
|
||||
}
|
||||
|
||||
is_ram = memory_region_is_ram(section->mr);
|
||||
is_romd = memory_region_is_romd(section->mr);
|
||||
@@ -1221,35 +1299,22 @@ void tlb_set_page(CPUState *cpu, vaddr addr,
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: tlb_fill_align() can trigger a resize of the TLB.
|
||||
* This means that all of the caller's prior references to the TLB table
|
||||
* (e.g. CPUTLBEntry pointers) must be discarded and looked up again
|
||||
* (e.g. via tlb_entry()).
|
||||
* Note: tlb_fill() can trigger a resize of the TLB. This means that all of the
|
||||
* caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must
|
||||
* be discarded and looked up again (e.g. via tlb_entry()).
|
||||
*/
|
||||
static bool tlb_fill_align(CPUState *cpu, vaddr addr, MMUAccessType type,
|
||||
int mmu_idx, MemOp memop, int size,
|
||||
bool probe, uintptr_t ra)
|
||||
static void tlb_fill(CPUState *cpu, vaddr addr, int size,
|
||||
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
const TCGCPUOps *ops = cpu->cc->tcg_ops;
|
||||
CPUTLBEntryFull full;
|
||||
bool ok;
|
||||
|
||||
if (ops->tlb_fill_align) {
|
||||
if (ops->tlb_fill_align(cpu, &full, addr, type, mmu_idx,
|
||||
memop, size, probe, ra)) {
|
||||
tlb_set_page_full(cpu, mmu_idx, addr, &full);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
/* Legacy behaviour is alignment before paging. */
|
||||
if (addr & ((1u << memop_alignment_bits(memop)) - 1)) {
|
||||
ops->do_unaligned_access(cpu, addr, type, mmu_idx, ra);
|
||||
}
|
||||
if (ops->tlb_fill(cpu, addr, size, type, mmu_idx, probe, ra)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assert(probe);
|
||||
return false;
|
||||
/*
|
||||
* This is not a probe, so only valid return is success; failure
|
||||
* should result in exception + longjmp to the cpu loop.
|
||||
*/
|
||||
ok = cpu->cc->tcg_ops->tlb_fill(cpu, addr, size,
|
||||
access_type, mmu_idx, false, retaddr);
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
|
||||
@@ -1364,22 +1429,22 @@ static int probe_access_internal(CPUState *cpu, vaddr addr,
|
||||
|
||||
if (!tlb_hit_page(tlb_addr, page_addr)) {
|
||||
if (!victim_tlb_hit(cpu, mmu_idx, index, access_type, page_addr)) {
|
||||
if (!tlb_fill_align(cpu, addr, access_type, mmu_idx,
|
||||
0, fault_size, nonfault, retaddr)) {
|
||||
if (!cpu->cc->tcg_ops->tlb_fill(cpu, addr, fault_size, access_type,
|
||||
mmu_idx, nonfault, retaddr)) {
|
||||
/* Non-faulting page table read failed. */
|
||||
*phost = NULL;
|
||||
*pfull = NULL;
|
||||
return TLB_INVALID_MASK;
|
||||
}
|
||||
|
||||
/* TLB resize via tlb_fill_align may have moved the entry. */
|
||||
/* TLB resize via tlb_fill may have moved the entry. */
|
||||
index = tlb_index(cpu, mmu_idx, addr);
|
||||
entry = tlb_entry(cpu, mmu_idx, addr);
|
||||
|
||||
/*
|
||||
* With PAGE_WRITE_INV, we set TLB_INVALID_MASK immediately,
|
||||
* to force the next access through tlb_fill_align. We've just
|
||||
* called tlb_fill_align, so we know that this entry *is* valid.
|
||||
* to force the next access through tlb_fill. We've just
|
||||
* called tlb_fill, so we know that this entry *is* valid.
|
||||
*/
|
||||
flags &= ~TLB_INVALID_MASK;
|
||||
}
|
||||
@@ -1391,8 +1456,9 @@ static int probe_access_internal(CPUState *cpu, vaddr addr,
|
||||
flags |= full->slow_flags[access_type];
|
||||
|
||||
/* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */
|
||||
if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY | TLB_CHECK_ALIGNED))
|
||||
|| (access_type != MMU_INST_FETCH && force_mmio)) {
|
||||
if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))
|
||||
||
|
||||
(access_type != MMU_INST_FETCH && force_mmio)) {
|
||||
*phost = NULL;
|
||||
return TLB_MMIO;
|
||||
}
|
||||
@@ -1620,17 +1686,16 @@ typedef struct MMULookupLocals {
|
||||
* mmu_lookup1: translate one page
|
||||
* @cpu: generic cpu state
|
||||
* @data: lookup parameters
|
||||
* @memop: memory operation for the access, or 0
|
||||
* @mmu_idx: virtual address context
|
||||
* @access_type: load/store/code
|
||||
* @ra: return address into tcg generated code, or 0
|
||||
*
|
||||
* Resolve the translation for the one page at @data.addr, filling in
|
||||
* the rest of @data with the results. If the translation fails,
|
||||
* tlb_fill_align will longjmp out. Return true if the softmmu tlb for
|
||||
* tlb_fill will longjmp out. Return true if the softmmu tlb for
|
||||
* @mmu_idx may have resized.
|
||||
*/
|
||||
static bool mmu_lookup1(CPUState *cpu, MMULookupPageData *data, MemOp memop,
|
||||
static bool mmu_lookup1(CPUState *cpu, MMULookupPageData *data,
|
||||
int mmu_idx, MMUAccessType access_type, uintptr_t ra)
|
||||
{
|
||||
vaddr addr = data->addr;
|
||||
@@ -1645,8 +1710,7 @@ static bool mmu_lookup1(CPUState *cpu, MMULookupPageData *data, MemOp memop,
|
||||
if (!tlb_hit(tlb_addr, addr)) {
|
||||
if (!victim_tlb_hit(cpu, mmu_idx, index, access_type,
|
||||
addr & TARGET_PAGE_MASK)) {
|
||||
tlb_fill_align(cpu, addr, access_type, mmu_idx,
|
||||
memop, data->size, false, ra);
|
||||
tlb_fill(cpu, addr, data->size, access_type, mmu_idx, ra);
|
||||
maybe_resized = true;
|
||||
index = tlb_index(cpu, mmu_idx, addr);
|
||||
entry = tlb_entry(cpu, mmu_idx, addr);
|
||||
@@ -1658,25 +1722,6 @@ static bool mmu_lookup1(CPUState *cpu, MMULookupPageData *data, MemOp memop,
|
||||
flags = tlb_addr & (TLB_FLAGS_MASK & ~TLB_FORCE_SLOW);
|
||||
flags |= full->slow_flags[access_type];
|
||||
|
||||
if (likely(!maybe_resized)) {
|
||||
/* Alignment has not been checked by tlb_fill_align. */
|
||||
int a_bits = memop_alignment_bits(memop);
|
||||
|
||||
/*
|
||||
* This alignment check differs from the one above, in that this is
|
||||
* based on the atomicity of the operation. The intended use case is
|
||||
* the ARM memory type field of each PTE, where access to pages with
|
||||
* Device memory type require alignment.
|
||||
*/
|
||||
if (unlikely(flags & TLB_CHECK_ALIGNED)) {
|
||||
int at_bits = memop_atomicity_bits(memop);
|
||||
a_bits = MAX(a_bits, at_bits);
|
||||
}
|
||||
if (unlikely(addr & ((1 << a_bits) - 1))) {
|
||||
cpu_unaligned_access(cpu, addr, access_type, mmu_idx, ra);
|
||||
}
|
||||
}
|
||||
|
||||
data->full = full;
|
||||
data->flags = flags;
|
||||
/* Compute haddr speculatively; depending on flags it might be invalid. */
|
||||
@@ -1733,6 +1778,7 @@ static void mmu_watch_or_dirty(CPUState *cpu, MMULookupPageData *data,
|
||||
static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
uintptr_t ra, MMUAccessType type, MMULookupLocals *l)
|
||||
{
|
||||
unsigned a_bits;
|
||||
bool crosspage;
|
||||
int flags;
|
||||
|
||||
@@ -1741,6 +1787,12 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
|
||||
tcg_debug_assert(l->mmu_idx < NB_MMU_MODES);
|
||||
|
||||
/* Handle CPU specific unaligned behaviour */
|
||||
a_bits = get_alignment_bits(l->memop);
|
||||
if (addr & ((1 << a_bits) - 1)) {
|
||||
cpu_unaligned_access(cpu, addr, type, l->mmu_idx, ra);
|
||||
}
|
||||
|
||||
l->page[0].addr = addr;
|
||||
l->page[0].size = memop_size(l->memop);
|
||||
l->page[1].addr = (addr + l->page[0].size - 1) & TARGET_PAGE_MASK;
|
||||
@@ -1748,7 +1800,7 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
crosspage = (addr ^ l->page[1].addr) & TARGET_PAGE_MASK;
|
||||
|
||||
if (likely(!crosspage)) {
|
||||
mmu_lookup1(cpu, &l->page[0], l->memop, l->mmu_idx, type, ra);
|
||||
mmu_lookup1(cpu, &l->page[0], l->mmu_idx, type, ra);
|
||||
|
||||
flags = l->page[0].flags;
|
||||
if (unlikely(flags & (TLB_WATCHPOINT | TLB_NOTDIRTY))) {
|
||||
@@ -1767,8 +1819,8 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
* Lookup both pages, recognizing exceptions from either. If the
|
||||
* second lookup potentially resized, refresh first CPUTLBEntryFull.
|
||||
*/
|
||||
mmu_lookup1(cpu, &l->page[0], l->memop, l->mmu_idx, type, ra);
|
||||
if (mmu_lookup1(cpu, &l->page[1], 0, l->mmu_idx, type, ra)) {
|
||||
mmu_lookup1(cpu, &l->page[0], l->mmu_idx, type, ra);
|
||||
if (mmu_lookup1(cpu, &l->page[1], l->mmu_idx, type, ra)) {
|
||||
uintptr_t index = tlb_index(cpu, l->mmu_idx, addr);
|
||||
l->page[0].full = &cpu->neg.tlb.d[l->mmu_idx].fulltlb[index];
|
||||
}
|
||||
@@ -1799,18 +1851,34 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
{
|
||||
uintptr_t mmu_idx = get_mmuidx(oi);
|
||||
MemOp mop = get_memop(oi);
|
||||
int a_bits = get_alignment_bits(mop);
|
||||
uintptr_t index;
|
||||
CPUTLBEntry *tlbe;
|
||||
vaddr tlb_addr;
|
||||
void *hostaddr;
|
||||
CPUTLBEntryFull *full;
|
||||
bool did_tlb_fill = false;
|
||||
|
||||
tcg_debug_assert(mmu_idx < NB_MMU_MODES);
|
||||
|
||||
/* Adjust the given return address. */
|
||||
retaddr -= GETPC_ADJ;
|
||||
|
||||
/* Enforce guest required alignment. */
|
||||
if (unlikely(a_bits > 0 && (addr & ((1 << a_bits) - 1)))) {
|
||||
/* ??? Maybe indicate atomic op to cpu_unaligned_access */
|
||||
cpu_unaligned_access(cpu, addr, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
}
|
||||
|
||||
/* Enforce qemu required alignment. */
|
||||
if (unlikely(addr & (size - 1))) {
|
||||
/* We get here if guest alignment was not requested,
|
||||
or was not enforced by cpu_unaligned_access above.
|
||||
We might widen the access and emulate, but for now
|
||||
mark an exception and exit the cpu loop. */
|
||||
goto stop_the_world;
|
||||
}
|
||||
|
||||
index = tlb_index(cpu, mmu_idx, addr);
|
||||
tlbe = tlb_entry(cpu, mmu_idx, addr);
|
||||
|
||||
@@ -1819,9 +1887,8 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
if (!tlb_hit(tlb_addr, addr)) {
|
||||
if (!victim_tlb_hit(cpu, mmu_idx, index, MMU_DATA_STORE,
|
||||
addr & TARGET_PAGE_MASK)) {
|
||||
tlb_fill_align(cpu, addr, MMU_DATA_STORE, mmu_idx,
|
||||
mop, size, false, retaddr);
|
||||
did_tlb_fill = true;
|
||||
tlb_fill(cpu, addr, size,
|
||||
MMU_DATA_STORE, mmu_idx, retaddr);
|
||||
index = tlb_index(cpu, mmu_idx, addr);
|
||||
tlbe = tlb_entry(cpu, mmu_idx, addr);
|
||||
}
|
||||
@@ -1835,32 +1902,15 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
* but addr_read will only be -1 if PAGE_READ was unset.
|
||||
*/
|
||||
if (unlikely(tlbe->addr_read == -1)) {
|
||||
tlb_fill_align(cpu, addr, MMU_DATA_LOAD, mmu_idx,
|
||||
0, size, false, retaddr);
|
||||
tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
|
||||
/*
|
||||
* Since we don't support reads and writes to different
|
||||
* addresses, and we do have the proper page loaded for
|
||||
* write, this shouldn't ever return.
|
||||
*/
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
/* Enforce guest required alignment, if not handled by tlb_fill_align. */
|
||||
if (!did_tlb_fill && (addr & ((1 << memop_alignment_bits(mop)) - 1))) {
|
||||
cpu_unaligned_access(cpu, addr, MMU_DATA_STORE, mmu_idx, retaddr);
|
||||
}
|
||||
|
||||
/* Enforce qemu required alignment. */
|
||||
if (unlikely(addr & (size - 1))) {
|
||||
/*
|
||||
* We get here if guest alignment was not requested, or was not
|
||||
* enforced by cpu_unaligned_access or tlb_fill_align above.
|
||||
* We might widen the access and emulate, but for now
|
||||
* mark an exception and exit the cpu loop.
|
||||
* write, this shouldn't ever return. But just in case,
|
||||
* handle via stop-the-world.
|
||||
*/
|
||||
goto stop_the_world;
|
||||
}
|
||||
|
||||
/* Collect tlb flags for read. */
|
||||
tlb_addr |= tlbe->addr_read;
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "sysemu/cpu-throttle.h"
|
||||
#include "sysemu/cpu-timers-internal.h"
|
||||
|
||||
/*
|
||||
@@ -335,8 +336,10 @@ void icount_start_warp_timer(void)
|
||||
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
|
||||
~QEMU_TIMER_ATTR_EXTERNAL);
|
||||
if (deadline < 0) {
|
||||
if (!icount_sleep) {
|
||||
warn_report_once("icount sleep disabled and no active timers");
|
||||
static bool notified;
|
||||
if (!icount_sleep && !notified) {
|
||||
warn_report("icount sleep disabled and no active timers");
|
||||
notified = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9,51 +9,18 @@
|
||||
#ifndef ACCEL_TCG_INTERNAL_COMMON_H
|
||||
#define ACCEL_TCG_INTERNAL_COMMON_H
|
||||
|
||||
#include "exec/cpu-common.h"
|
||||
#include "exec/translation-block.h"
|
||||
|
||||
extern int64_t max_delay;
|
||||
extern int64_t max_advance;
|
||||
|
||||
extern bool one_insn_per_tb;
|
||||
|
||||
/*
|
||||
* Return true if CS is not running in parallel with other cpus, either
|
||||
* because there are no other cpus or we are within an exclusive context.
|
||||
*/
|
||||
static inline bool cpu_in_serial_context(CPUState *cs)
|
||||
{
|
||||
return !tcg_cflags_has(cs, CF_PARALLEL) || cpu_in_exclusive_context(cs);
|
||||
return !(cs->tcg_cflags & CF_PARALLEL) || cpu_in_exclusive_context(cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* cpu_plugin_mem_cbs_enabled() - are plugin memory callbacks enabled?
|
||||
* @cs: CPUState pointer
|
||||
*
|
||||
* The memory callbacks are installed if a plugin has instrumented an
|
||||
* instruction for memory. This can be useful to know if you want to
|
||||
* force a slow path for a series of memory accesses.
|
||||
*/
|
||||
static inline bool cpu_plugin_mem_cbs_enabled(const CPUState *cpu)
|
||||
{
|
||||
#ifdef CONFIG_PLUGIN
|
||||
return !!cpu->neg.plugin_mem_cbs;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
TranslationBlock *tb_gen_code(CPUState *cpu, vaddr pc,
|
||||
uint64_t cs_base, uint32_t flags,
|
||||
int cflags);
|
||||
void page_init(void);
|
||||
void tb_htable_init(void);
|
||||
void tb_reset_jump(TranslationBlock *tb, int n);
|
||||
TranslationBlock *tb_link_page(TranslationBlock *tb);
|
||||
void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
uintptr_t host_pc);
|
||||
|
||||
bool tcg_exec_realizefn(CPUState *cpu, Error **errp);
|
||||
void tcg_exec_unrealizefn(CPUState *cpu);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -69,7 +69,19 @@ void tb_invalidate_phys_range_fast(ram_addr_t ram_addr,
|
||||
G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
|
||||
#endif /* CONFIG_SOFTMMU */
|
||||
|
||||
TranslationBlock *tb_gen_code(CPUState *cpu, vaddr pc,
|
||||
uint64_t cs_base, uint32_t flags,
|
||||
int cflags);
|
||||
void page_init(void);
|
||||
void tb_htable_init(void);
|
||||
void tb_reset_jump(TranslationBlock *tb, int n);
|
||||
TranslationBlock *tb_link_page(TranslationBlock *tb);
|
||||
bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc);
|
||||
void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
uintptr_t host_pc);
|
||||
|
||||
bool tcg_exec_realizefn(CPUState *cpu, Error **errp);
|
||||
void tcg_exec_unrealizefn(CPUState *cpu);
|
||||
|
||||
/* Return the current PC from CPU, which may be cached in TB. */
|
||||
static inline vaddr log_pc(CPUState *cpu, const TranslationBlock *tb)
|
||||
@@ -81,6 +93,8 @@ static inline vaddr log_pc(CPUState *cpu, const TranslationBlock *tb)
|
||||
}
|
||||
}
|
||||
|
||||
extern bool one_insn_per_tb;
|
||||
|
||||
/**
|
||||
* tcg_req_mo:
|
||||
* @type: TCGBar
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "host/load-extract-al16-al8.h.inc"
|
||||
#include "host/store-insert-al16.h.inc"
|
||||
#include "host/load-extract-al16-al8.h"
|
||||
#include "host/store-insert-al16.h"
|
||||
|
||||
#ifdef CONFIG_ATOMIC64
|
||||
# define HAVE_al8 true
|
||||
@@ -168,7 +168,6 @@ static uint64_t load_atomic8_or_exit(CPUState *cpu, uintptr_t ra, void *pv)
|
||||
#endif
|
||||
|
||||
/* Ultimate fallback: re-execute in serial context. */
|
||||
trace_load_atom8_or_exit_fallback(ra);
|
||||
cpu_loop_exit_atomic(cpu, ra);
|
||||
}
|
||||
|
||||
@@ -213,7 +212,6 @@ static Int128 load_atomic16_or_exit(CPUState *cpu, uintptr_t ra, void *pv)
|
||||
}
|
||||
|
||||
/* Ultimate fallback: re-execute in serial context. */
|
||||
trace_load_atom16_or_exit_fallback(ra);
|
||||
cpu_loop_exit_atomic(cpu, ra);
|
||||
}
|
||||
|
||||
@@ -521,7 +519,6 @@ static uint64_t load_atom_8(CPUState *cpu, uintptr_t ra,
|
||||
if (HAVE_al8) {
|
||||
return load_atom_extract_al8x2(pv);
|
||||
}
|
||||
trace_load_atom8_fallback(memop, ra);
|
||||
cpu_loop_exit_atomic(cpu, ra);
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
@@ -566,7 +563,6 @@ static Int128 load_atom_16(CPUState *cpu, uintptr_t ra,
|
||||
break;
|
||||
case MO_64:
|
||||
if (!HAVE_al8) {
|
||||
trace_load_atom16_fallback(memop, ra);
|
||||
cpu_loop_exit_atomic(cpu, ra);
|
||||
}
|
||||
a = load_atomic8(pv);
|
||||
@@ -574,7 +570,6 @@ static Int128 load_atom_16(CPUState *cpu, uintptr_t ra,
|
||||
break;
|
||||
case -MO_64:
|
||||
if (!HAVE_al8) {
|
||||
trace_load_atom16_fallback(memop, ra);
|
||||
cpu_loop_exit_atomic(cpu, ra);
|
||||
}
|
||||
a = load_atom_extract_al8x2(pv);
|
||||
@@ -902,7 +897,6 @@ static void store_atom_2(CPUState *cpu, uintptr_t ra,
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
trace_store_atom2_fallback(memop, ra);
|
||||
cpu_loop_exit_atomic(cpu, ra);
|
||||
}
|
||||
|
||||
@@ -967,7 +961,6 @@ static void store_atom_4(CPUState *cpu, uintptr_t ra,
|
||||
return;
|
||||
}
|
||||
}
|
||||
trace_store_atom4_fallback(memop, ra);
|
||||
cpu_loop_exit_atomic(cpu, ra);
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
@@ -1036,7 +1029,6 @@ static void store_atom_8(CPUState *cpu, uintptr_t ra,
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
trace_store_atom8_fallback(memop, ra);
|
||||
cpu_loop_exit_atomic(cpu, ra);
|
||||
}
|
||||
|
||||
@@ -1115,6 +1107,5 @@ static void store_atom_16(CPUState *cpu, uintptr_t ra,
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
trace_store_atom16_fallback(memop, ra);
|
||||
cpu_loop_exit_atomic(cpu, ra);
|
||||
}
|
||||
|
||||
+14
-28
@@ -123,16 +123,9 @@ void helper_st_i128(CPUArchState *env, uint64_t addr, Int128 val, MemOpIdx oi)
|
||||
* Load helpers for cpu_ldst.h
|
||||
*/
|
||||
|
||||
static void plugin_load_cb(CPUArchState *env, abi_ptr addr,
|
||||
uint64_t value_low,
|
||||
uint64_t value_high,
|
||||
MemOpIdx oi)
|
||||
static void plugin_load_cb(CPUArchState *env, abi_ptr addr, MemOpIdx oi)
|
||||
{
|
||||
if (cpu_plugin_mem_cbs_enabled(env_cpu(env))) {
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr,
|
||||
value_low, value_high,
|
||||
oi, QEMU_PLUGIN_MEM_R);
|
||||
}
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
|
||||
}
|
||||
|
||||
uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra)
|
||||
@@ -141,7 +134,7 @@ uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra)
|
||||
|
||||
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_UB);
|
||||
ret = do_ld1_mmu(env_cpu(env), addr, oi, ra, MMU_DATA_LOAD);
|
||||
plugin_load_cb(env, addr, ret, 0, oi);
|
||||
plugin_load_cb(env, addr, oi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -152,7 +145,7 @@ uint16_t cpu_ldw_mmu(CPUArchState *env, abi_ptr addr,
|
||||
|
||||
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_16);
|
||||
ret = do_ld2_mmu(env_cpu(env), addr, oi, ra, MMU_DATA_LOAD);
|
||||
plugin_load_cb(env, addr, ret, 0, oi);
|
||||
plugin_load_cb(env, addr, oi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -163,7 +156,7 @@ uint32_t cpu_ldl_mmu(CPUArchState *env, abi_ptr addr,
|
||||
|
||||
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_32);
|
||||
ret = do_ld4_mmu(env_cpu(env), addr, oi, ra, MMU_DATA_LOAD);
|
||||
plugin_load_cb(env, addr, ret, 0, oi);
|
||||
plugin_load_cb(env, addr, oi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -174,7 +167,7 @@ uint64_t cpu_ldq_mmu(CPUArchState *env, abi_ptr addr,
|
||||
|
||||
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_64);
|
||||
ret = do_ld8_mmu(env_cpu(env), addr, oi, ra, MMU_DATA_LOAD);
|
||||
plugin_load_cb(env, addr, ret, 0, oi);
|
||||
plugin_load_cb(env, addr, oi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -185,7 +178,7 @@ Int128 cpu_ld16_mmu(CPUArchState *env, abi_ptr addr,
|
||||
|
||||
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_128);
|
||||
ret = do_ld16_mmu(env_cpu(env), addr, oi, ra);
|
||||
plugin_load_cb(env, addr, int128_getlo(ret), int128_gethi(ret), oi);
|
||||
plugin_load_cb(env, addr, oi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -193,23 +186,16 @@ Int128 cpu_ld16_mmu(CPUArchState *env, abi_ptr addr,
|
||||
* Store helpers for cpu_ldst.h
|
||||
*/
|
||||
|
||||
static void plugin_store_cb(CPUArchState *env, abi_ptr addr,
|
||||
uint64_t value_low,
|
||||
uint64_t value_high,
|
||||
MemOpIdx oi)
|
||||
static void plugin_store_cb(CPUArchState *env, abi_ptr addr, MemOpIdx oi)
|
||||
{
|
||||
if (cpu_plugin_mem_cbs_enabled(env_cpu(env))) {
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr,
|
||||
value_low, value_high,
|
||||
oi, QEMU_PLUGIN_MEM_W);
|
||||
}
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
|
||||
}
|
||||
|
||||
void cpu_stb_mmu(CPUArchState *env, abi_ptr addr, uint8_t val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
helper_stb_mmu(env, addr, val, oi, retaddr);
|
||||
plugin_store_cb(env, addr, val, 0, oi);
|
||||
plugin_store_cb(env, addr, oi);
|
||||
}
|
||||
|
||||
void cpu_stw_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
|
||||
@@ -217,7 +203,7 @@ void cpu_stw_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
|
||||
{
|
||||
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_16);
|
||||
do_st2_mmu(env_cpu(env), addr, val, oi, retaddr);
|
||||
plugin_store_cb(env, addr, val, 0, oi);
|
||||
plugin_store_cb(env, addr, oi);
|
||||
}
|
||||
|
||||
void cpu_stl_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
@@ -225,7 +211,7 @@ void cpu_stl_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
{
|
||||
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_32);
|
||||
do_st4_mmu(env_cpu(env), addr, val, oi, retaddr);
|
||||
plugin_store_cb(env, addr, val, 0, oi);
|
||||
plugin_store_cb(env, addr, oi);
|
||||
}
|
||||
|
||||
void cpu_stq_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
@@ -233,7 +219,7 @@ void cpu_stq_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
{
|
||||
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_64);
|
||||
do_st8_mmu(env_cpu(env), addr, val, oi, retaddr);
|
||||
plugin_store_cb(env, addr, val, 0, oi);
|
||||
plugin_store_cb(env, addr, oi);
|
||||
}
|
||||
|
||||
void cpu_st16_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
|
||||
@@ -241,7 +227,7 @@ void cpu_st16_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
|
||||
{
|
||||
tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_128);
|
||||
do_st16_mmu(env_cpu(env), addr, val, oi, retaddr);
|
||||
plugin_store_cb(env, addr, int128_getlo(val), int128_gethi(val), oi);
|
||||
plugin_store_cb(env, addr, oi);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+759
-318
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
#ifdef CONFIG_PLUGIN
|
||||
DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_wg, TCG_CALL_NO_WG | TCG_CALL_PLUGIN, void, i32, ptr)
|
||||
DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_rwg, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, void, i32, ptr)
|
||||
DEF_HELPER_FLAGS_4(plugin_vcpu_mem_cb, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, void, i32, i32, i64, ptr)
|
||||
#endif
|
||||
@@ -9,9 +9,6 @@
|
||||
#ifndef ACCEL_TCG_TB_JMP_CACHE_H
|
||||
#define ACCEL_TCG_TB_JMP_CACHE_H
|
||||
|
||||
#include "qemu/rcu.h"
|
||||
#include "exec/cpu-common.h"
|
||||
|
||||
#define TB_JMP_CACHE_BITS 12
|
||||
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
|
||||
|
||||
@@ -22,12 +19,12 @@
|
||||
* non-NULL value of 'tb'. Strictly speaking pc is only needed for
|
||||
* CF_PCREL, but it's used always for simplicity.
|
||||
*/
|
||||
typedef struct CPUJumpCache {
|
||||
struct CPUJumpCache {
|
||||
struct rcu_head rcu;
|
||||
struct {
|
||||
TranslationBlock *tb;
|
||||
vaddr pc;
|
||||
} array[TB_JMP_CACHE_SIZE];
|
||||
} CPUJumpCache;
|
||||
};
|
||||
|
||||
#endif /* ACCEL_TCG_TB_JMP_CACHE_H */
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "exec/cputlb.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/page-protection.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "exec/translate-all.h"
|
||||
#include "sysemu/tcg.h"
|
||||
@@ -713,7 +712,7 @@ static void tb_record(TranslationBlock *tb)
|
||||
tb_page_addr_t paddr0 = tb_page_addr0(tb);
|
||||
tb_page_addr_t paddr1 = tb_page_addr1(tb);
|
||||
tb_page_addr_t pindex0 = paddr0 >> TARGET_PAGE_BITS;
|
||||
tb_page_addr_t pindex1 = paddr1 >> TARGET_PAGE_BITS;
|
||||
tb_page_addr_t pindex1 = paddr0 >> TARGET_PAGE_BITS;
|
||||
|
||||
assert(paddr0 != -1);
|
||||
if (unlikely(paddr1 != -1) && pindex0 != pindex1) {
|
||||
@@ -745,7 +744,7 @@ static void tb_remove(TranslationBlock *tb)
|
||||
tb_page_addr_t paddr0 = tb_page_addr0(tb);
|
||||
tb_page_addr_t paddr1 = tb_page_addr1(tb);
|
||||
tb_page_addr_t pindex0 = paddr0 >> TARGET_PAGE_BITS;
|
||||
tb_page_addr_t pindex1 = paddr1 >> TARGET_PAGE_BITS;
|
||||
tb_page_addr_t pindex1 = paddr0 >> TARGET_PAGE_BITS;
|
||||
|
||||
assert(paddr0 != -1);
|
||||
if (unlikely(paddr1 != -1) && pindex0 != pindex1) {
|
||||
|
||||
@@ -137,6 +137,10 @@ void mttcg_start_vcpu_thread(CPUState *cpu)
|
||||
g_assert(tcg_enabled());
|
||||
tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1);
|
||||
|
||||
cpu->thread = g_new0(QemuThread, 1);
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
|
||||
/* create a thread per vCPU with TCG (MTTCG) */
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
|
||||
cpu->cpu_index);
|
||||
|
||||
@@ -109,7 +109,7 @@ static void rr_wait_io_event(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
while (all_cpu_threads_idle()) {
|
||||
while (all_cpu_threads_idle() && replay_can_wait()) {
|
||||
rr_stop_kick_timer();
|
||||
qemu_cond_wait_bql(first_cpu->halt_cond);
|
||||
}
|
||||
@@ -302,7 +302,9 @@ static void *rr_cpu_thread_fn(void *arg)
|
||||
rr_deal_with_unplugged_cpus();
|
||||
}
|
||||
|
||||
g_assert_not_reached();
|
||||
rcu_remove_force_rcu_notifier(&force_rcu);
|
||||
rcu_unregister_thread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rr_start_vcpu_thread(CPUState *cpu)
|
||||
@@ -315,23 +317,22 @@ void rr_start_vcpu_thread(CPUState *cpu)
|
||||
tcg_cpu_init_cflags(cpu, false);
|
||||
|
||||
if (!single_tcg_cpu_thread) {
|
||||
single_tcg_halt_cond = cpu->halt_cond;
|
||||
single_tcg_cpu_thread = cpu->thread;
|
||||
cpu->thread = g_new0(QemuThread, 1);
|
||||
cpu->halt_cond = g_new0(QemuCond, 1);
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
|
||||
/* share a single thread for all cpus with TCG */
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG");
|
||||
qemu_thread_create(cpu->thread, thread_name,
|
||||
rr_cpu_thread_fn,
|
||||
cpu, QEMU_THREAD_JOINABLE);
|
||||
|
||||
single_tcg_halt_cond = cpu->halt_cond;
|
||||
single_tcg_cpu_thread = cpu->thread;
|
||||
} else {
|
||||
/* we share the thread, dump spare data */
|
||||
g_free(cpu->thread);
|
||||
qemu_cond_destroy(cpu->halt_cond);
|
||||
g_free(cpu->halt_cond);
|
||||
/* we share the thread */
|
||||
cpu->thread = single_tcg_cpu_thread;
|
||||
cpu->halt_cond = single_tcg_halt_cond;
|
||||
|
||||
/* copy the stuff done at start of rr_cpu_thread_fn */
|
||||
cpu->thread_id = first_cpu->thread_id;
|
||||
cpu->neg.can_do_io = 1;
|
||||
cpu->created = true;
|
||||
|
||||
@@ -35,9 +35,7 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/hwaddr.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "gdbstub/enums.h"
|
||||
|
||||
#include "hw/core/cpu.h"
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
#include "tcg-accel-ops.h"
|
||||
#include "tcg-accel-ops-mttcg.h"
|
||||
@@ -62,7 +60,7 @@ void tcg_cpu_init_cflags(CPUState *cpu, bool parallel)
|
||||
|
||||
cflags |= parallel ? CF_PARALLEL : 0;
|
||||
cflags |= icount_enabled() ? CF_USE_ICOUNT : 0;
|
||||
tcg_cflags_set(cpu, cflags);
|
||||
cpu->tcg_cflags |= cflags;
|
||||
}
|
||||
|
||||
void tcg_cpu_destroy(CPUState *cpu)
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#include "hw/boards.h"
|
||||
#endif
|
||||
#include "internal-common.h"
|
||||
#include "internal-target.h"
|
||||
|
||||
struct TCGState {
|
||||
AccelState parent_obj;
|
||||
|
||||
@@ -12,15 +12,3 @@ memory_notdirty_set_dirty(uint64_t vaddr) "0x%" PRIx64
|
||||
|
||||
# translate-all.c
|
||||
translate_block(void *tb, uintptr_t pc, const void *tb_code) "tb:%p, pc:0x%"PRIxPTR", tb_code:%p"
|
||||
|
||||
# ldst_atomicity
|
||||
load_atom2_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||
load_atom4_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||
load_atom8_or_exit_fallback(uintptr_t ra) "ra:0x%"PRIxPTR""
|
||||
load_atom8_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||
load_atom16_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||
load_atom16_or_exit_fallback(uintptr_t ra) "ra:0x%"PRIxPTR""
|
||||
store_atom2_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||
store_atom4_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||
store_atom8_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||
store_atom16_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||
|
||||
@@ -634,7 +634,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | n;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
|
||||
vaddr pc = cpu->cc->get_pc(cpu);
|
||||
vaddr pc = log_pc(cpu, tb);
|
||||
if (qemu_log_in_addr_range(pc)) {
|
||||
qemu_log("cpu_io_recompile: rewound execution of TB to %016"
|
||||
VADDR_PRIx "\n", pc);
|
||||
@@ -644,6 +644,15 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
cpu_loop_exit_noexc(cpu);
|
||||
}
|
||||
|
||||
#else /* CONFIG_USER_ONLY */
|
||||
|
||||
void cpu_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
g_assert(bql_locked());
|
||||
cpu->interrupt_request |= mask;
|
||||
qatomic_set(&cpu->neg.icount_decr.u16.high, -1);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
/*
|
||||
|
||||
+138
-236
@@ -12,23 +12,26 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/translator.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/plugin-gen.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "tcg/tcg-op-common.h"
|
||||
#include "internal-target.h"
|
||||
#include "disas/disas.h"
|
||||
|
||||
static void set_can_do_io(DisasContextBase *db, bool val)
|
||||
{
|
||||
QEMU_BUILD_BUG_ON(sizeof_field(CPUState, neg.can_do_io) != 1);
|
||||
tcg_gen_st8_i32(tcg_constant_i32(val), tcg_env,
|
||||
offsetof(ArchCPU, parent_obj.neg.can_do_io) -
|
||||
offsetof(ArchCPU, env));
|
||||
if (db->saved_can_do_io != val) {
|
||||
db->saved_can_do_io = val;
|
||||
|
||||
QEMU_BUILD_BUG_ON(sizeof_field(CPUState, neg.can_do_io) != 1);
|
||||
tcg_gen_st8_i32(tcg_constant_i32(val), tcg_env,
|
||||
offsetof(ArchCPU, parent_obj.neg.can_do_io) -
|
||||
offsetof(ArchCPU, env));
|
||||
}
|
||||
}
|
||||
|
||||
bool translator_io_start(DisasContextBase *db)
|
||||
{
|
||||
set_can_do_io(db, true);
|
||||
|
||||
/*
|
||||
* Ensure that this instruction will be the last in the TB.
|
||||
* The target may override this to something more forceful.
|
||||
@@ -81,6 +84,13 @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags)
|
||||
- offsetof(ArchCPU, env));
|
||||
}
|
||||
|
||||
/*
|
||||
* cpu->neg.can_do_io is set automatically here at the beginning of
|
||||
* each translation block. The cost is minimal, plus it would be
|
||||
* very easy to forget doing it in the translator.
|
||||
*/
|
||||
set_can_do_io(db, db->max_insns == 1);
|
||||
|
||||
return icount_start_insn;
|
||||
}
|
||||
|
||||
@@ -119,7 +129,6 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
{
|
||||
uint32_t cflags = tb_cflags(tb);
|
||||
TCGOp *icount_start_insn;
|
||||
TCGOp *first_insn_start = NULL;
|
||||
bool plugin_enabled;
|
||||
|
||||
/* Initialize DisasContext */
|
||||
@@ -129,12 +138,10 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
db->is_jmp = DISAS_NEXT;
|
||||
db->num_insns = 0;
|
||||
db->max_insns = *max_insns;
|
||||
db->insn_start = NULL;
|
||||
db->fake_insn = false;
|
||||
db->singlestep_enabled = cflags & CF_SINGLE_STEP;
|
||||
db->saved_can_do_io = -1;
|
||||
db->host_addr[0] = host_pc;
|
||||
db->host_addr[1] = NULL;
|
||||
db->record_start = 0;
|
||||
db->record_len = 0;
|
||||
|
||||
ops->init_disas_context(db, cpu);
|
||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||
@@ -144,16 +151,12 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
ops->tb_start(db, cpu);
|
||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||
|
||||
plugin_enabled = plugin_gen_tb_start(cpu, db);
|
||||
plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY);
|
||||
db->plugin_enabled = plugin_enabled;
|
||||
|
||||
while (true) {
|
||||
*max_insns = ++db->num_insns;
|
||||
ops->insn_start(db, cpu);
|
||||
db->insn_start = tcg_last_op();
|
||||
if (first_insn_start == NULL) {
|
||||
first_insn_start = db->insn_start;
|
||||
}
|
||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||
|
||||
if (plugin_enabled) {
|
||||
@@ -166,6 +169,10 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
* done next -- either exiting this loop or locate the start of
|
||||
* the next instruction.
|
||||
*/
|
||||
if (db->num_insns == db->max_insns) {
|
||||
/* Accept I/O on the last instruction. */
|
||||
set_can_do_io(db, true);
|
||||
}
|
||||
ops->translate_insn(db, cpu);
|
||||
|
||||
/*
|
||||
@@ -198,277 +205,172 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
ops->tb_stop(db, cpu);
|
||||
gen_tb_end(tb, cflags, icount_start_insn, db->num_insns);
|
||||
|
||||
/*
|
||||
* Manage can_do_io for the translation block: set to false before
|
||||
* the first insn and set to true before the last insn.
|
||||
*/
|
||||
if (db->num_insns == 1) {
|
||||
tcg_debug_assert(first_insn_start == db->insn_start);
|
||||
} else {
|
||||
tcg_debug_assert(first_insn_start != db->insn_start);
|
||||
tcg_ctx->emit_before_op = first_insn_start;
|
||||
set_can_do_io(db, false);
|
||||
}
|
||||
tcg_ctx->emit_before_op = db->insn_start;
|
||||
set_can_do_io(db, true);
|
||||
tcg_ctx->emit_before_op = NULL;
|
||||
|
||||
/* May be used by disas_log or plugin callbacks. */
|
||||
tb->size = db->pc_next - db->pc_first;
|
||||
tb->icount = db->num_insns;
|
||||
|
||||
if (plugin_enabled) {
|
||||
plugin_gen_tb_end(cpu, db->num_insns);
|
||||
}
|
||||
|
||||
/* The disas_log hook may use these values rather than recompute. */
|
||||
tb->size = db->pc_next - db->pc_first;
|
||||
tb->icount = db->num_insns;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||
&& qemu_log_in_addr_range(db->pc_first)) {
|
||||
FILE *logfile = qemu_log_trylock();
|
||||
if (logfile) {
|
||||
fprintf(logfile, "----------------\n");
|
||||
|
||||
if (!ops->disas_log ||
|
||||
!ops->disas_log(db, cpu, logfile)) {
|
||||
fprintf(logfile, "IN: %s\n", lookup_symbol(db->pc_first));
|
||||
target_disas(logfile, cpu, db);
|
||||
}
|
||||
ops->disas_log(db, cpu, logfile);
|
||||
fprintf(logfile, "\n");
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool translator_ld(CPUArchState *env, DisasContextBase *db,
|
||||
void *dest, vaddr pc, size_t len)
|
||||
static void *translator_access(CPUArchState *env, DisasContextBase *db,
|
||||
vaddr pc, size_t len)
|
||||
{
|
||||
TranslationBlock *tb = db->tb;
|
||||
vaddr last = pc + len - 1;
|
||||
void *host;
|
||||
vaddr base;
|
||||
vaddr base, end;
|
||||
TranslationBlock *tb;
|
||||
|
||||
tb = db->tb;
|
||||
|
||||
/* Use slow path if first page is MMIO. */
|
||||
if (unlikely(tb_page_addr0(tb) == -1)) {
|
||||
/* We capped translation with first page MMIO in tb_gen_code. */
|
||||
tcg_debug_assert(db->max_insns == 1);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
host = db->host_addr[0];
|
||||
base = db->pc_first;
|
||||
|
||||
if (likely(((base ^ last) & TARGET_PAGE_MASK) == 0)) {
|
||||
/* Entire read is from the first page. */
|
||||
memcpy(dest, host + (pc - base), len);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (unlikely(((base ^ pc) & TARGET_PAGE_MASK) == 0)) {
|
||||
/* Read begins on the first page and extends to the second. */
|
||||
size_t len0 = -(pc | TARGET_PAGE_MASK);
|
||||
memcpy(dest, host + (pc - base), len0);
|
||||
pc += len0;
|
||||
dest += len0;
|
||||
len -= len0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The read must conclude on the second page and not extend to a third.
|
||||
*
|
||||
* TODO: We could allow the two pages to be virtually discontiguous,
|
||||
* since we already allow the two pages to be physically discontiguous.
|
||||
* The only reasonable use case would be executing an insn at the end
|
||||
* of the address space wrapping around to the beginning. For that,
|
||||
* we would need to know the current width of the address space.
|
||||
* In the meantime, assert.
|
||||
*/
|
||||
base = (base & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
|
||||
assert(((base ^ pc) & TARGET_PAGE_MASK) == 0);
|
||||
assert(((base ^ last) & TARGET_PAGE_MASK) == 0);
|
||||
host = db->host_addr[1];
|
||||
|
||||
if (host == NULL) {
|
||||
tb_page_addr_t page0, old_page1, new_page1;
|
||||
|
||||
new_page1 = get_page_addr_code_hostp(env, base, &db->host_addr[1]);
|
||||
|
||||
/*
|
||||
* If the second page is MMIO, treat as if the first page
|
||||
* was MMIO as well, so that we do not cache the TB.
|
||||
*/
|
||||
if (unlikely(new_page1 == -1)) {
|
||||
tb_unlock_pages(tb);
|
||||
tb_set_page_addr0(tb, -1);
|
||||
/* Require that this be the final insn. */
|
||||
db->max_insns = db->num_insns;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is not the first time around, and page1 matches,
|
||||
* then we already have the page locked. Alternately, we're
|
||||
* not doing anything to prevent the PTE from changing, so
|
||||
* we might wind up with a different page, requiring us to
|
||||
* re-do the locking.
|
||||
*/
|
||||
old_page1 = tb_page_addr1(tb);
|
||||
if (likely(new_page1 != old_page1)) {
|
||||
page0 = tb_page_addr0(tb);
|
||||
if (unlikely(old_page1 != -1)) {
|
||||
tb_unlock_page1(page0, old_page1);
|
||||
}
|
||||
tb_set_page_addr1(tb, new_page1);
|
||||
tb_lock_page1(page0, new_page1);
|
||||
}
|
||||
end = pc + len - 1;
|
||||
if (likely(is_same_page(db, end))) {
|
||||
host = db->host_addr[0];
|
||||
base = db->pc_first;
|
||||
} else {
|
||||
host = db->host_addr[1];
|
||||
base = TARGET_PAGE_ALIGN(db->pc_first);
|
||||
if (host == NULL) {
|
||||
tb_page_addr_t page0, old_page1, new_page1;
|
||||
|
||||
new_page1 = get_page_addr_code_hostp(env, base, &db->host_addr[1]);
|
||||
|
||||
/*
|
||||
* If the second page is MMIO, treat as if the first page
|
||||
* was MMIO as well, so that we do not cache the TB.
|
||||
*/
|
||||
if (unlikely(new_page1 == -1)) {
|
||||
tb_unlock_pages(tb);
|
||||
tb_set_page_addr0(tb, -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is not the first time around, and page1 matches,
|
||||
* then we already have the page locked. Alternately, we're
|
||||
* not doing anything to prevent the PTE from changing, so
|
||||
* we might wind up with a different page, requiring us to
|
||||
* re-do the locking.
|
||||
*/
|
||||
old_page1 = tb_page_addr1(tb);
|
||||
if (likely(new_page1 != old_page1)) {
|
||||
page0 = tb_page_addr0(tb);
|
||||
if (unlikely(old_page1 != -1)) {
|
||||
tb_unlock_page1(page0, old_page1);
|
||||
}
|
||||
tb_set_page_addr1(tb, new_page1);
|
||||
tb_lock_page1(page0, new_page1);
|
||||
}
|
||||
host = db->host_addr[1];
|
||||
}
|
||||
|
||||
/* Use slow path when crossing pages. */
|
||||
if (is_same_page(db, pc)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(dest, host + (pc - base), len);
|
||||
return true;
|
||||
tcg_debug_assert(pc >= base);
|
||||
return host + (pc - base);
|
||||
}
|
||||
|
||||
static void record_save(DisasContextBase *db, vaddr pc,
|
||||
const void *from, int size)
|
||||
static void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
|
||||
{
|
||||
int offset;
|
||||
#ifdef CONFIG_PLUGIN
|
||||
struct qemu_plugin_insn *insn = tcg_ctx->plugin_insn;
|
||||
abi_ptr off;
|
||||
|
||||
/* Do not record probes before the start of TB. */
|
||||
if (pc < db->pc_first) {
|
||||
if (insn == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* In translator_access, we verified that pc is within 2 pages
|
||||
* of pc_first, thus this will never overflow.
|
||||
*/
|
||||
offset = pc - db->pc_first;
|
||||
|
||||
/*
|
||||
* Either the first or second page may be I/O. If it is the second,
|
||||
* then the first byte we need to record will be at a non-zero offset.
|
||||
* In either case, we should not need to record but a single insn.
|
||||
*/
|
||||
if (db->record_len == 0) {
|
||||
db->record_start = offset;
|
||||
db->record_len = size;
|
||||
} else {
|
||||
assert(offset == db->record_start + db->record_len);
|
||||
assert(db->record_len + size <= sizeof(db->record));
|
||||
db->record_len += size;
|
||||
off = pc - insn->vaddr;
|
||||
if (off < insn->data->len) {
|
||||
g_byte_array_set_size(insn->data, off);
|
||||
} else if (off > insn->data->len) {
|
||||
/* we have an unexpected gap */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
memcpy(db->record + (offset - db->record_start), from, size);
|
||||
insn->data = g_byte_array_append(insn->data, from, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t translator_st_len(const DisasContextBase *db)
|
||||
uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
||||
{
|
||||
return db->fake_insn ? db->record_len : db->tb->size;
|
||||
uint8_t ret;
|
||||
void *p = translator_access(env, db, pc, sizeof(ret));
|
||||
|
||||
if (p) {
|
||||
plugin_insn_append(pc, p, sizeof(ret));
|
||||
return ldub_p(p);
|
||||
}
|
||||
ret = cpu_ldub_code(env, pc);
|
||||
plugin_insn_append(pc, &ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool translator_st(const DisasContextBase *db, void *dest,
|
||||
vaddr addr, size_t len)
|
||||
uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
||||
{
|
||||
size_t offset, offset_end;
|
||||
uint16_t ret, plug;
|
||||
void *p = translator_access(env, db, pc, sizeof(ret));
|
||||
|
||||
if (addr < db->pc_first) {
|
||||
return false;
|
||||
if (p) {
|
||||
plugin_insn_append(pc, p, sizeof(ret));
|
||||
return lduw_p(p);
|
||||
}
|
||||
offset = addr - db->pc_first;
|
||||
offset_end = offset + len;
|
||||
if (offset_end > translator_st_len(db)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!db->fake_insn) {
|
||||
size_t offset_page1 = -(db->pc_first | TARGET_PAGE_MASK);
|
||||
|
||||
/* Get all the bytes from the first page. */
|
||||
if (db->host_addr[0]) {
|
||||
if (offset_end <= offset_page1) {
|
||||
memcpy(dest, db->host_addr[0] + offset, len);
|
||||
return true;
|
||||
}
|
||||
if (offset < offset_page1) {
|
||||
size_t len0 = offset_page1 - offset;
|
||||
memcpy(dest, db->host_addr[0] + offset, len0);
|
||||
offset += len0;
|
||||
dest += len0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get any bytes from the second page. */
|
||||
if (db->host_addr[1] && offset >= offset_page1) {
|
||||
memcpy(dest, db->host_addr[1] + (offset - offset_page1),
|
||||
offset_end - offset);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Else get recorded bytes. */
|
||||
if (db->record_len != 0 &&
|
||||
offset >= db->record_start &&
|
||||
offset_end <= db->record_start + db->record_len) {
|
||||
memcpy(dest, db->record + (offset - db->record_start),
|
||||
offset_end - offset);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
ret = cpu_lduw_code(env, pc);
|
||||
plug = tswap16(ret);
|
||||
plugin_insn_append(pc, &plug, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, vaddr pc)
|
||||
uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
||||
{
|
||||
uint8_t raw;
|
||||
uint32_t ret, plug;
|
||||
void *p = translator_access(env, db, pc, sizeof(ret));
|
||||
|
||||
if (!translator_ld(env, db, &raw, pc, sizeof(raw))) {
|
||||
raw = cpu_ldub_code(env, pc);
|
||||
record_save(db, pc, &raw, sizeof(raw));
|
||||
if (p) {
|
||||
plugin_insn_append(pc, p, sizeof(ret));
|
||||
return ldl_p(p);
|
||||
}
|
||||
return raw;
|
||||
ret = cpu_ldl_code(env, pc);
|
||||
plug = tswap32(ret);
|
||||
plugin_insn_append(pc, &plug, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, vaddr pc)
|
||||
uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
||||
{
|
||||
uint16_t raw, tgt;
|
||||
uint64_t ret, plug;
|
||||
void *p = translator_access(env, db, pc, sizeof(ret));
|
||||
|
||||
if (translator_ld(env, db, &raw, pc, sizeof(raw))) {
|
||||
tgt = tswap16(raw);
|
||||
} else {
|
||||
tgt = cpu_lduw_code(env, pc);
|
||||
raw = tswap16(tgt);
|
||||
record_save(db, pc, &raw, sizeof(raw));
|
||||
if (p) {
|
||||
plugin_insn_append(pc, p, sizeof(ret));
|
||||
return ldq_p(p);
|
||||
}
|
||||
return tgt;
|
||||
ret = cpu_ldq_code(env, pc);
|
||||
plug = tswap64(ret);
|
||||
plugin_insn_append(pc, &plug, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, vaddr pc)
|
||||
void translator_fake_ldb(uint8_t insn8, abi_ptr pc)
|
||||
{
|
||||
uint32_t raw, tgt;
|
||||
|
||||
if (translator_ld(env, db, &raw, pc, sizeof(raw))) {
|
||||
tgt = tswap32(raw);
|
||||
} else {
|
||||
tgt = cpu_ldl_code(env, pc);
|
||||
raw = tswap32(tgt);
|
||||
record_save(db, pc, &raw, sizeof(raw));
|
||||
}
|
||||
return tgt;
|
||||
}
|
||||
|
||||
uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, vaddr pc)
|
||||
{
|
||||
uint64_t raw, tgt;
|
||||
|
||||
if (translator_ld(env, db, &raw, pc, sizeof(raw))) {
|
||||
tgt = tswap64(raw);
|
||||
} else {
|
||||
tgt = cpu_ldq_code(env, pc);
|
||||
raw = tswap64(tgt);
|
||||
record_save(db, pc, &raw, sizeof(raw));
|
||||
}
|
||||
return tgt;
|
||||
}
|
||||
|
||||
void translator_fake_ld(DisasContextBase *db, const void *data, size_t len)
|
||||
{
|
||||
db->fake_insn = true;
|
||||
record_save(db, db->pc_first, data, len);
|
||||
plugin_insn_append(pc, &insn8, sizeof(insn8));
|
||||
}
|
||||
|
||||
+10
-14
@@ -24,12 +24,10 @@
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/rcu.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "exec/translate-all.h"
|
||||
#include "exec/page-protection.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "qemu/atomic128.h"
|
||||
#include "trace.h"
|
||||
#include "trace/trace-root.h"
|
||||
#include "tcg/tcg-ldst.h"
|
||||
#include "internal-common.h"
|
||||
#include "internal-target.h"
|
||||
@@ -38,13 +36,6 @@ __thread uintptr_t helper_retaddr;
|
||||
|
||||
//#define DEBUG_SIGNAL
|
||||
|
||||
void cpu_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
g_assert(bql_locked());
|
||||
cpu->interrupt_request |= mask;
|
||||
qatomic_set(&cpu->neg.icount_decr.u16.high, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust the pc to pass to cpu_restore_state; return the memop type.
|
||||
*/
|
||||
@@ -485,6 +476,11 @@ static bool pageflags_set_clear(target_ulong start, target_ulong last,
|
||||
return inval_tb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify the flags of a page and invalidate the code if necessary.
|
||||
* The flag PAGE_WRITE_ORG is positioned automatically depending
|
||||
* on PAGE_WRITE. The mmap_lock should already be held.
|
||||
*/
|
||||
void page_set_flags(target_ulong start, target_ulong last, int flags)
|
||||
{
|
||||
bool reset = false;
|
||||
@@ -768,7 +764,7 @@ int page_unprotect(target_ulong address, uintptr_t pc)
|
||||
if (prot & PAGE_EXEC) {
|
||||
prot = (prot & ~PAGE_EXEC) | PAGE_READ;
|
||||
}
|
||||
mprotect((void *)g2h_untagged(start), len, prot & PAGE_RWX);
|
||||
mprotect((void *)g2h_untagged(start), len, prot & PAGE_BITS);
|
||||
}
|
||||
mmap_unlock();
|
||||
|
||||
@@ -800,7 +796,7 @@ static int probe_access_internal(CPUArchState *env, vaddr addr,
|
||||
if (guest_addr_valid_untagged(addr)) {
|
||||
int page_flags = page_get_flags(addr);
|
||||
if (page_flags & acc_flag) {
|
||||
if (access_type != MMU_INST_FETCH
|
||||
if ((acc_flag == PAGE_READ || acc_flag == PAGE_WRITE)
|
||||
&& cpu_plugin_mem_cbs_enabled(env_cpu(env))) {
|
||||
return TLB_MMIO;
|
||||
}
|
||||
@@ -954,7 +950,7 @@ void page_reset_target_data(target_ulong start, target_ulong last) { }
|
||||
static void *cpu_mmu_lookup(CPUState *cpu, vaddr addr,
|
||||
MemOp mop, uintptr_t ra, MMUAccessType type)
|
||||
{
|
||||
int a_bits = memop_alignment_bits(mop);
|
||||
int a_bits = get_alignment_bits(mop);
|
||||
void *ret;
|
||||
|
||||
/* Enforce guest required alignment. */
|
||||
@@ -1236,7 +1232,7 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
int size, uintptr_t retaddr)
|
||||
{
|
||||
MemOp mop = get_memop(oi);
|
||||
int a_bits = memop_alignment_bits(mop);
|
||||
int a_bits = get_alignment_bits(mop);
|
||||
void *ret;
|
||||
|
||||
/* Enforce guest required alignment. */
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileContributor: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
* SPDX-FileCopyrightText: 2023 Linaro Ltd.
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef ACCEL_TCG_VCPU_STATE_H
|
||||
#define ACCEL_TCG_VCPU_STATE_H
|
||||
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
static inline TaskState *get_task_state(const CPUState *cs)
|
||||
{
|
||||
return cs->opaque;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "hw/xen/xen_native.h"
|
||||
#include "hw/xen/xen-legacy-backend.h"
|
||||
#include "hw/xen/xen_pt.h"
|
||||
#include "hw/xen/xen_igd.h"
|
||||
#include "chardev/char.h"
|
||||
#include "qemu/accel.h"
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
@@ -44,6 +44,11 @@ typedef struct coreaudioVoiceOut {
|
||||
bool enabled;
|
||||
} coreaudioVoiceOut;
|
||||
|
||||
#if !defined(MAC_OS_VERSION_12_0) \
|
||||
|| (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0)
|
||||
#define kAudioObjectPropertyElementMain kAudioObjectPropertyElementMaster
|
||||
#endif
|
||||
|
||||
static const AudioObjectPropertyAddress voice_addr = {
|
||||
kAudioHardwarePropertyDefaultOutputDevice,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ static size_t dbus_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
|
||||
assert(buf == vo->buf + vo->buf_pos && vo->buf_pos + size <= vo->buf_size);
|
||||
vo->buf_pos += size;
|
||||
|
||||
trace_dbus_audio_put_buffer_out(vo->buf_pos, vo->buf_size);
|
||||
trace_dbus_audio_put_buffer_out(size);
|
||||
|
||||
if (vo->buf_pos < vo->buf_size) {
|
||||
return size;
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@ endforeach
|
||||
|
||||
if dbus_display
|
||||
module_ss = ss.source_set()
|
||||
module_ss.add(when: [gio, pixman],
|
||||
if_true: [dbus_display1, files('dbusaudio.c')])
|
||||
module_ss.add(when: [gio, dbus_display1_dep, pixman],
|
||||
if_true: files('dbusaudio.c'))
|
||||
audio_modules += {'dbus': module_ss}
|
||||
endif
|
||||
|
||||
|
||||
+4
-4
@@ -769,15 +769,13 @@ qpw_audio_init(Audiodev *dev, Error **errp)
|
||||
pw->core = pw_context_connect(pw->context, NULL, 0);
|
||||
if (pw->core == NULL) {
|
||||
pw_thread_loop_unlock(pw->thread_loop);
|
||||
error_setg_errno(errp, errno, "Failed to connect to PipeWire instance");
|
||||
goto fail;
|
||||
goto fail_error;
|
||||
}
|
||||
|
||||
if (pw_core_add_listener(pw->core, &pw->core_listener,
|
||||
&core_events, pw) < 0) {
|
||||
pw_thread_loop_unlock(pw->thread_loop);
|
||||
error_setg(errp, "Failed to add PipeWire listener");
|
||||
goto fail;
|
||||
goto fail_error;
|
||||
}
|
||||
if (wait_resync(pw) < 0) {
|
||||
pw_thread_loop_unlock(pw->thread_loop);
|
||||
@@ -787,6 +785,8 @@ qpw_audio_init(Audiodev *dev, Error **errp)
|
||||
|
||||
return g_steal_pointer(&pw);
|
||||
|
||||
fail_error:
|
||||
error_setg(errp, "Failed to initialize PW context");
|
||||
fail:
|
||||
if (pw->thread_loop) {
|
||||
pw_thread_loop_stop(pw->thread_loop);
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ 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 pos, size_t size) "buf_pos = %zu, buf_size = %zu"
|
||||
dbus_audio_put_buffer_out(size_t len) "len = %zu"
|
||||
dbus_audio_read(size_t len) "len = %zu"
|
||||
|
||||
# pwaudio.c
|
||||
|
||||
@@ -3,7 +3,3 @@ source tpm/Kconfig
|
||||
config IOMMUFD
|
||||
bool
|
||||
depends on VFIO
|
||||
|
||||
config SPDM_SOCKET
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/cryptodev.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "standard-headers/linux/virtio_crypto.h"
|
||||
#include "crypto/cipher.h"
|
||||
@@ -64,11 +63,11 @@ static void cryptodev_builtin_init_akcipher(CryptoDevBackend *backend)
|
||||
{
|
||||
QCryptoAkCipherOptions opts;
|
||||
|
||||
opts.alg = QCRYPTO_AK_CIPHER_ALGO_RSA;
|
||||
opts.u.rsa.padding_alg = QCRYPTO_RSA_PADDING_ALGO_RAW;
|
||||
opts.alg = QCRYPTO_AKCIPHER_ALG_RSA;
|
||||
opts.u.rsa.padding_alg = QCRYPTO_RSA_PADDING_ALG_RAW;
|
||||
if (qcrypto_akcipher_supports(&opts)) {
|
||||
backend->conf.crypto_services |=
|
||||
(1u << QCRYPTODEV_BACKEND_SERVICE_TYPE_AKCIPHER);
|
||||
(1u << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER);
|
||||
backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
|
||||
}
|
||||
}
|
||||
@@ -93,9 +92,9 @@ static void cryptodev_builtin_init(
|
||||
backend->conf.peers.ccs[0] = cc;
|
||||
|
||||
backend->conf.crypto_services =
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_TYPE_CIPHER |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_TYPE_HASH |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_TYPE_MAC;
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_CIPHER |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_HASH |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_MAC;
|
||||
backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
|
||||
backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
|
||||
/*
|
||||
@@ -138,18 +137,18 @@ cryptodev_builtin_get_aes_algo(uint32_t key_len, int mode, Error **errp)
|
||||
int algo;
|
||||
|
||||
if (key_len == AES_KEYSIZE_128) {
|
||||
algo = QCRYPTO_CIPHER_ALGO_AES_128;
|
||||
algo = QCRYPTO_CIPHER_ALG_AES_128;
|
||||
} else if (key_len == AES_KEYSIZE_192) {
|
||||
algo = QCRYPTO_CIPHER_ALGO_AES_192;
|
||||
algo = QCRYPTO_CIPHER_ALG_AES_192;
|
||||
} else if (key_len == AES_KEYSIZE_256) { /* equals AES_KEYSIZE_128_XTS */
|
||||
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
|
||||
algo = QCRYPTO_CIPHER_ALGO_AES_128;
|
||||
algo = QCRYPTO_CIPHER_ALG_AES_128;
|
||||
} else {
|
||||
algo = QCRYPTO_CIPHER_ALGO_AES_256;
|
||||
algo = QCRYPTO_CIPHER_ALG_AES_256;
|
||||
}
|
||||
} else if (key_len == AES_KEYSIZE_256_XTS) {
|
||||
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
|
||||
algo = QCRYPTO_CIPHER_ALGO_AES_256;
|
||||
algo = QCRYPTO_CIPHER_ALG_AES_256;
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
@@ -169,16 +168,16 @@ static int cryptodev_builtin_get_rsa_hash_algo(
|
||||
{
|
||||
switch (virtio_rsa_hash) {
|
||||
case VIRTIO_CRYPTO_RSA_MD5:
|
||||
return QCRYPTO_HASH_ALGO_MD5;
|
||||
return QCRYPTO_HASH_ALG_MD5;
|
||||
|
||||
case VIRTIO_CRYPTO_RSA_SHA1:
|
||||
return QCRYPTO_HASH_ALGO_SHA1;
|
||||
return QCRYPTO_HASH_ALG_SHA1;
|
||||
|
||||
case VIRTIO_CRYPTO_RSA_SHA256:
|
||||
return QCRYPTO_HASH_ALGO_SHA256;
|
||||
return QCRYPTO_HASH_ALG_SHA256;
|
||||
|
||||
case VIRTIO_CRYPTO_RSA_SHA512:
|
||||
return QCRYPTO_HASH_ALGO_SHA512;
|
||||
return QCRYPTO_HASH_ALG_SHA512;
|
||||
|
||||
default:
|
||||
error_setg(errp, "Unsupported rsa hash algo: %d", virtio_rsa_hash);
|
||||
@@ -200,12 +199,12 @@ static int cryptodev_builtin_set_rsa_options(
|
||||
return -1;
|
||||
}
|
||||
opt->hash_alg = hash_alg;
|
||||
opt->padding_alg = QCRYPTO_RSA_PADDING_ALGO_PKCS1;
|
||||
opt->padding_alg = QCRYPTO_RSA_PADDING_ALG_PKCS1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (virtio_padding_algo == VIRTIO_CRYPTO_RSA_RAW_PADDING) {
|
||||
opt->padding_alg = QCRYPTO_RSA_PADDING_ALGO_RAW;
|
||||
opt->padding_alg = QCRYPTO_RSA_PADDING_ALG_RAW;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -271,15 +270,15 @@ static int cryptodev_builtin_create_cipher_session(
|
||||
break;
|
||||
case VIRTIO_CRYPTO_CIPHER_3DES_ECB:
|
||||
mode = QCRYPTO_CIPHER_MODE_ECB;
|
||||
algo = QCRYPTO_CIPHER_ALGO_3DES;
|
||||
algo = QCRYPTO_CIPHER_ALG_3DES;
|
||||
break;
|
||||
case VIRTIO_CRYPTO_CIPHER_3DES_CBC:
|
||||
mode = QCRYPTO_CIPHER_MODE_CBC;
|
||||
algo = QCRYPTO_CIPHER_ALGO_3DES;
|
||||
algo = QCRYPTO_CIPHER_ALG_3DES;
|
||||
break;
|
||||
case VIRTIO_CRYPTO_CIPHER_3DES_CTR:
|
||||
mode = QCRYPTO_CIPHER_MODE_CTR;
|
||||
algo = QCRYPTO_CIPHER_ALGO_3DES;
|
||||
algo = QCRYPTO_CIPHER_ALG_3DES;
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "Unsupported cipher alg :%u",
|
||||
@@ -318,7 +317,7 @@ static int cryptodev_builtin_create_akcipher_session(
|
||||
|
||||
switch (sess_info->algo) {
|
||||
case VIRTIO_CRYPTO_AKCIPHER_RSA:
|
||||
opts.alg = QCRYPTO_AK_CIPHER_ALGO_RSA;
|
||||
opts.alg = QCRYPTO_AKCIPHER_ALG_RSA;
|
||||
if (cryptodev_builtin_set_rsa_options(sess_info->u.rsa.padding_algo,
|
||||
sess_info->u.rsa.hash_algo, &opts.u.rsa, errp) != 0) {
|
||||
return -1;
|
||||
@@ -334,11 +333,11 @@ static int cryptodev_builtin_create_akcipher_session(
|
||||
|
||||
switch (sess_info->keytype) {
|
||||
case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC:
|
||||
type = QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC;
|
||||
type = QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC;
|
||||
break;
|
||||
|
||||
case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE:
|
||||
type = QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE;
|
||||
type = QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -397,8 +396,8 @@ static int cryptodev_builtin_create_session(
|
||||
case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
|
||||
case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
|
||||
default:
|
||||
error_report("Unsupported opcode :%" PRIu32 "",
|
||||
sess_info->op_code);
|
||||
error_setg(&local_error, "Unsupported opcode :%" PRIu32 "",
|
||||
sess_info->op_code);
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
|
||||
@@ -428,9 +427,7 @@ static int cryptodev_builtin_close_session(
|
||||
CRYPTODEV_BACKEND_BUILTIN(backend);
|
||||
CryptoDevBackendBuiltinSession *session;
|
||||
|
||||
if (session_id >= MAX_NUM_SESSIONS || !builtin->sessions[session_id]) {
|
||||
return -VIRTIO_CRYPTO_INVSESS;
|
||||
}
|
||||
assert(session_id < MAX_NUM_SESSIONS && builtin->sessions[session_id]);
|
||||
|
||||
session = builtin->sessions[session_id];
|
||||
if (session->cipher) {
|
||||
@@ -549,23 +546,23 @@ static int cryptodev_builtin_operation(
|
||||
CryptoDevBackendBuiltinSession *sess;
|
||||
CryptoDevBackendSymOpInfo *sym_op_info;
|
||||
CryptoDevBackendAsymOpInfo *asym_op_info;
|
||||
QCryptodevBackendAlgoType algtype = op_info->algtype;
|
||||
QCryptodevBackendAlgType algtype = op_info->algtype;
|
||||
int status = -VIRTIO_CRYPTO_ERR;
|
||||
Error *local_error = NULL;
|
||||
|
||||
if (op_info->session_id >= MAX_NUM_SESSIONS ||
|
||||
builtin->sessions[op_info->session_id] == NULL) {
|
||||
error_report("Cannot find a valid session id: %" PRIu64 "",
|
||||
op_info->session_id);
|
||||
error_setg(&local_error, "Cannot find a valid session id: %" PRIu64 "",
|
||||
op_info->session_id);
|
||||
return -VIRTIO_CRYPTO_INVSESS;
|
||||
}
|
||||
|
||||
sess = builtin->sessions[op_info->session_id];
|
||||
if (algtype == QCRYPTODEV_BACKEND_ALGO_TYPE_SYM) {
|
||||
if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) {
|
||||
sym_op_info = op_info->u.sym_op_info;
|
||||
status = cryptodev_builtin_sym_operation(sess, sym_op_info,
|
||||
&local_error);
|
||||
} else if (algtype == QCRYPTODEV_BACKEND_ALGO_TYPE_ASYM) {
|
||||
} else if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) {
|
||||
asym_op_info = op_info->u.asym_op_info;
|
||||
status = cryptodev_builtin_asym_operation(sess, op_info->op_code,
|
||||
asym_op_info, &local_error);
|
||||
|
||||
+18
-18
@@ -133,20 +133,20 @@ static int cryptodev_lkcf_set_op_desc(QCryptoAkCipherOptions *opts,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoAkCipherOptionsRSA *rsa_opt;
|
||||
if (opts->alg != QCRYPTO_AK_CIPHER_ALGO_RSA) {
|
||||
if (opts->alg != QCRYPTO_AKCIPHER_ALG_RSA) {
|
||||
error_setg(errp, "Unsupported alg: %u", opts->alg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rsa_opt = &opts->u.rsa;
|
||||
if (rsa_opt->padding_alg == QCRYPTO_RSA_PADDING_ALGO_PKCS1) {
|
||||
if (rsa_opt->padding_alg == QCRYPTO_RSA_PADDING_ALG_PKCS1) {
|
||||
snprintf(key_desc, desc_len, "enc=%s hash=%s",
|
||||
QCryptoRSAPaddingAlgo_str(rsa_opt->padding_alg),
|
||||
QCryptoHashAlgo_str(rsa_opt->hash_alg));
|
||||
QCryptoRSAPaddingAlgorithm_str(rsa_opt->padding_alg),
|
||||
QCryptoHashAlgorithm_str(rsa_opt->hash_alg));
|
||||
|
||||
} else {
|
||||
snprintf(key_desc, desc_len, "enc=%s",
|
||||
QCryptoRSAPaddingAlgo_str(rsa_opt->padding_alg));
|
||||
QCryptoRSAPaddingAlgorithm_str(rsa_opt->padding_alg));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -157,23 +157,23 @@ static int cryptodev_lkcf_set_rsa_opt(int virtio_padding_alg,
|
||||
Error **errp)
|
||||
{
|
||||
if (virtio_padding_alg == VIRTIO_CRYPTO_RSA_PKCS1_PADDING) {
|
||||
opt->padding_alg = QCRYPTO_RSA_PADDING_ALGO_PKCS1;
|
||||
opt->padding_alg = QCRYPTO_RSA_PADDING_ALG_PKCS1;
|
||||
|
||||
switch (virtio_hash_alg) {
|
||||
case VIRTIO_CRYPTO_RSA_MD5:
|
||||
opt->hash_alg = QCRYPTO_HASH_ALGO_MD5;
|
||||
opt->hash_alg = QCRYPTO_HASH_ALG_MD5;
|
||||
break;
|
||||
|
||||
case VIRTIO_CRYPTO_RSA_SHA1:
|
||||
opt->hash_alg = QCRYPTO_HASH_ALGO_SHA1;
|
||||
opt->hash_alg = QCRYPTO_HASH_ALG_SHA1;
|
||||
break;
|
||||
|
||||
case VIRTIO_CRYPTO_RSA_SHA256:
|
||||
opt->hash_alg = QCRYPTO_HASH_ALGO_SHA256;
|
||||
opt->hash_alg = QCRYPTO_HASH_ALG_SHA256;
|
||||
break;
|
||||
|
||||
case VIRTIO_CRYPTO_RSA_SHA512:
|
||||
opt->hash_alg = QCRYPTO_HASH_ALGO_SHA512;
|
||||
opt->hash_alg = QCRYPTO_HASH_ALG_SHA512;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -184,7 +184,7 @@ static int cryptodev_lkcf_set_rsa_opt(int virtio_padding_alg,
|
||||
}
|
||||
|
||||
if (virtio_padding_alg == VIRTIO_CRYPTO_RSA_RAW_PADDING) {
|
||||
opt->padding_alg = QCRYPTO_RSA_PADDING_ALGO_RAW;
|
||||
opt->padding_alg = QCRYPTO_RSA_PADDING_ALG_RAW;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ static void cryptodev_lkcf_init(CryptoDevBackend *backend, Error **errp)
|
||||
backend->conf.peers.ccs[0] = cc;
|
||||
|
||||
backend->conf.crypto_services =
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_TYPE_AKCIPHER;
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER;
|
||||
backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
|
||||
lkcf->running = true;
|
||||
|
||||
@@ -322,7 +322,7 @@ static void cryptodev_lkcf_execute_task(CryptoDevLKCFTask *task)
|
||||
* 2. generally, public key related compution is fast, just compute it with
|
||||
* thread-pool.
|
||||
*/
|
||||
if (session->keytype == QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE) {
|
||||
if (session->keytype == QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE) {
|
||||
if (qcrypto_akcipher_export_p8info(&session->akcipher_opts,
|
||||
session->key, session->keylen,
|
||||
&p8info, &p8info_len,
|
||||
@@ -474,7 +474,7 @@ static int cryptodev_lkcf_operation(
|
||||
CryptoDevBackendLKCF *lkcf =
|
||||
CRYPTODEV_BACKEND_LKCF(backend);
|
||||
CryptoDevBackendLKCFSession *sess;
|
||||
QCryptodevBackendAlgoType algtype = op_info->algtype;
|
||||
QCryptodevBackendAlgType algtype = op_info->algtype;
|
||||
CryptoDevLKCFTask *task;
|
||||
|
||||
if (op_info->session_id >= MAX_SESSIONS ||
|
||||
@@ -485,7 +485,7 @@ static int cryptodev_lkcf_operation(
|
||||
}
|
||||
|
||||
sess = lkcf->sess[op_info->session_id];
|
||||
if (algtype != QCRYPTODEV_BACKEND_ALGO_TYPE_ASYM) {
|
||||
if (algtype != QCRYPTODEV_BACKEND_ALG_ASYM) {
|
||||
error_report("algtype not supported: %u", algtype);
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
@@ -518,7 +518,7 @@ static int cryptodev_lkcf_create_asym_session(
|
||||
|
||||
switch (sess_info->algo) {
|
||||
case VIRTIO_CRYPTO_AKCIPHER_RSA:
|
||||
sess->akcipher_opts.alg = QCRYPTO_AK_CIPHER_ALGO_RSA;
|
||||
sess->akcipher_opts.alg = QCRYPTO_AKCIPHER_ALG_RSA;
|
||||
if (cryptodev_lkcf_set_rsa_opt(
|
||||
sess_info->u.rsa.padding_algo, sess_info->u.rsa.hash_algo,
|
||||
&sess->akcipher_opts.u.rsa, &local_error) != 0) {
|
||||
@@ -534,11 +534,11 @@ static int cryptodev_lkcf_create_asym_session(
|
||||
|
||||
switch (sess_info->keytype) {
|
||||
case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC:
|
||||
sess->keytype = QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC;
|
||||
sess->keytype = QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC;
|
||||
break;
|
||||
|
||||
case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE:
|
||||
sess->keytype = QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE;
|
||||
sess->keytype = QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -221,9 +221,9 @@ static void cryptodev_vhost_user_init(
|
||||
cryptodev_vhost_user_event, NULL, s, NULL, true);
|
||||
|
||||
backend->conf.crypto_services =
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_TYPE_CIPHER |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_TYPE_HASH |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_TYPE_MAC;
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_CIPHER |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_HASH |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_MAC;
|
||||
backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
|
||||
backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
|
||||
|
||||
@@ -281,7 +281,8 @@ static int cryptodev_vhost_user_create_session(
|
||||
break;
|
||||
|
||||
default:
|
||||
error_report("Unsupported opcode :%" PRIu32 "", sess_info->op_code);
|
||||
error_setg(&local_error, "Unsupported opcode :%" PRIu32 "",
|
||||
sess_info->op_code);
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ static int qmp_query_cryptodev_foreach(Object *obj, void *data)
|
||||
|
||||
backend = CRYPTODEV_BACKEND(obj);
|
||||
services = backend->conf.crypto_services;
|
||||
for (i = 0; i < QCRYPTODEV_BACKEND_SERVICE_TYPE__MAX; i++) {
|
||||
for (i = 0; i < QCRYPTODEV_BACKEND_SERVICE__MAX; i++) {
|
||||
if (services & (1 << i)) {
|
||||
QAPI_LIST_PREPEND(info->service, i);
|
||||
}
|
||||
@@ -185,10 +185,10 @@ static int cryptodev_backend_operation(
|
||||
static int cryptodev_backend_account(CryptoDevBackend *backend,
|
||||
CryptoDevBackendOpInfo *op_info)
|
||||
{
|
||||
enum QCryptodevBackendAlgoType algtype = op_info->algtype;
|
||||
enum QCryptodevBackendAlgType algtype = op_info->algtype;
|
||||
int len;
|
||||
|
||||
if (algtype == QCRYPTODEV_BACKEND_ALGO_TYPE_ASYM) {
|
||||
if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) {
|
||||
CryptoDevBackendAsymOpInfo *asym_op_info = op_info->u.asym_op_info;
|
||||
len = asym_op_info->src_len;
|
||||
|
||||
@@ -212,7 +212,7 @@ static int cryptodev_backend_account(CryptoDevBackend *backend,
|
||||
default:
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
} else if (algtype == QCRYPTODEV_BACKEND_ALGO_TYPE_SYM) {
|
||||
} else if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) {
|
||||
CryptoDevBackendSymOpInfo *sym_op_info = op_info->u.sym_op_info;
|
||||
len = sym_op_info->src_len;
|
||||
|
||||
@@ -424,11 +424,11 @@ cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
||||
}
|
||||
|
||||
services = backend->conf.crypto_services;
|
||||
if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_TYPE_CIPHER)) {
|
||||
if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_CIPHER)) {
|
||||
backend->sym_stat = g_new0(CryptodevBackendSymStat, 1);
|
||||
}
|
||||
|
||||
if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_TYPE_AKCIPHER)) {
|
||||
if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER)) {
|
||||
backend->asym_stat = g_new0(CryptodevBackendAsymStat, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Host IOMMU device abstract
|
||||
*
|
||||
* Copyright (C) 2024 Intel Corporation.
|
||||
*
|
||||
* Authors: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/host_iommu_device.h"
|
||||
|
||||
OBJECT_DEFINE_ABSTRACT_TYPE(HostIOMMUDevice,
|
||||
host_iommu_device,
|
||||
HOST_IOMMU_DEVICE,
|
||||
OBJECT)
|
||||
|
||||
static void host_iommu_device_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static void host_iommu_device_init(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static void host_iommu_device_finalize(Object *obj)
|
||||
{
|
||||
HostIOMMUDevice *hiod = HOST_IOMMU_DEVICE(obj);
|
||||
|
||||
g_free(hiod->name);
|
||||
}
|
||||
@@ -29,12 +29,13 @@ sgx_epc_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
return false;
|
||||
}
|
||||
|
||||
fd = qemu_open("/dev/sgx_vepc", O_RDWR, errp);
|
||||
fd = qemu_open_old("/dev/sgx_vepc", O_RDWR);
|
||||
if (fd < 0) {
|
||||
error_setg_errno(errp, errno,
|
||||
"failed to open /dev/sgx_vepc to alloc SGX EPC");
|
||||
return false;
|
||||
}
|
||||
|
||||
backend->aligned = true;
|
||||
name = object_get_canonical_path(OBJECT(backend));
|
||||
ram_flags = (backend->share ? RAM_SHARED : 0) | RAM_PROTECTED;
|
||||
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
|
||||
|
||||
@@ -80,13 +80,11 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
backend->aligned = true;
|
||||
name = host_memory_backend_get_name(backend);
|
||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||
ram_flags |= fb->readonly ? RAM_READONLY_FD : 0;
|
||||
ram_flags |= fb->rom == ON_OFF_AUTO_ON ? RAM_READONLY : 0;
|
||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||
ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||
ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
|
||||
ram_flags |= RAM_NAMED_FILE;
|
||||
return memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendMemfd, MEMORY_BACKEND_MEMFD)
|
||||
|
||||
|
||||
@@ -50,11 +52,9 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
return false;
|
||||
}
|
||||
|
||||
backend->aligned = true;
|
||||
name = host_memory_backend_get_name(backend);
|
||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||
ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
|
||||
backend->size, ram_flags, fd, 0, errp);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
name = host_memory_backend_get_name(backend);
|
||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||
ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||
return memory_region_init_ram_flags_nomigrate(&backend->mr, OBJECT(backend),
|
||||
name, backend->size,
|
||||
ram_flags, errp);
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* QEMU host POSIX shared memory object backend
|
||||
*
|
||||
* Copyright (C) 2024 Red Hat Inc
|
||||
*
|
||||
* Authors:
|
||||
* Stefano Garzarella <sgarzare@redhat.com>
|
||||
*
|
||||
* 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 "qemu/osdep.h"
|
||||
#include "sysemu/hostmem.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#define TYPE_MEMORY_BACKEND_SHM "memory-backend-shm"
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendShm, MEMORY_BACKEND_SHM)
|
||||
|
||||
struct HostMemoryBackendShm {
|
||||
HostMemoryBackend parent_obj;
|
||||
};
|
||||
|
||||
static bool
|
||||
shm_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
{
|
||||
g_autoptr(GString) shm_name = g_string_new(NULL);
|
||||
g_autofree char *backend_name = NULL;
|
||||
uint32_t ram_flags;
|
||||
int fd, oflag;
|
||||
mode_t mode;
|
||||
|
||||
if (!backend->size) {
|
||||
error_setg(errp, "can't create shm backend with size 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!backend->share) {
|
||||
error_setg(errp, "can't create shm backend with `share=off`");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Let's use `mode = 0` because we don't want other processes to open our
|
||||
* memory unless we share the file descriptor with them.
|
||||
*/
|
||||
mode = 0;
|
||||
oflag = O_RDWR | O_CREAT | O_EXCL;
|
||||
backend_name = host_memory_backend_get_name(backend);
|
||||
|
||||
/*
|
||||
* Some operating systems allow creating anonymous POSIX shared memory
|
||||
* objects (e.g. FreeBSD provides the SHM_ANON constant), but this is not
|
||||
* defined by POSIX, so let's create a unique name.
|
||||
*
|
||||
* From Linux's shm_open(3) man-page:
|
||||
* For portable use, a shared memory object should be identified
|
||||
* by a name of the form /somename;"
|
||||
*/
|
||||
g_string_printf(shm_name, "/qemu-" FMT_pid "-shm-%s", getpid(),
|
||||
backend_name);
|
||||
|
||||
fd = shm_open(shm_name->str, oflag, mode);
|
||||
if (fd < 0) {
|
||||
error_setg_errno(errp, errno,
|
||||
"failed to create POSIX shared memory");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have the file descriptor, so we no longer need to expose the
|
||||
* POSIX shared memory object. However it will remain allocated as long as
|
||||
* there are file descriptors pointing to it.
|
||||
*/
|
||||
shm_unlink(shm_name->str);
|
||||
|
||||
if (ftruncate(fd, backend->size) == -1) {
|
||||
error_setg_errno(errp, errno,
|
||||
"failed to resize POSIX shared memory to %" PRIu64,
|
||||
backend->size);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
ram_flags = RAM_SHARED;
|
||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||
|
||||
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
|
||||
backend_name, backend->size,
|
||||
ram_flags, fd, 0, errp);
|
||||
}
|
||||
|
||||
static void
|
||||
shm_backend_instance_init(Object *obj)
|
||||
{
|
||||
HostMemoryBackendShm *m = MEMORY_BACKEND_SHM(obj);
|
||||
|
||||
MEMORY_BACKEND(m)->share = true;
|
||||
}
|
||||
|
||||
static void
|
||||
shm_backend_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
|
||||
|
||||
bc->alloc = shm_backend_memory_alloc;
|
||||
}
|
||||
|
||||
static const TypeInfo shm_backend_info = {
|
||||
.name = TYPE_MEMORY_BACKEND_SHM,
|
||||
.parent = TYPE_MEMORY_BACKEND,
|
||||
.instance_init = shm_backend_instance_init,
|
||||
.class_init = shm_backend_class_init,
|
||||
.instance_size = sizeof(HostMemoryBackendShm),
|
||||
};
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&shm_backend_info);
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
+8
-29
@@ -20,7 +20,6 @@
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "qemu/mmap-alloc.h"
|
||||
#include "qemu/madvise.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "hw/qdev-core.h"
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
@@ -170,24 +169,19 @@ static void host_memory_backend_set_merge(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
||||
|
||||
if (QEMU_MADV_MERGEABLE == QEMU_MADV_INVALID) {
|
||||
if (value) {
|
||||
error_setg(errp, "Memory merging is not supported on this host");
|
||||
}
|
||||
assert(!backend->merge);
|
||||
if (!host_memory_backend_mr_inited(backend)) {
|
||||
backend->merge = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (host_memory_backend_mr_inited(backend) &&
|
||||
value != backend->merge) {
|
||||
if (value != backend->merge) {
|
||||
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||
uint64_t sz = memory_region_size(&backend->mr);
|
||||
|
||||
qemu_madvise(ptr, sz,
|
||||
value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE);
|
||||
backend->merge = value;
|
||||
}
|
||||
|
||||
backend->merge = value;
|
||||
}
|
||||
|
||||
static bool host_memory_backend_get_dump(Object *obj, Error **errp)
|
||||
@@ -201,24 +195,19 @@ static void host_memory_backend_set_dump(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
||||
|
||||
if (QEMU_MADV_DONTDUMP == QEMU_MADV_INVALID) {
|
||||
if (!value) {
|
||||
error_setg(errp, "Dumping guest memory cannot be disabled on this host");
|
||||
}
|
||||
assert(backend->dump);
|
||||
if (!host_memory_backend_mr_inited(backend)) {
|
||||
backend->dump = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (host_memory_backend_mr_inited(backend) &&
|
||||
value != backend->dump) {
|
||||
if (value != backend->dump) {
|
||||
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||
uint64_t sz = memory_region_size(&backend->mr);
|
||||
|
||||
qemu_madvise(ptr, sz,
|
||||
value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP);
|
||||
backend->dump = value;
|
||||
}
|
||||
|
||||
backend->dump = value;
|
||||
}
|
||||
|
||||
static bool host_memory_backend_get_prealloc(Object *obj, Error **errp)
|
||||
@@ -288,7 +277,6 @@ static void host_memory_backend_init(Object *obj)
|
||||
/* TODO: convert access to globals to compat properties */
|
||||
backend->merge = machine_mem_merge(machine);
|
||||
backend->dump = machine_dump_guest_core(machine);
|
||||
backend->guest_memfd = machine_require_guest_memfd(machine);
|
||||
backend->reserve = true;
|
||||
backend->prealloc_threads = machine->smp.cpus;
|
||||
}
|
||||
@@ -336,7 +324,6 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
||||
HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
|
||||
void *ptr;
|
||||
uint64_t sz;
|
||||
size_t pagesize;
|
||||
bool async = !phase_check(PHASE_LATE_BACKENDS_CREATED);
|
||||
|
||||
if (!bc->alloc) {
|
||||
@@ -348,14 +335,6 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
||||
|
||||
ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||
sz = memory_region_size(&backend->mr);
|
||||
pagesize = qemu_ram_pagesize(backend->mr.ram_block);
|
||||
|
||||
if (backend->aligned && !QEMU_IS_ALIGNED(sz, pagesize)) {
|
||||
g_autofree char *pagesize_str = size_to_str(pagesize);
|
||||
error_setg(errp, "backend '%s' memory size must be multiple of %s",
|
||||
object_get_typename(OBJECT(uc)), pagesize_str);
|
||||
return;
|
||||
}
|
||||
|
||||
if (backend->merge) {
|
||||
qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE);
|
||||
|
||||
+36
-163
@@ -13,12 +13,12 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/iommufd.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "trace.h"
|
||||
#include "hw/vfio/vfio-common.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/iommufd.h>
|
||||
|
||||
@@ -43,7 +43,6 @@ static void iommufd_backend_finalize(Object *obj)
|
||||
|
||||
static void iommufd_backend_set_fd(Object *obj, const char *str, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
IOMMUFDBackend *be = IOMMUFD_BACKEND(obj);
|
||||
int fd = -1;
|
||||
|
||||
@@ -73,21 +72,24 @@ static void iommufd_backend_class_init(ObjectClass *oc, void *data)
|
||||
object_class_property_add_str(oc, "fd", NULL, iommufd_backend_set_fd);
|
||||
}
|
||||
|
||||
bool iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
|
||||
int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
|
||||
{
|
||||
int fd;
|
||||
int fd, ret = 0;
|
||||
|
||||
if (be->owned && !be->users) {
|
||||
fd = qemu_open("/dev/iommu", O_RDWR, errp);
|
||||
fd = qemu_open_old("/dev/iommu", O_RDWR);
|
||||
if (fd < 0) {
|
||||
return false;
|
||||
error_setg_errno(errp, errno, "/dev/iommu opening failed");
|
||||
ret = fd;
|
||||
goto out;
|
||||
}
|
||||
be->fd = fd;
|
||||
}
|
||||
be->users++;
|
||||
|
||||
trace_iommufd_backend_connect(be->fd, be->owned, be->users);
|
||||
return true;
|
||||
out:
|
||||
trace_iommufd_backend_connect(be->fd, be->owned,
|
||||
be->users, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iommufd_backend_disconnect(IOMMUFDBackend *be)
|
||||
@@ -104,24 +106,25 @@ out:
|
||||
trace_iommufd_backend_disconnect(be->fd, be->users);
|
||||
}
|
||||
|
||||
bool iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id,
|
||||
Error **errp)
|
||||
int iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id,
|
||||
Error **errp)
|
||||
{
|
||||
int fd = be->fd;
|
||||
int ret, fd = be->fd;
|
||||
struct iommu_ioas_alloc alloc_data = {
|
||||
.size = sizeof(alloc_data),
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
if (ioctl(fd, IOMMU_IOAS_ALLOC, &alloc_data)) {
|
||||
ret = ioctl(fd, IOMMU_IOAS_ALLOC, &alloc_data);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, errno, "Failed to allocate ioas");
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*ioas_id = alloc_data.out_ioas_id;
|
||||
trace_iommufd_backend_alloc_ioas(fd, *ioas_id);
|
||||
trace_iommufd_backend_alloc_ioas(fd, *ioas_id, ret);
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iommufd_backend_free_id(IOMMUFDBackend *be, uint32_t id)
|
||||
@@ -208,153 +211,23 @@ int iommufd_backend_unmap_dma(IOMMUFDBackend *be, uint32_t ioas_id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool iommufd_backend_alloc_hwpt(IOMMUFDBackend *be, uint32_t dev_id,
|
||||
uint32_t pt_id, uint32_t flags,
|
||||
uint32_t data_type, uint32_t data_len,
|
||||
void *data_ptr, uint32_t *out_hwpt,
|
||||
Error **errp)
|
||||
{
|
||||
int ret, fd = be->fd;
|
||||
struct iommu_hwpt_alloc alloc_hwpt = {
|
||||
.size = sizeof(struct iommu_hwpt_alloc),
|
||||
.flags = flags,
|
||||
.dev_id = dev_id,
|
||||
.pt_id = pt_id,
|
||||
.data_type = data_type,
|
||||
.data_len = data_len,
|
||||
.data_uptr = (uintptr_t)data_ptr,
|
||||
};
|
||||
|
||||
ret = ioctl(fd, IOMMU_HWPT_ALLOC, &alloc_hwpt);
|
||||
trace_iommufd_backend_alloc_hwpt(fd, dev_id, pt_id, flags, data_type,
|
||||
data_len, (uintptr_t)data_ptr,
|
||||
alloc_hwpt.out_hwpt_id, ret);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, errno, "Failed to allocate hwpt");
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_hwpt = alloc_hwpt.out_hwpt_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool iommufd_backend_set_dirty_tracking(IOMMUFDBackend *be,
|
||||
uint32_t hwpt_id, bool start,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
struct iommu_hwpt_set_dirty_tracking set_dirty = {
|
||||
.size = sizeof(set_dirty),
|
||||
.hwpt_id = hwpt_id,
|
||||
.flags = start ? IOMMU_HWPT_DIRTY_TRACKING_ENABLE : 0,
|
||||
};
|
||||
|
||||
ret = ioctl(be->fd, IOMMU_HWPT_SET_DIRTY_TRACKING, &set_dirty);
|
||||
trace_iommufd_backend_set_dirty(be->fd, hwpt_id, start, ret ? errno : 0);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, errno,
|
||||
"IOMMU_HWPT_SET_DIRTY_TRACKING(hwpt_id %u) failed",
|
||||
hwpt_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool iommufd_backend_get_dirty_bitmap(IOMMUFDBackend *be,
|
||||
uint32_t hwpt_id,
|
||||
uint64_t iova, ram_addr_t size,
|
||||
uint64_t page_size, uint64_t *data,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
struct iommu_hwpt_get_dirty_bitmap get_dirty_bitmap = {
|
||||
.size = sizeof(get_dirty_bitmap),
|
||||
.hwpt_id = hwpt_id,
|
||||
.iova = iova,
|
||||
.length = size,
|
||||
.page_size = page_size,
|
||||
.data = (uintptr_t)data,
|
||||
};
|
||||
|
||||
ret = ioctl(be->fd, IOMMU_HWPT_GET_DIRTY_BITMAP, &get_dirty_bitmap);
|
||||
trace_iommufd_backend_get_dirty_bitmap(be->fd, hwpt_id, iova, size,
|
||||
page_size, ret ? errno : 0);
|
||||
if (ret) {
|
||||
error_setg_errno(errp, errno,
|
||||
"IOMMU_HWPT_GET_DIRTY_BITMAP (iova: 0x%"HWADDR_PRIx
|
||||
" size: 0x"RAM_ADDR_FMT") failed", iova, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool iommufd_backend_get_device_info(IOMMUFDBackend *be, uint32_t devid,
|
||||
uint32_t *type, void *data, uint32_t len,
|
||||
uint64_t *caps, Error **errp)
|
||||
{
|
||||
struct iommu_hw_info info = {
|
||||
.size = sizeof(info),
|
||||
.dev_id = devid,
|
||||
.data_len = len,
|
||||
.data_uptr = (uintptr_t)data,
|
||||
};
|
||||
|
||||
if (ioctl(be->fd, IOMMU_GET_HW_INFO, &info)) {
|
||||
error_setg_errno(errp, errno, "Failed to get hardware info");
|
||||
return false;
|
||||
}
|
||||
|
||||
g_assert(type);
|
||||
*type = info.out_data_type;
|
||||
g_assert(caps);
|
||||
*caps = info.out_capabilities;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int hiod_iommufd_get_cap(HostIOMMUDevice *hiod, int cap, Error **errp)
|
||||
{
|
||||
HostIOMMUDeviceCaps *caps = &hiod->caps;
|
||||
|
||||
switch (cap) {
|
||||
case HOST_IOMMU_DEVICE_CAP_IOMMU_TYPE:
|
||||
return caps->type;
|
||||
case HOST_IOMMU_DEVICE_CAP_AW_BITS:
|
||||
return vfio_device_get_aw_bits(hiod->agent);
|
||||
default:
|
||||
error_setg(errp, "%s: unsupported capability %x", hiod->name, cap);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void hiod_iommufd_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
HostIOMMUDeviceClass *hioc = HOST_IOMMU_DEVICE_CLASS(oc);
|
||||
|
||||
hioc->get_cap = hiod_iommufd_get_cap;
|
||||
};
|
||||
|
||||
static const TypeInfo types[] = {
|
||||
{
|
||||
.name = TYPE_IOMMUFD_BACKEND,
|
||||
.parent = TYPE_OBJECT,
|
||||
.instance_size = sizeof(IOMMUFDBackend),
|
||||
.instance_init = iommufd_backend_init,
|
||||
.instance_finalize = iommufd_backend_finalize,
|
||||
.class_size = sizeof(IOMMUFDBackendClass),
|
||||
.class_init = iommufd_backend_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_USER_CREATABLE },
|
||||
{ }
|
||||
}
|
||||
}, {
|
||||
.name = TYPE_HOST_IOMMU_DEVICE_IOMMUFD,
|
||||
.parent = TYPE_HOST_IOMMU_DEVICE,
|
||||
.class_init = hiod_iommufd_class_init,
|
||||
.abstract = true,
|
||||
static const TypeInfo iommufd_backend_info = {
|
||||
.name = TYPE_IOMMUFD_BACKEND,
|
||||
.parent = TYPE_OBJECT,
|
||||
.instance_size = sizeof(IOMMUFDBackend),
|
||||
.instance_init = iommufd_backend_init,
|
||||
.instance_finalize = iommufd_backend_finalize,
|
||||
.class_size = sizeof(IOMMUFDBackendClass),
|
||||
.class_init = iommufd_backend_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_USER_CREATABLE },
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
DEFINE_TYPES(types)
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&iommufd_backend_info);
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
|
||||
@@ -13,11 +13,9 @@ system_ss.add([files(
|
||||
if host_os != 'windows'
|
||||
system_ss.add(files('rng-random.c'))
|
||||
system_ss.add(files('hostmem-file.c'))
|
||||
system_ss.add([files('hostmem-shm.c'), rt])
|
||||
endif
|
||||
if host_os == 'linux'
|
||||
system_ss.add(files('hostmem-memfd.c'))
|
||||
system_ss.add(files('host_iommu_device.c'))
|
||||
endif
|
||||
if keyutils.found()
|
||||
system_ss.add(keyutils, files('cryptodev-lkcf.c'))
|
||||
@@ -33,6 +31,4 @@ endif
|
||||
system_ss.add(when: gio, if_true: files('dbus-vmstate.c'))
|
||||
system_ss.add(when: 'CONFIG_SGX', if_true: files('hostmem-epc.c'))
|
||||
|
||||
system_ss.add(when: 'CONFIG_SPDM_SOCKET', if_true: files('spdm-socket.c'))
|
||||
|
||||
subdir('tpm')
|
||||
|
||||
@@ -75,7 +75,10 @@ static void rng_random_opened(RngBackend *b, Error **errp)
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
|
||||
"filename", "a valid filename");
|
||||
} else {
|
||||
s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK, errp);
|
||||
s->fd = qemu_open_old(s->filename, O_RDONLY | O_NONBLOCK);
|
||||
if (s->fd == -1) {
|
||||
error_setg_file_open(errp, errno, s->filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* QEMU SPDM socket support
|
||||
*
|
||||
* This is based on:
|
||||
* https://github.com/DMTF/spdm-emu/blob/07c0a838bcc1c6207c656ac75885c0603e344b6f/spdm_emu/spdm_emu_common/command.c
|
||||
* but has been re-written to match QEMU style
|
||||
*
|
||||
* Copyright (c) 2021, DMTF. All rights reserved.
|
||||
* Copyright (c) 2023. Western Digital Corporation or its affiliates.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/spdm-socket.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
static bool read_bytes(const int socket, uint8_t *buffer,
|
||||
size_t number_of_bytes)
|
||||
{
|
||||
ssize_t number_received = 0;
|
||||
ssize_t result;
|
||||
|
||||
while (number_received < number_of_bytes) {
|
||||
result = recv(socket, buffer + number_received,
|
||||
number_of_bytes - number_received, 0);
|
||||
if (result <= 0) {
|
||||
return false;
|
||||
}
|
||||
number_received += result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_data32(const int socket, uint32_t *data)
|
||||
{
|
||||
bool result;
|
||||
|
||||
result = read_bytes(socket, (uint8_t *)data, sizeof(uint32_t));
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
*data = ntohl(*data);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_multiple_bytes(const int socket, uint8_t *buffer,
|
||||
uint32_t *bytes_received,
|
||||
uint32_t max_buffer_length)
|
||||
{
|
||||
uint32_t length;
|
||||
bool result;
|
||||
|
||||
result = read_data32(socket, &length);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (length > max_buffer_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bytes_received) {
|
||||
*bytes_received = length;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return read_bytes(socket, buffer, length);
|
||||
}
|
||||
|
||||
static bool receive_platform_data(const int socket,
|
||||
uint32_t transport_type,
|
||||
uint32_t *command,
|
||||
uint8_t *receive_buffer,
|
||||
uint32_t *bytes_to_receive)
|
||||
{
|
||||
bool result;
|
||||
uint32_t response;
|
||||
uint32_t bytes_received;
|
||||
|
||||
result = read_data32(socket, &response);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
*command = response;
|
||||
|
||||
result = read_data32(socket, &transport_type);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bytes_received = 0;
|
||||
result = read_multiple_bytes(socket, receive_buffer, &bytes_received,
|
||||
*bytes_to_receive);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
*bytes_to_receive = bytes_received;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool write_bytes(const int socket, const uint8_t *buffer,
|
||||
uint32_t number_of_bytes)
|
||||
{
|
||||
ssize_t number_sent = 0;
|
||||
ssize_t result;
|
||||
|
||||
while (number_sent < number_of_bytes) {
|
||||
result = send(socket, buffer + number_sent,
|
||||
number_of_bytes - number_sent, 0);
|
||||
if (result == -1) {
|
||||
return false;
|
||||
}
|
||||
number_sent += result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool write_data32(const int socket, uint32_t data)
|
||||
{
|
||||
data = htonl(data);
|
||||
return write_bytes(socket, (uint8_t *)&data, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
static bool write_multiple_bytes(const int socket, const uint8_t *buffer,
|
||||
uint32_t bytes_to_send)
|
||||
{
|
||||
bool result;
|
||||
|
||||
result = write_data32(socket, bytes_to_send);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return write_bytes(socket, buffer, bytes_to_send);
|
||||
}
|
||||
|
||||
static bool send_platform_data(const int socket,
|
||||
uint32_t transport_type, uint32_t command,
|
||||
const uint8_t *send_buffer, size_t bytes_to_send)
|
||||
{
|
||||
bool result;
|
||||
|
||||
result = write_data32(socket, command);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = write_data32(socket, transport_type);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return write_multiple_bytes(socket, send_buffer, bytes_to_send);
|
||||
}
|
||||
|
||||
int spdm_socket_connect(uint16_t port, Error **errp)
|
||||
{
|
||||
int client_socket;
|
||||
struct sockaddr_in server_addr;
|
||||
|
||||
client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (client_socket < 0) {
|
||||
error_setg(errp, "cannot create socket: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset((char *)&server_addr, 0, sizeof(server_addr));
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
server_addr.sin_port = htons(port);
|
||||
|
||||
|
||||
if (connect(client_socket, (struct sockaddr *)&server_addr,
|
||||
sizeof(server_addr)) < 0) {
|
||||
error_setg(errp, "cannot connect: %s", strerror(errno));
|
||||
close(client_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return client_socket;
|
||||
}
|
||||
|
||||
uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type,
|
||||
void *req, uint32_t req_len,
|
||||
void *rsp, uint32_t rsp_len)
|
||||
{
|
||||
uint32_t command;
|
||||
bool result;
|
||||
|
||||
result = send_platform_data(socket, transport_type,
|
||||
SPDM_SOCKET_COMMAND_NORMAL,
|
||||
req, req_len);
|
||||
if (!result) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = receive_platform_data(socket, transport_type, &command,
|
||||
(uint8_t *)rsp, &rsp_len);
|
||||
if (!result) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(command != 0);
|
||||
|
||||
return rsp_len;
|
||||
}
|
||||
|
||||
void spdm_socket_close(const int socket, uint32_t transport_type)
|
||||
{
|
||||
send_platform_data(socket, transport_type,
|
||||
SPDM_SOCKET_COMMAND_SHUTDOWN, NULL, 0);
|
||||
}
|
||||
+21
-53
@@ -72,7 +72,7 @@ struct TPMEmulator {
|
||||
CharBackend ctrl_chr;
|
||||
QIOChannel *data_ioc;
|
||||
TPMVersion tpm_version;
|
||||
uint32_t caps; /* capabilities of the TPM */
|
||||
ptm_cap caps; /* capabilities of the TPM */
|
||||
uint8_t cur_locty_number; /* last set locality */
|
||||
Error *migration_blocker;
|
||||
|
||||
@@ -123,14 +123,12 @@ static const char *tpm_emulator_strerror(uint32_t tpm_result)
|
||||
}
|
||||
|
||||
static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
|
||||
size_t msg_len_in, size_t msg_len_out_err,
|
||||
size_t msg_len_out_total)
|
||||
size_t msg_len_in, size_t msg_len_out)
|
||||
{
|
||||
CharBackend *dev = &tpm->ctrl_chr;
|
||||
uint32_t cmd_no = cpu_to_be32(cmd);
|
||||
ssize_t n = sizeof(uint32_t) + msg_len_in;
|
||||
uint8_t *buf = NULL;
|
||||
ptm_res res;
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&tpm->mutex) {
|
||||
buf = g_alloca(n);
|
||||
@@ -142,25 +140,8 @@ static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg_len_out_total > 0) {
|
||||
assert(msg_len_out_total >= msg_len_out_err);
|
||||
|
||||
n = qemu_chr_fe_read_all(dev, (uint8_t *)msg, msg_len_out_err);
|
||||
if (n <= 0) {
|
||||
return -1;
|
||||
}
|
||||
if (msg_len_out_err == msg_len_out_total) {
|
||||
return 0;
|
||||
}
|
||||
/* result error code is always in the first 4 bytes */
|
||||
assert(sizeof(res) <= msg_len_out_err);
|
||||
memcpy(&res, msg, sizeof(res));
|
||||
if (res) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = qemu_chr_fe_read_all(dev, (uint8_t *)msg + msg_len_out_err,
|
||||
msg_len_out_total - msg_len_out_err);
|
||||
if (msg_len_out != 0) {
|
||||
n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
|
||||
if (n <= 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -223,8 +204,7 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number,
|
||||
memset(&loc, 0, sizeof(loc));
|
||||
loc.u.req.loc = locty_number;
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc,
|
||||
sizeof(loc), sizeof(loc.u.resp.tpm_result),
|
||||
sizeof(loc)) < 0) {
|
||||
sizeof(loc), sizeof(loc)) < 0) {
|
||||
error_setg(errp, "tpm-emulator: could not set locality : %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
@@ -259,16 +239,13 @@ static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
|
||||
|
||||
static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
|
||||
{
|
||||
ptm_cap_n cap_n;
|
||||
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY, &cap_n, 0,
|
||||
sizeof(cap_n.u.resp.tpm_result),
|
||||
sizeof(cap_n)) < 0) {
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_CAPABILITY,
|
||||
&tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
|
||||
error_report("tpm-emulator: probing failed : %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
tpm_emu->caps = be32_to_cpu(cap_n.u.resp.caps);
|
||||
tpm_emu->caps = be64_to_cpu(tpm_emu->caps);
|
||||
|
||||
trace_tpm_emulator_probe_caps(tpm_emu->caps);
|
||||
|
||||
@@ -277,7 +254,7 @@ static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
|
||||
|
||||
static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
|
||||
{
|
||||
uint32_t caps = 0;
|
||||
ptm_cap caps = 0;
|
||||
const char *tpm = NULL;
|
||||
|
||||
/* check for min. required capabilities */
|
||||
@@ -313,8 +290,7 @@ static int tpm_emulator_stop_tpm(TPMBackend *tb)
|
||||
TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
|
||||
ptm_res res;
|
||||
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0,
|
||||
sizeof(ptm_res), sizeof(res)) < 0) {
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) {
|
||||
error_report("tpm-emulator: Could not stop TPM: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
@@ -341,9 +317,8 @@ static int tpm_emulator_lock_storage(TPMEmulator *tpm_emu)
|
||||
|
||||
/* give failing side 300 * 10ms time to release lock */
|
||||
pls.u.req.retries = cpu_to_be32(300);
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_LOCK_STORAGE, &pls, sizeof(pls.u.req),
|
||||
sizeof(pls.u.resp.tpm_result),
|
||||
sizeof(pls.u.resp)) < 0) {
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_LOCK_STORAGE, &pls,
|
||||
sizeof(pls.u.req), sizeof(pls.u.resp)) < 0) {
|
||||
error_report("tpm-emulator: Could not lock storage within 3 seconds: "
|
||||
"%s", strerror(errno));
|
||||
return -1;
|
||||
@@ -374,8 +349,7 @@ static int tpm_emulator_set_buffer_size(TPMBackend *tb,
|
||||
psbs.u.req.buffersize = cpu_to_be32(wanted_size);
|
||||
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs,
|
||||
sizeof(psbs.u.req), sizeof(psbs.u.resp.tpm_result),
|
||||
sizeof(psbs.u.resp)) < 0) {
|
||||
sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) {
|
||||
error_report("tpm-emulator: Could not set buffer size: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
@@ -422,7 +396,6 @@ static int tpm_emulator_startup_tpm_resume(TPMBackend *tb, size_t buffersize,
|
||||
}
|
||||
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init),
|
||||
sizeof(init.u.resp.tpm_result),
|
||||
sizeof(init)) < 0) {
|
||||
error_report("tpm-emulator: could not send INIT: %s",
|
||||
strerror(errno));
|
||||
@@ -464,9 +437,8 @@ static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
|
||||
return tpm_emu->established_flag;
|
||||
}
|
||||
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_TPMESTABLISHED, &est, 0,
|
||||
sizeof(est) /* always returns resp.bit */,
|
||||
sizeof(est)) < 0) {
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_TPMESTABLISHED, &est,
|
||||
0, sizeof(est)) < 0) {
|
||||
error_report("tpm-emulator: Could not get the TPM established flag: %s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
@@ -494,7 +466,6 @@ static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
|
||||
reset_est.u.req.loc = tpm_emu->cur_locty_number;
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_RESET_TPMESTABLISHED,
|
||||
&reset_est, sizeof(reset_est),
|
||||
sizeof(reset_est.u.resp.tpm_result),
|
||||
sizeof(reset_est)) < 0) {
|
||||
error_report("tpm-emulator: Could not reset the establishment bit: %s",
|
||||
strerror(errno));
|
||||
@@ -526,7 +497,7 @@ static void tpm_emulator_cancel_cmd(TPMBackend *tb)
|
||||
|
||||
/* FIXME: make the function non-blocking, or it may block a VCPU */
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_CANCEL_TPM_CMD, &res, 0,
|
||||
sizeof(ptm_res), sizeof(res)) < 0) {
|
||||
sizeof(res)) < 0) {
|
||||
error_report("tpm-emulator: Could not cancel command: %s",
|
||||
strerror(errno));
|
||||
} else if (res != 0) {
|
||||
@@ -556,8 +527,8 @@ static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
|
||||
static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
|
||||
{
|
||||
Error *err = NULL;
|
||||
uint32_t caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
|
||||
PTM_CAP_STOP;
|
||||
ptm_cap caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB |
|
||||
PTM_CAP_STOP;
|
||||
|
||||
if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
|
||||
error_setg(&tpm_emu->migration_blocker,
|
||||
@@ -586,7 +557,7 @@ static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
|
||||
qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1);
|
||||
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_DATAFD, &res, 0,
|
||||
sizeof(ptm_res), sizeof(res)) < 0 || res != 0) {
|
||||
sizeof(res)) < 0 || res != 0) {
|
||||
error_report("tpm-emulator: Failed to send CMD_SET_DATAFD: %s",
|
||||
strerror(errno));
|
||||
goto err_exit;
|
||||
@@ -733,8 +704,6 @@ static int tpm_emulator_get_state_blob(TPMEmulator *tpm_emu,
|
||||
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_STATEBLOB,
|
||||
&pgs, sizeof(pgs.u.req),
|
||||
/* always returns up to resp.data */
|
||||
offsetof(ptm_getstate, u.resp.data),
|
||||
offsetof(ptm_getstate, u.resp.data)) < 0) {
|
||||
error_report("tpm-emulator: could not get state blob type %d : %s",
|
||||
type, strerror(errno));
|
||||
@@ -837,7 +806,7 @@ static int tpm_emulator_set_state_blob(TPMEmulator *tpm_emu,
|
||||
|
||||
/* write the header only */
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_STATEBLOB, &pss,
|
||||
offsetof(ptm_setstate, u.req.data), 0, 0) < 0) {
|
||||
offsetof(ptm_setstate, u.req.data), 0) < 0) {
|
||||
error_report("tpm-emulator: could not set state blob type %d : %s",
|
||||
type, strerror(errno));
|
||||
return -1;
|
||||
@@ -1021,8 +990,7 @@ static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0,
|
||||
sizeof(ptm_res), sizeof(res)) < 0) {
|
||||
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SHUTDOWN, &res, 0, sizeof(res)) < 0) {
|
||||
error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
|
||||
strerror(errno));
|
||||
} else if (res != 0) {
|
||||
|
||||
@@ -29,16 +29,6 @@
|
||||
|
||||
typedef uint32_t ptm_res;
|
||||
|
||||
/* PTM_GET_CAPABILITY: Get supported capabilities (ioctl's) */
|
||||
struct ptm_cap_n {
|
||||
union {
|
||||
struct {
|
||||
ptm_res tpm_result; /* will always be TPM_SUCCESS (0) */
|
||||
uint32_t caps;
|
||||
} resp; /* response */
|
||||
} u;
|
||||
};
|
||||
|
||||
/* PTM_GET_TPMESTABLISHED: get the establishment bit */
|
||||
struct ptm_est {
|
||||
union {
|
||||
@@ -252,8 +242,7 @@ struct ptm_lockstorage {
|
||||
} u;
|
||||
};
|
||||
|
||||
typedef uint64_t ptm_cap; /* CUSE-only; use ptm_cap_n otherwise */
|
||||
typedef struct ptm_cap_n ptm_cap_n;
|
||||
typedef uint64_t ptm_cap;
|
||||
typedef struct ptm_est ptm_est;
|
||||
typedef struct ptm_reset_est ptm_reset_est;
|
||||
typedef struct ptm_loc ptm_loc;
|
||||
|
||||
@@ -339,11 +339,10 @@ void tpm_util_show_buffer(const unsigned char *buffer,
|
||||
size_t len, i;
|
||||
char *line_buffer, *p;
|
||||
|
||||
if (!trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER_CONTENT)) {
|
||||
if (!trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) {
|
||||
return;
|
||||
}
|
||||
len = MIN(tpm_cmd_get_size(buffer), buffer_size);
|
||||
trace_tpm_util_show_buffer_header(string, len);
|
||||
|
||||
/*
|
||||
* allocate enough room for 3 chars per buffer entry plus a
|
||||
@@ -357,7 +356,7 @@ void tpm_util_show_buffer(const unsigned char *buffer,
|
||||
}
|
||||
p += sprintf(p, "%.2X ", buffer[i]);
|
||||
}
|
||||
trace_tpm_util_show_buffer_content(line_buffer);
|
||||
trace_tpm_util_show_buffer(string, len, line_buffer);
|
||||
|
||||
g_free(line_buffer);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,12 @@ tpm_util_get_buffer_size_len(uint32_t len, size_t expected) "tpm_resp->len = %u,
|
||||
tpm_util_get_buffer_size_hdr_len2(uint32_t len, size_t expected) "tpm2_resp->hdr.len = %u, expected = %zu"
|
||||
tpm_util_get_buffer_size_len2(uint32_t len, size_t expected) "tpm2_resp->len = %u, expected = %zu"
|
||||
tpm_util_get_buffer_size(size_t len) "buffersize of device: %zu"
|
||||
tpm_util_show_buffer_header(const char *direction, size_t len) "direction: %s len: %zu"
|
||||
tpm_util_show_buffer_content(const char *buf) "%s"
|
||||
tpm_util_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s"
|
||||
|
||||
# tpm_emulator.c
|
||||
tpm_emulator_set_locality(uint8_t locty) "setting locality to %d"
|
||||
tpm_emulator_handle_request(void) "processing TPM command"
|
||||
tpm_emulator_probe_caps(uint32_t caps) "capabilities: 0x%x"
|
||||
tpm_emulator_probe_caps(uint64_t caps) "capabilities: 0x%"PRIx64
|
||||
tpm_emulator_set_buffer_size(uint32_t buffersize, uint32_t minsize, uint32_t maxsize) "buffer size: %u, min: %u, max: %u"
|
||||
tpm_emulator_startup_tpm_resume(bool is_resume, size_t buffersize) "is_resume: %d, buffer size: %zu"
|
||||
tpm_emulator_get_tpm_established_flag(uint8_t flag) "got established flag: %d"
|
||||
|
||||
@@ -7,14 +7,11 @@ dbus_vmstate_loading(const char *id) "id: %s"
|
||||
dbus_vmstate_saving(const char *id) "id: %s"
|
||||
|
||||
# iommufd.c
|
||||
iommufd_backend_connect(int fd, bool owned, uint32_t users) "fd=%d owned=%d users=%d"
|
||||
iommufd_backend_connect(int fd, bool owned, uint32_t users, int ret) "fd=%d owned=%d users=%d (%d)"
|
||||
iommufd_backend_disconnect(int fd, uint32_t users) "fd=%d users=%d"
|
||||
iommu_backend_set_fd(int fd) "pre-opened /dev/iommu fd=%d"
|
||||
iommufd_backend_map_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, void *vaddr, bool readonly, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" addr=%p readonly=%d (%d)"
|
||||
iommufd_backend_unmap_dma_non_exist(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " Unmap nonexistent mapping: iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)"
|
||||
iommufd_backend_unmap_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)"
|
||||
iommufd_backend_alloc_ioas(int iommufd, uint32_t ioas) " iommufd=%d ioas=%d"
|
||||
iommufd_backend_alloc_hwpt(int iommufd, uint32_t dev_id, uint32_t pt_id, uint32_t flags, uint32_t hwpt_type, uint32_t len, uint64_t data_ptr, uint32_t out_hwpt_id, int ret) " iommufd=%d dev_id=%u pt_id=%u flags=0x%x hwpt_type=%u len=%u data_ptr=0x%"PRIx64" out_hwpt=%u (%d)"
|
||||
iommufd_backend_alloc_ioas(int iommufd, uint32_t ioas, int ret) " iommufd=%d ioas=%d (%d)"
|
||||
iommufd_backend_free_id(int iommufd, uint32_t id, int ret) " iommufd=%d id=%d (%d)"
|
||||
iommufd_backend_set_dirty(int iommufd, uint32_t hwpt_id, bool start, int ret) " iommufd=%d hwpt=%u enable=%d (%d)"
|
||||
iommufd_backend_get_dirty_bitmap(int iommufd, uint32_t hwpt_id, uint64_t iova, uint64_t size, uint64_t page_size, int ret) " iommufd=%d hwpt=%u iova=0x%"PRIx64" size=0x%"PRIx64" page_size=0x%"PRIx64" (%d)"
|
||||
|
||||
@@ -86,7 +86,6 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role,
|
||||
bool parse_filename,
|
||||
Error **errp);
|
||||
|
||||
static bool bdrv_recurse_has_child(BlockDriverState *bs,
|
||||
@@ -535,9 +534,9 @@ typedef struct CreateCo {
|
||||
int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename,
|
||||
QemuOpts *opts, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
int ret;
|
||||
GLOBAL_STATE_CODE();
|
||||
ERRP_GUARD();
|
||||
|
||||
if (!drv->bdrv_co_create_opts) {
|
||||
error_setg(errp, "Driver '%s' does not support image creation",
|
||||
@@ -634,7 +633,6 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv,
|
||||
QemuOpts *opts,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
BlockBackend *blk;
|
||||
QDict *options;
|
||||
int64_t size = 0;
|
||||
@@ -927,6 +925,7 @@ BlockDriver *bdrv_find_protocol(const char *filename,
|
||||
int i;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
/* TODO Drivers without bdrv_file_open must be specified explicitly */
|
||||
|
||||
/*
|
||||
* XXX(hch): we really should not let host device detection
|
||||
@@ -1655,8 +1654,10 @@ bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name,
|
||||
bs->drv = drv;
|
||||
bs->opaque = g_malloc0(drv->instance_size);
|
||||
|
||||
assert(!drv->bdrv_needs_filename || bs->filename[0]);
|
||||
if (drv->bdrv_open) {
|
||||
if (drv->bdrv_file_open) {
|
||||
assert(!drv->bdrv_needs_filename || bs->filename[0]);
|
||||
ret = drv->bdrv_file_open(bs, options, open_flags, &local_err);
|
||||
} else if (drv->bdrv_open) {
|
||||
ret = drv->bdrv_open(bs, options, open_flags, &local_err);
|
||||
} else {
|
||||
ret = 0;
|
||||
@@ -1981,7 +1982,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
|
||||
open_flags = bdrv_open_flags(bs, bs->open_flags);
|
||||
node_name = qemu_opt_get(opts, "node-name");
|
||||
|
||||
assert(!drv->protocol_name || file == NULL);
|
||||
assert(!drv->bdrv_file_open || file == NULL);
|
||||
ret = bdrv_open_driver(bs, drv, node_name, options, open_flags, errp);
|
||||
if (ret < 0) {
|
||||
goto fail_opts;
|
||||
@@ -1997,7 +1998,6 @@ fail_opts:
|
||||
|
||||
static QDict *parse_json_filename(const char *filename, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
QObject *options_obj;
|
||||
QDict *options;
|
||||
int ret;
|
||||
@@ -2056,8 +2056,7 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
|
||||
* block driver has been specified explicitly.
|
||||
*/
|
||||
static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
int *flags, bool allow_parse_filename,
|
||||
Error **errp)
|
||||
int *flags, Error **errp)
|
||||
{
|
||||
const char *drvname;
|
||||
bool protocol = *flags & BDRV_O_PROTOCOL;
|
||||
@@ -2083,7 +2082,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
}
|
||||
/* If the user has explicitly specified the driver, this choice should
|
||||
* override the BDRV_O_PROTOCOL flag */
|
||||
protocol = drv->protocol_name;
|
||||
protocol = drv->bdrv_file_open;
|
||||
}
|
||||
|
||||
if (protocol) {
|
||||
@@ -2099,7 +2098,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
if (protocol && filename) {
|
||||
if (!qdict_haskey(*options, "filename")) {
|
||||
qdict_put_str(*options, "filename", filename);
|
||||
parse_filename = allow_parse_filename;
|
||||
parse_filename = true;
|
||||
} else {
|
||||
error_setg(errp, "Can't specify 'file' and 'filename' options at "
|
||||
"the same time");
|
||||
@@ -3586,7 +3585,6 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
const char *bdref_key, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
char *backing_filename = NULL;
|
||||
char *bdref_key_dot;
|
||||
const char *reference = NULL;
|
||||
@@ -3662,8 +3660,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
}
|
||||
|
||||
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
|
||||
&child_of_bds, bdrv_backing_role(bs), true,
|
||||
errp);
|
||||
&child_of_bds, bdrv_backing_role(bs), errp);
|
||||
if (!backing_hd) {
|
||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||
error_prepend(errp, "Could not open backing file: ");
|
||||
@@ -3697,8 +3694,7 @@ free_exit:
|
||||
static BlockDriverState *
|
||||
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||
BlockDriverState *parent, const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role, bool allow_none,
|
||||
bool parse_filename, Error **errp)
|
||||
BdrvChildRole child_role, bool allow_none, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
QDict *image_options;
|
||||
@@ -3729,8 +3725,7 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||
}
|
||||
|
||||
bs = bdrv_open_inherit(filename, reference, image_options, 0,
|
||||
parent, child_class, child_role, parse_filename,
|
||||
errp);
|
||||
parent, child_class, child_role, errp);
|
||||
if (!bs) {
|
||||
goto done;
|
||||
}
|
||||
@@ -3740,33 +3735,6 @@ done:
|
||||
return bs;
|
||||
}
|
||||
|
||||
static BdrvChild *bdrv_open_child_common(const char *filename,
|
||||
QDict *options, const char *bdref_key,
|
||||
BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role,
|
||||
bool allow_none, bool parse_filename,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BdrvChild *child;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
||||
child_role, allow_none, parse_filename, errp);
|
||||
if (bs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdrv_graph_wrlock();
|
||||
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
errp);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens a disk image whose options are given as BlockdevRef in another block
|
||||
* device's options.
|
||||
@@ -3790,15 +3758,27 @@ BdrvChild *bdrv_open_child(const char *filename,
|
||||
BdrvChildRole child_role,
|
||||
bool allow_none, Error **errp)
|
||||
{
|
||||
return bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||
child_class, child_role, allow_none, false,
|
||||
errp);
|
||||
BlockDriverState *bs;
|
||||
BdrvChild *child;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
||||
child_role, allow_none, errp);
|
||||
if (bs == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdrv_graph_wrlock();
|
||||
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
errp);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* This does mostly the same as bdrv_open_child(), but for opening the primary
|
||||
* child of a node. A notable difference from bdrv_open_child() is that it
|
||||
* enables filename parsing for protocol names (including json:).
|
||||
* Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
|
||||
*
|
||||
* @parent can move to a different AioContext in this function.
|
||||
*/
|
||||
@@ -3813,8 +3793,8 @@ int bdrv_open_file_child(const char *filename,
|
||||
role = parent->drv->is_filter ?
|
||||
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
|
||||
|
||||
if (!bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||
&child_of_bds, role, false, true, errp))
|
||||
if (!bdrv_open_child(filename, options, bdref_key, parent,
|
||||
&child_of_bds, role, false, errp))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -3859,8 +3839,7 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
|
||||
|
||||
}
|
||||
|
||||
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
|
||||
errp);
|
||||
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
|
||||
obj = NULL;
|
||||
qobject_unref(obj);
|
||||
visit_free(v);
|
||||
@@ -3872,7 +3851,6 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
||||
QDict *snapshot_options,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
g_autofree char *tmp_filename = NULL;
|
||||
int64_t total_size;
|
||||
QemuOpts *opts = NULL;
|
||||
@@ -3950,7 +3928,7 @@ static BlockDriverState * no_coroutine_fn
|
||||
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
int flags, BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class, BdrvChildRole child_role,
|
||||
bool parse_filename, Error **errp)
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
BlockBackend *file = NULL;
|
||||
@@ -3998,11 +3976,9 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
}
|
||||
|
||||
/* json: syntax counts as explicit options, as if in the QDict */
|
||||
if (parse_filename) {
|
||||
parse_json_protocol(options, &filename, &local_err);
|
||||
if (local_err) {
|
||||
goto fail;
|
||||
}
|
||||
parse_json_protocol(options, &filename, &local_err);
|
||||
if (local_err) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bs->explicit_options = qdict_clone_shallow(options);
|
||||
@@ -4027,8 +4003,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
parent->open_flags, parent->options);
|
||||
}
|
||||
|
||||
ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
|
||||
&local_err);
|
||||
ret = bdrv_fill_options(&options, filename, &flags, &local_err);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -4097,7 +4072,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
|
||||
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
|
||||
&child_of_bds, BDRV_CHILD_IMAGE,
|
||||
true, true, &local_err);
|
||||
true, &local_err);
|
||||
if (local_err) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -4144,7 +4119,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
}
|
||||
|
||||
/* BDRV_O_PROTOCOL must be set iff a protocol BDS is about to be created */
|
||||
assert(!!(flags & BDRV_O_PROTOCOL) == !!drv->protocol_name);
|
||||
assert(!!(flags & BDRV_O_PROTOCOL) == !!drv->bdrv_file_open);
|
||||
/* file must be NULL if a protocol BDS is about to be created
|
||||
* (the inverse results in an error message from bdrv_open_common()) */
|
||||
assert(!(flags & BDRV_O_PROTOCOL) || !file);
|
||||
@@ -4246,7 +4221,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
return bdrv_open_inherit(filename, reference, options, flags, NULL,
|
||||
NULL, 0, true, errp);
|
||||
NULL, 0, errp);
|
||||
}
|
||||
|
||||
/* Return true if the NULL-terminated @list contains @str */
|
||||
@@ -5992,7 +5967,7 @@ int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs)
|
||||
return drv->bdrv_co_get_allocated_file_size(bs);
|
||||
}
|
||||
|
||||
if (drv->protocol_name) {
|
||||
if (drv->bdrv_file_open) {
|
||||
/*
|
||||
* Protocol drivers default to -ENOTSUP (most of their data is
|
||||
* not stored in any of their children (if they even have any),
|
||||
@@ -6351,7 +6326,7 @@ XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp)
|
||||
if (!*name) {
|
||||
name = allocated_name = blk_get_attached_dev_id(blk);
|
||||
}
|
||||
xdbg_graph_add_node(gr, blk, XDBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_BACKEND,
|
||||
xdbg_graph_add_node(gr, blk, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_BACKEND,
|
||||
name);
|
||||
g_free(allocated_name);
|
||||
if (blk_root(blk)) {
|
||||
@@ -6364,7 +6339,7 @@ XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp)
|
||||
job = block_job_next_locked(job)) {
|
||||
GSList *el;
|
||||
|
||||
xdbg_graph_add_node(gr, job, XDBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB,
|
||||
xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB,
|
||||
job->job.id);
|
||||
for (el = job->nodes; el; el = el->next) {
|
||||
xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data);
|
||||
@@ -6373,7 +6348,7 @@ XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp)
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(bs, &graph_bdrv_states, node_list) {
|
||||
xdbg_graph_add_node(gr, bs, XDBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_DRIVER,
|
||||
xdbg_graph_add_node(gr, bs, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_DRIVER,
|
||||
bs->node_name);
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
xdbg_graph_add_edge(gr, bs, child);
|
||||
@@ -8051,7 +8026,7 @@ void bdrv_refresh_filename(BlockDriverState *bs)
|
||||
* Both of these conditions are represented by generate_json_filename.
|
||||
*/
|
||||
if (primary_child_bs->exact_filename[0] &&
|
||||
primary_child_bs->drv->protocol_name &&
|
||||
primary_child_bs->drv->bdrv_file_open &&
|
||||
!drv->is_filter && !generate_json_filename)
|
||||
{
|
||||
strcpy(bs->exact_filename, primary_child_bs->exact_filename);
|
||||
|
||||
@@ -119,3 +119,8 @@ int aio_task_pool_status(AioTaskPool *pool)
|
||||
|
||||
return pool->status;
|
||||
}
|
||||
|
||||
bool aio_task_pool_empty(AioTaskPool *pool)
|
||||
{
|
||||
return pool->busy_tasks == 0;
|
||||
}
|
||||
|
||||
+2
-3
@@ -356,7 +356,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *target, int64_t speed,
|
||||
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
|
||||
BitmapSyncMode bitmap_mode,
|
||||
bool compress, bool discard_source,
|
||||
bool compress,
|
||||
const char *filter_node_name,
|
||||
BackupPerf *perf,
|
||||
BlockdevOnError on_source_error,
|
||||
@@ -457,8 +457,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
goto error;
|
||||
}
|
||||
|
||||
cbw = bdrv_cbw_append(bs, target, filter_node_name, discard_source,
|
||||
perf->min_cluster_size, &bcs, errp);
|
||||
cbw = bdrv_cbw_append(bs, target, filter_node_name, &bcs, errp);
|
||||
if (!cbw) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1073,7 +1073,7 @@ static BlockDriver bdrv_blkdebug = {
|
||||
.is_filter = true,
|
||||
|
||||
.bdrv_parse_filename = blkdebug_parse_filename,
|
||||
.bdrv_open = blkdebug_open,
|
||||
.bdrv_file_open = blkdebug_open,
|
||||
.bdrv_close = blkdebug_close,
|
||||
.bdrv_reopen_prepare = blkdebug_reopen_prepare,
|
||||
.bdrv_child_perm = blkdebug_child_perm,
|
||||
|
||||
+6
-8
@@ -713,7 +713,7 @@ static int blkio_virtio_blk_connect(BlockDriverState *bs, QDict *options,
|
||||
* for example will fail.
|
||||
*
|
||||
* In order to open the device read-only, we are using the `read-only`
|
||||
* property of the libblkio driver in blkio_open().
|
||||
* property of the libblkio driver in blkio_file_open().
|
||||
*/
|
||||
fd = qemu_open(path, O_RDWR, NULL);
|
||||
if (fd < 0) {
|
||||
@@ -791,8 +791,8 @@ static int blkio_virtio_blk_connect(BlockDriverState *bs, QDict *options,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int blkio_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
Error **errp)
|
||||
static int blkio_file_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
Error **errp)
|
||||
{
|
||||
const char *blkio_driver = bs->drv->protocol_name;
|
||||
BDRVBlkioState *s = bs->opaque;
|
||||
@@ -899,10 +899,8 @@ static int blkio_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
bs->supported_write_flags = BDRV_REQ_FUA | BDRV_REQ_REGISTERED_BUF;
|
||||
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
|
||||
#ifdef CONFIG_BLKIO_WRITE_ZEROS_FUA
|
||||
bs->supported_zero_flags |= BDRV_REQ_FUA;
|
||||
#endif
|
||||
bs->supported_zero_flags = BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP |
|
||||
BDRV_REQ_NO_FALLBACK;
|
||||
|
||||
qemu_mutex_init(&s->blkio_lock);
|
||||
qemu_co_mutex_init(&s->bounce_lock);
|
||||
@@ -1090,7 +1088,7 @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
*/
|
||||
#define BLKIO_DRIVER_COMMON \
|
||||
.instance_size = sizeof(BDRVBlkioState), \
|
||||
.bdrv_open = blkio_open, \
|
||||
.bdrv_file_open = blkio_file_open, \
|
||||
.bdrv_close = blkio_close, \
|
||||
.bdrv_co_getlength = blkio_co_getlength, \
|
||||
.bdrv_co_truncate = blkio_truncate, \
|
||||
|
||||
+1
-1
@@ -321,7 +321,7 @@ static BlockDriver bdrv_blkverify = {
|
||||
.instance_size = sizeof(BDRVBlkverifyState),
|
||||
|
||||
.bdrv_parse_filename = blkverify_parse_filename,
|
||||
.bdrv_open = blkverify_open,
|
||||
.bdrv_file_open = blkverify_open,
|
||||
.bdrv_close = blkverify_close,
|
||||
.bdrv_child_perm = bdrv_default_perms,
|
||||
.bdrv_co_getlength = blkverify_co_getlength,
|
||||
|
||||
+89
-25
@@ -599,14 +599,14 @@ BlockDriverState *bdrv_next(BdrvNextIterator *it)
|
||||
/* Must be called from the main loop */
|
||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||
|
||||
old_bs = it->bs;
|
||||
|
||||
/* First, return all root nodes of BlockBackends. In order to avoid
|
||||
* returning a BDS twice when multiple BBs refer to it, we only return it
|
||||
* if the BB is the first one in the parent list of the BDS. */
|
||||
if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
|
||||
BlockBackend *old_blk = it->blk;
|
||||
|
||||
old_bs = old_blk ? blk_bs(old_blk) : NULL;
|
||||
|
||||
do {
|
||||
it->blk = blk_all_next(it->blk);
|
||||
bs = it->blk ? blk_bs(it->blk) : NULL;
|
||||
@@ -620,10 +620,11 @@ BlockDriverState *bdrv_next(BdrvNextIterator *it)
|
||||
if (bs) {
|
||||
bdrv_ref(bs);
|
||||
bdrv_unref(old_bs);
|
||||
it->bs = bs;
|
||||
return bs;
|
||||
}
|
||||
it->phase = BDRV_NEXT_MONITOR_OWNED;
|
||||
} else {
|
||||
old_bs = it->bs;
|
||||
}
|
||||
|
||||
/* Then return the monitor-owned BDSes without a BB attached. Ignore all
|
||||
@@ -663,10 +664,13 @@ void bdrv_next_cleanup(BdrvNextIterator *it)
|
||||
/* Must be called from the main loop */
|
||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||
|
||||
bdrv_unref(it->bs);
|
||||
|
||||
if (it->phase == BDRV_NEXT_BACKEND_ROOTS && it->blk) {
|
||||
blk_unref(it->blk);
|
||||
if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
|
||||
if (it->blk) {
|
||||
bdrv_unref(blk_bs(it->blk));
|
||||
blk_unref(it->blk);
|
||||
}
|
||||
} else {
|
||||
bdrv_unref(it->bs);
|
||||
}
|
||||
|
||||
bdrv_next_reset(it);
|
||||
@@ -853,6 +857,15 @@ BlockBackendPublic *blk_get_public(BlockBackend *blk)
|
||||
return &blk->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a BlockBackend given the associated @public fields.
|
||||
*/
|
||||
BlockBackend *blk_by_public(BlockBackendPublic *public)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
return container_of(public, BlockBackend, public);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disassociates the currently associated BlockDriverState from @blk.
|
||||
*/
|
||||
@@ -1019,34 +1032,22 @@ DeviceState *blk_get_attached_dev(BlockBackend *blk)
|
||||
return blk->dev;
|
||||
}
|
||||
|
||||
static char *blk_get_attached_dev_id_or_path(BlockBackend *blk, bool want_id)
|
||||
/* Return the qdev ID, or if no ID is assigned the QOM path, of the block
|
||||
* device attached to the BlockBackend. */
|
||||
char *blk_get_attached_dev_id(BlockBackend *blk)
|
||||
{
|
||||
DeviceState *dev = blk->dev;
|
||||
IO_CODE();
|
||||
|
||||
if (!dev) {
|
||||
return g_strdup("");
|
||||
} else if (want_id && dev->id) {
|
||||
} else if (dev->id) {
|
||||
return g_strdup(dev->id);
|
||||
}
|
||||
|
||||
return object_get_canonical_path(OBJECT(dev)) ?: g_strdup("");
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the qdev ID, or if no ID is assigned the QOM path, of the block
|
||||
* device attached to the BlockBackend.
|
||||
*/
|
||||
char *blk_get_attached_dev_id(BlockBackend *blk)
|
||||
{
|
||||
return blk_get_attached_dev_id_or_path(blk, true);
|
||||
}
|
||||
|
||||
static char *blk_get_attached_dev_path(BlockBackend *blk)
|
||||
{
|
||||
return blk_get_attached_dev_id_or_path(blk, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the BlockBackend which has the device model @dev attached if it
|
||||
* exists, else null.
|
||||
@@ -1217,6 +1218,12 @@ BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk)
|
||||
return blk->iostatus;
|
||||
}
|
||||
|
||||
void blk_iostatus_disable(BlockBackend *blk)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
blk->iostatus_enabled = false;
|
||||
}
|
||||
|
||||
void blk_iostatus_reset(BlockBackend *blk)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
@@ -2134,10 +2141,9 @@ static void send_qmp_error_event(BlockBackend *blk,
|
||||
{
|
||||
IoOperationType optype;
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
g_autofree char *path = blk_get_attached_dev_path(blk);
|
||||
|
||||
optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
|
||||
qapi_event_send_block_io_error(path, blk_name(blk),
|
||||
qapi_event_send_block_io_error(blk_name(blk),
|
||||
bs ? bdrv_get_node_name(bs) : NULL, optype,
|
||||
action, blk_iostatus_is_enabled(blk),
|
||||
error == ENOSPC, strerror(error));
|
||||
@@ -2226,6 +2232,28 @@ void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
|
||||
blk->enable_write_cache = wce;
|
||||
}
|
||||
|
||||
void blk_activate(BlockBackend *blk, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
if (!bs) {
|
||||
error_setg(errp, "Device '%s' has no medium", blk->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Migration code can call this function in coroutine context, so leave
|
||||
* coroutine context if necessary.
|
||||
*/
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_activate(bs, errp);
|
||||
} else {
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
bdrv_activate(bs, errp);
|
||||
}
|
||||
}
|
||||
|
||||
bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
@@ -2356,6 +2384,36 @@ bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
|
||||
return bdrv_op_is_blocked(bs, op, errp);
|
||||
}
|
||||
|
||||
void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
if (bs) {
|
||||
bdrv_op_unblock(bs, op, reason);
|
||||
}
|
||||
}
|
||||
|
||||
void blk_op_block_all(BlockBackend *blk, Error *reason)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
if (bs) {
|
||||
bdrv_op_block_all(bs, reason);
|
||||
}
|
||||
}
|
||||
|
||||
void blk_op_unblock_all(BlockBackend *blk, Error *reason)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
if (bs) {
|
||||
bdrv_op_unblock_all(bs, reason);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return BB's current AioContext. Note that this context may change
|
||||
* concurrently at any time, with one exception: If the BB has a root node
|
||||
@@ -2510,6 +2568,12 @@ void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify)
|
||||
notifier_list_add(&blk->remove_bs_notifiers, notify);
|
||||
}
|
||||
|
||||
void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
notifier_list_add(&blk->insert_bs_notifiers, notify);
|
||||
}
|
||||
|
||||
BlockAcctStats *blk_get_stats(BlockBackend *blk)
|
||||
{
|
||||
IO_CODE();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user