Compare commits
106
Commits
v4.1.0
..
stable-4.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23967e5b2a | ||
|
|
a678cd4d30 | ||
|
|
6341bef468 | ||
|
|
35d6458d6a | ||
|
|
306ecc0d24 | ||
|
|
1e821a0abc | ||
|
|
96389e9061 | ||
|
|
535b8d00c1 | ||
|
|
a81a7fc22e | ||
|
|
b65e78320b | ||
|
|
4f1c6cb2f9 | ||
|
|
a8f24b6bdf | ||
|
|
b27192be13 | ||
|
|
c2e03e2aa4 | ||
|
|
4e5fe75422 | ||
|
|
6739c97bde | ||
|
|
deea66dc61 | ||
|
|
076796fd39 | ||
|
|
2aba40a2c8 | ||
|
|
06b178eb61 | ||
|
|
c4134c9c46 | ||
|
|
b9405afb09 | ||
|
|
6cb3e9e4f1 | ||
|
|
c24d971c13 | ||
|
|
ce9c8f6767 | ||
|
|
e40124c487 | ||
|
|
491bf15671 | ||
|
|
f949655dd3 | ||
|
|
89e4faa9ca | ||
|
|
43143d5d91 | ||
|
|
88a2ea5a48 | ||
|
|
83f9b84c8b | ||
|
|
434a15214f | ||
|
|
0570d468b7 | ||
|
|
53c641048e | ||
|
|
cb7630af20 | ||
|
|
107018c4fd | ||
|
|
7d4b467790 | ||
|
|
5a35dbf228 | ||
|
|
d65d02614b | ||
|
|
f69d8f2347 | ||
|
|
fc5c701636 | ||
|
|
c430d7684e | ||
|
|
70353442db | ||
|
|
872b7b8ef9 | ||
|
|
54d45c8251 | ||
|
|
87851171b4 | ||
|
|
3f6c00eb61 | ||
|
|
0b55b27908 | ||
|
|
6210ff6aa2 | ||
|
|
0647727e47 | ||
|
|
d7e9b19f0b | ||
|
|
c4ac494578 | ||
|
|
f18bce29e1 | ||
|
|
8e20acad63 | ||
|
|
d0444b1ee3 | ||
|
|
b50aab6b83 | ||
|
|
2c743c8522 | ||
|
|
04e35fe3c4 | ||
|
|
912440beb5 | ||
|
|
eeb25956e7 | ||
|
|
d25b37247d | ||
|
|
5ad70231d3 | ||
|
|
804a0ae6c0 | ||
|
|
255325da13 | ||
|
|
e11cd43f24 | ||
|
|
22a03c48e7 | ||
|
|
e653d5ed18 | ||
|
|
a6fe4a3aa8 | ||
|
|
e86e620656 | ||
|
|
32e8ac8a28 | ||
|
|
8da804f4f9 | ||
|
|
7427060f98 | ||
|
|
41e1564fb5 | ||
|
|
8e29c657ca | ||
|
|
92fa1b1a28 | ||
|
|
75f83e7c4a | ||
|
|
b6159fc9a6 | ||
|
|
da3bd13802 | ||
|
|
fd72de9047 | ||
|
|
14c9bbab09 | ||
|
|
1cf90f8a97 | ||
|
|
3a87d07722 | ||
|
|
07cc0a207f | ||
|
|
32097f14fc | ||
|
|
2ab69df8db | ||
|
|
c7b4a73541 | ||
|
|
94a14e6f2a | ||
|
|
7415a83e9b | ||
|
|
627fadfa1c | ||
|
|
2429dc4eea | ||
|
|
f8d98e2b6d | ||
|
|
d8328a3ca5 | ||
|
|
241d89b760 | ||
|
|
665218cc08 | ||
|
|
a68ab7c88f | ||
|
|
ffabb55ec2 | ||
|
|
2974d63658 | ||
|
|
da436b77d8 | ||
|
|
48025d942e | ||
|
|
626a95f4aa | ||
|
|
774f013111 | ||
|
|
173e30de4c | ||
|
|
4382e8da22 | ||
|
|
e628c14be4 | ||
|
|
5669ef1e6c |
No files matched your search
+2
-2
@@ -7,7 +7,7 @@ freebsd_12_task:
|
||||
cpu: 8
|
||||
memory: 8G
|
||||
install_script: pkg install -y
|
||||
bash bison curl cyrus-sasl git glib gmake gnutls gsed
|
||||
bison curl cyrus-sasl git glib gmake gnutls
|
||||
nettle perl5 pixman pkgconf png usbredir
|
||||
script:
|
||||
- mkdir build
|
||||
@@ -20,7 +20,7 @@ macos_task:
|
||||
osx_instance:
|
||||
image: mojave-base
|
||||
install_script:
|
||||
- brew install pkg-config python gnu-sed glib pixman make sdl2
|
||||
- brew install pkg-config python glib pixman make sdl2
|
||||
script:
|
||||
- ./configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
|
||||
- gmake -j$(sysctl -n hw.ncpu)
|
||||
|
||||
@@ -26,15 +26,6 @@ file_type_emacs = makefile
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.sh]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{s,S}]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
file_type_emacs = asm
|
||||
|
||||
[*.{vert,frag}]
|
||||
file_type_emacs = glsl
|
||||
|
||||
|
||||
@@ -97,7 +97,6 @@
|
||||
*.gcno
|
||||
*.gcov
|
||||
/pc-bios/bios-pq/status
|
||||
/pc-bios/edk2-*.fd
|
||||
/pc-bios/vgabios-pq/status
|
||||
/pc-bios/optionrom/linuxboot.asm
|
||||
/pc-bios/optionrom/linuxboot.bin
|
||||
|
||||
@@ -71,18 +71,3 @@ build-clang:
|
||||
ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user"
|
||||
- make -j2
|
||||
- make -j2 check
|
||||
|
||||
build-tci:
|
||||
script:
|
||||
- TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64"
|
||||
- ./configure --enable-tcg-interpreter
|
||||
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
|
||||
- make -j2
|
||||
- make tests/boot-serial-test tests/cdrom-test tests/pxe-test
|
||||
- for tg in $TARGETS ; do
|
||||
export QTEST_QEMU_BINARY="${tg}-softmmu/qemu-system-${tg}" ;
|
||||
./tests/boot-serial-test || exit 1 ;
|
||||
./tests/cdrom-test || exit 1 ;
|
||||
done
|
||||
- QTEST_QEMU_BINARY="x86_64-softmmu/qemu-system-x86_64" ./tests/pxe-test
|
||||
- QTEST_QEMU_BINARY="s390x-softmmu/qemu-system-s390x" ./tests/pxe-test -m slow
|
||||
+4
-10
@@ -39,22 +39,16 @@
|
||||
url = https://git.qemu.org/git/capstone.git
|
||||
[submodule "roms/seabios-hppa"]
|
||||
path = roms/seabios-hppa
|
||||
url = https://git.qemu.org/git/seabios-hppa.git
|
||||
url = https://github.com/hdeller/seabios-hppa.git
|
||||
[submodule "roms/u-boot-sam460ex"]
|
||||
path = roms/u-boot-sam460ex
|
||||
url = https://git.qemu.org/git/u-boot-sam460ex.git
|
||||
[submodule "tests/fp/berkeley-testfloat-3"]
|
||||
path = tests/fp/berkeley-testfloat-3
|
||||
url = https://git.qemu.org/git/berkeley-testfloat-3.git
|
||||
url = https://github.com/cota/berkeley-testfloat-3
|
||||
[submodule "tests/fp/berkeley-softfloat-3"]
|
||||
path = tests/fp/berkeley-softfloat-3
|
||||
url = https://git.qemu.org/git/berkeley-softfloat-3.git
|
||||
url = https://github.com/cota/berkeley-softfloat-3
|
||||
[submodule "roms/edk2"]
|
||||
path = roms/edk2
|
||||
url = https://git.qemu.org/git/edk2.git
|
||||
[submodule "slirp"]
|
||||
path = slirp
|
||||
url = https://git.qemu.org/git/libslirp.git
|
||||
[submodule "roms/opensbi"]
|
||||
path = roms/opensbi
|
||||
url = https://git.qemu.org/git/opensbi.git
|
||||
url = https://github.com/tianocore/edk2.git
|
||||
-302
@@ -1,302 +0,0 @@
|
||||
---
|
||||
# Note: this file is still unused. It serves as a documentation for the
|
||||
# Patchew configuration in case patchew.org disappears or has to be
|
||||
# reinstalled.
|
||||
#
|
||||
# Patchew configuration is available to project administrators at
|
||||
# https://patchew.org/api/v1/projects/1/config/ and can be configured
|
||||
# to YAML using the following Python script:
|
||||
#
|
||||
# import json
|
||||
# import sys
|
||||
# import ruamel.yaml
|
||||
#
|
||||
# json_str = sys.stdin.read()
|
||||
# yaml = ruamel.yaml.YAML()
|
||||
# yaml.explicit_start = True
|
||||
# data = json.loads(json_str, object_pairs_hook=ruamel.yaml.comments.CommentedMap)
|
||||
# ruamel.yaml.scalarstring.walk_tree(data)
|
||||
# yaml.dump(data, sys.stdout)
|
||||
|
||||
email:
|
||||
notifications:
|
||||
timeouts:
|
||||
event: TestingReport
|
||||
enabled: true
|
||||
to_user: false
|
||||
reply_subject: true
|
||||
set_reply_to: true
|
||||
in_reply_to: true
|
||||
reply_to_all: false
|
||||
subject_template: none
|
||||
to: fam@euphon.net
|
||||
cc: ''
|
||||
body_template: |
|
||||
{% if not is_timeout %} {{ cancel }} {% endif %}
|
||||
|
||||
Test '{{ test }}' timeout, log:
|
||||
|
||||
{{ log }}
|
||||
ENOSPC:
|
||||
event: TestingReport
|
||||
enabled: true
|
||||
to_user: false
|
||||
reply_subject: false
|
||||
set_reply_to: false
|
||||
in_reply_to: true
|
||||
reply_to_all: false
|
||||
subject_template: Out of space error
|
||||
to: fam@euphon.net
|
||||
cc: ''
|
||||
body_template: |
|
||||
{% if passed %}
|
||||
{{ cancel }}
|
||||
{% endif %}
|
||||
|
||||
{% if 'No space left on device' in log %}
|
||||
Tester {{ tester }} out of space when running {{ test }}
|
||||
|
||||
{{ log }}
|
||||
{% else %}
|
||||
{{ cancel }}
|
||||
{% endif %}
|
||||
FailureShort:
|
||||
event: TestingReport
|
||||
enabled: true
|
||||
to_user: false
|
||||
reply_subject: true
|
||||
set_reply_to: true
|
||||
in_reply_to: true
|
||||
reply_to_all: true
|
||||
subject_template: Testing failed
|
||||
to: ''
|
||||
cc: ''
|
||||
body_template: |
|
||||
{% if passed or not obj.message_id or is_timeout %}
|
||||
{{ cancel }}
|
||||
{% endif %}
|
||||
{% if 'No space left on device' in log %}
|
||||
{{ cancel }}
|
||||
{% endif %}
|
||||
Patchew URL: https://patchew.org/QEMU/{{ obj.message_id }}/
|
||||
|
||||
{% ansi2text log as logtext %}
|
||||
{% if test == "checkpatch" %}
|
||||
Hi,
|
||||
|
||||
This series seems to have some coding style problems. See output below for
|
||||
more information:
|
||||
|
||||
{{ logtext }}
|
||||
{% elif test == "docker-mingw@fedora" or test == "docker-quick@centos7" or test == "asan" %}
|
||||
Hi,
|
||||
|
||||
This series failed the {{ test }} build test. Please find the testing commands and
|
||||
their output below. If you have Docker installed, you can probably reproduce it
|
||||
locally.
|
||||
|
||||
{% lines_between logtext start="^=== TEST SCRIPT BEGIN ===$" stop="^=== TEST SCRIPT END ===$" %}
|
||||
{% lines_between logtext start="^=== OUTPUT BEGIN ===$" stop="=== OUTPUT END ===$" as output %}
|
||||
{% grep_C output regex="\b(FAIL|XPASS|ERROR|WARN|error:|warning:)" n=3 %}
|
||||
{% elif test == "s390x" or test == "FreeBSD" or test == "ppcle" or test == "ppcbe" %}
|
||||
Hi,
|
||||
|
||||
This series failed build test on {{test}} host. Please find the details below.
|
||||
|
||||
{% lines_between logtext start="^=== TEST SCRIPT BEGIN ===$" stop="^=== TEST SCRIPT END ===$" %}
|
||||
{% lines_between logtext start="^=== OUTPUT BEGIN ===$" stop="=== OUTPUT END ===$" as output %}
|
||||
{% grep_C output regex="\b(FAIL|XPASS|ERROR|WARN|error:|warning:)" n=3 %}
|
||||
{% else %}
|
||||
{{ cancel }}
|
||||
{% endif %}
|
||||
|
||||
The full log is available at
|
||||
{{ log_url }}.
|
||||
---
|
||||
Email generated automatically by Patchew [https://patchew.org/].
|
||||
Please send your feedback to patchew-devel@redhat.com
|
||||
testing:
|
||||
tests:
|
||||
asan:
|
||||
enabled: true
|
||||
requirements: docker
|
||||
timeout: 3600
|
||||
script: |
|
||||
#!/bin/bash
|
||||
time make docker-test-debug@fedora TARGET_LIST=x86_64-softmmu J=14 NETWORK=1
|
||||
docker-quick@centos7:
|
||||
enabled: false
|
||||
requirements: docker,x86_64
|
||||
timeout: 3600
|
||||
script: |
|
||||
#!/bin/bash
|
||||
time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
|
||||
checkpatch:
|
||||
enabled: true
|
||||
requirements: ''
|
||||
timeout: 600
|
||||
script: |
|
||||
#!/bin/bash
|
||||
git rev-parse base > /dev/null || exit 0
|
||||
git config --local diff.renamelimit 0
|
||||
git config --local diff.renames True
|
||||
git config --local diff.algorithm histogram
|
||||
./scripts/checkpatch.pl --mailback base..
|
||||
docker-mingw@fedora:
|
||||
enabled: true
|
||||
requirements: docker,x86_64
|
||||
timeout: 3600
|
||||
script: |
|
||||
#! /bin/bash
|
||||
test "$(uname -m)" = "x86_64"
|
||||
ppcle:
|
||||
enabled: false
|
||||
requirements: ppcle
|
||||
timeout: 3600
|
||||
script: |
|
||||
#!/bin/bash
|
||||
# Testing script will be invoked under the git checkout with
|
||||
# HEAD pointing to a commit that has the patches applied on top of "base"
|
||||
# branch
|
||||
set -e
|
||||
CC=$HOME/bin/cc
|
||||
INSTALL=$PWD/install
|
||||
BUILD=$PWD/build
|
||||
mkdir -p $BUILD $INSTALL
|
||||
SRC=$PWD
|
||||
cd $BUILD
|
||||
$SRC/configure --cc=$CC --prefix=$INSTALL
|
||||
make -j4
|
||||
# XXX: we need reliable clean up
|
||||
# make check -j4 V=1
|
||||
make install
|
||||
|
||||
echo
|
||||
echo "=== ENV ==="
|
||||
env
|
||||
|
||||
echo
|
||||
echo "=== PACKAGES ==="
|
||||
rpm -qa
|
||||
ppcbe:
|
||||
enabled: false
|
||||
requirements: ppcbe
|
||||
timeout: 3600
|
||||
script: |
|
||||
#!/bin/bash
|
||||
# Testing script will be invoked under the git checkout with
|
||||
# HEAD pointing to a commit that has the patches applied on top of "base"
|
||||
# branch
|
||||
set -e
|
||||
CC=$HOME/bin/cc
|
||||
INSTALL=$PWD/install
|
||||
BUILD=$PWD/build
|
||||
mkdir -p $BUILD $INSTALL
|
||||
SRC=$PWD
|
||||
cd $BUILD
|
||||
$SRC/configure --cc=$CC --prefix=$INSTALL
|
||||
make -j4
|
||||
# XXX: we need reliable clean up
|
||||
# make check -j4 V=1
|
||||
make install
|
||||
|
||||
echo
|
||||
echo "=== ENV ==="
|
||||
env
|
||||
|
||||
echo
|
||||
echo "=== PACKAGES ==="
|
||||
rpm -qa
|
||||
FreeBSD:
|
||||
enabled: true
|
||||
requirements: qemu-x86,x86_64,git
|
||||
timeout: 3600
|
||||
script: |
|
||||
#!/bin/bash
|
||||
# Testing script will be invoked under the git checkout with
|
||||
# HEAD pointing to a commit that has the patches applied on top of "base"
|
||||
# branch
|
||||
if qemu-system-x86_64 --help >/dev/null 2>&1; then
|
||||
QEMU=qemu-system-x86_64
|
||||
elif /usr/libexec/qemu-kvm --help >/dev/null 2>&1; then
|
||||
QEMU=/usr/libexec/qemu-kvm
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
make vm-build-freebsd J=21 QEMU=$QEMU
|
||||
exit 0
|
||||
docker-clang@ubuntu:
|
||||
enabled: true
|
||||
requirements: docker,x86_64
|
||||
timeout: 3600
|
||||
script: |
|
||||
#!/bin/bash
|
||||
time make docker-test-clang@ubuntu SHOW_ENV=1 J=14 NETWORK=1
|
||||
s390x:
|
||||
enabled: true
|
||||
requirements: s390x
|
||||
timeout: 3600
|
||||
script: |
|
||||
#!/bin/bash
|
||||
# Testing script will be invoked under the git checkout with
|
||||
# HEAD pointing to a commit that has the patches applied on top of "base"
|
||||
# branch
|
||||
set -e
|
||||
CC=$HOME/bin/cc
|
||||
INSTALL=$PWD/install
|
||||
BUILD=$PWD/build
|
||||
mkdir -p $BUILD $INSTALL
|
||||
SRC=$PWD
|
||||
cd $BUILD
|
||||
$SRC/configure --cc=$CC --prefix=$INSTALL
|
||||
make -j4
|
||||
# XXX: we need reliable clean up
|
||||
# make check -j4 V=1
|
||||
make install
|
||||
|
||||
echo
|
||||
echo "=== ENV ==="
|
||||
env
|
||||
|
||||
echo
|
||||
echo "=== PACKAGES ==="
|
||||
rpm -qa
|
||||
requirements:
|
||||
x86_64:
|
||||
script: |
|
||||
#! /bin/bash
|
||||
test "$(uname -m)" = "x86_64"
|
||||
qemu-x86:
|
||||
script: |
|
||||
#!/bin/bash
|
||||
if qemu-system-x86_64 --help >/dev/null 2>&1; then
|
||||
:
|
||||
elif /usr/libexec/qemu-kvm --help >/dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
ppcle:
|
||||
script: |
|
||||
#!/bin/bash
|
||||
test "$(uname -m)" = "ppc64le"
|
||||
ppcbe:
|
||||
script: |
|
||||
#!/bin/bash
|
||||
test "$(uname -m)" = "ppc64"
|
||||
git:
|
||||
script: |
|
||||
#! /bin/bash
|
||||
git config user.name > /dev/null 2>&1
|
||||
docker:
|
||||
script: |
|
||||
#!/bin/bash
|
||||
docker ps || sudo -n docker ps
|
||||
s390x:
|
||||
script: |
|
||||
#!/bin/bash
|
||||
test "$(uname -m)" = "s390x"
|
||||
git:
|
||||
push_to: git@github.com:patchew-project/qemu
|
||||
public_repo: https://github.com/patchew-project/qemu
|
||||
url_template: https://github.com/patchew-project/qemu/tree/%t
|
||||
+5
-4
@@ -7,10 +7,11 @@ env:
|
||||
matrix:
|
||||
- IMAGE=debian-amd64
|
||||
TARGET_LIST=x86_64-softmmu,x86_64-linux-user
|
||||
- IMAGE=debian-win32-cross
|
||||
TARGET_LIST=arm-softmmu,i386-softmmu,lm32-softmmu
|
||||
- IMAGE=debian-win64-cross
|
||||
TARGET_LIST=aarch64-softmmu,sparc64-softmmu,x86_64-softmmu
|
||||
# currently disabled as the mxe.cc repos are down
|
||||
# - IMAGE=debian-win32-cross
|
||||
# TARGET_LIST=arm-softmmu,i386-softmmu,lm32-softmmu
|
||||
# - IMAGE=debian-win64-cross
|
||||
# TARGET_LIST=aarch64-softmmu,sparc64-softmmu,x86_64-softmmu
|
||||
- IMAGE=debian-armel-cross
|
||||
TARGET_LIST=arm-softmmu,arm-linux-user,armeb-linux-user
|
||||
- IMAGE=debian-armhf-cross
|
||||
|
||||
+12
-23
@@ -31,7 +31,7 @@ addons:
|
||||
- libseccomp-dev
|
||||
- libspice-protocol-dev
|
||||
- libspice-server-dev
|
||||
- libssh-dev
|
||||
- libssh2-1-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvte-2.91-dev
|
||||
@@ -42,8 +42,6 @@ addons:
|
||||
packages:
|
||||
- glib
|
||||
- pixman
|
||||
- gnu-sed
|
||||
update: true
|
||||
|
||||
|
||||
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
|
||||
@@ -75,13 +73,13 @@ before_script:
|
||||
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
|
||||
- ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
|
||||
script:
|
||||
- make -j3 && travis_retry ${TEST_CMD}
|
||||
- make -j3 && ${TEST_CMD}
|
||||
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env:
|
||||
- CONFIG="--disable-system --static"
|
||||
- CONFIG="--disable-system"
|
||||
|
||||
|
||||
# we split the system builds as it takes a while to build them all
|
||||
@@ -153,13 +151,6 @@ matrix:
|
||||
compiler: clang
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} "
|
||||
compiler: clang
|
||||
before_script:
|
||||
- ./configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
|
||||
compiler: clang
|
||||
@@ -232,10 +223,8 @@ matrix:
|
||||
|
||||
# Acceptance (Functional) tests
|
||||
- env:
|
||||
- CONFIG="--python=/usr/bin/python3 --target-list=x86_64-softmmu,mips-softmmu,mips64el-softmmu,aarch64-softmmu,arm-softmmu,s390x-softmmu,alpha-softmmu"
|
||||
- TEST_CMD="make check-acceptance"
|
||||
after_failure:
|
||||
- cat tests/results/latest/job.log
|
||||
- CONFIG="--python=/usr/bin/python3 --target-list=x86_64-softmmu"
|
||||
- TEST_CMD="make AVOCADO_SHOW=app check-acceptance"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
@@ -250,8 +239,8 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
# Extra toolchains
|
||||
- gcc-9
|
||||
- g++-9
|
||||
- gcc-7
|
||||
- g++-7
|
||||
# Build dependencies
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
@@ -271,7 +260,7 @@ matrix:
|
||||
- libseccomp-dev
|
||||
- libspice-protocol-dev
|
||||
- libspice-server-dev
|
||||
- libssh-dev
|
||||
- libssh2-1-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvte-2.91-dev
|
||||
@@ -280,11 +269,11 @@ matrix:
|
||||
language: generic
|
||||
compiler: none
|
||||
env:
|
||||
- COMPILER_NAME=gcc CXX=g++-9 CC=gcc-9
|
||||
- CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-pie --disable-linux-user"
|
||||
- COMPILER_NAME=gcc CXX=g++-7 CC=gcc-7
|
||||
- CONFIG="--cc=gcc-7 --cxx=g++-7 --disable-pie --disable-linux-user"
|
||||
- TEST_CMD=""
|
||||
before_script:
|
||||
- ./configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
|
||||
- ./configure ${CONFIG} --extra-cflags="-g3 -O0 -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
|
||||
|
||||
|
||||
# Run check-tcg against linux-user
|
||||
@@ -294,5 +283,5 @@ matrix:
|
||||
|
||||
# Run check-tcg against softmmu targets
|
||||
- env:
|
||||
- CONFIG="--target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu"
|
||||
- CONFIG="--target-list=xtensa-softmmu,arm-softmmu"
|
||||
- TEST_CMD="make -j3 check-tcg V=1"
|
||||
+4
-43
@@ -29,45 +29,6 @@ Spaces of course are superior to tabs because:
|
||||
|
||||
Do not leave whitespace dangling off the ends of lines.
|
||||
|
||||
1.1 Multiline Indent
|
||||
|
||||
There are several places where indent is necessary:
|
||||
|
||||
- if/else
|
||||
- while/for
|
||||
- function definition & call
|
||||
|
||||
When breaking up a long line to fit within line width, we need a proper indent
|
||||
for the following lines.
|
||||
|
||||
In case of if/else, while/for, align the secondary lines just after the
|
||||
opening parenthesis of the first.
|
||||
|
||||
For example:
|
||||
|
||||
if (a == 1 &&
|
||||
b == 2) {
|
||||
|
||||
while (a == 1 &&
|
||||
b == 2) {
|
||||
|
||||
In case of function, there are several variants:
|
||||
|
||||
* 4 spaces indent from the beginning
|
||||
* align the secondary lines just after the opening parenthesis of the
|
||||
first
|
||||
|
||||
For example:
|
||||
|
||||
do_something(x, y,
|
||||
z);
|
||||
|
||||
do_something(x, y,
|
||||
z);
|
||||
|
||||
do_something(x, do_another(y,
|
||||
z));
|
||||
|
||||
2. Line width
|
||||
|
||||
Lines should be 80 characters; try not to make them longer.
|
||||
@@ -147,10 +108,10 @@ block to a separate function altogether.
|
||||
When comparing a variable for (in)equality with a constant, list the
|
||||
constant on the right, as in:
|
||||
|
||||
if (a == 1) {
|
||||
/* Reads like: "If a equals 1" */
|
||||
do_something();
|
||||
}
|
||||
if (a == 1) {
|
||||
/* Reads like: "If a equals 1" */
|
||||
do_something();
|
||||
}
|
||||
|
||||
Rationale: Yoda conditions (as in 'if (1 == a)') are awkward to read.
|
||||
Besides, good compilers already warn users when '==' is mis-typed as '=',
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
The QEMU distribution includes both the QEMU emulator and
|
||||
various firmware files. These are separate programs that are
|
||||
distributed together for our users' convenience, and they have
|
||||
separate licenses.
|
||||
The following points clarify the QEMU license:
|
||||
|
||||
The following points clarify the license of the QEMU emulator:
|
||||
1) QEMU as a whole is released under the GNU General Public License,
|
||||
version 2.
|
||||
|
||||
1) The QEMU emulator as a whole is released under the GNU General
|
||||
Public License, version 2.
|
||||
|
||||
2) Parts of the QEMU emulator have specific licenses which are compatible
|
||||
with the GNU General Public License, version 2. Hence each source file
|
||||
contains its own licensing information. Source files with no licensing
|
||||
information are released under the GNU General Public License, version
|
||||
2 or (at your option) any later version.
|
||||
2) Parts of QEMU have specific licenses which are compatible with the
|
||||
GNU General Public License, version 2. Hence each source file contains
|
||||
its own licensing information. Source files with no licensing information
|
||||
are released under the GNU General Public License, version 2 or (at your
|
||||
option) any later version.
|
||||
|
||||
As of July 2013, contributions under version 2 of the GNU General Public
|
||||
License (and no later version) are only accepted for the following files
|
||||
|
||||
+95
-162
@@ -65,7 +65,7 @@ F: *
|
||||
F: */
|
||||
|
||||
Responsible Disclosure, Reporting Security Issues
|
||||
-------------------------------------------------
|
||||
------------------------------
|
||||
W: https://wiki.qemu.org/SecurityProcess
|
||||
M: Michael S. Tsirkin <mst@redhat.com>
|
||||
L: secalert@redhat.com
|
||||
@@ -83,7 +83,7 @@ T: git https://github.com/vivier/qemu.git trivial-patches
|
||||
|
||||
Architecture support
|
||||
--------------------
|
||||
S390 general architecture support
|
||||
S390
|
||||
M: Cornelia Huck <cohuck@redhat.com>
|
||||
S: Supported
|
||||
F: default-configs/s390x-softmmu.mak
|
||||
@@ -102,14 +102,14 @@ F: pc-bios/s390-ccw/
|
||||
F: pc-bios/s390-ccw.img
|
||||
F: target/s390x/
|
||||
F: docs/vfio-ap.txt
|
||||
F: tests/migration/s390x/
|
||||
K: ^Subject:.*(?i)s390x?
|
||||
T: git https://github.com/cohuck/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
Guest CPU cores (TCG)
|
||||
---------------------
|
||||
Overall TCG CPUs
|
||||
Guest CPU cores (TCG):
|
||||
----------------------
|
||||
Overall
|
||||
L: qemu-devel@nongnu.org
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
R: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Maintained
|
||||
@@ -124,7 +124,6 @@ F: include/exec/exec-all.h
|
||||
F: include/exec/helper*.h
|
||||
F: include/exec/tb-hash.h
|
||||
F: include/sysemu/cpus.h
|
||||
F: include/sysemu/tcg.h
|
||||
|
||||
FPU emulation
|
||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||
@@ -135,14 +134,14 @@ F: fpu/
|
||||
F: include/fpu/
|
||||
F: tests/fp/
|
||||
|
||||
Alpha TCG CPUs
|
||||
Alpha
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
S: Maintained
|
||||
F: target/alpha/
|
||||
F: tests/tcg/alpha/
|
||||
F: disas/alpha.c
|
||||
|
||||
ARM TCG CPUs
|
||||
ARM
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
@@ -163,7 +162,7 @@ S: Maintained
|
||||
F: hw/arm/smmu*
|
||||
F: include/hw/arm/smmu*
|
||||
|
||||
CRIS TCG CPUs
|
||||
CRIS
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
S: Maintained
|
||||
F: target/cris/
|
||||
@@ -172,14 +171,14 @@ F: include/hw/cris/
|
||||
F: tests/tcg/cris/
|
||||
F: disas/cris.c
|
||||
|
||||
HPPA (PA-RISC) TCG CPUs
|
||||
HPPA (PA-RISC)
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
S: Maintained
|
||||
F: target/hppa/
|
||||
F: hw/hppa/
|
||||
F: disas/hppa.c
|
||||
|
||||
LM32 TCG CPUs
|
||||
LM32
|
||||
M: Michael Walle <michael@walle.cc>
|
||||
S: Maintained
|
||||
F: target/lm32/
|
||||
@@ -192,27 +191,29 @@ F: include/hw/char/lm32_juart.h
|
||||
F: include/hw/lm32/
|
||||
F: tests/tcg/lm32/
|
||||
|
||||
M68K TCG CPUs
|
||||
M68K
|
||||
M: Laurent Vivier <laurent@vivier.eu>
|
||||
S: Maintained
|
||||
F: target/m68k/
|
||||
F: disas/m68k.c
|
||||
|
||||
MicroBlaze TCG CPUs
|
||||
MicroBlaze
|
||||
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
S: Maintained
|
||||
F: target/microblaze/
|
||||
F: hw/microblaze/
|
||||
F: disas/microblaze.c
|
||||
|
||||
MIPS TCG CPUs
|
||||
MIPS
|
||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||
M: Aleksandar Markovic <amarkovic@wavecomp.com>
|
||||
R: Aleksandar Rikalo <arikalo@wavecomp.com>
|
||||
S: Maintained
|
||||
F: target/mips/
|
||||
F: default-configs/*mips*
|
||||
F: disas/*mips*
|
||||
F: disas/mips.c
|
||||
F: disas/nanomips.cpp
|
||||
F: disas/nanomips.h
|
||||
F: hw/intc/mips_gic.c
|
||||
F: hw/mips/
|
||||
F: hw/misc/mips_*
|
||||
@@ -224,7 +225,7 @@ F: include/hw/timer/mips_gictimer.h
|
||||
F: tests/tcg/mips/
|
||||
K: ^Subject:.*(?i)mips
|
||||
|
||||
Moxie TCG CPUs
|
||||
Moxie
|
||||
M: Anthony Green <green@moxielogic.com>
|
||||
S: Maintained
|
||||
F: target/moxie/
|
||||
@@ -232,7 +233,7 @@ F: disas/moxie.c
|
||||
F: hw/moxie/
|
||||
F: default-configs/moxie-softmmu.mak
|
||||
|
||||
NiosII TCG CPUs
|
||||
NiosII
|
||||
M: Chris Wulff <crwulff@gmail.com>
|
||||
M: Marek Vasut <marex@denx.de>
|
||||
S: Maintained
|
||||
@@ -242,14 +243,14 @@ F: hw/intc/nios2_iic.c
|
||||
F: disas/nios2.c
|
||||
F: default-configs/nios2-softmmu.mak
|
||||
|
||||
OpenRISC TCG CPUs
|
||||
OpenRISC
|
||||
M: Stafford Horne <shorne@gmail.com>
|
||||
S: Odd Fixes
|
||||
F: target/openrisc/
|
||||
F: hw/openrisc/
|
||||
F: tests/tcg/openrisc/
|
||||
|
||||
PowerPC TCG CPUs
|
||||
PowerPC
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Maintained
|
||||
@@ -258,7 +259,7 @@ F: hw/ppc/
|
||||
F: include/hw/ppc/
|
||||
F: disas/ppc.c
|
||||
|
||||
RISC-V TCG CPUs
|
||||
RISC-V
|
||||
M: Palmer Dabbelt <palmer@sifive.com>
|
||||
M: Alistair Francis <Alistair.Francis@wdc.com>
|
||||
M: Sagar Karandikar <sagark@eecs.berkeley.edu>
|
||||
@@ -271,7 +272,7 @@ F: include/hw/riscv/
|
||||
F: linux-user/host/riscv32/
|
||||
F: linux-user/host/riscv64/
|
||||
|
||||
S390 TCG CPUs
|
||||
S390
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
M: David Hildenbrand <david@redhat.com>
|
||||
S: Maintained
|
||||
@@ -281,7 +282,7 @@ F: disas/s390.c
|
||||
F: tests/tcg/s390x/
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
SH4 TCG CPUs
|
||||
SH4
|
||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||
S: Odd Fixes
|
||||
F: target/sh4/
|
||||
@@ -289,7 +290,7 @@ F: hw/sh4/
|
||||
F: disas/sh4.c
|
||||
F: include/hw/sh4/
|
||||
|
||||
SPARC TCG CPUs
|
||||
SPARC
|
||||
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
|
||||
M: Artyom Tarasenko <atar4qemu@gmail.com>
|
||||
S: Maintained
|
||||
@@ -299,14 +300,14 @@ F: hw/sparc64/
|
||||
F: include/hw/sparc/sparc64.h
|
||||
F: disas/sparc.c
|
||||
|
||||
UniCore32 TCG CPUs
|
||||
UniCore32
|
||||
M: Guan Xuetao <gxt@mprc.pku.edu.cn>
|
||||
S: Maintained
|
||||
F: target/unicore32/
|
||||
F: hw/unicore32/
|
||||
F: include/hw/unicore32/
|
||||
|
||||
X86 TCG CPUs
|
||||
X86
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||
@@ -319,7 +320,7 @@ F: disas/i386.c
|
||||
F: docs/qemu-cpu-models.texi
|
||||
T: git https://github.com/ehabkost/qemu.git x86-next
|
||||
|
||||
Xtensa TCG CPUs
|
||||
Xtensa
|
||||
M: Max Filippov <jcmvbkbc@gmail.com>
|
||||
W: http://wiki.osll.ru/doku.php?id=etc:users:jcmvbkbc:qemu-target-xtensa
|
||||
S: Maintained
|
||||
@@ -330,7 +331,7 @@ F: disas/xtensa.c
|
||||
F: include/hw/xtensa/xtensa-isa.h
|
||||
F: default-configs/xtensa*.mak
|
||||
|
||||
TriCore TCG CPUs
|
||||
TriCore
|
||||
M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
|
||||
S: Maintained
|
||||
F: target/tricore/
|
||||
@@ -342,9 +343,10 @@ M: Alex Bennée <alex.bennee@linaro.org>
|
||||
S: Maintained
|
||||
F: tests/tcg/multiarch/
|
||||
|
||||
Guest CPU Cores (KVM)
|
||||
---------------------
|
||||
Overall KVM CPUs
|
||||
Guest CPU Cores (KVM):
|
||||
----------------------
|
||||
|
||||
Overall
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
L: kvm@vger.kernel.org
|
||||
S: Supported
|
||||
@@ -355,24 +357,24 @@ F: include/hw/kvm/
|
||||
F: include/sysemu/kvm*.h
|
||||
F: scripts/kvm/kvm_flightrecorder
|
||||
|
||||
ARM KVM CPUs
|
||||
ARM
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: target/arm/kvm.c
|
||||
|
||||
MIPS KVM CPUs
|
||||
MIPS
|
||||
M: James Hogan <jhogan@kernel.org>
|
||||
R: Aleksandar Rikalo <arikalo@wavecomp.com>
|
||||
S: Maintained
|
||||
F: target/mips/kvm.c
|
||||
|
||||
PPC KVM CPUs
|
||||
PPC
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
S: Maintained
|
||||
F: target/ppc/kvm.c
|
||||
|
||||
S390 KVM CPUs
|
||||
S390
|
||||
M: Halil Pasic <pasic@linux.ibm.com>
|
||||
M: Cornelia Huck <cohuck@redhat.com>
|
||||
M: Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
@@ -383,8 +385,6 @@ F: target/s390x/kvm-stub.c
|
||||
F: target/s390x/ioinst.[ch]
|
||||
F: target/s390x/machine.c
|
||||
F: target/s390x/sigp.c
|
||||
F: target/s390x/cpu_features*.[ch]
|
||||
F: target/s390x/cpu_models.[ch]
|
||||
F: hw/intc/s390_flic.c
|
||||
F: hw/intc/s390_flic_kvm.c
|
||||
F: include/hw/s390x/s390_flic.h
|
||||
@@ -393,7 +393,7 @@ T: git https://github.com/cohuck/qemu.git s390-next
|
||||
T: git https://github.com/borntraeger/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
X86 KVM CPUs
|
||||
X86
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
M: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
L: kvm@vger.kernel.org
|
||||
@@ -401,16 +401,17 @@ S: Supported
|
||||
F: target/i386/kvm.c
|
||||
F: scripts/kvm/vmxcap
|
||||
|
||||
Guest CPU Cores (Xen)
|
||||
---------------------
|
||||
X86 Xen CPUs
|
||||
Guest CPU Cores (Xen):
|
||||
----------------------
|
||||
|
||||
X86
|
||||
M: Stefano Stabellini <sstabellini@kernel.org>
|
||||
M: Anthony Perard <anthony.perard@citrix.com>
|
||||
M: Paul Durrant <paul.durrant@citrix.com>
|
||||
L: xen-devel@lists.xenproject.org
|
||||
S: Supported
|
||||
F: */xen*
|
||||
F: hw/9pfs/xen-9p*
|
||||
F: hw/9pfs/xen-9p-backend.c
|
||||
F: hw/char/xen_console.c
|
||||
F: hw/display/xenfb.c
|
||||
F: hw/net/xen_nic.c
|
||||
@@ -423,8 +424,9 @@ F: include/hw/block/dataplane/xen*
|
||||
F: include/hw/xen/
|
||||
F: include/sysemu/xen-mapcache.h
|
||||
|
||||
Hosts
|
||||
-----
|
||||
Hosts:
|
||||
------
|
||||
|
||||
LINUX
|
||||
M: Michael S. Tsirkin <mst@redhat.com>
|
||||
M: Cornelia Huck <cohuck@redhat.com>
|
||||
@@ -442,16 +444,19 @@ F: util/*posix*.c
|
||||
F: include/qemu/*posix*.h
|
||||
|
||||
NETBSD
|
||||
L: qemu-devel@nongnu.org
|
||||
M: Kamil Rytarowski <kamil@netbsd.org>
|
||||
S: Maintained
|
||||
K: ^Subject:.*(?i)NetBSD
|
||||
|
||||
OPENBSD
|
||||
L: qemu-devel@nongnu.org
|
||||
M: Brad Smith <brad@comstyle.com>
|
||||
S: Maintained
|
||||
K: ^Subject:.*(?i)OpenBSD
|
||||
|
||||
W32, W64
|
||||
L: qemu-devel@nongnu.org
|
||||
M: Stefan Weil <sw@weilnetz.de>
|
||||
S: Maintained
|
||||
F: *win32*
|
||||
@@ -461,12 +466,10 @@ X: qga/*win32*
|
||||
F: qemu.nsi
|
||||
|
||||
Alpha Machines
|
||||
--------------
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
S: Maintained
|
||||
F: hw/alpha/
|
||||
F: hw/isa/smc37c669-superio.c
|
||||
F: tests/tcg/alpha/system/
|
||||
|
||||
ARM Machines
|
||||
------------
|
||||
@@ -561,6 +564,7 @@ F: include/hw/*/digic*
|
||||
Gumstix
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
R: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
L: qemu-devel@nongnu.org
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/arm/gumstix.c
|
||||
@@ -659,14 +663,10 @@ M: Peter Maydell <peter.maydell@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/arm/nseries.c
|
||||
F: hw/display/blizzard.c
|
||||
F: hw/input/lm832x.c
|
||||
F: hw/input/tsc2005.c
|
||||
F: hw/misc/cbus.c
|
||||
F: hw/timer/twl92230.c
|
||||
F: include/hw/display/blizzard.h
|
||||
F: include/hw/input/tsc2xxx.h
|
||||
F: include/hw/misc/cbus.h
|
||||
|
||||
Palm
|
||||
M: Andrzej Zaborowski <balrogg@gmail.com>
|
||||
@@ -675,7 +675,6 @@ L: qemu-arm@nongnu.org
|
||||
S: Odd Fixes
|
||||
F: hw/arm/palm.c
|
||||
F: hw/input/tsc210x.c
|
||||
F: include/hw/input/tsc2xxx.h
|
||||
|
||||
Raspberry Pi
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
@@ -715,7 +714,6 @@ F: hw/misc/mst_fpga.c
|
||||
F: hw/misc/max111x.c
|
||||
F: include/hw/arm/pxa.h
|
||||
F: include/hw/arm/sharpsl.h
|
||||
F: include/hw/display/tc6393xb.h
|
||||
|
||||
SABRELITE / i.MX6
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
@@ -730,14 +728,6 @@ F: include/hw/arm/fsl-imx6.h
|
||||
F: include/hw/misc/imx6_*.h
|
||||
F: include/hw/ssi/imx_spi.h
|
||||
|
||||
SBSA-REF
|
||||
M: Radoslaw Biernacki <radoslaw.biernacki@linaro.org>
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
R: Leif Lindholm <leif.lindholm@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/arm/sbsa-ref.c
|
||||
|
||||
Sharp SL-5500 (Collie) PDA
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
@@ -750,7 +740,6 @@ M: Peter Maydell <peter.maydell@linaro.org>
|
||||
L: qemu-arm@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/*/stellaris*
|
||||
F: include/hw/input/gamepad.h
|
||||
|
||||
Versatile Express
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
@@ -938,8 +927,6 @@ M: Aurelien Jarno <aurelien@aurel32.net>
|
||||
R: Aleksandar Rikalo <arikalo@wavecomp.com>
|
||||
S: Maintained
|
||||
F: hw/mips/mips_malta.c
|
||||
F: hw/mips/gt64xxx_pci.c
|
||||
F: tests/acceptance/linux_ssh_mips_malta.py
|
||||
|
||||
Mipssim
|
||||
M: Aleksandar Markovic <amarkovic@wavecomp.com>
|
||||
@@ -1048,6 +1035,7 @@ F: pc-bios/qemu_vga.ndrv
|
||||
|
||||
PReP
|
||||
M: Hervé Poussineau <hpoussin@reactos.org>
|
||||
L: qemu-devel@nongnu.org
|
||||
L: qemu-ppc@nongnu.org
|
||||
S: Maintained
|
||||
F: hw/ppc/prep.c
|
||||
@@ -1163,11 +1151,10 @@ F: include/hw/timer/sun4v-rtc.h
|
||||
|
||||
Leon3
|
||||
M: Fabien Chouteau <chouteau@adacore.com>
|
||||
M: KONRAD Frederic <frederic.konrad@adacore.com>
|
||||
S: Maintained
|
||||
F: hw/sparc/leon3.c
|
||||
F: hw/*/grlib*
|
||||
F: include/hw/*/grlib*
|
||||
F: include/hw/sparc/grlib.h
|
||||
|
||||
S390 Machines
|
||||
-------------
|
||||
@@ -1194,7 +1181,6 @@ S: Supported
|
||||
F: hw/s390x/ipl.*
|
||||
F: pc-bios/s390-ccw/
|
||||
F: pc-bios/s390-ccw.img
|
||||
F: docs/devel/s390-dasd-ipl.txt
|
||||
T: git https://github.com/borntraeger/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
@@ -1205,7 +1191,7 @@ F: hw/s390x/s390-pci*
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
UniCore32 Machines
|
||||
------------------
|
||||
-------------
|
||||
PKUnity-3 SoC initramfs-with-busybox
|
||||
M: Guan Xuetao <gxt@mprc.pku.edu.cn>
|
||||
S: Maintained
|
||||
@@ -1274,18 +1260,11 @@ Machine core
|
||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||
M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
|
||||
S: Supported
|
||||
F: hw/core/machine-qmp-cmds.c
|
||||
F: hw/core/machine.c
|
||||
F: hw/core/null-machine.c
|
||||
F: hw/core/numa.c
|
||||
F: hw/cpu/cluster.c
|
||||
F: qapi/machine.json
|
||||
F: qapi/machine-target.json
|
||||
F: qom/cpu.c
|
||||
F: include/hw/boards.h
|
||||
F: include/hw/cpu/cluster.h
|
||||
F: include/qom/cpu.h
|
||||
F: include/sysemu/numa.h
|
||||
T: git https://github.com/ehabkost/qemu.git machine-next
|
||||
|
||||
Xtensa Machines
|
||||
@@ -1404,13 +1383,6 @@ F: include/hw/net/
|
||||
F: tests/virtio-net-test.c
|
||||
T: git https://github.com/jasowang/qemu.git net
|
||||
|
||||
Parallel NOR Flash devices
|
||||
M: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
T: git https://gitlab.com/philmd/qemu.git pflash-next
|
||||
S: Maintained
|
||||
F: hw/block/pflash_cfi*.c
|
||||
F: include/hw/block/flash.h
|
||||
|
||||
SCSI
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
R: Fam Zheng <fam@euphon.net>
|
||||
@@ -1468,11 +1440,11 @@ F: include/hw/vfio/
|
||||
vfio-ccw
|
||||
M: Cornelia Huck <cohuck@redhat.com>
|
||||
M: Eric Farman <farman@linux.ibm.com>
|
||||
M: Farhan Ali <alifm@linux.ibm.com>
|
||||
S: Supported
|
||||
F: hw/vfio/ccw.c
|
||||
F: hw/s390x/s390-ccw.c
|
||||
F: include/hw/s390x/s390-ccw.h
|
||||
F: include/hw/s390x/vfio-ccw.h
|
||||
T: git https://github.com/cohuck/qemu.git s390-next
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
@@ -1495,10 +1467,8 @@ M: Michael S. Tsirkin <mst@redhat.com>
|
||||
S: Supported
|
||||
F: hw/*/*vhost*
|
||||
F: docs/interop/vhost-user.json
|
||||
F: docs/interop/vhost-user.rst
|
||||
F: docs/interop/vhost-user.txt
|
||||
F: contrib/vhost-user-*/
|
||||
F: backends/vhost-user.c
|
||||
F: include/sysemu/vhost-user-backend.h
|
||||
|
||||
virtio
|
||||
M: Michael S. Tsirkin <mst@redhat.com>
|
||||
@@ -1514,7 +1484,6 @@ virtio-9p
|
||||
M: Greg Kurz <groug@kaod.org>
|
||||
S: Supported
|
||||
F: hw/9pfs/
|
||||
X: hw/9pfs/xen-9p*
|
||||
F: fsdev/
|
||||
F: tests/virtio-9p-test.c
|
||||
T: git https://github.com/gkurz/qemu.git 9p-next
|
||||
@@ -1541,10 +1510,8 @@ L: qemu-s390x@nongnu.org
|
||||
virtio-input
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
S: Maintained
|
||||
F: hw/input/vhost-user-input.c
|
||||
F: hw/input/virtio-input*.c
|
||||
F: include/hw/virtio/virtio-input.h
|
||||
F: contrib/vhost-user-input/*
|
||||
|
||||
virtio-serial
|
||||
M: Amit Shah <amit@kernel.org>
|
||||
@@ -1685,17 +1652,9 @@ virtio-gpu
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
S: Maintained
|
||||
F: hw/display/virtio-gpu*
|
||||
F: hw/display/virtio-vga.*
|
||||
F: hw/display/virtio-vga.c
|
||||
F: include/hw/virtio/virtio-gpu.h
|
||||
|
||||
vhost-user-gpu
|
||||
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
S: Maintained
|
||||
F: docs/interop/vhost-user-gpu.rst
|
||||
F: contrib/vhost-user-gpu
|
||||
F: hw/display/vhost-user-*
|
||||
|
||||
Cirrus VGA
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
S: Odd Fixes
|
||||
@@ -1716,7 +1675,6 @@ R: Gerd Hoffmann <kraxel@redhat.com>
|
||||
S: Supported
|
||||
F: docs/specs/fw_cfg.txt
|
||||
F: hw/nvram/fw_cfg.c
|
||||
F: stubs/fw_cfg.c
|
||||
F: include/hw/nvram/fw_cfg.h
|
||||
F: include/standard-headers/linux/qemu_fw_cfg.h
|
||||
F: tests/libqos/fw_cfg.c
|
||||
@@ -1730,7 +1688,6 @@ L: qemu-ppc@nongnu.org
|
||||
S: Supported
|
||||
F: hw/*/*xive*
|
||||
F: include/hw/*/*xive*
|
||||
F: docs/*/*xive*
|
||||
|
||||
Subsystems
|
||||
----------
|
||||
@@ -1849,6 +1806,12 @@ M: Markus Armbruster <armbru@redhat.com>
|
||||
S: Supported
|
||||
F: scripts/coverity-model.c
|
||||
|
||||
CPU
|
||||
L: qemu-devel@nongnu.org
|
||||
S: Supported
|
||||
F: qom/cpu.c
|
||||
F: include/qom/cpu.h
|
||||
|
||||
Device Tree
|
||||
M: Alistair Francis <alistair.francis@wdc.com>
|
||||
R: David Gibson <david@gibson.dropbear.id.au>
|
||||
@@ -1859,13 +1822,11 @@ F: include/sysemu/device_tree.h
|
||||
Dump
|
||||
S: Supported
|
||||
M: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
F: dump/
|
||||
F: dump.c
|
||||
F: hw/misc/vmcoreinfo.c
|
||||
F: include/hw/misc/vmcoreinfo.h
|
||||
F: include/qemu/win_dump_defs
|
||||
F: include/sysemu/dump-arch.h
|
||||
F: include/sysemu/dump.h
|
||||
F: qapi/dump.json
|
||||
F: scripts/dump-guest-memory.py
|
||||
F: stubs/dump.c
|
||||
|
||||
@@ -1878,9 +1839,7 @@ F: util/error.c
|
||||
F: util/qemu-error.c
|
||||
|
||||
GDB stub
|
||||
M: Alex Bennée <alex.bennee@linaro.org>
|
||||
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: gdbstub*
|
||||
F: gdb-xml/
|
||||
|
||||
@@ -1931,23 +1890,17 @@ F: qapi/run-state.json
|
||||
Human Monitor (HMP)
|
||||
M: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
S: Maintained
|
||||
F: monitor/monitor-internal.h
|
||||
F: monitor/misc.c
|
||||
F: monitor/monitor.c
|
||||
F: monitor/hmp*
|
||||
F: hmp.h
|
||||
F: monitor.c
|
||||
F: hmp.[ch]
|
||||
F: hmp-commands*.hx
|
||||
F: include/monitor/hmp-target.h
|
||||
F: tests/test-hmp.c
|
||||
F: include/qemu/qemu-print.h
|
||||
F: util/qemu-print.c
|
||||
|
||||
Network device backends
|
||||
M: Jason Wang <jasowang@redhat.com>
|
||||
S: Maintained
|
||||
F: net/
|
||||
F: include/net/
|
||||
F: qemu-bridge-helper.c
|
||||
T: git https://github.com/jasowang/qemu.git net
|
||||
F: qapi/net.json
|
||||
|
||||
@@ -1959,6 +1912,13 @@ W: http://info.iet.unipi.it/~luigi/netmap/
|
||||
S: Maintained
|
||||
F: net/netmap.c
|
||||
|
||||
NUMA
|
||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||
S: Maintained
|
||||
F: numa.c
|
||||
F: include/sysemu/numa.h
|
||||
T: git https://github.com/ehabkost/qemu.git machine-next
|
||||
|
||||
Host Memory Backends
|
||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
||||
M: Igor Mammedov <imammedo@redhat.com>
|
||||
@@ -2036,32 +1996,21 @@ F: docs/interop/qemu-ga-ref.texi
|
||||
T: git https://github.com/mdroth/qemu.git qga
|
||||
|
||||
QOM
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
R: Daniel P. Berrange <berrange@redhat.com>
|
||||
R: Eduardo Habkost <ehabkost@redhat.com>
|
||||
M: Andreas Färber <afaerber@suse.de>
|
||||
S: Supported
|
||||
F: docs/qdev-device-use.txt
|
||||
F: hw/core/qdev*
|
||||
F: include/hw/qdev*
|
||||
F: include/monitor/qdev.h
|
||||
T: git https://github.com/afaerber/qemu-cpu.git qom-next
|
||||
F: include/qom/
|
||||
X: include/qom/cpu.h
|
||||
F: qapi/qom.json
|
||||
F: qapi/qdev.json
|
||||
F: qdev-monitor.c
|
||||
F: qom/
|
||||
X: qom/cpu.c
|
||||
F: tests/check-qom-interface.c
|
||||
F: tests/check-qom-proplist.c
|
||||
F: tests/test-qdev-global-props.c
|
||||
|
||||
QMP
|
||||
M: Markus Armbruster <armbru@redhat.com>
|
||||
S: Supported
|
||||
F: monitor/monitor-internal.h
|
||||
F: monitor/qmp*
|
||||
F: monitor/misc.c
|
||||
F: monitor/monitor.c
|
||||
F: qmp.c
|
||||
F: monitor.c
|
||||
F: docs/devel/*qmp-*
|
||||
F: docs/interop/*qmp-*
|
||||
F: scripts/qmp/
|
||||
@@ -2075,7 +2024,6 @@ M: Laurent Vivier <lvivier@redhat.com>
|
||||
R: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Maintained
|
||||
F: qtest.c
|
||||
F: accel/qtest.c
|
||||
F: tests/libqtest.*
|
||||
F: tests/libqos/
|
||||
F: tests/*-test.c
|
||||
@@ -2274,21 +2222,9 @@ F: include/hw/i2c/smbus_master.h
|
||||
F: include/hw/i2c/smbus_slave.h
|
||||
F: include/hw/i2c/smbus_eeprom.h
|
||||
|
||||
EDK2 Firmware
|
||||
M: Laszlo Ersek <lersek@redhat.com>
|
||||
M: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
S: Supported
|
||||
F: pc-bios/descriptors/??-edk2-*.json
|
||||
F: pc-bios/edk2-*
|
||||
F: roms/Makefile.edk2
|
||||
F: roms/edk2
|
||||
F: roms/edk2-*
|
||||
F: tests/data/uefi-boot-images/
|
||||
F: tests/uefi-test-tools/
|
||||
|
||||
Usermode Emulation
|
||||
------------------
|
||||
Overall usermode emulation
|
||||
Overall
|
||||
M: Riku Voipio <riku.voipio@iki.fi>
|
||||
S: Maintained
|
||||
F: thunk.c
|
||||
@@ -2309,12 +2245,12 @@ F: scripts/qemu-binfmt-conf.sh
|
||||
|
||||
Tiny Code Generator (TCG)
|
||||
-------------------------
|
||||
Common TCG code
|
||||
Common code
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
S: Maintained
|
||||
F: tcg/
|
||||
|
||||
AArch64 TCG target
|
||||
AArch64 target
|
||||
M: Claudio Fontana <claudio.fontana@huawei.com>
|
||||
M: Claudio Fontana <claudio.fontana@gmail.com>
|
||||
S: Maintained
|
||||
@@ -2323,32 +2259,33 @@ F: tcg/aarch64/
|
||||
F: disas/arm-a64.cc
|
||||
F: disas/libvixl/
|
||||
|
||||
ARM TCG target
|
||||
ARM target
|
||||
M: Andrzej Zaborowski <balrogg@gmail.com>
|
||||
S: Maintained
|
||||
L: qemu-arm@nongnu.org
|
||||
F: tcg/arm/
|
||||
F: disas/arm.c
|
||||
|
||||
i386 TCG target
|
||||
i386 target
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
S: Maintained
|
||||
F: tcg/i386/
|
||||
F: disas/i386.c
|
||||
|
||||
MIPS TCG target
|
||||
MIPS target
|
||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||
R: Aleksandar Rikalo <arikalo@wavecomp.com>
|
||||
S: Maintained
|
||||
F: tcg/mips/
|
||||
F: disas/mips.c
|
||||
|
||||
PPC TCG target
|
||||
PPC
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
S: Odd Fixes
|
||||
F: tcg/ppc/
|
||||
F: disas/ppc.c
|
||||
|
||||
RISC-V TCG target
|
||||
RISC-V
|
||||
M: Palmer Dabbelt <palmer@sifive.com>
|
||||
M: Alistair Francis <Alistair.Francis@wdc.com>
|
||||
L: qemu-riscv@nongnu.org
|
||||
@@ -2356,19 +2293,19 @@ S: Maintained
|
||||
F: tcg/riscv/
|
||||
F: disas/riscv.c
|
||||
|
||||
S390 TCG target
|
||||
S390 target
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
S: Maintained
|
||||
F: tcg/s390/
|
||||
F: disas/s390.c
|
||||
L: qemu-s390x@nongnu.org
|
||||
|
||||
SPARC TCG target
|
||||
SPARC target
|
||||
S: Odd Fixes
|
||||
F: tcg/sparc/
|
||||
F: disas/sparc.c
|
||||
|
||||
TCI TCG target
|
||||
TCI target
|
||||
M: Stefan Weil <sw@weilnetz.de>
|
||||
S: Maintained
|
||||
F: tcg/tci/
|
||||
@@ -2384,7 +2321,7 @@ S: Supported
|
||||
F: block/vmdk.c
|
||||
|
||||
RBD
|
||||
M: Jason Dillaman <dillaman@redhat.com>
|
||||
M: Josh Durgin <jdurgin@redhat.com>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: block/rbd.c
|
||||
@@ -2443,13 +2380,12 @@ F: block/ssh.c
|
||||
|
||||
CURL
|
||||
L: qemu-block@nongnu.org
|
||||
S: Odd Fixes
|
||||
S: Supported
|
||||
F: block/curl.c
|
||||
|
||||
GLUSTER
|
||||
L: qemu-block@nongnu.org
|
||||
L: integration@gluster.org
|
||||
S: Odd Fixes
|
||||
S: Supported
|
||||
F: block/gluster.c
|
||||
|
||||
Null Block Driver
|
||||
@@ -2588,18 +2524,13 @@ F: docs/pvrdma.txt
|
||||
F: contrib/rdmacm-mux/*
|
||||
F: qapi/rdma.json
|
||||
|
||||
Semihosting
|
||||
M: Alex Bennée <alex.bennee@linaro.org>
|
||||
S: Maintained
|
||||
F: hw/semihosting/
|
||||
F: include/hw/semihosting/
|
||||
|
||||
Build and test automation
|
||||
-------------------------
|
||||
Build and test automation
|
||||
M: Alex Bennée <alex.bennee@linaro.org>
|
||||
M: Fam Zheng <fam@euphon.net>
|
||||
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
L: qemu-devel@nongnu.org
|
||||
S: Maintained
|
||||
F: .travis.yml
|
||||
F: scripts/travis/
|
||||
@@ -2614,6 +2545,7 @@ W: http://patchew.org/QEMU/
|
||||
FreeBSD Hosted Continuous Integration
|
||||
M: Ed Maste <emaste@freebsd.org>
|
||||
M: Li-Wen Hsu <lwhsu@freebsd.org>
|
||||
L: qemu-devel@nongnu.org
|
||||
S: Maintained
|
||||
F: .cirrus.yml
|
||||
W: https://cirrus-ci.com/github/qemu/qemu
|
||||
@@ -2629,6 +2561,7 @@ R: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||
S: Maintained
|
||||
F: tests/tcg/Makefile
|
||||
F: tests/tcg/Makefile.include
|
||||
L: qemu-devel@nongnu.org
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
# Makefile for QEMU.
|
||||
|
||||
ifneq ($(words $(subst :, ,$(CURDIR))), 1)
|
||||
$(error main directory cannot contain spaces nor colons)
|
||||
endif
|
||||
|
||||
# Always point to the root of the build tree (needs GNU make).
|
||||
BUILD_DIR=$(CURDIR)
|
||||
|
||||
@@ -13,7 +9,7 @@ SRC_PATH=.
|
||||
UNCHECKED_GOALS := %clean TAGS cscope ctags dist \
|
||||
html info pdf txt \
|
||||
help check-help print-% \
|
||||
docker docker-% vm-help vm-test vm-build-%
|
||||
docker docker-% vm-test vm-build-%
|
||||
|
||||
print-%:
|
||||
@echo '$*=$($*)'
|
||||
@@ -73,7 +69,14 @@ CONFIG_ALL=y
|
||||
|
||||
config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION
|
||||
@echo $@ is out-of-date, running configure
|
||||
@./config.status
|
||||
@# TODO: The next lines include code which supports a smooth
|
||||
@# transition from old configurations without config.status.
|
||||
@# This code can be removed after QEMU 1.7.
|
||||
@if test -x config.status; then \
|
||||
./config.status; \
|
||||
else \
|
||||
sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh; \
|
||||
fi
|
||||
else
|
||||
config-host.mak:
|
||||
ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
|
||||
@@ -84,10 +87,6 @@ endif
|
||||
|
||||
include $(SRC_PATH)/rules.mak
|
||||
|
||||
# notempy and lor are defined in rules.mak
|
||||
CONFIG_TOOLS := $(call notempty,$(TOOLS))
|
||||
CONFIG_BLOCK := $(call lor,$(CONFIG_SOFTMMU),$(CONFIG_TOOLS))
|
||||
|
||||
# Create QEMU_PKGVERSION and FULL_VERSION strings
|
||||
# If PKGVERSION is set, use that; otherwise get version and -dirty status from git
|
||||
QEMU_PKGVERSION := $(if $(PKGVERSION),$(PKGVERSION),$(shell \
|
||||
@@ -102,7 +101,7 @@ QEMU_PKGVERSION := $(if $(PKGVERSION),$(PKGVERSION),$(shell \
|
||||
# Either "version (pkgversion)", or just "version" if pkgversion not set
|
||||
FULL_VERSION := $(if $(QEMU_PKGVERSION),$(VERSION) ($(QEMU_PKGVERSION)),$(VERSION))
|
||||
|
||||
generated-files-y = qemu-version.h config-host.h qemu-options.def
|
||||
GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
|
||||
|
||||
GENERATED_QAPI_FILES = qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c
|
||||
GENERATED_QAPI_FILES += qapi/qapi-types.h qapi/qapi-types.c
|
||||
@@ -122,18 +121,20 @@ GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-events-%.c)
|
||||
GENERATED_QAPI_FILES += qapi/qapi-introspect.c qapi/qapi-introspect.h
|
||||
GENERATED_QAPI_FILES += qapi/qapi-doc.texi
|
||||
|
||||
generated-files-y += $(GENERATED_QAPI_FILES)
|
||||
GENERATED_FILES += $(GENERATED_QAPI_FILES)
|
||||
|
||||
generated-files-y += trace/generated-tcg-tracers.h
|
||||
GENERATED_FILES += trace/generated-tcg-tracers.h
|
||||
|
||||
generated-files-y += trace/generated-helpers-wrappers.h
|
||||
generated-files-y += trace/generated-helpers.h
|
||||
generated-files-y += trace/generated-helpers.c
|
||||
GENERATED_FILES += trace/generated-helpers-wrappers.h
|
||||
GENERATED_FILES += trace/generated-helpers.h
|
||||
GENERATED_FILES += trace/generated-helpers.c
|
||||
|
||||
generated-files-$(CONFIG_TRACE_UST) += trace-ust-all.h
|
||||
generated-files-$(CONFIG_TRACE_UST) += trace-ust-all.c
|
||||
ifdef CONFIG_TRACE_UST
|
||||
GENERATED_FILES += trace-ust-all.h
|
||||
GENERATED_FILES += trace-ust-all.c
|
||||
endif
|
||||
|
||||
generated-files-y += module_block.h
|
||||
GENERATED_FILES += module_block.h
|
||||
|
||||
TRACE_HEADERS = trace-root.h $(trace-events-subdirs:%=%/trace.h)
|
||||
TRACE_SOURCES = trace-root.c $(trace-events-subdirs:%=%/trace.c)
|
||||
@@ -146,10 +147,10 @@ ifdef CONFIG_TRACE_UST
|
||||
TRACE_HEADERS += trace-ust-root.h $(trace-events-subdirs:%=%/trace-ust.h)
|
||||
endif
|
||||
|
||||
generated-files-y += $(TRACE_HEADERS)
|
||||
generated-files-y += $(TRACE_SOURCES)
|
||||
generated-files-y += $(BUILD_DIR)/trace-events-all
|
||||
generated-files-y += .git-submodule-status
|
||||
GENERATED_FILES += $(TRACE_HEADERS)
|
||||
GENERATED_FILES += $(TRACE_SOURCES)
|
||||
GENERATED_FILES += $(BUILD_DIR)/trace-events-all
|
||||
GENERATED_FILES += .git-submodule-status
|
||||
|
||||
trace-group-name = $(shell dirname $1 | sed -e 's/[^a-zA-Z0-9]/_/g')
|
||||
|
||||
@@ -280,7 +281,7 @@ KEYCODEMAP_FILES = \
|
||||
ui/input-keymap-osx-to-qcode.c \
|
||||
$(NULL)
|
||||
|
||||
generated-files-$(CONFIG_SOFTMMU) += $(KEYCODEMAP_FILES)
|
||||
GENERATED_FILES += $(KEYCODEMAP_FILES)
|
||||
|
||||
ui/input-keymap-%.c: $(KEYCODEMAP_GEN) $(KEYCODEMAP_CSV) $(SRC_PATH)/ui/Makefile.objs
|
||||
$(call quiet-command,\
|
||||
@@ -295,10 +296,6 @@ ui/input-keymap-%.c: $(KEYCODEMAP_GEN) $(KEYCODEMAP_CSV) $(SRC_PATH)/ui/Makefile
|
||||
$(KEYCODEMAP_GEN): .git-submodule-status
|
||||
$(KEYCODEMAP_CSV): .git-submodule-status
|
||||
|
||||
edk2-decompressed = $(basename $(wildcard pc-bios/edk2-*.fd.bz2))
|
||||
pc-bios/edk2-%.fd: pc-bios/edk2-%.fd.bz2
|
||||
$(call quiet-command,bzip2 -d -c $< > $@,"BUNZIP2",$<)
|
||||
|
||||
# Don't try to regenerate Makefile or configure
|
||||
# We don't generate any of them
|
||||
Makefile: ;
|
||||
@@ -311,20 +308,8 @@ $(call set-vpath, $(SRC_PATH))
|
||||
|
||||
LIBS+=-lz $(LIBS_TOOLS)
|
||||
|
||||
vhost-user-json-y =
|
||||
HELPERS-y =
|
||||
|
||||
HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = qemu-bridge-helper$(EXESUF)
|
||||
|
||||
ifdef CONFIG_LINUX
|
||||
ifdef CONFIG_VIRGL
|
||||
ifdef CONFIG_GBM
|
||||
HELPERS-y += vhost-user-gpu$(EXESUF)
|
||||
vhost-user-json-y += contrib/vhost-user-gpu/50-qemu-gpu.json
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef BUILD_DOCS
|
||||
DOCS=qemu-doc.html qemu-doc.txt qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
|
||||
DOCS+=docs/interop/qemu-qmp-ref.html docs/interop/qemu-qmp-ref.txt docs/interop/qemu-qmp-ref.7
|
||||
@@ -361,7 +346,7 @@ endif
|
||||
# This has to be kept in sync with Kconfig.host.
|
||||
MINIKCONF_ARGS = \
|
||||
$(CONFIG_MINIKCONF_MODE) \
|
||||
$@ $*/config-devices.mak.d $< $(MINIKCONF_INPUTS) \
|
||||
$@ $*-config.devices.mak.d $< $(MINIKCONF_INPUTS) \
|
||||
CONFIG_KVM=$(CONFIG_KVM) \
|
||||
CONFIG_SPICE=$(CONFIG_SPICE) \
|
||||
CONFIG_IVSHMEM=$(CONFIG_IVSHMEM) \
|
||||
@@ -417,13 +402,11 @@ dummy := $(call unnest-vars,, \
|
||||
libvhost-user-obj-y \
|
||||
vhost-user-scsi-obj-y \
|
||||
vhost-user-blk-obj-y \
|
||||
vhost-user-input-obj-y \
|
||||
vhost-user-gpu-obj-y \
|
||||
qga-vss-dll-obj-y \
|
||||
block-obj-y \
|
||||
block-obj-m \
|
||||
crypto-obj-y \
|
||||
crypto-user-obj-y \
|
||||
crypto-aes-obj-y \
|
||||
qom-obj-y \
|
||||
io-obj-y \
|
||||
common-obj-y \
|
||||
@@ -436,7 +419,7 @@ dummy := $(call unnest-vars,, \
|
||||
|
||||
include $(SRC_PATH)/tests/Makefile.include
|
||||
|
||||
all: $(DOCS) $(if $(BUILD_DOCS),sphinxdocs) $(TOOLS) $(HELPERS-y) recurse-all modules $(vhost-user-json-y)
|
||||
all: $(DOCS) $(if $(BUILD_DOCS),sphinxdocs) $(TOOLS) $(HELPERS-y) recurse-all modules
|
||||
|
||||
qemu-version.h: FORCE
|
||||
$(call quiet-command, \
|
||||
@@ -454,29 +437,23 @@ config-host.h-timestamp: config-host.mak
|
||||
qemu-options.def: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"GEN","$@")
|
||||
|
||||
TARGET_DIRS_RULES := $(foreach t, all clean install, $(addsuffix /$(t), $(TARGET_DIRS)))
|
||||
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
|
||||
SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
|
||||
|
||||
SOFTMMU_ALL_RULES=$(filter %-softmmu/all, $(TARGET_DIRS_RULES))
|
||||
$(SOFTMMU_ALL_RULES): $(authz-obj-y)
|
||||
$(SOFTMMU_ALL_RULES): $(block-obj-y)
|
||||
$(SOFTMMU_ALL_RULES): $(chardev-obj-y)
|
||||
$(SOFTMMU_ALL_RULES): $(crypto-obj-y)
|
||||
$(SOFTMMU_ALL_RULES): $(io-obj-y)
|
||||
$(SOFTMMU_ALL_RULES): config-all-devices.mak
|
||||
$(SOFTMMU_ALL_RULES): $(edk2-decompressed)
|
||||
$(SOFTMMU_SUBDIR_RULES): $(authz-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): $(block-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): $(crypto-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): $(io-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): config-all-devices.mak
|
||||
|
||||
.PHONY: $(TARGET_DIRS_RULES)
|
||||
# The $(TARGET_DIRS_RULES) are of the form SUBDIR/GOAL, so that
|
||||
# $(dir $@) yields the sub-directory, and $(notdir $@) yields the sub-goal
|
||||
$(TARGET_DIRS_RULES):
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" $(notdir $@),)
|
||||
subdir-%:
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $* V="$(V)" TARGET_DIR="$*/" all,)
|
||||
|
||||
DTC_MAKE_ARGS=-I$(SRC_PATH)/dtc VPATH=$(SRC_PATH)/dtc -C dtc V="$(V)" LIBFDT_srcdir=$(SRC_PATH)/dtc/libfdt
|
||||
DTC_CFLAGS=$(CFLAGS) $(QEMU_CFLAGS)
|
||||
DTC_CPPFLAGS=-I$(BUILD_DIR)/dtc -I$(SRC_PATH)/dtc -I$(SRC_PATH)/dtc/libfdt
|
||||
|
||||
.PHONY: dtc/all
|
||||
dtc/all: .git-submodule-status dtc/libfdt dtc/tests
|
||||
subdir-dtc: .git-submodule-status dtc/libfdt dtc/tests
|
||||
$(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CPPFLAGS="$(DTC_CPPFLAGS)" CFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt/libfdt.a,)
|
||||
|
||||
dtc/%: .git-submodule-status
|
||||
@@ -494,35 +471,23 @@ CAP_CFLAGS += -DCAPSTONE_HAS_ARM64
|
||||
CAP_CFLAGS += -DCAPSTONE_HAS_POWERPC
|
||||
CAP_CFLAGS += -DCAPSTONE_HAS_X86
|
||||
|
||||
.PHONY: capstone/all
|
||||
capstone/all: .git-submodule-status
|
||||
subdir-capstone: .git-submodule-status
|
||||
$(call quiet-command,$(MAKE) -C $(SRC_PATH)/capstone CAPSTONE_SHARED=no BUILDDIR="$(BUILD_DIR)/capstone" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(CAP_CFLAGS)" $(SUBDIR_MAKEFLAGS) $(BUILD_DIR)/capstone/$(LIBCAPSTONE))
|
||||
|
||||
.PHONY: slirp/all
|
||||
slirp/all: .git-submodule-status
|
||||
$(call quiet-command,$(MAKE) -C $(SRC_PATH)/slirp BUILD_DIR="$(BUILD_DIR)/slirp" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(QEMU_CFLAGS) $(CFLAGS)" LDFLAGS="$(LDFLAGS)")
|
||||
subdir-slirp: .git-submodule-status
|
||||
$(call quiet-command,$(MAKE) -C $(SRC_PATH)/slirp BUILD_DIR="$(BUILD_DIR)/slirp" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(QEMU_CFLAGS)")
|
||||
|
||||
# Compatibility gunk to keep make working across the rename of targets
|
||||
# for recursion, to be removed some time after 4.1.
|
||||
subdir-dtc: dtc/all
|
||||
subdir-capstone: capstone/all
|
||||
subdir-slirp: slirp/all
|
||||
$(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) \
|
||||
$(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
|
||||
|
||||
$(filter %/all, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \
|
||||
$(qom-obj-y) $(crypto-user-obj-$(CONFIG_USER_ONLY))
|
||||
|
||||
ROM_DIRS = $(addprefix pc-bios/, $(ROMS))
|
||||
ROM_DIRS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROM_DIRS)))
|
||||
ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
|
||||
# Only keep -O and -g cflags
|
||||
.PHONY: $(ROM_DIRS_RULES)
|
||||
$(ROM_DIRS_RULES):
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" CFLAGS="$(filter -O% -g%,$(CFLAGS))" $(notdir $@),)
|
||||
romsubdir-%:
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C pc-bios/$* V="$(V)" TARGET_DIR="$*/" CFLAGS="$(filter -O% -g%,$(CFLAGS))",)
|
||||
|
||||
.PHONY: recurse-all recurse-clean recurse-install
|
||||
recurse-all: $(addsuffix /all, $(TARGET_DIRS) $(ROM_DIRS))
|
||||
recurse-clean: $(addsuffix /clean, $(TARGET_DIRS) $(ROM_DIRS))
|
||||
recurse-install: $(addsuffix /install, $(TARGET_DIRS))
|
||||
$(addsuffix /install, $(TARGET_DIRS)): all
|
||||
ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))
|
||||
|
||||
recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
|
||||
|
||||
$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc config-host.h
|
||||
$(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<,"RC","version.o")
|
||||
@@ -626,6 +591,7 @@ ifneq ($(EXESUF),)
|
||||
qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI)
|
||||
endif
|
||||
|
||||
elf2dmp$(EXESUF): LIBS += $(CURL_LIBS)
|
||||
elf2dmp$(EXESUF): $(elf2dmp-obj-y)
|
||||
$(call LINK, $^)
|
||||
|
||||
@@ -644,19 +610,6 @@ rdmacm-mux$(EXESUF): LIBS += "-libumad"
|
||||
rdmacm-mux$(EXESUF): $(rdmacm-mux-obj-y) $(COMMON_LDADDS)
|
||||
$(call LINK, $^)
|
||||
|
||||
vhost-user-gpu$(EXESUF): $(vhost-user-gpu-obj-y) $(libvhost-user-obj-y) libqemuutil.a libqemustub.a
|
||||
$(call LINK, $^)
|
||||
|
||||
ifdef CONFIG_VHOST_USER_INPUT
|
||||
ifdef CONFIG_LINUX
|
||||
vhost-user-input$(EXESUF): $(vhost-user-input-obj-y) libvhost-user.a libqemuutil.a
|
||||
$(call LINK, $^)
|
||||
|
||||
# build by default, do not install
|
||||
all: vhost-user-input$(EXESUF)
|
||||
endif
|
||||
endif
|
||||
|
||||
module_block.h: $(SRC_PATH)/scripts/modules/module_block.py config-host.mak
|
||||
$(call quiet-command,$(PYTHON) $< $@ \
|
||||
$(addprefix $(SRC_PATH)/,$(patsubst %.mo,%.c,$(block-obj-m))), \
|
||||
@@ -670,7 +623,7 @@ clean-coverage:
|
||||
"CLEAN", "coverage files")
|
||||
endif
|
||||
|
||||
clean: recurse-clean
|
||||
clean:
|
||||
# avoid old build problems by removing potentially incorrect old files
|
||||
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
|
||||
rm -f qemu-options.def
|
||||
@@ -680,17 +633,20 @@ clean: recurse-clean
|
||||
! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \
|
||||
! -path ./roms/edk2/BaseTools/Source/Python/UPT/Dll/sqlite3.dll \
|
||||
-exec rm {} +
|
||||
rm -f $(edk2-decompressed)
|
||||
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga$(EXESUF) TAGS cscope.* *.pod *~ */*~
|
||||
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
|
||||
rm -f fsdev/*.pod scsi/*.pod
|
||||
rm -f qemu-img-cmds.h
|
||||
rm -f ui/shader/*-vert.h ui/shader/*-frag.h
|
||||
@# May not be present in generated-files-y
|
||||
@# May not be present in GENERATED_FILES
|
||||
rm -f trace/generated-tracers-dtrace.dtrace*
|
||||
rm -f trace/generated-tracers-dtrace.h*
|
||||
rm -f $(foreach f,$(generated-files-y),$(f) $(f)-timestamp)
|
||||
rm -f $(foreach f,$(GENERATED_FILES),$(f) $(f)-timestamp)
|
||||
rm -f qapi-gen-timestamp
|
||||
rm -rf qga/qapi-generated
|
||||
for d in $(ALL_SUBDIRS); do \
|
||||
if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
|
||||
rm -f $$d/qemu-options.def; \
|
||||
done
|
||||
rm -f config-all-devices.mak
|
||||
|
||||
VERSION ?= $(shell cat VERSION)
|
||||
@@ -739,7 +695,6 @@ distclean: clean
|
||||
rm -rf .doctrees
|
||||
$(call clean-manual,devel)
|
||||
$(call clean-manual,interop)
|
||||
$(call clean-manual,specs)
|
||||
for d in $(TARGET_DIRS); do \
|
||||
rm -rf $$d || exit 1 ; \
|
||||
done
|
||||
@@ -754,14 +709,13 @@ bepo cz
|
||||
ifdef INSTALL_BLOBS
|
||||
BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
|
||||
vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-virtio.bin \
|
||||
vgabios-ramfb.bin vgabios-bochs-display.bin vgabios-ati.bin \
|
||||
vgabios-ramfb.bin vgabios-bochs-display.bin \
|
||||
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin \
|
||||
pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
|
||||
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
|
||||
efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
|
||||
efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom \
|
||||
efi-e1000e.rom efi-vmxnet3.rom \
|
||||
qemu-nsis.bmp \
|
||||
bamboo.dtb canyonlands.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
|
||||
multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin \
|
||||
s390-ccw.img s390-netboot.img \
|
||||
@@ -769,17 +723,9 @@ spapr-rtas.bin slof.bin skiboot.lid \
|
||||
palcode-clipper \
|
||||
u-boot.e500 u-boot-sam460-20100605.bin \
|
||||
qemu_vga.ndrv \
|
||||
edk2-licenses.txt \
|
||||
hppa-firmware.img \
|
||||
opensbi-riscv32-virt-fw_jump.bin \
|
||||
opensbi-riscv64-sifive_u-fw_jump.bin opensbi-riscv64-virt-fw_jump.bin
|
||||
|
||||
|
||||
DESCS=50-edk2-i386-secure.json 50-edk2-x86_64-secure.json \
|
||||
60-edk2-aarch64.json 60-edk2-arm.json 60-edk2-i386.json 60-edk2-x86_64.json
|
||||
hppa-firmware.img
|
||||
else
|
||||
BLOBS=
|
||||
DESCS=
|
||||
endif
|
||||
|
||||
# Note that we manually filter-out the non-Sphinx documentation which
|
||||
@@ -794,7 +740,6 @@ endef
|
||||
.PHONY: install-sphinxdocs
|
||||
install-sphinxdocs: sphinxdocs
|
||||
$(call install-manual,interop)
|
||||
$(call install-manual,specs)
|
||||
|
||||
install-doc: $(DOCS) install-sphinxdocs
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)"
|
||||
@@ -841,9 +786,7 @@ endif
|
||||
|
||||
ICON_SIZES=16x16 24x24 32x32 48x48 64x64 128x128 256x256 512x512
|
||||
|
||||
install: all $(if $(BUILD_DOCS),install-doc) install-datadir install-localstatedir \
|
||||
$(if $(INSTALL_BLOBS),$(edk2-decompressed)) \
|
||||
recurse-install
|
||||
install: all $(if $(BUILD_DOCS),install-doc) install-datadir install-localstatedir
|
||||
ifneq ($(TOOLS),)
|
||||
$(call install-prog,$(subst qemu-ga,qemu-ga$(EXESUF),$(TOOLS)),$(DESTDIR)$(bindir))
|
||||
endif
|
||||
@@ -858,12 +801,6 @@ endif
|
||||
ifneq ($(HELPERS-y),)
|
||||
$(call install-prog,$(HELPERS-y),$(DESTDIR)$(libexecdir))
|
||||
endif
|
||||
ifneq ($(vhost-user-json-y),)
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/vhost-user/"
|
||||
for x in $(vhost-user-json-y); do \
|
||||
$(INSTALL_DATA) $$x "$(DESTDIR)$(qemu_datadir)/vhost-user/"; \
|
||||
done
|
||||
endif
|
||||
ifdef CONFIG_TRACE_SYSTEMTAP
|
||||
$(INSTALL_PROG) "scripts/qemu-trace-stap" $(DESTDIR)$(bindir)
|
||||
endif
|
||||
@@ -871,36 +808,21 @@ ifneq ($(BLOBS),)
|
||||
set -e; for x in $(BLOBS); do \
|
||||
$(INSTALL_DATA) $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(qemu_datadir)"; \
|
||||
done
|
||||
endif
|
||||
ifdef INSTALL_BLOBS
|
||||
set -e; for x in $(edk2-decompressed); do \
|
||||
$(INSTALL_DATA) $$x "$(DESTDIR)$(qemu_datadir)"; \
|
||||
done
|
||||
endif
|
||||
ifneq ($(DESCS),)
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/firmware"
|
||||
set -e; tmpf=$$(mktemp); trap 'rm -f -- "$$tmpf"' EXIT; \
|
||||
for x in $(DESCS); do \
|
||||
sed -e 's,@DATADIR@,$(qemu_datadir),' \
|
||||
"$(SRC_PATH)/pc-bios/descriptors/$$x" > "$$tmpf"; \
|
||||
$(INSTALL_DATA) "$$tmpf" \
|
||||
"$(DESTDIR)$(qemu_datadir)/firmware/$$x"; \
|
||||
done
|
||||
endif
|
||||
for s in $(ICON_SIZES); do \
|
||||
mkdir -p "$(DESTDIR)$(qemu_icondir)/hicolor/$${s}/apps"; \
|
||||
mkdir -p "$(DESTDIR)/$(qemu_icondir)/hicolor/$${s}/apps"; \
|
||||
$(INSTALL_DATA) $(SRC_PATH)/ui/icons/qemu_$${s}.png \
|
||||
"$(DESTDIR)$(qemu_icondir)/hicolor/$${s}/apps/qemu.png"; \
|
||||
"$(DESTDIR)/$(qemu_icondir)/hicolor/$${s}/apps/qemu.png"; \
|
||||
done; \
|
||||
mkdir -p "$(DESTDIR)$(qemu_icondir)/hicolor/32x32/apps"; \
|
||||
mkdir -p "$(DESTDIR)/$(qemu_icondir)/hicolor/32x32/apps"; \
|
||||
$(INSTALL_DATA) $(SRC_PATH)/ui/icons/qemu_32x32.bmp \
|
||||
"$(DESTDIR)$(qemu_icondir)/hicolor/32x32/apps/qemu.bmp"; \
|
||||
mkdir -p "$(DESTDIR)$(qemu_icondir)/hicolor/scalable/apps"; \
|
||||
"$(DESTDIR)/$(qemu_icondir)/hicolor/32x32/apps/qemu.bmp"; \
|
||||
mkdir -p "$(DESTDIR)/$(qemu_icondir)/hicolor/scalable/apps"; \
|
||||
$(INSTALL_DATA) $(SRC_PATH)/ui/icons/qemu.svg \
|
||||
"$(DESTDIR)$(qemu_icondir)/hicolor/scalable/apps/qemu.svg"
|
||||
mkdir -p "$(DESTDIR)$(qemu_desktopdir)"
|
||||
"$(DESTDIR)/$(qemu_icondir)/hicolor/scalable/apps/qemu.svg"
|
||||
mkdir -p "$(DESTDIR)/$(qemu_desktopdir)"
|
||||
$(INSTALL_DATA) $(SRC_PATH)/ui/qemu.desktop \
|
||||
"$(DESTDIR)$(qemu_desktopdir)/qemu.desktop"
|
||||
"$(DESTDIR)/$(qemu_desktopdir)/qemu.desktop"
|
||||
ifdef CONFIG_GTK
|
||||
$(MAKE) -C po $@
|
||||
endif
|
||||
@@ -909,6 +831,9 @@ endif
|
||||
$(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \
|
||||
done
|
||||
$(INSTALL_DATA) $(BUILD_DIR)/trace-events-all "$(DESTDIR)$(qemu_datadir)/trace-events-all"
|
||||
for d in $(TARGET_DIRS); do \
|
||||
$(MAKE) $(SUBDIR_MAKEFLAGS) TARGET_DIR=$$d/ -C $$d $@ || exit 1 ; \
|
||||
done
|
||||
|
||||
.PHONY: ctags
|
||||
ctags:
|
||||
@@ -947,14 +872,11 @@ ui/shader.o: $(SRC_PATH)/ui/shader.c \
|
||||
MAKEINFO=makeinfo
|
||||
MAKEINFOINCLUDES= -I docs -I $(<D) -I $(@D)
|
||||
MAKEINFOFLAGS=--no-split --number-sections $(MAKEINFOINCLUDES)
|
||||
TEXI2PODFLAGS=$(MAKEINFOINCLUDES) -DVERSION="$(VERSION)" -DCONFDIR="$(qemu_confdir)"
|
||||
TEXI2PODFLAGS=$(MAKEINFOINCLUDES) "-DVERSION=$(VERSION)"
|
||||
TEXI2PDFFLAGS=$(if $(V),,--quiet) -I $(SRC_PATH) $(MAKEINFOINCLUDES)
|
||||
|
||||
docs/version.texi: $(SRC_PATH)/VERSION config-host.mak
|
||||
$(call quiet-command,(\
|
||||
echo "@set VERSION $(VERSION)" && \
|
||||
echo "@set CONFDIR $(qemu_confdir)" \
|
||||
)> $@,"GEN","$@")
|
||||
docs/version.texi: $(SRC_PATH)/VERSION
|
||||
$(call quiet-command,echo "@set VERSION $(VERSION)" > $@,"GEN","$@")
|
||||
|
||||
%.html: %.texi docs/version.texi
|
||||
$(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --no-headers \
|
||||
@@ -974,7 +896,7 @@ docs/version.texi: $(SRC_PATH)/VERSION config-host.mak
|
||||
# and handles "don't rebuild things unless necessary" itself.
|
||||
# The '.doctrees' files are cached information to speed this up.
|
||||
.PHONY: sphinxdocs
|
||||
sphinxdocs: $(MANUAL_BUILDDIR)/devel/index.html $(MANUAL_BUILDDIR)/interop/index.html $(MANUAL_BUILDDIR)/specs/index.html
|
||||
sphinxdocs: $(MANUAL_BUILDDIR)/devel/index.html $(MANUAL_BUILDDIR)/interop/index.html
|
||||
|
||||
# Canned command to build a single manual
|
||||
build-manual = $(call quiet-command,sphinx-build $(if $(V),,-q) -W -n -b html -D version=$(VERSION) -D release="$(FULL_VERSION)" -d .doctrees/$1 $(SRC_PATH)/docs/$1 $(MANUAL_BUILDDIR)/$1 ,"SPHINX","$(MANUAL_BUILDDIR)/$1")
|
||||
@@ -987,9 +909,6 @@ $(MANUAL_BUILDDIR)/devel/index.html: $(call manual-deps,devel)
|
||||
$(MANUAL_BUILDDIR)/interop/index.html: $(call manual-deps,interop)
|
||||
$(call build-manual,interop)
|
||||
|
||||
$(MANUAL_BUILDDIR)/specs/index.html: $(call manual-deps,specs)
|
||||
$(call build-manual,specs)
|
||||
|
||||
qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@,"GEN","$@")
|
||||
|
||||
@@ -1024,11 +943,10 @@ pdf: qemu-doc.pdf docs/interop/qemu-qmp-ref.pdf docs/interop/qemu-ga-ref.pdf
|
||||
txt: qemu-doc.txt docs/interop/qemu-qmp-ref.txt docs/interop/qemu-ga-ref.txt
|
||||
|
||||
qemu-doc.html qemu-doc.info qemu-doc.pdf qemu-doc.txt: \
|
||||
qemu-img.texi qemu-nbd.texi qemu-options.texi \
|
||||
qemu-tech.texi qemu-option-trace.texi \
|
||||
qemu-img.texi qemu-nbd.texi qemu-options.texi qemu-option-trace.texi \
|
||||
qemu-deprecated.texi qemu-monitor.texi qemu-img-cmds.texi qemu-ga.texi \
|
||||
qemu-monitor-info.texi docs/qemu-block-drivers.texi \
|
||||
docs/qemu-cpu-models.texi docs/security.texi
|
||||
docs/qemu-cpu-models.texi
|
||||
|
||||
docs/interop/qemu-ga-ref.dvi docs/interop/qemu-ga-ref.html \
|
||||
docs/interop/qemu-ga-ref.info docs/interop/qemu-ga-ref.pdf \
|
||||
@@ -1047,9 +965,7 @@ $(filter %.1 %.7 %.8,$(DOCS)): scripts/texi2pod.pl
|
||||
%/coverage-report.html:
|
||||
@mkdir -p $*
|
||||
$(call quiet-command,\
|
||||
gcovr -r $(SRC_PATH) \
|
||||
$(foreach t, $(TARGET_DIRS), --object-directory $(BUILD_DIR)/$(t)) \
|
||||
--object-directory $(BUILD_DIR) \
|
||||
gcovr -r $(SRC_PATH) --object-directory $(BUILD_PATH) \
|
||||
-p --html --html-details -o $@, \
|
||||
"GEN", "coverage-report.html")
|
||||
|
||||
@@ -1078,7 +994,7 @@ installer: $(INSTALLER)
|
||||
|
||||
INSTDIR=/tmp/qemu-nsis
|
||||
|
||||
$(INSTALLER): install-doc $(SRC_PATH)/qemu.nsi
|
||||
$(INSTALLER): $(SRC_PATH)/qemu.nsi
|
||||
$(MAKE) install prefix=${INSTDIR}
|
||||
ifdef SIGNCODE
|
||||
(cd ${INSTDIR}; \
|
||||
@@ -1116,7 +1032,7 @@ endif # CONFIG_WIN
|
||||
# rebuilt before other object files
|
||||
ifneq ($(wildcard config-host.mak),)
|
||||
ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
|
||||
Makefile: $(generated-files-y)
|
||||
Makefile: $(GENERATED_FILES)
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -1146,7 +1062,7 @@ endif
|
||||
@$(if $(TARGET_DIRS), \
|
||||
echo 'Architecture specific targets:'; \
|
||||
$(foreach t, $(TARGET_DIRS), \
|
||||
printf " %-30s - Build for %s\\n" $(t)/all $(t);) \
|
||||
printf " %-30s - Build for %s\\n" $(patsubst %,subdir-%,$(t)) $(t);) \
|
||||
echo '')
|
||||
@echo 'Cleaning targets:'
|
||||
@echo ' clean - Remove most generated files but keep the config'
|
||||
@@ -1159,7 +1075,7 @@ endif
|
||||
@echo 'Test targets:'
|
||||
@echo ' check - Run all tests (check-help for details)'
|
||||
@echo ' docker - Help about targets running tests inside Docker containers'
|
||||
@echo ' vm-help - Help about targets running tests inside VM'
|
||||
@echo ' vm-test - Help about targets running tests inside VM'
|
||||
@echo ''
|
||||
@echo 'Documentation targets:'
|
||||
@echo ' html info pdf txt'
|
||||
|
||||
+10
-22
@@ -25,7 +25,7 @@ block-obj-m = block/
|
||||
# crypto-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
crypto-obj-y = crypto/
|
||||
crypto-user-obj-y = crypto/
|
||||
crypto-aes-obj-y = crypto/
|
||||
|
||||
#######################################################################
|
||||
# qom-obj-y is code used by both qemu system emulation and qemu-img
|
||||
@@ -45,9 +45,7 @@ io-obj-y = io/
|
||||
ifeq ($(CONFIG_SOFTMMU),y)
|
||||
common-obj-y = blockdev.o blockdev-nbd.o block/
|
||||
common-obj-y += bootdevice.o iothread.o
|
||||
common-obj-y += dump/
|
||||
common-obj-y += job-qmp.o
|
||||
common-obj-y += monitor/
|
||||
common-obj-y += net/
|
||||
common-obj-y += qdev-monitor.o device-hotplug.o
|
||||
common-obj-$(CONFIG_WIN32) += os-win32.o
|
||||
@@ -85,6 +83,7 @@ common-obj-$(CONFIG_FDT) += device_tree.o
|
||||
######################################################################
|
||||
# qapi
|
||||
|
||||
common-obj-y += qmp.o hmp.o
|
||||
common-obj-y += qapi/
|
||||
endif
|
||||
|
||||
@@ -123,28 +122,16 @@ vhost-user-scsi.o-libs := $(LIBISCSI_LIBS)
|
||||
vhost-user-scsi-obj-y = contrib/vhost-user-scsi/
|
||||
vhost-user-blk-obj-y = contrib/vhost-user-blk/
|
||||
rdmacm-mux-obj-y = contrib/rdmacm-mux/
|
||||
vhost-user-input-obj-y = contrib/vhost-user-input/
|
||||
vhost-user-gpu-obj-y = contrib/vhost-user-gpu/
|
||||
|
||||
######################################################################
|
||||
trace-events-subdirs =
|
||||
trace-events-subdirs += accel/kvm
|
||||
trace-events-subdirs += accel/tcg
|
||||
trace-events-subdirs += crypto
|
||||
trace-events-subdirs += monitor
|
||||
ifeq ($(CONFIG_USER_ONLY),y)
|
||||
trace-events-subdirs += linux-user
|
||||
endif
|
||||
ifeq ($(CONFIG_BLOCK),y)
|
||||
trace-events-subdirs += audio
|
||||
trace-events-subdirs += authz
|
||||
trace-events-subdirs += block
|
||||
trace-events-subdirs += io
|
||||
trace-events-subdirs += nbd
|
||||
trace-events-subdirs += scsi
|
||||
endif
|
||||
ifeq ($(CONFIG_SOFTMMU),y)
|
||||
trace-events-subdirs += chardev
|
||||
trace-events-subdirs += audio
|
||||
trace-events-subdirs += crypto
|
||||
trace-events-subdirs += hw/9pfs
|
||||
trace-events-subdirs += hw/acpi
|
||||
trace-events-subdirs += hw/alpha
|
||||
@@ -153,6 +140,7 @@ trace-events-subdirs += hw/audio
|
||||
trace-events-subdirs += hw/block
|
||||
trace-events-subdirs += hw/block/dataplane
|
||||
trace-events-subdirs += hw/char
|
||||
trace-events-subdirs += hw/display
|
||||
trace-events-subdirs += hw/dma
|
||||
trace-events-subdirs += hw/hppa
|
||||
trace-events-subdirs += hw/i2c
|
||||
@@ -163,7 +151,6 @@ trace-events-subdirs += hw/input
|
||||
trace-events-subdirs += hw/intc
|
||||
trace-events-subdirs += hw/isa
|
||||
trace-events-subdirs += hw/mem
|
||||
trace-events-subdirs += hw/mips
|
||||
trace-events-subdirs += hw/misc
|
||||
trace-events-subdirs += hw/misc/macio
|
||||
trace-events-subdirs += hw/net
|
||||
@@ -186,14 +173,14 @@ trace-events-subdirs += hw/virtio
|
||||
trace-events-subdirs += hw/watchdog
|
||||
trace-events-subdirs += hw/xen
|
||||
trace-events-subdirs += hw/gpio
|
||||
trace-events-subdirs += hw/riscv
|
||||
trace-events-subdirs += io
|
||||
trace-events-subdirs += linux-user
|
||||
trace-events-subdirs += migration
|
||||
trace-events-subdirs += nbd
|
||||
trace-events-subdirs += net
|
||||
trace-events-subdirs += ui
|
||||
endif
|
||||
trace-events-subdirs += hw/display
|
||||
trace-events-subdirs += qapi
|
||||
trace-events-subdirs += qom
|
||||
trace-events-subdirs += scsi
|
||||
trace-events-subdirs += target/arm
|
||||
trace-events-subdirs += target/hppa
|
||||
trace-events-subdirs += target/i386
|
||||
@@ -202,6 +189,7 @@ trace-events-subdirs += target/ppc
|
||||
trace-events-subdirs += target/riscv
|
||||
trace-events-subdirs += target/s390x
|
||||
trace-events-subdirs += target/sparc
|
||||
trace-events-subdirs += ui
|
||||
trace-events-subdirs += util
|
||||
|
||||
trace-events-files = $(SRC_PATH)/trace-events $(trace-events-subdirs:%=$(SRC_PATH)/%/trace-events)
|
||||
|
||||
+8
-29
@@ -45,9 +45,6 @@ include $(SRC_PATH)/tests/tcg/Makefile.include
|
||||
config-target.h: config-target.h-timestamp
|
||||
config-target.h-timestamp: config-target.mak
|
||||
|
||||
config-devices.h: config-devices.h-timestamp
|
||||
config-devices.h-timestamp: config-devices.mak
|
||||
|
||||
ifdef CONFIG_TRACE_SYSTEMTAP
|
||||
stap: $(QEMU_PROG).stp-installed $(QEMU_PROG).stp $(QEMU_PROG)-simpletrace.stp $(QEMU_PROG)-log.stp
|
||||
|
||||
@@ -120,7 +117,6 @@ obj-$(CONFIG_TCG) += fpu/softfloat.o
|
||||
obj-y += target/$(TARGET_BASE_ARCH)/
|
||||
obj-y += disas.o
|
||||
obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
|
||||
LIBS := $(libs_cpu) $(LIBS)
|
||||
|
||||
#########################################################
|
||||
# Linux user emulator target
|
||||
@@ -152,14 +148,14 @@ endif #CONFIG_BSD_USER
|
||||
#########################################################
|
||||
# System emulator target
|
||||
ifdef CONFIG_SOFTMMU
|
||||
obj-y += arch_init.o cpus.o gdbstub.o balloon.o ioport.o
|
||||
obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
|
||||
obj-y += qtest.o
|
||||
obj-y += dump/
|
||||
obj-y += hw/
|
||||
obj-y += monitor/
|
||||
obj-y += qapi/
|
||||
obj-y += memory.o
|
||||
obj-y += memory_mapping.o
|
||||
obj-y += dump.o
|
||||
obj-$(TARGET_X86_64) += win_dump.o
|
||||
obj-y += migration/ram.o
|
||||
LIBS := $(libs_softmmu) $(LIBS)
|
||||
|
||||
@@ -170,8 +166,7 @@ else
|
||||
obj-y += hw/$(TARGET_BASE_ARCH)/
|
||||
endif
|
||||
|
||||
generated-files-y += hmp-commands.h hmp-commands-info.h
|
||||
generated-files-y += config-devices.h
|
||||
GENERATED_FILES += hmp-commands.h hmp-commands-info.h
|
||||
|
||||
endif # CONFIG_SOFTMMU
|
||||
|
||||
@@ -185,7 +180,7 @@ dummy := $(call unnest-vars,.., \
|
||||
block-obj-m \
|
||||
chardev-obj-y \
|
||||
crypto-obj-y \
|
||||
crypto-user-obj-y \
|
||||
crypto-aes-obj-y \
|
||||
qom-obj-y \
|
||||
io-obj-y \
|
||||
common-obj-y \
|
||||
@@ -194,7 +189,7 @@ all-obj-y += $(common-obj-y)
|
||||
all-obj-y += $(qom-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(authz-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y)
|
||||
all-obj-$(CONFIG_USER_ONLY) += $(crypto-user-obj-y)
|
||||
all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
|
||||
|
||||
@@ -241,21 +236,5 @@ ifdef CONFIG_TRACE_SYSTEMTAP
|
||||
$(INSTALL_DATA) $(QEMU_PROG)-log.stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG)-log.stp"
|
||||
endif
|
||||
|
||||
generated-files-y += config-target.h
|
||||
Makefile: $(generated-files-y)
|
||||
|
||||
# Reports/Analysis
|
||||
#
|
||||
# The target specific coverage report only cares about target specific
|
||||
# blobs and not the shared code.
|
||||
#
|
||||
|
||||
%/coverage-report.html:
|
||||
@mkdir -p $*
|
||||
$(call quiet-command,\
|
||||
gcovr -r $(SRC_PATH) --object-directory $(CURDIR) \
|
||||
-p --html --html-details -o $@, \
|
||||
"GEN", "coverage-report.html")
|
||||
|
||||
.PHONY: coverage-report
|
||||
coverage-report: $(CURDIR)/reports/coverage/coverage-report.html
|
||||
GENERATED_FILES += config-target.h
|
||||
Makefile: $(GENERATED_FILES)
|
||||
@@ -1,5 +1,4 @@
|
||||
obj-$(CONFIG_SOFTMMU) += accel.o
|
||||
obj-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_POSIX)) += qtest.o
|
||||
obj-$(CONFIG_KVM) += kvm/
|
||||
obj-$(CONFIG_TCG) += tcg/
|
||||
obj-y += stubs/
|
||||
@@ -107,6 +107,11 @@ void configure_accelerator(MachineState *ms, const char *progname)
|
||||
if (!acc) {
|
||||
continue;
|
||||
}
|
||||
if (acc->available && !acc->available()) {
|
||||
printf("%s not supported for this target\n",
|
||||
acc->name);
|
||||
continue;
|
||||
}
|
||||
ret = accel_init_machine(acc, ms);
|
||||
if (ret < 0) {
|
||||
init_failed = true;
|
||||
|
||||
+29
-303
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <linux/kvm.h>
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
@@ -87,11 +88,9 @@ struct KVMState
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
QTAILQ_HEAD(, kvm_sw_breakpoint) kvm_sw_breakpoints;
|
||||
#endif
|
||||
int max_nested_state_len;
|
||||
int many_ioeventfds;
|
||||
int intx_set_mask;
|
||||
bool sync_mmu;
|
||||
bool manual_dirty_log_protect;
|
||||
/* The man page (and posix) say ioctl numbers are signed int, but
|
||||
* they're not. Linux, glibc and *BSD all treat ioctl numbers as
|
||||
* unsigned, and treating them as signed here can break things */
|
||||
@@ -111,13 +110,6 @@ struct KVMState
|
||||
/* memory encryption */
|
||||
void *memcrypt_handle;
|
||||
int (*memcrypt_encrypt_data)(void *handle, uint8_t *ptr, uint64_t len);
|
||||
|
||||
/* For "info mtree -f" to tell if an MR is registered in KVM */
|
||||
int nr_as;
|
||||
struct KVMAs {
|
||||
KVMMemoryListener *ml;
|
||||
AddressSpace *as;
|
||||
} *as;
|
||||
};
|
||||
|
||||
KVMState *kvm_state;
|
||||
@@ -146,9 +138,6 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||
KVM_CAP_LAST_INFO
|
||||
};
|
||||
|
||||
#define kvm_slots_lock(kml) qemu_mutex_lock(&(kml)->slots_lock)
|
||||
#define kvm_slots_unlock(kml) qemu_mutex_unlock(&(kml)->slots_lock)
|
||||
|
||||
int kvm_get_max_memslots(void)
|
||||
{
|
||||
KVMState *s = KVM_STATE(current_machine->accelerator);
|
||||
@@ -176,7 +165,6 @@ int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Called with KVMMemoryListener.slots_lock held */
|
||||
static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
@@ -194,17 +182,10 @@ static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
|
||||
bool kvm_has_free_slot(MachineState *ms)
|
||||
{
|
||||
KVMState *s = KVM_STATE(ms->accelerator);
|
||||
bool result;
|
||||
KVMMemoryListener *kml = &s->memory_listener;
|
||||
|
||||
kvm_slots_lock(kml);
|
||||
result = !!kvm_get_free_slot(kml);
|
||||
kvm_slots_unlock(kml);
|
||||
|
||||
return result;
|
||||
return kvm_get_free_slot(&s->memory_listener);
|
||||
}
|
||||
|
||||
/* Called with KVMMemoryListener.slots_lock held */
|
||||
static KVMSlot *kvm_alloc_slot(KVMMemoryListener *kml)
|
||||
{
|
||||
KVMSlot *slot = kvm_get_free_slot(kml);
|
||||
@@ -263,21 +244,18 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
|
||||
hwaddr *phys_addr)
|
||||
{
|
||||
KVMMemoryListener *kml = &s->memory_listener;
|
||||
int i, ret = 0;
|
||||
int i;
|
||||
|
||||
kvm_slots_lock(kml);
|
||||
for (i = 0; i < s->nr_slots; i++) {
|
||||
KVMSlot *mem = &kml->slots[i];
|
||||
|
||||
if (ram >= mem->ram && ram < mem->ram + mem->memory_size) {
|
||||
*phys_addr = mem->start_addr + (ram - mem->ram);
|
||||
ret = 1;
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
kvm_slots_unlock(kml);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot, bool new)
|
||||
@@ -314,11 +292,6 @@ int kvm_destroy_vcpu(CPUState *cpu)
|
||||
|
||||
DPRINTF("kvm_destroy_vcpu\n");
|
||||
|
||||
ret = kvm_arch_destroy_vcpu(cpu);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
|
||||
if (mmap_size < 0) {
|
||||
ret = mmap_size;
|
||||
@@ -418,7 +391,6 @@ static int kvm_mem_flags(MemoryRegion *mr)
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* Called with KVMMemoryListener.slots_lock held */
|
||||
static int kvm_slot_update_flags(KVMMemoryListener *kml, KVMSlot *mem,
|
||||
MemoryRegion *mr)
|
||||
{
|
||||
@@ -437,26 +409,19 @@ static int kvm_section_update_flags(KVMMemoryListener *kml,
|
||||
{
|
||||
hwaddr start_addr, size;
|
||||
KVMSlot *mem;
|
||||
int ret = 0;
|
||||
|
||||
size = kvm_align_section(section, &start_addr);
|
||||
if (!size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
kvm_slots_lock(kml);
|
||||
|
||||
mem = kvm_lookup_matching_slot(kml, start_addr, size);
|
||||
if (!mem) {
|
||||
/* We don't have a slot if we want to trap every access. */
|
||||
goto out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = kvm_slot_update_flags(kml, mem, section->mr);
|
||||
|
||||
out:
|
||||
kvm_slots_unlock(kml);
|
||||
return ret;
|
||||
return kvm_slot_update_flags(kml, mem, section->mr);
|
||||
}
|
||||
|
||||
static void kvm_log_start(MemoryListener *listener,
|
||||
@@ -508,15 +473,13 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
|
||||
#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
|
||||
|
||||
/**
|
||||
* kvm_physical_sync_dirty_bitmap - Sync dirty bitmap from kernel space
|
||||
* kvm_physical_sync_dirty_bitmap - Grab dirty bitmap from kernel space
|
||||
* This function updates qemu's dirty bitmap using
|
||||
* memory_region_set_dirty(). This means all bits are set
|
||||
* to dirty.
|
||||
*
|
||||
* This function will first try to fetch dirty bitmap from the kernel,
|
||||
* and then updates qemu's dirty bitmap.
|
||||
*
|
||||
* NOTE: caller must be with kml->slots_lock held.
|
||||
*
|
||||
* @kml: the KVM memory listener object
|
||||
* @section: the memory section to sync the dirty bitmap with
|
||||
* @start_add: start of logged region.
|
||||
* @end_addr: end of logged region.
|
||||
*/
|
||||
static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
|
||||
MemoryRegionSection *section)
|
||||
@@ -525,14 +488,13 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
|
||||
struct kvm_dirty_log d = {};
|
||||
KVMSlot *mem;
|
||||
hwaddr start_addr, size;
|
||||
int ret = 0;
|
||||
|
||||
size = kvm_align_section(section, &start_addr);
|
||||
if (size) {
|
||||
mem = kvm_lookup_matching_slot(kml, start_addr, size);
|
||||
if (!mem) {
|
||||
/* We don't have a slot if we want to trap every access. */
|
||||
goto out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX bad kernel interface alert
|
||||
@@ -549,176 +511,20 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
|
||||
*/
|
||||
size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS),
|
||||
/*HOST_LONG_BITS*/ 64) / 8;
|
||||
if (!mem->dirty_bmap) {
|
||||
/* Allocate on the first log_sync, once and for all */
|
||||
mem->dirty_bmap = g_malloc0(size);
|
||||
}
|
||||
d.dirty_bitmap = g_malloc0(size);
|
||||
|
||||
d.dirty_bitmap = mem->dirty_bmap;
|
||||
d.slot = mem->slot | (kml->as_id << 16);
|
||||
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
|
||||
DPRINTF("ioctl failed %d\n", errno);
|
||||
ret = -1;
|
||||
goto out;
|
||||
g_free(d.dirty_bitmap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kvm_get_dirty_pages_log_range(section, d.dirty_bitmap);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Alignment requirement for KVM_CLEAR_DIRTY_LOG - 64 pages */
|
||||
#define KVM_CLEAR_LOG_SHIFT 6
|
||||
#define KVM_CLEAR_LOG_ALIGN (qemu_real_host_page_size << KVM_CLEAR_LOG_SHIFT)
|
||||
#define KVM_CLEAR_LOG_MASK (-KVM_CLEAR_LOG_ALIGN)
|
||||
|
||||
/**
|
||||
* kvm_physical_log_clear - Clear the kernel's dirty bitmap for range
|
||||
*
|
||||
* NOTE: this will be a no-op if we haven't enabled manual dirty log
|
||||
* protection in the host kernel because in that case this operation
|
||||
* will be done within log_sync().
|
||||
*
|
||||
* @kml: the kvm memory listener
|
||||
* @section: the memory range to clear dirty bitmap
|
||||
*/
|
||||
static int kvm_physical_log_clear(KVMMemoryListener *kml,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
struct kvm_clear_dirty_log d;
|
||||
uint64_t start, end, bmap_start, start_delta, bmap_npages, size;
|
||||
unsigned long *bmap_clear = NULL, psize = qemu_real_host_page_size;
|
||||
KVMSlot *mem = NULL;
|
||||
int ret, i;
|
||||
|
||||
if (!s->manual_dirty_log_protect) {
|
||||
/* No need to do explicit clear */
|
||||
return 0;
|
||||
g_free(d.dirty_bitmap);
|
||||
}
|
||||
|
||||
start = section->offset_within_address_space;
|
||||
size = int128_get64(section->size);
|
||||
|
||||
if (!size) {
|
||||
/* Nothing more we can do... */
|
||||
return 0;
|
||||
}
|
||||
|
||||
kvm_slots_lock(kml);
|
||||
|
||||
/* Find any possible slot that covers the section */
|
||||
for (i = 0; i < s->nr_slots; i++) {
|
||||
mem = &kml->slots[i];
|
||||
if (mem->start_addr <= start &&
|
||||
start + size <= mem->start_addr + mem->memory_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We should always find one memslot until this point, otherwise
|
||||
* there could be something wrong from the upper layer
|
||||
*/
|
||||
assert(mem && i != s->nr_slots);
|
||||
|
||||
/*
|
||||
* We need to extend either the start or the size or both to
|
||||
* satisfy the KVM interface requirement. Firstly, do the start
|
||||
* page alignment on 64 host pages
|
||||
*/
|
||||
bmap_start = (start - mem->start_addr) & KVM_CLEAR_LOG_MASK;
|
||||
start_delta = start - mem->start_addr - bmap_start;
|
||||
bmap_start /= psize;
|
||||
|
||||
/*
|
||||
* The kernel interface has restriction on the size too, that either:
|
||||
*
|
||||
* (1) the size is 64 host pages aligned (just like the start), or
|
||||
* (2) the size fills up until the end of the KVM memslot.
|
||||
*/
|
||||
bmap_npages = DIV_ROUND_UP(size + start_delta, KVM_CLEAR_LOG_ALIGN)
|
||||
<< KVM_CLEAR_LOG_SHIFT;
|
||||
end = mem->memory_size / psize;
|
||||
if (bmap_npages > end - bmap_start) {
|
||||
bmap_npages = end - bmap_start;
|
||||
}
|
||||
start_delta /= psize;
|
||||
|
||||
/*
|
||||
* Prepare the bitmap to clear dirty bits. Here we must guarantee
|
||||
* that we won't clear any unknown dirty bits otherwise we might
|
||||
* accidentally clear some set bits which are not yet synced from
|
||||
* the kernel into QEMU's bitmap, then we'll lose track of the
|
||||
* guest modifications upon those pages (which can directly lead
|
||||
* to guest data loss or panic after migration).
|
||||
*
|
||||
* Layout of the KVMSlot.dirty_bmap:
|
||||
*
|
||||
* |<-------- bmap_npages -----------..>|
|
||||
* [1]
|
||||
* start_delta size
|
||||
* |----------------|-------------|------------------|------------|
|
||||
* ^ ^ ^ ^
|
||||
* | | | |
|
||||
* start bmap_start (start) end
|
||||
* of memslot of memslot
|
||||
*
|
||||
* [1] bmap_npages can be aligned to either 64 pages or the end of slot
|
||||
*/
|
||||
|
||||
assert(bmap_start % BITS_PER_LONG == 0);
|
||||
/* We should never do log_clear before log_sync */
|
||||
assert(mem->dirty_bmap);
|
||||
if (start_delta) {
|
||||
/* Slow path - we need to manipulate a temp bitmap */
|
||||
bmap_clear = bitmap_new(bmap_npages);
|
||||
bitmap_copy_with_src_offset(bmap_clear, mem->dirty_bmap,
|
||||
bmap_start, start_delta + size / psize);
|
||||
/*
|
||||
* We need to fill the holes at start because that was not
|
||||
* specified by the caller and we extended the bitmap only for
|
||||
* 64 pages alignment
|
||||
*/
|
||||
bitmap_clear(bmap_clear, 0, start_delta);
|
||||
d.dirty_bitmap = bmap_clear;
|
||||
} else {
|
||||
/* Fast path - start address aligns well with BITS_PER_LONG */
|
||||
d.dirty_bitmap = mem->dirty_bmap + BIT_WORD(bmap_start);
|
||||
}
|
||||
|
||||
d.first_page = bmap_start;
|
||||
/* It should never overflow. If it happens, say something */
|
||||
assert(bmap_npages <= UINT32_MAX);
|
||||
d.num_pages = bmap_npages;
|
||||
d.slot = mem->slot | (kml->as_id << 16);
|
||||
|
||||
if (kvm_vm_ioctl(s, KVM_CLEAR_DIRTY_LOG, &d) == -1) {
|
||||
ret = -errno;
|
||||
error_report("%s: KVM_CLEAR_DIRTY_LOG failed, slot=%d, "
|
||||
"start=0x%"PRIx64", size=0x%"PRIx32", errno=%d",
|
||||
__func__, d.slot, (uint64_t)d.first_page,
|
||||
(uint32_t)d.num_pages, ret);
|
||||
} else {
|
||||
ret = 0;
|
||||
trace_kvm_clear_dirty_log(d.slot, d.first_page, d.num_pages);
|
||||
}
|
||||
|
||||
/*
|
||||
* After we have updated the remote dirty bitmap, we update the
|
||||
* cached bitmap as well for the memslot, then if another user
|
||||
* clears the same region we know we shouldn't clear it again on
|
||||
* the remote otherwise it's data loss as well.
|
||||
*/
|
||||
bitmap_clear(mem->dirty_bmap, bmap_start + start_delta,
|
||||
size / psize);
|
||||
/* This handles the NULL case well */
|
||||
g_free(bmap_clear);
|
||||
|
||||
kvm_slots_unlock(kml);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kvm_coalesce_mmio_region(MemoryListener *listener,
|
||||
@@ -980,20 +786,16 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
ram = memory_region_get_ram_ptr(mr) + section->offset_within_region +
|
||||
(start_addr - section->offset_within_address_space);
|
||||
|
||||
kvm_slots_lock(kml);
|
||||
|
||||
if (!add) {
|
||||
mem = kvm_lookup_matching_slot(kml, start_addr, size);
|
||||
if (!mem) {
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
|
||||
kvm_physical_sync_dirty_bitmap(kml, section);
|
||||
}
|
||||
|
||||
/* unregister the slot */
|
||||
g_free(mem->dirty_bmap);
|
||||
mem->dirty_bmap = NULL;
|
||||
mem->memory_size = 0;
|
||||
mem->flags = 0;
|
||||
err = kvm_set_user_memory_region(kml, mem, false);
|
||||
@@ -1002,7 +804,7 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
__func__, strerror(-err));
|
||||
abort();
|
||||
}
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/* register the new slot */
|
||||
@@ -1018,9 +820,6 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
strerror(-err));
|
||||
abort();
|
||||
}
|
||||
|
||||
out:
|
||||
kvm_slots_unlock(kml);
|
||||
}
|
||||
|
||||
static void kvm_region_add(MemoryListener *listener,
|
||||
@@ -1047,30 +846,12 @@ static void kvm_log_sync(MemoryListener *listener,
|
||||
KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, listener);
|
||||
int r;
|
||||
|
||||
kvm_slots_lock(kml);
|
||||
r = kvm_physical_sync_dirty_bitmap(kml, section);
|
||||
kvm_slots_unlock(kml);
|
||||
if (r < 0) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_log_clear(MemoryListener *listener,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, listener);
|
||||
int r;
|
||||
|
||||
r = kvm_physical_log_clear(kml, section);
|
||||
if (r < 0) {
|
||||
error_report_once("%s: kvm log clear failed: mr=%s "
|
||||
"offset=%"HWADDR_PRIx" size=%"PRIx64, __func__,
|
||||
section->mr->name, section->offset_within_region,
|
||||
int128_get64(section->size));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_mem_ioeventfd_add(MemoryListener *listener,
|
||||
MemoryRegionSection *section,
|
||||
bool match_data, uint64_t data,
|
||||
@@ -1083,8 +864,8 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener,
|
||||
data, true, int128_get64(section->size),
|
||||
match_data);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "%s: error adding ioeventfd: %s (%d)\n",
|
||||
__func__, strerror(-r), -r);
|
||||
fprintf(stderr, "%s: error adding ioeventfd: %s\n",
|
||||
__func__, strerror(-r));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@@ -1101,8 +882,6 @@ static void kvm_mem_ioeventfd_del(MemoryListener *listener,
|
||||
data, false, int128_get64(section->size),
|
||||
match_data);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "%s: error deleting ioeventfd: %s (%d)\n",
|
||||
__func__, strerror(-r), -r);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@@ -1119,8 +898,8 @@ static void kvm_io_ioeventfd_add(MemoryListener *listener,
|
||||
data, true, int128_get64(section->size),
|
||||
match_data);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "%s: error adding ioeventfd: %s (%d)\n",
|
||||
__func__, strerror(-r), -r);
|
||||
fprintf(stderr, "%s: error adding ioeventfd: %s\n",
|
||||
__func__, strerror(-r));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@@ -1138,8 +917,6 @@ static void kvm_io_ioeventfd_del(MemoryListener *listener,
|
||||
data, false, int128_get64(section->size),
|
||||
match_data);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "%s: error deleting ioeventfd: %s (%d)\n",
|
||||
__func__, strerror(-r), -r);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@@ -1149,7 +926,6 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
|
||||
{
|
||||
int i;
|
||||
|
||||
qemu_mutex_init(&kml->slots_lock);
|
||||
kml->slots = g_malloc0(s->nr_slots * sizeof(KVMSlot));
|
||||
kml->as_id = as_id;
|
||||
|
||||
@@ -1162,18 +938,9 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
|
||||
kml->listener.log_start = kvm_log_start;
|
||||
kml->listener.log_stop = kvm_log_stop;
|
||||
kml->listener.log_sync = kvm_log_sync;
|
||||
kml->listener.log_clear = kvm_log_clear;
|
||||
kml->listener.priority = 10;
|
||||
|
||||
memory_listener_register(&kml->listener, as);
|
||||
|
||||
for (i = 0; i < s->nr_as; ++i) {
|
||||
if (!s->as[i].as) {
|
||||
s->as[i].as = as;
|
||||
s->as[i].ml = kml;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static MemoryListener kvm_io_listener = {
|
||||
@@ -1766,8 +1533,8 @@ static int kvm_init(MachineState *ms)
|
||||
const char *name;
|
||||
int num;
|
||||
} num_cpus[] = {
|
||||
{ "SMP", ms->smp.cpus },
|
||||
{ "hotpluggable", ms->smp.max_cpus },
|
||||
{ "SMP", smp_cpus },
|
||||
{ "hotpluggable", max_cpus },
|
||||
{ NULL, }
|
||||
}, *nc = num_cpus;
|
||||
int soft_vcpus_limit, hard_vcpus_limit;
|
||||
@@ -1824,12 +1591,6 @@ static int kvm_init(MachineState *ms)
|
||||
s->nr_slots = 32;
|
||||
}
|
||||
|
||||
s->nr_as = kvm_check_extension(s, KVM_CAP_MULTI_ADDRESS_SPACE);
|
||||
if (s->nr_as <= 1) {
|
||||
s->nr_as = 1;
|
||||
}
|
||||
s->as = g_new0(struct KVMAs, s->nr_as);
|
||||
|
||||
kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type");
|
||||
if (mc->kvm_type) {
|
||||
type = mc->kvm_type(ms, kvm_type);
|
||||
@@ -1901,17 +1662,6 @@ static int kvm_init(MachineState *ms)
|
||||
s->coalesced_pio = s->coalesced_mmio &&
|
||||
kvm_check_extension(s, KVM_CAP_COALESCED_PIO);
|
||||
|
||||
s->manual_dirty_log_protect =
|
||||
kvm_check_extension(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
|
||||
if (s->manual_dirty_log_protect) {
|
||||
ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0, 1);
|
||||
if (ret) {
|
||||
warn_report("Trying to enable KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 "
|
||||
"but failed. Falling back to the legacy mode. ");
|
||||
s->manual_dirty_log_protect = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KVM_CAP_VCPU_EVENTS
|
||||
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
|
||||
#endif
|
||||
@@ -1923,8 +1673,6 @@ static int kvm_init(MachineState *ms)
|
||||
s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS);
|
||||
#endif
|
||||
|
||||
s->max_nested_state_len = kvm_check_extension(s, KVM_CAP_NESTED_STATE);
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
kvm_direct_msi_allowed = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0);
|
||||
#endif
|
||||
@@ -2050,7 +1798,7 @@ static int kvm_handle_internal_error(CPUState *cpu, struct kvm_run *run)
|
||||
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
|
||||
fprintf(stderr, "emulation failure\n");
|
||||
if (!kvm_arch_stop_on_emulation_error(cpu)) {
|
||||
cpu_dump_state(cpu, stderr, CPU_DUMP_CODE);
|
||||
cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_CODE);
|
||||
return EXCP_INTERRUPT;
|
||||
}
|
||||
}
|
||||
@@ -2341,7 +2089,7 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||
qemu_mutex_lock_iothread();
|
||||
|
||||
if (ret < 0) {
|
||||
cpu_dump_state(cpu, stderr, CPU_DUMP_CODE);
|
||||
cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_CODE);
|
||||
vm_stop(RUN_STATE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
@@ -2492,11 +2240,6 @@ int kvm_has_debugregs(void)
|
||||
return kvm_state->debugregs;
|
||||
}
|
||||
|
||||
int kvm_max_nested_state_length(void)
|
||||
{
|
||||
return kvm_state->max_nested_state_len;
|
||||
}
|
||||
|
||||
int kvm_has_many_ioeventfds(void)
|
||||
{
|
||||
if (!kvm_enabled()) {
|
||||
@@ -2849,28 +2592,11 @@ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target)
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool kvm_accel_has_memory(MachineState *ms, AddressSpace *as,
|
||||
hwaddr start_addr, hwaddr size)
|
||||
{
|
||||
KVMState *kvm = KVM_STATE(ms->accelerator);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kvm->nr_as; ++i) {
|
||||
if (kvm->as[i].as == as && kvm->as[i].ml) {
|
||||
return NULL != kvm_lookup_matching_slot(kvm->as[i].ml,
|
||||
start_addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void kvm_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(oc);
|
||||
ac->name = "KVM";
|
||||
ac->init_machine = kvm_init;
|
||||
ac->has_memory = kvm_accel_has_memory;
|
||||
ac->allowed = &kvm_allowed;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,5 +15,4 @@ kvm_irqchip_release_virq(int virq) "virq %d"
|
||||
kvm_set_ioeventfd_mmio(int fd, uint64_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%" PRIx64 " val=0x%x assign: %d size: %d match: %d"
|
||||
kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%x val=0x%x assign: %d size: %d match: %d"
|
||||
kvm_set_user_memory(uint32_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, int ret) "Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " ret=%d"
|
||||
kvm_clear_dirty_log(uint32_t slot, uint64_t start, uint32_t size) "slot#%"PRId32" start 0x%"PRIx64" size 0x%"PRIx32
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* QTest accelerator code
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "sysemu/accel.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
static int qtest_init_accel(MachineState *ms)
|
||||
{
|
||||
QemuOpts *opts = qemu_opts_create(qemu_find_opts("icount"), NULL, 0,
|
||||
&error_abort);
|
||||
qemu_opt_set(opts, "shift", "0", &error_abort);
|
||||
configure_icount(opts, &error_abort);
|
||||
qemu_opts_del(opts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qtest_accel_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AccelClass *ac = ACCEL_CLASS(oc);
|
||||
ac->name = "QTest";
|
||||
ac->init_machine = qtest_init_accel;
|
||||
ac->allowed = &qtest_allowed;
|
||||
}
|
||||
|
||||
#define TYPE_QTEST_ACCEL ACCEL_CLASS_NAME("qtest")
|
||||
|
||||
static const TypeInfo qtest_accel_type = {
|
||||
.name = TYPE_QTEST_ACCEL,
|
||||
.parent = TYPE_ACCEL,
|
||||
.class_init = qtest_accel_class_init,
|
||||
};
|
||||
|
||||
static void qtest_type_init(void)
|
||||
{
|
||||
type_register_static(&qtest_accel_type);
|
||||
}
|
||||
|
||||
type_init(qtest_type_init);
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/hax.h"
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/hvf.h"
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/whpx.h"
|
||||
|
||||
|
||||
@@ -62,21 +62,21 @@
|
||||
#define ATOMIC_TRACE_RMW do { \
|
||||
uint8_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, false); \
|
||||
\
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, info); \
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, \
|
||||
trace_guest_mem_before_exec(ENV_GET_CPU(env), addr, info); \
|
||||
trace_guest_mem_before_exec(ENV_GET_CPU(env), addr, \
|
||||
info | TRACE_MEM_ST); \
|
||||
} while (0)
|
||||
|
||||
#define ATOMIC_TRACE_LD do { \
|
||||
uint8_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, false); \
|
||||
\
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, info); \
|
||||
trace_guest_mem_before_exec(ENV_GET_CPU(env), addr, info); \
|
||||
} while (0)
|
||||
|
||||
# define ATOMIC_TRACE_ST do { \
|
||||
uint8_t info = glue(trace_mem_build_info_no_se, MEND)(SHIFT, true); \
|
||||
\
|
||||
trace_guest_mem_before_exec(env_cpu(env), addr, info); \
|
||||
trace_guest_mem_before_exec(ENV_GET_CPU(env), addr, info); \
|
||||
} while (0)
|
||||
|
||||
/* Define host-endian atomic operations. Note that END is used within
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
bool tcg_allowed;
|
||||
|
||||
+11
-14
@@ -16,9 +16,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "trace.h"
|
||||
#include "disas/disas.h"
|
||||
@@ -56,7 +54,7 @@ typedef struct SyncClocks {
|
||||
#define MAX_DELAY_PRINT_RATE 2000000000LL
|
||||
#define MAX_NB_PRINTS 100
|
||||
|
||||
static void align_clocks(SyncClocks *sc, CPUState *cpu)
|
||||
static void align_clocks(SyncClocks *sc, const CPUState *cpu)
|
||||
{
|
||||
int64_t cpu_icount;
|
||||
|
||||
@@ -64,7 +62,7 @@ static void align_clocks(SyncClocks *sc, CPUState *cpu)
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_icount = cpu->icount_extra + cpu_neg(cpu)->icount_decr.u16.low;
|
||||
cpu_icount = cpu->icount_extra + cpu->icount_decr.u16.low;
|
||||
sc->diff_clk += cpu_icount_to_ns(sc->last_cpu_icount - cpu_icount);
|
||||
sc->last_cpu_icount = cpu_icount;
|
||||
|
||||
@@ -107,15 +105,15 @@ static void print_delay(const SyncClocks *sc)
|
||||
}
|
||||
}
|
||||
|
||||
static void init_delay_params(SyncClocks *sc, CPUState *cpu)
|
||||
static void init_delay_params(SyncClocks *sc,
|
||||
const CPUState *cpu)
|
||||
{
|
||||
if (!icount_align_option) {
|
||||
return;
|
||||
}
|
||||
sc->realtime_clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT);
|
||||
sc->diff_clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - sc->realtime_clock;
|
||||
sc->last_cpu_icount
|
||||
= cpu->icount_extra + cpu_neg(cpu)->icount_decr.u16.low;
|
||||
sc->last_cpu_icount = cpu->icount_extra + cpu->icount_decr.u16.low;
|
||||
if (sc->diff_clk < max_delay) {
|
||||
max_delay = sc->diff_clk;
|
||||
}
|
||||
@@ -469,7 +467,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
if (cpu->exception_index < 0) {
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (replay_has_exception()
|
||||
&& cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0) {
|
||||
&& cpu->icount_decr.u16.low + cpu->icount_extra == 0) {
|
||||
/* try to cause an exception pending in the log */
|
||||
cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0, curr_cflags()), true);
|
||||
}
|
||||
@@ -527,7 +525,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
* Ensure zeroing happens before reading cpu->exit_request or
|
||||
* cpu->interrupt_request (see also smp_wmb in cpu_exit())
|
||||
*/
|
||||
atomic_mb_set(&cpu_neg(cpu)->icount_decr.u16.high, 0);
|
||||
atomic_mb_set(&cpu->icount_decr.u16.high, 0);
|
||||
|
||||
if (unlikely(atomic_read(&cpu->interrupt_request))) {
|
||||
int interrupt_request;
|
||||
@@ -598,9 +596,8 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
}
|
||||
|
||||
/* Finally, check if we need to exit to the main loop. */
|
||||
if (unlikely(atomic_read(&cpu->exit_request))
|
||||
|| (use_icount
|
||||
&& cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0)) {
|
||||
if (unlikely(atomic_read(&cpu->exit_request)
|
||||
|| (use_icount && cpu->icount_decr.u16.low + cpu->icount_extra == 0))) {
|
||||
atomic_set(&cpu->exit_request, 0);
|
||||
if (cpu->exception_index == -1) {
|
||||
cpu->exception_index = EXCP_INTERRUPT;
|
||||
@@ -627,7 +624,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
}
|
||||
|
||||
*last_tb = NULL;
|
||||
insns_left = atomic_read(&cpu_neg(cpu)->icount_decr.u32);
|
||||
insns_left = atomic_read(&cpu->icount_decr.u32);
|
||||
if (insns_left < 0) {
|
||||
/* Something asked us to stop executing chained TBs; just
|
||||
* continue round the main loop. Whatever requested the exit
|
||||
@@ -646,7 +643,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
cpu_update_icount(cpu);
|
||||
/* Refill decrementer and continue execution. */
|
||||
insns_left = MIN(0xffff, cpu->icount_budget);
|
||||
cpu_neg(cpu)->icount_decr.u16.low = insns_left;
|
||||
cpu->icount_decr.u16.low = insns_left;
|
||||
cpu->icount_extra = cpu->icount_budget - insns_left;
|
||||
if (!cpu->icount_extra) {
|
||||
/* Execute any remaining instructions, then let the main loop
|
||||
|
||||
+174
-725
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* Software MMU support
|
||||
*
|
||||
* Generate helpers used by TCG for qemu_ld/st ops and code load
|
||||
* functions.
|
||||
*
|
||||
* Included from target op helpers and exec.c.
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#if DATA_SIZE == 8
|
||||
#define SUFFIX q
|
||||
#define LSUFFIX q
|
||||
#define SDATA_TYPE int64_t
|
||||
#define DATA_TYPE uint64_t
|
||||
#elif DATA_SIZE == 4
|
||||
#define SUFFIX l
|
||||
#define LSUFFIX l
|
||||
#define SDATA_TYPE int32_t
|
||||
#define DATA_TYPE uint32_t
|
||||
#elif DATA_SIZE == 2
|
||||
#define SUFFIX w
|
||||
#define LSUFFIX uw
|
||||
#define SDATA_TYPE int16_t
|
||||
#define DATA_TYPE uint16_t
|
||||
#elif DATA_SIZE == 1
|
||||
#define SUFFIX b
|
||||
#define LSUFFIX ub
|
||||
#define SDATA_TYPE int8_t
|
||||
#define DATA_TYPE uint8_t
|
||||
#else
|
||||
#error unsupported data size
|
||||
#endif
|
||||
|
||||
|
||||
/* For the benefit of TCG generated code, we want to avoid the complication
|
||||
of ABI-specific return type promotion and always return a value extended
|
||||
to the register size of the host. This is tcg_target_long, except in the
|
||||
case of a 32-bit host and 64-bit data, and for that we always have
|
||||
uint64_t. Don't bother with this widened value for SOFTMMU_CODE_ACCESS. */
|
||||
#if defined(SOFTMMU_CODE_ACCESS) || DATA_SIZE == 8
|
||||
# define WORD_TYPE DATA_TYPE
|
||||
# define USUFFIX SUFFIX
|
||||
#else
|
||||
# define WORD_TYPE tcg_target_ulong
|
||||
# define USUFFIX glue(u, SUFFIX)
|
||||
# define SSUFFIX glue(s, SUFFIX)
|
||||
#endif
|
||||
|
||||
#ifdef SOFTMMU_CODE_ACCESS
|
||||
#define READ_ACCESS_TYPE MMU_INST_FETCH
|
||||
#define ADDR_READ addr_code
|
||||
#else
|
||||
#define READ_ACCESS_TYPE MMU_DATA_LOAD
|
||||
#define ADDR_READ addr_read
|
||||
#endif
|
||||
|
||||
#if DATA_SIZE == 8
|
||||
# define BSWAP(X) bswap64(X)
|
||||
#elif DATA_SIZE == 4
|
||||
# define BSWAP(X) bswap32(X)
|
||||
#elif DATA_SIZE == 2
|
||||
# define BSWAP(X) bswap16(X)
|
||||
#else
|
||||
# define BSWAP(X) (X)
|
||||
#endif
|
||||
|
||||
#if DATA_SIZE == 1
|
||||
# define helper_le_ld_name glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)
|
||||
# define helper_be_ld_name helper_le_ld_name
|
||||
# define helper_le_lds_name glue(glue(helper_ret_ld, SSUFFIX), MMUSUFFIX)
|
||||
# define helper_be_lds_name helper_le_lds_name
|
||||
# define helper_le_st_name glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)
|
||||
# define helper_be_st_name helper_le_st_name
|
||||
#else
|
||||
# define helper_le_ld_name glue(glue(helper_le_ld, USUFFIX), MMUSUFFIX)
|
||||
# define helper_be_ld_name glue(glue(helper_be_ld, USUFFIX), MMUSUFFIX)
|
||||
# define helper_le_lds_name glue(glue(helper_le_ld, SSUFFIX), MMUSUFFIX)
|
||||
# define helper_be_lds_name glue(glue(helper_be_ld, SSUFFIX), MMUSUFFIX)
|
||||
# define helper_le_st_name glue(glue(helper_le_st, SUFFIX), MMUSUFFIX)
|
||||
# define helper_be_st_name glue(glue(helper_be_st, SUFFIX), MMUSUFFIX)
|
||||
#endif
|
||||
|
||||
#ifndef SOFTMMU_CODE_ACCESS
|
||||
static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
|
||||
size_t mmu_idx, size_t index,
|
||||
target_ulong addr,
|
||||
uintptr_t retaddr,
|
||||
bool recheck,
|
||||
MMUAccessType access_type)
|
||||
{
|
||||
CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
|
||||
return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, recheck,
|
||||
access_type, DATA_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
uintptr_t mmu_idx = get_mmuidx(oi);
|
||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
||||
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
|
||||
target_ulong tlb_addr = entry->ADDR_READ;
|
||||
unsigned a_bits = get_alignment_bits(get_memop(oi));
|
||||
uintptr_t haddr;
|
||||
DATA_TYPE res;
|
||||
|
||||
if (addr & ((1 << a_bits) - 1)) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
}
|
||||
|
||||
/* If the TLB entry is for a different page, reload and try again. */
|
||||
if (!tlb_hit(tlb_addr, addr)) {
|
||||
if (!VICTIM_TLB_HIT(ADDR_READ, addr)) {
|
||||
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
index = tlb_index(env, mmu_idx, addr);
|
||||
entry = tlb_entry(env, mmu_idx, addr);
|
||||
}
|
||||
tlb_addr = entry->ADDR_READ;
|
||||
}
|
||||
|
||||
/* Handle an IO access. */
|
||||
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
goto do_unaligned_access;
|
||||
}
|
||||
|
||||
/* ??? Note that the io helpers always read data in the target
|
||||
byte ordering. We should push the LE/BE request down into io. */
|
||||
res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
|
||||
tlb_addr & TLB_RECHECK,
|
||||
READ_ACCESS_TYPE);
|
||||
res = TGT_LE(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Handle slow unaligned access (it spans two pages or IO). */
|
||||
if (DATA_SIZE > 1
|
||||
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
|
||||
>= TARGET_PAGE_SIZE)) {
|
||||
target_ulong addr1, addr2;
|
||||
DATA_TYPE res1, res2;
|
||||
unsigned shift;
|
||||
do_unaligned_access:
|
||||
addr1 = addr & ~(DATA_SIZE - 1);
|
||||
addr2 = addr1 + DATA_SIZE;
|
||||
res1 = helper_le_ld_name(env, addr1, oi, retaddr);
|
||||
res2 = helper_le_ld_name(env, addr2, oi, retaddr);
|
||||
shift = (addr & (DATA_SIZE - 1)) * 8;
|
||||
|
||||
/* Little-endian combine. */
|
||||
res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
|
||||
return res;
|
||||
}
|
||||
|
||||
haddr = addr + entry->addend;
|
||||
#if DATA_SIZE == 1
|
||||
res = glue(glue(ld, LSUFFIX), _p)((uint8_t *)haddr);
|
||||
#else
|
||||
res = glue(glue(ld, LSUFFIX), _le_p)((uint8_t *)haddr);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
#if DATA_SIZE > 1
|
||||
WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
uintptr_t mmu_idx = get_mmuidx(oi);
|
||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
||||
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
|
||||
target_ulong tlb_addr = entry->ADDR_READ;
|
||||
unsigned a_bits = get_alignment_bits(get_memop(oi));
|
||||
uintptr_t haddr;
|
||||
DATA_TYPE res;
|
||||
|
||||
if (addr & ((1 << a_bits) - 1)) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
}
|
||||
|
||||
/* If the TLB entry is for a different page, reload and try again. */
|
||||
if (!tlb_hit(tlb_addr, addr)) {
|
||||
if (!VICTIM_TLB_HIT(ADDR_READ, addr)) {
|
||||
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
|
||||
mmu_idx, retaddr);
|
||||
index = tlb_index(env, mmu_idx, addr);
|
||||
entry = tlb_entry(env, mmu_idx, addr);
|
||||
}
|
||||
tlb_addr = entry->ADDR_READ;
|
||||
}
|
||||
|
||||
/* Handle an IO access. */
|
||||
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
goto do_unaligned_access;
|
||||
}
|
||||
|
||||
/* ??? Note that the io helpers always read data in the target
|
||||
byte ordering. We should push the LE/BE request down into io. */
|
||||
res = glue(io_read, SUFFIX)(env, mmu_idx, index, addr, retaddr,
|
||||
tlb_addr & TLB_RECHECK,
|
||||
READ_ACCESS_TYPE);
|
||||
res = TGT_BE(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Handle slow unaligned access (it spans two pages or IO). */
|
||||
if (DATA_SIZE > 1
|
||||
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
|
||||
>= TARGET_PAGE_SIZE)) {
|
||||
target_ulong addr1, addr2;
|
||||
DATA_TYPE res1, res2;
|
||||
unsigned shift;
|
||||
do_unaligned_access:
|
||||
addr1 = addr & ~(DATA_SIZE - 1);
|
||||
addr2 = addr1 + DATA_SIZE;
|
||||
res1 = helper_be_ld_name(env, addr1, oi, retaddr);
|
||||
res2 = helper_be_ld_name(env, addr2, oi, retaddr);
|
||||
shift = (addr & (DATA_SIZE - 1)) * 8;
|
||||
|
||||
/* Big-endian combine. */
|
||||
res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
|
||||
return res;
|
||||
}
|
||||
|
||||
haddr = addr + entry->addend;
|
||||
res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
|
||||
return res;
|
||||
}
|
||||
#endif /* DATA_SIZE > 1 */
|
||||
|
||||
#ifndef SOFTMMU_CODE_ACCESS
|
||||
|
||||
/* Provide signed versions of the load routines as well. We can of course
|
||||
avoid this for 64-bit data, or for 32-bit data on 32-bit host. */
|
||||
#if DATA_SIZE * 8 < TCG_TARGET_REG_BITS
|
||||
WORD_TYPE helper_le_lds_name(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return (SDATA_TYPE)helper_le_ld_name(env, addr, oi, retaddr);
|
||||
}
|
||||
|
||||
# if DATA_SIZE > 1
|
||||
WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
return (SDATA_TYPE)helper_be_ld_name(env, addr, oi, retaddr);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static inline void glue(io_write, SUFFIX)(CPUArchState *env,
|
||||
size_t mmu_idx, size_t index,
|
||||
DATA_TYPE val,
|
||||
target_ulong addr,
|
||||
uintptr_t retaddr,
|
||||
bool recheck)
|
||||
{
|
||||
CPUIOTLBEntry *iotlbentry = &env->iotlb[mmu_idx][index];
|
||||
return io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
|
||||
recheck, DATA_SIZE);
|
||||
}
|
||||
|
||||
void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
uintptr_t mmu_idx = get_mmuidx(oi);
|
||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
||||
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
|
||||
target_ulong tlb_addr = tlb_addr_write(entry);
|
||||
unsigned a_bits = get_alignment_bits(get_memop(oi));
|
||||
uintptr_t haddr;
|
||||
|
||||
if (addr & ((1 << a_bits) - 1)) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
}
|
||||
|
||||
/* If the TLB entry is for a different page, reload and try again. */
|
||||
if (!tlb_hit(tlb_addr, addr)) {
|
||||
if (!VICTIM_TLB_HIT(addr_write, addr)) {
|
||||
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
index = tlb_index(env, mmu_idx, addr);
|
||||
entry = tlb_entry(env, mmu_idx, addr);
|
||||
}
|
||||
tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
|
||||
}
|
||||
|
||||
/* Handle an IO access. */
|
||||
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
goto do_unaligned_access;
|
||||
}
|
||||
|
||||
/* ??? Note that the io helpers always read data in the target
|
||||
byte ordering. We should push the LE/BE request down into io. */
|
||||
val = TGT_LE(val);
|
||||
glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr,
|
||||
retaddr, tlb_addr & TLB_RECHECK);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle slow unaligned access (it spans two pages or IO). */
|
||||
if (DATA_SIZE > 1
|
||||
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
|
||||
>= TARGET_PAGE_SIZE)) {
|
||||
int i;
|
||||
target_ulong page2;
|
||||
CPUTLBEntry *entry2;
|
||||
do_unaligned_access:
|
||||
/* Ensure the second page is in the TLB. Note that the first page
|
||||
is already guaranteed to be filled, and that the second page
|
||||
cannot evict the first. */
|
||||
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
|
||||
entry2 = tlb_entry(env, mmu_idx, page2);
|
||||
if (!tlb_hit_page(tlb_addr_write(entry2), page2)
|
||||
&& !VICTIM_TLB_HIT(addr_write, page2)) {
|
||||
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
}
|
||||
|
||||
/* XXX: not efficient, but simple. */
|
||||
/* This loop must go in the forward direction to avoid issues
|
||||
with self-modifying code in Windows 64-bit. */
|
||||
for (i = 0; i < DATA_SIZE; ++i) {
|
||||
/* Little-endian extract. */
|
||||
uint8_t val8 = val >> (i * 8);
|
||||
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
|
||||
oi, retaddr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
haddr = addr + entry->addend;
|
||||
#if DATA_SIZE == 1
|
||||
glue(glue(st, SUFFIX), _p)((uint8_t *)haddr, val);
|
||||
#else
|
||||
glue(glue(st, SUFFIX), _le_p)((uint8_t *)haddr, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DATA_SIZE > 1
|
||||
void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
|
||||
TCGMemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
uintptr_t mmu_idx = get_mmuidx(oi);
|
||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
||||
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
|
||||
target_ulong tlb_addr = tlb_addr_write(entry);
|
||||
unsigned a_bits = get_alignment_bits(get_memop(oi));
|
||||
uintptr_t haddr;
|
||||
|
||||
if (addr & ((1 << a_bits) - 1)) {
|
||||
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
}
|
||||
|
||||
/* If the TLB entry is for a different page, reload and try again. */
|
||||
if (!tlb_hit(tlb_addr, addr)) {
|
||||
if (!VICTIM_TLB_HIT(addr_write, addr)) {
|
||||
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
index = tlb_index(env, mmu_idx, addr);
|
||||
entry = tlb_entry(env, mmu_idx, addr);
|
||||
}
|
||||
tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
|
||||
}
|
||||
|
||||
/* Handle an IO access. */
|
||||
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
||||
if ((addr & (DATA_SIZE - 1)) != 0) {
|
||||
goto do_unaligned_access;
|
||||
}
|
||||
|
||||
/* ??? Note that the io helpers always read data in the target
|
||||
byte ordering. We should push the LE/BE request down into io. */
|
||||
val = TGT_BE(val);
|
||||
glue(io_write, SUFFIX)(env, mmu_idx, index, val, addr, retaddr,
|
||||
tlb_addr & TLB_RECHECK);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle slow unaligned access (it spans two pages or IO). */
|
||||
if (DATA_SIZE > 1
|
||||
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
|
||||
>= TARGET_PAGE_SIZE)) {
|
||||
int i;
|
||||
target_ulong page2;
|
||||
CPUTLBEntry *entry2;
|
||||
do_unaligned_access:
|
||||
/* Ensure the second page is in the TLB. Note that the first page
|
||||
is already guaranteed to be filled, and that the second page
|
||||
cannot evict the first. */
|
||||
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
|
||||
entry2 = tlb_entry(env, mmu_idx, page2);
|
||||
if (!tlb_hit_page(tlb_addr_write(entry2), page2)
|
||||
&& !VICTIM_TLB_HIT(addr_write, page2)) {
|
||||
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
|
||||
mmu_idx, retaddr);
|
||||
}
|
||||
|
||||
/* XXX: not efficient, but simple */
|
||||
/* This loop must go in the forward direction to avoid issues
|
||||
with self-modifying code. */
|
||||
for (i = 0; i < DATA_SIZE; ++i) {
|
||||
/* Big-endian extract. */
|
||||
uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8));
|
||||
glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
|
||||
oi, retaddr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
haddr = addr + entry->addend;
|
||||
glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
|
||||
}
|
||||
#endif /* DATA_SIZE > 1 */
|
||||
#endif /* !defined(SOFTMMU_CODE_ACCESS) */
|
||||
|
||||
#undef READ_ACCESS_TYPE
|
||||
#undef DATA_TYPE
|
||||
#undef SUFFIX
|
||||
#undef LSUFFIX
|
||||
#undef DATA_SIZE
|
||||
#undef ADDR_READ
|
||||
#undef WORD_TYPE
|
||||
#undef SDATA_TYPE
|
||||
#undef USUFFIX
|
||||
#undef SSUFFIX
|
||||
#undef BSWAP
|
||||
#undef helper_le_ld_name
|
||||
#undef helper_be_ld_name
|
||||
#undef helper_le_lds_name
|
||||
#undef helper_be_lds_name
|
||||
#undef helper_le_st_name
|
||||
#undef helper_be_st_name
|
||||
+5
-3
@@ -26,14 +26,15 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/accel.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "qom/object.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qom/cpu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
unsigned long tcg_tb_size;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* mask must never be zero, except for A20 change call */
|
||||
static void tcg_handle_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
@@ -50,7 +51,7 @@ static void tcg_handle_interrupt(CPUState *cpu, int mask)
|
||||
if (!qemu_cpu_is_self(cpu)) {
|
||||
qemu_cpu_kick(cpu);
|
||||
} else {
|
||||
atomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
|
||||
atomic_set(&cpu->icount_decr.u16.high, -1);
|
||||
if (use_icount &&
|
||||
!cpu->can_do_io
|
||||
&& (mask & ~old_mask) != 0) {
|
||||
@@ -58,6 +59,7 @@ static void tcg_handle_interrupt(CPUState *cpu, int mask)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tcg_init(MachineState *ms)
|
||||
{
|
||||
|
||||
@@ -398,54 +398,6 @@ void HELPER(gvec_neg64)(void *d, void *a, uint32_t desc)
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_abs8)(void *d, void *a, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(int8_t)) {
|
||||
int8_t aa = *(int8_t *)(a + i);
|
||||
*(int8_t *)(d + i) = aa < 0 ? -aa : aa;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_abs16)(void *d, void *a, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(int16_t)) {
|
||||
int16_t aa = *(int16_t *)(a + i);
|
||||
*(int16_t *)(d + i) = aa < 0 ? -aa : aa;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_abs32)(void *d, void *a, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(int32_t)) {
|
||||
int32_t aa = *(int32_t *)(a + i);
|
||||
*(int32_t *)(d + i) = aa < 0 ? -aa : aa;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_abs64)(void *d, void *a, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(int64_t)) {
|
||||
int64_t aa = *(int64_t *)(a + i);
|
||||
*(int64_t *)(d + i) = aa < 0 ? -aa : aa;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_mov)(void *d, void *a, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
@@ -773,150 +725,6 @@ void HELPER(gvec_sar64i)(void *d, void *a, uint32_t desc)
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_shl8v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
uint8_t sh = *(uint8_t *)(b + i) & 7;
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) << sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_shl16v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
uint8_t sh = *(uint16_t *)(b + i) & 15;
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) << sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_shl32v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
uint8_t sh = *(uint32_t *)(b + i) & 31;
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) << sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_shl64v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
uint8_t sh = *(uint64_t *)(b + i) & 63;
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) << sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_shr8v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
|
||||
uint8_t sh = *(uint8_t *)(b + i) & 7;
|
||||
*(uint8_t *)(d + i) = *(uint8_t *)(a + i) >> sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_shr16v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
|
||||
uint8_t sh = *(uint16_t *)(b + i) & 15;
|
||||
*(uint16_t *)(d + i) = *(uint16_t *)(a + i) >> sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_shr32v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
|
||||
uint8_t sh = *(uint32_t *)(b + i) & 31;
|
||||
*(uint32_t *)(d + i) = *(uint32_t *)(a + i) >> sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_shr64v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
|
||||
uint8_t sh = *(uint64_t *)(b + i) & 63;
|
||||
*(uint64_t *)(d + i) = *(uint64_t *)(a + i) >> sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_sar8v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(int8_t)) {
|
||||
uint8_t sh = *(uint8_t *)(b + i) & 7;
|
||||
*(int8_t *)(d + i) = *(int8_t *)(a + i) >> sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_sar16v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(int16_t)) {
|
||||
uint8_t sh = *(uint16_t *)(b + i) & 15;
|
||||
*(int16_t *)(d + i) = *(int16_t *)(a + i) >> sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_sar32v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(int32_t)) {
|
||||
uint8_t sh = *(uint32_t *)(b + i) & 31;
|
||||
*(int32_t *)(d + i) = *(int32_t *)(a + i) >> sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_sar64v)(void *d, void *a, void *b, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(int64_t)) {
|
||||
uint8_t sh = *(uint64_t *)(b + i) & 63;
|
||||
*(int64_t *)(d + i) = *(int64_t *)(a + i) >> sh;
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
/* If vectors are enabled, the compiler fills in -1 for true.
|
||||
Otherwise, we must take care of this by hand. */
|
||||
#ifdef CONFIG_VECTOR16
|
||||
@@ -1444,17 +1252,3 @@ void HELPER(gvec_umax64)(void *d, void *a, void *b, uint32_t desc)
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
|
||||
void HELPER(gvec_bitsel)(void *d, void *a, void *b, void *c, uint32_t desc)
|
||||
{
|
||||
intptr_t oprsz = simd_oprsz(desc);
|
||||
intptr_t i;
|
||||
|
||||
for (i = 0; i < oprsz; i += sizeof(vec64)) {
|
||||
vec64 aa = *(vec64 *)(a + i);
|
||||
vec64 bb = *(vec64 *)(b + i);
|
||||
vec64 cc = *(vec64 *)(c + i);
|
||||
*(vec64 *)(d + i) = (bb & aa) | (cc & ~aa);
|
||||
}
|
||||
clear_high(d, oprsz, desc);
|
||||
}
|
||||
@@ -146,7 +146,7 @@ uint64_t HELPER(ctpop_i64)(uint64_t arg)
|
||||
|
||||
void *HELPER(lookup_tb_ptr)(CPUArchState *env)
|
||||
{
|
||||
CPUState *cpu = env_cpu(env);
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
TranslationBlock *tb;
|
||||
target_ulong cs_base, pc;
|
||||
uint32_t flags;
|
||||
@@ -165,5 +165,5 @@ void *HELPER(lookup_tb_ptr)(CPUArchState *env)
|
||||
|
||||
void HELPER(exit_atomic)(CPUArchState *env)
|
||||
{
|
||||
cpu_loop_exit_atomic(env_cpu(env), GETPC());
|
||||
cpu_loop_exit_atomic(ENV_GET_CPU(env), GETPC());
|
||||
}
|
||||
@@ -225,11 +225,6 @@ DEF_HELPER_FLAGS_3(gvec_neg16, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_neg32, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_neg64, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_abs8, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_abs16, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_abs32, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_abs64, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_not, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_and, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_or, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
@@ -259,21 +254,6 @@ DEF_HELPER_FLAGS_3(gvec_sar16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_sar32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_sar64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_shl8v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_shl16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_shl32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_shl64v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_shr8v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_shr16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_shr32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_shr64v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_sar8v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sar16v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sar32v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sar64v, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_eq8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_eq16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_eq32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
@@ -303,5 +283,3 @@ DEF_HELPER_FLAGS_4(gvec_leu8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_leu16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_leu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_leu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(gvec_bitsel, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
+38
-78
@@ -16,10 +16,9 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
#include "qemu-common.h"
|
||||
#define NO_CPU_IO_DEFS
|
||||
#include "cpu.h"
|
||||
#include "trace.h"
|
||||
@@ -51,12 +50,10 @@
|
||||
#include "translate-all.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "exec/log.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/tcg.h"
|
||||
|
||||
/* #define DEBUG_TB_INVALIDATE */
|
||||
/* #define DEBUG_TB_FLUSH */
|
||||
@@ -366,7 +363,7 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
assert(use_icount);
|
||||
/* Reset the cycle counter to the start of the block
|
||||
and shift if to the number of actually executed instructions */
|
||||
cpu_neg(cpu)->icount_decr.u16.low += num_insns - i;
|
||||
cpu->icount_decr.u16.low += num_insns - i;
|
||||
}
|
||||
restore_state_to_opc(env, tb, data);
|
||||
|
||||
@@ -1676,7 +1673,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
tb_page_addr_t phys_pc, phys_page2;
|
||||
target_ulong virt_page2;
|
||||
tcg_insn_unit *gen_code_buf;
|
||||
int gen_code_size, search_size, max_insns;
|
||||
int gen_code_size, search_size;
|
||||
#ifdef CONFIG_PROFILER
|
||||
TCGProfile *prof = &tcg_ctx->prof;
|
||||
int64_t ti;
|
||||
@@ -1694,17 +1691,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
cflags &= ~CF_CLUSTER_MASK;
|
||||
cflags |= cpu->cluster_index << CF_CLUSTER_SHIFT;
|
||||
|
||||
max_insns = cflags & CF_COUNT_MASK;
|
||||
if (max_insns == 0) {
|
||||
max_insns = CF_COUNT_MASK;
|
||||
}
|
||||
if (max_insns > TCG_MAX_INSNS) {
|
||||
max_insns = TCG_MAX_INSNS;
|
||||
}
|
||||
if (cpu->singlestep_enabled || singlestep) {
|
||||
max_insns = 1;
|
||||
}
|
||||
|
||||
buffer_overflow:
|
||||
tb = tb_alloc(pc);
|
||||
if (unlikely(!tb)) {
|
||||
@@ -1724,7 +1710,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
tb->cflags = cflags;
|
||||
tb->trace_vcpu_dstate = *cpu->trace_dstate;
|
||||
tcg_ctx->tb_cflags = cflags;
|
||||
tb_overflow:
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
/* includes aborted translations because of exceptions */
|
||||
@@ -1734,8 +1719,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
|
||||
tcg_func_start(tcg_ctx);
|
||||
|
||||
tcg_ctx->cpu = env_cpu(env);
|
||||
gen_intermediate_code(cpu, tb, max_insns);
|
||||
tcg_ctx->cpu = ENV_GET_CPU(env);
|
||||
gen_intermediate_code(cpu, tb);
|
||||
tcg_ctx->cpu = NULL;
|
||||
|
||||
trace_translate_block(tb, tb->pc, tb->tc.ptr);
|
||||
@@ -1758,39 +1743,14 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
ti = profile_getclock();
|
||||
#endif
|
||||
|
||||
/* ??? Overflow could be handled better here. In particular, we
|
||||
don't need to re-do gen_intermediate_code, nor should we re-do
|
||||
the tcg optimization currently hidden inside tcg_gen_code. All
|
||||
that should be required is to flush the TBs, allocate a new TB,
|
||||
re-initialize it per above, and re-do the actual code generation. */
|
||||
gen_code_size = tcg_gen_code(tcg_ctx, tb);
|
||||
if (unlikely(gen_code_size < 0)) {
|
||||
switch (gen_code_size) {
|
||||
case -1:
|
||||
/*
|
||||
* Overflow of code_gen_buffer, or the current slice of it.
|
||||
*
|
||||
* TODO: We don't need to re-do gen_intermediate_code, nor
|
||||
* should we re-do the tcg optimization currently hidden
|
||||
* inside tcg_gen_code. All that should be required is to
|
||||
* flush the TBs, allocate a new TB, re-initialize it per
|
||||
* above, and re-do the actual code generation.
|
||||
*/
|
||||
goto buffer_overflow;
|
||||
|
||||
case -2:
|
||||
/*
|
||||
* The code generated for the TranslationBlock is too large.
|
||||
* The maximum size allowed by the unwind info is 64k.
|
||||
* There may be stricter constraints from relocations
|
||||
* in the tcg backend.
|
||||
*
|
||||
* Try again with half as many insns as we attempted this time.
|
||||
* If a single insn overflows, there's a bug somewhere...
|
||||
*/
|
||||
max_insns = tb->icount;
|
||||
assert(max_insns > 1);
|
||||
max_insns /= 2;
|
||||
goto tb_overflow;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
goto buffer_overflow;
|
||||
}
|
||||
search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size);
|
||||
if (unlikely(search_size < 0)) {
|
||||
@@ -2202,7 +2162,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
if ((env->hflags & MIPS_HFLAG_BMASK) != 0
|
||||
&& env->active_tc.PC != tb->pc) {
|
||||
env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
|
||||
cpu_neg(cpu)->icount_decr.u16.low++;
|
||||
cpu->icount_decr.u16.low++;
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
n = 2;
|
||||
}
|
||||
@@ -2210,7 +2170,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
|
||||
&& env->pc != tb->pc) {
|
||||
env->pc -= 2;
|
||||
cpu_neg(cpu)->icount_decr.u16.low++;
|
||||
cpu->icount_decr.u16.low++;
|
||||
env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
|
||||
n = 2;
|
||||
}
|
||||
@@ -2254,7 +2214,8 @@ void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr)
|
||||
tb_jmp_cache_clear_page(cpu, addr);
|
||||
}
|
||||
|
||||
static void print_qht_statistics(struct qht_stats hst)
|
||||
static void print_qht_statistics(FILE *f, fprintf_function cpu_fprintf,
|
||||
struct qht_stats hst)
|
||||
{
|
||||
uint32_t hgram_opts;
|
||||
size_t hgram_bins;
|
||||
@@ -2263,7 +2224,7 @@ static void print_qht_statistics(struct qht_stats hst)
|
||||
if (!hst.head_buckets) {
|
||||
return;
|
||||
}
|
||||
qemu_printf("TB hash buckets %zu/%zu (%0.2f%% head buckets used)\n",
|
||||
cpu_fprintf(f, "TB hash buckets %zu/%zu (%0.2f%% head buckets used)\n",
|
||||
hst.used_head_buckets, hst.head_buckets,
|
||||
(double)hst.used_head_buckets / hst.head_buckets * 100);
|
||||
|
||||
@@ -2273,7 +2234,7 @@ static void print_qht_statistics(struct qht_stats hst)
|
||||
hgram_opts |= QDIST_PR_NODECIMAL;
|
||||
}
|
||||
hgram = qdist_pr(&hst.occupancy, 10, hgram_opts);
|
||||
qemu_printf("TB hash occupancy %0.2f%% avg chain occ. Histogram: %s\n",
|
||||
cpu_fprintf(f, "TB hash occupancy %0.2f%% avg chain occ. Histogram: %s\n",
|
||||
qdist_avg(&hst.occupancy) * 100, hgram);
|
||||
g_free(hgram);
|
||||
|
||||
@@ -2286,7 +2247,7 @@ static void print_qht_statistics(struct qht_stats hst)
|
||||
hgram_opts |= QDIST_PR_NODECIMAL | QDIST_PR_NOBINRANGE;
|
||||
}
|
||||
hgram = qdist_pr(&hst.chain, hgram_bins, hgram_opts);
|
||||
qemu_printf("TB hash avg chain %0.3f buckets. Histogram: %s\n",
|
||||
cpu_fprintf(f, "TB hash avg chain %0.3f buckets. Histogram: %s\n",
|
||||
qdist_avg(&hst.chain), hgram);
|
||||
g_free(hgram);
|
||||
}
|
||||
@@ -2324,7 +2285,7 @@ static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
|
||||
return false;
|
||||
}
|
||||
|
||||
void dump_exec_info(void)
|
||||
void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
|
||||
{
|
||||
struct tb_tree_stats tst = {};
|
||||
struct qht_stats hst;
|
||||
@@ -2333,49 +2294,48 @@ void dump_exec_info(void)
|
||||
tcg_tb_foreach(tb_tree_stats_iter, &tst);
|
||||
nb_tbs = tst.nb_tbs;
|
||||
/* XXX: avoid using doubles ? */
|
||||
qemu_printf("Translation buffer state:\n");
|
||||
cpu_fprintf(f, "Translation buffer state:\n");
|
||||
/*
|
||||
* Report total code size including the padding and TB structs;
|
||||
* otherwise users might think "-tb-size" is not honoured.
|
||||
* For avg host size we use the precise numbers from tb_tree_stats though.
|
||||
*/
|
||||
qemu_printf("gen code size %zu/%zu\n",
|
||||
cpu_fprintf(f, "gen code size %zu/%zu\n",
|
||||
tcg_code_size(), tcg_code_capacity());
|
||||
qemu_printf("TB count %zu\n", nb_tbs);
|
||||
qemu_printf("TB avg target size %zu max=%zu bytes\n",
|
||||
cpu_fprintf(f, "TB count %zu\n", nb_tbs);
|
||||
cpu_fprintf(f, "TB avg target size %zu max=%zu bytes\n",
|
||||
nb_tbs ? tst.target_size / nb_tbs : 0,
|
||||
tst.max_target_size);
|
||||
qemu_printf("TB avg host size %zu bytes (expansion ratio: %0.1f)\n",
|
||||
cpu_fprintf(f, "TB avg host size %zu bytes (expansion ratio: %0.1f)\n",
|
||||
nb_tbs ? tst.host_size / nb_tbs : 0,
|
||||
tst.target_size ? (double)tst.host_size / tst.target_size : 0);
|
||||
qemu_printf("cross page TB count %zu (%zu%%)\n", tst.cross_page,
|
||||
nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
|
||||
qemu_printf("direct jump count %zu (%zu%%) (2 jumps=%zu %zu%%)\n",
|
||||
cpu_fprintf(f, "cross page TB count %zu (%zu%%)\n", tst.cross_page,
|
||||
nb_tbs ? (tst.cross_page * 100) / nb_tbs : 0);
|
||||
cpu_fprintf(f, "direct jump count %zu (%zu%%) (2 jumps=%zu %zu%%)\n",
|
||||
tst.direct_jmp_count,
|
||||
nb_tbs ? (tst.direct_jmp_count * 100) / nb_tbs : 0,
|
||||
tst.direct_jmp2_count,
|
||||
nb_tbs ? (tst.direct_jmp2_count * 100) / nb_tbs : 0);
|
||||
|
||||
qht_statistics_init(&tb_ctx.htable, &hst);
|
||||
print_qht_statistics(hst);
|
||||
print_qht_statistics(f, cpu_fprintf, hst);
|
||||
qht_statistics_destroy(&hst);
|
||||
|
||||
qemu_printf("\nStatistics:\n");
|
||||
qemu_printf("TB flush count %u\n",
|
||||
cpu_fprintf(f, "\nStatistics:\n");
|
||||
cpu_fprintf(f, "TB flush count %u\n",
|
||||
atomic_read(&tb_ctx.tb_flush_count));
|
||||
qemu_printf("TB invalidate count %zu\n",
|
||||
tcg_tb_phys_invalidate_count());
|
||||
cpu_fprintf(f, "TB invalidate count %zu\n", tcg_tb_phys_invalidate_count());
|
||||
|
||||
tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
|
||||
qemu_printf("TLB full flushes %zu\n", flush_full);
|
||||
qemu_printf("TLB partial flushes %zu\n", flush_part);
|
||||
qemu_printf("TLB elided flushes %zu\n", flush_elide);
|
||||
tcg_dump_info();
|
||||
cpu_fprintf(f, "TLB full flushes %zu\n", flush_full);
|
||||
cpu_fprintf(f, "TLB partial flushes %zu\n", flush_part);
|
||||
cpu_fprintf(f, "TLB elided flushes %zu\n", flush_elide);
|
||||
tcg_dump_info(f, cpu_fprintf);
|
||||
}
|
||||
|
||||
void dump_opcount_info(void)
|
||||
void dump_opcount_info(FILE *f, fprintf_function cpu_fprintf)
|
||||
{
|
||||
tcg_dump_op_count();
|
||||
tcg_dump_op_count(f, cpu_fprintf);
|
||||
}
|
||||
|
||||
#else /* CONFIG_USER_ONLY */
|
||||
@@ -2384,7 +2344,7 @@ void cpu_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
g_assert(qemu_mutex_iothread_locked());
|
||||
cpu->interrupt_request |= mask;
|
||||
atomic_set(&cpu_neg(cpu)->icount_decr.u16.high, -1);
|
||||
atomic_set(&cpu->icount_decr.u16.high, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+14
-2
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "cpu.h"
|
||||
#include "tcg/tcg.h"
|
||||
@@ -31,7 +32,7 @@ void translator_loop_temp_check(DisasContextBase *db)
|
||||
}
|
||||
|
||||
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
CPUState *cpu, TranslationBlock *tb, int max_insns)
|
||||
CPUState *cpu, TranslationBlock *tb)
|
||||
{
|
||||
int bp_insn = 0;
|
||||
|
||||
@@ -41,9 +42,20 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
db->pc_next = db->pc_first;
|
||||
db->is_jmp = DISAS_NEXT;
|
||||
db->num_insns = 0;
|
||||
db->max_insns = max_insns;
|
||||
db->singlestep_enabled = cpu->singlestep_enabled;
|
||||
|
||||
/* Instruction counting */
|
||||
db->max_insns = tb_cflags(db->tb) & CF_COUNT_MASK;
|
||||
if (db->max_insns == 0) {
|
||||
db->max_insns = CF_COUNT_MASK;
|
||||
}
|
||||
if (db->max_insns > TCG_MAX_INSNS) {
|
||||
db->max_insns = TCG_MAX_INSNS;
|
||||
}
|
||||
if (db->singlestep_enabled || singlestep) {
|
||||
db->max_insns = 1;
|
||||
}
|
||||
|
||||
ops->init_disas_context(db, cpu);
|
||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qom/cpu.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
+51
-62
@@ -63,57 +63,28 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
|
||||
{
|
||||
CPUState *cpu = current_cpu;
|
||||
CPUClass *cc;
|
||||
int ret;
|
||||
unsigned long address = (unsigned long)info->si_addr;
|
||||
MMUAccessType access_type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD;
|
||||
|
||||
switch (helper_retaddr) {
|
||||
default:
|
||||
/*
|
||||
* Fault during host memory operation within a helper function.
|
||||
* The helper's host return address, saved here, gives us a
|
||||
* pointer into the generated code that will unwind to the
|
||||
* correct guest pc.
|
||||
*/
|
||||
/* We must handle PC addresses from two different sources:
|
||||
* a call return address and a signal frame address.
|
||||
*
|
||||
* Within cpu_restore_state_from_tb we assume the former and adjust
|
||||
* the address by -GETPC_ADJ so that the address is within the call
|
||||
* insn so that addr does not accidentally match the beginning of the
|
||||
* next guest insn.
|
||||
*
|
||||
* However, when the PC comes from the signal frame, it points to
|
||||
* the actual faulting host insn and not a call insn. Subtracting
|
||||
* GETPC_ADJ in that case may accidentally match the previous guest insn.
|
||||
*
|
||||
* So for the later case, adjust forward to compensate for what
|
||||
* will be done later by cpu_restore_state_from_tb.
|
||||
*/
|
||||
if (helper_retaddr) {
|
||||
pc = helper_retaddr;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
/*
|
||||
* Fault during host memory operation within generated code.
|
||||
* (Or, a unrelated bug within qemu, but we can't tell from here).
|
||||
*
|
||||
* We take the host pc from the signal frame. However, we cannot
|
||||
* use that value directly. Within cpu_restore_state_from_tb, we
|
||||
* assume PC comes from GETPC(), as used by the helper functions,
|
||||
* so we adjust the address by -GETPC_ADJ to form an address that
|
||||
* is within the call insn, so that the address does not accidentially
|
||||
* match the beginning of the next guest insn. However, when the
|
||||
* pc comes from the signal frame it points to the actual faulting
|
||||
* host memory insn and not the return from a call insn.
|
||||
*
|
||||
* Therefore, adjust to compensate for what will be done later
|
||||
* by cpu_restore_state_from_tb.
|
||||
*/
|
||||
} else {
|
||||
pc += GETPC_ADJ;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/*
|
||||
* Fault during host read for translation, or loosely, "execution".
|
||||
*
|
||||
* The guest pc is already pointing to the start of the TB for which
|
||||
* code is being generated. If the guest translator manages the
|
||||
* page crossings correctly, this is exactly the correct address
|
||||
* (and if the translator doesn't handle page boundaries correctly
|
||||
* there's little we can do about that here). Therefore, do not
|
||||
* trigger the unwinder.
|
||||
*
|
||||
* Like tb_gen_code, release the memory lock before cpu_loop_exit.
|
||||
*/
|
||||
pc = 0;
|
||||
access_type = MMU_INST_FETCH;
|
||||
mmap_unlock();
|
||||
break;
|
||||
}
|
||||
|
||||
/* For synchronous signals we expect to be coming from the vCPU
|
||||
@@ -163,7 +134,7 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
|
||||
* currently executing TB was modified and must be exited
|
||||
* immediately. Clear helper_retaddr for next execution.
|
||||
*/
|
||||
clear_helper_retaddr();
|
||||
helper_retaddr = 0;
|
||||
cpu_exit_tb_from_sighandler(cpu, old_set);
|
||||
/* NORETURN */
|
||||
|
||||
@@ -176,16 +147,35 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
|
||||
are still valid segv ones */
|
||||
address = h2g_nocheck(address);
|
||||
|
||||
/*
|
||||
* There is no way the target can handle this other than raising
|
||||
* an exception. Undo signal and retaddr state prior to longjmp.
|
||||
*/
|
||||
sigprocmask(SIG_SETMASK, old_set, NULL);
|
||||
clear_helper_retaddr();
|
||||
|
||||
cc = CPU_GET_CLASS(cpu);
|
||||
cc->tlb_fill(cpu, address, 0, access_type, MMU_USER_IDX, false, pc);
|
||||
g_assert_not_reached();
|
||||
/* see if it is an MMU fault */
|
||||
g_assert(cc->handle_mmu_fault);
|
||||
ret = cc->handle_mmu_fault(cpu, address, 0, is_write, MMU_USER_IDX);
|
||||
|
||||
if (ret == 0) {
|
||||
/* The MMU fault was handled without causing real CPU fault.
|
||||
* Retain helper_retaddr for a possible second fault.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* All other paths lead to cpu_exit; clear helper_retaddr
|
||||
* for next execution.
|
||||
*/
|
||||
helper_retaddr = 0;
|
||||
|
||||
if (ret < 0) {
|
||||
return 0; /* not an MMU fault */
|
||||
}
|
||||
|
||||
/* Now we have a real cpu fault. */
|
||||
cpu_restore_state(cpu, pc, true);
|
||||
|
||||
sigprocmask(SIG_SETMASK, old_set, NULL);
|
||||
cpu_loop_exit(cpu);
|
||||
|
||||
/* never comes here */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(__i386__)
|
||||
@@ -708,17 +698,16 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||
{
|
||||
/* Enforce qemu required alignment. */
|
||||
if (unlikely(addr & (size - 1))) {
|
||||
cpu_loop_exit_atomic(env_cpu(env), retaddr);
|
||||
cpu_loop_exit_atomic(ENV_GET_CPU(env), retaddr);
|
||||
}
|
||||
void *ret = g2h(addr);
|
||||
set_helper_retaddr(retaddr);
|
||||
return ret;
|
||||
helper_retaddr = retaddr;
|
||||
return g2h(addr);
|
||||
}
|
||||
|
||||
/* Macro to call the above, with local variables from the use context. */
|
||||
#define ATOMIC_MMU_DECLS do {} while (0)
|
||||
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, GETPC())
|
||||
#define ATOMIC_MMU_CLEANUP do { clear_helper_retaddr(); } while (0)
|
||||
#define ATOMIC_MMU_CLEANUP do { helper_retaddr = 0; } while (0)
|
||||
|
||||
#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
|
||||
#define EXTRA_ARGS
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
|
||||
+1
-2
@@ -21,11 +21,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <alsa/asoundlib.h>
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "audio.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "audio.h"
|
||||
@@ -32,7 +31,6 @@
|
||||
#include "qapi/qapi-visit-audio.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "audio.h"
|
||||
#include "audio_int.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "audio.h"
|
||||
|
||||
#define AUDIO_CAP "audio-pt"
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
#include <CoreAudio/CoreAudio.h>
|
||||
#include <pthread.h> /* pthread_X */
|
||||
|
||||
#include "qemu/module.h"
|
||||
#include "qemu-common.h"
|
||||
#include "audio.h"
|
||||
|
||||
#define AUDIO_CAP "coreaudio"
|
||||
|
||||
+1
-1
@@ -27,12 +27,12 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "audio.h"
|
||||
|
||||
#define AUDIO_CAP "dsound"
|
||||
#include "audio_int.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/module.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "audio.h"
|
||||
|
||||
+1
-2
@@ -21,10 +21,9 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "audio.h"
|
||||
#include "qemu/timer.h"
|
||||
|
||||
|
||||
+1
-2
@@ -21,12 +21,11 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "audio.h"
|
||||
#include "trace.h"
|
||||
|
||||
+2
-3
@@ -1,7 +1,6 @@
|
||||
/* public domain */
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu-common.h"
|
||||
#include "audio.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
|
||||
@@ -618,7 +617,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
|
||||
ss.rate = as->freq;
|
||||
|
||||
ba.fragsize = pa_usec_to_bytes(ppdo->latency, &ss);
|
||||
ba.maxlength = pa_usec_to_bytes(ppdo->latency * 2, &ss);
|
||||
ba.maxlength = -1;
|
||||
ba.minreq = -1;
|
||||
ba.prebuf = -1;
|
||||
|
||||
|
||||
+1
-2
@@ -21,11 +21,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
#include "qemu/module.h"
|
||||
#include "qemu-common.h"
|
||||
#include "audio.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "ui/qemu-spice.h"
|
||||
|
||||
@@ -21,10 +21,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "audio.h"
|
||||
|
||||
+1
-2
@@ -20,8 +20,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "authz/base.h"
|
||||
#include "qemu/module.h"
|
||||
#include "trace.h"
|
||||
#include "authz/trace.h"
|
||||
|
||||
bool qauthz_is_allowed(QAuthZ *authz,
|
||||
const char *identity,
|
||||
|
||||
+1
-2
@@ -20,10 +20,9 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "authz/list.h"
|
||||
#include "trace.h"
|
||||
#include "authz/trace.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "qapi/qapi-visit-authz.h"
|
||||
#include "qemu/module.h"
|
||||
|
||||
static bool qauthz_list_is_allowed(QAuthZ *authz,
|
||||
const char *identity,
|
||||
|
||||
+1
-2
@@ -20,10 +20,9 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "authz/listfile.h"
|
||||
#include "trace.h"
|
||||
#include "authz/trace.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qemu/filemonitor.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
|
||||
+1
-2
@@ -20,8 +20,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "authz/pamacct.h"
|
||||
#include "trace.h"
|
||||
#include "qemu/module.h"
|
||||
#include "authz/trace.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
+1
-2
@@ -20,8 +20,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "authz/simple.h"
|
||||
#include "trace.h"
|
||||
#include "qemu/module.h"
|
||||
#include "authz/trace.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
|
||||
static bool qauthz_simple_is_allowed(QAuthZ *authz,
|
||||
|
||||
@@ -14,6 +14,4 @@ common-obj-y += cryptodev-vhost.o
|
||||
common-obj-$(CONFIG_VHOST_CRYPTO) += cryptodev-vhost-user.o
|
||||
endif
|
||||
|
||||
common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_VIRTIO)) += vhost-user.o
|
||||
|
||||
common-obj-$(CONFIG_LINUX) += hostmem-memfd.o
|
||||
@@ -9,11 +9,10 @@
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
#include "sysemu/hostmem.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
|
||||
@@ -9,13 +9,12 @@
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/hostmem.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "qemu/memfd.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
|
||||
|
||||
@@ -9,11 +9,9 @@
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/hostmem.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
|
||||
#define TYPE_MEMORY_BACKEND_RAM "memory-backend-ram"
|
||||
|
||||
+2
-4
@@ -222,7 +222,6 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value,
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
|
||||
if (backend->force_prealloc) {
|
||||
if (value) {
|
||||
@@ -242,7 +241,7 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value,
|
||||
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||
uint64_t sz = memory_region_size(&backend->mr);
|
||||
|
||||
os_mem_prealloc(fd, ptr, sz, ms->smp.cpus, &local_err);
|
||||
os_mem_prealloc(fd, ptr, sz, smp_cpus, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
@@ -312,7 +311,6 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(uc);
|
||||
HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
Error *local_err = NULL;
|
||||
void *ptr;
|
||||
uint64_t sz;
|
||||
@@ -377,7 +375,7 @@ host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
|
||||
*/
|
||||
if (backend->prealloc) {
|
||||
os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz,
|
||||
ms->smp.cpus, &local_err);
|
||||
smp_cpus, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "chardev/char-fe.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/module.h"
|
||||
|
||||
#define TYPE_RNG_EGD "rng-egd"
|
||||
#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD)
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
|
||||
struct RngRandom
|
||||
{
|
||||
@@ -113,7 +112,7 @@ static void rng_random_init(Object *obj)
|
||||
rng_random_set_filename,
|
||||
NULL);
|
||||
|
||||
s->filename = g_strdup("/dev/urandom");
|
||||
s->filename = g_strdup("/dev/random");
|
||||
s->fd = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "sysemu/rng.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
|
||||
void rng_backend_request_entropy(RngBackend *s, size_t size,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "sysemu/tpm.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "block/thread-pool.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* QEMU vhost-user backend
|
||||
*
|
||||
* Copyright (C) 2018 Red Hat Inc
|
||||
*
|
||||
* Authors:
|
||||
* Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/qdev.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "sysemu/vhost-user-backend.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "io/channel-command.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
|
||||
static bool
|
||||
ioeventfd_enabled(void)
|
||||
{
|
||||
return kvm_enabled() && kvm_eventfds_enabled();
|
||||
}
|
||||
|
||||
int
|
||||
vhost_user_backend_dev_init(VhostUserBackend *b, VirtIODevice *vdev,
|
||||
unsigned nvqs, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
assert(!b->vdev && vdev);
|
||||
|
||||
if (!ioeventfd_enabled()) {
|
||||
error_setg(errp, "vhost initialization failed: requires kvm");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!vhost_user_init(&b->vhost_user, &b->chr, errp)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
b->vdev = vdev;
|
||||
b->dev.nvqs = nvqs;
|
||||
b->dev.vqs = g_new(struct vhost_virtqueue, nvqs);
|
||||
|
||||
ret = vhost_dev_init(&b->dev, &b->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "vhost initialization failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
vhost_user_backend_start(VhostUserBackend *b)
|
||||
{
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(b->vdev)));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
int ret, i ;
|
||||
|
||||
if (b->started) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!k->set_guest_notifiers) {
|
||||
error_report("binding does not support guest notifiers");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = vhost_dev_enable_notifiers(&b->dev, b->vdev);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = k->set_guest_notifiers(qbus->parent, b->dev.nvqs, true);
|
||||
if (ret < 0) {
|
||||
error_report("Error binding guest notifier");
|
||||
goto err_host_notifiers;
|
||||
}
|
||||
|
||||
b->dev.acked_features = b->vdev->guest_features;
|
||||
ret = vhost_dev_start(&b->dev, b->vdev);
|
||||
if (ret < 0) {
|
||||
error_report("Error start vhost dev");
|
||||
goto err_guest_notifiers;
|
||||
}
|
||||
|
||||
/* guest_notifier_mask/pending not used yet, so just unmask
|
||||
* everything here. virtio-pci will do the right thing by
|
||||
* enabling/disabling irqfd.
|
||||
*/
|
||||
for (i = 0; i < b->dev.nvqs; i++) {
|
||||
vhost_virtqueue_mask(&b->dev, b->vdev,
|
||||
b->dev.vq_index + i, false);
|
||||
}
|
||||
|
||||
b->started = true;
|
||||
return;
|
||||
|
||||
err_guest_notifiers:
|
||||
k->set_guest_notifiers(qbus->parent, b->dev.nvqs, false);
|
||||
err_host_notifiers:
|
||||
vhost_dev_disable_notifiers(&b->dev, b->vdev);
|
||||
}
|
||||
|
||||
void
|
||||
vhost_user_backend_stop(VhostUserBackend *b)
|
||||
{
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(b->vdev)));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
int ret = 0;
|
||||
|
||||
if (!b->started) {
|
||||
return;
|
||||
}
|
||||
|
||||
vhost_dev_stop(&b->dev, b->vdev);
|
||||
|
||||
if (k->set_guest_notifiers) {
|
||||
ret = k->set_guest_notifiers(qbus->parent,
|
||||
b->dev.nvqs, false);
|
||||
if (ret < 0) {
|
||||
error_report("vhost guest notifier cleanup failed: %d", ret);
|
||||
}
|
||||
}
|
||||
assert(ret >= 0);
|
||||
|
||||
vhost_dev_disable_notifiers(&b->dev, b->vdev);
|
||||
b->started = false;
|
||||
}
|
||||
|
||||
static void set_chardev(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
VhostUserBackend *b = VHOST_USER_BACKEND(obj);
|
||||
Chardev *chr;
|
||||
|
||||
if (b->completed) {
|
||||
error_setg(errp, QERR_PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
g_free(b->chr_name);
|
||||
b->chr_name = g_strdup(value);
|
||||
|
||||
chr = qemu_chr_find(b->chr_name);
|
||||
if (chr == NULL) {
|
||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||
"Chardev '%s' not found", b->chr_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!qemu_chr_fe_init(&b->chr, chr, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
b->completed = true;
|
||||
/* could call vhost_dev_init() so early message can be exchanged */
|
||||
}
|
||||
|
||||
static char *get_chardev(Object *obj, Error **errp)
|
||||
{
|
||||
VhostUserBackend *b = VHOST_USER_BACKEND(obj);
|
||||
Chardev *chr = qemu_chr_fe_get_driver(&b->chr);
|
||||
|
||||
if (chr && chr->label) {
|
||||
return g_strdup(chr->label);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void vhost_user_backend_init(Object *obj)
|
||||
{
|
||||
object_property_add_str(obj, "chardev", get_chardev, set_chardev, NULL);
|
||||
}
|
||||
|
||||
static void vhost_user_backend_finalize(Object *obj)
|
||||
{
|
||||
VhostUserBackend *b = VHOST_USER_BACKEND(obj);
|
||||
|
||||
g_free(b->dev.vqs);
|
||||
g_free(b->chr_name);
|
||||
|
||||
vhost_user_cleanup(&b->vhost_user);
|
||||
qemu_chr_fe_deinit(&b->chr, true);
|
||||
}
|
||||
|
||||
static const TypeInfo vhost_user_backend_info = {
|
||||
.name = TYPE_VHOST_USER_BACKEND,
|
||||
.parent = TYPE_OBJECT,
|
||||
.instance_size = sizeof(VhostUserBackend),
|
||||
.instance_init = vhost_user_backend_init,
|
||||
.instance_finalize = vhost_user_backend_finalize,
|
||||
.class_size = sizeof(VhostUserBackendClass),
|
||||
};
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&vhost_user_backend_info);
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/atomic.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
@@ -911,11 +911,10 @@ static bool bdrv_child_cb_drained_poll(BdrvChild *child)
|
||||
return bdrv_drain_poll(bs, false, NULL, false);
|
||||
}
|
||||
|
||||
static void bdrv_child_cb_drained_end(BdrvChild *child,
|
||||
int *drained_end_counter)
|
||||
static void bdrv_child_cb_drained_end(BdrvChild *child)
|
||||
{
|
||||
BlockDriverState *bs = child->opaque;
|
||||
bdrv_drained_end_no_poll(bs, drained_end_counter);
|
||||
bdrv_drained_end(bs);
|
||||
}
|
||||
|
||||
static void bdrv_child_cb_attach(BdrvChild *child)
|
||||
@@ -937,20 +936,6 @@ static int bdrv_child_cb_inactivate(BdrvChild *child)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool bdrv_child_cb_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
|
||||
GSList **ignore, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = child->opaque;
|
||||
return bdrv_can_set_aio_context(bs, ctx, ignore, errp);
|
||||
}
|
||||
|
||||
static void bdrv_child_cb_set_aio_ctx(BdrvChild *child, AioContext *ctx,
|
||||
GSList **ignore)
|
||||
{
|
||||
BlockDriverState *bs = child->opaque;
|
||||
return bdrv_set_aio_context_ignore(bs, ctx, ignore);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the options and flags that a temporary snapshot should get, based on
|
||||
* the originally requested flags (the originally requested image will have
|
||||
@@ -1018,8 +1003,6 @@ const BdrvChildRole child_file = {
|
||||
.attach = bdrv_child_cb_attach,
|
||||
.detach = bdrv_child_cb_detach,
|
||||
.inactivate = bdrv_child_cb_inactivate,
|
||||
.can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
|
||||
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1046,8 +1029,6 @@ const BdrvChildRole child_format = {
|
||||
.attach = bdrv_child_cb_attach,
|
||||
.detach = bdrv_child_cb_detach,
|
||||
.inactivate = bdrv_child_cb_inactivate,
|
||||
.can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
|
||||
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
|
||||
};
|
||||
|
||||
static void bdrv_backing_attach(BdrvChild *c)
|
||||
@@ -1171,8 +1152,6 @@ const BdrvChildRole child_backing = {
|
||||
.drained_end = bdrv_child_cb_drained_end,
|
||||
.inactivate = bdrv_child_cb_inactivate,
|
||||
.update_filename = bdrv_backing_update_filename,
|
||||
.can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
|
||||
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
|
||||
};
|
||||
|
||||
static int bdrv_open_flags(BlockDriverState *bs, int flags)
|
||||
@@ -1707,12 +1686,9 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
|
||||
static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
|
||||
uint64_t perm, uint64_t shared,
|
||||
GSList *ignore_children,
|
||||
bool *tighten_restrictions, Error **errp);
|
||||
GSList *ignore_children, Error **errp);
|
||||
static void bdrv_child_abort_perm_update(BdrvChild *c);
|
||||
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared);
|
||||
static void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
|
||||
uint64_t *shared_perm);
|
||||
|
||||
typedef struct BlockReopenQueueEntry {
|
||||
bool prepared;
|
||||
@@ -1767,10 +1743,11 @@ static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
|
||||
uint64_t parent_perm, uint64_t parent_shared,
|
||||
uint64_t *nperm, uint64_t *nshared)
|
||||
{
|
||||
assert(bs->drv && bs->drv->bdrv_child_perm);
|
||||
bs->drv->bdrv_child_perm(bs, c, role, reopen_queue,
|
||||
parent_perm, parent_shared,
|
||||
nperm, nshared);
|
||||
if (bs->drv && bs->drv->bdrv_child_perm) {
|
||||
bs->drv->bdrv_child_perm(bs, c, role, reopen_queue,
|
||||
parent_perm, parent_shared,
|
||||
nperm, nshared);
|
||||
}
|
||||
/* TODO Take force_share from reopen_queue */
|
||||
if (child_bs && child_bs->force_share) {
|
||||
*nshared = BLK_PERM_ALL;
|
||||
@@ -1783,61 +1760,23 @@ static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
|
||||
* permissions of all its parents. This involves checking whether all necessary
|
||||
* permission changes to child nodes can be performed.
|
||||
*
|
||||
* Will set *tighten_restrictions to true if and only if new permissions have to
|
||||
* be taken or currently shared permissions are to be unshared. Otherwise,
|
||||
* errors are not fatal as long as the caller accepts that the restrictions
|
||||
* remain tighter than they need to be. The caller still has to abort the
|
||||
* transaction.
|
||||
* @tighten_restrictions cannot be used together with @q: When reopening, we may
|
||||
* encounter fatal errors even though no restrictions are to be tightened. For
|
||||
* example, changing a node from RW to RO will fail if the WRITE permission is
|
||||
* to be kept.
|
||||
*
|
||||
* A call to this function must always be followed by a call to bdrv_set_perm()
|
||||
* or bdrv_abort_perm_update().
|
||||
*/
|
||||
static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
|
||||
uint64_t cumulative_perms,
|
||||
uint64_t cumulative_shared_perms,
|
||||
GSList *ignore_children,
|
||||
bool *tighten_restrictions, Error **errp)
|
||||
GSList *ignore_children, Error **errp)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
BdrvChild *c;
|
||||
int ret;
|
||||
|
||||
assert(!q || !tighten_restrictions);
|
||||
|
||||
if (tighten_restrictions) {
|
||||
uint64_t current_perms, current_shared;
|
||||
uint64_t added_perms, removed_shared_perms;
|
||||
|
||||
bdrv_get_cumulative_perm(bs, ¤t_perms, ¤t_shared);
|
||||
|
||||
added_perms = cumulative_perms & ~current_perms;
|
||||
removed_shared_perms = current_shared & ~cumulative_shared_perms;
|
||||
|
||||
*tighten_restrictions = added_perms || removed_shared_perms;
|
||||
}
|
||||
|
||||
/* Write permissions never work with read-only images */
|
||||
if ((cumulative_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) &&
|
||||
!bdrv_is_writable_after_reopen(bs, q))
|
||||
{
|
||||
if (!bdrv_is_writable_after_reopen(bs, NULL)) {
|
||||
error_setg(errp, "Block node is read-only");
|
||||
} else {
|
||||
uint64_t current_perms, current_shared;
|
||||
bdrv_get_cumulative_perm(bs, ¤t_perms, ¤t_shared);
|
||||
if (current_perms & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED)) {
|
||||
error_setg(errp, "Cannot make block node read-only, there is "
|
||||
"a writer on it");
|
||||
} else {
|
||||
error_setg(errp, "Cannot make block node read-only and create "
|
||||
"a writer on it");
|
||||
}
|
||||
}
|
||||
|
||||
error_setg(errp, "Block node is read-only");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@@ -1860,18 +1799,11 @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
|
||||
/* Check all children */
|
||||
QLIST_FOREACH(c, &bs->children, next) {
|
||||
uint64_t cur_perm, cur_shared;
|
||||
bool child_tighten_restr;
|
||||
|
||||
bdrv_child_perm(bs, c->bs, c, c->role, q,
|
||||
cumulative_perms, cumulative_shared_perms,
|
||||
&cur_perm, &cur_shared);
|
||||
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
|
||||
tighten_restrictions ? &child_tighten_restr
|
||||
: NULL,
|
||||
errp);
|
||||
if (tighten_restrictions) {
|
||||
*tighten_restrictions |= child_tighten_restr;
|
||||
}
|
||||
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared,
|
||||
ignore_children, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -1995,23 +1927,17 @@ char *bdrv_perm_names(uint64_t perm)
|
||||
* set, the BdrvChild objects in this list are ignored in the calculations;
|
||||
* this allows checking permission updates for an existing reference.
|
||||
*
|
||||
* See bdrv_check_perm() for the semantics of @tighten_restrictions.
|
||||
*
|
||||
* Needs to be followed by a call to either bdrv_set_perm() or
|
||||
* bdrv_abort_perm_update(). */
|
||||
static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
|
||||
uint64_t new_used_perm,
|
||||
uint64_t new_shared_perm,
|
||||
GSList *ignore_children,
|
||||
bool *tighten_restrictions,
|
||||
Error **errp)
|
||||
GSList *ignore_children, Error **errp)
|
||||
{
|
||||
BdrvChild *c;
|
||||
uint64_t cumulative_perms = new_used_perm;
|
||||
uint64_t cumulative_shared_perms = new_shared_perm;
|
||||
|
||||
assert(!q || !tighten_restrictions);
|
||||
|
||||
/* There is no reason why anyone couldn't tolerate write_unchanged */
|
||||
assert(new_shared_perm & BLK_PERM_WRITE_UNCHANGED);
|
||||
|
||||
@@ -2023,11 +1949,6 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
|
||||
if ((new_used_perm & c->shared_perm) != new_used_perm) {
|
||||
char *user = bdrv_child_user_desc(c);
|
||||
char *perm_names = bdrv_perm_names(new_used_perm & ~c->shared_perm);
|
||||
|
||||
if (tighten_restrictions) {
|
||||
*tighten_restrictions = true;
|
||||
}
|
||||
|
||||
error_setg(errp, "Conflicts with use by %s as '%s', which does not "
|
||||
"allow '%s' on %s",
|
||||
user, c->name, perm_names, bdrv_get_node_name(c->bs));
|
||||
@@ -2039,11 +1960,6 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
|
||||
if ((c->perm & new_shared_perm) != c->perm) {
|
||||
char *user = bdrv_child_user_desc(c);
|
||||
char *perm_names = bdrv_perm_names(c->perm & ~new_shared_perm);
|
||||
|
||||
if (tighten_restrictions) {
|
||||
*tighten_restrictions = true;
|
||||
}
|
||||
|
||||
error_setg(errp, "Conflicts with use by %s as '%s', which uses "
|
||||
"'%s' on %s",
|
||||
user, c->name, perm_names, bdrv_get_node_name(c->bs));
|
||||
@@ -2057,21 +1973,19 @@ static int bdrv_check_update_perm(BlockDriverState *bs, BlockReopenQueue *q,
|
||||
}
|
||||
|
||||
return bdrv_check_perm(bs, q, cumulative_perms, cumulative_shared_perms,
|
||||
ignore_children, tighten_restrictions, errp);
|
||||
ignore_children, errp);
|
||||
}
|
||||
|
||||
/* Needs to be followed by a call to either bdrv_child_set_perm() or
|
||||
* bdrv_child_abort_perm_update(). */
|
||||
static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
|
||||
uint64_t perm, uint64_t shared,
|
||||
GSList *ignore_children,
|
||||
bool *tighten_restrictions, Error **errp)
|
||||
GSList *ignore_children, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ignore_children = g_slist_prepend(g_slist_copy(ignore_children), c);
|
||||
ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children,
|
||||
tighten_restrictions, errp);
|
||||
ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
|
||||
g_slist_free(ignore_children);
|
||||
|
||||
if (ret < 0) {
|
||||
@@ -2122,26 +2036,11 @@ static void bdrv_child_abort_perm_update(BdrvChild *c)
|
||||
int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
|
||||
Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
bool tighten_restrictions;
|
||||
|
||||
ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL,
|
||||
&tighten_restrictions, &local_err);
|
||||
ret = bdrv_child_check_perm(c, NULL, perm, shared, NULL, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_child_abort_perm_update(c);
|
||||
if (tighten_restrictions) {
|
||||
error_propagate(errp, local_err);
|
||||
} else {
|
||||
/*
|
||||
* Our caller may intend to only loosen restrictions and
|
||||
* does not expect this function to fail. Errors are not
|
||||
* fatal in such a case, so we can just hide them from our
|
||||
* caller.
|
||||
*/
|
||||
error_free(local_err);
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2150,18 +2049,6 @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
|
||||
{
|
||||
uint64_t parent_perms, parent_shared;
|
||||
uint64_t perms, shared;
|
||||
|
||||
bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared);
|
||||
bdrv_child_perm(bs, c->bs, c, c->role, NULL, parent_perms, parent_shared,
|
||||
&perms, &shared);
|
||||
|
||||
return bdrv_child_try_set_perm(c, perms, shared, errp);
|
||||
}
|
||||
|
||||
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
|
||||
const BdrvChildRole *role,
|
||||
BlockReopenQueue *reopen_queue,
|
||||
@@ -2252,19 +2139,24 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
|
||||
if (child->role->detach) {
|
||||
child->role->detach(child);
|
||||
}
|
||||
while (child->parent_quiesce_counter) {
|
||||
bdrv_parent_drained_end_single(child);
|
||||
if (old_bs->quiesce_counter && child->role->drained_end) {
|
||||
int num = old_bs->quiesce_counter;
|
||||
if (child->role->parent_is_bds) {
|
||||
num -= bdrv_drain_all_count;
|
||||
}
|
||||
assert(num >= 0);
|
||||
for (i = 0; i < num; i++) {
|
||||
child->role->drained_end(child);
|
||||
}
|
||||
}
|
||||
QLIST_REMOVE(child, next_parent);
|
||||
} else {
|
||||
assert(child->parent_quiesce_counter == 0);
|
||||
}
|
||||
|
||||
child->bs = new_bs;
|
||||
|
||||
if (new_bs) {
|
||||
QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent);
|
||||
if (new_bs->quiesce_counter) {
|
||||
if (new_bs->quiesce_counter && child->role->drained_begin) {
|
||||
int num = new_bs->quiesce_counter;
|
||||
if (child->role->parent_is_bds) {
|
||||
num -= bdrv_drain_all_count;
|
||||
@@ -2302,69 +2194,33 @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
|
||||
|
||||
bdrv_replace_child_noperm(child, new_bs);
|
||||
|
||||
/*
|
||||
* Start with the new node's permissions. If @new_bs is a (direct
|
||||
* or indirect) child of @old_bs, we must complete the permission
|
||||
* update on @new_bs before we loosen the restrictions on @old_bs.
|
||||
* Otherwise, bdrv_check_perm() on @old_bs would re-initiate
|
||||
* updating the permissions of @new_bs, and thus not purely loosen
|
||||
* restrictions.
|
||||
*/
|
||||
if (new_bs) {
|
||||
bdrv_get_cumulative_perm(new_bs, &perm, &shared_perm);
|
||||
bdrv_set_perm(new_bs, perm, shared_perm);
|
||||
}
|
||||
|
||||
if (old_bs) {
|
||||
/* Update permissions for old node. This is guaranteed to succeed
|
||||
* because we're just taking a parent away, so we're loosening
|
||||
* restrictions. */
|
||||
bool tighten_restrictions;
|
||||
int ret;
|
||||
|
||||
bdrv_get_cumulative_perm(old_bs, &perm, &shared_perm);
|
||||
ret = bdrv_check_perm(old_bs, NULL, perm, shared_perm, NULL,
|
||||
&tighten_restrictions, NULL);
|
||||
assert(tighten_restrictions == false);
|
||||
if (ret < 0) {
|
||||
/* We only tried to loosen restrictions, so errors are not fatal */
|
||||
bdrv_abort_perm_update(old_bs);
|
||||
} else {
|
||||
bdrv_set_perm(old_bs, perm, shared_perm);
|
||||
}
|
||||
bdrv_check_perm(old_bs, NULL, perm, shared_perm, NULL, &error_abort);
|
||||
bdrv_set_perm(old_bs, perm, shared_perm);
|
||||
}
|
||||
|
||||
/* When the parent requiring a non-default AioContext is removed, the
|
||||
* node moves back to the main AioContext */
|
||||
bdrv_try_set_aio_context(old_bs, qemu_get_aio_context(), NULL);
|
||||
if (new_bs) {
|
||||
bdrv_get_cumulative_perm(new_bs, &perm, &shared_perm);
|
||||
bdrv_set_perm(new_bs, perm, shared_perm);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function steals the reference to child_bs from the caller.
|
||||
* That reference is later dropped by bdrv_root_unref_child().
|
||||
*
|
||||
* On failure NULL is returned, errp is set and the reference to
|
||||
* child_bs is also dropped.
|
||||
*
|
||||
* The caller must hold the AioContext lock @child_bs, but not that of @ctx
|
||||
* (unless @child_bs is already in @ctx).
|
||||
*/
|
||||
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
|
||||
const char *child_name,
|
||||
const BdrvChildRole *child_role,
|
||||
AioContext *ctx,
|
||||
uint64_t perm, uint64_t shared_perm,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
BdrvChild *child;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, NULL,
|
||||
errp);
|
||||
ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_abort_perm_update(child_bs);
|
||||
bdrv_unref(child_bs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2378,48 +2234,12 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
|
||||
.opaque = opaque,
|
||||
};
|
||||
|
||||
/* If the AioContexts don't match, first try to move the subtree of
|
||||
* child_bs into the AioContext of the new parent. If this doesn't work,
|
||||
* try moving the parent into the AioContext of child_bs instead. */
|
||||
if (bdrv_get_aio_context(child_bs) != ctx) {
|
||||
ret = bdrv_try_set_aio_context(child_bs, ctx, &local_err);
|
||||
if (ret < 0 && child_role->can_set_aio_ctx) {
|
||||
GSList *ignore = g_slist_prepend(NULL, child);;
|
||||
ctx = bdrv_get_aio_context(child_bs);
|
||||
if (child_role->can_set_aio_ctx(child, ctx, &ignore, NULL)) {
|
||||
error_free(local_err);
|
||||
ret = 0;
|
||||
g_slist_free(ignore);
|
||||
ignore = g_slist_prepend(NULL, child);;
|
||||
child_role->set_aio_ctx(child, ctx, &ignore);
|
||||
}
|
||||
g_slist_free(ignore);
|
||||
}
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
g_free(child);
|
||||
bdrv_abort_perm_update(child_bs);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* This performs the matching bdrv_set_perm() for the above check. */
|
||||
bdrv_replace_child(child, child_bs);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function transfers the reference to child_bs from the caller
|
||||
* to parent_bs. That reference is later dropped by parent_bs on
|
||||
* bdrv_close() or if someone calls bdrv_unref_child().
|
||||
*
|
||||
* On failure NULL is returned, errp is set and the reference to
|
||||
* child_bs is also dropped.
|
||||
*
|
||||
* If @parent_bs and @child_bs are in different AioContexts, the caller must
|
||||
* hold the AioContext lock for @child_bs, but not for @parent_bs.
|
||||
*/
|
||||
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
||||
BlockDriverState *child_bs,
|
||||
const char *child_name,
|
||||
@@ -2432,11 +2252,11 @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
||||
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
|
||||
|
||||
assert(parent_bs->drv);
|
||||
assert(bdrv_get_aio_context(parent_bs) == bdrv_get_aio_context(child_bs));
|
||||
bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
|
||||
perm, shared_perm, &perm, &shared_perm);
|
||||
|
||||
child = bdrv_root_attach_child(child_bs, child_name, child_role,
|
||||
bdrv_get_aio_context(parent_bs),
|
||||
perm, shared_perm, parent_bs, errp);
|
||||
if (child == NULL) {
|
||||
return NULL;
|
||||
@@ -2468,20 +2288,18 @@ void bdrv_root_unref_child(BdrvChild *child)
|
||||
bdrv_unref(child_bs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all inherits_from pointers from children and grandchildren of
|
||||
* @root that point to @root, where necessary.
|
||||
*/
|
||||
static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child)
|
||||
void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child)
|
||||
{
|
||||
BdrvChild *c;
|
||||
if (child == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (child->bs->inherits_from == root) {
|
||||
/*
|
||||
* Remove inherits_from only when the last reference between root and
|
||||
* child->bs goes away.
|
||||
*/
|
||||
QLIST_FOREACH(c, &root->children, next) {
|
||||
if (child->bs->inherits_from == parent) {
|
||||
BdrvChild *c;
|
||||
|
||||
/* Remove inherits_from only when the last reference between parent and
|
||||
* child->bs goes away. */
|
||||
QLIST_FOREACH(c, &parent->children, next) {
|
||||
if (c != child && c->bs == child->bs) {
|
||||
break;
|
||||
}
|
||||
@@ -2491,18 +2309,6 @@ static void bdrv_unset_inherits_from(BlockDriverState *root, BdrvChild *child)
|
||||
}
|
||||
}
|
||||
|
||||
QLIST_FOREACH(c, &child->bs->children, next) {
|
||||
bdrv_unset_inherits_from(root, c);
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child)
|
||||
{
|
||||
if (child == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
bdrv_unset_inherits_from(parent, child);
|
||||
bdrv_root_unref_child(child);
|
||||
}
|
||||
|
||||
@@ -2561,9 +2367,12 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||
/* If backing_hd was already part of bs's backing chain, and
|
||||
* inherits_from pointed recursively to bs then let's update it to
|
||||
* point directly to bs (else it will become NULL). */
|
||||
if (bs->backing && update_inherits_from) {
|
||||
if (update_inherits_from) {
|
||||
backing_hd->inherits_from = bs;
|
||||
}
|
||||
if (!bs->backing) {
|
||||
bdrv_unref(backing_hd);
|
||||
}
|
||||
|
||||
out:
|
||||
bdrv_refresh_limits(bs, NULL);
|
||||
@@ -2661,6 +2470,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
ret = -EINVAL;
|
||||
goto free_exit;
|
||||
}
|
||||
bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
|
||||
|
||||
if (implicit_backing) {
|
||||
bdrv_refresh_filename(backing_hd);
|
||||
@@ -2750,6 +2560,7 @@ BdrvChild *bdrv_open_child(const char *filename,
|
||||
const BdrvChildRole *child_role,
|
||||
bool allow_none, Error **errp)
|
||||
{
|
||||
BdrvChild *c;
|
||||
BlockDriverState *bs;
|
||||
|
||||
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_role,
|
||||
@@ -2758,7 +2569,13 @@ BdrvChild *bdrv_open_child(const char *filename,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bdrv_attach_child(parent, bs, bdref_key, child_role, errp);
|
||||
c = bdrv_attach_child(parent, bs, bdref_key, child_role, errp);
|
||||
if (!c) {
|
||||
bdrv_unref(bs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* TODO Future callers may need to specify parent/child_role in order for
|
||||
@@ -3027,7 +2844,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
/* Not requesting BLK_PERM_CONSISTENT_READ because we're only
|
||||
* looking at the header to guess the image format. This works even
|
||||
* in cases where a guest would not see a consistent state. */
|
||||
file = blk_new(bdrv_get_aio_context(file_bs), 0, BLK_PERM_ALL);
|
||||
file = blk_new(0, BLK_PERM_ALL);
|
||||
blk_insert_bs(file, file_bs, &local_err);
|
||||
bdrv_unref(file_bs);
|
||||
if (local_err) {
|
||||
@@ -3456,7 +3273,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
|
||||
QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
|
||||
BDRVReopenState *state = &bs_entry->state;
|
||||
ret = bdrv_check_perm(state->bs, bs_queue, state->perm,
|
||||
state->shared_perm, NULL, NULL, errp);
|
||||
state->shared_perm, NULL, errp);
|
||||
if (ret < 0) {
|
||||
goto cleanup_perm;
|
||||
}
|
||||
@@ -3468,7 +3285,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
|
||||
state->perm, state->shared_perm,
|
||||
&nperm, &nshared);
|
||||
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
|
||||
nperm, nshared, NULL, NULL, errp);
|
||||
nperm, nshared, NULL, errp);
|
||||
if (ret < 0) {
|
||||
goto cleanup_perm;
|
||||
}
|
||||
@@ -4012,6 +3829,7 @@ static void bdrv_close(BlockDriverState *bs)
|
||||
BdrvAioNotifier *ban, *ban_next;
|
||||
BdrvChild *child, *next;
|
||||
|
||||
assert(!bs->job);
|
||||
assert(!bs->refcnt);
|
||||
|
||||
bdrv_drained_begin(bs); /* complete I/O */
|
||||
@@ -4025,12 +3843,22 @@ static void bdrv_close(BlockDriverState *bs)
|
||||
bs->drv = NULL;
|
||||
}
|
||||
|
||||
bdrv_set_backing_hd(bs, NULL, &error_abort);
|
||||
|
||||
if (bs->file != NULL) {
|
||||
bdrv_unref_child(bs, bs->file);
|
||||
bs->file = NULL;
|
||||
}
|
||||
|
||||
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
|
||||
bdrv_unref_child(bs, child);
|
||||
/* TODO Remove bdrv_unref() from drivers' close function and use
|
||||
* bdrv_unref_child() here */
|
||||
if (child->bs->inherits_from == bs) {
|
||||
child->bs->inherits_from = NULL;
|
||||
}
|
||||
bdrv_detach_child(child);
|
||||
}
|
||||
|
||||
bs->backing = NULL;
|
||||
bs->file = NULL;
|
||||
g_free(bs->opaque);
|
||||
bs->opaque = NULL;
|
||||
atomic_set(&bs->copy_on_read, 0);
|
||||
@@ -4184,7 +4012,7 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
|
||||
|
||||
/* Check whether the required permissions can be granted on @to, ignoring
|
||||
* all BdrvChild in @list so that they can't block themselves. */
|
||||
ret = bdrv_check_update_perm(to, NULL, perm, shared, list, NULL, errp);
|
||||
ret = bdrv_check_update_perm(to, NULL, perm, shared, list, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_abort_perm_update(to);
|
||||
goto out;
|
||||
@@ -4252,17 +4080,18 @@ out:
|
||||
|
||||
static void bdrv_delete(BlockDriverState *bs)
|
||||
{
|
||||
assert(!bs->job);
|
||||
assert(bdrv_op_blocker_is_empty(bs));
|
||||
assert(!bs->refcnt);
|
||||
|
||||
bdrv_close(bs);
|
||||
|
||||
/* remove from list, if necessary */
|
||||
if (bs->node_name[0] != '\0') {
|
||||
QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list);
|
||||
}
|
||||
QTAILQ_REMOVE(&all_bdrv_states, bs, bs_list);
|
||||
|
||||
bdrv_close(bs);
|
||||
|
||||
g_free(bs);
|
||||
}
|
||||
|
||||
@@ -4294,7 +4123,7 @@ typedef struct CheckCo {
|
||||
int ret;
|
||||
} CheckCo;
|
||||
|
||||
static void coroutine_fn bdrv_check_co_entry(void *opaque)
|
||||
static void bdrv_check_co_entry(void *opaque)
|
||||
{
|
||||
CheckCo *cco = opaque;
|
||||
cco->ret = bdrv_co_check(cco->bs, cco->res, cco->fix);
|
||||
@@ -4426,14 +4255,6 @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base,
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
for (i = bs; i != base; i = backing_bs(i)) {
|
||||
if (i->backing && backing_bs(i)->never_freeze) {
|
||||
error_setg(errp, "Cannot freeze '%s' link to '%s'",
|
||||
i->backing->name, backing_bs(i)->node_name);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = bs; i != base; i = backing_bs(i)) {
|
||||
if (i->backing) {
|
||||
i->backing->frozen = true;
|
||||
@@ -4539,7 +4360,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
|
||||
/* Check whether we are allowed to switch c from top to base */
|
||||
GSList *ignore_children = g_slist_prepend(NULL, c);
|
||||
ret = bdrv_check_update_perm(base, NULL, c->perm, c->shared_perm,
|
||||
ignore_children, NULL, &local_err);
|
||||
ignore_children, &local_err);
|
||||
g_slist_free(ignore_children);
|
||||
if (ret < 0) {
|
||||
error_report_err(local_err);
|
||||
@@ -5314,7 +5135,7 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
|
||||
*/
|
||||
bs->open_flags &= ~BDRV_O_INACTIVE;
|
||||
bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
|
||||
ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, NULL, &local_err);
|
||||
ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &local_err);
|
||||
if (ret < 0) {
|
||||
bs->open_flags |= BDRV_O_INACTIVE;
|
||||
error_propagate(errp, local_err);
|
||||
@@ -5428,7 +5249,6 @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
|
||||
static int bdrv_inactivate_recurse(BlockDriverState *bs)
|
||||
{
|
||||
BdrvChild *child, *parent;
|
||||
bool tighten_restrictions;
|
||||
uint64_t perm, shared_perm;
|
||||
int ret;
|
||||
|
||||
@@ -5465,15 +5285,8 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs)
|
||||
|
||||
/* Update permissions, they may differ for inactive nodes */
|
||||
bdrv_get_cumulative_perm(bs, &perm, &shared_perm);
|
||||
ret = bdrv_check_perm(bs, NULL, perm, shared_perm, NULL,
|
||||
&tighten_restrictions, NULL);
|
||||
assert(tighten_restrictions == false);
|
||||
if (ret < 0) {
|
||||
/* We only tried to loosen restrictions, so errors are not fatal */
|
||||
bdrv_abort_perm_update(bs);
|
||||
} else {
|
||||
bdrv_set_perm(bs, perm, shared_perm);
|
||||
}
|
||||
bdrv_check_perm(bs, NULL, perm, shared_perm, NULL, &error_abort);
|
||||
bdrv_set_perm(bs, perm, shared_perm);
|
||||
|
||||
|
||||
/* Recursively inactivate children */
|
||||
@@ -5855,9 +5668,10 @@ static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban)
|
||||
g_free(ban);
|
||||
}
|
||||
|
||||
static void bdrv_detach_aio_context(BlockDriverState *bs)
|
||||
void bdrv_detach_aio_context(BlockDriverState *bs)
|
||||
{
|
||||
BdrvAioNotifier *baf, *baf_tmp;
|
||||
BdrvChild *child;
|
||||
|
||||
assert(!bs->walking_aio_notifiers);
|
||||
bs->walking_aio_notifiers = true;
|
||||
@@ -5876,6 +5690,9 @@ static void bdrv_detach_aio_context(BlockDriverState *bs)
|
||||
if (bs->drv && bs->drv->bdrv_detach_aio_context) {
|
||||
bs->drv->bdrv_detach_aio_context(bs);
|
||||
}
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
bdrv_detach_aio_context(child->bs);
|
||||
}
|
||||
|
||||
if (bs->quiesce_counter) {
|
||||
aio_enable_external(bs->aio_context);
|
||||
@@ -5883,10 +5700,11 @@ static void bdrv_detach_aio_context(BlockDriverState *bs)
|
||||
bs->aio_context = NULL;
|
||||
}
|
||||
|
||||
static void bdrv_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
void bdrv_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context)
|
||||
{
|
||||
BdrvAioNotifier *ban, *ban_tmp;
|
||||
BdrvChild *child;
|
||||
|
||||
if (bs->quiesce_counter) {
|
||||
aio_disable_external(new_context);
|
||||
@@ -5894,6 +5712,9 @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
|
||||
|
||||
bs->aio_context = new_context;
|
||||
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
bdrv_attach_aio_context(child->bs, new_context);
|
||||
}
|
||||
if (bs->drv && bs->drv->bdrv_attach_aio_context) {
|
||||
bs->drv->bdrv_attach_aio_context(bs, new_context);
|
||||
}
|
||||
@@ -5910,161 +5731,25 @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
|
||||
bs->walking_aio_notifiers = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Changes the AioContext used for fd handlers, timers, and BHs by this
|
||||
* BlockDriverState and all its children and parents.
|
||||
*
|
||||
* Must be called from the main AioContext.
|
||||
*
|
||||
* The caller must own the AioContext lock for the old AioContext of bs, but it
|
||||
* must not own the AioContext lock for new_context (unless new_context is the
|
||||
* same as the current context of bs).
|
||||
*
|
||||
* @ignore will accumulate all visited BdrvChild object. The caller is
|
||||
* responsible for freeing the list afterwards.
|
||||
*/
|
||||
void bdrv_set_aio_context_ignore(BlockDriverState *bs,
|
||||
AioContext *new_context, GSList **ignore)
|
||||
/* The caller must own the AioContext lock for the old AioContext of bs, but it
|
||||
* must not own the AioContext lock for new_context (unless new_context is
|
||||
* the same as the current context of bs). */
|
||||
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
|
||||
{
|
||||
AioContext *old_context = bdrv_get_aio_context(bs);
|
||||
BdrvChild *child;
|
||||
|
||||
g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||
|
||||
if (old_context == new_context) {
|
||||
if (bdrv_get_aio_context(bs) == new_context) {
|
||||
return;
|
||||
}
|
||||
|
||||
bdrv_drained_begin(bs);
|
||||
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
if (g_slist_find(*ignore, child)) {
|
||||
continue;
|
||||
}
|
||||
*ignore = g_slist_prepend(*ignore, child);
|
||||
bdrv_set_aio_context_ignore(child->bs, new_context, ignore);
|
||||
}
|
||||
QLIST_FOREACH(child, &bs->parents, next_parent) {
|
||||
if (g_slist_find(*ignore, child)) {
|
||||
continue;
|
||||
}
|
||||
assert(child->role->set_aio_ctx);
|
||||
*ignore = g_slist_prepend(*ignore, child);
|
||||
child->role->set_aio_ctx(child, new_context, ignore);
|
||||
}
|
||||
|
||||
bdrv_detach_aio_context(bs);
|
||||
|
||||
/* Acquire the new context, if necessary */
|
||||
if (qemu_get_aio_context() != new_context) {
|
||||
aio_context_acquire(new_context);
|
||||
}
|
||||
|
||||
bdrv_attach_aio_context(bs, new_context);
|
||||
|
||||
/*
|
||||
* If this function was recursively called from
|
||||
* bdrv_set_aio_context_ignore(), there may be nodes in the
|
||||
* subtree that have not yet been moved to the new AioContext.
|
||||
* Release the old one so bdrv_drained_end() can poll them.
|
||||
/* This function executes in the old AioContext so acquire the new one in
|
||||
* case it runs in a different thread.
|
||||
*/
|
||||
if (qemu_get_aio_context() != old_context) {
|
||||
aio_context_release(old_context);
|
||||
}
|
||||
|
||||
aio_context_acquire(new_context);
|
||||
bdrv_attach_aio_context(bs, new_context);
|
||||
bdrv_drained_end(bs);
|
||||
|
||||
if (qemu_get_aio_context() != old_context) {
|
||||
aio_context_acquire(old_context);
|
||||
}
|
||||
if (qemu_get_aio_context() != new_context) {
|
||||
aio_context_release(new_context);
|
||||
}
|
||||
}
|
||||
|
||||
static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
|
||||
GSList **ignore, Error **errp)
|
||||
{
|
||||
if (g_slist_find(*ignore, c)) {
|
||||
return true;
|
||||
}
|
||||
*ignore = g_slist_prepend(*ignore, c);
|
||||
|
||||
/* A BdrvChildRole that doesn't handle AioContext changes cannot
|
||||
* tolerate any AioContext changes */
|
||||
if (!c->role->can_set_aio_ctx) {
|
||||
char *user = bdrv_child_user_desc(c);
|
||||
error_setg(errp, "Changing iothreads is not supported by %s", user);
|
||||
g_free(user);
|
||||
return false;
|
||||
}
|
||||
if (!c->role->can_set_aio_ctx(c, ctx, ignore, errp)) {
|
||||
assert(!errp || *errp);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
|
||||
GSList **ignore, Error **errp)
|
||||
{
|
||||
if (g_slist_find(*ignore, c)) {
|
||||
return true;
|
||||
}
|
||||
*ignore = g_slist_prepend(*ignore, c);
|
||||
return bdrv_can_set_aio_context(c->bs, ctx, ignore, errp);
|
||||
}
|
||||
|
||||
/* @ignore will accumulate all visited BdrvChild object. The caller is
|
||||
* responsible for freeing the list afterwards. */
|
||||
bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
|
||||
GSList **ignore, Error **errp)
|
||||
{
|
||||
BdrvChild *c;
|
||||
|
||||
if (bdrv_get_aio_context(bs) == ctx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QLIST_FOREACH(c, &bs->parents, next_parent) {
|
||||
if (!bdrv_parent_can_set_aio_context(c, ctx, ignore, errp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
QLIST_FOREACH(c, &bs->children, next) {
|
||||
if (!bdrv_child_can_set_aio_context(c, ctx, ignore, errp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
|
||||
BdrvChild *ignore_child, Error **errp)
|
||||
{
|
||||
GSList *ignore;
|
||||
bool ret;
|
||||
|
||||
ignore = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
|
||||
ret = bdrv_can_set_aio_context(bs, ctx, &ignore, errp);
|
||||
g_slist_free(ignore);
|
||||
|
||||
if (!ret) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ignore = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
|
||||
bdrv_set_aio_context_ignore(bs, ctx, &ignore);
|
||||
g_slist_free(ignore);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
|
||||
Error **errp)
|
||||
{
|
||||
return bdrv_child_try_set_aio_context(bs, ctx, NULL, errp);
|
||||
aio_context_release(new_context);
|
||||
}
|
||||
|
||||
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
|
||||
|
||||
+5
-5
@@ -6,7 +6,7 @@ block-obj-$(CONFIG_BOCHS) += bochs.o
|
||||
block-obj-$(CONFIG_VVFAT) += vvfat.o
|
||||
block-obj-$(CONFIG_DMG) += dmg.o
|
||||
|
||||
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o qcow2-threads.o
|
||||
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o
|
||||
block-obj-$(CONFIG_QED) += qed.o qed-l2-cache.o qed-table.o qed-cluster.o
|
||||
block-obj-$(CONFIG_QED) += qed-check.o
|
||||
block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o
|
||||
@@ -22,7 +22,7 @@ block-obj-y += null.o mirror.o commit.o io.o create.o
|
||||
block-obj-y += throttle-groups.o
|
||||
block-obj-$(CONFIG_LINUX) += nvme.o
|
||||
|
||||
block-obj-y += nbd.o
|
||||
block-obj-y += nbd.o nbd-client.o
|
||||
block-obj-$(CONFIG_SHEEPDOG) += sheepdog.o
|
||||
block-obj-$(CONFIG_LIBISCSI) += iscsi.o
|
||||
block-obj-$(if $(CONFIG_LIBISCSI),y,n) += iscsi-opts.o
|
||||
@@ -31,7 +31,7 @@ block-obj-$(CONFIG_CURL) += curl.o
|
||||
block-obj-$(CONFIG_RBD) += rbd.o
|
||||
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
|
||||
block-obj-$(CONFIG_VXHS) += vxhs.o
|
||||
block-obj-$(CONFIG_LIBSSH) += ssh.o
|
||||
block-obj-$(CONFIG_LIBSSH2) += ssh.o
|
||||
block-obj-y += accounting.o dirty-bitmap.o
|
||||
block-obj-y += write-threshold.o
|
||||
block-obj-y += backup.o
|
||||
@@ -52,8 +52,8 @@ rbd.o-libs := $(RBD_LIBS)
|
||||
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
|
||||
gluster.o-libs := $(GLUSTERFS_LIBS)
|
||||
vxhs.o-libs := $(VXHS_LIBS)
|
||||
ssh.o-cflags := $(LIBSSH_CFLAGS)
|
||||
ssh.o-libs := $(LIBSSH_LIBS)
|
||||
ssh.o-cflags := $(LIBSSH2_CFLAGS)
|
||||
ssh.o-libs := $(LIBSSH2_LIBS)
|
||||
block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o
|
||||
block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y)
|
||||
dmg-bz2.o-libs := $(BZIP2_LIBS)
|
||||
|
||||
+17
-8
@@ -107,6 +107,7 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
|
||||
void **bounce_buffer)
|
||||
{
|
||||
int ret;
|
||||
QEMUIOVector qiov;
|
||||
BlockBackend *blk = job->common.blk;
|
||||
int nbytes;
|
||||
int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
|
||||
@@ -118,8 +119,9 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
|
||||
if (!*bounce_buffer) {
|
||||
*bounce_buffer = blk_blockalign(blk, job->cluster_size);
|
||||
}
|
||||
qemu_iovec_init_buf(&qiov, *bounce_buffer, nbytes);
|
||||
|
||||
ret = blk_co_pread(blk, start, nbytes, *bounce_buffer, read_flags);
|
||||
ret = blk_co_preadv(blk, start, qiov.size, &qiov, read_flags);
|
||||
if (ret < 0) {
|
||||
trace_backup_do_cow_read_fail(job, start, ret);
|
||||
if (error_is_read) {
|
||||
@@ -128,13 +130,13 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (buffer_is_zero(*bounce_buffer, nbytes)) {
|
||||
if (qemu_iovec_is_zero(&qiov)) {
|
||||
ret = blk_co_pwrite_zeroes(job->target, start,
|
||||
nbytes, write_flags | BDRV_REQ_MAY_UNMAP);
|
||||
qiov.size, write_flags | BDRV_REQ_MAY_UNMAP);
|
||||
} else {
|
||||
ret = blk_co_pwrite(job->target, start,
|
||||
nbytes, *bounce_buffer, write_flags |
|
||||
(job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0));
|
||||
ret = blk_co_pwritev(job->target, start,
|
||||
qiov.size, &qiov, write_flags |
|
||||
(job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0));
|
||||
}
|
||||
if (ret < 0) {
|
||||
trace_backup_do_cow_write_fail(job, start, ret);
|
||||
@@ -314,6 +316,13 @@ static void backup_clean(Job *job)
|
||||
}
|
||||
}
|
||||
|
||||
static void backup_attached_aio_context(BlockJob *job, AioContext *aio_context)
|
||||
{
|
||||
BackupBlockJob *s = container_of(job, BackupBlockJob, common);
|
||||
|
||||
blk_set_aio_context(s->target, aio_context);
|
||||
}
|
||||
|
||||
void backup_do_checkpoint(BlockJob *job, Error **errp)
|
||||
{
|
||||
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
|
||||
@@ -503,6 +512,7 @@ static const BlockJobDriver backup_job_driver = {
|
||||
.abort = backup_abort,
|
||||
.clean = backup_clean,
|
||||
},
|
||||
.attached_aio_context = backup_attached_aio_context,
|
||||
.drain = backup_drain,
|
||||
};
|
||||
|
||||
@@ -636,8 +646,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
}
|
||||
|
||||
/* The target must match the source in size, so no resize here either */
|
||||
job->target = blk_new(job->common.job.aio_context,
|
||||
BLK_PERM_WRITE,
|
||||
job->target = blk_new(BLK_PERM_WRITE,
|
||||
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
|
||||
BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD);
|
||||
ret = blk_insert_bs(job->target, target, errp);
|
||||
|
||||
+9
-51
@@ -75,7 +75,6 @@ typedef struct BlkdebugRule {
|
||||
int state;
|
||||
union {
|
||||
struct {
|
||||
uint64_t iotype_mask;
|
||||
int error;
|
||||
int immediately;
|
||||
int once;
|
||||
@@ -92,9 +91,6 @@ typedef struct BlkdebugRule {
|
||||
QSIMPLEQ_ENTRY(BlkdebugRule) active_next;
|
||||
} BlkdebugRule;
|
||||
|
||||
QEMU_BUILD_BUG_MSG(BLKDEBUG_IO_TYPE__MAX > 64,
|
||||
"BlkdebugIOType mask does not fit into an uint64_t");
|
||||
|
||||
static QemuOptsList inject_error_opts = {
|
||||
.name = "inject-error",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(inject_error_opts.head),
|
||||
@@ -107,10 +103,6 @@ static QemuOptsList inject_error_opts = {
|
||||
.name = "state",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
},
|
||||
{
|
||||
.name = "iotype",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},
|
||||
{
|
||||
.name = "errno",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
@@ -170,8 +162,6 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
|
||||
int event;
|
||||
struct BlkdebugRule *rule;
|
||||
int64_t sector;
|
||||
BlkdebugIOType iotype;
|
||||
Error *local_error = NULL;
|
||||
|
||||
/* Find the right event for the rule */
|
||||
event_name = qemu_opt_get(opts, "event");
|
||||
@@ -202,26 +192,6 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
|
||||
sector = qemu_opt_get_number(opts, "sector", -1);
|
||||
rule->options.inject.offset =
|
||||
sector == -1 ? -1 : sector * BDRV_SECTOR_SIZE;
|
||||
|
||||
iotype = qapi_enum_parse(&BlkdebugIOType_lookup,
|
||||
qemu_opt_get(opts, "iotype"),
|
||||
BLKDEBUG_IO_TYPE__MAX, &local_error);
|
||||
if (local_error) {
|
||||
error_propagate(errp, local_error);
|
||||
return -1;
|
||||
}
|
||||
if (iotype != BLKDEBUG_IO_TYPE__MAX) {
|
||||
rule->options.inject.iotype_mask = (1ull << iotype);
|
||||
} else {
|
||||
/* Apply the default */
|
||||
rule->options.inject.iotype_mask =
|
||||
(1ull << BLKDEBUG_IO_TYPE_READ)
|
||||
| (1ull << BLKDEBUG_IO_TYPE_WRITE)
|
||||
| (1ull << BLKDEBUG_IO_TYPE_WRITE_ZEROES)
|
||||
| (1ull << BLKDEBUG_IO_TYPE_DISCARD)
|
||||
| (1ull << BLKDEBUG_IO_TYPE_FLUSH);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ACTION_SET_STATE:
|
||||
@@ -491,8 +461,6 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto out;
|
||||
}
|
||||
|
||||
bdrv_debug_event(bs, BLKDBG_NONE);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (ret < 0) {
|
||||
@@ -502,8 +470,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
BlkdebugIOType iotype)
|
||||
static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes)
|
||||
{
|
||||
BDRVBlkdebugState *s = bs->opaque;
|
||||
BlkdebugRule *rule = NULL;
|
||||
@@ -513,10 +480,9 @@ static int rule_check(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
|
||||
uint64_t inject_offset = rule->options.inject.offset;
|
||||
|
||||
if ((inject_offset == -1 ||
|
||||
(bytes && inject_offset >= offset &&
|
||||
inject_offset < offset + bytes)) &&
|
||||
(rule->options.inject.iotype_mask & (1ull << iotype)))
|
||||
if (inject_offset == -1 ||
|
||||
(bytes && inject_offset >= offset &&
|
||||
inject_offset < offset + bytes))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -555,7 +521,7 @@ blkdebug_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
assert(bytes <= bs->bl.max_transfer);
|
||||
}
|
||||
|
||||
err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_READ);
|
||||
err = rule_check(bs, offset, bytes);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -576,7 +542,7 @@ blkdebug_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
assert(bytes <= bs->bl.max_transfer);
|
||||
}
|
||||
|
||||
err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_WRITE);
|
||||
err = rule_check(bs, offset, bytes);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -586,7 +552,7 @@ blkdebug_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
|
||||
|
||||
static int blkdebug_co_flush(BlockDriverState *bs)
|
||||
{
|
||||
int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
|
||||
int err = rule_check(bs, 0, 0);
|
||||
|
||||
if (err) {
|
||||
return err;
|
||||
@@ -620,7 +586,7 @@ static int coroutine_fn blkdebug_co_pwrite_zeroes(BlockDriverState *bs,
|
||||
assert(bytes <= bs->bl.max_pwrite_zeroes);
|
||||
}
|
||||
|
||||
err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_WRITE_ZEROES);
|
||||
err = rule_check(bs, offset, bytes);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -654,7 +620,7 @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
|
||||
assert(bytes <= bs->bl.max_pdiscard);
|
||||
}
|
||||
|
||||
err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_DISCARD);
|
||||
err = rule_check(bs, offset, bytes);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -670,15 +636,7 @@ static int coroutine_fn blkdebug_co_block_status(BlockDriverState *bs,
|
||||
int64_t *map,
|
||||
BlockDriverState **file)
|
||||
{
|
||||
int err;
|
||||
|
||||
assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
|
||||
|
||||
err = rule_check(bs, offset, bytes, BLKDEBUG_IO_TYPE_BLOCK_STATUS);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return bdrv_co_block_status_from_file(bs, want_zero, offset, bytes,
|
||||
pnum, map, file);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
|
||||
/* Disk format stuff - taken from Linux drivers/md/dm-log-writes.c */
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
|
||||
typedef struct {
|
||||
|
||||
+16
-79
@@ -42,7 +42,6 @@ struct BlockBackend {
|
||||
char *name;
|
||||
int refcnt;
|
||||
BdrvChild *root;
|
||||
AioContext *ctx;
|
||||
DriveInfo *legacy_dinfo; /* null unless created by drive_new() */
|
||||
QTAILQ_ENTRY(BlockBackend) link; /* for block_backends */
|
||||
QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
|
||||
@@ -72,7 +71,6 @@ struct BlockBackend {
|
||||
uint64_t shared_perm;
|
||||
bool disable_perm;
|
||||
|
||||
bool allow_aio_context_change;
|
||||
bool allow_write_beyond_eof;
|
||||
|
||||
NotifierList remove_bs_notifiers, insert_bs_notifiers;
|
||||
@@ -121,16 +119,11 @@ static void blk_root_inherit_options(int *child_flags, QDict *child_options,
|
||||
}
|
||||
static void blk_root_drained_begin(BdrvChild *child);
|
||||
static bool blk_root_drained_poll(BdrvChild *child);
|
||||
static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter);
|
||||
static void blk_root_drained_end(BdrvChild *child);
|
||||
|
||||
static void blk_root_change_media(BdrvChild *child, bool load);
|
||||
static void blk_root_resize(BdrvChild *child);
|
||||
|
||||
static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
|
||||
GSList **ignore, Error **errp);
|
||||
static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
|
||||
GSList **ignore);
|
||||
|
||||
static char *blk_root_get_parent_desc(BdrvChild *child)
|
||||
{
|
||||
BlockBackend *blk = child->opaque;
|
||||
@@ -307,9 +300,6 @@ static const BdrvChildRole child_root = {
|
||||
|
||||
.attach = blk_root_attach,
|
||||
.detach = blk_root_detach,
|
||||
|
||||
.can_set_aio_ctx = blk_root_can_set_aio_ctx,
|
||||
.set_aio_ctx = blk_root_set_aio_ctx,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -323,13 +313,12 @@ static const BdrvChildRole child_root = {
|
||||
*
|
||||
* Return the new BlockBackend on success, null on failure.
|
||||
*/
|
||||
BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
|
||||
BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
|
||||
blk = g_new0(BlockBackend, 1);
|
||||
blk->refcnt = 1;
|
||||
blk->ctx = ctx;
|
||||
blk->perm = perm;
|
||||
blk->shared_perm = shared_perm;
|
||||
blk_set_enable_write_cache(blk, true);
|
||||
@@ -349,7 +338,6 @@ BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
|
||||
|
||||
/*
|
||||
* Creates a new BlockBackend, opens a new BlockDriverState, and connects both.
|
||||
* The new BlockBackend is in the main AioContext.
|
||||
*
|
||||
* Just as with bdrv_open(), after having called this function the reference to
|
||||
* @options belongs to the block layer (even on failure).
|
||||
@@ -385,16 +373,17 @@ BlockBackend *blk_new_open(const char *filename, const char *reference,
|
||||
perm |= BLK_PERM_RESIZE;
|
||||
}
|
||||
|
||||
blk = blk_new(qemu_get_aio_context(), perm, BLK_PERM_ALL);
|
||||
blk = blk_new(perm, BLK_PERM_ALL);
|
||||
bs = bdrv_open(filename, reference, options, flags, errp);
|
||||
if (!bs) {
|
||||
blk_unref(blk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
|
||||
blk->root = bdrv_root_attach_child(bs, "root", &child_root,
|
||||
perm, BLK_PERM_ALL, blk, errp);
|
||||
if (!blk->root) {
|
||||
bdrv_unref(bs);
|
||||
blk_unref(blk);
|
||||
return NULL;
|
||||
}
|
||||
@@ -802,12 +791,12 @@ void blk_remove_bs(BlockBackend *blk)
|
||||
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
||||
bdrv_ref(bs);
|
||||
blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
|
||||
blk->root = bdrv_root_attach_child(bs, "root", &child_root,
|
||||
blk->perm, blk->shared_perm, blk, errp);
|
||||
if (blk->root == NULL) {
|
||||
return -EPERM;
|
||||
}
|
||||
bdrv_ref(bs);
|
||||
|
||||
notifier_list_notify(&blk->insert_bs_notifiers, blk);
|
||||
if (tgm->throttle_state) {
|
||||
@@ -1073,7 +1062,11 @@ void blk_iostatus_disable(BlockBackend *blk)
|
||||
void blk_iostatus_reset(BlockBackend *blk)
|
||||
{
|
||||
if (blk_iostatus_is_enabled(blk)) {
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
|
||||
if (bs && bs->job) {
|
||||
block_job_iostatus_reset(bs->job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1091,11 +1084,6 @@ void blk_set_allow_write_beyond_eof(BlockBackend *blk, bool allow)
|
||||
blk->allow_write_beyond_eof = allow;
|
||||
}
|
||||
|
||||
void blk_set_allow_aio_context_change(BlockBackend *blk, bool allow)
|
||||
{
|
||||
blk->allow_aio_context_change = allow;
|
||||
}
|
||||
|
||||
static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
|
||||
size_t size)
|
||||
{
|
||||
@@ -1249,7 +1237,7 @@ int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf,
|
||||
|
||||
blk_root_drained_begin(blk->root);
|
||||
ret = blk_pread(blk, offset, buf, count);
|
||||
blk_root_drained_end(blk->root, NULL);
|
||||
blk_root_drained_end(blk->root);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1855,14 +1843,7 @@ void blk_op_unblock_all(BlockBackend *blk, Error *reason)
|
||||
|
||||
AioContext *blk_get_aio_context(BlockBackend *blk)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
|
||||
if (bs) {
|
||||
AioContext *ctx = bdrv_get_aio_context(blk_bs(blk));
|
||||
assert(ctx == blk->ctx);
|
||||
}
|
||||
|
||||
return blk->ctx;
|
||||
return bdrv_get_aio_context(blk_bs(blk));
|
||||
}
|
||||
|
||||
static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
|
||||
@@ -1871,64 +1852,20 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
|
||||
return blk_get_aio_context(blk_acb->blk);
|
||||
}
|
||||
|
||||
static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
|
||||
bool update_root_node, Error **errp)
|
||||
void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
|
||||
{
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
||||
int ret;
|
||||
|
||||
if (bs) {
|
||||
if (update_root_node) {
|
||||
ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
|
||||
errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (tgm->throttle_state) {
|
||||
bdrv_drained_begin(bs);
|
||||
throttle_group_detach_aio_context(tgm);
|
||||
throttle_group_attach_aio_context(tgm, new_context);
|
||||
bdrv_drained_end(bs);
|
||||
}
|
||||
bdrv_set_aio_context(bs, new_context);
|
||||
}
|
||||
|
||||
blk->ctx = new_context;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
|
||||
Error **errp)
|
||||
{
|
||||
return blk_do_set_aio_context(blk, new_context, true, errp);
|
||||
}
|
||||
|
||||
static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
|
||||
GSList **ignore, Error **errp)
|
||||
{
|
||||
BlockBackend *blk = child->opaque;
|
||||
|
||||
if (blk->allow_aio_context_change) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Only manually created BlockBackends that are not attached to anything
|
||||
* can change their AioContext without updating their user. */
|
||||
if (!blk->name || blk->dev) {
|
||||
/* TODO Add BB name/QOM path */
|
||||
error_setg(errp, "Cannot change iothread of active block backend");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
|
||||
GSList **ignore)
|
||||
{
|
||||
BlockBackend *blk = child->opaque;
|
||||
blk_do_set_aio_context(blk, ctx, false, &error_abort);
|
||||
}
|
||||
|
||||
void blk_add_aio_context_notifier(BlockBackend *blk,
|
||||
@@ -2236,7 +2173,7 @@ static bool blk_root_drained_poll(BdrvChild *child)
|
||||
return !!blk->in_flight;
|
||||
}
|
||||
|
||||
static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter)
|
||||
static void blk_root_drained_end(BdrvChild *child)
|
||||
{
|
||||
BlockBackend *blk = child->opaque;
|
||||
assert(blk->quiesce_counter);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
+22
-18
@@ -48,15 +48,16 @@ static int coroutine_fn commit_populate(BlockBackend *bs, BlockBackend *base,
|
||||
void *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||
|
||||
assert(bytes < SIZE_MAX);
|
||||
|
||||
ret = blk_co_pread(bs, offset, bytes, buf, 0);
|
||||
ret = blk_co_preadv(bs, offset, qiov.size, &qiov, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = blk_co_pwrite(base, offset, bytes, buf, 0);
|
||||
ret = blk_co_pwritev(base, offset, qiov.size, &qiov, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -110,6 +111,8 @@ static void commit_abort(Job *job)
|
||||
* XXX Can (or should) we somehow keep 'consistent read' blocked even
|
||||
* after the failed/cancelled commit job is gone? If we already wrote
|
||||
* something to base, the intermediate images aren't valid any more. */
|
||||
bdrv_child_try_set_perm(s->commit_top_bs->backing, 0, BLK_PERM_ALL,
|
||||
&error_abort);
|
||||
bdrv_replace_node(s->commit_top_bs, backing_bs(s->commit_top_bs),
|
||||
&error_abort);
|
||||
|
||||
@@ -174,7 +177,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp)
|
||||
break;
|
||||
}
|
||||
/* Copy if allocated above the base */
|
||||
ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base), false,
|
||||
ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base),
|
||||
offset, COMMIT_BUFFER_SIZE, &n);
|
||||
copy = (ret == 1);
|
||||
trace_commit_one_iteration(s, offset, n, ret);
|
||||
@@ -298,20 +301,26 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||
if (!filter_node_name) {
|
||||
commit_top_bs->implicit = true;
|
||||
}
|
||||
|
||||
/* So that we can always drop this node */
|
||||
commit_top_bs->never_freeze = true;
|
||||
|
||||
commit_top_bs->total_sectors = top->total_sectors;
|
||||
bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(top));
|
||||
|
||||
bdrv_append(commit_top_bs, top, &local_err);
|
||||
bdrv_set_backing_hd(commit_top_bs, top, &local_err);
|
||||
if (local_err) {
|
||||
bdrv_unref(commit_top_bs);
|
||||
commit_top_bs = NULL;
|
||||
error_propagate(errp, local_err);
|
||||
goto fail;
|
||||
}
|
||||
bdrv_replace_node(top, commit_top_bs, &local_err);
|
||||
if (local_err) {
|
||||
bdrv_unref(commit_top_bs);
|
||||
commit_top_bs = NULL;
|
||||
error_propagate(errp, local_err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s->commit_top_bs = commit_top_bs;
|
||||
bdrv_unref(commit_top_bs);
|
||||
|
||||
/* Block all nodes between top and base, because they will
|
||||
* disappear from the chain after this operation. */
|
||||
@@ -339,8 +348,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
s->base = blk_new(s->common.job.aio_context,
|
||||
BLK_PERM_CONSISTENT_READ
|
||||
s->base = blk_new(BLK_PERM_CONSISTENT_READ
|
||||
| BLK_PERM_WRITE
|
||||
| BLK_PERM_RESIZE,
|
||||
BLK_PERM_CONSISTENT_READ
|
||||
@@ -353,7 +361,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||
s->base_bs = base;
|
||||
|
||||
/* Required permissions are already taken with block_job_add_bdrv() */
|
||||
s->top = blk_new(s->common.job.aio_context, 0, BLK_PERM_ALL);
|
||||
s->top = blk_new(0, BLK_PERM_ALL);
|
||||
ret = blk_insert_bs(s->top, top, errp);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -376,9 +384,6 @@ fail:
|
||||
if (s->top) {
|
||||
blk_unref(s->top);
|
||||
}
|
||||
if (s->base_read_only) {
|
||||
bdrv_reopen_set_read_only(base, true, NULL);
|
||||
}
|
||||
job_early_fail(&s->common.job);
|
||||
/* commit_top_bs has to be replaced after deleting the block job,
|
||||
* otherwise this would fail because of lack of permissions. */
|
||||
@@ -397,7 +402,6 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
BlockDriverState *backing_file_bs = NULL;
|
||||
BlockDriverState *commit_top_bs = NULL;
|
||||
BlockDriver *drv = bs->drv;
|
||||
AioContext *ctx;
|
||||
int64_t offset, length, backing_length;
|
||||
int ro;
|
||||
int64_t n;
|
||||
@@ -425,9 +429,8 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
src = blk_new(ctx, BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
|
||||
backing = blk_new(ctx, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
|
||||
src = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
|
||||
backing = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
|
||||
|
||||
ret = blk_insert_bs(src, bs, &local_err);
|
||||
if (ret < 0) {
|
||||
@@ -444,6 +447,7 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
error_report_err(local_err);
|
||||
goto ro_cleanup;
|
||||
}
|
||||
bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(backing_file_bs));
|
||||
|
||||
bdrv_set_backing_hd(commit_top_bs, backing_file_bs, &error_abort);
|
||||
bdrv_set_backing_hd(bs, commit_top_bs, &error_abort);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
|
||||
|
||||
static int cor_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
@@ -56,14 +55,16 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
|
||||
uint64_t perm, uint64_t shared,
|
||||
uint64_t *nperm, uint64_t *nshared)
|
||||
{
|
||||
*nperm = perm & PERM_PASSTHROUGH;
|
||||
*nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED;
|
||||
|
||||
/* We must not request write permissions for an inactive node, the child
|
||||
* cannot provide it. */
|
||||
if (!(bs->open_flags & BDRV_O_INACTIVE)) {
|
||||
*nperm |= BLK_PERM_WRITE_UNCHANGED;
|
||||
if (c == NULL) {
|
||||
*nperm = (perm & PERM_PASSTHROUGH) | BLK_PERM_WRITE_UNCHANGED;
|
||||
*nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED;
|
||||
return;
|
||||
}
|
||||
|
||||
*nperm = (perm & PERM_PASSTHROUGH) |
|
||||
(c->perm & PERM_UNCHANGED);
|
||||
*nshared = (shared & PERM_PASSTHROUGH) |
|
||||
(c->shared_perm & PERM_UNCHANGED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-1
@@ -63,9 +63,13 @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
|
||||
const char *fmt = BlockdevDriver_str(options->driver);
|
||||
BlockDriver *drv = bdrv_find_format(fmt);
|
||||
|
||||
if (!drv) {
|
||||
error_setg(errp, "Block driver '%s' not found or not supported", fmt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the driver is in the schema, we know that it exists. But it may not
|
||||
* be whitelisted. */
|
||||
assert(drv);
|
||||
if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) {
|
||||
error_setg(errp, "Driver is not whitelisted");
|
||||
return;
|
||||
|
||||
+1
-3
@@ -28,7 +28,6 @@
|
||||
#include "qapi/qapi-visit-crypto.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
#include "crypto.h"
|
||||
|
||||
@@ -258,8 +257,7 @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
|
||||
QCryptoBlock *crypto = NULL;
|
||||
struct BlockCryptoCreateData data;
|
||||
|
||||
blk = blk_new(bdrv_get_aio_context(bs),
|
||||
BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
|
||||
blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
|
||||
|
||||
ret = blk_insert_bs(blk, bs, errp);
|
||||
if (ret < 0) {
|
||||
|
||||
+3
-3
@@ -18,8 +18,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLOCK_CRYPTO_H
|
||||
#define BLOCK_CRYPTO_H
|
||||
#ifndef BLOCK_CRYPTO_H__
|
||||
#define BLOCK_CRYPTO_H__
|
||||
|
||||
#define BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, helpstr) \
|
||||
{ \
|
||||
@@ -94,4 +94,4 @@ block_crypto_create_opts_init(QDict *opts, Error **errp);
|
||||
QCryptoBlockOpenOptions *
|
||||
block_crypto_open_opts_init(QDict *opts, Error **errp);
|
||||
|
||||
#endif /* BLOCK_CRYPTO_H */
|
||||
#endif /* BLOCK_CRYPTO_H__ */
|
||||
+60
-76
@@ -25,7 +25,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
@@ -80,6 +79,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
|
||||
#define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5
|
||||
|
||||
struct BDRVCURLState;
|
||||
struct CURLState;
|
||||
|
||||
static bool libcurl_initialized;
|
||||
|
||||
@@ -97,6 +97,7 @@ typedef struct CURLAIOCB {
|
||||
|
||||
typedef struct CURLSocket {
|
||||
int fd;
|
||||
struct CURLState *state;
|
||||
QLIST_ENTRY(CURLSocket) next;
|
||||
} CURLSocket;
|
||||
|
||||
@@ -137,7 +138,6 @@ typedef struct BDRVCURLState {
|
||||
|
||||
static void curl_clean_state(CURLState *s);
|
||||
static void curl_multi_do(void *arg);
|
||||
static void curl_multi_read(void *arg);
|
||||
|
||||
#ifdef NEED_CURL_TIMER_CALLBACK
|
||||
/* Called from curl_multi_do_locked, with s->mutex held. */
|
||||
@@ -170,33 +170,29 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
|
||||
|
||||
QLIST_FOREACH(socket, &state->sockets, next) {
|
||||
if (socket->fd == fd) {
|
||||
if (action == CURL_POLL_REMOVE) {
|
||||
QLIST_REMOVE(socket, next);
|
||||
g_free(socket);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!socket) {
|
||||
socket = g_new0(CURLSocket, 1);
|
||||
socket->fd = fd;
|
||||
socket->state = state;
|
||||
QLIST_INSERT_HEAD(&state->sockets, socket, next);
|
||||
}
|
||||
socket = NULL;
|
||||
|
||||
trace_curl_sock_cb(action, (int)fd);
|
||||
switch (action) {
|
||||
case CURL_POLL_IN:
|
||||
aio_set_fd_handler(s->aio_context, fd, false,
|
||||
curl_multi_read, NULL, NULL, state);
|
||||
curl_multi_do, NULL, NULL, socket);
|
||||
break;
|
||||
case CURL_POLL_OUT:
|
||||
aio_set_fd_handler(s->aio_context, fd, false,
|
||||
NULL, curl_multi_do, NULL, state);
|
||||
NULL, curl_multi_do, NULL, socket);
|
||||
break;
|
||||
case CURL_POLL_INOUT:
|
||||
aio_set_fd_handler(s->aio_context, fd, false,
|
||||
curl_multi_read, curl_multi_do, NULL, state);
|
||||
curl_multi_do, curl_multi_do, NULL, socket);
|
||||
break;
|
||||
case CURL_POLL_REMOVE:
|
||||
aio_set_fd_handler(s->aio_context, fd, false,
|
||||
@@ -204,6 +200,11 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
|
||||
break;
|
||||
}
|
||||
|
||||
if (action == CURL_POLL_REMOVE) {
|
||||
QLIST_REMOVE(socket, next);
|
||||
g_free(socket);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -227,7 +228,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
|
||||
{
|
||||
CURLState *s = ((CURLState*)opaque);
|
||||
size_t realsize = size * nmemb;
|
||||
int i;
|
||||
|
||||
trace_curl_read_cb(realsize);
|
||||
|
||||
@@ -243,32 +243,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
|
||||
memcpy(s->orig_buf + s->buf_off, ptr, realsize);
|
||||
s->buf_off += realsize;
|
||||
|
||||
for(i=0; i<CURL_NUM_ACB; i++) {
|
||||
CURLAIOCB *acb = s->acb[i];
|
||||
|
||||
if (!acb)
|
||||
continue;
|
||||
|
||||
if ((s->buf_off >= acb->end)) {
|
||||
size_t request_length = acb->bytes;
|
||||
|
||||
qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start,
|
||||
acb->end - acb->start);
|
||||
|
||||
if (acb->end - acb->start < request_length) {
|
||||
size_t offset = acb->end - acb->start;
|
||||
qemu_iovec_memset(acb->qiov, offset, 0,
|
||||
request_length - offset);
|
||||
}
|
||||
|
||||
acb->ret = 0;
|
||||
s->acb[i] = NULL;
|
||||
qemu_mutex_unlock(&s->s->mutex);
|
||||
aio_co_wake(acb->co);
|
||||
qemu_mutex_lock(&s->s->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
read_end:
|
||||
/* curl will error out if we do not return this value */
|
||||
return size * nmemb;
|
||||
@@ -349,13 +323,14 @@ static void curl_multi_check_completion(BDRVCURLState *s)
|
||||
break;
|
||||
|
||||
if (msg->msg == CURLMSG_DONE) {
|
||||
int i;
|
||||
CURLState *state = NULL;
|
||||
bool error = msg->data.result != CURLE_OK;
|
||||
|
||||
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
|
||||
(char **)&state);
|
||||
|
||||
/* ACBs for successful messages get completed in curl_read_cb */
|
||||
if (msg->data.result != CURLE_OK) {
|
||||
int i;
|
||||
if (error) {
|
||||
static int errcount = 100;
|
||||
|
||||
/* Don't lose the original error message from curl, since
|
||||
@@ -367,20 +342,35 @@ static void curl_multi_check_completion(BDRVCURLState *s)
|
||||
error_report("curl: further errors suppressed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < CURL_NUM_ACB; i++) {
|
||||
CURLAIOCB *acb = state->acb[i];
|
||||
for (i = 0; i < CURL_NUM_ACB; i++) {
|
||||
CURLAIOCB *acb = state->acb[i];
|
||||
|
||||
if (acb == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
acb->ret = -EIO;
|
||||
state->acb[i] = NULL;
|
||||
qemu_mutex_unlock(&s->mutex);
|
||||
aio_co_wake(acb->co);
|
||||
qemu_mutex_lock(&s->mutex);
|
||||
if (acb == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
/* Assert that we have read all data */
|
||||
assert(state->buf_off >= acb->end);
|
||||
|
||||
qemu_iovec_from_buf(acb->qiov, 0,
|
||||
state->orig_buf + acb->start,
|
||||
acb->end - acb->start);
|
||||
|
||||
if (acb->end - acb->start < acb->bytes) {
|
||||
size_t offset = acb->end - acb->start;
|
||||
qemu_iovec_memset(acb->qiov, offset, 0,
|
||||
acb->bytes - offset);
|
||||
}
|
||||
}
|
||||
|
||||
acb->ret = error ? -EIO : 0;
|
||||
state->acb[i] = NULL;
|
||||
qemu_mutex_unlock(&s->mutex);
|
||||
aio_co_wake(acb->co);
|
||||
qemu_mutex_lock(&s->mutex);
|
||||
}
|
||||
|
||||
curl_clean_state(state);
|
||||
@@ -390,42 +380,30 @@ static void curl_multi_check_completion(BDRVCURLState *s)
|
||||
}
|
||||
|
||||
/* Called with s->mutex held. */
|
||||
static void curl_multi_do_locked(CURLState *s)
|
||||
static void curl_multi_do_locked(CURLSocket *socket)
|
||||
{
|
||||
CURLSocket *socket, *next_socket;
|
||||
BDRVCURLState *s = socket->state->s;
|
||||
int running;
|
||||
int r;
|
||||
|
||||
if (!s->s->multi) {
|
||||
if (!s->multi) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Need to use _SAFE because curl_multi_socket_action() may trigger
|
||||
* curl_sock_cb() which might modify this list */
|
||||
QLIST_FOREACH_SAFE(socket, &s->sockets, next, next_socket) {
|
||||
do {
|
||||
r = curl_multi_socket_action(s->s->multi, socket->fd, 0, &running);
|
||||
} while (r == CURLM_CALL_MULTI_PERFORM);
|
||||
}
|
||||
do {
|
||||
r = curl_multi_socket_action(s->multi, socket->fd, 0, &running);
|
||||
} while (r == CURLM_CALL_MULTI_PERFORM);
|
||||
}
|
||||
|
||||
static void curl_multi_do(void *arg)
|
||||
{
|
||||
CURLState *s = (CURLState *)arg;
|
||||
CURLSocket *socket = arg;
|
||||
BDRVCURLState *s = socket->state->s;
|
||||
|
||||
qemu_mutex_lock(&s->s->mutex);
|
||||
curl_multi_do_locked(s);
|
||||
qemu_mutex_unlock(&s->s->mutex);
|
||||
}
|
||||
|
||||
static void curl_multi_read(void *arg)
|
||||
{
|
||||
CURLState *s = (CURLState *)arg;
|
||||
|
||||
qemu_mutex_lock(&s->s->mutex);
|
||||
curl_multi_do_locked(s);
|
||||
curl_multi_check_completion(s->s);
|
||||
qemu_mutex_unlock(&s->s->mutex);
|
||||
qemu_mutex_lock(&s->mutex);
|
||||
curl_multi_do_locked(socket);
|
||||
curl_multi_check_completion(s);
|
||||
qemu_mutex_unlock(&s->mutex);
|
||||
}
|
||||
|
||||
static void curl_multi_timeout_do(void *arg)
|
||||
@@ -903,7 +881,13 @@ static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb)
|
||||
trace_curl_setup_preadv(acb->bytes, start, state->range);
|
||||
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
|
||||
|
||||
curl_multi_add_handle(s->multi, state->curl);
|
||||
if (curl_multi_add_handle(s->multi, state->curl) != CURLM_OK) {
|
||||
state->acb[0] = NULL;
|
||||
acb->ret = -EIO;
|
||||
|
||||
curl_clean_state(state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Tell curl it needs to kick things off */
|
||||
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "trace.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/blockjob.h"
|
||||
@@ -815,10 +816,10 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
|
||||
{
|
||||
bool ret;
|
||||
|
||||
/* only bitmaps from one bds are supported */
|
||||
assert(dest->mutex == src->mutex);
|
||||
|
||||
qemu_mutex_lock(dest->mutex);
|
||||
if (src->mutex != dest->mutex) {
|
||||
qemu_mutex_lock(src->mutex);
|
||||
}
|
||||
|
||||
if (bdrv_dirty_bitmap_check(dest, BDRV_BITMAP_DEFAULT, errp)) {
|
||||
goto out;
|
||||
@@ -844,7 +845,4 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
|
||||
|
||||
out:
|
||||
qemu_mutex_unlock(dest->mutex);
|
||||
if (src->mutex != dest->mutex) {
|
||||
qemu_mutex_unlock(src->mutex);
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "dmg.h"
|
||||
#include <bzlib.h>
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#ifndef BLOCK_DMG_H
|
||||
#define BLOCK_DMG_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include <zlib.h>
|
||||
|
||||
|
||||
+27
-51
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -146,7 +145,6 @@ typedef struct BDRVRawState {
|
||||
uint64_t locked_shared_perm;
|
||||
|
||||
int perm_change_fd;
|
||||
int perm_change_flags;
|
||||
BDRVReopenState *reopen_state;
|
||||
|
||||
#ifdef CONFIG_XFS
|
||||
@@ -1038,13 +1036,15 @@ static void raw_reopen_abort(BDRVReopenState *state)
|
||||
s->reopen_state = NULL;
|
||||
}
|
||||
|
||||
static int sg_get_max_transfer_length(int fd)
|
||||
static int hdev_get_max_transfer_length(BlockDriverState *bs, int fd)
|
||||
{
|
||||
#ifdef BLKSECTGET
|
||||
int max_bytes = 0;
|
||||
|
||||
if (ioctl(fd, BLKSECTGET, &max_bytes) == 0) {
|
||||
short max_sectors = 0;
|
||||
if (bs->sg && ioctl(fd, BLKSECTGET, &max_bytes) == 0) {
|
||||
return max_bytes;
|
||||
} else if (!bs->sg && ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
|
||||
return max_sectors << BDRV_SECTOR_BITS;
|
||||
} else {
|
||||
return -errno;
|
||||
}
|
||||
@@ -1053,31 +1053,25 @@ static int sg_get_max_transfer_length(int fd)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int sg_get_max_segments(int fd)
|
||||
static int hdev_get_max_segments(const struct stat *st)
|
||||
{
|
||||
#ifdef CONFIG_LINUX
|
||||
char buf[32];
|
||||
const char *end;
|
||||
char *sysfspath = NULL;
|
||||
char *sysfspath;
|
||||
int ret;
|
||||
int sysfd = -1;
|
||||
int fd = -1;
|
||||
long max_segments;
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st)) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments",
|
||||
major(st.st_rdev), minor(st.st_rdev));
|
||||
sysfd = open(sysfspath, O_RDONLY);
|
||||
if (sysfd == -1) {
|
||||
major(st->st_rdev), minor(st->st_rdev));
|
||||
fd = open(sysfspath, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
do {
|
||||
ret = read(sysfd, buf, sizeof(buf) - 1);
|
||||
ret = read(fd, buf, sizeof(buf) - 1);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
@@ -1094,8 +1088,8 @@ static int sg_get_max_segments(int fd)
|
||||
}
|
||||
|
||||
out:
|
||||
if (sysfd != -1) {
|
||||
close(sysfd);
|
||||
if (fd != -1) {
|
||||
close(fd);
|
||||
}
|
||||
g_free(sysfspath);
|
||||
return ret;
|
||||
@@ -1107,17 +1101,19 @@ out:
|
||||
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
struct stat st;
|
||||
|
||||
if (bs->sg) {
|
||||
int ret = sg_get_max_transfer_length(s->fd);
|
||||
|
||||
if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
|
||||
bs->bl.max_transfer = pow2floor(ret);
|
||||
}
|
||||
|
||||
ret = sg_get_max_segments(s->fd);
|
||||
if (ret > 0) {
|
||||
bs->bl.max_transfer = MIN(bs->bl.max_transfer, ret * getpagesize());
|
||||
if (!fstat(s->fd, &st)) {
|
||||
if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
|
||||
int ret = hdev_get_max_transfer_length(bs, s->fd);
|
||||
if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
|
||||
bs->bl.max_transfer = pow2floor(ret);
|
||||
}
|
||||
ret = hdev_get_max_segments(&st);
|
||||
if (ret > 0) {
|
||||
bs->bl.max_transfer = MIN(bs->bl.max_transfer,
|
||||
ret * getpagesize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1448,22 +1444,9 @@ out:
|
||||
#ifdef CONFIG_XFS
|
||||
static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes)
|
||||
{
|
||||
int64_t len;
|
||||
struct xfs_flock64 fl;
|
||||
int err;
|
||||
|
||||
len = lseek(s->fd, 0, SEEK_END);
|
||||
if (len < 0) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (offset + bytes > len) {
|
||||
/* XFS_IOC_ZERO_RANGE does not increase the file length */
|
||||
if (ftruncate(s->fd, offset + bytes) < 0) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&fl, 0, sizeof(fl));
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = offset;
|
||||
@@ -2755,11 +2738,7 @@ static QemuOptsList raw_create_opts = {
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off"
|
||||
#ifdef CONFIG_POSIX_FALLOCATE
|
||||
", falloc"
|
||||
#endif
|
||||
", full)"
|
||||
.help = "Preallocation mode (allowed values: off, falloc, full)"
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
@@ -2791,7 +2770,6 @@ static int raw_check_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared,
|
||||
assert(s->reopen_state->shared_perm == shared);
|
||||
rs = s->reopen_state->opaque;
|
||||
s->perm_change_fd = rs->fd;
|
||||
s->perm_change_flags = rs->open_flags;
|
||||
} else {
|
||||
/* We may need a new fd if auto-read-only switches the mode */
|
||||
ret = raw_reconfigure_getfd(bs, bs->open_flags, &open_flags, perm,
|
||||
@@ -2800,7 +2778,6 @@ static int raw_check_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared,
|
||||
return ret;
|
||||
} else if (ret != s->fd) {
|
||||
s->perm_change_fd = ret;
|
||||
s->perm_change_flags = open_flags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2839,7 +2816,6 @@ static void raw_set_perm(BlockDriverState *bs, uint64_t perm, uint64_t shared)
|
||||
if (s->perm_change_fd && s->fd != s->perm_change_fd) {
|
||||
qemu_close(s->fd);
|
||||
s->fd = s->perm_change_fd;
|
||||
s->open_flags = s->perm_change_flags;
|
||||
}
|
||||
s->perm_change_fd = 0;
|
||||
|
||||
|
||||
+2
-20
@@ -18,7 +18,6 @@
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/uri.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
||||
@@ -98,14 +97,7 @@ static QemuOptsList qemu_gluster_create_opts = {
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off"
|
||||
#ifdef CONFIG_GLUSTERFS_FALLOCATE
|
||||
", falloc"
|
||||
#endif
|
||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||
", full"
|
||||
#endif
|
||||
")"
|
||||
.help = "Preallocation mode (allowed values: off, full)"
|
||||
},
|
||||
{
|
||||
.name = GLUSTER_OPT_DEBUG,
|
||||
@@ -931,17 +923,7 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
|
||||
gconf->has_debug = true;
|
||||
gconf->logfile = g_strdup(s->logfile);
|
||||
gconf->has_logfile = true;
|
||||
|
||||
/*
|
||||
* If 'state->bs->exact_filename' is empty, 'state->options' should contain
|
||||
* the JSON parameters already parsed.
|
||||
*/
|
||||
if (state->bs->exact_filename[0] != '\0') {
|
||||
reop_s->glfs = qemu_gluster_init(gconf, state->bs->exact_filename, NULL,
|
||||
errp);
|
||||
} else {
|
||||
reop_s->glfs = qemu_gluster_init(gconf, NULL, state->options, errp);
|
||||
}
|
||||
reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, NULL, errp);
|
||||
if (reop_s->glfs == NULL) {
|
||||
ret = -errno;
|
||||
goto exit;
|
||||
|
||||
+93
-144
@@ -42,8 +42,8 @@ static void bdrv_parent_cb_resize(BlockDriverState *bs);
|
||||
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||
int64_t offset, int bytes, BdrvRequestFlags flags);
|
||||
|
||||
static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
|
||||
bool ignore_bds_parents)
|
||||
void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
|
||||
bool ignore_bds_parents)
|
||||
{
|
||||
BdrvChild *c, *next;
|
||||
|
||||
@@ -55,34 +55,18 @@ static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
|
||||
}
|
||||
}
|
||||
|
||||
static void bdrv_parent_drained_end_single_no_poll(BdrvChild *c,
|
||||
int *drained_end_counter)
|
||||
void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore,
|
||||
bool ignore_bds_parents)
|
||||
{
|
||||
assert(c->parent_quiesce_counter > 0);
|
||||
c->parent_quiesce_counter--;
|
||||
if (c->role->drained_end) {
|
||||
c->role->drained_end(c, drained_end_counter);
|
||||
}
|
||||
}
|
||||
BdrvChild *c, *next;
|
||||
|
||||
void bdrv_parent_drained_end_single(BdrvChild *c)
|
||||
{
|
||||
int drained_end_counter = 0;
|
||||
bdrv_parent_drained_end_single_no_poll(c, &drained_end_counter);
|
||||
BDRV_POLL_WHILE(c->bs, atomic_read(&drained_end_counter) > 0);
|
||||
}
|
||||
|
||||
static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore,
|
||||
bool ignore_bds_parents,
|
||||
int *drained_end_counter)
|
||||
{
|
||||
BdrvChild *c;
|
||||
|
||||
QLIST_FOREACH(c, &bs->parents, next_parent) {
|
||||
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
|
||||
if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
|
||||
continue;
|
||||
}
|
||||
bdrv_parent_drained_end_single_no_poll(c, drained_end_counter);
|
||||
if (c->role->drained_end) {
|
||||
c->role->drained_end(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +96,6 @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
|
||||
|
||||
void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
|
||||
{
|
||||
c->parent_quiesce_counter++;
|
||||
if (c->role->drained_begin) {
|
||||
c->role->drained_begin(c);
|
||||
}
|
||||
@@ -203,7 +186,6 @@ typedef struct {
|
||||
bool poll;
|
||||
BdrvChild *parent;
|
||||
bool ignore_bds_parents;
|
||||
int *drained_end_counter;
|
||||
} BdrvCoDrainData;
|
||||
|
||||
static void coroutine_fn bdrv_drain_invoke_entry(void *opaque)
|
||||
@@ -217,19 +199,17 @@ static void coroutine_fn bdrv_drain_invoke_entry(void *opaque)
|
||||
bs->drv->bdrv_co_drain_end(bs);
|
||||
}
|
||||
|
||||
/* Set data->done and decrement drained_end_counter before bdrv_wakeup() */
|
||||
/* Set data->done before reading bs->wakeup. */
|
||||
atomic_mb_set(&data->done, true);
|
||||
if (!data->begin) {
|
||||
atomic_dec(data->drained_end_counter);
|
||||
}
|
||||
bdrv_dec_in_flight(bs);
|
||||
|
||||
g_free(data);
|
||||
if (data->begin) {
|
||||
g_free(data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Recursively call BlockDriver.bdrv_co_drain_begin/end callbacks */
|
||||
static void bdrv_drain_invoke(BlockDriverState *bs, bool begin,
|
||||
int *drained_end_counter)
|
||||
static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
|
||||
{
|
||||
BdrvCoDrainData *data;
|
||||
|
||||
@@ -242,19 +222,19 @@ static void bdrv_drain_invoke(BlockDriverState *bs, bool begin,
|
||||
*data = (BdrvCoDrainData) {
|
||||
.bs = bs,
|
||||
.done = false,
|
||||
.begin = begin,
|
||||
.drained_end_counter = drained_end_counter,
|
||||
.begin = begin
|
||||
};
|
||||
|
||||
if (!begin) {
|
||||
atomic_inc(drained_end_counter);
|
||||
}
|
||||
|
||||
/* Make sure the driver callback completes during the polling phase for
|
||||
* drain_begin. */
|
||||
bdrv_inc_in_flight(bs);
|
||||
data->co = qemu_coroutine_create(bdrv_drain_invoke_entry, data);
|
||||
aio_co_schedule(bdrv_get_aio_context(bs), data->co);
|
||||
|
||||
if (!begin) {
|
||||
BDRV_POLL_WHILE(bs, !data->done);
|
||||
g_free(data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if BDRV_POLL_WHILE() should go into a blocking aio_poll() */
|
||||
@@ -293,8 +273,7 @@ static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
|
||||
BdrvChild *parent, bool ignore_bds_parents,
|
||||
bool poll);
|
||||
static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
|
||||
BdrvChild *parent, bool ignore_bds_parents,
|
||||
int *drained_end_counter);
|
||||
BdrvChild *parent, bool ignore_bds_parents);
|
||||
|
||||
static void bdrv_co_drain_bh_cb(void *opaque)
|
||||
{
|
||||
@@ -317,14 +296,11 @@ static void bdrv_co_drain_bh_cb(void *opaque)
|
||||
}
|
||||
bdrv_dec_in_flight(bs);
|
||||
if (data->begin) {
|
||||
assert(!data->drained_end_counter);
|
||||
bdrv_do_drained_begin(bs, data->recursive, data->parent,
|
||||
data->ignore_bds_parents, data->poll);
|
||||
} else {
|
||||
assert(!data->poll);
|
||||
bdrv_do_drained_end(bs, data->recursive, data->parent,
|
||||
data->ignore_bds_parents,
|
||||
data->drained_end_counter);
|
||||
data->ignore_bds_parents);
|
||||
}
|
||||
if (ctx == co_ctx) {
|
||||
aio_context_release(ctx);
|
||||
@@ -342,8 +318,7 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
|
||||
bool begin, bool recursive,
|
||||
BdrvChild *parent,
|
||||
bool ignore_bds_parents,
|
||||
bool poll,
|
||||
int *drained_end_counter)
|
||||
bool poll)
|
||||
{
|
||||
BdrvCoDrainData data;
|
||||
|
||||
@@ -360,9 +335,7 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
|
||||
.parent = parent,
|
||||
.ignore_bds_parents = ignore_bds_parents,
|
||||
.poll = poll,
|
||||
.drained_end_counter = drained_end_counter,
|
||||
};
|
||||
|
||||
if (bs) {
|
||||
bdrv_inc_in_flight(bs);
|
||||
}
|
||||
@@ -386,7 +359,7 @@ void bdrv_do_drained_begin_quiesce(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
bdrv_parent_drained_begin(bs, parent, ignore_bds_parents);
|
||||
bdrv_drain_invoke(bs, true, NULL);
|
||||
bdrv_drain_invoke(bs, true);
|
||||
}
|
||||
|
||||
static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
|
||||
@@ -397,7 +370,7 @@ static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_yield_to_drain(bs, true, recursive, parent, ignore_bds_parents,
|
||||
poll, NULL);
|
||||
poll);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -437,42 +410,23 @@ void bdrv_subtree_drained_begin(BlockDriverState *bs)
|
||||
bdrv_do_drained_begin(bs, true, NULL, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function does not poll, nor must any of its recursively called
|
||||
* functions. The *drained_end_counter pointee will be incremented
|
||||
* once for every background operation scheduled, and decremented once
|
||||
* the operation settles. Therefore, the pointer must remain valid
|
||||
* until the pointee reaches 0. That implies that whoever sets up the
|
||||
* pointee has to poll until it is 0.
|
||||
*
|
||||
* We use atomic operations to access *drained_end_counter, because
|
||||
* (1) when called from bdrv_set_aio_context_ignore(), the subgraph of
|
||||
* @bs may contain nodes in different AioContexts,
|
||||
* (2) bdrv_drain_all_end() uses the same counter for all nodes,
|
||||
* regardless of which AioContext they are in.
|
||||
*/
|
||||
static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
|
||||
BdrvChild *parent, bool ignore_bds_parents,
|
||||
int *drained_end_counter)
|
||||
BdrvChild *parent, bool ignore_bds_parents)
|
||||
{
|
||||
BdrvChild *child;
|
||||
BdrvChild *child, *next;
|
||||
int old_quiesce_counter;
|
||||
|
||||
assert(drained_end_counter != NULL);
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_yield_to_drain(bs, false, recursive, parent, ignore_bds_parents,
|
||||
false, drained_end_counter);
|
||||
false);
|
||||
return;
|
||||
}
|
||||
assert(bs->quiesce_counter > 0);
|
||||
old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter);
|
||||
|
||||
/* Re-enable things in child-to-parent order */
|
||||
bdrv_drain_invoke(bs, false, drained_end_counter);
|
||||
bdrv_parent_drained_end(bs, parent, ignore_bds_parents,
|
||||
drained_end_counter);
|
||||
|
||||
old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter);
|
||||
bdrv_drain_invoke(bs, false);
|
||||
bdrv_parent_drained_end(bs, parent, ignore_bds_parents);
|
||||
if (old_quiesce_counter == 1) {
|
||||
aio_enable_external(bdrv_get_aio_context(bs));
|
||||
}
|
||||
@@ -480,30 +434,20 @@ static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
|
||||
if (recursive) {
|
||||
assert(!ignore_bds_parents);
|
||||
bs->recursive_quiesce_counter--;
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
bdrv_do_drained_end(child->bs, true, child, ignore_bds_parents,
|
||||
drained_end_counter);
|
||||
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
|
||||
bdrv_do_drained_end(child->bs, true, child, ignore_bds_parents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_drained_end(BlockDriverState *bs)
|
||||
{
|
||||
int drained_end_counter = 0;
|
||||
bdrv_do_drained_end(bs, false, NULL, false, &drained_end_counter);
|
||||
BDRV_POLL_WHILE(bs, atomic_read(&drained_end_counter) > 0);
|
||||
}
|
||||
|
||||
void bdrv_drained_end_no_poll(BlockDriverState *bs, int *drained_end_counter)
|
||||
{
|
||||
bdrv_do_drained_end(bs, false, NULL, false, drained_end_counter);
|
||||
bdrv_do_drained_end(bs, false, NULL, false);
|
||||
}
|
||||
|
||||
void bdrv_subtree_drained_end(BlockDriverState *bs)
|
||||
{
|
||||
int drained_end_counter = 0;
|
||||
bdrv_do_drained_end(bs, true, NULL, false, &drained_end_counter);
|
||||
BDRV_POLL_WHILE(bs, atomic_read(&drained_end_counter) > 0);
|
||||
bdrv_do_drained_end(bs, true, NULL, false);
|
||||
}
|
||||
|
||||
void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent)
|
||||
@@ -517,15 +461,11 @@ void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent)
|
||||
|
||||
void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent)
|
||||
{
|
||||
int drained_end_counter = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < old_parent->recursive_quiesce_counter; i++) {
|
||||
bdrv_do_drained_end(child->bs, true, child, false,
|
||||
&drained_end_counter);
|
||||
bdrv_do_drained_end(child->bs, true, child, false);
|
||||
}
|
||||
|
||||
BDRV_POLL_WHILE(child->bs, atomic_read(&drained_end_counter) > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -594,7 +534,7 @@ void bdrv_drain_all_begin(void)
|
||||
BlockDriverState *bs = NULL;
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_yield_to_drain(NULL, true, false, NULL, true, true, NULL);
|
||||
bdrv_co_yield_to_drain(NULL, true, false, NULL, true, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -625,19 +565,15 @@ void bdrv_drain_all_begin(void)
|
||||
void bdrv_drain_all_end(void)
|
||||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
int drained_end_counter = 0;
|
||||
|
||||
while ((bs = bdrv_next_all_states(bs))) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_do_drained_end(bs, false, NULL, true, &drained_end_counter);
|
||||
bdrv_do_drained_end(bs, false, NULL, true);
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||
AIO_WAIT_WHILE(NULL, atomic_read(&drained_end_counter) > 0);
|
||||
|
||||
assert(bdrv_drain_all_count > 0);
|
||||
bdrv_drain_all_count--;
|
||||
}
|
||||
@@ -833,7 +769,7 @@ static bool coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self)
|
||||
static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
|
||||
size_t size)
|
||||
{
|
||||
if (size > BDRV_REQUEST_MAX_BYTES) {
|
||||
if (size > BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -901,6 +837,42 @@ static int bdrv_prwv_co(BdrvChild *child, int64_t offset,
|
||||
return rwco.ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a synchronous request using coroutines
|
||||
*/
|
||||
static int bdrv_rw_co(BdrvChild *child, int64_t sector_num, uint8_t *buf,
|
||||
int nb_sectors, bool is_write, BdrvRequestFlags flags)
|
||||
{
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf,
|
||||
nb_sectors * BDRV_SECTOR_SIZE);
|
||||
|
||||
if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bdrv_prwv_co(child, sector_num << BDRV_SECTOR_BITS,
|
||||
&qiov, is_write, flags);
|
||||
}
|
||||
|
||||
/* return < 0 if error. See bdrv_write() for the return codes */
|
||||
int bdrv_read(BdrvChild *child, int64_t sector_num,
|
||||
uint8_t *buf, int nb_sectors)
|
||||
{
|
||||
return bdrv_rw_co(child, sector_num, buf, nb_sectors, false, 0);
|
||||
}
|
||||
|
||||
/* Return < 0 if error. Important errors are:
|
||||
-EIO generic I/O error (may happen for all errors)
|
||||
-ENOMEDIUM No media inserted.
|
||||
-EINVAL Invalid sector number or nb_sectors
|
||||
-EACCES Trying to write a read-only device
|
||||
*/
|
||||
int bdrv_write(BdrvChild *child, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors)
|
||||
{
|
||||
return bdrv_rw_co(child, sector_num, (uint8_t *)buf, nb_sectors, true, 0);
|
||||
}
|
||||
|
||||
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
||||
int bytes, BdrvRequestFlags flags)
|
||||
{
|
||||
@@ -963,7 +935,6 @@ int bdrv_preadv(BdrvChild *child, int64_t offset, QEMUIOVector *qiov)
|
||||
return qiov->size;
|
||||
}
|
||||
|
||||
/* See bdrv_pwrite() for the return codes */
|
||||
int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int bytes)
|
||||
{
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||
@@ -987,12 +958,6 @@ int bdrv_pwritev(BdrvChild *child, int64_t offset, QEMUIOVector *qiov)
|
||||
return qiov->size;
|
||||
}
|
||||
|
||||
/* Return no. of bytes on success or < 0 on error. Important errors are:
|
||||
-EIO generic I/O error (may happen for all errors)
|
||||
-ENOMEDIUM No media inserted.
|
||||
-EINVAL Invalid offset or number of bytes
|
||||
-EACCES Trying to write a read-only device
|
||||
*/
|
||||
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf, int bytes)
|
||||
{
|
||||
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
||||
@@ -1081,7 +1046,7 @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
|
||||
|
||||
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
assert(bytes <= BDRV_REQUEST_MAX_BYTES);
|
||||
assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
|
||||
assert(drv->bdrv_co_readv);
|
||||
|
||||
return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
|
||||
@@ -1134,7 +1099,7 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
|
||||
|
||||
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
||||
assert(bytes <= BDRV_REQUEST_MAX_BYTES);
|
||||
assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
|
||||
|
||||
assert(drv->bdrv_co_writev);
|
||||
ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov,
|
||||
@@ -1551,7 +1516,7 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||
assert(!bs->supported_zero_flags);
|
||||
}
|
||||
|
||||
if (ret < 0 && !(flags & BDRV_REQ_NO_FALLBACK)) {
|
||||
if (ret == -ENOTSUP && !(flags & BDRV_REQ_NO_FALLBACK)) {
|
||||
/* Fall back to bounce buffer if write zeroes is unsupported */
|
||||
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
|
||||
|
||||
@@ -2156,12 +2121,6 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
|
||||
*/
|
||||
assert(*pnum && QEMU_IS_ALIGNED(*pnum, align) &&
|
||||
align > offset - aligned_offset);
|
||||
if (ret & BDRV_BLOCK_RECURSE) {
|
||||
assert(ret & BDRV_BLOCK_DATA);
|
||||
assert(ret & BDRV_BLOCK_OFFSET_VALID);
|
||||
assert(!(ret & BDRV_BLOCK_ZERO));
|
||||
}
|
||||
|
||||
*pnum -= offset - aligned_offset;
|
||||
if (*pnum > bytes) {
|
||||
*pnum = bytes;
|
||||
@@ -2192,8 +2151,7 @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
|
||||
}
|
||||
}
|
||||
|
||||
if (want_zero && ret & BDRV_BLOCK_RECURSE &&
|
||||
local_file && local_file != bs &&
|
||||
if (want_zero && local_file && local_file != bs &&
|
||||
(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) &&
|
||||
(ret & BDRV_BLOCK_OFFSET_VALID)) {
|
||||
int64_t file_pnum;
|
||||
@@ -2358,11 +2316,10 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
|
||||
/*
|
||||
* Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP]
|
||||
*
|
||||
* Return 1 if (a prefix of) the given range is allocated in any image
|
||||
* between BASE and TOP (BASE is only included if include_base is set).
|
||||
* BASE can be NULL to check if the given offset is allocated in any
|
||||
* image of the chain. Return 0 otherwise, or negative errno on
|
||||
* failure.
|
||||
* Return true if (a prefix of) the given range is allocated in any image
|
||||
* between BASE and TOP (inclusive). BASE can be NULL to check if the given
|
||||
* offset is allocated in any image of the chain. Return false otherwise,
|
||||
* or negative errno on failure.
|
||||
*
|
||||
* 'pnum' is set to the number of bytes (including and immediately
|
||||
* following the specified offset) that are known to be in the same
|
||||
@@ -2374,21 +2331,17 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
|
||||
*/
|
||||
int bdrv_is_allocated_above(BlockDriverState *top,
|
||||
BlockDriverState *base,
|
||||
bool include_base, int64_t offset,
|
||||
int64_t bytes, int64_t *pnum)
|
||||
int64_t offset, int64_t bytes, int64_t *pnum)
|
||||
{
|
||||
BlockDriverState *intermediate;
|
||||
int ret;
|
||||
int64_t n = bytes;
|
||||
|
||||
assert(base || !include_base);
|
||||
|
||||
intermediate = top;
|
||||
while (include_base || intermediate != base) {
|
||||
while (intermediate && intermediate != base) {
|
||||
int64_t pnum_inter;
|
||||
int64_t size_inter;
|
||||
|
||||
assert(intermediate);
|
||||
ret = bdrv_is_allocated(intermediate, offset, bytes, &pnum_inter);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -2407,10 +2360,6 @@ int bdrv_is_allocated_above(BlockDriverState *top,
|
||||
n = pnum_inter;
|
||||
}
|
||||
|
||||
if (intermediate == base) {
|
||||
break;
|
||||
}
|
||||
|
||||
intermediate = backing_bs(intermediate);
|
||||
}
|
||||
|
||||
@@ -2704,7 +2653,7 @@ int bdrv_flush(BlockDriverState *bs)
|
||||
typedef struct DiscardCo {
|
||||
BdrvChild *child;
|
||||
int64_t offset;
|
||||
int64_t bytes;
|
||||
int bytes;
|
||||
int ret;
|
||||
} DiscardCo;
|
||||
static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque)
|
||||
@@ -2715,15 +2664,14 @@ static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque)
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
|
||||
int64_t bytes)
|
||||
int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
|
||||
{
|
||||
BdrvTrackedRequest req;
|
||||
int max_pdiscard, ret;
|
||||
int head, tail, align;
|
||||
BlockDriverState *bs = child->bs;
|
||||
|
||||
if (!bs || !bs->drv || !bdrv_is_inserted(bs)) {
|
||||
if (!bs || !bs->drv) {
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
@@ -2731,8 +2679,9 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (offset < 0 || bytes < 0 || bytes > INT64_MAX - offset) {
|
||||
return -EIO;
|
||||
ret = bdrv_check_byte_request(bs, offset, bytes);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Do nothing if disabled. */
|
||||
@@ -2767,7 +2716,7 @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
|
||||
assert(max_pdiscard >= bs->bl.request_alignment);
|
||||
|
||||
while (bytes > 0) {
|
||||
int64_t num = bytes;
|
||||
int num = bytes;
|
||||
|
||||
if (head) {
|
||||
/* Make small requests to get to alignment boundaries. */
|
||||
@@ -2829,7 +2778,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes)
|
||||
int bdrv_pdiscard(BdrvChild *child, int64_t offset, int bytes)
|
||||
{
|
||||
Coroutine *co;
|
||||
DiscardCo rwco = {
|
||||
|
||||
+1
-1
@@ -23,8 +23,8 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
|
||||
static QemuOptsList qemu_iscsi_opts = {
|
||||
|
||||
+15
-16
@@ -28,7 +28,6 @@
|
||||
#include <poll.h>
|
||||
#include <math.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/bitops.h"
|
||||
@@ -37,7 +36,6 @@
|
||||
#include "block/qdict.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/uuid.h"
|
||||
#include "qapi/error.h"
|
||||
@@ -225,9 +223,9 @@ static inline unsigned exp_random(double mean)
|
||||
|
||||
static int iscsi_translate_sense(struct scsi_sense *sense)
|
||||
{
|
||||
return scsi_sense_to_errno(sense->key,
|
||||
(sense->ascq & 0xFF00) >> 8,
|
||||
sense->ascq & 0xFF);
|
||||
return - scsi_sense_to_errno(sense->key,
|
||||
(sense->ascq & 0xFF00) >> 8,
|
||||
sense->ascq & 0xFF);
|
||||
}
|
||||
|
||||
/* Called (via iscsi_service) with QemuMutex held. */
|
||||
@@ -244,6 +242,13 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
|
||||
|
||||
if (status != SCSI_STATUS_GOOD) {
|
||||
if (iTask->retries++ < ISCSI_CMD_RETRIES) {
|
||||
if (status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
|
||||
error_report("iSCSI CheckCondition: %s",
|
||||
iscsi_get_error(iscsi));
|
||||
iTask->do_retry = 1;
|
||||
goto out;
|
||||
}
|
||||
if (status == SCSI_STATUS_BUSY ||
|
||||
status == SCSI_STATUS_TIMEOUT ||
|
||||
status == SCSI_STATUS_TASK_SET_FULL) {
|
||||
@@ -265,20 +270,14 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
|
||||
timer_mod(&iTask->retry_timer,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + retry_time);
|
||||
iTask->do_retry = 1;
|
||||
}
|
||||
} else if (status == SCSI_STATUS_CHECK_CONDITION) {
|
||||
int error = iscsi_translate_sense(&task->sense);
|
||||
if (error == EAGAIN) {
|
||||
error_report("iSCSI CheckCondition: %s",
|
||||
iscsi_get_error(iscsi));
|
||||
iTask->do_retry = 1;
|
||||
} else {
|
||||
iTask->err_code = -error;
|
||||
iTask->err_str = g_strdup(iscsi_get_error(iscsi));
|
||||
return;
|
||||
}
|
||||
}
|
||||
iTask->err_code = iscsi_translate_sense(&task->sense);
|
||||
iTask->err_str = g_strdup(iscsi_get_error(iscsi));
|
||||
}
|
||||
|
||||
out:
|
||||
if (iTask->co) {
|
||||
aio_bh_schedule_oneshot(iTask->iscsilun->aio_context,
|
||||
iscsi_co_generic_bh_cb, iTask);
|
||||
@@ -973,7 +972,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
|
||||
if (status < 0) {
|
||||
error_report("Failed to ioctl(SG_IO) to iSCSI lun. %s",
|
||||
iscsi_get_error(iscsi));
|
||||
acb->status = -iscsi_translate_sense(&acb->task->sense);
|
||||
acb->status = iscsi_translate_sense(&acb->task->sense);
|
||||
}
|
||||
|
||||
acb->ioh->driver_status = 0;
|
||||
|
||||
+63
-10
@@ -8,6 +8,7 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/aio.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "block/block.h"
|
||||
@@ -29,6 +30,7 @@
|
||||
#define MAX_EVENTS 128
|
||||
|
||||
struct qemu_laiocb {
|
||||
BlockAIOCB common;
|
||||
Coroutine *co;
|
||||
LinuxAioState *ctx;
|
||||
struct iocb iocb;
|
||||
@@ -70,7 +72,7 @@ static inline ssize_t io_event_ret(struct io_event *ev)
|
||||
}
|
||||
|
||||
/*
|
||||
* Completes an AIO request.
|
||||
* Completes an AIO request (calls the callback and frees the ACB).
|
||||
*/
|
||||
static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
|
||||
{
|
||||
@@ -92,15 +94,18 @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
|
||||
}
|
||||
|
||||
laiocb->ret = ret;
|
||||
|
||||
/*
|
||||
* If the coroutine is already entered it must be in ioq_submit() and
|
||||
* will notice laio->ret has been filled in when it eventually runs
|
||||
* later. Coroutines cannot be entered recursively so avoid doing
|
||||
* that!
|
||||
*/
|
||||
if (!qemu_coroutine_entered(laiocb->co)) {
|
||||
aio_co_wake(laiocb->co);
|
||||
if (laiocb->co) {
|
||||
/* If the coroutine is already entered it must be in ioq_submit() and
|
||||
* will notice laio->ret has been filled in when it eventually runs
|
||||
* later. Coroutines cannot be entered recursively so avoid doing
|
||||
* that!
|
||||
*/
|
||||
if (!qemu_coroutine_entered(laiocb->co)) {
|
||||
aio_co_wake(laiocb->co);
|
||||
}
|
||||
} else {
|
||||
laiocb->common.cb(laiocb->common.opaque, ret);
|
||||
qemu_aio_unref(laiocb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +273,30 @@ static bool qemu_laio_poll_cb(void *opaque)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void laio_cancel(BlockAIOCB *blockacb)
|
||||
{
|
||||
struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb;
|
||||
struct io_event event;
|
||||
int ret;
|
||||
|
||||
if (laiocb->ret != -EINPROGRESS) {
|
||||
return;
|
||||
}
|
||||
ret = io_cancel(laiocb->ctx->ctx, &laiocb->iocb, &event);
|
||||
laiocb->ret = -ECANCELED;
|
||||
if (ret != 0) {
|
||||
/* iocb is not cancelled, cb will be called by the event loop later */
|
||||
return;
|
||||
}
|
||||
|
||||
laiocb->common.cb(laiocb->common.opaque, laiocb->ret);
|
||||
}
|
||||
|
||||
static const AIOCBInfo laio_aiocb_info = {
|
||||
.aiocb_size = sizeof(struct qemu_laiocb),
|
||||
.cancel_async = laio_cancel,
|
||||
};
|
||||
|
||||
static void ioq_init(LaioQueue *io_q)
|
||||
{
|
||||
QSIMPLEQ_INIT(&io_q->pending);
|
||||
@@ -402,6 +431,30 @@ int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
|
||||
return laiocb.ret;
|
||||
}
|
||||
|
||||
BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
|
||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
BlockCompletionFunc *cb, void *opaque, int type)
|
||||
{
|
||||
struct qemu_laiocb *laiocb;
|
||||
off_t offset = sector_num * BDRV_SECTOR_SIZE;
|
||||
int ret;
|
||||
|
||||
laiocb = qemu_aio_get(&laio_aiocb_info, bs, cb, opaque);
|
||||
laiocb->nbytes = nb_sectors * BDRV_SECTOR_SIZE;
|
||||
laiocb->ctx = s;
|
||||
laiocb->ret = -EINPROGRESS;
|
||||
laiocb->is_read = (type == QEMU_AIO_READ);
|
||||
laiocb->qiov = qiov;
|
||||
|
||||
ret = laio_do_submit(fd, laiocb, offset, type);
|
||||
if (ret < 0) {
|
||||
qemu_aio_unref(laiocb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &laiocb->common;
|
||||
}
|
||||
|
||||
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context)
|
||||
{
|
||||
aio_set_event_notifier(old_context, &s->e, false, NULL, NULL);
|
||||
|
||||
+37
-53
@@ -85,7 +85,6 @@ typedef struct MirrorBlockJob {
|
||||
|
||||
typedef struct MirrorBDSOpaque {
|
||||
MirrorBlockJob *job;
|
||||
bool stop;
|
||||
} MirrorBDSOpaque;
|
||||
|
||||
struct MirrorOp {
|
||||
@@ -657,9 +656,8 @@ static int mirror_exit_common(Job *job)
|
||||
|
||||
/* We don't access the source any more. Dropping any WRITE/RESIZE is
|
||||
* required before it could become a backing file of target_bs. */
|
||||
bs_opaque->stop = true;
|
||||
bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing,
|
||||
&error_abort);
|
||||
bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,
|
||||
&error_abort);
|
||||
if (!abort && s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) {
|
||||
BlockDriverState *backing = s->is_none_mode ? src : s->base;
|
||||
if (backing_bs(target_bs) != backing) {
|
||||
@@ -706,12 +704,13 @@ static int mirror_exit_common(Job *job)
|
||||
g_free(s->replaces);
|
||||
bdrv_unref(target_bs);
|
||||
|
||||
/*
|
||||
* Remove the mirror filter driver from the graph. Before this, get rid of
|
||||
/* Remove the mirror filter driver from the graph. Before this, get rid of
|
||||
* the blockers on the intermediate nodes so that the resulting state is
|
||||
* valid.
|
||||
*/
|
||||
* valid. Also give up permissions on mirror_top_bs->backing, which might
|
||||
* block the removal. */
|
||||
block_job_remove_all_bdrv(bjob);
|
||||
bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,
|
||||
&error_abort);
|
||||
bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);
|
||||
|
||||
/* We just changed the BDS the job BB refers to (with either or both of the
|
||||
@@ -808,7 +807,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = bdrv_is_allocated_above(bs, base, false, offset, bytes, &count);
|
||||
ret = bdrv_is_allocated_above(bs, base, offset, bytes, &count);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -1143,6 +1142,13 @@ static bool mirror_drained_poll(BlockJob *job)
|
||||
return !!s->in_flight;
|
||||
}
|
||||
|
||||
static void mirror_attached_aio_context(BlockJob *job, AioContext *new_context)
|
||||
{
|
||||
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
|
||||
|
||||
blk_set_aio_context(s->target, new_context);
|
||||
}
|
||||
|
||||
static void mirror_drain(BlockJob *job)
|
||||
{
|
||||
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
|
||||
@@ -1172,6 +1178,7 @@ static const BlockJobDriver mirror_job_driver = {
|
||||
.complete = mirror_complete,
|
||||
},
|
||||
.drained_poll = mirror_drained_poll,
|
||||
.attached_aio_context = mirror_attached_aio_context,
|
||||
.drain = mirror_drain,
|
||||
};
|
||||
|
||||
@@ -1189,6 +1196,7 @@ static const BlockJobDriver commit_active_job_driver = {
|
||||
.complete = mirror_complete,
|
||||
},
|
||||
.drained_poll = mirror_drained_poll,
|
||||
.attached_aio_context = mirror_attached_aio_context,
|
||||
.drain = mirror_drain,
|
||||
};
|
||||
|
||||
@@ -1460,18 +1468,6 @@ static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
|
||||
uint64_t perm, uint64_t shared,
|
||||
uint64_t *nperm, uint64_t *nshared)
|
||||
{
|
||||
MirrorBDSOpaque *s = bs->opaque;
|
||||
|
||||
if (s->stop) {
|
||||
/*
|
||||
* If the job is to be stopped, we do not need to forward
|
||||
* anything to the real image.
|
||||
*/
|
||||
*nperm = 0;
|
||||
*nshared = BLK_PERM_ALL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Must be able to forward guest writes to the real image */
|
||||
*nperm = 0;
|
||||
if (perm & BLK_PERM_WRITE) {
|
||||
@@ -1505,8 +1501,7 @@ static BlockDriver bdrv_mirror_top = {
|
||||
.bdrv_refresh_limits = bdrv_mirror_top_refresh_limits,
|
||||
};
|
||||
|
||||
static BlockJob *mirror_start_job(
|
||||
const char *job_id, BlockDriverState *bs,
|
||||
static void mirror_start_job(const char *job_id, BlockDriverState *bs,
|
||||
int creation_flags, BlockDriverState *target,
|
||||
const char *replaces, int64_t speed,
|
||||
uint32_t granularity, int64_t buf_size,
|
||||
@@ -1538,7 +1533,7 @@ static BlockJob *mirror_start_job(
|
||||
|
||||
if (buf_size < 0) {
|
||||
error_setg(errp, "Invalid parameter 'buf-size'");
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf_size == 0) {
|
||||
@@ -1547,7 +1542,7 @@ static BlockJob *mirror_start_job(
|
||||
|
||||
if (bs == target) {
|
||||
error_setg(errp, "Can't mirror node into itself");
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* In the case of active commit, add dummy driver to provide consistent
|
||||
@@ -1556,21 +1551,18 @@ static BlockJob *mirror_start_job(
|
||||
mirror_top_bs = bdrv_new_open_driver(&bdrv_mirror_top, filter_node_name,
|
||||
BDRV_O_RDWR, errp);
|
||||
if (mirror_top_bs == NULL) {
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
if (!filter_node_name) {
|
||||
mirror_top_bs->implicit = true;
|
||||
}
|
||||
|
||||
/* So that we can always drop this node */
|
||||
mirror_top_bs->never_freeze = true;
|
||||
|
||||
mirror_top_bs->total_sectors = bs->total_sectors;
|
||||
mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
|
||||
mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
|
||||
BDRV_REQ_NO_FALLBACK;
|
||||
bs_opaque = g_new0(MirrorBDSOpaque, 1);
|
||||
mirror_top_bs->opaque = bs_opaque;
|
||||
bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));
|
||||
|
||||
/* bdrv_append takes ownership of the mirror_top_bs reference, need to keep
|
||||
* it alive until block_job_create() succeeds even if bs has no parent. */
|
||||
@@ -1582,7 +1574,7 @@ static BlockJob *mirror_start_job(
|
||||
if (local_err) {
|
||||
bdrv_unref(mirror_top_bs);
|
||||
error_propagate(errp, local_err);
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure that the source is not resized while the job is running */
|
||||
@@ -1611,8 +1603,7 @@ static BlockJob *mirror_start_job(
|
||||
* We can allow anything except resize there.*/
|
||||
target_is_backing = bdrv_chain_contains(bs, target);
|
||||
target_graph_mod = (backing_mode != MIRROR_LEAVE_BACKING_CHAIN);
|
||||
s->target = blk_new(s->common.job.aio_context,
|
||||
BLK_PERM_WRITE | BLK_PERM_RESIZE |
|
||||
s->target = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE |
|
||||
(target_graph_mod ? BLK_PERM_GRAPH_MOD : 0),
|
||||
BLK_PERM_WRITE_UNCHANGED |
|
||||
(target_is_backing ? BLK_PERM_CONSISTENT_READ |
|
||||
@@ -1631,7 +1622,6 @@ static BlockJob *mirror_start_job(
|
||||
* ensure that. */
|
||||
blk_set_force_allow_inactivate(s->target);
|
||||
}
|
||||
blk_set_allow_aio_context_change(s->target, true);
|
||||
|
||||
s->replaces = g_strdup(replaces);
|
||||
s->on_source_error = on_source_error;
|
||||
@@ -1709,8 +1699,7 @@ static BlockJob *mirror_start_job(
|
||||
|
||||
trace_mirror_start(bs, s, opaque);
|
||||
job_start(&s->common.job);
|
||||
|
||||
return &s->common;
|
||||
return;
|
||||
|
||||
fail:
|
||||
if (s) {
|
||||
@@ -1727,14 +1716,11 @@ fail:
|
||||
job_early_fail(&s->common.job);
|
||||
}
|
||||
|
||||
bs_opaque->stop = true;
|
||||
bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing,
|
||||
&error_abort);
|
||||
bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,
|
||||
&error_abort);
|
||||
bdrv_replace_node(mirror_top_bs, backing_bs(mirror_top_bs), &error_abort);
|
||||
|
||||
bdrv_unref(mirror_top_bs);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
@@ -1763,27 +1749,25 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
||||
filter_node_name, true, copy_mode, errp);
|
||||
}
|
||||
|
||||
BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *base, int creation_flags,
|
||||
int64_t speed, BlockdevOnError on_error,
|
||||
const char *filter_node_name,
|
||||
BlockCompletionFunc *cb, void *opaque,
|
||||
bool auto_complete, Error **errp)
|
||||
void commit_active_start(const char *job_id, BlockDriverState *bs,
|
||||
BlockDriverState *base, int creation_flags,
|
||||
int64_t speed, BlockdevOnError on_error,
|
||||
const char *filter_node_name,
|
||||
BlockCompletionFunc *cb, void *opaque,
|
||||
bool auto_complete, Error **errp)
|
||||
{
|
||||
bool base_read_only;
|
||||
Error *local_err = NULL;
|
||||
BlockJob *ret;
|
||||
|
||||
base_read_only = bdrv_is_read_only(base);
|
||||
|
||||
if (base_read_only) {
|
||||
if (bdrv_reopen_set_read_only(base, false, errp) < 0) {
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mirror_start_job(
|
||||
job_id, bs, creation_flags, base, NULL, speed, 0, 0,
|
||||
mirror_start_job(job_id, bs, creation_flags, base, NULL, speed, 0, 0,
|
||||
MIRROR_LEAVE_BACKING_CHAIN,
|
||||
on_error, on_error, true, cb, opaque,
|
||||
&commit_active_job_driver, false, base, auto_complete,
|
||||
@@ -1794,7 +1778,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs,
|
||||
goto error_restore_flags;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return;
|
||||
|
||||
error_restore_flags:
|
||||
/* ignore error and errp for bdrv_reopen, because we want to propagate
|
||||
@@ -1802,5 +1786,5 @@ error_restore_flags:
|
||||
if (base_read_only) {
|
||||
bdrv_reopen_set_read_only(base, true, NULL);
|
||||
}
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
+1226
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,72 @@
|
||||
#ifndef NBD_CLIENT_H
|
||||
#define NBD_CLIENT_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "block/nbd.h"
|
||||
#include "block/block_int.h"
|
||||
#include "io/channel-socket.h"
|
||||
|
||||
/* #define DEBUG_NBD */
|
||||
|
||||
#if defined(DEBUG_NBD)
|
||||
#define logout(fmt, ...) \
|
||||
fprintf(stderr, "nbd\t%-24s" fmt, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define logout(fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#define MAX_NBD_REQUESTS 16
|
||||
|
||||
typedef struct {
|
||||
Coroutine *coroutine;
|
||||
uint64_t offset; /* original offset of the request */
|
||||
bool receiving; /* waiting for connection_co? */
|
||||
} NBDClientRequest;
|
||||
|
||||
typedef struct NBDClientSession {
|
||||
QIOChannelSocket *sioc; /* The master data channel */
|
||||
QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
|
||||
NBDExportInfo info;
|
||||
|
||||
CoMutex send_mutex;
|
||||
CoQueue free_sema;
|
||||
Coroutine *connection_co;
|
||||
int in_flight;
|
||||
|
||||
NBDClientRequest requests[MAX_NBD_REQUESTS];
|
||||
NBDReply reply;
|
||||
BlockDriverState *bs;
|
||||
bool quit;
|
||||
} NBDClientSession;
|
||||
|
||||
NBDClientSession *nbd_get_client_session(BlockDriverState *bs);
|
||||
|
||||
int nbd_client_init(BlockDriverState *bs,
|
||||
SocketAddress *saddr,
|
||||
const char *export_name,
|
||||
QCryptoTLSCreds *tlscreds,
|
||||
const char *hostname,
|
||||
const char *x_dirty_bitmap,
|
||||
Error **errp);
|
||||
void nbd_client_close(BlockDriverState *bs);
|
||||
|
||||
int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes);
|
||||
int nbd_client_co_flush(BlockDriverState *bs);
|
||||
int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t bytes, QEMUIOVector *qiov, int flags);
|
||||
int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
|
||||
int bytes, BdrvRequestFlags flags);
|
||||
int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t bytes, QEMUIOVector *qiov, int flags);
|
||||
|
||||
void nbd_client_detach_aio_context(BlockDriverState *bs);
|
||||
void nbd_client_attach_aio_context(BlockDriverState *bs,
|
||||
AioContext *new_context);
|
||||
|
||||
int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs,
|
||||
bool want_zero,
|
||||
int64_t offset, int64_t bytes,
|
||||
int64_t *pnum, int64_t *map,
|
||||
BlockDriverState **file);
|
||||
|
||||
#endif /* NBD_CLIENT_H */
|
||||
+36
-1247
File diff suppressed because it is too large.
Load diff
+4
-3
@@ -32,7 +32,6 @@
|
||||
#include "block/qdict.h"
|
||||
#include "trace.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/uri.h"
|
||||
#include "qemu/cutils.h"
|
||||
@@ -390,12 +389,14 @@ static void nfs_attach_aio_context(BlockDriverState *bs,
|
||||
static void nfs_client_close(NFSClient *client)
|
||||
{
|
||||
if (client->context) {
|
||||
qemu_mutex_lock(&client->mutex);
|
||||
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
||||
false, NULL, NULL, NULL, NULL);
|
||||
qemu_mutex_unlock(&client->mutex);
|
||||
if (client->fh) {
|
||||
nfs_close(client->context, client->fh);
|
||||
client->fh = NULL;
|
||||
}
|
||||
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
||||
false, NULL, NULL, NULL, NULL);
|
||||
nfs_destroy_context(client->context);
|
||||
client->context = NULL;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/option.h"
|
||||
#include "block/block_int.h"
|
||||
|
||||
|
||||
+9
-42
@@ -17,7 +17,6 @@
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/vfio-helpers.h"
|
||||
@@ -102,11 +101,8 @@ typedef struct {
|
||||
size_t doorbell_scale;
|
||||
bool write_cache_supported;
|
||||
EventNotifier irq_notifier;
|
||||
|
||||
uint64_t nsze; /* Namespace size reported by identify command */
|
||||
int nsid; /* The namespace id to read/write data. */
|
||||
int blkshift;
|
||||
|
||||
uint64_t max_transfer;
|
||||
bool plugged;
|
||||
|
||||
@@ -220,7 +216,7 @@ static NVMeQueuePair *nvme_create_queue_pair(BlockDriverState *bs,
|
||||
error_propagate(errp, local_err);
|
||||
goto fail;
|
||||
}
|
||||
q->cq.doorbell = &s->regs->doorbells[(idx * 2 + 1) * s->doorbell_scale];
|
||||
q->cq.doorbell = &s->regs->doorbells[idx * 2 * s->doorbell_scale + 1];
|
||||
|
||||
return q;
|
||||
fail:
|
||||
@@ -318,7 +314,7 @@ static bool nvme_process_completion(BDRVNVMeState *s, NVMeQueuePair *q)
|
||||
while (q->inflight) {
|
||||
int16_t cid;
|
||||
c = (NvmeCqe *)&q->cq.queue[q->cq.head * NVME_CQ_ENTRY_BYTES];
|
||||
if ((le16_to_cpu(c->status) & 0x1) == q->cq_phase) {
|
||||
if (!c->cid || (le16_to_cpu(c->status) & 0x1) == q->cq_phase) {
|
||||
break;
|
||||
}
|
||||
q->cq.head = (q->cq.head + 1) % NVME_QUEUE_SIZE;
|
||||
@@ -342,7 +338,10 @@ static bool nvme_process_completion(BDRVNVMeState *s, NVMeQueuePair *q)
|
||||
qemu_mutex_unlock(&q->lock);
|
||||
req.cb(req.opaque, nvme_translate_error(c));
|
||||
qemu_mutex_lock(&q->lock);
|
||||
c->cid = cpu_to_le16(0);
|
||||
q->inflight--;
|
||||
/* Flip Phase Tag bit. */
|
||||
c->status = cpu_to_le16(le16_to_cpu(c->status) ^ 0x1);
|
||||
progress = true;
|
||||
}
|
||||
if (progress) {
|
||||
@@ -418,7 +417,6 @@ static void nvme_identify(BlockDriverState *bs, int namespace, Error **errp)
|
||||
BDRVNVMeState *s = bs->opaque;
|
||||
NvmeIdCtrl *idctrl;
|
||||
NvmeIdNs *idns;
|
||||
NvmeLBAF *lbaf;
|
||||
uint8_t *resp;
|
||||
int r;
|
||||
uint64_t iova;
|
||||
@@ -467,22 +465,7 @@ static void nvme_identify(BlockDriverState *bs, int namespace, Error **errp)
|
||||
}
|
||||
|
||||
s->nsze = le64_to_cpu(idns->nsze);
|
||||
lbaf = &idns->lbaf[NVME_ID_NS_FLBAS_INDEX(idns->flbas)];
|
||||
|
||||
if (lbaf->ms) {
|
||||
error_setg(errp, "Namespaces with metadata are not yet supported");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lbaf->ds < BDRV_SECTOR_BITS || lbaf->ds > 12 ||
|
||||
(1 << lbaf->ds) > s->page_size)
|
||||
{
|
||||
error_setg(errp, "Namespace has unsupported block size (2^%d)",
|
||||
lbaf->ds);
|
||||
goto out;
|
||||
}
|
||||
|
||||
s->blkshift = lbaf->ds;
|
||||
out:
|
||||
qemu_vfio_dma_unmap(s->vfio, resp);
|
||||
qemu_vfree(resp);
|
||||
@@ -801,22 +784,8 @@ fail:
|
||||
static int64_t nvme_getlength(BlockDriverState *bs)
|
||||
{
|
||||
BDRVNVMeState *s = bs->opaque;
|
||||
return s->nsze << s->blkshift;
|
||||
}
|
||||
|
||||
static uint32_t nvme_get_blocksize(BlockDriverState *bs)
|
||||
{
|
||||
BDRVNVMeState *s = bs->opaque;
|
||||
assert(s->blkshift >= BDRV_SECTOR_BITS && s->blkshift <= 12);
|
||||
return UINT32_C(1) << s->blkshift;
|
||||
}
|
||||
|
||||
static int nvme_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
|
||||
{
|
||||
uint32_t blocksize = nvme_get_blocksize(bs);
|
||||
bsz->phys = blocksize;
|
||||
bsz->log = blocksize;
|
||||
return 0;
|
||||
return s->nsze << BDRV_SECTOR_BITS;
|
||||
}
|
||||
|
||||
/* Called with s->dma_map_lock */
|
||||
@@ -947,14 +916,13 @@ static coroutine_fn int nvme_co_prw_aligned(BlockDriverState *bs,
|
||||
BDRVNVMeState *s = bs->opaque;
|
||||
NVMeQueuePair *ioq = s->queues[1];
|
||||
NVMeRequest *req;
|
||||
|
||||
uint32_t cdw12 = (((bytes >> s->blkshift) - 1) & 0xFFFF) |
|
||||
uint32_t cdw12 = (((bytes >> BDRV_SECTOR_BITS) - 1) & 0xFFFF) |
|
||||
(flags & BDRV_REQ_FUA ? 1 << 30 : 0);
|
||||
NvmeCmd cmd = {
|
||||
.opcode = is_write ? NVME_CMD_WRITE : NVME_CMD_READ,
|
||||
.nsid = cpu_to_le32(s->nsid),
|
||||
.cdw10 = cpu_to_le32((offset >> s->blkshift) & 0xFFFFFFFF),
|
||||
.cdw11 = cpu_to_le32(((offset >> s->blkshift) >> 32) & 0xFFFFFFFF),
|
||||
.cdw10 = cpu_to_le32((offset >> BDRV_SECTOR_BITS) & 0xFFFFFFFF),
|
||||
.cdw11 = cpu_to_le32(((offset >> BDRV_SECTOR_BITS) >> 32) & 0xFFFFFFFF),
|
||||
.cdw12 = cpu_to_le32(cdw12),
|
||||
};
|
||||
NVMeCoData data = {
|
||||
@@ -1185,7 +1153,6 @@ static BlockDriver bdrv_nvme = {
|
||||
.bdrv_file_open = nvme_file_open,
|
||||
.bdrv_close = nvme_close,
|
||||
.bdrv_getlength = nvme_getlength,
|
||||
.bdrv_probe_blocksizes = nvme_probe_blocksizes,
|
||||
|
||||
.bdrv_co_preadv = nvme_co_preadv,
|
||||
.bdrv_co_pwritev = nvme_co_pwritev,
|
||||
|
||||
Loaded 100 of 3200 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user