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
|
memory: 8G
|
||||||
env:
|
env:
|
||||||
CIRRUS_SHELL: powershell
|
CIRRUS_SHELL: powershell
|
||||||
MSYS: winsymlinks:native
|
MSYS: winsymlinks:nativestrict
|
||||||
MSYSTEM: MINGW64
|
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_FINGERPRINT: 0
|
||||||
MSYS2_PACKAGES: "
|
MSYS2_PACKAGES: "
|
||||||
diffutils git grep make pkg-config sed
|
diffutils git grep make pkg-config sed
|
||||||
@ -32,6 +32,7 @@ windows_msys2_task:
|
|||||||
mingw-w64-x86_64-libgcrypt
|
mingw-w64-x86_64-libgcrypt
|
||||||
mingw-w64-x86_64-libpng
|
mingw-w64-x86_64-libpng
|
||||||
mingw-w64-x86_64-libssh
|
mingw-w64-x86_64-libssh
|
||||||
|
mingw-w64-x86_64-libxml2
|
||||||
mingw-w64-x86_64-snappy
|
mingw-w64-x86_64-snappy
|
||||||
mingw-w64-x86_64-libusb
|
mingw-w64-x86_64-libusb
|
||||||
mingw-w64-x86_64-usbredir
|
mingw-w64-x86_64-usbredir
|
||||||
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1,4 +1,3 @@
|
|||||||
*.c.inc diff=c
|
*.c.inc diff=c
|
||||||
*.h.inc diff=c
|
*.h.inc diff=c
|
||||||
*.m diff=objc
|
|
||||||
*.py diff=python
|
*.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
|
/GNUmakefile
|
||||||
/build/
|
/build/
|
||||||
/.cache/
|
|
||||||
/.vscode/
|
|
||||||
*.pyc
|
*.pyc
|
||||||
.sdk
|
.sdk
|
||||||
.stgit-*
|
.stgit-*
|
||||||
.git-submodule-status
|
.git-submodule-status
|
||||||
.clang-format
|
|
||||||
.gdb_history
|
|
||||||
cscope.*
|
cscope.*
|
||||||
tags
|
tags
|
||||||
TAGS
|
TAGS
|
||||||
@ -21,4 +15,6 @@ GTAGS
|
|||||||
*.depend_raw
|
*.depend_raw
|
||||||
*.swp
|
*.swp
|
||||||
*.patch
|
*.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:
|
.native_build_job_template:
|
||||||
extends: .base_job_template
|
|
||||||
stage: build
|
stage: build
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||||
before_script:
|
before_script:
|
||||||
@ -11,10 +10,12 @@
|
|||||||
fi
|
fi
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- ../configure --enable-werror --disable-docs --enable-fdt=system
|
- if test -n "$TARGETS";
|
||||||
${LD_JOBS:+--meson=git} ${TARGETS:+--target-list="$TARGETS"}
|
then
|
||||||
$CONFIGURE_ARGS ||
|
../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=git} $CONFIGURE_ARGS --target-list="$TARGETS" ;
|
||||||
{ cat config.log meson-logs/meson-log.txt && exit 1; }
|
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";
|
- if test -n "$LD_JOBS";
|
||||||
then
|
then
|
||||||
../meson/meson.py configure . -Dbackend_max_links="$LD_JOBS" ;
|
../meson/meson.py configure . -Dbackend_max_links="$LD_JOBS" ;
|
||||||
@ -25,8 +26,7 @@
|
|||||||
make -j"$JOBS" $MAKE_CHECK_ARGS ;
|
make -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
.common_test_job_template:
|
.native_test_job_template:
|
||||||
extends: .base_job_template
|
|
||||||
stage: test
|
stage: test
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||||
script:
|
script:
|
||||||
@ -37,18 +37,8 @@
|
|||||||
# Avoid recompiling by hiding ninja with NINJA=":"
|
# Avoid recompiling by hiding ninja with NINJA=":"
|
||||||
- make NINJA=":" $MAKE_CHECK_ARGS
|
- make NINJA=":" $MAKE_CHECK_ARGS
|
||||||
|
|
||||||
.native_test_job_template:
|
.acceptance_test_job_template:
|
||||||
extends: .common_test_job_template
|
extends: .native_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
|
|
||||||
cache:
|
cache:
|
||||||
key: "${CI_JOB_NAME}-cache"
|
key: "${CI_JOB_NAME}-cache"
|
||||||
paths:
|
paths:
|
||||||
@ -77,5 +67,15 @@
|
|||||||
after_script:
|
after_script:
|
||||||
- cd build
|
- cd build
|
||||||
- du -chs ${CI_PROJECT_DIR}/avocado-cache
|
- du -chs ${CI_PROJECT_DIR}/avocado-cache
|
||||||
variables:
|
rules:
|
||||||
QEMU_JOB_AVOCADO: 1
|
# 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
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: alpine
|
IMAGE: alpine
|
||||||
MAKE_CHECK_ARGS: check-unit check-qtest
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-system-alpine:
|
acceptance-system-alpine:
|
||||||
extends: .avocado_test_job_template
|
extends: .acceptance_test_job_template
|
||||||
needs:
|
needs:
|
||||||
- job: build-system-alpine
|
- job: build-system-alpine
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: alpine
|
IMAGE: alpine
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-acceptance
|
||||||
|
|
||||||
build-system-ubuntu:
|
build-system-ubuntu:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -41,8 +41,8 @@ build-system-ubuntu:
|
|||||||
job: amd64-ubuntu2004-container
|
job: amd64-ubuntu2004-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: ubuntu2004
|
IMAGE: ubuntu2004
|
||||||
CONFIGURE_ARGS: --enable-docs
|
CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-slirp=system
|
||||||
TARGETS: alpha-softmmu cris-softmmu hppa-softmmu
|
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
|
||||||
microblazeel-softmmu mips64el-softmmu
|
microblazeel-softmmu mips64el-softmmu
|
||||||
MAKE_CHECK_ARGS: check-build
|
MAKE_CHECK_ARGS: check-build
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -59,14 +59,14 @@ check-system-ubuntu:
|
|||||||
IMAGE: ubuntu2004
|
IMAGE: ubuntu2004
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-system-ubuntu:
|
acceptance-system-ubuntu:
|
||||||
extends: .avocado_test_job_template
|
extends: .acceptance_test_job_template
|
||||||
needs:
|
needs:
|
||||||
- job: build-system-ubuntu
|
- job: build-system-ubuntu
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: ubuntu2004
|
IMAGE: ubuntu2004
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-acceptance
|
||||||
|
|
||||||
build-system-debian:
|
build-system-debian:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -74,7 +74,7 @@ build-system-debian:
|
|||||||
job: amd64-debian-container
|
job: amd64-debian-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian-amd64
|
IMAGE: debian-amd64
|
||||||
CONFIGURE_ARGS: --with-coroutine=sigaltstack
|
CONFIGURE_ARGS: --enable-fdt=system
|
||||||
TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
|
TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
|
||||||
riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
|
riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
|
||||||
MAKE_CHECK_ARGS: check-build
|
MAKE_CHECK_ARGS: check-build
|
||||||
@ -92,26 +92,14 @@ check-system-debian:
|
|||||||
IMAGE: debian-amd64
|
IMAGE: debian-amd64
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-system-debian:
|
acceptance-system-debian:
|
||||||
extends: .avocado_test_job_template
|
extends: .acceptance_test_job_template
|
||||||
needs:
|
needs:
|
||||||
- job: build-system-debian
|
- job: build-system-debian
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian-amd64
|
IMAGE: debian-amd64
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-acceptance
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
build-system-fedora:
|
build-system-fedora:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -120,6 +108,7 @@ build-system-fedora:
|
|||||||
variables:
|
variables:
|
||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
|
CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
|
||||||
|
--enable-fdt=system --enable-slirp=system --enable-capstone=system
|
||||||
TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu
|
TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu
|
||||||
xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
|
xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
|
||||||
MAKE_CHECK_ARGS: check-build
|
MAKE_CHECK_ARGS: check-build
|
||||||
@ -137,27 +126,14 @@ check-system-fedora:
|
|||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-system-fedora:
|
acceptance-system-fedora:
|
||||||
extends: .avocado_test_job_template
|
extends: .acceptance_test_job_template
|
||||||
needs:
|
needs:
|
||||||
- job: build-system-fedora
|
- job: build-system-fedora
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-acceptance
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
build-system-centos:
|
build-system-centos:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -165,8 +141,8 @@ build-system-centos:
|
|||||||
job: amd64-centos8-container
|
job: amd64-centos8-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: centos8
|
IMAGE: centos8
|
||||||
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
|
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system
|
||||||
--enable-modules --enable-trace-backends=dtrace --enable-docs
|
--enable-modules --enable-trace-backends=dtrace
|
||||||
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
|
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
|
||||||
x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu
|
x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu
|
||||||
MAKE_CHECK_ARGS: check-build
|
MAKE_CHECK_ARGS: check-build
|
||||||
@ -184,14 +160,14 @@ check-system-centos:
|
|||||||
IMAGE: centos8
|
IMAGE: centos8
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-system-centos:
|
acceptance-system-centos:
|
||||||
extends: .avocado_test_job_template
|
extends: .acceptance_test_job_template
|
||||||
needs:
|
needs:
|
||||||
- job: build-system-centos
|
- job: build-system-centos
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: centos8
|
IMAGE: centos8
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-acceptance
|
||||||
|
|
||||||
build-system-opensuse:
|
build-system-opensuse:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -199,6 +175,7 @@ build-system-opensuse:
|
|||||||
job: amd64-opensuse-leap-container
|
job: amd64-opensuse-leap-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: opensuse-leap
|
IMAGE: opensuse-leap
|
||||||
|
CONFIGURE_ARGS: --enable-fdt=system
|
||||||
TARGETS: s390x-softmmu x86_64-softmmu aarch64-softmmu
|
TARGETS: s390x-softmmu x86_64-softmmu aarch64-softmmu
|
||||||
MAKE_CHECK_ARGS: check-build
|
MAKE_CHECK_ARGS: check-build
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -215,16 +192,95 @@ check-system-opensuse:
|
|||||||
IMAGE: opensuse-leap
|
IMAGE: opensuse-leap
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-system-opensuse:
|
acceptance-system-opensuse:
|
||||||
extends: .avocado_test_job_template
|
extends: .acceptance_test_job_template
|
||||||
needs:
|
needs:
|
||||||
- job: build-system-opensuse
|
- job: build-system-opensuse
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: opensuse-leap
|
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
|
# This jobs explicitly disable TCG (--disable-tcg), KVM is detected by
|
||||||
# the configure script. The container doesn't contain Xen headers so
|
# the configure script. The container doesn't contain Xen headers so
|
||||||
# Xen accelerator is not detected / selected. As result it build the
|
# Xen accelerator is not detected / selected. As result it build the
|
||||||
@ -242,7 +298,6 @@ build-tcg-disabled:
|
|||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- ../configure --disable-tcg --audio-drv-list="" --with-coroutine=ucontext
|
- ../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; }
|
|| { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||||
- make -j"$JOBS"
|
- make -j"$JOBS"
|
||||||
- make check-unit
|
- make check-unit
|
||||||
@ -250,11 +305,11 @@ build-tcg-disabled:
|
|||||||
- cd tests/qemu-iotests/
|
- cd tests/qemu-iotests/
|
||||||
- ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
|
- ./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
|
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
|
- ./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
|
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
|
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 image-fleecing
|
260 261 262 263 264 270 272 273 277 279
|
||||||
|
|
||||||
build-user:
|
build-user:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -274,10 +329,14 @@ build-user-static:
|
|||||||
CONFIGURE_ARGS: --disable-tools --disable-system --static
|
CONFIGURE_ARGS: --disable-tools --disable-system --static
|
||||||
MAKE_CHECK_ARGS: check-tcg
|
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:
|
build-user-hexagon:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
needs:
|
needs:
|
||||||
job: hexagon-cross-container
|
job: hexagon-cross-container
|
||||||
|
optional: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian-hexagon-cross
|
IMAGE: debian-hexagon-cross
|
||||||
TARGETS: hexagon-linux-user
|
TARGETS: hexagon-linux-user
|
||||||
@ -314,14 +373,14 @@ clang-system:
|
|||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++
|
CONFIGURE_ARGS: --cc=clang --cxx=clang++
|
||||||
--extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined
|
--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
|
MAKE_CHECK_ARGS: check-qtest check-tcg
|
||||||
|
|
||||||
clang-user:
|
clang-user:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
needs:
|
needs:
|
||||||
job: amd64-debian-user-cross-container
|
job: amd64-debian-user-cross-container
|
||||||
timeout: 70m
|
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian-all-test-cross
|
IMAGE: debian-all-test-cross
|
||||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --disable-system
|
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
|
# On gitlab runners, default value sometimes end up calling 2 lds concurrently and
|
||||||
# triggers an Out-Of-Memory error
|
# triggers an Out-Of-Memory error
|
||||||
#
|
#
|
||||||
# Since slirp callbacks are used in QEMU Timers, we cannot use libslirp with
|
# Since slirp callbacks are used in QEMU Timers, slirp needs to be compiled together
|
||||||
# CFI builds, and thus have to disable it here.
|
# 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
|
# job
|
||||||
build-cfi-aarch64:
|
build-cfi-aarch64:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -347,18 +408,20 @@ build-cfi-aarch64:
|
|||||||
AR: llvm-ar
|
AR: llvm-ar
|
||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
|
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
|
TARGETS: aarch64-softmmu
|
||||||
MAKE_CHECK_ARGS: check-build
|
MAKE_CHECK_ARGS: check-build
|
||||||
# FIXME: This job is often failing, likely due to out-of-memory problems in
|
timeout: 70m
|
||||||
# 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
|
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 2 days
|
expire_in: 2 days
|
||||||
paths:
|
paths:
|
||||||
- build
|
- 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:
|
check-cfi-aarch64:
|
||||||
extends: .native_test_job_template
|
extends: .native_test_job_template
|
||||||
@ -369,14 +432,14 @@ check-cfi-aarch64:
|
|||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-cfi-aarch64:
|
acceptance-cfi-aarch64:
|
||||||
extends: .avocado_test_job_template
|
extends: .acceptance_test_job_template
|
||||||
needs:
|
needs:
|
||||||
- job: build-cfi-aarch64
|
- job: build-cfi-aarch64
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-acceptance
|
||||||
|
|
||||||
build-cfi-ppc64-s390x:
|
build-cfi-ppc64-s390x:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -387,18 +450,20 @@ build-cfi-ppc64-s390x:
|
|||||||
AR: llvm-ar
|
AR: llvm-ar
|
||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
|
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
|
TARGETS: ppc64-softmmu s390x-softmmu
|
||||||
MAKE_CHECK_ARGS: check-build
|
MAKE_CHECK_ARGS: check-build
|
||||||
# FIXME: This job is often failing, likely due to out-of-memory problems in
|
timeout: 70m
|
||||||
# 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
|
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 2 days
|
expire_in: 2 days
|
||||||
paths:
|
paths:
|
||||||
- build
|
- 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:
|
check-cfi-ppc64-s390x:
|
||||||
extends: .native_test_job_template
|
extends: .native_test_job_template
|
||||||
@ -409,14 +474,14 @@ check-cfi-ppc64-s390x:
|
|||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-cfi-ppc64-s390x:
|
acceptance-cfi-ppc64-s390x:
|
||||||
extends: .avocado_test_job_template
|
extends: .acceptance_test_job_template
|
||||||
needs:
|
needs:
|
||||||
- job: build-cfi-ppc64-s390x
|
- job: build-cfi-ppc64-s390x
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-acceptance
|
||||||
|
|
||||||
build-cfi-x86_64:
|
build-cfi-x86_64:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -427,7 +492,7 @@ build-cfi-x86_64:
|
|||||||
AR: llvm-ar
|
AR: llvm-ar
|
||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
|
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
|
TARGETS: x86_64-softmmu
|
||||||
MAKE_CHECK_ARGS: check-build
|
MAKE_CHECK_ARGS: check-build
|
||||||
timeout: 70m
|
timeout: 70m
|
||||||
@ -445,14 +510,14 @@ check-cfi-x86_64:
|
|||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
MAKE_CHECK_ARGS: check
|
MAKE_CHECK_ARGS: check
|
||||||
|
|
||||||
avocado-cfi-x86_64:
|
acceptance-cfi-x86_64:
|
||||||
extends: .avocado_test_job_template
|
extends: .acceptance_test_job_template
|
||||||
needs:
|
needs:
|
||||||
- job: build-cfi-x86_64
|
- job: build-cfi-x86_64
|
||||||
artifacts: true
|
artifacts: true
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
MAKE_CHECK_ARGS: check-avocado
|
MAKE_CHECK_ARGS: check-acceptance
|
||||||
|
|
||||||
tsan-build:
|
tsan-build:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -461,33 +526,61 @@ tsan-build:
|
|||||||
variables:
|
variables:
|
||||||
IMAGE: ubuntu2004
|
IMAGE: ubuntu2004
|
||||||
CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10
|
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
|
TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
|
||||||
MAKE_CHECK_ARGS: bench V=1
|
MAKE_CHECK_ARGS: bench V=1
|
||||||
|
|
||||||
# gcov is a GCC features
|
# These targets are on the way out
|
||||||
gcov:
|
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
|
extends: .native_build_job_template
|
||||||
needs:
|
needs:
|
||||||
job: amd64-ubuntu2004-container
|
job: amd64-ubuntu2004-container
|
||||||
timeout: 80m
|
|
||||||
variables:
|
variables:
|
||||||
IMAGE: ubuntu2004
|
IMAGE: ubuntu2004
|
||||||
CONFIGURE_ARGS: --enable-gcov
|
CONFIGURE_ARGS: --enable-gprof --enable-gcov
|
||||||
TARGETS: aarch64-softmmu ppc64-softmmu s390x-softmmu x86_64-softmmu
|
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
|
MAKE_CHECK_ARGS: check
|
||||||
after_script:
|
after_script:
|
||||||
- cd build
|
- ${CI_PROJECT_DIR}/scripts/ci/coverage-summary.sh
|
||||||
- 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
|
|
||||||
|
|
||||||
build-oss-fuzz:
|
build-oss-fuzz:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -497,7 +590,6 @@ build-oss-fuzz:
|
|||||||
IMAGE: fedora
|
IMAGE: fedora
|
||||||
script:
|
script:
|
||||||
- mkdir build-oss-fuzz
|
- mkdir build-oss-fuzz
|
||||||
- export LSAN_OPTIONS=suppressions=scripts/oss-fuzz/lsan_suppressions.txt
|
|
||||||
- CC="clang" CXX="clang++" CFLAGS="-fsanitize=address"
|
- CC="clang" CXX="clang++" CFLAGS="-fsanitize=address"
|
||||||
./scripts/oss-fuzz/build.sh
|
./scripts/oss-fuzz/build.sh
|
||||||
- export ASAN_OPTIONS="fast_unwind_on_malloc=0"
|
- export ASAN_OPTIONS="fast_unwind_on_malloc=0"
|
||||||
@ -507,6 +599,8 @@ build-oss-fuzz:
|
|||||||
echo Testing ${fuzzer} ... ;
|
echo Testing ${fuzzer} ... ;
|
||||||
"${fuzzer}" -runs=1 -seed=1 || exit 1 ;
|
"${fuzzer}" -runs=1 -seed=1 || exit 1 ;
|
||||||
done
|
done
|
||||||
|
# Unrelated to fuzzer: run some tests with -fsanitize=address
|
||||||
|
- cd build-oss-fuzz && make check-qtest-i386 check-unit
|
||||||
|
|
||||||
build-tci:
|
build-tci:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
@ -518,9 +612,8 @@ build-tci:
|
|||||||
- TARGETS="aarch64 alpha arm hppa m68k microblaze ppc64 s390x x86_64"
|
- TARGETS="aarch64 alpha arm hppa m68k microblaze ppc64 s390x x86_64"
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- ../configure --enable-tcg-interpreter --disable-docs --disable-gtk --disable-vnc
|
- ../configure --enable-tcg-interpreter
|
||||||
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
|
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)" || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||||
|| { cat config.log meson-logs/meson-log.txt && exit 1; }
|
|
||||||
- make -j"$JOBS"
|
- make -j"$JOBS"
|
||||||
- make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test
|
- make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test
|
||||||
- for tg in $TARGETS ; do
|
- for tg in $TARGETS ; do
|
||||||
@ -532,30 +625,44 @@ build-tci:
|
|||||||
- QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow
|
- QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow
|
||||||
- make check-tcg
|
- 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
|
# Check our reduced build configurations
|
||||||
build-without-defaults:
|
build-without-default-devices:
|
||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
needs:
|
needs:
|
||||||
job: amd64-centos8-container
|
job: amd64-centos8-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: centos8
|
IMAGE: centos8
|
||||||
CONFIGURE_ARGS:
|
CONFIGURE_ARGS: --without-default-devices --disable-user
|
||||||
--without-default-devices
|
|
||||||
--without-default-features
|
build-without-default-features:
|
||||||
--disable-fdt
|
extends: .native_build_job_template
|
||||||
--disable-pie
|
needs:
|
||||||
--disable-qom-cast-debug
|
job: amd64-debian-container
|
||||||
--disable-strip
|
variables:
|
||||||
TARGETS: avr-softmmu mips64-softmmu s390x-softmmu sh4-softmmu
|
IMAGE: debian-amd64
|
||||||
sparc64-softmmu hexagon-linux-user i386-linux-user s390x-linux-user
|
CONFIGURE_ARGS: --without-default-features --disable-user
|
||||||
MAKE_CHECK_ARGS: check-unit check-qtest-avr check-qtest-mips64
|
--target-list-exclude=arm-softmmu,i386-softmmu,mipsel-softmmu,mips64-softmmu,ppc-softmmu
|
||||||
|
MAKE_CHECK_ARGS: check-unit
|
||||||
|
|
||||||
build-libvhost-user:
|
build-libvhost-user:
|
||||||
extends: .base_job_template
|
|
||||||
stage: build
|
stage: build
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/fedora:latest
|
image: $CI_REGISTRY_IMAGE/qemu/fedora:latest
|
||||||
needs:
|
needs:
|
||||||
job: amd64-fedora-container
|
job: amd64-fedora-container
|
||||||
|
before_script:
|
||||||
|
- dnf install -y meson ninja-build
|
||||||
script:
|
script:
|
||||||
- mkdir subprojects/libvhost-user/build
|
- mkdir subprojects/libvhost-user/build
|
||||||
- cd subprojects/libvhost-user/build
|
- cd subprojects/libvhost-user/build
|
||||||
@ -568,13 +675,10 @@ build-tools-and-docs-debian:
|
|||||||
extends: .native_build_job_template
|
extends: .native_build_job_template
|
||||||
needs:
|
needs:
|
||||||
job: amd64-debian-container
|
job: amd64-debian-container
|
||||||
# when running on 'master' we use pre-existing container
|
|
||||||
optional: true
|
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian-amd64
|
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
|
CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
|
||||||
QEMU_JOB_PUBLISH: 1
|
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 2 days
|
expire_in: 2 days
|
||||||
paths:
|
paths:
|
||||||
@ -594,7 +698,6 @@ build-tools-and-docs-debian:
|
|||||||
# that users can see the results of their commits, regardless
|
# that users can see the results of their commits, regardless
|
||||||
# of what topic branch they're currently using
|
# of what topic branch they're currently using
|
||||||
pages:
|
pages:
|
||||||
extends: .base_job_template
|
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:latest
|
image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:latest
|
||||||
stage: test
|
stage: test
|
||||||
needs:
|
needs:
|
||||||
@ -612,5 +715,10 @@ pages:
|
|||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- public
|
- public
|
||||||
variables:
|
rules:
|
||||||
QEMU_JOB_PUBLISH: 1
|
- 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
|
# special care, because we can't just override it at the GitLab CI job
|
||||||
# definition level or we risk breaking it completely.
|
# definition level or we risk breaking it completely.
|
||||||
.cirrus_build_job:
|
.cirrus_build_job:
|
||||||
extends: .base_job_template
|
|
||||||
stage: build
|
stage: build
|
||||||
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
image: registry.gitlab.com/libvirt/libvirt-ci/cirrus-run:master
|
||||||
needs: []
|
needs: []
|
||||||
timeout: 80m
|
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
script:
|
script:
|
||||||
- source .gitlab-ci.d/cirrus/$NAME.vars
|
- source .gitlab-ci.d/cirrus/$NAME.vars
|
||||||
@ -37,12 +35,12 @@
|
|||||||
-e "s|[@]PIP3@|$PIP3|g"
|
-e "s|[@]PIP3@|$PIP3|g"
|
||||||
-e "s|[@]PYPI_PKGS@|$PYPI_PKGS|g"
|
-e "s|[@]PYPI_PKGS@|$PYPI_PKGS|g"
|
||||||
-e "s|[@]CONFIGURE_ARGS@|$CONFIGURE_ARGS|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
|
<.gitlab-ci.d/cirrus/build.yml >.gitlab-ci.d/cirrus/$NAME.yml
|
||||||
- cat .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
|
- cirrus-run -v --show-build-log always .gitlab-ci.d/cirrus/$NAME.yml
|
||||||
variables:
|
rules:
|
||||||
QEMU_JOB_CIRRUS: 1
|
- if: "$CIRRUS_GITHUB_REPO && $CIRRUS_API_TOKEN"
|
||||||
|
|
||||||
x64-freebsd-12-build:
|
x64-freebsd-12-build:
|
||||||
extends: .cirrus_build_job
|
extends: .cirrus_build_job
|
||||||
@ -50,11 +48,14 @@ x64-freebsd-12-build:
|
|||||||
NAME: freebsd-12
|
NAME: freebsd-12
|
||||||
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
||||||
CIRRUS_VM_IMAGE_SELECTOR: image_family
|
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_CPUS: 8
|
||||||
CIRRUS_VM_RAM: 8G
|
CIRRUS_VM_RAM: 8G
|
||||||
UPDATE_COMMAND: pkg update; pkg upgrade -y
|
UPDATE_COMMAND: pkg update
|
||||||
INSTALL_COMMAND: pkg install -y
|
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
|
TEST_TARGETS: check
|
||||||
|
|
||||||
x64-freebsd-13-build:
|
x64-freebsd-13-build:
|
||||||
@ -63,61 +64,24 @@ x64-freebsd-13-build:
|
|||||||
NAME: freebsd-13
|
NAME: freebsd-13
|
||||||
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
CIRRUS_VM_INSTANCE_TYPE: freebsd_instance
|
||||||
CIRRUS_VM_IMAGE_SELECTOR: image_family
|
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_CPUS: 8
|
||||||
CIRRUS_VM_RAM: 8G
|
CIRRUS_VM_RAM: 8G
|
||||||
UPDATE_COMMAND: pkg update; pkg upgrade -y
|
UPDATE_COMMAND: pkg update
|
||||||
INSTALL_COMMAND: pkg install -y
|
INSTALL_COMMAND: pkg install -y
|
||||||
TEST_TARGETS: check
|
TEST_TARGETS: check
|
||||||
|
|
||||||
aarch64-macos-12-base-build:
|
x64-macos-11-base-build:
|
||||||
extends: .cirrus_build_job
|
extends: .cirrus_build_job
|
||||||
variables:
|
variables:
|
||||||
NAME: macos-12
|
NAME: macos-11
|
||||||
CIRRUS_VM_INSTANCE_TYPE: macos_instance
|
CIRRUS_VM_INSTANCE_TYPE: osx_instance
|
||||||
CIRRUS_VM_IMAGE_SELECTOR: image
|
CIRRUS_VM_IMAGE_SELECTOR: image
|
||||||
CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-monterey-base:latest
|
CIRRUS_VM_IMAGE_NAME: big-sur-base
|
||||||
CIRRUS_VM_CPUS: 12
|
CIRRUS_VM_CPUS: 12
|
||||||
CIRRUS_VM_RAM: 24G
|
CIRRUS_VM_RAM: 24G
|
||||||
UPDATE_COMMAND: brew update
|
UPDATE_COMMAND: brew update
|
||||||
INSTALL_COMMAND: brew install
|
INSTALL_COMMAND: brew install
|
||||||
PATH_EXTRA: /opt/homebrew/ccache/libexec:/opt/homebrew/gettext/bin
|
PATH_EXTRA: /usr/local/opt/ccache/libexec:/usr/local/opt/gettext/bin
|
||||||
PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig
|
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
|
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@"
|
PYTHON: "@PYTHON@"
|
||||||
MAKE: "@MAKE@"
|
MAKE: "@MAKE@"
|
||||||
CONFIGURE_ARGS: "@CONFIGURE_ARGS@"
|
CONFIGURE_ARGS: "@CONFIGURE_ARGS@"
|
||||||
TEST_TARGETS: "@TEST_TARGETS@"
|
|
||||||
|
|
||||||
build_task:
|
build_task:
|
||||||
install_script:
|
install_script:
|
||||||
@ -32,6 +31,5 @@ build_task:
|
|||||||
- $MAKE -j$(sysctl -n hw.ncpu)
|
- $MAKE -j$(sysctl -n hw.ncpu)
|
||||||
- for TARGET in $TEST_TARGETS ;
|
- for TARGET in $TEST_TARGETS ;
|
||||||
do
|
do
|
||||||
$MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1
|
$MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1 ;
|
||||||
|| { cat meson-logs/testlog.txt; exit 1; } ;
|
|
||||||
done
|
done
|
||||||
|
@ -2,15 +2,12 @@
|
|||||||
#
|
#
|
||||||
# $ lcitool variables freebsd-12 qemu
|
# $ 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'
|
CCACHE='/usr/local/bin/ccache'
|
||||||
CPAN_PKGS=''
|
|
||||||
CROSS_PKGS=''
|
|
||||||
MAKE='/usr/local/bin/gmake'
|
MAKE='/usr/local/bin/gmake'
|
||||||
NINJA='/usr/local/bin/ninja'
|
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'
|
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
|
# $ 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'
|
CCACHE='/usr/local/bin/ccache'
|
||||||
CPAN_PKGS=''
|
|
||||||
CROSS_PKGS=''
|
|
||||||
MAKE='/usr/local/bin/gmake'
|
MAKE='/usr/local/bin/gmake'
|
||||||
NINJA='/usr/local/bin/ninja'
|
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'
|
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
|
extends: .container_job_template
|
||||||
variables:
|
variables:
|
||||||
NAME: fedora
|
NAME: fedora
|
||||||
|
|
||||||
|
amd64-debian10-container:
|
||||||
|
extends: .container_job_template
|
||||||
|
variables:
|
||||||
|
NAME: debian10
|
||||||
|
@ -1,129 +1,168 @@
|
|||||||
alpha-debian-cross-container:
|
alpha-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-alpha-cross
|
NAME: debian-alpha-cross
|
||||||
|
|
||||||
amd64-debian-cross-container:
|
amd64-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-amd64-cross
|
NAME: debian-amd64-cross
|
||||||
|
|
||||||
amd64-debian-user-cross-container:
|
amd64-debian-user-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-all-test-cross
|
NAME: debian-all-test-cross
|
||||||
|
|
||||||
arm64-debian-cross-container:
|
arm64-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-arm64-cross
|
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:
|
armel-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-armel-cross
|
NAME: debian-armel-cross
|
||||||
|
|
||||||
armhf-debian-cross-container:
|
armhf-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-armhf-cross
|
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:
|
hexagon-cross-container:
|
||||||
extends: .container_job_template
|
image: docker:stable
|
||||||
stage: containers
|
stage: containers
|
||||||
|
rules:
|
||||||
|
- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
|
||||||
|
when: never
|
||||||
|
- when: always
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-hexagon-cross
|
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:
|
hppa-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-hppa-cross
|
NAME: debian-hppa-cross
|
||||||
|
|
||||||
m68k-debian-cross-container:
|
m68k-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-m68k-cross
|
NAME: debian-m68k-cross
|
||||||
|
|
||||||
mips64-debian-cross-container:
|
mips64-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-mips64-cross
|
NAME: debian-mips64-cross
|
||||||
|
|
||||||
mips64el-debian-cross-container:
|
mips64el-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-mips64el-cross
|
NAME: debian-mips64el-cross
|
||||||
|
|
||||||
mips-debian-cross-container:
|
mips-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-mips-cross
|
NAME: debian-mips-cross
|
||||||
|
|
||||||
mipsel-debian-cross-container:
|
mipsel-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-mipsel-cross
|
NAME: debian-mipsel-cross
|
||||||
|
|
||||||
powerpc-test-cross-container:
|
powerpc-test-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian11-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-powerpc-test-cross
|
NAME: debian-powerpc-test-cross
|
||||||
|
|
||||||
ppc64el-debian-cross-container:
|
ppc64el-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-ppc64el-cross
|
NAME: debian-ppc64el-cross
|
||||||
|
|
||||||
riscv64-debian-cross-container:
|
riscv64-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
# as we are currently based on 'sid/unstable' we may break so...
|
needs: ['amd64-debian10-container']
|
||||||
allow_failure: true
|
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-riscv64-cross
|
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:
|
s390x-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-s390x-cross
|
NAME: debian-s390x-cross
|
||||||
|
|
||||||
sh4-debian-cross-container:
|
sh4-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-sh4-cross
|
NAME: debian-sh4-cross
|
||||||
|
|
||||||
sparc64-debian-cross-container:
|
sparc64-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-sparc64-cross
|
NAME: debian-sparc64-cross
|
||||||
|
|
||||||
tricore-debian-cross-container:
|
tricore-debian-cross-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-tricore-cross
|
NAME: debian-tricore-cross
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
.container_job_template:
|
.container_job_template:
|
||||||
extends: .base_job_template
|
|
||||||
image: docker:stable
|
image: docker:stable
|
||||||
stage: containers
|
stage: containers
|
||||||
services:
|
services:
|
||||||
|
@ -7,17 +7,33 @@ amd64-alpine-container:
|
|||||||
variables:
|
variables:
|
||||||
NAME: alpine
|
NAME: alpine
|
||||||
|
|
||||||
|
amd64-debian11-container:
|
||||||
|
extends: .container_job_template
|
||||||
|
variables:
|
||||||
|
NAME: debian11
|
||||||
|
|
||||||
amd64-debian-container:
|
amd64-debian-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
stage: containers
|
stage: containers-layer2
|
||||||
|
needs: ['amd64-debian10-container']
|
||||||
variables:
|
variables:
|
||||||
NAME: debian-amd64
|
NAME: debian-amd64
|
||||||
|
|
||||||
|
amd64-ubuntu1804-container:
|
||||||
|
extends: .container_job_template
|
||||||
|
variables:
|
||||||
|
NAME: ubuntu1804
|
||||||
|
|
||||||
amd64-ubuntu2004-container:
|
amd64-ubuntu2004-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
variables:
|
variables:
|
||||||
NAME: ubuntu2004
|
NAME: ubuntu2004
|
||||||
|
|
||||||
|
amd64-ubuntu-container:
|
||||||
|
extends: .container_job_template
|
||||||
|
variables:
|
||||||
|
NAME: ubuntu
|
||||||
|
|
||||||
amd64-opensuse-leap-container:
|
amd64-opensuse-leap-container:
|
||||||
extends: .container_job_template
|
extends: .container_job_template
|
||||||
variables:
|
variables:
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
.cross_system_build_job:
|
.cross_system_build_job:
|
||||||
extends: .base_job_template
|
|
||||||
stage: build
|
stage: build
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||||
timeout: 80m
|
timeout: 80m
|
||||||
script:
|
script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- ../configure --enable-werror --disable-docs --enable-fdt=system
|
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||||
--disable-user $QEMU_CONFIGURE_OPTS $EXTRA_CONFIGURE_OPTS
|
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||||
--target-list-exclude="arm-softmmu cris-softmmu
|
--disable-user --target-list-exclude="arm-softmmu cris-softmmu
|
||||||
i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu
|
i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu
|
||||||
mips64-softmmu ppc-softmmu riscv32-softmmu sh4-softmmu
|
mips64-softmmu ppc-softmmu riscv32-softmmu sh4-softmmu
|
||||||
sparc-softmmu xtensa-softmmu $CROSS_SKIP_TARGETS"
|
sparc-softmmu xtensa-softmmu $CROSS_SKIP_TARGETS"
|
||||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||||
- if grep -q "EXESUF=.exe" config-host.mak;
|
- if grep -q "EXESUF=.exe" config-host.mak;
|
||||||
then make installer;
|
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;
|
mv -v qemu-setup*.exe qemu-setup-${version}.exe;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -25,27 +24,24 @@
|
|||||||
# KVM), and set extra options (such disabling other accelerators) via the
|
# KVM), and set extra options (such disabling other accelerators) via the
|
||||||
# $EXTRA_CONFIGURE_OPTS variable.
|
# $EXTRA_CONFIGURE_OPTS variable.
|
||||||
.cross_accel_build_job:
|
.cross_accel_build_job:
|
||||||
extends: .base_job_template
|
|
||||||
stage: build
|
stage: build
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||||
timeout: 30m
|
timeout: 30m
|
||||||
script:
|
script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd 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
|
--disable-tools --enable-${ACCEL:-kvm} $EXTRA_CONFIGURE_OPTS
|
||||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||||
|
|
||||||
.cross_user_build_job:
|
.cross_user_build_job:
|
||||||
extends: .base_job_template
|
|
||||||
stage: build
|
stage: build
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||||
script:
|
script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||||
--disable-system --target-list-exclude="aarch64_be-linux-user
|
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||||
alpha-linux-user cris-linux-user m68k-linux-user microblazeel-linux-user
|
--disable-system
|
||||||
nios2-linux-user or1k-linux-user ppc-linux-user sparc-linux-user
|
|
||||||
xtensa-linux-user $CROSS_SKIP_TARGETS"
|
|
||||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||||
|
@ -62,14 +62,26 @@ cross-i386-user:
|
|||||||
cross-i386-tci:
|
cross-i386-tci:
|
||||||
extends: .cross_accel_build_job
|
extends: .cross_accel_build_job
|
||||||
timeout: 60m
|
timeout: 60m
|
||||||
needs:
|
|
||||||
job: i386-fedora-cross-container
|
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora-i386-cross
|
IMAGE: fedora-i386-cross
|
||||||
ACCEL: tcg-interpreter
|
ACCEL: tcg-interpreter
|
||||||
EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user
|
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
|
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:
|
cross-mipsel-system:
|
||||||
extends: .cross_system_build_job
|
extends: .cross_system_build_job
|
||||||
needs:
|
needs:
|
||||||
@ -112,33 +124,6 @@ cross-ppc64el-user:
|
|||||||
variables:
|
variables:
|
||||||
IMAGE: debian-ppc64el-cross
|
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:
|
cross-s390x-system:
|
||||||
extends: .cross_system_build_job
|
extends: .cross_system_build_job
|
||||||
needs:
|
needs:
|
||||||
@ -159,7 +144,7 @@ cross-s390x-kvm-only:
|
|||||||
job: s390x-debian-cross-container
|
job: s390x-debian-cross-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: debian-s390x-cross
|
IMAGE: debian-s390x-cross
|
||||||
EXTRA_CONFIGURE_OPTS: --disable-tcg --enable-trace-backends=ftrace
|
EXTRA_CONFIGURE_OPTS: --disable-tcg
|
||||||
|
|
||||||
cross-mips64el-kvm-only:
|
cross-mips64el-kvm-only:
|
||||||
extends: .cross_accel_build_job
|
extends: .cross_accel_build_job
|
||||||
@ -175,7 +160,6 @@ cross-win32-system:
|
|||||||
job: win32-fedora-cross-container
|
job: win32-fedora-cross-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora-win32-cross
|
IMAGE: fedora-win32-cross
|
||||||
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal
|
|
||||||
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
|
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu
|
||||||
microblazeel-softmmu mips64el-softmmu nios2-softmmu
|
microblazeel-softmmu mips64el-softmmu nios2-softmmu
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -188,10 +172,7 @@ cross-win64-system:
|
|||||||
job: win64-fedora-cross-container
|
job: win64-fedora-cross-container
|
||||||
variables:
|
variables:
|
||||||
IMAGE: fedora-win64-cross
|
IMAGE: fedora-win64-cross
|
||||||
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal
|
CROSS_SKIP_TARGETS: or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu
|
||||||
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu
|
|
||||||
m68k-softmmu microblazeel-softmmu nios2-softmmu
|
|
||||||
or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu
|
|
||||||
tricore-softmmu xtensaeb-softmmu
|
tricore-softmmu xtensaeb-softmmu
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
|
@ -13,19 +13,226 @@
|
|||||||
variables:
|
variables:
|
||||||
GIT_STRATEGY: clone
|
GIT_STRATEGY: clone
|
||||||
|
|
||||||
# All custom runners can extend this template to upload the testlog
|
# All ubuntu-18.04 jobs should run successfully in an environment
|
||||||
# data as an artifact and also feed the junit report
|
# setup by the scripts/ci/setup/build-environment.yml task
|
||||||
.custom_artifacts_template:
|
# "Install basic packages to build QEMU on Ubuntu 18.04/20.04"
|
||||||
artifacts:
|
ubuntu-18.04-s390x-all-linux-static:
|
||||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
allow_failure: true
|
||||||
expire_in: 7 days
|
needs: []
|
||||||
paths:
|
stage: build
|
||||||
- build/meson-logs/testlog.txt
|
tags:
|
||||||
reports:
|
- ubuntu_18.04
|
||||||
junit: build/meson-logs/testlog.junit.xml
|
- 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:
|
ubuntu-18.04-s390x-all:
|
||||||
- local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml'
|
allow_failure: true
|
||||||
- local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml'
|
needs: []
|
||||||
- local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml'
|
stage: build
|
||||||
- local: '/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml'
|
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,42 +1,17 @@
|
|||||||
# All jobs needing docker-edk2 must use the same rules it uses.
|
# All jobs needing docker-edk2 must use the same rules it uses.
|
||||||
.edk2_job_rules:
|
.edk2_job_rules:
|
||||||
rules:
|
rules: # Only run this job when ...
|
||||||
# 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:
|
- changes:
|
||||||
|
# this file is modified
|
||||||
- .gitlab-ci.d/edk2.yml
|
- .gitlab-ci.d/edk2.yml
|
||||||
|
# or the Dockerfile is modified
|
||||||
- .gitlab-ci.d/edk2/Dockerfile
|
- .gitlab-ci.d/edk2/Dockerfile
|
||||||
|
# or roms/edk2/ is modified (submodule updated)
|
||||||
- roms/edk2/*
|
- roms/edk2/*
|
||||||
when: on_success
|
when: on_success
|
||||||
|
- if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2'
|
||||||
# Run if the branch/tag starts with 'edk2'
|
|
||||||
- if: '$CI_COMMIT_REF_NAME =~ /^edk2/'
|
|
||||||
when: on_success
|
when: on_success
|
||||||
|
- if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2'
|
||||||
# Run if last commit msg contains 'EDK2' (case insensitive)
|
|
||||||
- if: '$CI_COMMIT_MESSAGE =~ /edk2/i'
|
|
||||||
when: on_success
|
when: on_success
|
||||||
|
|
||||||
docker-edk2:
|
docker-edk2:
|
||||||
@ -75,11 +50,7 @@ build-edk2:
|
|||||||
GIT_DEPTH: 3
|
GIT_DEPTH: 3
|
||||||
script: # Clone the required submodules and build EDK2
|
script: # Clone the required submodules and build EDK2
|
||||||
- git submodule update --init roms/edk2
|
- git submodule update --init roms/edk2
|
||||||
- git -C roms/edk2 submodule update --init --
|
- 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))
|
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||||
- make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2
|
- 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
|
# 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
|
# Install packages required to build EDK2
|
||||||
RUN apt update \
|
RUN apt update \
|
||||||
@ -20,7 +20,7 @@ RUN apt update \
|
|||||||
iasl \
|
iasl \
|
||||||
make \
|
make \
|
||||||
nasm \
|
nasm \
|
||||||
python3 \
|
python \
|
||||||
uuid-dev \
|
uuid-dev \
|
||||||
&& \
|
&& \
|
||||||
\
|
\
|
||||||
|
@ -1,42 +1,18 @@
|
|||||||
# All jobs needing docker-opensbi must use the same rules it uses.
|
# All jobs needing docker-opensbi must use the same rules it uses.
|
||||||
.opensbi_job_rules:
|
.opensbi_job_rules:
|
||||||
rules:
|
rules: # Only run this job when ...
|
||||||
# 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:
|
- changes:
|
||||||
|
# this file is modified
|
||||||
- .gitlab-ci.d/opensbi.yml
|
- .gitlab-ci.d/opensbi.yml
|
||||||
|
# or the Dockerfile is modified
|
||||||
- .gitlab-ci.d/opensbi/Dockerfile
|
- .gitlab-ci.d/opensbi/Dockerfile
|
||||||
|
when: on_success
|
||||||
|
- changes: # or roms/opensbi/ is modified (submodule updated)
|
||||||
- roms/opensbi/*
|
- roms/opensbi/*
|
||||||
when: on_success
|
when: on_success
|
||||||
|
- if: '$CI_COMMIT_REF_NAME =~ /^opensbi/' # or the branch/tag starts with 'opensbi'
|
||||||
# Run if the branch/tag starts with 'opensbi'
|
|
||||||
- if: '$CI_COMMIT_REF_NAME =~ /^opensbi/'
|
|
||||||
when: on_success
|
when: on_success
|
||||||
|
- if: '$CI_COMMIT_MESSAGE =~ /opensbi/i' # or last commit description contains 'OpenSBI'
|
||||||
# Run if the last commit msg contains 'OpenSBI' (case insensitive)
|
|
||||||
- if: '$CI_COMMIT_MESSAGE =~ /opensbi/i'
|
|
||||||
when: on_success
|
when: on_success
|
||||||
|
|
||||||
docker-opensbi:
|
docker-opensbi:
|
||||||
@ -67,7 +43,9 @@ build-opensbi:
|
|||||||
artifacts:
|
artifacts:
|
||||||
paths: # 'artifacts.zip' will contains the following files:
|
paths: # 'artifacts.zip' will contains the following files:
|
||||||
- pc-bios/opensbi-riscv32-generic-fw_dynamic.bin
|
- 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.bin
|
||||||
|
- pc-bios/opensbi-riscv64-generic-fw_dynamic.elf
|
||||||
- opensbi32-generic-stdout.log
|
- opensbi32-generic-stdout.log
|
||||||
- opensbi32-generic-stderr.log
|
- opensbi32-generic-stderr.log
|
||||||
- opensbi64-generic-stdout.log
|
- opensbi64-generic-stdout.log
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
# https://gitlab.com/qemu-project/qemu/-/pipelines
|
# https://gitlab.com/qemu-project/qemu/-/pipelines
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- local: '/.gitlab-ci.d/base.yml'
|
|
||||||
- local: '/.gitlab-ci.d/stages.yml'
|
- local: '/.gitlab-ci.d/stages.yml'
|
||||||
- local: '/.gitlab-ci.d/edk2.yml'
|
- local: '/.gitlab-ci.d/edk2.yml'
|
||||||
- local: '/.gitlab-ci.d/opensbi.yml'
|
- local: '/.gitlab-ci.d/opensbi.yml'
|
||||||
@ -12,4 +11,3 @@ include:
|
|||||||
- local: '/.gitlab-ci.d/static_checks.yml'
|
- local: '/.gitlab-ci.d/static_checks.yml'
|
||||||
- local: '/.gitlab-ci.d/custom-runners.yml'
|
- local: '/.gitlab-ci.d/custom-runners.yml'
|
||||||
- local: '/.gitlab-ci.d/cirrus.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)
|
# - test (for test stages, using build artefacts from a build stage)
|
||||||
stages:
|
stages:
|
||||||
- containers
|
- containers
|
||||||
|
- containers-layer2
|
||||||
- build
|
- build
|
||||||
- test
|
- test
|
||||||
|
@ -1,41 +1,42 @@
|
|||||||
check-patch:
|
check-patch:
|
||||||
extends: .base_job_template
|
|
||||||
stage: build
|
stage: build
|
||||||
image: python:3.10-alpine
|
image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
|
||||||
needs: []
|
needs:
|
||||||
|
job: amd64-centos8-container
|
||||||
script:
|
script:
|
||||||
- .gitlab-ci.d/check-patch.py
|
- .gitlab-ci.d/check-patch.py
|
||||||
variables:
|
variables:
|
||||||
GIT_DEPTH: 1000
|
GIT_DEPTH: 1000
|
||||||
QEMU_JOB_ONLY_FORKS: 1
|
rules:
|
||||||
before_script:
|
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||||
- apk -U add git perl
|
when: never
|
||||||
|
- when: on_success
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
|
|
||||||
check-dco:
|
check-dco:
|
||||||
extends: .base_job_template
|
|
||||||
stage: build
|
stage: build
|
||||||
image: python:3.10-alpine
|
image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
|
||||||
needs: []
|
needs:
|
||||||
|
job: amd64-centos8-container
|
||||||
script: .gitlab-ci.d/check-dco.py
|
script: .gitlab-ci.d/check-dco.py
|
||||||
variables:
|
variables:
|
||||||
GIT_DEPTH: 1000
|
GIT_DEPTH: 1000
|
||||||
before_script:
|
rules:
|
||||||
- apk -U add git
|
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||||
|
when: never
|
||||||
|
- when: on_success
|
||||||
|
|
||||||
check-python-minreqs:
|
check-python-pipenv:
|
||||||
extends: .base_job_template
|
|
||||||
stage: test
|
stage: test
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/python:latest
|
image: $CI_REGISTRY_IMAGE/qemu/python:latest
|
||||||
script:
|
script:
|
||||||
- make -C python check-minreqs
|
- make -C python check-pipenv
|
||||||
variables:
|
variables:
|
||||||
GIT_DEPTH: 1
|
GIT_DEPTH: 1
|
||||||
needs:
|
needs:
|
||||||
job: python-container
|
job: python-container
|
||||||
|
|
||||||
check-python-tox:
|
check-python-tox:
|
||||||
extends: .base_job_template
|
|
||||||
stage: test
|
stage: test
|
||||||
image: $CI_REGISTRY_IMAGE/qemu/python:latest
|
image: $CI_REGISTRY_IMAGE/qemu/python:latest
|
||||||
script:
|
script:
|
||||||
@ -43,6 +44,6 @@ check-python-tox:
|
|||||||
variables:
|
variables:
|
||||||
GIT_DEPTH: 1
|
GIT_DEPTH: 1
|
||||||
QEMU_TOX_EXTRA_ARGS: --skip-missing-interpreters=false
|
QEMU_TOX_EXTRA_ARGS: --skip-missing-interpreters=false
|
||||||
QEMU_JOB_OPTIONAL: 1
|
|
||||||
needs:
|
needs:
|
||||||
job: python-container
|
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
|
## Host environment
|
||||||
- Operating system: <!-- Windows 10 21H1, Fedora 37, etc. -->
|
- Operating system: (Windows 10 21H1, Fedora 34, etc.)
|
||||||
- OS/kernel version: <!-- For POSIX hosts, use `uname -a` -->
|
- OS/kernel version: (For POSIX hosts, use `uname -a`)
|
||||||
- Architecture: <!-- x86, ARM, s390x, etc. -->
|
- Architecture: (x86, ARM, s390x, etc.)
|
||||||
- QEMU flavor: <!-- qemu-system-x86_64, qemu-aarch64, qemu-img, etc. -->
|
- QEMU flavor: (qemu-system-x86_64, qemu-aarch64, qemu-img, etc.)
|
||||||
- QEMU version: <!-- e.g. `qemu-system-x86_64 --version` -->
|
- QEMU version: (e.g. `qemu-system-x86_64 --version`)
|
||||||
- QEMU command line:
|
- QEMU command line:
|
||||||
<!--
|
<!--
|
||||||
Give the smallest, complete command line that exhibits the problem.
|
Give the smallest, complete command line that exhibits the problem.
|
||||||
@ -35,9 +35,9 @@ https://www.qemu.org/contribute/security-process/
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Emulated/Virtualized environment
|
## Emulated/Virtualized environment
|
||||||
- Operating system: <!-- Windows 10 21H1, Fedora 37, etc. -->
|
- Operating system: (Windows 10 21H1, Fedora 34, etc.)
|
||||||
- OS/kernel version: <!-- For POSIX guests, use `uname -a`. -->
|
- OS/kernel version: (For POSIX guests, use `uname -a`.)
|
||||||
- Architecture: <!-- x86, ARM, s390x, etc. -->
|
- Architecture: (x86, ARM, s390x, etc.)
|
||||||
|
|
||||||
|
|
||||||
## Description of problem
|
## Description of problem
|
||||||
|
15
.gitmodules
vendored
15
.gitmodules
vendored
@ -13,6 +13,9 @@
|
|||||||
[submodule "roms/qemu-palcode"]
|
[submodule "roms/qemu-palcode"]
|
||||||
path = roms/qemu-palcode
|
path = roms/qemu-palcode
|
||||||
url = https://gitlab.com/qemu-project/qemu-palcode.git
|
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"]
|
[submodule "dtc"]
|
||||||
path = dtc
|
path = dtc
|
||||||
url = https://gitlab.com/qemu-project/dtc.git
|
url = https://gitlab.com/qemu-project/dtc.git
|
||||||
@ -28,6 +31,9 @@
|
|||||||
[submodule "ui/keycodemapdb"]
|
[submodule "ui/keycodemapdb"]
|
||||||
path = ui/keycodemapdb
|
path = ui/keycodemapdb
|
||||||
url = https://gitlab.com/qemu-project/keycodemapdb.git
|
url = https://gitlab.com/qemu-project/keycodemapdb.git
|
||||||
|
[submodule "capstone"]
|
||||||
|
path = capstone
|
||||||
|
url = https://gitlab.com/qemu-project/capstone.git
|
||||||
[submodule "roms/seabios-hppa"]
|
[submodule "roms/seabios-hppa"]
|
||||||
path = roms/seabios-hppa
|
path = roms/seabios-hppa
|
||||||
url = https://gitlab.com/qemu-project/seabios-hppa.git
|
url = https://gitlab.com/qemu-project/seabios-hppa.git
|
||||||
@ -43,6 +49,9 @@
|
|||||||
[submodule "roms/edk2"]
|
[submodule "roms/edk2"]
|
||||||
path = roms/edk2
|
path = roms/edk2
|
||||||
url = https://gitlab.com/qemu-project/edk2.git
|
url = https://gitlab.com/qemu-project/edk2.git
|
||||||
|
[submodule "slirp"]
|
||||||
|
path = slirp
|
||||||
|
url = https://gitlab.com/qemu-project/libslirp.git
|
||||||
[submodule "roms/opensbi"]
|
[submodule "roms/opensbi"]
|
||||||
path = roms/opensbi
|
path = roms/opensbi
|
||||||
url = https://gitlab.com/qemu-project/opensbi.git
|
url = https://gitlab.com/qemu-project/opensbi.git
|
||||||
@ -55,9 +64,3 @@
|
|||||||
[submodule "roms/vbootrom"]
|
[submodule "roms/vbootrom"]
|
||||||
path = roms/vbootrom
|
path = roms/vbootrom
|
||||||
url = https://gitlab.com/qemu-project/vbootrom.git
|
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>
|
malc <av1474@comtv.ru> malc <malc@c046a42c-6fe2-441c-8c8c-71466251a162>
|
||||||
|
|
||||||
# Corrupted Author fields
|
# 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>
|
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>
|
Nick Hudson <hnick@vmware.com> hnick@vmware.com <hnick@vmware.com>
|
||||||
|
|
||||||
# There is also a:
|
# 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>
|
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>
|
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>
|
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.
|
# Next, replace old addresses by a more recent one.
|
||||||
Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <aleksandar.markovic@mips.com>
|
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>
|
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
|
||||||
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
|
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
|
||||||
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
|
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>
|
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@adacore.com> <fred.konrad@greensocs.com>
|
||||||
Frederic Konrad <konrad.frederic@yahoo.fr> <konrad@adacore.com>
|
|
||||||
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
|
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
|
||||||
Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
|
Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com>
|
||||||
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
|
Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
|
||||||
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
|
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
|
||||||
Leif Lindholm <quic_llindhol@quicinc.com> <leif.lindholm@linaro.org>
|
Leif Lindholm <leif@nuviainc.com> <leif.lindholm@linaro.org>
|
||||||
Leif Lindholm <quic_llindhol@quicinc.com> <leif@nuviainc.com>
|
|
||||||
Radoslaw Biernacki <rad@semihalf.com> <radoslaw.biernacki@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@mips.com>
|
||||||
Paul Burton <paulburton@kernel.org> <paul.burton@imgtec.com>
|
Paul Burton <paulburton@kernel.org> <paul.burton@imgtec.com>
|
||||||
Paul Burton <paulburton@kernel.org> <paul@archlinuxmips.org>
|
Paul Burton <paulburton@kernel.org> <paul@archlinuxmips.org>
|
||||||
Paul Burton <paulburton@kernel.org> <pburton@wavecomp.com>
|
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>
|
Stefan Brankovic <stefan.brankovic@syrmia.com> <stefan.brankovic@rt-rk.com.com>
|
||||||
Yongbok Kim <yongbok.kim@mips.com> <yongbok.kim@imgtec.com>
|
Yongbok Kim <yongbok.kim@mips.com> <yongbok.kim@imgtec.com>
|
||||||
|
|
||||||
# Also list preferred name forms where people have changed their
|
# Also list preferred name forms where people have changed their
|
||||||
# git author config, or had utf8/latin1 encoding issues.
|
# git author config, or had utf8/latin1 encoding issues.
|
||||||
Aaron Lindsay <aaron@os.amperecomputing.com>
|
Aaron Lindsay <aaron@os.amperecomputing.com>
|
||||||
Aaron Larson <alarson@ddci.com>
|
|
||||||
Alexey Gerasimenko <x1917x@gmail.com>
|
Alexey Gerasimenko <x1917x@gmail.com>
|
||||||
Alex Chen <alex.chen@huawei.com>
|
|
||||||
Alex Ivanov <void@aleksoft.net>
|
Alex Ivanov <void@aleksoft.net>
|
||||||
Andreas Färber <afaerber@suse.de>
|
Andreas Färber <afaerber@suse.de>
|
||||||
Bandan Das <bsd@redhat.com>
|
Bandan Das <bsd@redhat.com>
|
||||||
@ -113,11 +99,9 @@ Gautham R. Shenoy <ego@in.ibm.com>
|
|||||||
Gautham R. Shenoy <ego@linux.vnet.ibm.com>
|
Gautham R. Shenoy <ego@linux.vnet.ibm.com>
|
||||||
Gonglei (Arei) <arei.gonglei@huawei.com>
|
Gonglei (Arei) <arei.gonglei@huawei.com>
|
||||||
Guang Wang <wang.guang55@zte.com.cn>
|
Guang Wang <wang.guang55@zte.com.cn>
|
||||||
Haibin Zhang <haibinzhang@tencent.com>
|
|
||||||
Hailiang Zhang <zhang.zhanghailiang@huawei.com>
|
Hailiang Zhang <zhang.zhanghailiang@huawei.com>
|
||||||
Hanna Reitz <hreitz@redhat.com> <mreitz@redhat.com>
|
Hanna Reitz <hreitz@redhat.com> <mreitz@redhat.com>
|
||||||
Hervé Poussineau <hpoussin@reactos.org>
|
Hervé Poussineau <hpoussin@reactos.org>
|
||||||
Hyman Huang <huangy81@chinatelecom.cn>
|
|
||||||
Jakub Jermář <jakub@jermar.eu>
|
Jakub Jermář <jakub@jermar.eu>
|
||||||
Jakub Jermář <jakub.jermar@kernkonzept.com>
|
Jakub Jermář <jakub.jermar@kernkonzept.com>
|
||||||
Jean-Christophe Dubois <jcd@tribudubois.net>
|
Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||||
@ -151,11 +135,9 @@ Nicholas Thomas <nick@bytemark.co.uk>
|
|||||||
Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
|
Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
|
||||||
Orit Wasserman <owasserm@redhat.com>
|
Orit Wasserman <owasserm@redhat.com>
|
||||||
Paolo Bonzini <pbonzini@redhat.com>
|
Paolo Bonzini <pbonzini@redhat.com>
|
||||||
Pan Nengyuan <pannengyuan@huawei.com>
|
|
||||||
Pavel Dovgaluk <dovgaluk@ispras.ru>
|
Pavel Dovgaluk <dovgaluk@ispras.ru>
|
||||||
Pavel Dovgaluk <pavel.dovgaluk@gmail.com>
|
Pavel Dovgaluk <pavel.dovgaluk@gmail.com>
|
||||||
Pavel Dovgaluk <Pavel.Dovgaluk@ispras.ru>
|
Pavel Dovgaluk <Pavel.Dovgaluk@ispras.ru>
|
||||||
Peter Chubb <peter.chubb@nicta.com.au>
|
|
||||||
Peter Crosthwaite <crosthwaite.peter@gmail.com>
|
Peter Crosthwaite <crosthwaite.peter@gmail.com>
|
||||||
Peter Crosthwaite <peter.crosthwaite@petalogix.com>
|
Peter Crosthwaite <peter.crosthwaite@petalogix.com>
|
||||||
Peter Crosthwaite <peter.crosthwaite@xilinx.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
|
os: linux
|
||||||
dist: focal
|
dist: focal
|
||||||
language: c
|
language: c
|
||||||
@ -16,6 +19,43 @@ cache:
|
|||||||
- $HOME/avocado/data/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
|
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
|
||||||
# to prevent IRC notifications from forks. This was created using:
|
# to prevent IRC notifications from forks. This was created using:
|
||||||
# $ travis encrypt -r "qemu/qemu" "irc.oftc.net#qemu"
|
# $ travis encrypt -r "qemu/qemu" "irc.oftc.net#qemu"
|
||||||
@ -91,7 +131,6 @@ jobs:
|
|||||||
- libbrlapi-dev
|
- libbrlapi-dev
|
||||||
- libcacard-dev
|
- libcacard-dev
|
||||||
- libcap-ng-dev
|
- libcap-ng-dev
|
||||||
- libfdt-dev
|
|
||||||
- libgcrypt20-dev
|
- libgcrypt20-dev
|
||||||
- libgnutls28-dev
|
- libgnutls28-dev
|
||||||
- libgtk-3-dev
|
- libgtk-3-dev
|
||||||
@ -113,8 +152,7 @@ jobs:
|
|||||||
- genisoimage
|
- genisoimage
|
||||||
env:
|
env:
|
||||||
- TEST_CMD="make check check-tcg V=1"
|
- TEST_CMD="make check check-tcg V=1"
|
||||||
- CONFIG="--disable-containers --enable-fdt=system
|
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS} --cxx=/bin/false"
|
||||||
--target-list=${MAIN_SOFTMMU_TARGETS} --cxx=/bin/false"
|
|
||||||
- UNRELIABLE=true
|
- UNRELIABLE=true
|
||||||
|
|
||||||
- name: "[ppc64] GCC check-tcg"
|
- name: "[ppc64] GCC check-tcg"
|
||||||
@ -127,7 +165,6 @@ jobs:
|
|||||||
- libbrlapi-dev
|
- libbrlapi-dev
|
||||||
- libcacard-dev
|
- libcacard-dev
|
||||||
- libcap-ng-dev
|
- libcap-ng-dev
|
||||||
- libfdt-dev
|
|
||||||
- libgcrypt20-dev
|
- libgcrypt20-dev
|
||||||
- libgnutls28-dev
|
- libgnutls28-dev
|
||||||
- libgtk-3-dev
|
- libgtk-3-dev
|
||||||
@ -149,12 +186,11 @@ jobs:
|
|||||||
- genisoimage
|
- genisoimage
|
||||||
env:
|
env:
|
||||||
- TEST_CMD="make check check-tcg V=1"
|
- TEST_CMD="make check check-tcg V=1"
|
||||||
- CONFIG="--disable-containers --enable-fdt=system
|
- CONFIG="--disable-containers --target-list=ppc64-softmmu,ppc64le-linux-user"
|
||||||
--target-list=ppc64-softmmu,ppc64le-linux-user"
|
|
||||||
|
|
||||||
- name: "[s390x] GCC check-tcg"
|
- name: "[s390x] GCC check-tcg"
|
||||||
arch: s390x
|
arch: s390x
|
||||||
dist: focal
|
dist: bionic
|
||||||
addons:
|
addons:
|
||||||
apt_packages:
|
apt_packages:
|
||||||
- libaio-dev
|
- libaio-dev
|
||||||
@ -162,7 +198,6 @@ jobs:
|
|||||||
- libbrlapi-dev
|
- libbrlapi-dev
|
||||||
- libcacard-dev
|
- libcacard-dev
|
||||||
- libcap-ng-dev
|
- libcap-ng-dev
|
||||||
- libfdt-dev
|
|
||||||
- libgcrypt20-dev
|
- libgcrypt20-dev
|
||||||
- libgnutls28-dev
|
- libgnutls28-dev
|
||||||
- libgtk-3-dev
|
- libgtk-3-dev
|
||||||
@ -184,14 +219,13 @@ jobs:
|
|||||||
- genisoimage
|
- genisoimage
|
||||||
env:
|
env:
|
||||||
- TEST_CMD="make check check-tcg V=1"
|
- TEST_CMD="make check check-tcg V=1"
|
||||||
- CONFIG="--disable-containers --enable-fdt=system
|
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
|
||||||
--target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
|
|
||||||
- UNRELIABLE=true
|
- UNRELIABLE=true
|
||||||
script:
|
script:
|
||||||
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
|
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
|
||||||
- |
|
- |
|
||||||
if [ "$BUILD_RC" -eq 0 ] ; then
|
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} ;
|
${TEST_CMD} ;
|
||||||
else
|
else
|
||||||
$(exit $BUILD_RC);
|
$(exit $BUILD_RC);
|
||||||
@ -199,14 +233,13 @@ jobs:
|
|||||||
|
|
||||||
- name: "[s390x] GCC (other-softmmu)"
|
- name: "[s390x] GCC (other-softmmu)"
|
||||||
arch: s390x
|
arch: s390x
|
||||||
dist: focal
|
dist: bionic
|
||||||
addons:
|
addons:
|
||||||
apt_packages:
|
apt_packages:
|
||||||
- libaio-dev
|
- libaio-dev
|
||||||
- libattr1-dev
|
- libattr1-dev
|
||||||
- libcacard-dev
|
- libcacard-dev
|
||||||
- libcap-ng-dev
|
- libcap-ng-dev
|
||||||
- libfdt-dev
|
|
||||||
- libgnutls28-dev
|
- libgnutls28-dev
|
||||||
- libiscsi-dev
|
- libiscsi-dev
|
||||||
- liblttng-ust-dev
|
- liblttng-ust-dev
|
||||||
@ -225,16 +258,15 @@ jobs:
|
|||||||
# Tests dependencies
|
# Tests dependencies
|
||||||
- genisoimage
|
- genisoimage
|
||||||
env:
|
env:
|
||||||
- CONFIG="--disable-containers --enable-fdt=system --audio-drv-list=sdl
|
- CONFIG="--disable-containers --audio-drv-list=sdl --disable-user
|
||||||
--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
|
--target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
|
||||||
|
|
||||||
- name: "[s390x] GCC (user)"
|
- name: "[s390x] GCC (user)"
|
||||||
arch: s390x
|
arch: s390x
|
||||||
dist: focal
|
dist: bionic
|
||||||
addons:
|
addons:
|
||||||
apt_packages:
|
apt_packages:
|
||||||
- libgcrypt20-dev
|
- libgcrypt20-dev
|
||||||
- libglib2.0-dev
|
|
||||||
- libgnutls28-dev
|
- libgnutls28-dev
|
||||||
- ninja-build
|
- ninja-build
|
||||||
env:
|
env:
|
||||||
@ -242,7 +274,7 @@ jobs:
|
|||||||
|
|
||||||
- name: "[s390x] Clang (disable-tcg)"
|
- name: "[s390x] Clang (disable-tcg)"
|
||||||
arch: s390x
|
arch: s390x
|
||||||
dist: focal
|
dist: bionic
|
||||||
compiler: clang
|
compiler: clang
|
||||||
addons:
|
addons:
|
||||||
apt_packages:
|
apt_packages:
|
||||||
@ -251,7 +283,6 @@ jobs:
|
|||||||
- libbrlapi-dev
|
- libbrlapi-dev
|
||||||
- libcacard-dev
|
- libcacard-dev
|
||||||
- libcap-ng-dev
|
- libcap-ng-dev
|
||||||
- libfdt-dev
|
|
||||||
- libgcrypt20-dev
|
- libgcrypt20-dev
|
||||||
- libgnutls28-dev
|
- libgnutls28-dev
|
||||||
- libgtk-3-dev
|
- libgtk-3-dev
|
||||||
@ -271,6 +302,29 @@ jobs:
|
|||||||
- ninja-build
|
- ninja-build
|
||||||
env:
|
env:
|
||||||
- TEST_CMD="make check-unit"
|
- TEST_CMD="make check-unit"
|
||||||
- CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools
|
- CONFIG="--disable-containers --disable-tcg --enable-kvm
|
||||||
--enable-fdt=system --host-cc=clang --cxx=clang++"
|
--disable-tools --host-cc=clang --cxx=clang++"
|
||||||
- UNRELIABLE=true
|
- 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
|
config VHOST_USER
|
||||||
bool
|
bool
|
||||||
|
select VHOST
|
||||||
|
|
||||||
config VHOST_VDPA
|
config VHOST_VDPA
|
||||||
bool
|
bool
|
||||||
|
select VHOST
|
||||||
|
|
||||||
config VHOST_KERNEL
|
config VHOST_KERNEL
|
||||||
bool
|
bool
|
||||||
|
select VHOST
|
||||||
|
|
||||||
config VIRTFS
|
config VIRTFS
|
||||||
bool
|
bool
|
||||||
@ -38,11 +41,3 @@ config PVRDMA
|
|||||||
config MULTIPROCESS_ALLOWED
|
config MULTIPROCESS_ALLOWED
|
||||||
bool
|
bool
|
||||||
imply MULTIPROCESS
|
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),)
|
ifneq ($(wildcard config-host.mak),)
|
||||||
include config-host.mak
|
include config-host.mak
|
||||||
|
|
||||||
include Makefile.prereqs
|
|
||||||
Makefile.prereqs: config-host.mak
|
|
||||||
|
|
||||||
git-submodule-update:
|
git-submodule-update:
|
||||||
.git-submodule-status: git-submodule-update config-host.mak
|
.git-submodule-status: git-submodule-update config-host.mak
|
||||||
Makefile: .git-submodule-status
|
Makefile: .git-submodule-status
|
||||||
@ -90,7 +87,7 @@ x := $(shell rm -rf meson-private meson-info meson-logs)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# 1. ensure config-host.mak is up-to-date
|
# 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
|
@echo config-host.mak is out-of-date, running configure
|
||||||
@if test -f meson-private/coredata.dat; then \
|
@if test -f meson-private/coredata.dat; then \
|
||||||
./config.status --skip-meson; \
|
./config.status --skip-meson; \
|
||||||
@ -127,12 +124,6 @@ ifneq ($(MESON),)
|
|||||||
Makefile.mtest: build.ninja scripts/mtest2make.py
|
Makefile.mtest: build.ninja scripts/mtest2make.py
|
||||||
$(MESON) introspect --targets --tests --benchmarks | $(PYTHON) scripts/mtest2make.py > $@
|
$(MESON) introspect --targets --tests --benchmarks | $(PYTHON) scripts/mtest2make.py > $@
|
||||||
-include Makefile.mtest
|
-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
|
endif
|
||||||
|
|
||||||
# 4. Rules to bridge to other makefiles
|
# 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)
|
MAKE.nq = $(if $(word 2, $(MAKE.n) $(MAKE.q)),nq)
|
||||||
NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \
|
NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \
|
||||||
$(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \
|
$(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
|
# "ninja -t targets" also lists all prerequisites. If build system
|
||||||
# files are marked as PHONY, however, Make will always try to execute
|
# files are marked as PHONY, however, Make will always try to execute
|
||||||
# "ninja build.ninja".
|
# "ninja build.ninja".
|
||||||
@ -162,12 +153,15 @@ $(ninja-targets): run-ninja
|
|||||||
# --output-sync line.
|
# --output-sync line.
|
||||||
run-ninja: config-host.mak
|
run-ninja: config-host.mak
|
||||||
ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),)
|
ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),)
|
||||||
+$(if $(MAKE.nq),@:,$(quiet-@)$(NINJA) $(NINJAFLAGS) \
|
+$(quiet-@)$(if $(MAKE.nq),@:, $(NINJA) -d keepdepfile \
|
||||||
$(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat)
|
$(NINJAFLAGS) $(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Force configure to re-run if the API symbols are updated
|
||||||
ifeq ($(CONFIG_PLUGIN),y)
|
ifeq ($(CONFIG_PLUGIN),y)
|
||||||
|
config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols
|
||||||
|
|
||||||
.PHONY: plugins
|
.PHONY: plugins
|
||||||
plugins:
|
plugins:
|
||||||
$(call quiet-command,\
|
$(call quiet-command,\
|
||||||
@ -189,27 +183,30 @@ include $(SRC_PATH)/tests/Makefile.include
|
|||||||
|
|
||||||
all: recurse-all
|
all: recurse-all
|
||||||
|
|
||||||
ROMS_RULES=$(foreach t, all clean distclean, $(addsuffix /$(t), $(ROMS)))
|
ROM_DIRS = $(addprefix pc-bios/, $(ROMS))
|
||||||
.PHONY: $(ROMS_RULES)
|
ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS)))
|
||||||
$(ROMS_RULES):
|
# 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 $@),)
|
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" $(notdir $@),)
|
||||||
|
|
||||||
.PHONY: recurse-all recurse-clean
|
.PHONY: recurse-all recurse-clean
|
||||||
recurse-all: $(addsuffix /all, $(ROMS))
|
recurse-all: $(addsuffix /all, $(ROM_DIRS))
|
||||||
recurse-clean: $(addsuffix /clean, $(ROMS))
|
recurse-clean: $(addsuffix /clean, $(ROM_DIRS))
|
||||||
recurse-distclean: $(addsuffix /distclean, $(ROMS))
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
clean: recurse-clean
|
clean: recurse-clean
|
||||||
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean || :
|
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean || :
|
||||||
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) clean-ctlist || :
|
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) clean-ctlist || :
|
||||||
find . \( -name '*.so' -o -name '*.dll' -o \
|
# avoid old build problems by removing potentially incorrect old files
|
||||||
-name '*.[oda]' -o -name '*.gcno' \) -type f \
|
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-aarch64.a \
|
||||||
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \
|
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \
|
||||||
-exec rm {} +
|
-exec rm {} +
|
||||||
rm -f TAGS cscope.* *~ */*~
|
rm -f TAGS cscope.* *.pod *~ */*~
|
||||||
|
rm -f fsdev/*.pod scsi/*.pod
|
||||||
|
|
||||||
VERSION = $(shell cat $(SRC_PATH)/VERSION)
|
VERSION = $(shell cat $(SRC_PATH)/VERSION)
|
||||||
|
|
||||||
@ -218,12 +215,12 @@ dist: qemu-$(VERSION).tar.bz2
|
|||||||
qemu-%.tar.bz2:
|
qemu-%.tar.bz2:
|
||||||
$(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst 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 || :
|
-$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || :
|
||||||
rm -f config-host.mak Makefile.prereqs qemu-bundle
|
rm -f config-host.mak config-host.h* config-poison.h
|
||||||
rm -f tests/tcg/*/config-target.mak tests/tcg/config-host.mak
|
rm -f tests/tcg/config-*.mak
|
||||||
rm -f config.status
|
rm -f config-all-disas.mak config.status
|
||||||
rm -f roms/seabios/config.mak
|
rm -f roms/seabios/config.mak roms/vgabios/config.mak
|
||||||
rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols
|
rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols
|
||||||
rm -f *-config-target.h *-config-devices.mak *-config-devices.h
|
rm -f *-config-target.h *-config-devices.mak *-config-devices.h
|
||||||
rm -rf meson-private meson-logs meson-info compile_commands.json
|
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 -f linux-headers/asm
|
||||||
rm -Rf .sdk
|
rm -Rf .sdk
|
||||||
|
|
||||||
find-src-path = find "$(SRC_PATH)" -path "$(SRC_PATH)/meson" -prune -o \
|
find-src-path = find "$(SRC_PATH)/" -path "$(SRC_PATH)/meson" -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
|
||||||
-type l -prune -o \( -name "*.[chsS]" -o -name "*.[ch].inc" \)
|
|
||||||
|
|
||||||
.PHONY: ctags
|
.PHONY: ctags
|
||||||
ctags:
|
ctags:
|
||||||
@ -254,7 +250,7 @@ gtags:
|
|||||||
"GTAGS", "Remove old $@ files")
|
"GTAGS", "Remove old $@ files")
|
||||||
$(call quiet-command, \
|
$(call quiet-command, \
|
||||||
(cd $(SRC_PATH) && \
|
(cd $(SRC_PATH) && \
|
||||||
$(find-src-path) -print | gtags -f -), \
|
$(find-src-path) | gtags -f -), \
|
||||||
"GTAGS", "Re-index $(SRC_PATH)")
|
"GTAGS", "Re-index $(SRC_PATH)")
|
||||||
|
|
||||||
.PHONY: TAGS
|
.PHONY: TAGS
|
||||||
@ -284,7 +280,6 @@ cscope:
|
|||||||
# Needed by "meson install"
|
# Needed by "meson install"
|
||||||
export DESTDIR
|
export DESTDIR
|
||||||
|
|
||||||
include $(SRC_PATH)/tests/lcitool/Makefile.include
|
|
||||||
include $(SRC_PATH)/tests/docker/Makefile.include
|
include $(SRC_PATH)/tests/docker/Makefile.include
|
||||||
include $(SRC_PATH)/tests/vm/Makefile.include
|
include $(SRC_PATH)/tests/vm/Makefile.include
|
||||||
|
|
||||||
@ -314,7 +309,6 @@ endif
|
|||||||
@echo 'Test targets:'
|
@echo 'Test targets:'
|
||||||
$(call print-help,check,Run all tests (check-help for details))
|
$(call print-help,check,Run all tests (check-help for details))
|
||||||
$(call print-help,bench,Run all benchmarks)
|
$(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,docker-help,Help about targets running tests inside containers)
|
||||||
$(call print-help,vm-help,Help about targets running tests inside VM)
|
$(call print-help,vm-help,Help about targets running tests inside VM)
|
||||||
@echo ''
|
@echo ''
|
||||||
|
@ -39,7 +39,7 @@ Documentation can be found hosted online at
|
|||||||
current development version that is available at
|
current development version that is available at
|
||||||
`<https://www.qemu.org/docs/master/>`_ is generated from the ``docs/``
|
`<https://www.qemu.org/docs/master/>`_ is generated from the ``docs/``
|
||||||
folder in the source tree, and is built by `Sphinx
|
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
|
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:
|
Additional information can also be found online via the QEMU website:
|
||||||
|
|
||||||
* `<https://wiki.qemu.org/Hosts/Linux>`_
|
* `<https://qemu.org/Hosts/Linux>`_
|
||||||
* `<https://wiki.qemu.org/Hosts/Mac>`_
|
* `<https://qemu.org/Hosts/Mac>`_
|
||||||
* `<https://wiki.qemu.org/Hosts/W32>`_
|
* `<https://qemu.org/Hosts/W32>`_
|
||||||
|
|
||||||
|
|
||||||
Submitting patches
|
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
|
qemu-devel@nongnu.org mailing list. All patches submitted must contain
|
||||||
a 'Signed-off-by' line from the author. Patches should follow the
|
a 'Signed-off-by' line from the author. Patches should follow the
|
||||||
guidelines set out in the `style section
|
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.
|
the Developers Guide.
|
||||||
|
|
||||||
Additional information on submitting patches can be found online via
|
Additional information on submitting patches can be found online via
|
||||||
the QEMU website
|
the QEMU website
|
||||||
|
|
||||||
* `<https://wiki.qemu.org/Contribute/SubmitAPatch>`_
|
* `<https://qemu.org/Contribute/SubmitAPatch>`_
|
||||||
* `<https://wiki.qemu.org/Contribute/TrivialPatches>`_
|
* `<https://qemu.org/Contribute/TrivialPatches>`_
|
||||||
|
|
||||||
The QEMU website is also maintained under source control.
|
The QEMU website is also maintained under source control.
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ reported via GitLab.
|
|||||||
|
|
||||||
For additional information on bug reporting consult:
|
For additional information on bug reporting consult:
|
||||||
|
|
||||||
* `<https://wiki.qemu.org/Contribute/ReportABug>`_
|
* `<https://qemu.org/Contribute/ReportABug>`_
|
||||||
|
|
||||||
|
|
||||||
ChangeLog
|
ChangeLog
|
||||||
@ -168,4 +168,4 @@ main methods being email and IRC
|
|||||||
Information on additional methods of contacting the community can be
|
Information on additional methods of contacting the community can be
|
||||||
found online via the QEMU website:
|
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 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)
|
static void accel_init_cpu_int_aux(ObjectClass *klass, void *opaque)
|
||||||
{
|
{
|
||||||
CPUClass *cc = CPU_CLASS(klass);
|
CPUClass *cc = CPU_CLASS(klass);
|
||||||
@ -129,16 +121,6 @@ bool accel_cpu_realizefn(CPUState *cpu, Error **errp)
|
|||||||
return true;
|
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 = {
|
static const TypeInfo accel_cpu_type = {
|
||||||
.name = TYPE_ACCEL_CPU,
|
.name = TYPE_ACCEL_CPU,
|
||||||
.parent = TYPE_OBJECT,
|
.parent = TYPE_OBJECT,
|
||||||
|
@ -66,7 +66,6 @@ void accel_init_ops_interfaces(AccelClass *ac)
|
|||||||
{
|
{
|
||||||
const char *ac_name;
|
const char *ac_name;
|
||||||
char *ops_name;
|
char *ops_name;
|
||||||
ObjectClass *oc;
|
|
||||||
AccelOpsClass *ops;
|
AccelOpsClass *ops;
|
||||||
|
|
||||||
ac_name = object_class_get_name(OBJECT_CLASS(ac));
|
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_name = g_strdup_printf("%s" ACCEL_OPS_SUFFIX, ac_name);
|
||||||
ops = ACCEL_OPS_CLASS(module_object_class_by_name(ops_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);
|
g_free(ops_name);
|
||||||
ops = ACCEL_OPS_CLASS(oc);
|
|
||||||
/*
|
/*
|
||||||
* all accelerators need to define ops, providing at least a mandatory
|
* all accelerators need to define ops, providing at least a mandatory
|
||||||
* non-NULL create_vcpu_thread operation.
|
* non-NULL create_vcpu_thread operation.
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
static void *dummy_cpu_thread_fn(void *arg)
|
static void *dummy_cpu_thread_fn(void *arg)
|
||||||
{
|
{
|
||||||
CPUState *cpu = arg;
|
CPUState *cpu = arg;
|
||||||
|
sigset_t waitset;
|
||||||
|
int r;
|
||||||
|
|
||||||
rcu_register_thread();
|
rcu_register_thread();
|
||||||
|
|
||||||
@ -30,13 +32,8 @@ static void *dummy_cpu_thread_fn(void *arg)
|
|||||||
cpu->can_do_io = 1;
|
cpu->can_do_io = 1;
|
||||||
current_cpu = cpu;
|
current_cpu = cpu;
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
sigset_t waitset;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
sigemptyset(&waitset);
|
sigemptyset(&waitset);
|
||||||
sigaddset(&waitset, SIG_IPI);
|
sigaddset(&waitset, SIG_IPI);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* signal CPU creation */
|
/* signal CPU creation */
|
||||||
cpu_thread_signal_created(cpu);
|
cpu_thread_signal_created(cpu);
|
||||||
@ -44,7 +41,6 @@ static void *dummy_cpu_thread_fn(void *arg)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
#ifndef _WIN32
|
|
||||||
do {
|
do {
|
||||||
int sig;
|
int sig;
|
||||||
r = sigwait(&waitset, &sig);
|
r = sigwait(&waitset, &sig);
|
||||||
@ -53,9 +49,6 @@ static void *dummy_cpu_thread_fn(void *arg)
|
|||||||
perror("sigwait");
|
perror("sigwait");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
qemu_sem_wait(&cpu->sem);
|
|
||||||
#endif
|
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
qemu_wait_io_event(cpu);
|
qemu_wait_io_event(cpu);
|
||||||
} while (!cpu->unplug);
|
} while (!cpu->unplug);
|
||||||
@ -76,7 +69,4 @@ void dummy_start_vcpu_thread(CPUState *cpu)
|
|||||||
cpu->cpu_index);
|
cpu->cpu_index);
|
||||||
qemu_thread_create(cpu->thread, thread_name, dummy_cpu_thread_fn, cpu,
|
qemu_thread_create(cpu->thread, thread_name, dummy_cpu_thread_fn, cpu,
|
||||||
QEMU_THREAD_JOINABLE);
|
QEMU_THREAD_JOINABLE);
|
||||||
#ifdef _WIN32
|
|
||||||
qemu_sem_init(&cpu->sem, 0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -60,10 +60,6 @@
|
|||||||
|
|
||||||
HVFState *hvf_state;
|
HVFState *hvf_state;
|
||||||
|
|
||||||
#ifdef __aarch64__
|
|
||||||
#define HV_VM_DEFAULT NULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Memory slots */
|
/* Memory slots */
|
||||||
|
|
||||||
hvf_slot *hvf_find_overlap_slot(uint64_t start, uint64_t size)
|
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;
|
hvf_slot *mem;
|
||||||
MemoryRegion *area = section->mr;
|
MemoryRegion *area = section->mr;
|
||||||
bool writable = !area->readonly && !area->rom_device;
|
bool writeable = !area->readonly && !area->rom_device;
|
||||||
hv_memory_flags_t flags;
|
hv_memory_flags_t flags;
|
||||||
uint64_t page_size = qemu_real_host_page_size();
|
|
||||||
|
|
||||||
if (!memory_region_is_ram(area)) {
|
if (!memory_region_is_ram(area)) {
|
||||||
if (writable) {
|
if (writeable) {
|
||||||
return;
|
return;
|
||||||
} else if (!memory_region_is_romd(area)) {
|
} 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(
|
mem = hvf_find_overlap_slot(
|
||||||
section->offset_within_address_space,
|
section->offset_within_address_space,
|
||||||
int128_get64(section->size));
|
int128_get64(section->size));
|
||||||
@ -250,12 +239,12 @@ static void hvf_set_dirty_tracking(MemoryRegionSection *section, bool on)
|
|||||||
if (on) {
|
if (on) {
|
||||||
slot->flags |= HVF_SLOT_LOG;
|
slot->flags |= HVF_SLOT_LOG;
|
||||||
hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
|
hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
|
||||||
HV_MEMORY_READ | HV_MEMORY_EXEC);
|
HV_MEMORY_READ);
|
||||||
/* stop tracking region*/
|
/* stop tracking region*/
|
||||||
} else {
|
} else {
|
||||||
slot->flags &= ~HVF_SLOT_LOG;
|
slot->flags &= ~HVF_SLOT_LOG;
|
||||||
hv_vm_protect((uintptr_t)slot->start, (size_t)slot->size,
|
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 = {
|
static MemoryListener hvf_memory_listener = {
|
||||||
.name = "hvf",
|
|
||||||
.priority = 10,
|
.priority = 10,
|
||||||
.region_add = hvf_region_add,
|
.region_add = hvf_region_add,
|
||||||
.region_del = hvf_region_del,
|
.region_del = hvf_region_del,
|
||||||
@ -328,7 +316,7 @@ static int hvf_accel_init(MachineState *ms)
|
|||||||
|
|
||||||
s = g_new0(HVFState, 1);
|
s = g_new0(HVFState, 1);
|
||||||
|
|
||||||
s->num_slots = ARRAY_SIZE(s->slots);
|
s->num_slots = 32;
|
||||||
for (x = 0; x < s->num_slots; ++x) {
|
for (x = 0; x < s->num_slots; ++x) {
|
||||||
s->slots[x].size = 0;
|
s->slots[x].size = 0;
|
||||||
s->slots[x].slot_id = x;
|
s->slots[x].slot_id = x;
|
||||||
@ -336,8 +324,7 @@ static int hvf_accel_init(MachineState *ms)
|
|||||||
|
|
||||||
hvf_state = s;
|
hvf_state = s;
|
||||||
memory_listener_register(&hvf_memory_listener, &address_space_memory);
|
memory_listener_register(&hvf_memory_listener, &address_space_memory);
|
||||||
|
return 0;
|
||||||
return hvf_arch_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hvf_accel_class_init(ObjectClass *oc, void *data)
|
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));
|
cpu->hvf = g_malloc0(sizeof(*cpu->hvf));
|
||||||
|
|
||||||
/* init cpu signals */
|
/* init cpu signals */
|
||||||
|
sigset_t set;
|
||||||
struct sigaction sigact;
|
struct sigaction sigact;
|
||||||
|
|
||||||
memset(&sigact, 0, sizeof(sigact));
|
memset(&sigact, 0, sizeof(sigact));
|
||||||
sigact.sa_handler = dummy_signal;
|
sigact.sa_handler = dummy_signal;
|
||||||
sigaction(SIG_IPI, &sigact, NULL);
|
sigaction(SIG_IPI, &sigact, NULL);
|
||||||
|
|
||||||
pthread_sigmask(SIG_BLOCK, NULL, &cpu->hvf->unblock_ipi_mask);
|
pthread_sigmask(SIG_BLOCK, NULL, &set);
|
||||||
sigdelset(&cpu->hvf->unblock_ipi_mask, SIG_IPI);
|
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);
|
r = hv_vcpu_create((hv_vcpuid_t *)&cpu->hvf->fd, HV_VCPU_DEFAULT);
|
||||||
#endif
|
|
||||||
cpu->vcpu_dirty = 1;
|
cpu->vcpu_dirty = 1;
|
||||||
assert_hvf_ok(r);
|
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);
|
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||||
|
|
||||||
ops->create_vcpu_thread = hvf_start_vcpu_thread;
|
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_reset = hvf_cpu_synchronize_post_reset;
|
||||||
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
|
ops->synchronize_post_init = hvf_cpu_synchronize_post_init;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "sysemu/hvf.h"
|
#include "sysemu/hvf.h"
|
||||||
#include "sysemu/hvf_int.h"
|
#include "sysemu/hvf_int.h"
|
||||||
|
@ -16,14 +16,12 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "sysemu/kvm.h"
|
|
||||||
#include "sysemu/kvm_int.h"
|
#include "sysemu/kvm_int.h"
|
||||||
#include "sysemu/runstate.h"
|
#include "sysemu/runstate.h"
|
||||||
#include "sysemu/cpus.h"
|
#include "sysemu/cpus.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
|
||||||
#include <linux/kvm.h>
|
|
||||||
#include "kvm-cpus.h"
|
#include "kvm-cpus.h"
|
||||||
|
|
||||||
static void *kvm_vcpu_thread_fn(void *arg)
|
static void *kvm_vcpu_thread_fn(void *arg)
|
||||||
@ -76,34 +74,15 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
|
|||||||
cpu, QEMU_THREAD_JOINABLE);
|
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)
|
static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||||
|
|
||||||
ops->create_vcpu_thread = kvm_start_vcpu_thread;
|
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_reset = kvm_cpu_synchronize_post_reset;
|
||||||
ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
|
ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
|
||||||
ops->synchronize_state = kvm_cpu_synchronize_state;
|
ops->synchronize_state = kvm_cpu_synchronize_state;
|
||||||
ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;
|
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 = {
|
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_reset(CPUState *cpu);
|
||||||
void kvm_cpu_synchronize_post_init(CPUState *cpu);
|
void kvm_cpu_synchronize_post_init(CPUState *cpu);
|
||||||
void kvm_cpu_synchronize_pre_loadvm(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 */
|
#endif /* KVM_CPUS_H */
|
||||||
|
@ -3,5 +3,6 @@ kvm_ss.add(files(
|
|||||||
'kvm-all.c',
|
'kvm-all.c',
|
||||||
'kvm-accel-ops.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)
|
specific_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "sev.h"
|
#include "qemu-common.h"
|
||||||
|
#include "sysemu/sev.h"
|
||||||
|
|
||||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
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'))
|
softmmu_ss.add(files('accel-softmmu.c'))
|
||||||
user_ss.add(files('accel-user.c'))
|
user_ss.add(files('accel-user.c'))
|
||||||
|
|
||||||
|
subdir('hvf')
|
||||||
|
subdir('qtest')
|
||||||
|
subdir('kvm')
|
||||||
subdir('tcg')
|
subdir('tcg')
|
||||||
if have_system
|
subdir('xen')
|
||||||
subdir('hvf')
|
subdir('stubs')
|
||||||
subdir('qtest')
|
|
||||||
subdir('kvm')
|
|
||||||
subdir('xen')
|
|
||||||
subdir('stubs')
|
|
||||||
endif
|
|
||||||
|
|
||||||
# qtest
|
dummy_ss = ss.source_set()
|
||||||
softmmu_ss.add(files('dummy-cpus.c'))
|
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 "qemu/accel.h"
|
||||||
#include "sysemu/qtest.h"
|
#include "sysemu/qtest.h"
|
||||||
#include "sysemu/cpus.h"
|
#include "sysemu/cpus.h"
|
||||||
|
#include "sysemu/cpu-timers.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "hw/core/cpu.h"
|
#include "hw/core/cpu.h"
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "sysemu/hax.h"
|
#include "sysemu/hax.h"
|
||||||
|
|
||||||
bool hax_allowed;
|
|
||||||
|
|
||||||
int hax_sync_vcpus(void)
|
int hax_sync_vcpus(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -12,7 +12,10 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
#include "hw/pci/msi.h"
|
#include "hw/pci/msi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
KVMState *kvm_state;
|
KVMState *kvm_state;
|
||||||
bool kvm_kernel_irqchip;
|
bool kvm_kernel_irqchip;
|
||||||
@ -46,6 +49,27 @@ int kvm_has_many_ioeventfds(void)
|
|||||||
return 0;
|
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)
|
int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@ -56,7 +80,8 @@ int kvm_on_sigbus(int code, void *addr)
|
|||||||
return 1;
|
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;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
@ -122,13 +147,4 @@ bool kvm_arm_supports_user_irq(void)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
bool kvm_dirty_ring_enabled(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t kvm_dirty_ring_size(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
sysemu_stubs_ss = ss.source_set()
|
specific_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c'))
|
||||||
sysemu_stubs_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c'))
|
specific_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
|
||||||
sysemu_stubs_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
|
specific_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
|
||||||
sysemu_stubs_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
|
specific_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-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)
|
|
||||||
|
@ -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,
|
void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
||||||
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
|
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_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
G_NORETURN void cpu_loop_exit(CPUState *cpu)
|
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu)
|
||||||
{
|
{
|
||||||
g_assert_not_reached();
|
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();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -13,23 +13,56 @@
|
|||||||
* See the COPYING file in the top-level directory.
|
* See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void atomic_trace_rmw_post(CPUArchState *env, target_ulong addr,
|
static uint16_t atomic_trace_rmw_pre(CPUArchState *env, target_ulong addr,
|
||||||
MemOpIdx oi)
|
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
|
#if HAVE_ATOMIC128
|
||||||
static void atomic_trace_ld_post(CPUArchState *env, target_ulong addr,
|
static uint16_t atomic_trace_ld_pre(CPUArchState *env, target_ulong addr,
|
||||||
MemOpIdx oi)
|
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,
|
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
|
#endif
|
||||||
|
|
||||||
@ -55,53 +88,8 @@ CMPXCHG_HELPER(cmpxchgq_be, uint64_t)
|
|||||||
CMPXCHG_HELPER(cmpxchgq_le, uint64_t)
|
CMPXCHG_HELPER(cmpxchgq_le, uint64_t)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_CMPXCHG128
|
|
||||||
CMPXCHG_HELPER(cmpxchgo_be, Int128)
|
|
||||||
CMPXCHG_HELPER(cmpxchgo_le, Int128)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef CMPXCHG_HELPER
|
#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) \
|
#define ATOMIC_HELPER(OP, TYPE) \
|
||||||
TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, target_ulong addr, \
|
TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, target_ulong addr, \
|
||||||
TYPE val, uint32_t oi) \
|
TYPE val, uint32_t oi) \
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/plugin.h"
|
#include "qemu/plugin.h"
|
||||||
|
#include "trace/mem.h"
|
||||||
|
|
||||||
#if DATA_SIZE == 16
|
#if DATA_SIZE == 16
|
||||||
# define SUFFIX o
|
# define SUFFIX o
|
||||||
@ -63,7 +64,7 @@
|
|||||||
the ATOMIC_NAME macro, and redefined below. */
|
the ATOMIC_NAME macro, and redefined below. */
|
||||||
#if DATA_SIZE == 1
|
#if DATA_SIZE == 1
|
||||||
# define END
|
# define END
|
||||||
#elif HOST_BIG_ENDIAN
|
#elif defined(HOST_WORDS_BIGENDIAN)
|
||||||
# define END _be
|
# define END _be
|
||||||
#else
|
#else
|
||||||
# define END _le
|
# define END _le
|
||||||
@ -71,11 +72,12 @@
|
|||||||
|
|
||||||
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||||
ABI_TYPE cmpv, ABI_TYPE newv,
|
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,
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||||
PAGE_READ | PAGE_WRITE, retaddr);
|
PAGE_READ | PAGE_WRITE, retaddr);
|
||||||
DATA_TYPE ret;
|
DATA_TYPE ret;
|
||||||
|
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||||
|
|
||||||
#if DATA_SIZE == 16
|
#if DATA_SIZE == 16
|
||||||
ret = atomic16_cmpxchg(haddr, cmpv, newv);
|
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);
|
ret = qatomic_cmpxchg__nocheck(haddr, cmpv, newv);
|
||||||
#endif
|
#endif
|
||||||
ATOMIC_MMU_CLEANUP;
|
ATOMIC_MMU_CLEANUP;
|
||||||
atomic_trace_rmw_post(env, addr, oi);
|
atomic_trace_rmw_post(env, addr, info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DATA_SIZE >= 16
|
#if DATA_SIZE >= 16
|
||||||
#if HAVE_ATOMIC128
|
#if HAVE_ATOMIC128
|
||||||
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
|
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,
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||||
PAGE_READ, retaddr);
|
PAGE_READ, retaddr);
|
||||||
DATA_TYPE val;
|
DATA_TYPE val;
|
||||||
|
uint16_t info = atomic_trace_ld_pre(env, addr, oi);
|
||||||
|
|
||||||
val = atomic16_read(haddr);
|
val = atomic16_read(haddr);
|
||||||
ATOMIC_MMU_CLEANUP;
|
ATOMIC_MMU_CLEANUP;
|
||||||
atomic_trace_ld_post(env, addr, oi);
|
atomic_trace_ld_post(env, addr, info);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE 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,
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||||
PAGE_WRITE, retaddr);
|
PAGE_WRITE, retaddr);
|
||||||
|
uint16_t info = atomic_trace_st_pre(env, addr, oi);
|
||||||
|
|
||||||
atomic16_set(haddr, val);
|
atomic16_set(haddr, val);
|
||||||
ATOMIC_MMU_CLEANUP;
|
ATOMIC_MMU_CLEANUP;
|
||||||
atomic_trace_st_post(env, addr, oi);
|
atomic_trace_st_post(env, addr, info);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
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,
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||||
PAGE_READ | PAGE_WRITE, retaddr);
|
PAGE_READ | PAGE_WRITE, retaddr);
|
||||||
DATA_TYPE ret;
|
DATA_TYPE ret;
|
||||||
|
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||||
|
|
||||||
ret = qatomic_xchg__nocheck(haddr, val);
|
ret = qatomic_xchg__nocheck(haddr, val);
|
||||||
ATOMIC_MMU_CLEANUP;
|
ATOMIC_MMU_CLEANUP;
|
||||||
atomic_trace_rmw_post(env, addr, oi);
|
atomic_trace_rmw_post(env, addr, info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GEN_ATOMIC_HELPER(X) \
|
#define GEN_ATOMIC_HELPER(X) \
|
||||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
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, \
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||||
DATA_TYPE ret; \
|
DATA_TYPE ret; \
|
||||||
|
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||||
ret = qatomic_##X(haddr, val); \
|
ret = qatomic_##X(haddr, val); \
|
||||||
ATOMIC_MMU_CLEANUP; \
|
ATOMIC_MMU_CLEANUP; \
|
||||||
atomic_trace_rmw_post(env, addr, oi); \
|
atomic_trace_rmw_post(env, addr, info); \
|
||||||
return ret; \
|
return ret; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,11 +167,12 @@ GEN_ATOMIC_HELPER(xor_fetch)
|
|||||||
*/
|
*/
|
||||||
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
|
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
|
||||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
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, \
|
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||||
XDATA_TYPE cmp, old, new, val = xval; \
|
XDATA_TYPE cmp, old, new, val = xval; \
|
||||||
|
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||||
smp_mb(); \
|
smp_mb(); \
|
||||||
cmp = qatomic_read__nocheck(haddr); \
|
cmp = qatomic_read__nocheck(haddr); \
|
||||||
do { \
|
do { \
|
||||||
@ -173,7 +180,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
|||||||
cmp = qatomic_cmpxchg__nocheck(haddr, old, new); \
|
cmp = qatomic_cmpxchg__nocheck(haddr, old, new); \
|
||||||
} while (cmp != old); \
|
} while (cmp != old); \
|
||||||
ATOMIC_MMU_CLEANUP; \
|
ATOMIC_MMU_CLEANUP; \
|
||||||
atomic_trace_rmw_post(env, addr, oi); \
|
atomic_trace_rmw_post(env, addr, info); \
|
||||||
return RET; \
|
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
|
/* Define reverse-host-endian atomic operations. Note that END is used
|
||||||
within the ATOMIC_NAME macro. */
|
within the ATOMIC_NAME macro. */
|
||||||
#if HOST_BIG_ENDIAN
|
#ifdef HOST_WORDS_BIGENDIAN
|
||||||
# define END _le
|
# define END _le
|
||||||
#else
|
#else
|
||||||
# define END _be
|
# 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 ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||||
ABI_TYPE cmpv, ABI_TYPE newv,
|
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,
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||||
PAGE_READ | PAGE_WRITE, retaddr);
|
PAGE_READ | PAGE_WRITE, retaddr);
|
||||||
DATA_TYPE ret;
|
DATA_TYPE ret;
|
||||||
|
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||||
|
|
||||||
#if DATA_SIZE == 16
|
#if DATA_SIZE == 16
|
||||||
ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv));
|
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));
|
ret = qatomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||||
#endif
|
#endif
|
||||||
ATOMIC_MMU_CLEANUP;
|
ATOMIC_MMU_CLEANUP;
|
||||||
atomic_trace_rmw_post(env, addr, oi);
|
atomic_trace_rmw_post(env, addr, info);
|
||||||
return BSWAP(ret);
|
return BSWAP(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DATA_SIZE >= 16
|
#if DATA_SIZE >= 16
|
||||||
#if HAVE_ATOMIC128
|
#if HAVE_ATOMIC128
|
||||||
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
|
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,
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||||
PAGE_READ, retaddr);
|
PAGE_READ, retaddr);
|
||||||
DATA_TYPE val;
|
DATA_TYPE val;
|
||||||
|
uint16_t info = atomic_trace_ld_pre(env, addr, oi);
|
||||||
|
|
||||||
val = atomic16_read(haddr);
|
val = atomic16_read(haddr);
|
||||||
ATOMIC_MMU_CLEANUP;
|
ATOMIC_MMU_CLEANUP;
|
||||||
atomic_trace_ld_post(env, addr, oi);
|
atomic_trace_ld_post(env, addr, info);
|
||||||
return BSWAP(val);
|
return BSWAP(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE 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,
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||||
PAGE_WRITE, retaddr);
|
PAGE_WRITE, retaddr);
|
||||||
|
uint16_t info = atomic_trace_st_pre(env, addr, oi);
|
||||||
|
|
||||||
val = BSWAP(val);
|
val = BSWAP(val);
|
||||||
atomic16_set(haddr, val);
|
atomic16_set(haddr, val);
|
||||||
ATOMIC_MMU_CLEANUP;
|
ATOMIC_MMU_CLEANUP;
|
||||||
atomic_trace_st_post(env, addr, oi);
|
atomic_trace_st_post(env, addr, info);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
|
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,
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
|
||||||
PAGE_READ | PAGE_WRITE, retaddr);
|
PAGE_READ | PAGE_WRITE, retaddr);
|
||||||
ABI_TYPE ret;
|
ABI_TYPE ret;
|
||||||
|
uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
|
||||||
|
|
||||||
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
|
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
|
||||||
ATOMIC_MMU_CLEANUP;
|
ATOMIC_MMU_CLEANUP;
|
||||||
atomic_trace_rmw_post(env, addr, oi);
|
atomic_trace_rmw_post(env, addr, info);
|
||||||
return BSWAP(ret);
|
return BSWAP(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GEN_ATOMIC_HELPER(X) \
|
#define GEN_ATOMIC_HELPER(X) \
|
||||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
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, \
|
DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||||
DATA_TYPE ret; \
|
DATA_TYPE ret; \
|
||||||
|
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||||
ret = qatomic_##X(haddr, BSWAP(val)); \
|
ret = qatomic_##X(haddr, BSWAP(val)); \
|
||||||
ATOMIC_MMU_CLEANUP; \
|
ATOMIC_MMU_CLEANUP; \
|
||||||
atomic_trace_rmw_post(env, addr, oi); \
|
atomic_trace_rmw_post(env, addr, info); \
|
||||||
return BSWAP(ret); \
|
return BSWAP(ret); \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,11 +304,12 @@ GEN_ATOMIC_HELPER(xor_fetch)
|
|||||||
*/
|
*/
|
||||||
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
|
#define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET) \
|
||||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
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, \
|
XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
|
||||||
PAGE_READ | PAGE_WRITE, retaddr); \
|
PAGE_READ | PAGE_WRITE, retaddr); \
|
||||||
XDATA_TYPE ldo, ldn, old, new, val = xval; \
|
XDATA_TYPE ldo, ldn, old, new, val = xval; \
|
||||||
|
uint16_t info = atomic_trace_rmw_pre(env, addr, oi); \
|
||||||
smp_mb(); \
|
smp_mb(); \
|
||||||
ldn = qatomic_read__nocheck(haddr); \
|
ldn = qatomic_read__nocheck(haddr); \
|
||||||
do { \
|
do { \
|
||||||
@ -304,7 +317,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
|||||||
ldn = qatomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \
|
ldn = qatomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \
|
||||||
} while (ldo != ldn); \
|
} while (ldo != ldn); \
|
||||||
ATOMIC_MMU_CLEANUP; \
|
ATOMIC_MMU_CLEANUP; \
|
||||||
atomic_trace_rmw_post(env, addr, oi); \
|
atomic_trace_rmw_post(env, addr, info); \
|
||||||
return RET; \
|
return RET; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ void cpu_loop_exit(CPUState *cpu)
|
|||||||
void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
|
void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
|
||||||
{
|
{
|
||||||
if (pc) {
|
if (pc) {
|
||||||
cpu_restore_state(cpu, pc);
|
cpu_restore_state(cpu, pc, true);
|
||||||
}
|
}
|
||||||
cpu_loop_exit(cpu);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
#include "qemu/qemu-print.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 "hw/core/tcg-cpu-ops.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "disas/disas.h"
|
#include "disas/disas.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
#include "qemu/atomic.h"
|
#include "qemu/atomic.h"
|
||||||
|
#include "qemu/compiler.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "qemu/rcu.h"
|
#include "qemu/rcu.h"
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
@ -39,9 +38,7 @@
|
|||||||
#include "exec/cpu-all.h"
|
#include "exec/cpu-all.h"
|
||||||
#include "sysemu/cpu-timers.h"
|
#include "sysemu/cpu-timers.h"
|
||||||
#include "sysemu/replay.h"
|
#include "sysemu/replay.h"
|
||||||
#include "sysemu/tcg.h"
|
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "tb-jmp-cache.h"
|
|
||||||
#include "tb-hash.h"
|
#include "tb-hash.h"
|
||||||
#include "tb-context.h"
|
#include "tb-context.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@ -170,96 +167,22 @@ uint32_t curr_cflags(CPUState *cpu)
|
|||||||
return cflags;
|
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 */
|
/* Might cause an exception, so have a longjmp destination ready */
|
||||||
static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
|
static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
|
||||||
target_ulong cs_base,
|
target_ulong cs_base,
|
||||||
uint32_t flags, uint32_t cflags)
|
uint32_t flags, uint32_t cflags)
|
||||||
{
|
{
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
CPUJumpCache *jc;
|
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
|
|
||||||
/* we should never be trying to look up an INVALID tb */
|
/* we should never be trying to look up an INVALID tb */
|
||||||
tcg_debug_assert(!(cflags & CF_INVALID));
|
tcg_debug_assert(!(cflags & CF_INVALID));
|
||||||
|
|
||||||
hash = tb_jmp_cache_hash_func(pc);
|
hash = tb_jmp_cache_hash_func(pc);
|
||||||
jc = cpu->tb_jmp_cache;
|
tb = qatomic_rcu_read(&cpu->tb_jmp_cache[hash]);
|
||||||
tb = tb_jmp_cache_get_tb(jc, hash);
|
|
||||||
|
|
||||||
if (likely(tb &&
|
if (likely(tb &&
|
||||||
tb_jmp_cache_get_pc(jc, hash, tb) == pc &&
|
tb->pc == pc &&
|
||||||
tb->cs_base == cs_base &&
|
tb->cs_base == cs_base &&
|
||||||
tb->flags == flags &&
|
tb->flags == flags &&
|
||||||
tb->trace_vcpu_dstate == *cpu->trace_dstate &&
|
tb->trace_vcpu_dstate == *cpu->trace_dstate &&
|
||||||
@ -270,14 +193,16 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
|
|||||||
if (tb == NULL) {
|
if (tb == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
tb_jmp_cache_set(jc, hash, tb, pc);
|
qatomic_set(&cpu->tb_jmp_cache[hash], tb);
|
||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
static inline void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
||||||
const TranslationBlock *tb)
|
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,
|
qemu_log_mask(CPU_LOG_EXEC,
|
||||||
"Trace %d: %p [" TARGET_FMT_lx
|
"Trace %d: %p [" TARGET_FMT_lx
|
||||||
"/" TARGET_FMT_lx "/%08x/%08x] %s\n",
|
"/" TARGET_FMT_lx "/%08x/%08x] %s\n",
|
||||||
@ -286,8 +211,7 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
|||||||
|
|
||||||
#if defined(DEBUG_DISAS)
|
#if defined(DEBUG_DISAS)
|
||||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
|
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
|
||||||
FILE *logfile = qemu_log_trylock();
|
FILE *logfile = qemu_log_lock();
|
||||||
if (logfile) {
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
|
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
|
||||||
@ -296,20 +220,23 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
|||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
flags |= CPU_DUMP_CCOP;
|
flags |= CPU_DUMP_CCOP;
|
||||||
#endif
|
#endif
|
||||||
cpu_dump_state(cpu, logfile, flags);
|
log_cpu_state(cpu, flags);
|
||||||
qemu_log_unlock(logfile);
|
qemu_log_unlock(logfile);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif /* DEBUG_DISAS */
|
#endif /* DEBUG_DISAS */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_for_breakpoints_slow(CPUState *cpu, target_ulong pc,
|
static bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
|
||||||
uint32_t *cflags)
|
uint32_t *cflags)
|
||||||
{
|
{
|
||||||
CPUBreakpoint *bp;
|
CPUBreakpoint *bp;
|
||||||
bool match_page = false;
|
bool match_page = false;
|
||||||
|
|
||||||
|
if (likely(QTAILQ_EMPTY(&cpu->breakpoints))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Singlestep overrides breakpoints.
|
* Singlestep overrides breakpoints.
|
||||||
* This requirement is visible in the record-replay tests, where
|
* 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;
|
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
|
* helper_lookup_tb_ptr: quick check for next tb
|
||||||
* @env: current cpu state
|
* @env: current cpu state
|
||||||
@ -404,9 +324,7 @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
|
|||||||
return tcg_code_gen_epilogue;
|
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;
|
return tb->tc.ptr;
|
||||||
}
|
}
|
||||||
@ -429,9 +347,7 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
|
|||||||
TranslationBlock *last_tb;
|
TranslationBlock *last_tb;
|
||||||
const void *tb_ptr = itb->tc.ptr;
|
const void *tb_ptr = itb->tc.ptr;
|
||||||
|
|
||||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) {
|
log_cpu_exec(itb->pc, cpu, itb);
|
||||||
log_cpu_exec(log_pc(cpu, itb), cpu, itb);
|
|
||||||
}
|
|
||||||
|
|
||||||
qemu_thread_jit_execute();
|
qemu_thread_jit_execute();
|
||||||
ret = tcg_qemu_tb_exec(env, tb_ptr);
|
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.
|
* of the start of the TB.
|
||||||
*/
|
*/
|
||||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
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) {
|
if (cc->tcg_ops->synchronize_from_tb) {
|
||||||
cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
|
cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
|
||||||
} else {
|
} else {
|
||||||
assert(!TARGET_TB_PCREL);
|
|
||||||
assert(cc->set_pc);
|
assert(cc->set_pc);
|
||||||
cc->set_pc(cpu, tb_pc(last_tb));
|
cc->set_pc(cpu, last_tb->pc);
|
||||||
}
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
return last_tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,12 +403,11 @@ static void cpu_exec_exit(CPUState *cpu)
|
|||||||
if (cc->tcg_ops->cpu_exec_exit) {
|
if (cc->tcg_ops->cpu_exec_exit) {
|
||||||
cc->tcg_ops->cpu_exec_exit(cpu);
|
cc->tcg_ops->cpu_exec_exit(cpu);
|
||||||
}
|
}
|
||||||
QEMU_PLUGIN_ASSERT(cpu->plugin_mem_cbs == NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_exec_step_atomic(CPUState *cpu)
|
void cpu_exec_step_atomic(CPUState *cpu)
|
||||||
{
|
{
|
||||||
CPUArchState *env = cpu->env_ptr;
|
CPUArchState *env = (CPUArchState *)cpu->env_ptr;
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
target_ulong cs_base, pc;
|
target_ulong cs_base, pc;
|
||||||
uint32_t flags, cflags;
|
uint32_t flags, cflags;
|
||||||
@ -547,11 +446,12 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
|||||||
cpu_tb_exec(cpu, tb, &tb_exit);
|
cpu_tb_exec(cpu, tb, &tb_exit);
|
||||||
cpu_exec_exit(cpu);
|
cpu_exec_exit(cpu);
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
* The mmap_lock is dropped by tb_gen_code if it runs out of
|
||||||
|
* memory.
|
||||||
|
*/
|
||||||
#ifndef CONFIG_SOFTMMU
|
#ifndef CONFIG_SOFTMMU
|
||||||
clear_helper_retaddr();
|
tcg_debug_assert(!have_mmap_lock());
|
||||||
if (have_mmap_lock()) {
|
|
||||||
mmap_unlock();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (qemu_mutex_iothread_locked()) {
|
if (qemu_mutex_iothread_locked()) {
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
@ -560,6 +460,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
|||||||
qemu_plugin_disable_mem_helpers(cpu);
|
qemu_plugin_disable_mem_helpers(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* As we start the exclusive region before codegen we must still
|
* As we start the exclusive region before codegen we must still
|
||||||
* be in the region if we longjump out of either the codegen or
|
* 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();
|
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)
|
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr)
|
||||||
{
|
{
|
||||||
/*
|
if (TCG_TARGET_HAS_direct_jump) {
|
||||||
* Get the rx view of the structure, from which we find the
|
uintptr_t offset = tb->jmp_target_arg[n];
|
||||||
* executable code address, and tb_target_set_jmp_target can
|
uintptr_t tc_ptr = (uintptr_t)tb->tc.ptr;
|
||||||
* produce a pc-relative displacement to jmp_target_addr[n].
|
uintptr_t jmp_rx = tc_ptr + offset;
|
||||||
*/
|
|
||||||
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;
|
uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff;
|
||||||
|
tb_target_set_jmp_target(tc_ptr, jmp_rx, jmp_rw, addr);
|
||||||
tb->jmp_target_addr[n] = addr;
|
} else {
|
||||||
tb_target_set_jmp_target(c_tb, n, jmp_rx, jmp_rw);
|
tb->jmp_target_arg[n] = addr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
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_spin_unlock(&tb_next->jmp_lock);
|
||||||
|
|
||||||
qemu_log_mask(CPU_LOG_EXEC, "Linking TBs %p index %d -> %p\n",
|
qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
|
||||||
tb->tc.ptr, n, tb_next->tc.ptr);
|
"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;
|
return;
|
||||||
|
|
||||||
out_unlock_next:
|
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)
|
static inline bool cpu_handle_halt(CPUState *cpu)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
if (cpu->halted) {
|
if (cpu->halted) {
|
||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
|
||||||
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
|
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
|
||||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
@ -636,14 +597,13 @@ static inline bool cpu_handle_halt(CPUState *cpu)
|
|||||||
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
|
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
}
|
}
|
||||||
#endif /* TARGET_I386 */
|
#endif
|
||||||
if (!cpu_has_work(cpu)) {
|
if (!cpu_has_work(cpu)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->halted = 0;
|
cpu->halted = 0;
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
|
||||||
|
|
||||||
return false;
|
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)
|
static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||||
{
|
{
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
@ -679,8 +633,6 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
|||||||
if (cpu->exception_index == EXCP_LIBAFL_BP) {
|
if (cpu->exception_index == EXCP_LIBAFL_BP) {
|
||||||
*ret = cpu->exception_index;
|
*ret = cpu->exception_index;
|
||||||
cpu->exception_index = -1;
|
cpu->exception_index = -1;
|
||||||
|
|
||||||
libafl_sync_breakpoint_cpu();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,8 +643,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
|||||||
if (replay_has_exception()
|
if (replay_has_exception()
|
||||||
&& cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0) {
|
&& cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0) {
|
||||||
/* Execute just one insn to trigger exception pending in the log */
|
/* Execute just one insn to trigger exception pending in the log */
|
||||||
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
|
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT) | 1;
|
||||||
| CF_NOIRQ | 1;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
@ -712,8 +663,8 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
|||||||
loop */
|
loop */
|
||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||||
cc->tcg_ops->fake_user_interrupt(cpu);
|
cc->tcg_ops->do_interrupt(cpu);
|
||||||
#endif /* TARGET_I386 */
|
#endif
|
||||||
*ret = cpu->exception_index;
|
*ret = cpu->exception_index;
|
||||||
cpu->exception_index = -1;
|
cpu->exception_index = -1;
|
||||||
return true;
|
return true;
|
||||||
@ -746,7 +697,6 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
/*
|
/*
|
||||||
* CPU_INTERRUPT_POLL is a virtual event which gets converted into a
|
* CPU_INTERRUPT_POLL is a virtual event which gets converted into a
|
||||||
* "real" interrupt event later. It does not need to be recorded for
|
* "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;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
|
||||||
|
|
||||||
static inline bool cpu_handle_interrupt(CPUState *cpu,
|
static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||||
TranslationBlock **last_tb)
|
TranslationBlock **last_tb)
|
||||||
{
|
{
|
||||||
/*
|
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||||
* If we have requested custom cflags with CF_NOIRQ we should
|
|
||||||
* skip checking here. Any pending interrupts will get picked up
|
|
||||||
* by the next TB we execute under normal cflags.
|
|
||||||
*/
|
|
||||||
if (cpu->cflags_next_tb != -1 && cpu->cflags_next_tb & CF_NOIRQ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear the interrupt flag now since we're processing
|
/* Clear the interrupt flag now since we're processing
|
||||||
* cpu->interrupt_request and cpu->exit_request.
|
* cpu->interrupt_request and cpu->exit_request.
|
||||||
@ -795,7 +737,6 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
|||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
|
||||||
if (replay_mode == REPLAY_MODE_PLAY && !replay_has_interrupt()) {
|
if (replay_mode == REPLAY_MODE_PLAY && !replay_has_interrupt()) {
|
||||||
/* Do nothing */
|
/* Do nothing */
|
||||||
} else if (interrupt_request & CPU_INTERRUPT_HALT) {
|
} else if (interrupt_request & CPU_INTERRUPT_HALT) {
|
||||||
@ -824,14 +765,12 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
|||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif /* !TARGET_I386 */
|
#endif
|
||||||
/* The target hook has 3 exit conditions:
|
/* The target hook has 3 exit conditions:
|
||||||
False when the interrupt isn't processed,
|
False when the interrupt isn't processed,
|
||||||
True when it is, and we should restart on a new TB,
|
True when it is, and we should restart on a new TB,
|
||||||
and via longjmp via cpu_loop_exit. */
|
and via longjmp via cpu_loop_exit. */
|
||||||
else {
|
else {
|
||||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
|
||||||
|
|
||||||
if (cc->tcg_ops->cpu_exec_interrupt &&
|
if (cc->tcg_ops->cpu_exec_interrupt &&
|
||||||
cc->tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
|
cc->tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||||
if (need_replay_interrupt(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
|
* raised when single-stepping so that GDB doesn't miss the
|
||||||
* next instruction.
|
* next instruction.
|
||||||
*/
|
*/
|
||||||
if (unlikely(cpu->singlestep_enabled)) {
|
cpu->exception_index =
|
||||||
cpu->exception_index = EXCP_DEBUG;
|
(cpu->singlestep_enabled ? EXCP_DEBUG : -1);
|
||||||
qemu_mutex_unlock_iothread();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
cpu->exception_index = -1;
|
|
||||||
*last_tb = NULL;
|
*last_tb = NULL;
|
||||||
}
|
}
|
||||||
/* The target hook may have updated the 'cpu->interrupt_request';
|
/* The target hook may have updated the 'cpu->interrupt_request';
|
||||||
* reload the 'interrupt_request' value */
|
* reload the 'interrupt_request' value */
|
||||||
interrupt_request = cpu->interrupt_request;
|
interrupt_request = cpu->interrupt_request;
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
|
||||||
if (interrupt_request & CPU_INTERRUPT_EXITTB) {
|
if (interrupt_request & CPU_INTERRUPT_EXITTB) {
|
||||||
cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
|
cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
|
||||||
/* ensure that no TB jump will be modified as
|
/* 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,
|
static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||||
target_ulong pc,
|
|
||||||
TranslationBlock **last_tb, int *tb_exit)
|
TranslationBlock **last_tb, int *tb_exit)
|
||||||
{
|
{
|
||||||
int32_t insns_left;
|
int32_t insns_left;
|
||||||
|
|
||||||
trace_exec_tb(tb, pc);
|
trace_exec_tb(tb, tb->pc);
|
||||||
tb = cpu_tb_exec(cpu, tb, tb_exit);
|
tb = cpu_tb_exec(cpu, tb, tb_exit);
|
||||||
if (*tb_exit != TB_EXIT_REQUESTED) {
|
if (*tb_exit != TB_EXIT_REQUESTED) {
|
||||||
*last_tb = tb;
|
*last_tb = tb;
|
||||||
@ -933,19 +866,69 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
|||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
|
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);
|
uint32_t flags, int cflags);
|
||||||
|
void libafl_exec_edge_one_off(target_ulong src_block, target_ulong dst_block);
|
||||||
extern __thread int libafl_valid_current_cpu;
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
/* main execution loop */
|
/* main execution loop */
|
||||||
|
|
||||||
static int __attribute__((noinline))
|
int cpu_exec(CPUState *cpu)
|
||||||
cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
|
||||||
{
|
{
|
||||||
int ret;
|
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 */
|
/* if an exception is pending, we execute it here */
|
||||||
while (!cpu_handle_exception(cpu, &ret)) {
|
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);
|
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
|
||||||
if (tb == NULL) {
|
if (tb == NULL) {
|
||||||
uint32_t h;
|
|
||||||
|
|
||||||
mmap_lock();
|
mmap_lock();
|
||||||
tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
|
tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
|
||||||
mmap_unlock();
|
mmap_unlock();
|
||||||
@ -988,9 +969,14 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
|||||||
* We add the TB in the virtual pc hash table
|
* We add the TB in the virtual pc hash table
|
||||||
* for the fast lookup
|
* for the fast lookup
|
||||||
*/
|
*/
|
||||||
h = tb_jmp_cache_hash_func(pc);
|
qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
|
||||||
tb_jmp_cache_set(cpu->tb_jmp_cache, h, tb, pc);
|
|
||||||
}
|
}
|
||||||
|
//// --- 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
|
#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
|
* direct jump to a TB spanning two pages because the mapping
|
||||||
* for the second page can change.
|
* for the second page can change.
|
||||||
*/
|
*/
|
||||||
if (tb_page_addr1(tb) != -1) {
|
if (tb->page_addr[1] != -1) {
|
||||||
last_tb = NULL;
|
last_tb = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1009,11 +995,10 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
#if !TARGET_TB_PCREL
|
if (last_tb->jmp_reset_offset[1] != TB_JMP_RESET_OFFSET_INVALID) {
|
||||||
if (last_tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
|
|
||||||
mmap_lock();
|
mmap_lock();
|
||||||
TranslationBlock *edge = libafl_gen_edge(cpu, tb_pc(last_tb), tb_pc(tb),
|
TranslationBlock *edge = libafl_gen_edge(cpu, last_tb->pc, tb->pc,
|
||||||
tb_exit, cs_base, flags, cflags);
|
cs_base, flags, cflags);
|
||||||
mmap_unlock();
|
mmap_unlock();
|
||||||
|
|
||||||
if (edge) {
|
if (edge) {
|
||||||
@ -1025,79 +1010,17 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
|||||||
} else {
|
} else {
|
||||||
tb_add_jump(last_tb, tb_exit, tb);
|
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 ---
|
//// --- 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
|
/* Try to align the host and virtual clocks
|
||||||
if the guest is in advance */
|
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);
|
cpu_exec_exit(cpu);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
@ -1114,13 +1037,12 @@ void tcg_exec_realizefn(CPUState *cpu, Error **errp)
|
|||||||
cc->tcg_ops->initialize();
|
cc->tcg_ops->initialize();
|
||||||
tcg_target_initialized = true;
|
tcg_target_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->tb_jmp_cache = g_new0(CPUJumpCache, 1);
|
|
||||||
tlb_init(cpu);
|
tlb_init(cpu);
|
||||||
|
qemu_plugin_vcpu_init_hook(cpu);
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
tcg_iommu_init_notifier_list(cpu);
|
tcg_iommu_init_notifier_list(cpu);
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
/* qemu_plugin_vcpu_init_hook delayed until cpu_index assigned. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undo the initializations in reverse order */
|
/* undo the initializations in reverse order */
|
||||||
@ -1130,89 +1052,29 @@ void tcg_exec_unrealizefn(CPUState *cpu)
|
|||||||
tcg_iommu_free_notifier_list(cpu);
|
tcg_iommu_free_notifier_list(cpu);
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
|
qemu_plugin_vcpu_exit_hook(cpu);
|
||||||
tlb_destroy(cpu);
|
tlb_destroy(cpu);
|
||||||
g_free_rcu(cpu->tb_jmp_cache, rcu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
|
||||||
static void dump_drift_info(GString *buf)
|
void dump_drift_info(void)
|
||||||
{
|
{
|
||||||
if (!icount_enabled()) {
|
if (!icount_enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_string_append_printf(buf, "Host - Guest clock %"PRIi64" ms\n",
|
qemu_printf("Host - Guest clock %"PRIi64" ms\n",
|
||||||
(cpu_get_clock() - icount_get()) / SCALE_MS);
|
(cpu_get_clock() - icount_get()) / SCALE_MS);
|
||||||
if (icount_align_option) {
|
if (icount_align_option) {
|
||||||
g_string_append_printf(buf, "Max guest delay %"PRIi64" ms\n",
|
qemu_printf("Max guest delay %"PRIi64" ms\n",
|
||||||
-max_delay / SCALE_MS);
|
-max_delay / SCALE_MS);
|
||||||
g_string_append_printf(buf, "Max guest advance %"PRIi64" ms\n",
|
qemu_printf("Max guest advance %"PRIi64" ms\n",
|
||||||
max_advance / SCALE_MS);
|
max_advance / SCALE_MS);
|
||||||
} else {
|
} else {
|
||||||
g_string_append_printf(buf, "Max guest delay NA\n");
|
qemu_printf("Max guest delay NA\n");
|
||||||
g_string_append_printf(buf, "Max guest advance 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 */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
1034
accel/tcg/cputlb.c
1034
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/osdep.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qapi/error.h"
|
|
||||||
#include "qapi/qapi-commands-machine.h"
|
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "monitor/monitor.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)
|
static void hmp_tcg_register(void)
|
||||||
{
|
{
|
||||||
monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
|
monitor_register_hmp("jit", true, hmp_info_jit);
|
||||||
monitor_register_hmp_info_hrt("opcount", qmp_x_query_opcount);
|
monitor_register_hmp("opcount", true, hmp_info_opcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(hmp_tcg_register);
|
type_init(hmp_tcg_register);
|
||||||
|
@ -11,57 +11,12 @@
|
|||||||
|
|
||||||
#include "exec/exec-all.h"
|
#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,
|
TranslationBlock *tb_gen_code(CPUState *cpu, target_ulong pc,
|
||||||
target_ulong cs_base, uint32_t flags,
|
target_ulong cs_base, uint32_t flags,
|
||||||
int cflags);
|
int cflags);
|
||||||
|
|
||||||
|
void QEMU_NORETURN cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
|
||||||
void page_init(void);
|
void page_init(void);
|
||||||
void tb_htable_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 */
|
#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',
|
'tcg-all.c',
|
||||||
'cpu-exec-common.c',
|
'cpu-exec-common.c',
|
||||||
'cpu-exec.c',
|
'cpu-exec.c',
|
||||||
'tb-maint.c',
|
|
||||||
'tcg-runtime-gvec.c',
|
'tcg-runtime-gvec.c',
|
||||||
'tcg-runtime.c',
|
'tcg-runtime.c',
|
||||||
'translate-all.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_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_SOFTMMU', if_false: files('user-exec-stub.c'))
|
||||||
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c')])
|
tcg_ss.add(when: 'CONFIG_PLUGIN', if_true: [files('plugin-gen.c'), libdl])
|
||||||
tcg_ss.add(when: libdw, if_true: files('debuginfo.c'))
|
|
||||||
tcg_ss.add(when: 'CONFIG_LINUX', if_true: files('perf.c'))
|
|
||||||
specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
|
specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
|
||||||
|
|
||||||
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files(
|
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 "qemu/osdep.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
#include "tcg/tcg-op.h"
|
#include "tcg/tcg-op.h"
|
||||||
|
#include "trace/mem.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "exec/plugin-gen.h"
|
#include "exec/plugin-gen.h"
|
||||||
#include "exec/translator.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,
|
static void gen_plugin_cb_start(enum plugin_gen_from from,
|
||||||
enum plugin_gen_cb type, unsigned wr)
|
enum plugin_gen_cb type, unsigned wr)
|
||||||
{
|
{
|
||||||
|
TCGOp *op;
|
||||||
|
|
||||||
tcg_gen_plugin_cb_start(from, type, wr);
|
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,
|
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,
|
const union mem_gen_fn *f, TCGv addr,
|
||||||
uint32_t info, bool is_mem)
|
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) {
|
if (is_mem) {
|
||||||
f->mem_fn(addr, info);
|
f->mem_fn(addr, info);
|
||||||
} else {
|
} else {
|
||||||
@ -258,13 +263,10 @@ static TCGOp *rm_ops(TCGOp *op)
|
|||||||
|
|
||||||
static TCGOp *copy_op_nocheck(TCGOp **begin_op, TCGOp *op)
|
static TCGOp *copy_op_nocheck(TCGOp **begin_op, TCGOp *op)
|
||||||
{
|
{
|
||||||
TCGOp *old_op = QTAILQ_NEXT(*begin_op, link);
|
*begin_op = QTAILQ_NEXT(*begin_op, link);
|
||||||
unsigned nargs = old_op->nargs;
|
tcg_debug_assert(*begin_op);
|
||||||
|
op = tcg_op_insert_after(tcg_ctx, op, (*begin_op)->opc);
|
||||||
*begin_op = old_op;
|
memcpy(op->args, (*begin_op)->args, sizeof(op->args));
|
||||||
op = tcg_op_insert_after(tcg_ctx, op, old_op->opc, nargs);
|
|
||||||
memcpy(op->args, old_op->args, sizeof(op->args[0]) * nargs);
|
|
||||||
|
|
||||||
return op;
|
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,
|
static TCGOp *copy_call(TCGOp **begin_op, TCGOp *op, void *empty_func,
|
||||||
void *func, int *cb_idx)
|
void *func, int *cb_idx)
|
||||||
{
|
{
|
||||||
TCGOp *old_op;
|
|
||||||
int func_idx;
|
|
||||||
|
|
||||||
/* copy all ops until the call */
|
/* copy all ops until the call */
|
||||||
do {
|
do {
|
||||||
op = copy_op_nocheck(begin_op, op);
|
op = copy_op_nocheck(begin_op, op);
|
||||||
} while (op->opc != INDEX_op_call);
|
} while (op->opc != INDEX_op_call);
|
||||||
|
|
||||||
/* fill in the op call */
|
/* fill in the op call */
|
||||||
old_op = *begin_op;
|
op->param1 = (*begin_op)->param1;
|
||||||
TCGOP_CALLI(op) = TCGOP_CALLI(old_op);
|
op->param2 = (*begin_op)->param2;
|
||||||
TCGOP_CALLO(op) = TCGOP_CALLO(old_op);
|
|
||||||
tcg_debug_assert(op->life == 0);
|
tcg_debug_assert(op->life == 0);
|
||||||
|
if (*cb_idx == -1) {
|
||||||
|
int i;
|
||||||
|
|
||||||
func_idx = TCGOP_CALLO(op) + TCGOP_CALLI(op);
|
/*
|
||||||
*cb_idx = func_idx;
|
* Instead of working out the position of the callback in args[], just
|
||||||
op->args[func_idx] = (uintptr_t)func;
|
* 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;
|
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);
|
op = copy_const_ptr(&begin_op, op, cb->userp);
|
||||||
|
|
||||||
/* copy the ld_i32, but note that we only have to copy it once */
|
/* copy the ld_i32, but note that we only have to copy it once */
|
||||||
if (*cb_idx == -1) {
|
|
||||||
op = copy_op(&begin_op, op, INDEX_op_ld_i32);
|
|
||||||
} else {
|
|
||||||
begin_op = QTAILQ_NEXT(begin_op, link);
|
begin_op = QTAILQ_NEXT(begin_op, link);
|
||||||
tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
|
tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
|
||||||
|
if (*cb_idx == -1) {
|
||||||
|
op = tcg_op_insert_after(tcg_ctx, op, INDEX_op_ld_i32);
|
||||||
|
memcpy(op->args, begin_op->args, sizeof(op->args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call */
|
/* 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);
|
op = copy_const_ptr(&begin_op, op, cb->userp);
|
||||||
|
|
||||||
/* copy the ld_i32, but note that we only have to copy it once */
|
/* copy the ld_i32, but note that we only have to copy it once */
|
||||||
if (*cb_idx == -1) {
|
|
||||||
op = copy_op(&begin_op, op, INDEX_op_ld_i32);
|
|
||||||
} else {
|
|
||||||
begin_op = QTAILQ_NEXT(begin_op, link);
|
begin_op = QTAILQ_NEXT(begin_op, link);
|
||||||
tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
|
tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
|
||||||
|
if (*cb_idx == -1) {
|
||||||
|
op = tcg_op_insert_after(tcg_ctx, op, INDEX_op_ld_i32);
|
||||||
|
memcpy(op->args, begin_op->args, sizeof(op->args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* extu_tl_i64 */
|
/* 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
|
* is possible that the code we generate after the instruction is
|
||||||
* dead, we also add checks before generating tb_exit etc.
|
* dead, we also add checks before generating tb_exit etc.
|
||||||
*/
|
*/
|
||||||
static void inject_mem_enable_helper(struct qemu_plugin_tb *ptb,
|
static void inject_mem_enable_helper(struct qemu_plugin_insn *plugin_insn,
|
||||||
struct qemu_plugin_insn *plugin_insn,
|
|
||||||
TCGOp *begin_op)
|
TCGOp *begin_op)
|
||||||
{
|
{
|
||||||
GArray *cbs[2];
|
GArray *cbs[2];
|
||||||
@ -600,7 +610,6 @@ static void inject_mem_enable_helper(struct qemu_plugin_tb *ptb,
|
|||||||
rm_ops(begin_op);
|
rm_ops(begin_op);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ptb->mem_helper = true;
|
|
||||||
|
|
||||||
arr = g_array_sized_new(false, false,
|
arr = g_array_sized_new(false, false,
|
||||||
sizeof(struct qemu_plugin_dyn_cb), n_cbs);
|
sizeof(struct qemu_plugin_dyn_cb), n_cbs);
|
||||||
@ -628,22 +637,15 @@ void plugin_gen_disable_mem_helpers(void)
|
|||||||
{
|
{
|
||||||
TCGv_ptr ptr;
|
TCGv_ptr ptr;
|
||||||
|
|
||||||
/*
|
if (likely(tcg_ctx->plugin_insn == NULL ||
|
||||||
* We could emit the clearing unconditionally and be done. However, this can
|
!tcg_ctx->plugin_insn->mem_helper)) {
|
||||||
* 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) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ptr = tcg_const_ptr(NULL);
|
ptr = tcg_const_ptr(NULL);
|
||||||
tcg_gen_st_ptr(ptr, cpu_env, offsetof(CPUState, plugin_mem_cbs) -
|
tcg_gen_st_ptr(ptr, cpu_env, offsetof(CPUState, plugin_mem_cbs) -
|
||||||
offsetof(ArchCPU, env));
|
offsetof(ArchCPU, env));
|
||||||
tcg_temp_free_ptr(ptr);
|
tcg_temp_free_ptr(ptr);
|
||||||
|
tcg_ctx->plugin_insn->mem_helper = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_gen_tb_udata(const struct qemu_plugin_tb *ptb,
|
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);
|
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)
|
TCGOp *begin_op, int insn_idx)
|
||||||
{
|
{
|
||||||
struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, 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)
|
TCGOp *begin_op, int insn_idx)
|
||||||
{
|
{
|
||||||
struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
|
struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
|
||||||
inject_mem_disable_helper(insn, begin_op);
|
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 */
|
/* #define DEBUG_PLUGIN_GEN_OPS */
|
||||||
static void pr_ops(void)
|
static void pr_ops(void)
|
||||||
{
|
{
|
||||||
@ -759,133 +817,45 @@ static void pr_ops(void)
|
|||||||
#endif
|
#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;
|
TCGOp *op;
|
||||||
int insn_idx = -1;
|
int insn_idx;
|
||||||
|
|
||||||
pr_ops();
|
pr_ops();
|
||||||
|
insn_idx = -1;
|
||||||
QTAILQ_FOREACH(op, &tcg_ctx->ops, link) {
|
QSIMPLEQ_FOREACH(op, &tcg_ctx->plugin_ops, plugin_link) {
|
||||||
switch (op->opc) {
|
|
||||||
case INDEX_op_insn_start:
|
|
||||||
insn_idx++;
|
|
||||||
break;
|
|
||||||
case INDEX_op_plugin_cb_start:
|
|
||||||
{
|
|
||||||
enum plugin_gen_from from = op->args[0];
|
enum plugin_gen_from from = op->args[0];
|
||||||
enum plugin_gen_cb type = op->args[1];
|
enum plugin_gen_cb type = op->args[1];
|
||||||
|
|
||||||
switch (from) {
|
tcg_debug_assert(op->opc == INDEX_op_plugin_cb_start);
|
||||||
case PLUGIN_GEN_FROM_TB:
|
/* ENABLE_MEM_HELPER is the first callback of an instruction */
|
||||||
{
|
if (from == PLUGIN_GEN_FROM_INSN &&
|
||||||
g_assert(insn_idx == -1);
|
type == PLUGIN_GEN_ENABLE_MEM_HELPER) {
|
||||||
|
insn_idx++;
|
||||||
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();
|
pr_ops();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db,
|
bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_only)
|
||||||
bool mem_only)
|
|
||||||
{
|
{
|
||||||
|
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
if (test_bit(QEMU_PLUGIN_EV_VCPU_TB_TRANS, cpu->plugin_mask)) {
|
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;
|
ret = true;
|
||||||
|
|
||||||
ptb->vaddr = db->pc_first;
|
QSIMPLEQ_INIT(&tcg_ctx->plugin_ops);
|
||||||
|
ptb->vaddr = tb->pc;
|
||||||
ptb->vaddr2 = -1;
|
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->haddr2 = NULL;
|
||||||
ptb->mem_only = mem_only;
|
ptb->mem_only = mem_only;
|
||||||
ptb->mem_helper = false;
|
|
||||||
|
|
||||||
plugin_gen_empty_callback(PLUGIN_GEN_FROM_TB);
|
plugin_gen_empty_callback(PLUGIN_GEN_FROM_TB);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_ctx->plugin_insn = NULL;
|
|
||||||
|
|
||||||
return ret;
|
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_tb *ptb = tcg_ctx->plugin_tb;
|
||||||
struct qemu_plugin_insn *pinsn;
|
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;
|
tcg_ctx->plugin_insn = pinsn;
|
||||||
|
pinsn->vaddr = db->pc_next;
|
||||||
plugin_gen_empty_callback(PLUGIN_GEN_FROM_INSN);
|
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
|
* Note that we skip this when haddr1 == NULL, e.g. when we're
|
||||||
* fetching instructions from a region not backed by RAM.
|
* fetching instructions from a region not backed by RAM.
|
||||||
*/
|
*/
|
||||||
if (ptb->haddr1 == NULL) {
|
if (likely(ptb->haddr1 != NULL && ptb->vaddr2 == -1) &&
|
||||||
pinsn->haddr = NULL;
|
unlikely((db->pc_next & TARGET_PAGE_MASK) !=
|
||||||
} else if (is_same_page(db, db->pc_next)) {
|
(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;
|
pinsn->haddr = ptb->haddr1 + pinsn->vaddr - ptb->vaddr;
|
||||||
} else {
|
} 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;
|
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);
|
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)
|
void plugin_gen_tb_end(CPUState *cpu)
|
||||||
{
|
{
|
||||||
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* collect instrumentation requests */
|
/* collect instrumentation requests */
|
||||||
qemu_plugin_tb_trans_cb(cpu, ptb);
|
qemu_plugin_tb_trans_cb(cpu, ptb);
|
||||||
|
|
||||||
/* inject the instrumentation at the appropriate places */
|
/* inject the instrumentation at the appropriate places */
|
||||||
plugin_gen_inject(ptb);
|
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
|
#ifdef CONFIG_PLUGIN
|
||||||
DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, void, i32, 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 | TCG_CALL_PLUGIN, void, i32, i32, i64, ptr)
|
DEF_HELPER_FLAGS_4(plugin_vcpu_mem_cb, TCG_CALL_NO_RWG, void, i32, i32, i64, ptr)
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include "exec/cpu-defs.h"
|
#include "exec/cpu-defs.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "qemu/xxhash.h"
|
#include "qemu/xxhash.h"
|
||||||
#include "tb-jmp-cache.h"
|
|
||||||
|
|
||||||
#ifdef CONFIG_SOFTMMU
|
#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/osdep.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "sysemu/tcg.h"
|
||||||
#include "sysemu/replay.h"
|
#include "sysemu/replay.h"
|
||||||
#include "sysemu/cpu-timers.h"
|
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
#include "exec/exec-all.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
|
* Don't interrupt cpu thread, when these events are waiting
|
||||||
* (i.e., there is no checkpoint)
|
* (i.e., there is no checkpoint)
|
||||||
*/
|
*/
|
||||||
if (deadline == 0) {
|
if (deadline == 0
|
||||||
|
&& (replay_mode != REPLAY_MODE_PLAY || replay_has_checkpoint())) {
|
||||||
icount_notify_aio_contexts();
|
icount_notify_aio_contexts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,14 +110,8 @@ void icount_prepare_for_run(CPUState *cpu)
|
|||||||
|
|
||||||
replay_mutex_lock();
|
replay_mutex_lock();
|
||||||
|
|
||||||
if (cpu->icount_budget == 0) {
|
if (cpu->icount_budget == 0 && replay_has_checkpoint()) {
|
||||||
/*
|
|
||||||
* We're called without the iothread lock, so must take it while
|
|
||||||
* we're calling timer handlers.
|
|
||||||
*/
|
|
||||||
qemu_mutex_lock_iothread();
|
|
||||||
icount_notify_aio_contexts();
|
icount_notify_aio_contexts();
|
||||||
qemu_mutex_unlock_iothread();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
* See the COPYING file in the top-level directory.
|
* See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TCG_ACCEL_OPS_ICOUNT_H
|
#ifndef TCG_CPUS_ICOUNT_H
|
||||||
#define TCG_ACCEL_OPS_ICOUNT_H
|
#define TCG_CPUS_ICOUNT_H
|
||||||
|
|
||||||
void icount_handle_deadline(void);
|
void icount_handle_deadline(void);
|
||||||
void icount_prepare_for_run(CPUState *cpu);
|
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);
|
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/osdep.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
#include "sysemu/tcg.h"
|
#include "sysemu/tcg.h"
|
||||||
#include "sysemu/replay.h"
|
#include "sysemu/replay.h"
|
||||||
#include "sysemu/cpu-timers.h"
|
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "qemu/notify.h"
|
#include "qemu/notify.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
@ -142,7 +142,7 @@ void mttcg_start_vcpu_thread(CPUState *cpu)
|
|||||||
g_assert(tcg_enabled());
|
g_assert(tcg_enabled());
|
||||||
tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1);
|
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));
|
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||||
qemu_cond_init(cpu->halt_cond);
|
qemu_cond_init(cpu->halt_cond);
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
* See the COPYING file in the top-level directory.
|
* See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TCG_ACCEL_OPS_MTTCG_H
|
#ifndef TCG_CPUS_MTTCG_H
|
||||||
#define TCG_ACCEL_OPS_MTTCG_H
|
#define TCG_CPUS_MTTCG_H
|
||||||
|
|
||||||
/* kick MTTCG vCPU thread */
|
/* kick MTTCG vCPU thread */
|
||||||
void mttcg_kick_vcpu_thread(CPUState *cpu);
|
void mttcg_kick_vcpu_thread(CPUState *cpu);
|
||||||
@ -16,4 +16,4 @@ void mttcg_kick_vcpu_thread(CPUState *cpu);
|
|||||||
/* start an mttcg vCPU thread */
|
/* start an mttcg vCPU thread */
|
||||||
void mttcg_start_vcpu_thread(CPUState *cpu);
|
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/osdep.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
#include "sysemu/tcg.h"
|
#include "sysemu/tcg.h"
|
||||||
#include "sysemu/replay.h"
|
#include "sysemu/replay.h"
|
||||||
#include "sysemu/cpu-timers.h"
|
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "qemu/notify.h"
|
#include "qemu/notify.h"
|
||||||
#include "qemu/guest-random.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
|
* The kick timer is responsible for moving single threaded vCPU
|
||||||
* emulation on to the next vCPU. If more than one vCPU is running a
|
* 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.
|
* scheduled.
|
||||||
*
|
*
|
||||||
* The timer is removed if all vCPUs are idle and restarted again once
|
* 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 QEMUTimer *rr_kick_vcpu_timer;
|
||||||
static CPUState *rr_current_cpu;
|
static CPUState *rr_current_cpu;
|
||||||
|
|
||||||
|
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
|
||||||
|
|
||||||
static inline int64_t rr_next_kick_time(void)
|
static inline int64_t rr_next_kick_time(void)
|
||||||
{
|
{
|
||||||
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
|
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);
|
tcg_cpu_init_cflags(cpu, false);
|
||||||
|
|
||||||
if (!single_tcg_cpu_thread) {
|
if (!single_tcg_cpu_thread) {
|
||||||
cpu->thread = g_new0(QemuThread, 1);
|
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||||
cpu->halt_cond = g_new0(QemuCond, 1);
|
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||||
qemu_cond_init(cpu->halt_cond);
|
qemu_cond_init(cpu->halt_cond);
|
||||||
|
|
||||||
/* share a single thread for all cpus with TCG */
|
/* share a single thread for all cpus with TCG */
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
* See the COPYING file in the top-level directory.
|
* See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TCG_ACCEL_OPS_RR_H
|
#ifndef TCG_CPUS_RR_H
|
||||||
#define TCG_ACCEL_OPS_RR_H
|
#define TCG_CPUS_RR_H
|
||||||
|
|
||||||
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
|
#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 */
|
/* start the round robin vcpu thread */
|
||||||
void rr_start_vcpu_thread(CPUState *cpu);
|
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/osdep.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
#include "sysemu/tcg.h"
|
#include "sysemu/tcg.h"
|
||||||
#include "sysemu/replay.h"
|
#include "sysemu/replay.h"
|
||||||
#include "sysemu/cpu-timers.h"
|
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "exec/hwaddr.h"
|
|
||||||
#include "exec/gdbstub.h"
|
|
||||||
|
|
||||||
#include "tcg-accel-ops.h"
|
#include "tcg-accel-ops.h"
|
||||||
#include "tcg-accel-ops-mttcg.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)
|
static void tcg_accel_ops_init(AccelOpsClass *ops)
|
||||||
{
|
{
|
||||||
if (qemu_tcg_mttcg_enabled()) {
|
if (qemu_tcg_mttcg_enabled()) {
|
||||||
ops->create_vcpu_thread = mttcg_start_vcpu_thread;
|
ops->create_vcpu_thread = mttcg_start_vcpu_thread;
|
||||||
ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
|
ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
|
||||||
ops->handle_interrupt = tcg_handle_interrupt;
|
ops->handle_interrupt = tcg_handle_interrupt;
|
||||||
} else {
|
} else if (icount_enabled()) {
|
||||||
ops->create_vcpu_thread = rr_start_vcpu_thread;
|
ops->create_vcpu_thread = rr_start_vcpu_thread;
|
||||||
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
|
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
|
||||||
|
|
||||||
if (icount_enabled()) {
|
|
||||||
ops->handle_interrupt = icount_handle_interrupt;
|
ops->handle_interrupt = icount_handle_interrupt;
|
||||||
ops->get_virtual_clock = icount_get;
|
ops->get_virtual_clock = icount_get;
|
||||||
ops->get_elapsed_ticks = icount_get;
|
ops->get_elapsed_ticks = icount_get;
|
||||||
} else {
|
} else {
|
||||||
|
ops->create_vcpu_thread = rr_start_vcpu_thread;
|
||||||
|
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
|
||||||
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)
|
static void tcg_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
* See the COPYING file in the top-level directory.
|
* See the COPYING file in the top-level directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TCG_ACCEL_OPS_H
|
#ifndef TCG_CPUS_H
|
||||||
#define TCG_ACCEL_OPS_H
|
#define TCG_CPUS_H
|
||||||
|
|
||||||
#include "sysemu/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_handle_interrupt(CPUState *cpu, int mask);
|
||||||
void tcg_cpu_init_cflags(CPUState *cpu, bool parallel);
|
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/osdep.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
#include "sysemu/tcg.h"
|
#include "sysemu/tcg.h"
|
||||||
#include "sysemu/replay.h"
|
|
||||||
#include "sysemu/cpu-timers.h"
|
#include "sysemu/cpu-timers.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
@ -83,14 +83,6 @@ static bool check_tcg_memory_orders_compatible(void)
|
|||||||
|
|
||||||
static bool default_mttcg_enabled(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) {
|
if (icount_enabled() || TCG_OVERSIZED_GUEST) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -216,28 +208,12 @@ static void tcg_set_splitwx(Object *obj, bool value, Error **errp)
|
|||||||
s->splitwx_enabled = value;
|
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)
|
static void tcg_accel_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
AccelClass *ac = ACCEL_CLASS(oc);
|
AccelClass *ac = ACCEL_CLASS(oc);
|
||||||
ac->name = "tcg";
|
ac->name = "tcg";
|
||||||
ac->init_machine = tcg_init_machine;
|
ac->init_machine = tcg_init_machine;
|
||||||
ac->allowed = &tcg_allowed;
|
ac->allowed = &tcg_allowed;
|
||||||
ac->gdbstub_supported_sstep_flags = tcg_gdbstub_supported_sstep_flags;
|
|
||||||
|
|
||||||
object_class_property_add_str(oc, "thread",
|
object_class_property_add_str(oc, "thread",
|
||||||
tcg_get_thread,
|
tcg_get_thread,
|
||||||
|
@ -33,145 +33,13 @@
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- 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
|
#define EXCP_LIBAFL_BP 0xf4775747
|
||||||
|
|
||||||
int libafl_qemu_break_asap = 0;
|
void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env)
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
CPUState* cpu = env_cpu(env);
|
CPUState* cpu = env_cpu(env);
|
||||||
libafl_breakpoint_pc = pc;
|
cpu->exception_index = EXCP_LIBAFL_BP;
|
||||||
libafl_qemu_trigger_breakpoint(cpu);
|
cpu_loop_exit(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- 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,
|
DEF_HELPER_FLAGS_5(atomic_cmpxchgq_le, TCG_CALL_NO_WG,
|
||||||
i64, env, tl, i64, i64, i32)
|
i64, env, tl, i64, i64, i32)
|
||||||
#endif
|
#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
|
#ifdef CONFIG_ATOMIC64
|
||||||
#define GEN_ATOMIC_HELPERS(NAME) \
|
#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 ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
DEF_HELPER_FLAGS_2(libafl_qemu_handle_breakpoint, TCG_CALL_NO_RWG,
|
DEF_HELPER_FLAGS_1(libafl_qemu_handle_breakpoint, TCG_CALL_NO_RWG, void, env)
|
||||||
void, env, tl)
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- 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_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"
|
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-all.c
|
||||||
translate_block(void *tb, uintptr_t pc, const void *tb_code) "tb:%p, pc:0x%"PRIxPTR", tb_code:%p"
|
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"
|
#include "tcg/tcg-internal.h"
|
||||||
|
|
||||||
extern target_ulong libafl_gen_cur_pc;
|
|
||||||
|
|
||||||
struct libafl_breakpoint {
|
struct libafl_breakpoint {
|
||||||
target_ulong addr;
|
target_ulong addr;
|
||||||
struct libafl_breakpoint* next;
|
struct libafl_breakpoint* next;
|
||||||
@ -34,24 +32,13 @@ extern struct libafl_breakpoint* libafl_qemu_breakpoints;
|
|||||||
struct libafl_hook {
|
struct libafl_hook {
|
||||||
target_ulong addr;
|
target_ulong addr;
|
||||||
void (*callback)(uint64_t);
|
void (*callback)(uint64_t);
|
||||||
uint64_t data;
|
uint64_t value;
|
||||||
TCGHelperInfo helper_info;
|
TCGHelperInfo helper_info;
|
||||||
struct libafl_hook* next;
|
struct libafl_hook* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct libafl_hook* libafl_qemu_hooks;
|
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 ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
/* Pairs with tcg_clear_temp_count.
|
/* 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;
|
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
|
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||||
target_ulong pc, void *host_pc,
|
CPUState *cpu, TranslationBlock *tb, int max_insns)
|
||||||
const TranslatorOps *ops, DisasContextBase *db)
|
|
||||||
{
|
{
|
||||||
uint32_t cflags = tb_cflags(tb);
|
uint32_t cflags = tb_cflags(tb);
|
||||||
bool plugin_enabled;
|
bool plugin_enabled;
|
||||||
|
|
||||||
/* Initialize DisasContext */
|
/* Initialize DisasContext */
|
||||||
db->tb = tb;
|
db->tb = tb;
|
||||||
db->pc_first = pc;
|
db->pc_first = tb->pc;
|
||||||
db->pc_next = pc;
|
db->pc_next = db->pc_first;
|
||||||
db->is_jmp = DISAS_NEXT;
|
db->is_jmp = DISAS_NEXT;
|
||||||
db->num_insns = 0;
|
db->num_insns = 0;
|
||||||
db->max_insns = max_insns;
|
db->max_insns = max_insns;
|
||||||
db->singlestep_enabled = cflags & CF_SINGLE_STEP;
|
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);
|
ops->init_disas_context(db, cpu);
|
||||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
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);
|
ops->tb_start(db, cpu);
|
||||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
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) {
|
while (true) {
|
||||||
db->num_insns++;
|
db->num_insns++;
|
||||||
@ -124,75 +104,25 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
struct libafl_hook* hk = libafl_search_hook(db->pc_next);
|
struct libafl_hook* hk = libafl_qemu_hooks;
|
||||||
if (hk) {
|
while (hk) {
|
||||||
TCGv tmp0 = tcg_const_tl(db->pc_next);
|
if (hk->addr == db->pc_next) {
|
||||||
TCGv_i64 tmp1 = tcg_const_i64(hk->data);
|
TCGv_i64 tmp0 = tcg_const_i64(hk->value);
|
||||||
#if TARGET_LONG_BITS == 32
|
TCGTemp *tmp1[1] = { tcgv_i64_temp(tmp0) };
|
||||||
TCGTemp *tmp2[2] = { tcgv_i32_temp(tmp0), tcgv_i64_temp(tmp1) };
|
tcg_gen_callN(hk->callback, NULL, 1, 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);
|
tcg_temp_free_i64(tmp0);
|
||||||
#endif
|
}
|
||||||
tcg_temp_free_i64(tmp1);
|
hk = hk->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct libafl_breakpoint* bp = libafl_qemu_breakpoints;
|
struct libafl_breakpoint* bp = libafl_qemu_breakpoints;
|
||||||
while (bp) {
|
while (bp) {
|
||||||
if (bp->addr == db->pc_next) {
|
if (bp->addr == db->pc_next) {
|
||||||
TCGv tmp0 = tcg_const_tl(db->pc_next);
|
gen_helper_libafl_qemu_handle_breakpoint(cpu_env);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
bp = bp->next;
|
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 ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
/* Disassemble one instruction. The translate_insn hook should
|
/* 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);
|
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. */
|
/* Stop translation if translate_insn so indicated. */
|
||||||
if (db->is_jmp != DISAS_NEXT) {
|
if (db->is_jmp != DISAS_NEXT) {
|
||||||
break;
|
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,
|
/* Stop translation if the output buffer is full,
|
||||||
or we have executed all of the allowed instructions. */
|
or we have executed all of the allowed instructions. */
|
||||||
if (tcg_op_buf_full() || db->num_insns >= db->max_insns) {
|
if (tcg_op_buf_full() || db->num_insns >= db->max_insns) {
|
||||||
@ -251,123 +175,11 @@ post_translate_insn:
|
|||||||
#ifdef DEBUG_DISAS
|
#ifdef DEBUG_DISAS
|
||||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||||
&& qemu_log_in_addr_range(db->pc_first)) {
|
&& qemu_log_in_addr_range(db->pc_first)) {
|
||||||
FILE *logfile = qemu_log_trylock();
|
FILE *logfile = qemu_log_lock();
|
||||||
if (logfile) {
|
qemu_log("----------------\n");
|
||||||
fprintf(logfile, "----------------\n");
|
ops->disas_log(db, cpu);
|
||||||
ops->disas_log(db, cpu, logfile);
|
qemu_log("\n");
|
||||||
fprintf(logfile, "\n");
|
|
||||||
qemu_log_unlock(logfile);
|
qemu_log_unlock(logfile);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#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;
|
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;
|
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));
|
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,
|
int err,
|
||||||
const char *typ,
|
const char *typ,
|
||||||
const char *fmt,
|
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;
|
snd_pcm_hw_params_t *hw_params;
|
||||||
int err;
|
int err;
|
||||||
unsigned int freq, nchannels;
|
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;
|
snd_pcm_uframes_t obt_buffer_size;
|
||||||
const char *typ = in ? "ADC" : "DAC";
|
const char *typ = in ? "ADC" : "DAC";
|
||||||
snd_pcm_format_t obtfmt;
|
snd_pcm_format_t obtfmt;
|
||||||
@ -602,42 +602,6 @@ static int alsa_open(bool in, struct alsa_params_req *req,
|
|||||||
return -1;
|
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)
|
static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
|
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
|
||||||
@ -952,7 +916,6 @@ static struct audio_pcm_ops alsa_pcm_ops = {
|
|||||||
.init_out = alsa_init_out,
|
.init_out = alsa_init_out,
|
||||||
.fini_out = alsa_fini_out,
|
.fini_out = alsa_fini_out,
|
||||||
.write = alsa_write,
|
.write = alsa_write,
|
||||||
.buffer_get_free = alsa_buffer_get_free,
|
|
||||||
.run_buffer_out = audio_generic_run_buffer_out,
|
.run_buffer_out = audio_generic_run_buffer_out,
|
||||||
.enable_out = alsa_enable_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);
|
|
||||||
}
|
|
383
audio/audio.c
383
audio/audio.c
@ -28,14 +28,11 @@
|
|||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/clone-visitor.h"
|
|
||||||
#include "qapi/qobject-input-visitor.h"
|
#include "qapi/qobject-input-visitor.h"
|
||||||
#include "qapi/qapi-visit-audio.h"
|
#include "qapi/qapi-visit-audio.h"
|
||||||
#include "qapi/qapi-commands-audio.h"
|
|
||||||
#include "qemu/cutils.h"
|
#include "qemu/cutils.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qemu/help_option.h"
|
#include "qemu-common.h"
|
||||||
#include "sysemu/sysemu.h"
|
|
||||||
#include "sysemu/replay.h"
|
#include "sysemu/replay.h"
|
||||||
#include "sysemu/runstate.h"
|
#include "sysemu/runstate.h"
|
||||||
#include "ui/qemu-spice.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)
|
audio_driver *audio_driver_lookup(const char *name)
|
||||||
{
|
{
|
||||||
struct audio_driver *d;
|
struct audio_driver *d;
|
||||||
Error *local_err = NULL;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
QLIST_FOREACH(d, &audio_drivers, next) {
|
QLIST_FOREACH(d, &audio_drivers, next) {
|
||||||
if (strcmp(name, d->name) == 0) {
|
if (strcmp(name, d->name) == 0) {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rv = audio_module_load(name, &local_err);
|
|
||||||
if (rv > 0) {
|
audio_module_load_one(name);
|
||||||
QLIST_FOREACH(d, &audio_drivers, next) {
|
QLIST_FOREACH(d, &audio_drivers, next) {
|
||||||
if (strcmp(name, d->name) == 0) {
|
if (strcmp(name, d->name) == 0) {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (rv < 0) {
|
|
||||||
error_report_err(local_err);
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +117,7 @@ int audio_bug (const char *funcname, int cond)
|
|||||||
AUD_log (NULL, "I am sorry\n");
|
AUD_log (NULL, "I am sorry\n");
|
||||||
}
|
}
|
||||||
AUD_log (NULL, "Context:\n");
|
AUD_log (NULL, "Context:\n");
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
return cond;
|
return cond;
|
||||||
@ -554,45 +548,65 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
|
|||||||
return live;
|
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;
|
size_t clipped = 0;
|
||||||
STSampleBuffer *conv_buf = hw->conv_buf;
|
size_t pos = hw->mix_buf->pos;
|
||||||
|
|
||||||
while (samples) {
|
while (len) {
|
||||||
uint8_t *src = advance(pcm_buf, conv * hw->info.bytes_per_frame);
|
st_sample *src = hw->mix_buf->samples + pos;
|
||||||
size_t proc = MIN(samples, conv_buf->size - conv_buf->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);
|
hw->clip(dst, src, samples_to_clip);
|
||||||
conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
|
|
||||||
samples -= proc;
|
pos = (pos + samples_to_clip) % hw->mix_buf->size;
|
||||||
conv += proc;
|
len -= samples_to_clip;
|
||||||
|
clipped += samples_to_clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
return conv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Soft voice (capture)
|
* 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)
|
static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
HWVoiceIn *hw = sw->hw;
|
HWVoiceIn *hw = sw->hw;
|
||||||
size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
|
size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
|
||||||
struct st_sample *src, *dst = sw->buf;
|
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;
|
live = hw->total_samples_captured - sw->total_hw_samples_acquired;
|
||||||
if (!live) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (audio_bug(__func__, live > hw->conv_buf->size)) {
|
if (audio_bug(__func__, live > hw->conv_buf->size)) {
|
||||||
dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
|
dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rpos = audio_ring_posb(hw->conv_buf->pos, live, hw->conv_buf->size);
|
|
||||||
|
|
||||||
samples = size / sw->info.bytes_per_frame;
|
samples = size / sw->info.bytes_per_frame;
|
||||||
|
if (!live) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
swlim = (live * sw->ratio) >> 32;
|
swlim = (live * sw->ratio) >> 32;
|
||||||
swlim = MIN (swlim, samples);
|
swlim = MIN (swlim, samples);
|
||||||
@ -618,7 +632,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
|
|||||||
total += isamp;
|
total += isamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hw->pcm_ops->volume_in) {
|
if (hw->pcm_ops && !hw->pcm_ops->volume_in) {
|
||||||
mixeng_volume (sw->buf, ret, &sw->vol);
|
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;
|
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)
|
* Soft voice (playback)
|
||||||
*/
|
*/
|
||||||
static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
|
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 hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
|
||||||
size_t hw_free;
|
|
||||||
size_t ret = 0, pos = 0, total = 0;
|
size_t ret = 0, pos = 0, total = 0;
|
||||||
|
|
||||||
if (!sw) {
|
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;
|
wpos = (sw->hw->mix_buf->pos + live) % hwsamples;
|
||||||
|
samples = size / sw->info.bytes_per_frame;
|
||||||
|
|
||||||
dead = hwsamples - live;
|
dead = hwsamples - live;
|
||||||
hw_free = audio_pcm_hw_get_free(sw->hw);
|
swlim = ((int64_t) dead << 32) / sw->ratio;
|
||||||
hw_free = hw_free > live ? hw_free - live : 0;
|
swlim = MIN (swlim, samples);
|
||||||
samples = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
|
if (swlim) {
|
||||||
samples = MIN(samples, size / sw->info.bytes_per_frame);
|
sw->conv (sw->buf, buf, swlim);
|
||||||
if (samples) {
|
|
||||||
sw->conv(sw->buf, buf, samples);
|
|
||||||
|
|
||||||
if (!sw->hw->pcm_ops->volume_out) {
|
if (sw->hw->pcm_ops && !sw->hw->pcm_ops->volume_out) {
|
||||||
mixeng_volume(sw->buf, samples, &sw->vol);
|
mixeng_volume (sw->buf, swlim, &sw->vol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (samples) {
|
while (swlim) {
|
||||||
dead = hwsamples - live;
|
dead = hwsamples - live;
|
||||||
left = hwsamples - wpos;
|
left = hwsamples - wpos;
|
||||||
blck = MIN (dead, left);
|
blck = MIN (dead, left);
|
||||||
if (!blck) {
|
if (!blck) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
isamp = samples;
|
isamp = swlim;
|
||||||
osamp = blck;
|
osamp = blck;
|
||||||
st_rate_flow_mix (
|
st_rate_flow_mix (
|
||||||
sw->rate,
|
sw->rate,
|
||||||
@ -754,7 +741,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
|
|||||||
&osamp
|
&osamp
|
||||||
);
|
);
|
||||||
ret += isamp;
|
ret += isamp;
|
||||||
samples -= isamp;
|
swlim -= isamp;
|
||||||
pos += isamp;
|
pos += isamp;
|
||||||
live += osamp;
|
live += osamp;
|
||||||
wpos = (wpos + osamp) % hwsamples;
|
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)
|
static size_t audio_get_avail (SWVoiceIn *sw)
|
||||||
{
|
{
|
||||||
size_t live;
|
size_t live;
|
||||||
@ -1020,24 +995,12 @@ static size_t audio_get_avail (SWVoiceIn *sw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ldebug (
|
ldebug (
|
||||||
"%s: get_avail live %zu frontend frames %zu\n",
|
"%s: get_avail live %zu ret %" PRId64 "\n",
|
||||||
SW_NAME (sw),
|
SW_NAME (sw),
|
||||||
live, audio_frontend_frames_in(sw, live)
|
live, (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame
|
||||||
);
|
);
|
||||||
|
|
||||||
return live;
|
return (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t audio_get_free(SWVoiceOut *sw)
|
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;
|
dead = sw->hw->mix_buf->size - live;
|
||||||
|
|
||||||
#ifdef DEBUG_OUT
|
#ifdef DEBUG_OUT
|
||||||
dolog("%s: get_free live %zu dead %zu frontend frames %zu\n",
|
dolog ("%s: get_free live %zu dead %zu ret %" PRId64 "\n",
|
||||||
SW_NAME(sw), live, dead, audio_frontend_frames_out(sw, dead));
|
SW_NAME (sw),
|
||||||
|
live, dead, (((int64_t) dead << 32) / sw->ratio) *
|
||||||
|
sw->info.bytes_per_frame);
|
||||||
#endif
|
#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,
|
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;
|
HWVoiceOut *hw = NULL;
|
||||||
SWVoiceOut *sw;
|
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 */
|
/* there is exactly 1 sw for each hw with no mixeng */
|
||||||
sw = hw->sw_head.lh_first;
|
sw = hw->sw_head.lh_first;
|
||||||
|
|
||||||
@ -1164,34 +1125,15 @@ static void audio_run_out (AudioState *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sw->active) {
|
if (sw->active) {
|
||||||
sw->callback.fn(sw->callback.opaque,
|
sw->callback.fn(sw->callback.opaque, INT_MAX);
|
||||||
hw_free * sw->info.bytes_per_frame);
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hw->pcm_ops->run_buffer_out) {
|
while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
|
||||||
hw->pcm_ops->run_buffer_out(hw);
|
size_t played, live, prev_rpos, free;
|
||||||
}
|
int nb_live;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
live = audio_pcm_hw_get_live_out (hw, &nb_live);
|
live = audio_pcm_hw_get_live_out (hw, &nb_live);
|
||||||
if (!nb_live) {
|
if (!nb_live) {
|
||||||
@ -1221,6 +1163,14 @@ static void audio_run_out (AudioState *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!live) {
|
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) {
|
if (hw->pcm_ops->run_buffer_out) {
|
||||||
hw->pcm_ops->run_buffer_out(hw);
|
hw->pcm_ops->run_buffer_out(hw);
|
||||||
}
|
}
|
||||||
@ -1261,6 +1211,13 @@ static void audio_run_out (AudioState *s)
|
|||||||
if (!sw->total_hw_samples_mixed) {
|
if (!sw->total_hw_samples_mixed) {
|
||||||
sw->empty = 1;
|
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)
|
static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
|
||||||
{
|
{
|
||||||
size_t conv = 0;
|
size_t conv = 0;
|
||||||
|
STSampleBuffer *conv_buf = hw->conv_buf;
|
||||||
|
|
||||||
if (hw->pcm_ops->run_buffer_in) {
|
if (hw->pcm_ops->run_buffer_in) {
|
||||||
hw->pcm_ops->run_buffer_in(hw);
|
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;
|
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;
|
samples -= proc;
|
||||||
conv += proc;
|
conv += proc;
|
||||||
@ -1327,13 +1289,11 @@ static void audio_run_in (AudioState *s)
|
|||||||
sw->total_hw_samples_acquired -= min;
|
sw->total_hw_samples_acquired -= min;
|
||||||
|
|
||||||
if (sw->active) {
|
if (sw->active) {
|
||||||
size_t sw_avail = audio_get_avail(sw);
|
|
||||||
size_t avail;
|
size_t avail;
|
||||||
|
|
||||||
avail = audio_frontend_frames_in(sw, sw_avail);
|
avail = audio_get_avail (sw);
|
||||||
if (avail > 0) {
|
if (avail > 0) {
|
||||||
sw->callback.fn(sw->callback.opaque,
|
sw->callback.fn (sw->callback.opaque, avail);
|
||||||
avail * sw->info.bytes_per_frame);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1434,10 +1394,12 @@ void audio_generic_run_buffer_in(HWVoiceIn *hw)
|
|||||||
|
|
||||||
void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size)
|
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);
|
if (start < 0) {
|
||||||
assert(start < hw->size_emul);
|
start += hw->size_emul;
|
||||||
|
}
|
||||||
|
assert(start >= 0 && start < hw->size_emul);
|
||||||
|
|
||||||
*size = MIN(*size, hw->pending_emul);
|
*size = MIN(*size, hw->pending_emul);
|
||||||
*size = MIN(*size, hw->size_emul - start);
|
*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;
|
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)
|
void audio_generic_run_buffer_out(HWVoiceOut *hw)
|
||||||
{
|
{
|
||||||
while (hw->pending_emul) {
|
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);
|
if (start < 0) {
|
||||||
assert(start < hw->size_emul);
|
start += hw->size_emul;
|
||||||
|
}
|
||||||
|
assert(start >= 0 && start < hw->size_emul);
|
||||||
|
|
||||||
write_len = MIN(hw->pending_emul, hw->size_emul - start);
|
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;
|
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) {
|
while (total < size) {
|
||||||
size_t dst_size = size - total;
|
size_t dst_size = size - total;
|
||||||
size_t copy_size, proc;
|
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;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1762,7 +1716,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
|||||||
audio_validate_opts(dev, &error_abort);
|
audio_validate_opts(dev, &error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = g_new0(AudioState, 1);
|
s = g_malloc0(sizeof(AudioState));
|
||||||
s->dev = dev;
|
s->dev = dev;
|
||||||
|
|
||||||
QLIST_INIT (&s->hw_head_out);
|
QLIST_INIT (&s->hw_head_out);
|
||||||
@ -1772,19 +1726,20 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
|||||||
atexit(audio_cleanup);
|
atexit(audio_cleanup);
|
||||||
atexit_registered = true;
|
atexit_registered = true;
|
||||||
}
|
}
|
||||||
|
QTAILQ_INSERT_TAIL(&audio_states, s, list);
|
||||||
|
|
||||||
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
|
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_out = audio_get_pdo_out(dev)->voices;
|
||||||
s->nb_hw_voices_in = audio_get_pdo_in(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",
|
dolog ("Bogus number of playback voices %d, setting to 1\n",
|
||||||
s->nb_hw_voices_out);
|
s->nb_hw_voices_out);
|
||||||
s->nb_hw_voices_out = 1;
|
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",
|
dolog ("Bogus number of capture voices %d, setting to 0\n",
|
||||||
s->nb_hw_voices_in);
|
s->nb_hw_voices_in);
|
||||||
s->nb_hw_voices_in = 0;
|
s->nb_hw_voices_in = 0;
|
||||||
@ -1797,10 +1752,6 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
|||||||
} else {
|
} else {
|
||||||
dolog ("Unknown audio driver `%s'\n", drvname);
|
dolog ("Unknown audio driver `%s'\n", drvname);
|
||||||
}
|
}
|
||||||
if (!done) {
|
|
||||||
free_audio_state(s);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; audio_prio_list[i]; i++) {
|
for (i = 0; audio_prio_list[i]; i++) {
|
||||||
AudiodevListEntry *e = audiodev_find(&head, audio_prio_list[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");
|
"(Audio can continue looping even after stopping the VM)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
QTAILQ_INSERT_TAIL(&audio_states, s, list);
|
|
||||||
QLIST_INIT (&s->card_head);
|
QLIST_INIT (&s->card_head);
|
||||||
vmstate_register (NULL, 0, &vmstate_audio, s);
|
vmstate_register (NULL, 0, &vmstate_audio, s);
|
||||||
return s;
|
return s;
|
||||||
@ -1871,7 +1821,6 @@ void AUD_remove_card (QEMUSoundCard *card)
|
|||||||
g_free (card->name);
|
g_free (card->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct audio_pcm_ops capture_pcm_ops;
|
|
||||||
|
|
||||||
CaptureVoiceOut *AUD_add_capture(
|
CaptureVoiceOut *AUD_add_capture(
|
||||||
AudioState *s,
|
AudioState *s,
|
||||||
@ -1917,7 +1866,6 @@ CaptureVoiceOut *AUD_add_capture(
|
|||||||
|
|
||||||
hw = &cap->hw;
|
hw = &cap->hw;
|
||||||
hw->s = s;
|
hw->s = s;
|
||||||
hw->pcm_ops = &capture_pcm_ops;
|
|
||||||
QLIST_INIT (&hw->sw_head);
|
QLIST_INIT (&hw->sw_head);
|
||||||
QLIST_INIT (&cap->cb_head);
|
QLIST_INIT (&cap->cb_head);
|
||||||
|
|
||||||
@ -2037,47 +1985,27 @@ void audio_create_pdos(Audiodev *dev)
|
|||||||
switch (dev->driver) {
|
switch (dev->driver) {
|
||||||
#define CASE(DRIVER, driver, pdo_name) \
|
#define CASE(DRIVER, driver, pdo_name) \
|
||||||
case AUDIODEV_DRIVER_##DRIVER: \
|
case AUDIODEV_DRIVER_##DRIVER: \
|
||||||
if (!dev->u.driver.in) { \
|
if (!dev->u.driver.has_in) { \
|
||||||
dev->u.driver.in = g_malloc0( \
|
dev->u.driver.in = g_malloc0( \
|
||||||
sizeof(Audiodev##pdo_name##PerDirectionOptions)); \
|
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( \
|
dev->u.driver.out = g_malloc0( \
|
||||||
sizeof(Audiodev##pdo_name##PerDirectionOptions)); \
|
sizeof(Audiodev##pdo_name##PerDirectionOptions)); \
|
||||||
|
dev->u.driver.has_out = true; \
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
|
|
||||||
CASE(NONE, none, );
|
CASE(NONE, none, );
|
||||||
#ifdef CONFIG_AUDIO_ALSA
|
|
||||||
CASE(ALSA, alsa, Alsa);
|
CASE(ALSA, alsa, Alsa);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_COREAUDIO
|
|
||||||
CASE(COREAUDIO, coreaudio, Coreaudio);
|
CASE(COREAUDIO, coreaudio, Coreaudio);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_DBUS_DISPLAY
|
|
||||||
CASE(DBUS, dbus, );
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_DSOUND
|
|
||||||
CASE(DSOUND, dsound, );
|
CASE(DSOUND, dsound, );
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_JACK
|
|
||||||
CASE(JACK, jack, Jack);
|
CASE(JACK, jack, Jack);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_OSS
|
|
||||||
CASE(OSS, oss, Oss);
|
CASE(OSS, oss, Oss);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_PA
|
|
||||||
CASE(PA, pa, Pa);
|
CASE(PA, pa, Pa);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_SDL
|
|
||||||
CASE(SDL, sdl, Sdl);
|
CASE(SDL, sdl, Sdl);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_SNDIO
|
|
||||||
CASE(SNDIO, sndio, );
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_SPICE
|
|
||||||
CASE(SPICE, spice, );
|
CASE(SPICE, spice, );
|
||||||
#endif
|
|
||||||
CASE(WAV, wav, );
|
CASE(WAV, wav, );
|
||||||
|
|
||||||
case AUDIODEV_DRIVER__MAX:
|
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)
|
void audio_parse_option(const char *opt)
|
||||||
{
|
{
|
||||||
|
AudiodevListEntry *e;
|
||||||
Audiodev *dev = NULL;
|
Audiodev *dev = NULL;
|
||||||
|
|
||||||
if (is_help_option(opt)) {
|
|
||||||
audio_help();
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
|
Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
|
||||||
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
|
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
|
||||||
visit_free(v);
|
visit_free(v);
|
||||||
|
|
||||||
audio_define(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_define(Audiodev *dev)
|
|
||||||
{
|
|
||||||
AudiodevListEntry *e;
|
|
||||||
|
|
||||||
audio_validate_opts(dev, &error_fatal);
|
audio_validate_opts(dev, &error_fatal);
|
||||||
|
|
||||||
e = g_new0(AudiodevListEntry, 1);
|
e = g_malloc0(sizeof(AudiodevListEntry));
|
||||||
e->dev = dev;
|
e->dev = dev;
|
||||||
QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next);
|
QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool audio_init_audiodevs(void)
|
void audio_init_audiodevs(void)
|
||||||
{
|
{
|
||||||
AudiodevListEntry *e;
|
AudiodevListEntry *e;
|
||||||
|
|
||||||
QSIMPLEQ_FOREACH(e, &audiodevs, next) {
|
QSIMPLEQ_FOREACH(e, &audiodevs, next) {
|
||||||
if (!audio_init(e->dev, NULL)) {
|
audio_init(e->dev, NULL);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo)
|
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);
|
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 now;
|
||||||
int64_t ticks;
|
int64_t ticks;
|
||||||
int64_t bytes;
|
int64_t bytes;
|
||||||
int64_t frames;
|
int64_t samples;
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
ticks = now - rate->start_ticks;
|
ticks = now - rate->start_ticks;
|
||||||
bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
|
bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
|
||||||
frames = (bytes - rate->bytes_sent) / info->bytes_per_frame;
|
samples = (bytes - rate->bytes_sent) / info->bytes_per_frame;
|
||||||
if (frames < 0 || frames > 65536) {
|
if (samples < 0 || samples > 65536) {
|
||||||
AUD_log(NULL, "Resetting rate control (%" PRId64 " frames)\n", frames);
|
AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)\n", samples);
|
||||||
audio_rate_start(rate);
|
audio_rate_start(rate);
|
||||||
frames = 0;
|
samples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return frames * info->bytes_per_frame;
|
ret = MIN(samples * info->bytes_per_frame, bytes_avail);
|
||||||
}
|
rate->bytes_sent += ret;
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
typedef void (*audio_callback_fn) (void *opaque, int avail);
|
typedef void (*audio_callback_fn) (void *opaque, int avail);
|
||||||
|
|
||||||
#if HOST_BIG_ENDIAN
|
#ifdef HOST_WORDS_BIGENDIAN
|
||||||
#define AUDIO_HOST_ENDIANNESS 1
|
#define AUDIO_HOST_ENDIANNESS 1
|
||||||
#else
|
#else
|
||||||
#define AUDIO_HOST_ENDIANNESS 0
|
#define AUDIO_HOST_ENDIANNESS 0
|
||||||
@ -91,8 +91,8 @@ typedef struct QEMUAudioTimeStamp {
|
|||||||
uint64_t old_ts;
|
uint64_t old_ts;
|
||||||
} QEMUAudioTimeStamp;
|
} QEMUAudioTimeStamp;
|
||||||
|
|
||||||
void AUD_vlog (const char *cap, const char *fmt, va_list ap) G_GNUC_PRINTF(2, 0);
|
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, ...) G_GNUC_PRINTF(2, 3);
|
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_register_card (const char *name, QEMUSoundCard *card);
|
||||||
void AUD_remove_card (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,
|
void audio_sample_from_uint64(void *samples, int pos,
|
||||||
uint64_t left, uint64_t right);
|
uint64_t left, uint64_t right);
|
||||||
|
|
||||||
void audio_define(Audiodev *audio);
|
|
||||||
void audio_parse_option(const char *opt);
|
void audio_parse_option(const char *opt);
|
||||||
bool audio_init_audiodevs(void);
|
void audio_init_audiodevs(void);
|
||||||
void audio_help(void);
|
|
||||||
void audio_legacy_help(void);
|
void audio_legacy_help(void);
|
||||||
|
|
||||||
AudioState *audio_state_by_name(const char *name);
|
AudioState *audio_state_by_name(const char *name);
|
||||||
|
@ -31,10 +31,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "mixeng.h"
|
#include "mixeng.h"
|
||||||
|
|
||||||
#ifdef CONFIG_GIO
|
|
||||||
#include <gio/gio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct audio_pcm_ops;
|
struct audio_pcm_ops;
|
||||||
|
|
||||||
struct audio_callback {
|
struct audio_callback {
|
||||||
@ -144,9 +140,6 @@ struct audio_driver {
|
|||||||
const char *descr;
|
const char *descr;
|
||||||
void *(*init) (Audiodev *);
|
void *(*init) (Audiodev *);
|
||||||
void (*fini) (void *);
|
void (*fini) (void *);
|
||||||
#ifdef CONFIG_GIO
|
|
||||||
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager);
|
|
||||||
#endif
|
|
||||||
struct audio_pcm_ops *pcm_ops;
|
struct audio_pcm_ops *pcm_ops;
|
||||||
int can_be_default;
|
int can_be_default;
|
||||||
int max_voices_out;
|
int max_voices_out;
|
||||||
@ -161,14 +154,10 @@ struct audio_pcm_ops {
|
|||||||
void (*fini_out)(HWVoiceOut *hw);
|
void (*fini_out)(HWVoiceOut *hw);
|
||||||
size_t (*write) (HWVoiceOut *hw, void *buf, size_t size);
|
size_t (*write) (HWVoiceOut *hw, void *buf, size_t size);
|
||||||
void (*run_buffer_out)(HWVoiceOut *hw);
|
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
|
* 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)
|
* 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);
|
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_get_buffer_in(HWVoiceIn *hw, size_t *size);
|
||||||
void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
|
void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
|
||||||
void audio_generic_run_buffer_out(HWVoiceOut *hw);
|
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);
|
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_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size);
|
||||||
size_t audio_generic_write(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;
|
} RateCtl;
|
||||||
|
|
||||||
void audio_rate_start(RateCtl *rate);
|
void audio_rate_start(RateCtl *rate);
|
||||||
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,
|
||||||
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 bytes_avail);
|
size_t bytes_avail);
|
||||||
|
|
||||||
static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len)
|
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);
|
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__)
|
#define dolog(fmt, ...) AUD_log(AUDIO_CAP, fmt, ## __VA_ARGS__)
|
||||||
|
|
||||||
#ifdef DEBUG
|
#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);
|
const char *val = getenv(env);
|
||||||
if (val) {
|
if (val) {
|
||||||
|
if (*has_dst) {
|
||||||
g_free(*dst);
|
g_free(*dst);
|
||||||
|
}
|
||||||
*dst = g_strdup(val);
|
*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)
|
static void get_millis_to_usecs(const char *env, uint32_t *dst, bool *has_dst)
|
||||||
{
|
{
|
||||||
const char *val = getenv(env);
|
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;
|
*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,
|
static uint32_t frames_to_usecs(uint32_t frames,
|
||||||
AudiodevPerDirectionOptions *pdo)
|
AudiodevPerDirectionOptions *pdo)
|
||||||
{
|
{
|
||||||
uint32_t freq = pdo->has_frequency ? pdo->frequency : 44100;
|
uint32_t freq = pdo->has_frequency ? pdo->frequency : 44100;
|
||||||
return (frames * 1000000 + freq / 2) / freq;
|
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,
|
static void get_frames_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
|
||||||
AudiodevPerDirectionOptions *pdo)
|
AudiodevPerDirectionOptions *pdo)
|
||||||
{
|
{
|
||||||
@ -122,19 +119,14 @@ static void get_frames_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
|
|||||||
*has_dst = true;
|
*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,
|
static uint32_t samples_to_usecs(uint32_t samples,
|
||||||
AudiodevPerDirectionOptions *pdo)
|
AudiodevPerDirectionOptions *pdo)
|
||||||
{
|
{
|
||||||
uint32_t channels = pdo->has_channels ? pdo->channels : 2;
|
uint32_t channels = pdo->has_channels ? pdo->channels : 2;
|
||||||
return frames_to_usecs(samples / channels, pdo);
|
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,
|
static void get_samples_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
|
||||||
AudiodevPerDirectionOptions *pdo)
|
AudiodevPerDirectionOptions *pdo)
|
||||||
{
|
{
|
||||||
@ -144,9 +136,7 @@ static void get_samples_to_usecs(const char *env, uint32_t *dst, bool *has_dst,
|
|||||||
*has_dst = true;
|
*has_dst = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_AUDIO_DSOUND) || defined(CONFIG_AUDIO_OSS)
|
|
||||||
static uint32_t bytes_to_usecs(uint32_t bytes, AudiodevPerDirectionOptions *pdo)
|
static uint32_t bytes_to_usecs(uint32_t bytes, AudiodevPerDirectionOptions *pdo)
|
||||||
{
|
{
|
||||||
AudioFormat fmt = pdo->has_format ? pdo->format : AUDIO_FORMAT_S16;
|
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;
|
*has_dst = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* backend specific functions */
|
/* backend specific functions */
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_ALSA
|
|
||||||
/* ALSA */
|
/* ALSA */
|
||||||
static void handle_alsa_per_direction(
|
static void handle_alsa_per_direction(
|
||||||
AudiodevAlsaPerDirectionOptions *apdo, const char *prefix)
|
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);
|
get_bool(buf, &apdo->try_poll, &apdo->has_try_poll);
|
||||||
|
|
||||||
strcpy(buf + len, "DEV");
|
strcpy(buf + len, "DEV");
|
||||||
get_str(buf, &apdo->dev);
|
get_str(buf, &apdo->dev, &apdo->has_dev);
|
||||||
|
|
||||||
strcpy(buf + len, "SIZE_IN_USEC");
|
strcpy(buf + len, "SIZE_IN_USEC");
|
||||||
get_bool(buf, &size_in_usecs, &dummy);
|
get_bool(buf, &size_in_usecs, &dummy);
|
||||||
@ -213,9 +200,7 @@ static void handle_alsa(Audiodev *dev)
|
|||||||
get_millis_to_usecs("QEMU_ALSA_THRESHOLD",
|
get_millis_to_usecs("QEMU_ALSA_THRESHOLD",
|
||||||
&aopt->threshold, &aopt->has_threshold);
|
&aopt->threshold, &aopt->has_threshold);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_COREAUDIO
|
|
||||||
/* coreaudio */
|
/* coreaudio */
|
||||||
static void handle_coreaudio(Audiodev *dev)
|
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->buffer_count,
|
||||||
&dev->u.coreaudio.out->has_buffer_count);
|
&dev->u.coreaudio.out->has_buffer_count);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_DSOUND
|
|
||||||
/* dsound */
|
/* dsound */
|
||||||
static void handle_dsound(Audiodev *dev)
|
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->has_buffer_length,
|
||||||
dev->u.dsound.in);
|
dev->u.dsound.in);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_OSS
|
|
||||||
/* OSS */
|
/* OSS */
|
||||||
static void handle_oss_per_direction(
|
static void handle_oss_per_direction(
|
||||||
AudiodevOssPerDirectionOptions *opdo, const char *try_poll_env,
|
AudiodevOssPerDirectionOptions *opdo, const char *try_poll_env,
|
||||||
const char *dev_env)
|
const char *dev_env)
|
||||||
{
|
{
|
||||||
get_bool(try_poll_env, &opdo->try_poll, &opdo->has_try_poll);
|
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",
|
get_bytes_to_usecs("QEMU_OSS_FRAGSIZE",
|
||||||
&opdo->buffer_length, &opdo->has_buffer_length,
|
&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_bool("QEMU_OSS_EXCLUSIVE", &oopt->exclusive, &oopt->has_exclusive);
|
||||||
get_int("QEMU_OSS_POLICY", &oopt->dsp_policy, &oopt->has_dsp_policy);
|
get_int("QEMU_OSS_POLICY", &oopt->dsp_policy, &oopt->has_dsp_policy);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_PA
|
|
||||||
/* pulseaudio */
|
/* pulseaudio */
|
||||||
static void handle_pa_per_direction(
|
static void handle_pa_per_direction(
|
||||||
AudiodevPaPerDirectionOptions *ppdo, const char *env)
|
AudiodevPaPerDirectionOptions *ppdo, const char *env)
|
||||||
{
|
{
|
||||||
get_str(env, &ppdo->name);
|
get_str(env, &ppdo->name, &ppdo->has_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_pa(Audiodev *dev)
|
static void handle_pa(Audiodev *dev)
|
||||||
@ -299,11 +278,9 @@ static void handle_pa(Audiodev *dev)
|
|||||||
&dev->u.pa.out->has_buffer_length,
|
&dev->u.pa.out->has_buffer_length,
|
||||||
qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.out));
|
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 */
|
/* SDL */
|
||||||
static void handle_sdl(Audiodev *dev)
|
static void handle_sdl(Audiodev *dev)
|
||||||
{
|
{
|
||||||
@ -312,7 +289,6 @@ static void handle_sdl(Audiodev *dev)
|
|||||||
&dev->u.sdl.out->has_buffer_length,
|
&dev->u.sdl.out->has_buffer_length,
|
||||||
qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.out));
|
qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.out));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* wav */
|
/* wav */
|
||||||
static void handle_wav(Audiodev *dev)
|
static void handle_wav(Audiodev *dev)
|
||||||
@ -323,7 +299,7 @@ static void handle_wav(Audiodev *dev)
|
|||||||
&dev->u.wav.out->has_format);
|
&dev->u.wav.out->has_format);
|
||||||
get_int("QEMU_WAV_DAC_FIXED_CHANNELS",
|
get_int("QEMU_WAV_DAC_FIXED_CHANNELS",
|
||||||
&dev->u.wav.out->channels, &dev->u.wav.out->has_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 */
|
/* general */
|
||||||
@ -352,8 +328,8 @@ static void handle_per_direction(
|
|||||||
|
|
||||||
static AudiodevListEntry *legacy_opt(const char *drvname)
|
static AudiodevListEntry *legacy_opt(const char *drvname)
|
||||||
{
|
{
|
||||||
AudiodevListEntry *e = g_new0(AudiodevListEntry, 1);
|
AudiodevListEntry *e = g_malloc0(sizeof(AudiodevListEntry));
|
||||||
e->dev = g_new0(Audiodev, 1);
|
e->dev = g_malloc0(sizeof(Audiodev));
|
||||||
e->dev->id = g_strdup(drvname);
|
e->dev->id = g_strdup(drvname);
|
||||||
e->dev->driver = qapi_enum_parse(
|
e->dev->driver = qapi_enum_parse(
|
||||||
&AudiodevDriver_lookup, drvname, -1, &error_abort);
|
&AudiodevDriver_lookup, drvname, -1, &error_abort);
|
||||||
@ -372,41 +348,29 @@ static AudiodevListEntry *legacy_opt(const char *drvname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (e->dev->driver) {
|
switch (e->dev->driver) {
|
||||||
#ifdef CONFIG_AUDIO_ALSA
|
|
||||||
case AUDIODEV_DRIVER_ALSA:
|
case AUDIODEV_DRIVER_ALSA:
|
||||||
handle_alsa(e->dev);
|
handle_alsa(e->dev);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_COREAUDIO
|
|
||||||
case AUDIODEV_DRIVER_COREAUDIO:
|
case AUDIODEV_DRIVER_COREAUDIO:
|
||||||
handle_coreaudio(e->dev);
|
handle_coreaudio(e->dev);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_DSOUND
|
|
||||||
case AUDIODEV_DRIVER_DSOUND:
|
case AUDIODEV_DRIVER_DSOUND:
|
||||||
handle_dsound(e->dev);
|
handle_dsound(e->dev);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_OSS
|
|
||||||
case AUDIODEV_DRIVER_OSS:
|
case AUDIODEV_DRIVER_OSS:
|
||||||
handle_oss(e->dev);
|
handle_oss(e->dev);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_PA
|
|
||||||
case AUDIODEV_DRIVER_PA:
|
case AUDIODEV_DRIVER_PA:
|
||||||
handle_pa(e->dev);
|
handle_pa(e->dev);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUDIO_SDL
|
|
||||||
case AUDIODEV_DRIVER_SDL:
|
case AUDIODEV_DRIVER_SDL:
|
||||||
handle_sdl(e->dev);
|
handle_sdl(e->dev);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
case AUDIODEV_DRIVER_WAV:
|
case AUDIODEV_DRIVER_WAV:
|
||||||
handle_wav(e->dev);
|
handle_wav(e->dev);
|
||||||
@ -544,7 +508,7 @@ static void lv_free(Visitor *v)
|
|||||||
|
|
||||||
static Visitor *legacy_visitor_new(void)
|
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.start_struct = lv_start_struct;
|
||||||
lv->visitor.end_struct = lv_end_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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DAC
|
|
||||||
samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;
|
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));
|
sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
|
||||||
if (!sw->buf) {
|
if (!sw->buf) {
|
||||||
@ -326,47 +322,23 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
|
|||||||
switch (dev->driver) {
|
switch (dev->driver) {
|
||||||
case AUDIODEV_DRIVER_NONE:
|
case AUDIODEV_DRIVER_NONE:
|
||||||
return dev->u.none.TYPE;
|
return dev->u.none.TYPE;
|
||||||
#ifdef CONFIG_AUDIO_ALSA
|
|
||||||
case AUDIODEV_DRIVER_ALSA:
|
case AUDIODEV_DRIVER_ALSA:
|
||||||
return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.TYPE);
|
return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.TYPE);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_COREAUDIO
|
|
||||||
case AUDIODEV_DRIVER_COREAUDIO:
|
case AUDIODEV_DRIVER_COREAUDIO:
|
||||||
return qapi_AudiodevCoreaudioPerDirectionOptions_base(
|
return qapi_AudiodevCoreaudioPerDirectionOptions_base(
|
||||||
dev->u.coreaudio.TYPE);
|
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:
|
case AUDIODEV_DRIVER_DSOUND:
|
||||||
return dev->u.dsound.TYPE;
|
return dev->u.dsound.TYPE;
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_JACK
|
|
||||||
case AUDIODEV_DRIVER_JACK:
|
case AUDIODEV_DRIVER_JACK:
|
||||||
return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.TYPE);
|
return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.TYPE);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_OSS
|
|
||||||
case AUDIODEV_DRIVER_OSS:
|
case AUDIODEV_DRIVER_OSS:
|
||||||
return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE);
|
return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_PA
|
|
||||||
case AUDIODEV_DRIVER_PA:
|
case AUDIODEV_DRIVER_PA:
|
||||||
return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE);
|
return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE);
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_AUDIO_SDL
|
|
||||||
case AUDIODEV_DRIVER_SDL:
|
case AUDIODEV_DRIVER_SDL:
|
||||||
return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.TYPE);
|
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:
|
case AUDIODEV_DRIVER_SPICE:
|
||||||
return dev->u.spice.TYPE;
|
return dev->u.spice.TYPE;
|
||||||
#endif
|
|
||||||
case AUDIODEV_DRIVER_WAV:
|
case AUDIODEV_DRIVER_WAV:
|
||||||
return dev->u.wav.TYPE;
|
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