Compare commits
16 Commits
v8.0.2
...
fixed-ram-
Author | SHA1 | Date | |
---|---|---|---|
|
a0efb212fb | ||
|
9e086f2e2a | ||
|
cc57d6c75f | ||
|
c204cfeeb7 | ||
|
d5cd94bbaf | ||
|
4c2f145632 | ||
|
fb56e2387b | ||
|
5686566113 | ||
|
4c16cca0e1 | ||
|
895c40ce0a | ||
|
cad3bc2be3 | ||
|
ea1efd3d17 | ||
|
3ce4e2e8d5 | ||
|
c1eef47d79 | ||
|
80f68f67a9 | ||
|
4ed18df9df |
111
.cirrus.yml
Normal file
111
.cirrus.yml
Normal file
@@ -0,0 +1,111 @@
|
||||
env:
|
||||
CIRRUS_CLONE_DEPTH: 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:native
|
||||
MSYSTEM: MINGW64
|
||||
MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2022-06-03/msys2-base-x86_64-20220603.sfx.exe
|
||||
MSYS2_FINGERPRINT: 0
|
||||
MSYS2_PACKAGES: "
|
||||
diffutils git grep make pkg-config sed
|
||||
mingw-w64-x86_64-python
|
||||
mingw-w64-x86_64-python-sphinx
|
||||
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-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
|
||||
"
|
||||
CHERE_INVOKING: 1
|
||||
msys2_cache:
|
||||
folder: C:\tools\archive
|
||||
reupload_on_changes: false
|
||||
# These env variables are used to generate fingerprint to trigger the cache procedure
|
||||
# If wanna to force re-populate msys2, increase MSYS2_FINGERPRINT
|
||||
fingerprint_script:
|
||||
- |
|
||||
echo $env:CIRRUS_TASK_NAME
|
||||
echo $env:MSYS2_URL
|
||||
echo $env:MSYS2_FINGERPRINT
|
||||
echo $env:MSYS2_PACKAGES
|
||||
populate_script:
|
||||
- |
|
||||
md -Force C:\tools\archive\pkg
|
||||
$start_time = Get-Date
|
||||
bitsadmin /transfer msys_download /dynamic /download /priority FOREGROUND $env:MSYS2_URL C:\tools\archive\base.exe
|
||||
Write-Output "Download time taken: $((Get-Date).Subtract($start_time))"
|
||||
cd C:\tools
|
||||
C:\tools\archive\base.exe -y
|
||||
del -Force C:\tools\archive\base.exe
|
||||
Write-Output "Base install time taken: $((Get-Date).Subtract($start_time))"
|
||||
$start_time = Get-Date
|
||||
|
||||
((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 -Syuu --overwrite=*"
|
||||
Write-Output "Core install time taken: $((Get-Date).Subtract($start_time))"
|
||||
$start_time = Get-Date
|
||||
|
||||
C:\tools\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -S --needed $env:MSYS2_PACKAGES"
|
||||
Write-Output "Package install time taken: $((Get-Date).Subtract($start_time))"
|
||||
$start_time = Get-Date
|
||||
|
||||
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\etc\mtab
|
||||
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\fd
|
||||
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\stderr
|
||||
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\stdin
|
||||
del -Force -ErrorAction SilentlyContinue C:\tools\msys64\dev\stdout
|
||||
del -Force -Recurse -ErrorAction SilentlyContinue C:\tools\msys64\var\cache\pacman\pkg
|
||||
tar cf C:\tools\archive\msys64.tar -C C:\tools\ msys64
|
||||
|
||||
Write-Output "Package archive time taken: $((Get-Date).Subtract($start_time))"
|
||||
del -Force -Recurse -ErrorAction SilentlyContinue c:\tools\msys64
|
||||
install_script:
|
||||
- |
|
||||
$start_time = Get-Date
|
||||
cd C:\tools
|
||||
ls C:\tools\archive\msys64.tar
|
||||
tar xf C:\tools\archive\msys64.tar
|
||||
Write-Output "Extract msys2 time taken: $((Get-Date).Subtract($start_time))"
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- C:\tools\msys64\usr\bin\bash.exe -lc "../configure --python=python3
|
||||
--target-list-exclude=i386-softmmu,ppc64-softmmu,aarch64-softmmu,mips64-softmmu,mipsel-softmmu,sh4-softmmu"
|
||||
- C:\tools\msys64\usr\bin\bash.exe -lc "make -j8"
|
||||
- exit $LastExitCode
|
||||
test_script:
|
||||
- C:\tools\msys64\usr\bin\bash.exe -lc "cd build && make V=1 check"
|
||||
- exit $LastExitCode
|
@@ -1,21 +0,0 @@
|
||||
#
|
||||
# List of code-formatting clean ups the git blame can ignore
|
||||
#
|
||||
# git blame --ignore-revs-file .git-blame-ignore-revs
|
||||
#
|
||||
# or
|
||||
#
|
||||
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
#
|
||||
|
||||
# gdbstub: clean-up indents
|
||||
ad9e4585b3c7425759d3eea697afbca71d2c2082
|
||||
|
||||
# e1000e: fix code style
|
||||
0eadd56bf53ab196a16d492d7dd31c62e1c24c32
|
||||
|
||||
# target/riscv: coding style fixes
|
||||
8c7feddddd9218b407792120bcfda0347ed16205
|
||||
|
||||
# replace TABs with spaces
|
||||
48805df9c22a0700fba4b3b548fafaa21726ca68
|
@@ -75,5 +75,5 @@
|
||||
- if: '$QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
when: manual
|
||||
|
||||
# Jobs can run if any jobs they depend on were successful
|
||||
# Jobs can run if any jobs they depend on were successfull
|
||||
- when: on_success
|
||||
|
@@ -9,7 +9,8 @@ build-system-alpine:
|
||||
- job: amd64-alpine-container
|
||||
variables:
|
||||
IMAGE: alpine
|
||||
TARGETS: avr-softmmu loongarch64-softmmu mips64-softmmu mipsel-softmmu
|
||||
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
|
||||
microblazeel-softmmu mips64el-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
CONFIGURE_ARGS: --enable-docs --enable-trace-backends=log,simple,syslog
|
||||
|
||||
@@ -71,8 +72,8 @@ build-system-debian:
|
||||
variables:
|
||||
IMAGE: debian-amd64
|
||||
CONFIGURE_ARGS: --with-coroutine=sigaltstack
|
||||
TARGETS: arm-softmmu i386-softmmu riscv64-softmmu sh4eb-softmmu
|
||||
sparc-softmmu xtensaeb-softmmu
|
||||
TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
|
||||
riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
|
||||
check-system-debian:
|
||||
|
@@ -1,6 +1,13 @@
|
||||
include:
|
||||
- local: '/.gitlab-ci.d/crossbuild-template.yml'
|
||||
|
||||
cross-armel-system:
|
||||
extends: .cross_system_build_job
|
||||
needs:
|
||||
job: armel-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-armel-cross
|
||||
|
||||
cross-armel-user:
|
||||
extends: .cross_user_build_job
|
||||
needs:
|
||||
@@ -8,6 +15,13 @@ cross-armel-user:
|
||||
variables:
|
||||
IMAGE: debian-armel-cross
|
||||
|
||||
cross-armhf-system:
|
||||
extends: .cross_system_build_job
|
||||
needs:
|
||||
job: armhf-debian-cross-container
|
||||
variables:
|
||||
IMAGE: debian-armhf-cross
|
||||
|
||||
cross-armhf-user:
|
||||
extends: .cross_user_build_job
|
||||
needs:
|
||||
@@ -29,6 +43,16 @@ cross-arm64-user:
|
||||
variables:
|
||||
IMAGE: debian-arm64-cross
|
||||
|
||||
cross-i386-system:
|
||||
extends:
|
||||
- .cross_system_build_job
|
||||
- .cross_test_artifacts
|
||||
needs:
|
||||
job: i386-fedora-cross-container
|
||||
variables:
|
||||
IMAGE: fedora-i386-cross
|
||||
MAKE_CHECK_ARGS: check-qtest
|
||||
|
||||
cross-i386-user:
|
||||
extends:
|
||||
- .cross_user_build_job
|
||||
|
@@ -1,9 +1,4 @@
|
||||
# All centos-stream-8 jobs should run successfully in an environment
|
||||
# setup by the scripts/ci/setup/stream/8/build-environment.yml task
|
||||
# "Installation of extra packages to build QEMU"
|
||||
|
||||
centos-stream-8-x86_64:
|
||||
extends: .custom_runner_template
|
||||
allow_failure: true
|
||||
needs: []
|
||||
stage: build
|
||||
@@ -13,6 +8,15 @@ centos-stream-8-x86_64:
|
||||
rules:
|
||||
- if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/'
|
||||
- if: "$CENTOS_STREAM_8_x86_64_RUNNER_AVAILABLE"
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
|
||||
when: on_failure
|
||||
expire_in: 7 days
|
||||
paths:
|
||||
- build/tests/results/latest/results.xml
|
||||
- build/tests/results/latest/test-results
|
||||
reports:
|
||||
junit: build/tests/results/latest/results.xml
|
||||
before_script:
|
||||
- JOBS=$(expr $(nproc) + 1)
|
||||
script:
|
||||
@@ -21,4 +25,6 @@ centos-stream-8-x86_64:
|
||||
- ../scripts/ci/org.centos/stream/8/x86_64/configure
|
||||
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
|
||||
- make -j"$JOBS"
|
||||
- make NINJA=":" check check-avocado
|
||||
- make NINJA=":" check
|
||||
|| { cat meson-logs/testlog.txt; exit 1; } ;
|
||||
- ../scripts/ci/org.centos/stream/8/x86_64/test-avocado
|
||||
|
85
.gitlab-ci.d/edk2.yml
Normal file
85
.gitlab-ci.d/edk2.yml
Normal file
@@ -0,0 +1,85 @@
|
||||
# All jobs needing docker-edk2 must use the same rules it uses.
|
||||
.edk2_job_rules:
|
||||
rules:
|
||||
# Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set
|
||||
- if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
when: never
|
||||
|
||||
# In forks, if QEMU_CI=1 is set, then create manual job
|
||||
# if any of the files affecting the build are touched
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project"'
|
||||
changes:
|
||||
- .gitlab-ci.d/edk2.yml
|
||||
- .gitlab-ci.d/edk2/Dockerfile
|
||||
- roms/edk2/*
|
||||
when: manual
|
||||
|
||||
# In forks, if QEMU_CI=1 is set, then create manual job
|
||||
# if the branch/tag starts with 'edk2'
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_REF_NAME =~ /^edk2/'
|
||||
when: manual
|
||||
|
||||
# In forks, if QEMU_CI=1 is set, then create manual job
|
||||
# if last commit msg contains 'EDK2' (case insensitive)
|
||||
- if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_MESSAGE =~ /edk2/i'
|
||||
when: manual
|
||||
|
||||
# Run if any files affecting the build output are touched
|
||||
- changes:
|
||||
- .gitlab-ci.d/edk2.yml
|
||||
- .gitlab-ci.d/edk2/Dockerfile
|
||||
- roms/edk2/*
|
||||
when: on_success
|
||||
|
||||
# Run if the branch/tag starts with 'edk2'
|
||||
- if: '$CI_COMMIT_REF_NAME =~ /^edk2/'
|
||||
when: on_success
|
||||
|
||||
# Run if last commit msg contains 'EDK2' (case insensitive)
|
||||
- if: '$CI_COMMIT_MESSAGE =~ /edk2/i'
|
||||
when: on_success
|
||||
|
||||
docker-edk2:
|
||||
extends: .edk2_job_rules
|
||||
stage: containers
|
||||
image: docker:19.03.1
|
||||
services:
|
||||
- docker:19.03.1-dind
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:edk2-cross-build
|
||||
# We don't use TLS
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker pull $IMAGE_TAG || true
|
||||
- docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
--tag $IMAGE_TAG .gitlab-ci.d/edk2
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
- docker push $IMAGE_TAG
|
||||
|
||||
build-edk2:
|
||||
extends: .edk2_job_rules
|
||||
stage: build
|
||||
needs: ['docker-edk2']
|
||||
artifacts:
|
||||
paths: # 'artifacts.zip' will contains the following files:
|
||||
- pc-bios/edk2*bz2
|
||||
- pc-bios/edk2-licenses.txt
|
||||
- edk2-stdout.log
|
||||
- edk2-stderr.log
|
||||
image: $CI_REGISTRY_IMAGE:edk2-cross-build
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
script: # Clone the required submodules and build EDK2
|
||||
- git submodule update --init roms/edk2
|
||||
- git -C roms/edk2 submodule update --init --
|
||||
ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
|
||||
BaseTools/Source/C/BrotliCompress/brotli
|
||||
CryptoPkg/Library/OpensslLib/openssl
|
||||
MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
|
||||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
- make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2
|
27
.gitlab-ci.d/edk2/Dockerfile
Normal file
27
.gitlab-ci.d/edk2/Dockerfile
Normal file
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# Docker image to cross-compile EDK2 firmware binaries
|
||||
#
|
||||
FROM ubuntu:18.04
|
||||
|
||||
MAINTAINER Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
|
||||
# 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 \
|
||||
python3 \
|
||||
uuid-dev \
|
||||
&& \
|
||||
\
|
||||
rm -rf /var/lib/apt/lists/*
|
@@ -42,9 +42,9 @@
|
||||
docker-opensbi:
|
||||
extends: .opensbi_job_rules
|
||||
stage: containers
|
||||
image: docker:stable
|
||||
image: docker:19.03.1
|
||||
services:
|
||||
- docker:stable-dind
|
||||
- docker:19.03.1-dind
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build
|
||||
|
@@ -15,7 +15,6 @@ RUN apt update \
|
||||
ca-certificates \
|
||||
git \
|
||||
make \
|
||||
python3 \
|
||||
wget \
|
||||
&& \
|
||||
\
|
||||
|
@@ -4,6 +4,7 @@
|
||||
include:
|
||||
- local: '/.gitlab-ci.d/base.yml'
|
||||
- local: '/.gitlab-ci.d/stages.yml'
|
||||
- local: '/.gitlab-ci.d/edk2.yml'
|
||||
- local: '/.gitlab-ci.d/opensbi.yml'
|
||||
- local: '/.gitlab-ci.d/containers.yml'
|
||||
- local: '/.gitlab-ci.d/crossbuilds.yml'
|
||||
|
@@ -59,7 +59,6 @@ msys2-64bit:
|
||||
mingw-w64-x86_64-SDL2
|
||||
mingw-w64-x86_64-SDL2_image
|
||||
mingw-w64-x86_64-snappy
|
||||
mingw-w64-x86_64-spice
|
||||
mingw-w64-x86_64-usbredir
|
||||
mingw-w64-x86_64-zstd "
|
||||
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||
@@ -109,7 +108,6 @@ msys2-32bit:
|
||||
mingw-w64-i686-SDL2
|
||||
mingw-w64-i686-SDL2_image
|
||||
mingw-w64-i686-snappy
|
||||
mingw-w64-i686-spice
|
||||
mingw-w64-i686-usbredir
|
||||
mingw-w64-i686-zstd "
|
||||
- $env:CHERE_INVOKING = 'yes' # Preserve the current working directory
|
||||
|
1
.mailmap
1
.mailmap
@@ -56,7 +56,6 @@ Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
|
||||
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
|
||||
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
|
||||
Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
|
||||
Damien Hedde <damien.hedde@dahe.fr> <damien.hedde@greensocs.com>
|
||||
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
|
||||
Frederic Konrad <konrad.frederic@yahoo.fr> <fred.konrad@greensocs.com>
|
||||
Frederic Konrad <konrad.frederic@yahoo.fr> <konrad@adacore.com>
|
||||
|
87
MAINTAINERS
87
MAINTAINERS
@@ -64,20 +64,6 @@ L: qemu-devel@nongnu.org
|
||||
F: *
|
||||
F: */
|
||||
|
||||
Project policy and developer guides
|
||||
R: Alex Bennée <alex.bennee@linaro.org>
|
||||
R: Daniel P. Berrangé <berrange@redhat.com>
|
||||
R: Thomas Huth <thuth@redhat.com>
|
||||
R: Markus Armbruster <armbru@redhat.com>
|
||||
R: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
W: https://www.qemu.org/docs/master/devel/index.html
|
||||
S: Odd Fixes
|
||||
F: docs/devel/style.rst
|
||||
F: docs/devel/code-of-conduct.rst
|
||||
F: docs/devel/conflict-resolution.rst
|
||||
F: docs/devel/submitting-a-patch.rst
|
||||
F: docs/devel/submitting-a-pull-request.rst
|
||||
|
||||
Responsible Disclosure, Reporting Security Issues
|
||||
-------------------------------------------------
|
||||
W: https://wiki.qemu.org/SecurityProcess
|
||||
@@ -150,8 +136,6 @@ F: docs/devel/decodetree.rst
|
||||
F: docs/devel/tcg*
|
||||
F: include/exec/cpu*.h
|
||||
F: include/exec/exec-all.h
|
||||
F: include/exec/tb-flush.h
|
||||
F: include/exec/target_long.h
|
||||
F: include/exec/helper*.h
|
||||
F: include/sysemu/cpus.h
|
||||
F: include/sysemu/tcg.h
|
||||
@@ -271,9 +255,9 @@ F: docs/system/cpu-models-mips.rst.inc
|
||||
F: tests/tcg/mips/
|
||||
|
||||
NiosII TCG CPUs
|
||||
R: Chris Wulff <crwulff@gmail.com>
|
||||
R: Marek Vasut <marex@denx.de>
|
||||
S: Orphan
|
||||
M: Chris Wulff <crwulff@gmail.com>
|
||||
M: Marek Vasut <marex@denx.de>
|
||||
S: Maintained
|
||||
F: target/nios2/
|
||||
F: hw/nios2/
|
||||
F: disas/nios2.c
|
||||
@@ -385,7 +369,6 @@ S: Maintained
|
||||
F: target/xtensa/
|
||||
F: hw/xtensa/
|
||||
F: tests/tcg/xtensa/
|
||||
F: tests/tcg/xtensaeb/
|
||||
F: disas/xtensa.c
|
||||
F: include/hw/xtensa/xtensa-isa.h
|
||||
F: configs/devices/xtensa*/default.mak
|
||||
@@ -460,15 +443,6 @@ F: target/i386/kvm/
|
||||
F: target/i386/sev*
|
||||
F: scripts/kvm/vmxcap
|
||||
|
||||
Xen emulation on X86 KVM CPUs
|
||||
M: David Woodhouse <dwmw2@infradead.org>
|
||||
M: Paul Durrant <paul@xen.org>
|
||||
S: Supported
|
||||
F: include/sysemu/kvm_xen.h
|
||||
F: target/i386/kvm/xen*
|
||||
F: hw/i386/kvm/xen*
|
||||
F: tests/avocado/xen_guest.py
|
||||
|
||||
Guest CPU Cores (other accelerators)
|
||||
------------------------------------
|
||||
Overall
|
||||
@@ -1025,6 +999,12 @@ S: Maintained
|
||||
F: hw/ssi/xlnx-versal-ospi.c
|
||||
F: include/hw/ssi/xlnx-versal-ospi.h
|
||||
|
||||
ARM ACPI Subsystem
|
||||
M: Shannon Zhao <shannon.zhaosl@gmail.com>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/virt-acpi-build.c
|
||||
|
||||
STM32F100
|
||||
M: Alexandre Iooss <erdnaxe@crans.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
@@ -1912,18 +1892,6 @@ F: docs/specs/acpi_nvdimm.rst
|
||||
F: docs/specs/acpi_pci_hotplug.rst
|
||||
F: docs/specs/acpi_hw_reduced_hotplug.rst
|
||||
|
||||
ARM ACPI Subsystem
|
||||
M: Shannon Zhao <shannon.zhaosl@gmail.com>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/virt-acpi-build.c
|
||||
|
||||
RISC-V ACPI Subsystem
|
||||
M: Sunil V L <sunilvl@ventanamicro.com>
|
||||
L: qemu-riscv@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/riscv/virt-acpi-build.c
|
||||
|
||||
ACPI/VIOT
|
||||
M: Jean-Philippe Brucker <jean-philippe@linaro.org>
|
||||
S: Supported
|
||||
@@ -2133,6 +2101,7 @@ T: git https://github.com/borntraeger/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
virtiofs
|
||||
M: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
M: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
S: Supported
|
||||
F: hw/virtio/vhost-user-fs*
|
||||
@@ -2250,28 +2219,14 @@ F: docs/specs/rocker.txt
|
||||
|
||||
e1000x
|
||||
M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
|
||||
R: Akihiko Odaki <akihiko.odaki@daynix.com>
|
||||
S: Maintained
|
||||
F: hw/net/e1000x*
|
||||
|
||||
e1000e
|
||||
M: Dmitry Fleytman <dmitry.fleytman@gmail.com>
|
||||
R: Akihiko Odaki <akihiko.odaki@daynix.com>
|
||||
S: Maintained
|
||||
F: hw/net/e1000e*
|
||||
F: tests/qtest/fuzz-e1000e-test.c
|
||||
F: tests/qtest/e1000e-test.c
|
||||
F: tests/qtest/libqos/e1000e.*
|
||||
|
||||
igb
|
||||
M: Akihiko Odaki <akihiko.odaki@daynix.com>
|
||||
R: Sriram Yagnaraman <sriram.yagnaraman@est.tech>
|
||||
S: Maintained
|
||||
F: docs/system/devices/igb.rst
|
||||
F: hw/net/igb*
|
||||
F: tests/avocado/igb.py
|
||||
F: tests/qtest/igb-test.c
|
||||
F: tests/qtest/libqos/igb.c
|
||||
|
||||
eepro100
|
||||
M: Stefan Weil <sw@weilnetz.de>
|
||||
@@ -2535,7 +2490,6 @@ Subsystems
|
||||
----------
|
||||
Overall Audio backends
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
S: Odd Fixes
|
||||
F: audio/
|
||||
X: audio/alsaaudio.c
|
||||
@@ -2681,6 +2635,7 @@ T: git https://gitlab.com/jsnow/qemu.git jobs
|
||||
T: git https://gitlab.com/vsementsov/qemu.git block
|
||||
|
||||
Compute Express Link
|
||||
M: Ben Widawsky <ben.widawsky@intel.com>
|
||||
M: Jonathan Cameron <jonathan.cameron@huawei.com>
|
||||
R: Fan Ni <fan.ni@samsung.com>
|
||||
S: Supported
|
||||
@@ -2780,11 +2735,9 @@ S: Maintained
|
||||
F: docs/system/gdb.rst
|
||||
F: gdbstub/*
|
||||
F: include/exec/gdbstub.h
|
||||
F: include/gdbstub/*
|
||||
F: gdb-xml/
|
||||
F: tests/tcg/multiarch/gdbstub/
|
||||
F: scripts/feature_to_c.sh
|
||||
F: scripts/probe-gdb-support.py
|
||||
|
||||
Memory API
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
@@ -2832,7 +2785,6 @@ F: docs/spice-port-fqdn.txt
|
||||
|
||||
Graphics
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
S: Odd Fixes
|
||||
F: ui/
|
||||
F: include/ui/
|
||||
@@ -2876,7 +2828,7 @@ F: tests/unit/test-rcu-*.c
|
||||
F: util/rcu.c
|
||||
|
||||
Human Monitor (HMP)
|
||||
M: Dr. David Alan Gilbert <dave@treblig.org>
|
||||
M: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
S: Maintained
|
||||
F: monitor/monitor-internal.h
|
||||
F: monitor/misc.c
|
||||
@@ -2916,11 +2868,9 @@ T: git https://gitlab.com/ehabkost/qemu.git machine-next
|
||||
|
||||
Cryptodev Backends
|
||||
M: Gonglei <arei.gonglei@huawei.com>
|
||||
M: zhenwei pi <pizhenwei@bytedance.com>
|
||||
S: Maintained
|
||||
F: include/sysemu/cryptodev*.h
|
||||
F: backends/cryptodev*.c
|
||||
F: qapi/cryptodev.json
|
||||
|
||||
Python library
|
||||
M: John Snow <jsnow@redhat.com>
|
||||
@@ -3149,6 +3099,7 @@ F: scripts/checkpatch.pl
|
||||
|
||||
Migration
|
||||
M: Juan Quintela <quintela@redhat.com>
|
||||
M: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
S: Maintained
|
||||
F: hw/core/vmstate-if.c
|
||||
F: include/hw/vmstate-if.h
|
||||
@@ -3357,6 +3308,8 @@ F: roms/edk2
|
||||
F: roms/edk2-*
|
||||
F: tests/data/uefi-boot-images/
|
||||
F: tests/uefi-test-tools/
|
||||
F: .gitlab-ci.d/edk2.yml
|
||||
F: .gitlab-ci.d/edk2/
|
||||
|
||||
VT-d Emulation
|
||||
M: Michael S. Tsirkin <mst@redhat.com>
|
||||
@@ -3376,7 +3329,7 @@ F: .gitlab-ci.d/opensbi/
|
||||
|
||||
Clock framework
|
||||
M: Luc Michel <luc@lmichel.fr>
|
||||
R: Damien Hedde <damien.hedde@dahe.fr>
|
||||
R: Damien Hedde <damien.hedde@greensocs.com>
|
||||
S: Maintained
|
||||
F: include/hw/clock.h
|
||||
F: include/hw/qdev-clock.h
|
||||
@@ -3831,7 +3784,8 @@ W: https://cirrus-ci.com/github/qemu/qemu
|
||||
Windows Hosted Continuous Integration
|
||||
M: Yonggang Luo <luoyonggang@gmail.com>
|
||||
S: Maintained
|
||||
F: .gitlab-ci.d/windows.yml
|
||||
F: .cirrus.yml
|
||||
W: https://cirrus-ci.com/github/qemu/qemu
|
||||
|
||||
Guest Test Compilation Support
|
||||
M: Alex Bennée <alex.bennee@linaro.org>
|
||||
@@ -3920,8 +3874,3 @@ Performance Tools and Tests
|
||||
M: Ahmed Karaman <ahmedkhaledkaraman@gmail.com>
|
||||
S: Maintained
|
||||
F: scripts/performance/
|
||||
|
||||
Code Coverage Tools
|
||||
M: Alex Bennée <alex.bennee@linaro.org>
|
||||
S: Odd Fixes
|
||||
F: scripts/coverage/
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include "qemu/accel.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#include "accel-softmmu.h"
|
||||
|
||||
int accel_init_machine(AccelState *accel, MachineState *ms)
|
||||
|
@@ -86,13 +86,6 @@ static bool kvm_cpus_are_resettable(void)
|
||||
return !kvm_enabled() || kvm_cpu_check_are_resettable();
|
||||
}
|
||||
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
static int kvm_update_guest_debug_ops(CPUState *cpu)
|
||||
{
|
||||
return kvm_update_guest_debug(cpu, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
@@ -106,7 +99,6 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm;
|
||||
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
ops->update_guest_debug = kvm_update_guest_debug_ops;
|
||||
ops->supports_guest_debug = kvm_supports_guest_debug;
|
||||
ops->insert_breakpoint = kvm_insert_breakpoint;
|
||||
ops->remove_breakpoint = kvm_remove_breakpoint;
|
||||
|
@@ -685,15 +685,6 @@ static uint32_t kvm_dirty_ring_reap_one(KVMState *s, CPUState *cpu)
|
||||
uint32_t ring_size = s->kvm_dirty_ring_size;
|
||||
uint32_t count = 0, fetch = cpu->kvm_fetch_index;
|
||||
|
||||
/*
|
||||
* It's possible that we race with vcpu creation code where the vcpu is
|
||||
* put onto the vcpus list but not yet initialized the dirty ring
|
||||
* structures. If so, skip it.
|
||||
*/
|
||||
if (!cpu->created) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(dirty_gfns && ring_size);
|
||||
trace_kvm_dirty_ring_reap_vcpu(cpu->cpu_index);
|
||||
|
||||
|
@@ -11,7 +11,6 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
void tb_flush(CPUState *cpu)
|
||||
|
@@ -21,7 +21,6 @@
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/plugin.h"
|
||||
|
||||
bool tcg_allowed;
|
||||
|
||||
@@ -66,8 +65,6 @@ void cpu_loop_exit(CPUState *cpu)
|
||||
{
|
||||
/* Undo the setting in cpu_tb_exec. */
|
||||
cpu->can_do_io = 1;
|
||||
/* Undo any setting in generated code. */
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
siglongjmp(cpu->jmp_env, 1);
|
||||
}
|
||||
|
||||
|
@@ -257,7 +257,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
|
||||
|
||||
if (cflags & CF_PCREL) {
|
||||
/* Use acquire to ensure current load of pc from jc. */
|
||||
tb = qatomic_load_acquire(&jc->array[hash].tb);
|
||||
tb = qatomic_load_acquire(&jc->array[hash].tb);
|
||||
|
||||
if (likely(tb &&
|
||||
jc->array[hash].pc == pc &&
|
||||
@@ -272,7 +272,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
|
||||
return NULL;
|
||||
}
|
||||
jc->array[hash].pc = pc;
|
||||
/* Ensure pc is written first. */
|
||||
/* Use store_release on tb to ensure pc is written first. */
|
||||
qatomic_store_release(&jc->array[hash].tb, tb);
|
||||
} else {
|
||||
/* Use rcu_read to ensure current load of pc from *tb. */
|
||||
@@ -459,7 +459,6 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
|
||||
qemu_thread_jit_execute();
|
||||
ret = tcg_qemu_tb_exec(env, tb_ptr);
|
||||
cpu->can_do_io = 1;
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
/*
|
||||
* TODO: Delay swapping back to the read-write region of the TB
|
||||
* until we actually need to modify the TB. The read-only copy,
|
||||
@@ -527,6 +526,7 @@ static void cpu_exec_exit(CPUState *cpu)
|
||||
if (cc->tcg_ops->cpu_exec_exit) {
|
||||
cc->tcg_ops->cpu_exec_exit(cpu);
|
||||
}
|
||||
QEMU_PLUGIN_ASSERT(cpu->plugin_mem_cbs == NULL);
|
||||
}
|
||||
|
||||
void cpu_exec_step_atomic(CPUState *cpu)
|
||||
@@ -580,6 +580,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
assert_no_pages_locked();
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -971,27 +972,18 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
||||
|
||||
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
|
||||
if (tb == NULL) {
|
||||
CPUJumpCache *jc;
|
||||
uint32_t h;
|
||||
|
||||
mmap_lock();
|
||||
tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
|
||||
mmap_unlock();
|
||||
|
||||
/*
|
||||
* We add the TB in the virtual pc hash table
|
||||
* for the fast lookup
|
||||
*/
|
||||
h = tb_jmp_cache_hash_func(pc);
|
||||
jc = cpu->tb_jmp_cache;
|
||||
if (cflags & CF_PCREL) {
|
||||
jc->array[h].pc = pc;
|
||||
/* Ensure pc is written first. */
|
||||
qatomic_store_release(&jc->array[h].tb, tb);
|
||||
} else {
|
||||
/* Use the pc value already stored in tb->pc. */
|
||||
qatomic_set(&jc->array[h].tb, tb);
|
||||
}
|
||||
/* Use the pc value already stored in tb->pc. */
|
||||
qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
@@ -1012,6 +1004,7 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
|
||||
|
||||
cpu_loop_exec_tb(cpu, tb, pc, &last_tb, &tb_exit);
|
||||
|
||||
QEMU_PLUGIN_ASSERT(cpu->plugin_mem_cbs == NULL);
|
||||
/* Try to align the host and virtual clocks
|
||||
if the guest is in advance */
|
||||
align_clocks(sc, cpu);
|
||||
@@ -1036,6 +1029,7 @@ static int cpu_exec_setjmp(CPUState *cpu, SyncClocks *sc)
|
||||
if (qemu_mutex_iothread_locked()) {
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
qemu_plugin_disable_mem_helpers(cpu);
|
||||
|
||||
assert_no_pages_locked();
|
||||
}
|
||||
|
@@ -1830,7 +1830,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||
} else /* if (prot & PAGE_READ) */ {
|
||||
tlb_addr = tlbe->addr_read;
|
||||
if (!tlb_hit(tlb_addr, addr)) {
|
||||
if (!VICTIM_TLB_HIT(addr_read, addr)) {
|
||||
if (!VICTIM_TLB_HIT(addr_write, addr)) {
|
||||
tlb_fill(env_cpu(env), addr, size,
|
||||
MMU_DATA_LOAD, mmu_idx, retaddr);
|
||||
index = tlb_index(env, mmu_idx, addr);
|
||||
|
@@ -44,7 +44,6 @@
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg/tcg-temp-internal.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/plugin-gen.h"
|
||||
|
@@ -19,11 +19,9 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/interval-tree.h"
|
||||
#include "qemu/qtree.h"
|
||||
#include "exec/cputlb.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "exec/translate-all.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "tcg/tcg.h"
|
||||
@@ -127,29 +125,29 @@ static void tb_remove(TranslationBlock *tb)
|
||||
}
|
||||
|
||||
/* TODO: For now, still shared with translate-all.c for system mode. */
|
||||
#define PAGE_FOR_EACH_TB(start, last, pagedesc, T, N) \
|
||||
for (T = foreach_tb_first(start, last), \
|
||||
N = foreach_tb_next(T, start, last); \
|
||||
#define PAGE_FOR_EACH_TB(start, end, pagedesc, T, N) \
|
||||
for (T = foreach_tb_first(start, end), \
|
||||
N = foreach_tb_next(T, start, end); \
|
||||
T != NULL; \
|
||||
T = N, N = foreach_tb_next(N, start, last))
|
||||
T = N, N = foreach_tb_next(N, start, end))
|
||||
|
||||
typedef TranslationBlock *PageForEachNext;
|
||||
|
||||
static PageForEachNext foreach_tb_first(tb_page_addr_t start,
|
||||
tb_page_addr_t last)
|
||||
tb_page_addr_t end)
|
||||
{
|
||||
IntervalTreeNode *n = interval_tree_iter_first(&tb_root, start, last);
|
||||
IntervalTreeNode *n = interval_tree_iter_first(&tb_root, start, end - 1);
|
||||
return n ? container_of(n, TranslationBlock, itree) : NULL;
|
||||
}
|
||||
|
||||
static PageForEachNext foreach_tb_next(PageForEachNext tb,
|
||||
tb_page_addr_t start,
|
||||
tb_page_addr_t last)
|
||||
tb_page_addr_t end)
|
||||
{
|
||||
IntervalTreeNode *n;
|
||||
|
||||
if (tb) {
|
||||
n = interval_tree_iter_next(&tb->itree, start, last);
|
||||
n = interval_tree_iter_next(&tb->itree, start, end - 1);
|
||||
if (n) {
|
||||
return container_of(n, TranslationBlock, itree);
|
||||
}
|
||||
@@ -315,12 +313,12 @@ struct page_entry {
|
||||
* See also: page_collection_lock().
|
||||
*/
|
||||
struct page_collection {
|
||||
QTree *tree;
|
||||
GTree *tree;
|
||||
struct page_entry *max;
|
||||
};
|
||||
|
||||
typedef int PageForEachNext;
|
||||
#define PAGE_FOR_EACH_TB(start, last, pagedesc, tb, n) \
|
||||
#define PAGE_FOR_EACH_TB(start, end, pagedesc, tb, n) \
|
||||
TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next)
|
||||
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
@@ -468,7 +466,7 @@ static bool page_trylock_add(struct page_collection *set, tb_page_addr_t addr)
|
||||
struct page_entry *pe;
|
||||
PageDesc *pd;
|
||||
|
||||
pe = q_tree_lookup(set->tree, &index);
|
||||
pe = g_tree_lookup(set->tree, &index);
|
||||
if (pe) {
|
||||
return false;
|
||||
}
|
||||
@@ -479,7 +477,7 @@ static bool page_trylock_add(struct page_collection *set, tb_page_addr_t addr)
|
||||
}
|
||||
|
||||
pe = page_entry_new(pd, index);
|
||||
q_tree_insert(set->tree, &pe->index, pe);
|
||||
g_tree_insert(set->tree, &pe->index, pe);
|
||||
|
||||
/*
|
||||
* If this is either (1) the first insertion or (2) a page whose index
|
||||
@@ -511,30 +509,30 @@ static gint tb_page_addr_cmp(gconstpointer ap, gconstpointer bp, gpointer udata)
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock a range of pages ([@start,@last]) as well as the pages of all
|
||||
* Lock a range of pages ([@start,@end[) as well as the pages of all
|
||||
* intersecting TBs.
|
||||
* Locking order: acquire locks in ascending order of page index.
|
||||
*/
|
||||
static struct page_collection *page_collection_lock(tb_page_addr_t start,
|
||||
tb_page_addr_t last)
|
||||
tb_page_addr_t end)
|
||||
{
|
||||
struct page_collection *set = g_malloc(sizeof(*set));
|
||||
tb_page_addr_t index;
|
||||
PageDesc *pd;
|
||||
|
||||
start >>= TARGET_PAGE_BITS;
|
||||
last >>= TARGET_PAGE_BITS;
|
||||
g_assert(start <= last);
|
||||
end >>= TARGET_PAGE_BITS;
|
||||
g_assert(start <= end);
|
||||
|
||||
set->tree = q_tree_new_full(tb_page_addr_cmp, NULL, NULL,
|
||||
set->tree = g_tree_new_full(tb_page_addr_cmp, NULL, NULL,
|
||||
page_entry_destroy);
|
||||
set->max = NULL;
|
||||
assert_no_pages_locked();
|
||||
|
||||
retry:
|
||||
q_tree_foreach(set->tree, page_entry_lock, NULL);
|
||||
g_tree_foreach(set->tree, page_entry_lock, NULL);
|
||||
|
||||
for (index = start; index <= last; index++) {
|
||||
for (index = start; index <= end; index++) {
|
||||
TranslationBlock *tb;
|
||||
PageForEachNext n;
|
||||
|
||||
@@ -543,7 +541,7 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start,
|
||||
continue;
|
||||
}
|
||||
if (page_trylock_add(set, index << TARGET_PAGE_BITS)) {
|
||||
q_tree_foreach(set->tree, page_entry_unlock, NULL);
|
||||
g_tree_foreach(set->tree, page_entry_unlock, NULL);
|
||||
goto retry;
|
||||
}
|
||||
assert_page_locked(pd);
|
||||
@@ -552,7 +550,7 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start,
|
||||
(tb_page_addr1(tb) != -1 &&
|
||||
page_trylock_add(set, tb_page_addr1(tb)))) {
|
||||
/* drop all locks, and reacquire in order */
|
||||
q_tree_foreach(set->tree, page_entry_unlock, NULL);
|
||||
g_tree_foreach(set->tree, page_entry_unlock, NULL);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
@@ -563,7 +561,7 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start,
|
||||
static void page_collection_unlock(struct page_collection *set)
|
||||
{
|
||||
/* entries are unlocked and freed via page_entry_destroy */
|
||||
q_tree_destroy(set->tree);
|
||||
g_tree_destroy(set->tree);
|
||||
g_free(set);
|
||||
}
|
||||
|
||||
@@ -991,14 +989,14 @@ TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
|
||||
* Called with mmap_lock held for user-mode emulation.
|
||||
* NOTE: this function must not be called while a TB is running.
|
||||
*/
|
||||
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t last)
|
||||
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
PageForEachNext n;
|
||||
|
||||
assert_memory_lock();
|
||||
|
||||
PAGE_FOR_EACH_TB(start, last, unused, tb, n) {
|
||||
PAGE_FOR_EACH_TB(start, end, unused, tb, n) {
|
||||
tb_phys_invalidate__locked(tb);
|
||||
}
|
||||
}
|
||||
@@ -1010,11 +1008,11 @@ void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t last)
|
||||
*/
|
||||
void tb_invalidate_phys_page(tb_page_addr_t addr)
|
||||
{
|
||||
tb_page_addr_t start, last;
|
||||
tb_page_addr_t start, end;
|
||||
|
||||
start = addr & TARGET_PAGE_MASK;
|
||||
last = addr | ~TARGET_PAGE_MASK;
|
||||
tb_invalidate_phys_range(start, last);
|
||||
end = start + TARGET_PAGE_SIZE;
|
||||
tb_invalidate_phys_range(start, end);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1030,7 +1028,6 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
|
||||
bool current_tb_modified;
|
||||
TranslationBlock *tb;
|
||||
PageForEachNext n;
|
||||
tb_page_addr_t last;
|
||||
|
||||
/*
|
||||
* Without precise smc semantics, or when outside of a TB,
|
||||
@@ -1047,11 +1044,10 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
|
||||
assert_memory_lock();
|
||||
current_tb = tcg_tb_lookup(pc);
|
||||
|
||||
last = addr | ~TARGET_PAGE_MASK;
|
||||
addr &= TARGET_PAGE_MASK;
|
||||
current_tb_modified = false;
|
||||
|
||||
PAGE_FOR_EACH_TB(addr, last, unused, tb, n) {
|
||||
PAGE_FOR_EACH_TB(addr, addr + TARGET_PAGE_SIZE, unused, tb, n) {
|
||||
if (current_tb == tb &&
|
||||
(tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
|
||||
/*
|
||||
@@ -1083,10 +1079,11 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
|
||||
static void
|
||||
tb_invalidate_phys_page_range__locked(struct page_collection *pages,
|
||||
PageDesc *p, tb_page_addr_t start,
|
||||
tb_page_addr_t last,
|
||||
tb_page_addr_t end,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
tb_page_addr_t tb_start, tb_end;
|
||||
PageForEachNext n;
|
||||
#ifdef TARGET_HAS_PRECISE_SMC
|
||||
bool current_tb_modified = false;
|
||||
@@ -1094,22 +1091,22 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
|
||||
#endif /* TARGET_HAS_PRECISE_SMC */
|
||||
|
||||
/*
|
||||
* We remove all the TBs in the range [start, last].
|
||||
* We remove all the TBs in the range [start, end[.
|
||||
* XXX: see if in some cases it could be faster to invalidate all the code
|
||||
*/
|
||||
PAGE_FOR_EACH_TB(start, last, p, tb, n) {
|
||||
tb_page_addr_t tb_start, tb_last;
|
||||
|
||||
PAGE_FOR_EACH_TB(start, end, p, tb, n) {
|
||||
/* NOTE: this is subtle as a TB may span two physical pages */
|
||||
tb_start = tb_page_addr0(tb);
|
||||
tb_last = tb_start + tb->size - 1;
|
||||
if (n == 0) {
|
||||
tb_last = MIN(tb_last, tb_start | ~TARGET_PAGE_MASK);
|
||||
/* NOTE: tb_end may be after the end of the page, but
|
||||
it is not a problem */
|
||||
tb_start = tb_page_addr0(tb);
|
||||
tb_end = tb_start + tb->size;
|
||||
} else {
|
||||
tb_start = tb_page_addr1(tb);
|
||||
tb_last = tb_start + (tb_last & ~TARGET_PAGE_MASK);
|
||||
tb_end = tb_start + ((tb_page_addr0(tb) + tb->size)
|
||||
& ~TARGET_PAGE_MASK);
|
||||
}
|
||||
if (!(tb_last < start || tb_start > last)) {
|
||||
if (!(tb_end <= start || tb_start >= end)) {
|
||||
#ifdef TARGET_HAS_PRECISE_SMC
|
||||
if (current_tb == tb &&
|
||||
(tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
|
||||
@@ -1151,7 +1148,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
|
||||
void tb_invalidate_phys_page(tb_page_addr_t addr)
|
||||
{
|
||||
struct page_collection *pages;
|
||||
tb_page_addr_t start, last;
|
||||
tb_page_addr_t start, end;
|
||||
PageDesc *p;
|
||||
|
||||
p = page_find(addr >> TARGET_PAGE_BITS);
|
||||
@@ -1160,37 +1157,35 @@ void tb_invalidate_phys_page(tb_page_addr_t addr)
|
||||
}
|
||||
|
||||
start = addr & TARGET_PAGE_MASK;
|
||||
last = addr | ~TARGET_PAGE_MASK;
|
||||
pages = page_collection_lock(start, last);
|
||||
tb_invalidate_phys_page_range__locked(pages, p, start, last, 0);
|
||||
end = start + TARGET_PAGE_SIZE;
|
||||
pages = page_collection_lock(start, end);
|
||||
tb_invalidate_phys_page_range__locked(pages, p, start, end, 0);
|
||||
page_collection_unlock(pages);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invalidate all TBs which intersect with the target physical address range
|
||||
* [start;last]. NOTE: start and end may refer to *different* physical pages.
|
||||
* [start;end[. NOTE: start and end may refer to *different* physical pages.
|
||||
* 'is_cpu_write_access' should be true if called from a real cpu write
|
||||
* access: the virtual CPU will exit the current TB if code is modified inside
|
||||
* this TB.
|
||||
*/
|
||||
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t last)
|
||||
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
|
||||
{
|
||||
struct page_collection *pages;
|
||||
tb_page_addr_t index, index_last;
|
||||
tb_page_addr_t next;
|
||||
|
||||
pages = page_collection_lock(start, last);
|
||||
|
||||
index_last = last >> TARGET_PAGE_BITS;
|
||||
for (index = start >> TARGET_PAGE_BITS; index <= index_last; index++) {
|
||||
PageDesc *pd = page_find(index);
|
||||
tb_page_addr_t bound;
|
||||
pages = page_collection_lock(start, end);
|
||||
for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
|
||||
start < end;
|
||||
start = next, next += TARGET_PAGE_SIZE) {
|
||||
PageDesc *pd = page_find(start >> TARGET_PAGE_BITS);
|
||||
tb_page_addr_t bound = MIN(next, end);
|
||||
|
||||
if (pd == NULL) {
|
||||
continue;
|
||||
}
|
||||
assert_page_locked(pd);
|
||||
bound = (index << TARGET_PAGE_BITS) | ~TARGET_PAGE_MASK;
|
||||
bound = MIN(bound, last);
|
||||
tb_invalidate_phys_page_range__locked(pages, pd, start, bound, 0);
|
||||
}
|
||||
page_collection_unlock(pages);
|
||||
@@ -1211,7 +1206,7 @@ static void tb_invalidate_phys_page_fast__locked(struct page_collection *pages,
|
||||
}
|
||||
|
||||
assert_page_locked(p);
|
||||
tb_invalidate_phys_page_range__locked(pages, p, start, start + len - 1, ra);
|
||||
tb_invalidate_phys_page_range__locked(pages, p, start, start + len, ra);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1225,7 +1220,7 @@ void tb_invalidate_phys_range_fast(ram_addr_t ram_addr,
|
||||
{
|
||||
struct page_collection *pages;
|
||||
|
||||
pages = page_collection_lock(ram_addr, ram_addr + size - 1);
|
||||
pages = page_collection_lock(ram_addr, ram_addr + size);
|
||||
tb_invalidate_phys_page_fast__locked(pages, ram_addr, size, retaddr);
|
||||
page_collection_unlock(pages);
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ void tcg_cpu_init_cflags(CPUState *cpu, bool parallel)
|
||||
|
||||
cflags |= parallel ? CF_PARALLEL : 0;
|
||||
cflags |= icount_enabled() ? CF_USE_ICOUNT : 0;
|
||||
cpu->tcg_cflags |= cflags;
|
||||
cpu->tcg_cflags = cflags;
|
||||
}
|
||||
|
||||
void tcg_cpus_destroy(CPUState *cpu)
|
||||
|
@@ -47,7 +47,6 @@
|
||||
#include "exec/cputlb.h"
|
||||
#include "exec/translate-all.h"
|
||||
#include "exec/translator.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "qemu/main-loop.h"
|
||||
@@ -572,7 +571,7 @@ void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
|
||||
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
|
||||
addr = get_page_addr_code(env, pc);
|
||||
if (addr != -1) {
|
||||
tb_invalidate_phys_range(addr, addr);
|
||||
tb_invalidate_phys_range(addr, addr + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -480,22 +480,24 @@ static bool pageflags_set_clear(target_ulong start, target_ulong last,
|
||||
* The flag PAGE_WRITE_ORG is positioned automatically depending
|
||||
* on PAGE_WRITE. The mmap_lock should already be held.
|
||||
*/
|
||||
void page_set_flags(target_ulong start, target_ulong last, int flags)
|
||||
void page_set_flags(target_ulong start, target_ulong end, int flags)
|
||||
{
|
||||
target_ulong last;
|
||||
bool reset = false;
|
||||
bool inval_tb = false;
|
||||
|
||||
/* 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(start <= last);
|
||||
assert(last <= GUEST_ADDR_MAX);
|
||||
assert(start < end);
|
||||
assert(end - 1 <= GUEST_ADDR_MAX);
|
||||
/* Only set PAGE_ANON with new mappings. */
|
||||
assert(!(flags & PAGE_ANON) || (flags & PAGE_RESET));
|
||||
assert_memory_lock();
|
||||
|
||||
start &= TARGET_PAGE_MASK;
|
||||
last |= ~TARGET_PAGE_MASK;
|
||||
start = start & TARGET_PAGE_MASK;
|
||||
end = TARGET_PAGE_ALIGN(end);
|
||||
last = end - 1;
|
||||
|
||||
if (!(flags & PAGE_VALID)) {
|
||||
flags = 0;
|
||||
@@ -508,7 +510,7 @@ void page_set_flags(target_ulong start, target_ulong last, int flags)
|
||||
}
|
||||
|
||||
if (!flags || reset) {
|
||||
page_reset_target_data(start, last);
|
||||
page_reset_target_data(start, end);
|
||||
inval_tb |= pageflags_unset(start, last);
|
||||
}
|
||||
if (flags) {
|
||||
@@ -516,7 +518,7 @@ void page_set_flags(target_ulong start, target_ulong last, int flags)
|
||||
~(reset ? 0 : PAGE_STICKY));
|
||||
}
|
||||
if (inval_tb) {
|
||||
tb_invalidate_phys_range(start, last);
|
||||
tb_invalidate_phys_range(start, end);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,14 +816,15 @@ typedef struct TargetPageDataNode {
|
||||
|
||||
static IntervalTreeRoot targetdata_root;
|
||||
|
||||
void page_reset_target_data(target_ulong start, target_ulong last)
|
||||
void page_reset_target_data(target_ulong start, target_ulong end)
|
||||
{
|
||||
IntervalTreeNode *n, *next;
|
||||
target_ulong last;
|
||||
|
||||
assert_memory_lock();
|
||||
|
||||
start &= TARGET_PAGE_MASK;
|
||||
last |= ~TARGET_PAGE_MASK;
|
||||
start = start & TARGET_PAGE_MASK;
|
||||
last = TARGET_PAGE_ALIGN(end) - 1;
|
||||
|
||||
for (n = interval_tree_iter_first(&targetdata_root, start, last),
|
||||
next = n ? interval_tree_iter_next(n, start, last) : NULL;
|
||||
@@ -884,7 +887,7 @@ void *page_get_target_data(target_ulong address)
|
||||
return t->data[(page - region) >> TARGET_PAGE_BITS];
|
||||
}
|
||||
#else
|
||||
void page_reset_target_data(target_ulong start, target_ulong last) { }
|
||||
void page_reset_target_data(target_ulong start, target_ulong end) { }
|
||||
#endif /* TARGET_PAGE_DATA_SIZE */
|
||||
|
||||
/* The softmmu versions of these helpers are in cputlb.c. */
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/xen/xen_native.h"
|
||||
#include "hw/xen/xen-legacy-backend.h"
|
||||
#include "hw/xen/xen_pt.h"
|
||||
#include "chardev/char.h"
|
||||
@@ -30,12 +29,83 @@ xc_interface *xen_xc;
|
||||
xenforeignmemory_handle *xen_fmem;
|
||||
xendevicemodel_handle *xen_dmod;
|
||||
|
||||
static void xenstore_record_dm_state(const char *state)
|
||||
static int store_dev_info(int domid, Chardev *cs, const char *string)
|
||||
{
|
||||
struct xs_handle *xs = NULL;
|
||||
char *path = NULL;
|
||||
char *newpath = NULL;
|
||||
char *pts = NULL;
|
||||
int ret = -1;
|
||||
|
||||
/* Only continue if we're talking to a pty. */
|
||||
if (!CHARDEV_IS_PTY(cs)) {
|
||||
return 0;
|
||||
}
|
||||
pts = cs->filename + 4;
|
||||
|
||||
/* We now have everything we need to set the xenstore entry. */
|
||||
xs = xs_open(0);
|
||||
if (xs == NULL) {
|
||||
fprintf(stderr, "Could not contact XenStore\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
path = xs_get_domain_path(xs, domid);
|
||||
if (path == NULL) {
|
||||
fprintf(stderr, "xs_get_domain_path() error\n");
|
||||
goto out;
|
||||
}
|
||||
newpath = realloc(path, (strlen(path) + strlen(string) +
|
||||
strlen("/tty") + 1));
|
||||
if (newpath == NULL) {
|
||||
fprintf(stderr, "realloc error\n");
|
||||
goto out;
|
||||
}
|
||||
path = newpath;
|
||||
|
||||
strcat(path, string);
|
||||
strcat(path, "/tty");
|
||||
if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
|
||||
fprintf(stderr, "xs_write for '%s' fail", string);
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
free(path);
|
||||
xs_close(xs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void xenstore_store_pv_console_info(int i, Chardev *chr)
|
||||
{
|
||||
if (i == 0) {
|
||||
store_dev_info(xen_domid, chr, "/console");
|
||||
} else {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "/device/console/%d", i);
|
||||
store_dev_info(xen_domid, chr, buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
|
||||
{
|
||||
char path[50];
|
||||
|
||||
if (xs == NULL) {
|
||||
error_report("xenstore connection not initialized");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
|
||||
if (!qemu_xen_xs_write(xenstore, XBT_NULL, path, state, strlen(state))) {
|
||||
/*
|
||||
* This call may fail when running restricted so don't make it fatal in
|
||||
* that case. Toolstacks should instead use QMP to listen for state changes.
|
||||
*/
|
||||
if (!xs_write(xs, XBT_NULL, path, state, strlen(state)) &&
|
||||
!xen_domid_restrict) {
|
||||
error_report("error recording dm state");
|
||||
exit(1);
|
||||
}
|
||||
@@ -47,7 +117,7 @@ static void xen_change_state_handler(void *opaque, bool running,
|
||||
{
|
||||
if (running) {
|
||||
/* record state running */
|
||||
xenstore_record_dm_state("running");
|
||||
xenstore_record_dm_state(xenstore, "running");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,15 +166,7 @@ static int xen_init(MachineState *ms)
|
||||
xc_interface_close(xen_xc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The XenStore write would fail when running restricted so don't attempt
|
||||
* it in that case. Toolstacks should instead use QMP to listen for state
|
||||
* changes.
|
||||
*/
|
||||
if (!xen_domid_restrict) {
|
||||
qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
|
||||
}
|
||||
qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
|
||||
/*
|
||||
* opt out of system RAM being allocated by generic code
|
||||
*/
|
||||
|
@@ -222,7 +222,11 @@ static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfds = g_new0(struct pollfd, count);
|
||||
pfds = audio_calloc ("alsa_poll_helper", count, sizeof (*pfds));
|
||||
if (!pfds) {
|
||||
dolog ("Could not initialize poll mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_poll_descriptors (handle, pfds, count);
|
||||
if (err < 0) {
|
||||
@@ -913,23 +917,28 @@ static void *alsa_audio_init(Audiodev *dev)
|
||||
alsa_init_per_direction(aopts->in);
|
||||
alsa_init_per_direction(aopts->out);
|
||||
|
||||
/* don't set has_* so alsa_open can identify it wasn't set by the user */
|
||||
/*
|
||||
* need to define them, as otherwise alsa produces no sound
|
||||
* doesn't set has_* so alsa_open can identify it wasn't set by the user
|
||||
*/
|
||||
if (!dev->u.alsa.out->has_period_length) {
|
||||
/* 256 frames assuming 44100Hz */
|
||||
dev->u.alsa.out->period_length = 5805;
|
||||
/* 1024 frames assuming 44100Hz */
|
||||
dev->u.alsa.out->period_length = 1024 * 1000000 / 44100;
|
||||
}
|
||||
if (!dev->u.alsa.out->has_buffer_length) {
|
||||
/* 4096 frames assuming 44100Hz */
|
||||
dev->u.alsa.out->buffer_length = 92880;
|
||||
dev->u.alsa.out->buffer_length = 4096ll * 1000000 / 44100;
|
||||
}
|
||||
|
||||
/*
|
||||
* OptsVisitor sets unspecified optional fields to zero, but do not depend
|
||||
* on it...
|
||||
*/
|
||||
if (!dev->u.alsa.in->has_period_length) {
|
||||
/* 256 frames assuming 44100Hz */
|
||||
dev->u.alsa.in->period_length = 5805;
|
||||
dev->u.alsa.in->period_length = 0;
|
||||
}
|
||||
if (!dev->u.alsa.in->has_buffer_length) {
|
||||
/* 4096 frames assuming 44100Hz */
|
||||
dev->u.alsa.in->buffer_length = 92880;
|
||||
dev->u.alsa.in->buffer_length = 0;
|
||||
}
|
||||
|
||||
return dev;
|
||||
|
390
audio/audio.c
390
audio/audio.c
@@ -33,7 +33,6 @@
|
||||
#include "qapi/qapi-visit-audio.h"
|
||||
#include "qapi/qapi-commands-audio.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/help_option.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
@@ -149,6 +148,26 @@ static inline int audio_bits_to_index (int bits)
|
||||
}
|
||||
}
|
||||
|
||||
void *audio_calloc (const char *funcname, int nmemb, size_t size)
|
||||
{
|
||||
int cond;
|
||||
size_t len;
|
||||
|
||||
len = nmemb * size;
|
||||
cond = !nmemb || !size;
|
||||
cond |= nmemb < 0;
|
||||
cond |= len < size;
|
||||
|
||||
if (audio_bug ("audio_calloc", cond)) {
|
||||
AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n",
|
||||
funcname);
|
||||
AUD_log (NULL, "nmemb=%d size=%zu (len=%zu)\n", nmemb, size, len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_malloc0 (len);
|
||||
}
|
||||
|
||||
void AUD_vlog (const char *cap, const char *fmt, va_list ap)
|
||||
{
|
||||
if (cap) {
|
||||
@@ -381,6 +400,13 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
|
||||
/*
|
||||
* Capture
|
||||
*/
|
||||
static void noop_conv (struct st_sample *dst, const void *src, int samples)
|
||||
{
|
||||
(void) src;
|
||||
(void) dst;
|
||||
(void) samples;
|
||||
}
|
||||
|
||||
static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioState *s,
|
||||
struct audsettings *as)
|
||||
{
|
||||
@@ -478,8 +504,15 @@ static int audio_attach_capture (HWVoiceOut *hw)
|
||||
sw->info = hw->info;
|
||||
sw->empty = 1;
|
||||
sw->active = hw->enabled;
|
||||
sw->conv = noop_conv;
|
||||
sw->ratio = ((int64_t) hw_cap->info.freq << 32) / sw->info.freq;
|
||||
sw->vol = nominal_volume;
|
||||
sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);
|
||||
if (!sw->rate) {
|
||||
dolog ("Could not start rate conversion for `%s'\n", SW_NAME (sw));
|
||||
g_free (sw);
|
||||
return -1;
|
||||
}
|
||||
QLIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries);
|
||||
QLIST_INSERT_HEAD (&hw->cap_head, sc, entries);
|
||||
#ifdef DEBUG_CAPTURE
|
||||
@@ -514,8 +547,8 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)
|
||||
static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
|
||||
{
|
||||
size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
|
||||
if (audio_bug(__func__, live > hw->conv_buf.size)) {
|
||||
dolog("live=%zu hw->conv_buf.size=%zu\n", live, hw->conv_buf.size);
|
||||
if (audio_bug(__func__, live > hw->conv_buf->size)) {
|
||||
dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
|
||||
return 0;
|
||||
}
|
||||
return live;
|
||||
@@ -524,13 +557,13 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
|
||||
static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples)
|
||||
{
|
||||
size_t conv = 0;
|
||||
STSampleBuffer *conv_buf = &hw->conv_buf;
|
||||
STSampleBuffer *conv_buf = hw->conv_buf;
|
||||
|
||||
while (samples) {
|
||||
uint8_t *src = advance(pcm_buf, conv * hw->info.bytes_per_frame);
|
||||
size_t proc = MIN(samples, conv_buf->size - conv_buf->pos);
|
||||
|
||||
hw->conv(conv_buf->buffer + conv_buf->pos, src, proc);
|
||||
hw->conv(conv_buf->samples + conv_buf->pos, src, proc);
|
||||
conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size;
|
||||
samples -= proc;
|
||||
conv += proc;
|
||||
@@ -542,65 +575,56 @@ static size_t audio_pcm_hw_conv_in(HWVoiceIn *hw, void *pcm_buf, size_t samples)
|
||||
/*
|
||||
* Soft voice (capture)
|
||||
*/
|
||||
static void audio_pcm_sw_resample_in(SWVoiceIn *sw,
|
||||
size_t frames_in_max, size_t frames_out_max,
|
||||
size_t *total_in, size_t *total_out)
|
||||
static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size)
|
||||
{
|
||||
HWVoiceIn *hw = sw->hw;
|
||||
struct st_sample *src, *dst;
|
||||
size_t live, rpos, frames_in, frames_out;
|
||||
|
||||
live = hw->total_samples_captured - sw->total_hw_samples_acquired;
|
||||
rpos = audio_ring_posb(hw->conv_buf.pos, live, hw->conv_buf.size);
|
||||
|
||||
/* resample conv_buf from rpos to end of buffer */
|
||||
src = hw->conv_buf.buffer + rpos;
|
||||
frames_in = MIN(frames_in_max, hw->conv_buf.size - rpos);
|
||||
dst = sw->resample_buf.buffer;
|
||||
frames_out = frames_out_max;
|
||||
st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out);
|
||||
rpos += frames_in;
|
||||
*total_in = frames_in;
|
||||
*total_out = frames_out;
|
||||
|
||||
/* resample conv_buf from start of buffer if there are input frames left */
|
||||
if (frames_in_max - frames_in && rpos == hw->conv_buf.size) {
|
||||
src = hw->conv_buf.buffer;
|
||||
frames_in = frames_in_max - frames_in;
|
||||
dst += frames_out;
|
||||
frames_out = frames_out_max - frames_out;
|
||||
st_rate_flow(sw->rate, src, dst, &frames_in, &frames_out);
|
||||
*total_in += frames_in;
|
||||
*total_out += frames_out;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t buf_len)
|
||||
{
|
||||
HWVoiceIn *hw = sw->hw;
|
||||
size_t live, frames_out_max, total_in, total_out;
|
||||
size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
|
||||
struct st_sample *src, *dst = sw->buf;
|
||||
|
||||
live = hw->total_samples_captured - sw->total_hw_samples_acquired;
|
||||
if (!live) {
|
||||
return 0;
|
||||
}
|
||||
if (audio_bug(__func__, live > hw->conv_buf.size)) {
|
||||
dolog("live_in=%zu hw->conv_buf.size=%zu\n", live, hw->conv_buf.size);
|
||||
if (audio_bug(__func__, live > hw->conv_buf->size)) {
|
||||
dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
frames_out_max = MIN(buf_len / sw->info.bytes_per_frame,
|
||||
sw->resample_buf.size);
|
||||
rpos = audio_ring_posb(hw->conv_buf->pos, live, hw->conv_buf->size);
|
||||
|
||||
audio_pcm_sw_resample_in(sw, live, frames_out_max, &total_in, &total_out);
|
||||
samples = size / sw->info.bytes_per_frame;
|
||||
|
||||
swlim = (live * sw->ratio) >> 32;
|
||||
swlim = MIN (swlim, samples);
|
||||
|
||||
while (swlim) {
|
||||
src = hw->conv_buf->samples + rpos;
|
||||
if (hw->conv_buf->pos > rpos) {
|
||||
isamp = hw->conv_buf->pos - rpos;
|
||||
} else {
|
||||
isamp = hw->conv_buf->size - rpos;
|
||||
}
|
||||
|
||||
if (!isamp) {
|
||||
break;
|
||||
}
|
||||
osamp = swlim;
|
||||
|
||||
st_rate_flow (sw->rate, src, dst, &isamp, &osamp);
|
||||
swlim -= osamp;
|
||||
rpos = (rpos + isamp) % hw->conv_buf->size;
|
||||
dst += osamp;
|
||||
ret += osamp;
|
||||
total += isamp;
|
||||
}
|
||||
|
||||
if (!hw->pcm_ops->volume_in) {
|
||||
mixeng_volume(sw->resample_buf.buffer, total_out, &sw->vol);
|
||||
mixeng_volume (sw->buf, ret, &sw->vol);
|
||||
}
|
||||
sw->clip(buf, sw->resample_buf.buffer, total_out);
|
||||
|
||||
sw->total_hw_samples_acquired += total_in;
|
||||
return total_out * sw->info.bytes_per_frame;
|
||||
sw->clip (buf, sw->buf, ret);
|
||||
sw->total_hw_samples_acquired += total;
|
||||
return ret * sw->info.bytes_per_frame;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -636,8 +660,8 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live)
|
||||
if (nb_live1) {
|
||||
size_t live = smin;
|
||||
|
||||
if (audio_bug(__func__, live > hw->mix_buf.size)) {
|
||||
dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size);
|
||||
if (audio_bug(__func__, live > hw->mix_buf->size)) {
|
||||
dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size);
|
||||
return 0;
|
||||
}
|
||||
return live;
|
||||
@@ -654,17 +678,17 @@ static size_t audio_pcm_hw_get_free(HWVoiceOut *hw)
|
||||
static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
|
||||
{
|
||||
size_t clipped = 0;
|
||||
size_t pos = hw->mix_buf.pos;
|
||||
size_t pos = hw->mix_buf->pos;
|
||||
|
||||
while (len) {
|
||||
st_sample *src = hw->mix_buf.buffer + pos;
|
||||
st_sample *src = hw->mix_buf->samples + pos;
|
||||
uint8_t *dst = advance(pcm_buf, clipped * hw->info.bytes_per_frame);
|
||||
size_t samples_till_end_of_buf = hw->mix_buf.size - pos;
|
||||
size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
|
||||
size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
|
||||
|
||||
hw->clip(dst, src, samples_to_clip);
|
||||
|
||||
pos = (pos + samples_to_clip) % hw->mix_buf.size;
|
||||
pos = (pos + samples_to_clip) % hw->mix_buf->size;
|
||||
len -= samples_to_clip;
|
||||
clipped += samples_to_clip;
|
||||
}
|
||||
@@ -673,113 +697,84 @@ static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
|
||||
/*
|
||||
* Soft voice (playback)
|
||||
*/
|
||||
static void audio_pcm_sw_resample_out(SWVoiceOut *sw,
|
||||
size_t frames_in_max, size_t frames_out_max,
|
||||
size_t *total_in, size_t *total_out)
|
||||
static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
|
||||
{
|
||||
HWVoiceOut *hw = sw->hw;
|
||||
struct st_sample *src, *dst;
|
||||
size_t live, wpos, frames_in, frames_out;
|
||||
size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, blck;
|
||||
size_t hw_free;
|
||||
size_t ret = 0, pos = 0, total = 0;
|
||||
|
||||
live = sw->total_hw_samples_mixed;
|
||||
wpos = (hw->mix_buf.pos + live) % hw->mix_buf.size;
|
||||
|
||||
/* write to mix_buf from wpos to end of buffer */
|
||||
src = sw->resample_buf.buffer;
|
||||
frames_in = frames_in_max;
|
||||
dst = hw->mix_buf.buffer + wpos;
|
||||
frames_out = MIN(frames_out_max, hw->mix_buf.size - wpos);
|
||||
st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
|
||||
wpos += frames_out;
|
||||
*total_in = frames_in;
|
||||
*total_out = frames_out;
|
||||
|
||||
/* write to mix_buf from start of buffer if there are input frames left */
|
||||
if (frames_in_max - frames_in > 0 && wpos == hw->mix_buf.size) {
|
||||
src += frames_in;
|
||||
frames_in = frames_in_max - frames_in;
|
||||
dst = hw->mix_buf.buffer;
|
||||
frames_out = frames_out_max - frames_out;
|
||||
st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
|
||||
*total_in += frames_in;
|
||||
*total_out += frames_out;
|
||||
if (!sw) {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len)
|
||||
{
|
||||
HWVoiceOut *hw = sw->hw;
|
||||
size_t live, dead, hw_free, sw_max, fe_max;
|
||||
size_t frames_in_max, frames_out_max, total_in, total_out;
|
||||
hwsamples = sw->hw->mix_buf->size;
|
||||
|
||||
live = sw->total_hw_samples_mixed;
|
||||
if (audio_bug(__func__, live > hw->mix_buf.size)) {
|
||||
dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size);
|
||||
if (audio_bug(__func__, live > hwsamples)) {
|
||||
dolog("live=%zu hw->mix_buf->size=%zu\n", live, hwsamples);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (live == hw->mix_buf.size) {
|
||||
if (live == hwsamples) {
|
||||
#ifdef DEBUG_OUT
|
||||
dolog ("%s is full %zu\n", sw->name, live);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
dead = hw->mix_buf.size - live;
|
||||
hw_free = audio_pcm_hw_get_free(hw);
|
||||
wpos = (sw->hw->mix_buf->pos + live) % hwsamples;
|
||||
|
||||
dead = hwsamples - live;
|
||||
hw_free = audio_pcm_hw_get_free(sw->hw);
|
||||
hw_free = hw_free > live ? hw_free - live : 0;
|
||||
frames_out_max = MIN(dead, hw_free);
|
||||
sw_max = st_rate_frames_in(sw->rate, frames_out_max);
|
||||
fe_max = MIN(buf_len / sw->info.bytes_per_frame + sw->resample_buf.pos,
|
||||
sw->resample_buf.size);
|
||||
frames_in_max = MIN(sw_max, fe_max);
|
||||
samples = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
|
||||
samples = MIN(samples, size / sw->info.bytes_per_frame);
|
||||
if (samples) {
|
||||
sw->conv(sw->buf, buf, samples);
|
||||
|
||||
if (!frames_in_max) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (frames_in_max > sw->resample_buf.pos) {
|
||||
sw->conv(sw->resample_buf.buffer + sw->resample_buf.pos,
|
||||
buf, frames_in_max - sw->resample_buf.pos);
|
||||
if (!sw->hw->pcm_ops->volume_out) {
|
||||
mixeng_volume(sw->resample_buf.buffer + sw->resample_buf.pos,
|
||||
frames_in_max - sw->resample_buf.pos, &sw->vol);
|
||||
mixeng_volume(sw->buf, samples, &sw->vol);
|
||||
}
|
||||
}
|
||||
|
||||
audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max,
|
||||
&total_in, &total_out);
|
||||
|
||||
sw->total_hw_samples_mixed += total_out;
|
||||
sw->empty = sw->total_hw_samples_mixed == 0;
|
||||
|
||||
/*
|
||||
* Upsampling may leave one audio frame in the resample buffer. Decrement
|
||||
* total_in by one if there was a leftover frame from the previous resample
|
||||
* pass in the resample buffer. Increment total_in by one if the current
|
||||
* resample pass left one frame in the resample buffer.
|
||||
*/
|
||||
if (frames_in_max - total_in == 1) {
|
||||
/* copy one leftover audio frame to the beginning of the buffer */
|
||||
*sw->resample_buf.buffer = *(sw->resample_buf.buffer + total_in);
|
||||
total_in += 1 - sw->resample_buf.pos;
|
||||
sw->resample_buf.pos = 1;
|
||||
} else if (total_in >= sw->resample_buf.pos) {
|
||||
total_in -= sw->resample_buf.pos;
|
||||
sw->resample_buf.pos = 0;
|
||||
while (samples) {
|
||||
dead = hwsamples - live;
|
||||
left = hwsamples - wpos;
|
||||
blck = MIN (dead, left);
|
||||
if (!blck) {
|
||||
break;
|
||||
}
|
||||
isamp = samples;
|
||||
osamp = blck;
|
||||
st_rate_flow_mix (
|
||||
sw->rate,
|
||||
sw->buf + pos,
|
||||
sw->hw->mix_buf->samples + wpos,
|
||||
&isamp,
|
||||
&osamp
|
||||
);
|
||||
ret += isamp;
|
||||
samples -= isamp;
|
||||
pos += isamp;
|
||||
live += osamp;
|
||||
wpos = (wpos + osamp) % hwsamples;
|
||||
total += osamp;
|
||||
}
|
||||
|
||||
sw->total_hw_samples_mixed += total;
|
||||
sw->empty = sw->total_hw_samples_mixed == 0;
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
dolog (
|
||||
"%s: write size %zu written %zu total mixed %zu\n",
|
||||
SW_NAME(sw),
|
||||
buf_len / sw->info.bytes_per_frame,
|
||||
total_in,
|
||||
"%s: write size %zu ret %zu total sw %zu\n",
|
||||
SW_NAME (sw),
|
||||
size / sw->info.bytes_per_frame,
|
||||
ret,
|
||||
sw->total_hw_samples_mixed
|
||||
);
|
||||
#endif
|
||||
|
||||
return total_in * sw->info.bytes_per_frame;
|
||||
return ret * sw->info.bytes_per_frame;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
@@ -997,6 +992,18 @@ void AUD_set_active_in (SWVoiceIn *sw, int on)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* audio_frontend_frames_in() - returns the number of frames the resampling
|
||||
* code generates from frames_in frames
|
||||
*
|
||||
* @sw: audio recording frontend
|
||||
* @frames_in: number of frames
|
||||
*/
|
||||
static size_t audio_frontend_frames_in(SWVoiceIn *sw, size_t frames_in)
|
||||
{
|
||||
return (int64_t)frames_in * sw->ratio >> 32;
|
||||
}
|
||||
|
||||
static size_t audio_get_avail (SWVoiceIn *sw)
|
||||
{
|
||||
size_t live;
|
||||
@@ -1006,21 +1013,33 @@ static size_t audio_get_avail (SWVoiceIn *sw)
|
||||
}
|
||||
|
||||
live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
|
||||
if (audio_bug(__func__, live > sw->hw->conv_buf.size)) {
|
||||
dolog("live=%zu sw->hw->conv_buf.size=%zu\n", live,
|
||||
sw->hw->conv_buf.size);
|
||||
if (audio_bug(__func__, live > sw->hw->conv_buf->size)) {
|
||||
dolog("live=%zu sw->hw->conv_buf->size=%zu\n", live,
|
||||
sw->hw->conv_buf->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ldebug (
|
||||
"%s: get_avail live %zu frontend frames %u\n",
|
||||
"%s: get_avail live %zu frontend frames %zu\n",
|
||||
SW_NAME (sw),
|
||||
live, st_rate_frames_out(sw->rate, live)
|
||||
live, audio_frontend_frames_in(sw, live)
|
||||
);
|
||||
|
||||
return live;
|
||||
}
|
||||
|
||||
/**
|
||||
* audio_frontend_frames_out() - returns the number of frames needed to
|
||||
* get frames_out frames after resampling
|
||||
*
|
||||
* @sw: audio playback frontend
|
||||
* @frames_out: number of frames
|
||||
*/
|
||||
static size_t audio_frontend_frames_out(SWVoiceOut *sw, size_t frames_out)
|
||||
{
|
||||
return ((int64_t)frames_out << 32) / sw->ratio;
|
||||
}
|
||||
|
||||
static size_t audio_get_free(SWVoiceOut *sw)
|
||||
{
|
||||
size_t live, dead;
|
||||
@@ -1031,17 +1050,17 @@ static size_t audio_get_free(SWVoiceOut *sw)
|
||||
|
||||
live = sw->total_hw_samples_mixed;
|
||||
|
||||
if (audio_bug(__func__, live > sw->hw->mix_buf.size)) {
|
||||
dolog("live=%zu sw->hw->mix_buf.size=%zu\n", live,
|
||||
sw->hw->mix_buf.size);
|
||||
if (audio_bug(__func__, live > sw->hw->mix_buf->size)) {
|
||||
dolog("live=%zu sw->hw->mix_buf->size=%zu\n", live,
|
||||
sw->hw->mix_buf->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dead = sw->hw->mix_buf.size - live;
|
||||
dead = sw->hw->mix_buf->size - live;
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
dolog("%s: get_free live %zu dead %zu frontend frames %u\n",
|
||||
SW_NAME(sw), live, dead, st_rate_frames_in(sw->rate, dead));
|
||||
dolog("%s: get_free live %zu dead %zu frontend frames %zu\n",
|
||||
SW_NAME(sw), live, dead, audio_frontend_frames_out(sw, dead));
|
||||
#endif
|
||||
|
||||
return dead;
|
||||
@@ -1057,40 +1076,32 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
|
||||
|
||||
for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
|
||||
SWVoiceOut *sw = &sc->sw;
|
||||
size_t rpos2 = rpos;
|
||||
int rpos2 = rpos;
|
||||
|
||||
n = samples;
|
||||
while (n) {
|
||||
size_t till_end_of_hw = hw->mix_buf.size - rpos2;
|
||||
size_t to_read = MIN(till_end_of_hw, n);
|
||||
size_t live, frames_in, frames_out;
|
||||
size_t till_end_of_hw = hw->mix_buf->size - rpos2;
|
||||
size_t to_write = MIN(till_end_of_hw, n);
|
||||
size_t bytes = to_write * hw->info.bytes_per_frame;
|
||||
size_t written;
|
||||
|
||||
sw->resample_buf.buffer = hw->mix_buf.buffer + rpos2;
|
||||
sw->resample_buf.size = to_read;
|
||||
live = sw->total_hw_samples_mixed;
|
||||
|
||||
audio_pcm_sw_resample_out(sw,
|
||||
to_read, sw->hw->mix_buf.size - live,
|
||||
&frames_in, &frames_out);
|
||||
|
||||
sw->total_hw_samples_mixed += frames_out;
|
||||
sw->empty = sw->total_hw_samples_mixed == 0;
|
||||
|
||||
if (to_read - frames_in) {
|
||||
dolog("Could not mix %zu frames into a capture "
|
||||
sw->buf = hw->mix_buf->samples + rpos2;
|
||||
written = audio_pcm_sw_write (sw, NULL, bytes);
|
||||
if (written - bytes) {
|
||||
dolog("Could not mix %zu bytes into a capture "
|
||||
"buffer, mixed %zu\n",
|
||||
to_read, frames_in);
|
||||
bytes, written);
|
||||
break;
|
||||
}
|
||||
n -= to_read;
|
||||
rpos2 = (rpos2 + to_read) % hw->mix_buf.size;
|
||||
n -= to_write;
|
||||
rpos2 = (rpos2 + to_write) % hw->mix_buf->size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n = MIN(samples, hw->mix_buf.size - rpos);
|
||||
mixeng_clear(hw->mix_buf.buffer + rpos, n);
|
||||
mixeng_clear(hw->mix_buf.buffer, samples - n);
|
||||
n = MIN(samples, hw->mix_buf->size - rpos);
|
||||
mixeng_clear(hw->mix_buf->samples + rpos, n);
|
||||
mixeng_clear(hw->mix_buf->samples, samples - n);
|
||||
}
|
||||
|
||||
static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
|
||||
@@ -1116,7 +1127,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live)
|
||||
|
||||
live -= proc;
|
||||
clipped += proc;
|
||||
hw->mix_buf.pos = (hw->mix_buf.pos + proc) % hw->mix_buf.size;
|
||||
hw->mix_buf->pos = (hw->mix_buf->pos + proc) % hw->mix_buf->size;
|
||||
|
||||
if (proc == 0 || proc < decr) {
|
||||
break;
|
||||
@@ -1170,14 +1181,12 @@ static void audio_run_out (AudioState *s)
|
||||
size_t free;
|
||||
|
||||
if (hw_free > sw->total_hw_samples_mixed) {
|
||||
free = st_rate_frames_in(sw->rate,
|
||||
free = audio_frontend_frames_out(sw,
|
||||
MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
|
||||
} else {
|
||||
free = 0;
|
||||
}
|
||||
if (free > sw->resample_buf.pos) {
|
||||
free = MIN(free, sw->resample_buf.size)
|
||||
- sw->resample_buf.pos;
|
||||
if (free > 0) {
|
||||
sw->callback.fn(sw->callback.opaque,
|
||||
free * sw->info.bytes_per_frame);
|
||||
}
|
||||
@@ -1189,8 +1198,8 @@ static void audio_run_out (AudioState *s)
|
||||
live = 0;
|
||||
}
|
||||
|
||||
if (audio_bug(__func__, live > hw->mix_buf.size)) {
|
||||
dolog("live=%zu hw->mix_buf.size=%zu\n", live, hw->mix_buf.size);
|
||||
if (audio_bug(__func__, live > hw->mix_buf->size)) {
|
||||
dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1218,13 +1227,13 @@ static void audio_run_out (AudioState *s)
|
||||
continue;
|
||||
}
|
||||
|
||||
prev_rpos = hw->mix_buf.pos;
|
||||
prev_rpos = hw->mix_buf->pos;
|
||||
played = audio_pcm_hw_run_out(hw, live);
|
||||
replay_audio_out(&played);
|
||||
if (audio_bug(__func__, hw->mix_buf.pos >= hw->mix_buf.size)) {
|
||||
dolog("hw->mix_buf.pos=%zu hw->mix_buf.size=%zu played=%zu\n",
|
||||
hw->mix_buf.pos, hw->mix_buf.size, played);
|
||||
hw->mix_buf.pos = 0;
|
||||
if (audio_bug(__func__, hw->mix_buf->pos >= hw->mix_buf->size)) {
|
||||
dolog("hw->mix_buf->pos=%zu hw->mix_buf->size=%zu played=%zu\n",
|
||||
hw->mix_buf->pos, hw->mix_buf->size, played);
|
||||
hw->mix_buf->pos = 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
@@ -1305,10 +1314,10 @@ static void audio_run_in (AudioState *s)
|
||||
|
||||
if (replay_mode != REPLAY_MODE_PLAY) {
|
||||
captured = audio_pcm_hw_run_in(
|
||||
hw, hw->conv_buf.size - audio_pcm_hw_get_live_in(hw));
|
||||
hw, hw->conv_buf->size - audio_pcm_hw_get_live_in(hw));
|
||||
}
|
||||
replay_audio_in(&captured, hw->conv_buf.buffer, &hw->conv_buf.pos,
|
||||
hw->conv_buf.size);
|
||||
replay_audio_in(&captured, hw->conv_buf->samples, &hw->conv_buf->pos,
|
||||
hw->conv_buf->size);
|
||||
|
||||
min = audio_pcm_hw_find_min_in (hw);
|
||||
hw->total_samples_captured += captured - min;
|
||||
@@ -1321,9 +1330,8 @@ static void audio_run_in (AudioState *s)
|
||||
size_t sw_avail = audio_get_avail(sw);
|
||||
size_t avail;
|
||||
|
||||
avail = st_rate_frames_out(sw->rate, sw_avail);
|
||||
avail = audio_frontend_frames_in(sw, sw_avail);
|
||||
if (avail > 0) {
|
||||
avail = MIN(avail, sw->resample_buf.size);
|
||||
sw->callback.fn(sw->callback.opaque,
|
||||
avail * sw->info.bytes_per_frame);
|
||||
}
|
||||
@@ -1342,14 +1350,14 @@ static void audio_run_capture (AudioState *s)
|
||||
SWVoiceOut *sw;
|
||||
|
||||
captured = live = audio_pcm_hw_get_live_out (hw, NULL);
|
||||
rpos = hw->mix_buf.pos;
|
||||
rpos = hw->mix_buf->pos;
|
||||
while (live) {
|
||||
size_t left = hw->mix_buf.size - rpos;
|
||||
size_t left = hw->mix_buf->size - rpos;
|
||||
size_t to_capture = MIN(live, left);
|
||||
struct st_sample *src;
|
||||
struct capture_callback *cb;
|
||||
|
||||
src = hw->mix_buf.buffer + rpos;
|
||||
src = hw->mix_buf->samples + rpos;
|
||||
hw->clip (cap->buf, src, to_capture);
|
||||
mixeng_clear (src, to_capture);
|
||||
|
||||
@@ -1357,10 +1365,10 @@ static void audio_run_capture (AudioState *s)
|
||||
cb->ops.capture (cb->opaque, cap->buf,
|
||||
to_capture * hw->info.bytes_per_frame);
|
||||
}
|
||||
rpos = (rpos + to_capture) % hw->mix_buf.size;
|
||||
rpos = (rpos + to_capture) % hw->mix_buf->size;
|
||||
live -= to_capture;
|
||||
}
|
||||
hw->mix_buf.pos = rpos;
|
||||
hw->mix_buf->pos = rpos;
|
||||
|
||||
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
|
||||
if (!sw->active && sw->empty) {
|
||||
@@ -1919,7 +1927,7 @@ CaptureVoiceOut *AUD_add_capture(
|
||||
|
||||
audio_pcm_init_info (&hw->info, as);
|
||||
|
||||
cap->buf = g_malloc0_n(hw->mix_buf.size, hw->info.bytes_per_frame);
|
||||
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];
|
||||
@@ -1971,7 +1979,7 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
|
||||
sw = sw1;
|
||||
}
|
||||
QLIST_REMOVE (cap, entries);
|
||||
g_free(cap->hw.mix_buf.buffer);
|
||||
g_free (cap->hw.mix_buf);
|
||||
g_free (cap->buf);
|
||||
g_free (cap);
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@ typedef struct SWVoiceCap SWVoiceCap;
|
||||
|
||||
typedef struct STSampleBuffer {
|
||||
size_t pos, size;
|
||||
st_sample *buffer;
|
||||
st_sample samples[];
|
||||
} STSampleBuffer;
|
||||
|
||||
typedef struct HWVoiceOut {
|
||||
@@ -71,7 +71,7 @@ typedef struct HWVoiceOut {
|
||||
f_sample *clip;
|
||||
uint64_t ts_helper;
|
||||
|
||||
STSampleBuffer mix_buf;
|
||||
STSampleBuffer *mix_buf;
|
||||
void *buf_emul;
|
||||
size_t pos_emul, pending_emul, size_emul;
|
||||
|
||||
@@ -93,7 +93,7 @@ typedef struct HWVoiceIn {
|
||||
size_t total_samples_captured;
|
||||
uint64_t ts_helper;
|
||||
|
||||
STSampleBuffer conv_buf;
|
||||
STSampleBuffer *conv_buf;
|
||||
void *buf_emul;
|
||||
size_t pos_emul, pending_emul, size_emul;
|
||||
|
||||
@@ -108,7 +108,8 @@ struct SWVoiceOut {
|
||||
AudioState *s;
|
||||
struct audio_pcm_info info;
|
||||
t_sample *conv;
|
||||
STSampleBuffer resample_buf;
|
||||
int64_t ratio;
|
||||
struct st_sample *buf;
|
||||
void *rate;
|
||||
size_t total_hw_samples_mixed;
|
||||
int active;
|
||||
@@ -125,9 +126,10 @@ struct SWVoiceIn {
|
||||
AudioState *s;
|
||||
int active;
|
||||
struct audio_pcm_info info;
|
||||
int64_t ratio;
|
||||
void *rate;
|
||||
size_t total_hw_samples_acquired;
|
||||
STSampleBuffer resample_buf;
|
||||
struct st_sample *buf;
|
||||
f_sample *clip;
|
||||
HWVoiceIn *hw;
|
||||
char *name;
|
||||
@@ -143,14 +145,14 @@ struct audio_driver {
|
||||
void *(*init) (Audiodev *);
|
||||
void (*fini) (void *);
|
||||
#ifdef CONFIG_GIO
|
||||
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p);
|
||||
void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager);
|
||||
#endif
|
||||
struct audio_pcm_ops *pcm_ops;
|
||||
int can_be_default;
|
||||
int max_voices_out;
|
||||
int max_voices_in;
|
||||
size_t voice_size_out;
|
||||
size_t voice_size_in;
|
||||
int voice_size_out;
|
||||
int voice_size_in;
|
||||
QLIST_ENTRY(audio_driver) next;
|
||||
};
|
||||
|
||||
@@ -249,6 +251,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
|
||||
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
|
||||
|
||||
int audio_bug (const char *funcname, int cond);
|
||||
void *audio_calloc (const char *funcname, int nmemb, size_t size);
|
||||
|
||||
void audio_run(AudioState *s, const char *msg);
|
||||
|
||||
@@ -291,6 +294,9 @@ static inline size_t audio_ring_posb(size_t pos, size_t dist, size_t len)
|
||||
#define ldebug(fmt, ...) (void)0
|
||||
#endif
|
||||
|
||||
#define AUDIO_STRINGIFY_(n) #n
|
||||
#define AUDIO_STRINGIFY(n) AUDIO_STRINGIFY_(n)
|
||||
|
||||
typedef struct AudiodevListEntry {
|
||||
Audiodev *dev;
|
||||
QSIMPLEQ_ENTRY(AudiodevListEntry) next;
|
||||
|
@@ -40,7 +40,7 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
|
||||
struct audio_driver *drv)
|
||||
{
|
||||
int max_voices = glue (drv->max_voices_, TYPE);
|
||||
size_t voice_size = glue(drv->voice_size_, TYPE);
|
||||
int voice_size = glue (drv->voice_size_, TYPE);
|
||||
|
||||
if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
|
||||
if (!max_voices) {
|
||||
@@ -63,17 +63,16 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
|
||||
}
|
||||
|
||||
if (audio_bug(__func__, voice_size && !max_voices)) {
|
||||
dolog("drv=`%s' voice_size=%zu max_voices=0\n",
|
||||
drv->name, voice_size);
|
||||
dolog ("drv=`%s' voice_size=%d max_voices=0\n",
|
||||
drv->name, voice_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
|
||||
{
|
||||
g_free(hw->buf_emul);
|
||||
g_free(HWBUF.buffer);
|
||||
HWBUF.buffer = NULL;
|
||||
HWBUF.size = 0;
|
||||
g_free (HWBUF);
|
||||
HWBUF = NULL;
|
||||
}
|
||||
|
||||
static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
|
||||
@@ -84,67 +83,56 @@ static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
|
||||
dolog("Attempted to allocate empty buffer\n");
|
||||
}
|
||||
|
||||
HWBUF.buffer = g_new0(st_sample, samples);
|
||||
HWBUF.size = samples;
|
||||
HWBUF.pos = 0;
|
||||
HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples);
|
||||
HWBUF->size = samples;
|
||||
} else {
|
||||
HWBUF.buffer = NULL;
|
||||
HWBUF.size = 0;
|
||||
HWBUF = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
|
||||
{
|
||||
g_free(sw->resample_buf.buffer);
|
||||
sw->resample_buf.buffer = NULL;
|
||||
sw->resample_buf.size = 0;
|
||||
g_free (sw->buf);
|
||||
|
||||
if (sw->rate) {
|
||||
st_rate_stop (sw->rate);
|
||||
}
|
||||
|
||||
sw->buf = NULL;
|
||||
sw->rate = NULL;
|
||||
}
|
||||
|
||||
static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
|
||||
{
|
||||
HW *hw = sw->hw;
|
||||
uint64_t samples;
|
||||
int samples;
|
||||
|
||||
if (!glue(audio_get_pdo_, TYPE)(sw->s->dev)->mixing_engine) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
samples = muldiv64(HWBUF.size, sw->info.freq, hw->info.freq);
|
||||
if (samples == 0) {
|
||||
uint64_t f_fe_min;
|
||||
uint64_t f_be = (uint32_t)hw->info.freq;
|
||||
#ifdef DAC
|
||||
samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;
|
||||
#else
|
||||
samples = (int64_t)sw->HWBUF->size * sw->ratio >> 32;
|
||||
#endif
|
||||
|
||||
/* f_fe_min = ceil(1 [frames] * f_be [Hz] / size_be [frames]) */
|
||||
f_fe_min = (f_be + HWBUF.size - 1) / HWBUF.size;
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
AUDIO_CAP ": The guest selected a " NAME " sample rate"
|
||||
" of %d Hz for %s. Only sample rates >= %" PRIu64 " Hz"
|
||||
" are supported.\n",
|
||||
sw->info.freq, sw->name, f_fe_min);
|
||||
sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
|
||||
if (!sw->buf) {
|
||||
dolog ("Could not allocate buffer for `%s' (%d samples)\n",
|
||||
SW_NAME (sw), samples);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate one additional audio frame that is needed for upsampling
|
||||
* if the resample buffer size is small. For large buffer sizes take
|
||||
* care of overflows and truncation.
|
||||
*/
|
||||
samples = samples < SIZE_MAX ? samples + 1 : SIZE_MAX;
|
||||
sw->resample_buf.buffer = g_new0(st_sample, samples);
|
||||
sw->resample_buf.size = samples;
|
||||
sw->resample_buf.pos = 0;
|
||||
|
||||
#ifdef DAC
|
||||
sw->rate = st_rate_start(sw->info.freq, hw->info.freq);
|
||||
sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
|
||||
#else
|
||||
sw->rate = st_rate_start(hw->info.freq, sw->info.freq);
|
||||
sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
|
||||
#endif
|
||||
|
||||
if (!sw->rate) {
|
||||
g_free (sw->buf);
|
||||
sw->buf = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -161,8 +149,11 @@ static int glue (audio_pcm_sw_init_, TYPE) (
|
||||
sw->hw = hw;
|
||||
sw->active = 0;
|
||||
#ifdef DAC
|
||||
sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
|
||||
sw->total_hw_samples_mixed = 0;
|
||||
sw->empty = 1;
|
||||
#else
|
||||
sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
|
||||
#endif
|
||||
|
||||
if (sw->info.is_float) {
|
||||
@@ -273,11 +264,13 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since glue(s->nb_hw_voices_, TYPE) is != 0, glue(drv->voice_size_, TYPE)
|
||||
* is guaranteed to be != 0. See the audio_init_nb_voices_* functions.
|
||||
*/
|
||||
hw = g_malloc0(glue(drv->voice_size_, TYPE));
|
||||
hw = audio_calloc(__func__, 1, glue(drv->voice_size_, TYPE));
|
||||
if (!hw) {
|
||||
dolog ("Can not allocate voice `%s' size %d\n",
|
||||
drv->name, glue (drv->voice_size_, TYPE));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hw->s = s;
|
||||
hw->pcm_ops = drv->pcm_ops;
|
||||
|
||||
@@ -425,28 +418,33 @@ static SW *glue(audio_pcm_create_voice_pair_, TYPE)(
|
||||
hw_as = *as;
|
||||
}
|
||||
|
||||
sw = g_new0(SW, 1);
|
||||
sw = audio_calloc(__func__, 1, sizeof(*sw));
|
||||
if (!sw) {
|
||||
dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
|
||||
sw_name ? sw_name : "unknown", sizeof (*sw));
|
||||
goto err1;
|
||||
}
|
||||
sw->s = s;
|
||||
|
||||
hw = glue(audio_pcm_hw_add_, TYPE)(s, &hw_as);
|
||||
if (!hw) {
|
||||
dolog("Could not create a backend for voice `%s'\n", sw_name);
|
||||
goto err1;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
|
||||
|
||||
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
|
||||
goto err2;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
return sw;
|
||||
|
||||
err2:
|
||||
err3:
|
||||
glue (audio_pcm_hw_del_sw_, TYPE) (sw);
|
||||
glue (audio_pcm_hw_gc_, TYPE) (&hw);
|
||||
err2:
|
||||
g_free (sw);
|
||||
err1:
|
||||
g_free(sw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -517,8 +515,8 @@ SW *glue (AUD_open_, TYPE) (
|
||||
HW *hw = sw->hw;
|
||||
|
||||
if (!hw) {
|
||||
dolog("Internal logic error: voice `%s' has no backend\n",
|
||||
SW_NAME(sw));
|
||||
dolog ("Internal logic error voice `%s' has no hardware store\n",
|
||||
SW_NAME (sw));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -529,6 +527,7 @@ SW *glue (AUD_open_, TYPE) (
|
||||
} else {
|
||||
sw = glue(audio_pcm_create_voice_pair_, TYPE)(s, name, as);
|
||||
if (!sw) {
|
||||
dolog ("Failed to create voice `%s'\n", name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@@ -43,7 +43,6 @@
|
||||
|
||||
typedef struct DBusAudio {
|
||||
GDBusObjectManagerServer *server;
|
||||
bool p2p;
|
||||
GDBusObjectSkeleton *audio;
|
||||
QemuDBusDisplay1Audio *iface;
|
||||
GHashTable *out_listeners;
|
||||
@@ -449,8 +448,7 @@ dbus_audio_register_listener(AudioState *s,
|
||||
bool out)
|
||||
{
|
||||
DBusAudio *da = s->drv_opaque;
|
||||
const char *sender =
|
||||
da->p2p ? "p2p" : g_dbus_method_invocation_get_sender(invocation);
|
||||
const char *sender = g_dbus_method_invocation_get_sender(invocation);
|
||||
g_autoptr(GDBusConnection) listener_conn = NULL;
|
||||
g_autoptr(GError) err = NULL;
|
||||
g_autoptr(GSocket) socket = NULL;
|
||||
@@ -593,7 +591,7 @@ dbus_audio_register_in_listener(AudioState *s,
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p)
|
||||
dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server)
|
||||
{
|
||||
DBusAudio *da = s->drv_opaque;
|
||||
|
||||
@@ -601,7 +599,6 @@ dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p)
|
||||
g_assert(!da->server);
|
||||
|
||||
da->server = g_object_ref(server);
|
||||
da->p2p = p2p;
|
||||
|
||||
da->audio = g_dbus_object_skeleton_new(DBUS_DISPLAY1_AUDIO_PATH);
|
||||
da->iface = qemu_dbus_display1_audio_skeleton_new();
|
||||
|
@@ -414,7 +414,12 @@ struct rate {
|
||||
*/
|
||||
void *st_rate_start (int inrate, int outrate)
|
||||
{
|
||||
struct rate *rate = g_new0(struct rate, 1);
|
||||
struct rate *rate = audio_calloc(__func__, 1, sizeof(*rate));
|
||||
|
||||
if (!rate) {
|
||||
dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rate->opos = 0;
|
||||
|
||||
@@ -440,86 +445,6 @@ void st_rate_stop (void *opaque)
|
||||
g_free (opaque);
|
||||
}
|
||||
|
||||
/**
|
||||
* st_rate_frames_out() - returns the number of frames the resampling code
|
||||
* generates from frames_in frames
|
||||
*
|
||||
* @opaque: pointer to struct rate
|
||||
* @frames_in: number of frames
|
||||
*
|
||||
* When upsampling, there may be more than one correct result. In this case,
|
||||
* the function returns the maximum number of output frames the resampling
|
||||
* code can generate.
|
||||
*/
|
||||
uint32_t st_rate_frames_out(void *opaque, uint32_t frames_in)
|
||||
{
|
||||
struct rate *rate = opaque;
|
||||
uint64_t opos_end, opos_delta;
|
||||
uint32_t ipos_end;
|
||||
uint32_t frames_out;
|
||||
|
||||
if (rate->opos_inc == 1ULL << 32) {
|
||||
return frames_in;
|
||||
}
|
||||
|
||||
/* no output frame without at least one input frame */
|
||||
if (!frames_in) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* last frame read was at rate->ipos - 1 */
|
||||
ipos_end = rate->ipos - 1 + frames_in;
|
||||
opos_end = (uint64_t)ipos_end << 32;
|
||||
|
||||
/* last frame written was at rate->opos - rate->opos_inc */
|
||||
if (opos_end + rate->opos_inc <= rate->opos) {
|
||||
return 0;
|
||||
}
|
||||
opos_delta = opos_end - rate->opos + rate->opos_inc;
|
||||
frames_out = opos_delta / rate->opos_inc;
|
||||
|
||||
return opos_delta % rate->opos_inc ? frames_out : frames_out - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* st_rate_frames_in() - returns the number of frames needed to
|
||||
* get frames_out frames after resampling
|
||||
*
|
||||
* @opaque: pointer to struct rate
|
||||
* @frames_out: number of frames
|
||||
*
|
||||
* When downsampling, there may be more than one correct result. In this
|
||||
* case, the function returns the maximum number of input frames needed.
|
||||
*/
|
||||
uint32_t st_rate_frames_in(void *opaque, uint32_t frames_out)
|
||||
{
|
||||
struct rate *rate = opaque;
|
||||
uint64_t opos_start, opos_end;
|
||||
uint32_t ipos_start, ipos_end;
|
||||
|
||||
if (rate->opos_inc == 1ULL << 32) {
|
||||
return frames_out;
|
||||
}
|
||||
|
||||
if (frames_out) {
|
||||
opos_start = rate->opos;
|
||||
ipos_start = rate->ipos;
|
||||
} else {
|
||||
uint64_t offset;
|
||||
|
||||
/* add offset = ceil(opos_inc) to opos and ipos to avoid an underflow */
|
||||
offset = (rate->opos_inc + (1ULL << 32) - 1) & ~((1ULL << 32) - 1);
|
||||
opos_start = rate->opos + offset;
|
||||
ipos_start = rate->ipos + (offset >> 32);
|
||||
}
|
||||
/* last frame written was at opos_start - rate->opos_inc */
|
||||
opos_end = opos_start - rate->opos_inc + rate->opos_inc * frames_out;
|
||||
ipos_end = (opos_end >> 32) + 1;
|
||||
|
||||
/* last frame read was at ipos_start - 1 */
|
||||
return ipos_end + 1 > ipos_start ? ipos_end + 1 - ipos_start : 0;
|
||||
}
|
||||
|
||||
void mixeng_clear (struct st_sample *buf, int len)
|
||||
{
|
||||
memset (buf, 0, len * sizeof (struct st_sample));
|
||||
|
@@ -52,8 +52,6 @@ void st_rate_flow(void *opaque, st_sample *ibuf, st_sample *obuf,
|
||||
void st_rate_flow_mix(void *opaque, st_sample *ibuf, st_sample *obuf,
|
||||
size_t *isamp, size_t *osamp);
|
||||
void st_rate_stop (void *opaque);
|
||||
uint32_t st_rate_frames_out(void *opaque, uint32_t frames_in);
|
||||
uint32_t st_rate_frames_in(void *opaque, uint32_t frames_out);
|
||||
void mixeng_clear (struct st_sample *buf, int len);
|
||||
void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol);
|
||||
|
||||
|
@@ -40,6 +40,8 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
|
||||
int64_t t;
|
||||
#endif
|
||||
|
||||
ilast = rate->ilast;
|
||||
|
||||
istart = ibuf;
|
||||
iend = ibuf + *isamp;
|
||||
|
||||
@@ -57,17 +59,15 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
|
||||
return;
|
||||
}
|
||||
|
||||
/* without input samples, there's nothing to do */
|
||||
if (ibuf >= iend) {
|
||||
*osamp = 0;
|
||||
return;
|
||||
}
|
||||
while (obuf < oend) {
|
||||
|
||||
ilast = rate->ilast;
|
||||
|
||||
while (true) {
|
||||
/* Safety catch to make sure we have input samples. */
|
||||
if (ibuf >= iend) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* read as many input samples so that ipos > opos */
|
||||
|
||||
while (rate->ipos <= (rate->opos >> 32)) {
|
||||
ilast = *ibuf++;
|
||||
rate->ipos++;
|
||||
@@ -78,11 +78,6 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure that the next output sample can be written */
|
||||
if (obuf >= oend) {
|
||||
break;
|
||||
}
|
||||
|
||||
icur = *ibuf;
|
||||
|
||||
/* wrap ipos and opos around long before they overflow */
|
||||
|
@@ -59,19 +59,6 @@ struct CryptoDevBackendBuiltin {
|
||||
CryptoDevBackendBuiltinSession *sessions[MAX_NUM_SESSIONS];
|
||||
};
|
||||
|
||||
static void cryptodev_builtin_init_akcipher(CryptoDevBackend *backend)
|
||||
{
|
||||
QCryptoAkCipherOptions opts;
|
||||
|
||||
opts.alg = QCRYPTO_AKCIPHER_ALG_RSA;
|
||||
opts.u.rsa.padding_alg = QCRYPTO_RSA_PADDING_ALG_RAW;
|
||||
if (qcrypto_akcipher_supports(&opts)) {
|
||||
backend->conf.crypto_services |=
|
||||
(1u << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER);
|
||||
backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
|
||||
}
|
||||
}
|
||||
|
||||
static void cryptodev_builtin_init(
|
||||
CryptoDevBackend *backend, Error **errp)
|
||||
{
|
||||
@@ -85,18 +72,21 @@ static void cryptodev_builtin_init(
|
||||
return;
|
||||
}
|
||||
|
||||
cc = cryptodev_backend_new_client();
|
||||
cc = cryptodev_backend_new_client(
|
||||
"cryptodev-builtin", NULL);
|
||||
cc->info_str = g_strdup_printf("cryptodev-builtin0");
|
||||
cc->queue_index = 0;
|
||||
cc->type = QCRYPTODEV_BACKEND_TYPE_BUILTIN;
|
||||
cc->type = CRYPTODEV_BACKEND_TYPE_BUILTIN;
|
||||
backend->conf.peers.ccs[0] = cc;
|
||||
|
||||
backend->conf.crypto_services =
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_CIPHER |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_HASH |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_MAC;
|
||||
1u << VIRTIO_CRYPTO_SERVICE_CIPHER |
|
||||
1u << VIRTIO_CRYPTO_SERVICE_HASH |
|
||||
1u << VIRTIO_CRYPTO_SERVICE_MAC |
|
||||
1u << VIRTIO_CRYPTO_SERVICE_AKCIPHER;
|
||||
backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
|
||||
backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
|
||||
backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
|
||||
/*
|
||||
* Set the Maximum length of crypto request.
|
||||
* Why this value? Just avoid to overflow when
|
||||
@@ -105,7 +95,6 @@ static void cryptodev_builtin_init(
|
||||
backend->conf.max_size = LONG_MAX - sizeof(CryptoDevBackendOpInfo);
|
||||
backend->conf.max_cipher_key_len = CRYPTODEV_BUITLIN_MAX_CIPHER_KEY_LEN;
|
||||
backend->conf.max_auth_key_len = CRYPTODEV_BUITLIN_MAX_AUTH_KEY_LEN;
|
||||
cryptodev_builtin_init_akcipher(backend);
|
||||
|
||||
cryptodev_backend_set_ready(backend, true);
|
||||
}
|
||||
@@ -539,14 +528,17 @@ static int cryptodev_builtin_asym_operation(
|
||||
|
||||
static int cryptodev_builtin_operation(
|
||||
CryptoDevBackend *backend,
|
||||
CryptoDevBackendOpInfo *op_info)
|
||||
CryptoDevBackendOpInfo *op_info,
|
||||
uint32_t queue_index,
|
||||
CryptoDevCompletionFunc cb,
|
||||
void *opaque)
|
||||
{
|
||||
CryptoDevBackendBuiltin *builtin =
|
||||
CRYPTODEV_BACKEND_BUILTIN(backend);
|
||||
CryptoDevBackendBuiltinSession *sess;
|
||||
CryptoDevBackendSymOpInfo *sym_op_info;
|
||||
CryptoDevBackendAsymOpInfo *asym_op_info;
|
||||
QCryptodevBackendAlgType algtype = op_info->algtype;
|
||||
enum CryptoDevBackendAlgType algtype = op_info->algtype;
|
||||
int status = -VIRTIO_CRYPTO_ERR;
|
||||
Error *local_error = NULL;
|
||||
|
||||
@@ -558,11 +550,11 @@ static int cryptodev_builtin_operation(
|
||||
}
|
||||
|
||||
sess = builtin->sessions[op_info->session_id];
|
||||
if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) {
|
||||
if (algtype == CRYPTODEV_BACKEND_ALG_SYM) {
|
||||
sym_op_info = op_info->u.sym_op_info;
|
||||
status = cryptodev_builtin_sym_operation(sess, sym_op_info,
|
||||
&local_error);
|
||||
} else if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) {
|
||||
} else if (algtype == CRYPTODEV_BACKEND_ALG_ASYM) {
|
||||
asym_op_info = op_info->u.asym_op_info;
|
||||
status = cryptodev_builtin_asym_operation(sess, op_info->op_code,
|
||||
asym_op_info, &local_error);
|
||||
@@ -571,8 +563,8 @@ static int cryptodev_builtin_operation(
|
||||
if (local_error) {
|
||||
error_report_err(local_error);
|
||||
}
|
||||
if (op_info->cb) {
|
||||
op_info->cb(op_info->opaque, status);
|
||||
if (cb) {
|
||||
cb(opaque, status);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* HMP commands related to cryptodev
|
||||
*
|
||||
* Copyright (c) 2023 Bytedance.Inc
|
||||
*
|
||||
* Authors:
|
||||
* zhenwei pi<pizhenwei@bytedance.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "monitor/hmp.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qapi/qapi-commands-cryptodev.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
|
||||
|
||||
void hmp_info_cryptodev(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
QCryptodevInfoList *il;
|
||||
QCryptodevBackendServiceTypeList *sl;
|
||||
QCryptodevBackendClientList *cl;
|
||||
|
||||
for (il = qmp_query_cryptodev(NULL); il; il = il->next) {
|
||||
g_autofree char *services = NULL;
|
||||
QCryptodevInfo *info = il->value;
|
||||
char *tmp_services;
|
||||
|
||||
/* build a string like 'service=[akcipher|mac|hash|cipher]' */
|
||||
for (sl = info->service; sl; sl = sl->next) {
|
||||
const char *service = QCryptodevBackendServiceType_str(sl->value);
|
||||
|
||||
if (!services) {
|
||||
services = g_strdup(service);
|
||||
} else {
|
||||
tmp_services = g_strjoin("|", services, service, NULL);
|
||||
g_free(services);
|
||||
services = tmp_services;
|
||||
}
|
||||
}
|
||||
monitor_printf(mon, "%s: service=[%s]\n", info->id, services);
|
||||
|
||||
for (cl = info->client; cl; cl = cl->next) {
|
||||
QCryptodevBackendClient *client = cl->value;
|
||||
monitor_printf(mon, " queue %" PRIu32 ": type=%s\n",
|
||||
client->queue,
|
||||
QCryptodevBackendType_str(client->type));
|
||||
}
|
||||
}
|
||||
|
||||
qapi_free_QCryptodevInfoList(il);
|
||||
}
|
@@ -223,14 +223,14 @@ static void cryptodev_lkcf_init(CryptoDevBackend *backend, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
cc = cryptodev_backend_new_client();
|
||||
cc = cryptodev_backend_new_client("cryptodev-lkcf", NULL);
|
||||
cc->info_str = g_strdup_printf("cryptodev-lkcf0");
|
||||
cc->queue_index = 0;
|
||||
cc->type = QCRYPTODEV_BACKEND_TYPE_LKCF;
|
||||
cc->type = CRYPTODEV_BACKEND_TYPE_LKCF;
|
||||
backend->conf.peers.ccs[0] = cc;
|
||||
|
||||
backend->conf.crypto_services =
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER;
|
||||
1u << VIRTIO_CRYPTO_SERVICE_AKCIPHER;
|
||||
backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
|
||||
lkcf->running = true;
|
||||
|
||||
@@ -469,12 +469,15 @@ static void *cryptodev_lkcf_worker(void *arg)
|
||||
|
||||
static int cryptodev_lkcf_operation(
|
||||
CryptoDevBackend *backend,
|
||||
CryptoDevBackendOpInfo *op_info)
|
||||
CryptoDevBackendOpInfo *op_info,
|
||||
uint32_t queue_index,
|
||||
CryptoDevCompletionFunc cb,
|
||||
void *opaque)
|
||||
{
|
||||
CryptoDevBackendLKCF *lkcf =
|
||||
CRYPTODEV_BACKEND_LKCF(backend);
|
||||
CryptoDevBackendLKCFSession *sess;
|
||||
QCryptodevBackendAlgType algtype = op_info->algtype;
|
||||
enum CryptoDevBackendAlgType algtype = op_info->algtype;
|
||||
CryptoDevLKCFTask *task;
|
||||
|
||||
if (op_info->session_id >= MAX_SESSIONS ||
|
||||
@@ -485,15 +488,15 @@ static int cryptodev_lkcf_operation(
|
||||
}
|
||||
|
||||
sess = lkcf->sess[op_info->session_id];
|
||||
if (algtype != QCRYPTODEV_BACKEND_ALG_ASYM) {
|
||||
if (algtype != CRYPTODEV_BACKEND_ALG_ASYM) {
|
||||
error_report("algtype not supported: %u", algtype);
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
|
||||
task = g_new0(CryptoDevLKCFTask, 1);
|
||||
task->op_info = op_info;
|
||||
task->cb = op_info->cb;
|
||||
task->opaque = op_info->opaque;
|
||||
task->cb = cb;
|
||||
task->opaque = opaque;
|
||||
task->sess = sess;
|
||||
task->lkcf = lkcf;
|
||||
task->status = -VIRTIO_CRYPTO_ERR;
|
||||
|
@@ -67,7 +67,7 @@ cryptodev_vhost_user_get_vhost(
|
||||
{
|
||||
CryptoDevBackendVhostUser *s =
|
||||
CRYPTODEV_BACKEND_VHOST_USER(b);
|
||||
assert(cc->type == QCRYPTODEV_BACKEND_TYPE_VHOST_USER);
|
||||
assert(cc->type == CRYPTODEV_BACKEND_TYPE_VHOST_USER);
|
||||
assert(queue < MAX_CRYPTO_QUEUE_NUM);
|
||||
|
||||
return s->vhost_crypto[queue];
|
||||
@@ -198,11 +198,12 @@ static void cryptodev_vhost_user_init(
|
||||
s->opened = true;
|
||||
|
||||
for (i = 0; i < queues; i++) {
|
||||
cc = cryptodev_backend_new_client();
|
||||
cc = cryptodev_backend_new_client(
|
||||
"cryptodev-vhost-user", NULL);
|
||||
cc->info_str = g_strdup_printf("cryptodev-vhost-user%zu to %s ",
|
||||
i, chr->label);
|
||||
cc->queue_index = i;
|
||||
cc->type = QCRYPTODEV_BACKEND_TYPE_VHOST_USER;
|
||||
cc->type = CRYPTODEV_BACKEND_TYPE_VHOST_USER;
|
||||
|
||||
backend->conf.peers.ccs[i] = cc;
|
||||
|
||||
@@ -221,9 +222,9 @@ static void cryptodev_vhost_user_init(
|
||||
cryptodev_vhost_user_event, NULL, s, NULL, true);
|
||||
|
||||
backend->conf.crypto_services =
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_CIPHER |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_HASH |
|
||||
1u << QCRYPTODEV_BACKEND_SERVICE_MAC;
|
||||
1u << VIRTIO_CRYPTO_SERVICE_CIPHER |
|
||||
1u << VIRTIO_CRYPTO_SERVICE_HASH |
|
||||
1u << VIRTIO_CRYPTO_SERVICE_MAC;
|
||||
backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
|
||||
backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
|
||||
|
||||
|
@@ -127,7 +127,7 @@ cryptodev_get_vhost(CryptoDevBackendClient *cc,
|
||||
|
||||
switch (cc->type) {
|
||||
#if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX)
|
||||
case QCRYPTODEV_BACKEND_TYPE_VHOST_USER:
|
||||
case CRYPTODEV_BACKEND_TYPE_VHOST_USER:
|
||||
vhost_crypto = cryptodev_vhost_user_get_vhost(cc, b, queue);
|
||||
break;
|
||||
#endif
|
||||
@@ -195,7 +195,7 @@ int cryptodev_vhost_start(VirtIODevice *dev, int total_queues)
|
||||
* because vhost user doesn't interrupt masking/unmasking
|
||||
* properly.
|
||||
*/
|
||||
if (cc->type == QCRYPTODEV_BACKEND_TYPE_VHOST_USER) {
|
||||
if (cc->type == CRYPTODEV_BACKEND_TYPE_VHOST_USER) {
|
||||
dev->use_guest_notifier_mask = false;
|
||||
}
|
||||
}
|
||||
|
@@ -23,92 +23,29 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/cryptodev.h"
|
||||
#include "sysemu/stats.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-cryptodev.h"
|
||||
#include "qapi/qapi-types-stats.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "hw/virtio/virtio-crypto.h"
|
||||
|
||||
#define SYM_ENCRYPT_OPS_STR "sym-encrypt-ops"
|
||||
#define SYM_DECRYPT_OPS_STR "sym-decrypt-ops"
|
||||
#define SYM_ENCRYPT_BYTES_STR "sym-encrypt-bytes"
|
||||
#define SYM_DECRYPT_BYTES_STR "sym-decrypt-bytes"
|
||||
|
||||
#define ASYM_ENCRYPT_OPS_STR "asym-encrypt-ops"
|
||||
#define ASYM_DECRYPT_OPS_STR "asym-decrypt-ops"
|
||||
#define ASYM_SIGN_OPS_STR "asym-sign-ops"
|
||||
#define ASYM_VERIFY_OPS_STR "asym-verify-ops"
|
||||
#define ASYM_ENCRYPT_BYTES_STR "asym-encrypt-bytes"
|
||||
#define ASYM_DECRYPT_BYTES_STR "asym-decrypt-bytes"
|
||||
#define ASYM_SIGN_BYTES_STR "asym-sign-bytes"
|
||||
#define ASYM_VERIFY_BYTES_STR "asym-verify-bytes"
|
||||
|
||||
typedef struct StatsArgs {
|
||||
union StatsResultsType {
|
||||
StatsResultList **stats;
|
||||
StatsSchemaList **schema;
|
||||
} result;
|
||||
strList *names;
|
||||
Error **errp;
|
||||
} StatsArgs;
|
||||
|
||||
static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients;
|
||||
|
||||
static int qmp_query_cryptodev_foreach(Object *obj, void *data)
|
||||
{
|
||||
CryptoDevBackend *backend;
|
||||
QCryptodevInfoList **infolist = data;
|
||||
uint32_t services, i;
|
||||
|
||||
if (!object_dynamic_cast(obj, TYPE_CRYPTODEV_BACKEND)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
QCryptodevInfo *info = g_new0(QCryptodevInfo, 1);
|
||||
info->id = g_strdup(object_get_canonical_path_component(obj));
|
||||
|
||||
backend = CRYPTODEV_BACKEND(obj);
|
||||
services = backend->conf.crypto_services;
|
||||
for (i = 0; i < QCRYPTODEV_BACKEND_SERVICE__MAX; i++) {
|
||||
if (services & (1 << i)) {
|
||||
QAPI_LIST_PREPEND(info->service, i);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < backend->conf.peers.queues; i++) {
|
||||
CryptoDevBackendClient *cc = backend->conf.peers.ccs[i];
|
||||
QCryptodevBackendClient *client = g_new0(QCryptodevBackendClient, 1);
|
||||
|
||||
client->queue = cc->queue_index;
|
||||
client->type = cc->type;
|
||||
QAPI_LIST_PREPEND(info->client, client);
|
||||
}
|
||||
|
||||
QAPI_LIST_PREPEND(*infolist, info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QCryptodevInfoList *qmp_query_cryptodev(Error **errp)
|
||||
{
|
||||
QCryptodevInfoList *list = NULL;
|
||||
Object *objs = container_get(object_get_root(), "/objects");
|
||||
|
||||
object_child_foreach(objs, qmp_query_cryptodev_foreach, &list);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
CryptoDevBackendClient *cryptodev_backend_new_client(void)
|
||||
CryptoDevBackendClient *
|
||||
cryptodev_backend_new_client(const char *model,
|
||||
const char *name)
|
||||
{
|
||||
CryptoDevBackendClient *cc;
|
||||
|
||||
cc = g_new0(CryptoDevBackendClient, 1);
|
||||
cc->model = g_strdup(model);
|
||||
if (name) {
|
||||
cc->name = g_strdup(name);
|
||||
}
|
||||
|
||||
QTAILQ_INSERT_TAIL(&crypto_clients, cc, next);
|
||||
|
||||
return cc;
|
||||
@@ -118,6 +55,8 @@ void cryptodev_backend_free_client(
|
||||
CryptoDevBackendClient *cc)
|
||||
{
|
||||
QTAILQ_REMOVE(&crypto_clients, cc, next);
|
||||
g_free(cc->name);
|
||||
g_free(cc->model);
|
||||
g_free(cc->info_str);
|
||||
g_free(cc);
|
||||
}
|
||||
@@ -132,9 +71,6 @@ void cryptodev_backend_cleanup(
|
||||
if (bc->cleanup) {
|
||||
bc->cleanup(backend, errp);
|
||||
}
|
||||
|
||||
g_free(backend->sym_stat);
|
||||
g_free(backend->asym_stat);
|
||||
}
|
||||
|
||||
int cryptodev_backend_create_session(
|
||||
@@ -171,111 +107,38 @@ int cryptodev_backend_close_session(
|
||||
|
||||
static int cryptodev_backend_operation(
|
||||
CryptoDevBackend *backend,
|
||||
CryptoDevBackendOpInfo *op_info)
|
||||
CryptoDevBackendOpInfo *op_info,
|
||||
uint32_t queue_index,
|
||||
CryptoDevCompletionFunc cb,
|
||||
void *opaque)
|
||||
{
|
||||
CryptoDevBackendClass *bc =
|
||||
CRYPTODEV_BACKEND_GET_CLASS(backend);
|
||||
|
||||
if (bc->do_op) {
|
||||
return bc->do_op(backend, op_info);
|
||||
return bc->do_op(backend, op_info, queue_index, cb, opaque);
|
||||
}
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
|
||||
static int cryptodev_backend_account(CryptoDevBackend *backend,
|
||||
CryptoDevBackendOpInfo *op_info)
|
||||
int cryptodev_backend_crypto_operation(
|
||||
CryptoDevBackend *backend,
|
||||
void *opaque1,
|
||||
uint32_t queue_index,
|
||||
CryptoDevCompletionFunc cb, void *opaque2)
|
||||
{
|
||||
enum QCryptodevBackendAlgType algtype = op_info->algtype;
|
||||
int len;
|
||||
VirtIOCryptoReq *req = opaque1;
|
||||
CryptoDevBackendOpInfo *op_info = &req->op_info;
|
||||
enum CryptoDevBackendAlgType algtype = req->flags;
|
||||
|
||||
if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) {
|
||||
CryptoDevBackendAsymOpInfo *asym_op_info = op_info->u.asym_op_info;
|
||||
len = asym_op_info->src_len;
|
||||
switch (op_info->op_code) {
|
||||
case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT:
|
||||
CryptodevAsymStatIncEncrypt(backend, len);
|
||||
break;
|
||||
case VIRTIO_CRYPTO_AKCIPHER_DECRYPT:
|
||||
CryptodevAsymStatIncDecrypt(backend, len);
|
||||
break;
|
||||
case VIRTIO_CRYPTO_AKCIPHER_SIGN:
|
||||
CryptodevAsymStatIncSign(backend, len);
|
||||
break;
|
||||
case VIRTIO_CRYPTO_AKCIPHER_VERIFY:
|
||||
CryptodevAsymStatIncVerify(backend, len);
|
||||
break;
|
||||
default:
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
} else if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) {
|
||||
CryptoDevBackendSymOpInfo *sym_op_info = op_info->u.sym_op_info;
|
||||
len = sym_op_info->src_len;
|
||||
switch (op_info->op_code) {
|
||||
case VIRTIO_CRYPTO_CIPHER_ENCRYPT:
|
||||
CryptodevSymStatIncEncrypt(backend, len);
|
||||
break;
|
||||
case VIRTIO_CRYPTO_CIPHER_DECRYPT:
|
||||
CryptodevSymStatIncDecrypt(backend, len);
|
||||
break;
|
||||
default:
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
} else {
|
||||
if ((algtype != CRYPTODEV_BACKEND_ALG_SYM)
|
||||
&& (algtype != CRYPTODEV_BACKEND_ALG_ASYM)) {
|
||||
error_report("Unsupported cryptodev alg type: %" PRIu32 "", algtype);
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void cryptodev_backend_throttle_timer_cb(void *opaque)
|
||||
{
|
||||
CryptoDevBackend *backend = (CryptoDevBackend *)opaque;
|
||||
CryptoDevBackendOpInfo *op_info, *tmpop;
|
||||
int ret;
|
||||
|
||||
QTAILQ_FOREACH_SAFE(op_info, &backend->opinfos, next, tmpop) {
|
||||
QTAILQ_REMOVE(&backend->opinfos, op_info, next);
|
||||
ret = cryptodev_backend_account(backend, op_info);
|
||||
if (ret < 0) {
|
||||
op_info->cb(op_info->opaque, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
throttle_account(&backend->ts, true, ret);
|
||||
cryptodev_backend_operation(backend, op_info);
|
||||
if (throttle_enabled(&backend->tc) &&
|
||||
throttle_schedule_timer(&backend->ts, &backend->tt, true)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cryptodev_backend_crypto_operation(
|
||||
CryptoDevBackend *backend,
|
||||
CryptoDevBackendOpInfo *op_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!throttle_enabled(&backend->tc)) {
|
||||
goto do_account;
|
||||
}
|
||||
|
||||
if (throttle_schedule_timer(&backend->ts, &backend->tt, true) ||
|
||||
!QTAILQ_EMPTY(&backend->opinfos)) {
|
||||
QTAILQ_INSERT_TAIL(&backend->opinfos, op_info, next);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do_account:
|
||||
ret = cryptodev_backend_account(backend, op_info);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
throttle_account(&backend->ts, true, ret);
|
||||
|
||||
return cryptodev_backend_operation(backend, op_info);
|
||||
return cryptodev_backend_operation(backend, op_info, queue_index,
|
||||
cb, opaque2);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -306,111 +169,15 @@ cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
|
||||
backend->conf.peers.queues = value;
|
||||
}
|
||||
|
||||
static void cryptodev_backend_set_throttle(CryptoDevBackend *backend, int field,
|
||||
uint64_t value, Error **errp)
|
||||
{
|
||||
uint64_t orig = backend->tc.buckets[field].avg;
|
||||
bool enabled = throttle_enabled(&backend->tc);
|
||||
|
||||
if (orig == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
backend->tc.buckets[field].avg = value;
|
||||
if (!throttle_enabled(&backend->tc)) {
|
||||
throttle_timers_destroy(&backend->tt);
|
||||
cryptodev_backend_throttle_timer_cb(backend); /* drain opinfos */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!throttle_is_valid(&backend->tc, errp)) {
|
||||
backend->tc.buckets[field].avg = orig; /* revert change */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
throttle_init(&backend->ts);
|
||||
throttle_timers_init(&backend->tt, qemu_get_aio_context(),
|
||||
QEMU_CLOCK_REALTIME,
|
||||
cryptodev_backend_throttle_timer_cb, /* FIXME */
|
||||
cryptodev_backend_throttle_timer_cb, backend);
|
||||
}
|
||||
|
||||
throttle_config(&backend->ts, QEMU_CLOCK_REALTIME, &backend->tc);
|
||||
}
|
||||
|
||||
static void cryptodev_backend_get_bps(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||
uint64_t value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
|
||||
|
||||
visit_type_uint64(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void cryptodev_backend_set_bps(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||
uint64_t value;
|
||||
|
||||
if (!visit_type_uint64(v, name, &value, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
|
||||
}
|
||||
|
||||
static void cryptodev_backend_get_ops(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||
uint64_t value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
|
||||
|
||||
visit_type_uint64(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static void cryptodev_backend_set_ops(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||
uint64_t value;
|
||||
|
||||
if (!visit_type_uint64(v, name, &value, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
|
||||
}
|
||||
|
||||
static void
|
||||
cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
|
||||
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
|
||||
uint32_t services;
|
||||
uint64_t value;
|
||||
|
||||
QTAILQ_INIT(&backend->opinfos);
|
||||
value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
|
||||
cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
|
||||
value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
|
||||
cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
|
||||
|
||||
if (bc->init) {
|
||||
bc->init(backend, errp);
|
||||
}
|
||||
|
||||
services = backend->conf.crypto_services;
|
||||
if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_CIPHER)) {
|
||||
backend->sym_stat = g_new0(CryptodevBackendSymStat, 1);
|
||||
}
|
||||
|
||||
if (services & (1 << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER)) {
|
||||
backend->asym_stat = g_new0(CryptodevBackendAsymStat, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used)
|
||||
@@ -441,12 +208,8 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc)
|
||||
|
||||
static void cryptodev_backend_instance_init(Object *obj)
|
||||
{
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||
|
||||
/* Initialize devices' queues property to 1 */
|
||||
object_property_set_int(obj, "queues", 1, NULL);
|
||||
|
||||
throttle_config_init(&backend->tc);
|
||||
}
|
||||
|
||||
static void cryptodev_backend_finalize(Object *obj)
|
||||
@@ -454,137 +217,6 @@ static void cryptodev_backend_finalize(Object *obj)
|
||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||
|
||||
cryptodev_backend_cleanup(backend, NULL);
|
||||
if (throttle_enabled(&backend->tc)) {
|
||||
throttle_timers_destroy(&backend->tt);
|
||||
}
|
||||
}
|
||||
|
||||
static StatsList *cryptodev_backend_stats_add(const char *name, int64_t *val,
|
||||
StatsList *stats_list)
|
||||
{
|
||||
Stats *stats = g_new0(Stats, 1);
|
||||
|
||||
stats->name = g_strdup(name);
|
||||
stats->value = g_new0(StatsValue, 1);
|
||||
stats->value->type = QTYPE_QNUM;
|
||||
stats->value->u.scalar = *val;
|
||||
|
||||
QAPI_LIST_PREPEND(stats_list, stats);
|
||||
return stats_list;
|
||||
}
|
||||
|
||||
static int cryptodev_backend_stats_query(Object *obj, void *data)
|
||||
{
|
||||
StatsArgs *stats_args = data;
|
||||
StatsResultList **stats_results = stats_args->result.stats;
|
||||
StatsList *stats_list = NULL;
|
||||
StatsResult *entry;
|
||||
CryptoDevBackend *backend;
|
||||
CryptodevBackendSymStat *sym_stat;
|
||||
CryptodevBackendAsymStat *asym_stat;
|
||||
|
||||
if (!object_dynamic_cast(obj, TYPE_CRYPTODEV_BACKEND)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
backend = CRYPTODEV_BACKEND(obj);
|
||||
sym_stat = backend->sym_stat;
|
||||
if (sym_stat) {
|
||||
stats_list = cryptodev_backend_stats_add(SYM_ENCRYPT_OPS_STR,
|
||||
&sym_stat->encrypt_ops, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(SYM_DECRYPT_OPS_STR,
|
||||
&sym_stat->decrypt_ops, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(SYM_ENCRYPT_BYTES_STR,
|
||||
&sym_stat->encrypt_bytes, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(SYM_DECRYPT_BYTES_STR,
|
||||
&sym_stat->decrypt_bytes, stats_list);
|
||||
}
|
||||
|
||||
asym_stat = backend->asym_stat;
|
||||
if (asym_stat) {
|
||||
stats_list = cryptodev_backend_stats_add(ASYM_ENCRYPT_OPS_STR,
|
||||
&asym_stat->encrypt_ops, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(ASYM_DECRYPT_OPS_STR,
|
||||
&asym_stat->decrypt_ops, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(ASYM_SIGN_OPS_STR,
|
||||
&asym_stat->sign_ops, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(ASYM_VERIFY_OPS_STR,
|
||||
&asym_stat->verify_ops, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(ASYM_ENCRYPT_BYTES_STR,
|
||||
&asym_stat->encrypt_bytes, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(ASYM_DECRYPT_BYTES_STR,
|
||||
&asym_stat->decrypt_bytes, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(ASYM_SIGN_BYTES_STR,
|
||||
&asym_stat->sign_bytes, stats_list);
|
||||
stats_list = cryptodev_backend_stats_add(ASYM_VERIFY_BYTES_STR,
|
||||
&asym_stat->verify_bytes, stats_list);
|
||||
}
|
||||
|
||||
entry = g_new0(StatsResult, 1);
|
||||
entry->provider = STATS_PROVIDER_CRYPTODEV;
|
||||
entry->qom_path = g_strdup(object_get_canonical_path(obj));
|
||||
entry->stats = stats_list;
|
||||
QAPI_LIST_PREPEND(*stats_results, entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cryptodev_backend_stats_cb(StatsResultList **result,
|
||||
StatsTarget target,
|
||||
strList *names, strList *targets,
|
||||
Error **errp)
|
||||
{
|
||||
switch (target) {
|
||||
case STATS_TARGET_CRYPTODEV:
|
||||
{
|
||||
Object *objs = container_get(object_get_root(), "/objects");
|
||||
StatsArgs stats_args;
|
||||
stats_args.result.stats = result;
|
||||
stats_args.names = names;
|
||||
stats_args.errp = errp;
|
||||
|
||||
object_child_foreach(objs, cryptodev_backend_stats_query, &stats_args);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static StatsSchemaValueList *cryptodev_backend_schemas_add(const char *name,
|
||||
StatsSchemaValueList *list)
|
||||
{
|
||||
StatsSchemaValueList *schema_entry = g_new0(StatsSchemaValueList, 1);
|
||||
|
||||
schema_entry->value = g_new0(StatsSchemaValue, 1);
|
||||
schema_entry->value->type = STATS_TYPE_CUMULATIVE;
|
||||
schema_entry->value->name = g_strdup(name);
|
||||
schema_entry->next = list;
|
||||
|
||||
return schema_entry;
|
||||
}
|
||||
|
||||
static void cryptodev_backend_schemas_cb(StatsSchemaList **result,
|
||||
Error **errp)
|
||||
{
|
||||
StatsSchemaValueList *stats_list = NULL;
|
||||
const char *sym_stats[] = { SYM_ENCRYPT_OPS_STR, SYM_DECRYPT_OPS_STR,
|
||||
SYM_ENCRYPT_BYTES_STR, SYM_DECRYPT_BYTES_STR };
|
||||
const char *asym_stats[] = { ASYM_ENCRYPT_OPS_STR, ASYM_DECRYPT_OPS_STR,
|
||||
ASYM_SIGN_OPS_STR, ASYM_VERIFY_OPS_STR,
|
||||
ASYM_ENCRYPT_BYTES_STR, ASYM_DECRYPT_BYTES_STR,
|
||||
ASYM_SIGN_BYTES_STR, ASYM_VERIFY_BYTES_STR };
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(sym_stats); i++) {
|
||||
stats_list = cryptodev_backend_schemas_add(sym_stats[i], stats_list);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(asym_stats); i++) {
|
||||
stats_list = cryptodev_backend_schemas_add(asym_stats[i], stats_list);
|
||||
}
|
||||
|
||||
add_stats_schema(result, STATS_PROVIDER_CRYPTODEV, STATS_TARGET_CRYPTODEV,
|
||||
stats_list);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -600,17 +232,6 @@ cryptodev_backend_class_init(ObjectClass *oc, void *data)
|
||||
cryptodev_backend_get_queues,
|
||||
cryptodev_backend_set_queues,
|
||||
NULL, NULL);
|
||||
object_class_property_add(oc, "throttle-bps", "uint64",
|
||||
cryptodev_backend_get_bps,
|
||||
cryptodev_backend_set_bps,
|
||||
NULL, NULL);
|
||||
object_class_property_add(oc, "throttle-ops", "uint64",
|
||||
cryptodev_backend_get_ops,
|
||||
cryptodev_backend_set_ops,
|
||||
NULL, NULL);
|
||||
|
||||
add_stats_callbacks(STATS_PROVIDER_CRYPTODEV, cryptodev_backend_stats_cb,
|
||||
cryptodev_backend_schemas_cb);
|
||||
}
|
||||
|
||||
static const TypeInfo cryptodev_backend_info = {
|
||||
|
@@ -1,6 +1,5 @@
|
||||
softmmu_ss.add([files(
|
||||
'cryptodev-builtin.c',
|
||||
'cryptodev-hmp-cmds.c',
|
||||
'cryptodev.c',
|
||||
'hostmem-ram.c',
|
||||
'hostmem.c',
|
||||
|
@@ -573,13 +573,13 @@ static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
close(fds[1]);
|
||||
closesocket(fds[1]);
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
closesocket(fds[0]);
|
||||
closesocket(fds[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
36
block.c
36
block.c
@@ -680,7 +680,7 @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv,
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
blk_co_unref(blk);
|
||||
blk_unref(blk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -4918,7 +4918,6 @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
|
||||
qdict_del(bs->options, "backing");
|
||||
|
||||
bdrv_refresh_limits(bs, NULL, NULL);
|
||||
bdrv_refresh_total_sectors(bs, bs->total_sectors);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5850,7 +5849,7 @@ int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
||||
if (bs->bl.has_variable_length) {
|
||||
if (drv->has_variable_length) {
|
||||
int ret = bdrv_co_refresh_total_sectors(bs, bs->total_sectors);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -5859,28 +5858,6 @@ int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
|
||||
return bs->total_sectors;
|
||||
}
|
||||
|
||||
/*
|
||||
* This wrapper is written by hand because this function is in the hot I/O path,
|
||||
* via blk_get_geometry.
|
||||
*/
|
||||
int64_t coroutine_mixed_fn bdrv_nb_sectors(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
IO_CODE();
|
||||
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
||||
if (bs->bl.has_variable_length) {
|
||||
int ret = bdrv_refresh_total_sectors(bs, bs->total_sectors);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return bs->total_sectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return length in bytes on success, -errno on error.
|
||||
* The length is always a multiple of BDRV_SECTOR_SIZE.
|
||||
@@ -5901,6 +5878,15 @@ int64_t coroutine_fn bdrv_co_getlength(BlockDriverState *bs)
|
||||
return ret * BDRV_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
/* return 0 as number of sectors if no device present or error */
|
||||
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
|
||||
{
|
||||
int64_t nb_sectors = bdrv_nb_sectors(bs);
|
||||
IO_CODE();
|
||||
|
||||
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
|
||||
}
|
||||
|
||||
bool bdrv_is_sg(BlockDriverState *bs)
|
||||
{
|
||||
IO_CODE();
|
||||
|
@@ -1615,53 +1615,26 @@ int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
|
||||
return bdrv_co_getlength(blk_bs(blk));
|
||||
}
|
||||
|
||||
void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
|
||||
{
|
||||
IO_CODE();
|
||||
if (!blk_bs(blk)) {
|
||||
*nb_sectors_ptr = 0;
|
||||
} else {
|
||||
bdrv_get_geometry(blk_bs(blk), nb_sectors_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
|
||||
IO_CODE();
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
if (!bs) {
|
||||
if (!blk_co_is_available(blk)) {
|
||||
return -ENOMEDIUM;
|
||||
} else {
|
||||
return bdrv_co_nb_sectors(bs);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This wrapper is written by hand because this function is in the hot I/O path,
|
||||
* via blk_get_geometry.
|
||||
*/
|
||||
int64_t coroutine_mixed_fn blk_nb_sectors(BlockBackend *blk)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
|
||||
IO_CODE();
|
||||
|
||||
if (!bs) {
|
||||
return -ENOMEDIUM;
|
||||
} else {
|
||||
return bdrv_nb_sectors(bs);
|
||||
}
|
||||
}
|
||||
|
||||
/* return 0 as number of sectors if no device present or error */
|
||||
void coroutine_fn blk_co_get_geometry(BlockBackend *blk,
|
||||
uint64_t *nb_sectors_ptr)
|
||||
{
|
||||
int64_t ret = blk_co_nb_sectors(blk);
|
||||
*nb_sectors_ptr = ret < 0 ? 0 : ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This wrapper is written by hand because this function is in the hot I/O path.
|
||||
*/
|
||||
void coroutine_mixed_fn blk_get_geometry(BlockBackend *blk,
|
||||
uint64_t *nb_sectors_ptr)
|
||||
{
|
||||
int64_t ret = blk_nb_sectors(blk);
|
||||
*nb_sectors_ptr = ret < 0 ? 0 : ret;
|
||||
return bdrv_co_nb_sectors(blk_bs(blk));
|
||||
}
|
||||
|
||||
BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
|
||||
@@ -2018,15 +1991,7 @@ void blk_activate(BlockBackend *blk, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Migration code can call this function in coroutine context, so leave
|
||||
* coroutine context if necessary.
|
||||
*/
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_activate(bs, errp);
|
||||
} else {
|
||||
bdrv_activate(bs, errp);
|
||||
}
|
||||
bdrv_activate(bs, errp);
|
||||
}
|
||||
|
||||
bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
|
||||
|
@@ -259,6 +259,7 @@ static BlockDriver bdrv_copy_on_read = {
|
||||
.bdrv_co_eject = cor_co_eject,
|
||||
.bdrv_co_lock_medium = cor_co_lock_medium,
|
||||
|
||||
.has_variable_length = true,
|
||||
.is_filter = true,
|
||||
};
|
||||
|
||||
|
@@ -355,7 +355,7 @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
|
||||
ret = 0;
|
||||
cleanup:
|
||||
qcrypto_block_free(crypto);
|
||||
blk_co_unref(blk);
|
||||
blk_unref(blk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -661,7 +661,7 @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_unref(bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -730,7 +730,7 @@ fail:
|
||||
bdrv_co_delete_file_noerr(bs);
|
||||
}
|
||||
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_unref(bs);
|
||||
qapi_free_QCryptoBlockCreateOptions(create_opts);
|
||||
qobject_unref(cryptoopts);
|
||||
return ret;
|
||||
|
@@ -23,12 +23,7 @@
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "dmg.h"
|
||||
|
||||
/* Work around a -Wstrict-prototypes warning in LZFSE headers */
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
|
||||
#include <lzfse.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
static int dmg_uncompress_lzfse_do(char *next_in, unsigned int avail_in,
|
||||
char *next_out, unsigned int avail_out)
|
||||
|
@@ -192,10 +192,7 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
|
||||
return exp;
|
||||
|
||||
fail:
|
||||
if (blk) {
|
||||
blk_set_dev_ops(blk, NULL, NULL);
|
||||
blk_unref(blk);
|
||||
}
|
||||
blk_unref(blk);
|
||||
aio_context_release(ctx);
|
||||
if (exp) {
|
||||
g_free(exp->id);
|
||||
@@ -222,7 +219,6 @@ static void blk_exp_delete_bh(void *opaque)
|
||||
assert(exp->refcount == 0);
|
||||
QLIST_REMOVE(exp, next);
|
||||
exp->drv->delete(exp);
|
||||
blk_set_dev_ops(exp->blk, NULL, NULL);
|
||||
blk_unref(exp->blk);
|
||||
qapi_event_send_block_export_deleted(exp->id);
|
||||
g_free(exp->id);
|
||||
|
@@ -673,16 +673,7 @@ static void fuse_fallocate(fuse_req_t req, fuse_ino_t inode, int mode,
|
||||
do {
|
||||
int size = MIN(length, BDRV_REQUEST_MAX_BYTES);
|
||||
|
||||
ret = blk_pwrite_zeroes(exp->common.blk, offset, size,
|
||||
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK);
|
||||
if (ret == -ENOTSUP) {
|
||||
/*
|
||||
* fallocate() specifies to return EOPNOTSUPP for unsupported
|
||||
* operations
|
||||
*/
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = blk_pdiscard(exp->common.blk, offset, size);
|
||||
offset += size;
|
||||
length -= size;
|
||||
} while (ret == 0 && length > 0);
|
||||
|
@@ -346,6 +346,7 @@ static void vduse_blk_exp_delete(BlockExport *exp)
|
||||
|
||||
blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach,
|
||||
vblk_exp);
|
||||
blk_set_dev_ops(exp->blk, NULL, NULL);
|
||||
ret = vduse_dev_destroy(vblk_exp->dev);
|
||||
if (ret != -EBUSY) {
|
||||
unlink(vblk_exp->recon_file);
|
||||
|
@@ -22,9 +22,8 @@ struct virtio_blk_inhdr {
|
||||
unsigned char status;
|
||||
};
|
||||
|
||||
static bool coroutine_fn
|
||||
virtio_blk_sect_range_ok(BlockBackend *blk, uint32_t block_size,
|
||||
uint64_t sector, size_t size)
|
||||
static bool virtio_blk_sect_range_ok(BlockBackend *blk, uint32_t block_size,
|
||||
uint64_t sector, size_t size)
|
||||
{
|
||||
uint64_t nb_sectors;
|
||||
uint64_t total_sectors;
|
||||
@@ -42,7 +41,7 @@ virtio_blk_sect_range_ok(BlockBackend *blk, uint32_t block_size,
|
||||
if ((sector << VIRTIO_BLK_SECTOR_BITS) % block_size) {
|
||||
return false;
|
||||
}
|
||||
blk_co_get_geometry(blk, &total_sectors);
|
||||
blk_get_geometry(blk, &total_sectors);
|
||||
if (sector > total_sectors || nb_sectors > total_sectors - sector) {
|
||||
return false;
|
||||
}
|
||||
|
@@ -3743,12 +3743,6 @@ static void cdrom_parse_filename(const char *filename, QDict *options,
|
||||
{
|
||||
bdrv_parse_filename_strip_prefix(filename, "host_cdrom:", options);
|
||||
}
|
||||
|
||||
static void cdrom_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
bs->bl.has_variable_length = true;
|
||||
raw_refresh_limits(bs, errp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -3844,13 +3838,14 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_co_preadv = raw_co_preadv,
|
||||
.bdrv_co_pwritev = raw_co_pwritev,
|
||||
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
|
||||
.bdrv_refresh_limits = cdrom_refresh_limits,
|
||||
.bdrv_refresh_limits = raw_refresh_limits,
|
||||
.bdrv_co_io_plug = raw_co_io_plug,
|
||||
.bdrv_co_io_unplug = raw_co_io_unplug,
|
||||
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
|
||||
|
||||
.bdrv_co_truncate = raw_co_truncate,
|
||||
.bdrv_co_getlength = raw_co_getlength,
|
||||
.has_variable_length = true,
|
||||
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
|
||||
|
||||
/* removable device support */
|
||||
@@ -3972,13 +3967,14 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_co_preadv = raw_co_preadv,
|
||||
.bdrv_co_pwritev = raw_co_pwritev,
|
||||
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
|
||||
.bdrv_refresh_limits = cdrom_refresh_limits,
|
||||
.bdrv_refresh_limits = raw_refresh_limits,
|
||||
.bdrv_co_io_plug = raw_co_io_plug,
|
||||
.bdrv_co_io_unplug = raw_co_io_unplug,
|
||||
.bdrv_attach_aio_context = raw_aio_attach_aio_context,
|
||||
|
||||
.bdrv_co_truncate = raw_co_truncate,
|
||||
.bdrv_co_getlength = raw_co_getlength,
|
||||
.has_variable_length = true,
|
||||
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
|
||||
|
||||
/* removable device support */
|
||||
|
@@ -838,7 +838,6 @@ static void hdev_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
/* XXX Does Windows support AIO on less than 512-byte alignment? */
|
||||
bs->bl.request_alignment = 512;
|
||||
bs->bl.has_variable_length = true;
|
||||
}
|
||||
|
||||
static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
@@ -934,6 +933,7 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_attach_aio_context = raw_attach_aio_context,
|
||||
|
||||
.bdrv_co_getlength = raw_co_getlength,
|
||||
.has_variable_length = true,
|
||||
.bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size,
|
||||
};
|
||||
|
||||
|
@@ -146,6 +146,7 @@ static BlockDriver bdrv_compress = {
|
||||
.bdrv_co_eject = compress_co_eject,
|
||||
.bdrv_co_lock_medium = compress_co_lock_medium,
|
||||
|
||||
.has_variable_length = true,
|
||||
.is_filter = true,
|
||||
};
|
||||
|
||||
|
@@ -30,10 +30,8 @@ BdrvGraphLock graph_lock;
|
||||
/* Protects the list of aiocontext and orphaned_reader_count */
|
||||
static QemuMutex aio_context_list_lock;
|
||||
|
||||
#if 0
|
||||
/* Written and read with atomic operations. */
|
||||
static int has_writer;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A reader coroutine could move from an AioContext to another.
|
||||
@@ -90,7 +88,6 @@ void unregister_aiocontext(AioContext *ctx)
|
||||
g_free(ctx->bdrv_graph);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static uint32_t reader_count(void)
|
||||
{
|
||||
BdrvGraphRWlock *brdv_graph;
|
||||
@@ -108,17 +105,10 @@ static uint32_t reader_count(void)
|
||||
assert((int32_t)rd >= 0);
|
||||
return rd;
|
||||
}
|
||||
#endif
|
||||
|
||||
void bdrv_graph_wrlock(void)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
/*
|
||||
* TODO Some callers hold an AioContext lock when this is called, which
|
||||
* causes deadlocks. Reenable once the AioContext locking is cleaned up (or
|
||||
* AioContext locks are gone).
|
||||
*/
|
||||
#if 0
|
||||
assert(!qatomic_read(&has_writer));
|
||||
|
||||
/* Make sure that constantly arriving new I/O doesn't cause starvation */
|
||||
@@ -149,13 +139,11 @@ void bdrv_graph_wrlock(void)
|
||||
} while (reader_count() >= 1);
|
||||
|
||||
bdrv_drain_all_end();
|
||||
#endif
|
||||
}
|
||||
|
||||
void bdrv_graph_wrunlock(void)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
#if 0
|
||||
QEMU_LOCK_GUARD(&aio_context_list_lock);
|
||||
assert(qatomic_read(&has_writer));
|
||||
|
||||
@@ -167,13 +155,10 @@ void bdrv_graph_wrunlock(void)
|
||||
|
||||
/* Wake up all coroutine that are waiting to read the graph */
|
||||
qemu_co_enter_all(&reader_queue, &aio_context_list_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void coroutine_fn bdrv_graph_co_rdlock(void)
|
||||
{
|
||||
/* TODO Reenable when wrlock is reenabled */
|
||||
#if 0
|
||||
BdrvGraphRWlock *bdrv_graph;
|
||||
bdrv_graph = qemu_get_current_aio_context()->bdrv_graph;
|
||||
|
||||
@@ -238,12 +223,10 @@ void coroutine_fn bdrv_graph_co_rdlock(void)
|
||||
qemu_co_queue_wait(&reader_queue, &aio_context_list_lock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void coroutine_fn bdrv_graph_co_rdunlock(void)
|
||||
{
|
||||
#if 0
|
||||
BdrvGraphRWlock *bdrv_graph;
|
||||
bdrv_graph = qemu_get_current_aio_context()->bdrv_graph;
|
||||
|
||||
@@ -266,7 +249,6 @@ void coroutine_fn bdrv_graph_co_rdunlock(void)
|
||||
if (qatomic_read(&has_writer)) {
|
||||
aio_wait_kick();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void bdrv_graph_rdlock_main_loop(void)
|
||||
@@ -283,20 +265,11 @@ void bdrv_graph_rdunlock_main_loop(void)
|
||||
|
||||
void assert_bdrv_graph_readable(void)
|
||||
{
|
||||
/* reader_count() is slow due to aio_context_list_lock lock contention */
|
||||
/* TODO Reenable when wrlock is reenabled */
|
||||
#if 0
|
||||
#ifdef CONFIG_DEBUG_GRAPH_LOCK
|
||||
assert(qemu_in_main_thread() || reader_count());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void assert_bdrv_graph_writable(void)
|
||||
{
|
||||
assert(qemu_in_main_thread());
|
||||
/* TODO Reenable when wrlock is reenabled */
|
||||
#if 0
|
||||
assert(qatomic_read(&has_writer));
|
||||
#endif
|
||||
}
|
||||
|
@@ -190,10 +190,6 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
|
||||
bdrv_merge_limits(&bs->bl, &c->bs->bl);
|
||||
have_limits = true;
|
||||
}
|
||||
|
||||
if (c->role & BDRV_CHILD_FILTERED) {
|
||||
bs->bl.has_variable_length |= c->bs->bl.has_variable_length;
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_limits) {
|
||||
|
@@ -48,7 +48,6 @@
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "monitor/hmp.h"
|
||||
@@ -214,17 +213,15 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
|
||||
error_report("Device '%s' not found", device);
|
||||
return;
|
||||
}
|
||||
if (!blk_is_available(blk)) {
|
||||
error_report("Device '%s' has no medium", device);
|
||||
return;
|
||||
}
|
||||
|
||||
bs = bdrv_skip_implicit_filters(blk_bs(blk));
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
if (!blk_is_available(blk)) {
|
||||
error_report("Device '%s' has no medium", device);
|
||||
aio_context_release(aio_context);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = bdrv_commit(bs);
|
||||
|
||||
aio_context_release(aio_context);
|
||||
|
24
block/nfs.c
24
block/nfs.c
@@ -726,8 +726,10 @@ nfs_get_allocated_file_size_cb(int ret, struct nfs_context *nfs, void *data,
|
||||
if (task->ret < 0) {
|
||||
error_report("NFS Error: %s", nfs_get_error(nfs));
|
||||
}
|
||||
replay_bh_schedule_oneshot_event(task->client->aio_context,
|
||||
nfs_co_generic_bh_cb, task);
|
||||
|
||||
/* Set task->complete before reading bs->wakeup. */
|
||||
qatomic_mb_set(&task->complete, 1);
|
||||
bdrv_wakeup(task->bs);
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn nfs_co_get_allocated_file_size(BlockDriverState *bs)
|
||||
@@ -741,19 +743,15 @@ static int64_t coroutine_fn nfs_co_get_allocated_file_size(BlockDriverState *bs)
|
||||
return client->st_blocks * 512;
|
||||
}
|
||||
|
||||
nfs_co_init_task(bs, &task);
|
||||
task.bs = bs;
|
||||
task.st = &st;
|
||||
WITH_QEMU_LOCK_GUARD(&client->mutex) {
|
||||
if (nfs_fstat_async(client->context, client->fh, nfs_get_allocated_file_size_cb,
|
||||
&task) != 0) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (nfs_fstat_async(client->context, client->fh, nfs_get_allocated_file_size_cb,
|
||||
&task) != 0) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
nfs_set_events(client);
|
||||
}
|
||||
while (!task.complete) {
|
||||
qemu_coroutine_yield();
|
||||
}
|
||||
nfs_set_events(client);
|
||||
BDRV_POLL_WHILE(bs, !task.complete);
|
||||
|
||||
return (task.ret < 0 ? task.ret : st.st_blocks * 512);
|
||||
}
|
||||
|
@@ -613,8 +613,8 @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
return ret;
|
||||
|
||||
exit:
|
||||
@@ -691,7 +691,7 @@ parallels_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
|
||||
done:
|
||||
qobject_unref(qdict);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -558,6 +558,7 @@ BlockDriver bdrv_preallocate_filter = {
|
||||
.bdrv_set_perm = preallocate_set_perm,
|
||||
.bdrv_child_perm = preallocate_child_perm,
|
||||
|
||||
.has_variable_length = true,
|
||||
.is_filter = true,
|
||||
};
|
||||
|
||||
|
@@ -915,8 +915,8 @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
|
||||
g_free(tmp);
|
||||
ret = 0;
|
||||
exit:
|
||||
blk_co_unref(qcow_blk);
|
||||
bdrv_co_unref(bs);
|
||||
blk_unref(qcow_blk);
|
||||
bdrv_unref(bs);
|
||||
qcrypto_block_free(crypto);
|
||||
return ret;
|
||||
}
|
||||
@@ -1015,7 +1015,7 @@ qcow_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
fail:
|
||||
g_free(backing_fmt);
|
||||
qobject_unref(qdict);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -3705,7 +3705,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
blk_co_unref(blk);
|
||||
blk_unref(blk);
|
||||
blk = NULL;
|
||||
|
||||
/*
|
||||
@@ -3785,7 +3785,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
blk_co_unref(blk);
|
||||
blk_unref(blk);
|
||||
blk = NULL;
|
||||
|
||||
/* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning.
|
||||
@@ -3810,9 +3810,9 @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_co_unref(data_bs);
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
bdrv_unref(data_bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3943,8 +3943,8 @@ finish:
|
||||
}
|
||||
|
||||
qobject_unref(qdict);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_co_unref(data_bs);
|
||||
bdrv_unref(bs);
|
||||
bdrv_unref(data_bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -594,6 +594,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
|
||||
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
|
||||
}
|
||||
BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
|
||||
return qoc.ret;
|
||||
}
|
||||
|
||||
@@ -748,8 +749,8 @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
|
||||
ret = 0; /* success */
|
||||
out:
|
||||
g_free(l1_table);
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -819,7 +820,7 @@ bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
|
||||
fail:
|
||||
qobject_unref(qdict);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -377,8 +377,6 @@ raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
||||
|
||||
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
bs->bl.has_variable_length = bs->file->bs->bl.has_variable_length;
|
||||
|
||||
if (bs->probed) {
|
||||
/* To make it easier to protect the first sector, any probed
|
||||
* image is restricted to read-modify-write on sub-sector
|
||||
@@ -625,6 +623,7 @@ BlockDriver bdrv_raw = {
|
||||
.bdrv_co_truncate = &raw_co_truncate,
|
||||
.bdrv_co_getlength = &raw_co_getlength,
|
||||
.is_format = true,
|
||||
.has_variable_length = true,
|
||||
.bdrv_measure = &raw_measure,
|
||||
.bdrv_co_get_info = &raw_co_get_info,
|
||||
.bdrv_refresh_limits = &raw_refresh_limits,
|
||||
|
@@ -762,6 +762,7 @@ static BlockDriver bdrv_replication = {
|
||||
|
||||
.is_filter = true,
|
||||
|
||||
.has_variable_length = true,
|
||||
.strong_runtime_opts = replication_strong_runtime_opts,
|
||||
};
|
||||
|
||||
|
@@ -886,8 +886,8 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
|
||||
|
||||
ret = 0;
|
||||
exit:
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs_file);
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs_file);
|
||||
g_free(bmap);
|
||||
return ret;
|
||||
}
|
||||
@@ -975,7 +975,7 @@ vdi_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
done:
|
||||
qobject_unref(qdict);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
bdrv_co_unref(bs_file);
|
||||
bdrv_unref(bs_file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -981,7 +981,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
|
||||
sector_write = merged_sector;
|
||||
} else if (i == sectors - 1 && trailing_length) {
|
||||
/* partial sector at the end of the buffer */
|
||||
ret = bdrv_pread(bs->file, file_offset + trailing_length,
|
||||
ret = bdrv_pread(bs->file, file_offset,
|
||||
VHDX_LOG_SECTOR_SIZE - trailing_length,
|
||||
merged_sector + trailing_length, 0);
|
||||
if (ret < 0) {
|
||||
|
@@ -2053,8 +2053,8 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
|
||||
|
||||
ret = 0;
|
||||
delete_and_exit:
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
g_free(creator);
|
||||
return ret;
|
||||
}
|
||||
@@ -2144,7 +2144,7 @@ vhdx_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
|
||||
fail:
|
||||
qobject_unref(qdict);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
18
block/vmdk.c
18
block/vmdk.c
@@ -2306,7 +2306,7 @@ exit:
|
||||
if (pbb) {
|
||||
*pbb = blk;
|
||||
} else {
|
||||
blk_co_unref(blk);
|
||||
blk_unref(blk);
|
||||
blk = NULL;
|
||||
}
|
||||
}
|
||||
@@ -2516,12 +2516,12 @@ vmdk_co_do_create(int64_t size,
|
||||
if (strcmp(blk_bs(backing)->drv->format_name, "vmdk")) {
|
||||
error_setg(errp, "Invalid backing file format: %s. Must be vmdk",
|
||||
blk_bs(backing)->drv->format_name);
|
||||
blk_co_unref(backing);
|
||||
blk_unref(backing);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
ret = vmdk_read_cid(blk_bs(backing), 0, &parent_cid);
|
||||
blk_co_unref(backing);
|
||||
blk_unref(backing);
|
||||
if (ret) {
|
||||
error_setg(errp, "Failed to read parent CID");
|
||||
goto exit;
|
||||
@@ -2542,14 +2542,14 @@ vmdk_co_do_create(int64_t size,
|
||||
blk_bs(extent_blk)->filename);
|
||||
created_size += cur_size;
|
||||
extent_idx++;
|
||||
blk_co_unref(extent_blk);
|
||||
blk_unref(extent_blk);
|
||||
}
|
||||
|
||||
/* Check whether we got excess extents */
|
||||
extent_blk = extent_fn(-1, extent_idx, flat, split, compress, zeroed_grain,
|
||||
opaque, NULL);
|
||||
if (extent_blk) {
|
||||
blk_co_unref(extent_blk);
|
||||
blk_unref(extent_blk);
|
||||
error_setg(errp, "List of extents contains unused extents");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
@@ -2590,7 +2590,7 @@ vmdk_co_do_create(int64_t size,
|
||||
ret = 0;
|
||||
exit:
|
||||
if (blk) {
|
||||
blk_co_unref(blk);
|
||||
blk_unref(blk);
|
||||
}
|
||||
g_free(desc);
|
||||
g_free(parent_desc_line);
|
||||
@@ -2641,7 +2641,7 @@ vmdk_co_create_opts_cb(int64_t size, int idx, bool flat, bool split,
|
||||
errp)) {
|
||||
goto exit;
|
||||
}
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_unref(bs);
|
||||
exit:
|
||||
g_free(ext_filename);
|
||||
return blk;
|
||||
@@ -2797,12 +2797,12 @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
|
||||
return NULL;
|
||||
}
|
||||
blk_set_allow_write_beyond_eof(blk, true);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_unref(bs);
|
||||
|
||||
if (size != -1) {
|
||||
ret = vmdk_init_extent(blk, size, flat, compress, zeroed_grain, errp);
|
||||
if (ret) {
|
||||
blk_co_unref(blk);
|
||||
blk_unref(blk);
|
||||
blk = NULL;
|
||||
}
|
||||
}
|
||||
|
@@ -1082,8 +1082,8 @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
|
||||
}
|
||||
|
||||
out:
|
||||
blk_co_unref(blk);
|
||||
bdrv_co_unref(bs);
|
||||
blk_unref(blk);
|
||||
bdrv_unref(bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1162,7 +1162,7 @@ vpc_co_create_opts(BlockDriver *drv, const char *filename,
|
||||
|
||||
fail:
|
||||
qobject_unref(qdict);
|
||||
bdrv_co_unref(bs);
|
||||
bdrv_unref(bs);
|
||||
qapi_free_BlockdevCreateOptions(create_options);
|
||||
return ret;
|
||||
}
|
||||
|
22
blockdev.c
22
blockdev.c
@@ -153,22 +153,12 @@ void blockdev_mark_auto_del(BlockBackend *blk)
|
||||
|
||||
JOB_LOCK_GUARD();
|
||||
|
||||
do {
|
||||
job = block_job_next_locked(NULL);
|
||||
while (job && (job->job.cancelled ||
|
||||
job->job.deferred_to_main_loop ||
|
||||
!block_job_has_bdrv(job, blk_bs(blk))))
|
||||
{
|
||||
job = block_job_next_locked(job);
|
||||
}
|
||||
if (job) {
|
||||
/*
|
||||
* This drops the job lock temporarily and polls, so we need to
|
||||
* restart processing the list from the start after this.
|
||||
*/
|
||||
for (job = block_job_next_locked(NULL); job;
|
||||
job = block_job_next_locked(job)) {
|
||||
if (block_job_has_bdrv(job, blk_bs(blk))) {
|
||||
job_cancel_locked(&job->job, false);
|
||||
}
|
||||
} while (job);
|
||||
}
|
||||
|
||||
dinfo->auto_del = 1;
|
||||
}
|
||||
@@ -2440,7 +2430,7 @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
|
||||
return;
|
||||
}
|
||||
|
||||
blk = blk_co_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
|
||||
blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
|
||||
if (!blk) {
|
||||
return;
|
||||
}
|
||||
@@ -2455,7 +2445,7 @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
|
||||
|
||||
bdrv_co_lock(bs);
|
||||
bdrv_drained_end(bs);
|
||||
blk_co_unref(blk);
|
||||
blk_unref(blk);
|
||||
bdrv_co_unlock(bs);
|
||||
}
|
||||
|
||||
|
@@ -38,8 +38,6 @@
|
||||
#include <sys/sysctl.h>
|
||||
#include <utime.h>
|
||||
|
||||
#include "include/gdbstub/syscalls.h"
|
||||
|
||||
#include "qemu.h"
|
||||
#include "signal-common.h"
|
||||
#include "user/syscall-trace.h"
|
||||
|
@@ -44,7 +44,6 @@
|
||||
#include "trace/control.h"
|
||||
#include "crypto/init.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "gdbstub/user.h"
|
||||
|
||||
#include "host-os.h"
|
||||
#include "target_arch_cpu.h"
|
||||
@@ -68,9 +67,13 @@ bool have_guest_base;
|
||||
# if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
|
||||
# if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
|
||||
(TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
|
||||
# define MAX_RESERVED_VA 0xfffffffful
|
||||
/*
|
||||
* There are a number of places where we assign reserved_va to a variable
|
||||
* of type abi_ulong and expect it to fit. Avoid the last page.
|
||||
*/
|
||||
# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK)
|
||||
# else
|
||||
# define MAX_RESERVED_VA ((1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
|
||||
# define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
|
||||
# endif
|
||||
# else
|
||||
# define MAX_RESERVED_VA 0
|
||||
@@ -462,7 +465,7 @@ int main(int argc, char **argv)
|
||||
envlist_free(envlist);
|
||||
|
||||
if (reserved_va) {
|
||||
mmap_next_start = reserved_va + 1;
|
||||
mmap_next_start = reserved_va;
|
||||
}
|
||||
|
||||
{
|
||||
|
@@ -118,7 +118,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
}
|
||||
page_set_flags(start, start + len - 1, prot | PAGE_VALID);
|
||||
page_set_flags(start, start + len, prot | PAGE_VALID);
|
||||
mmap_unlock();
|
||||
return 0;
|
||||
error:
|
||||
@@ -234,7 +234,7 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size,
|
||||
size = HOST_PAGE_ALIGN(size) + alignment;
|
||||
end_addr = start + size;
|
||||
if (end_addr > reserved_va) {
|
||||
end_addr = reserved_va + 1;
|
||||
end_addr = reserved_va;
|
||||
}
|
||||
addr = end_addr - qemu_host_page_size;
|
||||
|
||||
@@ -243,7 +243,7 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size,
|
||||
if (looped) {
|
||||
return (abi_ulong)-1;
|
||||
}
|
||||
end_addr = reserved_va + 1;
|
||||
end_addr = reserved_va;
|
||||
addr = end_addr - qemu_host_page_size;
|
||||
looped = 1;
|
||||
continue;
|
||||
@@ -656,7 +656,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
}
|
||||
}
|
||||
the_end1:
|
||||
page_set_flags(start, start + len - 1, prot | PAGE_VALID);
|
||||
page_set_flags(start, start + len, prot | PAGE_VALID);
|
||||
the_end:
|
||||
#ifdef DEBUG_MMAP
|
||||
printf("ret=0x" TARGET_ABI_FMT_lx "\n", start);
|
||||
@@ -767,7 +767,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
page_set_flags(start, start + len - 1, 0);
|
||||
page_set_flags(start, start + len, 0);
|
||||
}
|
||||
mmap_unlock();
|
||||
return ret;
|
||||
|
@@ -21,7 +21,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu.h"
|
||||
#include "gdbstub/user.h"
|
||||
#include "signal-common.h"
|
||||
#include "trace.h"
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
|
@@ -44,39 +44,39 @@
|
||||
|
||||
#define ESC 0x1B
|
||||
|
||||
#define BAUM_REQ_DisplayData 0x01
|
||||
#define BAUM_REQ_GetVersionNumber 0x05
|
||||
#define BAUM_REQ_GetKeys 0x08
|
||||
#define BAUM_REQ_SetMode 0x12
|
||||
#define BAUM_REQ_SetProtocol 0x15
|
||||
#define BAUM_REQ_GetDeviceIdentity 0x84
|
||||
#define BAUM_REQ_GetSerialNumber 0x8A
|
||||
#define BAUM_REQ_DisplayData 0x01
|
||||
#define BAUM_REQ_GetVersionNumber 0x05
|
||||
#define BAUM_REQ_GetKeys 0x08
|
||||
#define BAUM_REQ_SetMode 0x12
|
||||
#define BAUM_REQ_SetProtocol 0x15
|
||||
#define BAUM_REQ_GetDeviceIdentity 0x84
|
||||
#define BAUM_REQ_GetSerialNumber 0x8A
|
||||
|
||||
#define BAUM_RSP_CellCount 0x01
|
||||
#define BAUM_RSP_VersionNumber 0x05
|
||||
#define BAUM_RSP_ModeSetting 0x11
|
||||
#define BAUM_RSP_CommunicationChannel 0x16
|
||||
#define BAUM_RSP_PowerdownSignal 0x17
|
||||
#define BAUM_RSP_HorizontalSensors 0x20
|
||||
#define BAUM_RSP_VerticalSensors 0x21
|
||||
#define BAUM_RSP_RoutingKeys 0x22
|
||||
#define BAUM_RSP_Switches 0x23
|
||||
#define BAUM_RSP_TopKeys 0x24
|
||||
#define BAUM_RSP_HorizontalSensor 0x25
|
||||
#define BAUM_RSP_VerticalSensor 0x26
|
||||
#define BAUM_RSP_RoutingKey 0x27
|
||||
#define BAUM_RSP_FrontKeys6 0x28
|
||||
#define BAUM_RSP_BackKeys6 0x29
|
||||
#define BAUM_RSP_CommandKeys 0x2B
|
||||
#define BAUM_RSP_FrontKeys10 0x2C
|
||||
#define BAUM_RSP_BackKeys10 0x2D
|
||||
#define BAUM_RSP_EntryKeys 0x33
|
||||
#define BAUM_RSP_JoyStick 0x34
|
||||
#define BAUM_RSP_ErrorCode 0x40
|
||||
#define BAUM_RSP_InfoBlock 0x42
|
||||
#define BAUM_RSP_DeviceIdentity 0x84
|
||||
#define BAUM_RSP_SerialNumber 0x8A
|
||||
#define BAUM_RSP_BluetoothName 0x8C
|
||||
#define BAUM_RSP_CellCount 0x01
|
||||
#define BAUM_RSP_VersionNumber 0x05
|
||||
#define BAUM_RSP_ModeSetting 0x11
|
||||
#define BAUM_RSP_CommunicationChannel 0x16
|
||||
#define BAUM_RSP_PowerdownSignal 0x17
|
||||
#define BAUM_RSP_HorizontalSensors 0x20
|
||||
#define BAUM_RSP_VerticalSensors 0x21
|
||||
#define BAUM_RSP_RoutingKeys 0x22
|
||||
#define BAUM_RSP_Switches 0x23
|
||||
#define BAUM_RSP_TopKeys 0x24
|
||||
#define BAUM_RSP_HorizontalSensor 0x25
|
||||
#define BAUM_RSP_VerticalSensor 0x26
|
||||
#define BAUM_RSP_RoutingKey 0x27
|
||||
#define BAUM_RSP_FrontKeys6 0x28
|
||||
#define BAUM_RSP_BackKeys6 0x29
|
||||
#define BAUM_RSP_CommandKeys 0x2B
|
||||
#define BAUM_RSP_FrontKeys10 0x2C
|
||||
#define BAUM_RSP_BackKeys10 0x2D
|
||||
#define BAUM_RSP_EntryKeys 0x33
|
||||
#define BAUM_RSP_JoyStick 0x34
|
||||
#define BAUM_RSP_ErrorCode 0x40
|
||||
#define BAUM_RSP_InfoBlock 0x42
|
||||
#define BAUM_RSP_DeviceIdentity 0x84
|
||||
#define BAUM_RSP_SerialNumber 0x8A
|
||||
#define BAUM_RSP_BluetoothName 0x8C
|
||||
|
||||
#define BAUM_TL1 0x01
|
||||
#define BAUM_TL2 0x02
|
||||
|
@@ -1175,10 +1175,12 @@ bool qmp_add_client_char(int fd, bool has_skipauth, bool skipauth,
|
||||
|
||||
if (!s) {
|
||||
error_setg(errp, "protocol '%s' is invalid", protocol);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
if (qemu_chr_add_client(s, fd) < 0) {
|
||||
error_setg(errp, "failed to add client");
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
TARGET_ARCH=aarch64
|
||||
TARGET_BASE_ARCH=arm
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/aarch64-pauth.xml
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
|
||||
TARGET_HAS_BFLT=y
|
||||
CONFIG_SEMIHOSTING=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
@@ -1,5 +1,5 @@
|
||||
TARGET_ARCH=aarch64
|
||||
TARGET_BASE_ARCH=arm
|
||||
TARGET_SUPPORTS_MTTCG=y
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml gdb-xml/aarch64-pauth.xml
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
|
||||
TARGET_NEED_FDT=y
|
||||
|
@@ -1,7 +1,7 @@
|
||||
TARGET_ARCH=aarch64
|
||||
TARGET_BASE_ARCH=arm
|
||||
TARGET_BIG_ENDIAN=y
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/aarch64-pauth.xml
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
|
||||
TARGET_HAS_BFLT=y
|
||||
CONFIG_SEMIHOSTING=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
25
configure
vendored
25
configure
vendored
@@ -230,8 +230,6 @@ stack_protector=""
|
||||
safe_stack=""
|
||||
use_containers="yes"
|
||||
gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb")
|
||||
gdb_arches=""
|
||||
glib_has_gslice="no"
|
||||
|
||||
if test -e "$source_path/.git"
|
||||
then
|
||||
@@ -806,7 +804,6 @@ for opt do
|
||||
--enable-debug)
|
||||
# Enable debugging options that aren't excessively noisy
|
||||
debug_tcg="yes"
|
||||
meson_option_parse --enable-debug-graph-lock ""
|
||||
meson_option_parse --enable-debug-mutex ""
|
||||
meson_option_add -Doptimization=0
|
||||
fortify_source="no"
|
||||
@@ -1496,17 +1493,6 @@ for i in $glib_modules; do
|
||||
fi
|
||||
done
|
||||
|
||||
# Check whether glib has gslice, which we have to avoid for correctness.
|
||||
# TODO: remove this check and the corresponding workaround (qtree) when
|
||||
# the minimum supported glib is >= $glib_dropped_gslice_version.
|
||||
glib_dropped_gslice_version=2.75.3
|
||||
for i in $glib_modules; do
|
||||
if ! $pkg_config --atleast-version=$glib_dropped_gslice_version $i; then
|
||||
glib_has_gslice="yes"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
glib_bindir="$($pkg_config --variable=bindir glib-2.0)"
|
||||
if test -z "$glib_bindir" ; then
|
||||
glib_bindir="$($pkg_config --variable=prefix glib-2.0)"/bin
|
||||
@@ -2276,7 +2262,6 @@ fi
|
||||
# tests might fail. Prefer to keep the relevant files in their own
|
||||
# directory and symlink the directory instead.
|
||||
LINKS="Makefile"
|
||||
LINKS="$LINKS docs/config"
|
||||
LINKS="$LINKS pc-bios/optionrom/Makefile"
|
||||
LINKS="$LINKS pc-bios/s390-ccw/Makefile"
|
||||
LINKS="$LINKS pc-bios/vof/Makefile"
|
||||
@@ -2410,7 +2395,6 @@ if test -n "$gdb_bin"; then
|
||||
gdb_version=$($gdb_bin --version | head -n 1)
|
||||
if version_ge ${gdb_version##* } 9.1; then
|
||||
echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak
|
||||
gdb_arches=$("$source_path/scripts/probe-gdb-support.py" $gdb_bin)
|
||||
else
|
||||
gdb_bin=""
|
||||
fi
|
||||
@@ -2433,9 +2417,6 @@ echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
|
||||
echo "GLIB_LIBS=$glib_libs" >> $config_host_mak
|
||||
echo "GLIB_BINDIR=$glib_bindir" >> $config_host_mak
|
||||
echo "GLIB_VERSION=$($pkg_config --modversion glib-2.0)" >> $config_host_mak
|
||||
if test "$glib_has_gslice" = "yes" ; then
|
||||
echo "HAVE_GLIB_WITH_SLICE_ALLOCATOR=y" >> $config_host_mak
|
||||
fi
|
||||
echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak
|
||||
echo "EXESUF=$EXESUF" >> $config_host_mak
|
||||
|
||||
@@ -2538,12 +2519,6 @@ for target in $target_list; do
|
||||
write_target_makefile "build-tcg-tests-$target" >> "$config_target_mak"
|
||||
echo "BUILD_STATIC=$build_static" >> "$config_target_mak"
|
||||
echo "QEMU=$PWD/$qemu" >> "$config_target_mak"
|
||||
|
||||
# will GDB work with these binaries?
|
||||
if test "${gdb_arches#*$arch}" != "$gdb_arches"; then
|
||||
echo "HOST_GDB_SUPPORTS_ARCH=y" >> "$config_target_mak"
|
||||
fi
|
||||
|
||||
echo "run-tcg-tests-$target: $qemu\$(EXESUF)" >> Makefile.prereqs
|
||||
tcg_tests_targets="$tcg_tests_targets $target"
|
||||
fi
|
||||
|
@@ -11,7 +11,6 @@
|
||||
static struct pa_block *pa_space_find_block(struct pa_space *ps, uint64_t pa)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ps->block_nr; i++) {
|
||||
if (ps->block[i].paddr <= pa &&
|
||||
pa <= ps->block[i].paddr + ps->block[i].size) {
|
||||
|
@@ -17,7 +17,6 @@
|
||||
|
||||
#define SYM_URL_BASE "https://msdl.microsoft.com/download/symbols/"
|
||||
#define PDB_NAME "ntkrnlmp.pdb"
|
||||
#define PE_NAME "ntoskrnl.exe"
|
||||
|
||||
#define INITIAL_MXCSR 0x1f80
|
||||
|
||||
@@ -283,16 +282,14 @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
|
||||
};
|
||||
|
||||
for (i = 0; i < ps->block_nr; i++) {
|
||||
h.PhysicalMemoryBlock.NumberOfPages +=
|
||||
ps->block[i].size / ELF2DMP_PAGE_SIZE;
|
||||
h.PhysicalMemoryBlock.NumberOfPages += ps->block[i].size / ELF2DMP_PAGE_SIZE;
|
||||
h.PhysicalMemoryBlock.Run[i] = (WinDumpPhyMemRun64) {
|
||||
.BasePage = ps->block[i].paddr / ELF2DMP_PAGE_SIZE,
|
||||
.PageCount = ps->block[i].size / ELF2DMP_PAGE_SIZE,
|
||||
};
|
||||
}
|
||||
|
||||
h.RequiredDumpSpace +=
|
||||
h.PhysicalMemoryBlock.NumberOfPages << ELF2DMP_PAGE_BITS;
|
||||
h.RequiredDumpSpace += h.PhysicalMemoryBlock.NumberOfPages << ELF2DMP_PAGE_BITS;
|
||||
|
||||
*hdr = h;
|
||||
|
||||
@@ -302,8 +299,7 @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
|
||||
static int fill_context(KDDEBUGGER_DATA64 *kdbg,
|
||||
struct va_space *vs, QEMU_Elf *qe)
|
||||
{
|
||||
int i;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < qe->state_nr; i++) {
|
||||
uint64_t Prcb;
|
||||
uint64_t Context;
|
||||
@@ -334,45 +330,6 @@ static int fill_context(KDDEBUGGER_DATA64 *kdbg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx,
|
||||
void *entry, size_t size, struct va_space *vs)
|
||||
{
|
||||
const char e_magic[2] = "MZ";
|
||||
const char Signature[4] = "PE\0\0";
|
||||
IMAGE_DOS_HEADER *dos_hdr = start_addr;
|
||||
IMAGE_NT_HEADERS64 nt_hdrs;
|
||||
IMAGE_FILE_HEADER *file_hdr = &nt_hdrs.FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER64 *opt_hdr = &nt_hdrs.OptionalHeader;
|
||||
IMAGE_DATA_DIRECTORY *data_dir = nt_hdrs.OptionalHeader.DataDirectory;
|
||||
|
||||
QEMU_BUILD_BUG_ON(sizeof(*dos_hdr) >= ELF2DMP_PAGE_SIZE);
|
||||
|
||||
if (memcmp(&dos_hdr->e_magic, e_magic, sizeof(e_magic))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (va_space_rw(vs, base + dos_hdr->e_lfanew,
|
||||
&nt_hdrs, sizeof(nt_hdrs), 0)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (memcmp(&nt_hdrs.Signature, Signature, sizeof(Signature)) ||
|
||||
file_hdr->Machine != 0x8664 || opt_hdr->Magic != 0x020b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (va_space_rw(vs,
|
||||
base + data_dir[idx].VirtualAddress,
|
||||
entry, size, 0)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Data directory entry #%d: RVA = 0x%08"PRIx32"\n", idx,
|
||||
(uint32_t)data_dir[idx].VirtualAddress);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_dump(struct pa_space *ps,
|
||||
WinDumpHeader64 *hdr, const char *name)
|
||||
{
|
||||
@@ -406,38 +363,45 @@ static int write_dump(struct pa_space *ps,
|
||||
return fclose(dmp_file);
|
||||
}
|
||||
|
||||
static bool pe_check_export_name(uint64_t base, void *start_addr,
|
||||
struct va_space *vs)
|
||||
{
|
||||
IMAGE_EXPORT_DIRECTORY export_dir;
|
||||
const char *pe_name;
|
||||
|
||||
if (pe_get_data_dir_entry(base, start_addr, IMAGE_FILE_EXPORT_DIRECTORY,
|
||||
&export_dir, sizeof(export_dir), vs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pe_name = va_space_resolve(vs, base + export_dir.Name);
|
||||
if (!pe_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !strcmp(pe_name, PE_NAME);
|
||||
}
|
||||
|
||||
static int pe_get_pdb_symstore_hash(uint64_t base, void *start_addr,
|
||||
char *hash, struct va_space *vs)
|
||||
{
|
||||
const char e_magic[2] = "MZ";
|
||||
const char Signature[4] = "PE\0\0";
|
||||
const char sign_rsds[4] = "RSDS";
|
||||
IMAGE_DOS_HEADER *dos_hdr = start_addr;
|
||||
IMAGE_NT_HEADERS64 nt_hdrs;
|
||||
IMAGE_FILE_HEADER *file_hdr = &nt_hdrs.FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER64 *opt_hdr = &nt_hdrs.OptionalHeader;
|
||||
IMAGE_DATA_DIRECTORY *data_dir = nt_hdrs.OptionalHeader.DataDirectory;
|
||||
IMAGE_DEBUG_DIRECTORY debug_dir;
|
||||
OMFSignatureRSDS rsds;
|
||||
char *pdb_name;
|
||||
size_t pdb_name_sz;
|
||||
size_t i;
|
||||
|
||||
if (pe_get_data_dir_entry(base, start_addr, IMAGE_FILE_DEBUG_DIRECTORY,
|
||||
&debug_dir, sizeof(debug_dir), vs)) {
|
||||
eprintf("Failed to get Debug Directory\n");
|
||||
QEMU_BUILD_BUG_ON(sizeof(*dos_hdr) >= ELF2DMP_PAGE_SIZE);
|
||||
|
||||
if (memcmp(&dos_hdr->e_magic, e_magic, sizeof(e_magic))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (va_space_rw(vs, base + dos_hdr->e_lfanew,
|
||||
&nt_hdrs, sizeof(nt_hdrs), 0)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (memcmp(&nt_hdrs.Signature, Signature, sizeof(Signature)) ||
|
||||
file_hdr->Machine != 0x8664 || opt_hdr->Magic != 0x020b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Debug Directory RVA = 0x%08"PRIx32"\n",
|
||||
(uint32_t)data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress);
|
||||
|
||||
if (va_space_rw(vs,
|
||||
base + data_dir[IMAGE_FILE_DEBUG_DIRECTORY].VirtualAddress,
|
||||
&debug_dir, sizeof(debug_dir), 0)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -509,7 +473,6 @@ int main(int argc, char *argv[])
|
||||
uint64_t KdDebuggerDataBlock;
|
||||
KDDEBUGGER_DATA64 *kdbg;
|
||||
uint64_t KdVersionBlock;
|
||||
bool kernel_found = false;
|
||||
|
||||
if (argc != 3) {
|
||||
eprintf("usage:\n\t%s elf_file dmp_file\n", argv[0]);
|
||||
@@ -557,14 +520,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (*(uint16_t *)nt_start_addr == 0x5a4d) { /* MZ */
|
||||
if (pe_check_export_name(KernBase, nt_start_addr, &vs)) {
|
||||
kernel_found = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!kernel_found) {
|
||||
if (!nt_start_addr) {
|
||||
eprintf("Failed to find NT kernel image\n");
|
||||
err = 1;
|
||||
goto out_ps;
|
||||
|
@@ -33,90 +33,75 @@ typedef struct IMAGE_DOS_HEADER {
|
||||
} __attribute__ ((packed)) IMAGE_DOS_HEADER;
|
||||
|
||||
typedef struct IMAGE_FILE_HEADER {
|
||||
uint16_t Machine;
|
||||
uint16_t NumberOfSections;
|
||||
uint32_t TimeDateStamp;
|
||||
uint32_t PointerToSymbolTable;
|
||||
uint32_t NumberOfSymbols;
|
||||
uint16_t SizeOfOptionalHeader;
|
||||
uint16_t Characteristics;
|
||||
uint16_t Machine;
|
||||
uint16_t NumberOfSections;
|
||||
uint32_t TimeDateStamp;
|
||||
uint32_t PointerToSymbolTable;
|
||||
uint32_t NumberOfSymbols;
|
||||
uint16_t SizeOfOptionalHeader;
|
||||
uint16_t Characteristics;
|
||||
} __attribute__ ((packed)) IMAGE_FILE_HEADER;
|
||||
|
||||
typedef struct IMAGE_DATA_DIRECTORY {
|
||||
uint32_t VirtualAddress;
|
||||
uint32_t Size;
|
||||
uint32_t VirtualAddress;
|
||||
uint32_t Size;
|
||||
} __attribute__ ((packed)) IMAGE_DATA_DIRECTORY;
|
||||
|
||||
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
||||
|
||||
typedef struct IMAGE_OPTIONAL_HEADER64 {
|
||||
uint16_t Magic; /* 0x20b */
|
||||
uint8_t MajorLinkerVersion;
|
||||
uint8_t MinorLinkerVersion;
|
||||
uint32_t SizeOfCode;
|
||||
uint32_t SizeOfInitializedData;
|
||||
uint32_t SizeOfUninitializedData;
|
||||
uint32_t AddressOfEntryPoint;
|
||||
uint32_t BaseOfCode;
|
||||
uint64_t ImageBase;
|
||||
uint32_t SectionAlignment;
|
||||
uint32_t FileAlignment;
|
||||
uint16_t MajorOperatingSystemVersion;
|
||||
uint16_t MinorOperatingSystemVersion;
|
||||
uint16_t MajorImageVersion;
|
||||
uint16_t MinorImageVersion;
|
||||
uint16_t MajorSubsystemVersion;
|
||||
uint16_t MinorSubsystemVersion;
|
||||
uint32_t Win32VersionValue;
|
||||
uint32_t SizeOfImage;
|
||||
uint32_t SizeOfHeaders;
|
||||
uint32_t CheckSum;
|
||||
uint16_t Subsystem;
|
||||
uint16_t DllCharacteristics;
|
||||
uint64_t SizeOfStackReserve;
|
||||
uint64_t SizeOfStackCommit;
|
||||
uint64_t SizeOfHeapReserve;
|
||||
uint64_t SizeOfHeapCommit;
|
||||
uint32_t LoaderFlags;
|
||||
uint32_t NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
uint16_t Magic; /* 0x20b */
|
||||
uint8_t MajorLinkerVersion;
|
||||
uint8_t MinorLinkerVersion;
|
||||
uint32_t SizeOfCode;
|
||||
uint32_t SizeOfInitializedData;
|
||||
uint32_t SizeOfUninitializedData;
|
||||
uint32_t AddressOfEntryPoint;
|
||||
uint32_t BaseOfCode;
|
||||
uint64_t ImageBase;
|
||||
uint32_t SectionAlignment;
|
||||
uint32_t FileAlignment;
|
||||
uint16_t MajorOperatingSystemVersion;
|
||||
uint16_t MinorOperatingSystemVersion;
|
||||
uint16_t MajorImageVersion;
|
||||
uint16_t MinorImageVersion;
|
||||
uint16_t MajorSubsystemVersion;
|
||||
uint16_t MinorSubsystemVersion;
|
||||
uint32_t Win32VersionValue;
|
||||
uint32_t SizeOfImage;
|
||||
uint32_t SizeOfHeaders;
|
||||
uint32_t CheckSum;
|
||||
uint16_t Subsystem;
|
||||
uint16_t DllCharacteristics;
|
||||
uint64_t SizeOfStackReserve;
|
||||
uint64_t SizeOfStackCommit;
|
||||
uint64_t SizeOfHeapReserve;
|
||||
uint64_t SizeOfHeapCommit;
|
||||
uint32_t LoaderFlags;
|
||||
uint32_t NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
} __attribute__ ((packed)) IMAGE_OPTIONAL_HEADER64;
|
||||
|
||||
typedef struct IMAGE_NT_HEADERS64 {
|
||||
uint32_t Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
uint32_t Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||
} __attribute__ ((packed)) IMAGE_NT_HEADERS64;
|
||||
|
||||
typedef struct IMAGE_EXPORT_DIRECTORY {
|
||||
uint32_t Characteristics;
|
||||
uint32_t TimeDateStamp;
|
||||
uint16_t MajorVersion;
|
||||
uint16_t MinorVersion;
|
||||
uint32_t Name;
|
||||
uint32_t Base;
|
||||
uint32_t NumberOfFunctions;
|
||||
uint32_t NumberOfNames;
|
||||
uint32_t AddressOfFunctions;
|
||||
uint32_t AddressOfNames;
|
||||
uint32_t AddressOfNameOrdinals;
|
||||
} __attribute__ ((packed)) IMAGE_EXPORT_DIRECTORY;
|
||||
|
||||
typedef struct IMAGE_DEBUG_DIRECTORY {
|
||||
uint32_t Characteristics;
|
||||
uint32_t TimeDateStamp;
|
||||
uint16_t MajorVersion;
|
||||
uint16_t MinorVersion;
|
||||
uint32_t Type;
|
||||
uint32_t SizeOfData;
|
||||
uint32_t AddressOfRawData;
|
||||
uint32_t PointerToRawData;
|
||||
uint32_t Characteristics;
|
||||
uint32_t TimeDateStamp;
|
||||
uint16_t MajorVersion;
|
||||
uint16_t MinorVersion;
|
||||
uint32_t Type;
|
||||
uint32_t SizeOfData;
|
||||
uint32_t AddressOfRawData;
|
||||
uint32_t PointerToRawData;
|
||||
} __attribute__ ((packed)) IMAGE_DEBUG_DIRECTORY;
|
||||
|
||||
#define IMAGE_DEBUG_TYPE_CODEVIEW 2
|
||||
#endif
|
||||
|
||||
#define IMAGE_FILE_EXPORT_DIRECTORY 0
|
||||
#define IMAGE_FILE_DEBUG_DIRECTORY 6
|
||||
|
||||
typedef struct guid_t {
|
||||
|
@@ -4,12 +4,7 @@
|
||||
# This maps email domains to nice easy to read company names
|
||||
#
|
||||
|
||||
linux.alibaba.com Alibaba
|
||||
amazon.com Amazon
|
||||
amazon.co.uk Amazon
|
||||
amazon.de Amazon
|
||||
amd.com AMD
|
||||
aspeedtech.com ASPEED Technology Inc.
|
||||
baidu.com Baidu
|
||||
bytedance.com ByteDance
|
||||
cmss.chinamobile.com China Mobile
|
||||
@@ -17,7 +12,6 @@ citrix.com Citrix
|
||||
crudebyte.com Crudebyte
|
||||
chinatelecom.cn China Telecom
|
||||
eldorado.org.br Instituto de Pesquisas Eldorado
|
||||
fb.com Facebook
|
||||
fujitsu.com Fujitsu
|
||||
google.com Google
|
||||
greensocs.com GreenSocs
|
||||
@@ -37,18 +31,15 @@ oracle.com Oracle
|
||||
proxmox.com Proxmox
|
||||
quicinc.com Qualcomm Innovation Center
|
||||
redhat.com Red Hat
|
||||
rev.ng rev.ng Labs
|
||||
rt-rk.com RT-RK
|
||||
samsung.com Samsung
|
||||
siemens.com Siemens
|
||||
sifive.com SiFive
|
||||
suse.com SUSE
|
||||
suse.de SUSE
|
||||
syrmia.com SYRMIA
|
||||
ventanamicro.com Ventana Micro Systems
|
||||
virtuozzo.com Virtuozzo
|
||||
vrull.eu VRULL
|
||||
wdc.com Western Digital
|
||||
windriver.com Wind River
|
||||
xilinx.com Xilinx
|
||||
yadro.com YADRO
|
||||
yandex-team.ru Yandex
|
||||
|
@@ -1,7 +0,0 @@
|
||||
#
|
||||
# Alibaba contributors including its subsidiaries
|
||||
#
|
||||
|
||||
# c-sky.com, now part of T-Head, wholly-owned entity of Alibaba Group
|
||||
ren_guo@c-sky.com
|
||||
zhiwei_liu@c-sky.com
|
@@ -1,8 +0,0 @@
|
||||
# AMD acquired Xilinx and contributors have been slowly updating emails
|
||||
|
||||
edgar.iglesias@xilinx.com
|
||||
fnu.vikram@xilinx.com
|
||||
francisco.iglesias@xilinx.com
|
||||
sai.pavan.boddu@xilinx.com
|
||||
stefano.stabellini@xilinx.com
|
||||
tong.ho@xilinx.com
|
@@ -1,5 +0,0 @@
|
||||
#
|
||||
# Some Facebook contributors also occasionally use personal email addresses.
|
||||
#
|
||||
|
||||
peter@pjd.dev
|
@@ -12,4 +12,3 @@ jcfaracco@gmail.com
|
||||
joel@jms.id.au
|
||||
sjitindarsingh@gmail.com
|
||||
tommusta@gmail.com
|
||||
idan.horowitz@gmail.com
|
||||
|
@@ -37,8 +37,3 @@ akihiko.odaki@gmail.com
|
||||
paul@nowt.org
|
||||
git@xen0n.name
|
||||
simon@simonsafar.com
|
||||
research_trasio@irq.a4lg.com
|
||||
shentey@gmail.com
|
||||
bmeng@tinylab.org
|
||||
strahinja.p.jankovic@gmail.com
|
||||
Jason@zx2c4.com
|
||||
|
13
cpu.c
13
cpu.c
@@ -31,18 +31,16 @@
|
||||
#include "hw/core/sysemu-cpu-ops.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#endif
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/replay-core.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "exec/translate-all.h"
|
||||
#include "exec/log.h"
|
||||
#include "hw/core/accel-cpu.h"
|
||||
#include "trace/trace-root.h"
|
||||
#include "qemu/accel.h"
|
||||
#include "qemu/plugin.h"
|
||||
|
||||
uintptr_t qemu_host_page_size;
|
||||
intptr_t qemu_host_page_mask;
|
||||
@@ -327,14 +325,9 @@ void cpu_single_step(CPUState *cpu, int enabled)
|
||||
{
|
||||
if (cpu->singlestep_enabled != enabled) {
|
||||
cpu->singlestep_enabled = enabled;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
const AccelOpsClass *ops = cpus_get_accel();
|
||||
if (ops->update_guest_debug) {
|
||||
ops->update_guest_debug(cpu);
|
||||
if (kvm_enabled()) {
|
||||
kvm_update_guest_debug(cpu, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
trace_breakpoint_singlestep(cpu->cpu_index, enabled);
|
||||
}
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ qcrypto_afalg_socket_bind(const char *type, const char *name,
|
||||
|
||||
if (bind(sbind, (const struct sockaddr *)&salg, sizeof(salg)) != 0) {
|
||||
error_setg_errno(errp, errno, "Failed to bind socket");
|
||||
close(sbind);
|
||||
closesocket(sbind);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -105,11 +105,11 @@ void qcrypto_afalg_comm_free(QCryptoAFAlg *afalg)
|
||||
}
|
||||
|
||||
if (afalg->tfmfd != -1) {
|
||||
close(afalg->tfmfd);
|
||||
closesocket(afalg->tfmfd);
|
||||
}
|
||||
|
||||
if (afalg->opfd != -1) {
|
||||
close(afalg->opfd);
|
||||
closesocket(afalg->opfd);
|
||||
}
|
||||
|
||||
g_free(afalg);
|
||||
|
@@ -1014,7 +1014,6 @@ static const char rv_vreg_name_sym[32][4] = {
|
||||
#define rv_fmt_rd_offset "O\t0,o"
|
||||
#define rv_fmt_rd_rs1_rs2 "O\t0,1,2"
|
||||
#define rv_fmt_frd_rs1 "O\t3,1"
|
||||
#define rv_fmt_frd_frs1 "O\t3,4"
|
||||
#define rv_fmt_rd_frs1 "O\t0,4"
|
||||
#define rv_fmt_rd_frs1_frs2 "O\t0,4,5"
|
||||
#define rv_fmt_frd_frs1_frs2 "O\t3,4,5"
|
||||
@@ -1581,15 +1580,15 @@ const rv_opcode_data opcode_data[] = {
|
||||
{ "snez", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
|
||||
{ "sltz", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "sgtz", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
|
||||
{ "fmv.s", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
|
||||
{ "fabs.s", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
|
||||
{ "fneg.s", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
|
||||
{ "fmv.d", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
|
||||
{ "fabs.d", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
|
||||
{ "fneg.d", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
|
||||
{ "fmv.q", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
|
||||
{ "fabs.q", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
|
||||
{ "fneg.q", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
|
||||
{ "fmv.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "fabs.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "fneg.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "fmv.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "fabs.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "fneg.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "fmv.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "fabs.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "fneg.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "beqz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
|
||||
{ "bnez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
|
||||
{ "blez", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 },
|
||||
@@ -1646,9 +1645,9 @@ const rv_opcode_data opcode_data[] = {
|
||||
{ "max", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
|
||||
{ "maxu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
|
||||
{ "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "ctzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
|
||||
{ "slli.uw", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
|
||||
{ "slli.uw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
|
||||
{ "add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
|
||||
{ "rolw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
|
||||
{ "rorw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
|
||||
@@ -2618,10 +2617,10 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
|
||||
switch (((inst >> 12) & 0b111)) {
|
||||
case 0: op = rv_op_addiw; break;
|
||||
case 1:
|
||||
switch (((inst >> 26) & 0b111111)) {
|
||||
switch (((inst >> 25) & 0b1111111)) {
|
||||
case 0: op = rv_op_slliw; break;
|
||||
case 2: op = rv_op_slli_uw; break;
|
||||
case 24:
|
||||
case 4: op = rv_op_slli_uw; break;
|
||||
case 48:
|
||||
switch ((inst >> 20) & 0b11111) {
|
||||
case 0b00000: op = rv_op_clzw; break;
|
||||
case 0b00001: op = rv_op_ctzw; break;
|
||||
|
@@ -67,8 +67,7 @@ Non-supported architectures may be removed in the future following the
|
||||
Linux OS, macOS, FreeBSD, NetBSD, OpenBSD
|
||||
-----------------------------------------
|
||||
|
||||
The project aims to support the most recent major version at all times for
|
||||
up to five years after its initial release. Support
|
||||
The project aims to support the most recent major version at all times. Support
|
||||
for the previous major version will be dropped 2 years after the new major
|
||||
version is released or when the vendor itself drops support, whichever comes
|
||||
first. In this context, third-party efforts to extend the lifetime of a distro
|
||||
|
@@ -111,10 +111,6 @@ Use ``-machine acpi=off`` instead.
|
||||
The HAXM project has been retired (see https://github.com/intel/haxm#status).
|
||||
Use "whpx" (on Windows) or "hvf" (on macOS) instead.
|
||||
|
||||
``-async-teardown`` (since 8.1)
|
||||
'''''''''''''''''''''''''''''''
|
||||
|
||||
Use ``-run-with async-teardown=on`` instead.
|
||||
|
||||
QEMU Machine Protocol (QMP) commands
|
||||
------------------------------------
|
||||
@@ -200,17 +196,6 @@ CI coverage support may bitrot away before the deprecation process
|
||||
completes. The little endian variants of MIPS (both 32 and 64 bit) are
|
||||
still a supported host architecture.
|
||||
|
||||
System emulation on 32-bit x86 hosts (since 8.0)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
Support for 32-bit x86 host deployments is increasingly uncommon in mainstream
|
||||
OS distributions given the widespread availability of 64-bit x86 hardware.
|
||||
The QEMU project no longer considers 32-bit x86 support for system emulation to
|
||||
be an effective use of its limited resources, and thus intends to discontinue
|
||||
it. Since all recent x86 hardware from the past >10 years is capable of the
|
||||
64-bit x86 extensions, a corresponding 64-bit OS should be used instead.
|
||||
|
||||
|
||||
QEMU API (QAPI) events
|
||||
----------------------
|
||||
|
||||
@@ -223,8 +208,8 @@ Use the more generic event ``DEVICE_UNPLUG_GUEST_ERROR`` instead.
|
||||
System emulator machines
|
||||
------------------------
|
||||
|
||||
Arm ``virt`` machine ``dtb-kaslr-seed`` property (since 7.1)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
Arm ``virt`` machine ``dtb-kaslr-seed`` property
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The ``dtb-kaslr-seed`` property on the ``virt`` board has been
|
||||
deprecated; use the new name ``dtb-randomness`` instead. The new name
|
||||
|
@@ -99,7 +99,7 @@ depending on the guest architecture.
|
||||
- Yes
|
||||
- A configurable 32 bit soft core now owned by Cadence
|
||||
|
||||
A number of features are only available when running under
|
||||
A number of features are are only available when running under
|
||||
emulation including :ref:`Record/Replay<replay>` and :ref:`TCG Plugins`.
|
||||
|
||||
.. _Semihosting:
|
||||
|
@@ -56,10 +56,8 @@
|
||||
|
||||
[machine]
|
||||
type = "virt"
|
||||
gic-version = "host"
|
||||
|
||||
[accel]
|
||||
accel = "kvm"
|
||||
gic-version = "host"
|
||||
|
||||
[memory]
|
||||
size = "1024"
|
||||
|
@@ -62,10 +62,8 @@
|
||||
|
||||
[machine]
|
||||
type = "virt"
|
||||
gic-version = "host"
|
||||
|
||||
[accel]
|
||||
accel = "kvm"
|
||||
gic-version = "host"
|
||||
|
||||
[memory]
|
||||
size = "1024"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user