Compare commits

..

16 Commits

Author SHA1 Message Date
Fabiano Rosas
a0efb212fb migration: Add completion tracepoint
Add a completion tracepoint that provides basic stats for
debug. Displays throughput (MB/s and pages/s), total time (ms), total
transferred (B).

Usage:
  $QEMU ... -trace migration_status

Output:
  migration_status 1506 MB/s, 436725 pages/s, 8698 ms 13093280510 B

Signed-off-by: Fabiano Rosas <farosas@suse.de>
2023-03-06 18:08:14 -03:00
Nikolay Borisov
9e086f2e2a tests/qtest: migration-test: Add tests for fixed-ram file-based migration
Add basic tests for 'fixed-ram' migration.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Fabiano Rosas <farosas@suse.com>
2023-03-06 18:01:25 -03:00
Nikolay Borisov
cc57d6c75f migration: Add support for 'fixed-ram' migration restore
Add the necessary code to parse the format changes for 'fixed-ram'
capability. One of the more notable changes in behavior is that in the
'fixed-ram' case ram pages are restored in one go rather than constantly
looping through the migration stream. Also due to idiosyncrasies of the
format I have added the 'ram_migrated' since it was easier to simply
return directly from ->load_state rather than introducing more
conditionals around the code to prevent ->load_state being called
multiple times (from
qemu_loadvm_section_start_full/qemu_loadvm_section_part_end i.e. from
multiple QEMU_VM_SECTION_(PART|END) flags).

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
2023-03-06 17:58:44 -03:00
Nikolay Borisov
c204cfeeb7 migration: Refactor precopy ram loading code
To facilitate easier implementaiton of the 'fixed-ram' migration restore
factor out the code responsible for parsing the ramblocks headers. This
also makes ram_load_precopy easier to comprehend.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
2023-03-06 17:53:51 -03:00
Nikolay Borisov
d5cd94bbaf migration/ram: Introduce 'fixed-ram' migration stream capability
Implement 'fixed-ram' feature. The core of the feature is to ensure that
each ram page of the migration stream has a specific offset in the
resulting migration stream. The reason why we'd want such behavior are
two fold:

 - When doing a 'fixed-ram' migration the resulting file will have a
   bounded size, since pages which are dirtied multiple times will
   always go to a fixed location in the file, rather than constantly
   being added to a sequential stream. This eliminates cases where a vm
   with, say, 1g of ram can result in a migration file that's 10s of
   Gbs, provided that the workload constantly redirties memory.

 - It paves the way to implement DIO-enabled save/restore of the
   migration stream as the pages are ensured to be written at aligned
   offsets.

The features requires changing the format. First, a bitmap is introduced
which tracks which pages have been written (i.e are dirtied) during
migration and subsequently it's being written in the resultin file,
again at a fixed location for every ramblock. Zero pages are ignored as
they'd be zero in the destination migration as well. With the changed
format data would look like the following:

|name len|name|used_len|pc*|bitmap_size|pages_offset|bitmap|pages|

* pc - refers to the page_size/mr->addr members, so newly added members
begin from "bitmap_size".

This layout is initialized during ram_save_setup so instead of having a
sequential stream of pages that follow the ramblock headers the dirty
pages for a ramblock follow its header. Since all pages have a fixed
location RAM_SAVE_FLAG_EOS is no longer generated on every migration
iteration but there is effectively a single RAM_SAVE_FLAG_EOS right at
the end.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
2023-03-06 17:50:31 -03:00
Fabiano Rosas
4c2f145632 fixup! io: Add generic pwritev/preadv interface 2023-03-06 17:46:00 -03:00
Fabiano Rosas
fb56e2387b migration: Add qemu_get/set_buffer_at
Restoring a 'fixed-ram' enabled migration stream would require reading
from specific offsets in the file so add a helper to QEMUFile that uses
the newly introduced qio_channel_file_preadv.

Signed-off-by: Fabiano Rosas <farosas@suse.com>
---
restructured to use qio_channel_file_preadv instead of the _full
variant
2023-03-06 17:43:23 -03:00
Nikolay Borisov
5686566113 migration/qemu-file: add utility methods for working with seekable channels
Add utility methods that will be needed when implementing 'fixed-ram'
migration capability.

qemu_file_is_seekable
qemu_put_buffer_at
qemu_set_offset
qemu_get_offset

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
---
(farosas) fixed total_transferred accounting
2023-03-06 16:37:35 -03:00
Nikolay Borisov
4c16cca0e1 io: implement io_pwritev/preadv for QIOChannelFile
The upcoming 'fixed-ram' feature will require qemu to write data to
(and restore from) specific offsets of the migration file.

Add a minimal implementation of pwritev/preadv and expose them via the
io_pwritev and io_preadv interfaces.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Fabiano Rosas <farosas@suse.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2023-03-06 16:34:04 -03:00
Nikolay Borisov
895c40ce0a io: Add generic pwritev/preadv interface
Introduce basic pwritev/preadv support in the generic channel layer.
Specific implementation will follow for the file channel as this is
required in order to support migration streams with fixed location of
each ram page.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
2023-03-06 16:26:01 -03:00
Nikolay Borisov
cad3bc2be3 io: add and implement QIO_CHANNEL_FEATURE_SEEKABLE for channel file
Add a generic QIOChannel feature SEEKABLE which would be used by the
qemu_file* apis. For the time being this will be only implemented for
file channels.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2023-03-06 16:07:38 -03:00
Nikolay Borisov
ea1efd3d17 migration: Initial support of fixed-ram feature for analyze-migration.py
In order to allow analyze-migration.py script to work with migration
streams that have the 'fixed-ram' capability set it's required to have
access to the stream's configuration object. This commit enables this
by making migration json writer part of MigrationState struct, allowing
the configuration object be serialized to json.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
2023-03-06 16:07:38 -03:00
Nikolay Borisov
3ce4e2e8d5 tests/qtest: migration-test: Add tests for file-based migration
Add basic tests for file-based migration.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
---
(farosas) fix segfault when connect_uri is not set
2023-03-06 16:07:38 -03:00
Nikolay Borisov
c1eef47d79 tests/qtest: migration: Add migrate_incoming_qmp helper
file-based migration requires the target to initiate its migration after
the source has finished writing out the data in the file. Currently
there's no easy way to initiate 'migrate-incoming', allow this by
introducing migrate_incoming_qmp helper, similarly to migrate_qmp.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Fabiano Rosas <farosas@suse.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2023-03-06 16:07:38 -03:00
Nikolay Borisov
80f68f67a9 migration: Add support for 'file:' uri for incoming migration
This is a counterpart to the 'file:' uri support for source migration,
now a file can also serve as the source of an incoming migration.

Unlike other migration protocol backends, the 'file' protocol cannot
honour non-blocking mode. POSIX file/block storage will always report
ready to read/write, regardless of how slow the underlying storage
will be at servicing the request.

For incoming migration this limitation may result in the main event
loop not being fully responsive while loading the VM state. This
won't impact the VM since it is not running at this phase, however,
it may impact management applications.

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
2023-03-06 15:20:04 -03:00
Nikolay Borisov
4ed18df9df migration: support file: uri for source migration
Implement support for a "file:" uri so that a migration can be initiated
directly to a file from QEMU.

Unlike other migration protocol backends, the 'file' protocol cannot
honour non-blocking mode. POSIX file/block storage will always report
ready to read/write, regardless of how slow the underlying storage
will be at servicing the request.

For outgoing migration this limitation is not a serious problem as
the migration data transfer always happens in a dedicated thread.
It may, however, result in delays in honouring a request to cancel
the migration operation.

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
2023-03-06 15:20:04 -03:00
921 changed files with 15871 additions and 38993 deletions

111
.cirrus.yml Normal file
View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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
View 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

View 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/*

View File

@@ -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

View File

@@ -15,7 +15,6 @@ RUN apt update \
ca-certificates \
git \
make \
python3 \
wget \
&& \
\

View File

@@ -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'

View File

@@ -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

View File

@@ -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>

View File

@@ -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/

View File

@@ -1 +1 @@
8.0.2
7.2.50

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);

View File

@@ -11,7 +11,6 @@
*/
#include "qemu/osdep.h"
#include "exec/tb-flush.h"
#include "exec/exec-all.h"
void tb_flush(CPUState *cpu)

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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"

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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);
}
}
}

View File

@@ -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. */

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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();

View File

@@ -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));

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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 = {

View File

@@ -1,6 +1,5 @@
softmmu_ss.add([files(
'cryptodev-builtin.c',
'cryptodev-hmp-cmds.c',
'cryptodev.c',
'hostmem-ram.c',
'hostmem.c',

View File

@@ -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
View File

@@ -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();

View File

@@ -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)

View File

@@ -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,
};

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View 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;
}

View File

@@ -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 */

View File

@@ -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,
};

View File

@@ -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,
};

View File

@@ -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
}

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -762,6 +762,7 @@ static BlockDriver bdrv_replication = {
.is_filter = true,
.has_variable_length = true,
.strong_runtime_opts = replication_strong_runtime_opts,
};

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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"

View File

@@ -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;
}
{

View File

@@ -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;

View File

@@ -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"

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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
View File

@@ -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

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,5 +0,0 @@
#
# Some Facebook contributors also occasionally use personal email addresses.
#
peter@pjd.dev

View File

@@ -12,4 +12,3 @@ jcfaracco@gmail.com
joel@jms.id.au
sjitindarsingh@gmail.com
tommusta@gmail.com
idan.horowitz@gmail.com

View File

@@ -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
View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -56,10 +56,8 @@
[machine]
type = "virt"
gic-version = "host"
[accel]
accel = "kvm"
gic-version = "host"
[memory]
size = "1024"

View File

@@ -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