Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cdf8c4efa | ||
|
|
4a0db6ba7d | ||
|
|
0664ffac4b | ||
|
|
27f56b9aa2 | ||
|
|
97701bc03e | ||
|
|
ecdb0d5651 | ||
|
|
9c2e242077 | ||
|
|
fb6a24fb1d | ||
|
|
60c21aa017 | ||
|
|
5eca12bbad | ||
|
|
1c8d9fb334 | ||
|
|
09397e9657 | ||
|
|
674d382225 | ||
|
|
5ff78dc9bc | ||
|
|
47e0fa7479 | ||
|
|
745859d5bf | ||
|
|
c6decabc4a | ||
|
|
580c08b326 | ||
|
|
9dd68ac26b | ||
|
|
4e258da94a | ||
|
|
e08de99abe | ||
|
|
5e063a5846 | ||
|
|
1509a13240 | ||
|
|
0b487ea664 | ||
|
|
3dd28c8ecc | ||
|
|
ee9f37f3e5 | ||
|
|
8952da32c3 | ||
|
|
e92b21ffc4 | ||
|
|
a967e75f3a | ||
|
|
aacf6bfb7e | ||
|
|
4b34c6d724 | ||
|
|
9adb6569bf | ||
|
|
b1b362aa8e | ||
|
|
dc6bdba433 | ||
|
|
bc509b2a5b | ||
|
|
cd8ecfb19c | ||
|
|
abf9ffa7b3 | ||
|
|
c44015c50c | ||
|
|
b5ba361d8f | ||
|
|
52771abbfa | ||
|
|
d306348fd6 | ||
|
|
f3ef98874e | ||
|
|
e8a286010c | ||
|
|
9a30621d3d | ||
|
|
0972fbf353 | ||
|
|
9b59fdf478 | ||
|
|
ec3bd881e2 | ||
|
|
65fad28d85 | ||
|
|
256ecc06eb | ||
|
|
606a6bf788 | ||
|
|
e8ae3a4e2b | ||
|
|
7e1bc51f3f | ||
|
|
8d151ab5c2 | ||
|
|
6772bba8a4 | ||
|
|
45b65bf8df | ||
|
|
aea7a50fb5 | ||
|
|
2f7597fbc2 | ||
|
|
f127d16397 | ||
|
|
862240852b | ||
|
|
1343d33371 | ||
|
|
c436692c6a | ||
|
|
69a6048e1e | ||
|
|
01392ae31a | ||
|
|
4e98c388d6 | ||
|
|
54bcaf08d6 | ||
|
|
e727aa1a7b | ||
|
|
690e3004ae | ||
|
|
a918ea2ec3 | ||
|
|
c1cad76dcd | ||
|
|
a6e44eee6c | ||
|
|
3729ff3032 | ||
|
|
2367c7235b | ||
|
|
0c6499ff2b | ||
|
|
17216bc044 | ||
|
|
410252fc5b | ||
|
|
603cda272d | ||
|
|
03afe9c035 | ||
|
|
18f6b13e08 | ||
|
|
6c75ddf4a9 | ||
|
|
d6d45d9ed1 | ||
|
|
2a7c80d82e | ||
|
|
e27f334fdc | ||
|
|
0c1d805360 | ||
|
|
252d614ea2 | ||
|
|
dad6d5e7e6 | ||
|
|
ad56aecb21 | ||
|
|
d5691a6373 | ||
|
|
34c78a4100 | ||
|
|
8d127b4be7 | ||
|
|
ea1518bb5e | ||
|
|
c5feb39219 | ||
|
|
25fcaed9a3 | ||
|
|
aabd9ddd2d | ||
|
|
33be7aa9b6 | ||
|
|
8f5728cb97 | ||
|
|
e3531619f1 | ||
|
|
4996bd7161 | ||
|
|
3c3e1653c5 | ||
|
|
7cc217b30d | ||
|
|
219362f965 | ||
|
|
8fc4aa4822 | ||
|
|
4a9486a02d | ||
|
|
c44c4f7229 | ||
|
|
a0dc4d2495 | ||
|
|
e0ccde3887 | ||
|
|
4a1c5955e7 | ||
|
|
2dc540e40d | ||
|
|
4540aa4a8d | ||
|
|
30aa0ea6c5 | ||
|
|
382b9f09bd | ||
|
|
373fd948ab | ||
|
|
ab7f6eaa5b | ||
|
|
f9854de0d8 | ||
|
|
e49ae74a24 | ||
|
|
0319118bcf | ||
|
|
2a7569e751 | ||
|
|
3e1d95301e | ||
|
|
735cd8ddab | ||
|
|
1190026fe4 | ||
|
|
8d61b1e2c4 | ||
|
|
cbc8277051 | ||
|
|
e7cad754fd | ||
|
|
d50aa8acbc | ||
|
|
3a8068f4eb | ||
|
|
5f08c382ca | ||
|
|
edd67a61f4 | ||
|
|
153c3320e7 | ||
|
|
bf3f12ac8c | ||
|
|
956e1b2d97 | ||
|
|
eb54a2f9ce | ||
|
|
fa446ae444 | ||
|
|
3fb2521040 | ||
|
|
742195db17 | ||
|
|
98c74fe49a | ||
|
|
7042922dd7 | ||
|
|
a474197f11 | ||
|
|
a843731d7f | ||
|
|
d5a5d43e27 | ||
|
|
0253531824 | ||
|
|
2f4affb721 | ||
|
|
77d9c84d9f | ||
|
|
4412cb3bca | ||
|
|
3a94a8b7fd | ||
|
|
0cfa46da8f | ||
|
|
ba6a94e64e | ||
|
|
a5f815514a | ||
|
|
2215837fe2 | ||
|
|
cbdfd3865b | ||
|
|
89eebb016d | ||
|
|
def30090ad | ||
|
|
52a02834e0 | ||
|
|
da0948d13c | ||
|
|
d636d64b35 | ||
|
|
bed590f2b8 | ||
|
|
a115daadf6 | ||
|
|
85df33073a |
No files matched your search
+15
-112
@@ -3,133 +3,36 @@ env:
|
||||
|
||||
freebsd_12_task:
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-1
|
||||
image: freebsd-12-0-release-amd64
|
||||
cpu: 8
|
||||
memory: 8G
|
||||
install_script:
|
||||
- ASSUME_ALWAYS_YES=yes pkg bootstrap -f ;
|
||||
- pkg install -y bash curl cyrus-sasl git glib gmake gnutls gsed
|
||||
nettle perl5 pixman pkgconf png usbredir ninja
|
||||
install_script: pkg install -y
|
||||
bash bison curl cyrus-sasl git glib gmake gnutls gsed
|
||||
nettle perl5 pixman pkgconf png usbredir
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror || { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- gmake -j$(sysctl -n hw.ncpu)
|
||||
- gmake -j$(sysctl -n hw.ncpu) check V=1
|
||||
- ../configure || { cat config.log; exit 1; }
|
||||
- gmake -j8
|
||||
- gmake -j8 V=1 check
|
||||
|
||||
macos_task:
|
||||
timeout_in: 90m
|
||||
osx_instance:
|
||||
image: catalina-base
|
||||
image: mojave-base
|
||||
install_script:
|
||||
- brew install pkg-config python gnu-sed glib pixman make sdl2 bash ninja
|
||||
- brew install pkg-config python gnu-sed glib pixman make sdl2
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --python=/usr/local/bin/python3 --enable-werror
|
||||
--extra-cflags='-Wno-error=deprecated-declarations'
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- ./configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
|
||||
- gmake -j$(sysctl -n hw.ncpu)
|
||||
- gmake check V=1
|
||||
- gmake check -j$(sysctl -n hw.ncpu)
|
||||
|
||||
macos_xcode_task:
|
||||
timeout_in: 90m
|
||||
osx_instance:
|
||||
# this is an alias for the latest Xcode
|
||||
image: catalina-xcode
|
||||
image: mojave-xcode
|
||||
install_script:
|
||||
- brew install pkg-config gnu-sed glib pixman make sdl2 bash ninja
|
||||
- brew install pkg-config gnu-sed glib pixman make sdl2
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --extra-cflags='-Wno-error=deprecated-declarations' --enable-modules
|
||||
--enable-werror --cc=clang || { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- ./configure --cc=clang || { cat config.log; exit 1; }
|
||||
- gmake -j$(sysctl -n hw.ncpu)
|
||||
- gmake check V=1
|
||||
|
||||
windows_msys2_task:
|
||||
timeout_in: 90m
|
||||
windows_container:
|
||||
image: cirrusci/windowsservercore:2019
|
||||
os_version: 2019
|
||||
cpu: 8
|
||||
memory: 8G
|
||||
env:
|
||||
CIRRUS_SHELL: powershell
|
||||
MSYS: winsymlinks:nativestrict
|
||||
MSYSTEM: MINGW64
|
||||
CHERE_INVOKING: 1
|
||||
setup_script:
|
||||
- choco install -y --no-progress 7zip
|
||||
- Write-Output $env:PATH
|
||||
msys2_cache:
|
||||
folder: C:\tools\archive
|
||||
reupload_on_changes: false
|
||||
fingerprint_script: cat .cirrus.yml
|
||||
populate_script:
|
||||
- |
|
||||
md C:\tools
|
||||
md C:\tools\archive
|
||||
$start_time = Get-Date
|
||||
cd C:\tools
|
||||
bitsadmin /transfer msys_download /dynamic /download /priority FOREGROUND https://github.com/msys2/msys2-installer/releases/download/2020-09-03/msys2-base-x86_64-20200903.sfx.exe C:\tools\base.exe
|
||||
Write-Output "Download time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"
|
||||
C:\tools\base.exe -y
|
||||
((Get-Content -path C:\tools\msys64\etc\\post-install\\07-pacman-key.post -Raw) -replace '--refresh-keys', '--version') | Set-Content -Path C:\tools\msys64\etc\\post-install\\07-pacman-key.post
|
||||
C:\tools\msys64\usr\bin\bash.exe -lc "sed -i 's/^CheckSpace/#CheckSpace/g' /etc/pacman.conf"
|
||||
C:\tools\msys64\usr\bin\bash.exe -lc "export"
|
||||
C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Sy
|
||||
echo Y | C:\tools\msys64\usr\bin\pacman.exe --noconfirm -Suu --overwrite=*
|
||||
taskkill /F /FI "MODULES eq msys-2.0.dll"
|
||||
tasklist
|
||||
C:\tools\msys64\usr\bin\bash.exe -lc "mv -f /etc/pacman.conf.pacnew /etc/pacman.conf || true"
|
||||
C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -Suu --overwrite=*"
|
||||
C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -S --needed \
|
||||
diffutils git grep make pkg-config sed \
|
||||
mingw-w64-x86_64-python \
|
||||
mingw-w64-x86_64-toolchain \
|
||||
mingw-w64-x86_64-SDL2 \
|
||||
mingw-w64-x86_64-SDL2_image \
|
||||
mingw-w64-x86_64-gtk3 \
|
||||
mingw-w64-x86_64-glib2 \
|
||||
mingw-w64-x86_64-ninja \
|
||||
mingw-w64-x86_64-jemalloc \
|
||||
mingw-w64-x86_64-lzo2 \
|
||||
mingw-w64-x86_64-zstd \
|
||||
mingw-w64-x86_64-libjpeg-turbo \
|
||||
mingw-w64-x86_64-pixman \
|
||||
mingw-w64-x86_64-libgcrypt \
|
||||
mingw-w64-x86_64-libpng \
|
||||
mingw-w64-x86_64-libssh \
|
||||
mingw-w64-x86_64-libxml2 \
|
||||
mingw-w64-x86_64-snappy \
|
||||
mingw-w64-x86_64-libusb \
|
||||
mingw-w64-x86_64-usbredir \
|
||||
mingw-w64-x86_64-libtasn1 \
|
||||
mingw-w64-x86_64-nettle \
|
||||
mingw-w64-x86_64-cyrus-sasl \
|
||||
mingw-w64-x86_64-curl \
|
||||
mingw-w64-x86_64-gnutls \
|
||||
mingw-w64-x86_64-libnfs \
|
||||
"
|
||||
bitsadmin /transfer msys_download /dynamic /download /priority FOREGROUND `
|
||||
https://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz `
|
||||
C:\tools\mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz
|
||||
C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -U /c/tools/mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz"
|
||||
del C:\tools\mingw-w64-x86_64-python-sphinx-2.3.1-1-any.pkg.tar.xz
|
||||
C:\tools\msys64\usr\bin\bash.exe -lc "rm -rf /var/cache/pacman/pkg/*"
|
||||
cd C:\tools\msys64
|
||||
echo "Start archive"
|
||||
cmd /C "7z a -ttar . -so | 7z a -txz -simsys2-x86_64.tar C:\tools\archive\msys2-x86_64.tar.xz"
|
||||
install_script:
|
||||
- |
|
||||
cd C:\tools
|
||||
cmd /C "7z x C:\tools\archive\msys2-x86_64.tar.xz -so | 7z x -aoa -simsys2-x86_64.tar -ttar -omsys64"
|
||||
C:\tools\msys64\usr\bin\bash.exe -lc "export"
|
||||
|
||||
script:
|
||||
- C:\tools\msys64\usr\bin\bash.exe -lc "mkdir build"
|
||||
- C:\tools\msys64\usr\bin\bash.exe -lc "cd build && ../configure --python=python3"
|
||||
- C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make -j8"
|
||||
test_script:
|
||||
- C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make V=1 check"
|
||||
- gmake check -j$(sysctl -n hw.ncpu)
|
||||
+1
-2
@@ -22,10 +22,9 @@ indent_style = tab
|
||||
indent_size = 8
|
||||
file_type_emacs = makefile
|
||||
|
||||
[*.{c,h,c.inc,h.inc}]
|
||||
[*.{c,h}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
file_type_emacs = c
|
||||
|
||||
[*.sh]
|
||||
indent_style = space
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
*.c.inc diff=c
|
||||
*.h.inc diff=c
|
||||
@@ -1,34 +0,0 @@
|
||||
# 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 master
|
||||
repostories hosted on https://git.qemu.org/git/qemu.git.
|
||||
The project does not process issues filed on GitHub.
|
||||
|
||||
The project issues are tracked on Launchpad:
|
||||
https://bugs.launchpad.net/qemu
|
||||
|
||||
QEMU welcomes bug report contributions. You can file new ones on:
|
||||
https://bugs.launchpad.net/qemu/+filebug
|
||||
|
||||
pulls:
|
||||
comment: |
|
||||
Thank you for your interest in the QEMU project.
|
||||
|
||||
This repository is a read-only mirror of the project's master
|
||||
repostories hosted on https://git.qemu.org/git/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/
|
||||
+154
-2
@@ -1,12 +1,164 @@
|
||||
/GNUmakefile
|
||||
/build/
|
||||
/.doctrees
|
||||
/config-devices.*
|
||||
/config-all-devices.*
|
||||
/config-all-disas.*
|
||||
/config-host.*
|
||||
/config-target.*
|
||||
/config.status
|
||||
/config-temp
|
||||
/elf2dmp
|
||||
/trace-events-all
|
||||
/trace/generated-events.h
|
||||
/trace/generated-events.c
|
||||
/trace/generated-helpers-wrappers.h
|
||||
/trace/generated-helpers.h
|
||||
/trace/generated-helpers.c
|
||||
/trace/generated-tcg-tracers.h
|
||||
/ui/shader/texture-blit-frag.h
|
||||
/ui/shader/texture-blit-vert.h
|
||||
/ui/shader/texture-blit-flip-vert.h
|
||||
/ui/input-keymap-*.c
|
||||
*-timestamp
|
||||
/*-softmmu
|
||||
/*-darwin-user
|
||||
/*-linux-user
|
||||
/*-bsd-user
|
||||
/ivshmem-client
|
||||
/ivshmem-server
|
||||
/libdis*
|
||||
/libuser
|
||||
/linux-headers/asm
|
||||
/qga/qapi-generated
|
||||
/qapi-gen-timestamp
|
||||
/qapi/qapi-builtin-types.[ch]
|
||||
/qapi/qapi-builtin-visit.[ch]
|
||||
/qapi/qapi-commands-*.[ch]
|
||||
/qapi/qapi-commands.[ch]
|
||||
/qapi/qapi-emit-events.[ch]
|
||||
/qapi/qapi-events-*.[ch]
|
||||
/qapi/qapi-events.[ch]
|
||||
/qapi/qapi-introspect.[ch]
|
||||
/qapi/qapi-types-*.[ch]
|
||||
/qapi/qapi-types.[ch]
|
||||
/qapi/qapi-visit-*.[ch]
|
||||
!/qapi/qapi-visit-core.c
|
||||
/qapi/qapi-visit.[ch]
|
||||
/qapi/qapi-doc.texi
|
||||
/qemu-doc.html
|
||||
/qemu-doc.info
|
||||
/qemu-doc.txt
|
||||
/qemu-edid
|
||||
/qemu-img
|
||||
/qemu-nbd
|
||||
/qemu-options.def
|
||||
/qemu-options.texi
|
||||
/qemu-img-cmds.texi
|
||||
/qemu-img-cmds.h
|
||||
/qemu-io
|
||||
/qemu-ga
|
||||
/qemu-bridge-helper
|
||||
/qemu-keymap
|
||||
/qemu-monitor.texi
|
||||
/qemu-monitor-info.texi
|
||||
/qemu-version.h
|
||||
/qemu-version.h.tmp
|
||||
/module_block.h
|
||||
/scsi/qemu-pr-helper
|
||||
/vhost-user-scsi
|
||||
/vhost-user-blk
|
||||
/vhost-user-gpu
|
||||
/vhost-user-input
|
||||
/fsdev/virtfs-proxy-helper
|
||||
*.tmp
|
||||
*.[1-9]
|
||||
*.a
|
||||
*.aux
|
||||
*.cp
|
||||
*.exe
|
||||
*.msi
|
||||
*.dll
|
||||
*.so
|
||||
*.mo
|
||||
*.fn
|
||||
*.ky
|
||||
*.log
|
||||
*.pdf
|
||||
*.pod
|
||||
*.cps
|
||||
*.fns
|
||||
*.kys
|
||||
*.pg
|
||||
*.pyc
|
||||
*.toc
|
||||
*.tp
|
||||
*.vr
|
||||
*.d
|
||||
!/scripts/qemu-guest-agent/fsfreeze-hook.d
|
||||
*.o
|
||||
.sdk
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.gcov
|
||||
/pc-bios/bios-pq/status
|
||||
/pc-bios/edk2-*.fd
|
||||
/pc-bios/vgabios-pq/status
|
||||
/pc-bios/optionrom/linuxboot.asm
|
||||
/pc-bios/optionrom/linuxboot.bin
|
||||
/pc-bios/optionrom/linuxboot.raw
|
||||
/pc-bios/optionrom/linuxboot.img
|
||||
/pc-bios/optionrom/linuxboot_dma.asm
|
||||
/pc-bios/optionrom/linuxboot_dma.bin
|
||||
/pc-bios/optionrom/linuxboot_dma.raw
|
||||
/pc-bios/optionrom/linuxboot_dma.img
|
||||
/pc-bios/optionrom/pvh.asm
|
||||
/pc-bios/optionrom/pvh.bin
|
||||
/pc-bios/optionrom/pvh.raw
|
||||
/pc-bios/optionrom/pvh.img
|
||||
/pc-bios/optionrom/multiboot.asm
|
||||
/pc-bios/optionrom/multiboot.bin
|
||||
/pc-bios/optionrom/multiboot.raw
|
||||
/pc-bios/optionrom/multiboot.img
|
||||
/pc-bios/optionrom/kvmvapic.asm
|
||||
/pc-bios/optionrom/kvmvapic.bin
|
||||
/pc-bios/optionrom/kvmvapic.raw
|
||||
/pc-bios/optionrom/kvmvapic.img
|
||||
/pc-bios/s390-ccw/s390-ccw.elf
|
||||
/pc-bios/s390-ccw/s390-ccw.img
|
||||
/docs/built
|
||||
/docs/interop/qemu-ga-qapi.texi
|
||||
/docs/interop/qemu-ga-ref.html
|
||||
/docs/interop/qemu-ga-ref.info*
|
||||
/docs/interop/qemu-ga-ref.txt
|
||||
/docs/interop/qemu-qmp-qapi.texi
|
||||
/docs/interop/qemu-qmp-ref.html
|
||||
/docs/interop/qemu-qmp-ref.info*
|
||||
/docs/interop/qemu-qmp-ref.txt
|
||||
/docs/version.texi
|
||||
/contrib/vhost-user-gpu/50-qemu-gpu.json
|
||||
*.tps
|
||||
.stgit-*
|
||||
.git-submodule-status
|
||||
cscope.*
|
||||
tags
|
||||
TAGS
|
||||
docker-src.*
|
||||
*~
|
||||
*.ast_raw
|
||||
*.depend_raw
|
||||
trace.h
|
||||
trace.c
|
||||
trace-ust.h
|
||||
trace-ust.h
|
||||
trace-dtrace.h
|
||||
trace-dtrace.dtrace
|
||||
trace-root.h
|
||||
trace-root.c
|
||||
trace-ust-root.h
|
||||
trace-ust-root.h
|
||||
trace-ust-all.h
|
||||
trace-ust-all.c
|
||||
trace-dtrace-root.h
|
||||
trace-dtrace-root.dtrace
|
||||
trace-ust-all.h
|
||||
trace-ust-all.c
|
||||
/target/arm/decode-sve.inc.c
|
||||
@@ -1,94 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# check-dco.py: validate all commits are signed off
|
||||
#
|
||||
# Copyright (C) 2020 Red Hat, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
namespace = "qemu-project"
|
||||
if len(sys.argv) >= 2:
|
||||
namespace = sys.argv[1]
|
||||
|
||||
cwd = os.getcwd()
|
||||
reponame = os.path.basename(cwd)
|
||||
repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
|
||||
|
||||
subprocess.check_call(["git", "remote", "add", "check-dco", repourl])
|
||||
subprocess.check_call(["git", "fetch", "check-dco", "master"],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
ancestor = subprocess.check_output(["git", "merge-base",
|
||||
"check-dco/master", "HEAD"],
|
||||
universal_newlines=True)
|
||||
|
||||
ancestor = ancestor.strip()
|
||||
|
||||
subprocess.check_call(["git", "remote", "rm", "check-dco"])
|
||||
|
||||
errors = False
|
||||
|
||||
print("\nChecking for 'Signed-off-by: NAME <EMAIL>' " +
|
||||
"on all commits since %s...\n" % ancestor)
|
||||
|
||||
log = subprocess.check_output(["git", "log", "--format=%H %s",
|
||||
ancestor + "..."],
|
||||
universal_newlines=True)
|
||||
|
||||
if log == "":
|
||||
commits = []
|
||||
else:
|
||||
commits = [[c[0:40], c[41:]] for c in log.strip().split("\n")]
|
||||
|
||||
for sha, subject in commits:
|
||||
|
||||
msg = subprocess.check_output(["git", "show", "-s", sha],
|
||||
universal_newlines=True)
|
||||
lines = msg.strip().split("\n")
|
||||
|
||||
print("🔍 %s %s" % (sha, subject))
|
||||
sob = False
|
||||
for line in lines:
|
||||
if "Signed-off-by:" in line:
|
||||
sob = True
|
||||
if "localhost" in line:
|
||||
print(" ❌ FAIL: bad email in %s" % line)
|
||||
errors = True
|
||||
|
||||
if not sob:
|
||||
print(" ❌ FAIL missing Signed-off-by tag")
|
||||
errors = True
|
||||
|
||||
if errors:
|
||||
print("""
|
||||
|
||||
❌ ERROR: One or more commits are missing a valid Signed-off-By tag.
|
||||
|
||||
|
||||
This project requires all contributors to assert that their contributions
|
||||
are provided in compliance with the terms of the Developer's Certificate
|
||||
of Origin 1.1 (DCO):
|
||||
|
||||
https://developercertificate.org/
|
||||
|
||||
To indicate acceptance of the DCO every commit must have a tag
|
||||
|
||||
Signed-off-by: REAL NAME <EMAIL>
|
||||
|
||||
This can be achieved by passing the "-s" flag to the "git commit" command.
|
||||
|
||||
To bulk update all commits on current branch "git rebase" can be used:
|
||||
|
||||
git rebase -i master -x 'git commit --amend --no-edit -s'
|
||||
|
||||
""")
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
sys.exit(0)
|
||||
@@ -1,56 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# check-patch.py: run checkpatch.pl across all commits in a branch
|
||||
#
|
||||
# Copyright (C) 2020 Red Hat, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
namespace = "qemu-project"
|
||||
if len(sys.argv) >= 2:
|
||||
namespace = sys.argv[1]
|
||||
|
||||
cwd = os.getcwd()
|
||||
reponame = os.path.basename(cwd)
|
||||
repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
|
||||
|
||||
# GitLab CI environment does not give us any direct info about the
|
||||
# base for the user's branch. We thus need to figure out a common
|
||||
# ancestor between the user's branch and current git master.
|
||||
subprocess.check_call(["git", "remote", "add", "check-patch", repourl])
|
||||
subprocess.check_call(["git", "fetch", "check-patch", "master"],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
ancestor = subprocess.check_output(["git", "merge-base",
|
||||
"check-patch/master", "HEAD"],
|
||||
universal_newlines=True)
|
||||
|
||||
ancestor = ancestor.strip()
|
||||
|
||||
log = subprocess.check_output(["git", "log", "--format=%H %s",
|
||||
ancestor + "..."],
|
||||
universal_newlines=True)
|
||||
|
||||
subprocess.check_call(["git", "remote", "rm", "check-patch"])
|
||||
|
||||
if log == "":
|
||||
print("\nNo commits since %s, skipping checks\n" % ancestor)
|
||||
sys.exit(0)
|
||||
|
||||
errors = False
|
||||
|
||||
print("\nChecking all commits since %s...\n" % ancestor, flush=True)
|
||||
|
||||
ret = subprocess.run(["scripts/checkpatch.pl", "--terse", ancestor + "..."])
|
||||
|
||||
if ret.returncode != 0:
|
||||
print(" ❌ FAIL one or more commits failed scripts/checkpatch.pl")
|
||||
sys.exit(1)
|
||||
|
||||
sys.exit(0)
|
||||
@@ -1,248 +0,0 @@
|
||||
.container_job_template: &container_job_definition
|
||||
image: docker:stable
|
||||
stage: containers
|
||||
services:
|
||||
- docker:dind
|
||||
before_script:
|
||||
- export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
|
||||
- export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/$NAME:latest"
|
||||
- apk add python3
|
||||
- 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 "$TAG" || docker pull "$COMMON_TAG" || true
|
||||
- ./tests/docker/docker.py --engine docker build
|
||||
-t "qemu/$NAME" -f "tests/docker/dockerfiles/$NAME.docker"
|
||||
-r $CI_REGISTRY_IMAGE
|
||||
- docker tag "qemu/$NAME" "$TAG"
|
||||
- docker push "$TAG"
|
||||
after_script:
|
||||
- docker logout
|
||||
rules:
|
||||
- changes:
|
||||
- .gitlab-ci.d/containers.yml
|
||||
- tests/docker/*
|
||||
- tests/docker/dockerfiles/*
|
||||
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
- if: '$CI_COMMIT_REF_NAME == "testing/next"'
|
||||
|
||||
amd64-centos7-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: centos7
|
||||
|
||||
amd64-centos8-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: centos8
|
||||
|
||||
amd64-debian10-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: debian10
|
||||
|
||||
amd64-debian11-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: debian11
|
||||
|
||||
alpha-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-alpha-cross
|
||||
|
||||
amd64-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-amd64-cross
|
||||
|
||||
amd64-debian-user-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-all-test-cross
|
||||
|
||||
amd64-debian-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-amd64
|
||||
|
||||
arm64-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-arm64-cross
|
||||
|
||||
arm64-test-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian11-container']
|
||||
variables:
|
||||
NAME: debian-arm64-test-cross
|
||||
|
||||
armel-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-armel-cross
|
||||
|
||||
armhf-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-armhf-cross
|
||||
|
||||
hppa-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-hppa-cross
|
||||
|
||||
m68k-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-m68k-cross
|
||||
|
||||
mips64-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-mips64-cross
|
||||
|
||||
mips64el-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-mips64el-cross
|
||||
|
||||
mips-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-mips-cross
|
||||
|
||||
mipsel-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-mipsel-cross
|
||||
|
||||
powerpc-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-powerpc-cross
|
||||
|
||||
ppc64-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-ppc64-cross
|
||||
|
||||
ppc64el-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-ppc64el-cross
|
||||
|
||||
riscv64-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-riscv64-cross
|
||||
|
||||
s390x-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-s390x-cross
|
||||
|
||||
sh4-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-sh4-cross
|
||||
|
||||
sparc64-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-sparc64-cross
|
||||
|
||||
tricore-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
stage: containers-layer2
|
||||
needs: ['amd64-debian10-container']
|
||||
variables:
|
||||
NAME: debian-tricore-cross
|
||||
|
||||
xtensa-debian-cross-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: debian-xtensa-cross
|
||||
|
||||
cris-fedora-cross-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: fedora-cris-cross
|
||||
|
||||
amd64-fedora-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: fedora
|
||||
|
||||
i386-fedora-cross-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: fedora-i386-cross
|
||||
|
||||
win32-fedora-cross-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: fedora-win32-cross
|
||||
|
||||
win64-fedora-cross-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: fedora-win64-cross
|
||||
|
||||
amd64-ubuntu1804-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: ubuntu1804
|
||||
|
||||
amd64-ubuntu2004-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: ubuntu2004
|
||||
|
||||
amd64-ubuntu-container:
|
||||
<<: *container_job_definition
|
||||
variables:
|
||||
NAME: ubuntu
|
||||
@@ -1,114 +0,0 @@
|
||||
|
||||
.cross_system_build_job_template: &cross_system_build_job_definition
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
timeout: 80m
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
../configure --enable-werror $QEMU_CONFIGURE_OPTS --disable-user
|
||||
--target-list-exclude="aarch64-softmmu i386-softmmu microblaze-softmmu
|
||||
mips-softmmu mipsel-softmmu mips64-softmmu ppc64-softmmu sh4-softmmu
|
||||
xtensa-softmmu"
|
||||
- make -j$(expr $(nproc) + 1) all check-build
|
||||
|
||||
.cross_user_build_job_template: &cross_user_build_job_definition
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
../configure --enable-werror $QEMU_CONFIGURE_OPTS --disable-system
|
||||
- make -j$(expr $(nproc) + 1) all check-build
|
||||
|
||||
cross-armel-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-armel-cross
|
||||
|
||||
cross-armel-user:
|
||||
<<: *cross_user_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-armel-cross
|
||||
|
||||
cross-armhf-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-armhf-cross
|
||||
|
||||
cross-armhf-user:
|
||||
<<: *cross_user_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-armhf-cross
|
||||
|
||||
cross-arm64-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-arm64-cross
|
||||
|
||||
cross-arm64-user:
|
||||
<<: *cross_user_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-arm64-cross
|
||||
|
||||
cross-mips-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-mips-cross
|
||||
|
||||
cross-mips-user:
|
||||
<<: *cross_user_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-mips-cross
|
||||
|
||||
cross-mipsel-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-mipsel-cross
|
||||
|
||||
cross-mipsel-user:
|
||||
<<: *cross_user_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-mipsel-cross
|
||||
|
||||
cross-mips64el-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-mips64el-cross
|
||||
|
||||
cross-mips64el-user:
|
||||
<<: *cross_user_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-mips64el-cross
|
||||
|
||||
cross-ppc64el-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-ppc64el-cross
|
||||
|
||||
cross-ppc64el-user:
|
||||
<<: *cross_user_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-ppc64el-cross
|
||||
|
||||
cross-s390x-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-s390x-cross
|
||||
|
||||
cross-s390x-user:
|
||||
<<: *cross_user_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-s390x-cross
|
||||
|
||||
cross-win32-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: fedora-win32-cross
|
||||
|
||||
cross-win64-system:
|
||||
<<: *cross_system_build_job_definition
|
||||
variables:
|
||||
IMAGE: fedora-win64-cross
|
||||
@@ -1,50 +0,0 @@
|
||||
docker-edk2:
|
||||
stage: containers
|
||||
rules: # Only run this job when the Dockerfile is modified
|
||||
- changes:
|
||||
- .gitlab-ci.d/edk2.yml
|
||||
- .gitlab-ci.d/edk2/Dockerfile
|
||||
when: always
|
||||
image: docker:19.03.1
|
||||
services:
|
||||
- docker:19.03.1-dind
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:edk2-cross-build
|
||||
# We don't use TLS
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker pull $IMAGE_TAG || true
|
||||
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
--tag $IMAGE_TAG .gitlab-ci.d/edk2
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
- docker push $IMAGE_TAG
|
||||
|
||||
build-edk2:
|
||||
stage: build
|
||||
rules: # Only run this job when ...
|
||||
- changes: # ... roms/edk2/ is modified (submodule updated)
|
||||
- roms/edk2/*
|
||||
when: always
|
||||
- if: '$CI_COMMIT_REF_NAME =~ /^edk2/' # or the branch/tag starts with 'edk2'
|
||||
when: always
|
||||
- if: '$CI_COMMIT_MESSAGE =~ /edk2/i' # or last commit description contains 'EDK2'
|
||||
when: always
|
||||
artifacts:
|
||||
paths: # 'artifacts.zip' will contains the following files:
|
||||
- pc-bios/edk2*bz2
|
||||
- pc-bios/edk2-licenses.txt
|
||||
- edk2-stdout.log
|
||||
- edk2-stderr.log
|
||||
image: $CI_REGISTRY_IMAGE:edk2-cross-build
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
script: # Clone the required submodules and build EDK2
|
||||
- git submodule update --init roms/edk2
|
||||
- git -C roms/edk2 submodule update --init
|
||||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
- make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2
|
||||
@@ -1,27 +0,0 @@
|
||||
#
|
||||
# Docker image to cross-compile EDK2 firmware binaries
|
||||
#
|
||||
FROM ubuntu:16.04
|
||||
|
||||
MAINTAINER Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
|
||||
# Install packages required to build EDK2
|
||||
RUN apt update \
|
||||
&& \
|
||||
\
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
apt install --assume-yes --no-install-recommends \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
dos2unix \
|
||||
gcc-aarch64-linux-gnu \
|
||||
gcc-arm-linux-gnueabi \
|
||||
git \
|
||||
iasl \
|
||||
make \
|
||||
nasm \
|
||||
python \
|
||||
uuid-dev \
|
||||
&& \
|
||||
\
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
@@ -1,56 +0,0 @@
|
||||
docker-opensbi:
|
||||
stage: containers
|
||||
rules: # Only run this job when the Dockerfile is modified
|
||||
- changes:
|
||||
- .gitlab-ci.d/opensbi.yml
|
||||
- .gitlab-ci.d/opensbi/Dockerfile
|
||||
when: always
|
||||
image: docker:19.03.1
|
||||
services:
|
||||
- docker:19.03.1-dind
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build
|
||||
# We don't use TLS
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker pull $IMAGE_TAG || true
|
||||
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
--tag $IMAGE_TAG .gitlab-ci.d/opensbi
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
- docker push $IMAGE_TAG
|
||||
|
||||
build-opensbi:
|
||||
stage: build
|
||||
rules: # Only run this job when ...
|
||||
- changes: # ... roms/opensbi/ is modified (submodule updated)
|
||||
- roms/opensbi/*
|
||||
when: always
|
||||
- if: '$CI_COMMIT_REF_NAME =~ /^opensbi/' # or the branch/tag starts with 'opensbi'
|
||||
when: always
|
||||
- if: '$CI_COMMIT_MESSAGE =~ /opensbi/i' # or last commit description contains 'OpenSBI'
|
||||
when: always
|
||||
artifacts:
|
||||
paths: # 'artifacts.zip' will contains the following files:
|
||||
- pc-bios/opensbi-riscv32-generic-fw_dynamic.bin
|
||||
- pc-bios/opensbi-riscv32-generic-fw_dynamic.elf
|
||||
- pc-bios/opensbi-riscv64-generic-fw_dynamic.bin
|
||||
- pc-bios/opensbi-riscv64-generic-fw_dynamic.elf
|
||||
- opensbi32-generic-stdout.log
|
||||
- opensbi32-generic-stderr.log
|
||||
- opensbi64-generic-stdout.log
|
||||
- opensbi64-generic-stderr.log
|
||||
image: $CI_REGISTRY_IMAGE:opensbi-cross-build
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
script: # Clone the required submodules and build OpenSBI
|
||||
- git submodule update --init roms/opensbi
|
||||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi32-generic 2>&1 1>opensbi32-generic-stdout.log | tee -a opensbi32-generic-stderr.log >&2
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi64-generic 2>&1 1>opensbi64-generic-stdout.log | tee -a opensbi64-generic-stderr.log >&2
|
||||
@@ -1,33 +0,0 @@
|
||||
#
|
||||
# Docker image to cross-compile OpenSBI firmware binaries
|
||||
#
|
||||
FROM ubuntu:18.04
|
||||
|
||||
MAINTAINER Bin Meng <bmeng.cn@gmail.com>
|
||||
|
||||
# Install packages required to build OpenSBI
|
||||
RUN apt update \
|
||||
&& \
|
||||
\
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
apt install --assume-yes --no-install-recommends \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
git \
|
||||
make \
|
||||
wget \
|
||||
&& \
|
||||
\
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Manually install the kernel.org "Crosstool" based toolchains for gcc-8.3
|
||||
RUN wget -O - \
|
||||
https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/8.3.0/x86_64-gcc-8.3.0-nolibc-riscv32-linux.tar.xz \
|
||||
| tar -C /opt -xJ
|
||||
RUN wget -O - \
|
||||
https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/8.3.0/x86_64-gcc-8.3.0-nolibc-riscv64-linux.tar.xz \
|
||||
| tar -C /opt -xJ
|
||||
|
||||
# Export the toolchains to the system path
|
||||
ENV PATH="/opt/gcc-8.3.0-nolibc/riscv32-linux/bin:${PATH}"
|
||||
ENV PATH="/opt/gcc-8.3.0-nolibc/riscv64-linux/bin:${PATH}"
|
||||
+71
-458
@@ -1,470 +1,83 @@
|
||||
# Currently we have two build stages after our containers are built:
|
||||
# - build (for traditional build and test or first stage build)
|
||||
# - test (for test stages, using build artefacts from a build stage)
|
||||
stages:
|
||||
- containers
|
||||
- containers-layer2
|
||||
- build
|
||||
- test
|
||||
before_script:
|
||||
- apt-get update -qq
|
||||
- apt-get install -y -qq flex bison libglib2.0-dev libpixman-1-dev genisoimage
|
||||
|
||||
include:
|
||||
- local: '/.gitlab-ci.d/edk2.yml'
|
||||
- local: '/.gitlab-ci.d/opensbi.yml'
|
||||
- local: '/.gitlab-ci.d/containers.yml'
|
||||
- local: '/.gitlab-ci.d/crossbuilds.yml'
|
||||
build-system1:
|
||||
script:
|
||||
- apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev
|
||||
libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev libvdeplug-dev
|
||||
- ./configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
|
||||
cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu
|
||||
mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu"
|
||||
- make -j2
|
||||
- make -j2 check
|
||||
|
||||
.native_build_job_template: &native_build_job_definition
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
before_script:
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
- sed -i s,git.qemu.org/git,gitlab.com/qemu-project, .gitmodules
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if test -n "$TARGETS";
|
||||
then
|
||||
../configure --enable-werror $CONFIGURE_ARGS --target-list="$TARGETS" ;
|
||||
else
|
||||
../configure --enable-werror $CONFIGURE_ARGS ;
|
||||
fi || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- make -j"$JOBS"
|
||||
- if test -n "$MAKE_CHECK_ARGS";
|
||||
then
|
||||
make -j"$JOBS" $MAKE_CHECK_ARGS ;
|
||||
fi
|
||||
|
||||
.native_test_job_template: &native_test_job_definition
|
||||
stage: test
|
||||
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
|
||||
script:
|
||||
- cd build
|
||||
- find . -type f -exec touch {} +
|
||||
- make $MAKE_CHECK_ARGS
|
||||
|
||||
.acceptance_template: &acceptance_definition
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}-cache"
|
||||
paths:
|
||||
- ${CI_PROJECT_DIR}/avocado-cache
|
||||
policy: pull-push
|
||||
artifacts:
|
||||
paths:
|
||||
- build/tests/results/latest/results.xml
|
||||
reports:
|
||||
junit: build/tests/results/latest/results.xml
|
||||
before_script:
|
||||
- mkdir -p ~/.config/avocado
|
||||
- echo "[datadir.paths]" > ~/.config/avocado/avocado.conf
|
||||
- echo "cache_dirs = ['${CI_PROJECT_DIR}/avocado-cache']"
|
||||
>> ~/.config/avocado/avocado.conf
|
||||
- if [ -d ${CI_PROJECT_DIR}/avocado-cache ]; then
|
||||
du -chs ${CI_PROJECT_DIR}/avocado-cache ;
|
||||
fi
|
||||
- export AVOCADO_ALLOW_UNTRUSTED_CODE=1
|
||||
after_script:
|
||||
- cd build
|
||||
- python3 -c 'import json; r = json.load(open("tests/results/latest/results.json")); [print(t["logfile"]) for t in r["tests"] if t["status"] not in ("PASS", "SKIP", "CANCEL")]' | xargs cat
|
||||
- du -chs ${CI_PROJECT_DIR}/avocado-cache
|
||||
|
||||
build-system-ubuntu:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
|
||||
moxie-softmmu microblazeel-softmmu mips64el-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
CONFIGURE_ARGS: --enable-docs
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
- build
|
||||
|
||||
check-system-ubuntu:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-system-ubuntu
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
acceptance-system-ubuntu:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-system-ubuntu
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
<<: *acceptance_definition
|
||||
|
||||
build-system-debian:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
|
||||
riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
CONFIGURE_ARGS: --enable-docs
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
- build
|
||||
|
||||
check-system-debian:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
acceptance-system-debian:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-system-debian
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
<<: *acceptance_definition
|
||||
|
||||
build-system-fedora:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
|
||||
TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu
|
||||
xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
- build
|
||||
|
||||
check-system-fedora:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-system-fedora
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
acceptance-system-fedora:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-system-fedora
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
<<: *acceptance_definition
|
||||
|
||||
build-system-centos:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: centos8
|
||||
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt
|
||||
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
|
||||
x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
artifacts:
|
||||
expire_in: 2 days
|
||||
paths:
|
||||
- build
|
||||
|
||||
check-system-centos:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-system-centos
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
acceptance-system-centos:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-system-centos
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check-acceptance
|
||||
<<: *acceptance_definition
|
||||
build-system2:
|
||||
script:
|
||||
- apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev
|
||||
libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev
|
||||
- ./configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
|
||||
microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu
|
||||
sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu"
|
||||
- make -j2
|
||||
- make -j2 check
|
||||
|
||||
build-disabled:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS: --disable-attr --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-glusterfs --disable-gnutls
|
||||
--disable-gtk --disable-guest-agent --disable-iconv --disable-kvm
|
||||
--disable-libiscsi --disable-libpmem --disable-libssh --disable-libusb
|
||||
--disable-libxml2 --disable-linux-aio --disable-live-block-migration
|
||||
--disable-lzo --disable-malloc-trim --disable-mpath --disable-nettle
|
||||
--disable-numa --disable-parallels --disable-pie --disable-qcow1
|
||||
--disable-qed --disable-qom-cast-debug --disable-rbd --disable-rdma
|
||||
--disable-replication --disable-sdl --disable-seccomp --disable-sheepdog
|
||||
--disable-slirp --disable-smartcard --disable-snappy --disable-spice
|
||||
--disable-strip --disable-tpm --disable-usb-redir --disable-vdi
|
||||
--disable-vhost-crypto --disable-vhost-net --disable-vhost-scsi
|
||||
--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
|
||||
script:
|
||||
- ./configure --enable-werror --disable-rdma --disable-slirp --disable-curl
|
||||
--disable-capstone --disable-live-block-migration --disable-glusterfs
|
||||
--disable-replication --disable-coroutine-pool --disable-smartcard
|
||||
--disable-guest-agent --disable-curses --disable-libxml2 --disable-tpm
|
||||
--disable-qom-cast-debug --disable-spice --disable-vhost-vsock
|
||||
--disable-vhost-net --disable-vhost-crypto --disable-vhost-user
|
||||
--target-list="i386-softmmu ppc64-softmmu mips64-softmmu i386-linux-user"
|
||||
- make -j2
|
||||
- make -j2 check-qtest SPEED=slow
|
||||
|
||||
build-tcg-disabled:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: centos8
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-tcg --audio-drv-list="" || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- make -j"$JOBS"
|
||||
- make check-unit
|
||||
- make check-qapi-schema
|
||||
- cd tests/qemu-iotests/
|
||||
- ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
|
||||
052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163
|
||||
170 171 183 184 192 194 197 208 215 221 222 226 227 236 253 277
|
||||
- ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122
|
||||
124 132 139 142 144 145 151 152 155 157 165 194 196 197 200 202
|
||||
208 209 215 216 218 222 227 234 246 247 248 250 254 255 257 258
|
||||
260 261 262 263 264 270 272 273 277 279
|
||||
script:
|
||||
- apt-get install -y -qq clang libgtk-3-dev libbluetooth-dev libusb-dev
|
||||
- ./configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
|
||||
- make -j2
|
||||
- make check-unit
|
||||
- make check-qapi-schema
|
||||
- cd tests/qemu-iotests/
|
||||
- ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
|
||||
052 063 077 086 101 104 106 113 147 148 150 151 152 157 159 160
|
||||
163 170 171 183 184 192 194 197 205 208 215 221 222 226 227 236
|
||||
- ./check -qcow2 028 040 051 056 057 058 065 067 068 082 085 091 095 096 102
|
||||
122 124 127 129 132 139 142 144 145 147 151 152 155 157 165 194
|
||||
196 197 200 202 203 205 208 209 215 216 218 222 227 234 246 247
|
||||
248 250 254 255 256
|
||||
|
||||
build-user:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --disable-tools --disable-system
|
||||
MAKE_CHECK_ARGS: check-tcg
|
||||
|
||||
# Only build the softmmu targets we have check-tcg tests for
|
||||
build-some-softmmu:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --disable-tools --enable-debug-tcg
|
||||
TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu
|
||||
MAKE_CHECK_ARGS: check-tcg
|
||||
|
||||
# Run check-tcg against linux-user (with plugins)
|
||||
# we skip sparc64-linux-user until it has been fixed somewhat
|
||||
# we skip cris-linux-user as it doesn't use the common run loop
|
||||
build-user-plugins:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --disable-tools --disable-system --enable-plugins --enable-debug-tcg --target-list-exclude=sparc64-linux-user,cris-linux-user
|
||||
MAKE_CHECK_ARGS: check-tcg
|
||||
timeout: 1h 30m
|
||||
|
||||
build-some-softmmu-plugins:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --disable-tools --disable-user --enable-plugins --enable-debug-tcg
|
||||
TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu
|
||||
MAKE_CHECK_ARGS: check-tcg
|
||||
script:
|
||||
- ./configure --enable-werror --disable-system --disable-guest-agent
|
||||
--disable-capstone --disable-slirp --disable-fdt
|
||||
- make -j2
|
||||
- make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user
|
||||
|
||||
build-clang:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
CONFIGURE_ARGS: --cc=clang --cxx=clang++
|
||||
TARGETS: alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
|
||||
ppc-softmmu s390x-softmmu arm-linux-user
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
# These targets are on the way out
|
||||
build-deprecated:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
CONFIGURE_ARGS: --disable-docs --disable-tools
|
||||
MAKE_CHECK_ARGS: build-tcg
|
||||
TARGETS: ppc64abi32-linux-user tilegx-linux-user lm32-softmmu
|
||||
unicore32-softmmu
|
||||
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:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-deprecated
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: debian-all-test-cross
|
||||
MAKE_CHECK_ARGS: check-tcg
|
||||
allow_failure: true
|
||||
|
||||
build-oss-fuzz:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
script:
|
||||
- mkdir build-oss-fuzz
|
||||
- CC="clang" CXX="clang++" CFLAGS="-fsanitize=address"
|
||||
./scripts/oss-fuzz/build.sh
|
||||
- export ASAN_OPTIONS="fast_unwind_on_malloc=0"
|
||||
- for fuzzer in $(find ./build-oss-fuzz/DEST_DIR/ -executable -type f
|
||||
| grep -v slirp); do
|
||||
grep "LLVMFuzzerTestOneInput" ${fuzzer} > /dev/null 2>&1 || continue ;
|
||||
echo Testing ${fuzzer} ... ;
|
||||
"${fuzzer}" -runs=1 -seed=1 || exit 1 ;
|
||||
done
|
||||
# Unrelated to fuzzer: run some tests with -fsanitize=address
|
||||
- cd build-oss-fuzz && make check-qtest-i386 check-unit
|
||||
script:
|
||||
- apt-get install -y -qq clang libsdl2-dev libattr1-dev libcap-dev
|
||||
xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev
|
||||
- ./configure --cc=clang --cxx=clang++ --enable-werror
|
||||
--target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
|
||||
ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user"
|
||||
- make -j2
|
||||
- make -j2 check
|
||||
|
||||
build-tci:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: fedora
|
||||
script:
|
||||
- TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64"
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-tcg-interpreter
|
||||
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)" || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- make -j"$JOBS"
|
||||
- make run-tcg-tests-x86_64-softmmu
|
||||
- make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test
|
||||
- for tg in $TARGETS ; do
|
||||
export QTEST_QEMU_BINARY="./qemu-system-${tg}" ;
|
||||
./tests/qtest/boot-serial-test || exit 1 ;
|
||||
./tests/qtest/cdrom-test || exit 1 ;
|
||||
done
|
||||
- QTEST_QEMU_BINARY="./qemu-system-x86_64" ./tests/qtest/pxe-test
|
||||
- QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow
|
||||
|
||||
# Most jobs test latest gcrypt or nettle builds
|
||||
#
|
||||
# These jobs test old gcrypt and nettle from RHEL7
|
||||
# which had some API differences.
|
||||
build-crypto-old-nettle:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: centos7
|
||||
TARGETS: x86_64-softmmu x86_64-linux-user
|
||||
CONFIGURE_ARGS: --disable-gcrypt --enable-nettle
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
artifacts:
|
||||
paths:
|
||||
- build
|
||||
|
||||
check-crypto-old-nettle:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-crypto-old-nettle
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos7
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
|
||||
build-crypto-old-gcrypt:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: centos7
|
||||
TARGETS: x86_64-softmmu x86_64-linux-user
|
||||
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
artifacts:
|
||||
paths:
|
||||
- build
|
||||
|
||||
check-crypto-old-gcrypt:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-crypto-old-gcrypt
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos7
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
|
||||
build-crypto-only-gnutls:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: centos7
|
||||
TARGETS: x86_64-softmmu x86_64-linux-user
|
||||
CONFIGURE_ARGS: --disable-nettle --disable-gcrypt --enable-gnutls
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
artifacts:
|
||||
paths:
|
||||
- build
|
||||
|
||||
check-crypto-only-gnutls:
|
||||
<<: *native_test_job_definition
|
||||
needs:
|
||||
- job: build-crypto-only-gnutls
|
||||
artifacts: true
|
||||
variables:
|
||||
IMAGE: centos7
|
||||
MAKE_CHECK_ARGS: check
|
||||
|
||||
# We don't need to exercise every backend with every front-end
|
||||
build-trace-multi-user:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
CONFIGURE_ARGS: --enable-trace-backends=log,simple,syslog --disable-system
|
||||
|
||||
build-trace-ftrace-system:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
CONFIGURE_ARGS: --enable-trace-backends=ftrace --target-list=x86_64-softmmu
|
||||
|
||||
build-trace-ust-system:
|
||||
<<: *native_build_job_definition
|
||||
variables:
|
||||
IMAGE: ubuntu2004
|
||||
CONFIGURE_ARGS: --enable-trace-backends=ust --target-list=x86_64-softmmu
|
||||
|
||||
check-patch:
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
|
||||
script: .gitlab-ci.d/check-patch.py
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_NAMESPACE == 'qemu-project' && $CI_COMMIT_BRANCH == 'master'
|
||||
variables:
|
||||
GIT_DEPTH: 1000
|
||||
allow_failure: true
|
||||
|
||||
check-dco:
|
||||
stage: build
|
||||
image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
|
||||
script: .gitlab-ci.d/check-dco.py
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_NAMESPACE == 'qemu-project' && $CI_COMMIT_BRANCH == 'master'
|
||||
variables:
|
||||
GIT_DEPTH: 1000
|
||||
|
||||
pages:
|
||||
image: $CI_REGISTRY_IMAGE/qemu/ubuntu2004:latest
|
||||
stage: test
|
||||
needs:
|
||||
- job: build-system-ubuntu
|
||||
artifacts: true
|
||||
script:
|
||||
- mkdir public
|
||||
- mv build/docs/index.html public/
|
||||
- for i in devel interop specs system tools user ; do mv build/docs/$i public/ ; done
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
script:
|
||||
- TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64"
|
||||
- ./configure --enable-tcg-interpreter
|
||||
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
|
||||
- make -j2
|
||||
- make tests/boot-serial-test tests/cdrom-test tests/pxe-test
|
||||
- for tg in $TARGETS ; do
|
||||
export QTEST_QEMU_BINARY="${tg}-softmmu/qemu-system-${tg}" ;
|
||||
./tests/boot-serial-test || exit 1 ;
|
||||
./tests/cdrom-test || exit 1 ;
|
||||
done
|
||||
- QTEST_QEMU_BINARY="x86_64-softmmu/qemu-system-x86_64" ./tests/pxe-test
|
||||
- QTEST_QEMU_BINARY="s390x-softmmu/qemu-system-s390x" ./tests/pxe-test -m slow
|
||||
+4
-7
@@ -10,6 +10,9 @@
|
||||
[submodule "roms/openbios"]
|
||||
path = roms/openbios
|
||||
url = https://git.qemu.org/git/openbios.git
|
||||
[submodule "roms/openhackware"]
|
||||
path = roms/openhackware
|
||||
url = https://git.qemu.org/git/openhackware.git
|
||||
[submodule "roms/qemu-palcode"]
|
||||
path = roms/qemu-palcode
|
||||
url = https://git.qemu.org/git/qemu-palcode.git
|
||||
@@ -57,10 +60,4 @@
|
||||
url = https://git.qemu.org/git/opensbi.git
|
||||
[submodule "roms/qboot"]
|
||||
path = roms/qboot
|
||||
url = https://git.qemu.org/git/qboot.git
|
||||
[submodule "meson"]
|
||||
path = meson
|
||||
url = https://git.qemu.org/git/meson.git
|
||||
[submodule "roms/vbootrom"]
|
||||
path = roms/vbootrom
|
||||
url = https://git.qemu.org/git/vbootrom.git
|
||||
url = https://github.com/bonzini/qboot
|
||||
@@ -39,24 +39,15 @@ Julia Suvorova <jusual@mail.ru> Julia Suvorova via Qemu-devel <qemu-devel@nongnu
|
||||
Justin Terry (VM) <juterry@microsoft.com> Justin Terry (VM) via Qemu-devel <qemu-devel@nongnu.org>
|
||||
|
||||
# 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@imgtec.com>
|
||||
Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <amarkovic@wavecomp.com>
|
||||
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <arikalo@wavecomp.com>
|
||||
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
|
||||
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
|
||||
Aleksandar Markovic <amarkovic@wavecomp.com> <aleksandar.markovic@mips.com>
|
||||
Aleksandar Markovic <amarkovic@wavecomp.com> <aleksandar.markovic@imgtec.com>
|
||||
Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com> <arikalo@wavecomp.com>
|
||||
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
|
||||
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
|
||||
Frederic Konrad <konrad@adacore.com> <fred.konrad@greensocs.com>
|
||||
Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
|
||||
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
|
||||
Leif Lindholm <leif@nuviainc.com> <leif.lindholm@linaro.org>
|
||||
Radoslaw Biernacki <rad@semihalf.com> <radoslaw.biernacki@linaro.org>
|
||||
Paul Burton <paulburton@kernel.org> <paul.burton@mips.com>
|
||||
Paul Burton <paulburton@kernel.org> <paul.burton@imgtec.com>
|
||||
Paul Burton <paulburton@kernel.org> <paul@archlinuxmips.org>
|
||||
Paul Burton <paulburton@kernel.org> <pburton@wavecomp.com>
|
||||
Stefan Brankovic <stefan.brankovic@syrmia.com> <stefan.brankovic@rt-rk.com.com>
|
||||
Paul Burton <pburton@wavecomp.com> <paul.burton@mips.com>
|
||||
Paul Burton <pburton@wavecomp.com> <paul.burton@imgtec.com>
|
||||
Paul Burton <pburton@wavecomp.com> <paul@archlinuxmips.org>
|
||||
Philippe Mathieu-Daudé <philmd@redhat.com> <f4bug@amsat.org>
|
||||
Yongbok Kim <yongbok.kim@mips.com> <yongbok.kim@imgtec.com>
|
||||
|
||||
# Also list preferred name forms where people have changed their
|
||||
@@ -85,7 +76,6 @@ Christophe Lyon <christophe.lyon@st.com>
|
||||
Collin L. Walling <walling@linux.ibm.com>
|
||||
Daniel P. Berrangé <berrange@redhat.com>
|
||||
Eduardo Otubo <otubo@redhat.com>
|
||||
Erik Smit <erik.lucas.smit@gmail.com>
|
||||
Fabrice Desclaux <fabrice.desclaux@cea.fr>
|
||||
Fernando Luis Vázquez Cao <fernando_b1@lab.ntt.co.jp>
|
||||
Fernando Luis Vázquez Cao <fernando@oss.ntt.co.jp>
|
||||
@@ -143,7 +133,6 @@ Roger Pau Monné <roger.pau@citrix.com>
|
||||
Shin'ichiro Kawasaki <kawasaki@juno.dti.ne.jp>
|
||||
Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
|
||||
Sochin Jiang <sochin.jiang@huawei.com>
|
||||
Stefan Berger <stefanb@linux.vnet.ibm.com> <stefanb@linux.ibm.com>
|
||||
Takashi Yoshii <takasi-y@ops.dti.ne.jp>
|
||||
Thomas Huth <thuth@redhat.com>
|
||||
Thomas Knych <thomaswk@google.com>
|
||||
@@ -162,8 +151,7 @@ Xiaoqiang Zhao <zxq_yx_007@163.com>
|
||||
Xinhua Cao <caoxinhua@huawei.com>
|
||||
Xiong Zhang <xiong.y.zhang@intel.com>
|
||||
Yin Yin <yin.yin@cs2c.com.cn>
|
||||
Yu-Chen Lin <npes87184@gmail.com>
|
||||
Yu-Chen Lin <npes87184@gmail.com> <yuchenlin@synology.com>
|
||||
yuchenlin <npes87184@gmail.com>
|
||||
YunQiang Su <syq@debian.org>
|
||||
YunQiang Su <ysu@wavecomp.com>
|
||||
Yuri Pudgorodskiy <yur@virtuozzo.com>
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# .readthedocs.yml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
# We want all the document formats
|
||||
formats: all
|
||||
|
||||
# For consistency, we require that QEMU's Sphinx extensions
|
||||
# run with at least the same minimum version of Python that
|
||||
# we require for other Python in our codebase (our conf.py
|
||||
# enforces this, and some code needs it.)
|
||||
python:
|
||||
version: 3.6
|
||||
+10
-6
@@ -7,6 +7,10 @@ env:
|
||||
matrix:
|
||||
- IMAGE=debian-amd64
|
||||
TARGET_LIST=x86_64-softmmu,x86_64-linux-user
|
||||
- IMAGE=debian-win32-cross
|
||||
TARGET_LIST=arm-softmmu,i386-softmmu,lm32-softmmu
|
||||
- IMAGE=debian-win64-cross
|
||||
TARGET_LIST=aarch64-softmmu,sparc64-softmmu,x86_64-softmmu
|
||||
- IMAGE=debian-armel-cross
|
||||
TARGET_LIST=arm-softmmu,arm-linux-user,armeb-linux-user
|
||||
- IMAGE=debian-armhf-cross
|
||||
@@ -22,14 +26,14 @@ env:
|
||||
- IMAGE=debian-ppc64el-cross
|
||||
TARGET_LIST=ppc64-softmmu,ppc64-linux-user,ppc64abi32-linux-user
|
||||
build:
|
||||
pre_ci:
|
||||
- make docker-image-${IMAGE} V=1
|
||||
pre_ci_boot:
|
||||
image_name: registry.gitlab.com/qemu-project/qemu/qemu/${IMAGE}
|
||||
image_tag: latest
|
||||
pull: true
|
||||
image_name: qemu
|
||||
image_tag: ${IMAGE}
|
||||
pull: false
|
||||
options: "-e HOME=/root"
|
||||
ci:
|
||||
- unset CC
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --disable-docs ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
|
||||
- ./configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
|
||||
- make -j$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
+165
-278
@@ -1,16 +1,16 @@
|
||||
# The current Travis default is a VM based 16.04 Xenial on GCE
|
||||
# Additional builds with specific requirements for a full VM need to
|
||||
# be added as additional matrix: entries later on
|
||||
os: linux
|
||||
dist: focal
|
||||
dist: xenial
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
cache:
|
||||
# There is one cache per branch and compiler version.
|
||||
# characteristics of each job are used to identify the cache:
|
||||
# - OS name (currently only linux)
|
||||
# - OS distribution (for Linux, bionic or focal)
|
||||
# - OS name (currently, linux, osx, or windows)
|
||||
# - OS distribution (for Linux, xenial, trusty, or precise)
|
||||
# - macOS image name (e.g., xcode7.2)
|
||||
# - Names and values of visible environment variables set in .travis.yml or Settings panel
|
||||
timeout: 1200
|
||||
ccache: true
|
||||
@@ -26,8 +26,9 @@ addons:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-dev
|
||||
- libcap-ng-dev
|
||||
- libgcc-7-dev
|
||||
- libgcc-4.8-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
@@ -48,13 +49,16 @@ addons:
|
||||
- libusb-1.0-0-dev
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- libzstd-dev
|
||||
- ninja-build
|
||||
- sparse
|
||||
- uuid-dev
|
||||
- gcovr
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
- glib
|
||||
- pixman
|
||||
- gnu-sed
|
||||
update: true
|
||||
|
||||
|
||||
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
|
||||
@@ -70,107 +74,94 @@ notifications:
|
||||
|
||||
env:
|
||||
global:
|
||||
- SRC_DIR=".."
|
||||
- BUILD_DIR="build"
|
||||
- SRC_DIR="."
|
||||
- BUILD_DIR="."
|
||||
- BASE_CONFIG="--disable-docs --disable-tools"
|
||||
- TEST_BUILD_CMD=""
|
||||
- TEST_CMD="make check V=1"
|
||||
# This is broadly a list of "mainline" softmmu targets which have support across the major distros
|
||||
- MAIN_SOFTMMU_TARGETS="aarch64-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
|
||||
- CCACHE_SLOPPINESS="include_file_ctime,include_file_mtime"
|
||||
- CCACHE_MAXSIZE=1G
|
||||
- G_MESSAGES_DEBUG=error
|
||||
|
||||
|
||||
git:
|
||||
# we want to do this ourselves
|
||||
submodules: false
|
||||
|
||||
# Common first phase for all steps
|
||||
before_install:
|
||||
- if command -v ccache ; then ccache --zero-stats ; fi
|
||||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
|
||||
# Configure step - may be overridden
|
||||
before_script:
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ] ; then export PATH="/usr/local/opt/ccache/libexec:$PATH" ; fi
|
||||
- if command -v ccache ; then ccache --zero-stats ; fi
|
||||
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
|
||||
- ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
|
||||
# Main build & test - rarely overridden - controlled by TEST_CMD
|
||||
- ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
|
||||
script:
|
||||
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
|
||||
- |
|
||||
if [ "$BUILD_RC" -eq 0 ] && [ -n "$TEST_BUILD_CMD" ]; then
|
||||
${TEST_BUILD_CMD} || BUILD_RC=$?
|
||||
else
|
||||
$(exit $BUILD_RC);
|
||||
fi
|
||||
- |
|
||||
if [ "$BUILD_RC" -eq 0 ] ; then
|
||||
${TEST_CMD} ;
|
||||
else
|
||||
$(exit $BUILD_RC);
|
||||
fi
|
||||
- make -j3 && travis_retry ${TEST_CMD}
|
||||
after_script:
|
||||
- df -h
|
||||
- if command -v ccache ; then ccache --show-stats ; fi
|
||||
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
include:
|
||||
- name: "GCC static (user)"
|
||||
env:
|
||||
- env:
|
||||
- CONFIG="--disable-system --static"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
|
||||
|
||||
# we split the system builds as it takes a while to build them all
|
||||
- env:
|
||||
- CONFIG="--disable-user --target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
|
||||
|
||||
# Just build tools and run minimal unit and softfloat checks
|
||||
- name: "GCC check-unit and check-softfloat"
|
||||
env:
|
||||
- env:
|
||||
- BASE_CONFIG="--enable-tools"
|
||||
- CONFIG="--disable-user --disable-system"
|
||||
- TEST_CMD="make check-unit check-softfloat -j${JOBS}"
|
||||
- TEST_CMD="make check-unit check-softfloat -j3"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
|
||||
|
||||
# --enable-debug implies --enable-debug-tcg, also runs quite a bit slower
|
||||
- name: "GCC debug (main-softmmu)"
|
||||
env:
|
||||
- env:
|
||||
- CONFIG="--enable-debug --target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug"
|
||||
|
||||
|
||||
# TCG debug can be run just on its own and is mostly agnostic to user/softmmu distinctions
|
||||
- name: "GCC debug (user)"
|
||||
env:
|
||||
- env:
|
||||
- CONFIG="--enable-debug-tcg --disable-system"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--disable-linux-aio --disable-cap-ng --disable-attr --disable-brlapi --disable-libusb --disable-replication --target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
|
||||
|
||||
# Module builds are mostly of interest to major distros
|
||||
- name: "GCC modules (main-softmmu)"
|
||||
env:
|
||||
- env:
|
||||
- CONFIG="--enable-modules --target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
|
||||
|
||||
# Alternate coroutines implementations are only really of interest to KVM users
|
||||
# However we can't test against KVM on Travis so we can only run unit tests
|
||||
- name: "check-unit coroutine=ucontext"
|
||||
env:
|
||||
- env:
|
||||
- CONFIG="--with-coroutine=ucontext --disable-tcg"
|
||||
- TEST_CMD="make check-unit -j${JOBS} V=1"
|
||||
- TEST_CMD="make check-unit -j3 V=1"
|
||||
|
||||
|
||||
- name: "check-unit coroutine=sigaltstack"
|
||||
env:
|
||||
- env:
|
||||
- CONFIG="--with-coroutine=sigaltstack --disable-tcg"
|
||||
- TEST_CMD="make check-unit -j${JOBS} V=1"
|
||||
- TEST_CMD="make check-unit -j3 V=1"
|
||||
|
||||
|
||||
# Check we can build docs and tools (out of tree)
|
||||
- name: "tools and docs (bionic)"
|
||||
dist: bionic
|
||||
env:
|
||||
- env:
|
||||
- BUILD_DIR="out-of-tree/build/dir" SRC_DIR="../../.."
|
||||
- BASE_CONFIG="--enable-tools --enable-docs"
|
||||
- CONFIG="--target-list=x86_64-softmmu,aarch64-linux-user"
|
||||
@@ -178,64 +169,118 @@ jobs:
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- ninja-build
|
||||
- python3-sphinx
|
||||
- python-sphinx
|
||||
- texinfo
|
||||
- perl
|
||||
|
||||
|
||||
# Test with Clang for compile portability (Travis uses clang-5.0)
|
||||
- name: "Clang (user)"
|
||||
env:
|
||||
- CONFIG="--disable-system --host-cc=clang --cxx=clang++"
|
||||
- env:
|
||||
- CONFIG="--disable-system"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default"
|
||||
compiler: clang
|
||||
|
||||
|
||||
- name: "Clang (main-softmmu)"
|
||||
env:
|
||||
- CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS}
|
||||
--host-cc=clang --cxx=clang++"
|
||||
- env:
|
||||
- CONFIG="--disable-user --target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default"
|
||||
compiler: clang
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} "
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-sanitize"
|
||||
compiler: clang
|
||||
before_script:
|
||||
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
|
||||
- ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- ./configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
|
||||
|
||||
|
||||
- name: "Clang (other-softmmu)"
|
||||
env:
|
||||
- CONFIG="--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}
|
||||
--host-cc=clang --cxx=clang++"
|
||||
- env:
|
||||
- CONFIG="--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default"
|
||||
compiler: clang
|
||||
|
||||
|
||||
# gprof/gcov are GCC features
|
||||
- name: "GCC gprof/gcov"
|
||||
dist: bionic
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- ninja-build
|
||||
env:
|
||||
- CONFIG="--enable-gprof --enable-gcov --disable-libssh
|
||||
--target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
- env:
|
||||
- CONFIG="--enable-gprof --enable-gcov --disable-pie --target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
after_success:
|
||||
- ${SRC_DIR}/scripts/travis/coverage-summary.sh
|
||||
|
||||
|
||||
# We manually include builds which we disable "make check" for
|
||||
- name: "GCC without-default-devices (softmmu)"
|
||||
env:
|
||||
- env:
|
||||
- CONFIG="--without-default-devices --disable-user"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
- TEST_CMD=""
|
||||
|
||||
|
||||
# Using newer GCC with sanitizers
|
||||
- name: "GCC9 with sanitizers (softmmu)"
|
||||
dist: bionic
|
||||
# We manually include builds which we disable "make check" for
|
||||
- env:
|
||||
- CONFIG="--enable-debug --enable-tcg-interpreter"
|
||||
- TEST_CMD=""
|
||||
|
||||
|
||||
# We don't need to exercise every backend with every front-end
|
||||
- env:
|
||||
- CONFIG="--enable-trace-backends=log,simple,syslog --disable-system"
|
||||
- TEST_CMD=""
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--enable-trace-backends=ftrace --target-list=x86_64-softmmu"
|
||||
- TEST_CMD=""
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--enable-trace-backends=ust --target-list=x86_64-softmmu"
|
||||
- TEST_CMD=""
|
||||
|
||||
|
||||
# MacOSX builds - cirrus.yml also tests some MacOS builds including latest Xcode
|
||||
|
||||
- env:
|
||||
- CONFIG="--target-list=i386-softmmu,ppc-softmmu,ppc64-softmmu,m68k-softmmu,x86_64-softmmu"
|
||||
os: osx
|
||||
osx_image: xcode10.3
|
||||
compiler: clang
|
||||
|
||||
|
||||
# Python builds
|
||||
- env:
|
||||
- CONFIG="--target-list=x86_64-softmmu"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
language: python
|
||||
python:
|
||||
- "3.4"
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--target-list=x86_64-softmmu"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
language: python
|
||||
python:
|
||||
- "3.6"
|
||||
|
||||
|
||||
# Acceptance (Functional) tests
|
||||
- env:
|
||||
- CONFIG="--python=/usr/bin/python3 --target-list=x86_64-softmmu,mips-softmmu,mips64el-softmmu,aarch64-softmmu,arm-softmmu,s390x-softmmu,alpha-softmmu,ppc-softmmu,ppc64-softmmu,m68k-softmmu,sparc-softmmu"
|
||||
- TEST_CMD="make check-acceptance"
|
||||
after_failure:
|
||||
- cat tests/results/latest/job.log
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- python3-pil
|
||||
- python3-pip
|
||||
- python3.5-venv
|
||||
- tesseract-ocr
|
||||
- tesseract-ocr-eng
|
||||
|
||||
|
||||
# Using newer GCC with sanitizers
|
||||
- addons:
|
||||
apt:
|
||||
update: true
|
||||
sources:
|
||||
@@ -250,7 +295,7 @@ jobs:
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libgnutls28-dev
|
||||
- libgnutls-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
@@ -258,234 +303,76 @@ jobs:
|
||||
- libncurses5-dev
|
||||
- libnss3-dev
|
||||
- libpixman-1-dev
|
||||
- libpng-dev
|
||||
- libpng12-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
|
||||
- libvte-2.91-dev
|
||||
- ninja-build
|
||||
- sparse
|
||||
- uuid-dev
|
||||
language: generic
|
||||
compiler: none
|
||||
env:
|
||||
- COMPILER_NAME=gcc CXX=g++-9 CC=gcc-9
|
||||
- CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-linux-user"
|
||||
- CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-pie --disable-linux-user"
|
||||
- TEST_CMD=""
|
||||
before_script:
|
||||
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
|
||||
- ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -fsanitize=thread" || { cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
- ./configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
|
||||
|
||||
|
||||
- name: "[aarch64] GCC check-tcg"
|
||||
arch: arm64
|
||||
dist: focal
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
- libncurses5-dev
|
||||
- libnfs-dev
|
||||
- libnss3-dev
|
||||
- libpixman-1-dev
|
||||
- libpng-dev
|
||||
- librados-dev
|
||||
- libsdl2-dev
|
||||
- libseccomp-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- ninja-build
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
- UNRELIABLE=true
|
||||
# Run check-tcg against linux-user
|
||||
- env:
|
||||
- CONFIG="--disable-system --enable-debug-tcg"
|
||||
- TEST_CMD="make -j3 check-tcg V=1"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
||||
|
||||
- name: "[ppc64] GCC check-tcg"
|
||||
arch: ppc64le
|
||||
dist: focal
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
- libncurses5-dev
|
||||
- libnfs-dev
|
||||
- libnss3-dev
|
||||
- libpixman-1-dev
|
||||
- libpng-dev
|
||||
- librados-dev
|
||||
- libsdl2-dev
|
||||
- libseccomp-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- ninja-build
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --target-list=ppc64-softmmu,ppc64le-linux-user"
|
||||
|
||||
- name: "[s390x] GCC check-tcg"
|
||||
arch: s390x
|
||||
dist: bionic
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
- libncurses5-dev
|
||||
- libnfs-dev
|
||||
- libnss3-dev
|
||||
- libpixman-1-dev
|
||||
- libpng-dev
|
||||
- librados-dev
|
||||
- libsdl2-dev
|
||||
- libseccomp-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- ninja-build
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
|
||||
- UNRELIABLE=true
|
||||
script:
|
||||
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
|
||||
- |
|
||||
if [ "$BUILD_RC" -eq 0 ] ; then
|
||||
mv pc-bios/s390-ccw/*.img pc-bios/ ;
|
||||
${TEST_CMD} ;
|
||||
else
|
||||
$(exit $BUILD_RC);
|
||||
fi
|
||||
# Run check-tcg against linux-user (with plugins)
|
||||
# we skip sparc64-linux-user until it has been fixed somewhat
|
||||
- env:
|
||||
- CONFIG="--disable-system --enable-plugins --enable-debug-tcg --target-list-exclude=sparc64-linux-user"
|
||||
- TEST_CMD="make -j3 check-tcg V=1"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
||||
|
||||
- name: "[s390x] GCC (other-softmmu)"
|
||||
arch: s390x
|
||||
dist: bionic
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libcap-ng-dev
|
||||
- libgnutls28-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
- liblzo2-dev
|
||||
- libncurses-dev
|
||||
- libnfs-dev
|
||||
- libnss3-dev
|
||||
- libpixman-1-dev
|
||||
- libsdl2-dev
|
||||
- libsdl2-image-dev
|
||||
- libseccomp-dev
|
||||
- libsnappy-dev
|
||||
- libzstd-dev
|
||||
- nettle-dev
|
||||
- xfslibs-dev
|
||||
- ninja-build
|
||||
# Tests dependencies
|
||||
- genisoimage
|
||||
env:
|
||||
- CONFIG="--disable-containers --audio-drv-list=sdl --disable-user
|
||||
--target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
|
||||
|
||||
- name: "[s390x] GCC (user)"
|
||||
arch: s390x
|
||||
dist: bionic
|
||||
addons:
|
||||
apt_packages:
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- ninja-build
|
||||
env:
|
||||
- CONFIG="--disable-containers --disable-system"
|
||||
# Run check-tcg against softmmu targets
|
||||
- env:
|
||||
- CONFIG="--enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu"
|
||||
- TEST_CMD="make -j3 check-tcg V=1"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
||||
|
||||
|
||||
# Run check-tcg against softmmu targets (with plugins)
|
||||
- env:
|
||||
- CONFIG="--enable-plugins --enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu"
|
||||
- TEST_CMD="make -j3 check-tcg V=1"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
||||
|
||||
- name: "[s390x] Clang (disable-tcg)"
|
||||
arch: s390x
|
||||
dist: bionic
|
||||
compiler: clang
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
- libncurses5-dev
|
||||
- libnfs-dev
|
||||
- libnss3-dev
|
||||
- libpixman-1-dev
|
||||
- libpng-dev
|
||||
- librados-dev
|
||||
- libsdl2-dev
|
||||
- libseccomp-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
- ninja-build
|
||||
env:
|
||||
- TEST_CMD="make check-unit"
|
||||
- CONFIG="--disable-containers --disable-tcg --enable-kvm
|
||||
--disable-tools --host-cc=clang --cxx=clang++"
|
||||
- UNRELIABLE=true
|
||||
|
||||
# Release builds
|
||||
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
|
||||
# This is the case when release candidate tags are created.
|
||||
- name: "Release tarball"
|
||||
if: tag IS present AND tag =~ /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
- 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}"
|
||||
- TEST_CMD="make install -j3"
|
||||
- QEMU_VERSION="${TRAVIS_TAG:1}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||
before_script:
|
||||
- command -v ccache && ccache --zero-stats
|
||||
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
|
||||
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; }
|
||||
- ./configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
|
||||
- make install
|
||||
allow_failures:
|
||||
- env: UNRELIABLE=true
|
||||
+2
-35
@@ -109,41 +109,8 @@ names are lower_case_with_underscores_ending_with_a_t, like the POSIX
|
||||
uint64_t and family. Note that this last convention contradicts POSIX
|
||||
and is therefore likely to be changed.
|
||||
|
||||
Variable Naming Conventions
|
||||
---------------------------
|
||||
|
||||
A number of short naming conventions exist for variables that use
|
||||
common QEMU types. For example, the architecture independent CPUState
|
||||
is often held as a ``cs`` pointer variable, whereas the concrete
|
||||
CPUArchState is usually held in a pointer called ``env``.
|
||||
|
||||
Likewise, in device emulation code the common DeviceState is usually
|
||||
called ``dev``.
|
||||
|
||||
Function Naming Conventions
|
||||
---------------------------
|
||||
|
||||
Wrapped version of standard library or GLib functions use a ``qemu_``
|
||||
prefix to alert readers that they are seeing a wrapped version, for
|
||||
example ``qemu_strtol`` or ``qemu_mutex_lock``. Other utility functions
|
||||
that are widely called from across the codebase should not have any
|
||||
prefix, for example ``pstrcpy`` or bit manipulation functions such as
|
||||
``find_first_bit``.
|
||||
|
||||
The ``qemu_`` prefix is also used for functions that modify global
|
||||
emulator state, for example ``qemu_add_vm_change_state_handler``.
|
||||
However, if there is an obvious subsystem-specific prefix it should be
|
||||
used instead.
|
||||
|
||||
Public functions from a file or subsystem (declared in headers) tend
|
||||
to have a consistent prefix to show where they came from. For example,
|
||||
``tlb_`` for functions from ``cputlb.c`` or ``cpu_`` for functions
|
||||
from cpus.c.
|
||||
|
||||
If there are two versions of a function to be called with or without a
|
||||
lock held, the function that expects the lock to be already held
|
||||
usually uses the suffix ``_locked``.
|
||||
|
||||
When wrapping standard library functions, use the prefix ``qemu_`` to alert
|
||||
readers that they are seeing a wrapped version; otherwise avoid this prefix.
|
||||
|
||||
Block structure
|
||||
===============
|
||||
|
||||
@@ -0,0 +1,580 @@
|
||||
This file documents changes for QEMU releases 0.12 and earlier.
|
||||
For changelog information for later releases, see
|
||||
https://wiki.qemu.org/ChangeLog or look at the git history for
|
||||
more detailed information.
|
||||
|
||||
|
||||
version 0.12.0:
|
||||
|
||||
- Update to SeaBIOS 0.5.0
|
||||
- e1000: fix device link status in Linux (Anthony Liguori)
|
||||
- monitor: fix QMP for balloon command (Luiz Capitulino)
|
||||
- QMP: Return an empty dict by default (Luiz Capitulino)
|
||||
- QMP: Only handle converted commands (Luiz Capitulino)
|
||||
- pci: support PCI based option rom loading (Gerd Hoffman/Anthony Liguori)
|
||||
- Fix backcompat for hotplug of SCSI controllers (Daniel P. Berrange)
|
||||
- fdc: fix migration from 0.11 (Juan Quintela)
|
||||
- vmware-vga: fix segv on cursor resize. (Dave Airlie)
|
||||
- vmware-vga: various fixes (Dave Airlie/Anthony Liguori)
|
||||
- qdev: improve property error reporting. (Gerd Hoffmann)
|
||||
- fix vga names in default_list (Gerd Hoffmann)
|
||||
- usb-host: check mon before using it. (Gerd Hoffmann)
|
||||
- usb-net: use qdev for -usbdevice (Gerd Hoffmann)
|
||||
- monitor: Catch printing to non-existent monitor (Luiz Capitulino)
|
||||
- Avoid permanently disabled QEMU monitor when UNIX migration fails (Daniel P. Berrange)
|
||||
- Fix loading of ELF multiboot kernels (Kevin Wolf)
|
||||
- qemu-io: Fix memory leak (Kevin Wolf)
|
||||
- Fix thinko in linuxboot.S (Paolo Bonzini)
|
||||
- target-i386: Fix evaluation of DR7 register (Jan Kiszka)
|
||||
- vnc: hextile: do not generate ForegroundSpecified and SubrectsColoured tiles (Anthony Liguori)
|
||||
- S390: Bail out without KVM (Alexander Graf)
|
||||
- S390: Don't tell guest we're updating config space (Alexander Graf)
|
||||
- target-s390: Fail on unknown instructions (Alexander Graf)
|
||||
- osdep: Fix runtime failure on older Linux kernels (Andre Przywara)
|
||||
- Fix a make -j race (Juergen Lock)
|
||||
- target-alpha: Fix generic ctz64. (Richard Henderson)
|
||||
- s390: Fix buggy assignment (Stefan Weil)
|
||||
- target-mips: fix user-mode emulation startup (Nathan Froyd)
|
||||
- target-i386: Update CPUID feature set for TCG (Andre Przywara)
|
||||
- s390: fix build on 32 bit host (Michael S. Tsirkin)
|
||||
|
||||
version 0.12.0-rc2:
|
||||
|
||||
- v2: properly save kvm system time msr registers (Glauber Costa)
|
||||
- convert more monitor commands to qmp (Luiz Capitulino)
|
||||
- vnc: fix capslock tracking logic. (Gerd Hoffmann)
|
||||
- QemuOpts: allow larger option values. (Gerd Hoffmann)
|
||||
- scsi: fix drive hotplug. (Gerd Hoffmann)
|
||||
- pci: don't hw_error() when no slot is available. (Gerd Hoffmann)
|
||||
- pci: don't abort() when trying to hotplug with acpi off. (Gerd Hoffmann)
|
||||
- allow default devices to be implemented in config file (Gerd Hoffman)
|
||||
- vc: colorize chardev title line with blue background. (Gerd Hoffmann)
|
||||
- chardev: make chardevs specified in config file work. (Gerd Hoffmann)
|
||||
- qdev: also match bus name for global properties (Gerd Hoffmann)
|
||||
- qdev: add command line option to set global defaults for properties. (Gerd Hoffmann)
|
||||
- kvm: x86: Save/restore exception_index (Jan Kiszka)
|
||||
- qdev: Replace device names containing whitespace (Markus Armbruster)
|
||||
- fix rtc-td-hack on host without high-res timers (Gleb Natapov)
|
||||
- virtio: verify features on load (Michael S. Tsirkin)
|
||||
- vmware_vga: add rom file so that it boots. (Dave Airlie)
|
||||
- Do not abort on qemu_malloc(0) in production builds (Anthony Liguori)
|
||||
- Fix ARM userspace strex implementation. (Paul Brook)
|
||||
- qemu: delete rule target on error (Michael S. Tsirkin)
|
||||
- QMP: add human-readable description to error response (Markus Armbruster)
|
||||
- convert more monitor commands to QError (Markus Armbruster)
|
||||
- monitor: Fix double-prompt after "change vnc passwd BLA" (Markus Armbruster)
|
||||
- monitor: do_cont(): Don't ask for passwords (Luiz Capitulino)
|
||||
- monitor: Introduce 'block_passwd' command (Luiz Capitulino)
|
||||
- pci: interrupt disable bit support (Michael S. Tsirkin)
|
||||
- pci: interrupt status bit implementation (Michael S. Tsirkin)
|
||||
- pci: prepare irq code for interrupt state (Michael S. Tsirkin)
|
||||
- msix: function mask support (Michael S. Tsirkin)
|
||||
- msix: macro rename for function mask support (Michael S. Tsirkin)
|
||||
- cpuid: Fix multicore setup on Intel (Andre Przywara)
|
||||
- kvm: x86: Fix initial kvm_has_msr_star (Jan Kiszka)
|
||||
- Update OpenBIOS images to r640 (Aurelien Jarno)
|
||||
|
||||
version 0.10.2:
|
||||
|
||||
- fix savevm/loadvm (Anthony Liguori)
|
||||
- live migration: fix dirty tracking windows (Glauber Costa)
|
||||
- live migration: improve error propagation (Glauber Costa)
|
||||
- qcow2: fix image creation for > ~2TB images (Chris Wright)
|
||||
- hotplug: fix error handling for if= parameter (Eduardo Habkost)
|
||||
- qcow2: fix data corruption (Nolan Leake)
|
||||
- virtio: fix guest oops with 2.6.25 kernels (Rusty Russell)
|
||||
- SH4: add support for -kernel (Takashi Yoshii, Aurelien Jarno)
|
||||
- hotplug: fix closing of char devices (Jan Kiszka)
|
||||
- hotplug: remove incorrect check for device name (Eduardo Habkost)
|
||||
- enable -k on win32 (Herve Poussineau)
|
||||
- configure: use LANG=C for grep (Andreas Faerber)
|
||||
- fix VGA regression (malc)
|
||||
|
||||
version 0.10.1:
|
||||
|
||||
- virtio-net: check right return size on sg list (Alex Williamson)
|
||||
- Make qemu_announce_self handle holes (live migration after hotplug)
|
||||
(Marcelo Tosatti)
|
||||
- Revert r6804-r6808 (qcow2 allocation info). This series of changes added
|
||||
a high cost to startup for large qcow2 images (Anthony Liguori)
|
||||
- qemu-img: fix help message (Aurelien Jarno)
|
||||
- Fix build for non-default installs of SDL (Anthony Liguori)
|
||||
- Fix race condition in env->interrupt_request. When using TCG and a dynticks
|
||||
host timer, this condition could cause TCG to get stuck in an infinite
|
||||
loop (Aurelien Jarno)
|
||||
- Fix reading encrypted hard disk passwords during early startup (Jan Kiszka)
|
||||
- Fix encrypted disk reporting in 'info block' (Jan Kiszka)
|
||||
- Fix console size with tiny displays (MusicPal) (Jan Kiszka)
|
||||
- Improve error handling in bdrv_open2 (Jan Kiszka)
|
||||
- Avoid leaking data in mux'ed character devices (Jan Kiszka)
|
||||
- Fix initial character device reset (no banner in monitor) (Jan Kiszka)
|
||||
- Fix cpuid KVM crash on i386 host (Lubomir Rintel)
|
||||
- Fix SLES10sp2 installation by adding ISTAT1 register to LSI SCSI emulation
|
||||
(Ryan Harper)
|
||||
|
||||
version 0.10.0:
|
||||
|
||||
- TCG support (No longer requires GCC 3.x)
|
||||
- Kernel Virtual Machine acceleration support
|
||||
- BSD userspace emulation
|
||||
- Bluetooth emulation and host passthrough support
|
||||
- GDB XML register description support
|
||||
- Intel e1000 emulation
|
||||
- HPET emulation
|
||||
- VirtIO paravirtual device support
|
||||
- Marvell 88w8618 / MusicPal emulation
|
||||
- Nokia N-series tablet emulation / OMAP2 processor emulation
|
||||
- PCI hotplug support
|
||||
- Live migration and new save/restore formats
|
||||
- Curses display support
|
||||
- qemu-nbd utility to mount supported block formats
|
||||
- Altivec support in PPC emulation and new firmware (OpenBIOS)
|
||||
- Multiple VNC clients are now supported
|
||||
- TLS encryption is now supported in VNC
|
||||
- MIPS Magnum R4000 machine (Hervé Poussineau)
|
||||
- Braille support (Samuel Thibault)
|
||||
- Freecom MusicPal system emulation (Jan Kiszka)
|
||||
- OMAP242x and Nokia N800, N810 machines (Andrzej Zaborowski)
|
||||
- EsounD audio driver (Frederick Reeve)
|
||||
- Gravis Ultrasound GF1 sound card (Tibor "TS" Schütz)
|
||||
- Many, many, bug fixes and new features
|
||||
|
||||
version 0.9.1:
|
||||
|
||||
- TFTP booting from host directory (Anthony Liguori, Erwan Velu)
|
||||
- Tap device emulation for Solaris (Sittichai Palanisong)
|
||||
- Monitor multiplexing to several I/O channels (Jason Wessel)
|
||||
- ds1225y nvram support (Herve Poussineau)
|
||||
- CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
|
||||
- Several Sparc fixes (Aurelien Jarno, Blue Swirl, Robert Reif)
|
||||
- MIPS 64-bit FPU support (Thiemo Seufer)
|
||||
- Xscale PDA emulation (Andrzej Zaborowski)
|
||||
- ColdFire system emulation (Paul Brook)
|
||||
- Improved SH4 support (Magnus Damm)
|
||||
- MIPS64 support (Aurelien Jarno, Thiemo Seufer)
|
||||
- Preliminary Alpha guest support (J. Mayer)
|
||||
- Read-only support for Parallels disk images (Alex Beregszaszi)
|
||||
- SVM (x86 virtualization) support (Alexander Graf)
|
||||
- CRIS emulation (Edgar E. Iglesias)
|
||||
- SPARC32PLUS execution support (Blue Swirl)
|
||||
- MIPS mipssim pseudo machine (Thiemo Seufer)
|
||||
- Strace for Linux userland emulation (Stuart Anderson, Thayne Harbaugh)
|
||||
- OMAP310 MPU emulation plus Palm T|E machine (Andrzej Zaborowski)
|
||||
- ARM v6, v7, NEON SIMD and SMP emulation (Paul Brook/CodeSourcery)
|
||||
- Gumstix boards: connex and verdex emulation (Thorsten Zitterell)
|
||||
- Intel mainstone II board emulation (Armin Kuster)
|
||||
- VMware SVGA II graphics card support (Andrzej Zaborowski)
|
||||
|
||||
version 0.9.0:
|
||||
|
||||
- Support for relative paths in backing files for disk images
|
||||
- Async file I/O API
|
||||
- New qcow2 disk image format
|
||||
- Support of multiple VM snapshots
|
||||
- Linux: specific host CDROM and floppy support
|
||||
- SMM support
|
||||
- Moved PCI init, MP table init and ACPI table init to Bochs BIOS
|
||||
- Support for MIPS32 Release 2 instruction set (Thiemo Seufer)
|
||||
- MIPS Malta system emulation (Aurelien Jarno, Stefan Weil)
|
||||
- Darwin userspace emulation (Pierre d'Herbemont)
|
||||
- m68k user support (Paul Brook)
|
||||
- several x86 and x86_64 emulation fixes
|
||||
- Mouse relative offset VNC extension (Anthony Liguori)
|
||||
- PXE boot support (Anthony Liguori)
|
||||
- '-daemonize' option (Anthony Liguori)
|
||||
|
||||
version 0.8.2:
|
||||
|
||||
- ACPI support
|
||||
- PC VGA BIOS fixes
|
||||
- switch to OpenBios for SPARC targets (Blue Swirl)
|
||||
- VNC server fixes
|
||||
- MIPS FPU support (Marius Groeger)
|
||||
- Solaris/SPARC host support (Juergen Keil)
|
||||
- PPC breakpoints and single stepping (Jason Wessel)
|
||||
- USB updates (Paul Brook)
|
||||
- UDP/TCP/telnet character devices (Jason Wessel)
|
||||
- Windows sparse file support (Frediano Ziglio)
|
||||
- RTL8139 NIC TCP segmentation offloading (Igor Kovalenko)
|
||||
- PCNET NIC support (Antony T Curtis)
|
||||
- Support for variable frequency host CPUs
|
||||
- Workaround for win32 SMP hosts
|
||||
- Support for AMD Flash memories (Jocelyn Mayer)
|
||||
- Audio capture to WAV files support (malc)
|
||||
|
||||
version 0.8.1:
|
||||
|
||||
- USB tablet support (Brad Campbell, Anthony Liguori)
|
||||
- win32 host serial support (Kazu)
|
||||
- PC speaker support (Joachim Henke)
|
||||
- IDE LBA48 support (Jens Axboe)
|
||||
- SSE3 support
|
||||
- Solaris port (Juergen Keil)
|
||||
- Preliminary SH4 target (Samuel Tardieu)
|
||||
- VNC server (Anthony Liguori)
|
||||
- slirp fixes (Ed Swierk et al.)
|
||||
- USB fixes
|
||||
- ARM Versatile Platform Baseboard emulation (Paul Brook)
|
||||
|
||||
version 0.8.0:
|
||||
|
||||
- ARM system emulation: Arm Integrator/CP board with an arm1026ej-s
|
||||
cpu (Paul Brook)
|
||||
- SMP support
|
||||
- Mac OS X cocoa improvements (Mike Kronenberg)
|
||||
- Mac OS X CoreAudio driver (Mike Kronenberg)
|
||||
- DirectSound driver (malc)
|
||||
- ALSA audio driver (malc)
|
||||
- new audio options: '-soundhw' and '-audio-help' (malc)
|
||||
- ES1370 PCI audio device (malc)
|
||||
- Initial USB support
|
||||
- Linux host serial port access
|
||||
- Linux host low level parallel port access
|
||||
- New network emulation code supporting VLANs.
|
||||
- MIPS and MIPSel User Linux emulation
|
||||
- MIPS fixes to boot Linux (Daniel Jacobowitz)
|
||||
- NX bit support
|
||||
- Initial SPARC SMP support (Blue Swirl)
|
||||
- Major overhaul of the virtual FAT driver for read/write support
|
||||
(Johannes Schindelin)
|
||||
|
||||
version 0.7.2:
|
||||
|
||||
- x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
|
||||
- merge self modifying code handling in dirty ram page mecanism.
|
||||
- MIPS fixes (Ralf Baechle)
|
||||
- better user net performances
|
||||
|
||||
version 0.7.1:
|
||||
|
||||
- read-only Virtual FAT support (Johannes Schindelin)
|
||||
- Windows 2000 install disk full hack (original idea from Vladimir
|
||||
N. Oleynik)
|
||||
- VMDK disk image creation (Filip Navara)
|
||||
- SPARC64 progress (Blue Swirl)
|
||||
- initial MIPS support (Jocelyn mayer)
|
||||
- MIPS improvements (Ralf Baechle)
|
||||
- 64 bit fixes in user networking (initial patch by Gwenole Beauchesne)
|
||||
- IOAPIC support (Filip Navara)
|
||||
|
||||
version 0.7.0:
|
||||
|
||||
- better BIOS translation and HDD geometry auto-detection
|
||||
- user mode networking bug fix
|
||||
- undocumented FPU ops support
|
||||
- Cirrus VGA: support for 1280x1024x[8,15,16] modes
|
||||
- 'pidfile' option
|
||||
- .dmg disk image format support (Johannes Schindelin)
|
||||
- keymaps support (initial patch by Johannes Schindelin)
|
||||
- big endian ARM support (Lennert Buytenhek)
|
||||
- added generic 64 bit target support
|
||||
- x86_64 target support
|
||||
- initial APIC support
|
||||
- MMX/SSE/SSE2/PNI support
|
||||
- PC parallel port support (Mark Jonckheere)
|
||||
- initial SPARC64 support (Blue Swirl)
|
||||
- SPARC target boots Linux (Blue Swirl)
|
||||
- armv5te user mode support (Paul Brook)
|
||||
- ARM VFP support (Paul Brook)
|
||||
- ARM "Angel" semihosting syscalls (Paul Brook)
|
||||
- user mode gdb stub support (Paul Brook)
|
||||
- Samba 3 support
|
||||
- initial Cocoa support (Pierre d'Herbemont)
|
||||
- generic FPU emulation code
|
||||
- Virtual PC read-only disk image support (Alex Beregszaszi)
|
||||
|
||||
version 0.6.1:
|
||||
|
||||
- Mac OS X port (Pierre d'Herbemont)
|
||||
- Virtual console support
|
||||
- Better monitor line edition
|
||||
- New block device layer
|
||||
- New 'qcow' growable disk image support with AES encryption and
|
||||
transparent decompression
|
||||
- VMware 3 and 4 read-only disk image support (untested)
|
||||
- Support for up to 4 serial ports
|
||||
- TFTP server support (Magnus Damm)
|
||||
- Port redirection support in user mode networking
|
||||
- Support for not executable data sections
|
||||
- Compressed loop disk image support (Johannes Schindelin)
|
||||
- Level triggered IRQ fix (aka NE2000 PCI performance fix) (Steve
|
||||
Wormley)
|
||||
- Fixed Fedora Core 2 problems (now you can run qemu without any
|
||||
LD_ASSUME_KERNEL tricks on FC2)
|
||||
- DHCP fix for Windows (accept DHCPREQUEST alone)
|
||||
- SPARC system emulation (Blue Swirl)
|
||||
- Automatic Samba configuration for host file access from Windows.
|
||||
- '-loadvm' and '-full-screen' options
|
||||
- ne2000 savevm support (Johannes Schindelin)
|
||||
- Ctrl-Alt is now the default grab key. Ctrl-Alt-[0-9] switches to
|
||||
the virtual consoles.
|
||||
- BIOS floppy fix for NT4 (Mike Nordell, Derek Fawcus, Volker Ruppert)
|
||||
- Floppy fixes for NT4 and NT5 (Mike Nordell)
|
||||
- NT4 IDE fixes (Ben Pfaf, Mike Nordell)
|
||||
- SDL Audio support and SB16 fixes (malc)
|
||||
- ENTER instruction bug fix (initial patch by Stefan Kisdaroczi)
|
||||
- VGA font change fix
|
||||
- VGA read-only CRTC register fix
|
||||
|
||||
version 0.6.0:
|
||||
|
||||
- minimalist FPU exception support (NetBSD FPU probe fix)
|
||||
- cr0.ET fix (Win95 boot)
|
||||
- *BSD port (Markus Niemisto)
|
||||
- I/O access fix (signaled by Mark Jonckheere)
|
||||
- IDE drives serial number fix (Mike Nordell)
|
||||
- int13 CDROM BIOS fix (aka Solaris x86 install CD fix)
|
||||
- int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix)
|
||||
- BSR/BSF "undefined behaviour" fix
|
||||
- vmdk2raw: convert VMware disk images to raw images
|
||||
- PCI support
|
||||
- NE2K PCI support
|
||||
- dummy VGA PCI support
|
||||
- VGA font selection fix (Daniel Serpell)
|
||||
- PIC reset fix (Hidemi KAWAI)
|
||||
- PIC spurious irq support (aka Solaris install bug)
|
||||
- added '-localtime' option
|
||||
- Cirrus CL-GD54xx VGA support (initial patch by Makoto Suzuki (suzu))
|
||||
- APM and system shutdown support
|
||||
- Fixed system reset
|
||||
- Support for other PC BIOSes
|
||||
- Initial PowerMac hardware emulation
|
||||
- PowerMac/PREP OpenFirmware compatible BIOS (Jocelyn Mayer)
|
||||
- initial IDE BMDMA support (needed for Darwin x86)
|
||||
- Set the default memory size for PC emulation to 128 MB
|
||||
|
||||
version 0.5.5:
|
||||
|
||||
- SDL full screen support (initial patch by malc)
|
||||
- VGA support on PowerPC PREP
|
||||
- VBE fixes (Matthew Mastracci)
|
||||
- PIT fixes (aka Win98 hardware probe and "VGA slowness" bug)
|
||||
- IDE master only fixes (aka Win98 CD-ROM probe bug)
|
||||
- ARM load/store half word fix (Ulrich Hecht)
|
||||
- FDC fixes for Win98
|
||||
|
||||
version 0.5.4:
|
||||
|
||||
- qemu-fast fixes
|
||||
- BIOS area protection fix (aka EMM386.EXE fix) (Mike Nordell)
|
||||
- keyboard/mouse fix (Mike Nordell)
|
||||
- IDE fixes (Linux did not recognized slave drivers)
|
||||
- VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell)
|
||||
- QEMU can now boot a PowerPC Linux kernel (Jocelyn Mayer)
|
||||
- User mode network stack
|
||||
- imul imm8 fix + 0x82 opcode support (Hidemi KAWAI)
|
||||
- precise self modifying code (aka BeOS install bug)
|
||||
|
||||
version 0.5.3:
|
||||
|
||||
- added Bochs VESA VBE support
|
||||
- VGA memory map mode 3 access fix (OS/2 install fix)
|
||||
- IDE fixes (Jens Axboe)
|
||||
- CPU interrupt fixes
|
||||
- fixed various TLB invalidation cases (NT install)
|
||||
- fixed cr0.WP semantics (XP install)
|
||||
- direct chaining support for SPARC and PowerPC (faster)
|
||||
- ARM NWFPE support (initial patch by Ulrich Hecht)
|
||||
- added specific x86 to x86 translator (close to native performance
|
||||
in qemu-i386 and qemu-fast)
|
||||
- shm syscalls support (Paul McKerras)
|
||||
- added accurate CR0.MP/ME/TS emulation
|
||||
- fixed DMA memory write access (Win95 boot floppy fix)
|
||||
- graphical x86 linux loader
|
||||
- command line monitor
|
||||
- generic removable device support
|
||||
- support of CD-ROM change
|
||||
- multiple network interface support
|
||||
- initial x86-64 host support (Gwenole Beauchesne)
|
||||
- lret to outer privilege fix (OS/2 install fix)
|
||||
- task switch fixes (SkyOS boot)
|
||||
- VM save/restore commands
|
||||
- new timer API
|
||||
- more precise RTC emulation (periodic timers + time updates)
|
||||
- Win32 port (initial patch by Kazu)
|
||||
|
||||
version 0.5.2:
|
||||
|
||||
- improved soft MMU speed (assembly functions and specializing)
|
||||
- improved multitasking speed by avoiding flushing TBs when
|
||||
switching tasks
|
||||
- improved qemu-fast speed
|
||||
- improved self modifying code handling (big performance gain in
|
||||
softmmu mode).
|
||||
- fixed IO checking
|
||||
- fixed CD-ROM detection (win98 install CD)
|
||||
- fixed addseg real mode bug (GRUB boot fix)
|
||||
- added ROM memory support (win98 boot)
|
||||
- fixed 'call Ev' in case of paging exception
|
||||
- updated the script 'qemu-binfmt-conf.sh' to use QEMU automagically
|
||||
when launching executables for the supported target CPUs.
|
||||
- PowerPC system emulation update (Jocelyn Mayer)
|
||||
- PC floppy emulation and DMA fixes (Jocelyn Mayer)
|
||||
- polled mode for PIC (Jocelyn Mayer)
|
||||
- fixed PTE dirty bit handling
|
||||
- fixed xadd same reg bug
|
||||
- fixed cmpxchg exception safeness
|
||||
- access to virtual memory in gdb stub
|
||||
- task gate and NT flag fixes
|
||||
- eflags optimisation fix for string operations
|
||||
|
||||
version 0.5.1:
|
||||
|
||||
- float access fixes when using soft mmu
|
||||
- PC emulation support on PowerPC
|
||||
- A20 support
|
||||
- IDE CD-ROM emulation
|
||||
- ARM fixes (Ulrich Hecht)
|
||||
- SB16 emulation (malc)
|
||||
- IRET and INT fixes in VM86 mode with IOPL=3
|
||||
- Port I/Os use TSS io map
|
||||
- Full task switching/task gate support
|
||||
- added verr, verw, arpl, fcmovxx
|
||||
- PowerPC target support (Jocelyn Mayer)
|
||||
- Major SPARC target fixes (dynamically linked programs begin to work)
|
||||
|
||||
version 0.5.0:
|
||||
|
||||
- full hardware level VGA emulation
|
||||
- graphical display with SDL
|
||||
- added PS/2 mouse and keyboard emulation
|
||||
- popw (%esp) fix
|
||||
- mov to/from segment data width fix
|
||||
- added real mode support
|
||||
- added Bochs BIOS and LGPL'ed VGA BIOS loader in qemu
|
||||
- m68k host port (Richard Zidlicky)
|
||||
- partial soft MMU support for memory mapped I/Os
|
||||
- multi-target build
|
||||
- fixed: no error code in hardware interrupts
|
||||
- fixed: pop ss, mov ss, x and sti disable hardware irqs for the next insn
|
||||
- correct single stepping through string operations
|
||||
- preliminary SPARC target support (Thomas M. Ogrisegg)
|
||||
- tun-fd option (Rusty Russell)
|
||||
- automatic IDE geometry detection
|
||||
- renamed 'vl' to qemu[-fast] and user qemu to qemu-{cpu}.
|
||||
- added man page
|
||||
- added full soft mmu mode to launch unpatched OSes.
|
||||
|
||||
version 0.4.3:
|
||||
|
||||
- x86 exception fix in case of nop instruction.
|
||||
- gcc 3.2.2 bug workaround (RedHat 9 fix)
|
||||
- sparc and Alpha host fixes
|
||||
- many ARM target fixes: 'ls' and 'bash' can be launched.
|
||||
|
||||
version 0.4.2:
|
||||
|
||||
- many exception handling fixes (can compile a Linux kernel inside vl)
|
||||
- IDE emulation support
|
||||
- initial GDB stub support
|
||||
- deferred update support for disk images (Rusty Russell)
|
||||
- accept User Mode Linux Copy On Write disk images
|
||||
- SMP kernels can at least be booted
|
||||
|
||||
version 0.4.1:
|
||||
|
||||
- more accurate timer support in vl.
|
||||
- more reliable NE2000 probe in vl.
|
||||
- added 2.5.66 kernel in vl-test.
|
||||
- added VLTMPDIR environment variable in vl.
|
||||
|
||||
version 0.4:
|
||||
|
||||
- initial support for ring 0 x86 processor emulation
|
||||
- fixed signal handling for correct dosemu DPMI emulation
|
||||
- fast x86 MMU emulation with mmap()
|
||||
- fixed popl (%esp) case
|
||||
- Linux kernel can be executed by QEMU with the 'vl' command.
|
||||
|
||||
version 0.3:
|
||||
|
||||
- initial support for ARM emulation
|
||||
- added fnsave, frstor, fnstenv, fldenv FPU instructions
|
||||
- added FPU register save in signal emulation
|
||||
- initial ARM port
|
||||
- Sparc and Alpha ports work on the regression test
|
||||
- generic ioctl number conversion
|
||||
- fixed ioctl type conversion
|
||||
|
||||
version 0.2:
|
||||
|
||||
- PowerPC disassembly and ELF symbols output (Rusty Russell)
|
||||
- flock support (Rusty Russell)
|
||||
- ugetrlimit support (Rusty Russell)
|
||||
- fstat64 fix (Rusty Russell)
|
||||
- initial Alpha port (Falk Hueffner)
|
||||
- initial IA64 port (Matt Wilson)
|
||||
- initial Sparc and Sparc64 port (David S. Miller)
|
||||
- added HLT instruction
|
||||
- LRET instruction fix.
|
||||
- added GPF generation for I/Os.
|
||||
- added INT3 and TF flag support.
|
||||
- SHL instruction C flag fix.
|
||||
- mmap emulation for host page size > 4KB
|
||||
- self-modifying code support
|
||||
- better VM86 support (dosemu works on non trivial programs)
|
||||
- precise exception support (EIP is computed correctly in most cases)
|
||||
- more precise LDT/GDT/IDT emulation
|
||||
- faster segment load in vm86 mode
|
||||
- direct chaining of basic blocks (faster emulation)
|
||||
|
||||
version 0.1.6:
|
||||
|
||||
- automatic library search system. QEMU can now work with unpatched
|
||||
ELF dynamic loader and libc (Rusty Russell).
|
||||
- ISO C warning fixes (Alistair Strachan)
|
||||
- first self-virtualizable version (works only as long as the
|
||||
translation cache is not flushed)
|
||||
- RH9 fixes
|
||||
|
||||
version 0.1.5:
|
||||
|
||||
- ppc64 support + personality() patch (Rusty Russell)
|
||||
- first Alpha CPU patches (Falk Hueffner)
|
||||
- removed bfd.h dependency
|
||||
- fixed shrd, shld, idivl and divl on PowerPC.
|
||||
- fixed buggy glibc PowerPC rint() function (test-i386 passes now on PowerPC).
|
||||
|
||||
version 0.1.4:
|
||||
|
||||
- more accurate VM86 emulation (can launch small DOS 16 bit
|
||||
executables in wine).
|
||||
- fixed push/pop fs/gs
|
||||
- added iret instruction.
|
||||
- added times() syscall and SIOCATMARK ioctl.
|
||||
|
||||
version 0.1.3:
|
||||
|
||||
- S390 support (Ulrich Weigand)
|
||||
- glibc 2.3.x compile fix (Ulrich Weigand)
|
||||
- socketcall endian fix (Ulrich Weigand)
|
||||
- struct sockaddr endian fix (Ulrich Weigand)
|
||||
- sendmsg/recvmsg endian fix (Ulrich Weigand)
|
||||
- execve endian fix (Ulrich Weigand)
|
||||
- fdset endian fix (Ulrich Weigand)
|
||||
- partial setsockopt syscall support (Ulrich Weigand)
|
||||
- more accurate pushf/popf emulation
|
||||
- first partial vm86() syscall support (can be used with runcom example).
|
||||
- added bound, cmpxchg8b, cpuid instructions
|
||||
- added 16 bit addressing support/override for string operations
|
||||
- poll() fix
|
||||
|
||||
version 0.1.2:
|
||||
|
||||
- compile fixes
|
||||
- xlat instruction
|
||||
- xchg instruction memory lock
|
||||
- added simple vm86 example (not working with QEMU yet). The 54 byte
|
||||
DOS executable 'pi_10.com' program was released by Bertram
|
||||
Felgenhauer (more information at http://www.boo.net/~jasonp/pipage.html).
|
||||
|
||||
version 0.1.1:
|
||||
|
||||
- glibc 2.2 compilation fixes
|
||||
- added -s and -L options
|
||||
- binary distribution of x86 glibc and wine
|
||||
- big endian fixes in ELF loader and getdents.
|
||||
|
||||
version 0.1:
|
||||
|
||||
- initial public release.
|
||||
@@ -1,4 +0,0 @@
|
||||
source Kconfig.host
|
||||
source backends/Kconfig
|
||||
source accel/Kconfig
|
||||
source hw/Kconfig
|
||||
+7
-9
@@ -1,6 +1,9 @@
|
||||
# These are "proxy" symbols used to pass config-host.mak values
|
||||
# down to Kconfig. See also kconfig_external_symbols in
|
||||
# meson.build: these two need to be kept in sync.
|
||||
# down to Kconfig. See also MINIKCONF_ARGS in the Makefile:
|
||||
# these two need to be kept in sync.
|
||||
|
||||
config KVM
|
||||
bool
|
||||
|
||||
config LINUX
|
||||
bool
|
||||
@@ -22,15 +25,10 @@ config TPM
|
||||
|
||||
config VHOST_USER
|
||||
bool
|
||||
select VHOST
|
||||
|
||||
config VHOST_VDPA
|
||||
config XEN
|
||||
bool
|
||||
select VHOST
|
||||
|
||||
config VHOST_KERNEL
|
||||
bool
|
||||
select VHOST
|
||||
select FSDEV_9P if VIRTFS
|
||||
|
||||
config VIRTFS
|
||||
bool
|
||||
|
||||
+150
-652
File diff suppressed because it is too large.
Load diff
+215
@@ -0,0 +1,215 @@
|
||||
#######################################################################
|
||||
# Common libraries for tools and emulators
|
||||
stub-obj-y = stubs/ util/ crypto/
|
||||
util-obj-y = util/ qobject/ qapi/
|
||||
|
||||
chardev-obj-y = chardev/
|
||||
|
||||
#######################################################################
|
||||
# authz-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
authz-obj-y = authz/
|
||||
|
||||
#######################################################################
|
||||
# block-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
block-obj-y = nbd/
|
||||
block-obj-y += block.o blockjob.o job.o
|
||||
block-obj-y += block/ scsi/
|
||||
block-obj-y += qemu-io-cmds.o
|
||||
block-obj-$(CONFIG_REPLICATION) += replication.o
|
||||
|
||||
block-obj-m = block/
|
||||
|
||||
#######################################################################
|
||||
# crypto-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
crypto-obj-y = crypto/
|
||||
crypto-user-obj-y = crypto/
|
||||
|
||||
#######################################################################
|
||||
# qom-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
qom-obj-y = qom/
|
||||
|
||||
#######################################################################
|
||||
# io-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
io-obj-y = io/
|
||||
|
||||
######################################################################
|
||||
# Target independent part of system emulation. The long term path is to
|
||||
# suppress *all* target specific code in case of system emulation, i.e. a
|
||||
# single QEMU executable should support all CPUs and machines.
|
||||
|
||||
ifeq ($(CONFIG_SOFTMMU),y)
|
||||
common-obj-y = blockdev.o blockdev-nbd.o block/
|
||||
common-obj-y += bootdevice.o iothread.o
|
||||
common-obj-y += dump/
|
||||
common-obj-y += job-qmp.o
|
||||
common-obj-y += monitor/
|
||||
common-obj-y += net/
|
||||
common-obj-y += qdev-monitor.o device-hotplug.o
|
||||
common-obj-$(CONFIG_WIN32) += os-win32.o
|
||||
common-obj-$(CONFIG_POSIX) += os-posix.o
|
||||
|
||||
common-obj-$(CONFIG_LINUX) += fsdev/
|
||||
|
||||
common-obj-y += migration/
|
||||
|
||||
common-obj-y += audio/
|
||||
common-obj-m += audio/
|
||||
common-obj-y += hw/
|
||||
|
||||
common-obj-y += replay/
|
||||
|
||||
common-obj-y += ui/
|
||||
common-obj-m += ui/
|
||||
common-obj-y += bt-host.o bt-vhci.o
|
||||
bt-host.o-cflags := $(BLUEZ_CFLAGS)
|
||||
|
||||
common-obj-y += dma-helpers.o
|
||||
common-obj-y += vl.o
|
||||
vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
|
||||
common-obj-$(CONFIG_TPM) += tpm.o
|
||||
|
||||
common-obj-y += backends/
|
||||
common-obj-y += chardev/
|
||||
|
||||
common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
|
||||
qemu-seccomp.o-cflags := $(SECCOMP_CFLAGS)
|
||||
qemu-seccomp.o-libs := $(SECCOMP_LIBS)
|
||||
|
||||
common-obj-$(CONFIG_FDT) += device_tree.o
|
||||
|
||||
######################################################################
|
||||
# qapi
|
||||
|
||||
common-obj-y += qapi/
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
# Target-independent parts used in system and user emulation
|
||||
common-obj-y += cpus-common.o
|
||||
common-obj-y += hw/
|
||||
common-obj-y += qom/
|
||||
common-obj-y += disas/
|
||||
|
||||
######################################################################
|
||||
# Resource file for Windows executables
|
||||
version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o
|
||||
|
||||
######################################################################
|
||||
# tracing
|
||||
util-obj-y += trace/
|
||||
|
||||
######################################################################
|
||||
# guest agent
|
||||
|
||||
# FIXME: a few definitions from qapi/qapi-types.o and
|
||||
# qapi/qapi-visit.o are needed by libqemuutil.a. These should be
|
||||
# extracted into a QAPI schema module, or perhaps a separate schema.
|
||||
qga-obj-y = qga/
|
||||
qga-vss-dll-obj-y = qga/
|
||||
|
||||
######################################################################
|
||||
# contrib
|
||||
elf2dmp-obj-y = contrib/elf2dmp/
|
||||
ivshmem-client-obj-$(CONFIG_IVSHMEM) = contrib/ivshmem-client/
|
||||
ivshmem-server-obj-$(CONFIG_IVSHMEM) = contrib/ivshmem-server/
|
||||
libvhost-user-obj-y = contrib/libvhost-user/
|
||||
vhost-user-scsi.o-cflags := $(LIBISCSI_CFLAGS)
|
||||
vhost-user-scsi.o-libs := $(LIBISCSI_LIBS)
|
||||
vhost-user-scsi-obj-y = contrib/vhost-user-scsi/
|
||||
vhost-user-blk-obj-y = contrib/vhost-user-blk/
|
||||
rdmacm-mux-obj-y = contrib/rdmacm-mux/
|
||||
vhost-user-input-obj-y = contrib/vhost-user-input/
|
||||
vhost-user-gpu-obj-y = contrib/vhost-user-gpu/
|
||||
|
||||
######################################################################
|
||||
trace-events-subdirs =
|
||||
trace-events-subdirs += accel/kvm
|
||||
trace-events-subdirs += accel/tcg
|
||||
trace-events-subdirs += crypto
|
||||
trace-events-subdirs += monitor
|
||||
ifeq ($(CONFIG_USER_ONLY),y)
|
||||
trace-events-subdirs += linux-user
|
||||
endif
|
||||
ifeq ($(CONFIG_BLOCK),y)
|
||||
trace-events-subdirs += authz
|
||||
trace-events-subdirs += block
|
||||
trace-events-subdirs += io
|
||||
trace-events-subdirs += nbd
|
||||
trace-events-subdirs += scsi
|
||||
endif
|
||||
ifeq ($(CONFIG_SOFTMMU),y)
|
||||
trace-events-subdirs += chardev
|
||||
trace-events-subdirs += audio
|
||||
trace-events-subdirs += hw/9pfs
|
||||
trace-events-subdirs += hw/acpi
|
||||
trace-events-subdirs += hw/alpha
|
||||
trace-events-subdirs += hw/arm
|
||||
trace-events-subdirs += hw/audio
|
||||
trace-events-subdirs += hw/block
|
||||
trace-events-subdirs += hw/block/dataplane
|
||||
trace-events-subdirs += hw/char
|
||||
trace-events-subdirs += hw/dma
|
||||
trace-events-subdirs += hw/hppa
|
||||
trace-events-subdirs += hw/i2c
|
||||
trace-events-subdirs += hw/i386
|
||||
trace-events-subdirs += hw/i386/xen
|
||||
trace-events-subdirs += hw/ide
|
||||
trace-events-subdirs += hw/input
|
||||
trace-events-subdirs += hw/intc
|
||||
trace-events-subdirs += hw/isa
|
||||
trace-events-subdirs += hw/mem
|
||||
trace-events-subdirs += hw/mips
|
||||
trace-events-subdirs += hw/misc
|
||||
trace-events-subdirs += hw/misc/macio
|
||||
trace-events-subdirs += hw/net
|
||||
trace-events-subdirs += hw/nvram
|
||||
trace-events-subdirs += hw/pci
|
||||
trace-events-subdirs += hw/pci-host
|
||||
trace-events-subdirs += hw/ppc
|
||||
trace-events-subdirs += hw/rdma
|
||||
trace-events-subdirs += hw/rdma/vmw
|
||||
trace-events-subdirs += hw/rtc
|
||||
trace-events-subdirs += hw/s390x
|
||||
trace-events-subdirs += hw/scsi
|
||||
trace-events-subdirs += hw/sd
|
||||
trace-events-subdirs += hw/sparc
|
||||
trace-events-subdirs += hw/sparc64
|
||||
trace-events-subdirs += hw/timer
|
||||
trace-events-subdirs += hw/tpm
|
||||
trace-events-subdirs += hw/usb
|
||||
trace-events-subdirs += hw/vfio
|
||||
trace-events-subdirs += hw/virtio
|
||||
trace-events-subdirs += hw/watchdog
|
||||
trace-events-subdirs += hw/xen
|
||||
trace-events-subdirs += hw/gpio
|
||||
trace-events-subdirs += hw/riscv
|
||||
trace-events-subdirs += migration
|
||||
trace-events-subdirs += net
|
||||
trace-events-subdirs += ui
|
||||
endif
|
||||
trace-events-subdirs += hw/display
|
||||
trace-events-subdirs += qapi
|
||||
trace-events-subdirs += qom
|
||||
trace-events-subdirs += target/arm
|
||||
trace-events-subdirs += target/hppa
|
||||
trace-events-subdirs += target/i386
|
||||
trace-events-subdirs += target/mips
|
||||
trace-events-subdirs += target/ppc
|
||||
trace-events-subdirs += target/riscv
|
||||
trace-events-subdirs += target/s390x
|
||||
trace-events-subdirs += target/sparc
|
||||
trace-events-subdirs += util
|
||||
trace-events-subdirs += hw/core
|
||||
|
||||
trace-events-files = $(SRC_PATH)/trace-events $(trace-events-subdirs:%=$(SRC_PATH)/%/trace-events)
|
||||
|
||||
trace-obj-y = trace-root.o
|
||||
trace-obj-y += $(trace-events-subdirs:%=%/trace.o)
|
||||
trace-obj-$(CONFIG_TRACE_UST) += trace-ust-all.o
|
||||
trace-obj-$(CONFIG_TRACE_DTRACE) += trace-dtrace-root.o
|
||||
trace-obj-$(CONFIG_TRACE_DTRACE) += $(trace-events-subdirs:%=%/trace-dtrace.o)
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
# -*- Mode: makefile -*-
|
||||
|
||||
BUILD_DIR?=$(CURDIR)/..
|
||||
|
||||
include ../config-host.mak
|
||||
include config-target.mak
|
||||
include $(SRC_PATH)/rules.mak
|
||||
|
||||
ifdef CONFIG_SOFTMMU
|
||||
include config-devices.mak
|
||||
endif
|
||||
|
||||
$(call set-vpath, $(SRC_PATH):$(BUILD_DIR))
|
||||
ifdef CONFIG_LINUX
|
||||
QEMU_CFLAGS += -I../linux-headers
|
||||
endif
|
||||
QEMU_CFLAGS += -iquote .. -iquote $(SRC_PATH)/target/$(TARGET_BASE_ARCH) -DNEED_CPU_H
|
||||
|
||||
QEMU_CFLAGS+=-iquote $(SRC_PATH)/include
|
||||
|
||||
ifdef CONFIG_USER_ONLY
|
||||
# user emulator name
|
||||
QEMU_PROG=qemu-$(TARGET_NAME)
|
||||
QEMU_PROG_BUILD = $(QEMU_PROG)
|
||||
else
|
||||
# system emulator name
|
||||
QEMU_PROG=qemu-system-$(TARGET_NAME)$(EXESUF)
|
||||
ifneq (,$(findstring -mwindows,$(SDL_LIBS)))
|
||||
# Terminate program name with a 'w' because the linker builds a windows executable.
|
||||
QEMU_PROGW=qemu-system-$(TARGET_NAME)w$(EXESUF)
|
||||
$(QEMU_PROG): $(QEMU_PROGW)
|
||||
$(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG),"GEN","$(TARGET_DIR)$(QEMU_PROG)")
|
||||
QEMU_PROG_BUILD = $(QEMU_PROGW)
|
||||
else
|
||||
QEMU_PROG_BUILD = $(QEMU_PROG)
|
||||
endif
|
||||
endif
|
||||
|
||||
PROGS=$(QEMU_PROG) $(QEMU_PROGW)
|
||||
STPFILES=
|
||||
|
||||
config-target.h: config-target.h-timestamp
|
||||
config-target.h-timestamp: config-target.mak
|
||||
|
||||
config-devices.h: config-devices.h-timestamp
|
||||
config-devices.h-timestamp: config-devices.mak
|
||||
|
||||
ifdef CONFIG_TRACE_SYSTEMTAP
|
||||
stap: $(QEMU_PROG).stp-installed $(QEMU_PROG).stp $(QEMU_PROG)-simpletrace.stp $(QEMU_PROG)-log.stp
|
||||
|
||||
ifdef CONFIG_USER_ONLY
|
||||
TARGET_TYPE=user
|
||||
else
|
||||
TARGET_TYPE=system
|
||||
endif
|
||||
|
||||
tracetool-y = $(SRC_PATH)/scripts/tracetool.py
|
||||
tracetool-y += $(shell find $(SRC_PATH)/scripts/tracetool -name "*.py")
|
||||
|
||||
$(QEMU_PROG).stp-installed: $(BUILD_DIR)/trace-events-all $(tracetool-y)
|
||||
$(call quiet-command,$(TRACETOOL) \
|
||||
--group=all \
|
||||
--format=stap \
|
||||
--backends=$(TRACE_BACKENDS) \
|
||||
--binary=$(bindir)/$(QEMU_PROG) \
|
||||
--target-name=$(TARGET_NAME) \
|
||||
--target-type=$(TARGET_TYPE) \
|
||||
$< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp-installed")
|
||||
|
||||
$(QEMU_PROG).stp: $(BUILD_DIR)/trace-events-all $(tracetool-y)
|
||||
$(call quiet-command,$(TRACETOOL) \
|
||||
--group=all \
|
||||
--format=stap \
|
||||
--backends=$(TRACE_BACKENDS) \
|
||||
--binary=$(realpath .)/$(QEMU_PROG) \
|
||||
--target-name=$(TARGET_NAME) \
|
||||
--target-type=$(TARGET_TYPE) \
|
||||
$< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG).stp")
|
||||
|
||||
$(QEMU_PROG)-simpletrace.stp: $(BUILD_DIR)/trace-events-all $(tracetool-y)
|
||||
$(call quiet-command,$(TRACETOOL) \
|
||||
--group=all \
|
||||
--format=simpletrace-stap \
|
||||
--backends=$(TRACE_BACKENDS) \
|
||||
--probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \
|
||||
$< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp")
|
||||
|
||||
$(QEMU_PROG)-log.stp: $(BUILD_DIR)/trace-events-all $(tracetool-y)
|
||||
$(call quiet-command,$(TRACETOOL) \
|
||||
--group=all \
|
||||
--format=log-stap \
|
||||
--backends=$(TRACE_BACKENDS) \
|
||||
--probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \
|
||||
$< > $@,"GEN","$(TARGET_DIR)$(QEMU_PROG)-log.stp")
|
||||
|
||||
else
|
||||
stap:
|
||||
endif
|
||||
.PHONY: stap
|
||||
|
||||
all: $(PROGS) stap
|
||||
|
||||
# Dummy command so that make thinks it has done something
|
||||
@true
|
||||
|
||||
obj-y += trace/
|
||||
|
||||
#########################################################
|
||||
# cpu emulator library
|
||||
obj-y += exec.o exec-vary.o
|
||||
obj-y += accel/
|
||||
obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/tcg-op-vec.o tcg/tcg-op-gvec.o
|
||||
obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/optimize.o
|
||||
obj-$(CONFIG_TCG_INTERPRETER) += tcg/tci.o
|
||||
obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
|
||||
obj-$(CONFIG_TCG) += fpu/softfloat.o
|
||||
obj-y += target/$(TARGET_BASE_ARCH)/
|
||||
obj-y += disas.o
|
||||
obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
|
||||
LIBS := $(libs_cpu) $(LIBS)
|
||||
|
||||
obj-$(CONFIG_PLUGIN) += plugins/
|
||||
|
||||
#########################################################
|
||||
# Linux user emulator target
|
||||
|
||||
ifdef CONFIG_LINUX_USER
|
||||
|
||||
QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) \
|
||||
-I$(SRC_PATH)/linux-user/host/$(ARCH) \
|
||||
-I$(SRC_PATH)/linux-user
|
||||
|
||||
obj-y += linux-user/
|
||||
obj-y += gdbstub.o thunk.o
|
||||
|
||||
endif #CONFIG_LINUX_USER
|
||||
|
||||
#########################################################
|
||||
# BSD user emulator target
|
||||
|
||||
ifdef CONFIG_BSD_USER
|
||||
|
||||
QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR) \
|
||||
-I$(SRC_PATH)/bsd-user/$(HOST_VARIANT_DIR)
|
||||
|
||||
obj-y += bsd-user/
|
||||
obj-y += gdbstub.o
|
||||
|
||||
endif #CONFIG_BSD_USER
|
||||
|
||||
#########################################################
|
||||
# System emulator target
|
||||
ifdef CONFIG_SOFTMMU
|
||||
obj-y += arch_init.o cpus.o gdbstub.o balloon.o ioport.o
|
||||
obj-y += qtest.o
|
||||
obj-y += dump/
|
||||
obj-y += hw/
|
||||
obj-y += monitor/
|
||||
obj-y += qapi/
|
||||
obj-y += memory.o
|
||||
obj-y += memory_mapping.o
|
||||
obj-y += migration/ram.o
|
||||
LIBS := $(libs_softmmu) $(LIBS)
|
||||
|
||||
# Hardware support
|
||||
ifeq ($(TARGET_NAME), sparc64)
|
||||
obj-y += hw/sparc64/
|
||||
else
|
||||
obj-y += hw/$(TARGET_BASE_ARCH)/
|
||||
endif
|
||||
|
||||
generated-files-y += hmp-commands.h hmp-commands-info.h
|
||||
generated-files-y += config-devices.h
|
||||
|
||||
endif # CONFIG_SOFTMMU
|
||||
|
||||
dummy := $(call unnest-vars,,obj-y)
|
||||
all-obj-y := $(obj-y)
|
||||
|
||||
include $(SRC_PATH)/Makefile.objs
|
||||
dummy := $(call unnest-vars,.., \
|
||||
authz-obj-y \
|
||||
block-obj-y \
|
||||
block-obj-m \
|
||||
chardev-obj-y \
|
||||
crypto-obj-y \
|
||||
crypto-user-obj-y \
|
||||
qom-obj-y \
|
||||
io-obj-y \
|
||||
common-obj-y \
|
||||
common-obj-m)
|
||||
all-obj-y += $(common-obj-y)
|
||||
all-obj-y += $(qom-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(authz-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y)
|
||||
all-obj-$(CONFIG_USER_ONLY) += $(crypto-user-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
|
||||
|
||||
ifdef CONFIG_SOFTMMU
|
||||
$(QEMU_PROG_BUILD): config-devices.mak
|
||||
endif
|
||||
|
||||
COMMON_LDADDS = ../libqemuutil.a
|
||||
|
||||
# build either PROG or PROGW
|
||||
$(QEMU_PROG_BUILD): $(all-obj-y) $(COMMON_LDADDS)
|
||||
$(call LINK, $(filter-out %.mak, $^))
|
||||
ifdef CONFIG_DARWIN
|
||||
$(call quiet-command,Rez -append $(SRC_PATH)/pc-bios/qemu.rsrc -o $@,"REZ","$(TARGET_DIR)$@")
|
||||
$(call quiet-command,SetFile -a C $@,"SETFILE","$(TARGET_DIR)$@")
|
||||
endif
|
||||
|
||||
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
|
||||
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES),"GEN","$(TARGET_DIR)$@")
|
||||
|
||||
hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@")
|
||||
|
||||
hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$(TARGET_DIR)$@")
|
||||
|
||||
clean: clean-target
|
||||
rm -f *.a *~ $(PROGS)
|
||||
rm -f $(shell find . -name '*.[od]')
|
||||
rm -f hmp-commands.h gdbstub-xml.c
|
||||
rm -f trace/generated-helpers.c trace/generated-helpers.c-timestamp
|
||||
ifdef CONFIG_TRACE_SYSTEMTAP
|
||||
rm -f *.stp
|
||||
endif
|
||||
|
||||
install: all
|
||||
ifneq ($(PROGS),)
|
||||
$(call install-prog,$(PROGS),$(DESTDIR)$(bindir))
|
||||
endif
|
||||
ifdef CONFIG_TRACE_SYSTEMTAP
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset"
|
||||
$(INSTALL_DATA) $(QEMU_PROG).stp-installed "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG).stp"
|
||||
$(INSTALL_DATA) $(QEMU_PROG)-simpletrace.stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG)-simpletrace.stp"
|
||||
$(INSTALL_DATA) $(QEMU_PROG)-log.stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG)-log.stp"
|
||||
endif
|
||||
|
||||
generated-files-y += config-target.h
|
||||
Makefile: $(generated-files-y)
|
||||
|
||||
# Reports/Analysis
|
||||
#
|
||||
# The target specific coverage report only cares about target specific
|
||||
# blobs and not the shared code.
|
||||
#
|
||||
|
||||
%/coverage-report.html:
|
||||
@mkdir -p $*
|
||||
$(call quiet-command,\
|
||||
gcovr -r $(SRC_PATH) --object-directory $(CURDIR) \
|
||||
-p --html --html-details -o $@, \
|
||||
"GEN", "coverage-report.html")
|
||||
|
||||
.PHONY: coverage-report
|
||||
coverage-report: $(CURDIR)/reports/coverage/coverage-report.html
|
||||
@@ -134,14 +134,6 @@ For additional information on bug reporting consult:
|
||||
* `<https://qemu.org/Contribute/ReportABug>`_
|
||||
|
||||
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
For version history and release notes, please visit
|
||||
`<https://wiki.qemu.org/ChangeLog/>`_ or look at the git history for
|
||||
more detailed information.
|
||||
|
||||
|
||||
Contact
|
||||
=======
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
config TCG
|
||||
bool
|
||||
|
||||
config KVM
|
||||
bool
|
||||
|
||||
config XEN
|
||||
bool
|
||||
select FSDEV_9P if VIRTFS
|
||||
@@ -0,0 +1,5 @@
|
||||
obj-$(CONFIG_SOFTMMU) += accel.o
|
||||
obj-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_POSIX)) += qtest.o
|
||||
obj-$(CONFIG_KVM) += kvm/
|
||||
obj-$(CONFIG_TCG) += tcg/
|
||||
obj-y += stubs/
|
||||
+67
-5
@@ -28,7 +28,13 @@
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/xen/xen.h"
|
||||
#include "qom/object.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
static const TypeInfo accel_type = {
|
||||
.name = TYPE_ACCEL,
|
||||
@@ -38,7 +44,7 @@ static const TypeInfo accel_type = {
|
||||
};
|
||||
|
||||
/* Lookup AccelClass from opt_name. Returns NULL if not found */
|
||||
AccelClass *accel_find(const char *opt_name)
|
||||
static AccelClass *accel_find(const char *opt_name)
|
||||
{
|
||||
char *class_name = g_strdup_printf(ACCEL_CLASS_NAME("%s"), opt_name);
|
||||
AccelClass *ac = ACCEL_CLASS(object_class_by_name(class_name));
|
||||
@@ -46,9 +52,11 @@ AccelClass *accel_find(const char *opt_name)
|
||||
return ac;
|
||||
}
|
||||
|
||||
int accel_init_machine(AccelState *accel, MachineState *ms)
|
||||
static int accel_init_machine(AccelClass *acc, MachineState *ms)
|
||||
{
|
||||
AccelClass *acc = ACCEL_GET_CLASS(accel);
|
||||
ObjectClass *oc = OBJECT_CLASS(acc);
|
||||
const char *cname = object_class_get_name(oc);
|
||||
AccelState *accel = ACCEL(object_new(cname));
|
||||
int ret;
|
||||
ms->accelerator = accel;
|
||||
*(acc->allowed) = true;
|
||||
@@ -63,9 +71,63 @@ int accel_init_machine(AccelState *accel, MachineState *ms)
|
||||
return ret;
|
||||
}
|
||||
|
||||
AccelState *current_accel(void)
|
||||
void configure_accelerator(MachineState *ms, const char *progname)
|
||||
{
|
||||
return current_machine->accelerator;
|
||||
const char *accel;
|
||||
char **accel_list, **tmp;
|
||||
int ret;
|
||||
bool accel_initialised = false;
|
||||
bool init_failed = false;
|
||||
AccelClass *acc = NULL;
|
||||
|
||||
accel = qemu_opt_get(qemu_get_machine_opts(), "accel");
|
||||
if (accel == NULL) {
|
||||
/* Select the default accelerator */
|
||||
int pnlen = strlen(progname);
|
||||
if (pnlen >= 3 && g_str_equal(&progname[pnlen - 3], "kvm")) {
|
||||
/* If the program name ends with "kvm", we prefer KVM */
|
||||
accel = "kvm:tcg";
|
||||
} else {
|
||||
#if defined(CONFIG_TCG)
|
||||
accel = "tcg";
|
||||
#elif defined(CONFIG_KVM)
|
||||
accel = "kvm";
|
||||
#else
|
||||
error_report("No accelerator selected and"
|
||||
" no default accelerator available");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
accel_list = g_strsplit(accel, ":", 0);
|
||||
|
||||
for (tmp = accel_list; !accel_initialised && tmp && *tmp; tmp++) {
|
||||
acc = accel_find(*tmp);
|
||||
if (!acc) {
|
||||
continue;
|
||||
}
|
||||
ret = accel_init_machine(acc, ms);
|
||||
if (ret < 0) {
|
||||
init_failed = true;
|
||||
error_report("failed to initialize %s: %s",
|
||||
acc->name, strerror(-ret));
|
||||
} else {
|
||||
accel_initialised = true;
|
||||
}
|
||||
}
|
||||
g_strfreev(accel_list);
|
||||
|
||||
if (!accel_initialised) {
|
||||
if (!init_failed) {
|
||||
error_report("-machine accel=%s: No accelerator found", accel);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (init_failed) {
|
||||
error_report("Back to %s accelerator", acc->name);
|
||||
}
|
||||
}
|
||||
|
||||
void accel_setup_post(MachineState *ms)
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Dummy cpu thread code
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/rcu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
static void *dummy_cpu_thread_fn(void *arg)
|
||||
{
|
||||
CPUState *cpu = arg;
|
||||
sigset_t waitset;
|
||||
int r;
|
||||
|
||||
rcu_register_thread();
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
qemu_thread_get_self(cpu->thread);
|
||||
cpu->thread_id = qemu_get_thread_id();
|
||||
cpu->can_do_io = 1;
|
||||
current_cpu = cpu;
|
||||
|
||||
sigemptyset(&waitset);
|
||||
sigaddset(&waitset, SIG_IPI);
|
||||
|
||||
/* signal CPU creation */
|
||||
cpu_thread_signal_created(cpu);
|
||||
qemu_guest_random_seed_thread_part2(cpu->random_seed);
|
||||
|
||||
do {
|
||||
qemu_mutex_unlock_iothread();
|
||||
do {
|
||||
int sig;
|
||||
r = sigwait(&waitset, &sig);
|
||||
} while (r == -1 && (errno == EAGAIN || errno == EINTR));
|
||||
if (r == -1) {
|
||||
perror("sigwait");
|
||||
exit(1);
|
||||
}
|
||||
qemu_mutex_lock_iothread();
|
||||
qemu_wait_io_event(cpu);
|
||||
} while (!cpu->unplug);
|
||||
|
||||
qemu_mutex_unlock_iothread();
|
||||
rcu_unregister_thread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dummy_start_vcpu_thread(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY",
|
||||
cpu->cpu_index);
|
||||
qemu_thread_create(cpu->thread, thread_name, dummy_cpu_thread_fn, cpu,
|
||||
QEMU_THREAD_JOINABLE);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
obj-y += kvm-all.o
|
||||
obj-$(call lnot,$(CONFIG_SEV)) += sev-stub.o
|
||||
+43
-305
@@ -40,13 +40,7 @@
|
||||
#include "trace.h"
|
||||
#include "hw/irq.h"
|
||||
#include "sysemu/sev.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qapi-types-common.h"
|
||||
#include "qapi/qapi-visit-common.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "kvm-cpus.h"
|
||||
#include "sysemu/balloon.h"
|
||||
|
||||
#include "hw/boards.h"
|
||||
|
||||
@@ -98,12 +92,8 @@ struct KVMState
|
||||
int max_nested_state_len;
|
||||
int many_ioeventfds;
|
||||
int intx_set_mask;
|
||||
int kvm_shadow_mem;
|
||||
bool kernel_irqchip_allowed;
|
||||
bool kernel_irqchip_required;
|
||||
OnOffAuto kernel_irqchip_split;
|
||||
bool sync_mmu;
|
||||
uint64_t manual_dirty_log_protect;
|
||||
bool manual_dirty_log_protect;
|
||||
/* The man page (and posix) say ioctl numbers are signed int, but
|
||||
* they're not. Linux, glibc and *BSD all treat ioctl numbers as
|
||||
* unsigned, and treating them as signed here can break things */
|
||||
@@ -162,62 +152,12 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||
static NotifierList kvm_irqchip_change_notifiers =
|
||||
NOTIFIER_LIST_INITIALIZER(kvm_irqchip_change_notifiers);
|
||||
|
||||
struct KVMResampleFd {
|
||||
int gsi;
|
||||
EventNotifier *resample_event;
|
||||
QLIST_ENTRY(KVMResampleFd) node;
|
||||
};
|
||||
typedef struct KVMResampleFd KVMResampleFd;
|
||||
|
||||
/*
|
||||
* Only used with split irqchip where we need to do the resample fd
|
||||
* kick for the kernel from userspace.
|
||||
*/
|
||||
static QLIST_HEAD(, KVMResampleFd) kvm_resample_fd_list =
|
||||
QLIST_HEAD_INITIALIZER(kvm_resample_fd_list);
|
||||
|
||||
#define kvm_slots_lock(kml) qemu_mutex_lock(&(kml)->slots_lock)
|
||||
#define kvm_slots_unlock(kml) qemu_mutex_unlock(&(kml)->slots_lock)
|
||||
|
||||
static inline void kvm_resample_fd_remove(int gsi)
|
||||
{
|
||||
KVMResampleFd *rfd;
|
||||
|
||||
QLIST_FOREACH(rfd, &kvm_resample_fd_list, node) {
|
||||
if (rfd->gsi == gsi) {
|
||||
QLIST_REMOVE(rfd, node);
|
||||
g_free(rfd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void kvm_resample_fd_insert(int gsi, EventNotifier *event)
|
||||
{
|
||||
KVMResampleFd *rfd = g_new0(KVMResampleFd, 1);
|
||||
|
||||
rfd->gsi = gsi;
|
||||
rfd->resample_event = event;
|
||||
|
||||
QLIST_INSERT_HEAD(&kvm_resample_fd_list, rfd, node);
|
||||
}
|
||||
|
||||
void kvm_resample_fd_notify(int gsi)
|
||||
{
|
||||
KVMResampleFd *rfd;
|
||||
|
||||
QLIST_FOREACH(rfd, &kvm_resample_fd_list, node) {
|
||||
if (rfd->gsi == gsi) {
|
||||
event_notifier_set(rfd->resample_event);
|
||||
trace_kvm_resample_fd_notify(gsi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int kvm_get_max_memslots(void)
|
||||
{
|
||||
KVMState *s = KVM_STATE(current_accel());
|
||||
KVMState *s = KVM_STATE(current_machine->accelerator);
|
||||
|
||||
return s->nr_slots;
|
||||
}
|
||||
@@ -361,27 +301,17 @@ static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot, boo
|
||||
/* Set the slot size to 0 before setting the slot to the desired
|
||||
* value. This is needed based on KVM commit 75d61fbc. */
|
||||
mem.memory_size = 0;
|
||||
ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
|
||||
}
|
||||
mem.memory_size = slot->memory_size;
|
||||
ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
|
||||
slot->old_flags = mem.flags;
|
||||
err:
|
||||
trace_kvm_set_user_memory(mem.slot, mem.flags, mem.guest_phys_addr,
|
||||
mem.memory_size, mem.userspace_addr, ret);
|
||||
if (ret < 0) {
|
||||
error_report("%s: KVM_SET_USER_MEMORY_REGION failed, slot=%d,"
|
||||
" start=0x%" PRIx64 ", size=0x%" PRIx64 ": %s",
|
||||
__func__, mem.slot, slot->start_addr,
|
||||
(uint64_t)mem.memory_size, strerror(errno));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_kvm_destroy_vcpu(CPUState *cpu)
|
||||
int kvm_destroy_vcpu(CPUState *cpu)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
long mmap_size;
|
||||
@@ -415,14 +345,6 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void kvm_destroy_vcpu(CPUState *cpu)
|
||||
{
|
||||
if (do_kvm_destroy_vcpu(cpu) < 0) {
|
||||
error_report("kvm_destroy_vcpu failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id)
|
||||
{
|
||||
struct KVMParkedVcpu *cpu;
|
||||
@@ -441,18 +363,17 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id)
|
||||
return kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id);
|
||||
}
|
||||
|
||||
int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
||||
int kvm_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
long mmap_size;
|
||||
int ret;
|
||||
|
||||
trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu));
|
||||
DPRINTF("kvm_init_vcpu\n");
|
||||
|
||||
ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu));
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "kvm_init_vcpu: kvm_get_vcpu failed (%lu)",
|
||||
kvm_arch_vcpu_id(cpu));
|
||||
DPRINTF("kvm_create_vcpu failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -463,8 +384,7 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
||||
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
|
||||
if (mmap_size < 0) {
|
||||
ret = mmap_size;
|
||||
error_setg_errno(errp, -mmap_size,
|
||||
"kvm_init_vcpu: KVM_GET_VCPU_MMAP_SIZE failed");
|
||||
DPRINTF("KVM_GET_VCPU_MMAP_SIZE failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -472,9 +392,7 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
||||
cpu->kvm_fd, 0);
|
||||
if (cpu->kvm_run == MAP_FAILED) {
|
||||
ret = -errno;
|
||||
error_setg_errno(errp, ret,
|
||||
"kvm_init_vcpu: mmap'ing vcpu state failed (%lu)",
|
||||
kvm_arch_vcpu_id(cpu));
|
||||
DPRINTF("mmap'ing vcpu state failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -484,11 +402,6 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
||||
}
|
||||
|
||||
ret = kvm_arch_init_vcpu(cpu);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret,
|
||||
"kvm_init_vcpu: kvm_arch_init_vcpu failed (%lu)",
|
||||
kvm_arch_vcpu_id(cpu));
|
||||
}
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@@ -953,39 +866,6 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension)
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct HWPoisonPage {
|
||||
ram_addr_t ram_addr;
|
||||
QLIST_ENTRY(HWPoisonPage) list;
|
||||
} HWPoisonPage;
|
||||
|
||||
static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
|
||||
QLIST_HEAD_INITIALIZER(hwpoison_page_list);
|
||||
|
||||
static void kvm_unpoison_all(void *param)
|
||||
{
|
||||
HWPoisonPage *page, *next_page;
|
||||
|
||||
QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
|
||||
QLIST_REMOVE(page, list);
|
||||
qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
|
||||
g_free(page);
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_hwpoison_page_add(ram_addr_t ram_addr)
|
||||
{
|
||||
HWPoisonPage *page;
|
||||
|
||||
QLIST_FOREACH(page, &hwpoison_page_list, list) {
|
||||
if (page->ram_addr == ram_addr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
page = g_new(HWPoisonPage, 1);
|
||||
page->ram_addr = ram_addr;
|
||||
QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
|
||||
}
|
||||
|
||||
static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
|
||||
{
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
@@ -1731,13 +1611,9 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
|
||||
return kvm_update_routing_entry(s, &kroute);
|
||||
}
|
||||
|
||||
static int kvm_irqchip_assign_irqfd(KVMState *s, EventNotifier *event,
|
||||
EventNotifier *resample, int virq,
|
||||
static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq,
|
||||
bool assign)
|
||||
{
|
||||
int fd = event_notifier_get_fd(event);
|
||||
int rfd = resample ? event_notifier_get_fd(resample) : -1;
|
||||
|
||||
struct kvm_irqfd irqfd = {
|
||||
.fd = fd,
|
||||
.gsi = virq,
|
||||
@@ -1745,33 +1621,8 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, EventNotifier *event,
|
||||
};
|
||||
|
||||
if (rfd != -1) {
|
||||
assert(assign);
|
||||
if (kvm_irqchip_is_split()) {
|
||||
/*
|
||||
* When the slow irqchip (e.g. IOAPIC) is in the
|
||||
* userspace, KVM kernel resamplefd will not work because
|
||||
* the EOI of the interrupt will be delivered to userspace
|
||||
* instead, so the KVM kernel resamplefd kick will be
|
||||
* skipped. The userspace here mimics what the kernel
|
||||
* provides with resamplefd, remember the resamplefd and
|
||||
* kick it when we receive EOI of this IRQ.
|
||||
*
|
||||
* This is hackery because IOAPIC is mostly bypassed
|
||||
* (except EOI broadcasts) when irqfd is used. However
|
||||
* this can bring much performance back for split irqchip
|
||||
* with INTx IRQs (for VFIO, this gives 93% perf of the
|
||||
* full fast path, which is 46% perf boost comparing to
|
||||
* the INTx slow path).
|
||||
*/
|
||||
kvm_resample_fd_insert(virq, resample);
|
||||
} else {
|
||||
irqfd.flags |= KVM_IRQFD_FLAG_RESAMPLE;
|
||||
irqfd.resamplefd = rfd;
|
||||
}
|
||||
} else if (!assign) {
|
||||
if (kvm_irqchip_is_split()) {
|
||||
kvm_resample_fd_remove(virq);
|
||||
}
|
||||
irqfd.flags |= KVM_IRQFD_FLAG_RESAMPLE;
|
||||
irqfd.resamplefd = rfd;
|
||||
}
|
||||
|
||||
if (!kvm_irqfds_enabled()) {
|
||||
@@ -1867,9 +1718,7 @@ int kvm_irqchip_add_hv_sint_route(KVMState *s, uint32_t vcpu, uint32_t sint)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int kvm_irqchip_assign_irqfd(KVMState *s, EventNotifier *event,
|
||||
EventNotifier *resample, int virq,
|
||||
bool assign)
|
||||
static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
@@ -1883,13 +1732,15 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
|
||||
int kvm_irqchip_add_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
|
||||
EventNotifier *rn, int virq)
|
||||
{
|
||||
return kvm_irqchip_assign_irqfd(s, n, rn, virq, true);
|
||||
return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n),
|
||||
rn ? event_notifier_get_fd(rn) : -1, virq, true);
|
||||
}
|
||||
|
||||
int kvm_irqchip_remove_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
|
||||
int virq)
|
||||
{
|
||||
return kvm_irqchip_assign_irqfd(s, n, NULL, virq, false);
|
||||
return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), -1, virq,
|
||||
false);
|
||||
}
|
||||
|
||||
int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
|
||||
@@ -1921,11 +1772,10 @@ void kvm_irqchip_set_qemuirq_gsi(KVMState *s, qemu_irq irq, int gsi)
|
||||
g_hash_table_insert(s->gsimap, irq, GINT_TO_POINTER(gsi));
|
||||
}
|
||||
|
||||
static void kvm_irqchip_create(KVMState *s)
|
||||
static void kvm_irqchip_create(MachineState *machine, KVMState *s)
|
||||
{
|
||||
int ret;
|
||||
|
||||
assert(s->kernel_irqchip_split != ON_OFF_AUTO_AUTO);
|
||||
if (kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
|
||||
;
|
||||
} else if (kvm_check_extension(s, KVM_CAP_S390_IRQCHIP)) {
|
||||
@@ -1940,9 +1790,9 @@ static void kvm_irqchip_create(KVMState *s)
|
||||
|
||||
/* First probe and see if there's a arch-specific hook to create the
|
||||
* in-kernel irqchip for us */
|
||||
ret = kvm_arch_irqchip_create(s);
|
||||
ret = kvm_arch_irqchip_create(machine, s);
|
||||
if (ret == 0) {
|
||||
if (s->kernel_irqchip_split == ON_OFF_AUTO_ON) {
|
||||
if (machine_kernel_irqchip_split(machine)) {
|
||||
perror("Split IRQ chip mode not supported.");
|
||||
exit(1);
|
||||
} else {
|
||||
@@ -1990,7 +1840,7 @@ static int kvm_max_vcpu_id(KVMState *s)
|
||||
|
||||
bool kvm_vcpu_id_is_valid(int vcpu_id)
|
||||
{
|
||||
KVMState *s = KVM_STATE(current_accel());
|
||||
KVMState *s = KVM_STATE(current_machine->accelerator);
|
||||
return vcpu_id >= 0 && vcpu_id < kvm_max_vcpu_id(s);
|
||||
}
|
||||
|
||||
@@ -2014,7 +1864,6 @@ static int kvm_init(MachineState *ms)
|
||||
int ret;
|
||||
int type = 0;
|
||||
const char *kvm_type;
|
||||
uint64_t dirty_log_manual_caps;
|
||||
|
||||
s = KVM_STATE(ms->accelerator);
|
||||
|
||||
@@ -2033,7 +1882,7 @@ static int kvm_init(MachineState *ms)
|
||||
#endif
|
||||
QLIST_INIT(&s->kvm_parked_vcpus);
|
||||
s->vmfd = -1;
|
||||
s->fd = qemu_open_old("/dev/kvm", O_RDWR);
|
||||
s->fd = qemu_open("/dev/kvm", O_RDWR);
|
||||
if (s->fd == -1) {
|
||||
fprintf(stderr, "Could not access KVM kernel module: %m\n");
|
||||
ret = -errno;
|
||||
@@ -2140,20 +1989,14 @@ static int kvm_init(MachineState *ms)
|
||||
s->coalesced_pio = s->coalesced_mmio &&
|
||||
kvm_check_extension(s, KVM_CAP_COALESCED_PIO);
|
||||
|
||||
dirty_log_manual_caps =
|
||||
s->manual_dirty_log_protect =
|
||||
kvm_check_extension(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
|
||||
dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
|
||||
KVM_DIRTY_LOG_INITIALLY_SET);
|
||||
s->manual_dirty_log_protect = dirty_log_manual_caps;
|
||||
if (dirty_log_manual_caps) {
|
||||
ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0,
|
||||
dirty_log_manual_caps);
|
||||
if (s->manual_dirty_log_protect) {
|
||||
ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0, 1);
|
||||
if (ret) {
|
||||
warn_report("Trying to enable capability %"PRIu64" of "
|
||||
"KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 but failed. "
|
||||
"Falling back to the legacy mode. ",
|
||||
dirty_log_manual_caps);
|
||||
s->manual_dirty_log_protect = 0;
|
||||
warn_report("Trying to enable KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 "
|
||||
"but failed. Falling back to the legacy mode. ");
|
||||
s->manual_dirty_log_protect = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2220,14 +2063,8 @@ static int kvm_init(MachineState *ms)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (s->kernel_irqchip_split == ON_OFF_AUTO_AUTO) {
|
||||
s->kernel_irqchip_split = mc->default_kernel_irqchip_split ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
|
||||
}
|
||||
|
||||
qemu_register_reset(kvm_unpoison_all, NULL);
|
||||
|
||||
if (s->kernel_irqchip_allowed) {
|
||||
kvm_irqchip_create(s);
|
||||
if (machine_kernel_irqchip_allowed(ms)) {
|
||||
kvm_irqchip_create(ms, s);
|
||||
}
|
||||
|
||||
if (kvm_eventfds_allowed) {
|
||||
@@ -2239,10 +2076,8 @@ static int kvm_init(MachineState *ms)
|
||||
|
||||
kvm_memory_listener_register(s, &s->memory_listener,
|
||||
&address_space_memory, 0);
|
||||
if (kvm_eventfds_allowed) {
|
||||
memory_listener_register(&kvm_io_listener,
|
||||
&address_space_io);
|
||||
}
|
||||
memory_listener_register(&kvm_io_listener,
|
||||
&address_space_io);
|
||||
memory_listener_register(&kvm_coalesced_pio_listener,
|
||||
&address_space_io);
|
||||
|
||||
@@ -2250,11 +2085,9 @@ static int kvm_init(MachineState *ms)
|
||||
|
||||
s->sync_mmu = !!kvm_vm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
|
||||
if (!s->sync_mmu) {
|
||||
ret = ram_block_discard_disable(true);
|
||||
assert(!ret);
|
||||
qemu_balloon_inhibit(true);
|
||||
}
|
||||
|
||||
cpus_register_accel(&kvm_cpus);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@@ -2333,9 +2166,9 @@ void kvm_flush_coalesced_mmio_buffer(void)
|
||||
ent = &ring->coalesced_mmio[ring->first];
|
||||
|
||||
if (ent->pio == 1) {
|
||||
address_space_write(&address_space_io, ent->phys_addr,
|
||||
MEMTXATTRS_UNSPECIFIED, ent->data,
|
||||
ent->len);
|
||||
address_space_rw(&address_space_io, ent->phys_addr,
|
||||
MEMTXATTRS_UNSPECIFIED, ent->data,
|
||||
ent->len, true);
|
||||
} else {
|
||||
cpu_physical_memory_write(ent->phys_addr, ent->data, ent->len);
|
||||
}
|
||||
@@ -2402,7 +2235,7 @@ static __thread bool have_sigbus_pending;
|
||||
|
||||
static void kvm_cpu_kick(CPUState *cpu)
|
||||
{
|
||||
qatomic_set(&cpu->kvm_run->immediate_exit, 1);
|
||||
atomic_set(&cpu->kvm_run->immediate_exit, 1);
|
||||
}
|
||||
|
||||
static void kvm_cpu_kick_self(void)
|
||||
@@ -2423,7 +2256,7 @@ static void kvm_eat_signals(CPUState *cpu)
|
||||
int r;
|
||||
|
||||
if (kvm_immediate_exit) {
|
||||
qatomic_set(&cpu->kvm_run->immediate_exit, 0);
|
||||
atomic_set(&cpu->kvm_run->immediate_exit, 0);
|
||||
/* Write kvm_run->immediate_exit before the cpu->exit_request
|
||||
* write in kvm_cpu_exec.
|
||||
*/
|
||||
@@ -2457,7 +2290,7 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||
DPRINTF("kvm_cpu_exec()\n");
|
||||
|
||||
if (kvm_arch_process_async_events(cpu)) {
|
||||
qatomic_set(&cpu->exit_request, 0);
|
||||
atomic_set(&cpu->exit_request, 0);
|
||||
return EXCP_HLT;
|
||||
}
|
||||
|
||||
@@ -2473,7 +2306,7 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||
}
|
||||
|
||||
kvm_arch_pre_run(cpu, run);
|
||||
if (qatomic_read(&cpu->exit_request)) {
|
||||
if (atomic_read(&cpu->exit_request)) {
|
||||
DPRINTF("interrupt exit requested\n");
|
||||
/*
|
||||
* KVM requires us to reenter the kernel after IO exits to complete
|
||||
@@ -2600,7 +2433,7 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||
vm_stop(RUN_STATE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
qatomic_set(&cpu->exit_request, 0);
|
||||
atomic_set(&cpu->exit_request, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3017,7 +2850,7 @@ int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
|
||||
have_sigbus_pending = true;
|
||||
pending_sigbus_addr = addr;
|
||||
pending_sigbus_code = code;
|
||||
qatomic_set(&cpu->exit_request, 1);
|
||||
atomic_set(&cpu->exit_request, 1);
|
||||
return 0;
|
||||
#else
|
||||
return 1;
|
||||
@@ -3121,88 +2954,6 @@ static bool kvm_accel_has_memory(MachineState *ms, AddressSpace *as,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void kvm_get_kvm_shadow_mem(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
KVMState *s = KVM_STATE(obj);
|
||||
int64_t value = s->kvm_shadow_mem;
|
||||
|
||||
visit_type_int(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void kvm_set_kvm_shadow_mem(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
KVMState *s = KVM_STATE(obj);
|
||||
int64_t value;
|
||||
|
||||
if (!visit_type_int(v, name, &value, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
s->kvm_shadow_mem = value;
|
||||
}
|
||||
|
||||
static void kvm_set_kernel_irqchip(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
KVMState *s = KVM_STATE(obj);
|
||||
OnOffSplit mode;
|
||||
|
||||
if (!visit_type_OnOffSplit(v, name, &mode, errp)) {
|
||||
return;
|
||||
}
|
||||
switch (mode) {
|
||||
case ON_OFF_SPLIT_ON:
|
||||
s->kernel_irqchip_allowed = true;
|
||||
s->kernel_irqchip_required = true;
|
||||
s->kernel_irqchip_split = ON_OFF_AUTO_OFF;
|
||||
break;
|
||||
case ON_OFF_SPLIT_OFF:
|
||||
s->kernel_irqchip_allowed = false;
|
||||
s->kernel_irqchip_required = false;
|
||||
s->kernel_irqchip_split = ON_OFF_AUTO_OFF;
|
||||
break;
|
||||
case ON_OFF_SPLIT_SPLIT:
|
||||
s->kernel_irqchip_allowed = true;
|
||||
s->kernel_irqchip_required = true;
|
||||
s->kernel_irqchip_split = ON_OFF_AUTO_ON;
|
||||
break;
|
||||
default:
|
||||
/* The value was checked in visit_type_OnOffSplit() above. If
|
||||
* we get here, then something is wrong in QEMU.
|
||||
*/
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
bool kvm_kernel_irqchip_allowed(void)
|
||||
{
|
||||
return kvm_state->kernel_irqchip_allowed;
|
||||
}
|
||||
|
||||
bool kvm_kernel_irqchip_required(void)
|
||||
{
|
||||
return kvm_state->kernel_irqchip_required;
|
||||
}
|
||||
|
||||
bool kvm_kernel_irqchip_split(void)
|
||||
{
|
||||
return kvm_state->kernel_irqchip_split == ON_OFF_AUTO_ON;
|
||||
}
|
||||
|
||||
static void kvm_accel_instance_init(Object *obj)
|
||||
{
|
||||
KVMState *s = KVM_STATE(obj);
|
||||
|
||||
s->kvm_shadow_mem = -1;
|
||||
s->kernel_irqchip_allowed = true;
|
||||
s->kernel_irqchip_split = ON_OFF_AUTO_AUTO;
|
||||
}
|
||||
|
||||
static void kvm_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(oc);
|
||||
@@ -3210,24 +2961,11 @@ static void kvm_accel_class_init(ObjectClass *oc, void *data)
|
||||
ac->init_machine = kvm_init;
|
||||
ac->has_memory = kvm_accel_has_memory;
|
||||
ac->allowed = &kvm_allowed;
|
||||
|
||||
object_class_property_add(oc, "kernel-irqchip", "on|off|split",
|
||||
NULL, kvm_set_kernel_irqchip,
|
||||
NULL, NULL);
|
||||
object_class_property_set_description(oc, "kernel-irqchip",
|
||||
"Configure KVM in-kernel irqchip");
|
||||
|
||||
object_class_property_add(oc, "kvm-shadow-mem", "int",
|
||||
kvm_get_kvm_shadow_mem, kvm_set_kvm_shadow_mem,
|
||||
NULL, NULL);
|
||||
object_class_property_set_description(oc, "kvm-shadow-mem",
|
||||
"KVM shadow MMU size");
|
||||
}
|
||||
|
||||
static const TypeInfo kvm_accel_type = {
|
||||
.name = TYPE_KVM_ACCEL,
|
||||
.parent = TYPE_ACCEL,
|
||||
.instance_init = kvm_accel_instance_init,
|
||||
.class_init = kvm_accel_class_init,
|
||||
.instance_size = sizeof(KVMState),
|
||||
};
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* QEMU KVM support
|
||||
*
|
||||
* Copyright IBM, Corp. 2008
|
||||
* Red Hat, Inc. 2008
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
* Glauber Costa <gcosta@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#include "kvm-cpus.h"
|
||||
|
||||
static void *kvm_vcpu_thread_fn(void *arg)
|
||||
{
|
||||
CPUState *cpu = arg;
|
||||
int r;
|
||||
|
||||
rcu_register_thread();
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
qemu_thread_get_self(cpu->thread);
|
||||
cpu->thread_id = qemu_get_thread_id();
|
||||
cpu->can_do_io = 1;
|
||||
current_cpu = cpu;
|
||||
|
||||
r = kvm_init_vcpu(cpu, &error_fatal);
|
||||
kvm_init_cpu_signals(cpu);
|
||||
|
||||
/* signal CPU creation */
|
||||
cpu_thread_signal_created(cpu);
|
||||
qemu_guest_random_seed_thread_part2(cpu->random_seed);
|
||||
|
||||
do {
|
||||
if (cpu_can_run(cpu)) {
|
||||
r = kvm_cpu_exec(cpu);
|
||||
if (r == EXCP_DEBUG) {
|
||||
cpu_handle_guest_debug(cpu);
|
||||
}
|
||||
}
|
||||
qemu_wait_io_event(cpu);
|
||||
} while (!cpu->unplug || cpu_can_run(cpu));
|
||||
|
||||
kvm_destroy_vcpu(cpu);
|
||||
cpu_thread_signal_destroyed(cpu);
|
||||
qemu_mutex_unlock_iothread();
|
||||
rcu_unregister_thread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void kvm_start_vcpu_thread(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
|
||||
cpu->cpu_index);
|
||||
qemu_thread_create(cpu->thread, thread_name, kvm_vcpu_thread_fn,
|
||||
cpu, QEMU_THREAD_JOINABLE);
|
||||
}
|
||||
|
||||
const CpusAccel kvm_cpus = {
|
||||
.create_vcpu_thread = kvm_start_vcpu_thread,
|
||||
|
||||
.synchronize_post_reset = kvm_cpu_synchronize_post_reset,
|
||||
.synchronize_post_init = kvm_cpu_synchronize_post_init,
|
||||
.synchronize_state = kvm_cpu_synchronize_state,
|
||||
.synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm,
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Accelerator CPUS Interface
|
||||
*
|
||||
* Copyright 2020 SUSE LLC
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef KVM_CPUS_H
|
||||
#define KVM_CPUS_H
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
extern const CpusAccel kvm_cpus;
|
||||
|
||||
int kvm_init_vcpu(CPUState *cpu, Error **errp);
|
||||
int kvm_cpu_exec(CPUState *cpu);
|
||||
void kvm_destroy_vcpu(CPUState *cpu);
|
||||
void kvm_cpu_synchronize_post_reset(CPUState *cpu);
|
||||
void kvm_cpu_synchronize_post_init(CPUState *cpu);
|
||||
void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu);
|
||||
|
||||
#endif /* KVM_CPUS_H */
|
||||
@@ -1,8 +0,0 @@
|
||||
kvm_ss = ss.source_set()
|
||||
kvm_ss.add(files(
|
||||
'kvm-all.c',
|
||||
'kvm-cpus.c',
|
||||
))
|
||||
kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
|
||||
|
||||
specific_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
|
||||
@@ -8,7 +8,6 @@ kvm_run_exit(int cpu_index, uint32_t reason) "cpu_index %d, reason %d"
|
||||
kvm_device_ioctl(int fd, int type, void *arg) "dev fd %d, type 0x%x, arg %p"
|
||||
kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s"
|
||||
kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s"
|
||||
kvm_init_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
|
||||
kvm_irqchip_commit_routes(void) ""
|
||||
kvm_irqchip_add_msi_route(char *name, int vector, int virq) "dev %s vector %d virq %d"
|
||||
kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d"
|
||||
@@ -17,5 +16,4 @@ kvm_set_ioeventfd_mmio(int fd, uint64_t addr, uint32_t val, bool assign, uint32_
|
||||
kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%x val=0x%x assign: %d size: %d match: %d"
|
||||
kvm_set_user_memory(uint32_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, int ret) "Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " ret=%d"
|
||||
kvm_clear_dirty_log(uint32_t slot, uint64_t start, uint32_t size) "slot#%"PRId32" start 0x%"PRIx64" size 0x%"PRIx32
|
||||
kvm_resample_fd_notify(int gsi) "gsi %d"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include "trace/trace-accel_kvm.h"
|
||||
@@ -1,15 +0,0 @@
|
||||
softmmu_ss.add(files('accel.c'))
|
||||
|
||||
subdir('qtest')
|
||||
subdir('kvm')
|
||||
subdir('tcg')
|
||||
subdir('xen')
|
||||
subdir('stubs')
|
||||
|
||||
dummy_ss = ss.source_set()
|
||||
dummy_ss.add(files(
|
||||
'dummy-cpus.c',
|
||||
))
|
||||
|
||||
specific_ss.add_all(when: ['CONFIG_SOFTMMU', 'CONFIG_POSIX'], if_true: dummy_ss)
|
||||
specific_ss.add_all(when: ['CONFIG_XEN'], if_true: dummy_ss)
|
||||
@@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/rcu.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
@@ -20,19 +19,14 @@
|
||||
#include "sysemu/accel.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
const CpusAccel qtest_cpus = {
|
||||
.create_vcpu_thread = dummy_start_vcpu_thread,
|
||||
.get_virtual_clock = qtest_get_virtual_clock,
|
||||
};
|
||||
|
||||
static int qtest_init_accel(MachineState *ms)
|
||||
{
|
||||
cpus_register_accel(&qtest_cpus);
|
||||
QemuOpts *opts = qemu_opts_create(qemu_find_opts("icount"), NULL, 0,
|
||||
&error_abort);
|
||||
qemu_opt_set(opts, "shift", "0", &error_abort);
|
||||
configure_icount(opts, &error_abort);
|
||||
qemu_opts_del(opts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
qtest_ss = ss.source_set()
|
||||
qtest_ss.add(files(
|
||||
'qtest.c',
|
||||
))
|
||||
|
||||
specific_ss.add_all(when: ['CONFIG_SOFTMMU', 'CONFIG_POSIX'], if_true: qtest_ss)
|
||||
@@ -0,0 +1,5 @@
|
||||
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
|
||||
obj-$(call lnot,$(CONFIG_HVF)) += hvf-stub.o
|
||||
obj-$(call lnot,$(CONFIG_WHPX)) += whpx-stub.o
|
||||
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
|
||||
obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o
|
||||
@@ -14,9 +14,20 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/hax.h"
|
||||
|
||||
int hax_sync_vcpus(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hax_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int hax_smp_cpu_exec(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* QEMU HVF support
|
||||
*
|
||||
* Copyright 2017 Red Hat, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2 or later, as published by the Free Software Foundation,
|
||||
* and may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/hvf.h"
|
||||
|
||||
int hvf_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int hvf_vcpu_exec(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void hvf_vcpu_destroy(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
@@ -32,6 +32,16 @@ bool kvm_readonly_mem_allowed;
|
||||
bool kvm_ioeventfd_any_length_allowed;
|
||||
bool kvm_msi_use_devid;
|
||||
|
||||
int kvm_destroy_vcpu(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int kvm_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void kvm_flush_coalesced_mmio_buffer(void)
|
||||
{
|
||||
}
|
||||
@@ -40,6 +50,19 @@ void kvm_cpu_synchronize_state(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_cpu_synchronize_post_reset(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_cpu_synchronize_post_init(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_cpu_exec(CPUState *cpu)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
bool kvm_has_sync_mmu(void)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
specific_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c'))
|
||||
specific_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
|
||||
specific_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
|
||||
specific_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
|
||||
@@ -22,10 +22,3 @@ void tb_flush(CPUState *cpu)
|
||||
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
|
||||
{
|
||||
}
|
||||
|
||||
void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
||||
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
/* Handled by hardware accelerator. */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* QEMU Windows Hypervisor Platform accelerator (WHPX) stub
|
||||
*
|
||||
* Copyright Microsoft Corp. 2017
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/whpx.h"
|
||||
|
||||
int whpx_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int whpx_vcpu_exec(CPUState *cpu)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void whpx_destroy_vcpu(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void whpx_vcpu_kick(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void whpx_cpu_synchronize_state(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void whpx_cpu_synchronize_post_reset(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void whpx_cpu_synchronize_post_init(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void whpx_cpu_synchronize_pre_loadvm(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
obj-$(CONFIG_SOFTMMU) += tcg-all.o
|
||||
obj-$(CONFIG_SOFTMMU) += cputlb.o
|
||||
obj-y += tcg-runtime.o tcg-runtime-gvec.o
|
||||
obj-y += cpu-exec.o cpu-exec-common.o translate-all.o
|
||||
obj-y += translator.o
|
||||
|
||||
obj-$(CONFIG_USER_ONLY) += user-exec.o
|
||||
obj-$(call lnot,$(CONFIG_SOFTMMU)) += user-exec-stub.o
|
||||
obj-$(CONFIG_PLUGIN) += plugin-gen.o
|
||||
File renamed without changes.
+53
-34
@@ -64,10 +64,13 @@
|
||||
the ATOMIC_NAME macro, and redefined below. */
|
||||
#if DATA_SIZE == 1
|
||||
# define END
|
||||
# define MEND _be /* either le or be would be fine */
|
||||
#elif defined(HOST_WORDS_BIGENDIAN)
|
||||
# define END _be
|
||||
# define MEND _be
|
||||
#else
|
||||
# define END _le
|
||||
# define MEND _le
|
||||
#endif
|
||||
|
||||
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
@@ -76,14 +79,14 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
ATOMIC_MMU_DECLS;
|
||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||
DATA_TYPE ret;
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, 0, false,
|
||||
ATOMIC_MMU_IDX);
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, false,
|
||||
ATOMIC_MMU_IDX);
|
||||
|
||||
atomic_trace_rmw_pre(env, addr, info);
|
||||
#if DATA_SIZE == 16
|
||||
ret = atomic16_cmpxchg(haddr, cmpv, newv);
|
||||
#else
|
||||
ret = qatomic_cmpxchg__nocheck(haddr, cmpv, newv);
|
||||
ret = atomic_cmpxchg__nocheck(haddr, cmpv, newv);
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
@@ -96,8 +99,8 @@ ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
|
||||
{
|
||||
ATOMIC_MMU_DECLS;
|
||||
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, 0, false,
|
||||
ATOMIC_MMU_IDX);
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, false,
|
||||
ATOMIC_MMU_IDX);
|
||||
|
||||
atomic_trace_ld_pre(env, addr, info);
|
||||
val = atomic16_read(haddr);
|
||||
@@ -111,8 +114,8 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
|
||||
{
|
||||
ATOMIC_MMU_DECLS;
|
||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, 0, true,
|
||||
ATOMIC_MMU_IDX);
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, true,
|
||||
ATOMIC_MMU_IDX);
|
||||
|
||||
atomic_trace_st_pre(env, addr, info);
|
||||
atomic16_set(haddr, val);
|
||||
@@ -127,11 +130,11 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
|
||||
ATOMIC_MMU_DECLS;
|
||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||
DATA_TYPE ret;
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, 0, false,
|
||||
ATOMIC_MMU_IDX);
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, false,
|
||||
ATOMIC_MMU_IDX);
|
||||
|
||||
atomic_trace_rmw_pre(env, addr, info);
|
||||
ret = qatomic_xchg__nocheck(haddr, val);
|
||||
ret = atomic_xchg__nocheck(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return ret;
|
||||
@@ -144,10 +147,12 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ATOMIC_MMU_DECLS; \
|
||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
|
||||
DATA_TYPE ret; \
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, 0, false, \
|
||||
ATOMIC_MMU_IDX); \
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, \
|
||||
false, \
|
||||
ATOMIC_MMU_IDX); \
|
||||
\
|
||||
atomic_trace_rmw_pre(env, addr, info); \
|
||||
ret = qatomic_##X(haddr, val); \
|
||||
ret = atomic_##X(haddr, val); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return ret; \
|
||||
@@ -178,14 +183,16 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ATOMIC_MMU_DECLS; \
|
||||
XDATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
|
||||
XDATA_TYPE cmp, old, new, val = xval; \
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, 0, false, \
|
||||
ATOMIC_MMU_IDX); \
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, \
|
||||
false, \
|
||||
ATOMIC_MMU_IDX); \
|
||||
\
|
||||
atomic_trace_rmw_pre(env, addr, info); \
|
||||
smp_mb(); \
|
||||
cmp = qatomic_read__nocheck(haddr); \
|
||||
cmp = atomic_read__nocheck(haddr); \
|
||||
do { \
|
||||
old = cmp; new = FN(old, val); \
|
||||
cmp = qatomic_cmpxchg__nocheck(haddr, old, new); \
|
||||
cmp = atomic_cmpxchg__nocheck(haddr, old, new); \
|
||||
} while (cmp != old); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
@@ -206,6 +213,7 @@ GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
|
||||
#endif /* DATA SIZE >= 16 */
|
||||
|
||||
#undef END
|
||||
#undef MEND
|
||||
|
||||
#if DATA_SIZE > 1
|
||||
|
||||
@@ -213,8 +221,10 @@ GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
|
||||
within the ATOMIC_NAME macro. */
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
# define END _le
|
||||
# define MEND _le
|
||||
#else
|
||||
# define END _be
|
||||
# define MEND _be
|
||||
#endif
|
||||
|
||||
ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
@@ -223,14 +233,15 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||
ATOMIC_MMU_DECLS;
|
||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||
DATA_TYPE ret;
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, MO_BSWAP, false,
|
||||
ATOMIC_MMU_IDX);
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT,
|
||||
false,
|
||||
ATOMIC_MMU_IDX);
|
||||
|
||||
atomic_trace_rmw_pre(env, addr, info);
|
||||
#if DATA_SIZE == 16
|
||||
ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||
#else
|
||||
ret = qatomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||
ret = atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
@@ -243,8 +254,9 @@ ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
|
||||
{
|
||||
ATOMIC_MMU_DECLS;
|
||||
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, MO_BSWAP, false,
|
||||
ATOMIC_MMU_IDX);
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT,
|
||||
false,
|
||||
ATOMIC_MMU_IDX);
|
||||
|
||||
atomic_trace_ld_pre(env, addr, info);
|
||||
val = atomic16_read(haddr);
|
||||
@@ -258,8 +270,9 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
|
||||
{
|
||||
ATOMIC_MMU_DECLS;
|
||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, MO_BSWAP, true,
|
||||
ATOMIC_MMU_IDX);
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT,
|
||||
true,
|
||||
ATOMIC_MMU_IDX);
|
||||
|
||||
val = BSWAP(val);
|
||||
atomic_trace_st_pre(env, addr, info);
|
||||
@@ -276,11 +289,12 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
|
||||
ATOMIC_MMU_DECLS;
|
||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||
ABI_TYPE ret;
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, MO_BSWAP, false,
|
||||
ATOMIC_MMU_IDX);
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT,
|
||||
false,
|
||||
ATOMIC_MMU_IDX);
|
||||
|
||||
atomic_trace_rmw_pre(env, addr, info);
|
||||
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
|
||||
ret = atomic_xchg__nocheck(haddr, BSWAP(val));
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr, info);
|
||||
return BSWAP(ret);
|
||||
@@ -293,10 +307,12 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ATOMIC_MMU_DECLS; \
|
||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
|
||||
DATA_TYPE ret; \
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, MO_BSWAP, \
|
||||
false, ATOMIC_MMU_IDX); \
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, \
|
||||
false, \
|
||||
ATOMIC_MMU_IDX); \
|
||||
\
|
||||
atomic_trace_rmw_pre(env, addr, info); \
|
||||
ret = qatomic_##X(haddr, BSWAP(val)); \
|
||||
ret = atomic_##X(haddr, BSWAP(val)); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
return BSWAP(ret); \
|
||||
@@ -325,14 +341,16 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||
ATOMIC_MMU_DECLS; \
|
||||
XDATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
|
||||
XDATA_TYPE ldo, ldn, old, new, val = xval; \
|
||||
uint16_t info = trace_mem_build_info(SHIFT, false, MO_BSWAP, \
|
||||
false, ATOMIC_MMU_IDX); \
|
||||
uint16_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, \
|
||||
false, \
|
||||
ATOMIC_MMU_IDX); \
|
||||
\
|
||||
atomic_trace_rmw_pre(env, addr, info); \
|
||||
smp_mb(); \
|
||||
ldn = qatomic_read__nocheck(haddr); \
|
||||
ldn = atomic_read__nocheck(haddr); \
|
||||
do { \
|
||||
ldo = ldn; old = BSWAP(ldo); new = FN(old, val); \
|
||||
ldn = qatomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \
|
||||
ldn = atomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new)); \
|
||||
} while (ldo != ldn); \
|
||||
ATOMIC_MMU_CLEANUP; \
|
||||
atomic_trace_rmw_post(env, addr, info); \
|
||||
@@ -360,6 +378,7 @@ GEN_ATOMIC_HELPER_FN(add_fetch, ADD, DATA_TYPE, new)
|
||||
#endif /* DATA_SIZE >= 16 */
|
||||
|
||||
#undef END
|
||||
#undef MEND
|
||||
#endif /* DATA_SIZE > 1 */
|
||||
|
||||
#undef BSWAP
|
||||
|
||||
+31
-94
@@ -19,12 +19,11 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "cpu.h"
|
||||
#include "trace.h"
|
||||
#include "disas/disas.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qemu/timer.h"
|
||||
@@ -37,8 +36,6 @@
|
||||
#include "hw/i386/apic.h"
|
||||
#endif
|
||||
#include "sysemu/cpus.h"
|
||||
#include "exec/cpu-all.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "sysemu/replay.h"
|
||||
|
||||
/* -icount align implementation. */
|
||||
@@ -59,9 +56,6 @@ typedef struct SyncClocks {
|
||||
#define MAX_DELAY_PRINT_RATE 2000000000LL
|
||||
#define MAX_NB_PRINTS 100
|
||||
|
||||
static int64_t max_delay;
|
||||
static int64_t max_advance;
|
||||
|
||||
static void align_clocks(SyncClocks *sc, CPUState *cpu)
|
||||
{
|
||||
int64_t cpu_icount;
|
||||
@@ -71,7 +65,7 @@ static void align_clocks(SyncClocks *sc, CPUState *cpu)
|
||||
}
|
||||
|
||||
cpu_icount = cpu->icount_extra + cpu_neg(cpu)->icount_decr.u16.low;
|
||||
sc->diff_clk += icount_to_ns(sc->last_cpu_icount - cpu_icount);
|
||||
sc->diff_clk += cpu_icount_to_ns(sc->last_cpu_icount - cpu_icount);
|
||||
sc->last_cpu_icount = cpu_icount;
|
||||
|
||||
if (sc->diff_clk > VM_CLOCK_ADVANCE) {
|
||||
@@ -104,9 +98,9 @@ static void print_delay(const SyncClocks *sc)
|
||||
(-sc->diff_clk / (float)1000000000LL <
|
||||
(threshold_delay - THRESHOLD_REDUCE))) {
|
||||
threshold_delay = (-sc->diff_clk / 1000000000LL) + 1;
|
||||
qemu_printf("Warning: The guest is now late by %.1f to %.1f seconds\n",
|
||||
threshold_delay - 1,
|
||||
threshold_delay);
|
||||
printf("Warning: The guest is now late by %.1f to %.1f seconds\n",
|
||||
threshold_delay - 1,
|
||||
threshold_delay);
|
||||
nb_prints++;
|
||||
last_realtime_clock = sc->realtime_clock;
|
||||
}
|
||||
@@ -162,7 +156,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
|
||||
#if defined(DEBUG_DISAS)
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)
|
||||
&& qemu_log_in_addr_range(itb->pc)) {
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log_lock();
|
||||
int flags = 0;
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
|
||||
flags |= CPU_DUMP_FPU;
|
||||
@@ -171,7 +165,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
|
||||
flags |= CPU_DUMP_CCOP;
|
||||
#endif
|
||||
log_cpu_state(cpu, flags);
|
||||
qemu_log_unlock(logfile);
|
||||
qemu_log_unlock();
|
||||
}
|
||||
#endif /* DEBUG_DISAS */
|
||||
|
||||
@@ -246,8 +240,6 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
uint32_t cf_mask = cflags & CF_HASH_MASK;
|
||||
|
||||
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
|
||||
start_exclusive();
|
||||
|
||||
tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask);
|
||||
if (tb == NULL) {
|
||||
mmap_lock();
|
||||
@@ -255,6 +247,8 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
mmap_unlock();
|
||||
}
|
||||
|
||||
start_exclusive();
|
||||
|
||||
/* Since we got here, we know that parallel_cpus must be true. */
|
||||
parallel_cpus = false;
|
||||
cc->cpu_exec_enter(cpu);
|
||||
@@ -277,15 +271,14 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* As we start the exclusive region before codegen we must still
|
||||
* be in the region if we longjump out of either the codegen or
|
||||
* the execution.
|
||||
*/
|
||||
g_assert(cpu_in_exclusive_context(cpu));
|
||||
parallel_cpus = true;
|
||||
end_exclusive();
|
||||
if (cpu_in_exclusive_context(cpu)) {
|
||||
/* We might longjump out of either the codegen or the
|
||||
* execution, so must make sure we only end the exclusive
|
||||
* region if we started it.
|
||||
*/
|
||||
parallel_cpus = true;
|
||||
end_exclusive();
|
||||
}
|
||||
}
|
||||
|
||||
struct tb_desc {
|
||||
@@ -373,8 +366,7 @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
|
||||
goto out_unlock_next;
|
||||
}
|
||||
/* Atomically claim the jump destination slot only if it was NULL */
|
||||
old = qatomic_cmpxchg(&tb->jmp_dest[n], (uintptr_t)NULL,
|
||||
(uintptr_t)tb_next);
|
||||
old = atomic_cmpxchg(&tb->jmp_dest[n], (uintptr_t)NULL, (uintptr_t)tb_next);
|
||||
if (old) {
|
||||
goto out_unlock_next;
|
||||
}
|
||||
@@ -414,7 +406,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
|
||||
tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask);
|
||||
mmap_unlock();
|
||||
/* We add the TB in the virtual pc hash table for the fast lookup */
|
||||
qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
|
||||
atomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
|
||||
}
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* We don't take care of direct jumps when address mapping changes in
|
||||
@@ -436,7 +428,8 @@ static inline bool cpu_handle_halt(CPUState *cpu)
|
||||
{
|
||||
if (cpu->halted) {
|
||||
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
|
||||
if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
|
||||
if ((cpu->interrupt_request & CPU_INTERRUPT_POLL)
|
||||
&& replay_interrupt()) {
|
||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
qemu_mutex_lock_iothread();
|
||||
apic_poll_irq(x86_cpu->apic_state);
|
||||
@@ -510,17 +503,6 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
cc->do_interrupt(cpu);
|
||||
qemu_mutex_unlock_iothread();
|
||||
cpu->exception_index = -1;
|
||||
|
||||
if (unlikely(cpu->singlestep_enabled)) {
|
||||
/*
|
||||
* After processing the exception, ensure an EXCP_DEBUG is
|
||||
* raised when single-stepping so that GDB doesn't miss the
|
||||
* next instruction.
|
||||
*/
|
||||
*ret = EXCP_DEBUG;
|
||||
cpu_handle_debug_exception(cpu);
|
||||
return true;
|
||||
}
|
||||
} else if (!replay_has_interrupt()) {
|
||||
/* give a chance to iothread in replay mode */
|
||||
*ret = EXCP_INTERRUPT;
|
||||
@@ -532,20 +514,6 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* CPU_INTERRUPT_POLL is a virtual event which gets converted into a
|
||||
* "real" interrupt event later. It does not need to be recorded for
|
||||
* replay purposes.
|
||||
*/
|
||||
static inline bool need_replay_interrupt(int interrupt_request)
|
||||
{
|
||||
#if defined(TARGET_I386)
|
||||
return !(interrupt_request & CPU_INTERRUPT_POLL);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
TranslationBlock **last_tb)
|
||||
{
|
||||
@@ -556,9 +524,9 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
* Ensure zeroing happens before reading cpu->exit_request or
|
||||
* cpu->interrupt_request (see also smp_wmb in cpu_exit())
|
||||
*/
|
||||
qatomic_mb_set(&cpu_neg(cpu)->icount_decr.u16.high, 0);
|
||||
atomic_mb_set(&cpu_neg(cpu)->icount_decr.u16.high, 0);
|
||||
|
||||
if (unlikely(qatomic_read(&cpu->interrupt_request))) {
|
||||
if (unlikely(atomic_read(&cpu->interrupt_request))) {
|
||||
int interrupt_request;
|
||||
qemu_mutex_lock_iothread();
|
||||
interrupt_request = cpu->interrupt_request;
|
||||
@@ -607,16 +575,8 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
and via longjmp via cpu_loop_exit. */
|
||||
else {
|
||||
if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||
if (need_replay_interrupt(interrupt_request)) {
|
||||
replay_interrupt();
|
||||
}
|
||||
/*
|
||||
* After processing the interrupt, ensure an EXCP_DEBUG is
|
||||
* raised when single-stepping so that GDB doesn't miss the
|
||||
* next instruction.
|
||||
*/
|
||||
cpu->exception_index =
|
||||
(cpu->singlestep_enabled ? EXCP_DEBUG : -1);
|
||||
replay_interrupt();
|
||||
cpu->exception_index = -1;
|
||||
*last_tb = NULL;
|
||||
}
|
||||
/* The target hook may have updated the 'cpu->interrupt_request';
|
||||
@@ -635,10 +595,10 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
}
|
||||
|
||||
/* Finally, check if we need to exit to the main loop. */
|
||||
if (unlikely(qatomic_read(&cpu->exit_request))
|
||||
|| (icount_enabled()
|
||||
if (unlikely(atomic_read(&cpu->exit_request))
|
||||
|| (use_icount
|
||||
&& cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0)) {
|
||||
qatomic_set(&cpu->exit_request, 0);
|
||||
atomic_set(&cpu->exit_request, 0);
|
||||
if (cpu->exception_index == -1) {
|
||||
cpu->exception_index = EXCP_INTERRUPT;
|
||||
}
|
||||
@@ -664,7 +624,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
}
|
||||
|
||||
*last_tb = NULL;
|
||||
insns_left = qatomic_read(&cpu_neg(cpu)->icount_decr.u32);
|
||||
insns_left = atomic_read(&cpu_neg(cpu)->icount_decr.u32);
|
||||
if (insns_left < 0) {
|
||||
/* Something asked us to stop executing chained TBs; just
|
||||
* continue round the main loop. Whatever requested the exit
|
||||
@@ -677,10 +637,10 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
}
|
||||
|
||||
/* Instruction counter expired. */
|
||||
assert(icount_enabled());
|
||||
assert(use_icount);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* Ensure global icount has gone forward */
|
||||
icount_update(cpu);
|
||||
cpu_update_icount(cpu);
|
||||
/* Refill decrementer and continue execution. */
|
||||
insns_left = MIN(0xffff, cpu->icount_budget);
|
||||
cpu_neg(cpu)->icount_decr.u16.low = insns_left;
|
||||
@@ -780,26 +740,3 @@ int cpu_exec(CPUState *cpu)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
void dump_drift_info(void)
|
||||
{
|
||||
if (!icount_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_printf("Host - Guest clock %"PRIi64" ms\n",
|
||||
(cpu_get_clock() - icount_get()) / SCALE_MS);
|
||||
if (icount_align_option) {
|
||||
qemu_printf("Max guest delay %"PRIi64" ms\n",
|
||||
-max_delay / SCALE_MS);
|
||||
qemu_printf("Max guest advance %"PRIi64" ms\n",
|
||||
max_advance / SCALE_MS);
|
||||
} else {
|
||||
qemu_printf("Max guest delay NA\n");
|
||||
qemu_printf("Max guest advance NA\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
+335
-1053
File diff suppressed because it is too large.
Load diff
@@ -1,15 +0,0 @@
|
||||
tcg_ss = ss.source_set()
|
||||
tcg_ss.add(files(
|
||||
'cpu-exec-common.c',
|
||||
'cpu-exec.c',
|
||||
'tcg-runtime-gvec.c',
|
||||
'tcg-runtime.c',
|
||||
'translate-all.c',
|
||||
'translator.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_PLUGIN', if_true: [files('plugin-gen.c'), libdl])
|
||||
specific_ss.add_all(when: 'CONFIG_TCG', if_true: tcg_ss)
|
||||
|
||||
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: files('tcg-all.c', 'cputlb.c', 'tcg-cpus.c'))
|
||||
+29
-143
@@ -24,175 +24,61 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/accel.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qapi/qapi-builtin-visit.h"
|
||||
#include "tcg-cpus.h"
|
||||
#include "qom/object.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
struct TCGState {
|
||||
AccelState parent_obj;
|
||||
unsigned long tcg_tb_size;
|
||||
|
||||
bool mttcg_enabled;
|
||||
unsigned long tb_size;
|
||||
};
|
||||
typedef struct TCGState TCGState;
|
||||
|
||||
#define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg")
|
||||
|
||||
DECLARE_INSTANCE_CHECKER(TCGState, TCG_STATE,
|
||||
TYPE_TCG_ACCEL)
|
||||
|
||||
/*
|
||||
* We default to false if we know other options have been enabled
|
||||
* which are currently incompatible with MTTCG. Otherwise when each
|
||||
* guest (target) has been updated to support:
|
||||
* - atomic instructions
|
||||
* - memory ordering primitives (barriers)
|
||||
* they can set the appropriate CONFIG flags in ${target}-softmmu.mak
|
||||
*
|
||||
* Once a guest architecture has been converted to the new primitives
|
||||
* there are two remaining limitations to check.
|
||||
*
|
||||
* - The guest can't be oversized (e.g. 64 bit guest on 32 bit host)
|
||||
* - The host must have a stronger memory order than the guest
|
||||
*
|
||||
* It may be possible in future to support strong guests on weak hosts
|
||||
* but that will require tagging all load/stores in a guest with their
|
||||
* implicit memory order requirements which would likely slow things
|
||||
* down a lot.
|
||||
*/
|
||||
|
||||
static bool check_tcg_memory_orders_compatible(void)
|
||||
/* mask must never be zero, except for A20 change call */
|
||||
static void tcg_handle_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
#if defined(TCG_GUEST_DEFAULT_MO) && defined(TCG_TARGET_DEFAULT_MO)
|
||||
return (TCG_GUEST_DEFAULT_MO & ~TCG_TARGET_DEFAULT_MO) == 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
int old_mask;
|
||||
g_assert(qemu_mutex_iothread_locked());
|
||||
|
||||
static bool default_mttcg_enabled(void)
|
||||
{
|
||||
if (icount_enabled() || TCG_OVERSIZED_GUEST) {
|
||||
return false;
|
||||
old_mask = cpu->interrupt_request;
|
||||
cpu->interrupt_request |= mask;
|
||||
|
||||
/*
|
||||
* If called from iothread context, wake the target cpu in
|
||||
* case its halted.
|
||||
*/
|
||||
if (!qemu_cpu_is_self(cpu)) {
|
||||
qemu_cpu_kick(cpu);
|
||||
} else {
|
||||
#ifdef TARGET_SUPPORTS_MTTCG
|
||||
return check_tcg_memory_orders_compatible();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
atomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
|
||||
if (use_icount &&
|
||||
!cpu->can_do_io
|
||||
&& (mask & ~old_mask) != 0) {
|
||||
cpu_abort(cpu, "Raised interrupt while not in I/O function");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tcg_accel_instance_init(Object *obj)
|
||||
{
|
||||
TCGState *s = TCG_STATE(obj);
|
||||
|
||||
s->mttcg_enabled = default_mttcg_enabled();
|
||||
}
|
||||
|
||||
bool mttcg_enabled;
|
||||
|
||||
static int tcg_init(MachineState *ms)
|
||||
{
|
||||
TCGState *s = TCG_STATE(current_accel());
|
||||
|
||||
tcg_exec_init(s->tb_size * 1024 * 1024);
|
||||
mttcg_enabled = s->mttcg_enabled;
|
||||
cpus_register_accel(&tcg_cpus);
|
||||
|
||||
tcg_exec_init(tcg_tb_size * 1024 * 1024);
|
||||
cpu_interrupt_handler = tcg_handle_interrupt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *tcg_get_thread(Object *obj, Error **errp)
|
||||
{
|
||||
TCGState *s = TCG_STATE(obj);
|
||||
|
||||
return g_strdup(s->mttcg_enabled ? "multi" : "single");
|
||||
}
|
||||
|
||||
static void tcg_set_thread(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
TCGState *s = TCG_STATE(obj);
|
||||
|
||||
if (strcmp(value, "multi") == 0) {
|
||||
if (TCG_OVERSIZED_GUEST) {
|
||||
error_setg(errp, "No MTTCG when guest word size > hosts");
|
||||
} else if (icount_enabled()) {
|
||||
error_setg(errp, "No MTTCG when icount is enabled");
|
||||
} else {
|
||||
#ifndef TARGET_SUPPORTS_MTTCG
|
||||
warn_report("Guest not yet converted to MTTCG - "
|
||||
"you may get unexpected results");
|
||||
#endif
|
||||
if (!check_tcg_memory_orders_compatible()) {
|
||||
warn_report("Guest expects a stronger memory ordering "
|
||||
"than the host provides");
|
||||
error_printf("This may cause strange/hard to debug errors\n");
|
||||
}
|
||||
s->mttcg_enabled = true;
|
||||
}
|
||||
} else if (strcmp(value, "single") == 0) {
|
||||
s->mttcg_enabled = false;
|
||||
} else {
|
||||
error_setg(errp, "Invalid 'thread' setting %s", value);
|
||||
}
|
||||
}
|
||||
|
||||
static void tcg_get_tb_size(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
TCGState *s = TCG_STATE(obj);
|
||||
uint32_t value = s->tb_size;
|
||||
|
||||
visit_type_uint32(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void tcg_set_tb_size(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
TCGState *s = TCG_STATE(obj);
|
||||
uint32_t value;
|
||||
|
||||
if (!visit_type_uint32(v, name, &value, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
s->tb_size = value;
|
||||
}
|
||||
|
||||
static void tcg_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(oc);
|
||||
ac->name = "tcg";
|
||||
ac->init_machine = tcg_init;
|
||||
ac->allowed = &tcg_allowed;
|
||||
|
||||
object_class_property_add_str(oc, "thread",
|
||||
tcg_get_thread,
|
||||
tcg_set_thread);
|
||||
|
||||
object_class_property_add(oc, "tb-size", "int",
|
||||
tcg_get_tb_size, tcg_set_tb_size,
|
||||
NULL, NULL);
|
||||
object_class_property_set_description(oc, "tb-size",
|
||||
"TCG translation block cache size");
|
||||
|
||||
}
|
||||
|
||||
#define TYPE_TCG_ACCEL ACCEL_CLASS_NAME("tcg")
|
||||
|
||||
static const TypeInfo tcg_accel_type = {
|
||||
.name = TYPE_TCG_ACCEL,
|
||||
.parent = TYPE_ACCEL,
|
||||
.instance_init = tcg_accel_instance_init,
|
||||
.class_init = tcg_accel_class_init,
|
||||
.instance_size = sizeof(TCGState),
|
||||
};
|
||||
|
||||
static void register_accel_types(void)
|
||||
|
||||
@@ -1,570 +0,0 @@
|
||||
/*
|
||||
* QEMU System Emulator
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2014 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
#include "tcg-cpus.h"
|
||||
|
||||
/* Kick all RR vCPUs */
|
||||
static void qemu_cpu_kick_rr_cpus(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
cpu_exit(cpu);
|
||||
};
|
||||
}
|
||||
|
||||
static void tcg_kick_vcpu_thread(CPUState *cpu)
|
||||
{
|
||||
if (qemu_tcg_mttcg_enabled()) {
|
||||
cpu_exit(cpu);
|
||||
} else {
|
||||
qemu_cpu_kick_rr_cpus();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TCG vCPU kick timer
|
||||
*
|
||||
* The kick timer is responsible for moving single threaded vCPU
|
||||
* emulation on to the next vCPU. If more than one vCPU is running a
|
||||
* timer event with force a cpu->exit so the next vCPU can get
|
||||
* scheduled.
|
||||
*
|
||||
* The timer is removed if all vCPUs are idle and restarted again once
|
||||
* idleness is complete.
|
||||
*/
|
||||
|
||||
static QEMUTimer *tcg_kick_vcpu_timer;
|
||||
static CPUState *tcg_current_rr_cpu;
|
||||
|
||||
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
|
||||
|
||||
static inline int64_t qemu_tcg_next_kick(void)
|
||||
{
|
||||
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
|
||||
}
|
||||
|
||||
/* Kick the currently round-robin scheduled vCPU to next */
|
||||
static void qemu_cpu_kick_rr_next_cpu(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
do {
|
||||
cpu = qatomic_mb_read(&tcg_current_rr_cpu);
|
||||
if (cpu) {
|
||||
cpu_exit(cpu);
|
||||
}
|
||||
} while (cpu != qatomic_mb_read(&tcg_current_rr_cpu));
|
||||
}
|
||||
|
||||
static void kick_tcg_thread(void *opaque)
|
||||
{
|
||||
timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
|
||||
qemu_cpu_kick_rr_next_cpu();
|
||||
}
|
||||
|
||||
static void start_tcg_kick_timer(void)
|
||||
{
|
||||
assert(!mttcg_enabled);
|
||||
if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) {
|
||||
tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||
kick_tcg_thread, NULL);
|
||||
}
|
||||
if (tcg_kick_vcpu_timer && !timer_pending(tcg_kick_vcpu_timer)) {
|
||||
timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick());
|
||||
}
|
||||
}
|
||||
|
||||
static void stop_tcg_kick_timer(void)
|
||||
{
|
||||
assert(!mttcg_enabled);
|
||||
if (tcg_kick_vcpu_timer && timer_pending(tcg_kick_vcpu_timer)) {
|
||||
timer_del(tcg_kick_vcpu_timer);
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_tcg_destroy_vcpu(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
static void qemu_tcg_rr_wait_io_event(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
while (all_cpu_threads_idle()) {
|
||||
stop_tcg_kick_timer();
|
||||
qemu_cond_wait_iothread(first_cpu->halt_cond);
|
||||
}
|
||||
|
||||
start_tcg_kick_timer();
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
qemu_wait_io_event_common(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t tcg_get_icount_limit(void)
|
||||
{
|
||||
int64_t deadline;
|
||||
|
||||
if (replay_mode != REPLAY_MODE_PLAY) {
|
||||
/*
|
||||
* Include all the timers, because they may need an attention.
|
||||
* Too long CPU execution may create unnecessary delay in UI.
|
||||
*/
|
||||
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
|
||||
QEMU_TIMER_ATTR_ALL);
|
||||
/* Check realtime timers, because they help with input processing */
|
||||
deadline = qemu_soonest_timeout(deadline,
|
||||
qemu_clock_deadline_ns_all(QEMU_CLOCK_REALTIME,
|
||||
QEMU_TIMER_ATTR_ALL));
|
||||
|
||||
/*
|
||||
* Maintain prior (possibly buggy) behaviour where if no deadline
|
||||
* was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than
|
||||
* INT32_MAX nanoseconds ahead, we still use INT32_MAX
|
||||
* nanoseconds.
|
||||
*/
|
||||
if ((deadline < 0) || (deadline > INT32_MAX)) {
|
||||
deadline = INT32_MAX;
|
||||
}
|
||||
|
||||
return icount_round(deadline);
|
||||
} else {
|
||||
return replay_get_instructions();
|
||||
}
|
||||
}
|
||||
|
||||
static void notify_aio_contexts(void)
|
||||
{
|
||||
/* Wake up other AioContexts. */
|
||||
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
|
||||
qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
|
||||
}
|
||||
|
||||
static void handle_icount_deadline(void)
|
||||
{
|
||||
assert(qemu_in_vcpu_thread());
|
||||
if (icount_enabled()) {
|
||||
int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL,
|
||||
QEMU_TIMER_ATTR_ALL);
|
||||
|
||||
if (deadline == 0) {
|
||||
notify_aio_contexts();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void prepare_icount_for_run(CPUState *cpu)
|
||||
{
|
||||
if (icount_enabled()) {
|
||||
int insns_left;
|
||||
|
||||
/*
|
||||
* These should always be cleared by process_icount_data after
|
||||
* each vCPU execution. However u16.high can be raised
|
||||
* asynchronously by cpu_exit/cpu_interrupt/tcg_handle_interrupt
|
||||
*/
|
||||
g_assert(cpu_neg(cpu)->icount_decr.u16.low == 0);
|
||||
g_assert(cpu->icount_extra == 0);
|
||||
|
||||
cpu->icount_budget = tcg_get_icount_limit();
|
||||
insns_left = MIN(0xffff, cpu->icount_budget);
|
||||
cpu_neg(cpu)->icount_decr.u16.low = insns_left;
|
||||
cpu->icount_extra = cpu->icount_budget - insns_left;
|
||||
|
||||
replay_mutex_lock();
|
||||
|
||||
if (cpu->icount_budget == 0 && replay_has_checkpoint()) {
|
||||
notify_aio_contexts();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void process_icount_data(CPUState *cpu)
|
||||
{
|
||||
if (icount_enabled()) {
|
||||
/* Account for executed instructions */
|
||||
icount_update(cpu);
|
||||
|
||||
/* Reset the counters */
|
||||
cpu_neg(cpu)->icount_decr.u16.low = 0;
|
||||
cpu->icount_extra = 0;
|
||||
cpu->icount_budget = 0;
|
||||
|
||||
replay_account_executed_instructions();
|
||||
|
||||
replay_mutex_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
static int tcg_cpu_exec(CPUState *cpu)
|
||||
{
|
||||
int ret;
|
||||
#ifdef CONFIG_PROFILER
|
||||
int64_t ti;
|
||||
#endif
|
||||
|
||||
assert(tcg_enabled());
|
||||
#ifdef CONFIG_PROFILER
|
||||
ti = profile_getclock();
|
||||
#endif
|
||||
cpu_exec_start(cpu);
|
||||
ret = cpu_exec(cpu);
|
||||
cpu_exec_end(cpu);
|
||||
#ifdef CONFIG_PROFILER
|
||||
qatomic_set(&tcg_ctx->prof.cpu_exec_time,
|
||||
tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy any remaining vCPUs which have been unplugged and have
|
||||
* finished running
|
||||
*/
|
||||
static void deal_with_unplugged_cpus(void)
|
||||
{
|
||||
CPUState *cpu;
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
if (cpu->unplug && !cpu_can_run(cpu)) {
|
||||
qemu_tcg_destroy_vcpu(cpu);
|
||||
cpu_thread_signal_destroyed(cpu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Single-threaded TCG
|
||||
*
|
||||
* In the single-threaded case each vCPU is simulated in turn. If
|
||||
* there is more than a single vCPU we create a simple timer to kick
|
||||
* the vCPU and ensure we don't get stuck in a tight loop in one vCPU.
|
||||
* This is done explicitly rather than relying on side-effects
|
||||
* elsewhere.
|
||||
*/
|
||||
|
||||
static void *tcg_rr_cpu_thread_fn(void *arg)
|
||||
{
|
||||
CPUState *cpu = arg;
|
||||
|
||||
assert(tcg_enabled());
|
||||
rcu_register_thread();
|
||||
tcg_register_thread();
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
qemu_thread_get_self(cpu->thread);
|
||||
|
||||
cpu->thread_id = qemu_get_thread_id();
|
||||
cpu->can_do_io = 1;
|
||||
cpu_thread_signal_created(cpu);
|
||||
qemu_guest_random_seed_thread_part2(cpu->random_seed);
|
||||
|
||||
/* wait for initial kick-off after machine start */
|
||||
while (first_cpu->stopped) {
|
||||
qemu_cond_wait_iothread(first_cpu->halt_cond);
|
||||
|
||||
/* process any pending work */
|
||||
CPU_FOREACH(cpu) {
|
||||
current_cpu = cpu;
|
||||
qemu_wait_io_event_common(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
start_tcg_kick_timer();
|
||||
|
||||
cpu = first_cpu;
|
||||
|
||||
/* process any pending work */
|
||||
cpu->exit_request = 1;
|
||||
|
||||
while (1) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
replay_mutex_lock();
|
||||
qemu_mutex_lock_iothread();
|
||||
/* Account partial waits to QEMU_CLOCK_VIRTUAL. */
|
||||
icount_account_warp_timer();
|
||||
|
||||
/*
|
||||
* Run the timers here. This is much more efficient than
|
||||
* waking up the I/O thread and waiting for completion.
|
||||
*/
|
||||
handle_icount_deadline();
|
||||
|
||||
replay_mutex_unlock();
|
||||
|
||||
if (!cpu) {
|
||||
cpu = first_cpu;
|
||||
}
|
||||
|
||||
while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) {
|
||||
|
||||
qatomic_mb_set(&tcg_current_rr_cpu, cpu);
|
||||
current_cpu = cpu;
|
||||
|
||||
qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
|
||||
(cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);
|
||||
|
||||
if (cpu_can_run(cpu)) {
|
||||
int r;
|
||||
|
||||
qemu_mutex_unlock_iothread();
|
||||
prepare_icount_for_run(cpu);
|
||||
|
||||
r = tcg_cpu_exec(cpu);
|
||||
|
||||
process_icount_data(cpu);
|
||||
qemu_mutex_lock_iothread();
|
||||
|
||||
if (r == EXCP_DEBUG) {
|
||||
cpu_handle_guest_debug(cpu);
|
||||
break;
|
||||
} else if (r == EXCP_ATOMIC) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
cpu_exec_step_atomic(cpu);
|
||||
qemu_mutex_lock_iothread();
|
||||
break;
|
||||
}
|
||||
} else if (cpu->stop) {
|
||||
if (cpu->unplug) {
|
||||
cpu = CPU_NEXT(cpu);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cpu = CPU_NEXT(cpu);
|
||||
} /* while (cpu && !cpu->exit_request).. */
|
||||
|
||||
/* Does not need qatomic_mb_set because a spurious wakeup is okay. */
|
||||
qatomic_set(&tcg_current_rr_cpu, NULL);
|
||||
|
||||
if (cpu && cpu->exit_request) {
|
||||
qatomic_mb_set(&cpu->exit_request, 0);
|
||||
}
|
||||
|
||||
if (icount_enabled() && all_cpu_threads_idle()) {
|
||||
/*
|
||||
* When all cpus are sleeping (e.g in WFI), to avoid a deadlock
|
||||
* in the main_loop, wake it up in order to start the warp timer.
|
||||
*/
|
||||
qemu_notify_event();
|
||||
}
|
||||
|
||||
qemu_tcg_rr_wait_io_event();
|
||||
deal_with_unplugged_cpus();
|
||||
}
|
||||
|
||||
rcu_unregister_thread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Multi-threaded TCG
|
||||
*
|
||||
* In the multi-threaded case each vCPU has its own thread. The TLS
|
||||
* variable current_cpu can be used deep in the code to find the
|
||||
* current CPUState for a given thread.
|
||||
*/
|
||||
|
||||
static void *tcg_cpu_thread_fn(void *arg)
|
||||
{
|
||||
CPUState *cpu = arg;
|
||||
|
||||
assert(tcg_enabled());
|
||||
g_assert(!icount_enabled());
|
||||
|
||||
rcu_register_thread();
|
||||
tcg_register_thread();
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
qemu_thread_get_self(cpu->thread);
|
||||
|
||||
cpu->thread_id = qemu_get_thread_id();
|
||||
cpu->can_do_io = 1;
|
||||
current_cpu = cpu;
|
||||
cpu_thread_signal_created(cpu);
|
||||
qemu_guest_random_seed_thread_part2(cpu->random_seed);
|
||||
|
||||
/* process any pending work */
|
||||
cpu->exit_request = 1;
|
||||
|
||||
do {
|
||||
if (cpu_can_run(cpu)) {
|
||||
int r;
|
||||
qemu_mutex_unlock_iothread();
|
||||
r = tcg_cpu_exec(cpu);
|
||||
qemu_mutex_lock_iothread();
|
||||
switch (r) {
|
||||
case EXCP_DEBUG:
|
||||
cpu_handle_guest_debug(cpu);
|
||||
break;
|
||||
case EXCP_HALTED:
|
||||
/*
|
||||
* during start-up the vCPU is reset and the thread is
|
||||
* kicked several times. If we don't ensure we go back
|
||||
* to sleep in the halted state we won't cleanly
|
||||
* start-up when the vCPU is enabled.
|
||||
*
|
||||
* cpu->halted should ensure we sleep in wait_io_event
|
||||
*/
|
||||
g_assert(cpu->halted);
|
||||
break;
|
||||
case EXCP_ATOMIC:
|
||||
qemu_mutex_unlock_iothread();
|
||||
cpu_exec_step_atomic(cpu);
|
||||
qemu_mutex_lock_iothread();
|
||||
default:
|
||||
/* Ignore everything else? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qatomic_mb_set(&cpu->exit_request, 0);
|
||||
qemu_wait_io_event(cpu);
|
||||
} while (!cpu->unplug || cpu_can_run(cpu));
|
||||
|
||||
qemu_tcg_destroy_vcpu(cpu);
|
||||
cpu_thread_signal_destroyed(cpu);
|
||||
qemu_mutex_unlock_iothread();
|
||||
rcu_unregister_thread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void tcg_start_vcpu_thread(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
static QemuCond *single_tcg_halt_cond;
|
||||
static QemuThread *single_tcg_cpu_thread;
|
||||
static int tcg_region_inited;
|
||||
|
||||
assert(tcg_enabled());
|
||||
/*
|
||||
* Initialize TCG regions--once. Now is a good time, because:
|
||||
* (1) TCG's init context, prologue and target globals have been set up.
|
||||
* (2) qemu_tcg_mttcg_enabled() works now (TCG init code runs before the
|
||||
* -accel flag is processed, so the check doesn't work then).
|
||||
*/
|
||||
if (!tcg_region_inited) {
|
||||
tcg_region_inited = 1;
|
||||
tcg_region_init();
|
||||
parallel_cpus = qemu_tcg_mttcg_enabled() && current_machine->smp.max_cpus > 1;
|
||||
}
|
||||
|
||||
if (qemu_tcg_mttcg_enabled() || !single_tcg_cpu_thread) {
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
|
||||
if (qemu_tcg_mttcg_enabled()) {
|
||||
/* create a thread per vCPU with TCG (MTTCG) */
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
|
||||
cpu->cpu_index);
|
||||
|
||||
qemu_thread_create(cpu->thread, thread_name, tcg_cpu_thread_fn,
|
||||
cpu, QEMU_THREAD_JOINABLE);
|
||||
|
||||
} else {
|
||||
/* share a single thread for all cpus with TCG */
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG");
|
||||
qemu_thread_create(cpu->thread, thread_name,
|
||||
tcg_rr_cpu_thread_fn,
|
||||
cpu, QEMU_THREAD_JOINABLE);
|
||||
|
||||
single_tcg_halt_cond = cpu->halt_cond;
|
||||
single_tcg_cpu_thread = cpu->thread;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
cpu->hThread = qemu_thread_get_handle(cpu->thread);
|
||||
#endif
|
||||
} else {
|
||||
/* For non-MTTCG cases we share the thread */
|
||||
cpu->thread = single_tcg_cpu_thread;
|
||||
cpu->halt_cond = single_tcg_halt_cond;
|
||||
cpu->thread_id = first_cpu->thread_id;
|
||||
cpu->can_do_io = 1;
|
||||
cpu->created = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t tcg_get_virtual_clock(void)
|
||||
{
|
||||
if (icount_enabled()) {
|
||||
return icount_get();
|
||||
}
|
||||
return cpu_get_clock();
|
||||
}
|
||||
|
||||
static int64_t tcg_get_elapsed_ticks(void)
|
||||
{
|
||||
if (icount_enabled()) {
|
||||
return icount_get();
|
||||
}
|
||||
return cpu_get_ticks();
|
||||
}
|
||||
|
||||
/* mask must never be zero, except for A20 change call */
|
||||
static void tcg_handle_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
int old_mask;
|
||||
g_assert(qemu_mutex_iothread_locked());
|
||||
|
||||
old_mask = cpu->interrupt_request;
|
||||
cpu->interrupt_request |= mask;
|
||||
|
||||
/*
|
||||
* If called from iothread context, wake the target cpu in
|
||||
* case its halted.
|
||||
*/
|
||||
if (!qemu_cpu_is_self(cpu)) {
|
||||
qemu_cpu_kick(cpu);
|
||||
} else {
|
||||
qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
|
||||
if (icount_enabled() &&
|
||||
!cpu->can_do_io
|
||||
&& (mask & ~old_mask) != 0) {
|
||||
cpu_abort(cpu, "Raised interrupt while not in I/O function");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CpusAccel tcg_cpus = {
|
||||
.create_vcpu_thread = tcg_start_vcpu_thread,
|
||||
.kick_vcpu_thread = tcg_kick_vcpu_thread,
|
||||
|
||||
.handle_interrupt = tcg_handle_interrupt,
|
||||
|
||||
.get_virtual_clock = tcg_get_virtual_clock,
|
||||
.get_elapsed_ticks = tcg_get_elapsed_ticks,
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Accelerator CPUS Interface
|
||||
*
|
||||
* Copyright 2020 SUSE LLC
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TCG_CPUS_H
|
||||
#define TCG_CPUS_H
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
extern const CpusAccel tcg_cpus;
|
||||
|
||||
#endif /* TCG_CPUS_H */
|
||||
+182
-260
@@ -21,9 +21,51 @@
|
||||
#include "qemu/host-utils.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "tcg/tcg-gvec-desc.h"
|
||||
#include "tcg-gvec-desc.h"
|
||||
|
||||
|
||||
/* Virtually all hosts support 16-byte vectors. Those that don't can emulate
|
||||
* them via GCC's generic vector extension. This turns out to be simpler and
|
||||
* more reliable than getting the compiler to autovectorize.
|
||||
*
|
||||
* In tcg-op-gvec.c, we asserted that both the size and alignment of the data
|
||||
* are multiples of 16.
|
||||
*
|
||||
* When the compiler does not support all of the operations we require, the
|
||||
* loops are written so that we can always fall back on the base types.
|
||||
*/
|
||||
#ifdef CONFIG_VECTOR16
|
||||
typedef uint8_t vec8 __attribute__((vector_size(16)));
|
||||
typedef uint16_t vec16 __attribute__((vector_size(16)));
|
||||
typedef uint32_t vec32 __attribute__((vector_size(16)));
|
||||
typedef uint64_t vec64 __attribute__((vector_size(16)));
|
||||
|
||||
typedef int8_t svec8 __attribute__((vector_size(16)));
|
||||
typedef int16_t svec16 __attribute__((vector_size(16)));
|
||||
typedef int32_t svec32 __attribute__((vector_size(16)));
|
||||
typedef int64_t svec64 __attribute__((vector_size(16)));
|
||||
|
||||
#define DUP16(X) { X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X }
|
||||
#define DUP8(X) { X, X, X, X, X, X, X, X }
|
||||
#define DUP4(X) { X, X, X, X }
|
||||
#define DUP2(X) { X, X }
|
||||
#else
|
||||
typedef uint8_t vec8;
|
||||
typedef uint16_t vec16;
|
||||
typedef uint32_t vec32;
|
||||
typedef uint64_t vec64;
|
||||
|
||||
typedef int8_t svec8;
|
||||
typedef int16_t svec16;
|
||||
typedef int32_t svec32;
|
||||
typedef int64_t svec64;
|
||||
|
||||
#define DUP16(X) X
|
||||
#define DUP8(X) X
|
||||
#define DUP4(X) X
|
||||
#define DUP2(X) X
|
||||
#endif /* CONFIG_VECTOR16 */
|
||||
|
||||
static inline void clear_high(void *d, intptr_t oprsz, uint32_t desc)
|
||||
{
|
||||
intptr_t maxsz = simd_maxsz(desc);
|
||||
@@ -41,8 +83,8 @@ void HELPER(gvec_add8)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) + *(uint8_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(vec8 *)(d + i) = *(vec8 *)(a + i) + *(vec8 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -52,8 +94,8 @@ void HELPER(gvec_add16)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) + *(uint16_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(vec16 *)(d + i) = *(vec16 *)(a + i) + *(vec16 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -63,8 +105,8 @@ void HELPER(gvec_add32)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) + *(uint32_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(vec32 *)(d + i) = *(vec32 *)(a + i) + *(vec32 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -74,8 +116,8 @@ void HELPER(gvec_add64)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) + *(uint64_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) + *(vec64 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -83,10 +125,11 @@ void HELPER(gvec_add64)(void *d, void *a, void *b, uint32_t desc)
|
||||
void HELPER(gvec_adds8)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec8 vecb = (vec8)DUP16(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) + (uint8_t)b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(vec8 *)(d + i) = *(vec8 *)(a + i) + vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -94,10 +137,11 @@ void HELPER(gvec_adds8)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_adds16)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec16 vecb = (vec16)DUP8(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) + (uint16_t)b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(vec16 *)(d + i) = *(vec16 *)(a + i) + vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -105,10 +149,11 @@ void HELPER(gvec_adds16)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_adds32)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec32 vecb = (vec32)DUP4(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) + (uint32_t)b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(vec32 *)(d + i) = *(vec32 *)(a + i) + vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -116,10 +161,11 @@ void HELPER(gvec_adds32)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_adds64)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec64 vecb = (vec64)DUP2(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) + b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) + vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -129,8 +175,8 @@ void HELPER(gvec_sub8)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) - *(uint8_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(vec8 *)(d + i) = *(vec8 *)(a + i) - *(vec8 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -140,8 +186,8 @@ void HELPER(gvec_sub16)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) - *(uint16_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(vec16 *)(d + i) = *(vec16 *)(a + i) - *(vec16 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -151,8 +197,8 @@ void HELPER(gvec_sub32)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) - *(uint32_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(vec32 *)(d + i) = *(vec32 *)(a + i) - *(vec32 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -162,8 +208,8 @@ void HELPER(gvec_sub64)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) - *(uint64_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) - *(vec64 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -171,10 +217,11 @@ void HELPER(gvec_sub64)(void *d, void *a, void *b, uint32_t desc)
|
||||
void HELPER(gvec_subs8)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec8 vecb = (vec8)DUP16(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) - (uint8_t)b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(vec8 *)(d + i) = *(vec8 *)(a + i) - vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -182,10 +229,11 @@ void HELPER(gvec_subs8)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_subs16)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec16 vecb = (vec16)DUP8(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) - (uint16_t)b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(vec16 *)(d + i) = *(vec16 *)(a + i) - vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -193,10 +241,11 @@ void HELPER(gvec_subs16)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_subs32)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec32 vecb = (vec32)DUP4(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) - (uint32_t)b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(vec32 *)(d + i) = *(vec32 *)(a + i) - vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -204,10 +253,11 @@ void HELPER(gvec_subs32)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_subs64)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec64 vecb = (vec64)DUP2(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) - b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) - vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -217,8 +267,8 @@ void HELPER(gvec_mul8)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) * *(uint8_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(vec8 *)(d + i) = *(vec8 *)(a + i) * *(vec8 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -228,8 +278,8 @@ void HELPER(gvec_mul16)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) * *(uint16_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(vec16 *)(d + i) = *(vec16 *)(a + i) * *(vec16 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -239,8 +289,8 @@ void HELPER(gvec_mul32)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) * *(uint32_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(vec32 *)(d + i) = *(vec32 *)(a + i) * *(vec32 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -250,8 +300,8 @@ void HELPER(gvec_mul64)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) * *(uint64_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) * *(vec64 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -259,10 +309,11 @@ void HELPER(gvec_mul64)(void *d, void *a, void *b, uint32_t desc)
|
||||
void HELPER(gvec_muls8)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec8 vecb = (vec8)DUP16(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) * (uint8_t)b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(vec8 *)(d + i) = *(vec8 *)(a + i) * vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -270,10 +321,11 @@ void HELPER(gvec_muls8)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_muls16)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec16 vecb = (vec16)DUP8(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) * (uint16_t)b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(vec16 *)(d + i) = *(vec16 *)(a + i) * vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -281,10 +333,11 @@ void HELPER(gvec_muls16)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_muls32)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec32 vecb = (vec32)DUP4(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) * (uint32_t)b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(vec32 *)(d + i) = *(vec32 *)(a + i) * vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -292,10 +345,11 @@ void HELPER(gvec_muls32)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_muls64)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec64 vecb = (vec64)DUP2(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) * b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) * vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -305,8 +359,8 @@ void HELPER(gvec_neg8)(void *d, void *a, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = -*(uint8_t *)(a + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(vec8 *)(d + i) = -*(vec8 *)(a + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -316,8 +370,8 @@ void HELPER(gvec_neg16)(void *d, void *a, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = -*(uint16_t *)(a + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(vec16 *)(d + i) = -*(vec16 *)(a + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -327,8 +381,8 @@ void HELPER(gvec_neg32)(void *d, void *a, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = -*(uint32_t *)(a + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(vec32 *)(d + i) = -*(vec32 *)(a + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -338,8 +392,8 @@ void HELPER(gvec_neg64)(void *d, void *a, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = -*(uint64_t *)(a + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = -*(vec64 *)(a + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -445,8 +499,8 @@ void HELPER(gvec_not)(void *d, void *a, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = ~*(uint64_t *)(a + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = ~*(vec64 *)(a + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -456,8 +510,8 @@ void HELPER(gvec_and)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) & *(uint64_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) & *(vec64 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -467,8 +521,8 @@ void HELPER(gvec_or)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) | *(uint64_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) | *(vec64 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -478,8 +532,8 @@ void HELPER(gvec_xor)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) ^ *(uint64_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) ^ *(vec64 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -489,8 +543,8 @@ void HELPER(gvec_andc)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) &~ *(uint64_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) &~ *(vec64 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -500,8 +554,8 @@ void HELPER(gvec_orc)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) |~ *(uint64_t *)(b + i);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) |~ *(vec64 *)(b + i);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -511,8 +565,8 @@ void HELPER(gvec_nand)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = ~(*(uint64_t *)(a + i) & *(uint64_t *)(b + i));
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = ~(*(vec64 *)(a + i) & *(vec64 *)(b + i));
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -522,8 +576,8 @@ void HELPER(gvec_nor)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = ~(*(uint64_t *)(a + i) | *(uint64_t *)(b + i));
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = ~(*(vec64 *)(a + i) | *(vec64 *)(b + i));
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -533,8 +587,8 @@ void HELPER(gvec_eqv)(void *d, void *a, void *b, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = ~(*(uint64_t *)(a + i) ^ *(uint64_t *)(b + i));
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = ~(*(vec64 *)(a + i) ^ *(vec64 *)(b + i));
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -542,10 +596,11 @@ void HELPER(gvec_eqv)(void *d, void *a, void *b, uint32_t desc)
|
||||
void HELPER(gvec_ands)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec64 vecb = (vec64)DUP2(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) & b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) & vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -553,10 +608,11 @@ void HELPER(gvec_ands)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_xors)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec64 vecb = (vec64)DUP2(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) ^ b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) ^ vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -564,10 +620,11 @@ void HELPER(gvec_xors)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
void HELPER(gvec_ors)(void *d, void *a, uint64_t b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
vec64 vecb = (vec64)DUP2(b);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) | b;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) | vecb;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -578,8 +635,8 @@ void HELPER(gvec_shl8i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) << shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(vec8 *)(d + i) = *(vec8 *)(a + i) << shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -590,8 +647,8 @@ void HELPER(gvec_shl16i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) << shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(vec16 *)(d + i) = *(vec16 *)(a + i) << shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -602,8 +659,8 @@ void HELPER(gvec_shl32i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) << shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(vec32 *)(d + i) = *(vec32 *)(a + i) << shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -614,8 +671,8 @@ void HELPER(gvec_shl64i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) << shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) << shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -626,8 +683,8 @@ void HELPER(gvec_shr8i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) >> shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(vec8 *)(d + i) = *(vec8 *)(a + i) >> shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -638,8 +695,8 @@ void HELPER(gvec_shr16i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) >> shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(vec16 *)(d + i) = *(vec16 *)(a + i) >> shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -650,8 +707,8 @@ void HELPER(gvec_shr32i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) >> shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(vec32 *)(d + i) = *(vec32 *)(a + i) >> shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -662,8 +719,8 @@ void HELPER(gvec_shr64i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) >> shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(vec64 *)(d + i) = *(vec64 *)(a + i) >> shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -674,8 +731,8 @@ void HELPER(gvec_sar8i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(int8_t *)(d + i) = *(int8_t *)(a + i) >> shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec8)) {
|
||||
*(svec8 *)(d + i) = *(svec8 *)(a + i) >> shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -686,8 +743,8 @@ void HELPER(gvec_sar16i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(int16_t *)(d + i) = *(int16_t *)(a + i) >> shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec16)) {
|
||||
*(svec16 *)(d + i) = *(svec16 *)(a + i) >> shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -698,8 +755,8 @@ void HELPER(gvec_sar32i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(int32_t *)(d + i) = *(int32_t *)(a + i) >> shift;
|
||||
for (i = 0; i < oprsz; i += sizeof(vec32)) {
|
||||
*(svec32 *)(d + i) = *(svec32 *)(a + i) >> shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -710,56 +767,8 @@ void HELPER(gvec_sar64i)(void *d, void *a, uint32_t desc)
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(int64_t *)(d + i) = *(int64_t *)(a + i) >> shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotl8i)(void *d, void *a, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
*(uint8_t *)(d + i) = rol8(*(uint8_t *)(a + i), shift);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotl16i)(void *d, void *a, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
*(uint16_t *)(d + i) = rol16(*(uint16_t *)(a + i), shift);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotl32i)(void *d, void *a, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
*(uint32_t *)(d + i) = rol32(*(uint32_t *)(a + i), shift);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotl64i)(void *d, void *a, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
int shift = simd_data(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
*(uint64_t *)(d + i) = rol64(*(uint64_t *)(a + i), shift);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
*(svec64 *)(d + i) = *(svec64 *)(a + i) >> shift;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -908,101 +917,13 @@ void HELPER(gvec_sar64v)(void *d, void *a, void *b, uint32_t desc)
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotl8v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
uint8_t sh = *(uint8_t *)(b + i) & 7;
|
||||
*(uint8_t *)(d + i) = rol8(*(uint8_t *)(a + i), sh);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotl16v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
uint8_t sh = *(uint16_t *)(b + i) & 15;
|
||||
*(uint16_t *)(d + i) = rol16(*(uint16_t *)(a + i), sh);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotl32v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
uint8_t sh = *(uint32_t *)(b + i) & 31;
|
||||
*(uint32_t *)(d + i) = rol32(*(uint32_t *)(a + i), sh);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotl64v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
uint8_t sh = *(uint64_t *)(b + i) & 63;
|
||||
*(uint64_t *)(d + i) = rol64(*(uint64_t *)(a + i), sh);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotr8v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
uint8_t sh = *(uint8_t *)(b + i) & 7;
|
||||
*(uint8_t *)(d + i) = ror8(*(uint8_t *)(a + i), sh);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotr16v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
uint8_t sh = *(uint16_t *)(b + i) & 15;
|
||||
*(uint16_t *)(d + i) = ror16(*(uint16_t *)(a + i), sh);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotr32v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
uint8_t sh = *(uint32_t *)(b + i) & 31;
|
||||
*(uint32_t *)(d + i) = ror32(*(uint32_t *)(a + i), sh);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_rotr64v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
uint8_t sh = *(uint64_t *)(b + i) & 63;
|
||||
*(uint64_t *)(d + i) = ror64(*(uint64_t *)(a + i), sh);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
/* If vectors are enabled, the compiler fills in -1 for true.
|
||||
Otherwise, we must take care of this by hand. */
|
||||
#ifdef CONFIG_VECTOR16
|
||||
# define DO_CMP0(X) X
|
||||
#else
|
||||
# define DO_CMP0(X) -(X)
|
||||
#endif
|
||||
|
||||
#define DO_CMP1(NAME, TYPE, OP) \
|
||||
void HELPER(NAME)(void *d, void *a, void *b, uint32_t desc) \
|
||||
@@ -1010,24 +931,25 @@ void HELPER(NAME)(void *d, void *a, void *b, uint32_t desc) \
|
||||
intptr_t oprsz = simd_oprsz(desc); \
|
||||
intptr_t i; \
|
||||
for (i = 0; i < oprsz; i += sizeof(TYPE)) { \
|
||||
*(TYPE *)(d + i) = -(*(TYPE *)(a + i) OP *(TYPE *)(b + i)); \
|
||||
*(TYPE *)(d + i) = DO_CMP0(*(TYPE *)(a + i) OP *(TYPE *)(b + i)); \
|
||||
} \
|
||||
clear_high(d, oprsz, desc); \
|
||||
}
|
||||
|
||||
#define DO_CMP2(SZ) \
|
||||
DO_CMP1(gvec_eq##SZ, uint##SZ##_t, ==) \
|
||||
DO_CMP1(gvec_ne##SZ, uint##SZ##_t, !=) \
|
||||
DO_CMP1(gvec_lt##SZ, int##SZ##_t, <) \
|
||||
DO_CMP1(gvec_le##SZ, int##SZ##_t, <=) \
|
||||
DO_CMP1(gvec_ltu##SZ, uint##SZ##_t, <) \
|
||||
DO_CMP1(gvec_leu##SZ, uint##SZ##_t, <=)
|
||||
DO_CMP1(gvec_eq##SZ, vec##SZ, ==) \
|
||||
DO_CMP1(gvec_ne##SZ, vec##SZ, !=) \
|
||||
DO_CMP1(gvec_lt##SZ, svec##SZ, <) \
|
||||
DO_CMP1(gvec_le##SZ, svec##SZ, <=) \
|
||||
DO_CMP1(gvec_ltu##SZ, vec##SZ, <) \
|
||||
DO_CMP1(gvec_leu##SZ, vec##SZ, <=)
|
||||
|
||||
DO_CMP2(8)
|
||||
DO_CMP2(16)
|
||||
DO_CMP2(32)
|
||||
DO_CMP2(64)
|
||||
|
||||
#undef DO_CMP0
|
||||
#undef DO_CMP1
|
||||
#undef DO_CMP2
|
||||
|
||||
@@ -1528,11 +1450,11 @@ void HELPER(gvec_bitsel)(void *d, void *a, void *b, void *c, uint32_t desc)
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
uint64_t aa = *(uint64_t *)(a + i);
|
||||
uint64_t bb = *(uint64_t *)(b + i);
|
||||
uint64_t cc = *(uint64_t *)(c + i);
|
||||
*(uint64_t *)(d + i) = (bb & aa) | (cc & ~aa);
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
vec64 aa = *(vec64 *)(a + i);
|
||||
vec64 bb = *(vec64 *)(b + i);
|
||||
vec64 cc = *(vec64 *)(c + i);
|
||||
*(vec64 *)(d + i) = (bb & aa) | (cc & ~aa);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "exec/tb-lookup.h"
|
||||
#include "disas/disas.h"
|
||||
#include "exec/log.h"
|
||||
#include "tcg/tcg.h"
|
||||
|
||||
/* 32-bit helpers */
|
||||
|
||||
|
||||
@@ -259,11 +259,6 @@ DEF_HELPER_FLAGS_3(gvec_sar16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_sar32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_sar64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_rotl8i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_rotl16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_rotl32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_rotl64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_shl8v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_shl16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_shl32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
@@ -279,16 +274,6 @@ DEF_HELPER_FLAGS_4(gvec_sar16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sar32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sar64v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_rotl8v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_rotl16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_rotl32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_rotl64v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_rotr8v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_rotr16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_rotr32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_rotr64v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_eq8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_eq16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_eq32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# See docs/devel/tracing.txt for syntax documentation.
|
||||
|
||||
# TCG related tracing
|
||||
# TCG related tracing (mostly disabled by default)
|
||||
# cpu-exec.c
|
||||
exec_tb(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
|
||||
exec_tb_nocache(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
|
||||
exec_tb_exit(void *last_tb, unsigned int flags) "tb:%p flags=0x%x"
|
||||
disable exec_tb(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
|
||||
disable exec_tb_nocache(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
|
||||
disable exec_tb_exit(void *last_tb, unsigned int flags) "tb:%p flags=0x%x"
|
||||
|
||||
# translate-all.c
|
||||
translate_block(void *tb, uintptr_t pc, uint8_t *tb_code) "tb:%p, pc:0x%"PRIxPTR", tb_code:%p"
|
||||
@@ -1 +0,0 @@
|
||||
#include "trace/trace-accel_tcg.h"
|
||||
+105
-153
@@ -18,7 +18,6 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
#define NO_CPU_IO_DEFS
|
||||
@@ -26,7 +25,7 @@
|
||||
#include "trace.h"
|
||||
#include "disas/disas.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg.h"
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
#include "qemu.h"
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
@@ -57,7 +56,6 @@
|
||||
#include "qemu/main-loop.h"
|
||||
#include "exec/log.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "sysemu/tcg.h"
|
||||
|
||||
/* #define DEBUG_TB_INVALIDATE */
|
||||
@@ -174,13 +172,8 @@ struct page_collection {
|
||||
#define TB_FOR_EACH_JMP(head_tb, tb, n) \
|
||||
TB_FOR_EACH_TAGGED((head_tb)->jmp_list_head, tb, n, jmp_list_next)
|
||||
|
||||
/*
|
||||
* In system mode we want L1_MAP to be based on ram offsets,
|
||||
* while in user mode we want it to be based on virtual addresses.
|
||||
*
|
||||
* TODO: For user mode, see the caveat re host vs guest virtual
|
||||
* address spaces near GUEST_ADDR_MAX.
|
||||
*/
|
||||
/* In system mode we want L1_MAP to be based on ram offsets,
|
||||
while in user mode we want it to be based on virtual addresses. */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#if HOST_LONG_BITS < TARGET_PHYS_ADDR_SPACE_BITS
|
||||
# define L1_MAP_ADDR_SPACE_BITS HOST_LONG_BITS
|
||||
@@ -188,7 +181,7 @@ struct page_collection {
|
||||
# define L1_MAP_ADDR_SPACE_BITS TARGET_PHYS_ADDR_SPACE_BITS
|
||||
#endif
|
||||
#else
|
||||
# define L1_MAP_ADDR_SPACE_BITS MIN(HOST_LONG_BITS, TARGET_ABI_BITS)
|
||||
# define L1_MAP_ADDR_SPACE_BITS TARGET_VIRT_ADDR_SPACE_BITS
|
||||
#endif
|
||||
|
||||
/* Size of the L2 (and L3, etc) page tables. */
|
||||
@@ -370,7 +363,7 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
|
||||
found:
|
||||
if (reset_icount && (tb_cflags(tb) & CF_USE_ICOUNT)) {
|
||||
assert(icount_enabled());
|
||||
assert(use_icount);
|
||||
/* Reset the cycle counter to the start of the block
|
||||
and shift if to the number of actually executed instructions */
|
||||
cpu_neg(cpu)->icount_decr.u16.low += num_insns - i;
|
||||
@@ -378,18 +371,13 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
restore_state_to_opc(env, tb, data);
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
qatomic_set(&prof->restore_time,
|
||||
atomic_set(&prof->restore_time,
|
||||
prof->restore_time + profile_getclock() - ti);
|
||||
qatomic_set(&prof->restore_count, prof->restore_count + 1);
|
||||
atomic_set(&prof->restore_count, prof->restore_count + 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tb_destroy(TranslationBlock *tb)
|
||||
{
|
||||
qemu_spin_destroy(&tb->jmp_lock);
|
||||
}
|
||||
|
||||
bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
@@ -419,7 +407,6 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
|
||||
/* one-shot translation, invalidate it immediately */
|
||||
tb_phys_invalidate(tb, -1);
|
||||
tcg_tb_remove(tb);
|
||||
tb_destroy(tb);
|
||||
}
|
||||
r = true;
|
||||
}
|
||||
@@ -510,7 +497,7 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
|
||||
|
||||
/* Level 2..N-1. */
|
||||
for (i = v_l2_levels; i > 0; i--) {
|
||||
void **p = qatomic_rcu_read(lp);
|
||||
void **p = atomic_rcu_read(lp);
|
||||
|
||||
if (p == NULL) {
|
||||
void *existing;
|
||||
@@ -519,7 +506,7 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
|
||||
return NULL;
|
||||
}
|
||||
p = g_new0(void *, V_L2_SIZE);
|
||||
existing = qatomic_cmpxchg(lp, NULL, p);
|
||||
existing = atomic_cmpxchg(lp, NULL, p);
|
||||
if (unlikely(existing)) {
|
||||
g_free(p);
|
||||
p = existing;
|
||||
@@ -529,7 +516,7 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
|
||||
lp = p + ((index >> (i * V_L2_BITS)) & (V_L2_SIZE - 1));
|
||||
}
|
||||
|
||||
pd = qatomic_rcu_read(lp);
|
||||
pd = atomic_rcu_read(lp);
|
||||
if (pd == NULL) {
|
||||
void *existing;
|
||||
|
||||
@@ -546,17 +533,8 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
existing = qatomic_cmpxchg(lp, NULL, pd);
|
||||
existing = atomic_cmpxchg(lp, NULL, pd);
|
||||
if (unlikely(existing)) {
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < V_L2_SIZE; i++) {
|
||||
qemu_spin_destroy(&pd[i].lock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
g_free(pd);
|
||||
pd = existing;
|
||||
}
|
||||
@@ -913,61 +891,43 @@ static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* Currently it is not recommended to allocate big chunks of data in
|
||||
user mode. It will change when a dedicated libc will be used. */
|
||||
/* ??? 64-bit hosts ought to have no problem mmaping data outside the
|
||||
region in which the guest needs to run. Revisit this. */
|
||||
#define USE_STATIC_CODE_GEN_BUFFER
|
||||
#endif
|
||||
|
||||
/* Minimum size of the code gen buffer. This number is randomly chosen,
|
||||
but not so small that we can't have a fair number of TB's live. */
|
||||
#define MIN_CODE_GEN_BUFFER_SIZE (1 * MiB)
|
||||
#define MIN_CODE_GEN_BUFFER_SIZE (1024u * 1024)
|
||||
|
||||
/* Maximum size of the code gen buffer we'd like to use. Unless otherwise
|
||||
indicated, this is constrained by the range of direct branches on the
|
||||
host cpu, as used by the TCG implementation of goto_tb. */
|
||||
#if defined(__x86_64__)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024)
|
||||
#elif defined(__sparc__)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024)
|
||||
#elif defined(__powerpc64__)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024)
|
||||
#elif defined(__powerpc__)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (32 * MiB)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (32u * 1024 * 1024)
|
||||
#elif defined(__aarch64__)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024)
|
||||
#elif defined(__s390x__)
|
||||
/* We have a +- 4GB range on the branches; leave some slop. */
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (3 * GiB)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (3ul * 1024 * 1024 * 1024)
|
||||
#elif defined(__mips__)
|
||||
/* We have a 256MB branch region, but leave room to make sure the
|
||||
main executable is also within that region. */
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (128 * MiB)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (128ul * 1024 * 1024)
|
||||
#else
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
|
||||
#endif
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
#define DEFAULT_CODE_GEN_BUFFER_SIZE_1 (32 * MiB)
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/*
|
||||
* For user mode on smaller 32 bit systems we may run into trouble
|
||||
* allocating big chunks of data in the right place. On these systems
|
||||
* we utilise a static code generation buffer directly in the binary.
|
||||
*/
|
||||
#define USE_STATIC_CODE_GEN_BUFFER
|
||||
#endif
|
||||
#else /* TCG_TARGET_REG_BITS == 64 */
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/*
|
||||
* As user-mode emulation typically means running multiple instances
|
||||
* of the translator don't go too nuts with our default code gen
|
||||
* buffer lest we make things too hard for the OS.
|
||||
*/
|
||||
#define DEFAULT_CODE_GEN_BUFFER_SIZE_1 (128 * MiB)
|
||||
#else
|
||||
/*
|
||||
* We expect most system emulation to run one or two guests per host.
|
||||
* Users running large scale system emulation may want to tweak their
|
||||
* runtime setup via the tb-size control on the command line.
|
||||
*/
|
||||
#define DEFAULT_CODE_GEN_BUFFER_SIZE_1 (1 * GiB)
|
||||
#endif
|
||||
#endif
|
||||
#define DEFAULT_CODE_GEN_BUFFER_SIZE_1 (32u * 1024 * 1024)
|
||||
|
||||
#define DEFAULT_CODE_GEN_BUFFER_SIZE \
|
||||
(DEFAULT_CODE_GEN_BUFFER_SIZE_1 < MAX_CODE_GEN_BUFFER_SIZE \
|
||||
@@ -977,12 +937,15 @@ static inline size_t size_code_gen_buffer(size_t tb_size)
|
||||
{
|
||||
/* Size the buffer. */
|
||||
if (tb_size == 0) {
|
||||
size_t phys_mem = qemu_get_host_physmem();
|
||||
if (phys_mem == 0) {
|
||||
tb_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
|
||||
} else {
|
||||
tb_size = MIN(DEFAULT_CODE_GEN_BUFFER_SIZE, phys_mem / 8);
|
||||
}
|
||||
#ifdef USE_STATIC_CODE_GEN_BUFFER
|
||||
tb_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
|
||||
#else
|
||||
/* ??? Needs adjustments. */
|
||||
/* ??? If we relax the requirement that CONFIG_USER_ONLY use the
|
||||
static buffer, we could size this on RESERVED_VA, on the text
|
||||
segment size of the executable, or continue to use the default. */
|
||||
tb_size = (unsigned long)(ram_size / 4);
|
||||
#endif
|
||||
}
|
||||
if (tb_size < MIN_CODE_GEN_BUFFER_SIZE) {
|
||||
tb_size = MIN_CODE_GEN_BUFFER_SIZE;
|
||||
@@ -1069,20 +1032,47 @@ static inline void *alloc_code_gen_buffer(void)
|
||||
{
|
||||
int prot = PROT_WRITE | PROT_READ | PROT_EXEC;
|
||||
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
uintptr_t start = 0;
|
||||
size_t size = tcg_ctx->code_gen_buffer_size;
|
||||
void *buf;
|
||||
|
||||
buf = mmap(NULL, size, prot, flags, -1, 0);
|
||||
/* Constrain the position of the buffer based on the host cpu.
|
||||
Note that these addresses are chosen in concert with the
|
||||
addresses assigned in the relevant linker script file. */
|
||||
# if defined(__PIE__) || defined(__PIC__)
|
||||
/* Don't bother setting a preferred location if we're building
|
||||
a position-independent executable. We're more likely to get
|
||||
an address near the main executable if we let the kernel
|
||||
choose the address. */
|
||||
# elif defined(__x86_64__) && defined(MAP_32BIT)
|
||||
/* Force the memory down into low memory with the executable.
|
||||
Leave the choice of exact location with the kernel. */
|
||||
flags |= MAP_32BIT;
|
||||
/* Cannot expect to map more than 800MB in low memory. */
|
||||
if (size > 800u * 1024 * 1024) {
|
||||
tcg_ctx->code_gen_buffer_size = size = 800u * 1024 * 1024;
|
||||
}
|
||||
# elif defined(__sparc__)
|
||||
start = 0x40000000ul;
|
||||
# elif defined(__s390x__)
|
||||
start = 0x90000000ul;
|
||||
# elif defined(__mips__)
|
||||
# if _MIPS_SIM == _ABI64
|
||||
start = 0x128000000ul;
|
||||
# else
|
||||
start = 0x08000000ul;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
buf = mmap((void *)start, size, prot, flags, -1, 0);
|
||||
if (buf == MAP_FAILED) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef __mips__
|
||||
if (cross_256mb(buf, size)) {
|
||||
/*
|
||||
* Try again, with the original still mapped, to avoid re-acquiring
|
||||
* the same 256mb crossing.
|
||||
*/
|
||||
/* Try again, with the original still mapped, to avoid re-acquiring
|
||||
that 256mb crossing. This time don't specify an address. */
|
||||
size_t size2;
|
||||
void *buf2 = mmap(NULL, size, prot, flags, -1, 0);
|
||||
switch ((int)(buf2 != MAP_FAILED)) {
|
||||
@@ -1254,7 +1244,7 @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count)
|
||||
tcg_region_reset_all();
|
||||
/* XXX: flush processor icache at this point if cache flush is
|
||||
expensive */
|
||||
qatomic_mb_set(&tb_ctx.tb_flush_count, tb_ctx.tb_flush_count + 1);
|
||||
atomic_mb_set(&tb_ctx.tb_flush_count, tb_ctx.tb_flush_count + 1);
|
||||
|
||||
done:
|
||||
mmap_unlock();
|
||||
@@ -1266,7 +1256,7 @@ done:
|
||||
void tb_flush(CPUState *cpu)
|
||||
{
|
||||
if (tcg_enabled()) {
|
||||
unsigned tb_flush_count = qatomic_mb_read(&tb_ctx.tb_flush_count);
|
||||
unsigned tb_flush_count = atomic_mb_read(&tb_ctx.tb_flush_count);
|
||||
|
||||
if (cpu_in_exclusive_context(cpu)) {
|
||||
do_tb_flush(cpu, RUN_ON_CPU_HOST_INT(tb_flush_count));
|
||||
@@ -1359,7 +1349,7 @@ static inline void tb_remove_from_jmp_list(TranslationBlock *orig, int n_orig)
|
||||
int n;
|
||||
|
||||
/* mark the LSB of jmp_dest[] so that no further jumps can be inserted */
|
||||
ptr = qatomic_or_fetch(&orig->jmp_dest[n_orig], 1);
|
||||
ptr = atomic_or_fetch(&orig->jmp_dest[n_orig], 1);
|
||||
dest = (TranslationBlock *)(ptr & ~1);
|
||||
if (dest == NULL) {
|
||||
return;
|
||||
@@ -1370,7 +1360,7 @@ static inline void tb_remove_from_jmp_list(TranslationBlock *orig, int n_orig)
|
||||
* While acquiring the lock, the jump might have been removed if the
|
||||
* destination TB was invalidated; check again.
|
||||
*/
|
||||
ptr_locked = qatomic_read(&orig->jmp_dest[n_orig]);
|
||||
ptr_locked = atomic_read(&orig->jmp_dest[n_orig]);
|
||||
if (ptr_locked != ptr) {
|
||||
qemu_spin_unlock(&dest->jmp_lock);
|
||||
/*
|
||||
@@ -1416,7 +1406,7 @@ static inline void tb_jmp_unlink(TranslationBlock *dest)
|
||||
|
||||
TB_FOR_EACH_JMP(dest, tb, n) {
|
||||
tb_reset_jump(tb, n);
|
||||
qatomic_and(&tb->jmp_dest[n], (uintptr_t)NULL | 1);
|
||||
atomic_and(&tb->jmp_dest[n], (uintptr_t)NULL | 1);
|
||||
/* No need to clear the list entry; setting the dest ptr is enough */
|
||||
}
|
||||
dest->jmp_list_head = (uintptr_t)NULL;
|
||||
@@ -1440,7 +1430,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
|
||||
|
||||
/* make sure no further incoming jumps will be chained to this TB */
|
||||
qemu_spin_lock(&tb->jmp_lock);
|
||||
qatomic_set(&tb->cflags, tb->cflags | CF_INVALID);
|
||||
atomic_set(&tb->cflags, tb->cflags | CF_INVALID);
|
||||
qemu_spin_unlock(&tb->jmp_lock);
|
||||
|
||||
/* remove the TB from the hash list */
|
||||
@@ -1467,8 +1457,8 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
|
||||
/* remove the TB from the hash list */
|
||||
h = tb_jmp_cache_hash_func(tb->pc);
|
||||
CPU_FOREACH(cpu) {
|
||||
if (qatomic_read(&cpu->tb_jmp_cache[h]) == tb) {
|
||||
qatomic_set(&cpu->tb_jmp_cache[h], NULL);
|
||||
if (atomic_read(&cpu->tb_jmp_cache[h]) == tb) {
|
||||
atomic_set(&cpu->tb_jmp_cache[h], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1479,7 +1469,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
|
||||
/* suppress any remaining jumps to this TB */
|
||||
tb_jmp_unlink(tb);
|
||||
|
||||
qatomic_set(&tcg_ctx->tb_phys_invalidate_count,
|
||||
atomic_set(&tcg_ctx->tb_phys_invalidate_count,
|
||||
tcg_ctx->tb_phys_invalidate_count + 1);
|
||||
}
|
||||
|
||||
@@ -1734,7 +1724,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
/* includes aborted translations because of exceptions */
|
||||
qatomic_set(&prof->tb_count1, prof->tb_count1 + 1);
|
||||
atomic_set(&prof->tb_count1, prof->tb_count1 + 1);
|
||||
ti = profile_getclock();
|
||||
#endif
|
||||
|
||||
@@ -1759,9 +1749,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
qatomic_set(&prof->tb_count, prof->tb_count + 1);
|
||||
qatomic_set(&prof->interm_time,
|
||||
prof->interm_time + profile_getclock() - ti);
|
||||
atomic_set(&prof->tb_count, prof->tb_count + 1);
|
||||
atomic_set(&prof->interm_time, prof->interm_time + profile_getclock() - ti);
|
||||
ti = profile_getclock();
|
||||
#endif
|
||||
|
||||
@@ -1806,59 +1795,24 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
tb->tc.size = gen_code_size;
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
qatomic_set(&prof->code_time, prof->code_time + profile_getclock() - ti);
|
||||
qatomic_set(&prof->code_in_len, prof->code_in_len + tb->size);
|
||||
qatomic_set(&prof->code_out_len, prof->code_out_len + gen_code_size);
|
||||
qatomic_set(&prof->search_out_len, prof->search_out_len + search_size);
|
||||
atomic_set(&prof->code_time, prof->code_time + profile_getclock() - ti);
|
||||
atomic_set(&prof->code_in_len, prof->code_in_len + tb->size);
|
||||
atomic_set(&prof->code_out_len, prof->code_out_len + gen_code_size);
|
||||
atomic_set(&prof->search_out_len, prof->search_out_len + search_size);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_DISAS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
|
||||
qemu_log_in_addr_range(tb->pc)) {
|
||||
FILE *logfile = qemu_log_lock();
|
||||
int code_size, data_size = 0;
|
||||
size_t chunk_start;
|
||||
int insn = 0;
|
||||
|
||||
if (tcg_ctx->data_gen_ptr) {
|
||||
code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr;
|
||||
data_size = gen_code_size - code_size;
|
||||
} else {
|
||||
code_size = gen_code_size;
|
||||
}
|
||||
|
||||
/* Dump header and the first instruction */
|
||||
qemu_log_lock();
|
||||
qemu_log("OUT: [size=%d]\n", gen_code_size);
|
||||
qemu_log(" -- guest addr 0x" TARGET_FMT_lx " + tb prologue\n",
|
||||
tcg_ctx->gen_insn_data[insn][0]);
|
||||
chunk_start = tcg_ctx->gen_insn_end_off[insn];
|
||||
log_disas(tb->tc.ptr, chunk_start);
|
||||
if (tcg_ctx->data_gen_ptr) {
|
||||
size_t code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr;
|
||||
size_t data_size = gen_code_size - code_size;
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
* Dump each instruction chunk, wrapping up empty chunks into
|
||||
* the next instruction. The whole array is offset so the
|
||||
* first entry is the beginning of the 2nd instruction.
|
||||
*/
|
||||
while (insn < tb->icount) {
|
||||
size_t chunk_end = tcg_ctx->gen_insn_end_off[insn];
|
||||
if (chunk_end > chunk_start) {
|
||||
qemu_log(" -- guest addr 0x" TARGET_FMT_lx "\n",
|
||||
tcg_ctx->gen_insn_data[insn][0]);
|
||||
log_disas(tb->tc.ptr + chunk_start, chunk_end - chunk_start);
|
||||
chunk_start = chunk_end;
|
||||
}
|
||||
insn++;
|
||||
}
|
||||
log_disas(tb->tc.ptr, code_size);
|
||||
|
||||
if (chunk_start < code_size) {
|
||||
qemu_log(" -- tb slow paths + alignment\n");
|
||||
log_disas(tb->tc.ptr + chunk_start, code_size - chunk_start);
|
||||
}
|
||||
|
||||
/* Finally dump any data we may have after the block */
|
||||
if (data_size) {
|
||||
int i;
|
||||
qemu_log(" data: [size=%d]\n", data_size);
|
||||
for (i = 0; i < data_size; i += sizeof(tcg_target_ulong)) {
|
||||
if (sizeof(tcg_target_ulong) == 8) {
|
||||
qemu_log("0x%08" PRIxPTR ": .quad 0x%016" PRIx64 "\n",
|
||||
@@ -1870,14 +1824,16 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
*(uint32_t *)(tcg_ctx->data_gen_ptr + i));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_disas(tb->tc.ptr, gen_code_size);
|
||||
}
|
||||
qemu_log("\n");
|
||||
qemu_log_flush();
|
||||
qemu_log_unlock(logfile);
|
||||
qemu_log_unlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
qatomic_set(&tcg_ctx->code_gen_ptr, (void *)
|
||||
atomic_set(&tcg_ctx->code_gen_ptr, (void *)
|
||||
ROUND_UP((uintptr_t)gen_code_buf + gen_code_size + search_size,
|
||||
CODE_GEN_ALIGN));
|
||||
|
||||
@@ -1913,8 +1869,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
uintptr_t orig_aligned = (uintptr_t)gen_code_buf;
|
||||
|
||||
orig_aligned -= ROUND_UP(sizeof(*tb), qemu_icache_linesize);
|
||||
qatomic_set(&tcg_ctx->code_gen_ptr, (void *)orig_aligned);
|
||||
tb_destroy(tb);
|
||||
atomic_set(&tcg_ctx->code_gen_ptr, (void *)orig_aligned);
|
||||
return existing_tb;
|
||||
}
|
||||
tcg_tb_insert(tb);
|
||||
@@ -2264,13 +2219,8 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
tb_phys_invalidate(tb->orig_tb, -1);
|
||||
}
|
||||
tcg_tb_remove(tb);
|
||||
tb_destroy(tb);
|
||||
}
|
||||
|
||||
qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
|
||||
"cpu_io_recompile: rewound execution of TB to "
|
||||
TARGET_FMT_lx "\n", tb->pc);
|
||||
|
||||
/* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
|
||||
* the first in the TB) then we end up generating a whole new TB and
|
||||
* repeating the fault, which is horribly inefficient.
|
||||
@@ -2285,7 +2235,7 @@ static void tb_jmp_cache_clear_page(CPUState *cpu, target_ulong page_addr)
|
||||
unsigned int i, i0 = tb_jmp_cache_hash_page(page_addr);
|
||||
|
||||
for (i = 0; i < TB_JMP_PAGE_SIZE; i++) {
|
||||
qatomic_set(&cpu->tb_jmp_cache[i0 + i], NULL);
|
||||
atomic_set(&cpu->tb_jmp_cache[i0 + i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2405,7 +2355,7 @@ void dump_exec_info(void)
|
||||
|
||||
qemu_printf("\nStatistics:\n");
|
||||
qemu_printf("TB flush count %u\n",
|
||||
qatomic_read(&tb_ctx.tb_flush_count));
|
||||
atomic_read(&tb_ctx.tb_flush_count));
|
||||
qemu_printf("TB invalidate count %zu\n",
|
||||
tcg_tb_phys_invalidate_count());
|
||||
|
||||
@@ -2427,7 +2377,7 @@ void cpu_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
g_assert(qemu_mutex_iothread_locked());
|
||||
cpu->interrupt_request |= mask;
|
||||
qatomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
|
||||
atomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2563,7 +2513,9 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
|
||||
/* This function should never be called with addresses outside the
|
||||
guest address space. If this assert fires, it probably indicates
|
||||
a missing call to h2g_valid. */
|
||||
assert(end - 1 <= GUEST_ADDR_MAX);
|
||||
#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS
|
||||
assert(end <= ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
|
||||
#endif
|
||||
assert(start < end);
|
||||
assert_memory_lock();
|
||||
|
||||
@@ -2599,9 +2551,9 @@ int page_check_range(target_ulong start, target_ulong len, int flags)
|
||||
/* This function should never be called with addresses outside the
|
||||
guest address space. If this assert fires, it probably indicates
|
||||
a missing call to h2g_valid. */
|
||||
if (TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS) {
|
||||
assert(start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
|
||||
}
|
||||
#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS
|
||||
assert(start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
|
||||
#endif
|
||||
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "exec/log.h"
|
||||
#include "exec/translator.h"
|
||||
#include "exec/plugin-gen.h"
|
||||
#include "sysemu/replay.h"
|
||||
|
||||
/* Pairs with tcg_clear_temp_count.
|
||||
To be called by #TranslatorOps.{translate_insn,tb_stop} if
|
||||
@@ -139,11 +138,11 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
#ifdef DEBUG_DISAS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||
&& qemu_log_in_addr_range(db->pc_first)) {
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log_lock();
|
||||
qemu_log("----------------\n");
|
||||
ops->disas_log(db, cpu);
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock(logfile);
|
||||
qemu_log_unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -9,10 +9,6 @@ void cpu_resume(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void cpu_remove_sync(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
void qemu_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
+20
-488
@@ -20,14 +20,12 @@
|
||||
#include "cpu.h"
|
||||
#include "disas/disas.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "translate-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "qemu/atomic128.h"
|
||||
#include "trace/trace-root.h"
|
||||
#include "trace/mem.h"
|
||||
|
||||
#undef EAX
|
||||
#undef ECX
|
||||
@@ -88,7 +86,7 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
|
||||
* use that value directly. Within cpu_restore_state_from_tb, we
|
||||
* assume PC comes from GETPC(), as used by the helper functions,
|
||||
* so we adjust the address by -GETPC_ADJ to form an address that
|
||||
* is within the call insn, so that the address does not accidentally
|
||||
* is within the call insn, so that the address does not accidentially
|
||||
* match the beginning of the next guest insn. However, when the
|
||||
* pc comes from the signal frame it points to the actual faulting
|
||||
* host memory insn and not the return from a call insn.
|
||||
@@ -190,12 +188,13 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static int probe_access_internal(CPUArchState *env, target_ulong addr,
|
||||
int fault_size, MMUAccessType access_type,
|
||||
bool nonfault, uintptr_t ra)
|
||||
void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
||||
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
int flags;
|
||||
|
||||
g_assert(-(addr | TARGET_PAGE_MASK) >= size);
|
||||
|
||||
switch (access_type) {
|
||||
case MMU_DATA_STORE:
|
||||
flags = PAGE_WRITE;
|
||||
@@ -210,39 +209,13 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (!guest_addr_valid(addr) || page_check_range(addr, 1, flags) < 0) {
|
||||
if (nonfault) {
|
||||
return TLB_INVALID_MASK;
|
||||
} else {
|
||||
CPUState *cpu = env_cpu(env);
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
cc->tlb_fill(cpu, addr, fault_size, access_type,
|
||||
MMU_USER_IDX, false, ra);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
if (!guest_addr_valid(addr) || page_check_range(addr, size, flags) < 0) {
|
||||
CPUState *cpu = env_cpu(env);
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
cc->tlb_fill(cpu, addr, size, access_type, MMU_USER_IDX, false,
|
||||
retaddr);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probe_access_flags(CPUArchState *env, target_ulong addr,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool nonfault, void **phost, uintptr_t ra)
|
||||
{
|
||||
int flags;
|
||||
|
||||
flags = probe_access_internal(env, addr, 0, access_type, nonfault, ra);
|
||||
*phost = flags ? NULL : g2h(addr);
|
||||
return flags;
|
||||
}
|
||||
|
||||
void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
||||
MMUAccessType access_type, int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
int flags;
|
||||
|
||||
g_assert(-(addr | TARGET_PAGE_MASK) >= size);
|
||||
flags = probe_access_internal(env, addr, size, access_type, false, ra);
|
||||
g_assert(flags == 0);
|
||||
|
||||
return size ? g2h(addr) : NULL;
|
||||
}
|
||||
@@ -517,7 +490,6 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
#include <ucontext.h>
|
||||
#include <sys/siginfo.h>
|
||||
#endif
|
||||
|
||||
int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
@@ -526,12 +498,10 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
siginfo_t *info = pinfo;
|
||||
#if defined(__NetBSD__)
|
||||
ucontext_t *uc = puc;
|
||||
siginfo_t *si = pinfo;
|
||||
#else
|
||||
ucontext_t *uc = puc;
|
||||
#endif
|
||||
unsigned long pc;
|
||||
uint32_t fsr;
|
||||
int is_write;
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
@@ -542,48 +512,15 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
pc = uc->uc_mcontext.arm_pc;
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
fsr = si->si_trap;
|
||||
#else
|
||||
fsr = uc->uc_mcontext.error_code;
|
||||
#endif
|
||||
/*
|
||||
* In the FSR, bit 11 is WnR, assuming a v6 or
|
||||
* later processor. On v5 we will always report
|
||||
* this as a read, which will fail later.
|
||||
/* error_code is the FSR value, in which bit 11 is WnR (assuming a v6 or
|
||||
* later processor; on v5 we will always report this as a read).
|
||||
*/
|
||||
is_write = extract32(fsr, 11, 1);
|
||||
is_write = extract32(uc->uc_mcontext.error_code, 11, 1);
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
|
||||
#include <ucontext.h>
|
||||
#include <sys/siginfo.h>
|
||||
|
||||
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
|
||||
{
|
||||
ucontext_t *uc = puc;
|
||||
siginfo_t *si = pinfo;
|
||||
unsigned long pc;
|
||||
int is_write;
|
||||
uint32_t esr;
|
||||
|
||||
pc = uc->uc_mcontext.__gregs[_REG_PC];
|
||||
esr = si->si_trap;
|
||||
|
||||
/*
|
||||
* siginfo_t::si_trap is the ESR value, for data aborts ESR.EC
|
||||
* is 0b10010x: then bit 6 is the WnR bit
|
||||
*/
|
||||
is_write = extract32(esr, 27, 5) == 0x12 && extract32(esr, 6, 1) == 1;
|
||||
return handle_cpu_signal(pc, si, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifndef ESR_MAGIC
|
||||
/* Pre-3.16 kernel headers don't have these, so provide fallback definitions */
|
||||
#define ESR_MAGIC 0x45535201
|
||||
@@ -646,7 +583,6 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
|
||||
}
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined(__s390__)
|
||||
|
||||
@@ -702,51 +638,16 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
#if defined(__misp16) || defined(__mips_micromips)
|
||||
#error "Unsupported encoding"
|
||||
#endif
|
||||
|
||||
int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
void *puc)
|
||||
{
|
||||
siginfo_t *info = pinfo;
|
||||
ucontext_t *uc = puc;
|
||||
uintptr_t pc = uc->uc_mcontext.pc;
|
||||
uint32_t insn = *(uint32_t *)pc;
|
||||
int is_write = 0;
|
||||
|
||||
/* Detect all store instructions at program counter. */
|
||||
switch((insn >> 26) & 077) {
|
||||
case 050: /* SB */
|
||||
case 051: /* SH */
|
||||
case 052: /* SWL */
|
||||
case 053: /* SW */
|
||||
case 054: /* SDL */
|
||||
case 055: /* SDR */
|
||||
case 056: /* SWR */
|
||||
case 070: /* SC */
|
||||
case 071: /* SWC1 */
|
||||
case 074: /* SCD */
|
||||
case 075: /* SDC1 */
|
||||
case 077: /* SD */
|
||||
#if !defined(__mips_isa_rev) || __mips_isa_rev < 6
|
||||
case 072: /* SWC2 */
|
||||
case 076: /* SDC2 */
|
||||
#endif
|
||||
is_write = 1;
|
||||
break;
|
||||
case 023: /* COP1X */
|
||||
/* Required in all versions of MIPS64 since
|
||||
MIPS64r1 and subsequent versions of MIPS32r2. */
|
||||
switch (insn & 077) {
|
||||
case 010: /* SWXC1 */
|
||||
case 011: /* SDXC1 */
|
||||
case 015: /* SUXC1 */
|
||||
is_write = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
greg_t pc = uc->uc_mcontext.pc;
|
||||
int is_write;
|
||||
|
||||
/* XXX: compute is_write */
|
||||
is_write = 0;
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
@@ -833,375 +734,6 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
|
||||
/* The softmmu versions of these helpers are in cputlb.c. */
|
||||
|
||||
uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_UB, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldub_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
int ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_SB, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldsb_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEUW, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = lduw_be_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
int ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BESW, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldsw_be_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEUL, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldl_be_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint64_t ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEQ, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldq_be_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEUW, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = lduw_le_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
int ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LESW, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldsw_le_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEUL, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldl_le_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint64_t ret;
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEQ, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldq_le_p(g2h(ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_ldub_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_ldsb_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_lduw_be_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_ldsw_be_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_ldl_be_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
uint64_t ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_ldq_be_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_lduw_le_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_ldsw_le_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_ldl_le_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
|
||||
{
|
||||
uint64_t ret;
|
||||
|
||||
set_helper_retaddr(retaddr);
|
||||
ret = cpu_ldq_le_data(env, ptr);
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cpu_stb_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
{
|
||||
uint16_t meminfo = trace_mem_get_info(MO_UB, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stb_p(g2h(ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
void cpu_stw_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
{
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEUW, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stw_be_p(g2h(ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
void cpu_stl_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
{
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEUL, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stl_be_p(g2h(ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
void cpu_stq_be_data(CPUArchState *env, abi_ptr ptr, uint64_t val)
|
||||
{
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEQ, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stq_be_p(g2h(ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
void cpu_stw_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
{
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEUW, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stw_le_p(g2h(ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
void cpu_stl_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
{
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEUL, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stl_le_p(g2h(ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
void cpu_stq_le_data(CPUArchState *env, abi_ptr ptr, uint64_t val)
|
||||
{
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEQ, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stq_le_p(g2h(ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
void cpu_stb_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
set_helper_retaddr(retaddr);
|
||||
cpu_stb_data(env, ptr, val);
|
||||
clear_helper_retaddr();
|
||||
}
|
||||
|
||||
void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
set_helper_retaddr(retaddr);
|
||||
cpu_stw_be_data(env, ptr, val);
|
||||
clear_helper_retaddr();
|
||||
}
|
||||
|
||||
void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
set_helper_retaddr(retaddr);
|
||||
cpu_stl_be_data(env, ptr, val);
|
||||
clear_helper_retaddr();
|
||||
}
|
||||
|
||||
void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint64_t val, uintptr_t retaddr)
|
||||
{
|
||||
set_helper_retaddr(retaddr);
|
||||
cpu_stq_be_data(env, ptr, val);
|
||||
clear_helper_retaddr();
|
||||
}
|
||||
|
||||
void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
set_helper_retaddr(retaddr);
|
||||
cpu_stw_le_data(env, ptr, val);
|
||||
clear_helper_retaddr();
|
||||
}
|
||||
|
||||
void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint32_t val, uintptr_t retaddr)
|
||||
{
|
||||
set_helper_retaddr(retaddr);
|
||||
cpu_stl_le_data(env, ptr, val);
|
||||
clear_helper_retaddr();
|
||||
}
|
||||
|
||||
void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint64_t val, uintptr_t retaddr)
|
||||
{
|
||||
set_helper_retaddr(retaddr);
|
||||
cpu_stq_le_data(env, ptr, val);
|
||||
clear_helper_retaddr();
|
||||
}
|
||||
|
||||
uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(1);
|
||||
ret = ldub_p(g2h(ptr));
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(1);
|
||||
ret = lduw_p(g2h(ptr));
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(1);
|
||||
ret = ldl_p(g2h(ptr));
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr ptr)
|
||||
{
|
||||
uint64_t ret;
|
||||
|
||||
set_helper_retaddr(1);
|
||||
ret = ldq_p(g2h(ptr));
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Do not allow unaligned operations to proceed. Return the host address. */
|
||||
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||
int size, uintptr_t retaddr)
|
||||
@@ -1224,7 +756,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||
#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
|
||||
#define EXTRA_ARGS
|
||||
|
||||
#include "atomic_common.c.inc"
|
||||
#include "atomic_common.inc.c"
|
||||
|
||||
#define DATA_SIZE 1
|
||||
#include "atomic_template.h"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
specific_ss.add(when: 'CONFIG_XEN', if_true: files('xen-all.c'))
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/audio/soundhw.h"
|
||||
#include "qapi/qapi-commands-misc.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -76,8 +77,6 @@ int graphic_depth = 32;
|
||||
#define QEMU_ARCH QEMU_ARCH_PPC
|
||||
#elif defined(TARGET_RISCV)
|
||||
#define QEMU_ARCH QEMU_ARCH_RISCV
|
||||
#elif defined(TARGET_RX)
|
||||
#define QEMU_ARCH QEMU_ARCH_RX
|
||||
#elif defined(TARGET_S390X)
|
||||
#define QEMU_ARCH QEMU_ARCH_S390X
|
||||
#elif defined(TARGET_SH4)
|
||||
@@ -90,8 +89,6 @@ int graphic_depth = 32;
|
||||
#define QEMU_ARCH QEMU_ARCH_UNICORE32
|
||||
#elif defined(TARGET_XTENSA)
|
||||
#define QEMU_ARCH QEMU_ARCH_XTENSA
|
||||
#elif defined(TARGET_AVR)
|
||||
#define QEMU_ARCH QEMU_ARCH_AVR
|
||||
#endif
|
||||
|
||||
const uint32_t arch_type = QEMU_ARCH;
|
||||
@@ -0,0 +1,30 @@
|
||||
common-obj-y = audio.o audio_legacy.o noaudio.o wavaudio.o mixeng.o
|
||||
common-obj-$(CONFIG_SPICE) += spiceaudio.o
|
||||
common-obj-$(CONFIG_AUDIO_COREAUDIO) += coreaudio.o
|
||||
common-obj-$(CONFIG_AUDIO_DSOUND) += dsoundaudio.o
|
||||
common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o
|
||||
common-obj-y += wavcapture.o
|
||||
|
||||
coreaudio.o-libs := $(COREAUDIO_LIBS)
|
||||
dsoundaudio.o-libs := $(DSOUND_LIBS)
|
||||
|
||||
# alsa module
|
||||
common-obj-$(CONFIG_AUDIO_ALSA) += alsa.mo
|
||||
alsa.mo-objs = alsaaudio.o
|
||||
alsa.mo-libs := $(ALSA_LIBS)
|
||||
|
||||
# oss module
|
||||
common-obj-$(CONFIG_AUDIO_OSS) += oss.mo
|
||||
oss.mo-objs = ossaudio.o
|
||||
oss.mo-libs := $(OSS_LIBS)
|
||||
|
||||
# pulseaudio module
|
||||
common-obj-$(CONFIG_AUDIO_PA) += pa.mo
|
||||
pa.mo-objs = paaudio.o
|
||||
pa.mo-libs := $(PULSE_LIBS)
|
||||
|
||||
# sdl module
|
||||
common-obj-$(CONFIG_AUDIO_SDL) += sdl.mo
|
||||
sdl.mo-objs = sdlaudio.o
|
||||
sdl.mo-cflags := $(SDL_CFLAGS)
|
||||
sdl.mo-libs := $(SDL_LIBS)
|
||||
+2
-20
@@ -307,13 +307,6 @@ static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness)
|
||||
return SND_PCM_FORMAT_U32_LE;
|
||||
}
|
||||
|
||||
case AUDIO_FORMAT_F32:
|
||||
if (endianness) {
|
||||
return SND_PCM_FORMAT_FLOAT_BE;
|
||||
} else {
|
||||
return SND_PCM_FORMAT_FLOAT_LE;
|
||||
}
|
||||
|
||||
default:
|
||||
dolog ("Internal logic error: Bad audio format %d\n", fmt);
|
||||
#ifdef DEBUG_AUDIO
|
||||
@@ -377,16 +370,6 @@ static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt,
|
||||
*fmt = AUDIO_FORMAT_U32;
|
||||
break;
|
||||
|
||||
case SND_PCM_FORMAT_FLOAT_LE:
|
||||
*endianness = 0;
|
||||
*fmt = AUDIO_FORMAT_F32;
|
||||
break;
|
||||
|
||||
case SND_PCM_FORMAT_FLOAT_BE:
|
||||
*endianness = 1;
|
||||
*fmt = AUDIO_FORMAT_F32;
|
||||
break;
|
||||
|
||||
default:
|
||||
dolog ("Unrecognized audio format %d\n", alsafmt);
|
||||
return -1;
|
||||
@@ -819,7 +802,7 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len)
|
||||
switch (nread) {
|
||||
case 0:
|
||||
trace_alsa_read_zero(len);
|
||||
return pos;
|
||||
return pos;;
|
||||
|
||||
case -EPIPE:
|
||||
if (alsa_recover(alsa->handle)) {
|
||||
@@ -835,7 +818,7 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len)
|
||||
default:
|
||||
alsa_logerr(nread, "Failed to read %zu frames to %p\n",
|
||||
len, dst);
|
||||
return pos;
|
||||
return pos;;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -923,7 +906,6 @@ static struct audio_pcm_ops alsa_pcm_ops = {
|
||||
.init_out = alsa_init_out,
|
||||
.fini_out = alsa_fini_out,
|
||||
.write = alsa_write,
|
||||
.run_buffer_out = audio_generic_run_buffer_out,
|
||||
.enable_out = alsa_enable_out,
|
||||
|
||||
.init_in = alsa_init_in,
|
||||
|
||||
+75
-144
@@ -34,7 +34,6 @@
|
||||
#include "qemu/module.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "ui/qemu-spice.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define AUDIO_CAP "audio"
|
||||
@@ -219,9 +218,6 @@ static void audio_print_settings (struct audsettings *as)
|
||||
case AUDIO_FORMAT_U32:
|
||||
AUD_log (NULL, "U32");
|
||||
break;
|
||||
case AUDIO_FORMAT_F32:
|
||||
AUD_log (NULL, "F32");
|
||||
break;
|
||||
default:
|
||||
AUD_log (NULL, "invalid(%d)", as->fmt);
|
||||
break;
|
||||
@@ -256,7 +252,6 @@ static int audio_validate_settings (struct audsettings *as)
|
||||
case AUDIO_FORMAT_U16:
|
||||
case AUDIO_FORMAT_S32:
|
||||
case AUDIO_FORMAT_U32:
|
||||
case AUDIO_FORMAT_F32:
|
||||
break;
|
||||
default:
|
||||
invalid = 1;
|
||||
@@ -269,28 +264,24 @@ static int audio_validate_settings (struct audsettings *as)
|
||||
|
||||
static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *as)
|
||||
{
|
||||
int bits = 8;
|
||||
bool is_signed = false, is_float = false;
|
||||
int bits = 8, sign = 0;
|
||||
|
||||
switch (as->fmt) {
|
||||
case AUDIO_FORMAT_S8:
|
||||
is_signed = true;
|
||||
sign = 1;
|
||||
/* fall through */
|
||||
case AUDIO_FORMAT_U8:
|
||||
break;
|
||||
|
||||
case AUDIO_FORMAT_S16:
|
||||
is_signed = true;
|
||||
sign = 1;
|
||||
/* fall through */
|
||||
case AUDIO_FORMAT_U16:
|
||||
bits = 16;
|
||||
break;
|
||||
|
||||
case AUDIO_FORMAT_F32:
|
||||
is_float = true;
|
||||
/* fall through */
|
||||
case AUDIO_FORMAT_S32:
|
||||
is_signed = true;
|
||||
sign = 1;
|
||||
/* fall through */
|
||||
case AUDIO_FORMAT_U32:
|
||||
bits = 32;
|
||||
@@ -301,38 +292,32 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *a
|
||||
}
|
||||
return info->freq == as->freq
|
||||
&& info->nchannels == as->nchannels
|
||||
&& info->is_signed == is_signed
|
||||
&& info->is_float == is_float
|
||||
&& info->sign == sign
|
||||
&& info->bits == bits
|
||||
&& info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS);
|
||||
}
|
||||
|
||||
void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
|
||||
{
|
||||
int bits = 8, mul;
|
||||
bool is_signed = false, is_float = false;
|
||||
int bits = 8, sign = 0, mul;
|
||||
|
||||
switch (as->fmt) {
|
||||
case AUDIO_FORMAT_S8:
|
||||
is_signed = true;
|
||||
/* fall through */
|
||||
sign = 1;
|
||||
case AUDIO_FORMAT_U8:
|
||||
mul = 1;
|
||||
break;
|
||||
|
||||
case AUDIO_FORMAT_S16:
|
||||
is_signed = true;
|
||||
sign = 1;
|
||||
/* fall through */
|
||||
case AUDIO_FORMAT_U16:
|
||||
bits = 16;
|
||||
mul = 2;
|
||||
break;
|
||||
|
||||
case AUDIO_FORMAT_F32:
|
||||
is_float = true;
|
||||
/* fall through */
|
||||
case AUDIO_FORMAT_S32:
|
||||
is_signed = true;
|
||||
sign = 1;
|
||||
/* fall through */
|
||||
case AUDIO_FORMAT_U32:
|
||||
bits = 32;
|
||||
@@ -345,8 +330,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
|
||||
|
||||
info->freq = as->freq;
|
||||
info->bits = bits;
|
||||
info->is_signed = is_signed;
|
||||
info->is_float = is_float;
|
||||
info->sign = sign;
|
||||
info->nchannels = as->nchannels;
|
||||
info->bytes_per_frame = as->nchannels * mul;
|
||||
info->bytes_per_second = info->freq * info->bytes_per_frame;
|
||||
@@ -359,7 +343,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->is_signed || info->is_float) {
|
||||
if (info->sign) {
|
||||
memset(buf, 0x00, len * info->bytes_per_frame);
|
||||
}
|
||||
else {
|
||||
@@ -650,7 +634,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
|
||||
total += isamp;
|
||||
}
|
||||
|
||||
if (hw->pcm_ops && !hw->pcm_ops->volume_in) {
|
||||
if (!hw->pcm_ops->volume_in) {
|
||||
mixeng_volume (sw->buf, ret, &sw->vol);
|
||||
}
|
||||
|
||||
@@ -737,7 +721,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
|
||||
if (swlim) {
|
||||
sw->conv (sw->buf, buf, swlim);
|
||||
|
||||
if (sw->hw->pcm_ops && !sw->hw->pcm_ops->volume_out) {
|
||||
if (!sw->hw->pcm_ops->volume_out) {
|
||||
mixeng_volume (sw->buf, swlim, &sw->vol);
|
||||
}
|
||||
}
|
||||
@@ -785,9 +769,8 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
|
||||
#ifdef DEBUG_AUDIO
|
||||
static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info)
|
||||
{
|
||||
dolog("%s: bits %d, sign %d, float %d, freq %d, nchan %d\n",
|
||||
cap, info->bits, info->is_signed, info->is_float, info->freq,
|
||||
info->nchannels);
|
||||
dolog ("%s: bits %d, sign %d, freq %d, nchan %d\n",
|
||||
cap, info->bits, info->sign, info->freq, info->nchannels);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -895,9 +878,9 @@ size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
int AUD_get_buffer_size_out(SWVoiceOut *sw)
|
||||
int AUD_get_buffer_size_out (SWVoiceOut *sw)
|
||||
{
|
||||
return sw->hw->samples * sw->hw->info.bytes_per_frame;
|
||||
return sw->hw->mix_buf->size * sw->hw->info.bytes_per_frame;
|
||||
}
|
||||
|
||||
void AUD_set_active_out (SWVoiceOut *sw, int on)
|
||||
@@ -1090,18 +1073,16 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
|
||||
size_t clipped = 0;
|
||||
|
||||
while (live) {
|
||||
size_t size = live * hw->info.bytes_per_frame;
|
||||
size_t decr, proc;
|
||||
size_t size, decr, proc;
|
||||
void *buf = hw->pcm_ops->get_buffer_out(hw, &size);
|
||||
|
||||
if (size == 0) {
|
||||
break;
|
||||
if (!buf) {
|
||||
/* retrying will likely won't help, drop everything. */
|
||||
hw->mix_buf->pos = (hw->mix_buf->pos + live) % hw->mix_buf->size;
|
||||
return clipped + live;
|
||||
}
|
||||
|
||||
decr = MIN(size / hw->info.bytes_per_frame, live);
|
||||
if (buf) {
|
||||
audio_pcm_hw_clip_out(hw, buf, decr);
|
||||
}
|
||||
audio_pcm_hw_clip_out(hw, buf, decr);
|
||||
proc = hw->pcm_ops->put_buffer_out(hw, buf,
|
||||
decr * hw->info.bytes_per_frame) /
|
||||
hw->info.bytes_per_frame;
|
||||
@@ -1115,10 +1096,6 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
|
||||
}
|
||||
}
|
||||
|
||||
if (hw->pcm_ops->run_buffer_out) {
|
||||
hw->pcm_ops->run_buffer_out(hw);
|
||||
}
|
||||
|
||||
return clipped;
|
||||
}
|
||||
|
||||
@@ -1187,9 +1164,6 @@ static void audio_run_out (AudioState *s)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hw->pcm_ops->run_buffer_out) {
|
||||
hw->pcm_ops->run_buffer_out(hw);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1265,6 +1239,7 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples)
|
||||
|
||||
assert(size % hw->info.bytes_per_frame == 0);
|
||||
if (size == 0) {
|
||||
hw->pcm_ops->put_buffer_in(hw, buf, size);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1427,8 +1402,7 @@ void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size)
|
||||
}
|
||||
assert(start >= 0 && start < hw->size_emul);
|
||||
|
||||
*size = MIN(*size, hw->pending_emul);
|
||||
*size = MIN(*size, hw->size_emul - start);
|
||||
*size = MIN(hw->pending_emul, hw->size_emul - start);
|
||||
return hw->buf_emul + start;
|
||||
}
|
||||
|
||||
@@ -1438,28 +1412,6 @@ void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
|
||||
hw->pending_emul -= size;
|
||||
}
|
||||
|
||||
void audio_generic_run_buffer_out(HWVoiceOut *hw)
|
||||
{
|
||||
while (hw->pending_emul) {
|
||||
size_t write_len, written;
|
||||
ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
|
||||
|
||||
if (start < 0) {
|
||||
start += hw->size_emul;
|
||||
}
|
||||
assert(start >= 0 && start < hw->size_emul);
|
||||
|
||||
write_len = MIN(hw->pending_emul, hw->size_emul - start);
|
||||
|
||||
written = hw->pcm_ops->write(hw, hw->buf_emul + start, write_len);
|
||||
hw->pending_emul -= written;
|
||||
|
||||
if (written < write_len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size)
|
||||
{
|
||||
if (unlikely(!hw->buf_emul)) {
|
||||
@@ -1475,7 +1427,8 @@ void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size)
|
||||
return hw->buf_emul + hw->pos_emul;
|
||||
}
|
||||
|
||||
size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
|
||||
size_t audio_generic_put_buffer_out_nowrite(HWVoiceOut *hw, void *buf,
|
||||
size_t size)
|
||||
{
|
||||
assert(buf == hw->buf_emul + hw->pos_emul &&
|
||||
size + hw->pending_emul <= hw->size_emul);
|
||||
@@ -1486,58 +1439,57 @@ size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
|
||||
{
|
||||
audio_generic_put_buffer_out_nowrite(hw, buf, size);
|
||||
|
||||
while (hw->pending_emul) {
|
||||
size_t write_len, written;
|
||||
ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
|
||||
if (start < 0) {
|
||||
start += hw->size_emul;
|
||||
}
|
||||
assert(start >= 0 && start < hw->size_emul);
|
||||
|
||||
write_len = MIN(hw->pending_emul, hw->size_emul - start);
|
||||
|
||||
written = hw->pcm_ops->write(hw, hw->buf_emul + start, write_len);
|
||||
hw->pending_emul -= written;
|
||||
|
||||
if (written < write_len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fake we have written everything. non-written data remain in pending_emul,
|
||||
* so we do not have to clip them multiple times
|
||||
*/
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size)
|
||||
{
|
||||
size_t total = 0;
|
||||
size_t dst_size, copy_size;
|
||||
void *dst = hw->pcm_ops->get_buffer_out(hw, &dst_size);
|
||||
copy_size = MIN(size, dst_size);
|
||||
|
||||
while (total < size) {
|
||||
size_t dst_size = size - total;
|
||||
size_t copy_size, proc;
|
||||
void *dst = hw->pcm_ops->get_buffer_out(hw, &dst_size);
|
||||
|
||||
if (dst_size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
copy_size = MIN(size - total, dst_size);
|
||||
if (dst) {
|
||||
memcpy(dst, (char *)buf + total, copy_size);
|
||||
}
|
||||
proc = hw->pcm_ops->put_buffer_out(hw, dst, copy_size);
|
||||
total += proc;
|
||||
|
||||
if (proc == 0 || proc < copy_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hw->pcm_ops->run_buffer_out) {
|
||||
hw->pcm_ops->run_buffer_out(hw);
|
||||
}
|
||||
|
||||
return total;
|
||||
memcpy(dst, buf, copy_size);
|
||||
return hw->pcm_ops->put_buffer_out(hw, buf, copy_size);
|
||||
}
|
||||
|
||||
size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
|
||||
{
|
||||
size_t total = 0;
|
||||
size_t dst_size, copy_size;
|
||||
void *dst = hw->pcm_ops->get_buffer_in(hw, &dst_size);
|
||||
copy_size = MIN(size, dst_size);
|
||||
|
||||
while (total < size) {
|
||||
size_t src_size = size - total;
|
||||
void *src = hw->pcm_ops->get_buffer_in(hw, &src_size);
|
||||
|
||||
if (src_size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy((char *)buf + total, src, src_size);
|
||||
hw->pcm_ops->put_buffer_in(hw, src, src_size);
|
||||
total += src_size;
|
||||
}
|
||||
|
||||
return total;
|
||||
memcpy(dst, buf, copy_size);
|
||||
hw->pcm_ops->put_buffer_in(hw, buf, copy_size);
|
||||
return copy_size;
|
||||
}
|
||||
|
||||
|
||||
static int audio_driver_init(AudioState *s, struct audio_driver *drv,
|
||||
bool msg, Audiodev *dev)
|
||||
{
|
||||
@@ -1697,21 +1649,6 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
||||
/* silence gcc warning about uninitialized variable */
|
||||
AudiodevListHead head = QSIMPLEQ_HEAD_INITIALIZER(head);
|
||||
|
||||
if (using_spice) {
|
||||
/*
|
||||
* When using spice allow the spice audio driver being picked
|
||||
* as default.
|
||||
*
|
||||
* Temporary hack. Using audio devices without explicit
|
||||
* audiodev= property is already deprecated. Same goes for
|
||||
* the -soundhw switch. Once this support gets finally
|
||||
* removed we can also drop the concept of a default audio
|
||||
* backend and this can go away.
|
||||
*/
|
||||
driver = audio_driver_lookup("spice");
|
||||
driver->can_be_default = 1;
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
/* -audiodev option */
|
||||
legacy_config = false;
|
||||
@@ -1728,7 +1665,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
||||
head = audio_handle_legacy_opts();
|
||||
/*
|
||||
* In case of legacy initialization, all Audiodevs in the list will have
|
||||
* the same configuration (except the driver), so it doesn't matter which
|
||||
* the same configuration (except the driver), so it does't matter which
|
||||
* one we chose. We need an Audiodev to set up AudioState before we can
|
||||
* init a driver. Also note that dev at this point is still in the
|
||||
* list.
|
||||
@@ -1801,7 +1738,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
||||
if (dev->timer_period <= 0) {
|
||||
s->period_ticks = 1;
|
||||
} else {
|
||||
s->period_ticks = dev->timer_period * (int64_t)SCALE_US;
|
||||
s->period_ticks = dev->timer_period * SCALE_US;
|
||||
}
|
||||
|
||||
e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
|
||||
@@ -1899,15 +1836,11 @@ CaptureVoiceOut *AUD_add_capture(
|
||||
|
||||
cap->buf = g_malloc0_n(hw->mix_buf->size, hw->info.bytes_per_frame);
|
||||
|
||||
if (hw->info.is_float) {
|
||||
hw->clip = mixeng_clip_float[hw->info.nchannels == 2];
|
||||
} else {
|
||||
hw->clip = mixeng_clip
|
||||
[hw->info.nchannels == 2]
|
||||
[hw->info.is_signed]
|
||||
[hw->info.swap_endianness]
|
||||
[audio_bits_to_index(hw->info.bits)];
|
||||
}
|
||||
hw->clip = mixeng_clip
|
||||
[hw->info.nchannels == 2]
|
||||
[hw->info.sign]
|
||||
[hw->info.swap_endianness]
|
||||
[audio_bits_to_index (hw->info.bits)];
|
||||
|
||||
QLIST_INSERT_HEAD (&s->cap_head, cap, entries);
|
||||
QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
|
||||
@@ -2023,7 +1956,6 @@ void audio_create_pdos(Audiodev *dev)
|
||||
CASE(ALSA, alsa, Alsa);
|
||||
CASE(COREAUDIO, coreaudio, Coreaudio);
|
||||
CASE(DSOUND, dsound, );
|
||||
CASE(JACK, jack, Jack);
|
||||
CASE(OSS, oss, Oss);
|
||||
CASE(PA, pa, Pa);
|
||||
CASE(SDL, sdl, );
|
||||
@@ -2147,7 +2079,6 @@ int audioformat_bytes_per_sample(AudioFormat fmt)
|
||||
|
||||
case AUDIO_FORMAT_U32:
|
||||
case AUDIO_FORMAT_S32:
|
||||
case AUDIO_FORMAT_F32:
|
||||
return 4;
|
||||
|
||||
case AUDIO_FORMAT__MAX:
|
||||
|
||||
+2
-2
@@ -60,7 +60,7 @@ typedef enum {
|
||||
|
||||
struct audio_capture_ops {
|
||||
void (*notify) (void *opaque, audcnotification_e cmd);
|
||||
void (*capture) (void *opaque, const void *buf, int size);
|
||||
void (*capture) (void *opaque, void *buf, int size);
|
||||
void (*destroy) (void *opaque);
|
||||
};
|
||||
|
||||
@@ -163,7 +163,7 @@ int wav_start_capture(AudioState *state, CaptureState *s, const char *path,
|
||||
bool audio_is_cleaning_up(void);
|
||||
void audio_cleanup(void);
|
||||
|
||||
void audio_sample_to_uint64(const void *samples, int pos,
|
||||
void audio_sample_to_uint64(void *samples, int pos,
|
||||
uint64_t *left, uint64_t *right);
|
||||
void audio_sample_from_uint64(void *samples, int pos,
|
||||
uint64_t left, uint64_t right);
|
||||
|
||||
+3
-4
@@ -40,8 +40,7 @@ struct audio_callback {
|
||||
|
||||
struct audio_pcm_info {
|
||||
int bits;
|
||||
bool is_signed;
|
||||
bool is_float;
|
||||
int sign;
|
||||
int freq;
|
||||
int nchannels;
|
||||
int bytes_per_frame;
|
||||
@@ -153,7 +152,6 @@ struct audio_pcm_ops {
|
||||
int (*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque);
|
||||
void (*fini_out)(HWVoiceOut *hw);
|
||||
size_t (*write) (HWVoiceOut *hw, void *buf, size_t size);
|
||||
void (*run_buffer_out)(HWVoiceOut *hw);
|
||||
/*
|
||||
* get a buffer that after later can be passed to put_buffer_out; optional
|
||||
* returns the buffer, and writes it's size to size (in bytes)
|
||||
@@ -180,9 +178,10 @@ struct audio_pcm_ops {
|
||||
|
||||
void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
|
||||
void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
|
||||
void audio_generic_run_buffer_out(HWVoiceOut *hw);
|
||||
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_nowrite(HWVoiceOut *hw, void *buf,
|
||||
size_t size);
|
||||
size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size);
|
||||
size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size);
|
||||
|
||||
|
||||
+5
-10
@@ -421,12 +421,11 @@ typedef struct {
|
||||
GList *path;
|
||||
} LegacyPrintVisitor;
|
||||
|
||||
static bool lv_start_struct(Visitor *v, const char *name, void **obj,
|
||||
static void lv_start_struct(Visitor *v, const char *name, void **obj,
|
||||
size_t size, Error **errp)
|
||||
{
|
||||
LegacyPrintVisitor *lv = (LegacyPrintVisitor *) v;
|
||||
lv->path = g_list_append(lv->path, g_strdup(name));
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lv_end_struct(Visitor *v, void **obj)
|
||||
@@ -454,30 +453,27 @@ static void lv_print_key(Visitor *v, const char *name)
|
||||
printf("%s=", name);
|
||||
}
|
||||
|
||||
static bool lv_type_int64(Visitor *v, const char *name, int64_t *obj,
|
||||
static void lv_type_int64(Visitor *v, const char *name, int64_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
lv_print_key(v, name);
|
||||
printf("%" PRIi64, *obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lv_type_uint64(Visitor *v, const char *name, uint64_t *obj,
|
||||
static void lv_type_uint64(Visitor *v, const char *name, uint64_t *obj,
|
||||
Error **errp)
|
||||
{
|
||||
lv_print_key(v, name);
|
||||
printf("%" PRIu64, *obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lv_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
|
||||
static void lv_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
|
||||
{
|
||||
lv_print_key(v, name);
|
||||
printf("%s", *obj ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lv_type_str(Visitor *v, const char *name, char **obj, Error **errp)
|
||||
static void lv_type_str(Visitor *v, const char *name, char **obj, Error **errp)
|
||||
{
|
||||
const char *str = *obj;
|
||||
lv_print_key(v, name);
|
||||
@@ -488,7 +484,6 @@ static bool lv_type_str(Visitor *v, const char *name, char **obj, Error **errp)
|
||||
}
|
||||
putchar(*str++);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lv_complete(Visitor *v, void *opaque)
|
||||
|
||||
+12
-30
@@ -153,23 +153,15 @@ static int glue (audio_pcm_sw_init_, TYPE) (
|
||||
sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
|
||||
#endif
|
||||
|
||||
if (sw->info.is_float) {
|
||||
#ifdef DAC
|
||||
sw->conv = mixeng_conv_float[sw->info.nchannels == 2];
|
||||
sw->conv = mixeng_conv
|
||||
#else
|
||||
sw->clip = mixeng_clip_float[sw->info.nchannels == 2];
|
||||
sw->clip = mixeng_clip
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DAC
|
||||
sw->conv = mixeng_conv
|
||||
#else
|
||||
sw->clip = mixeng_clip
|
||||
#endif
|
||||
[sw->info.nchannels == 2]
|
||||
[sw->info.is_signed]
|
||||
[sw->info.swap_endianness]
|
||||
[audio_bits_to_index(sw->info.bits)];
|
||||
}
|
||||
[sw->info.nchannels == 2]
|
||||
[sw->info.sign]
|
||||
[sw->info.swap_endianness]
|
||||
[audio_bits_to_index (sw->info.bits)];
|
||||
|
||||
sw->name = g_strdup (name);
|
||||
err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
|
||||
@@ -284,23 +276,15 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (hw->info.is_float) {
|
||||
#ifdef DAC
|
||||
hw->clip = mixeng_clip_float[hw->info.nchannels == 2];
|
||||
hw->clip = mixeng_clip
|
||||
#else
|
||||
hw->conv = mixeng_conv_float[hw->info.nchannels == 2];
|
||||
hw->conv = mixeng_conv
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DAC
|
||||
hw->clip = mixeng_clip
|
||||
#else
|
||||
hw->conv = mixeng_conv
|
||||
#endif
|
||||
[hw->info.nchannels == 2]
|
||||
[hw->info.is_signed]
|
||||
[hw->info.swap_endianness]
|
||||
[audio_bits_to_index(hw->info.bits)];
|
||||
}
|
||||
[hw->info.nchannels == 2]
|
||||
[hw->info.sign]
|
||||
[hw->info.swap_endianness]
|
||||
[audio_bits_to_index (hw->info.bits)];
|
||||
|
||||
glue(audio_pcm_hw_alloc_resources_, TYPE)(hw);
|
||||
|
||||
@@ -330,8 +314,6 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
|
||||
dev->u.coreaudio.TYPE);
|
||||
case AUDIODEV_DRIVER_DSOUND:
|
||||
return dev->u.dsound.TYPE;
|
||||
case AUDIODEV_DRIVER_JACK:
|
||||
return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.TYPE);
|
||||
case AUDIODEV_DRIVER_OSS:
|
||||
return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE);
|
||||
case AUDIODEV_DRIVER_PA:
|
||||
|
||||
+25
-9
@@ -411,7 +411,7 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
|
||||
}
|
||||
COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
|
||||
(hw, size))
|
||||
COREAUDIO_WRAPPER_FUNC(put_buffer_out, size_t,
|
||||
COREAUDIO_WRAPPER_FUNC(put_buffer_out_nowrite, size_t,
|
||||
(HWVoiceOut *hw, void *buf, size_t size),
|
||||
(hw, buf, size))
|
||||
COREAUDIO_WRAPPER_FUNC(write, size_t, (HWVoiceOut *hw, void *buf, size_t size),
|
||||
@@ -471,6 +471,20 @@ static OSStatus audioDeviceIOProc(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UInt32 coreaudio_get_flags(struct audio_pcm_info *info,
|
||||
struct audsettings *as)
|
||||
{
|
||||
UInt32 flags = info->sign ? kAudioFormatFlagIsSignedInteger : 0;
|
||||
if (as->endianness) { /* 0 = little, 1 = big */
|
||||
flags |= kAudioFormatFlagIsBigEndian;
|
||||
}
|
||||
|
||||
if (flags == 0) { /* must not be 0 */
|
||||
flags = kAudioFormatFlagsAreAllClear;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
void *drv_opaque)
|
||||
{
|
||||
@@ -482,7 +496,6 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
Audiodev *dev = drv_opaque;
|
||||
AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
|
||||
int frames;
|
||||
struct audsettings fake_as;
|
||||
|
||||
/* create mutex */
|
||||
err = pthread_mutex_init(&core->mutex, NULL);
|
||||
@@ -491,9 +504,6 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
return -1;
|
||||
}
|
||||
|
||||
fake_as = *as;
|
||||
as = &fake_as;
|
||||
as->fmt = AUDIO_FORMAT_F32;
|
||||
audio_pcm_init_info (&hw->info, as);
|
||||
|
||||
status = coreaudio_get_voice(&core->outputDeviceID);
|
||||
@@ -562,6 +572,15 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
|
||||
/* set Samplerate */
|
||||
core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
|
||||
core->outputStreamBasicDescription.mFormatID = kAudioFormatLinearPCM;
|
||||
core->outputStreamBasicDescription.mFormatFlags =
|
||||
coreaudio_get_flags(&hw->info, as);
|
||||
core->outputStreamBasicDescription.mBytesPerPacket =
|
||||
core->outputStreamBasicDescription.mBytesPerFrame =
|
||||
hw->info.nchannels * hw->info.bits / 8;
|
||||
core->outputStreamBasicDescription.mFramesPerPacket = 1;
|
||||
core->outputStreamBasicDescription.mChannelsPerFrame = hw->info.nchannels;
|
||||
core->outputStreamBasicDescription.mBitsPerChannel = hw->info.bits;
|
||||
|
||||
status = coreaudio_set_streamformat(core->outputDeviceID,
|
||||
&core->outputStreamBasicDescription);
|
||||
@@ -668,12 +687,9 @@ static void coreaudio_audio_fini (void *opaque)
|
||||
static struct audio_pcm_ops coreaudio_pcm_ops = {
|
||||
.init_out = coreaudio_init_out,
|
||||
.fini_out = coreaudio_fini_out,
|
||||
/* wrapper for audio_generic_write */
|
||||
.write = coreaudio_write,
|
||||
/* wrapper for audio_generic_get_buffer_out */
|
||||
.get_buffer_out = coreaudio_get_buffer_out,
|
||||
/* wrapper for audio_generic_put_buffer_out */
|
||||
.put_buffer_out = coreaudio_put_buffer_out,
|
||||
.put_buffer_out = coreaudio_put_buffer_out_nowrite,
|
||||
.enable_out = coreaudio_enable_out
|
||||
};
|
||||
|
||||
|
||||
@@ -244,7 +244,6 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
goto fail0;
|
||||
}
|
||||
|
||||
ds->first_time = true;
|
||||
obt_as.endianness = 0;
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
|
||||
|
||||
+6
-30
@@ -53,14 +53,12 @@ typedef struct {
|
||||
typedef struct {
|
||||
HWVoiceOut hw;
|
||||
LPDIRECTSOUNDBUFFER dsound_buffer;
|
||||
bool first_time;
|
||||
dsound *s;
|
||||
} DSoundVoiceOut;
|
||||
|
||||
typedef struct {
|
||||
HWVoiceIn hw;
|
||||
LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
|
||||
bool first_time;
|
||||
dsound *s;
|
||||
} DSoundVoiceIn;
|
||||
|
||||
@@ -279,7 +277,7 @@ static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*statusp & DSBSTATUS_BUFFERLOST) {
|
||||
if (*statusp & DSERR_BUFFERLOST) {
|
||||
dsound_restore_out(dsb, s);
|
||||
return -1;
|
||||
}
|
||||
@@ -416,32 +414,21 @@ static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
|
||||
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
|
||||
LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
|
||||
HRESULT hr;
|
||||
DWORD ppos, wpos, act_size;
|
||||
DWORD ppos, act_size;
|
||||
size_t req_size;
|
||||
int err;
|
||||
void *ret;
|
||||
|
||||
hr = IDirectSoundBuffer_GetCurrentPosition(
|
||||
dsb, &ppos, ds->first_time ? &wpos : NULL);
|
||||
hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, NULL);
|
||||
if (FAILED(hr)) {
|
||||
dsound_logerr(hr, "Could not get playback buffer position\n");
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ds->first_time) {
|
||||
hw->pos_emul = wpos;
|
||||
ds->first_time = false;
|
||||
}
|
||||
|
||||
req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul);
|
||||
req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
|
||||
|
||||
if (req_size == 0) {
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
|
||||
&act_size, NULL, false, ds->s);
|
||||
if (err) {
|
||||
@@ -521,31 +508,20 @@ static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size)
|
||||
DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
|
||||
LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
|
||||
HRESULT hr;
|
||||
DWORD cpos, rpos, act_size;
|
||||
DWORD cpos, act_size;
|
||||
size_t req_size;
|
||||
int err;
|
||||
void *ret;
|
||||
|
||||
hr = IDirectSoundCaptureBuffer_GetCurrentPosition(
|
||||
dscb, &cpos, ds->first_time ? &rpos : NULL);
|
||||
hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, &cpos, NULL);
|
||||
if (FAILED(hr)) {
|
||||
dsound_logerr(hr, "Could not get capture buffer position\n");
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ds->first_time) {
|
||||
hw->pos_emul = rpos;
|
||||
ds->first_time = false;
|
||||
}
|
||||
|
||||
req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul);
|
||||
req_size = MIN(*size, MIN(req_size, hw->size_emul - hw->pos_emul));
|
||||
|
||||
if (req_size == 0) {
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
req_size = MIN(req_size, hw->size_emul - hw->pos_emul);
|
||||
|
||||
err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
|
||||
&act_size, NULL, false, ds->s);
|
||||
|
||||
@@ -1,694 +0,0 @@
|
||||
/*
|
||||
* QEMU JACK Audio Connection Kit Client
|
||||
*
|
||||
* Copyright (c) 2020 Geoffrey McRae (gnif)
|
||||
*
|
||||
* 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/module.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu-common.h"
|
||||
#include "audio.h"
|
||||
|
||||
#define AUDIO_CAP "jack"
|
||||
#include "audio_int.h"
|
||||
|
||||
#include <jack/jack.h>
|
||||
#include <jack/thread.h>
|
||||
|
||||
struct QJack;
|
||||
|
||||
typedef enum QJackState {
|
||||
QJACK_STATE_DISCONNECTED,
|
||||
QJACK_STATE_RUNNING,
|
||||
QJACK_STATE_SHUTDOWN
|
||||
}
|
||||
QJackState;
|
||||
|
||||
typedef struct QJackBuffer {
|
||||
int channels;
|
||||
int frames;
|
||||
uint32_t used;
|
||||
int rptr, wptr;
|
||||
float **data;
|
||||
}
|
||||
QJackBuffer;
|
||||
|
||||
typedef struct QJackClient {
|
||||
AudiodevJackPerDirectionOptions *opt;
|
||||
|
||||
bool out;
|
||||
bool enabled;
|
||||
bool connect_ports;
|
||||
int packets;
|
||||
|
||||
QJackState state;
|
||||
jack_client_t *client;
|
||||
jack_nframes_t freq;
|
||||
QEMUBH *shutdown_bh;
|
||||
|
||||
struct QJack *j;
|
||||
int nchannels;
|
||||
int buffersize;
|
||||
jack_port_t **port;
|
||||
QJackBuffer fifo;
|
||||
}
|
||||
QJackClient;
|
||||
|
||||
typedef struct QJackOut {
|
||||
HWVoiceOut hw;
|
||||
QJackClient c;
|
||||
}
|
||||
QJackOut;
|
||||
|
||||
typedef struct QJackIn {
|
||||
HWVoiceIn hw;
|
||||
QJackClient c;
|
||||
}
|
||||
QJackIn;
|
||||
|
||||
static int qjack_client_init(QJackClient *c);
|
||||
static void qjack_client_connect_ports(QJackClient *c);
|
||||
static void qjack_client_fini(QJackClient *c);
|
||||
static QemuMutex qjack_shutdown_lock;
|
||||
|
||||
static void qjack_buffer_create(QJackBuffer *buffer, int channels, int frames)
|
||||
{
|
||||
buffer->channels = channels;
|
||||
buffer->frames = frames;
|
||||
buffer->used = 0;
|
||||
buffer->rptr = 0;
|
||||
buffer->wptr = 0;
|
||||
buffer->data = g_malloc(channels * sizeof(float *));
|
||||
for (int i = 0; i < channels; ++i) {
|
||||
buffer->data[i] = g_malloc(frames * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
static void qjack_buffer_clear(QJackBuffer *buffer)
|
||||
{
|
||||
assert(buffer->data);
|
||||
qatomic_store_release(&buffer->used, 0);
|
||||
buffer->rptr = 0;
|
||||
buffer->wptr = 0;
|
||||
}
|
||||
|
||||
static void qjack_buffer_free(QJackBuffer *buffer)
|
||||
{
|
||||
if (!buffer->data) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < buffer->channels; ++i) {
|
||||
g_free(buffer->data[i]);
|
||||
}
|
||||
|
||||
g_free(buffer->data);
|
||||
buffer->data = NULL;
|
||||
}
|
||||
|
||||
/* write PCM interleaved */
|
||||
static int qjack_buffer_write(QJackBuffer *buffer, float *data, int size)
|
||||
{
|
||||
assert(buffer->data);
|
||||
const int samples = size / sizeof(float);
|
||||
int frames = samples / buffer->channels;
|
||||
const int avail = buffer->frames - qatomic_load_acquire(&buffer->used);
|
||||
|
||||
if (frames > avail) {
|
||||
frames = avail;
|
||||
}
|
||||
|
||||
int copy = frames;
|
||||
int wptr = buffer->wptr;
|
||||
|
||||
while (copy) {
|
||||
|
||||
for (int c = 0; c < buffer->channels; ++c) {
|
||||
buffer->data[c][wptr] = *data++;
|
||||
}
|
||||
|
||||
if (++wptr == buffer->frames) {
|
||||
wptr = 0;
|
||||
}
|
||||
|
||||
--copy;
|
||||
}
|
||||
|
||||
buffer->wptr = wptr;
|
||||
|
||||
qatomic_add(&buffer->used, frames);
|
||||
return frames * buffer->channels * sizeof(float);
|
||||
};
|
||||
|
||||
/* write PCM linear */
|
||||
static int qjack_buffer_write_l(QJackBuffer *buffer, float **dest, int frames)
|
||||
{
|
||||
assert(buffer->data);
|
||||
const int avail = buffer->frames - qatomic_load_acquire(&buffer->used);
|
||||
int wptr = buffer->wptr;
|
||||
|
||||
if (frames > avail) {
|
||||
frames = avail;
|
||||
}
|
||||
|
||||
int right = buffer->frames - wptr;
|
||||
if (right > frames) {
|
||||
right = frames;
|
||||
}
|
||||
|
||||
const int left = frames - right;
|
||||
for (int c = 0; c < buffer->channels; ++c) {
|
||||
memcpy(buffer->data[c] + wptr, dest[c] , right * sizeof(float));
|
||||
memcpy(buffer->data[c] , dest[c] + right, left * sizeof(float));
|
||||
}
|
||||
|
||||
wptr += frames;
|
||||
if (wptr >= buffer->frames) {
|
||||
wptr -= buffer->frames;
|
||||
}
|
||||
buffer->wptr = wptr;
|
||||
|
||||
qatomic_add(&buffer->used, frames);
|
||||
return frames;
|
||||
}
|
||||
|
||||
/* read PCM interleaved */
|
||||
static int qjack_buffer_read(QJackBuffer *buffer, float *dest, int size)
|
||||
{
|
||||
assert(buffer->data);
|
||||
const int samples = size / sizeof(float);
|
||||
int frames = samples / buffer->channels;
|
||||
const int avail = qatomic_load_acquire(&buffer->used);
|
||||
|
||||
if (frames > avail) {
|
||||
frames = avail;
|
||||
}
|
||||
|
||||
int copy = frames;
|
||||
int rptr = buffer->rptr;
|
||||
|
||||
while (copy) {
|
||||
|
||||
for (int c = 0; c < buffer->channels; ++c) {
|
||||
*dest++ = buffer->data[c][rptr];
|
||||
}
|
||||
|
||||
if (++rptr == buffer->frames) {
|
||||
rptr = 0;
|
||||
}
|
||||
|
||||
--copy;
|
||||
}
|
||||
|
||||
buffer->rptr = rptr;
|
||||
|
||||
qatomic_sub(&buffer->used, frames);
|
||||
return frames * buffer->channels * sizeof(float);
|
||||
}
|
||||
|
||||
/* read PCM linear */
|
||||
static int qjack_buffer_read_l(QJackBuffer *buffer, float **dest, int frames)
|
||||
{
|
||||
assert(buffer->data);
|
||||
int copy = frames;
|
||||
const int used = qatomic_load_acquire(&buffer->used);
|
||||
int rptr = buffer->rptr;
|
||||
|
||||
if (copy > used) {
|
||||
copy = used;
|
||||
}
|
||||
|
||||
int right = buffer->frames - rptr;
|
||||
if (right > copy) {
|
||||
right = copy;
|
||||
}
|
||||
|
||||
const int left = copy - right;
|
||||
for (int c = 0; c < buffer->channels; ++c) {
|
||||
memcpy(dest[c] , buffer->data[c] + rptr, right * sizeof(float));
|
||||
memcpy(dest[c] + right, buffer->data[c] , left * sizeof(float));
|
||||
}
|
||||
|
||||
rptr += copy;
|
||||
if (rptr >= buffer->frames) {
|
||||
rptr -= buffer->frames;
|
||||
}
|
||||
buffer->rptr = rptr;
|
||||
|
||||
qatomic_sub(&buffer->used, copy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
static int qjack_process(jack_nframes_t nframes, void *arg)
|
||||
{
|
||||
QJackClient *c = (QJackClient *)arg;
|
||||
|
||||
if (c->state != QJACK_STATE_RUNNING) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get the buffers for the ports */
|
||||
float *buffers[c->nchannels];
|
||||
for (int i = 0; i < c->nchannels; ++i) {
|
||||
buffers[i] = jack_port_get_buffer(c->port[i], nframes);
|
||||
}
|
||||
|
||||
if (c->out) {
|
||||
if (likely(c->enabled)) {
|
||||
qjack_buffer_read_l(&c->fifo, buffers, nframes);
|
||||
} else {
|
||||
for(int i = 0; i < c->nchannels; ++i) {
|
||||
memset(buffers[i], 0, nframes * sizeof(float));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (likely(c->enabled)) {
|
||||
qjack_buffer_write_l(&c->fifo, buffers, nframes);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qjack_port_registration(jack_port_id_t port, int reg, void *arg)
|
||||
{
|
||||
if (reg) {
|
||||
QJackClient *c = (QJackClient *)arg;
|
||||
c->connect_ports = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int qjack_xrun(void *arg)
|
||||
{
|
||||
QJackClient *c = (QJackClient *)arg;
|
||||
if (c->state != QJACK_STATE_RUNNING) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
qjack_buffer_clear(&c->fifo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qjack_shutdown_bh(void *opaque)
|
||||
{
|
||||
QJackClient *c = (QJackClient *)opaque;
|
||||
qjack_client_fini(c);
|
||||
}
|
||||
|
||||
static void qjack_shutdown(void *arg)
|
||||
{
|
||||
QJackClient *c = (QJackClient *)arg;
|
||||
c->state = QJACK_STATE_SHUTDOWN;
|
||||
qemu_bh_schedule(c->shutdown_bh);
|
||||
}
|
||||
|
||||
static void qjack_client_recover(QJackClient *c)
|
||||
{
|
||||
if (c->state != QJACK_STATE_DISCONNECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* packets is used simply to throttle this */
|
||||
if (c->packets % 100 == 0) {
|
||||
|
||||
/* if enabled then attempt to recover */
|
||||
if (c->enabled) {
|
||||
dolog("attempting to reconnect to server\n");
|
||||
qjack_client_init(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static size_t qjack_write(HWVoiceOut *hw, void *buf, size_t len)
|
||||
{
|
||||
QJackOut *jo = (QJackOut *)hw;
|
||||
++jo->c.packets;
|
||||
|
||||
if (jo->c.state != QJACK_STATE_RUNNING) {
|
||||
qjack_client_recover(&jo->c);
|
||||
return len;
|
||||
}
|
||||
|
||||
qjack_client_connect_ports(&jo->c);
|
||||
return qjack_buffer_write(&jo->c.fifo, buf, len);
|
||||
}
|
||||
|
||||
static size_t qjack_read(HWVoiceIn *hw, void *buf, size_t len)
|
||||
{
|
||||
QJackIn *ji = (QJackIn *)hw;
|
||||
++ji->c.packets;
|
||||
|
||||
if (ji->c.state != QJACK_STATE_RUNNING) {
|
||||
qjack_client_recover(&ji->c);
|
||||
return len;
|
||||
}
|
||||
|
||||
qjack_client_connect_ports(&ji->c);
|
||||
return qjack_buffer_read(&ji->c.fifo, buf, len);
|
||||
}
|
||||
|
||||
static void qjack_client_connect_ports(QJackClient *c)
|
||||
{
|
||||
if (!c->connect_ports || !c->opt->connect_ports) {
|
||||
return;
|
||||
}
|
||||
|
||||
c->connect_ports = false;
|
||||
const char **ports;
|
||||
ports = jack_get_ports(c->client, c->opt->connect_ports, NULL,
|
||||
c->out ? JackPortIsInput : JackPortIsOutput);
|
||||
|
||||
if (!ports) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < c->nchannels && ports[i]; ++i) {
|
||||
const char *p = jack_port_name(c->port[i]);
|
||||
if (jack_port_connected_to(c->port[i], ports[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->out) {
|
||||
dolog("connect %s -> %s\n", p, ports[i]);
|
||||
jack_connect(c->client, p, ports[i]);
|
||||
} else {
|
||||
dolog("connect %s -> %s\n", ports[i], p);
|
||||
jack_connect(c->client, ports[i], p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int qjack_client_init(QJackClient *c)
|
||||
{
|
||||
jack_status_t status;
|
||||
char client_name[jack_client_name_size()];
|
||||
jack_options_t options = JackNullOption;
|
||||
|
||||
if (c->state == QJACK_STATE_RUNNING) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->connect_ports = true;
|
||||
|
||||
snprintf(client_name, sizeof(client_name), "%s-%s",
|
||||
c->out ? "out" : "in",
|
||||
c->opt->client_name ? c->opt->client_name : qemu_get_vm_name());
|
||||
|
||||
if (c->opt->exact_name) {
|
||||
options |= JackUseExactName;
|
||||
}
|
||||
|
||||
if (!c->opt->start_server) {
|
||||
options |= JackNoStartServer;
|
||||
}
|
||||
|
||||
if (c->opt->server_name) {
|
||||
options |= JackServerName;
|
||||
}
|
||||
|
||||
c->client = jack_client_open(client_name, options, &status,
|
||||
c->opt->server_name);
|
||||
|
||||
if (c->client == NULL) {
|
||||
dolog("jack_client_open failed: status = 0x%2.0x\n", status);
|
||||
if (status & JackServerFailed) {
|
||||
dolog("unable to connect to JACK server\n");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->freq = jack_get_sample_rate(c->client);
|
||||
|
||||
if (status & JackServerStarted) {
|
||||
dolog("JACK server started\n");
|
||||
}
|
||||
|
||||
if (status & JackNameNotUnique) {
|
||||
dolog("JACK unique name assigned %s\n",
|
||||
jack_get_client_name(c->client));
|
||||
}
|
||||
|
||||
jack_set_process_callback(c->client, qjack_process , c);
|
||||
jack_set_port_registration_callback(c->client, qjack_port_registration, c);
|
||||
jack_set_xrun_callback(c->client, qjack_xrun, c);
|
||||
jack_on_shutdown(c->client, qjack_shutdown, c);
|
||||
|
||||
/* allocate and register the ports */
|
||||
c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels);
|
||||
for (int i = 0; i < c->nchannels; ++i) {
|
||||
|
||||
char port_name[16];
|
||||
snprintf(
|
||||
port_name,
|
||||
sizeof(port_name),
|
||||
c->out ? "output %d" : "input %d",
|
||||
i);
|
||||
|
||||
c->port[i] = jack_port_register(
|
||||
c->client,
|
||||
port_name,
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
c->out ? JackPortIsOutput : JackPortIsInput,
|
||||
0);
|
||||
}
|
||||
|
||||
/* activate the session */
|
||||
jack_activate(c->client);
|
||||
c->buffersize = jack_get_buffer_size(c->client);
|
||||
|
||||
/*
|
||||
* ensure the buffersize is no smaller then 512 samples, some (all?) qemu
|
||||
* virtual devices do not work correctly otherwise
|
||||
*/
|
||||
if (c->buffersize < 512) {
|
||||
c->buffersize = 512;
|
||||
}
|
||||
|
||||
/* create a 2 period buffer */
|
||||
qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 2);
|
||||
|
||||
qjack_client_connect_ports(c);
|
||||
c->state = QJACK_STATE_RUNNING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
void *drv_opaque)
|
||||
{
|
||||
QJackOut *jo = (QJackOut *)hw;
|
||||
Audiodev *dev = (Audiodev *)drv_opaque;
|
||||
|
||||
jo->c.out = true;
|
||||
jo->c.enabled = false;
|
||||
jo->c.nchannels = as->nchannels;
|
||||
jo->c.opt = dev->u.jack.out;
|
||||
|
||||
jo->c.shutdown_bh = qemu_bh_new(qjack_shutdown_bh, &jo->c);
|
||||
|
||||
int ret = qjack_client_init(&jo->c);
|
||||
if (ret != 0) {
|
||||
qemu_bh_delete(jo->c.shutdown_bh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* report the buffer size to qemu */
|
||||
hw->samples = jo->c.buffersize;
|
||||
|
||||
/* report the audio format we support */
|
||||
struct audsettings os = {
|
||||
.freq = jo->c.freq,
|
||||
.nchannels = jo->c.nchannels,
|
||||
.fmt = AUDIO_FORMAT_F32,
|
||||
.endianness = 0
|
||||
};
|
||||
audio_pcm_init_info(&hw->info, &os);
|
||||
|
||||
dolog("JACK output configured for %dHz (%d samples)\n",
|
||||
jo->c.freq, jo->c.buffersize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as,
|
||||
void *drv_opaque)
|
||||
{
|
||||
QJackIn *ji = (QJackIn *)hw;
|
||||
Audiodev *dev = (Audiodev *)drv_opaque;
|
||||
|
||||
ji->c.out = false;
|
||||
ji->c.enabled = false;
|
||||
ji->c.nchannels = as->nchannels;
|
||||
ji->c.opt = dev->u.jack.in;
|
||||
|
||||
ji->c.shutdown_bh = qemu_bh_new(qjack_shutdown_bh, &ji->c);
|
||||
|
||||
int ret = qjack_client_init(&ji->c);
|
||||
if (ret != 0) {
|
||||
qemu_bh_delete(ji->c.shutdown_bh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* report the buffer size to qemu */
|
||||
hw->samples = ji->c.buffersize;
|
||||
|
||||
/* report the audio format we support */
|
||||
struct audsettings is = {
|
||||
.freq = ji->c.freq,
|
||||
.nchannels = ji->c.nchannels,
|
||||
.fmt = AUDIO_FORMAT_F32,
|
||||
.endianness = 0
|
||||
};
|
||||
audio_pcm_init_info(&hw->info, &is);
|
||||
|
||||
dolog("JACK input configured for %dHz (%d samples)\n",
|
||||
ji->c.freq, ji->c.buffersize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qjack_client_fini_locked(QJackClient *c)
|
||||
{
|
||||
switch (c->state) {
|
||||
case QJACK_STATE_RUNNING:
|
||||
jack_deactivate(c->client);
|
||||
/* fallthrough */
|
||||
|
||||
case QJACK_STATE_SHUTDOWN:
|
||||
jack_client_close(c->client);
|
||||
c->client = NULL;
|
||||
|
||||
qjack_buffer_free(&c->fifo);
|
||||
g_free(c->port);
|
||||
|
||||
c->state = QJACK_STATE_DISCONNECTED;
|
||||
/* fallthrough */
|
||||
|
||||
case QJACK_STATE_DISCONNECTED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void qjack_client_fini(QJackClient *c)
|
||||
{
|
||||
qemu_mutex_lock(&qjack_shutdown_lock);
|
||||
qjack_client_fini_locked(c);
|
||||
qemu_mutex_unlock(&qjack_shutdown_lock);
|
||||
}
|
||||
|
||||
static void qjack_fini_out(HWVoiceOut *hw)
|
||||
{
|
||||
QJackOut *jo = (QJackOut *)hw;
|
||||
qjack_client_fini(&jo->c);
|
||||
|
||||
qemu_bh_delete(jo->c.shutdown_bh);
|
||||
}
|
||||
|
||||
static void qjack_fini_in(HWVoiceIn *hw)
|
||||
{
|
||||
QJackIn *ji = (QJackIn *)hw;
|
||||
qjack_client_fini(&ji->c);
|
||||
|
||||
qemu_bh_delete(ji->c.shutdown_bh);
|
||||
}
|
||||
|
||||
static void qjack_enable_out(HWVoiceOut *hw, bool enable)
|
||||
{
|
||||
QJackOut *jo = (QJackOut *)hw;
|
||||
jo->c.enabled = enable;
|
||||
}
|
||||
|
||||
static void qjack_enable_in(HWVoiceIn *hw, bool enable)
|
||||
{
|
||||
QJackIn *ji = (QJackIn *)hw;
|
||||
ji->c.enabled = enable;
|
||||
}
|
||||
|
||||
static int qjack_thread_creator(jack_native_thread_t *thread,
|
||||
const pthread_attr_t *attr, void *(*function)(void *), void *arg)
|
||||
{
|
||||
int ret = pthread_create(thread, attr, function, arg);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set the name of the thread */
|
||||
pthread_setname_np(*thread, "jack-client");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *qjack_init(Audiodev *dev)
|
||||
{
|
||||
assert(dev->driver == AUDIODEV_DRIVER_JACK);
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void qjack_fini(void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
static struct audio_pcm_ops jack_pcm_ops = {
|
||||
.init_out = qjack_init_out,
|
||||
.fini_out = qjack_fini_out,
|
||||
.write = qjack_write,
|
||||
.run_buffer_out = audio_generic_run_buffer_out,
|
||||
.enable_out = qjack_enable_out,
|
||||
|
||||
.init_in = qjack_init_in,
|
||||
.fini_in = qjack_fini_in,
|
||||
.read = qjack_read,
|
||||
.enable_in = qjack_enable_in
|
||||
};
|
||||
|
||||
static struct audio_driver jack_driver = {
|
||||
.name = "jack",
|
||||
.descr = "JACK Audio Connection Kit Client",
|
||||
.init = qjack_init,
|
||||
.fini = qjack_fini,
|
||||
.pcm_ops = &jack_pcm_ops,
|
||||
.can_be_default = 1,
|
||||
.max_voices_out = INT_MAX,
|
||||
.max_voices_in = INT_MAX,
|
||||
.voice_size_out = sizeof(QJackOut),
|
||||
.voice_size_in = sizeof(QJackIn)
|
||||
};
|
||||
|
||||
static void qjack_error(const char *msg)
|
||||
{
|
||||
dolog("E: %s\n", msg);
|
||||
}
|
||||
|
||||
static void qjack_info(const char *msg)
|
||||
{
|
||||
dolog("I: %s\n", msg);
|
||||
}
|
||||
|
||||
static void register_audio_jack(void)
|
||||
{
|
||||
qemu_mutex_init(&qjack_shutdown_lock);
|
||||
audio_driver_register(&jack_driver);
|
||||
jack_set_thread_creator(qjack_thread_creator);
|
||||
jack_set_error_function(qjack_error);
|
||||
jack_set_info_function(qjack_info);
|
||||
}
|
||||
type_init(register_audio_jack);
|
||||
@@ -1,30 +0,0 @@
|
||||
softmmu_ss.add([spice_headers, files('audio.c')])
|
||||
softmmu_ss.add(files(
|
||||
'audio_legacy.c',
|
||||
'mixeng.c',
|
||||
'noaudio.c',
|
||||
'wavaudio.c',
|
||||
'wavcapture.c',
|
||||
))
|
||||
|
||||
softmmu_ss.add(when: [coreaudio, 'CONFIG_AUDIO_COREAUDIO'], if_true: files('coreaudio.c'))
|
||||
softmmu_ss.add(when: [dsound, 'CONFIG_AUDIO_DSOUND'], if_true: files('dsoundaudio.c'))
|
||||
softmmu_ss.add(when: ['CONFIG_AUDIO_WIN_INT'], if_true: files('audio_win_int.c'))
|
||||
|
||||
audio_modules = {}
|
||||
foreach m : [
|
||||
['CONFIG_AUDIO_ALSA', 'alsa', alsa, 'alsaaudio.c'],
|
||||
['CONFIG_AUDIO_OSS', 'oss', oss, 'ossaudio.c'],
|
||||
['CONFIG_AUDIO_PA', 'pa', pulse, 'paaudio.c'],
|
||||
['CONFIG_AUDIO_SDL', 'sdl', sdl, 'sdlaudio.c'],
|
||||
['CONFIG_AUDIO_JACK', 'jack', jack, 'jackaudio.c'],
|
||||
['CONFIG_SPICE', 'spice', spice, 'spiceaudio.c']
|
||||
]
|
||||
if config_host.has_key(m[0])
|
||||
module_ss = ss.source_set()
|
||||
module_ss.add(when: m[2], if_true: files(m[3]))
|
||||
audio_modules += {m[1] : module_ss}
|
||||
endif
|
||||
endforeach
|
||||
|
||||
modules += {'audio': audio_modules}
|
||||
+2
-73
@@ -267,82 +267,11 @@ f_sample *mixeng_clip[2][2][2][3] = {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef FLOAT_MIXENG
|
||||
#define CONV_NATURAL_FLOAT(x) (x)
|
||||
#define CLIP_NATURAL_FLOAT(x) (x)
|
||||
#else
|
||||
/* macros to map [-1.f, 1.f] <-> [INT32_MIN, INT32_MAX + 1] */
|
||||
static const float float_scale = (int64_t)INT32_MAX + 1;
|
||||
#define CONV_NATURAL_FLOAT(x) ((x) * float_scale)
|
||||
|
||||
#ifdef RECIPROCAL
|
||||
static const float float_scale_reciprocal = 1.f / ((int64_t)INT32_MAX + 1);
|
||||
#define CLIP_NATURAL_FLOAT(x) ((x) * float_scale_reciprocal)
|
||||
#else
|
||||
#define CLIP_NATURAL_FLOAT(x) ((x) / float_scale)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void conv_natural_float_to_mono(struct st_sample *dst, const void *src,
|
||||
int samples)
|
||||
{
|
||||
float *in = (float *)src;
|
||||
|
||||
while (samples--) {
|
||||
dst->r = dst->l = CONV_NATURAL_FLOAT(*in++);
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
static void conv_natural_float_to_stereo(struct st_sample *dst, const void *src,
|
||||
int samples)
|
||||
{
|
||||
float *in = (float *)src;
|
||||
|
||||
while (samples--) {
|
||||
dst->l = CONV_NATURAL_FLOAT(*in++);
|
||||
dst->r = CONV_NATURAL_FLOAT(*in++);
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
t_sample *mixeng_conv_float[2] = {
|
||||
conv_natural_float_to_mono,
|
||||
conv_natural_float_to_stereo,
|
||||
};
|
||||
|
||||
static void clip_natural_float_from_mono(void *dst, const struct st_sample *src,
|
||||
int samples)
|
||||
{
|
||||
float *out = (float *)dst;
|
||||
|
||||
while (samples--) {
|
||||
*out++ = CLIP_NATURAL_FLOAT(src->l + src->r);
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
static void clip_natural_float_from_stereo(
|
||||
void *dst, const struct st_sample *src, int samples)
|
||||
{
|
||||
float *out = (float *)dst;
|
||||
|
||||
while (samples--) {
|
||||
*out++ = CLIP_NATURAL_FLOAT(src->l);
|
||||
*out++ = CLIP_NATURAL_FLOAT(src->r);
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
f_sample *mixeng_clip_float[2] = {
|
||||
clip_natural_float_from_mono,
|
||||
clip_natural_float_from_stereo,
|
||||
};
|
||||
|
||||
void audio_sample_to_uint64(const void *samples, int pos,
|
||||
void audio_sample_to_uint64(void *samples, int pos,
|
||||
uint64_t *left, uint64_t *right)
|
||||
{
|
||||
const struct st_sample *sample = samples;
|
||||
struct st_sample *sample = samples;
|
||||
sample += pos;
|
||||
#ifdef FLOAT_MIXENG
|
||||
error_report(
|
||||
|
||||
@@ -38,14 +38,9 @@ typedef struct st_sample st_sample;
|
||||
typedef void (t_sample) (struct st_sample *dst, const void *src, int samples);
|
||||
typedef void (f_sample) (void *dst, const struct st_sample *src, int samples);
|
||||
|
||||
/* indices: [stereo][signed][swap endiannes][8, 16 or 32-bits] */
|
||||
extern t_sample *mixeng_conv[2][2][2][3];
|
||||
extern f_sample *mixeng_clip[2][2][2][3];
|
||||
|
||||
/* indices: [stereo] */
|
||||
extern t_sample *mixeng_conv_float[2];
|
||||
extern f_sample *mixeng_clip_float[2];
|
||||
|
||||
void *st_rate_start (int inrate, int outrate);
|
||||
void st_rate_flow(void *opaque, st_sample *ibuf, st_sample *obuf,
|
||||
size_t *isamp, size_t *osamp);
|
||||
|
||||
+12
-10
@@ -41,31 +41,32 @@ static inline mixeng_real glue (conv_, ET) (IN_T v)
|
||||
|
||||
#ifdef RECIPROCAL
|
||||
#ifdef SIGNED
|
||||
return nv * (2.f / ((mixeng_real)IN_MAX - IN_MIN));
|
||||
return nv * (1.f / (mixeng_real) (IN_MAX - IN_MIN));
|
||||
#else
|
||||
return (nv - HALF) * (2.f / (mixeng_real)IN_MAX);
|
||||
return (nv - HALF) * (1.f / (mixeng_real) IN_MAX);
|
||||
#endif
|
||||
#else /* !RECIPROCAL */
|
||||
#ifdef SIGNED
|
||||
return nv / (((mixeng_real)IN_MAX - IN_MIN) / 2.f);
|
||||
return nv / (mixeng_real) ((mixeng_real) IN_MAX - IN_MIN);
|
||||
#else
|
||||
return (nv - HALF) / ((mixeng_real)IN_MAX / 2.f);
|
||||
return (nv - HALF) / (mixeng_real) IN_MAX;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline IN_T glue (clip_, ET) (mixeng_real v)
|
||||
{
|
||||
if (v >= 1.f) {
|
||||
if (v >= 0.5) {
|
||||
return IN_MAX;
|
||||
} else if (v < -1.f) {
|
||||
}
|
||||
else if (v < -0.5) {
|
||||
return IN_MIN;
|
||||
}
|
||||
|
||||
#ifdef SIGNED
|
||||
return ENDIAN_CONVERT((IN_T)(v * (((mixeng_real)IN_MAX - IN_MIN) / 2.f)));
|
||||
return ENDIAN_CONVERT ((IN_T) (v * ((mixeng_real) IN_MAX - IN_MIN)));
|
||||
#else
|
||||
return ENDIAN_CONVERT((IN_T)((v * ((mixeng_real)IN_MAX / 2.f)) + HALF));
|
||||
return ENDIAN_CONVERT ((IN_T) ((v * IN_MAX) + HALF));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -83,9 +84,10 @@ static inline int64_t glue (conv_, ET) (IN_T v)
|
||||
|
||||
static inline IN_T glue (clip_, ET) (int64_t v)
|
||||
{
|
||||
if (v >= 0x7fffffffLL) {
|
||||
if (v >= 0x7f000000) {
|
||||
return IN_MAX;
|
||||
} else if (v < -2147483648LL) {
|
||||
}
|
||||
else if (v < -2147483648LL) {
|
||||
return IN_MIN;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,7 +118,6 @@ static struct audio_pcm_ops no_pcm_ops = {
|
||||
.init_out = no_init_out,
|
||||
.fini_out = no_fini_out,
|
||||
.write = no_write,
|
||||
.run_buffer_out = audio_generic_run_buffer_out,
|
||||
.enable_out = no_enable_out,
|
||||
|
||||
.init_in = no_init_in,
|
||||
|
||||
+10
-17
@@ -382,15 +382,6 @@ static size_t oss_get_available_bytes(OSSVoiceOut *oss)
|
||||
return audio_ring_dist(cntinfo.ptr, oss->hw.pos_emul, oss->hw.size_emul);
|
||||
}
|
||||
|
||||
static void oss_run_buffer_out(HWVoiceOut *hw)
|
||||
{
|
||||
OSSVoiceOut *oss = (OSSVoiceOut *)hw;
|
||||
|
||||
if (!oss->mmapped) {
|
||||
audio_generic_run_buffer_out(hw);
|
||||
}
|
||||
}
|
||||
|
||||
static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size)
|
||||
{
|
||||
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
|
||||
@@ -579,18 +570,20 @@ static void oss_enable_out(HWVoiceOut *hw, bool enable)
|
||||
AudiodevOssPerDirectionOptions *opdo = oss->dev->u.oss.out;
|
||||
|
||||
if (enable) {
|
||||
hw->poll_mode = opdo->try_poll;
|
||||
bool poll_mode = opdo->try_poll;
|
||||
|
||||
ldebug("enabling voice\n");
|
||||
if (hw->poll_mode) {
|
||||
if (poll_mode) {
|
||||
oss_poll_out(hw);
|
||||
poll_mode = 0;
|
||||
}
|
||||
hw->poll_mode = poll_mode;
|
||||
|
||||
if (!oss->mmapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->samples);
|
||||
audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->mix_buf->size);
|
||||
trig = PCM_ENABLE_OUTPUT;
|
||||
if (ioctl(oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
|
||||
oss_logerr(errno,
|
||||
@@ -691,7 +684,6 @@ static size_t oss_read(HWVoiceIn *hw, void *buf, size_t len)
|
||||
len, dst);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
pos += nread;
|
||||
@@ -707,15 +699,17 @@ static void oss_enable_in(HWVoiceIn *hw, bool enable)
|
||||
AudiodevOssPerDirectionOptions *opdo = oss->dev->u.oss.out;
|
||||
|
||||
if (enable) {
|
||||
hw->poll_mode = opdo->try_poll;
|
||||
bool poll_mode = opdo->try_poll;
|
||||
|
||||
if (hw->poll_mode) {
|
||||
if (poll_mode) {
|
||||
oss_poll_in(hw);
|
||||
poll_mode = 0;
|
||||
}
|
||||
hw->poll_mode = poll_mode;
|
||||
} else {
|
||||
if (hw->poll_mode) {
|
||||
qemu_set_fd_handler (oss->fd, NULL, NULL, NULL);
|
||||
hw->poll_mode = 0;
|
||||
qemu_set_fd_handler (oss->fd, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -754,7 +748,6 @@ static struct audio_pcm_ops oss_pcm_ops = {
|
||||
.init_out = oss_init_out,
|
||||
.fini_out = oss_fini_out,
|
||||
.write = oss_write,
|
||||
.run_buffer_out = oss_run_buffer_out,
|
||||
.get_buffer_out = oss_get_buffer_out,
|
||||
.put_buffer_out = oss_put_buffer_out,
|
||||
.enable_out = oss_enable_out,
|
||||
|
||||
+24
-59
@@ -32,6 +32,7 @@ typedef struct {
|
||||
HWVoiceOut hw;
|
||||
pa_stream *stream;
|
||||
paaudio *g;
|
||||
size_t samples;
|
||||
} PAVoiceOut;
|
||||
|
||||
typedef struct {
|
||||
@@ -40,6 +41,7 @@ typedef struct {
|
||||
const void *read_data;
|
||||
size_t read_length;
|
||||
paaudio *g;
|
||||
size_t samples;
|
||||
} PAVoiceIn;
|
||||
|
||||
static void qpa_conn_fini(PAConnection *c);
|
||||
@@ -154,48 +156,34 @@ static size_t qpa_read(HWVoiceIn *hw, void *data, size_t length)
|
||||
{
|
||||
PAVoiceIn *p = (PAVoiceIn *) hw;
|
||||
PAConnection *c = p->g->conn;
|
||||
size_t total = 0;
|
||||
size_t l;
|
||||
int r;
|
||||
|
||||
pa_threaded_mainloop_lock(c->mainloop);
|
||||
|
||||
CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
|
||||
"pa_threaded_mainloop_lock failed\n");
|
||||
if (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
|
||||
/* wait for stream to become ready */
|
||||
goto unlock;
|
||||
|
||||
if (!p->read_length) {
|
||||
r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
|
||||
CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
|
||||
"pa_stream_peek failed\n");
|
||||
}
|
||||
|
||||
while (total < length) {
|
||||
size_t l;
|
||||
int r;
|
||||
l = MIN(p->read_length, length);
|
||||
memcpy(data, p->read_data, l);
|
||||
|
||||
if (!p->read_length) {
|
||||
r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
|
||||
CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
|
||||
"pa_stream_peek failed\n");
|
||||
if (!p->read_length) {
|
||||
/* buffer is empty */
|
||||
break;
|
||||
}
|
||||
}
|
||||
p->read_data += l;
|
||||
p->read_length -= l;
|
||||
|
||||
l = MIN(p->read_length, length - total);
|
||||
memcpy((char *)data + total, p->read_data, l);
|
||||
|
||||
p->read_data += l;
|
||||
p->read_length -= l;
|
||||
total += l;
|
||||
|
||||
if (!p->read_length) {
|
||||
r = pa_stream_drop(p->stream);
|
||||
CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
|
||||
"pa_stream_drop failed\n");
|
||||
}
|
||||
if (!p->read_length) {
|
||||
r = pa_stream_drop(p->stream);
|
||||
CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
|
||||
"pa_stream_drop failed\n");
|
||||
}
|
||||
|
||||
unlock:
|
||||
pa_threaded_mainloop_unlock(c->mainloop);
|
||||
return total;
|
||||
return l;
|
||||
|
||||
unlock_and_fail:
|
||||
pa_threaded_mainloop_unlock(c->mainloop);
|
||||
@@ -277,9 +265,6 @@ static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness)
|
||||
case AUDIO_FORMAT_U32:
|
||||
format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
|
||||
break;
|
||||
case AUDIO_FORMAT_F32:
|
||||
format = endianness ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE;
|
||||
break;
|
||||
default:
|
||||
dolog ("Internal logic error: Bad audio format %d\n", afmt);
|
||||
format = PA_SAMPLE_U8;
|
||||
@@ -305,12 +290,6 @@ static AudioFormat pa_to_audfmt (pa_sample_format_t fmt, int *endianness)
|
||||
case PA_SAMPLE_S32LE:
|
||||
*endianness = 0;
|
||||
return AUDIO_FORMAT_S32;
|
||||
case PA_SAMPLE_FLOAT32BE:
|
||||
*endianness = 1;
|
||||
return AUDIO_FORMAT_F32;
|
||||
case PA_SAMPLE_FLOAT32LE:
|
||||
*endianness = 0;
|
||||
return AUDIO_FORMAT_F32;
|
||||
default:
|
||||
dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt);
|
||||
return AUDIO_FORMAT_U8;
|
||||
@@ -495,7 +474,7 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
}
|
||||
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
hw->samples = audio_buffer_samples(
|
||||
hw->samples = pa->samples = audio_buffer_samples(
|
||||
qapi_AudiodevPaPerDirectionOptions_base(ppdo),
|
||||
&obt_as, ppdo->buffer_length);
|
||||
|
||||
@@ -543,7 +522,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
|
||||
}
|
||||
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
hw->samples = audio_buffer_samples(
|
||||
hw->samples = pa->samples = audio_buffer_samples(
|
||||
qapi_AudiodevPaPerDirectionOptions_base(ppdo),
|
||||
&obt_as, ppdo->buffer_length);
|
||||
|
||||
@@ -557,6 +536,7 @@ static void qpa_simple_disconnect(PAConnection *c, pa_stream *stream)
|
||||
{
|
||||
int err;
|
||||
|
||||
pa_threaded_mainloop_lock(c->mainloop);
|
||||
/*
|
||||
* wait until actually connects. workaround pa bug #247
|
||||
* https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/247
|
||||
@@ -570,6 +550,7 @@ static void qpa_simple_disconnect(PAConnection *c, pa_stream *stream)
|
||||
dolog("Failed to disconnect! err=%d\n", err);
|
||||
}
|
||||
pa_stream_unref(stream);
|
||||
pa_threaded_mainloop_unlock(c->mainloop);
|
||||
}
|
||||
|
||||
static void qpa_fini_out (HWVoiceOut *hw)
|
||||
@@ -577,12 +558,8 @@ static void qpa_fini_out (HWVoiceOut *hw)
|
||||
PAVoiceOut *pa = (PAVoiceOut *) hw;
|
||||
|
||||
if (pa->stream) {
|
||||
PAConnection *c = pa->g->conn;
|
||||
|
||||
pa_threaded_mainloop_lock(c->mainloop);
|
||||
qpa_simple_disconnect(c, pa->stream);
|
||||
qpa_simple_disconnect(pa->g->conn, pa->stream);
|
||||
pa->stream = NULL;
|
||||
pa_threaded_mainloop_unlock(c->mainloop);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,20 +568,8 @@ static void qpa_fini_in (HWVoiceIn *hw)
|
||||
PAVoiceIn *pa = (PAVoiceIn *) hw;
|
||||
|
||||
if (pa->stream) {
|
||||
PAConnection *c = pa->g->conn;
|
||||
|
||||
pa_threaded_mainloop_lock(c->mainloop);
|
||||
if (pa->read_length) {
|
||||
int r = pa_stream_drop(pa->stream);
|
||||
if (r) {
|
||||
qpa_logerr(pa_context_errno(c->context),
|
||||
"pa_stream_drop failed\n");
|
||||
}
|
||||
pa->read_length = 0;
|
||||
}
|
||||
qpa_simple_disconnect(c, pa->stream);
|
||||
qpa_simple_disconnect(pa->g->conn, pa->stream);
|
||||
pa->stream = NULL;
|
||||
pa_threaded_mainloop_unlock(c->mainloop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-33
@@ -77,14 +77,6 @@ static int aud_to_sdlfmt (AudioFormat fmt)
|
||||
case AUDIO_FORMAT_U16:
|
||||
return AUDIO_U16LSB;
|
||||
|
||||
case AUDIO_FORMAT_S32:
|
||||
return AUDIO_S32LSB;
|
||||
|
||||
/* no unsigned 32-bit support in SDL */
|
||||
|
||||
case AUDIO_FORMAT_F32:
|
||||
return AUDIO_F32LSB;
|
||||
|
||||
default:
|
||||
dolog ("Internal logic error: Bad audio format %d\n", fmt);
|
||||
#ifdef DEBUG_AUDIO
|
||||
@@ -127,26 +119,6 @@ static int sdl_to_audfmt(int sdlfmt, AudioFormat *fmt, int *endianness)
|
||||
*fmt = AUDIO_FORMAT_U16;
|
||||
break;
|
||||
|
||||
case AUDIO_S32LSB:
|
||||
*endianness = 0;
|
||||
*fmt = AUDIO_FORMAT_S32;
|
||||
break;
|
||||
|
||||
case AUDIO_S32MSB:
|
||||
*endianness = 1;
|
||||
*fmt = AUDIO_FORMAT_S32;
|
||||
break;
|
||||
|
||||
case AUDIO_F32LSB:
|
||||
*endianness = 0;
|
||||
*fmt = AUDIO_FORMAT_F32;
|
||||
break;
|
||||
|
||||
case AUDIO_F32MSB:
|
||||
*endianness = 1;
|
||||
*fmt = AUDIO_FORMAT_F32;
|
||||
break;
|
||||
|
||||
default:
|
||||
dolog ("Unrecognized SDL audio format %d\n", sdlfmt);
|
||||
return -1;
|
||||
@@ -255,7 +227,7 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
|
||||
|
||||
SDL_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
|
||||
(hw, size), *size = 0, sdl_unlock)
|
||||
SDL_WRAPPER_FUNC(put_buffer_out, size_t,
|
||||
SDL_WRAPPER_FUNC(put_buffer_out_nowrite, size_t,
|
||||
(HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size),
|
||||
/*nothing*/, sdl_unlock_and_post)
|
||||
SDL_WRAPPER_FUNC(write, size_t,
|
||||
@@ -348,12 +320,9 @@ static void sdl_audio_fini (void *opaque)
|
||||
static struct audio_pcm_ops sdl_pcm_ops = {
|
||||
.init_out = sdl_init_out,
|
||||
.fini_out = sdl_fini_out,
|
||||
/* wrapper for audio_generic_write */
|
||||
.write = sdl_write,
|
||||
/* wrapper for audio_generic_get_buffer_out */
|
||||
.get_buffer_out = sdl_get_buffer_out,
|
||||
/* wrapper for audio_generic_put_buffer_out */
|
||||
.put_buffer_out = sdl_put_buffer_out,
|
||||
.put_buffer_out = sdl_put_buffer_out_nowrite,
|
||||
.enable_out = sdl_enable_out,
|
||||
};
|
||||
|
||||
|
||||
+17
-13
@@ -106,7 +106,7 @@ static int line_out_init(HWVoiceOut *hw, struct audsettings *as,
|
||||
out->active = 0;
|
||||
|
||||
out->sin.base.sif = &playback_sif.base;
|
||||
qemu_spice.add_interface(&out->sin.base);
|
||||
qemu_spice_add_interface (&out->sin.base);
|
||||
#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3
|
||||
spice_server_set_playback_rate(&out->sin, settings.freq);
|
||||
#endif
|
||||
@@ -130,11 +130,12 @@ static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size)
|
||||
}
|
||||
|
||||
if (out->frame) {
|
||||
*size = MIN((out->fsize - out->fpos) << 2, *size);
|
||||
*size = audio_rate_get_bytes(
|
||||
&hw->info, &out->rate,
|
||||
(out->fsize - out->fpos) * hw->info.bytes_per_frame);
|
||||
} else {
|
||||
audio_rate_start(&out->rate);
|
||||
}
|
||||
|
||||
*size = audio_rate_get_bytes(&hw->info, &out->rate, *size);
|
||||
|
||||
return out->frame + out->fpos;
|
||||
}
|
||||
|
||||
@@ -142,14 +143,12 @@ static size_t line_out_put_buffer(HWVoiceOut *hw, void *buf, size_t size)
|
||||
{
|
||||
SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||
|
||||
if (buf) {
|
||||
assert(buf == out->frame + out->fpos && out->fpos <= out->fsize);
|
||||
out->fpos += size >> 2;
|
||||
assert(buf == out->frame + out->fpos && out->fpos <= out->fsize);
|
||||
out->fpos += size >> 2;
|
||||
|
||||
if (out->fpos == out->fsize) { /* buffer full */
|
||||
spice_server_playback_put_samples(&out->sin, out->frame);
|
||||
out->frame = NULL;
|
||||
}
|
||||
if (out->fpos == out->fsize) { /* buffer full */
|
||||
spice_server_playback_put_samples(&out->sin, out->frame);
|
||||
out->frame = NULL;
|
||||
}
|
||||
|
||||
return size;
|
||||
@@ -215,7 +214,7 @@ static int line_in_init(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
|
||||
in->active = 0;
|
||||
|
||||
in->sin.base.sif = &record_sif.base;
|
||||
qemu_spice.add_interface(&in->sin.base);
|
||||
qemu_spice_add_interface (&in->sin.base);
|
||||
#if SPICE_INTERFACE_RECORD_MAJOR > 2 || SPICE_INTERFACE_RECORD_MINOR >= 3
|
||||
spice_server_set_record_rate(&in->sin, settings.freq);
|
||||
#endif
|
||||
@@ -311,6 +310,11 @@ static struct audio_driver spice_audio_driver = {
|
||||
.voice_size_in = sizeof (SpiceVoiceIn),
|
||||
};
|
||||
|
||||
void qemu_spice_audio_init (void)
|
||||
{
|
||||
spice_audio_driver.can_be_default = 1;
|
||||
}
|
||||
|
||||
static void register_audio_spice(void)
|
||||
{
|
||||
audio_driver_register(&spice_audio_driver);
|
||||
|
||||
@@ -9,9 +9,12 @@ alsa_read_zero(long len) "Failed to read %ld frames (read zero)"
|
||||
alsa_xrun_out(void) "Recovering from playback xrun"
|
||||
alsa_xrun_in(void) "Recovering from capture xrun"
|
||||
alsa_resume_out(void) "Resuming suspended output stream"
|
||||
alsa_resume_in(void) "Resuming suspended input stream"
|
||||
alsa_no_frames(int state) "No frames available and ALSA state is %d"
|
||||
|
||||
# ossaudio.c
|
||||
oss_version(int version) "OSS version = 0x%x"
|
||||
oss_invalid_available_size(int size, int bufsize) "Invalid available size, size=%d bufsize=%d"
|
||||
|
||||
# audio.c
|
||||
audio_timer_start(int interval) "interval %d ms"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include "trace/trace-audio.h"
|
||||
@@ -197,7 +197,6 @@ static struct audio_pcm_ops wav_pcm_ops = {
|
||||
.init_out = wav_init_out,
|
||||
.fini_out = wav_fini_out,
|
||||
.write = wav_write_out,
|
||||
.run_buffer_out = audio_generic_run_buffer_out,
|
||||
.enable_out = wav_enable_out,
|
||||
};
|
||||
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "audio.h"
|
||||
@@ -71,7 +71,7 @@ static void wav_destroy (void *opaque)
|
||||
g_free (wav->path);
|
||||
}
|
||||
|
||||
static void wav_capture(void *opaque, const void *buf, int size)
|
||||
static void wav_capture (void *opaque, void *buf, int size)
|
||||
{
|
||||
WAVState *wav = opaque;
|
||||
|
||||
@@ -94,9 +94,9 @@ static void wav_capture_info (void *opaque)
|
||||
WAVState *wav = opaque;
|
||||
char *path = wav->path;
|
||||
|
||||
qemu_printf("Capturing audio(%d,%d,%d) to %s: %d bytes\n",
|
||||
wav->freq, wav->bits, wav->nchannels,
|
||||
path ? path : "<not available>", wav->bytes);
|
||||
monitor_printf (cur_mon, "Capturing audio(%d,%d,%d) to %s: %d bytes\n",
|
||||
wav->freq, wav->bits, wav->nchannels,
|
||||
path ? path : "<not available>", wav->bytes);
|
||||
}
|
||||
|
||||
static struct capture_ops wav_capture_ops = {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
authz-obj-y += base.o
|
||||
authz-obj-y += simple.o
|
||||
authz-obj-y += list.o
|
||||
authz-obj-y += listfile.o
|
||||
authz-obj-$(CONFIG_AUTH_PAM) += pamacct.o
|
||||
|
||||
pamacct.o-libs = -lpam
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
||||
+5
-3
@@ -6,7 +6,7 @@
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -124,12 +124,13 @@ qauthz_list_class_init(ObjectClass *oc, void *data)
|
||||
"QAuthZListPolicy",
|
||||
&QAuthZListPolicy_lookup,
|
||||
qauthz_list_prop_get_policy,
|
||||
qauthz_list_prop_set_policy);
|
||||
qauthz_list_prop_set_policy,
|
||||
NULL);
|
||||
|
||||
object_class_property_add(oc, "rules", "QAuthZListRule",
|
||||
qauthz_list_prop_get_rules,
|
||||
qauthz_list_prop_set_rules,
|
||||
NULL, NULL);
|
||||
NULL, NULL, NULL);
|
||||
|
||||
authz->is_allowed = qauthz_list_is_allowed;
|
||||
}
|
||||
@@ -252,6 +253,7 @@ static const TypeInfo qauthz_list_info = {
|
||||
.name = TYPE_QAUTHZ_LIST,
|
||||
.instance_size = sizeof(QAuthZList),
|
||||
.instance_finalize = qauthz_list_finalize,
|
||||
.class_size = sizeof(QAuthZListClass),
|
||||
.class_init = qauthz_list_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_USER_CREATABLE },
|
||||
|
||||
+8
-14
@@ -6,7 +6,7 @@
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -73,8 +73,7 @@ qauthz_list_file_load(QAuthZListFile *fauthz, Error **errp)
|
||||
|
||||
pdict = qobject_to(QDict, obj);
|
||||
if (!pdict) {
|
||||
error_setg(errp, "File '%s' must contain a JSON object",
|
||||
fauthz->filename);
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "obj", "dict");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -123,15 +122,7 @@ qauthz_list_file_complete(UserCreatable *uc, Error **errp)
|
||||
QAuthZListFile *fauthz = QAUTHZ_LIST_FILE(uc);
|
||||
gchar *dir = NULL, *file = NULL;
|
||||
|
||||
if (!fauthz->filename) {
|
||||
error_setg(errp, "filename not provided");
|
||||
return;
|
||||
}
|
||||
|
||||
fauthz->list = qauthz_list_file_load(fauthz, errp);
|
||||
if (!fauthz->list) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fauthz->refresh) {
|
||||
return;
|
||||
@@ -230,10 +221,12 @@ qauthz_list_file_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
object_class_property_add_str(oc, "filename",
|
||||
qauthz_list_file_prop_get_filename,
|
||||
qauthz_list_file_prop_set_filename);
|
||||
qauthz_list_file_prop_set_filename,
|
||||
NULL);
|
||||
object_class_property_add_bool(oc, "refresh",
|
||||
qauthz_list_file_prop_get_refresh,
|
||||
qauthz_list_file_prop_set_refresh);
|
||||
qauthz_list_file_prop_set_refresh,
|
||||
NULL);
|
||||
|
||||
authz->is_allowed = qauthz_list_file_is_allowed;
|
||||
}
|
||||
@@ -246,7 +239,7 @@ qauthz_list_file_init(Object *obj)
|
||||
|
||||
authz->file_watch = -1;
|
||||
#ifdef CONFIG_INOTIFY1
|
||||
authz->refresh = true;
|
||||
authz->refresh = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -272,6 +265,7 @@ static const TypeInfo qauthz_list_file_info = {
|
||||
.instance_init = qauthz_list_file_init,
|
||||
.instance_size = sizeof(QAuthZListFile),
|
||||
.instance_finalize = qauthz_list_file_finalize,
|
||||
.class_size = sizeof(QAuthZListFileClass),
|
||||
.class_init = qauthz_list_file_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_USER_CREATABLE },
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
authz_ss.add(genh)
|
||||
authz_ss.add(files(
|
||||
'base.c',
|
||||
'list.c',
|
||||
'listfile.c',
|
||||
'simple.c',
|
||||
))
|
||||
|
||||
authz_ss.add(when: ['CONFIG_AUTH_PAM', pam], if_true: files('pamacct.c'))
|
||||
+4
-8
@@ -6,7 +6,7 @@
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -84,12 +84,6 @@ qauthz_pam_prop_get_service(Object *obj,
|
||||
static void
|
||||
qauthz_pam_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
QAuthZPAM *pauthz = QAUTHZ_PAM(uc);
|
||||
|
||||
if (!pauthz->service) {
|
||||
error_setg(errp, "The 'service' property must be set");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +107,8 @@ qauthz_pam_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
object_class_property_add_str(oc, "service",
|
||||
qauthz_pam_prop_get_service,
|
||||
qauthz_pam_prop_set_service);
|
||||
qauthz_pam_prop_set_service,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +130,7 @@ static const TypeInfo qauthz_pam_info = {
|
||||
.name = TYPE_QAUTHZ_PAM,
|
||||
.instance_size = sizeof(QAuthZPAM),
|
||||
.instance_finalize = qauthz_pam_finalize,
|
||||
.class_size = sizeof(QAuthZPAMClass),
|
||||
.class_init = qauthz_pam_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_USER_CREATABLE },
|
||||
|
||||
Loaded 100 of 5019 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user