Compare commits
72 Commits
fret_v3
...
wcet_syste
Author | SHA1 | Date | |
---|---|---|---|
85e0a3f630 | |||
ab54074925 | |||
f5b92c8907 | |||
f438967783 | |||
3493dfa219 | |||
a5a49c3292 | |||
8a379ba198 | |||
6ffc2bbe4f | |||
0cf10fb0ff | |||
404cb91655 | |||
ff823f26ff | |||
80af255c2e | |||
e62b0072ea | |||
6ec50ee9c3 | |||
88a0358a4e | |||
78dac2f524 | |||
9caef2e60f | |||
b781a3ebce | |||
5a1cf4d873 | |||
c1dba1b39d | |||
![]() |
54e1f5be86 | ||
![]() |
fddd169de5 | ||
![]() |
711bd602cc | ||
![]() |
e88636b4d4 | ||
![]() |
34833f361b | ||
![]() |
43583f0c07 | ||
![]() |
1ce084af08 | ||
![]() |
fec12fc888 | ||
![]() |
ef0cf1887e | ||
![]() |
71ba2adfeb | ||
![]() |
7629818574 | ||
![]() |
4658dfcbc0 | ||
![]() |
2b2eb343a0 | ||
![]() |
932333c5f0 | ||
![]() |
8c2d5911de | ||
![]() |
08e46e6d92 | ||
![]() |
df1c9c3039 | ||
![]() |
7204b8f3c6 | ||
![]() |
36c651c226 | ||
![]() |
fceaefb43f | ||
![]() |
7d71e6bfb0 | ||
![]() |
c2c7f108b8 | ||
![]() |
3488bb205d | ||
![]() |
cddfaf96ab | ||
![]() |
43a457841f | ||
![]() |
ebf660beb1 | ||
![]() |
bbbdedb386 | ||
![]() |
8319de607f | ||
![]() |
a759dc19ec | ||
![]() |
24101e36f1 | ||
![]() |
a43e057bd6 | ||
![]() |
3aa2c2cd67 | ||
![]() |
9e80a430ed | ||
![]() |
c66f5dfc12 | ||
![]() |
5cf977a2a1 | ||
![]() |
36cfd11a86 | ||
![]() |
246ccfbf44 | ||
![]() |
3ee93e456d | ||
![]() |
ec08035102 | ||
![]() |
f97853c8cb | ||
![]() |
abeee2a470 | ||
![]() |
ff6d391e10 | ||
![]() |
b19de1137b | ||
![]() |
3c6e5df1f6 | ||
![]() |
695c25e167 | ||
![]() |
23ba9f170f | ||
![]() |
f0dee5a40d | ||
![]() |
7637373b23 | ||
![]() |
4c34ef3d34 | ||
![]() |
9e41f16fca | ||
![]() |
3054f772de | ||
![]() |
aa77e375a5 |
@ -10,9 +10,9 @@ windows_msys2_task:
|
||||
memory: 8G
|
||||
env:
|
||||
CIRRUS_SHELL: powershell
|
||||
MSYS: winsymlinks:native
|
||||
MSYS: winsymlinks:nativestrict
|
||||
MSYSTEM: MINGW64
|
||||
MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2022-06-03/msys2-base-x86_64-20220603.sfx.exe
|
||||
MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2021-04-19/msys2-base-x86_64-20210419.sfx.exe
|
||||
MSYS2_FINGERPRINT: 0
|
||||
MSYS2_PACKAGES: "
|
||||
diffutils git grep make pkg-config sed
|
||||
@ -32,6 +32,7 @@ windows_msys2_task:
|
||||
mingw-w64-x86_64-libgcrypt
|
||||
mingw-w64-x86_64-libpng
|
||||
mingw-w64-x86_64-libssh
|
||||
mingw-w64-x86_64-libxml2
|
||||
mingw-w64-x86_64-snappy
|
||||
mingw-w64-x86_64-libusb
|
||||
mingw-w64-x86_64-usbredir
|
||||
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1,4 +1,3 @@
|
||||
*.c.inc diff=c
|
||||
*.h.inc diff=c
|
||||
*.m diff=objc
|
||||
*.py diff=python
|
||||
|
34
.github/lockdown.yml
vendored
Normal file
34
.github/lockdown.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown
|
||||
|
||||
# Close issues and pull requests
|
||||
close: true
|
||||
|
||||
# Lock issues and pull requests
|
||||
lock: true
|
||||
|
||||
issues:
|
||||
comment: |
|
||||
Thank you for your interest in the QEMU project.
|
||||
|
||||
This repository is a read-only mirror of the project's repostories hosted
|
||||
at https://gitlab.com/qemu-project/qemu.git.
|
||||
The project does not process issues filed on GitHub.
|
||||
|
||||
The project issues are tracked on GitLab:
|
||||
https://gitlab.com/qemu-project/qemu/-/issues
|
||||
|
||||
QEMU welcomes bug report contributions. You can file new ones on:
|
||||
https://gitlab.com/qemu-project/qemu/-/issues/new
|
||||
|
||||
pulls:
|
||||
comment: |
|
||||
Thank you for your interest in the QEMU project.
|
||||
|
||||
This repository is a read-only mirror of the project's repostories hosted
|
||||
on https://gitlab.com/qemu-project/qemu.git.
|
||||
The project does not process merge requests filed on GitHub.
|
||||
|
||||
QEMU welcomes contributions of code (either fixing bugs or adding new
|
||||
functionality). However, we get a lot of patches, and so we have some
|
||||
guidelines about contributing on the project website:
|
||||
https://www.qemu.org/contribute/
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,15 +1,9 @@
|
||||
/qemu_libafl_bridge/Cargo.lock
|
||||
/qemu_libafl_bridge/target/
|
||||
/GNUmakefile
|
||||
/build/
|
||||
/.cache/
|
||||
/.vscode/
|
||||
*.pyc
|
||||
.sdk
|
||||
.stgit-*
|
||||
.git-submodule-status
|
||||
.clang-format
|
||||
.gdb_history
|
||||
cscope.*
|
||||
tags
|
||||
TAGS
|
||||
@ -21,4 +15,6 @@ GTAGS
|
||||
*.depend_raw
|
||||
*.swp
|
||||
*.patch
|
||||
*.gcov
|
||||
.cache
|
||||
*.axf
|
||||
*.qcow2
|
@ -1,79 +0,0 @@
|
||||
|
||||
# The order of rules defined here is critically important.
|
||||
# They are evaluated in order and first match wins.
|
||||
#
|
||||
# Thus we group them into a number of stages, ordered from
|
||||
# most restrictive to least restrictive
|
||||
#
|
||||
.base_job_template:
|
||||
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
|
||||
|
||||
interruptible: true
|
||||
|
||||
rules:
|
||||
#############################################################
|
||||
# Stage 1: exclude scenarios where we definitely don't
|
||||
# want jobs to run
|
||||
#############################################################
|
||||
|
||||
# Cirrus jobs can't run unless the creds / target repo are set
|
||||
- if: '$QEMU_JOB_CIRRUS && ($CIRRUS_GITHUB_REPO == null || $CIRRUS_API_TOKEN == null)'
|
||||
when: never
|
||||
|
||||
# Publishing jobs should only run on the default branch in upstream
|
||||
- if: '$QEMU_JOB_PUBLISH == "1" && $CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'
|
||||
when: never
|
||||
|
||||
# Non-publishing jobs should only run on staging branches in upstream
|
||||
- if: '$QEMU_JOB_PUBLISH != "1" && $CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH !~ /staging/'
|
||||
when: never
|
||||
|
||||
# Jobs only intended for forks should always be skipped on upstream
|
||||
- if: '$QEMU_JOB_ONLY_FORKS == "1" && $CI_PROJECT_NAMESPACE == "qemu-project"'
|
||||
when: never
|
||||
|
||||
# Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
|
||||
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
when: never
|
||||
|
||||
# Avocado jobs don't run in forks unless $QEMU_CI_AVOCADO_TESTING is set
|
||||
- if: '$QEMU_JOB_AVOCADO && $QEMU_CI_AVOCADO_TESTING != "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
when: never
|
||||
|
||||
|
||||
#############################################################
|
||||
# Stage 2: fine tune execution of jobs in specific scenarios
|
||||
# where the catch all logic is inapprorpaite
|
||||
#############################################################
|
||||
|
||||
# Optional jobs should not be run unless manually triggered
|
||||
- if: '$QEMU_JOB_OPTIONAL'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
# Skipped jobs should not be run unless manually triggered
|
||||
- if: '$QEMU_JOB_SKIPPED'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
# Avocado jobs can be manually start in forks if $QEMU_CI_AVOCADO_TESTING is unset
|
||||
- if: '$QEMU_JOB_AVOCADO && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
|
||||
|
||||
#############################################################
|
||||
# Stage 3: catch all logic applying to any job not matching
|
||||
# an earlier criteria
|
||||
#############################################################
|
||||
|
||||
# Forks pipeline jobs don't start automatically unless
|
||||
# QEMU_CI=2 is set
|
||||
- if: '$QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
when: manual
|
||||
|
||||
# Jobs can run if any jobs they depend on were successfull
|
||||
- when: on_success
|
@ -1,5 +1,4 @@
|
||||
.native_build_job_template:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
before_script:
|
||||
@ -11,10 +10,12 @@
|
||||
fi
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror --disable-docs --enable-fdt=system
|
||||
${LD_JOBS:+--meson=git} ${TARGETS:+--target-list="$TARGETS"}
|
||||
$CONFIGURE_ARGS ||
|
||||
{ cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- if test -n "$TARGETS";
|
||||
then
|
||||
../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=git} $CONFIGURE_ARGS --target-list="$TARGETS" ;
|
||||
else
|
||||
../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=git} $CONFIGURE_ARGS ;
|
||||
fi || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- if test -n "$LD_JOBS";
|
||||
then
|
||||
../meson/meson.py configure . -Dbackend_max_links="$LD_JOBS" ;
|
||||
@ -25,8 +26,7 @@
|
||||
make -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||
fi
|
||||
|
||||
.common_test_job_template:
|
||||
extends: .base_job_template
|
||||
.native_test_job_template:
|
||||
stage: test
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
script:
|
||||
@ -37,18 +37,8 @@
|
||||
# Avoid recompiling by hiding ninja with NINJA=":"
|
||||
- make NINJA=":" $MAKE_CHECK_ARGS
|
||||
|
||||
.native_test_job_template:
|
||||
extends: .common_test_job_template
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
expire_in: 7 days
|
||||
paths:
|
||||
- build/meson-logs/testlog.txt
|
||||
reports:
|
||||
junit: build/meson-logs/testlog.junit.xml
|
||||
|
||||
.avocado_test_job_template:
|
||||
extends: .common_test_job_template
|
||||
.acceptance_test_job_template:
|
||||
extends: .native_test_job_template
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}-cache"
|
||||
paths:
|
||||
@ -77,5 +67,15 @@
|
||||
after_script:
|
||||
- cd build
|
||||
- du -chs ${CI_PROJECT_DIR}/avocado-cache
|
||||
variables:
|
||||
QEMU_JOB_AVOCADO: 1
|
||||
rules:
|
||||
# Only run these jobs if running on the mainstream namespace,
|
||||
# or if the user set the QEMU_CI_AVOCADO_TESTING variable (either
|
||||
# in its namespace setting or via git-push option, see documentation
|
||||
# in /.gitlab-ci.yml of this repository).
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
|
||||
when: on_success
|
||||
- if: '$QEMU_CI_AVOCADO_TESTING'
|
||||
when: on_success
|
||||
# Otherwise, set to manual (the jobs are created but not run).
|
||||
- when: manual
|
||||
allow_failure: true
|
||||
|
@ -24,16 +24,16 @@ check-system-alpine:
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: alpine
|
||||
MAKE_CHECK_ARGS: check-unit check-qtest
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-alpine:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-alpine:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-alpine
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: alpine
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-ubuntu:
|
||||
extends: .native_build_job_template
|
||||
@ -41,8 +41,8 @@ build-system-ubuntu:
|
||||
job: amd64-ubuntu2004-container
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
CONFIGURE_ARGS: --enable-docs
|
||||
TARGETS: alpha-softmmu cris-softmmu hppa-softmmu
|
||||
CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-slirp=system
|
||||
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
|
||||
microblazeel-softmmu mips64el-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
artifacts:
|
||||
@ -59,14 +59,14 @@ check-system-ubuntu:
|
||||
IMAGE: ubuntu2004
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-ubuntu:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-ubuntu:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-ubuntu
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-debian:
|
||||
extends: .native_build_job_template
|
||||
@ -74,7 +74,7 @@ build-system-debian:
|
||||
job: amd64-debian-container
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
CONFIGURE_ARGS: --with-coroutine=sigaltstack
|
||||
CONFIGURE_ARGS: --enable-fdt=system
|
||||
TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
|
||||
riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
@ -92,26 +92,14 @@ check-system-debian:
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-debian:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-debian:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
|
||||
crash-test-debian:
|
||||
extends: .native_test_job_template
|
||||
needs:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
script:
|
||||
- cd build
|
||||
- make check-venv
|
||||
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-i386
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-fedora:
|
||||
extends: .native_build_job_template
|
||||
@ -120,6 +108,7 @@ build-system-fedora:
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
|
||||
--enable-fdt=system --enable-slirp=system --enable-capstone=system
|
||||
TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu
|
||||
xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
@ -137,27 +126,14 @@ check-system-fedora:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-fedora:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-fedora:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-fedora
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
|
||||
crash-test-fedora:
|
||||
extends: .native_test_job_template
|
||||
needs:
|
||||
- job: build-system-fedora
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
script:
|
||||
- cd build
|
||||
- make check-venv
|
||||
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-ppc
|
||||
- tests/venv/bin/python3 scripts/device-crash-test -q ./qemu-system-riscv32
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-centos:
|
||||
extends: .native_build_job_template
|
||||
@ -165,8 +141,8 @@ build-system-centos:
|
||||
job: amd64-centos8-container
|
||||
variables:
|
||||
IMAGE: centos8
|
||||
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
|
||||
--enable-modules --enable-trace-backends=dtrace --enable-docs
|
||||
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system
|
||||
--enable-modules --enable-trace-backends=dtrace
|
||||
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
|
||||
x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
@ -184,14 +160,14 @@ check-system-centos:
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-centos:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-centos:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-centos
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-system-opensuse:
|
||||
extends: .native_build_job_template
|
||||
@ -199,6 +175,7 @@ build-system-opensuse:
|
||||
job: amd64-opensuse-leap-container
|
||||
variables:
|
||||
IMAGE: opensuse-leap
|
||||
CONFIGURE_ARGS: --enable-fdt=system
|
||||
TARGETS: s390x-softmmu x86_64-softmmu aarch64-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
artifacts:
|
||||
@ -215,16 +192,95 @@ check-system-opensuse:
|
||||
IMAGE: opensuse-leap
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-system-opensuse:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-system-opensuse:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-system-opensuse
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: opensuse-leap
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
|
||||
build-disabled:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-fedora-container
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS:
|
||||
--disable-attr
|
||||
--disable-auth-pam
|
||||
--disable-avx2
|
||||
--disable-bochs
|
||||
--disable-brlapi
|
||||
--disable-bzip2
|
||||
--disable-cap-ng
|
||||
--disable-capstone
|
||||
--disable-cloop
|
||||
--disable-coroutine-pool
|
||||
--disable-curl
|
||||
--disable-curses
|
||||
--disable-dmg
|
||||
--disable-docs
|
||||
--disable-gcrypt
|
||||
--disable-glusterfs
|
||||
--disable-gnutls
|
||||
--disable-gtk
|
||||
--disable-guest-agent
|
||||
--disable-iconv
|
||||
--disable-keyring
|
||||
--disable-kvm
|
||||
--disable-libiscsi
|
||||
--disable-libpmem
|
||||
--disable-libssh
|
||||
--disable-libudev
|
||||
--disable-libusb
|
||||
--disable-libxml2
|
||||
--disable-linux-aio
|
||||
--disable-live-block-migration
|
||||
--disable-lzo
|
||||
--disable-malloc-trim
|
||||
--disable-mpath
|
||||
--disable-nettle
|
||||
--disable-numa
|
||||
--disable-opengl
|
||||
--disable-parallels
|
||||
--disable-pie
|
||||
--disable-qcow1
|
||||
--disable-qed
|
||||
--disable-qom-cast-debug
|
||||
--disable-rbd
|
||||
--disable-rdma
|
||||
--disable-replication
|
||||
--disable-sdl
|
||||
--disable-seccomp
|
||||
--disable-slirp
|
||||
--disable-smartcard
|
||||
--disable-snappy
|
||||
--disable-sparse
|
||||
--disable-spice
|
||||
--disable-strip
|
||||
--disable-tpm
|
||||
--disable-usb-redir
|
||||
--disable-vdi
|
||||
--disable-vhost-crypto
|
||||
--disable-vhost-net
|
||||
--disable-vhost-scsi
|
||||
--disable-vhost-kernel
|
||||
--disable-vhost-user
|
||||
--disable-vhost-vdpa
|
||||
--disable-vhost-vsock
|
||||
--disable-virglrenderer
|
||||
--disable-vnc
|
||||
--disable-vte
|
||||
--disable-vvfat
|
||||
--disable-xen
|
||||
--disable-zstd
|
||||
TARGETS: arm-softmmu i386-softmmu ppc64-softmmu mips64-softmmu
|
||||
s390x-softmmu i386-linux-user
|
||||
MAKE_CHECK_ARGS: check-qtest SPEED=slow
|
||||
|
||||
# This jobs explicitly disable TCG (--disable-tcg), KVM is detected by
|
||||
# the configure script. The container doesn't contain Xen headers so
|
||||
# Xen accelerator is not detected / selected. As result it build the
|
||||
@ -242,7 +298,6 @@ build-tcg-disabled:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-tcg --audio-drv-list="" --with-coroutine=ucontext
|
||||
--disable-docs --disable-sdl --disable-gtk --disable-vnc
|
||||
|| { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- make -j"$JOBS"
|
||||
- make check-unit
|
||||
@ -250,11 +305,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 183 184 192 194 208 221 226 227 236 253 277 image-fleecing
|
||||
170 171 183 184 192 194 208 221 222 226 227 236 253 277
|
||||
- ./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
|
||||
208 209 216 218 222 227 234 246 247 248 250 254 255 257 258
|
||||
260 261 262 263 264 270 272 273 277 279
|
||||
|
||||
build-user:
|
||||
extends: .native_build_job_template
|
||||
@ -274,10 +329,14 @@ build-user-static:
|
||||
CONFIGURE_ARGS: --disable-tools --disable-system --static
|
||||
MAKE_CHECK_ARGS: check-tcg
|
||||
|
||||
# Because the hexagon cross-compiler takes so long to build we don't rely
|
||||
# on the CI system to build it and hence this job has an optional dependency
|
||||
# declared. The image is manually uploaded.
|
||||
build-user-hexagon:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: hexagon-cross-container
|
||||
optional: true
|
||||
variables:
|
||||
IMAGE: debian-hexagon-cross
|
||||
TARGETS: hexagon-linux-user
|
||||
@ -314,14 +373,14 @@ clang-system:
|
||||
IMAGE: fedora
|
||||
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
|
||||
TARGETS: alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
|
||||
ppc-softmmu s390x-softmmu
|
||||
MAKE_CHECK_ARGS: check-qtest check-tcg
|
||||
|
||||
clang-user:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-debian-user-cross-container
|
||||
timeout: 70m
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --disable-system
|
||||
@ -333,10 +392,12 @@ clang-user:
|
||||
# On gitlab runners, default value sometimes end up calling 2 lds concurrently and
|
||||
# triggers an Out-Of-Memory error
|
||||
#
|
||||
# Since slirp callbacks are used in QEMU Timers, we cannot use libslirp with
|
||||
# CFI builds, and thus have to disable it here.
|
||||
# Since slirp callbacks are used in QEMU Timers, slirp needs to be compiled together
|
||||
# with QEMU and linked as a static library to avoid false positives in CFI checks.
|
||||
# This can be accomplished by using -enable-slirp=git, which avoids the use of
|
||||
# a system-wide version of the library
|
||||
#
|
||||
# Split in three sets of build/check/avocado to limit the execution time of each
|
||||
# Split in three sets of build/check/acceptance to limit the execution time of each
|
||||
# job
|
||||
build-cfi-aarch64:
|
||||
extends: .native_build_job_template
|
||||
@ -347,18 +408,20 @@ build-cfi-aarch64:
|
||||
AR: llvm-ar
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
|
||||
--enable-safe-stack --disable-slirp
|
||||
--enable-safe-stack --enable-slirp=git
|
||||
TARGETS: aarch64-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
# FIXME: This job is often failing, likely due to out-of-memory problems in
|
||||
# the constrained containers of the shared runners. Thus this is marked as
|
||||
# skipped until the situation has been solved.
|
||||
QEMU_JOB_SKIPPED: 1
|
||||
timeout: 90m
|
||||
timeout: 70m
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
- build
|
||||
rules:
|
||||
# FIXME: This job is often failing, likely due to out-of-memory problems in
|
||||
# the constrained containers of the shared runners. Thus this is marked as
|
||||
# manual until the situation has been solved.
|
||||
- when: manual
|
||||
allow_failure: true
|
||||
|
||||
check-cfi-aarch64:
|
||||
extends: .native_test_job_template
|
||||
@ -369,14 +432,14 @@ check-cfi-aarch64:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-cfi-aarch64:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-cfi-aarch64:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-cfi-aarch64
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-cfi-ppc64-s390x:
|
||||
extends: .native_build_job_template
|
||||
@ -387,18 +450,20 @@ build-cfi-ppc64-s390x:
|
||||
AR: llvm-ar
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
|
||||
--enable-safe-stack --disable-slirp
|
||||
--enable-safe-stack --enable-slirp=git
|
||||
TARGETS: ppc64-softmmu s390x-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
# FIXME: This job is often failing, likely due to out-of-memory problems in
|
||||
# the constrained containers of the shared runners. Thus this is marked as
|
||||
# skipped until the situation has been solved.
|
||||
QEMU_JOB_SKIPPED: 1
|
||||
timeout: 80m
|
||||
timeout: 70m
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
- build
|
||||
rules:
|
||||
# FIXME: This job is often failing, likely due to out-of-memory problems in
|
||||
# the constrained containers of the shared runners. Thus this is marked as
|
||||
# manual until the situation has been solved.
|
||||
- when: manual
|
||||
allow_failure: true
|
||||
|
||||
check-cfi-ppc64-s390x:
|
||||
extends: .native_test_job_template
|
||||
@ -409,14 +474,14 @@ check-cfi-ppc64-s390x:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-cfi-ppc64-s390x:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-cfi-ppc64-s390x:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-cfi-ppc64-s390x
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
build-cfi-x86_64:
|
||||
extends: .native_build_job_template
|
||||
@ -427,7 +492,7 @@ build-cfi-x86_64:
|
||||
AR: llvm-ar
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
|
||||
--enable-safe-stack --disable-slirp
|
||||
--enable-safe-stack --enable-slirp=git
|
||||
TARGETS: x86_64-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
timeout: 70m
|
||||
@ -445,14 +510,14 @@ check-cfi-x86_64:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
avocado-cfi-x86_64:
|
||||
extends: .avocado_test_job_template
|
||||
acceptance-cfi-x86_64:
|
||||
extends: .acceptance_test_job_template
|
||||
needs:
|
||||
- job: build-cfi-x86_64
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
|
||||
tsan-build:
|
||||
extends: .native_build_job_template
|
||||
@ -461,33 +526,61 @@ tsan-build:
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10
|
||||
--enable-trace-backends=ust --disable-slirp
|
||||
--enable-trace-backends=ust --enable-fdt=system --enable-slirp=system
|
||||
TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
|
||||
MAKE_CHECK_ARGS: bench V=1
|
||||
|
||||
# gcov is a GCC features
|
||||
gcov:
|
||||
# These targets are on the way out
|
||||
build-deprecated:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-debian-user-cross-container
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --disable-tools
|
||||
MAKE_CHECK_ARGS: build-tcg
|
||||
TARGETS: ppc64abi32-linux-user
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
- build
|
||||
|
||||
# We split the check-tcg step as test failures are expected but we still
|
||||
# want to catch the build breaking.
|
||||
check-deprecated:
|
||||
extends: .native_test_job_template
|
||||
needs:
|
||||
- job: build-deprecated
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
MAKE_CHECK_ARGS: check-tcg
|
||||
allow_failure: true
|
||||
|
||||
# gprof/gcov are GCC features
|
||||
build-gprof-gcov:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-ubuntu2004-container
|
||||
timeout: 80m
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
CONFIGURE_ARGS: --enable-gcov
|
||||
CONFIGURE_ARGS: --enable-gprof --enable-gcov
|
||||
TARGETS: aarch64-softmmu ppc64-softmmu s390x-softmmu x86_64-softmmu
|
||||
artifacts:
|
||||
expire_in: 1 days
|
||||
paths:
|
||||
- build
|
||||
|
||||
check-gprof-gcov:
|
||||
extends: .native_test_job_template
|
||||
needs:
|
||||
- job: build-gprof-gcov
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
MAKE_CHECK_ARGS: check
|
||||
after_script:
|
||||
- cd build
|
||||
- gcovr --xml-pretty --exclude-unreachable-branches --print-summary
|
||||
-o coverage.xml --root ${CI_PROJECT_DIR} . *.p
|
||||
coverage: /^\s*lines:\s*\d+.\d+\%/
|
||||
artifacts:
|
||||
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||
expire_in: 2 days
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: build/coverage.xml
|
||||
- ${CI_PROJECT_DIR}/scripts/ci/coverage-summary.sh
|
||||
|
||||
build-oss-fuzz:
|
||||
extends: .native_build_job_template
|
||||
@ -497,7 +590,6 @@ build-oss-fuzz:
|
||||
IMAGE: fedora
|
||||
script:
|
||||
- mkdir build-oss-fuzz
|
||||
- export LSAN_OPTIONS=suppressions=scripts/oss-fuzz/lsan_suppressions.txt
|
||||
- CC="clang" CXX="clang++" CFLAGS="-fsanitize=address"
|
||||
./scripts/oss-fuzz/build.sh
|
||||
- export ASAN_OPTIONS="fast_unwind_on_malloc=0"
|
||||
@ -507,6 +599,8 @@ build-oss-fuzz:
|
||||
echo Testing ${fuzzer} ... ;
|
||||
"${fuzzer}" -runs=1 -seed=1 || exit 1 ;
|
||||
done
|
||||
# Unrelated to fuzzer: run some tests with -fsanitize=address
|
||||
- cd build-oss-fuzz && make check-qtest-i386 check-unit
|
||||
|
||||
build-tci:
|
||||
extends: .native_build_job_template
|
||||
@ -518,9 +612,8 @@ build-tci:
|
||||
- TARGETS="aarch64 alpha arm hppa m68k microblaze ppc64 s390x x86_64"
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../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; }
|
||||
- ../configure --enable-tcg-interpreter
|
||||
--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"
|
||||
- make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test
|
||||
- for tg in $TARGETS ; do
|
||||
@ -532,30 +625,44 @@ build-tci:
|
||||
- QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow
|
||||
- make check-tcg
|
||||
|
||||
# Alternate coroutines implementations are only really of interest to KVM users
|
||||
# However we can't test against KVM on Gitlab-CI so we can only run unit tests
|
||||
build-coroutine-sigaltstack:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-ubuntu2004-container
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
CONFIGURE_ARGS: --with-coroutine=sigaltstack --disable-tcg
|
||||
--enable-trace-backends=ftrace
|
||||
MAKE_CHECK_ARGS: check-unit
|
||||
|
||||
# Check our reduced build configurations
|
||||
build-without-defaults:
|
||||
build-without-default-devices:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-centos8-container
|
||||
variables:
|
||||
IMAGE: centos8
|
||||
CONFIGURE_ARGS:
|
||||
--without-default-devices
|
||||
--without-default-features
|
||||
--disable-fdt
|
||||
--disable-pie
|
||||
--disable-qom-cast-debug
|
||||
--disable-strip
|
||||
TARGETS: avr-softmmu mips64-softmmu s390x-softmmu sh4-softmmu
|
||||
sparc64-softmmu hexagon-linux-user i386-linux-user s390x-linux-user
|
||||
MAKE_CHECK_ARGS: check-unit check-qtest-avr check-qtest-mips64
|
||||
CONFIGURE_ARGS: --without-default-devices --disable-user
|
||||
|
||||
build-without-default-features:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-debian-container
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
CONFIGURE_ARGS: --without-default-features --disable-user
|
||||
--target-list-exclude=arm-softmmu,i386-softmmu,mipsel-softmmu,mips64-softmmu,ppc-softmmu
|
||||
MAKE_CHECK_ARGS: check-unit
|
||||
|
||||
build-libvhost-user:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/fedora:latest
|
||||
needs:
|
||||
job: amd64-fedora-container
|
||||
before_script:
|
||||
- dnf install -y meson ninja-build
|
||||
script:
|
||||
- mkdir subprojects/libvhost-user/build
|
||||
- cd subprojects/libvhost-user/build
|
||||
@ -568,13 +675,10 @@ build-tools-and-docs-debian:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
job: amd64-debian-container
|
||||
# when running on 'master' we use pre-existing container
|
||||
optional: true
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check-unit ctags TAGS cscope
|
||||
MAKE_CHECK_ARGS: check-unit check-softfloat ctags TAGS cscope
|
||||
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
|
||||
QEMU_JOB_PUBLISH: 1
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
@ -594,7 +698,6 @@ build-tools-and-docs-debian:
|
||||
# that users can see the results of their commits, regardless
|
||||
# of what topic branch they're currently using
|
||||
pages:
|
||||
extends: .base_job_template
|
||||
image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:latest
|
||||
stage: test
|
||||
needs:
|
||||
@ -612,5 +715,10 @@ pages:
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
variables:
|
||||
QEMU_JOB_PUBLISH: 1
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
when: on_success
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
|
||||
when: never
|
||||
- if: '$CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
when: on_success
|
||||
|
@ -11,11 +11,9 @@
|
||||
# special care, because we can't just override it at the GitLab CI job
|
||||
# definition level or we risk breaking it completely.
|
||||
.cirrus_build_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
||||
needs: []
|
||||
timeout: 80m
|
||||
allow_failure: true
|
||||
script:
|
||||
- source .gitlab-ci.d/cirrus/$NAME.vars
|
||||
@ -37,12 +35,12 @@
|
||||
-e "s|[@]PIP3@|$PIP3|g"
|
||||
-e "s|[@]PYPI_PKGS@|$PYPI_PKGS|g"
|
||||
-e "s|[@]CONFIGURE_ARGS@|$CONFIGURE_ARGS|g"
|
||||
-e "s|[@]TEST_TARGETS@|$TEST_TARGETS|g"
|
||||
-e "s|[@]TEST_TARGETSS@|$TEST_TARGETSS|g"
|
||||
<.gitlab-ci.d/cirrus/build.yml >.gitlab-ci.d/cirrus/$NAME.yml
|
||||
- cat .gitlab-ci.d/cirrus/$NAME.yml
|
||||
- cirrus-run -v --show-build-log always .gitlab-ci.d/cirrus/$NAME.yml
|
||||
variables:
|
||||
QEMU_JOB_CIRRUS: 1
|
||||
rules:
|
||||
- if: "$CIRRUS_GITHUB_REPO && $CIRRUS_API_TOKEN"
|
||||
|
||||
x64-freebsd-12-build:
|
||||
extends: .cirrus_build_job
|
||||
@ -50,11 +48,14 @@ x64-freebsd-12-build:
|
||||
NAME: freebsd-12
|
||||
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
||||
CIRRUS_VM_IMAGE_SELECTOR: image_family
|
||||
CIRRUS_VM_IMAGE_NAME: freebsd-12-4
|
||||
CIRRUS_VM_IMAGE_NAME: freebsd-12-2
|
||||
CIRRUS_VM_CPUS: 8
|
||||
CIRRUS_VM_RAM: 8G
|
||||
UPDATE_COMMAND: pkg update; pkg upgrade -y
|
||||
UPDATE_COMMAND: pkg update
|
||||
INSTALL_COMMAND: pkg install -y
|
||||
# TODO: Enable gnutls again once FreeBSD's libtasn1 got fixed
|
||||
# See: https://gitlab.com/gnutls/libtasn1/-/merge_requests/71
|
||||
CONFIGURE_ARGS: --disable-gnutls
|
||||
TEST_TARGETS: check
|
||||
|
||||
x64-freebsd-13-build:
|
||||
@ -63,61 +64,24 @@ x64-freebsd-13-build:
|
||||
NAME: freebsd-13
|
||||
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
||||
CIRRUS_VM_IMAGE_SELECTOR: image_family
|
||||
CIRRUS_VM_IMAGE_NAME: freebsd-13-1
|
||||
CIRRUS_VM_IMAGE_NAME: freebsd-13-0
|
||||
CIRRUS_VM_CPUS: 8
|
||||
CIRRUS_VM_RAM: 8G
|
||||
UPDATE_COMMAND: pkg update; pkg upgrade -y
|
||||
UPDATE_COMMAND: pkg update
|
||||
INSTALL_COMMAND: pkg install -y
|
||||
TEST_TARGETS: check
|
||||
|
||||
aarch64-macos-12-base-build:
|
||||
x64-macos-11-base-build:
|
||||
extends: .cirrus_build_job
|
||||
variables:
|
||||
NAME: macos-12
|
||||
CIRRUS_VM_INSTANCE_TYPE: macos_instance
|
||||
NAME: macos-11
|
||||
CIRRUS_VM_INSTANCE_TYPE: osx_instance
|
||||
CIRRUS_VM_IMAGE_SELECTOR: image
|
||||
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-monterey-base:latest
|
||||
CIRRUS_VM_IMAGE_NAME: big-sur-base
|
||||
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
|
||||
PATH_EXTRA: /usr/local/opt/ccache/libexec:/usr/local/opt/gettext/bin
|
||||
PKG_CONFIG_PATH: /usr/local/opt/curl/lib/pkgconfig:/usr/local/opt/ncurses/lib/pkgconfig:/usr/local/opt/readline/lib/pkgconfig
|
||||
TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64
|
||||
|
||||
|
||||
# The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job
|
||||
.cirrus_kvm_job:
|
||||
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
|
||||
|
@ -13,7 +13,6 @@ env:
|
||||
PYTHON: "@PYTHON@"
|
||||
MAKE: "@MAKE@"
|
||||
CONFIGURE_ARGS: "@CONFIGURE_ARGS@"
|
||||
TEST_TARGETS: "@TEST_TARGETS@"
|
||||
|
||||
build_task:
|
||||
install_script:
|
||||
@ -32,6 +31,5 @@ build_task:
|
||||
- $MAKE -j$(sysctl -n hw.ncpu)
|
||||
- for TARGET in $TEST_TARGETS ;
|
||||
do
|
||||
$MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1
|
||||
|| { cat meson-logs/testlog.txt; exit 1; } ;
|
||||
$MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1 ;
|
||||
done
|
||||
|
@ -2,15 +2,12 @@
|
||||
#
|
||||
# $ lcitool variables freebsd-12 qemu
|
||||
#
|
||||
# https://gitlab.com/libvirt/libvirt-ci
|
||||
# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1
|
||||
|
||||
PACKAGING_COMMAND='pkg'
|
||||
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 cdrkit-genisoimage 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 ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio spice-protocol tesseract usbredir virglrenderer vte3 zstd'
|
||||
PYPI_PKGS=''
|
||||
PYTHON='/usr/local/bin/python3'
|
||||
PIP3='/usr/local/bin/pip-3.8'
|
||||
PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd'
|
||||
|
@ -2,15 +2,12 @@
|
||||
#
|
||||
# $ lcitool variables freebsd-13 qemu
|
||||
#
|
||||
# https://gitlab.com/libvirt/libvirt-ci
|
||||
# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1
|
||||
|
||||
PACKAGING_COMMAND='pkg'
|
||||
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 cdrkit-genisoimage 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 ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio spice-protocol tesseract usbredir virglrenderer vte3 zstd'
|
||||
PYPI_PKGS=''
|
||||
PYTHON='/usr/local/bin/python3'
|
||||
PIP3='/usr/local/bin/pip-3.8'
|
||||
PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd'
|
||||
|
@ -1,31 +0,0 @@
|
||||
container:
|
||||
image: fedora:35
|
||||
cpu: 4
|
||||
memory: 8Gb
|
||||
kvm: true
|
||||
|
||||
env:
|
||||
CIRRUS_CLONE_DEPTH: 1
|
||||
CI_REPOSITORY_URL: "@CI_REPOSITORY_URL@"
|
||||
CI_COMMIT_REF_NAME: "@CI_COMMIT_REF_NAME@"
|
||||
CI_COMMIT_SHA: "@CI_COMMIT_SHA@"
|
||||
|
||||
@NAME@_task:
|
||||
@NAME@_vm_cache:
|
||||
folder: $HOME/.cache/qemu-vm
|
||||
install_script:
|
||||
- dnf update -y
|
||||
- dnf install -y git make openssh-clients qemu-img qemu-system-x86 wget
|
||||
clone_script:
|
||||
- git clone --depth 100 "$CI_REPOSITORY_URL" .
|
||||
- git fetch origin "$CI_COMMIT_REF_NAME"
|
||||
- git reset --hard "$CI_COMMIT_SHA"
|
||||
build_script:
|
||||
- if [ -f $HOME/.cache/qemu-vm/images/@NAME@.img ]; then
|
||||
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN)
|
||||
EXTRA_CONFIGURE_OPTS="@CONFIGURE_ARGS@"
|
||||
BUILD_TARGET="@TEST_TARGETS@" ;
|
||||
else
|
||||
make vm-build-@NAME@ J=$(getconf _NPROCESSORS_ONLN) BUILD_TARGET=help
|
||||
EXTRA_CONFIGURE_OPTS="--disable-system --disable-user --disable-tools" ;
|
||||
fi
|
15
.gitlab-ci.d/cirrus/macos-11.vars
Normal file
15
.gitlab-ci.d/cirrus/macos-11.vars
Normal file
@ -0,0 +1,15 @@
|
||||
# THIS FILE WAS AUTO-GENERATED
|
||||
#
|
||||
# $ lcitool variables macos-11 qemu
|
||||
#
|
||||
# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1
|
||||
|
||||
PACKAGING_COMMAND='brew'
|
||||
CCACHE='/usr/local/bin/ccache'
|
||||
MAKE='/usr/local/bin/gmake'
|
||||
NINJA='/usr/local/bin/ninja'
|
||||
PYTHON='/usr/local/bin/python3'
|
||||
PIP3='/usr/local/bin/pip3'
|
||||
PKGS='bash bc bzip2 capstone ccache cpanminus ctags curl dbus diffutils gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb libxml2 llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd'
|
||||
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme virtualenv'
|
||||
CPAN_PKGS='Test::Harness'
|
@ -1,16 +0,0 @@
|
||||
# THIS FILE WAS AUTO-GENERATED
|
||||
#
|
||||
# $ lcitool variables macos-12 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 ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract usbredir vde vte3 zlib zstd'
|
||||
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme'
|
||||
PYTHON='/opt/homebrew/bin/python3'
|
@ -10,3 +10,8 @@ amd64-fedora-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: fedora
|
||||
|
||||
amd64-debian10-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: debian10
|
||||
|
@ -1,129 +1,168 @@
|
||||
alpha-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-alpha-cross
|
||||
|
||||
amd64-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-amd64-cross
|
||||
|
||||
amd64-debian-user-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-all-test-cross
|
||||
|
||||
arm64-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-arm64-cross
|
||||
|
||||
arm64-test-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian11-container']
|
||||
variables:
|
||||
NAME: debian-arm64-test-cross
|
||||
|
||||
armel-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-armel-cross
|
||||
|
||||
armhf-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-armhf-cross
|
||||
|
||||
# We never want to build hexagon in the CI system and by default we
|
||||
# always want to refer to the master registry where it lives.
|
||||
hexagon-cross-container:
|
||||
extends: .container_job_template
|
||||
image: docker:stable
|
||||
stage: containers
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
|
||||
when: never
|
||||
- when: always
|
||||
variables:
|
||||
NAME: debian-hexagon-cross
|
||||
GIT_DEPTH: 1
|
||||
services:
|
||||
- docker:dind
|
||||
before_script:
|
||||
- export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
|
||||
- export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/qemu/$NAME:latest"
|
||||
- docker info
|
||||
- docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
|
||||
script:
|
||||
- echo "TAG:$TAG"
|
||||
- echo "COMMON_TAG:$COMMON_TAG"
|
||||
- docker pull $COMMON_TAG
|
||||
- docker tag $COMMON_TAG $TAG
|
||||
- docker push "$TAG"
|
||||
after_script:
|
||||
- docker logout
|
||||
|
||||
hppa-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-hppa-cross
|
||||
|
||||
m68k-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-m68k-cross
|
||||
|
||||
mips64-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-mips64-cross
|
||||
|
||||
mips64el-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-mips64el-cross
|
||||
|
||||
mips-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-mips-cross
|
||||
|
||||
mipsel-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-mipsel-cross
|
||||
|
||||
powerpc-test-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian11-container']
|
||||
variables:
|
||||
NAME: debian-powerpc-test-cross
|
||||
|
||||
ppc64el-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-ppc64el-cross
|
||||
|
||||
riscv64-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
# as we are currently based on 'sid/unstable' we may break so...
|
||||
allow_failure: true
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-riscv64-cross
|
||||
|
||||
# we can however build TCG tests using a non-sid base
|
||||
riscv64-debian-test-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
variables:
|
||||
NAME: debian-riscv64-test-cross
|
||||
|
||||
s390x-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-s390x-cross
|
||||
|
||||
sh4-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-sh4-cross
|
||||
|
||||
sparc64-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-sparc64-cross
|
||||
|
||||
tricore-debian-cross-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-tricore-cross
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
.container_job_template:
|
||||
extends: .base_job_template
|
||||
image: docker:stable
|
||||
stage: containers
|
||||
services:
|
||||
|
@ -7,17 +7,33 @@ amd64-alpine-container:
|
||||
variables:
|
||||
NAME: alpine
|
||||
|
||||
amd64-debian11-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: debian11
|
||||
|
||||
amd64-debian-container:
|
||||
extends: .container_job_template
|
||||
stage: containers
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-amd64
|
||||
|
||||
amd64-ubuntu1804-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: ubuntu1804
|
||||
|
||||
amd64-ubuntu2004-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: ubuntu2004
|
||||
|
||||
amd64-ubuntu-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
NAME: ubuntu
|
||||
|
||||
amd64-opensuse-leap-container:
|
||||
extends: .container_job_template
|
||||
variables:
|
||||
|
@ -1,21 +1,20 @@
|
||||
.cross_system_build_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
timeout: 80m
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror --disable-docs --enable-fdt=system
|
||||
--disable-user $QEMU_CONFIGURE_OPTS $EXTRA_CONFIGURE_OPTS
|
||||
--target-list-exclude="arm-softmmu cris-softmmu
|
||||
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-user --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"
|
||||
- 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)";
|
||||
version="$(git describe --match v[0-9]*)";
|
||||
mv -v qemu-setup*.exe qemu-setup-${version}.exe;
|
||||
fi
|
||||
|
||||
@ -25,27 +24,24 @@
|
||||
# KVM), and set extra options (such disabling other accelerators) via the
|
||||
# $EXTRA_CONFIGURE_OPTS variable.
|
||||
.cross_accel_build_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
timeout: 30m
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-tools --enable-${ACCEL:-kvm} $EXTRA_CONFIGURE_OPTS
|
||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||
|
||||
.cross_user_build_job:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-system --target-list-exclude="aarch64_be-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"
|
||||
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-system
|
||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||
|
@ -62,14 +62,26 @@ cross-i386-user:
|
||||
cross-i386-tci:
|
||||
extends: .cross_accel_build_job
|
||||
timeout: 60m
|
||||
needs:
|
||||
job: i386-fedora-cross-container
|
||||
variables:
|
||||
IMAGE: fedora-i386-cross
|
||||
ACCEL: tcg-interpreter
|
||||
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user
|
||||
MAKE_CHECK_ARGS: check check-tcg
|
||||
|
||||
cross-mips-system:
|
||||
extends: .cross_system_build_job
|
||||
needs:
|
||||
job: mips-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-mips-cross
|
||||
|
||||
cross-mips-user:
|
||||
extends: .cross_user_build_job
|
||||
needs:
|
||||
job: mips-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-mips-cross
|
||||
|
||||
cross-mipsel-system:
|
||||
extends: .cross_system_build_job
|
||||
needs:
|
||||
@ -112,33 +124,6 @@ cross-ppc64el-user:
|
||||
variables:
|
||||
IMAGE: debian-ppc64el-cross
|
||||
|
||||
cross-ppc64el-kvm-only:
|
||||
extends: .cross_accel_build_job
|
||||
needs:
|
||||
job: ppc64el-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-ppc64el-cross
|
||||
EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-devices
|
||||
|
||||
# The riscv64 cross-builds currently use a 'sid' container to get
|
||||
# compilers and libraries. Until something more stable is found we
|
||||
# allow_failure so as not to block CI.
|
||||
cross-riscv64-system:
|
||||
extends: .cross_system_build_job
|
||||
allow_failure: true
|
||||
needs:
|
||||
job: riscv64-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-riscv64-cross
|
||||
|
||||
cross-riscv64-user:
|
||||
extends: .cross_user_build_job
|
||||
allow_failure: true
|
||||
needs:
|
||||
job: riscv64-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-riscv64-cross
|
||||
|
||||
cross-s390x-system:
|
||||
extends: .cross_system_build_job
|
||||
needs:
|
||||
@ -159,7 +144,7 @@ cross-s390x-kvm-only:
|
||||
job: s390x-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-s390x-cross
|
||||
EXTRA_CONFIGURE_OPTS: --disable-tcg --enable-trace-backends=ftrace
|
||||
EXTRA_CONFIGURE_OPTS: --disable-tcg
|
||||
|
||||
cross-mips64el-kvm-only:
|
||||
extends: .cross_accel_build_job
|
||||
@ -175,7 +160,6 @@ cross-win32-system:
|
||||
job: win32-fedora-cross-container
|
||||
variables:
|
||||
IMAGE: fedora-win32-cross
|
||||
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal
|
||||
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
|
||||
microblazeel-softmmu mips64el-softmmu nios2-softmmu
|
||||
artifacts:
|
||||
@ -188,10 +172,7 @@ cross-win64-system:
|
||||
job: win64-fedora-cross-container
|
||||
variables:
|
||||
IMAGE: fedora-win64-cross
|
||||
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal
|
||||
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu
|
||||
m68k-softmmu microblazeel-softmmu nios2-softmmu
|
||||
or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu
|
||||
CROSS_SKIP_TARGETS: or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu
|
||||
tricore-softmmu xtensaeb-softmmu
|
||||
artifacts:
|
||||
paths:
|
||||
|
@ -13,19 +13,226 @@
|
||||
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_artifacts_template:
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
expire_in: 7 days
|
||||
paths:
|
||||
- build/meson-logs/testlog.txt
|
||||
reports:
|
||||
junit: build/meson-logs/testlog.junit.xml
|
||||
# All ubuntu-18.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
|
||||
ubuntu-18.04-s390x-all-linux-static:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
|
||||
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
- make --output-sync -j`nproc` check-tcg V=1
|
||||
|
||||
include:
|
||||
- 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'
|
||||
ubuntu-18.04-s390x-all:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-18.04-s390x-alldbg:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --disable-libssh
|
||||
- make clean
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-18.04-s390x-clang:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-18.04-s390x-tci:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --enable-tcg-interpreter
|
||||
- make --output-sync -j`nproc`
|
||||
|
||||
ubuntu-18.04-s390x-notcg:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_18.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --disable-tcg
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
# All ubuntu-20.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/qemu/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
|
||||
ubuntu-20.04-aarch64-all-linux-static:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
# --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763
|
||||
# --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
- make --output-sync -j`nproc` check-tcg V=1
|
||||
|
||||
ubuntu-20.04-aarch64-all:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-20.04-aarch64-alldbg:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --disable-libssh
|
||||
- make clean
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-20.04-aarch64-clang:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --cc=clang-10 --cxx=clang++-10 --enable-sanitizers
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
||||
ubuntu-20.04-aarch64-tci:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --enable-tcg-interpreter
|
||||
- make --output-sync -j`nproc`
|
||||
|
||||
ubuntu-20.04-aarch64-notcg:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --disable-tcg
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check V=1
|
||||
|
@ -1,30 +0,0 @@
|
||||
centos-stream-8-x86_64:
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- centos_stream_8
|
||||
- x86_64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$CENTOS_STREAM_8_x86_64_RUNNER_AVAILABLE"
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
when: on_failure
|
||||
expire_in: 7 days
|
||||
paths:
|
||||
- build/tests/results/latest/results.xml
|
||||
- build/tests/results/latest/test-results
|
||||
reports:
|
||||
junit: build/tests/results/latest/results.xml
|
||||
before_script:
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../scripts/ci/org.centos/stream/8/x86_64/configure
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make -j"$JOBS"
|
||||
- make NINJA=":" check
|
||||
|| { cat meson-logs/testlog.txt; exit 1; } ;
|
||||
- ../scripts/ci/org.centos/stream/8/x86_64/test-avocado
|
@ -1,130 +0,0 @@
|
||||
# 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-20.04-s390x-all-linux-static:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- 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 --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-20.04-s390x-all:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
timeout: 75m
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../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-20.04-s390x-alldbg:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug --disable-libssh
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make clean
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check
|
||||
|
||||
ubuntu-20.04-s390x-clang:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check
|
||||
|
||||
ubuntu-20.04-s390x-tci:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --enable-tcg-interpreter
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc`
|
||||
|
||||
ubuntu-20.04-s390x-notcg:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_20.04
|
||||
- s390x
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$S390X_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --disable-tcg
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc`
|
||||
- make --output-sync -j`nproc` check
|
@ -1,25 +0,0 @@
|
||||
# All ubuntu-22.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/qemu/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 20.04"
|
||||
|
||||
ubuntu-22.04-aarch32-all:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- aarch32
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH32_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --cross-prefix=arm-linux-gnueabihf-
|
||||
|| { 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,129 +0,0 @@
|
||||
# All ubuntu-20.04 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/qemu/build-environment.yml task
|
||||
# "Install basic packages to build QEMU on Ubuntu 20.04"
|
||||
|
||||
ubuntu-22.04-aarch64-all-linux-static:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
# Disable -static-pie due to build error with system libc:
|
||||
# https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1987438
|
||||
- ../configure --enable-debug --static --disable-system --disable-pie
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc --ignore=40`
|
||||
- make check-tcg
|
||||
- make --output-sync -j`nproc --ignore=40` check
|
||||
|
||||
ubuntu-22.04-aarch64-all:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure
|
||||
|| { 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
|
||||
|
||||
ubuntu-22.04-aarch64-alldbg:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-debug
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make clean
|
||||
- make --output-sync -j`nproc --ignore=40`
|
||||
- make --output-sync -j`nproc --ignore=40` check
|
||||
|
||||
ubuntu-22.04-aarch64-clang:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-libssh --cc=clang --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
|
||||
|
||||
ubuntu-22.04-aarch64-tci:
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-tcg-interpreter
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make --output-sync -j`nproc --ignore=40`
|
||||
|
||||
ubuntu-22.04-aarch64-notcg:
|
||||
extends: .custom_artifacts_template
|
||||
needs: []
|
||||
stage: build
|
||||
tags:
|
||||
- ubuntu_22.04
|
||||
- aarch64
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: "$AARCH64_RUNNER_AVAILABLE"
|
||||
when: manual
|
||||
allow_failure: true
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-tcg
|
||||
|| { 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,85 +1,56 @@
|
||||
# All jobs needing docker-edk2 must use the same rules it uses.
|
||||
.edk2_job_rules:
|
||||
rules:
|
||||
# Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
|
||||
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
when: never
|
||||
|
||||
# In forks, if QEMU_CI=1 is set, then create manual job
|
||||
# if any of the files affecting the build are touched
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
changes:
|
||||
- .gitlab-ci.d/edk2.yml
|
||||
- .gitlab-ci.d/edk2/Dockerfile
|
||||
- roms/edk2/*
|
||||
when: manual
|
||||
|
||||
# In forks, if QEMU_CI=1 is set, then create manual job
|
||||
# if the branch/tag starts with 'edk2'
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_REF_NAME =~ /^edk2/'
|
||||
when: manual
|
||||
|
||||
# In forks, if QEMU_CI=1 is set, then create manual job
|
||||
# if last commit msg contains 'EDK2' (case insensitive)
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_MESSAGE =~ /edk2/i'
|
||||
when: manual
|
||||
|
||||
# Run if any files affecting the build output are touched
|
||||
- changes:
|
||||
- .gitlab-ci.d/edk2.yml
|
||||
- .gitlab-ci.d/edk2/Dockerfile
|
||||
- roms/edk2/*
|
||||
when: on_success
|
||||
|
||||
# Run if the branch/tag starts with 'edk2'
|
||||
- if: '$CI_COMMIT_REF_NAME =~ /^edk2/'
|
||||
when: on_success
|
||||
|
||||
# Run if last commit msg contains 'EDK2' (case insensitive)
|
||||
- if: '$CI_COMMIT_MESSAGE =~ /edk2/i'
|
||||
when: on_success
|
||||
rules: # Only run this job when ...
|
||||
- changes:
|
||||
# this file is modified
|
||||
- .gitlab-ci.d/edk2.yml
|
||||
# or the Dockerfile is modified
|
||||
- .gitlab-ci.d/edk2/Dockerfile
|
||||
# or roms/edk2/ is modified (submodule updated)
|
||||
- roms/edk2/*
|
||||
when: on_success
|
||||
- if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2'
|
||||
when: on_success
|
||||
- if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2'
|
||||
when: on_success
|
||||
|
||||
docker-edk2:
|
||||
extends: .edk2_job_rules
|
||||
stage: containers
|
||||
image: docker:19.03.1
|
||||
services:
|
||||
- docker:19.03.1-dind
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:edk2-cross-build
|
||||
# We don't use TLS
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker pull $IMAGE_TAG || true
|
||||
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
--tag $IMAGE_TAG .gitlab-ci.d/edk2
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
- docker push $IMAGE_TAG
|
||||
extends: .edk2_job_rules
|
||||
stage: containers
|
||||
image: docker:19.03.1
|
||||
services:
|
||||
- docker:19.03.1-dind
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:edk2-cross-build
|
||||
# We don't use TLS
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker pull $IMAGE_TAG || true
|
||||
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
--tag $IMAGE_TAG .gitlab-ci.d/edk2
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
- docker push $IMAGE_TAG
|
||||
|
||||
build-edk2:
|
||||
extends: .edk2_job_rules
|
||||
stage: build
|
||||
needs: ['docker-edk2']
|
||||
artifacts:
|
||||
paths: # 'artifacts.zip' will contains the following files:
|
||||
- pc-bios/edk2*bz2
|
||||
- pc-bios/edk2-licenses.txt
|
||||
- edk2-stdout.log
|
||||
- edk2-stderr.log
|
||||
image: $CI_REGISTRY_IMAGE:edk2-cross-build
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
script: # Clone the required submodules and build EDK2
|
||||
- git submodule update --init roms/edk2
|
||||
- git -C roms/edk2 submodule update --init --
|
||||
ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
|
||||
BaseTools/Source/C/BrotliCompress/brotli
|
||||
CryptoPkg/Library/OpensslLib/openssl
|
||||
MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
|
||||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
- make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2
|
||||
extends: .edk2_job_rules
|
||||
stage: build
|
||||
needs: ['docker-edk2']
|
||||
artifacts:
|
||||
paths: # 'artifacts.zip' will contains the following files:
|
||||
- pc-bios/edk2*bz2
|
||||
- pc-bios/edk2-licenses.txt
|
||||
- edk2-stdout.log
|
||||
- edk2-stderr.log
|
||||
image: $CI_REGISTRY_IMAGE:edk2-cross-build
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
script: # Clone the required submodules and build EDK2
|
||||
- git submodule update --init roms/edk2
|
||||
- git -C roms/edk2 submodule update --init
|
||||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
- make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2
|
||||
|
@ -1,9 +1,9 @@
|
||||
#
|
||||
# Docker image to cross-compile EDK2 firmware binaries
|
||||
#
|
||||
FROM ubuntu:18.04
|
||||
FROM ubuntu:16.04
|
||||
|
||||
MAINTAINER Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
MAINTAINER Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
|
||||
# Install packages required to build EDK2
|
||||
RUN apt update \
|
||||
@ -20,7 +20,7 @@ RUN apt update \
|
||||
iasl \
|
||||
make \
|
||||
nasm \
|
||||
python3 \
|
||||
python \
|
||||
uuid-dev \
|
||||
&& \
|
||||
\
|
||||
|
@ -1,85 +1,63 @@
|
||||
# All jobs needing docker-opensbi must use the same rules it uses.
|
||||
.opensbi_job_rules:
|
||||
rules:
|
||||
# Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
|
||||
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
when: never
|
||||
|
||||
# In forks, if QEMU_CI=1 is set, then create manual job
|
||||
# if any files affecting the build output are touched
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
changes:
|
||||
- .gitlab-ci.d/opensbi.yml
|
||||
- .gitlab-ci.d/opensbi/Dockerfile
|
||||
- roms/opensbi/*
|
||||
when: manual
|
||||
|
||||
# In forks, if QEMU_CI=1 is set, then create manual job
|
||||
# if the branch/tag starts with 'opensbi'
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_REF_NAME =~ /^opensbi/'
|
||||
when: manual
|
||||
|
||||
# In forks, if QEMU_CI=1 is set, then create manual job
|
||||
# if the last commit msg contains 'OpenSBI' (case insensitive)
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_MESSAGE =~ /opensbi/i'
|
||||
when: manual
|
||||
|
||||
# Run if any files affecting the build output are touched
|
||||
- changes:
|
||||
- .gitlab-ci.d/opensbi.yml
|
||||
- .gitlab-ci.d/opensbi/Dockerfile
|
||||
- roms/opensbi/*
|
||||
when: on_success
|
||||
|
||||
# Run if the branch/tag starts with 'opensbi'
|
||||
- if: '$CI_COMMIT_REF_NAME =~ /^opensbi/'
|
||||
when: on_success
|
||||
|
||||
# Run if the last commit msg contains 'OpenSBI' (case insensitive)
|
||||
- if: '$CI_COMMIT_MESSAGE =~ /opensbi/i'
|
||||
when: on_success
|
||||
rules: # Only run this job when ...
|
||||
- changes:
|
||||
# this file is modified
|
||||
- .gitlab-ci.d/opensbi.yml
|
||||
# or the Dockerfile is modified
|
||||
- .gitlab-ci.d/opensbi/Dockerfile
|
||||
when: on_success
|
||||
- changes: # or roms/opensbi/ is modified (submodule updated)
|
||||
- roms/opensbi/*
|
||||
when: on_success
|
||||
- if: '$CI_COMMIT_REF_NAME =~ /^opensbi/' # or the branch/tag starts with 'opensbi'
|
||||
when: on_success
|
||||
- if: '$CI_COMMIT_MESSAGE =~ /opensbi/i' # or last commit description contains 'OpenSBI'
|
||||
when: on_success
|
||||
|
||||
docker-opensbi:
|
||||
extends: .opensbi_job_rules
|
||||
stage: containers
|
||||
image: docker:19.03.1
|
||||
services:
|
||||
- docker:19.03.1-dind
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build
|
||||
# We don't use TLS
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker pull $IMAGE_TAG || true
|
||||
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
--tag $IMAGE_TAG .gitlab-ci.d/opensbi
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
- docker push $IMAGE_TAG
|
||||
extends: .opensbi_job_rules
|
||||
stage: containers
|
||||
image: docker:19.03.1
|
||||
services:
|
||||
- docker:19.03.1-dind
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build
|
||||
# We don't use TLS
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker pull $IMAGE_TAG || true
|
||||
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
--tag $IMAGE_TAG .gitlab-ci.d/opensbi
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
- docker push $IMAGE_TAG
|
||||
|
||||
build-opensbi:
|
||||
extends: .opensbi_job_rules
|
||||
stage: build
|
||||
needs: ['docker-opensbi']
|
||||
artifacts:
|
||||
paths: # 'artifacts.zip' will contains the following files:
|
||||
- pc-bios/opensbi-riscv32-generic-fw_dynamic.bin
|
||||
- pc-bios/opensbi-riscv64-generic-fw_dynamic.bin
|
||||
- opensbi32-generic-stdout.log
|
||||
- opensbi32-generic-stderr.log
|
||||
- opensbi64-generic-stdout.log
|
||||
- opensbi64-generic-stderr.log
|
||||
image: $CI_REGISTRY_IMAGE:opensbi-cross-build
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
script: # Clone the required submodules and build OpenSBI
|
||||
- git submodule update --init roms/opensbi
|
||||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi32-generic 2>&1 1>opensbi32-generic-stdout.log | tee -a opensbi32-generic-stderr.log >&2
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi64-generic 2>&1 1>opensbi64-generic-stdout.log | tee -a opensbi64-generic-stderr.log >&2
|
||||
extends: .opensbi_job_rules
|
||||
stage: build
|
||||
needs: ['docker-opensbi']
|
||||
artifacts:
|
||||
paths: # 'artifacts.zip' will contains the following files:
|
||||
- pc-bios/opensbi-riscv32-generic-fw_dynamic.bin
|
||||
- pc-bios/opensbi-riscv32-generic-fw_dynamic.elf
|
||||
- pc-bios/opensbi-riscv64-generic-fw_dynamic.bin
|
||||
- pc-bios/opensbi-riscv64-generic-fw_dynamic.elf
|
||||
- opensbi32-generic-stdout.log
|
||||
- opensbi32-generic-stderr.log
|
||||
- opensbi64-generic-stdout.log
|
||||
- opensbi64-generic-stderr.log
|
||||
image: $CI_REGISTRY_IMAGE:opensbi-cross-build
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
script: # Clone the required submodules and build OpenSBI
|
||||
- git submodule update --init roms/opensbi
|
||||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi32-generic 2>&1 1>opensbi32-generic-stdout.log | tee -a opensbi32-generic-stderr.log >&2
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi64-generic 2>&1 1>opensbi64-generic-stdout.log | tee -a opensbi64-generic-stderr.log >&2
|
||||
|
@ -2,7 +2,6 @@
|
||||
# https://gitlab.com/qemu-project/qemu/-/pipelines
|
||||
|
||||
include:
|
||||
- local: '/.gitlab-ci.d/base.yml'
|
||||
- local: '/.gitlab-ci.d/stages.yml'
|
||||
- local: '/.gitlab-ci.d/edk2.yml'
|
||||
- local: '/.gitlab-ci.d/opensbi.yml'
|
||||
@ -12,4 +11,3 @@ include:
|
||||
- local: '/.gitlab-ci.d/static_checks.yml'
|
||||
- local: '/.gitlab-ci.d/custom-runners.yml'
|
||||
- local: '/.gitlab-ci.d/cirrus.yml'
|
||||
- local: '/.gitlab-ci.d/windows.yml'
|
||||
|
@ -3,5 +3,6 @@
|
||||
# - test (for test stages, using build artefacts from a build stage)
|
||||
stages:
|
||||
- containers
|
||||
- containers-layer2
|
||||
- build
|
||||
- test
|
||||
|
@ -1,41 +1,42 @@
|
||||
check-patch:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: python:3.10-alpine
|
||||
needs: []
|
||||
image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
|
||||
needs:
|
||||
job: amd64-centos8-container
|
||||
script:
|
||||
- .gitlab-ci.d/check-patch.py
|
||||
variables:
|
||||
GIT_DEPTH: 1000
|
||||
QEMU_JOB_ONLY_FORKS: 1
|
||||
before_script:
|
||||
- apk -U add git perl
|
||||
allow_failure: true
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
when: never
|
||||
- when: on_success
|
||||
allow_failure: true
|
||||
|
||||
check-dco:
|
||||
extends: .base_job_template
|
||||
stage: build
|
||||
image: python:3.10-alpine
|
||||
needs: []
|
||||
image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
|
||||
needs:
|
||||
job: amd64-centos8-container
|
||||
script: .gitlab-ci.d/check-dco.py
|
||||
variables:
|
||||
GIT_DEPTH: 1000
|
||||
before_script:
|
||||
- apk -U add git
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
when: never
|
||||
- when: on_success
|
||||
|
||||
check-python-minreqs:
|
||||
extends: .base_job_template
|
||||
check-python-pipenv:
|
||||
stage: test
|
||||
image: $CI_REGISTRY_IMAGE/qemu/python:latest
|
||||
script:
|
||||
- make -C python check-minreqs
|
||||
- make -C python check-pipenv
|
||||
variables:
|
||||
GIT_DEPTH: 1
|
||||
needs:
|
||||
job: python-container
|
||||
|
||||
check-python-tox:
|
||||
extends: .base_job_template
|
||||
stage: test
|
||||
image: $CI_REGISTRY_IMAGE/qemu/python:latest
|
||||
script:
|
||||
@ -43,6 +44,6 @@ check-python-tox:
|
||||
variables:
|
||||
GIT_DEPTH: 1
|
||||
QEMU_TOX_EXTRA_ARGS: --skip-missing-interpreters=false
|
||||
QEMU_JOB_OPTIONAL: 1
|
||||
needs:
|
||||
job: python-container
|
||||
allow_failure: true
|
||||
|
@ -1,122 +0,0 @@
|
||||
.shared_msys2_builder:
|
||||
extends: .base_job_template
|
||||
tags:
|
||||
- shared-windows
|
||||
- windows
|
||||
- windows-1809
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}-cache"
|
||||
paths:
|
||||
- ${CI_PROJECT_DIR}/msys64/var/cache
|
||||
needs: []
|
||||
stage: build
|
||||
timeout: 80m
|
||||
before_script:
|
||||
- If ( !(Test-Path -Path msys64\var\cache ) ) {
|
||||
mkdir msys64\var\cache
|
||||
}
|
||||
- If ( !(Test-Path -Path msys64\var\cache\msys2.exe ) ) {
|
||||
Invoke-WebRequest
|
||||
"https://github.com/msys2/msys2-installer/releases/download/2022-06-03/msys2-base-x86_64-20220603.sfx.exe"
|
||||
-outfile "msys64\var\cache\msys2.exe"
|
||||
}
|
||||
- msys64\var\cache\msys2.exe -y
|
||||
- ((Get-Content -path .\msys64\etc\\post-install\\07-pacman-key.post -Raw)
|
||||
-replace '--refresh-keys', '--version') |
|
||||
Set-Content -Path ${CI_PROJECT_DIR}\msys64\etc\\post-install\\07-pacman-key.post
|
||||
- .\msys64\usr\bin\bash -lc "sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf"
|
||||
- .\msys64\usr\bin\bash -lc 'pacman --noconfirm -Syuu' # Core update
|
||||
- .\msys64\usr\bin\bash -lc 'pacman --noconfirm -Syuu' # Normal update
|
||||
- taskkill /F /FI "MODULES eq msys-2.0.dll"
|
||||
|
||||
msys2-64bit:
|
||||
extends: .shared_msys2_builder
|
||||
script:
|
||||
- .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed
|
||||
bison diffutils flex
|
||||
git grep make sed
|
||||
mingw-w64-x86_64-capstone
|
||||
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-usbredir
|
||||
mingw-w64-x86_64-zstd "
|
||||
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||
- $env:MSYSTEM = 'MINGW64' # Start a 64-bit MinGW environment
|
||||
- $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
|
||||
- mkdir output
|
||||
- cd output
|
||||
# Note: 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 the msys2 64-bit job, due to the build could not complete within
|
||||
# the project timeout.
|
||||
- ..\msys64\usr\bin\bash -lc '../configure --target-list=x86_64-softmmu
|
||||
--without-default-devices --enable-fdt=system'
|
||||
- ..\msys64\usr\bin\bash -lc 'make'
|
||||
# qTests don't run successfully with "--without-default-devices",
|
||||
# so let's exclude the qtests from CI for now.
|
||||
- ..\msys64\usr\bin\bash -lc 'make check MTESTARGS=\"--no-suite qtest\" || { cat meson-logs/testlog.txt; exit 1; } ;'
|
||||
|
||||
msys2-32bit:
|
||||
extends: .shared_msys2_builder
|
||||
script:
|
||||
- .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed
|
||||
bison diffutils flex
|
||||
git grep make sed
|
||||
mingw-w64-i686-capstone
|
||||
mingw-w64-i686-curl
|
||||
mingw-w64-i686-cyrus-sasl
|
||||
mingw-w64-i686-dtc
|
||||
mingw-w64-i686-gcc
|
||||
mingw-w64-i686-glib2
|
||||
mingw-w64-i686-gnutls
|
||||
mingw-w64-i686-gtk3
|
||||
mingw-w64-i686-libgcrypt
|
||||
mingw-w64-i686-libjpeg-turbo
|
||||
mingw-w64-i686-libnfs
|
||||
mingw-w64-i686-libpng
|
||||
mingw-w64-i686-libssh
|
||||
mingw-w64-i686-libtasn1
|
||||
mingw-w64-i686-libusb
|
||||
mingw-w64-i686-lzo2
|
||||
mingw-w64-i686-nettle
|
||||
mingw-w64-i686-ninja
|
||||
mingw-w64-i686-pixman
|
||||
mingw-w64-i686-pkgconf
|
||||
mingw-w64-i686-python
|
||||
mingw-w64-i686-SDL2
|
||||
mingw-w64-i686-SDL2_image
|
||||
mingw-w64-i686-snappy
|
||||
mingw-w64-i686-usbredir
|
||||
mingw-w64-i686-zstd "
|
||||
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||
- $env:MSYSTEM = 'MINGW32' # Start a 32-bit MinGW environment
|
||||
- $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink
|
||||
- mkdir output
|
||||
- cd output
|
||||
- ..\msys64\usr\bin\bash -lc '../configure --target-list=ppc64-softmmu
|
||||
--enable-fdt=system'
|
||||
- ..\msys64\usr\bin\bash -lc 'make'
|
||||
- ..\msys64\usr\bin\bash -lc 'make check MTESTARGS=\"--no-suite qtest\" ||
|
||||
{ cat meson-logs/testlog.txt; exit 1; }'
|
@ -18,11 +18,11 @@ https://www.qemu.org/contribute/security-process/
|
||||
-->
|
||||
|
||||
## Host environment
|
||||
- Operating system: <!-- Windows 10 21H1, Fedora 37, etc. -->
|
||||
- OS/kernel version: <!-- For POSIX hosts, use `uname -a` -->
|
||||
- Architecture: <!-- x86, ARM, s390x, etc. -->
|
||||
- QEMU flavor: <!-- qemu-system-x86_64, qemu-aarch64, qemu-img, etc. -->
|
||||
- QEMU version: <!-- e.g. `qemu-system-x86_64 --version` -->
|
||||
- Operating system: (Windows 10 21H1, Fedora 34, etc.)
|
||||
- OS/kernel version: (For POSIX hosts, use `uname -a`)
|
||||
- Architecture: (x86, ARM, s390x, etc.)
|
||||
- QEMU flavor: (qemu-system-x86_64, qemu-aarch64, qemu-img, etc.)
|
||||
- QEMU version: (e.g. `qemu-system-x86_64 --version`)
|
||||
- QEMU command line:
|
||||
<!--
|
||||
Give the smallest, complete command line that exhibits the problem.
|
||||
@ -35,9 +35,9 @@ https://www.qemu.org/contribute/security-process/
|
||||
```
|
||||
|
||||
## Emulated/Virtualized environment
|
||||
- Operating system: <!-- Windows 10 21H1, Fedora 37, etc. -->
|
||||
- OS/kernel version: <!-- For POSIX guests, use `uname -a`. -->
|
||||
- Architecture: <!-- x86, ARM, s390x, etc. -->
|
||||
- Operating system: (Windows 10 21H1, Fedora 34, etc.)
|
||||
- OS/kernel version: (For POSIX guests, use `uname -a`.)
|
||||
- Architecture: (x86, ARM, s390x, etc.)
|
||||
|
||||
|
||||
## Description of problem
|
||||
|
15
.gitmodules
vendored
15
.gitmodules
vendored
@ -13,6 +13,9 @@
|
||||
[submodule "roms/qemu-palcode"]
|
||||
path = roms/qemu-palcode
|
||||
url = https://gitlab.com/qemu-project/qemu-palcode.git
|
||||
[submodule "roms/sgabios"]
|
||||
path = roms/sgabios
|
||||
url = https://gitlab.com/qemu-project/sgabios.git
|
||||
[submodule "dtc"]
|
||||
path = dtc
|
||||
url = https://gitlab.com/qemu-project/dtc.git
|
||||
@ -28,6 +31,9 @@
|
||||
[submodule "ui/keycodemapdb"]
|
||||
path = ui/keycodemapdb
|
||||
url = https://gitlab.com/qemu-project/keycodemapdb.git
|
||||
[submodule "capstone"]
|
||||
path = capstone
|
||||
url = https://gitlab.com/qemu-project/capstone.git
|
||||
[submodule "roms/seabios-hppa"]
|
||||
path = roms/seabios-hppa
|
||||
url = https://gitlab.com/qemu-project/seabios-hppa.git
|
||||
@ -43,6 +49,9 @@
|
||||
[submodule "roms/edk2"]
|
||||
path = roms/edk2
|
||||
url = https://gitlab.com/qemu-project/edk2.git
|
||||
[submodule "slirp"]
|
||||
path = slirp
|
||||
url = https://gitlab.com/qemu-project/libslirp.git
|
||||
[submodule "roms/opensbi"]
|
||||
path = roms/opensbi
|
||||
url = https://gitlab.com/qemu-project/opensbi.git
|
||||
@ -55,9 +64,3 @@
|
||||
[submodule "roms/vbootrom"]
|
||||
path = roms/vbootrom
|
||||
url = https://gitlab.com/qemu-project/vbootrom.git
|
||||
[submodule "tests/lcitool/libvirt-ci"]
|
||||
path = tests/lcitool/libvirt-ci
|
||||
url = https://gitlab.com/libvirt/libvirt-ci.git
|
||||
[submodule "subprojects/libvfio-user"]
|
||||
path = subprojects/libvfio-user
|
||||
url = https://gitlab.com/qemu-project/libvfio-user.git
|
||||
|
22
.mailmap
22
.mailmap
@ -28,11 +28,7 @@ Thiemo Seufer <ths@networkno.de> ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
|
||||
malc <av1474@comtv.ru> malc <malc@c046a42c-6fe2-441c-8c8c-71466251a162>
|
||||
|
||||
# Corrupted Author fields
|
||||
Aaron Larson <alarson@ddci.com> alarson@ddci.com
|
||||
Andreas Färber <andreas.faerber@web.de> Andreas Färber <andreas.faerber>
|
||||
Jason Wang <jasowang@redhat.com> Jason Wang <jasowang>
|
||||
Marek Dolata <mkdolata@us.ibm.com> mkdolata@us.ibm.com <mkdolata@us.ibm.com>
|
||||
Michael Ellerman <mpe@ellerman.id.au> michael@ozlabs.org <michael@ozlabs.org>
|
||||
Nick Hudson <hnick@vmware.com> hnick@vmware.com <hnick@vmware.com>
|
||||
|
||||
# There is also a:
|
||||
@ -45,7 +41,6 @@ Ed Swierk <eswierk@skyportsystems.com> Ed Swierk via Qemu-devel <qemu-devel@nong
|
||||
Ian McKellar <ianloic@google.com> Ian McKellar via Qemu-devel <qemu-devel@nongnu.org>
|
||||
Julia Suvorova <jusual@mail.ru> Julia Suvorova via Qemu-devel <qemu-devel@nongnu.org>
|
||||
Justin Terry (VM) <juterry@microsoft.com> Justin Terry (VM) via Qemu-devel <qemu-devel@nongnu.org>
|
||||
Stefan Weil <sw@weilnetz.de> Stefan Weil via <qemu-devel@nongnu.org>
|
||||
|
||||
# Next, replace old addresses by a more recent one.
|
||||
Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <aleksandar.markovic@mips.com>
|
||||
@ -55,34 +50,25 @@ Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <arikalo@wavecomp.com>
|
||||
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
|
||||
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
|
||||
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
|
||||
Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
|
||||
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
|
||||
Frederic Konrad <konrad.frederic@yahoo.fr> <fred.konrad@greensocs.com>
|
||||
Frederic Konrad <konrad.frederic@yahoo.fr> <konrad@adacore.com>
|
||||
Frederic Konrad <konrad@adacore.com> <fred.konrad@greensocs.com>
|
||||
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
|
||||
Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
|
||||
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
|
||||
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
|
||||
Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
|
||||
Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
|
||||
Leif Lindholm <leif@nuviainc.com> <leif.lindholm@linaro.org>
|
||||
Radoslaw Biernacki <rad@semihalf.com> <radoslaw.biernacki@linaro.org>
|
||||
Paul Brook <paul@nowt.org> <paul@codesourcery.com>
|
||||
Paul Burton <paulburton@kernel.org> <paul.burton@mips.com>
|
||||
Paul Burton <paulburton@kernel.org> <paul.burton@imgtec.com>
|
||||
Paul Burton <paulburton@kernel.org> <paul@archlinuxmips.org>
|
||||
Paul Burton <paulburton@kernel.org> <pburton@wavecomp.com>
|
||||
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>
|
||||
Stefan Brankovic <stefan.brankovic@syrmia.com> <stefan.brankovic@rt-rk.com.com>
|
||||
Yongbok Kim <yongbok.kim@mips.com> <yongbok.kim@imgtec.com>
|
||||
|
||||
# Also list preferred name forms where people have changed their
|
||||
# git author config, or had utf8/latin1 encoding issues.
|
||||
Aaron Lindsay <aaron@os.amperecomputing.com>
|
||||
Aaron Larson <alarson@ddci.com>
|
||||
Alexey Gerasimenko <x1917x@gmail.com>
|
||||
Alex Chen <alex.chen@huawei.com>
|
||||
Alex Ivanov <void@aleksoft.net>
|
||||
Andreas Färber <afaerber@suse.de>
|
||||
Bandan Das <bsd@redhat.com>
|
||||
@ -113,11 +99,9 @@ Gautham R. Shenoy <ego@in.ibm.com>
|
||||
Gautham R. Shenoy <ego@linux.vnet.ibm.com>
|
||||
Gonglei (Arei) <arei.gonglei@huawei.com>
|
||||
Guang Wang <wang.guang55@zte.com.cn>
|
||||
Haibin Zhang <haibinzhang@tencent.com>
|
||||
Hailiang Zhang <zhang.zhanghailiang@huawei.com>
|
||||
Hanna Reitz <hreitz@redhat.com> <mreitz@redhat.com>
|
||||
Hervé Poussineau <hpoussin@reactos.org>
|
||||
Hyman Huang <huangy81@chinatelecom.cn>
|
||||
Jakub Jermář <jakub@jermar.eu>
|
||||
Jakub Jermář <jakub.jermar@kernkonzept.com>
|
||||
Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
@ -151,11 +135,9 @@ Nicholas Thomas <nick@bytemark.co.uk>
|
||||
Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
|
||||
Orit Wasserman <owasserm@redhat.com>
|
||||
Paolo Bonzini <pbonzini@redhat.com>
|
||||
Pan Nengyuan <pannengyuan@huawei.com>
|
||||
Pavel Dovgaluk <dovgaluk@ispras.ru>
|
||||
Pavel Dovgaluk <pavel.dovgaluk@gmail.com>
|
||||
Pavel Dovgaluk <Pavel.Dovgaluk@ispras.ru>
|
||||
Peter Chubb <peter.chubb@nicta.com.au>
|
||||
Peter Crosthwaite <crosthwaite.peter@gmail.com>
|
||||
Peter Crosthwaite <peter.crosthwaite@petalogix.com>
|
||||
Peter Crosthwaite <peter.crosthwaite@xilinx.com>
|
||||
|
96
.travis.yml
96
.travis.yml
@ -1,3 +1,6 @@
|
||||
# The current Travis default is a VM based 16.04 Xenial on GCE
|
||||
# Additional builds with specific requirements for a full VM need to
|
||||
# be added as additional matrix: entries later on
|
||||
os: linux
|
||||
dist: focal
|
||||
language: c
|
||||
@ -16,6 +19,43 @@ cache:
|
||||
- $HOME/avocado/data/cache
|
||||
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# Build dependencies
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libcacard-dev
|
||||
- libgcc-7-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
- libncurses5-dev
|
||||
- libnfs-dev
|
||||
- libpixman-1-dev
|
||||
- libpng-dev
|
||||
- librados-dev
|
||||
- libsdl2-dev
|
||||
- libsdl2-image-dev
|
||||
- libseccomp-dev
|
||||
- libspice-protocol-dev
|
||||
- libspice-server-dev
|
||||
- libssh-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- libzstd-dev
|
||||
- ninja-build
|
||||
- sparse
|
||||
- uuid-dev
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
|
||||
|
||||
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
|
||||
# to prevent IRC notifications from forks. This was created using:
|
||||
# $ travis encrypt -r "qemu/qemu" "irc.oftc.net#qemu"
|
||||
@ -91,7 +131,6 @@ jobs:
|
||||
- libbrlapi-dev
|
||||
- libcacard-dev
|
||||
- libcap-ng-dev
|
||||
- libfdt-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
@ -113,8 +152,7 @@ jobs:
|
||||
- genisoimage
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --enable-fdt=system
|
||||
--target-list=${MAIN_SOFTMMU_TARGETS} --cxx=/bin/false"
|
||||
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS} --cxx=/bin/false"
|
||||
- UNRELIABLE=true
|
||||
|
||||
- name: "[ppc64] GCC check-tcg"
|
||||
@ -127,7 +165,6 @@ jobs:
|
||||
- libbrlapi-dev
|
||||
- libcacard-dev
|
||||
- libcap-ng-dev
|
||||
- libfdt-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
@ -149,12 +186,11 @@ jobs:
|
||||
- genisoimage
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --enable-fdt=system
|
||||
--target-list=ppc64-softmmu,ppc64le-linux-user"
|
||||
- CONFIG="--disable-containers --target-list=ppc64-softmmu,ppc64le-linux-user"
|
||||
|
||||
- name: "[s390x] GCC check-tcg"
|
||||
arch: s390x
|
||||
dist: focal
|
||||
dist: bionic
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
@ -162,7 +198,6 @@ jobs:
|
||||
- libbrlapi-dev
|
||||
- libcacard-dev
|
||||
- libcap-ng-dev
|
||||
- libfdt-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
@ -184,14 +219,13 @@ jobs:
|
||||
- genisoimage
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --enable-fdt=system
|
||||
--target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
|
||||
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
|
||||
- UNRELIABLE=true
|
||||
script:
|
||||
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
|
||||
- |
|
||||
if [ "$BUILD_RC" -eq 0 ] ; then
|
||||
mv pc-bios/s390-ccw/*.img qemu-bundle/usr/local/share/qemu ;
|
||||
mv pc-bios/s390-ccw/*.img pc-bios/ ;
|
||||
${TEST_CMD} ;
|
||||
else
|
||||
$(exit $BUILD_RC);
|
||||
@ -199,14 +233,13 @@ jobs:
|
||||
|
||||
- name: "[s390x] GCC (other-softmmu)"
|
||||
arch: s390x
|
||||
dist: focal
|
||||
dist: bionic
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libcacard-dev
|
||||
- libcap-ng-dev
|
||||
- libfdt-dev
|
||||
- libgnutls28-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
@ -225,16 +258,15 @@ jobs:
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
env:
|
||||
- CONFIG="--disable-containers --enable-fdt=system --audio-drv-list=sdl
|
||||
--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
|
||||
- CONFIG="--disable-containers --audio-drv-list=sdl --disable-user
|
||||
--target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
|
||||
|
||||
- name: "[s390x] GCC (user)"
|
||||
arch: s390x
|
||||
dist: focal
|
||||
dist: bionic
|
||||
addons:
|
||||
apt_packages:
|
||||
- libgcrypt20-dev
|
||||
- libglib2.0-dev
|
||||
- libgnutls28-dev
|
||||
- ninja-build
|
||||
env:
|
||||
@ -242,7 +274,7 @@ jobs:
|
||||
|
||||
- name: "[s390x] Clang (disable-tcg)"
|
||||
arch: s390x
|
||||
dist: focal
|
||||
dist: bionic
|
||||
compiler: clang
|
||||
addons:
|
||||
apt_packages:
|
||||
@ -251,7 +283,6 @@ jobs:
|
||||
- libbrlapi-dev
|
||||
- libcacard-dev
|
||||
- libcap-ng-dev
|
||||
- libfdt-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
@ -271,6 +302,29 @@ jobs:
|
||||
- ninja-build
|
||||
env:
|
||||
- TEST_CMD="make check-unit"
|
||||
- CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools
|
||||
--enable-fdt=system --host-cc=clang --cxx=clang++"
|
||||
- CONFIG="--disable-containers --disable-tcg --enable-kvm
|
||||
--disable-tools --host-cc=clang --cxx=clang++"
|
||||
- UNRELIABLE=true
|
||||
|
||||
# Release builds
|
||||
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
|
||||
# This is the case when release candidate tags are created.
|
||||
- name: "Release tarball"
|
||||
if: tag IS present AND tag =~ /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
env:
|
||||
# We want to build from the release tarball
|
||||
- BUILD_DIR="release/build/dir" SRC_DIR="../../.."
|
||||
- BASE_CONFIG="--prefix=$PWD/dist"
|
||||
- CONFIG="--target-list=x86_64-softmmu,aarch64-softmmu,armeb-linux-user,ppc-linux-user"
|
||||
- TEST_CMD="make install -j${JOBS}"
|
||||
- QEMU_VERSION="${TRAVIS_TAG:1}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
script:
|
||||
- make -C ${SRC_DIR} qemu-${QEMU_VERSION}.tar.bz2
|
||||
- ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2
|
||||
- tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION}
|
||||
- mkdir -p release-build && cd release-build
|
||||
- ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- make install
|
||||
allow_failures:
|
||||
- env: UNRELIABLE=true
|
||||
|
72
3k.c
Normal file
72
3k.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void libafl_qemu_main_loop( void );
|
||||
void libafl_qemu_sys_init(int argc, char **argv, char **envp);
|
||||
void libafl_qemu_cleanup( void );
|
||||
|
||||
void libafl_qemu_set_breakpoint( unsigned long int );
|
||||
|
||||
void libafl_qemu_remove_native_breakpoint( unsigned long int );
|
||||
void libafl_qemu_set_native_breakpoint( unsigned long int );
|
||||
void libafl_snapshot_save( const char* );
|
||||
void libafl_snapshot_load( const char* );
|
||||
|
||||
void libafl_phys_read(uint32_t, uint8_t*, int);
|
||||
|
||||
void libafl_phys_write(uint32_t, uint8_t*, int);
|
||||
|
||||
int64_t icount_to_ns(int64_t icount);
|
||||
|
||||
int64_t libafl_get_clock( void );
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
unsigned char buf[32] = "_`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||
unsigned char buf2[32] = "0";
|
||||
unsigned char buf3[32] = "z";
|
||||
unsigned char buf4[32] = "a!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
||||
unsigned char buf5[32] = "b!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
|
||||
libafl_qemu_sys_init(argc, argv, envp);
|
||||
int pheader = 0x00006a4c;
|
||||
// libafl_phys_read(0x20000110-0x20000100+pheader, buf,32);
|
||||
// printf("FUZZ_INPUT[0]: %c\n", buf[0]);
|
||||
// Start pre-run
|
||||
libafl_qemu_set_native_breakpoint(0x4ce2);//send 217028
|
||||
libafl_qemu_main_loop();
|
||||
libafl_qemu_remove_native_breakpoint(0x4ce2);
|
||||
// End pre-run
|
||||
libafl_snapshot_save("Start");
|
||||
libafl_qemu_set_native_breakpoint(0x4be0);
|
||||
int64_t tmp = libafl_get_clock();
|
||||
printf("snapshot icount: %ld, %ldns\n",tmp,icount_to_ns(tmp));
|
||||
libafl_snapshot_load("Start");
|
||||
tmp = libafl_get_clock();
|
||||
printf("snapshot icount after load: %ld, %ldns\n",tmp,icount_to_ns(tmp));
|
||||
|
||||
libafl_phys_write(0x20000110-0x20000100+pheader, buf,32);
|
||||
libafl_qemu_main_loop();
|
||||
printf("%ld für %s\n",libafl_get_clock(),buf);
|
||||
libafl_snapshot_load("Start");
|
||||
|
||||
libafl_phys_write(0x20000110-0x20000100+pheader, buf2,32);
|
||||
libafl_qemu_main_loop();
|
||||
printf("%ld für %s\n",libafl_get_clock(),buf2);
|
||||
libafl_snapshot_load("Start");
|
||||
|
||||
libafl_phys_write(0x20000110-0x20000100+pheader, buf3,32);
|
||||
libafl_qemu_main_loop();
|
||||
printf("%ld für %s\n",libafl_get_clock(),buf3);
|
||||
libafl_snapshot_load("Start");
|
||||
/*int counter = 3000;
|
||||
do {
|
||||
libafl_phys_write(0x20000110-0x20000100+pheader, buf,32);
|
||||
libafl_qemu_main_loop();
|
||||
int64_t tmp = libafl_get_clock();
|
||||
printf("%ld, %ldns\n",tmp,icount_to_ns(tmp));
|
||||
libafl_snapshot_load("Start");
|
||||
// puts("Reload has occured");
|
||||
counter--;
|
||||
} while (counter);*/
|
||||
libafl_qemu_cleanup();
|
||||
return 0;
|
||||
}
|
11
Kconfig.host
11
Kconfig.host
@ -22,12 +22,15 @@ config TPM
|
||||
|
||||
config VHOST_USER
|
||||
bool
|
||||
select VHOST
|
||||
|
||||
config VHOST_VDPA
|
||||
bool
|
||||
select VHOST
|
||||
|
||||
config VHOST_KERNEL
|
||||
bool
|
||||
select VHOST
|
||||
|
||||
config VIRTFS
|
||||
bool
|
||||
@ -38,11 +41,3 @@ config PVRDMA
|
||||
config MULTIPROCESS_ALLOWED
|
||||
bool
|
||||
imply MULTIPROCESS
|
||||
|
||||
config FUZZ
|
||||
bool
|
||||
select SPARSE_MEM
|
||||
|
||||
config VFIO_USER_SERVER_ALLOWED
|
||||
bool
|
||||
imply VFIO_USER_SERVER
|
||||
|
869
MAINTAINERS
869
MAINTAINERS
File diff suppressed because it is too large
Load Diff
64
Makefile
64
Makefile
@ -42,9 +42,6 @@ configure: ;
|
||||
ifneq ($(wildcard config-host.mak),)
|
||||
include config-host.mak
|
||||
|
||||
include Makefile.prereqs
|
||||
Makefile.prereqs: config-host.mak
|
||||
|
||||
git-submodule-update:
|
||||
.git-submodule-status: git-submodule-update config-host.mak
|
||||
Makefile: .git-submodule-status
|
||||
@ -90,7 +87,7 @@ x := $(shell rm -rf meson-private meson-info meson-logs)
|
||||
endif
|
||||
|
||||
# 1. ensure config-host.mak is up-to-date
|
||||
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/scripts/meson-buildoptions.sh $(SRC_PATH)/VERSION
|
||||
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION
|
||||
@echo config-host.mak is out-of-date, running configure
|
||||
@if test -f meson-private/coredata.dat; then \
|
||||
./config.status --skip-meson; \
|
||||
@ -127,12 +124,6 @@ ifneq ($(MESON),)
|
||||
Makefile.mtest: build.ninja scripts/mtest2make.py
|
||||
$(MESON) introspect --targets --tests --benchmarks | $(PYTHON) scripts/mtest2make.py > $@
|
||||
-include Makefile.mtest
|
||||
|
||||
.PHONY: update-buildoptions
|
||||
all update-buildoptions: $(SRC_PATH)/scripts/meson-buildoptions.sh
|
||||
$(SRC_PATH)/scripts/meson-buildoptions.sh: $(SRC_PATH)/meson_options.txt
|
||||
$(MESON) introspect --buildoptions $(SRC_PATH)/meson.build | $(PYTHON) \
|
||||
scripts/meson-buildoptions.py > $@.tmp && mv $@.tmp $@
|
||||
endif
|
||||
|
||||
# 4. Rules to bridge to other makefiles
|
||||
@ -146,11 +137,11 @@ 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, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \
|
||||
-d keepdepfile
|
||||
ninja-cmd-goals = $(or $(MAKECMDGOALS), all)
|
||||
ninja-cmd-goals += $(foreach g, $(MAKECMDGOALS), $(.ninja-goals.$g))
|
||||
|
||||
makefile-targets := build.ninja ctags TAGS cscope dist clean
|
||||
ninja-cmd-goals = $(or $(MAKECMDGOALS), all)
|
||||
ninja-cmd-goals += $(foreach t, $(.tests), $(.test.deps.$t))
|
||||
|
||||
makefile-targets := build.ninja ctags TAGS cscope dist clean uninstall
|
||||
# "ninja -t targets" also lists all prerequisites. If build system
|
||||
# files are marked as PHONY, however, Make will always try to execute
|
||||
# "ninja build.ninja".
|
||||
@ -162,12 +153,15 @@ $(ninja-targets): run-ninja
|
||||
# --output-sync line.
|
||||
run-ninja: config-host.mak
|
||||
ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),)
|
||||
+$(if $(MAKE.nq),@:,$(quiet-@)$(NINJA) $(NINJAFLAGS) \
|
||||
$(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat)
|
||||
+$(quiet-@)$(if $(MAKE.nq),@:, $(NINJA) -d keepdepfile \
|
||||
$(NINJAFLAGS) $(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Force configure to re-run if the API symbols are updated
|
||||
ifeq ($(CONFIG_PLUGIN),y)
|
||||
config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols
|
||||
|
||||
.PHONY: plugins
|
||||
plugins:
|
||||
$(call quiet-command,\
|
||||
@ -189,27 +183,30 @@ include $(SRC_PATH)/tests/Makefile.include
|
||||
|
||||
all: recurse-all
|
||||
|
||||
ROMS_RULES=$(foreach t, all clean distclean, $(addsuffix /$(t), $(ROMS)))
|
||||
.PHONY: $(ROMS_RULES)
|
||||
$(ROMS_RULES):
|
||||
ROM_DIRS = $(addprefix pc-bios/, $(ROMS))
|
||||
ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS)))
|
||||
# Only keep -O and -g cflags
|
||||
.PHONY: $(ROM_DIRS_RULES)
|
||||
$(ROM_DIRS_RULES):
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" $(notdir $@),)
|
||||
|
||||
.PHONY: recurse-all recurse-clean
|
||||
recurse-all: $(addsuffix /all, $(ROMS))
|
||||
recurse-clean: $(addsuffix /clean, $(ROMS))
|
||||
recurse-distclean: $(addsuffix /distclean, $(ROMS))
|
||||
recurse-all: $(addsuffix /all, $(ROM_DIRS))
|
||||
recurse-clean: $(addsuffix /clean, $(ROM_DIRS))
|
||||
|
||||
######################################################################
|
||||
|
||||
clean: recurse-clean
|
||||
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean || :
|
||||
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) clean-ctlist || :
|
||||
find . \( -name '*.so' -o -name '*.dll' -o \
|
||||
-name '*.[oda]' -o -name '*.gcno' \) -type f \
|
||||
# avoid old build problems by removing potentially incorrect old files
|
||||
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
|
||||
find . \( -name '*.so' -o -name '*.dll' -o -name '*.[oda]' \) -type f \
|
||||
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-aarch64.a \
|
||||
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \
|
||||
-exec rm {} +
|
||||
rm -f TAGS cscope.* *~ */*~
|
||||
rm -f TAGS cscope.* *.pod *~ */*~
|
||||
rm -f fsdev/*.pod scsi/*.pod
|
||||
|
||||
VERSION = $(shell cat $(SRC_PATH)/VERSION)
|
||||
|
||||
@ -218,12 +215,12 @@ dist: qemu-$(VERSION).tar.bz2
|
||||
qemu-%.tar.bz2:
|
||||
$(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst qemu-%.tar.bz2,%,$@)"
|
||||
|
||||
distclean: clean recurse-distclean
|
||||
distclean: clean
|
||||
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || :
|
||||
rm -f config-host.mak Makefile.prereqs qemu-bundle
|
||||
rm -f tests/tcg/*/config-target.mak tests/tcg/config-host.mak
|
||||
rm -f config.status
|
||||
rm -f roms/seabios/config.mak
|
||||
rm -f config-host.mak config-host.h* config-poison.h
|
||||
rm -f tests/tcg/config-*.mak
|
||||
rm -f config-all-disas.mak config.status
|
||||
rm -f roms/seabios/config.mak roms/vgabios/config.mak
|
||||
rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols
|
||||
rm -f *-config-target.h *-config-devices.mak *-config-devices.h
|
||||
rm -rf meson-private meson-logs meson-info compile_commands.json
|
||||
@ -232,8 +229,7 @@ distclean: clean recurse-distclean
|
||||
rm -f linux-headers/asm
|
||||
rm -Rf .sdk
|
||||
|
||||
find-src-path = find "$(SRC_PATH)" -path "$(SRC_PATH)/meson" -prune -o \
|
||||
-type l -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
|
||||
find-src-path = find "$(SRC_PATH)/" -path "$(SRC_PATH)/meson" -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
|
||||
|
||||
.PHONY: ctags
|
||||
ctags:
|
||||
@ -254,7 +250,7 @@ gtags:
|
||||
"GTAGS", "Remove old $@ files")
|
||||
$(call quiet-command, \
|
||||
(cd $(SRC_PATH) && \
|
||||
$(find-src-path) -print | gtags -f -), \
|
||||
$(find-src-path) | gtags -f -), \
|
||||
"GTAGS", "Re-index $(SRC_PATH)")
|
||||
|
||||
.PHONY: TAGS
|
||||
@ -284,7 +280,6 @@ cscope:
|
||||
# Needed by "meson install"
|
||||
export DESTDIR
|
||||
|
||||
include $(SRC_PATH)/tests/lcitool/Makefile.include
|
||||
include $(SRC_PATH)/tests/docker/Makefile.include
|
||||
include $(SRC_PATH)/tests/vm/Makefile.include
|
||||
|
||||
@ -314,7 +309,6 @@ endif
|
||||
@echo 'Test targets:'
|
||||
$(call print-help,check,Run all tests (check-help for details))
|
||||
$(call print-help,bench,Run all benchmarks)
|
||||
$(call print-help,lcitool-help,Help about targets for managing build environment manifests)
|
||||
$(call print-help,docker-help,Help about targets running tests inside containers)
|
||||
$(call print-help,vm-help,Help about targets running tests inside VM)
|
||||
@echo ''
|
||||
|
@ -39,7 +39,7 @@ Documentation can be found hosted online at
|
||||
current development version that is available at
|
||||
`<https://www.qemu.org/docs/master/>`_ is generated from the ``docs/``
|
||||
folder in the source tree, and is built by `Sphinx
|
||||
<https://www.sphinx-doc.org/en/master/>`_.
|
||||
<https://www.sphinx-doc.org/en/master/>_`.
|
||||
|
||||
|
||||
Building
|
||||
@ -59,9 +59,9 @@ of other UNIX targets. The simple steps to build QEMU are:
|
||||
|
||||
Additional information can also be found online via the QEMU website:
|
||||
|
||||
* `<https://wiki.qemu.org/Hosts/Linux>`_
|
||||
* `<https://wiki.qemu.org/Hosts/Mac>`_
|
||||
* `<https://wiki.qemu.org/Hosts/W32>`_
|
||||
* `<https://qemu.org/Hosts/Linux>`_
|
||||
* `<https://qemu.org/Hosts/Mac>`_
|
||||
* `<https://qemu.org/Hosts/W32>`_
|
||||
|
||||
|
||||
Submitting patches
|
||||
@ -78,14 +78,14 @@ format-patch' and/or 'git send-email' to format & send the mail to the
|
||||
qemu-devel@nongnu.org mailing list. All patches submitted must contain
|
||||
a 'Signed-off-by' line from the author. Patches should follow the
|
||||
guidelines set out in the `style section
|
||||
<https://www.qemu.org/docs/master/devel/style.html>`_ of
|
||||
<https://www.qemu.org/docs/master/devel/style.html>` of
|
||||
the Developers Guide.
|
||||
|
||||
Additional information on submitting patches can be found online via
|
||||
the QEMU website
|
||||
|
||||
* `<https://wiki.qemu.org/Contribute/SubmitAPatch>`_
|
||||
* `<https://wiki.qemu.org/Contribute/TrivialPatches>`_
|
||||
* `<https://qemu.org/Contribute/SubmitAPatch>`_
|
||||
* `<https://qemu.org/Contribute/TrivialPatches>`_
|
||||
|
||||
The QEMU website is also maintained under source control.
|
||||
|
||||
@ -144,7 +144,7 @@ reported via GitLab.
|
||||
|
||||
For additional information on bug reporting consult:
|
||||
|
||||
* `<https://wiki.qemu.org/Contribute/ReportABug>`_
|
||||
* `<https://qemu.org/Contribute/ReportABug>`_
|
||||
|
||||
|
||||
ChangeLog
|
||||
@ -168,4 +168,4 @@ main methods being email and IRC
|
||||
Information on additional methods of contacting the community can be
|
||||
found online via the QEMU website:
|
||||
|
||||
* `<https://wiki.qemu.org/Contribute/StartHere>`_
|
||||
* `<https://qemu.org/Contribute/StartHere>`_
|
@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Lock to inhibit accelerator ioctls
|
||||
*
|
||||
* Copyright (c) 2022 Red Hat Inc.
|
||||
*
|
||||
* Author: Emanuele Giuseppe Esposito <eesposit@redhat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "sysemu/accel-blocker.h"
|
||||
|
||||
static QemuLockCnt accel_in_ioctl_lock;
|
||||
static QemuEvent accel_in_ioctl_event;
|
||||
|
||||
void accel_blocker_init(void)
|
||||
{
|
||||
qemu_lockcnt_init(&accel_in_ioctl_lock);
|
||||
qemu_event_init(&accel_in_ioctl_event, false);
|
||||
}
|
||||
|
||||
void accel_ioctl_begin(void)
|
||||
{
|
||||
if (likely(qemu_mutex_iothread_locked())) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* block if lock is taken in kvm_ioctl_inhibit_begin() */
|
||||
qemu_lockcnt_inc(&accel_in_ioctl_lock);
|
||||
}
|
||||
|
||||
void accel_ioctl_end(void)
|
||||
{
|
||||
if (likely(qemu_mutex_iothread_locked())) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_lockcnt_dec(&accel_in_ioctl_lock);
|
||||
/* change event to SET. If event was BUSY, wake up all waiters */
|
||||
qemu_event_set(&accel_in_ioctl_event);
|
||||
}
|
||||
|
||||
void accel_cpu_ioctl_begin(CPUState *cpu)
|
||||
{
|
||||
if (unlikely(qemu_mutex_iothread_locked())) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* block if lock is taken in kvm_ioctl_inhibit_begin() */
|
||||
qemu_lockcnt_inc(&cpu->in_ioctl_lock);
|
||||
}
|
||||
|
||||
void accel_cpu_ioctl_end(CPUState *cpu)
|
||||
{
|
||||
if (unlikely(qemu_mutex_iothread_locked())) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_lockcnt_dec(&cpu->in_ioctl_lock);
|
||||
/* change event to SET. If event was BUSY, wake up all waiters */
|
||||
qemu_event_set(&accel_in_ioctl_event);
|
||||
}
|
||||
|
||||
static bool accel_has_to_wait(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
bool needs_to_wait = false;
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
if (qemu_lockcnt_count(&cpu->in_ioctl_lock)) {
|
||||
/* exit the ioctl, if vcpu is running it */
|
||||
qemu_cpu_kick(cpu);
|
||||
needs_to_wait = true;
|
||||
}
|
||||
}
|
||||
|
||||
return needs_to_wait || qemu_lockcnt_count(&accel_in_ioctl_lock);
|
||||
}
|
||||
|
||||
void accel_ioctl_inhibit_begin(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
/*
|
||||
* We allow to inhibit only when holding the BQL, so we can identify
|
||||
* when an inhibitor wants to issue an ioctl easily.
|
||||
*/
|
||||
g_assert(qemu_mutex_iothread_locked());
|
||||
|
||||
/* Block further invocations of the ioctls outside the BQL. */
|
||||
CPU_FOREACH(cpu) {
|
||||
qemu_lockcnt_lock(&cpu->in_ioctl_lock);
|
||||
}
|
||||
qemu_lockcnt_lock(&accel_in_ioctl_lock);
|
||||
|
||||
/* Keep waiting until there are running ioctls */
|
||||
while (true) {
|
||||
|
||||
/* Reset event to FREE. */
|
||||
qemu_event_reset(&accel_in_ioctl_event);
|
||||
|
||||
if (accel_has_to_wait()) {
|
||||
/*
|
||||
* If event is still FREE, and there are ioctls still in progress,
|
||||
* wait.
|
||||
*
|
||||
* If an ioctl finishes before qemu_event_wait(), it will change
|
||||
* the event state to SET. This will prevent qemu_event_wait() from
|
||||
* blocking, but it's not a problem because if other ioctls are
|
||||
* still running the loop will iterate once more and reset the event
|
||||
* status to FREE so that it can wait properly.
|
||||
*
|
||||
* If an ioctls finishes while qemu_event_wait() is blocking, then
|
||||
* it will be waken up, but also here the while loop makes sure
|
||||
* to re-enter the wait if there are other running ioctls.
|
||||
*/
|
||||
qemu_event_wait(&accel_in_ioctl_event);
|
||||
} else {
|
||||
/* No ioctl is running */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void accel_ioctl_inhibit_end(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
qemu_lockcnt_unlock(&accel_in_ioctl_lock);
|
||||
CPU_FOREACH(cpu) {
|
||||
qemu_lockcnt_unlock(&cpu->in_ioctl_lock);
|
||||
}
|
||||
}
|
||||
|
@ -49,14 +49,6 @@ AccelClass *accel_find(const char *opt_name)
|
||||
return ac;
|
||||
}
|
||||
|
||||
/* Return the name of the current accelerator */
|
||||
const char *current_accel_name(void)
|
||||
{
|
||||
AccelClass *ac = ACCEL_GET_CLASS(current_accel());
|
||||
|
||||
return ac->name;
|
||||
}
|
||||
|
||||
static void accel_init_cpu_int_aux(ObjectClass *klass, void *opaque)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(klass);
|
||||
@ -129,16 +121,6 @@ bool accel_cpu_realizefn(CPUState *cpu, Error **errp)
|
||||
return true;
|
||||
}
|
||||
|
||||
int accel_supported_gdbstub_sstep_flags(void)
|
||||
{
|
||||
AccelState *accel = current_accel();
|
||||
AccelClass *acc = ACCEL_GET_CLASS(accel);
|
||||
if (acc->gdbstub_supported_sstep_flags) {
|
||||
return acc->gdbstub_supported_sstep_flags();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const TypeInfo accel_cpu_type = {
|
||||
.name = TYPE_ACCEL_CPU,
|
||||
.parent = TYPE_OBJECT,
|
||||
|
@ -66,7 +66,6 @@ void accel_init_ops_interfaces(AccelClass *ac)
|
||||
{
|
||||
const char *ac_name;
|
||||
char *ops_name;
|
||||
ObjectClass *oc;
|
||||
AccelOpsClass *ops;
|
||||
|
||||
ac_name = object_class_get_name(OBJECT_CLASS(ac));
|
||||
@ -74,13 +73,8 @@ void accel_init_ops_interfaces(AccelClass *ac)
|
||||
|
||||
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.
|
||||
|
@ -21,6 +21,8 @@
|
||||
static void *dummy_cpu_thread_fn(void *arg)
|
||||
{
|
||||
CPUState *cpu = arg;
|
||||
sigset_t waitset;
|
||||
int r;
|
||||
|
||||
rcu_register_thread();
|
||||
|
||||
@ -30,13 +32,8 @@ static void *dummy_cpu_thread_fn(void *arg)
|
||||
cpu->can_do_io = 1;
|
||||
current_cpu = cpu;
|
||||
|
||||
#ifndef _WIN32
|
||||
sigset_t waitset;
|
||||
int r;
|
||||
|
||||
sigemptyset(&waitset);
|
||||
sigaddset(&waitset, SIG_IPI);
|
||||
#endif
|
||||
|
||||
/* signal CPU creation */
|
||||
cpu_thread_signal_created(cpu);
|
||||
@ -44,7 +41,6 @@ static void *dummy_cpu_thread_fn(void *arg)
|
||||
|
||||
do {
|
||||
qemu_mutex_unlock_iothread();
|
||||
#ifndef _WIN32
|
||||
do {
|
||||
int sig;
|
||||
r = sigwait(&waitset, &sig);
|
||||
@ -53,9 +49,6 @@ static void *dummy_cpu_thread_fn(void *arg)
|
||||
perror("sigwait");
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
qemu_sem_wait(&cpu->sem);
|
||||
#endif
|
||||
qemu_mutex_lock_iothread();
|
||||
qemu_wait_io_event(cpu);
|
||||
} while (!cpu->unplug);
|
||||
@ -76,7 +69,4 @@ void dummy_start_vcpu_thread(CPUState *cpu)
|
||||
cpu->cpu_index);
|
||||
qemu_thread_create(cpu->thread, thread_name, dummy_cpu_thread_fn, cpu,
|
||||
QEMU_THREAD_JOINABLE);
|
||||
#ifdef _WIN32
|
||||
qemu_sem_init(&cpu->sem, 0);
|
||||
#endif
|
||||
}
|
||||
|
@ -60,10 +60,6 @@
|
||||
|
||||
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)
|
||||
@ -120,12 +116,11 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||
{
|
||||
hvf_slot *mem;
|
||||
MemoryRegion *area = section->mr;
|
||||
bool writable = !area->readonly && !area->rom_device;
|
||||
bool writeable = !area->readonly && !area->rom_device;
|
||||
hv_memory_flags_t flags;
|
||||
uint64_t page_size = qemu_real_host_page_size();
|
||||
|
||||
if (!memory_region_is_ram(area)) {
|
||||
if (writable) {
|
||||
if (writeable) {
|
||||
return;
|
||||
} else if (!memory_region_is_romd(area)) {
|
||||
/*
|
||||
@ -136,12 +131,6 @@ static void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
||||
}
|
||||
}
|
||||
|
||||
if (!QEMU_IS_ALIGNED(int128_get64(section->size), page_size) ||
|
||||
!QEMU_IS_ALIGNED(section->offset_within_address_space, page_size)) {
|
||||
/* Not page aligned, so we can not map as RAM */
|
||||
add = false;
|
||||
}
|
||||
|
||||
mem = hvf_find_overlap_slot(
|
||||
section->offset_within_address_space,
|
||||
int128_get64(section->size));
|
||||
@ -250,12 +239,12 @@ static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
|
||||
if (on) {
|
||||
slot->flags |= HVF_SLOT_LOG;
|
||||
hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
|
||||
HV_MEMORY_READ | HV_MEMORY_EXEC);
|
||||
HV_MEMORY_READ);
|
||||
/* stop tracking region*/
|
||||
} else {
|
||||
slot->flags &= ~HVF_SLOT_LOG;
|
||||
hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
|
||||
HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
|
||||
HV_MEMORY_READ | HV_MEMORY_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,7 +291,6 @@ static void hvf_region_del(MemoryListener *listener,
|
||||
}
|
||||
|
||||
static MemoryListener hvf_memory_listener = {
|
||||
.name = "hvf",
|
||||
.priority = 10,
|
||||
.region_add = hvf_region_add,
|
||||
.region_del = hvf_region_del,
|
||||
@ -328,7 +316,7 @@ static int hvf_accel_init(MachineState *ms)
|
||||
|
||||
s = g_new0(HVFState, 1);
|
||||
|
||||
s->num_slots = ARRAY_SIZE(s->slots);
|
||||
s->num_slots = 32;
|
||||
for (x = 0; x < s->num_slots; ++x) {
|
||||
s->slots[x].size = 0;
|
||||
s->slots[x].slot_id = x;
|
||||
@ -336,8 +324,7 @@ static int hvf_accel_init(MachineState *ms)
|
||||
|
||||
hvf_state = s;
|
||||
memory_listener_register(&hvf_memory_listener, &address_space_memory);
|
||||
|
||||
return hvf_arch_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hvf_accel_class_init(ObjectClass *oc, void *data)
|
||||
@ -378,20 +365,17 @@ static int hvf_init_vcpu(CPUState *cpu)
|
||||
cpu->hvf = g_malloc0(sizeof(*cpu->hvf));
|
||||
|
||||
/* init cpu signals */
|
||||
sigset_t set;
|
||||
struct sigaction sigact;
|
||||
|
||||
memset(&sigact, 0, sizeof(sigact));
|
||||
sigact.sa_handler = dummy_signal;
|
||||
sigaction(SIG_IPI, &sigact, NULL);
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, NULL, &cpu->hvf->unblock_ipi_mask);
|
||||
sigdelset(&cpu->hvf->unblock_ipi_mask, SIG_IPI);
|
||||
pthread_sigmask(SIG_BLOCK, NULL, &set);
|
||||
sigdelset(&set, SIG_IPI);
|
||||
|
||||
#ifdef __aarch64__
|
||||
r = hv_vcpu_create(&cpu->hvf->fd, (hv_vcpu_exit_t **)&cpu->hvf->exit, NULL);
|
||||
#else
|
||||
r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf->fd, HV_VCPU_DEFAULT);
|
||||
#endif
|
||||
cpu->vcpu_dirty = 1;
|
||||
assert_hvf_ok(r);
|
||||
|
||||
@ -467,7 +451,6 @@ static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
ops->create_vcpu_thread = hvf_start_vcpu_thread;
|
||||
ops->kick_vcpu_thread = hvf_kick_vcpu_thread;
|
||||
|
||||
ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset;
|
||||
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/hvf.h"
|
||||
#include "sysemu/hvf_int.h"
|
||||
|
@ -16,14 +16,12 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#include <linux/kvm.h>
|
||||
#include "kvm-cpus.h"
|
||||
|
||||
static void *kvm_vcpu_thread_fn(void *arg)
|
||||
@ -76,34 +74,15 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
|
||||
cpu, QEMU_THREAD_JOINABLE);
|
||||
}
|
||||
|
||||
static bool kvm_vcpu_thread_is_idle(CPUState *cpu)
|
||||
{
|
||||
return !kvm_halt_in_kernel();
|
||||
}
|
||||
|
||||
static bool kvm_cpus_are_resettable(void)
|
||||
{
|
||||
return !kvm_enabled() || kvm_cpu_check_are_resettable();
|
||||
}
|
||||
|
||||
static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
ops->create_vcpu_thread = kvm_start_vcpu_thread;
|
||||
ops->cpu_thread_is_idle = kvm_vcpu_thread_is_idle;
|
||||
ops->cpus_are_resettable = kvm_cpus_are_resettable;
|
||||
ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset;
|
||||
ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
|
||||
ops->synchronize_state = kvm_cpu_synchronize_state;
|
||||
ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;
|
||||
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
ops->supports_guest_debug = kvm_supports_guest_debug;
|
||||
ops->insert_breakpoint = kvm_insert_breakpoint;
|
||||
ops->remove_breakpoint = kvm_remove_breakpoint;
|
||||
ops->remove_all_breakpoints = kvm_remove_all_breakpoints;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const TypeInfo kvm_accel_ops_type = {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,9 +18,5 @@ void kvm_destroy_vcpu(CPUState *cpu);
|
||||
void kvm_cpu_synchronize_post_reset(CPUState *cpu);
|
||||
void kvm_cpu_synchronize_post_init(CPUState *cpu);
|
||||
void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu);
|
||||
bool kvm_supports_guest_debug(void);
|
||||
int kvm_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len);
|
||||
int kvm_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len);
|
||||
void kvm_remove_all_breakpoints(CPUState *cpu);
|
||||
|
||||
#endif /* KVM_CPUS_H */
|
||||
|
@ -3,5 +3,6 @@ kvm_ss.add(files(
|
||||
'kvm-all.c',
|
||||
'kvm-accel-ops.c',
|
||||
))
|
||||
kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
|
||||
|
||||
specific_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
|
||||
|
@ -12,7 +12,8 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sev.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/sev.h"
|
||||
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
{
|
@ -1,15 +1,18 @@
|
||||
specific_ss.add(files('accel-common.c', 'accel-blocker.c'))
|
||||
specific_ss.add(files('accel-common.c'))
|
||||
softmmu_ss.add(files('accel-softmmu.c'))
|
||||
user_ss.add(files('accel-user.c'))
|
||||
|
||||
subdir('hvf')
|
||||
subdir('qtest')
|
||||
subdir('kvm')
|
||||
subdir('tcg')
|
||||
if have_system
|
||||
subdir('hvf')
|
||||
subdir('qtest')
|
||||
subdir('kvm')
|
||||
subdir('xen')
|
||||
subdir('stubs')
|
||||
endif
|
||||
subdir('xen')
|
||||
subdir('stubs')
|
||||
|
||||
# qtest
|
||||
softmmu_ss.add(files('dummy-cpus.c'))
|
||||
dummy_ss = ss.source_set()
|
||||
dummy_ss.add(files(
|
||||
'dummy-cpus.c',
|
||||
))
|
||||
|
||||
specific_ss.add_all(when: ['CONFIG_SOFTMMU', 'CONFIG_POSIX'], if_true: dummy_ss)
|
||||
specific_ss.add_all(when: ['CONFIG_XEN'], if_true: dummy_ss)
|
||||
|
@ -1 +1,2 @@
|
||||
qtest_module_ss.add(when: ['CONFIG_SOFTMMU'], if_true: files('qtest.c'))
|
||||
qtest_module_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_POSIX'],
|
||||
if_true: files('qtest.c'))
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "qemu/accel.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
@ -16,8 +16,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/hax.h"
|
||||
|
||||
bool hax_allowed;
|
||||
|
||||
int hax_sync_vcpus(void)
|
||||
{
|
||||
return 0;
|
||||
|
@ -12,7 +12,10 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "hw/pci/msi.h"
|
||||
#endif
|
||||
|
||||
KVMState *kvm_state;
|
||||
bool kvm_kernel_irqchip;
|
||||
@ -46,6 +49,27 @@ int kvm_has_many_ioeventfds(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr,
|
||||
target_ulong len, int type)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
|
||||
target_ulong len, int type)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void kvm_remove_all_breakpoints(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
|
||||
{
|
||||
return 1;
|
||||
@ -56,7 +80,8 @@ int kvm_on_sigbus(int code, void *addr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kvm_irqchip_add_msi_route(KVMRouteChange *c, int vector, PCIDevice *dev)
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
@ -122,13 +147,4 @@ bool kvm_arm_supports_user_irq(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool kvm_dirty_ring_enabled(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t kvm_dirty_ring_size(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,7 +1,4 @@
|
||||
sysemu_stubs_ss = ss.source_set()
|
||||
sysemu_stubs_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c'))
|
||||
sysemu_stubs_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
|
||||
sysemu_stubs_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
|
||||
sysemu_stubs_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
|
||||
|
||||
specific_ss.add_all(when: ['CONFIG_SOFTMMU'], if_true: sysemu_stubs_ss)
|
||||
specific_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c'))
|
||||
specific_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
|
||||
specific_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
|
||||
specific_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
|
||||
|
@ -21,17 +21,6 @@ void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
|
||||
{
|
||||
}
|
||||
|
||||
void tcg_flush_jmp_cache(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
int probe_access_flags(CPUArchState *env, target_ulong addr,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool nonfault, void **phost, uintptr_t retaddr)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
||||
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
@ -39,12 +28,12 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
G_NORETURN void cpu_loop_exit(CPUState *cpu)
|
||||
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
G_NORETURN void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
|
||||
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
@ -13,23 +13,56 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi)
|
||||
static uint16_t atomic_trace_rmw_pre(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi)
|
||||
{
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_RW);
|
||||
CPUState *cpu = env_cpu(env);
|
||||
uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), false);
|
||||
|
||||
trace_guest_mem_before_exec(cpu, addr, info);
|
||||
trace_guest_mem_before_exec(cpu, addr, info | TRACE_MEM_ST);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr,
|
||||
uint16_t info)
|
||||
{
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info | TRACE_MEM_ST);
|
||||
}
|
||||
|
||||
#if HAVE_ATOMIC128
|
||||
static void atomic_trace_ld_post(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi)
|
||||
static uint16_t atomic_trace_ld_pre(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi)
|
||||
{
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
|
||||
uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void atomic_trace_ld_post(CPUArchState *env, target_ulong addr,
|
||||
uint16_t info)
|
||||
{
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info);
|
||||
}
|
||||
|
||||
static uint16_t atomic_trace_st_pre(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi)
|
||||
{
|
||||
uint16_t info = trace_mem_get_info(get_memop(oi), get_mmuidx(oi), true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void atomic_trace_st_post(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi)
|
||||
uint16_t info)
|
||||
{
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, info);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -55,53 +88,8 @@ CMPXCHG_HELPER(cmpxchgq_be, uint64_t)
|
||||
CMPXCHG_HELPER(cmpxchgq_le, uint64_t)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CMPXCHG128
|
||||
CMPXCHG_HELPER(cmpxchgo_be, Int128)
|
||||
CMPXCHG_HELPER(cmpxchgo_le, Int128)
|
||||
#endif
|
||||
|
||||
#undef CMPXCHG_HELPER
|
||||
|
||||
Int128 HELPER(nonatomic_cmpxchgo_be)(CPUArchState *env, target_ulong addr,
|
||||
Int128 cmpv, Int128 newv, uint32_t oi)
|
||||
{
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
uintptr_t ra = GETPC();
|
||||
Int128 oldv;
|
||||
|
||||
oldv = cpu_ld16_be_mmu(env, addr, oi, ra);
|
||||
if (int128_eq(oldv, cmpv)) {
|
||||
cpu_st16_be_mmu(env, addr, newv, oi, ra);
|
||||
} else {
|
||||
/* Even with comparison failure, still need a write cycle. */
|
||||
probe_write(env, addr, 16, get_mmuidx(oi), ra);
|
||||
}
|
||||
return oldv;
|
||||
#else
|
||||
g_assert_not_reached();
|
||||
#endif
|
||||
}
|
||||
|
||||
Int128 HELPER(nonatomic_cmpxchgo_le)(CPUArchState *env, target_ulong addr,
|
||||
Int128 cmpv, Int128 newv, uint32_t oi)
|
||||
{
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
uintptr_t ra = GETPC();
|
||||
Int128 oldv;
|
||||
|
||||
oldv = cpu_ld16_le_mmu(env, addr, oi, ra);
|
||||
if (int128_eq(oldv, cmpv)) {
|
||||
cpu_st16_le_mmu(env, addr, newv, oi, ra);
|
||||
} else {
|
||||
/* Even with comparison failure, still need a write cycle. */
|
||||
probe_write(env, addr, 16, get_mmuidx(oi), ra);
|
||||
}
|
||||
return oldv;
|
||||
#else
|
||||
g_assert_not_reached();
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ATOMIC_HELPER(OP, TYPE) \
|
||||
TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, target_ulong addr, \
|
||||
TYPE val, uint32_t oi) \
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/plugin.h"
|
||||
#include "trace/mem.h"
|
||||
|
||||
#if DATA_SIZE == 16
|
||||
# define SUFFIX o
|
||||
@ -63,7 +64,7 @@
|
||||
the ATOMIC_NAME macro, and redefined below. */
|
||||
#if DATA_SIZE == 1
|
||||
# define END
|
||||
#elif HOST_BIG_ENDIAN
|
||||
#elif defined(HOST_WORDS_BIGENDIAN)
|
||||
# define END _be
|
||||
#else
|
||||
# define END _le
|
||||
@ -71,11 +72,12 @@
|
||||
|
||||
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
ABI_TYPE cmpv, ABI_TYPE newv,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ | PAGE_WRITE, retaddr);
|
||||
DATA_TYPE ret;
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||
|
||||
#if DATA_SIZE == 16
|
||||
ret = atomic16_cmpxchg(haddr, cmpv, newv);
|
||||
@ -83,60 +85,64 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
ret = qatomic_cmpxchg__nocheck(haddr, cmpv, newv);
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if DATA_SIZE >= 16
|
||||
#if HAVE_ATOMIC128
|
||||
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ, retaddr);
|
||||
DATA_TYPE val;
|
||||
uint16_t info = atomic_trace_ld_pre(env, addr, oi);
|
||||
|
||||
val = atomic16_read(haddr);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_ld_post(env, addr, oi);
|
||||
atomic_trace_ld_post(env, addr, info);
|
||||
return val;
|
||||
}
|
||||
|
||||
void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_WRITE, retaddr);
|
||||
uint16_t info = atomic_trace_st_pre(env, addr, oi);
|
||||
|
||||
atomic16_set(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_st_post(env, addr, oi);
|
||||
atomic_trace_st_post(env, addr, info);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ | PAGE_WRITE, retaddr);
|
||||
DATA_TYPE ret;
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||
|
||||
ret = qatomic_xchg__nocheck(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define GEN_ATOMIC_HELPER(X) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
|
||||
ABI_TYPE val, TCGMemOpIdx oi, uintptr_t retaddr) \
|
||||
{ \
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||
DATA_TYPE ret; \
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||
ret = qatomic_##X(haddr, val); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
@ -161,11 +167,12 @@ GEN_ATOMIC_HELPER(xor_fetch)
|
||||
*/
|
||||
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
|
||||
ABI_TYPE xval, TCGMemOpIdx oi, uintptr_t retaddr) \
|
||||
{ \
|
||||
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||
XDATA_TYPE cmp, old, new, val = xval; \
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||
smp_mb(); \
|
||||
cmp = qatomic_read__nocheck(haddr); \
|
||||
do { \
|
||||
@ -173,7 +180,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
cmp = qatomic_cmpxchg__nocheck(haddr, old, new); \
|
||||
} while (cmp != old); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return RET; \
|
||||
}
|
||||
|
||||
@ -196,7 +203,7 @@ GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
|
||||
|
||||
/* Define reverse-host-endian atomic operations. Note that END is used
|
||||
within the ATOMIC_NAME macro. */
|
||||
#if HOST_BIG_ENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
# define END _le
|
||||
#else
|
||||
# define END _be
|
||||
@ -204,11 +211,12 @@ GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
|
||||
|
||||
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
ABI_TYPE cmpv, ABI_TYPE newv,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ | PAGE_WRITE, retaddr);
|
||||
DATA_TYPE ret;
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||
|
||||
#if DATA_SIZE == 16
|
||||
ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||
@ -216,61 +224,65 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
ret = qatomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return BSWAP(ret);
|
||||
}
|
||||
|
||||
#if DATA_SIZE >= 16
|
||||
#if HAVE_ATOMIC128
|
||||
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ, retaddr);
|
||||
DATA_TYPE val;
|
||||
uint16_t info = atomic_trace_ld_pre(env, addr, oi);
|
||||
|
||||
val = atomic16_read(haddr);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_ld_post(env, addr, oi);
|
||||
atomic_trace_ld_post(env, addr, info);
|
||||
return BSWAP(val);
|
||||
}
|
||||
|
||||
void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_WRITE, retaddr);
|
||||
uint16_t info = atomic_trace_st_pre(env, addr, oi);
|
||||
|
||||
val = BSWAP(val);
|
||||
atomic16_set(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_st_post(env, addr, oi);
|
||||
atomic_trace_st_post(env, addr, info);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||
PAGE_READ | PAGE_WRITE, retaddr);
|
||||
ABI_TYPE ret;
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||
|
||||
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, oi);
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return BSWAP(ret);
|
||||
}
|
||||
|
||||
#define GEN_ATOMIC_HELPER(X) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
|
||||
ABI_TYPE val, TCGMemOpIdx oi, uintptr_t retaddr) \
|
||||
{ \
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||
DATA_TYPE ret; \
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||
ret = qatomic_##X(haddr, BSWAP(val)); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return BSWAP(ret); \
|
||||
}
|
||||
|
||||
@ -292,11 +304,12 @@ GEN_ATOMIC_HELPER(xor_fetch)
|
||||
*/
|
||||
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
|
||||
ABI_TYPE xval, TCGMemOpIdx oi, uintptr_t retaddr) \
|
||||
{ \
|
||||
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||
XDATA_TYPE ldo, ldn, old, new, val = xval; \
|
||||
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||
smp_mb(); \
|
||||
ldn = qatomic_read__nocheck(haddr); \
|
||||
do { \
|
||||
@ -304,7 +317,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ldn = qatomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \
|
||||
} while (ldo != ldn); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, oi); \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return RET; \
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ void cpu_loop_exit(CPUState *cpu)
|
||||
void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
|
||||
{
|
||||
if (pc) {
|
||||
cpu_restore_state(cpu, pc);
|
||||
cpu_restore_state(cpu, pc, true);
|
||||
}
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
|
@ -18,16 +18,15 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-machine.h"
|
||||
#include "qapi/type-helpers.h"
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
#include "trace.h"
|
||||
#include "disas/disas.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/compiler.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/rcu.h"
|
||||
#include "exec/log.h"
|
||||
@ -39,9 +38,7 @@
|
||||
#include "exec/cpu-all.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "tb-jmp-cache.h"
|
||||
#include "tb-hash.h"
|
||||
#include "tb-context.h"
|
||||
#include "internal.h"
|
||||
@ -170,96 +167,22 @@ uint32_t curr_cflags(CPUState *cpu)
|
||||
return cflags;
|
||||
}
|
||||
|
||||
struct tb_desc {
|
||||
target_ulong pc;
|
||||
target_ulong cs_base;
|
||||
CPUArchState *env;
|
||||
tb_page_addr_t page_addr0;
|
||||
uint32_t flags;
|
||||
uint32_t cflags;
|
||||
uint32_t trace_vcpu_dstate;
|
||||
};
|
||||
|
||||
static bool tb_lookup_cmp(const void *p, const void *d)
|
||||
{
|
||||
const TranslationBlock *tb = p;
|
||||
const struct tb_desc *desc = d;
|
||||
|
||||
if ((TARGET_TB_PCREL || tb_pc(tb) == desc->pc) &&
|
||||
tb_page_addr0(tb) == desc->page_addr0 &&
|
||||
tb->cs_base == desc->cs_base &&
|
||||
tb->flags == desc->flags &&
|
||||
tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
|
||||
tb_cflags(tb) == desc->cflags) {
|
||||
/* check next page if needed */
|
||||
tb_page_addr_t tb_phys_page1 = tb_page_addr1(tb);
|
||||
if (tb_phys_page1 == -1) {
|
||||
return true;
|
||||
} else {
|
||||
tb_page_addr_t phys_page1;
|
||||
target_ulong virt_page1;
|
||||
|
||||
/*
|
||||
* We know that the first page matched, and an otherwise valid TB
|
||||
* encountered an incomplete instruction at the end of that page,
|
||||
* therefore we know that generating a new TB from the current PC
|
||||
* must also require reading from the next page -- even if the
|
||||
* second pages do not match, and therefore the resulting insn
|
||||
* is different for the new TB. Therefore any exception raised
|
||||
* here by the faulting lookup is not premature.
|
||||
*/
|
||||
virt_page1 = TARGET_PAGE_ALIGN(desc->pc);
|
||||
phys_page1 = get_page_addr_code(desc->env, virt_page1);
|
||||
if (tb_phys_page1 == phys_page1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
|
||||
target_ulong cs_base, uint32_t flags,
|
||||
uint32_t cflags)
|
||||
{
|
||||
tb_page_addr_t phys_pc;
|
||||
struct tb_desc desc;
|
||||
uint32_t h;
|
||||
|
||||
desc.env = cpu->env_ptr;
|
||||
desc.cs_base = cs_base;
|
||||
desc.flags = flags;
|
||||
desc.cflags = cflags;
|
||||
desc.trace_vcpu_dstate = *cpu->trace_dstate;
|
||||
desc.pc = pc;
|
||||
phys_pc = get_page_addr_code(desc.env, pc);
|
||||
if (phys_pc == -1) {
|
||||
return NULL;
|
||||
}
|
||||
desc.page_addr0 = phys_pc;
|
||||
h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : pc),
|
||||
flags, cflags, *cpu->trace_dstate);
|
||||
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
|
||||
}
|
||||
|
||||
/* Might cause an exception, so have a longjmp destination ready */
|
||||
static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
|
||||
target_ulong cs_base,
|
||||
uint32_t flags, uint32_t cflags)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
CPUJumpCache *jc;
|
||||
uint32_t hash;
|
||||
|
||||
/* we should never be trying to look up an INVALID tb */
|
||||
tcg_debug_assert(!(cflags & CF_INVALID));
|
||||
|
||||
hash = tb_jmp_cache_hash_func(pc);
|
||||
jc = cpu->tb_jmp_cache;
|
||||
tb = tb_jmp_cache_get_tb(jc, hash);
|
||||
tb = qatomic_rcu_read(&cpu->tb_jmp_cache[hash]);
|
||||
|
||||
if (likely(tb &&
|
||||
tb_jmp_cache_get_pc(jc, hash, tb) == pc &&
|
||||
tb->pc == pc &&
|
||||
tb->cs_base == cs_base &&
|
||||
tb->flags == flags &&
|
||||
tb->trace_vcpu_dstate == *cpu->trace_dstate &&
|
||||
@ -270,14 +193,16 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
|
||||
if (tb == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
tb_jmp_cache_set(jc, hash, tb, pc);
|
||||
qatomic_set(&cpu->tb_jmp_cache[hash], tb);
|
||||
return tb;
|
||||
}
|
||||
|
||||
static void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
||||
const TranslationBlock *tb)
|
||||
static inline void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
||||
const TranslationBlock *tb)
|
||||
{
|
||||
if (qemu_log_in_addr_range(pc)) {
|
||||
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC))
|
||||
&& qemu_log_in_addr_range(pc)) {
|
||||
|
||||
qemu_log_mask(CPU_LOG_EXEC,
|
||||
"Trace %d: %p [" TARGET_FMT_lx
|
||||
"/" TARGET_FMT_lx "/%08x/%08x] %s\n",
|
||||
@ -286,30 +211,32 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
||||
|
||||
#if defined(DEBUG_DISAS)
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
|
||||
FILE *logfile = qemu_log_trylock();
|
||||
if (logfile) {
|
||||
int flags = 0;
|
||||
FILE *logfile = qemu_log_lock();
|
||||
int flags = 0;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
|
||||
flags |= CPU_DUMP_FPU;
|
||||
}
|
||||
#if defined(TARGET_I386)
|
||||
flags |= CPU_DUMP_CCOP;
|
||||
#endif
|
||||
cpu_dump_state(cpu, logfile, flags);
|
||||
qemu_log_unlock(logfile);
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
|
||||
flags |= CPU_DUMP_FPU;
|
||||
}
|
||||
#if defined(TARGET_I386)
|
||||
flags |= CPU_DUMP_CCOP;
|
||||
#endif
|
||||
log_cpu_state(cpu, flags);
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif /* DEBUG_DISAS */
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_for_breakpoints_slow(CPUState *cpu, target_ulong pc,
|
||||
uint32_t *cflags)
|
||||
static bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
|
||||
uint32_t *cflags)
|
||||
{
|
||||
CPUBreakpoint *bp;
|
||||
bool match_page = false;
|
||||
|
||||
if (likely(QTAILQ_EMPTY(&cpu->breakpoints))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Singlestep overrides breakpoints.
|
||||
* This requirement is visible in the record-replay tests, where
|
||||
@ -370,13 +297,6 @@ static bool check_for_breakpoints_slow(CPUState *cpu, target_ulong pc,
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
|
||||
uint32_t *cflags)
|
||||
{
|
||||
return unlikely(!QTAILQ_EMPTY(&cpu->breakpoints)) &&
|
||||
check_for_breakpoints_slow(cpu, pc, cflags);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper_lookup_tb_ptr: quick check for next tb
|
||||
* @env: current cpu state
|
||||
@ -404,9 +324,7 @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
|
||||
return tcg_code_gen_epilogue;
|
||||
}
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) {
|
||||
log_cpu_exec(pc, cpu, tb);
|
||||
}
|
||||
log_cpu_exec(pc, cpu, tb);
|
||||
|
||||
return tb->tc.ptr;
|
||||
}
|
||||
@ -429,9 +347,7 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
|
||||
TranslationBlock *last_tb;
|
||||
const void *tb_ptr = itb->tc.ptr;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) {
|
||||
log_cpu_exec(log_pc(cpu, itb), cpu, itb);
|
||||
}
|
||||
log_cpu_exec(itb->pc, cpu, itb);
|
||||
|
||||
qemu_thread_jit_execute();
|
||||
ret = tcg_qemu_tb_exec(env, tb_ptr);
|
||||
@ -455,34 +371,18 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
|
||||
* of the start of the TB.
|
||||
*/
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
|
||||
qemu_log_mask_and_addr(CPU_LOG_EXEC, last_tb->pc,
|
||||
"Stopped execution of TB chain before %p ["
|
||||
TARGET_FMT_lx "] %s\n",
|
||||
last_tb->tc.ptr, last_tb->pc,
|
||||
lookup_symbol(last_tb->pc));
|
||||
if (cc->tcg_ops->synchronize_from_tb) {
|
||||
cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
|
||||
} else {
|
||||
assert(!TARGET_TB_PCREL);
|
||||
assert(cc->set_pc);
|
||||
cc->set_pc(cpu, tb_pc(last_tb));
|
||||
}
|
||||
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
|
||||
target_ulong pc = log_pc(cpu, last_tb);
|
||||
if (qemu_log_in_addr_range(pc)) {
|
||||
qemu_log("Stopped execution of TB chain before %p ["
|
||||
TARGET_FMT_lx "] %s\n",
|
||||
last_tb->tc.ptr, pc, lookup_symbol(pc));
|
||||
}
|
||||
cc->set_pc(cpu, last_tb->pc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If gdb single-step, and we haven't raised another exception,
|
||||
* raise a debug exception. Single-step with another exception
|
||||
* is handled in cpu_handle_exception.
|
||||
*/
|
||||
if (unlikely(cpu->singlestep_enabled) && cpu->exception_index == -1) {
|
||||
cpu->exception_index = EXCP_DEBUG;
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
|
||||
return last_tb;
|
||||
}
|
||||
|
||||
@ -503,12 +403,11 @@ static void cpu_exec_exit(CPUState *cpu)
|
||||
if (cc->tcg_ops->cpu_exec_exit) {
|
||||
cc->tcg_ops->cpu_exec_exit(cpu);
|
||||
}
|
||||
QEMU_PLUGIN_ASSERT(cpu->plugin_mem_cbs == NULL);
|
||||
}
|
||||
|
||||
void cpu_exec_step_atomic(CPUState *cpu)
|
||||
{
|
||||
CPUArchState *env = cpu->env_ptr;
|
||||
CPUArchState *env = (CPUArchState *)cpu->env_ptr;
|
||||
TranslationBlock *tb;
|
||||
target_ulong cs_base, pc;
|
||||
uint32_t flags, cflags;
|
||||
@ -547,11 +446,12 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
cpu_tb_exec(cpu, tb, &tb_exit);
|
||||
cpu_exec_exit(cpu);
|
||||
} else {
|
||||
/*
|
||||
* The mmap_lock is dropped by tb_gen_code if it runs out of
|
||||
* memory.
|
||||
*/
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
clear_helper_retaddr();
|
||||
if (have_mmap_lock()) {
|
||||
mmap_unlock();
|
||||
}
|
||||
tcg_debug_assert(!have_mmap_lock());
|
||||
#endif
|
||||
if (qemu_mutex_iothread_locked()) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
@ -560,6 +460,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* As we start the exclusive region before codegen we must still
|
||||
* be in the region if we longjump out of either the codegen or
|
||||
@ -570,20 +471,78 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
end_exclusive();
|
||||
}
|
||||
|
||||
struct tb_desc {
|
||||
target_ulong pc;
|
||||
target_ulong cs_base;
|
||||
CPUArchState *env;
|
||||
tb_page_addr_t phys_page1;
|
||||
uint32_t flags;
|
||||
uint32_t cflags;
|
||||
uint32_t trace_vcpu_dstate;
|
||||
};
|
||||
|
||||
static bool tb_lookup_cmp(const void *p, const void *d)
|
||||
{
|
||||
const TranslationBlock *tb = p;
|
||||
const struct tb_desc *desc = d;
|
||||
|
||||
if (tb->pc == desc->pc &&
|
||||
tb->page_addr[0] == desc->phys_page1 &&
|
||||
tb->cs_base == desc->cs_base &&
|
||||
tb->flags == desc->flags &&
|
||||
tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
|
||||
tb_cflags(tb) == desc->cflags) {
|
||||
/* check next page if needed */
|
||||
if (tb->page_addr[1] == -1) {
|
||||
return true;
|
||||
} else {
|
||||
tb_page_addr_t phys_page2;
|
||||
target_ulong virt_page2;
|
||||
|
||||
virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
|
||||
phys_page2 = get_page_addr_code(desc->env, virt_page2);
|
||||
if (tb->page_addr[1] == phys_page2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
|
||||
target_ulong cs_base, uint32_t flags,
|
||||
uint32_t cflags)
|
||||
{
|
||||
tb_page_addr_t phys_pc;
|
||||
struct tb_desc desc;
|
||||
uint32_t h;
|
||||
|
||||
desc.env = (CPUArchState *)cpu->env_ptr;
|
||||
desc.cs_base = cs_base;
|
||||
desc.flags = flags;
|
||||
desc.cflags = cflags;
|
||||
desc.trace_vcpu_dstate = *cpu->trace_dstate;
|
||||
desc.pc = pc;
|
||||
phys_pc = get_page_addr_code(desc.env, pc);
|
||||
if (phys_pc == -1) {
|
||||
return NULL;
|
||||
}
|
||||
desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
|
||||
h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate);
|
||||
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
|
||||
}
|
||||
|
||||
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr)
|
||||
{
|
||||
/*
|
||||
* Get the rx view of the structure, from which we find the
|
||||
* executable code address, and tb_target_set_jmp_target can
|
||||
* produce a pc-relative displacement to jmp_target_addr[n].
|
||||
*/
|
||||
const TranslationBlock *c_tb = tcg_splitwx_to_rx(tb);
|
||||
uintptr_t offset = tb->jmp_insn_offset[n];
|
||||
uintptr_t jmp_rx = (uintptr_t)tb->tc.ptr + offset;
|
||||
uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff;
|
||||
|
||||
tb->jmp_target_addr[n] = addr;
|
||||
tb_target_set_jmp_target(c_tb, n, jmp_rx, jmp_rw);
|
||||
if (TCG_TARGET_HAS_direct_jump) {
|
||||
uintptr_t offset = tb->jmp_target_arg[n];
|
||||
uintptr_t tc_ptr = (uintptr_t)tb->tc.ptr;
|
||||
uintptr_t jmp_rx = tc_ptr + offset;
|
||||
uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff;
|
||||
tb_target_set_jmp_target(tc_ptr, jmp_rx, jmp_rw, addr);
|
||||
} else {
|
||||
tb->jmp_target_arg[n] = addr;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
||||
@ -615,8 +574,11 @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
|
||||
|
||||
qemu_spin_unlock(&tb_next->jmp_lock);
|
||||
|
||||
qemu_log_mask(CPU_LOG_EXEC, "Linking TBs %p index %d -> %p\n",
|
||||
tb->tc.ptr, n, tb_next->tc.ptr);
|
||||
qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
|
||||
"Linking TBs %p [" TARGET_FMT_lx
|
||||
"] index %d -> %p [" TARGET_FMT_lx "]\n",
|
||||
tb->tc.ptr, tb->pc, n,
|
||||
tb_next->tc.ptr, tb_next->pc);
|
||||
return;
|
||||
|
||||
out_unlock_next:
|
||||
@ -626,9 +588,8 @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
|
||||
|
||||
static inline bool cpu_handle_halt(CPUState *cpu)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (cpu->halted) {
|
||||
#if defined(TARGET_I386)
|
||||
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
|
||||
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
|
||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
qemu_mutex_lock_iothread();
|
||||
@ -636,14 +597,13 @@ static inline bool cpu_handle_halt(CPUState *cpu)
|
||||
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
#endif /* TARGET_I386 */
|
||||
#endif
|
||||
if (!cpu_has_work(cpu)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cpu->halted = 0;
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -664,12 +624,6 @@ static inline void cpu_handle_debug_exception(CPUState *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
void libafl_sync_breakpoint_cpu(void);
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
{
|
||||
//// --- Begin LibAFL code ---
|
||||
@ -679,8 +633,6 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
if (cpu->exception_index == EXCP_LIBAFL_BP) {
|
||||
*ret = cpu->exception_index;
|
||||
cpu->exception_index = -1;
|
||||
|
||||
libafl_sync_breakpoint_cpu();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -691,8 +643,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
if (replay_has_exception()
|
||||
&& cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0) {
|
||||
/* Execute just one insn to trigger exception pending in the log */
|
||||
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
|
||||
| CF_NOIRQ | 1;
|
||||
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT) | 1;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
@ -712,8 +663,8 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
loop */
|
||||
#if defined(TARGET_I386)
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
cc->tcg_ops->fake_user_interrupt(cpu);
|
||||
#endif /* TARGET_I386 */
|
||||
cc->tcg_ops->do_interrupt(cpu);
|
||||
#endif
|
||||
*ret = cpu->exception_index;
|
||||
cpu->exception_index = -1;
|
||||
return true;
|
||||
@ -746,7 +697,6 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/*
|
||||
* CPU_INTERRUPT_POLL is a virtual event which gets converted into a
|
||||
* "real" interrupt event later. It does not need to be recorded for
|
||||
@ -760,19 +710,11 @@ static inline bool need_replay_interrupt(int interrupt_request)
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
TranslationBlock **last_tb)
|
||||
{
|
||||
/*
|
||||
* If we have requested custom cflags with CF_NOIRQ we should
|
||||
* skip checking here. Any pending interrupts will get picked up
|
||||
* by the next TB we execute under normal cflags.
|
||||
*/
|
||||
if (cpu->cflags_next_tb != -1 && cpu->cflags_next_tb & CF_NOIRQ) {
|
||||
return false;
|
||||
}
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
|
||||
/* Clear the interrupt flag now since we're processing
|
||||
* cpu->interrupt_request and cpu->exit_request.
|
||||
@ -795,7 +737,6 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
qemu_mutex_unlock_iothread();
|
||||
return true;
|
||||
}
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (replay_mode == REPLAY_MODE_PLAY && !replay_has_interrupt()) {
|
||||
/* Do nothing */
|
||||
} else if (interrupt_request & CPU_INTERRUPT_HALT) {
|
||||
@ -824,14 +765,12 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
qemu_mutex_unlock_iothread();
|
||||
return true;
|
||||
}
|
||||
#endif /* !TARGET_I386 */
|
||||
#endif
|
||||
/* The target hook has 3 exit conditions:
|
||||
False when the interrupt isn't processed,
|
||||
True when it is, and we should restart on a new TB,
|
||||
and via longjmp via cpu_loop_exit. */
|
||||
else {
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
|
||||
if (cc->tcg_ops->cpu_exec_interrupt &&
|
||||
cc->tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||
if (need_replay_interrupt(interrupt_request)) {
|
||||
@ -842,19 +781,14 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
* raised when single-stepping so that GDB doesn't miss the
|
||||
* next instruction.
|
||||
*/
|
||||
if (unlikely(cpu->singlestep_enabled)) {
|
||||
cpu->exception_index = EXCP_DEBUG;
|
||||
qemu_mutex_unlock_iothread();
|
||||
return true;
|
||||
}
|
||||
cpu->exception_index = -1;
|
||||
cpu->exception_index =
|
||||
(cpu->singlestep_enabled ? EXCP_DEBUG : -1);
|
||||
*last_tb = NULL;
|
||||
}
|
||||
/* The target hook may have updated the 'cpu->interrupt_request';
|
||||
* reload the 'interrupt_request' value */
|
||||
interrupt_request = cpu->interrupt_request;
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
if (interrupt_request & CPU_INTERRUPT_EXITTB) {
|
||||
cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
|
||||
/* ensure that no TB jump will be modified as
|
||||
@ -882,12 +816,11 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
}
|
||||
|
||||
static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
target_ulong pc,
|
||||
TranslationBlock **last_tb, int *tb_exit)
|
||||
{
|
||||
int32_t insns_left;
|
||||
|
||||
trace_exec_tb(tb, pc);
|
||||
trace_exec_tb(tb, tb->pc);
|
||||
tb = cpu_tb_exec(cpu, tb, tb_exit);
|
||||
if (*tb_exit != TB_EXIT_REQUESTED) {
|
||||
*last_tb = tb;
|
||||
@ -933,19 +866,69 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
||||
target_ulong dst_block, int exit_n, target_ulong cs_base,
|
||||
target_ulong dst_block, target_ulong cs_base,
|
||||
uint32_t flags, int cflags);
|
||||
|
||||
extern __thread int libafl_valid_current_cpu;
|
||||
void libafl_exec_edge_one_off(target_ulong src_block, target_ulong dst_block);
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
/* main execution loop */
|
||||
|
||||
static int __attribute__((noinline))
|
||||
cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
||||
int cpu_exec(CPUState *cpu)
|
||||
{
|
||||
int ret;
|
||||
SyncClocks sc = { 0 };
|
||||
|
||||
/* replay_interrupt may need current_cpu */
|
||||
current_cpu = cpu;
|
||||
|
||||
if (cpu_handle_halt(cpu)) {
|
||||
return EXCP_HALTED;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
cpu_exec_enter(cpu);
|
||||
|
||||
/* Calculate difference between guest clock and host clock.
|
||||
* This delay includes the delay of the last cycle, so
|
||||
* what we have to do is sleep until it is 0. As for the
|
||||
* advance/delay we gain here, we try to fix it next time.
|
||||
*/
|
||||
init_delay_params(&sc, cpu);
|
||||
|
||||
/* prepare setjmp context for exception handling */
|
||||
if (sigsetjmp(cpu->jmp_env, 0) != 0) {
|
||||
#if defined(__clang__)
|
||||
/*
|
||||
* Some compilers wrongly smash all local variables after
|
||||
* siglongjmp (the spec requires that only non-volatile locals
|
||||
* which are changed between the sigsetjmp and siglongjmp are
|
||||
* permitted to be trashed). There were bug reports for gcc
|
||||
* 4.5.0 and clang. The bug is fixed in all versions of gcc
|
||||
* that we support, but is still unfixed in clang:
|
||||
* https://bugs.llvm.org/show_bug.cgi?id=21183
|
||||
*
|
||||
* Reload an essential local variable here for those compilers.
|
||||
* Newer versions of gcc would complain about this code (-Wclobbered),
|
||||
* so we only perform the workaround for clang.
|
||||
*/
|
||||
cpu = current_cpu;
|
||||
#else
|
||||
/* Non-buggy compilers preserve this; assert the correct value. */
|
||||
g_assert(cpu == current_cpu);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
tcg_debug_assert(!have_mmap_lock());
|
||||
#endif
|
||||
if (qemu_mutex_iothread_locked()) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
|
||||
assert_no_pages_locked();
|
||||
}
|
||||
|
||||
/* if an exception is pending, we execute it here */
|
||||
while (!cpu_handle_exception(cpu, &ret)) {
|
||||
@ -979,8 +962,6 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
||||
|
||||
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
|
||||
if (tb == NULL) {
|
||||
uint32_t h;
|
||||
|
||||
mmap_lock();
|
||||
tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
|
||||
mmap_unlock();
|
||||
@ -988,9 +969,14 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
||||
* We add the TB in the virtual pc hash table
|
||||
* for the fast lookup
|
||||
*/
|
||||
h = tb_jmp_cache_hash_func(pc);
|
||||
tb_jmp_cache_set(cpu->tb_jmp_cache, h, tb, pc);
|
||||
qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
|
||||
}
|
||||
//// --- Begin LibAFL code ---
|
||||
// This will save an edge (0,pc) after interrupts
|
||||
// if (!last_tb) {
|
||||
// libafl_exec_edge_one_off(0, tb->pc);
|
||||
// }
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/*
|
||||
@ -999,7 +985,7 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
||||
* direct jump to a TB spanning two pages because the mapping
|
||||
* for the second page can change.
|
||||
*/
|
||||
if (tb_page_addr1(tb) != -1) {
|
||||
if (tb->page_addr[1] != -1) {
|
||||
last_tb = NULL;
|
||||
}
|
||||
#endif
|
||||
@ -1009,11 +995,10 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
#if !TARGET_TB_PCREL
|
||||
if (last_tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
|
||||
if (last_tb->jmp_reset_offset[1] != TB_JMP_RESET_OFFSET_INVALID) {
|
||||
mmap_lock();
|
||||
TranslationBlock *edge = libafl_gen_edge(cpu, tb_pc(last_tb), tb_pc(tb),
|
||||
tb_exit, cs_base, flags, cflags);
|
||||
TranslationBlock *edge = libafl_gen_edge(cpu, last_tb->pc, tb->pc,
|
||||
cs_base, flags, cflags);
|
||||
mmap_unlock();
|
||||
|
||||
if (edge) {
|
||||
@ -1025,79 +1010,17 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
||||
} else {
|
||||
tb_add_jump(last_tb, tb_exit, tb);
|
||||
}
|
||||
#else
|
||||
// No party if TARGET_TB_PCREL is 1
|
||||
tb_add_jump(last_tb, tb_exit, tb);
|
||||
#endif
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
}
|
||||
|
||||
cpu_loop_exec_tb(cpu, tb, pc, &last_tb, &tb_exit);
|
||||
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit);
|
||||
|
||||
QEMU_PLUGIN_ASSERT(cpu->plugin_mem_cbs == NULL);
|
||||
/* Try to align the host and virtual clocks
|
||||
if the guest is in advance */
|
||||
align_clocks(sc, cpu);
|
||||
align_clocks(&sc, cpu);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cpu_exec_setjmp(CPUState *cpu, SyncClocks *sc)
|
||||
{
|
||||
/* Prepare setjmp context for exception handling. */
|
||||
if (unlikely(sigsetjmp(cpu->jmp_env, 0) != 0)) {
|
||||
/* Non-buggy compilers preserve this; assert the correct value. */
|
||||
g_assert(cpu == current_cpu);
|
||||
|
||||
#ifndef CONFIG_SOFTMMU
|
||||
clear_helper_retaddr();
|
||||
if (have_mmap_lock()) {
|
||||
mmap_unlock();
|
||||
}
|
||||
#endif
|
||||
if (qemu_mutex_iothread_locked()) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
|
||||
assert_no_pages_locked();
|
||||
}
|
||||
|
||||
return cpu_exec_loop(cpu, sc);
|
||||
}
|
||||
|
||||
int cpu_exec(CPUState *cpu)
|
||||
{
|
||||
int ret;
|
||||
SyncClocks sc = { 0 };
|
||||
|
||||
/* replay_interrupt may need current_cpu */
|
||||
current_cpu = cpu;
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
libafl_valid_current_cpu = 1;
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
if (cpu_handle_halt(cpu)) {
|
||||
return EXCP_HALTED;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
cpu_exec_enter(cpu);
|
||||
|
||||
/*
|
||||
* Calculate difference between guest clock and host clock.
|
||||
* This delay includes the delay of the last cycle, so
|
||||
* what we have to do is sleep until it is 0. As for the
|
||||
* advance/delay we gain here, we try to fix it next time.
|
||||
*/
|
||||
init_delay_params(&sc, cpu);
|
||||
|
||||
ret = cpu_exec_setjmp(cpu, &sc);
|
||||
|
||||
cpu_exec_exit(cpu);
|
||||
rcu_read_unlock();
|
||||
@ -1114,13 +1037,12 @@ void tcg_exec_realizefn(CPUState *cpu, Error **errp)
|
||||
cc->tcg_ops->initialize();
|
||||
tcg_target_initialized = true;
|
||||
}
|
||||
|
||||
cpu->tb_jmp_cache = g_new0(CPUJumpCache, 1);
|
||||
tlb_init(cpu);
|
||||
qemu_plugin_vcpu_init_hook(cpu);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
tcg_iommu_init_notifier_list(cpu);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
/* qemu_plugin_vcpu_init_hook delayed until cpu_index assigned. */
|
||||
}
|
||||
|
||||
/* undo the initializations in reverse order */
|
||||
@ -1130,89 +1052,29 @@ void tcg_exec_unrealizefn(CPUState *cpu)
|
||||
tcg_iommu_free_notifier_list(cpu);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
qemu_plugin_vcpu_exit_hook(cpu);
|
||||
tlb_destroy(cpu);
|
||||
g_free_rcu(cpu->tb_jmp_cache, rcu);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
static void dump_drift_info(GString *buf)
|
||||
void dump_drift_info(void)
|
||||
{
|
||||
if (!icount_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n",
|
||||
(cpu_get_clock() - icount_get()) / SCALE_MS);
|
||||
qemu_printf("Host - Guest clock %"PRIi64" ms\n",
|
||||
(cpu_get_clock() - icount_get()) / SCALE_MS);
|
||||
if (icount_align_option) {
|
||||
g_string_append_printf(buf, "Max guest delay %"PRIi64" ms\n",
|
||||
-max_delay / SCALE_MS);
|
||||
g_string_append_printf(buf, "Max guest advance %"PRIi64" ms\n",
|
||||
max_advance / SCALE_MS);
|
||||
qemu_printf("Max guest delay %"PRIi64" ms\n",
|
||||
-max_delay / SCALE_MS);
|
||||
qemu_printf("Max guest advance %"PRIi64" ms\n",
|
||||
max_advance / SCALE_MS);
|
||||
} else {
|
||||
g_string_append_printf(buf, "Max guest delay NA\n");
|
||||
g_string_append_printf(buf, "Max guest advance NA\n");
|
||||
qemu_printf("Max guest delay NA\n");
|
||||
qemu_printf("Max guest advance NA\n");
|
||||
}
|
||||
}
|
||||
|
||||
HumanReadableText *qmp_x_query_jit(Error **errp)
|
||||
{
|
||||
g_autoptr(GString) buf = g_string_new("");
|
||||
|
||||
if (!tcg_enabled()) {
|
||||
error_setg(errp, "JIT information is only available with accel=tcg");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dump_exec_info(buf);
|
||||
dump_drift_info(buf);
|
||||
|
||||
return human_readable_text_from_str(buf);
|
||||
}
|
||||
|
||||
HumanReadableText *qmp_x_query_opcount(Error **errp)
|
||||
{
|
||||
g_autoptr(GString) buf = g_string_new("");
|
||||
|
||||
if (!tcg_enabled()) {
|
||||
error_setg(errp, "Opcode count information is only available with accel=tcg");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tcg_dump_op_count(buf);
|
||||
|
||||
return human_readable_text_from_str(buf);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
|
||||
int64_t dev_time;
|
||||
|
||||
HumanReadableText *qmp_x_query_profile(Error **errp)
|
||||
{
|
||||
g_autoptr(GString) buf = g_string_new("");
|
||||
static int64_t last_cpu_exec_time;
|
||||
int64_t cpu_exec_time;
|
||||
int64_t delta;
|
||||
|
||||
cpu_exec_time = tcg_cpu_exec_time();
|
||||
delta = cpu_exec_time - last_cpu_exec_time;
|
||||
|
||||
g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n",
|
||||
dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
|
||||
g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n",
|
||||
delta, delta / (double)NANOSECONDS_PER_SECOND);
|
||||
last_cpu_exec_time = cpu_exec_time;
|
||||
dev_time = 0;
|
||||
|
||||
return human_readable_text_from_str(buf);
|
||||
}
|
||||
#else
|
||||
HumanReadableText *qmp_x_query_profile(Error **errp)
|
||||
{
|
||||
error_setg(errp, "Internal profiler not compiled");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
1040
accel/tcg/cputlb.c
1040
accel/tcg/cputlb.c
File diff suppressed because it is too large
Load Diff
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Debug information support.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/lockable.h"
|
||||
|
||||
#include <elfutils/libdwfl.h>
|
||||
|
||||
#include "debuginfo.h"
|
||||
|
||||
static QemuMutex lock;
|
||||
static Dwfl *dwfl;
|
||||
static const Dwfl_Callbacks dwfl_callbacks = {
|
||||
.find_elf = NULL,
|
||||
.find_debuginfo = dwfl_standard_find_debuginfo,
|
||||
.section_address = NULL,
|
||||
.debuginfo_path = NULL,
|
||||
};
|
||||
|
||||
__attribute__((constructor))
|
||||
static void debuginfo_init(void)
|
||||
{
|
||||
qemu_mutex_init(&lock);
|
||||
}
|
||||
|
||||
void debuginfo_report_elf(const char *name, int fd, uint64_t bias)
|
||||
{
|
||||
QEMU_LOCK_GUARD(&lock);
|
||||
|
||||
if (dwfl) {
|
||||
dwfl_report_begin_add(dwfl);
|
||||
} else {
|
||||
dwfl = dwfl_begin(&dwfl_callbacks);
|
||||
}
|
||||
|
||||
if (dwfl) {
|
||||
dwfl_report_elf(dwfl, name, name, fd, bias, true);
|
||||
dwfl_report_end(dwfl, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void debuginfo_lock(void)
|
||||
{
|
||||
qemu_mutex_lock(&lock);
|
||||
}
|
||||
|
||||
void debuginfo_query(struct debuginfo_query *q, size_t n)
|
||||
{
|
||||
const char *symbol, *file;
|
||||
Dwfl_Module *dwfl_module;
|
||||
Dwfl_Line *dwfl_line;
|
||||
GElf_Off dwfl_offset;
|
||||
GElf_Sym dwfl_sym;
|
||||
size_t i;
|
||||
int line;
|
||||
|
||||
if (!dwfl) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
dwfl_module = dwfl_addrmodule(dwfl, q[i].address);
|
||||
if (!dwfl_module) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (q[i].flags & DEBUGINFO_SYMBOL) {
|
||||
symbol = dwfl_module_addrinfo(dwfl_module, q[i].address,
|
||||
&dwfl_offset, &dwfl_sym,
|
||||
NULL, NULL, NULL);
|
||||
if (symbol) {
|
||||
q[i].symbol = symbol;
|
||||
q[i].offset = dwfl_offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (q[i].flags & DEBUGINFO_LINE) {
|
||||
dwfl_line = dwfl_module_getsrc(dwfl_module, q[i].address);
|
||||
if (dwfl_line) {
|
||||
file = dwfl_lineinfo(dwfl_line, NULL, &line, 0, NULL, NULL);
|
||||
if (file) {
|
||||
q[i].file = file;
|
||||
q[i].line = line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void debuginfo_unlock(void)
|
||||
{
|
||||
qemu_mutex_unlock(&lock);
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Debug information support.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef ACCEL_TCG_DEBUGINFO_H
|
||||
#define ACCEL_TCG_DEBUGINFO_H
|
||||
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
/*
|
||||
* Debuginfo describing a certain address.
|
||||
*/
|
||||
struct debuginfo_query {
|
||||
uint64_t address; /* Input: address. */
|
||||
int flags; /* Input: debuginfo subset. */
|
||||
const char *symbol; /* Symbol that the address is part of. */
|
||||
uint64_t offset; /* Offset from the symbol. */
|
||||
const char *file; /* Source file associated with the address. */
|
||||
int line; /* Line number in the source file. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Debuginfo subsets.
|
||||
*/
|
||||
#define DEBUGINFO_SYMBOL BIT(1)
|
||||
#define DEBUGINFO_LINE BIT(2)
|
||||
|
||||
#if defined(CONFIG_TCG) && defined(CONFIG_LIBDW)
|
||||
/*
|
||||
* Load debuginfo for the specified guest ELF image.
|
||||
* Return true on success, false on failure.
|
||||
*/
|
||||
void debuginfo_report_elf(const char *name, int fd, uint64_t bias);
|
||||
|
||||
/*
|
||||
* Take the debuginfo lock.
|
||||
*/
|
||||
void debuginfo_lock(void);
|
||||
|
||||
/*
|
||||
* Fill each on N Qs with the debuginfo about Q->ADDRESS as specified by
|
||||
* Q->FLAGS:
|
||||
*
|
||||
* - DEBUGINFO_SYMBOL: update Q->SYMBOL and Q->OFFSET. If symbol debuginfo is
|
||||
* missing, then leave them as is.
|
||||
* - DEBUINFO_LINE: update Q->FILE and Q->LINE. If line debuginfo is missing,
|
||||
* then leave them as is.
|
||||
*
|
||||
* This function must be called under the debuginfo lock. The results can be
|
||||
* accessed only until the debuginfo lock is released.
|
||||
*/
|
||||
void debuginfo_query(struct debuginfo_query *q, size_t n);
|
||||
|
||||
/*
|
||||
* Release the debuginfo lock.
|
||||
*/
|
||||
void debuginfo_unlock(void);
|
||||
#else
|
||||
static inline void debuginfo_report_elf(const char *image_name, int image_fd,
|
||||
uint64_t load_bias)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void debuginfo_lock(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void debuginfo_query(struct debuginfo_query *q, size_t n)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void debuginfo_unlock(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,14 +1,29 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-machine.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "sysemu/tcg.h"
|
||||
|
||||
static void hmp_info_jit(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
if (!tcg_enabled()) {
|
||||
error_report("JIT information is only available with accel=tcg");
|
||||
return;
|
||||
}
|
||||
|
||||
dump_exec_info();
|
||||
dump_drift_info();
|
||||
}
|
||||
|
||||
static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
dump_opcount_info();
|
||||
}
|
||||
|
||||
static void hmp_tcg_register(void)
|
||||
{
|
||||
monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
|
||||
monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount);
|
||||
monitor_register_hmp("jit", true, hmp_info_jit);
|
||||
monitor_register_hmp("opcount", true, hmp_info_opcount);
|
||||
}
|
||||
|
||||
type_init(hmp_tcg_register);
|
||||
|
@ -11,57 +11,12 @@
|
||||
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
/*
|
||||
* Access to the various translations structures need to be serialised
|
||||
* via locks for consistency. In user-mode emulation access to the
|
||||
* memory related structures are protected with mmap_lock.
|
||||
* In !user-mode we use per-page locks.
|
||||
*/
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define assert_memory_lock()
|
||||
#else
|
||||
#define assert_memory_lock() tcg_debug_assert(have_mmap_lock())
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOFTMMU) && defined(CONFIG_DEBUG_TCG)
|
||||
void assert_no_pages_locked(void);
|
||||
#else
|
||||
static inline void assert_no_pages_locked(void) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
static inline void page_table_config_init(void) { }
|
||||
#else
|
||||
void page_table_config_init(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
void tb_invalidate_phys_range_fast(ram_addr_t ram_addr,
|
||||
unsigned size,
|
||||
uintptr_t retaddr);
|
||||
G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
|
||||
#endif /* CONFIG_SOFTMMU */
|
||||
|
||||
TranslationBlock *tb_gen_code(CPUState *cpu, target_ulong pc,
|
||||
target_ulong cs_base, uint32_t flags,
|
||||
int cflags);
|
||||
|
||||
void QEMU_NORETURN cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
|
||||
void page_init(void);
|
||||
void tb_htable_init(void);
|
||||
void tb_reset_jump(TranslationBlock *tb, int n);
|
||||
TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
|
||||
tb_page_addr_t phys_page2);
|
||||
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);
|
||||
|
||||
/* Return the current PC from CPU, which may be cached in TB. */
|
||||
static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
|
||||
{
|
||||
#if TARGET_TB_PCREL
|
||||
return cpu->cc->get_pc(cpu);
|
||||
#else
|
||||
return tb_pc(tb);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* ACCEL_TCG_INTERNAL_H */
|
||||
|
@ -1,307 +0,0 @@
|
||||
/*
|
||||
* Routines common to user and system emulation of load/store.
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
||||
return cpu_ldb_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return (int8_t)cpu_ldub_mmuidx_ra(env, addr, mmu_idx, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
|
||||
return cpu_ldw_be_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return (int16_t)cpu_lduw_be_mmuidx_ra(env, addr, mmu_idx, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
|
||||
return cpu_ldl_be_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
|
||||
return cpu_ldq_be_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
|
||||
return cpu_ldw_le_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return (int16_t)cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
|
||||
return cpu_ldl_le_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
|
||||
return cpu_ldq_le_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
||||
cpu_stb_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
|
||||
cpu_stw_be_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
|
||||
cpu_stl_be_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
|
||||
cpu_stq_be_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
|
||||
cpu_stw_le_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
|
||||
cpu_stl_le_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
|
||||
cpu_stq_le_mmu(env, addr, val, oi, ra);
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
|
||||
uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldub_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return (int8_t)cpu_ldub_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_lduw_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return (int16_t)cpu_lduw_be_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldl_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldq_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_lduw_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return (int16_t)cpu_lduw_le_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldl_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldq_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stb_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stb_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stw_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stl_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint64_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stq_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stw_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stl_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint64_t val, uintptr_t ra)
|
||||
{
|
||||
cpu_stq_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
|
||||
}
|
||||
|
||||
/*--------------------------*/
|
||||
|
||||
uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldub_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
int cpu_ldsb_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return (int8_t)cpu_ldub_data(env, addr);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_lduw_be_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return (int16_t)cpu_lduw_be_data(env, addr);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldl_be_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldq_be_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_lduw_le_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return (int16_t)cpu_lduw_le_data(env, addr);
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldl_le_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr addr)
|
||||
{
|
||||
return cpu_ldq_le_data_ra(env, addr, 0);
|
||||
}
|
||||
|
||||
void cpu_stb_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stb_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stw_be_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stw_be_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stl_be_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stl_be_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stq_be_data(CPUArchState *env, abi_ptr addr, uint64_t val)
|
||||
{
|
||||
cpu_stq_be_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stw_le_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stw_le_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stl_le_data(CPUArchState *env, abi_ptr addr, uint32_t val)
|
||||
{
|
||||
cpu_stl_le_data_ra(env, addr, val, 0);
|
||||
}
|
||||
|
||||
void cpu_stq_le_data(CPUArchState *env, abi_ptr addr, uint64_t val)
|
||||
{
|
||||
cpu_stq_le_data_ra(env, addr, val, 0);
|
||||
}
|
@ -3,7 +3,6 @@ tcg_ss.add(files(
|
||||
'tcg-all.c',
|
||||
'cpu-exec-common.c',
|
||||
'cpu-exec.c',
|
||||
'tb-maint.c',
|
||||
'tcg-runtime-gvec.c',
|
||||
'tcg-runtime.c',
|
||||
'translate-all.c',
|
||||
@ -11,9 +10,7 @@ tcg_ss.add(files(
|
||||
))
|
||||
tcg_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user-exec.c'))
|
||||
tcg_ss.add(when: 'CONFIG_SOFTMMU', if_false: files('user-exec-stub.c'))
|
||||
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c')])
|
||||
tcg_ss.add(when: libdw, if_true: files('debuginfo.c'))
|
||||
tcg_ss.add(when: 'CONFIG_LINUX', if_true: files('perf.c'))
|
||||
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c'), libdl])
|
||||
specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
|
||||
|
||||
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(
|
||||
|
375
accel/tcg/perf.c
375
accel/tcg/perf.c
@ -1,375 +0,0 @@
|
||||
/*
|
||||
* Linux perf perf-<pid>.map and jit-<pid>.dump integration.
|
||||
*
|
||||
* The jitdump spec can be found at [1].
|
||||
*
|
||||
* [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/tools/perf/Documentation/jitdump-specification.txt
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "elf.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "tcg/tcg.h"
|
||||
|
||||
#include "debuginfo.h"
|
||||
#include "perf.h"
|
||||
|
||||
static FILE *safe_fopen_w(const char *path)
|
||||
{
|
||||
int saved_errno;
|
||||
FILE *f;
|
||||
int fd;
|
||||
|
||||
/* Delete the old file, if any. */
|
||||
unlink(path);
|
||||
|
||||
/* Avoid symlink attacks by using O_CREAT | O_EXCL. */
|
||||
fd = open(path, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
|
||||
if (fd == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Convert fd to FILE*. */
|
||||
f = fdopen(fd, "w");
|
||||
if (f == NULL) {
|
||||
saved_errno = errno;
|
||||
close(fd);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static FILE *perfmap;
|
||||
|
||||
void perf_enable_perfmap(void)
|
||||
{
|
||||
char map_file[32];
|
||||
|
||||
snprintf(map_file, sizeof(map_file), "/tmp/perf-%d.map", getpid());
|
||||
perfmap = safe_fopen_w(map_file);
|
||||
if (perfmap == NULL) {
|
||||
warn_report("Could not open %s: %s, proceeding without perfmap",
|
||||
map_file, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* Get PC and size of code JITed for guest instruction #INSN. */
|
||||
static void get_host_pc_size(uintptr_t *host_pc, uint16_t *host_size,
|
||||
const void *start, size_t insn)
|
||||
{
|
||||
uint16_t start_off = insn ? tcg_ctx->gen_insn_end_off[insn - 1] : 0;
|
||||
|
||||
if (host_pc) {
|
||||
*host_pc = (uintptr_t)start + start_off;
|
||||
}
|
||||
if (host_size) {
|
||||
*host_size = tcg_ctx->gen_insn_end_off[insn] - start_off;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *pretty_symbol(const struct debuginfo_query *q, size_t *len)
|
||||
{
|
||||
static __thread char buf[64];
|
||||
int tmp;
|
||||
|
||||
if (!q->symbol) {
|
||||
tmp = snprintf(buf, sizeof(buf), "guest-0x%"PRIx64, q->address);
|
||||
if (len) {
|
||||
*len = MIN(tmp + 1, sizeof(buf));
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (!q->offset) {
|
||||
if (len) {
|
||||
*len = strlen(q->symbol) + 1;
|
||||
}
|
||||
return q->symbol;
|
||||
}
|
||||
|
||||
tmp = snprintf(buf, sizeof(buf), "%s+0x%"PRIx64, q->symbol, q->offset);
|
||||
if (len) {
|
||||
*len = MIN(tmp + 1, sizeof(buf));
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void write_perfmap_entry(const void *start, size_t insn,
|
||||
const struct debuginfo_query *q)
|
||||
{
|
||||
uint16_t host_size;
|
||||
uintptr_t host_pc;
|
||||
|
||||
get_host_pc_size(&host_pc, &host_size, start, insn);
|
||||
fprintf(perfmap, "%"PRIxPTR" %"PRIx16" %s\n",
|
||||
host_pc, host_size, pretty_symbol(q, NULL));
|
||||
}
|
||||
|
||||
static FILE *jitdump;
|
||||
|
||||
#define JITHEADER_MAGIC 0x4A695444
|
||||
#define JITHEADER_VERSION 1
|
||||
|
||||
struct jitheader {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
uint32_t total_size;
|
||||
uint32_t elf_mach;
|
||||
uint32_t pad1;
|
||||
uint32_t pid;
|
||||
uint64_t timestamp;
|
||||
uint64_t flags;
|
||||
};
|
||||
|
||||
enum jit_record_type {
|
||||
JIT_CODE_LOAD = 0,
|
||||
JIT_CODE_DEBUG_INFO = 2,
|
||||
};
|
||||
|
||||
struct jr_prefix {
|
||||
uint32_t id;
|
||||
uint32_t total_size;
|
||||
uint64_t timestamp;
|
||||
};
|
||||
|
||||
struct jr_code_load {
|
||||
struct jr_prefix p;
|
||||
|
||||
uint32_t pid;
|
||||
uint32_t tid;
|
||||
uint64_t vma;
|
||||
uint64_t code_addr;
|
||||
uint64_t code_size;
|
||||
uint64_t code_index;
|
||||
};
|
||||
|
||||
struct debug_entry {
|
||||
uint64_t addr;
|
||||
int lineno;
|
||||
int discrim;
|
||||
const char name[];
|
||||
};
|
||||
|
||||
struct jr_code_debug_info {
|
||||
struct jr_prefix p;
|
||||
|
||||
uint64_t code_addr;
|
||||
uint64_t nr_entry;
|
||||
struct debug_entry entries[];
|
||||
};
|
||||
|
||||
static uint32_t get_e_machine(void)
|
||||
{
|
||||
Elf64_Ehdr elf_header;
|
||||
FILE *exe;
|
||||
size_t n;
|
||||
|
||||
QEMU_BUILD_BUG_ON(offsetof(Elf32_Ehdr, e_machine) !=
|
||||
offsetof(Elf64_Ehdr, e_machine));
|
||||
|
||||
exe = fopen("/proc/self/exe", "r");
|
||||
if (exe == NULL) {
|
||||
return EM_NONE;
|
||||
}
|
||||
|
||||
n = fread(&elf_header, sizeof(elf_header), 1, exe);
|
||||
fclose(exe);
|
||||
if (n != 1) {
|
||||
return EM_NONE;
|
||||
}
|
||||
|
||||
return elf_header.e_machine;
|
||||
}
|
||||
|
||||
void perf_enable_jitdump(void)
|
||||
{
|
||||
struct jitheader header;
|
||||
char jitdump_file[32];
|
||||
void *perf_marker;
|
||||
|
||||
if (!use_rt_clock) {
|
||||
warn_report("CLOCK_MONOTONIC is not available, proceeding without jitdump");
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(jitdump_file, sizeof(jitdump_file), "jit-%d.dump", getpid());
|
||||
jitdump = safe_fopen_w(jitdump_file);
|
||||
if (jitdump == NULL) {
|
||||
warn_report("Could not open %s: %s, proceeding without jitdump",
|
||||
jitdump_file, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* `perf inject` will see that the mapped file name in the corresponding
|
||||
* PERF_RECORD_MMAP or PERF_RECORD_MMAP2 event is of the form jit-%d.dump
|
||||
* and will process it as a jitdump file.
|
||||
*/
|
||||
perf_marker = mmap(NULL, qemu_real_host_page_size(), PROT_READ | PROT_EXEC,
|
||||
MAP_PRIVATE, fileno(jitdump), 0);
|
||||
if (perf_marker == MAP_FAILED) {
|
||||
warn_report("Could not map %s: %s, proceeding without jitdump",
|
||||
jitdump_file, strerror(errno));
|
||||
fclose(jitdump);
|
||||
jitdump = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
header.magic = JITHEADER_MAGIC;
|
||||
header.version = JITHEADER_VERSION;
|
||||
header.total_size = sizeof(header);
|
||||
header.elf_mach = get_e_machine();
|
||||
header.pad1 = 0;
|
||||
header.pid = getpid();
|
||||
header.timestamp = get_clock();
|
||||
header.flags = 0;
|
||||
fwrite(&header, sizeof(header), 1, jitdump);
|
||||
}
|
||||
|
||||
void perf_report_prologue(const void *start, size_t size)
|
||||
{
|
||||
if (perfmap) {
|
||||
fprintf(perfmap, "%"PRIxPTR" %zx tcg-prologue-buffer\n",
|
||||
(uintptr_t)start, size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write a JIT_CODE_DEBUG_INFO jitdump entry. */
|
||||
static void write_jr_code_debug_info(const void *start,
|
||||
const struct debuginfo_query *q,
|
||||
size_t icount)
|
||||
{
|
||||
struct jr_code_debug_info rec;
|
||||
struct debug_entry ent;
|
||||
uintptr_t host_pc;
|
||||
int insn;
|
||||
|
||||
/* Write the header. */
|
||||
rec.p.id = JIT_CODE_DEBUG_INFO;
|
||||
rec.p.total_size = sizeof(rec) + sizeof(ent) + 1;
|
||||
rec.p.timestamp = get_clock();
|
||||
rec.code_addr = (uintptr_t)start;
|
||||
rec.nr_entry = 1;
|
||||
for (insn = 0; insn < icount; insn++) {
|
||||
if (q[insn].file) {
|
||||
rec.p.total_size += sizeof(ent) + strlen(q[insn].file) + 1;
|
||||
rec.nr_entry++;
|
||||
}
|
||||
}
|
||||
fwrite(&rec, sizeof(rec), 1, jitdump);
|
||||
|
||||
/* Write the main debug entries. */
|
||||
for (insn = 0; insn < icount; insn++) {
|
||||
if (q[insn].file) {
|
||||
get_host_pc_size(&host_pc, NULL, start, insn);
|
||||
ent.addr = host_pc;
|
||||
ent.lineno = q[insn].line;
|
||||
ent.discrim = 0;
|
||||
fwrite(&ent, sizeof(ent), 1, jitdump);
|
||||
fwrite(q[insn].file, strlen(q[insn].file) + 1, 1, jitdump);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the trailing debug_entry. */
|
||||
ent.addr = (uintptr_t)start + tcg_ctx->gen_insn_end_off[icount - 1];
|
||||
ent.lineno = 0;
|
||||
ent.discrim = 0;
|
||||
fwrite(&ent, sizeof(ent), 1, jitdump);
|
||||
fwrite("", 1, 1, jitdump);
|
||||
}
|
||||
|
||||
/* Write a JIT_CODE_LOAD jitdump entry. */
|
||||
static void write_jr_code_load(const void *start, uint16_t host_size,
|
||||
const struct debuginfo_query *q)
|
||||
{
|
||||
static uint64_t code_index;
|
||||
struct jr_code_load rec;
|
||||
const char *symbol;
|
||||
size_t symbol_size;
|
||||
|
||||
symbol = pretty_symbol(q, &symbol_size);
|
||||
rec.p.id = JIT_CODE_LOAD;
|
||||
rec.p.total_size = sizeof(rec) + symbol_size + host_size;
|
||||
rec.p.timestamp = get_clock();
|
||||
rec.pid = getpid();
|
||||
rec.tid = qemu_get_thread_id();
|
||||
rec.vma = (uintptr_t)start;
|
||||
rec.code_addr = (uintptr_t)start;
|
||||
rec.code_size = host_size;
|
||||
rec.code_index = code_index++;
|
||||
fwrite(&rec, sizeof(rec), 1, jitdump);
|
||||
fwrite(symbol, symbol_size, 1, jitdump);
|
||||
fwrite(start, host_size, 1, jitdump);
|
||||
}
|
||||
|
||||
void perf_report_code(uint64_t guest_pc, TranslationBlock *tb,
|
||||
const void *start)
|
||||
{
|
||||
struct debuginfo_query *q;
|
||||
size_t insn;
|
||||
|
||||
if (!perfmap && !jitdump) {
|
||||
return;
|
||||
}
|
||||
|
||||
q = g_try_malloc0_n(tb->icount, sizeof(*q));
|
||||
if (!q) {
|
||||
return;
|
||||
}
|
||||
|
||||
debuginfo_lock();
|
||||
|
||||
/* Query debuginfo for each guest instruction. */
|
||||
for (insn = 0; insn < tb->icount; insn++) {
|
||||
/* FIXME: This replicates the restore_state_to_opc() logic. */
|
||||
q[insn].address = tcg_ctx->gen_insn_data[insn][0];
|
||||
if (TARGET_TB_PCREL) {
|
||||
q[insn].address |= (guest_pc & TARGET_PAGE_MASK);
|
||||
} else {
|
||||
#if defined(TARGET_I386)
|
||||
q[insn].address -= tb->cs_base;
|
||||
#endif
|
||||
}
|
||||
q[insn].flags = DEBUGINFO_SYMBOL | (jitdump ? DEBUGINFO_LINE : 0);
|
||||
}
|
||||
debuginfo_query(q, tb->icount);
|
||||
|
||||
/* Emit perfmap entries if needed. */
|
||||
if (perfmap) {
|
||||
flockfile(perfmap);
|
||||
for (insn = 0; insn < tb->icount; insn++) {
|
||||
write_perfmap_entry(start, insn, &q[insn]);
|
||||
}
|
||||
funlockfile(perfmap);
|
||||
}
|
||||
|
||||
/* Emit jitdump entries if needed. */
|
||||
if (jitdump) {
|
||||
flockfile(jitdump);
|
||||
write_jr_code_debug_info(start, q, tb->icount);
|
||||
write_jr_code_load(start, tcg_ctx->gen_insn_end_off[tb->icount - 1],
|
||||
q);
|
||||
funlockfile(jitdump);
|
||||
}
|
||||
|
||||
debuginfo_unlock();
|
||||
g_free(q);
|
||||
}
|
||||
|
||||
void perf_exit(void)
|
||||
{
|
||||
if (perfmap) {
|
||||
fclose(perfmap);
|
||||
perfmap = NULL;
|
||||
}
|
||||
|
||||
if (jitdump) {
|
||||
fclose(jitdump);
|
||||
jitdump = NULL;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Linux perf perf-<pid>.map and jit-<pid>.dump integration.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef ACCEL_TCG_PERF_H
|
||||
#define ACCEL_TCG_PERF_H
|
||||
|
||||
#if defined(CONFIG_TCG) && defined(CONFIG_LINUX)
|
||||
/* Start writing perf-<pid>.map. */
|
||||
void perf_enable_perfmap(void);
|
||||
|
||||
/* Start writing jit-<pid>.dump. */
|
||||
void perf_enable_jitdump(void);
|
||||
|
||||
/* Add information about TCG prologue to profiler maps. */
|
||||
void perf_report_prologue(const void *start, size_t size);
|
||||
|
||||
/* Add information about JITted guest code to profiler maps. */
|
||||
void perf_report_code(uint64_t guest_pc, TranslationBlock *tb,
|
||||
const void *start);
|
||||
|
||||
/* Stop writing perf-<pid>.map and/or jit-<pid>.dump. */
|
||||
void perf_exit(void);
|
||||
#else
|
||||
static inline void perf_enable_perfmap(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void perf_enable_jitdump(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void perf_report_prologue(const void *start, size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void perf_report_code(uint64_t guest_pc, TranslationBlock *tb,
|
||||
const void *start)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void perf_exit(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -45,6 +45,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "trace/mem.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/plugin-gen.h"
|
||||
#include "exec/translator.h"
|
||||
@ -162,7 +163,11 @@ static void gen_empty_mem_helper(void)
|
||||
static void gen_plugin_cb_start(enum plugin_gen_from from,
|
||||
enum plugin_gen_cb type, unsigned wr)
|
||||
{
|
||||
TCGOp *op;
|
||||
|
||||
tcg_gen_plugin_cb_start(from, type, wr);
|
||||
op = tcg_last_op();
|
||||
QSIMPLEQ_INSERT_TAIL(&tcg_ctx->plugin_ops, op, plugin_link);
|
||||
}
|
||||
|
||||
static void gen_wrapped(enum plugin_gen_from from,
|
||||
@ -206,9 +211,9 @@ static void gen_mem_wrapped(enum plugin_gen_cb type,
|
||||
const union mem_gen_fn *f, TCGv addr,
|
||||
uint32_t info, bool is_mem)
|
||||
{
|
||||
enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info);
|
||||
int wr = !!(info & TRACE_MEM_ST);
|
||||
|
||||
gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, type, rw);
|
||||
gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, type, wr);
|
||||
if (is_mem) {
|
||||
f->mem_fn(addr, info);
|
||||
} else {
|
||||
@ -258,13 +263,10 @@ static TCGOp *rm_ops(TCGOp *op)
|
||||
|
||||
static TCGOp *copy_op_nocheck(TCGOp **begin_op, TCGOp *op)
|
||||
{
|
||||
TCGOp *old_op = QTAILQ_NEXT(*begin_op, link);
|
||||
unsigned nargs = old_op->nargs;
|
||||
|
||||
*begin_op = old_op;
|
||||
op = tcg_op_insert_after(tcg_ctx, op, old_op->opc, nargs);
|
||||
memcpy(op->args, old_op->args, sizeof(op->args[0]) * nargs);
|
||||
|
||||
*begin_op = QTAILQ_NEXT(*begin_op, link);
|
||||
tcg_debug_assert(*begin_op);
|
||||
op = tcg_op_insert_after(tcg_ctx, op, (*begin_op)->opc);
|
||||
memcpy(op->args, (*begin_op)->args, sizeof(op->args));
|
||||
return op;
|
||||
}
|
||||
|
||||
@ -384,23 +386,32 @@ static TCGOp *copy_st_ptr(TCGOp **begin_op, TCGOp *op)
|
||||
static TCGOp *copy_call(TCGOp **begin_op, TCGOp *op, void *empty_func,
|
||||
void *func, int *cb_idx)
|
||||
{
|
||||
TCGOp *old_op;
|
||||
int func_idx;
|
||||
|
||||
/* copy all ops until the call */
|
||||
do {
|
||||
op = copy_op_nocheck(begin_op, op);
|
||||
} while (op->opc != INDEX_op_call);
|
||||
|
||||
/* fill in the op call */
|
||||
old_op = *begin_op;
|
||||
TCGOP_CALLI(op) = TCGOP_CALLI(old_op);
|
||||
TCGOP_CALLO(op) = TCGOP_CALLO(old_op);
|
||||
op->param1 = (*begin_op)->param1;
|
||||
op->param2 = (*begin_op)->param2;
|
||||
tcg_debug_assert(op->life == 0);
|
||||
if (*cb_idx == -1) {
|
||||
int i;
|
||||
|
||||
func_idx = TCGOP_CALLO(op) + TCGOP_CALLI(op);
|
||||
*cb_idx = func_idx;
|
||||
op->args[func_idx] = (uintptr_t)func;
|
||||
/*
|
||||
* Instead of working out the position of the callback in args[], just
|
||||
* look for @empty_func, since it should be a unique pointer.
|
||||
*/
|
||||
for (i = 0; i < MAX_OPC_PARAM_ARGS; i++) {
|
||||
if ((uintptr_t)(*begin_op)->args[i] == (uintptr_t)empty_func) {
|
||||
*cb_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
tcg_debug_assert(i < MAX_OPC_PARAM_ARGS);
|
||||
}
|
||||
op->args[*cb_idx] = (uintptr_t)func;
|
||||
op->args[*cb_idx + 1] = (*begin_op)->args[*cb_idx + 1];
|
||||
|
||||
return op;
|
||||
}
|
||||
@ -418,11 +429,11 @@ static TCGOp *append_udata_cb(const struct qemu_plugin_dyn_cb *cb,
|
||||
op = copy_const_ptr(&begin_op, op, cb->userp);
|
||||
|
||||
/* copy the ld_i32, but note that we only have to copy it once */
|
||||
begin_op = QTAILQ_NEXT(begin_op, link);
|
||||
tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
|
||||
if (*cb_idx == -1) {
|
||||
op = copy_op(&begin_op, op, INDEX_op_ld_i32);
|
||||
} else {
|
||||
begin_op = QTAILQ_NEXT(begin_op, link);
|
||||
tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
|
||||
op = tcg_op_insert_after(tcg_ctx, op, INDEX_op_ld_i32);
|
||||
memcpy(op->args, begin_op->args, sizeof(op->args));
|
||||
}
|
||||
|
||||
/* call */
|
||||
@ -465,11 +476,11 @@ static TCGOp *append_mem_cb(const struct qemu_plugin_dyn_cb *cb,
|
||||
op = copy_const_ptr(&begin_op, op, cb->userp);
|
||||
|
||||
/* copy the ld_i32, but note that we only have to copy it once */
|
||||
begin_op = QTAILQ_NEXT(begin_op, link);
|
||||
tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
|
||||
if (*cb_idx == -1) {
|
||||
op = copy_op(&begin_op, op, INDEX_op_ld_i32);
|
||||
} else {
|
||||
begin_op = QTAILQ_NEXT(begin_op, link);
|
||||
tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
|
||||
op = tcg_op_insert_after(tcg_ctx, op, INDEX_op_ld_i32);
|
||||
memcpy(op->args, begin_op->args, sizeof(op->args));
|
||||
}
|
||||
|
||||
/* extu_tl_i64 */
|
||||
@ -579,8 +590,7 @@ static void inject_mem_helper(TCGOp *begin_op, GArray *arr)
|
||||
* is possible that the code we generate after the instruction is
|
||||
* dead, we also add checks before generating tb_exit etc.
|
||||
*/
|
||||
static void inject_mem_enable_helper(struct qemu_plugin_tb *ptb,
|
||||
struct qemu_plugin_insn *plugin_insn,
|
||||
static void inject_mem_enable_helper(struct qemu_plugin_insn *plugin_insn,
|
||||
TCGOp *begin_op)
|
||||
{
|
||||
GArray *cbs[2];
|
||||
@ -600,7 +610,6 @@ static void inject_mem_enable_helper(struct qemu_plugin_tb *ptb,
|
||||
rm_ops(begin_op);
|
||||
return;
|
||||
}
|
||||
ptb->mem_helper = true;
|
||||
|
||||
arr = g_array_sized_new(false, false,
|
||||
sizeof(struct qemu_plugin_dyn_cb), n_cbs);
|
||||
@ -628,22 +637,15 @@ void plugin_gen_disable_mem_helpers(void)
|
||||
{
|
||||
TCGv_ptr ptr;
|
||||
|
||||
/*
|
||||
* We could emit the clearing unconditionally and be done. However, this can
|
||||
* be wasteful if for instance plugins don't track memory accesses, or if
|
||||
* most TBs don't use helpers. Instead, emit the clearing iff the TB calls
|
||||
* helpers that might access guest memory.
|
||||
*
|
||||
* Note: we do not reset plugin_tb->mem_helper here; a TB might have several
|
||||
* exit points, and we want to emit the clearing from all of them.
|
||||
*/
|
||||
if (!tcg_ctx->plugin_tb->mem_helper) {
|
||||
if (likely(tcg_ctx->plugin_insn == NULL ||
|
||||
!tcg_ctx->plugin_insn->mem_helper)) {
|
||||
return;
|
||||
}
|
||||
ptr = tcg_const_ptr(NULL);
|
||||
tcg_gen_st_ptr(ptr, cpu_env, offsetof(CPUState, plugin_mem_cbs) -
|
||||
offsetof(ArchCPU, env));
|
||||
tcg_temp_free_ptr(ptr);
|
||||
tcg_ctx->plugin_insn->mem_helper = false;
|
||||
}
|
||||
|
||||
static void plugin_gen_tb_udata(const struct qemu_plugin_tb *ptb,
|
||||
@ -691,20 +693,76 @@ static void plugin_gen_mem_inline(const struct qemu_plugin_tb *ptb,
|
||||
inject_inline_cb(cbs, begin_op, op_rw);
|
||||
}
|
||||
|
||||
static void plugin_gen_enable_mem_helper(struct qemu_plugin_tb *ptb,
|
||||
static void plugin_gen_enable_mem_helper(const struct qemu_plugin_tb *ptb,
|
||||
TCGOp *begin_op, int insn_idx)
|
||||
{
|
||||
struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
|
||||
inject_mem_enable_helper(ptb, insn, begin_op);
|
||||
inject_mem_enable_helper(insn, begin_op);
|
||||
}
|
||||
|
||||
static void plugin_gen_disable_mem_helper(struct qemu_plugin_tb *ptb,
|
||||
static void plugin_gen_disable_mem_helper(const struct qemu_plugin_tb *ptb,
|
||||
TCGOp *begin_op, int insn_idx)
|
||||
{
|
||||
struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
|
||||
inject_mem_disable_helper(insn, begin_op);
|
||||
}
|
||||
|
||||
static void plugin_inject_cb(const struct qemu_plugin_tb *ptb, TCGOp *begin_op,
|
||||
int insn_idx)
|
||||
{
|
||||
enum plugin_gen_from from = begin_op->args[0];
|
||||
enum plugin_gen_cb type = begin_op->args[1];
|
||||
|
||||
switch (from) {
|
||||
case PLUGIN_GEN_FROM_TB:
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_UDATA:
|
||||
plugin_gen_tb_udata(ptb, begin_op);
|
||||
return;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_tb_inline(ptb, begin_op);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
case PLUGIN_GEN_FROM_INSN:
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_UDATA:
|
||||
plugin_gen_insn_udata(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_insn_inline(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
case PLUGIN_GEN_ENABLE_MEM_HELPER:
|
||||
plugin_gen_enable_mem_helper(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
case PLUGIN_GEN_FROM_MEM:
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_MEM:
|
||||
plugin_gen_mem_regular(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_mem_inline(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
case PLUGIN_GEN_AFTER_INSN:
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_DISABLE_MEM_HELPER:
|
||||
plugin_gen_disable_mem_helper(ptb, begin_op, insn_idx);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
/* #define DEBUG_PLUGIN_GEN_OPS */
|
||||
static void pr_ops(void)
|
||||
{
|
||||
@ -759,133 +817,45 @@ static void pr_ops(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
|
||||
static void plugin_gen_inject(const struct qemu_plugin_tb *plugin_tb)
|
||||
{
|
||||
TCGOp *op;
|
||||
int insn_idx = -1;
|
||||
int insn_idx;
|
||||
|
||||
pr_ops();
|
||||
insn_idx = -1;
|
||||
QSIMPLEQ_FOREACH(op, &tcg_ctx->plugin_ops, plugin_link) {
|
||||
enum plugin_gen_from from = op->args[0];
|
||||
enum plugin_gen_cb type = op->args[1];
|
||||
|
||||
QTAILQ_FOREACH(op, &tcg_ctx->ops, link) {
|
||||
switch (op->opc) {
|
||||
case INDEX_op_insn_start:
|
||||
tcg_debug_assert(op->opc == INDEX_op_plugin_cb_start);
|
||||
/* ENABLE_MEM_HELPER is the first callback of an instruction */
|
||||
if (from == PLUGIN_GEN_FROM_INSN &&
|
||||
type == PLUGIN_GEN_ENABLE_MEM_HELPER) {
|
||||
insn_idx++;
|
||||
break;
|
||||
case INDEX_op_plugin_cb_start:
|
||||
{
|
||||
enum plugin_gen_from from = op->args[0];
|
||||
enum plugin_gen_cb type = op->args[1];
|
||||
|
||||
switch (from) {
|
||||
case PLUGIN_GEN_FROM_TB:
|
||||
{
|
||||
g_assert(insn_idx == -1);
|
||||
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_UDATA:
|
||||
plugin_gen_tb_udata(plugin_tb, op);
|
||||
break;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_tb_inline(plugin_tb, op);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PLUGIN_GEN_FROM_INSN:
|
||||
{
|
||||
g_assert(insn_idx >= 0);
|
||||
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_UDATA:
|
||||
plugin_gen_insn_udata(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_insn_inline(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
case PLUGIN_GEN_ENABLE_MEM_HELPER:
|
||||
plugin_gen_enable_mem_helper(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PLUGIN_GEN_FROM_MEM:
|
||||
{
|
||||
g_assert(insn_idx >= 0);
|
||||
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_CB_MEM:
|
||||
plugin_gen_mem_regular(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
case PLUGIN_GEN_CB_INLINE:
|
||||
plugin_gen_mem_inline(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PLUGIN_GEN_AFTER_INSN:
|
||||
{
|
||||
g_assert(insn_idx >= 0);
|
||||
|
||||
switch (type) {
|
||||
case PLUGIN_GEN_DISABLE_MEM_HELPER:
|
||||
plugin_gen_disable_mem_helper(plugin_tb, op, insn_idx);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* plugins don't care about any other ops */
|
||||
break;
|
||||
}
|
||||
plugin_inject_cb(plugin_tb, op, insn_idx);
|
||||
}
|
||||
pr_ops();
|
||||
}
|
||||
|
||||
bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db,
|
||||
bool mem_only)
|
||||
bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_only)
|
||||
{
|
||||
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
||||
bool ret = false;
|
||||
|
||||
if (test_bit(QEMU_PLUGIN_EV_VCPU_TB_TRANS, cpu->plugin_mask)) {
|
||||
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
||||
int i;
|
||||
|
||||
/* reset callbacks */
|
||||
for (i = 0; i < PLUGIN_N_CB_SUBTYPES; i++) {
|
||||
if (ptb->cbs[i]) {
|
||||
g_array_set_size(ptb->cbs[i], 0);
|
||||
}
|
||||
}
|
||||
ptb->n = 0;
|
||||
|
||||
ret = true;
|
||||
|
||||
ptb->vaddr = db->pc_first;
|
||||
QSIMPLEQ_INIT(&tcg_ctx->plugin_ops);
|
||||
ptb->vaddr = tb->pc;
|
||||
ptb->vaddr2 = -1;
|
||||
ptb->haddr1 = db->host_addr[0];
|
||||
get_page_addr_code_hostp(cpu->env_ptr, tb->pc, &ptb->haddr1);
|
||||
ptb->haddr2 = NULL;
|
||||
ptb->mem_only = mem_only;
|
||||
ptb->mem_helper = false;
|
||||
|
||||
plugin_gen_empty_callback(PLUGIN_GEN_FROM_TB);
|
||||
}
|
||||
|
||||
tcg_ctx->plugin_insn = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -894,8 +864,9 @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
|
||||
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
||||
struct qemu_plugin_insn *pinsn;
|
||||
|
||||
pinsn = qemu_plugin_tb_insn_get(ptb, db->pc_next);
|
||||
pinsn = qemu_plugin_tb_insn_get(ptb);
|
||||
tcg_ctx->plugin_insn = pinsn;
|
||||
pinsn->vaddr = db->pc_next;
|
||||
plugin_gen_empty_callback(PLUGIN_GEN_FROM_INSN);
|
||||
|
||||
/*
|
||||
@ -903,15 +874,16 @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
|
||||
* Note that we skip this when haddr1 == NULL, e.g. when we're
|
||||
* fetching instructions from a region not backed by RAM.
|
||||
*/
|
||||
if (ptb->haddr1 == NULL) {
|
||||
pinsn->haddr = NULL;
|
||||
} else if (is_same_page(db, db->pc_next)) {
|
||||
if (likely(ptb->haddr1 != NULL && ptb->vaddr2 == -1) &&
|
||||
unlikely((db->pc_next & TARGET_PAGE_MASK) !=
|
||||
(db->pc_first & TARGET_PAGE_MASK))) {
|
||||
get_page_addr_code_hostp(cpu->env_ptr, db->pc_next,
|
||||
&ptb->haddr2);
|
||||
ptb->vaddr2 = db->pc_next;
|
||||
}
|
||||
if (likely(ptb->vaddr2 == -1)) {
|
||||
pinsn->haddr = ptb->haddr1 + pinsn->vaddr - ptb->vaddr;
|
||||
} else {
|
||||
if (ptb->vaddr2 == -1) {
|
||||
ptb->vaddr2 = TARGET_PAGE_ALIGN(db->pc_first);
|
||||
get_page_addr_code_hostp(cpu->env_ptr, ptb->vaddr2, &ptb->haddr2);
|
||||
}
|
||||
pinsn->haddr = ptb->haddr2 + pinsn->vaddr - ptb->vaddr2;
|
||||
}
|
||||
}
|
||||
@ -921,19 +893,23 @@ void plugin_gen_insn_end(void)
|
||||
plugin_gen_empty_callback(PLUGIN_GEN_AFTER_INSN);
|
||||
}
|
||||
|
||||
/*
|
||||
* There are cases where we never get to finalise a translation - for
|
||||
* example a page fault during translation. As a result we shouldn't
|
||||
* do any clean-up here and make sure things are reset in
|
||||
* plugin_gen_tb_start.
|
||||
*/
|
||||
void plugin_gen_tb_end(CPUState *cpu)
|
||||
{
|
||||
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
||||
int i;
|
||||
|
||||
/* collect instrumentation requests */
|
||||
qemu_plugin_tb_trans_cb(cpu, ptb);
|
||||
|
||||
/* inject the instrumentation at the appropriate places */
|
||||
plugin_gen_inject(ptb);
|
||||
|
||||
/* clean up */
|
||||
for (i = 0; i < PLUGIN_N_CB_SUBTYPES; i++) {
|
||||
if (ptb->cbs[i]) {
|
||||
g_array_set_size(ptb->cbs[i], 0);
|
||||
}
|
||||
}
|
||||
ptb->n = 0;
|
||||
tcg_ctx->plugin_insn = NULL;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifdef CONFIG_PLUGIN
|
||||
DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb, 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)
|
||||
DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb, TCG_CALL_NO_RWG, void, i32, ptr)
|
||||
DEF_HELPER_FLAGS_4(plugin_vcpu_mem_cb, TCG_CALL_NO_RWG, void, i32, i32, i64, ptr)
|
||||
#endif
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "exec/cpu-defs.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/xxhash.h"
|
||||
#include "tb-jmp-cache.h"
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
|
||||
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* The per-CPU TranslationBlock jump cache.
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef ACCEL_TCG_TB_JMP_CACHE_H
|
||||
#define ACCEL_TCG_TB_JMP_CACHE_H
|
||||
|
||||
#define TB_JMP_CACHE_BITS 12
|
||||
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
|
||||
|
||||
/*
|
||||
* Accessed in parallel; all accesses to 'tb' must be atomic.
|
||||
* For TARGET_TB_PCREL, accesses to 'pc' must be protected by
|
||||
* a load_acquire/store_release to 'tb'.
|
||||
*/
|
||||
struct CPUJumpCache {
|
||||
struct rcu_head rcu;
|
||||
struct {
|
||||
TranslationBlock *tb;
|
||||
#if TARGET_TB_PCREL
|
||||
target_ulong pc;
|
||||
#endif
|
||||
} array[TB_JMP_CACHE_SIZE];
|
||||
};
|
||||
|
||||
static inline TranslationBlock *
|
||||
tb_jmp_cache_get_tb(CPUJumpCache *jc, uint32_t hash)
|
||||
{
|
||||
#if TARGET_TB_PCREL
|
||||
/* Use acquire to ensure current load of pc from jc. */
|
||||
return qatomic_load_acquire(&jc->array[hash].tb);
|
||||
#else
|
||||
/* Use rcu_read to ensure current load of pc from *tb. */
|
||||
return qatomic_rcu_read(&jc->array[hash].tb);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline target_ulong
|
||||
tb_jmp_cache_get_pc(CPUJumpCache *jc, uint32_t hash, TranslationBlock *tb)
|
||||
{
|
||||
#if TARGET_TB_PCREL
|
||||
return jc->array[hash].pc;
|
||||
#else
|
||||
return tb_pc(tb);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
tb_jmp_cache_set(CPUJumpCache *jc, uint32_t hash,
|
||||
TranslationBlock *tb, target_ulong pc)
|
||||
{
|
||||
#if TARGET_TB_PCREL
|
||||
jc->array[hash].pc = pc;
|
||||
/* Use store_release on tb to ensure pc is written first. */
|
||||
qatomic_store_release(&jc->array[hash].tb, tb);
|
||||
#else
|
||||
/* Use the pc value already stored in tb->pc. */
|
||||
qatomic_set(&jc->array[hash].tb, tb);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* ACCEL_TCG_TB_JMP_CACHE_H */
|
1228
accel/tcg/tb-maint.c
1228
accel/tcg/tb-maint.c
File diff suppressed because it is too large
Load Diff
@ -24,8 +24,9 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "exec/exec-all.h"
|
||||
@ -84,7 +85,8 @@ void icount_handle_deadline(void)
|
||||
* Don't interrupt cpu thread, when these events are waiting
|
||||
* (i.e., there is no checkpoint)
|
||||
*/
|
||||
if (deadline == 0) {
|
||||
if (deadline == 0
|
||||
&& (replay_mode != REPLAY_MODE_PLAY || replay_has_checkpoint())) {
|
||||
icount_notify_aio_contexts();
|
||||
}
|
||||
}
|
||||
@ -108,14 +110,8 @@ void icount_prepare_for_run(CPUState *cpu)
|
||||
|
||||
replay_mutex_lock();
|
||||
|
||||
if (cpu->icount_budget == 0) {
|
||||
/*
|
||||
* We're called without the iothread lock, so must take it while
|
||||
* we're calling timer handlers.
|
||||
*/
|
||||
qemu_mutex_lock_iothread();
|
||||
if (cpu->icount_budget == 0 && replay_has_checkpoint()) {
|
||||
icount_notify_aio_contexts();
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,8 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TCG_ACCEL_OPS_ICOUNT_H
|
||||
#define TCG_ACCEL_OPS_ICOUNT_H
|
||||
#ifndef TCG_CPUS_ICOUNT_H
|
||||
#define TCG_CPUS_ICOUNT_H
|
||||
|
||||
void icount_handle_deadline(void);
|
||||
void icount_prepare_for_run(CPUState *cpu);
|
||||
@ -16,4 +16,4 @@ void icount_process_data(CPUState *cpu);
|
||||
|
||||
void icount_handle_interrupt(CPUState *cpu, int mask);
|
||||
|
||||
#endif /* TCG_ACCEL_OPS_ICOUNT_H */
|
||||
#endif /* TCG_CPUS_ICOUNT_H */
|
||||
|
@ -24,9 +24,9 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/guest-random.h"
|
||||
@ -142,7 +142,7 @@ 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->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
|
||||
|
@ -7,8 +7,8 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TCG_ACCEL_OPS_MTTCG_H
|
||||
#define TCG_ACCEL_OPS_MTTCG_H
|
||||
#ifndef TCG_CPUS_MTTCG_H
|
||||
#define TCG_CPUS_MTTCG_H
|
||||
|
||||
/* kick MTTCG vCPU thread */
|
||||
void mttcg_kick_vcpu_thread(CPUState *cpu);
|
||||
@ -16,4 +16,4 @@ void mttcg_kick_vcpu_thread(CPUState *cpu);
|
||||
/* start an mttcg vCPU thread */
|
||||
void mttcg_start_vcpu_thread(CPUState *cpu);
|
||||
|
||||
#endif /* TCG_ACCEL_OPS_MTTCG_H */
|
||||
#endif /* TCG_CPUS_MTTCG_H */
|
||||
|
@ -24,9 +24,9 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qemu/guest-random.h"
|
||||
@ -51,7 +51,7 @@ void rr_kick_vcpu_thread(CPUState *unused)
|
||||
*
|
||||
* The kick timer is responsible for moving single threaded vCPU
|
||||
* emulation on to the next vCPU. If more than one vCPU is running a
|
||||
* timer event we force a cpu->exit so the next vCPU can get
|
||||
* timer event with force a cpu->exit so the next vCPU can get
|
||||
* scheduled.
|
||||
*
|
||||
* The timer is removed if all vCPUs are idle and restarted again once
|
||||
@ -61,6 +61,8 @@ void rr_kick_vcpu_thread(CPUState *unused)
|
||||
static QEMUTimer *rr_kick_vcpu_timer;
|
||||
static CPUState *rr_current_cpu;
|
||||
|
||||
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
|
||||
|
||||
static inline int64_t rr_next_kick_time(void)
|
||||
{
|
||||
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
|
||||
@ -279,8 +281,8 @@ void rr_start_vcpu_thread(CPUState *cpu)
|
||||
tcg_cpu_init_cflags(cpu, false);
|
||||
|
||||
if (!single_tcg_cpu_thread) {
|
||||
cpu->thread = g_new0(QemuThread, 1);
|
||||
cpu->halt_cond = g_new0(QemuCond, 1);
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
|
||||
/* share a single thread for all cpus with TCG */
|
||||
|
@ -7,8 +7,8 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TCG_ACCEL_OPS_RR_H
|
||||
#define TCG_ACCEL_OPS_RR_H
|
||||
#ifndef TCG_CPUS_RR_H
|
||||
#define TCG_CPUS_RR_H
|
||||
|
||||
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
|
||||
|
||||
@ -18,4 +18,4 @@ void rr_kick_vcpu_thread(CPUState *unused);
|
||||
/* start the round robin vcpu thread */
|
||||
void rr_start_vcpu_thread(CPUState *cpu);
|
||||
|
||||
#endif /* TCG_ACCEL_OPS_RR_H */
|
||||
#endif /* TCG_CPUS_RR_H */
|
||||
|
@ -26,14 +26,12 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/hwaddr.h"
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
#include "tcg-accel-ops.h"
|
||||
#include "tcg-accel-ops-mttcg.h"
|
||||
@ -93,120 +91,23 @@ void tcg_handle_interrupt(CPUState *cpu, int mask)
|
||||
}
|
||||
}
|
||||
|
||||
static bool tcg_supports_guest_debug(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Translate GDB watchpoint type to a flags value for cpu_watchpoint_* */
|
||||
static inline int xlat_gdb_type(CPUState *cpu, int gdbtype)
|
||||
{
|
||||
static const int xlat[] = {
|
||||
[GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE,
|
||||
[GDB_WATCHPOINT_READ] = BP_GDB | BP_MEM_READ,
|
||||
[GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS,
|
||||
};
|
||||
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
int cputype = xlat[gdbtype];
|
||||
|
||||
if (cc->gdb_stop_before_watchpoint) {
|
||||
cputype |= BP_STOP_BEFORE_ACCESS;
|
||||
}
|
||||
return cputype;
|
||||
}
|
||||
|
||||
static int tcg_insert_breakpoint(CPUState *cs, int type, hwaddr addr, hwaddr len)
|
||||
{
|
||||
CPUState *cpu;
|
||||
int err = 0;
|
||||
|
||||
switch (type) {
|
||||
case GDB_BREAKPOINT_SW:
|
||||
case GDB_BREAKPOINT_HW:
|
||||
CPU_FOREACH(cpu) {
|
||||
err = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL);
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
case GDB_WATCHPOINT_WRITE:
|
||||
case GDB_WATCHPOINT_READ:
|
||||
case GDB_WATCHPOINT_ACCESS:
|
||||
CPU_FOREACH(cpu) {
|
||||
err = cpu_watchpoint_insert(cpu, addr, len,
|
||||
xlat_gdb_type(cpu, type), NULL);
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
static int tcg_remove_breakpoint(CPUState *cs, int type, hwaddr addr, hwaddr len)
|
||||
{
|
||||
CPUState *cpu;
|
||||
int err = 0;
|
||||
|
||||
switch (type) {
|
||||
case GDB_BREAKPOINT_SW:
|
||||
case GDB_BREAKPOINT_HW:
|
||||
CPU_FOREACH(cpu) {
|
||||
err = cpu_breakpoint_remove(cpu, addr, BP_GDB);
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
case GDB_WATCHPOINT_WRITE:
|
||||
case GDB_WATCHPOINT_READ:
|
||||
case GDB_WATCHPOINT_ACCESS:
|
||||
CPU_FOREACH(cpu) {
|
||||
err = cpu_watchpoint_remove(cpu, addr, len,
|
||||
xlat_gdb_type(cpu, type));
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tcg_remove_all_breakpoints(CPUState *cpu)
|
||||
{
|
||||
cpu_breakpoint_remove_all(cpu, BP_GDB);
|
||||
cpu_watchpoint_remove_all(cpu, BP_GDB);
|
||||
}
|
||||
|
||||
static void tcg_accel_ops_init(AccelOpsClass *ops)
|
||||
{
|
||||
if (qemu_tcg_mttcg_enabled()) {
|
||||
ops->create_vcpu_thread = mttcg_start_vcpu_thread;
|
||||
ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
|
||||
ops->handle_interrupt = tcg_handle_interrupt;
|
||||
} else if (icount_enabled()) {
|
||||
ops->create_vcpu_thread = rr_start_vcpu_thread;
|
||||
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
|
||||
ops->handle_interrupt = icount_handle_interrupt;
|
||||
ops->get_virtual_clock = icount_get;
|
||||
ops->get_elapsed_ticks = icount_get;
|
||||
} else {
|
||||
ops->create_vcpu_thread = rr_start_vcpu_thread;
|
||||
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
|
||||
|
||||
if (icount_enabled()) {
|
||||
ops->handle_interrupt = icount_handle_interrupt;
|
||||
ops->get_virtual_clock = icount_get;
|
||||
ops->get_elapsed_ticks = icount_get;
|
||||
} else {
|
||||
ops->handle_interrupt = tcg_handle_interrupt;
|
||||
}
|
||||
ops->handle_interrupt = tcg_handle_interrupt;
|
||||
}
|
||||
|
||||
ops->supports_guest_debug = tcg_supports_guest_debug;
|
||||
ops->insert_breakpoint = tcg_insert_breakpoint;
|
||||
ops->remove_breakpoint = tcg_remove_breakpoint;
|
||||
ops->remove_all_breakpoints = tcg_remove_all_breakpoints;
|
||||
}
|
||||
|
||||
static void tcg_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
|
@ -9,8 +9,8 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TCG_ACCEL_OPS_H
|
||||
#define TCG_ACCEL_OPS_H
|
||||
#ifndef TCG_CPUS_H
|
||||
#define TCG_CPUS_H
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
@ -19,4 +19,4 @@ int tcg_cpus_exec(CPUState *cpu);
|
||||
void tcg_handle_interrupt(CPUState *cpu, int mask);
|
||||
void tcg_cpu_init_cflags(CPUState *cpu, bool parallel);
|
||||
|
||||
#endif /* TCG_ACCEL_OPS_H */
|
||||
#endif /* TCG_CPUS_H */
|
||||
|
@ -24,8 +24,8 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "qapi/error.h"
|
||||
@ -83,14 +83,6 @@ static bool check_tcg_memory_orders_compatible(void)
|
||||
|
||||
static bool default_mttcg_enabled(void)
|
||||
{
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
// Only the RR ops works with libafl_qemu, so avoid MTTCG by default
|
||||
return false;
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
if (icount_enabled() || TCG_OVERSIZED_GUEST) {
|
||||
return false;
|
||||
} else {
|
||||
@ -216,28 +208,12 @@ static void tcg_set_splitwx(Object *obj, bool value, Error **errp)
|
||||
s->splitwx_enabled = value;
|
||||
}
|
||||
|
||||
static int tcg_gdbstub_supported_sstep_flags(void)
|
||||
{
|
||||
/*
|
||||
* In replay mode all events will come from the log and can't be
|
||||
* suppressed otherwise we would break determinism. However as those
|
||||
* events are tied to the number of executed instructions we won't see
|
||||
* them occurring every time we single step.
|
||||
*/
|
||||
if (replay_mode != REPLAY_MODE_NONE) {
|
||||
return SSTEP_ENABLE;
|
||||
} else {
|
||||
return SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER;
|
||||
}
|
||||
}
|
||||
|
||||
static void tcg_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(oc);
|
||||
ac->name = "tcg";
|
||||
ac->init_machine = tcg_init_machine;
|
||||
ac->allowed = &tcg_allowed;
|
||||
ac->gdbstub_supported_sstep_flags = tcg_gdbstub_supported_sstep_flags;
|
||||
|
||||
object_class_property_add_str(oc, "thread",
|
||||
tcg_get_thread,
|
||||
|
@ -33,145 +33,13 @@
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
#include "sysemu/runstate.h"
|
||||
#include "migration/snapshot.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void libafl_save_qemu_snapshot(char *name, bool sync);
|
||||
void libafl_load_qemu_snapshot(char *name, bool sync);
|
||||
|
||||
static void save_snapshot_cb(void* opaque)
|
||||
{
|
||||
char* name = (char*)opaque;
|
||||
Error *err = NULL;
|
||||
if(!save_snapshot(name, true, NULL, false, NULL, &err)) {
|
||||
error_report_err(err);
|
||||
error_report("Could not save snapshot");
|
||||
}
|
||||
free(opaque);
|
||||
}
|
||||
|
||||
void libafl_save_qemu_snapshot(char *name, bool sync)
|
||||
{
|
||||
// use snapshots synchronously, use if main loop is not running
|
||||
if (sync) {
|
||||
//TODO: eliminate this code duplication
|
||||
//by passing a heap-allocated buffer from rust to c,
|
||||
//which c needs to free
|
||||
Error *err = NULL;
|
||||
if(!save_snapshot(name, true, NULL, false, NULL, &err)) {
|
||||
error_report_err(err);
|
||||
error_report("Could not save snapshot");
|
||||
}
|
||||
return;
|
||||
}
|
||||
char* name_buffer = malloc(strlen(name)+1);
|
||||
strcpy(name_buffer, name);
|
||||
aio_bh_schedule_oneshot_full(qemu_get_aio_context(), save_snapshot_cb, (void*)name_buffer, "save_snapshot");
|
||||
}
|
||||
|
||||
static void load_snapshot_cb(void* opaque)
|
||||
{
|
||||
char* name = (char*)opaque;
|
||||
Error *err = NULL;
|
||||
|
||||
int saved_vm_running = runstate_is_running();
|
||||
vm_stop(RUN_STATE_RESTORE_VM);
|
||||
|
||||
bool loaded = load_snapshot(name, NULL, false, NULL, &err);
|
||||
|
||||
if(!loaded) {
|
||||
error_report_err(err);
|
||||
error_report("Could not load snapshot");
|
||||
}
|
||||
if (loaded && saved_vm_running) {
|
||||
vm_start();
|
||||
}
|
||||
free(opaque);
|
||||
}
|
||||
|
||||
void libafl_load_qemu_snapshot(char *name, bool sync)
|
||||
{
|
||||
// use snapshots synchronously, use if main loop is not running
|
||||
if (sync) {
|
||||
//TODO: see libafl_save_qemu_snapshot
|
||||
Error *err = NULL;
|
||||
|
||||
int saved_vm_running = runstate_is_running();
|
||||
vm_stop(RUN_STATE_RESTORE_VM);
|
||||
|
||||
bool loaded = load_snapshot(name, NULL, false, NULL, &err);
|
||||
|
||||
if(!loaded) {
|
||||
error_report_err(err);
|
||||
error_report("Could not load snapshot");
|
||||
}
|
||||
if (loaded && saved_vm_running) {
|
||||
vm_start();
|
||||
}
|
||||
return;
|
||||
}
|
||||
char* name_buffer = malloc(strlen(name)+1);
|
||||
strcpy(name_buffer, name);
|
||||
aio_bh_schedule_oneshot_full(qemu_get_aio_context(), load_snapshot_cb, (void*)name_buffer, "load_snapshot");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define EXCP_LIBAFL_BP 0xf4775747
|
||||
|
||||
int libafl_qemu_break_asap = 0;
|
||||
|
||||
CPUState* libafl_breakpoint_cpu;
|
||||
vaddr libafl_breakpoint_pc;
|
||||
|
||||
#ifdef TARGET_ARM
|
||||
#define THUMB_MASK(value) (value | libafl_breakpoint_cpu->env_ptr->thumb)
|
||||
#else
|
||||
#define THUMB_MASK(value) value
|
||||
#endif
|
||||
|
||||
void libafl_qemu_trigger_breakpoint(CPUState* cpu);
|
||||
|
||||
void libafl_sync_breakpoint_cpu(void);
|
||||
|
||||
void libafl_sync_breakpoint_cpu(void)
|
||||
{
|
||||
if (libafl_breakpoint_pc) {
|
||||
CPUClass* cc = CPU_GET_CLASS(libafl_breakpoint_cpu);
|
||||
cc->set_pc(libafl_breakpoint_cpu, THUMB_MASK(libafl_breakpoint_pc));
|
||||
}
|
||||
libafl_breakpoint_pc = 0;
|
||||
}
|
||||
|
||||
void libafl_qemu_trigger_breakpoint(CPUState* cpu)
|
||||
{
|
||||
libafl_breakpoint_cpu = cpu;
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
qemu_system_debug_request();
|
||||
cpu->stopped = true;
|
||||
#endif
|
||||
if (cpu->running) {
|
||||
cpu->exception_index = EXCP_LIBAFL_BP;
|
||||
cpu_loop_exit(cpu);
|
||||
} else {
|
||||
libafl_qemu_break_asap = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env, target_ulong pc)
|
||||
void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env)
|
||||
{
|
||||
CPUState* cpu = env_cpu(env);
|
||||
libafl_breakpoint_pc = pc;
|
||||
libafl_qemu_trigger_breakpoint(cpu);
|
||||
cpu->exception_index = EXCP_LIBAFL_BP;
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
@ -55,17 +55,6 @@ DEF_HELPER_FLAGS_5(atomic_cmpxchgq_be, TCG_CALL_NO_WG,
|
||||
DEF_HELPER_FLAGS_5(atomic_cmpxchgq_le, TCG_CALL_NO_WG,
|
||||
i64, env, tl, i64, i64, i32)
|
||||
#endif
|
||||
#ifdef CONFIG_CMPXCHG128
|
||||
DEF_HELPER_FLAGS_5(atomic_cmpxchgo_be, TCG_CALL_NO_WG,
|
||||
i128, env, tl, i128, i128, i32)
|
||||
DEF_HELPER_FLAGS_5(atomic_cmpxchgo_le, TCG_CALL_NO_WG,
|
||||
i128, env, tl, i128, i128, i32)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_FLAGS_5(nonatomic_cmpxchgo_be, TCG_CALL_NO_WG,
|
||||
i128, env, tl, i128, i128, i32)
|
||||
DEF_HELPER_FLAGS_5(nonatomic_cmpxchgo_le, TCG_CALL_NO_WG,
|
||||
i128, env, tl, i128, i128, i32)
|
||||
|
||||
#ifdef CONFIG_ATOMIC64
|
||||
#define GEN_ATOMIC_HELPERS(NAME) \
|
||||
@ -299,7 +288,6 @@ DEF_HELPER_FLAGS_5(gvec_bitsel, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
DEF_HELPER_FLAGS_2(libafl_qemu_handle_breakpoint, TCG_CALL_NO_RWG,
|
||||
void, env, tl)
|
||||
DEF_HELPER_FLAGS_1(libafl_qemu_handle_breakpoint, TCG_CALL_NO_RWG, void, env)
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
@ -6,9 +6,5 @@ exec_tb(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
|
||||
exec_tb_nocache(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
|
||||
exec_tb_exit(void *last_tb, unsigned int flags) "tb:%p flags=0x%x"
|
||||
|
||||
# cputlb.c
|
||||
memory_notdirty_write_access(uint64_t vaddr, uint64_t ram_addr, unsigned size) "0x%" PRIx64 " ram_addr 0x%" PRIx64 " size %u"
|
||||
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"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,8 +22,6 @@
|
||||
|
||||
#include "tcg/tcg-internal.h"
|
||||
|
||||
extern target_ulong libafl_gen_cur_pc;
|
||||
|
||||
struct libafl_breakpoint {
|
||||
target_ulong addr;
|
||||
struct libafl_breakpoint* next;
|
||||
@ -34,24 +32,13 @@ extern struct libafl_breakpoint* libafl_qemu_breakpoints;
|
||||
struct libafl_hook {
|
||||
target_ulong addr;
|
||||
void (*callback)(uint64_t);
|
||||
uint64_t data;
|
||||
uint64_t value;
|
||||
TCGHelperInfo helper_info;
|
||||
struct libafl_hook* next;
|
||||
};
|
||||
|
||||
extern struct libafl_hook* libafl_qemu_hooks;
|
||||
|
||||
struct libafl_hook* libafl_search_hook(target_ulong addr);
|
||||
|
||||
struct libafl_backdoor_hook {
|
||||
void (*exec)(target_ulong pc, uint64_t data);
|
||||
uint64_t data;
|
||||
TCGHelperInfo helper_info;
|
||||
struct libafl_backdoor_hook* next;
|
||||
};
|
||||
|
||||
extern struct libafl_backdoor_hook* libafl_backdoor_hooks;
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
/* Pairs with tcg_clear_temp_count.
|
||||
@ -78,27 +65,20 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
|
||||
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
|
||||
}
|
||||
|
||||
void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
|
||||
target_ulong pc, void *host_pc,
|
||||
const TranslatorOps *ops, DisasContextBase *db)
|
||||
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
CPUState *cpu, TranslationBlock *tb, int max_insns)
|
||||
{
|
||||
uint32_t cflags = tb_cflags(tb);
|
||||
bool plugin_enabled;
|
||||
|
||||
/* Initialize DisasContext */
|
||||
db->tb = tb;
|
||||
db->pc_first = pc;
|
||||
db->pc_next = pc;
|
||||
db->pc_first = tb->pc;
|
||||
db->pc_next = db->pc_first;
|
||||
db->is_jmp = DISAS_NEXT;
|
||||
db->num_insns = 0;
|
||||
db->max_insns = max_insns;
|
||||
db->singlestep_enabled = cflags & CF_SINGLE_STEP;
|
||||
db->host_addr[0] = host_pc;
|
||||
db->host_addr[1] = NULL;
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
page_protect(pc);
|
||||
#endif
|
||||
|
||||
ops->init_disas_context(db, cpu);
|
||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||
@ -111,7 +91,7 @@ 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, cflags & CF_MEMI_ONLY);
|
||||
plugin_enabled = plugin_gen_tb_start(cpu, tb, cflags & CF_MEMI_ONLY);
|
||||
|
||||
while (true) {
|
||||
db->num_insns++;
|
||||
@ -124,75 +104,25 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
|
||||
|
||||
//// --- Begin LibAFL code ---
|
||||
|
||||
struct libafl_hook* hk = libafl_search_hook(db->pc_next);
|
||||
if (hk) {
|
||||
TCGv tmp0 = tcg_const_tl(db->pc_next);
|
||||
TCGv_i64 tmp1 = tcg_const_i64(hk->data);
|
||||
#if TARGET_LONG_BITS == 32
|
||||
TCGTemp *tmp2[2] = { tcgv_i32_temp(tmp0), tcgv_i64_temp(tmp1) };
|
||||
#else
|
||||
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
||||
#endif
|
||||
tcg_gen_callN(hk->callback, NULL, 2, tmp2);
|
||||
#if TARGET_LONG_BITS == 32
|
||||
tcg_temp_free_i32(tmp0);
|
||||
#else
|
||||
tcg_temp_free_i64(tmp0);
|
||||
#endif
|
||||
tcg_temp_free_i64(tmp1);
|
||||
struct libafl_hook* hk = libafl_qemu_hooks;
|
||||
while (hk) {
|
||||
if (hk->addr == db->pc_next) {
|
||||
TCGv_i64 tmp0 = tcg_const_i64(hk->value);
|
||||
TCGTemp *tmp1[1] = { tcgv_i64_temp(tmp0) };
|
||||
tcg_gen_callN(hk->callback, NULL, 1, tmp1);
|
||||
tcg_temp_free_i64(tmp0);
|
||||
}
|
||||
hk = hk->next;
|
||||
}
|
||||
|
||||
struct libafl_breakpoint* bp = libafl_qemu_breakpoints;
|
||||
while (bp) {
|
||||
if (bp->addr == db->pc_next) {
|
||||
TCGv tmp0 = tcg_const_tl(db->pc_next);
|
||||
gen_helper_libafl_qemu_handle_breakpoint(cpu_env, tmp0);
|
||||
#if TARGET_LONG_BITS == 32
|
||||
tcg_temp_free_i32(tmp0);
|
||||
#else
|
||||
tcg_temp_free_i64(tmp0);
|
||||
#endif
|
||||
gen_helper_libafl_qemu_handle_breakpoint(cpu_env);
|
||||
}
|
||||
bp = bp->next;
|
||||
}
|
||||
|
||||
libafl_gen_cur_pc = db->pc_next;
|
||||
|
||||
// 0x0f, 0x3a, 0xf2, 0x44
|
||||
uint8_t backdoor = translator_ldub(cpu->env_ptr, db, db->pc_next);
|
||||
if (backdoor == 0x0f) {
|
||||
backdoor = translator_ldub(cpu->env_ptr, db, db->pc_next +1);
|
||||
if (backdoor == 0x3a) {
|
||||
backdoor = translator_ldub(cpu->env_ptr, db, db->pc_next +2);
|
||||
if (backdoor == 0xf2) {
|
||||
backdoor = translator_ldub(cpu->env_ptr, db, db->pc_next +3);
|
||||
if (backdoor == 0x44) {
|
||||
struct libafl_backdoor_hook* hk = libafl_backdoor_hooks;
|
||||
while (hk) {
|
||||
TCGv tmp0 = tcg_const_tl(db->pc_next);
|
||||
TCGv_i64 tmp1 = tcg_const_i64(hk->data);
|
||||
#if TARGET_LONG_BITS == 32
|
||||
TCGTemp *tmp2[2] = { tcgv_i32_temp(tmp0), tcgv_i64_temp(tmp1) };
|
||||
#else
|
||||
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
|
||||
#endif
|
||||
tcg_gen_callN(hk->exec, NULL, 2, tmp2);
|
||||
#if TARGET_LONG_BITS == 32
|
||||
tcg_temp_free_i32(tmp0);
|
||||
#else
|
||||
tcg_temp_free_i64(tmp0);
|
||||
#endif
|
||||
tcg_temp_free_i64(tmp1);
|
||||
hk = hk->next;
|
||||
}
|
||||
|
||||
db->pc_next += 4;
|
||||
goto post_translate_insn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// --- End LibAFL code ---
|
||||
|
||||
/* Disassemble one instruction. The translate_insn hook should
|
||||
@ -209,25 +139,19 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
|
||||
ops->translate_insn(db, cpu);
|
||||
}
|
||||
|
||||
post_translate_insn:
|
||||
/*
|
||||
* We can't instrument after instructions that change control
|
||||
* flow although this only really affects post-load operations.
|
||||
*
|
||||
* Calling plugin_gen_insn_end() before we possibly stop translation
|
||||
* is important. Even if this ends up as dead code, plugin generation
|
||||
* needs to see a matching plugin_gen_insn_{start,end}() pair in order
|
||||
* to accurately track instrumented helpers that might access memory.
|
||||
*/
|
||||
if (plugin_enabled) {
|
||||
plugin_gen_insn_end();
|
||||
}
|
||||
|
||||
/* Stop translation if translate_insn so indicated. */
|
||||
if (db->is_jmp != DISAS_NEXT) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't instrument after instructions that change control
|
||||
* flow although this only really affects post-load operations.
|
||||
*/
|
||||
if (plugin_enabled) {
|
||||
plugin_gen_insn_end();
|
||||
}
|
||||
|
||||
/* Stop translation if the output buffer is full,
|
||||
or we have executed all of the allowed instructions. */
|
||||
if (tcg_op_buf_full() || db->num_insns >= db->max_insns) {
|
||||
@ -251,123 +175,11 @@ post_translate_insn:
|
||||
#ifdef DEBUG_DISAS
|
||||
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");
|
||||
ops->disas_log(db, cpu, logfile);
|
||||
fprintf(logfile, "\n");
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("----------------\n");
|
||||
ops->disas_log(db, cpu);
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *translator_access(CPUArchState *env, DisasContextBase *db,
|
||||
target_ulong pc, size_t len)
|
||||
{
|
||||
void *host;
|
||||
target_ulong base, end;
|
||||
TranslationBlock *tb;
|
||||
|
||||
tb = db->tb;
|
||||
|
||||
/* Use slow path if first page is MMIO. */
|
||||
if (unlikely(tb_page_addr0(tb) == -1)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 phys_page =
|
||||
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(phys_page == -1)) {
|
||||
tb_set_page_addr0(tb, -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tb_set_page_addr1(tb, phys_page);
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
page_protect(end);
|
||||
#endif
|
||||
host = db->host_addr[1];
|
||||
}
|
||||
|
||||
/* Use slow path when crossing pages. */
|
||||
if (is_same_page(db, pc)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
tcg_debug_assert(pc >= base);
|
||||
return host + (pc - base);
|
||||
}
|
||||
|
||||
uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
||||
{
|
||||
uint16_t ret, plug;
|
||||
void *p = translator_access(env, db, pc, sizeof(ret));
|
||||
|
||||
if (p) {
|
||||
plugin_insn_append(pc, p, sizeof(ret));
|
||||
return lduw_p(p);
|
||||
}
|
||||
ret = cpu_lduw_code(env, pc);
|
||||
plug = tswap16(ret);
|
||||
plugin_insn_append(pc, &plug, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
||||
{
|
||||
uint32_t ret, plug;
|
||||
void *p = translator_access(env, db, pc, sizeof(ret));
|
||||
|
||||
if (p) {
|
||||
plugin_insn_append(pc, p, sizeof(ret));
|
||||
return ldl_p(p);
|
||||
}
|
||||
ret = cpu_ldl_code(env, pc);
|
||||
plug = tswap32(ret);
|
||||
plugin_insn_append(pc, &plug, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
|
||||
{
|
||||
uint64_t ret, plug;
|
||||
void *p = translator_access(env, db, pc, sizeof(ret));
|
||||
|
||||
if (p) {
|
||||
plugin_insn_append(pc, p, sizeof(ret));
|
||||
return ldq_p(p);
|
||||
}
|
||||
ret = cpu_ldq_code(env, pc);
|
||||
plug = tswap64(ret);
|
||||
plugin_insn_append(pc, &plug, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -72,7 +72,7 @@ struct alsa_params_obt {
|
||||
snd_pcm_uframes_t samples;
|
||||
};
|
||||
|
||||
static void G_GNUC_PRINTF (2, 3) alsa_logerr (int err, const char *fmt, ...)
|
||||
static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@ -83,7 +83,7 @@ static void G_GNUC_PRINTF (2, 3) alsa_logerr (int err, const char *fmt, ...)
|
||||
AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
|
||||
}
|
||||
|
||||
static void G_GNUC_PRINTF (3, 4) alsa_logerr2 (
|
||||
static void GCC_FMT_ATTR (3, 4) alsa_logerr2 (
|
||||
int err,
|
||||
const char *typ,
|
||||
const char *fmt,
|
||||
@ -449,7 +449,7 @@ static int alsa_open(bool in, struct alsa_params_req *req,
|
||||
snd_pcm_hw_params_t *hw_params;
|
||||
int err;
|
||||
unsigned int freq, nchannels;
|
||||
const char *pcm_name = apdo->dev ?: "default";
|
||||
const char *pcm_name = apdo->has_dev ? apdo->dev : "default";
|
||||
snd_pcm_uframes_t obt_buffer_size;
|
||||
const char *typ = in ? "ADC" : "DAC";
|
||||
snd_pcm_format_t obtfmt;
|
||||
@ -602,42 +602,6 @@ static int alsa_open(bool in, struct alsa_params_req *req,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static size_t alsa_buffer_get_free(HWVoiceOut *hw)
|
||||
{
|
||||
ALSAVoiceOut *alsa = (ALSAVoiceOut *)hw;
|
||||
snd_pcm_sframes_t avail;
|
||||
size_t alsa_free, generic_free, generic_in_use;
|
||||
|
||||
avail = snd_pcm_avail_update(alsa->handle);
|
||||
if (avail < 0) {
|
||||
if (avail == -EPIPE) {
|
||||
if (!alsa_recover(alsa->handle)) {
|
||||
avail = snd_pcm_avail_update(alsa->handle);
|
||||
}
|
||||
}
|
||||
if (avail < 0) {
|
||||
alsa_logerr(avail,
|
||||
"Could not obtain number of available frames\n");
|
||||
avail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
alsa_free = avail * hw->info.bytes_per_frame;
|
||||
generic_free = audio_generic_buffer_get_free(hw);
|
||||
generic_in_use = hw->samples * hw->info.bytes_per_frame - generic_free;
|
||||
if (generic_in_use) {
|
||||
/*
|
||||
* This code can only be reached in the unlikely case that
|
||||
* snd_pcm_avail_update() returned a larger number of frames
|
||||
* than snd_pcm_writei() could write. Make sure that all
|
||||
* remaining bytes in the generic buffer can be written.
|
||||
*/
|
||||
alsa_free = alsa_free > generic_in_use ? alsa_free - generic_in_use : 0;
|
||||
}
|
||||
|
||||
return alsa_free;
|
||||
}
|
||||
|
||||
static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
|
||||
{
|
||||
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
|
||||
@ -952,7 +916,6 @@ static struct audio_pcm_ops alsa_pcm_ops = {
|
||||
.init_out = alsa_init_out,
|
||||
.fini_out = alsa_fini_out,
|
||||
.write = alsa_write,
|
||||
.buffer_get_free = alsa_buffer_get_free,
|
||||
.run_buffer_out = audio_generic_run_buffer_out,
|
||||
.enable_out = alsa_enable_out,
|
||||
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* HMP commands related to audio backends
|
||||
*
|
||||
* Copyright (c) 2003-2004 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "audio/audio.h"
|
||||
#include "monitor/hmp.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
|
||||
static QLIST_HEAD (capture_list_head, CaptureState) capture_head;
|
||||
|
||||
void hmp_info_capture(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int i;
|
||||
CaptureState *s;
|
||||
|
||||
for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
|
||||
monitor_printf(mon, "[%d]: ", i);
|
||||
s->ops.info (s->opaque);
|
||||
}
|
||||
}
|
||||
|
||||
void hmp_stopcapture(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int i;
|
||||
int n = qdict_get_int(qdict, "n");
|
||||
CaptureState *s;
|
||||
|
||||
for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) {
|
||||
if (i == n) {
|
||||
s->ops.destroy (s->opaque);
|
||||
QLIST_REMOVE (s, entries);
|
||||
g_free (s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hmp_wavcapture(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *path = qdict_get_str(qdict, "path");
|
||||
int freq = qdict_get_try_int(qdict, "freq", 44100);
|
||||
int bits = qdict_get_try_int(qdict, "bits", 16);
|
||||
int nchannels = qdict_get_try_int(qdict, "nchannels", 2);
|
||||
const char *audiodev = qdict_get_str(qdict, "audiodev");
|
||||
CaptureState *s;
|
||||
AudioState *as = audio_state_by_name(audiodev);
|
||||
|
||||
if (!as) {
|
||||
monitor_printf(mon, "Audiodev '%s' not found\n", audiodev);
|
||||
return;
|
||||
}
|
||||
|
||||
s = g_malloc0 (sizeof (*s));
|
||||
|
||||
if (wav_start_capture(as, s, path, freq, bits, nchannels)) {
|
||||
monitor_printf(mon, "Failed to add wave capture\n");
|
||||
g_free (s);
|
||||
return;
|
||||
}
|
||||
QLIST_INSERT_HEAD (&capture_head, s, entries);
|
||||
}
|
391
audio/audio.c
391
audio/audio.c
@ -28,14 +28,11 @@
|
||||
#include "monitor/monitor.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/clone-visitor.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/qapi-visit-audio.h"
|
||||
#include "qapi/qapi-commands-audio.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/help_option.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "ui/qemu-spice.h"
|
||||
@ -75,24 +72,20 @@ void audio_driver_register(audio_driver *drv)
|
||||
audio_driver *audio_driver_lookup(const char *name)
|
||||
{
|
||||
struct audio_driver *d;
|
||||
Error *local_err = NULL;
|
||||
int rv;
|
||||
|
||||
QLIST_FOREACH(d, &audio_drivers, next) {
|
||||
if (strcmp(name, d->name) == 0) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
rv = audio_module_load(name, &local_err);
|
||||
if (rv > 0) {
|
||||
QLIST_FOREACH(d, &audio_drivers, next) {
|
||||
if (strcmp(name, d->name) == 0) {
|
||||
return d;
|
||||
}
|
||||
|
||||
audio_module_load_one(name);
|
||||
QLIST_FOREACH(d, &audio_drivers, next) {
|
||||
if (strcmp(name, d->name) == 0) {
|
||||
return d;
|
||||
}
|
||||
} else if (rv < 0) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -124,6 +117,7 @@ int audio_bug (const char *funcname, int cond)
|
||||
AUD_log (NULL, "I am sorry\n");
|
||||
}
|
||||
AUD_log (NULL, "Context:\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
return cond;
|
||||
@ -554,45 +548,65 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
|
||||
return live;
|
||||
}
|
||||
|
||||
static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples)
|
||||
static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
|
||||
{
|
||||
size_t conv = 0;
|
||||
STSampleBuffer *conv_buf = hw->conv_buf;
|
||||
size_t clipped = 0;
|
||||
size_t pos = hw->mix_buf->pos;
|
||||
|
||||
while (samples) {
|
||||
uint8_t *src = advance(pcm_buf, conv * hw->info.bytes_per_frame);
|
||||
size_t proc = MIN(samples, conv_buf->size - conv_buf->pos);
|
||||
while (len) {
|
||||
st_sample *src = hw->mix_buf->samples + pos;
|
||||
uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
|
||||
size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
|
||||
size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
|
||||
|
||||
hw->conv(conv_buf->samples + conv_buf->pos, src, proc);
|
||||
conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
|
||||
samples -= proc;
|
||||
conv += proc;
|
||||
hw->clip(dst, src, samples_to_clip);
|
||||
|
||||
pos = (pos + samples_to_clip) % hw->mix_buf->size;
|
||||
len -= samples_to_clip;
|
||||
clipped += samples_to_clip;
|
||||
}
|
||||
|
||||
return conv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Soft voice (capture)
|
||||
*/
|
||||
static size_t audio_pcm_sw_get_rpos_in(SWVoiceIn *sw)
|
||||
{
|
||||
HWVoiceIn *hw = sw->hw;
|
||||
ssize_t live = hw->total_samples_captured - sw->total_hw_samples_acquired;
|
||||
ssize_t rpos;
|
||||
|
||||
if (audio_bug(__func__, live < 0 || live > hw->conv_buf->size)) {
|
||||
dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rpos = hw->conv_buf->pos - live;
|
||||
if (rpos >= 0) {
|
||||
return rpos;
|
||||
} else {
|
||||
return hw->conv_buf->size + rpos;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
|
||||
{
|
||||
HWVoiceIn *hw = sw->hw;
|
||||
size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
|
||||
struct st_sample *src, *dst = sw->buf;
|
||||
|
||||
rpos = audio_pcm_sw_get_rpos_in(sw) % hw->conv_buf->size;
|
||||
|
||||
live = hw->total_samples_captured - sw->total_hw_samples_acquired;
|
||||
if (!live) {
|
||||
return 0;
|
||||
}
|
||||
if (audio_bug(__func__, live > hw->conv_buf->size)) {
|
||||
dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rpos = audio_ring_posb(hw->conv_buf->pos, live, hw->conv_buf->size);
|
||||
|
||||
samples = size / sw->info.bytes_per_frame;
|
||||
if (!live) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
swlim = (live * sw->ratio) >> 32;
|
||||
swlim = MIN (swlim, samples);
|
||||
@ -618,7 +632,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
|
||||
total += isamp;
|
||||
}
|
||||
|
||||
if (!hw->pcm_ops->volume_in) {
|
||||
if (hw->pcm_ops && !hw->pcm_ops->volume_in) {
|
||||
mixeng_volume (sw->buf, ret, &sw->vol);
|
||||
}
|
||||
|
||||
@ -669,38 +683,12 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t audio_pcm_hw_get_free(HWVoiceOut *hw)
|
||||
{
|
||||
return (hw->pcm_ops->buffer_get_free ? hw->pcm_ops->buffer_get_free(hw) :
|
||||
INT_MAX) / hw->info.bytes_per_frame;
|
||||
}
|
||||
|
||||
static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
|
||||
{
|
||||
size_t clipped = 0;
|
||||
size_t pos = hw->mix_buf->pos;
|
||||
|
||||
while (len) {
|
||||
st_sample *src = hw->mix_buf->samples + pos;
|
||||
uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
|
||||
size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
|
||||
size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
|
||||
|
||||
hw->clip(dst, src, samples_to_clip);
|
||||
|
||||
pos = (pos + samples_to_clip) % hw->mix_buf->size;
|
||||
len -= samples_to_clip;
|
||||
clipped += samples_to_clip;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Soft voice (playback)
|
||||
*/
|
||||
static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
|
||||
{
|
||||
size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, blck;
|
||||
size_t hw_free;
|
||||
size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
|
||||
size_t ret = 0, pos = 0, total = 0;
|
||||
|
||||
if (!sw) {
|
||||
@ -723,28 +711,27 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
|
||||
}
|
||||
|
||||
wpos = (sw->hw->mix_buf->pos + live) % hwsamples;
|
||||
samples = size / sw->info.bytes_per_frame;
|
||||
|
||||
dead = hwsamples - live;
|
||||
hw_free = audio_pcm_hw_get_free(sw->hw);
|
||||
hw_free = hw_free > live ? hw_free - live : 0;
|
||||
samples = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
|
||||
samples = MIN(samples, size / sw->info.bytes_per_frame);
|
||||
if (samples) {
|
||||
sw->conv(sw->buf, buf, samples);
|
||||
swlim = ((int64_t) dead << 32) / sw->ratio;
|
||||
swlim = MIN (swlim, samples);
|
||||
if (swlim) {
|
||||
sw->conv (sw->buf, buf, swlim);
|
||||
|
||||
if (!sw->hw->pcm_ops->volume_out) {
|
||||
mixeng_volume(sw->buf, samples, &sw->vol);
|
||||
if (sw->hw->pcm_ops && !sw->hw->pcm_ops->volume_out) {
|
||||
mixeng_volume (sw->buf, swlim, &sw->vol);
|
||||
}
|
||||
}
|
||||
|
||||
while (samples) {
|
||||
while (swlim) {
|
||||
dead = hwsamples - live;
|
||||
left = hwsamples - wpos;
|
||||
blck = MIN (dead, left);
|
||||
if (!blck) {
|
||||
break;
|
||||
}
|
||||
isamp = samples;
|
||||
isamp = swlim;
|
||||
osamp = blck;
|
||||
st_rate_flow_mix (
|
||||
sw->rate,
|
||||
@ -754,7 +741,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
|
||||
&osamp
|
||||
);
|
||||
ret += isamp;
|
||||
samples -= isamp;
|
||||
swlim -= isamp;
|
||||
pos += isamp;
|
||||
live += osamp;
|
||||
wpos = (wpos + osamp) % hwsamples;
|
||||
@ -992,18 +979,6 @@ void AUD_set_active_in (SWVoiceIn *sw, int on)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* audio_frontend_frames_in() - returns the number of frames the resampling
|
||||
* code generates from frames_in frames
|
||||
*
|
||||
* @sw: audio recording frontend
|
||||
* @frames_in: number of frames
|
||||
*/
|
||||
static size_t audio_frontend_frames_in(SWVoiceIn *sw, size_t frames_in)
|
||||
{
|
||||
return (int64_t)frames_in * sw->ratio >> 32;
|
||||
}
|
||||
|
||||
static size_t audio_get_avail (SWVoiceIn *sw)
|
||||
{
|
||||
size_t live;
|
||||
@ -1020,24 +995,12 @@ static size_t audio_get_avail (SWVoiceIn *sw)
|
||||
}
|
||||
|
||||
ldebug (
|
||||
"%s: get_avail live %zu frontend frames %zu\n",
|
||||
"%s: get_avail live %zu ret %" PRId64 "\n",
|
||||
SW_NAME (sw),
|
||||
live, audio_frontend_frames_in(sw, live)
|
||||
live, (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame
|
||||
);
|
||||
|
||||
return live;
|
||||
}
|
||||
|
||||
/**
|
||||
* audio_frontend_frames_out() - returns the number of frames needed to
|
||||
* get frames_out frames after resampling
|
||||
*
|
||||
* @sw: audio playback frontend
|
||||
* @frames_out: number of frames
|
||||
*/
|
||||
static size_t audio_frontend_frames_out(SWVoiceOut *sw, size_t frames_out)
|
||||
{
|
||||
return ((int64_t)frames_out << 32) / sw->ratio;
|
||||
return (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame;
|
||||
}
|
||||
|
||||
static size_t audio_get_free(SWVoiceOut *sw)
|
||||
@ -1059,11 +1022,13 @@ static size_t audio_get_free(SWVoiceOut *sw)
|
||||
dead = sw->hw->mix_buf->size - live;
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
dolog("%s: get_free live %zu dead %zu frontend frames %zu\n",
|
||||
SW_NAME(sw), live, dead, audio_frontend_frames_out(sw, dead));
|
||||
dolog ("%s: get_free live %zu dead %zu ret %" PRId64 "\n",
|
||||
SW_NAME (sw),
|
||||
live, dead, (((int64_t) dead << 32) / sw->ratio) *
|
||||
sw->info.bytes_per_frame);
|
||||
#endif
|
||||
|
||||
return dead;
|
||||
return (((int64_t) dead << 32) / sw->ratio) * sw->info.bytes_per_frame;
|
||||
}
|
||||
|
||||
static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
|
||||
@ -1146,12 +1111,8 @@ static void audio_run_out (AudioState *s)
|
||||
HWVoiceOut *hw = NULL;
|
||||
SWVoiceOut *sw;
|
||||
|
||||
while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
|
||||
size_t played, live, prev_rpos;
|
||||
size_t hw_free = audio_pcm_hw_get_free(hw);
|
||||
int nb_live;
|
||||
|
||||
if (!audio_get_pdo_out(s->dev)->mixing_engine) {
|
||||
if (!audio_get_pdo_out(s->dev)->mixing_engine) {
|
||||
while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
|
||||
/* there is exactly 1 sw for each hw with no mixeng */
|
||||
sw = hw->sw_head.lh_first;
|
||||
|
||||
@ -1164,34 +1125,15 @@ static void audio_run_out (AudioState *s)
|
||||
}
|
||||
|
||||
if (sw->active) {
|
||||
sw->callback.fn(sw->callback.opaque,
|
||||
hw_free * sw->info.bytes_per_frame);
|
||||
}
|
||||
|
||||
if (hw->pcm_ops->run_buffer_out) {
|
||||
hw->pcm_ops->run_buffer_out(hw);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
|
||||
if (sw->active) {
|
||||
size_t sw_free = audio_get_free(sw);
|
||||
size_t free;
|
||||
|
||||
if (hw_free > sw->total_hw_samples_mixed) {
|
||||
free = audio_frontend_frames_out(sw,
|
||||
MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
|
||||
} else {
|
||||
free = 0;
|
||||
}
|
||||
if (free > 0) {
|
||||
sw->callback.fn(sw->callback.opaque,
|
||||
free * sw->info.bytes_per_frame);
|
||||
}
|
||||
sw->callback.fn(sw->callback.opaque, INT_MAX);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
|
||||
size_t played, live, prev_rpos, free;
|
||||
int nb_live;
|
||||
|
||||
live = audio_pcm_hw_get_live_out (hw, &nb_live);
|
||||
if (!nb_live) {
|
||||
@ -1221,6 +1163,14 @@ static void audio_run_out (AudioState *s)
|
||||
}
|
||||
|
||||
if (!live) {
|
||||
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
|
||||
if (sw->active) {
|
||||
free = audio_get_free (sw);
|
||||
if (free > 0) {
|
||||
sw->callback.fn (sw->callback.opaque, free);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hw->pcm_ops->run_buffer_out) {
|
||||
hw->pcm_ops->run_buffer_out(hw);
|
||||
}
|
||||
@ -1261,6 +1211,13 @@ static void audio_run_out (AudioState *s)
|
||||
if (!sw->total_hw_samples_mixed) {
|
||||
sw->empty = 1;
|
||||
}
|
||||
|
||||
if (sw->active) {
|
||||
free = audio_get_free (sw);
|
||||
if (free > 0) {
|
||||
sw->callback.fn (sw->callback.opaque, free);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1268,6 +1225,7 @@ static void audio_run_out (AudioState *s)
|
||||
static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
|
||||
{
|
||||
size_t conv = 0;
|
||||
STSampleBuffer *conv_buf = hw->conv_buf;
|
||||
|
||||
if (hw->pcm_ops->run_buffer_in) {
|
||||
hw->pcm_ops->run_buffer_in(hw);
|
||||
@ -1283,7 +1241,11 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
|
||||
break;
|
||||
}
|
||||
|
||||
proc = audio_pcm_hw_conv_in(hw, buf, size / hw->info.bytes_per_frame);
|
||||
proc = MIN(size / hw->info.bytes_per_frame,
|
||||
conv_buf->size - conv_buf->pos);
|
||||
|
||||
hw->conv(conv_buf->samples + conv_buf->pos, buf, proc);
|
||||
conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
|
||||
|
||||
samples -= proc;
|
||||
conv += proc;
|
||||
@ -1327,13 +1289,11 @@ static void audio_run_in (AudioState *s)
|
||||
sw->total_hw_samples_acquired -= min;
|
||||
|
||||
if (sw->active) {
|
||||
size_t sw_avail = audio_get_avail(sw);
|
||||
size_t avail;
|
||||
|
||||
avail = audio_frontend_frames_in(sw, sw_avail);
|
||||
avail = audio_get_avail (sw);
|
||||
if (avail > 0) {
|
||||
sw->callback.fn(sw->callback.opaque,
|
||||
avail * sw->info.bytes_per_frame);
|
||||
sw->callback.fn (sw->callback.opaque, avail);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1434,10 +1394,12 @@ void audio_generic_run_buffer_in(HWVoiceIn *hw)
|
||||
|
||||
void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size)
|
||||
{
|
||||
size_t start;
|
||||
ssize_t start = (ssize_t)hw->pos_emul - hw->pending_emul;
|
||||
|
||||
start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
|
||||
assert(start < hw->size_emul);
|
||||
if (start < 0) {
|
||||
start += hw->size_emul;
|
||||
}
|
||||
assert(start >= 0 && start < hw->size_emul);
|
||||
|
||||
*size = MIN(*size, hw->pending_emul);
|
||||
*size = MIN(*size, hw->size_emul - start);
|
||||
@ -1450,22 +1412,16 @@ void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
|
||||
hw->pending_emul -= size;
|
||||
}
|
||||
|
||||
size_t audio_generic_buffer_get_free(HWVoiceOut *hw)
|
||||
{
|
||||
if (hw->buf_emul) {
|
||||
return hw->size_emul - hw->pending_emul;
|
||||
} else {
|
||||
return hw->samples * hw->info.bytes_per_frame;
|
||||
}
|
||||
}
|
||||
|
||||
void audio_generic_run_buffer_out(HWVoiceOut *hw)
|
||||
{
|
||||
while (hw->pending_emul) {
|
||||
size_t write_len, written, start;
|
||||
size_t write_len, written;
|
||||
ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
|
||||
|
||||
start = audio_ring_posb(hw->pos_emul, hw->pending_emul, hw->size_emul);
|
||||
assert(start < hw->size_emul);
|
||||
if (start < 0) {
|
||||
start += hw->size_emul;
|
||||
}
|
||||
assert(start >= 0 && start < hw->size_emul);
|
||||
|
||||
write_len = MIN(hw->pending_emul, hw->size_emul - start);
|
||||
|
||||
@ -1506,12 +1462,6 @@ size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size)
|
||||
{
|
||||
size_t total = 0;
|
||||
|
||||
if (hw->pcm_ops->buffer_get_free) {
|
||||
size_t free = hw->pcm_ops->buffer_get_free(hw);
|
||||
|
||||
size = MIN(size, free);
|
||||
}
|
||||
|
||||
while (total < size) {
|
||||
size_t dst_size = size - total;
|
||||
size_t copy_size, proc;
|
||||
@ -1533,6 +1483,10 @@ size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
if (hw->pcm_ops->run_buffer_out) {
|
||||
hw->pcm_ops->run_buffer_out(hw);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
@ -1762,7 +1716,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
||||
audio_validate_opts(dev, &error_abort);
|
||||
}
|
||||
|
||||
s = g_new0(AudioState, 1);
|
||||
s = g_malloc0(sizeof(AudioState));
|
||||
s->dev = dev;
|
||||
|
||||
QLIST_INIT (&s->hw_head_out);
|
||||
@ -1772,19 +1726,20 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
||||
atexit(audio_cleanup);
|
||||
atexit_registered = true;
|
||||
}
|
||||
QTAILQ_INSERT_TAIL(&audio_states, s, list);
|
||||
|
||||
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
|
||||
|
||||
s->nb_hw_voices_out = audio_get_pdo_out(dev)->voices;
|
||||
s->nb_hw_voices_in = audio_get_pdo_in(dev)->voices;
|
||||
|
||||
if (s->nb_hw_voices_out < 1) {
|
||||
if (s->nb_hw_voices_out <= 0) {
|
||||
dolog ("Bogus number of playback voices %d, setting to 1\n",
|
||||
s->nb_hw_voices_out);
|
||||
s->nb_hw_voices_out = 1;
|
||||
}
|
||||
|
||||
if (s->nb_hw_voices_in < 0) {
|
||||
if (s->nb_hw_voices_in <= 0) {
|
||||
dolog ("Bogus number of capture voices %d, setting to 0\n",
|
||||
s->nb_hw_voices_in);
|
||||
s->nb_hw_voices_in = 0;
|
||||
@ -1797,10 +1752,6 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
||||
} else {
|
||||
dolog ("Unknown audio driver `%s'\n", drvname);
|
||||
}
|
||||
if (!done) {
|
||||
free_audio_state(s);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; audio_prio_list[i]; i++) {
|
||||
AudiodevListEntry *e = audiodev_find(&head, audio_prio_list[i]);
|
||||
@ -1838,7 +1789,6 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
||||
"(Audio can continue looping even after stopping the VM)\n");
|
||||
}
|
||||
|
||||
QTAILQ_INSERT_TAIL(&audio_states, s, list);
|
||||
QLIST_INIT (&s->card_head);
|
||||
vmstate_register (NULL, 0, &vmstate_audio, s);
|
||||
return s;
|
||||
@ -1871,7 +1821,6 @@ void AUD_remove_card (QEMUSoundCard *card)
|
||||
g_free (card->name);
|
||||
}
|
||||
|
||||
static struct audio_pcm_ops capture_pcm_ops;
|
||||
|
||||
CaptureVoiceOut *AUD_add_capture(
|
||||
AudioState *s,
|
||||
@ -1917,7 +1866,6 @@ CaptureVoiceOut *AUD_add_capture(
|
||||
|
||||
hw = &cap->hw;
|
||||
hw->s = s;
|
||||
hw->pcm_ops = &capture_pcm_ops;
|
||||
QLIST_INIT (&hw->sw_head);
|
||||
QLIST_INIT (&cap->cb_head);
|
||||
|
||||
@ -2037,47 +1985,27 @@ void audio_create_pdos(Audiodev *dev)
|
||||
switch (dev->driver) {
|
||||
#define CASE(DRIVER, driver, pdo_name) \
|
||||
case AUDIODEV_DRIVER_##DRIVER: \
|
||||
if (!dev->u.driver.in) { \
|
||||
if (!dev->u.driver.has_in) { \
|
||||
dev->u.driver.in = g_malloc0( \
|
||||
sizeof(Audiodev##pdo_name##PerDirectionOptions)); \
|
||||
dev->u.driver.has_in = true; \
|
||||
} \
|
||||
if (!dev->u.driver.out) { \
|
||||
if (!dev->u.driver.has_out) { \
|
||||
dev->u.driver.out = g_malloc0( \
|
||||
sizeof(Audiodev##pdo_name##PerDirectionOptions)); \
|
||||
dev->u.driver.has_out = true; \
|
||||
} \
|
||||
break
|
||||
|
||||
CASE(NONE, none, );
|
||||
#ifdef CONFIG_AUDIO_ALSA
|
||||
CASE(ALSA, alsa, Alsa);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_COREAUDIO
|
||||
CASE(COREAUDIO, coreaudio, Coreaudio);
|
||||
#endif
|
||||
#ifdef CONFIG_DBUS_DISPLAY
|
||||
CASE(DBUS, dbus, );
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_DSOUND
|
||||
CASE(DSOUND, dsound, );
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_JACK
|
||||
CASE(JACK, jack, Jack);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_OSS
|
||||
CASE(OSS, oss, Oss);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_PA
|
||||
CASE(PA, pa, Pa);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_SDL
|
||||
CASE(SDL, sdl, Sdl);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_SNDIO
|
||||
CASE(SNDIO, sndio, );
|
||||
#endif
|
||||
#ifdef CONFIG_SPICE
|
||||
CASE(SPICE, spice, );
|
||||
#endif
|
||||
CASE(WAV, wav, );
|
||||
|
||||
case AUDIODEV_DRIVER__MAX:
|
||||
@ -2149,57 +2077,29 @@ static void audio_validate_opts(Audiodev *dev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
void audio_help(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("Available audio drivers:\n");
|
||||
|
||||
for (i = 0; i < AUDIODEV_DRIVER__MAX; i++) {
|
||||
audio_driver *driver = audio_driver_lookup(AudiodevDriver_str(i));
|
||||
if (driver) {
|
||||
printf("%s\n", driver->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audio_parse_option(const char *opt)
|
||||
{
|
||||
AudiodevListEntry *e;
|
||||
Audiodev *dev = NULL;
|
||||
|
||||
if (is_help_option(opt)) {
|
||||
audio_help();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
|
||||
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
|
||||
visit_free(v);
|
||||
|
||||
audio_define(dev);
|
||||
}
|
||||
|
||||
void audio_define(Audiodev *dev)
|
||||
{
|
||||
AudiodevListEntry *e;
|
||||
|
||||
audio_validate_opts(dev, &error_fatal);
|
||||
|
||||
e = g_new0(AudiodevListEntry, 1);
|
||||
e = g_malloc0(sizeof(AudiodevListEntry));
|
||||
e->dev = dev;
|
||||
QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next);
|
||||
}
|
||||
|
||||
bool audio_init_audiodevs(void)
|
||||
void audio_init_audiodevs(void)
|
||||
{
|
||||
AudiodevListEntry *e;
|
||||
|
||||
QSIMPLEQ_FOREACH(e, &audiodevs, next) {
|
||||
if (!audio_init(e->dev, NULL)) {
|
||||
return false;
|
||||
}
|
||||
audio_init(e->dev, NULL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo)
|
||||
@ -2297,49 +2197,26 @@ void audio_rate_start(RateCtl *rate)
|
||||
rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
}
|
||||
|
||||
size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info)
|
||||
size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
|
||||
size_t bytes_avail)
|
||||
{
|
||||
int64_t now;
|
||||
int64_t ticks;
|
||||
int64_t bytes;
|
||||
int64_t frames;
|
||||
int64_t samples;
|
||||
size_t ret;
|
||||
|
||||
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ticks = now - rate->start_ticks;
|
||||
bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
|
||||
frames = (bytes - rate->bytes_sent) / info->bytes_per_frame;
|
||||
if (frames < 0 || frames > 65536) {
|
||||
AUD_log(NULL, "Resetting rate control (%" PRId64 " frames)\n", frames);
|
||||
samples = (bytes - rate->bytes_sent) / info->bytes_per_frame;
|
||||
if (samples < 0 || samples > 65536) {
|
||||
AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)\n", samples);
|
||||
audio_rate_start(rate);
|
||||
frames = 0;
|
||||
samples = 0;
|
||||
}
|
||||
|
||||
return frames * info->bytes_per_frame;
|
||||
}
|
||||
|
||||
void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used)
|
||||
{
|
||||
rate->bytes_sent += bytes_used;
|
||||
}
|
||||
|
||||
size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info,
|
||||
size_t bytes_avail)
|
||||
{
|
||||
size_t bytes;
|
||||
|
||||
bytes = audio_rate_peek_bytes(rate, info);
|
||||
bytes = MIN(bytes, bytes_avail);
|
||||
audio_rate_add_bytes(rate, bytes);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
AudiodevList *qmp_query_audiodevs(Error **errp)
|
||||
{
|
||||
AudiodevList *ret = NULL;
|
||||
AudiodevListEntry *e;
|
||||
QSIMPLEQ_FOREACH(e, &audiodevs, next) {
|
||||
QAPI_LIST_PREPEND(ret, QAPI_CLONE(Audiodev, e->dev));
|
||||
}
|
||||
ret = MIN(samples * info->bytes_per_frame, bytes_avail);
|
||||
rate->bytes_sent += ret;
|
||||
return ret;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
typedef void (*audio_callback_fn) (void *opaque, int avail);
|
||||
|
||||
#if HOST_BIG_ENDIAN
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
#define AUDIO_HOST_ENDIANNESS 1
|
||||
#else
|
||||
#define AUDIO_HOST_ENDIANNESS 0
|
||||
@ -91,8 +91,8 @@ typedef struct QEMUAudioTimeStamp {
|
||||
uint64_t old_ts;
|
||||
} QEMUAudioTimeStamp;
|
||||
|
||||
void AUD_vlog (const char *cap, const char *fmt, va_list ap) G_GNUC_PRINTF(2, 0);
|
||||
void AUD_log (const char *cap, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
|
||||
void AUD_vlog (const char *cap, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0);
|
||||
void AUD_log (const char *cap, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
||||
|
||||
void AUD_register_card (const char *name, QEMUSoundCard *card);
|
||||
void AUD_remove_card (QEMUSoundCard *card);
|
||||
@ -168,10 +168,8 @@ void audio_sample_to_uint64(const void *samples, int pos,
|
||||
void audio_sample_from_uint64(void *samples, int pos,
|
||||
uint64_t left, uint64_t right);
|
||||
|
||||
void audio_define(Audiodev *audio);
|
||||
void audio_parse_option(const char *opt);
|
||||
bool audio_init_audiodevs(void);
|
||||
void audio_help(void);
|
||||
void audio_init_audiodevs(void);
|
||||
void audio_legacy_help(void);
|
||||
|
||||
AudioState *audio_state_by_name(const char *name);
|
||||
|
@ -31,10 +31,6 @@
|
||||
#endif
|
||||
#include "mixeng.h"
|
||||
|
||||
#ifdef CONFIG_GIO
|
||||
#include <gio/gio.h>
|
||||
#endif
|
||||
|
||||
struct audio_pcm_ops;
|
||||
|
||||
struct audio_callback {
|
||||
@ -144,9 +140,6 @@ struct audio_driver {
|
||||
const char *descr;
|
||||
void *(*init) (Audiodev *);
|
||||
void (*fini) (void *);
|
||||
#ifdef CONFIG_GIO
|
||||
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager);
|
||||
#endif
|
||||
struct audio_pcm_ops *pcm_ops;
|
||||
int can_be_default;
|
||||
int max_voices_out;
|
||||
@ -161,14 +154,10 @@ struct audio_pcm_ops {
|
||||
void (*fini_out)(HWVoiceOut *hw);
|
||||
size_t (*write) (HWVoiceOut *hw, void *buf, size_t size);
|
||||
void (*run_buffer_out)(HWVoiceOut *hw);
|
||||
/*
|
||||
* Get the free output buffer size. This is an upper limit. The size
|
||||
* returned by function get_buffer_out may be smaller.
|
||||
*/
|
||||
size_t (*buffer_get_free)(HWVoiceOut *hw);
|
||||
/*
|
||||
* get a buffer that after later can be passed to put_buffer_out; optional
|
||||
* returns the buffer, and writes it's size to size (in bytes)
|
||||
* this is unrelated to the above buffer_size_out function
|
||||
*/
|
||||
void *(*get_buffer_out)(HWVoiceOut *hw, size_t *size);
|
||||
/*
|
||||
@ -194,7 +183,6 @@ void audio_generic_run_buffer_in(HWVoiceIn *hw);
|
||||
void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
|
||||
void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
|
||||
void audio_generic_run_buffer_out(HWVoiceOut *hw);
|
||||
size_t audio_generic_buffer_get_free(HWVoiceOut *hw);
|
||||
void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size);
|
||||
size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size);
|
||||
size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size);
|
||||
@ -263,9 +251,7 @@ typedef struct RateCtl {
|
||||
} RateCtl;
|
||||
|
||||
void audio_rate_start(RateCtl *rate);
|
||||
size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info);
|
||||
void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used);
|
||||
size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info,
|
||||
size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
|
||||
size_t bytes_avail);
|
||||
|
||||
static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len)
|
||||
@ -273,19 +259,6 @@ static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len)
|
||||
return (dst >= src) ? (dst - src) : (len - src + dst);
|
||||
}
|
||||
|
||||
/**
|
||||
* audio_ring_posb() - returns new position in ringbuffer in backward
|
||||
* direction at given distance
|
||||
*
|
||||
* @pos: current position in ringbuffer
|
||||
* @dist: distance in ringbuffer to walk in reverse direction
|
||||
* @len: size of ringbuffer
|
||||
*/
|
||||
static inline size_t audio_ring_posb(size_t pos, size_t dist, size_t len)
|
||||
{
|
||||
return pos >= dist ? pos - dist : len - dist + pos;
|
||||
}
|
||||
|
||||
#define dolog(fmt, ...) AUD_log(AUDIO_CAP, fmt, ## __VA_ARGS__)
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -62,12 +62,15 @@ static void get_int(const char *env, uint32_t *dst, bool *has_dst)
|
||||
}
|
||||
}
|
||||
|
||||
static void get_str(const char *env, char **dst)
|
||||
static void get_str(const char *env, char **dst, bool *has_dst)
|
||||
{
|
||||
const char *val = getenv(env);
|
||||
if (val) {
|
||||
g_free(*dst);
|
||||
if (*has_dst) {
|
||||
g_free(*dst);
|
||||
}
|
||||
*dst = g_strdup(val);
|
||||
*has_dst = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +93,6 @@ static void get_fmt(const char *env, AudioFormat *dst, bool *has_dst)
|
||||
}
|
||||
|
||||
|
||||
#if defined(CONFIG_AUDIO_ALSA) || defined(CONFIG_AUDIO_DSOUND)
|
||||
static void get_millis_to_usecs(const char *env, uint32_t *dst, bool *has_dst)
|
||||
{
|
||||
const char *val = getenv(env);
|
||||
@ -99,20 +101,15 @@ static void get_millis_to_usecs(const char *env, uint32_t *dst, bool *has_dst)
|
||||
*has_dst = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AUDIO_ALSA) || defined(CONFIG_AUDIO_COREAUDIO) || \
|
||||
defined(CONFIG_AUDIO_PA) || defined(CONFIG_AUDIO_SDL) || \
|
||||
defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS)
|
||||
static uint32_t frames_to_usecs(uint32_t frames,
|
||||
AudiodevPerDirectionOptions *pdo)
|
||||
{
|
||||
uint32_t freq = pdo->has_frequency ? pdo->frequency : 44100;
|
||||
return (frames * 1000000 + freq / 2) / freq;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_COREAUDIO
|
||||
|
||||
static void get_frames_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
|
||||
AudiodevPerDirectionOptions *pdo)
|
||||
{
|
||||
@ -122,19 +119,14 @@ static void get_frames_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
|
||||
*has_dst = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AUDIO_PA) || defined(CONFIG_AUDIO_SDL) || \
|
||||
defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS)
|
||||
static uint32_t samples_to_usecs(uint32_t samples,
|
||||
AudiodevPerDirectionOptions *pdo)
|
||||
{
|
||||
uint32_t channels = pdo->has_channels ? pdo->channels : 2;
|
||||
return frames_to_usecs(samples / channels, pdo);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AUDIO_PA) || defined(CONFIG_AUDIO_SDL)
|
||||
static void get_samples_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
|
||||
AudiodevPerDirectionOptions *pdo)
|
||||
{
|
||||
@ -144,9 +136,7 @@ static void get_samples_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
|
||||
*has_dst = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS)
|
||||
static uint32_t bytes_to_usecs(uint32_t bytes, AudiodevPerDirectionOptions *pdo)
|
||||
{
|
||||
AudioFormat fmt = pdo->has_format ? pdo->format : AUDIO_FORMAT_S16;
|
||||
@ -163,11 +153,8 @@ static void get_bytes_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
|
||||
*has_dst = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* backend specific functions */
|
||||
|
||||
#ifdef CONFIG_AUDIO_ALSA
|
||||
/* ALSA */
|
||||
static void handle_alsa_per_direction(
|
||||
AudiodevAlsaPerDirectionOptions *apdo, const char *prefix)
|
||||
@ -182,7 +169,7 @@ static void handle_alsa_per_direction(
|
||||
get_bool(buf, &apdo->try_poll, &apdo->has_try_poll);
|
||||
|
||||
strcpy(buf + len, "DEV");
|
||||
get_str(buf, &apdo->dev);
|
||||
get_str(buf, &apdo->dev, &apdo->has_dev);
|
||||
|
||||
strcpy(buf + len, "SIZE_IN_USEC");
|
||||
get_bool(buf, &size_in_usecs, &dummy);
|
||||
@ -213,9 +200,7 @@ static void handle_alsa(Audiodev *dev)
|
||||
get_millis_to_usecs("QEMU_ALSA_THRESHOLD",
|
||||
&aopt->threshold, &aopt->has_threshold);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_COREAUDIO
|
||||
/* coreaudio */
|
||||
static void handle_coreaudio(Audiodev *dev)
|
||||
{
|
||||
@ -228,9 +213,7 @@ static void handle_coreaudio(Audiodev *dev)
|
||||
&dev->u.coreaudio.out->buffer_count,
|
||||
&dev->u.coreaudio.out->has_buffer_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_DSOUND
|
||||
/* dsound */
|
||||
static void handle_dsound(Audiodev *dev)
|
||||
{
|
||||
@ -245,16 +228,14 @@ static void handle_dsound(Audiodev *dev)
|
||||
&dev->u.dsound.in->has_buffer_length,
|
||||
dev->u.dsound.in);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_OSS
|
||||
/* OSS */
|
||||
static void handle_oss_per_direction(
|
||||
AudiodevOssPerDirectionOptions *opdo, const char *try_poll_env,
|
||||
const char *dev_env)
|
||||
{
|
||||
get_bool(try_poll_env, &opdo->try_poll, &opdo->has_try_poll);
|
||||
get_str(dev_env, &opdo->dev);
|
||||
get_str(dev_env, &opdo->dev, &opdo->has_dev);
|
||||
|
||||
get_bytes_to_usecs("QEMU_OSS_FRAGSIZE",
|
||||
&opdo->buffer_length, &opdo->has_buffer_length,
|
||||
@ -275,14 +256,12 @@ static void handle_oss(Audiodev *dev)
|
||||
get_bool("QEMU_OSS_EXCLUSIVE", &oopt->exclusive, &oopt->has_exclusive);
|
||||
get_int("QEMU_OSS_POLICY", &oopt->dsp_policy, &oopt->has_dsp_policy);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_PA
|
||||
/* pulseaudio */
|
||||
static void handle_pa_per_direction(
|
||||
AudiodevPaPerDirectionOptions *ppdo, const char *env)
|
||||
{
|
||||
get_str(env, &ppdo->name);
|
||||
get_str(env, &ppdo->name, &ppdo->has_name);
|
||||
}
|
||||
|
||||
static void handle_pa(Audiodev *dev)
|
||||
@ -299,11 +278,9 @@ static void handle_pa(Audiodev *dev)
|
||||
&dev->u.pa.out->has_buffer_length,
|
||||
qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.out));
|
||||
|
||||
get_str("QEMU_PA_SERVER", &dev->u.pa.server);
|
||||
get_str("QEMU_PA_SERVER", &dev->u.pa.server, &dev->u.pa.has_server);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_SDL
|
||||
/* SDL */
|
||||
static void handle_sdl(Audiodev *dev)
|
||||
{
|
||||
@ -312,7 +289,6 @@ static void handle_sdl(Audiodev *dev)
|
||||
&dev->u.sdl.out->has_buffer_length,
|
||||
qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.out));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* wav */
|
||||
static void handle_wav(Audiodev *dev)
|
||||
@ -323,7 +299,7 @@ static void handle_wav(Audiodev *dev)
|
||||
&dev->u.wav.out->has_format);
|
||||
get_int("QEMU_WAV_DAC_FIXED_CHANNELS",
|
||||
&dev->u.wav.out->channels, &dev->u.wav.out->has_channels);
|
||||
get_str("QEMU_WAV_PATH", &dev->u.wav.path);
|
||||
get_str("QEMU_WAV_PATH", &dev->u.wav.path, &dev->u.wav.has_path);
|
||||
}
|
||||
|
||||
/* general */
|
||||
@ -352,8 +328,8 @@ static void handle_per_direction(
|
||||
|
||||
static AudiodevListEntry *legacy_opt(const char *drvname)
|
||||
{
|
||||
AudiodevListEntry *e = g_new0(AudiodevListEntry, 1);
|
||||
e->dev = g_new0(Audiodev, 1);
|
||||
AudiodevListEntry *e = g_malloc0(sizeof(AudiodevListEntry));
|
||||
e->dev = g_malloc0(sizeof(Audiodev));
|
||||
e->dev->id = g_strdup(drvname);
|
||||
e->dev->driver = qapi_enum_parse(
|
||||
&AudiodevDriver_lookup, drvname, -1, &error_abort);
|
||||
@ -372,41 +348,29 @@ static AudiodevListEntry *legacy_opt(const char *drvname)
|
||||
}
|
||||
|
||||
switch (e->dev->driver) {
|
||||
#ifdef CONFIG_AUDIO_ALSA
|
||||
case AUDIODEV_DRIVER_ALSA:
|
||||
handle_alsa(e->dev);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_COREAUDIO
|
||||
case AUDIODEV_DRIVER_COREAUDIO:
|
||||
handle_coreaudio(e->dev);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_DSOUND
|
||||
case AUDIODEV_DRIVER_DSOUND:
|
||||
handle_dsound(e->dev);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_OSS
|
||||
case AUDIODEV_DRIVER_OSS:
|
||||
handle_oss(e->dev);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_PA
|
||||
case AUDIODEV_DRIVER_PA:
|
||||
handle_pa(e->dev);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_SDL
|
||||
case AUDIODEV_DRIVER_SDL:
|
||||
handle_sdl(e->dev);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case AUDIODEV_DRIVER_WAV:
|
||||
handle_wav(e->dev);
|
||||
@ -544,7 +508,7 @@ static void lv_free(Visitor *v)
|
||||
|
||||
static Visitor *legacy_visitor_new(void)
|
||||
{
|
||||
LegacyPrintVisitor *lv = g_new0(LegacyPrintVisitor, 1);
|
||||
LegacyPrintVisitor *lv = g_malloc0(sizeof(LegacyPrintVisitor));
|
||||
|
||||
lv->visitor.start_struct = lv_start_struct;
|
||||
lv->visitor.end_struct = lv_end_struct;
|
||||
|
@ -110,11 +110,7 @@ static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DAC
|
||||
samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;
|
||||
#else
|
||||
samples = (int64_t)sw->HWBUF->size * sw->ratio >> 32;
|
||||
#endif
|
||||
|
||||
sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
|
||||
if (!sw->buf) {
|
||||
@ -326,47 +322,23 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
|
||||
switch (dev->driver) {
|
||||
case AUDIODEV_DRIVER_NONE:
|
||||
return dev->u.none.TYPE;
|
||||
#ifdef CONFIG_AUDIO_ALSA
|
||||
case AUDIODEV_DRIVER_ALSA:
|
||||
return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.TYPE);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_COREAUDIO
|
||||
case AUDIODEV_DRIVER_COREAUDIO:
|
||||
return qapi_AudiodevCoreaudioPerDirectionOptions_base(
|
||||
dev->u.coreaudio.TYPE);
|
||||
#endif
|
||||
#ifdef CONFIG_DBUS_DISPLAY
|
||||
case AUDIODEV_DRIVER_DBUS:
|
||||
return dev->u.dbus.TYPE;
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_DSOUND
|
||||
case AUDIODEV_DRIVER_DSOUND:
|
||||
return dev->u.dsound.TYPE;
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_JACK
|
||||
case AUDIODEV_DRIVER_JACK:
|
||||
return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.TYPE);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_OSS
|
||||
case AUDIODEV_DRIVER_OSS:
|
||||
return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_PA
|
||||
case AUDIODEV_DRIVER_PA:
|
||||
return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_SDL
|
||||
case AUDIODEV_DRIVER_SDL:
|
||||
return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.TYPE);
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_SNDIO
|
||||
case AUDIODEV_DRIVER_SNDIO:
|
||||
return dev->u.sndio.TYPE;
|
||||
#endif
|
||||
#ifdef CONFIG_SPICE
|
||||
case AUDIODEV_DRIVER_SPICE:
|
||||
return dev->u.spice.TYPE;
|
||||
#endif
|
||||
case AUDIODEV_DRIVER_WAV:
|
||||
return dev->u.wav.TYPE;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user