1
The following changes since commit 23919ddfd56135cad3cb468a8f54d5a595f024f4:
1
The following changes since commit 1214d55d1c41fbab3a9973a05085b8760647e411:
2
2
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20190827' into staging (2019-08-27 15:52:36 +0100)
3
Merge remote-tracking branch 'remotes/nvme/tags/nvme-next-pull-request' into staging (2021-02-09 13:24:37 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/XanClic/qemu.git tags/pull-block-2019-08-27
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to bb043c056cffcc2f3ce88bfdaf2e76e455c09e2c:
9
for you to fetch changes up to eb847c42296497978942f738cd41dc29a35a49b2:
10
10
11
iotests: Unify cache mode quoting (2019-08-27 19:48:44 +0200)
11
docs: fix Parallels Image "dirty bitmap" section (2021-02-10 09:23:28 +0000)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- qemu-io now accepts a file to read a write pattern from
15
16
- Ensure that raw files have their first block allocated so we can probe
16
v4:
17
the O_DIRECT alignment if necessary
17
* Add PCI_EXPRESS Kconfig dependency to fix s390x in "multi-process: setup PCI
18
- Various fixes
18
host bridge for remote device" [Philippe and Thomas]
19
19
20
----------------------------------------------------------------
20
----------------------------------------------------------------
21
Denis Plotnikov (1):
22
qemu-io: add pattern file for write command
23
21
24
Max Reitz (7):
22
Denis V. Lunev (1):
25
iotests: Fix _filter_img_create()
23
docs: fix Parallels Image "dirty bitmap" section
26
vmdk: Use bdrv_dirname() for relative extent paths
27
iotests: Keep testing broken relative extent paths
28
vmdk: Reject invalid compressed writes
29
iotests: Disable broken streamOptimized tests
30
iotests: Disable 110 for vmdk.twoGbMaxExtentSparse
31
iotests: Disable 126 for flat vmdk subformats
32
24
33
Nir Soffer (3):
25
Elena Ufimtseva (8):
34
block: posix: Always allocate the first block
26
multi-process: add configure and usage information
35
iotests: Test allocate_first_block() with O_DIRECT
27
io: add qio_channel_writev_full_all helper
36
iotests: Unify cache mode quoting
28
io: add qio_channel_readv_full_all_eof & qio_channel_readv_full_all
29
helpers
30
multi-process: define MPQemuMsg format and transmission functions
31
multi-process: introduce proxy object
32
multi-process: add proxy communication functions
33
multi-process: Forward PCI config space acceses to the remote process
34
multi-process: perform device reset in the remote process
37
35
38
Stefan Hajnoczi (1):
36
Jagannathan Raman (11):
39
file-posix: fix request_alignment typo
37
memory: alloc RAM from file at offset
38
multi-process: Add config option for multi-process QEMU
39
multi-process: setup PCI host bridge for remote device
40
multi-process: setup a machine object for remote device process
41
multi-process: Initialize message handler in remote device
42
multi-process: Associate fd of a PCIDevice with its object
43
multi-process: setup memory manager for remote device
44
multi-process: PCI BAR read/write handling for proxy & remote
45
endpoints
46
multi-process: Synchronize remote memory
47
multi-process: create IOHUB object to handle irq
48
multi-process: Retrieve PCI info from remote process
40
49
41
Thomas Huth (2):
50
John G Johnson (1):
42
iotests: Check for enabled drivers before testing them
51
multi-process: add the concept description to
43
tests/check-block: Skip iotests when sanitizers are enabled
52
docs/devel/qemu-multiprocess
44
53
45
Vladimir Sementsov-Ogievskiy (1):
54
Stefan Hajnoczi (6):
46
block: fix permission update in bdrv_replace_node
55
.github: point Repo Lockdown bot to GitLab repo
56
gitmodules: use GitLab repos instead of qemu.org
57
gitlab-ci: remove redundant GitLab repo URL command
58
docs: update README to use GitLab repo URLs
59
pc-bios: update mirror URLs to GitLab
60
get_maintainer: update repo URL to GitLab
47
61
48
block.c | 5 +-
62
MAINTAINERS | 24 +
49
block/file-posix.c | 53 +++++++++-
63
README.rst | 4 +-
50
block/vmdk.c | 64 ++++++++----
64
docs/devel/index.rst | 1 +
51
qemu-io-cmds.c | 99 +++++++++++++++++--
65
docs/devel/multi-process.rst | 966 ++++++++++++++++++++++
52
tests/check-block.sh | 5 +
66
docs/system/index.rst | 1 +
53
tests/qemu-iotests/002 | 1 +
67
docs/system/multi-process.rst | 64 ++
54
tests/qemu-iotests/003 | 1 +
68
docs/interop/parallels.txt | 2 +-
55
tests/qemu-iotests/005 | 3 +-
69
configure | 10 +
56
tests/qemu-iotests/009 | 1 +
70
meson.build | 5 +-
57
tests/qemu-iotests/010 | 1 +
71
hw/remote/trace.h | 1 +
58
tests/qemu-iotests/011 | 1 +
72
include/exec/memory.h | 2 +
59
tests/qemu-iotests/017 | 3 +-
73
include/exec/ram_addr.h | 4 +-
60
tests/qemu-iotests/018 | 3 +-
74
include/hw/pci-host/remote.h | 30 +
61
tests/qemu-iotests/019 | 3 +-
75
include/hw/pci/pci_ids.h | 3 +
62
tests/qemu-iotests/020 | 3 +-
76
include/hw/remote/iohub.h | 42 +
63
tests/qemu-iotests/026 | 4 +-
77
include/hw/remote/machine.h | 38 +
64
tests/qemu-iotests/027 | 1 +
78
include/hw/remote/memory.h | 19 +
65
tests/qemu-iotests/032 | 1 +
79
include/hw/remote/mpqemu-link.h | 99 +++
66
tests/qemu-iotests/033 | 1 +
80
include/hw/remote/proxy-memory-listener.h | 28 +
67
tests/qemu-iotests/034 | 3 +-
81
include/hw/remote/proxy.h | 48 ++
68
tests/qemu-iotests/037 | 3 +-
82
include/io/channel.h | 78 ++
69
tests/qemu-iotests/039 | 4 +-
83
include/qemu/mmap-alloc.h | 4 +-
70
tests/qemu-iotests/052 | 2 +-
84
include/sysemu/iothread.h | 6 +
71
tests/qemu-iotests/059 | 34 ++++++-
85
backends/hostmem-memfd.c | 2 +-
72
tests/qemu-iotests/059.out | 26 +++--
86
hw/misc/ivshmem.c | 3 +-
73
tests/qemu-iotests/063 | 3 +-
87
hw/pci-host/remote.c | 75 ++
74
tests/qemu-iotests/071 | 1 +
88
hw/remote/iohub.c | 119 +++
75
tests/qemu-iotests/072 | 1 +
89
hw/remote/machine.c | 80 ++
76
tests/qemu-iotests/081 | 4 +-
90
hw/remote/memory.c | 65 ++
77
tests/qemu-iotests/091 | 4 +-
91
hw/remote/message.c | 230 ++++++
78
tests/qemu-iotests/099 | 1 +
92
hw/remote/mpqemu-link.c | 267 ++++++
79
tests/qemu-iotests/105 | 3 +-
93
hw/remote/proxy-memory-listener.c | 227 +++++
80
tests/qemu-iotests/110 | 3 +-
94
hw/remote/proxy.c | 379 +++++++++
81
tests/qemu-iotests/120 | 1 +
95
hw/remote/remote-obj.c | 203 +++++
82
tests/qemu-iotests/126 | 2 +
96
io/channel.c | 116 ++-
83
tests/qemu-iotests/{150.out => 150.out.qcow2} | 0
97
iothread.c | 6 +
84
tests/qemu-iotests/150.out.raw | 12 +++
98
softmmu/memory.c | 3 +-
85
tests/qemu-iotests/162 | 4 +-
99
softmmu/physmem.c | 12 +-
86
tests/qemu-iotests/175 | 47 +++++++--
100
util/mmap-alloc.c | 8 +-
87
tests/qemu-iotests/175.out | 16 ++-
101
util/oslib-posix.c | 2 +-
88
tests/qemu-iotests/178.out.qcow2 | 4 +-
102
.github/lockdown.yml | 8 +-
89
tests/qemu-iotests/184 | 1 +
103
.gitlab-ci.yml | 1 -
90
tests/qemu-iotests/186 | 1 +
104
.gitmodules | 44 +-
91
tests/qemu-iotests/197 | 1 +
105
Kconfig.host | 4 +
92
tests/qemu-iotests/215 | 1 +
106
hw/Kconfig | 1 +
93
tests/qemu-iotests/221.out | 12 ++-
107
hw/meson.build | 1 +
94
tests/qemu-iotests/251 | 1 +
108
hw/pci-host/Kconfig | 3 +
95
tests/qemu-iotests/253.out | 12 ++-
109
hw/pci-host/meson.build | 1 +
96
tests/qemu-iotests/common.filter | 4 +-
110
hw/remote/Kconfig | 4 +
97
tests/qemu-iotests/common.rc | 14 +++
111
hw/remote/meson.build | 13 +
98
50 files changed, 391 insertions(+), 87 deletions(-)
112
hw/remote/trace-events | 4 +
99
rename tests/qemu-iotests/{150.out => 150.out.qcow2} (100%)
113
pc-bios/README | 4 +-
100
create mode 100644 tests/qemu-iotests/150.out.raw
114
scripts/get_maintainer.pl | 2 +-
115
53 files changed, 3296 insertions(+), 70 deletions(-)
116
create mode 100644 docs/devel/multi-process.rst
117
create mode 100644 docs/system/multi-process.rst
118
create mode 100644 hw/remote/trace.h
119
create mode 100644 include/hw/pci-host/remote.h
120
create mode 100644 include/hw/remote/iohub.h
121
create mode 100644 include/hw/remote/machine.h
122
create mode 100644 include/hw/remote/memory.h
123
create mode 100644 include/hw/remote/mpqemu-link.h
124
create mode 100644 include/hw/remote/proxy-memory-listener.h
125
create mode 100644 include/hw/remote/proxy.h
126
create mode 100644 hw/pci-host/remote.c
127
create mode 100644 hw/remote/iohub.c
128
create mode 100644 hw/remote/machine.c
129
create mode 100644 hw/remote/memory.c
130
create mode 100644 hw/remote/message.c
131
create mode 100644 hw/remote/mpqemu-link.c
132
create mode 100644 hw/remote/proxy-memory-listener.c
133
create mode 100644 hw/remote/proxy.c
134
create mode 100644 hw/remote/remote-obj.c
135
create mode 100644 hw/remote/Kconfig
136
create mode 100644 hw/remote/meson.build
137
create mode 100644 hw/remote/trace-events
101
138
102
--
139
--
103
2.21.0
140
2.29.2
104
141
105
diff view generated by jsdifflib
New patch
1
Use the GitLab repo URL as the main repo location in order to reduce
2
load on qemu.org.
1
3
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
6
Reviewed-by: Thomas Huth <thuth@redhat.com>
7
Message-id: 20210111115017.156802-2-stefanha@redhat.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
.github/lockdown.yml | 8 ++++----
11
1 file changed, 4 insertions(+), 4 deletions(-)
12
13
diff --git a/.github/lockdown.yml b/.github/lockdown.yml
14
index XXXXXXX..XXXXXXX 100644
15
--- a/.github/lockdown.yml
16
+++ b/.github/lockdown.yml
17
@@ -XXX,XX +XXX,XX @@ issues:
18
comment: |
19
Thank you for your interest in the QEMU project.
20
21
- This repository is a read-only mirror of the project's master
22
- repostories hosted on https://git.qemu.org/git/qemu.git.
23
+ This repository is a read-only mirror of the project's repostories hosted
24
+ at https://gitlab.com/qemu-project/qemu.git.
25
The project does not process issues filed on GitHub.
26
27
The project issues are tracked on Launchpad:
28
@@ -XXX,XX +XXX,XX @@ pulls:
29
comment: |
30
Thank you for your interest in the QEMU project.
31
32
- This repository is a read-only mirror of the project's master
33
- repostories hosted on https://git.qemu.org/git/qemu.git.
34
+ This repository is a read-only mirror of the project's repostories hosted
35
+ on https://gitlab.com/qemu-project/qemu.git.
36
The project does not process merge requests filed on GitHub.
37
38
QEMU welcomes contributions of code (either fixing bugs or adding new
39
--
40
2.29.2
41
diff view generated by jsdifflib
New patch
1
qemu.org is running out of bandwidth and the QEMU project is moving
2
towards a gating CI on GitLab. Use the GitLab repos instead of qemu.org
3
(they will become mirrors).
1
4
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20210111115017.156802-3-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
.gitmodules | 44 ++++++++++++++++++++++----------------------
13
1 file changed, 22 insertions(+), 22 deletions(-)
14
15
diff --git a/.gitmodules b/.gitmodules
16
index XXXXXXX..XXXXXXX 100644
17
--- a/.gitmodules
18
+++ b/.gitmodules
19
@@ -XXX,XX +XXX,XX @@
20
[submodule "roms/seabios"]
21
    path = roms/seabios
22
-    url = https://git.qemu.org/git/seabios.git/
23
+    url = https://gitlab.com/qemu-project/seabios.git/
24
[submodule "roms/SLOF"]
25
    path = roms/SLOF
26
-    url = https://git.qemu.org/git/SLOF.git
27
+    url = https://gitlab.com/qemu-project/SLOF.git
28
[submodule "roms/ipxe"]
29
    path = roms/ipxe
30
-    url = https://git.qemu.org/git/ipxe.git
31
+    url = https://gitlab.com/qemu-project/ipxe.git
32
[submodule "roms/openbios"]
33
    path = roms/openbios
34
-    url = https://git.qemu.org/git/openbios.git
35
+    url = https://gitlab.com/qemu-project/openbios.git
36
[submodule "roms/qemu-palcode"]
37
    path = roms/qemu-palcode
38
-    url = https://git.qemu.org/git/qemu-palcode.git
39
+    url = https://gitlab.com/qemu-project/qemu-palcode.git
40
[submodule "roms/sgabios"]
41
    path = roms/sgabios
42
-    url = https://git.qemu.org/git/sgabios.git
43
+    url = https://gitlab.com/qemu-project/sgabios.git
44
[submodule "dtc"]
45
    path = dtc
46
-    url = https://git.qemu.org/git/dtc.git
47
+    url = https://gitlab.com/qemu-project/dtc.git
48
[submodule "roms/u-boot"]
49
    path = roms/u-boot
50
-    url = https://git.qemu.org/git/u-boot.git
51
+    url = https://gitlab.com/qemu-project/u-boot.git
52
[submodule "roms/skiboot"]
53
    path = roms/skiboot
54
-    url = https://git.qemu.org/git/skiboot.git
55
+    url = https://gitlab.com/qemu-project/skiboot.git
56
[submodule "roms/QemuMacDrivers"]
57
    path = roms/QemuMacDrivers
58
-    url = https://git.qemu.org/git/QemuMacDrivers.git
59
+    url = https://gitlab.com/qemu-project/QemuMacDrivers.git
60
[submodule "ui/keycodemapdb"]
61
    path = ui/keycodemapdb
62
-    url = https://git.qemu.org/git/keycodemapdb.git
63
+    url = https://gitlab.com/qemu-project/keycodemapdb.git
64
[submodule "capstone"]
65
    path = capstone
66
-    url = https://git.qemu.org/git/capstone.git
67
+    url = https://gitlab.com/qemu-project/capstone.git
68
[submodule "roms/seabios-hppa"]
69
    path = roms/seabios-hppa
70
-    url = https://git.qemu.org/git/seabios-hppa.git
71
+    url = https://gitlab.com/qemu-project/seabios-hppa.git
72
[submodule "roms/u-boot-sam460ex"]
73
    path = roms/u-boot-sam460ex
74
-    url = https://git.qemu.org/git/u-boot-sam460ex.git
75
+    url = https://gitlab.com/qemu-project/u-boot-sam460ex.git
76
[submodule "tests/fp/berkeley-testfloat-3"]
77
    path = tests/fp/berkeley-testfloat-3
78
-    url = https://git.qemu.org/git/berkeley-testfloat-3.git
79
+    url = https://gitlab.com/qemu-project/berkeley-testfloat-3.git
80
[submodule "tests/fp/berkeley-softfloat-3"]
81
    path = tests/fp/berkeley-softfloat-3
82
-    url = https://git.qemu.org/git/berkeley-softfloat-3.git
83
+    url = https://gitlab.com/qemu-project/berkeley-softfloat-3.git
84
[submodule "roms/edk2"]
85
    path = roms/edk2
86
-    url = https://git.qemu.org/git/edk2.git
87
+    url = https://gitlab.com/qemu-project/edk2.git
88
[submodule "slirp"]
89
    path = slirp
90
-    url = https://git.qemu.org/git/libslirp.git
91
+    url = https://gitlab.com/qemu-project/libslirp.git
92
[submodule "roms/opensbi"]
93
    path = roms/opensbi
94
-    url =     https://git.qemu.org/git/opensbi.git
95
+    url =     https://gitlab.com/qemu-project/opensbi.git
96
[submodule "roms/qboot"]
97
    path = roms/qboot
98
-    url = https://git.qemu.org/git/qboot.git
99
+    url = https://gitlab.com/qemu-project/qboot.git
100
[submodule "meson"]
101
    path = meson
102
-    url = https://git.qemu.org/git/meson.git
103
+    url = https://gitlab.com/qemu-project/meson.git
104
[submodule "roms/vbootrom"]
105
    path = roms/vbootrom
106
-    url = https://git.qemu.org/git/vbootrom.git
107
+    url = https://gitlab.com/qemu-project/vbootrom.git
108
--
109
2.29.2
110
diff view generated by jsdifflib
New patch
1
It is no longer necessary to point .gitmodules at GitLab repos when
2
running in GitLab CI since they are now used all the time.
1
3
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
6
Reviewed-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20210111115017.156802-4-stefanha@redhat.com
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
11
.gitlab-ci.yml | 1 -
12
1 file changed, 1 deletion(-)
13
14
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
15
index XXXXXXX..XXXXXXX 100644
16
--- a/.gitlab-ci.yml
17
+++ b/.gitlab-ci.yml
18
@@ -XXX,XX +XXX,XX @@ include:
19
image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
20
before_script:
21
- JOBS=$(expr $(nproc) + 1)
22
- - sed -i s,git.qemu.org/git,gitlab.com/qemu-project, .gitmodules
23
script:
24
- mkdir build
25
- cd build
26
--
27
2.29.2
28
diff view generated by jsdifflib
New patch
1
qemu.org is running out of bandwidth and the QEMU project is moving
2
towards a gating CI on GitLab. Use the GitLab repos instead of qemu.org
3
(they will become mirrors).
1
4
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20210111115017.156802-5-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
README.rst | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/README.rst b/README.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/README.rst
18
+++ b/README.rst
19
@@ -XXX,XX +XXX,XX @@ The QEMU source code is maintained under the GIT version control system.
20
21
.. code-block:: shell
22
23
- git clone https://git.qemu.org/git/qemu.git
24
+ git clone https://gitlab.com/qemu-project/qemu.git
25
26
When submitting patches, one common approach is to use 'git
27
format-patch' and/or 'git send-email' to format & send the mail to the
28
@@ -XXX,XX +XXX,XX @@ The QEMU website is also maintained under source control.
29
30
.. code-block:: shell
31
32
- git clone https://git.qemu.org/git/qemu-web.git
33
+ git clone https://gitlab.com/qemu-project/qemu-web.git
34
35
* `<https://www.qemu.org/2017/02/04/the-new-qemu-website-is-up/>`_
36
37
--
38
2.29.2
39
diff view generated by jsdifflib
New patch
1
qemu.org is running out of bandwidth and the QEMU project is moving
2
towards a gating CI on GitLab. Use the GitLab repos instead of qemu.org
3
(they will become mirrors).
1
4
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20210111115017.156802-6-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
pc-bios/README | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/pc-bios/README b/pc-bios/README
16
index XXXXXXX..XXXXXXX 100644
17
--- a/pc-bios/README
18
+++ b/pc-bios/README
19
@@ -XXX,XX +XXX,XX @@
20
legacy x86 software to communicate with an attached serial console as
21
if a video card were attached. The master sources reside in a subversion
22
repository at http://sgabios.googlecode.com/svn/trunk. A git mirror is
23
- available at https://git.qemu.org/git/sgabios.git.
24
+ available at https://gitlab.com/qemu-project/sgabios.git.
25
26
- The PXE roms come from the iPXE project. Built with BANNER_TIME 0.
27
Sources available at http://ipxe.org. Vendor:Device ID -> ROM mapping:
28
@@ -XXX,XX +XXX,XX @@
29
30
- The u-boot binary for e500 comes from the upstream denx u-boot project where
31
it was compiled using the qemu-ppce500 target.
32
- A git mirror is available at: https://git.qemu.org/git/u-boot.git
33
+ A git mirror is available at: https://gitlab.com/qemu-project/u-boot.git
34
The hash used to compile the current version is: 2072e72
35
36
- Skiboot (https://github.com/open-power/skiboot/) is an OPAL
37
--
38
2.29.2
39
diff view generated by jsdifflib
New patch
1
qemu.org is running out of bandwidth and the QEMU project is moving
2
towards a gating CI on GitLab. Use the GitLab repos instead of qemu.org
3
(they will become mirrors).
1
4
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Wainer dos Santos Moschetta <wainersm@redhat.com>
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20210111115017.156802-7-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
scripts/get_maintainer.pl | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
16
index XXXXXXX..XXXXXXX 100755
17
--- a/scripts/get_maintainer.pl
18
+++ b/scripts/get_maintainer.pl
19
@@ -XXX,XX +XXX,XX @@ sub vcs_exists {
20
    warn("$P: No supported VCS found. Add --nogit to options?\n");
21
    warn("Using a git repository produces better results.\n");
22
    warn("Try latest git repository using:\n");
23
-    warn("git clone https://git.qemu.org/git/qemu.git\n");
24
+    warn("git clone https://gitlab.com/qemu-project/qemu.git\n");
25
    $printed_novcs = 1;
26
}
27
return 0;
28
--
29
2.29.2
30
diff view generated by jsdifflib
New patch
1
From: John G Johnson <john.g.johnson@oracle.com>
1
2
3
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
4
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
5
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-id: 02a68adef99f5df6a380bf8fd7b90948777e411c.1611938319.git.jag.raman@oracle.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
MAINTAINERS | 7 +
11
docs/devel/index.rst | 1 +
12
docs/devel/multi-process.rst | 966 +++++++++++++++++++++++++++++++++++
13
3 files changed, 974 insertions(+)
14
create mode 100644 docs/devel/multi-process.rst
15
16
diff --git a/MAINTAINERS b/MAINTAINERS
17
index XXXXXXX..XXXXXXX 100644
18
--- a/MAINTAINERS
19
+++ b/MAINTAINERS
20
@@ -XXX,XX +XXX,XX @@ S: Maintained
21
F: hw/semihosting/
22
F: include/hw/semihosting/
23
24
+Multi-process QEMU
25
+M: Elena Ufimtseva <elena.ufimtseva@oracle.com>
26
+M: Jagannathan Raman <jag.raman@oracle.com>
27
+M: John G Johnson <john.g.johnson@oracle.com>
28
+S: Maintained
29
+F: docs/devel/multi-process.rst
30
+
31
Build and test automation
32
-------------------------
33
Build and test automation
34
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
35
index XXXXXXX..XXXXXXX 100644
36
--- a/docs/devel/index.rst
37
+++ b/docs/devel/index.rst
38
@@ -XXX,XX +XXX,XX @@ Contents:
39
clocks
40
qom
41
block-coroutine-wrapper
42
+ multi-process
43
diff --git a/docs/devel/multi-process.rst b/docs/devel/multi-process.rst
44
new file mode 100644
45
index XXXXXXX..XXXXXXX
46
--- /dev/null
47
+++ b/docs/devel/multi-process.rst
48
@@ -XXX,XX +XXX,XX @@
49
+This is the design document for multi-process QEMU. It does not
50
+necessarily reflect the status of the current implementation, which
51
+may lack features or be considerably different from what is described
52
+in this document. This document is still useful as a description of
53
+the goals and general direction of this feature.
54
+
55
+Please refer to the following wiki for latest details:
56
+https://wiki.qemu.org/Features/MultiProcessQEMU
57
+
58
+Multi-process QEMU
59
+===================
60
+
61
+QEMU is often used as the hypervisor for virtual machines running in the
62
+Oracle cloud. Since one of the advantages of cloud computing is the
63
+ability to run many VMs from different tenants in the same cloud
64
+infrastructure, a guest that compromised its hypervisor could
65
+potentially use the hypervisor's access privileges to access data it is
66
+not authorized for.
67
+
68
+QEMU can be susceptible to security attacks because it is a large,
69
+monolithic program that provides many features to the VMs it services.
70
+Many of these features can be configured out of QEMU, but even a reduced
71
+configuration QEMU has a large amount of code a guest can potentially
72
+attack. Separating QEMU reduces the attack surface by aiding to
73
+limit each component in the system to only access the resources that
74
+it needs to perform its job.
75
+
76
+QEMU services
77
+-------------
78
+
79
+QEMU can be broadly described as providing three main services. One is a
80
+VM control point, where VMs can be created, migrated, re-configured, and
81
+destroyed. A second is to emulate the CPU instructions within the VM,
82
+often accelerated by HW virtualization features such as Intel's VT
83
+extensions. Finally, it provides IO services to the VM by emulating HW
84
+IO devices, such as disk and network devices.
85
+
86
+A multi-process QEMU
87
+~~~~~~~~~~~~~~~~~~~~
88
+
89
+A multi-process QEMU involves separating QEMU services into separate
90
+host processes. Each of these processes can be given only the privileges
91
+it needs to provide its service, e.g., a disk service could be given
92
+access only to the disk images it provides, and not be allowed to
93
+access other files, or any network devices. An attacker who compromised
94
+this service would not be able to use this exploit to access files or
95
+devices beyond what the disk service was given access to.
96
+
97
+A QEMU control process would remain, but in multi-process mode, will
98
+have no direct interfaces to the VM. During VM execution, it would still
99
+provide the user interface to hot-plug devices or live migrate the VM.
100
+
101
+A first step in creating a multi-process QEMU is to separate IO services
102
+from the main QEMU program, which would continue to provide CPU
103
+emulation. i.e., the control process would also be the CPU emulation
104
+process. In a later phase, CPU emulation could be separated from the
105
+control process.
106
+
107
+Separating IO services
108
+----------------------
109
+
110
+Separating IO services into individual host processes is a good place to
111
+begin for a couple of reasons. One is the sheer number of IO devices QEMU
112
+can emulate provides a large surface of interfaces which could potentially
113
+be exploited, and, indeed, have been a source of exploits in the past.
114
+Another is the modular nature of QEMU device emulation code provides
115
+interface points where the QEMU functions that perform device emulation
116
+can be separated from the QEMU functions that manage the emulation of
117
+guest CPU instructions. The devices emulated in the separate process are
118
+referred to as remote devices.
119
+
120
+QEMU device emulation
121
+~~~~~~~~~~~~~~~~~~~~~
122
+
123
+QEMU uses an object oriented SW architecture for device emulation code.
124
+Configured objects are all compiled into the QEMU binary, then objects
125
+are instantiated by name when used by the guest VM. For example, the
126
+code to emulate a device named "foo" is always present in QEMU, but its
127
+instantiation code is only run when the device is included in the target
128
+VM. (e.g., via the QEMU command line as *-device foo*)
129
+
130
+The object model is hierarchical, so device emulation code names its
131
+parent object (such as "pci-device" for a PCI device) and QEMU will
132
+instantiate a parent object before calling the device's instantiation
133
+code.
134
+
135
+Current separation models
136
+~~~~~~~~~~~~~~~~~~~~~~~~~
137
+
138
+In order to separate the device emulation code from the CPU emulation
139
+code, the device object code must run in a different process. There are
140
+a couple of existing QEMU features that can run emulation code
141
+separately from the main QEMU process. These are examined below.
142
+
143
+vhost user model
144
+^^^^^^^^^^^^^^^^
145
+
146
+Virtio guest device drivers can be connected to vhost user applications
147
+in order to perform their IO operations. This model uses special virtio
148
+device drivers in the guest and vhost user device objects in QEMU, but
149
+once the QEMU vhost user code has configured the vhost user application,
150
+mission-mode IO is performed by the application. The vhost user
151
+application is a daemon process that can be contacted via a known UNIX
152
+domain socket.
153
+
154
+vhost socket
155
+''''''''''''
156
+
157
+As mentioned above, one of the tasks of the vhost device object within
158
+QEMU is to contact the vhost application and send it configuration
159
+information about this device instance. As part of the configuration
160
+process, the application can also be sent other file descriptors over
161
+the socket, which then can be used by the vhost user application in
162
+various ways, some of which are described below.
163
+
164
+vhost MMIO store acceleration
165
+'''''''''''''''''''''''''''''
166
+
167
+VMs are often run using HW virtualization features via the KVM kernel
168
+driver. This driver allows QEMU to accelerate the emulation of guest CPU
169
+instructions by running the guest in a virtual HW mode. When the guest
170
+executes instructions that cannot be executed by virtual HW mode,
171
+execution returns to the KVM driver so it can inform QEMU to emulate the
172
+instructions in SW.
173
+
174
+One of the events that can cause a return to QEMU is when a guest device
175
+driver accesses an IO location. QEMU then dispatches the memory
176
+operation to the corresponding QEMU device object. In the case of a
177
+vhost user device, the memory operation would need to be sent over a
178
+socket to the vhost application. This path is accelerated by the QEMU
179
+virtio code by setting up an eventfd file descriptor that the vhost
180
+application can directly receive MMIO store notifications from the KVM
181
+driver, instead of needing them to be sent to the QEMU process first.
182
+
183
+vhost interrupt acceleration
184
+''''''''''''''''''''''''''''
185
+
186
+Another optimization used by the vhost application is the ability to
187
+directly inject interrupts into the VM via the KVM driver, again,
188
+bypassing the need to send the interrupt back to the QEMU process first.
189
+The QEMU virtio setup code configures the KVM driver with an eventfd
190
+that triggers the device interrupt in the guest when the eventfd is
191
+written. This irqfd file descriptor is then passed to the vhost user
192
+application program.
193
+
194
+vhost access to guest memory
195
+''''''''''''''''''''''''''''
196
+
197
+The vhost application is also allowed to directly access guest memory,
198
+instead of needing to send the data as messages to QEMU. This is also
199
+done with file descriptors sent to the vhost user application by QEMU.
200
+These descriptors can be passed to ``mmap()`` by the vhost application
201
+to map the guest address space into the vhost application.
202
+
203
+IOMMUs introduce another level of complexity, since the address given to
204
+the guest virtio device to DMA to or from is not a guest physical
205
+address. This case is handled by having vhost code within QEMU register
206
+as a listener for IOMMU mapping changes. The vhost application maintains
207
+a cache of IOMMMU translations: sending translation requests back to
208
+QEMU on cache misses, and in turn receiving flush requests from QEMU
209
+when mappings are purged.
210
+
211
+applicability to device separation
212
+''''''''''''''''''''''''''''''''''
213
+
214
+Much of the vhost model can be re-used by separated device emulation. In
215
+particular, the ideas of using a socket between QEMU and the device
216
+emulation application, using a file descriptor to inject interrupts into
217
+the VM via KVM, and allowing the application to ``mmap()`` the guest
218
+should be re used.
219
+
220
+There are, however, some notable differences between how a vhost
221
+application works and the needs of separated device emulation. The most
222
+basic is that vhost uses custom virtio device drivers which always
223
+trigger IO with MMIO stores. A separated device emulation model must
224
+work with existing IO device models and guest device drivers. MMIO loads
225
+break vhost store acceleration since they are synchronous - guest
226
+progress cannot continue until the load has been emulated. By contrast,
227
+stores are asynchronous, the guest can continue after the store event
228
+has been sent to the vhost application.
229
+
230
+Another difference is that in the vhost user model, a single daemon can
231
+support multiple QEMU instances. This is contrary to the security regime
232
+desired, in which the emulation application should only be allowed to
233
+access the files or devices the VM it's running on behalf of can access.
234
+#### qemu-io model
235
+
236
+Qemu-io is a test harness used to test changes to the QEMU block backend
237
+object code. (e.g., the code that implements disk images for disk driver
238
+emulation) Qemu-io is not a device emulation application per se, but it
239
+does compile the QEMU block objects into a separate binary from the main
240
+QEMU one. This could be useful for disk device emulation, since its
241
+emulation applications will need to include the QEMU block objects.
242
+
243
+New separation model based on proxy objects
244
+-------------------------------------------
245
+
246
+A different model based on proxy objects in the QEMU program
247
+communicating with remote emulation programs could provide separation
248
+while minimizing the changes needed to the device emulation code. The
249
+rest of this section is a discussion of how a proxy object model would
250
+work.
251
+
252
+Remote emulation processes
253
+~~~~~~~~~~~~~~~~~~~~~~~~~~
254
+
255
+The remote emulation process will run the QEMU object hierarchy without
256
+modification. The device emulation objects will be also be based on the
257
+QEMU code, because for anything but the simplest device, it would not be
258
+a tractable to re-implement both the object model and the many device
259
+backends that QEMU has.
260
+
261
+The processes will communicate with the QEMU process over UNIX domain
262
+sockets. The processes can be executed either as standalone processes,
263
+or be executed by QEMU. In both cases, the host backends the emulation
264
+processes will provide are specified on its command line, as they would
265
+be for QEMU. For example:
266
+
267
+::
268
+
269
+ disk-proc -blockdev driver=file,node-name=file0,filename=disk-file0 \
270
+ -blockdev driver=qcow2,node-name=drive0,file=file0
271
+
272
+would indicate process *disk-proc* uses a qcow2 emulated disk named
273
+*file0* as its backend.
274
+
275
+Emulation processes may emulate more than one guest controller. A common
276
+configuration might be to put all controllers of the same device class
277
+(e.g., disk, network, etc.) in a single process, so that all backends of
278
+the same type can be managed by a single QMP monitor.
279
+
280
+communication with QEMU
281
+^^^^^^^^^^^^^^^^^^^^^^^
282
+
283
+The first argument to the remote emulation process will be a Unix domain
284
+socket that connects with the Proxy object. This is a required argument.
285
+
286
+::
287
+
288
+ disk-proc <socket number> <backend list>
289
+
290
+remote process QMP monitor
291
+^^^^^^^^^^^^^^^^^^^^^^^^^^
292
+
293
+Remote emulation processes can be monitored via QMP, similar to QEMU
294
+itself. The QMP monitor socket is specified the same as for a QEMU
295
+process:
296
+
297
+::
298
+
299
+ disk-proc -qmp unix:/tmp/disk-mon,server
300
+
301
+can be monitored over the UNIX socket path */tmp/disk-mon*.
302
+
303
+QEMU command line
304
+~~~~~~~~~~~~~~~~~
305
+
306
+Each remote device emulated in a remote process on the host is
307
+represented as a *-device* of type *pci-proxy-dev*. A socket
308
+sub-option to this option specifies the Unix socket that connects
309
+to the remote process. An *id* sub-option is required, and it should
310
+be the same id as used in the remote process.
311
+
312
+::
313
+
314
+ qemu-system-x86_64 ... -device pci-proxy-dev,id=lsi0,socket=3
315
+
316
+can be used to add a device emulated in a remote process
317
+
318
+
319
+QEMU management of remote processes
320
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
321
+
322
+QEMU is not aware of the type of type of the remote PCI device. It is
323
+a pass through device as far as QEMU is concerned.
324
+
325
+communication with emulation process
326
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
327
+
328
+primary channel
329
+'''''''''''''''
330
+
331
+The primary channel (referred to as com in the code) is used to bootstrap
332
+the remote process. It is also used to pass on device-agnostic commands
333
+like reset.
334
+
335
+per-device channels
336
+'''''''''''''''''''
337
+
338
+Each remote device communicates with QEMU using a dedicated communication
339
+channel. The proxy object sets up this channel using the primary
340
+channel during its initialization.
341
+
342
+QEMU device proxy objects
343
+~~~~~~~~~~~~~~~~~~~~~~~~~
344
+
345
+QEMU has an object model based on sub-classes inherited from the
346
+"object" super-class. The sub-classes that are of interest here are the
347
+"device" and "bus" sub-classes whose child sub-classes make up the
348
+device tree of a QEMU emulated system.
349
+
350
+The proxy object model will use device proxy objects to replace the
351
+device emulation code within the QEMU process. These objects will live
352
+in the same place in the object and bus hierarchies as the objects they
353
+replace. i.e., the proxy object for an LSI SCSI controller will be a
354
+sub-class of the "pci-device" class, and will have the same PCI bus
355
+parent and the same SCSI bus child objects as the LSI controller object
356
+it replaces.
357
+
358
+It is worth noting that the same proxy object is used to mediate with
359
+all types of remote PCI devices.
360
+
361
+object initialization
362
+^^^^^^^^^^^^^^^^^^^^^
363
+
364
+The Proxy device objects are initialized in the exact same manner in
365
+which any other QEMU device would be initialized.
366
+
367
+In addition, the Proxy objects perform the following two tasks:
368
+- Parses the "socket" sub option and connects to the remote process
369
+using this channel
370
+- Uses the "id" sub-option to connect to the emulated device on the
371
+separate process
372
+
373
+class\_init
374
+'''''''''''
375
+
376
+The ``class_init()`` method of a proxy object will, in general behave
377
+similarly to the object it replaces, including setting any static
378
+properties and methods needed by the proxy.
379
+
380
+instance\_init / realize
381
+''''''''''''''''''''''''
382
+
383
+The ``instance_init()`` and ``realize()`` functions would only need to
384
+perform tasks related to being a proxy, such are registering its own
385
+MMIO handlers, or creating a child bus that other proxy devices can be
386
+attached to later.
387
+
388
+Other tasks will be device-specific. For example, PCI device objects
389
+will initialize the PCI config space in order to make a valid PCI device
390
+tree within the QEMU process.
391
+
392
+address space registration
393
+^^^^^^^^^^^^^^^^^^^^^^^^^^
394
+
395
+Most devices are driven by guest device driver accesses to IO addresses
396
+or ports. The QEMU device emulation code uses QEMU's memory region
397
+function calls (such as ``memory_region_init_io()``) to add callback
398
+functions that QEMU will invoke when the guest accesses the device's
399
+areas of the IO address space. When a guest driver does access the
400
+device, the VM will exit HW virtualization mode and return to QEMU,
401
+which will then lookup and execute the corresponding callback function.
402
+
403
+A proxy object would need to mirror the memory region calls the actual
404
+device emulator would perform in its initialization code, but with its
405
+own callbacks. When invoked by QEMU as a result of a guest IO operation,
406
+they will forward the operation to the device emulation process.
407
+
408
+PCI config space
409
+^^^^^^^^^^^^^^^^
410
+
411
+PCI devices also have a configuration space that can be accessed by the
412
+guest driver. Guest accesses to this space is not handled by the device
413
+emulation object, but by its PCI parent object. Much of this space is
414
+read-only, but certain registers (especially BAR and MSI-related ones)
415
+need to be propagated to the emulation process.
416
+
417
+PCI parent proxy
418
+''''''''''''''''
419
+
420
+One way to propagate guest PCI config accesses is to create a
421
+"pci-device-proxy" class that can serve as the parent of a PCI device
422
+proxy object. This class's parent would be "pci-device" and it would
423
+override the PCI parent's ``config_read()`` and ``config_write()``
424
+methods with ones that forward these operations to the emulation
425
+program.
426
+
427
+interrupt receipt
428
+^^^^^^^^^^^^^^^^^
429
+
430
+A proxy for a device that generates interrupts will need to create a
431
+socket to receive interrupt indications from the emulation process. An
432
+incoming interrupt indication would then be sent up to its bus parent to
433
+be injected into the guest. For example, a PCI device object may use
434
+``pci_set_irq()``.
435
+
436
+live migration
437
+^^^^^^^^^^^^^^
438
+
439
+The proxy will register to save and restore any *vmstate* it needs over
440
+a live migration event. The device proxy does not need to manage the
441
+remote device's *vmstate*; that will be handled by the remote process
442
+proxy (see below).
443
+
444
+QEMU remote device operation
445
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
446
+
447
+Generic device operations, such as DMA, will be performed by the remote
448
+process proxy by sending messages to the remote process.
449
+
450
+DMA operations
451
+^^^^^^^^^^^^^^
452
+
453
+DMA operations would be handled much like vhost applications do. One of
454
+the initial messages sent to the emulation process is a guest memory
455
+table. Each entry in this table consists of a file descriptor and size
456
+that the emulation process can ``mmap()`` to directly access guest
457
+memory, similar to ``vhost_user_set_mem_table()``. Note guest memory
458
+must be backed by file descriptors, such as when QEMU is given the
459
+*-mem-path* command line option.
460
+
461
+IOMMU operations
462
+^^^^^^^^^^^^^^^^
463
+
464
+When the emulated system includes an IOMMU, the remote process proxy in
465
+QEMU will need to create a socket for IOMMU requests from the emulation
466
+process. It will handle those requests with an
467
+``address_space_get_iotlb_entry()`` call. In order to handle IOMMU
468
+unmaps, the remote process proxy will also register as a listener on the
469
+device's DMA address space. When an IOMMU memory region is created
470
+within the DMA address space, an IOMMU notifier for unmaps will be added
471
+to the memory region that will forward unmaps to the emulation process
472
+over the IOMMU socket.
473
+
474
+device hot-plug via QMP
475
+^^^^^^^^^^^^^^^^^^^^^^^
476
+
477
+An QMP "device\_add" command can add a device emulated by a remote
478
+process. It will also have "rid" option to the command, just as the
479
+*-device* command line option does. The remote process may either be one
480
+started at QEMU startup, or be one added by the "add-process" QMP
481
+command described above. In either case, the remote process proxy will
482
+forward the new device's JSON description to the corresponding emulation
483
+process.
484
+
485
+live migration
486
+^^^^^^^^^^^^^^
487
+
488
+The remote process proxy will also register for live migration
489
+notifications with ``vmstate_register()``. When called to save state,
490
+the proxy will send the remote process a secondary socket file
491
+descriptor to save the remote process's device *vmstate* over. The
492
+incoming byte stream length and data will be saved as the proxy's
493
+*vmstate*. When the proxy is resumed on its new host, this *vmstate*
494
+will be extracted, and a secondary socket file descriptor will be sent
495
+to the new remote process through which it receives the *vmstate* in
496
+order to restore the devices there.
497
+
498
+device emulation in remote process
499
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
500
+
501
+The parts of QEMU that the emulation program will need include the
502
+object model; the memory emulation objects; the device emulation objects
503
+of the targeted device, and any dependent devices; and, the device's
504
+backends. It will also need code to setup the machine environment,
505
+handle requests from the QEMU process, and route machine-level requests
506
+(such as interrupts or IOMMU mappings) back to the QEMU process.
507
+
508
+initialization
509
+^^^^^^^^^^^^^^
510
+
511
+The process initialization sequence will follow the same sequence
512
+followed by QEMU. It will first initialize the backend objects, then
513
+device emulation objects. The JSON descriptions sent by the QEMU process
514
+will drive which objects need to be created.
515
+
516
+- address spaces
517
+
518
+Before the device objects are created, the initial address spaces and
519
+memory regions must be configured with ``memory_map_init()``. This
520
+creates a RAM memory region object (*system\_memory*) and an IO memory
521
+region object (*system\_io*).
522
+
523
+- RAM
524
+
525
+RAM memory region creation will follow how ``pc_memory_init()`` creates
526
+them, but must use ``memory_region_init_ram_from_fd()`` instead of
527
+``memory_region_allocate_system_memory()``. The file descriptors needed
528
+will be supplied by the guest memory table from above. Those RAM regions
529
+would then be added to the *system\_memory* memory region with
530
+``memory_region_add_subregion()``.
531
+
532
+- PCI
533
+
534
+IO initialization will be driven by the JSON descriptions sent from the
535
+QEMU process. For a PCI device, a PCI bus will need to be created with
536
+``pci_root_bus_new()``, and a PCI memory region will need to be created
537
+and added to the *system\_memory* memory region with
538
+``memory_region_add_subregion_overlap()``. The overlap version is
539
+required for architectures where PCI memory overlaps with RAM memory.
540
+
541
+MMIO handling
542
+^^^^^^^^^^^^^
543
+
544
+The device emulation objects will use ``memory_region_init_io()`` to
545
+install their MMIO handlers, and ``pci_register_bar()`` to associate
546
+those handlers with a PCI BAR, as they do within QEMU currently.
547
+
548
+In order to use ``address_space_rw()`` in the emulation process to
549
+handle MMIO requests from QEMU, the PCI physical addresses must be the
550
+same in the QEMU process and the device emulation process. In order to
551
+accomplish that, guest BAR programming must also be forwarded from QEMU
552
+to the emulation process.
553
+
554
+interrupt injection
555
+^^^^^^^^^^^^^^^^^^^
556
+
557
+When device emulation wants to inject an interrupt into the VM, the
558
+request climbs the device's bus object hierarchy until the point where a
559
+bus object knows how to signal the interrupt to the guest. The details
560
+depend on the type of interrupt being raised.
561
+
562
+- PCI pin interrupts
563
+
564
+On x86 systems, there is an emulated IOAPIC object attached to the root
565
+PCI bus object, and the root PCI object forwards interrupt requests to
566
+it. The IOAPIC object, in turn, calls the KVM driver to inject the
567
+corresponding interrupt into the VM. The simplest way to handle this in
568
+an emulation process would be to setup the root PCI bus driver (via
569
+``pci_bus_irqs()``) to send a interrupt request back to the QEMU
570
+process, and have the device proxy object reflect it up the PCI tree
571
+there.
572
+
573
+- PCI MSI/X interrupts
574
+
575
+PCI MSI/X interrupts are implemented in HW as DMA writes to a
576
+CPU-specific PCI address. In QEMU on x86, a KVM APIC object receives
577
+these DMA writes, then calls into the KVM driver to inject the interrupt
578
+into the VM. A simple emulation process implementation would be to send
579
+the MSI DMA address from QEMU as a message at initialization, then
580
+install an address space handler at that address which forwards the MSI
581
+message back to QEMU.
582
+
583
+DMA operations
584
+^^^^^^^^^^^^^^
585
+
586
+When a emulation object wants to DMA into or out of guest memory, it
587
+first must use dma\_memory\_map() to convert the DMA address to a local
588
+virtual address. The emulation process memory region objects setup above
589
+will be used to translate the DMA address to a local virtual address the
590
+device emulation code can access.
591
+
592
+IOMMU
593
+^^^^^
594
+
595
+When an IOMMU is in use in QEMU, DMA translation uses IOMMU memory
596
+regions to translate the DMA address to a guest physical address before
597
+that physical address can be translated to a local virtual address. The
598
+emulation process will need similar functionality.
599
+
600
+- IOTLB cache
601
+
602
+The emulation process will maintain a cache of recent IOMMU translations
603
+(the IOTLB). When the translate() callback of an IOMMU memory region is
604
+invoked, the IOTLB cache will be searched for an entry that will map the
605
+DMA address to a guest PA. On a cache miss, a message will be sent back
606
+to QEMU requesting the corresponding translation entry, which be both be
607
+used to return a guest address and be added to the cache.
608
+
609
+- IOTLB purge
610
+
611
+The IOMMU emulation will also need to act on unmap requests from QEMU.
612
+These happen when the guest IOMMU driver purges an entry from the
613
+guest's translation table.
614
+
615
+live migration
616
+^^^^^^^^^^^^^^
617
+
618
+When a remote process receives a live migration indication from QEMU, it
619
+will set up a channel using the received file descriptor with
620
+``qio_channel_socket_new_fd()``. This channel will be used to create a
621
+*QEMUfile* that can be passed to ``qemu_save_device_state()`` to send
622
+the process's device state back to QEMU. This method will be reversed on
623
+restore - the channel will be passed to ``qemu_loadvm_state()`` to
624
+restore the device state.
625
+
626
+Accelerating device emulation
627
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
628
+
629
+The messages that are required to be sent between QEMU and the emulation
630
+process can add considerable latency to IO operations. The optimizations
631
+described below attempt to ameliorate this effect by allowing the
632
+emulation process to communicate directly with the kernel KVM driver.
633
+The KVM file descriptors created would be passed to the emulation process
634
+via initialization messages, much like the guest memory table is done.
635
+#### MMIO acceleration
636
+
637
+Vhost user applications can receive guest virtio driver stores directly
638
+from KVM. The issue with the eventfd mechanism used by vhost user is
639
+that it does not pass any data with the event indication, so it cannot
640
+handle guest loads or guest stores that carry store data. This concept
641
+could, however, be expanded to cover more cases.
642
+
643
+The expanded idea would require a new type of KVM device:
644
+*KVM\_DEV\_TYPE\_USER*. This device has two file descriptors: a master
645
+descriptor that QEMU can use for configuration, and a slave descriptor
646
+that the emulation process can use to receive MMIO notifications. QEMU
647
+would create both descriptors using the KVM driver, and pass the slave
648
+descriptor to the emulation process via an initialization message.
649
+
650
+data structures
651
+^^^^^^^^^^^^^^^
652
+
653
+- guest physical range
654
+
655
+The guest physical range structure describes the address range that a
656
+device will respond to. It includes the base and length of the range, as
657
+well as which bus the range resides on (e.g., on an x86machine, it can
658
+specify whether the range refers to memory or IO addresses).
659
+
660
+A device can have multiple physical address ranges it responds to (e.g.,
661
+a PCI device can have multiple BARs), so the structure will also include
662
+an enumerated identifier to specify which of the device's ranges is
663
+being referred to.
664
+
665
++--------+----------------------------+
666
+| Name | Description |
667
++========+============================+
668
+| addr | range base address |
669
++--------+----------------------------+
670
+| len | range length |
671
++--------+----------------------------+
672
+| bus | addr type (memory or IO) |
673
++--------+----------------------------+
674
+| id | range ID (e.g., PCI BAR) |
675
++--------+----------------------------+
676
+
677
+- MMIO request structure
678
+
679
+This structure describes an MMIO operation. It includes which guest
680
+physical range the MMIO was within, the offset within that range, the
681
+MMIO type (e.g., load or store), and its length and data. It also
682
+includes a sequence number that can be used to reply to the MMIO, and
683
+the CPU that issued the MMIO.
684
+
685
++----------+------------------------+
686
+| Name | Description |
687
++==========+========================+
688
+| rid | range MMIO is within |
689
++----------+------------------------+
690
+| offset | offset withing *rid* |
691
++----------+------------------------+
692
+| type | e.g., load or store |
693
++----------+------------------------+
694
+| len | MMIO length |
695
++----------+------------------------+
696
+| data | store data |
697
++----------+------------------------+
698
+| seq | sequence ID |
699
++----------+------------------------+
700
+
701
+- MMIO request queues
702
+
703
+MMIO request queues are FIFO arrays of MMIO request structures. There
704
+are two queues: pending queue is for MMIOs that haven't been read by the
705
+emulation program, and the sent queue is for MMIOs that haven't been
706
+acknowledged. The main use of the second queue is to validate MMIO
707
+replies from the emulation program.
708
+
709
+- scoreboard
710
+
711
+Each CPU in the VM is emulated in QEMU by a separate thread, so multiple
712
+MMIOs may be waiting to be consumed by an emulation program and multiple
713
+threads may be waiting for MMIO replies. The scoreboard would contain a
714
+wait queue and sequence number for the per-CPU threads, allowing them to
715
+be individually woken when the MMIO reply is received from the emulation
716
+program. It also tracks the number of posted MMIO stores to the device
717
+that haven't been replied to, in order to satisfy the PCI constraint
718
+that a load to a device will not complete until all previous stores to
719
+that device have been completed.
720
+
721
+- device shadow memory
722
+
723
+Some MMIO loads do not have device side-effects. These MMIOs can be
724
+completed without sending a MMIO request to the emulation program if the
725
+emulation program shares a shadow image of the device's memory image
726
+with the KVM driver.
727
+
728
+The emulation program will ask the KVM driver to allocate memory for the
729
+shadow image, and will then use ``mmap()`` to directly access it. The
730
+emulation program can control KVM access to the shadow image by sending
731
+KVM an access map telling it which areas of the image have no
732
+side-effects (and can be completed immediately), and which require a
733
+MMIO request to the emulation program. The access map can also inform
734
+the KVM drive which size accesses are allowed to the image.
735
+
736
+master descriptor
737
+^^^^^^^^^^^^^^^^^
738
+
739
+The master descriptor is used by QEMU to configure the new KVM device.
740
+The descriptor would be returned by the KVM driver when QEMU issues a
741
+*KVM\_CREATE\_DEVICE* ``ioctl()`` with a *KVM\_DEV\_TYPE\_USER* type.
742
+
743
+KVM\_DEV\_TYPE\_USER device ops
744
+
745
+
746
+The *KVM\_DEV\_TYPE\_USER* operations vector will be registered by a
747
+``kvm_register_device_ops()`` call when the KVM system in initialized by
748
+``kvm_init()``. These device ops are called by the KVM driver when QEMU
749
+executes certain ``ioctl()`` operations on its KVM file descriptor. They
750
+include:
751
+
752
+- create
753
+
754
+This routine is called when QEMU issues a *KVM\_CREATE\_DEVICE*
755
+``ioctl()`` on its per-VM file descriptor. It will allocate and
756
+initialize a KVM user device specific data structure, and assign the
757
+*kvm\_device* private field to it.
758
+
759
+- ioctl
760
+
761
+This routine is invoked when QEMU issues an ``ioctl()`` on the master
762
+descriptor. The ``ioctl()`` commands supported are defined by the KVM
763
+device type. *KVM\_DEV\_TYPE\_USER* ones will need several commands:
764
+
765
+*KVM\_DEV\_USER\_SLAVE\_FD* creates the slave file descriptor that will
766
+be passed to the device emulation program. Only one slave can be created
767
+by each master descriptor. The file operations performed by this
768
+descriptor are described below.
769
+
770
+The *KVM\_DEV\_USER\_PA\_RANGE* command configures a guest physical
771
+address range that the slave descriptor will receive MMIO notifications
772
+for. The range is specified by a guest physical range structure
773
+argument. For buses that assign addresses to devices dynamically, this
774
+command can be executed while the guest is running, such as the case
775
+when a guest changes a device's PCI BAR registers.
776
+
777
+*KVM\_DEV\_USER\_PA\_RANGE* will use ``kvm_io_bus_register_dev()`` to
778
+register *kvm\_io\_device\_ops* callbacks to be invoked when the guest
779
+performs a MMIO operation within the range. When a range is changed,
780
+``kvm_io_bus_unregister_dev()`` is used to remove the previous
781
+instantiation.
782
+
783
+*KVM\_DEV\_USER\_TIMEOUT* will configure a timeout value that specifies
784
+how long KVM will wait for the emulation process to respond to a MMIO
785
+indication.
786
+
787
+- destroy
788
+
789
+This routine is called when the VM instance is destroyed. It will need
790
+to destroy the slave descriptor; and free any memory allocated by the
791
+driver, as well as the *kvm\_device* structure itself.
792
+
793
+slave descriptor
794
+^^^^^^^^^^^^^^^^
795
+
796
+The slave descriptor will have its own file operations vector, which
797
+responds to system calls on the descriptor performed by the device
798
+emulation program.
799
+
800
+- read
801
+
802
+A read returns any pending MMIO requests from the KVM driver as MMIO
803
+request structures. Multiple structures can be returned if there are
804
+multiple MMIO operations pending. The MMIO requests are moved from the
805
+pending queue to the sent queue, and if there are threads waiting for
806
+space in the pending to add new MMIO operations, they will be woken
807
+here.
808
+
809
+- write
810
+
811
+A write also consists of a set of MMIO requests. They are compared to
812
+the MMIO requests in the sent queue. Matches are removed from the sent
813
+queue, and any threads waiting for the reply are woken. If a store is
814
+removed, then the number of posted stores in the per-CPU scoreboard is
815
+decremented. When the number is zero, and a non side-effect load was
816
+waiting for posted stores to complete, the load is continued.
817
+
818
+- ioctl
819
+
820
+There are several ioctl()s that can be performed on the slave
821
+descriptor.
822
+
823
+A *KVM\_DEV\_USER\_SHADOW\_SIZE* ``ioctl()`` causes the KVM driver to
824
+allocate memory for the shadow image. This memory can later be
825
+``mmap()``\ ed by the emulation process to share the emulation's view of
826
+device memory with the KVM driver.
827
+
828
+A *KVM\_DEV\_USER\_SHADOW\_CTRL* ``ioctl()`` controls access to the
829
+shadow image. It will send the KVM driver a shadow control map, which
830
+specifies which areas of the image can complete guest loads without
831
+sending the load request to the emulation program. It will also specify
832
+the size of load operations that are allowed.
833
+
834
+- poll
835
+
836
+An emulation program will use the ``poll()`` call with a *POLLIN* flag
837
+to determine if there are MMIO requests waiting to be read. It will
838
+return if the pending MMIO request queue is not empty.
839
+
840
+- mmap
841
+
842
+This call allows the emulation program to directly access the shadow
843
+image allocated by the KVM driver. As device emulation updates device
844
+memory, changes with no side-effects will be reflected in the shadow,
845
+and the KVM driver can satisfy guest loads from the shadow image without
846
+needing to wait for the emulation program.
847
+
848
+kvm\_io\_device ops
849
+^^^^^^^^^^^^^^^^^^^
850
+
851
+Each KVM per-CPU thread can handle MMIO operation on behalf of the guest
852
+VM. KVM will use the MMIO's guest physical address to search for a
853
+matching *kvm\_io\_device* to see if the MMIO can be handled by the KVM
854
+driver instead of exiting back to QEMU. If a match is found, the
855
+corresponding callback will be invoked.
856
+
857
+- read
858
+
859
+This callback is invoked when the guest performs a load to the device.
860
+Loads with side-effects must be handled synchronously, with the KVM
861
+driver putting the QEMU thread to sleep waiting for the emulation
862
+process reply before re-starting the guest. Loads that do not have
863
+side-effects may be optimized by satisfying them from the shadow image,
864
+if there are no outstanding stores to the device by this CPU. PCI memory
865
+ordering demands that a load cannot complete before all older stores to
866
+the same device have been completed.
867
+
868
+- write
869
+
870
+Stores can be handled asynchronously unless the pending MMIO request
871
+queue is full. In this case, the QEMU thread must sleep waiting for
872
+space in the queue. Stores will increment the number of posted stores in
873
+the per-CPU scoreboard, in order to implement the PCI ordering
874
+constraint above.
875
+
876
+interrupt acceleration
877
+^^^^^^^^^^^^^^^^^^^^^^
878
+
879
+This performance optimization would work much like a vhost user
880
+application does, where the QEMU process sets up *eventfds* that cause
881
+the device's corresponding interrupt to be triggered by the KVM driver.
882
+These irq file descriptors are sent to the emulation process at
883
+initialization, and are used when the emulation code raises a device
884
+interrupt.
885
+
886
+intx acceleration
887
+'''''''''''''''''
888
+
889
+Traditional PCI pin interrupts are level based, so, in addition to an
890
+irq file descriptor, a re-sampling file descriptor needs to be sent to
891
+the emulation program. This second file descriptor allows multiple
892
+devices sharing an irq to be notified when the interrupt has been
893
+acknowledged by the guest, so they can re-trigger the interrupt if their
894
+device has not de-asserted its interrupt.
895
+
896
+intx irq descriptor
897
+
898
+
899
+The irq descriptors are created by the proxy object
900
+``using event_notifier_init()`` to create the irq and re-sampling
901
+*eventds*, and ``kvm_vm_ioctl(KVM_IRQFD)`` to bind them to an interrupt.
902
+The interrupt route can be found with
903
+``pci_device_route_intx_to_irq()``.
904
+
905
+intx routing changes
906
+
907
+
908
+Intx routing can be changed when the guest programs the APIC the device
909
+pin is connected to. The proxy object in QEMU will use
910
+``pci_device_set_intx_routing_notifier()`` to be informed of any guest
911
+changes to the route. This handler will broadly follow the VFIO
912
+interrupt logic to change the route: de-assigning the existing irq
913
+descriptor from its route, then assigning it the new route. (see
914
+``vfio_intx_update()``)
915
+
916
+MSI/X acceleration
917
+''''''''''''''''''
918
+
919
+MSI/X interrupts are sent as DMA transactions to the host. The interrupt
920
+data contains a vector that is programmed by the guest, A device may have
921
+multiple MSI interrupts associated with it, so multiple irq descriptors
922
+may need to be sent to the emulation program.
923
+
924
+MSI/X irq descriptor
925
+
926
+
927
+This case will also follow the VFIO example. For each MSI/X interrupt,
928
+an *eventfd* is created, a virtual interrupt is allocated by
929
+``kvm_irqchip_add_msi_route()``, and the virtual interrupt is bound to
930
+the eventfd with ``kvm_irqchip_add_irqfd_notifier()``.
931
+
932
+MSI/X config space changes
933
+
934
+
935
+The guest may dynamically update several MSI-related tables in the
936
+device's PCI config space. These include per-MSI interrupt enables and
937
+vector data. Additionally, MSIX tables exist in device memory space, not
938
+config space. Much like the BAR case above, the proxy object must look
939
+at guest config space programming to keep the MSI interrupt state
940
+consistent between QEMU and the emulation program.
941
+
942
+--------------
943
+
944
+Disaggregated CPU emulation
945
+---------------------------
946
+
947
+After IO services have been disaggregated, a second phase would be to
948
+separate a process to handle CPU instruction emulation from the main
949
+QEMU control function. There are no object separation points for this
950
+code, so the first task would be to create one.
951
+
952
+Host access controls
953
+--------------------
954
+
955
+Separating QEMU relies on the host OS's access restriction mechanisms to
956
+enforce that the differing processes can only access the objects they
957
+are entitled to. There are a couple types of mechanisms usually provided
958
+by general purpose OSs.
959
+
960
+Discretionary access control
961
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
962
+
963
+Discretionary access control allows each user to control who can access
964
+their files. In Linux, this type of control is usually too coarse for
965
+QEMU separation, since it only provides three separate access controls:
966
+one for the same user ID, the second for users IDs with the same group
967
+ID, and the third for all other user IDs. Each device instance would
968
+need a separate user ID to provide access control, which is likely to be
969
+unwieldy for dynamically created VMs.
970
+
971
+Mandatory access control
972
+~~~~~~~~~~~~~~~~~~~~~~~~
973
+
974
+Mandatory access control allows the OS to add an additional set of
975
+controls on top of discretionary access for the OS to control. It also
976
+adds other attributes to processes and files such as types, roles, and
977
+categories, and can establish rules for how processes and files can
978
+interact.
979
+
980
+Type enforcement
981
+^^^^^^^^^^^^^^^^
982
+
983
+Type enforcement assigns a *type* attribute to processes and files, and
984
+allows rules to be written on what operations a process with a given
985
+type can perform on a file with a given type. QEMU separation could take
986
+advantage of type enforcement by running the emulation processes with
987
+different types, both from the main QEMU process, and from the emulation
988
+processes of different classes of devices.
989
+
990
+For example, guest disk images and disk emulation processes could have
991
+types separate from the main QEMU process and non-disk emulation
992
+processes, and the type rules could prevent processes other than disk
993
+emulation ones from accessing guest disk images. Similarly, network
994
+emulation processes can have a type separate from the main QEMU process
995
+and non-network emulation process, and only that type can access the
996
+host tun/tap device used to provide guest networking.
997
+
998
+Category enforcement
999
+^^^^^^^^^^^^^^^^^^^^
1000
+
1001
+Category enforcement assigns a set of numbers within a given range to
1002
+the process or file. The process is granted access to the file if the
1003
+process's set is a superset of the file's set. This enforcement can be
1004
+used to separate multiple instances of devices in the same class.
1005
+
1006
+For example, if there are multiple disk devices provides to a guest,
1007
+each device emulation process could be provisioned with a separate
1008
+category. The different device emulation processes would not be able to
1009
+access each other's backing disk images.
1010
+
1011
+Alternatively, categories could be used in lieu of the type enforcement
1012
+scheme described above. In this scenario, different categories would be
1013
+used to prevent device emulation processes in different classes from
1014
+accessing resources assigned to other classes.
1015
--
1016
2.29.2
1017
diff view generated by jsdifflib
1
We had a test for a case where relative extent paths did not work, but
1
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
2
unfortunately we just fixed the underlying problem, so it works now.
3
This patch adds a new test case that still fails.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Adds documentation explaining the command-line arguments needed
6
Reviewed-by: John Snow <jsnow@redhat.com>
4
to use multi-process.
7
Message-id: 20190815153638.4600-4-mreitz@redhat.com
5
8
Reviewed-by: John Snow <jsnow@redhat.com>
6
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
8
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 49f757a84e5dd6fae14b22544897d1124c5fdbad.1611938319.git.jag.raman@oracle.com
11
12
[Move orphan docs/multi-process.rst document into docs/system/ and add
13
it to index.rst to prevent Sphinx "document isn't included in any
14
toctree" error.
15
--Stefan]
16
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
18
---
11
tests/qemu-iotests/059 | 27 +++++++++++++++++++++++++++
19
MAINTAINERS | 1 +
12
tests/qemu-iotests/059.out | 4 ++++
20
docs/system/index.rst | 1 +
13
2 files changed, 31 insertions(+)
21
docs/system/multi-process.rst | 64 +++++++++++++++++++++++++++++++++++
22
3 files changed, 66 insertions(+)
23
create mode 100644 docs/system/multi-process.rst
14
24
15
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
25
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100755
26
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/059
27
--- a/MAINTAINERS
18
+++ b/tests/qemu-iotests/059
28
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2
29
@@ -XXX,XX +XXX,XX @@ M: Jagannathan Raman <jag.raman@oracle.com>
20
30
M: John G Johnson <john.g.johnson@oracle.com>
21
echo
31
S: Maintained
22
echo "=== Testing monolithicFlat with internally generated JSON file name ==="
32
F: docs/devel/multi-process.rst
33
+F: docs/system/multi-process.rst
34
35
Build and test automation
36
-------------------------
37
diff --git a/docs/system/index.rst b/docs/system/index.rst
38
index XXXXXXX..XXXXXXX 100644
39
--- a/docs/system/index.rst
40
+++ b/docs/system/index.rst
41
@@ -XXX,XX +XXX,XX @@ Contents:
42
pr-manager
43
targets
44
security
45
+ multi-process
46
deprecated
47
removed-features
48
build-platforms
49
diff --git a/docs/system/multi-process.rst b/docs/system/multi-process.rst
50
new file mode 100644
51
index XXXXXXX..XXXXXXX
52
--- /dev/null
53
+++ b/docs/system/multi-process.rst
54
@@ -XXX,XX +XXX,XX @@
55
+Multi-process QEMU
56
+==================
23
+
57
+
24
+echo '--- blkdebug ---'
58
+This document describes how to configure and use multi-process qemu.
25
# Should work, because bdrv_dirname() works fine with blkdebug
59
+For the design document refer to docs/devel/qemu-multiprocess.
26
IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
27
$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" \
28
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TE
29
| _filter_testdir | _filter_imgfmt | _filter_img_info
30
_cleanup_test_img
31
32
+echo '--- quorum ---'
33
+# Should not work, because bdrv_dirname() does not work with quorum
34
+IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
35
+cp "$TEST_IMG" "$TEST_IMG.orig"
36
+
60
+
37
+filename="json:{
61
+1) Configuration
38
+ \"driver\": \"$IMGFMT\",
62
+----------------
39
+ \"file\": {
40
+ \"driver\": \"quorum\",
41
+ \"children\": [ {
42
+ \"driver\": \"file\",
43
+ \"filename\": \"$TEST_IMG\"
44
+ }, {
45
+ \"driver\": \"file\",
46
+ \"filename\": \"$TEST_IMG.orig\"
47
+ } ],
48
+ \"vote-threshold\": 1
49
+ } }"
50
+
63
+
51
+filename=$(echo "$filename" | tr '\n' ' ' | sed -e 's/\s\+/ /g')
64
+multi-process is enabled by default for targets that enable KVM
52
+$QEMU_IMG info "$filename" 2>&1 \
53
+ | sed -e "s/'json:[^']*'/\$QUORUM_FILE/g" \
54
+ | _filter_testdir | _filter_imgfmt | _filter_img_info
55
+
65
+
56
+
66
+
57
echo
67
+2) Usage
58
echo "=== Testing version 3 ==="
68
+--------
59
_use_sample_img iotest-version3.vmdk.bz2
69
+
60
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
70
+Multi-process QEMU requires an orchestrator to launch.
61
index XXXXXXX..XXXXXXX 100644
71
+
62
--- a/tests/qemu-iotests/059.out
72
+Following is a description of command-line used to launch mpqemu.
63
+++ b/tests/qemu-iotests/059.out
73
+
64
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 10240
74
+* Orchestrator:
65
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
75
+
66
76
+ - The Orchestrator creates a unix socketpair
67
=== Testing monolithicFlat with internally generated JSON file name ===
77
+
68
+--- blkdebug ---
78
+ - It launches the remote process and passes one of the
69
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
79
+ sockets to it via command-line.
70
format name: IMGFMT
80
+
71
cluster size: 0 bytes
81
+ - It then launches QEMU and specifies the other socket as an option
72
vm state offset: 0 bytes
82
+ to the Proxy device object
73
+--- quorum ---
83
+
74
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
84
+* Remote Process:
75
+qemu-img: Could not open $QUORUM_FILE: Cannot use relative paths with VMDK descriptor file $QUORUM_FILE: Cannot generate a base directory for quorum nodes
85
+
76
86
+ - QEMU can enter remote process mode by using the "remote" machine
77
=== Testing version 3 ===
87
+ option.
78
image: TEST_DIR/iotest-version3.IMGFMT
88
+
89
+ - The orchestrator creates a "remote-object" with details about
90
+ the device and the file descriptor for the device
91
+
92
+ - The remaining options are no different from how one launches QEMU with
93
+ devices.
94
+
95
+ - Example command-line for the remote process is as follows:
96
+
97
+ /usr/bin/qemu-system-x86_64 \
98
+ -machine x-remote \
99
+ -device lsi53c895a,id=lsi0 \
100
+ -drive id=drive_image2,file=/build/ol7-nvme-test-1.qcow2 \
101
+ -device scsi-hd,id=drive2,drive=drive_image2,bus=lsi0.0,scsi-id=0 \
102
+ -object x-remote-object,id=robj1,devid=lsi1,fd=4,
103
+
104
+* QEMU:
105
+
106
+ - Since parts of the RAM are shared between QEMU & remote process, a
107
+ memory-backend-memfd is required to facilitate this, as follows:
108
+
109
+ -object memory-backend-memfd,id=mem,size=2G
110
+
111
+ - A "x-pci-proxy-dev" device is created for each of the PCI devices emulated
112
+ in the remote process. A "socket" sub-option specifies the other end of
113
+ unix channel created by orchestrator. The "id" sub-option must be specified
114
+ and should be the same as the "id" specified for the remote PCI device
115
+
116
+ - Example commandline for QEMU is as follows:
117
+
118
+ -device x-pci-proxy-dev,id=lsi0,socket=3
79
--
119
--
80
2.21.0
120
2.29.2
81
121
82
diff view generated by jsdifflib
New patch
1
1
From: Jagannathan Raman <jag.raman@oracle.com>
2
3
Allow RAM MemoryRegion to be created from an offset in a file, instead
4
of allocating at offset of 0 by default. This is needed to synchronize
5
RAM between QEMU & remote process.
6
7
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
8
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
9
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-id: 609996697ad8617e3b01df38accc5c208c24d74e.1611938319.git.jag.raman@oracle.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
14
include/exec/memory.h | 2 ++
15
include/exec/ram_addr.h | 4 ++--
16
include/qemu/mmap-alloc.h | 4 +++-
17
backends/hostmem-memfd.c | 2 +-
18
hw/misc/ivshmem.c | 3 ++-
19
softmmu/memory.c | 3 ++-
20
softmmu/physmem.c | 12 +++++++-----
21
util/mmap-alloc.c | 8 +++++---
22
util/oslib-posix.c | 2 +-
23
9 files changed, 25 insertions(+), 15 deletions(-)
24
25
diff --git a/include/exec/memory.h b/include/exec/memory.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/exec/memory.h
28
+++ b/include/exec/memory.h
29
@@ -XXX,XX +XXX,XX @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
30
* @size: size of the region.
31
* @share: %true if memory must be mmaped with the MAP_SHARED flag
32
* @fd: the fd to mmap.
33
+ * @offset: offset within the file referenced by fd
34
* @errp: pointer to Error*, to store an error if it happens.
35
*
36
* Note that this function does not do anything to cause the data in the
37
@@ -XXX,XX +XXX,XX @@ void memory_region_init_ram_from_fd(MemoryRegion *mr,
38
uint64_t size,
39
bool share,
40
int fd,
41
+ ram_addr_t offset,
42
Error **errp);
43
#endif
44
45
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/exec/ram_addr.h
48
+++ b/include/exec/ram_addr.h
49
@@ -XXX,XX +XXX,XX @@ RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
50
uint32_t ram_flags, const char *mem_path,
51
bool readonly, Error **errp);
52
RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
53
- uint32_t ram_flags, int fd, bool readonly,
54
- Error **errp);
55
+ uint32_t ram_flags, int fd, off_t offset,
56
+ bool readonly, Error **errp);
57
58
RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
59
MemoryRegion *mr, Error **errp);
60
diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h
61
index XXXXXXX..XXXXXXX 100644
62
--- a/include/qemu/mmap-alloc.h
63
+++ b/include/qemu/mmap-alloc.h
64
@@ -XXX,XX +XXX,XX @@ size_t qemu_mempath_getpagesize(const char *mem_path);
65
* @readonly: true for a read-only mapping, false for read/write.
66
* @shared: map has RAM_SHARED flag.
67
* @is_pmem: map has RAM_PMEM flag.
68
+ * @map_offset: map starts at offset of map_offset from the start of fd
69
*
70
* Return:
71
* On success, return a pointer to the mapped area.
72
@@ -XXX,XX +XXX,XX @@ void *qemu_ram_mmap(int fd,
73
size_t align,
74
bool readonly,
75
bool shared,
76
- bool is_pmem);
77
+ bool is_pmem,
78
+ off_t map_offset);
79
80
void qemu_ram_munmap(int fd, void *ptr, size_t size);
81
82
diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/backends/hostmem-memfd.c
85
+++ b/backends/hostmem-memfd.c
86
@@ -XXX,XX +XXX,XX @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
87
name = host_memory_backend_get_name(backend);
88
memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
89
name, backend->size,
90
- backend->share, fd, errp);
91
+ backend->share, fd, 0, errp);
92
g_free(name);
93
}
94
95
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/hw/misc/ivshmem.c
98
+++ b/hw/misc/ivshmem.c
99
@@ -XXX,XX +XXX,XX @@ static void process_msg_shmem(IVShmemState *s, int fd, Error **errp)
100
101
/* mmap the region and map into the BAR2 */
102
memory_region_init_ram_from_fd(&s->server_bar2, OBJECT(s),
103
- "ivshmem.bar2", size, true, fd, &local_err);
104
+ "ivshmem.bar2", size, true, fd, 0,
105
+ &local_err);
106
if (local_err) {
107
error_propagate(errp, local_err);
108
return;
109
diff --git a/softmmu/memory.c b/softmmu/memory.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/softmmu/memory.c
112
+++ b/softmmu/memory.c
113
@@ -XXX,XX +XXX,XX @@ void memory_region_init_ram_from_fd(MemoryRegion *mr,
114
uint64_t size,
115
bool share,
116
int fd,
117
+ ram_addr_t offset,
118
Error **errp)
119
{
120
Error *err = NULL;
121
@@ -XXX,XX +XXX,XX @@ void memory_region_init_ram_from_fd(MemoryRegion *mr,
122
mr->destructor = memory_region_destructor_ram;
123
mr->ram_block = qemu_ram_alloc_from_fd(size, mr,
124
share ? RAM_SHARED : 0,
125
- fd, false, &err);
126
+ fd, offset, false, &err);
127
if (err) {
128
mr->size = int128_zero();
129
object_unparent(OBJECT(mr));
130
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/softmmu/physmem.c
133
+++ b/softmmu/physmem.c
134
@@ -XXX,XX +XXX,XX @@ static void *file_ram_alloc(RAMBlock *block,
135
int fd,
136
bool readonly,
137
bool truncate,
138
+ off_t offset,
139
Error **errp)
140
{
141
void *area;
142
@@ -XXX,XX +XXX,XX @@ static void *file_ram_alloc(RAMBlock *block,
143
}
144
145
area = qemu_ram_mmap(fd, memory, block->mr->align, readonly,
146
- block->flags & RAM_SHARED, block->flags & RAM_PMEM);
147
+ block->flags & RAM_SHARED, block->flags & RAM_PMEM,
148
+ offset);
149
if (area == MAP_FAILED) {
150
error_setg_errno(errp, errno,
151
"unable to map backing store for guest RAM");
152
@@ -XXX,XX +XXX,XX @@ static void ram_block_add(RAMBlock *new_block, Error **errp, bool shared)
153
154
#ifdef CONFIG_POSIX
155
RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
156
- uint32_t ram_flags, int fd, bool readonly,
157
- Error **errp)
158
+ uint32_t ram_flags, int fd, off_t offset,
159
+ bool readonly, Error **errp)
160
{
161
RAMBlock *new_block;
162
Error *local_err = NULL;
163
@@ -XXX,XX +XXX,XX @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
164
new_block->max_length = size;
165
new_block->flags = ram_flags;
166
new_block->host = file_ram_alloc(new_block, size, fd, readonly,
167
- !file_size, errp);
168
+ !file_size, offset, errp);
169
if (!new_block->host) {
170
g_free(new_block);
171
return NULL;
172
@@ -XXX,XX +XXX,XX @@ RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
173
return NULL;
174
}
175
176
- block = qemu_ram_alloc_from_fd(size, mr, ram_flags, fd, readonly, errp);
177
+ block = qemu_ram_alloc_from_fd(size, mr, ram_flags, fd, 0, readonly, errp);
178
if (!block) {
179
if (created) {
180
unlink(mem_path);
181
diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/util/mmap-alloc.c
184
+++ b/util/mmap-alloc.c
185
@@ -XXX,XX +XXX,XX @@ void *qemu_ram_mmap(int fd,
186
size_t align,
187
bool readonly,
188
bool shared,
189
- bool is_pmem)
190
+ bool is_pmem,
191
+ off_t map_offset)
192
{
193
int prot;
194
int flags;
195
@@ -XXX,XX +XXX,XX @@ void *qemu_ram_mmap(int fd,
196
197
prot = PROT_READ | (readonly ? 0 : PROT_WRITE);
198
199
- ptr = mmap(guardptr + offset, size, prot, flags | map_sync_flags, fd, 0);
200
+ ptr = mmap(guardptr + offset, size, prot,
201
+ flags | map_sync_flags, fd, map_offset);
202
203
if (ptr == MAP_FAILED && map_sync_flags) {
204
if (errno == ENOTSUP) {
205
@@ -XXX,XX +XXX,XX @@ void *qemu_ram_mmap(int fd,
206
* if map failed with MAP_SHARED_VALIDATE | MAP_SYNC,
207
* we will remove these flags to handle compatibility.
208
*/
209
- ptr = mmap(guardptr + offset, size, prot, flags, fd, 0);
210
+ ptr = mmap(guardptr + offset, size, prot, flags, fd, map_offset);
211
}
212
213
if (ptr == MAP_FAILED) {
214
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
215
index XXXXXXX..XXXXXXX 100644
216
--- a/util/oslib-posix.c
217
+++ b/util/oslib-posix.c
218
@@ -XXX,XX +XXX,XX @@ void *qemu_memalign(size_t alignment, size_t size)
219
void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared)
220
{
221
size_t align = QEMU_VMALLOC_ALIGN;
222
- void *ptr = qemu_ram_mmap(-1, size, align, false, shared, false);
223
+ void *ptr = qemu_ram_mmap(-1, size, align, false, shared, false, 0);
224
225
if (ptr == MAP_FAILED) {
226
return NULL;
227
--
228
2.29.2
229
diff view generated by jsdifflib
New patch
1
From: Jagannathan Raman <jag.raman@oracle.com>
1
2
3
Add configuration options to enable or disable multiprocess QEMU code
4
5
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
6
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
7
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 6cc37253e35418ebd7b675a31a3df6e3c7a12dc1.1611938319.git.jag.raman@oracle.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
configure | 10 ++++++++++
13
meson.build | 4 +++-
14
Kconfig.host | 4 ++++
15
hw/Kconfig | 1 +
16
hw/remote/Kconfig | 3 +++
17
5 files changed, 21 insertions(+), 1 deletion(-)
18
create mode 100644 hw/remote/Kconfig
19
20
diff --git a/configure b/configure
21
index XXXXXXX..XXXXXXX 100755
22
--- a/configure
23
+++ b/configure
24
@@ -XXX,XX +XXX,XX @@ skip_meson=no
25
gettext="auto"
26
fuse="auto"
27
fuse_lseek="auto"
28
+multiprocess="no"
29
30
malloc_trim="auto"
31
32
@@ -XXX,XX +XXX,XX @@ Linux)
33
linux="yes"
34
linux_user="yes"
35
vhost_user=${default_feature:-yes}
36
+ multiprocess=${default_feature:-yes}
37
;;
38
esac
39
40
@@ -XXX,XX +XXX,XX @@ for opt do
41
;;
42
--disable-fuse-lseek) fuse_lseek="disabled"
43
;;
44
+ --enable-multiprocess) multiprocess="yes"
45
+ ;;
46
+ --disable-multiprocess) multiprocess="no"
47
+ ;;
48
*)
49
echo "ERROR: unknown option $opt"
50
echo "Try '$0 --help' for more information"
51
@@ -XXX,XX +XXX,XX @@ disabled with --disable-FEATURE, default is enabled if available
52
libdaxctl libdaxctl support
53
fuse FUSE block device export
54
fuse-lseek SEEK_HOLE/SEEK_DATA support for FUSE exports
55
+ multiprocess Multiprocess QEMU support
56
57
NOTE: The object files are built at the place where configure is launched
58
EOF
59
@@ -XXX,XX +XXX,XX @@ fi
60
if test "$have_mlockall" = "yes" ; then
61
echo "HAVE_MLOCKALL=y" >> $config_host_mak
62
fi
63
+if test "$multiprocess" = "yes" ; then
64
+ echo "CONFIG_MULTIPROCESS_ALLOWED=y" >> $config_host_mak
65
+fi
66
if test "$fuzzing" = "yes" ; then
67
# If LIB_FUZZING_ENGINE is set, assume we are running on OSS-Fuzz, and the
68
# needed CFLAGS have already been provided
69
diff --git a/meson.build b/meson.build
70
index XXXXXXX..XXXXXXX 100644
71
--- a/meson.build
72
+++ b/meson.build
73
@@ -XXX,XX +XXX,XX @@ host_kconfig = \
74
('CONFIG_VHOST_KERNEL' in config_host ? ['CONFIG_VHOST_KERNEL=y'] : []) + \
75
(have_virtfs ? ['CONFIG_VIRTFS=y'] : []) + \
76
('CONFIG_LINUX' in config_host ? ['CONFIG_LINUX=y'] : []) + \
77
- ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : [])
78
+ ('CONFIG_PVRDMA' in config_host ? ['CONFIG_PVRDMA=y'] : []) + \
79
+ ('CONFIG_MULTIPROCESS_ALLOWED' in config_host ? ['CONFIG_MULTIPROCESS_ALLOWED=y'] : [])
80
81
ignored = [ 'TARGET_XML_FILES', 'TARGET_ABI_DIR', 'TARGET_ARCH' ]
82
83
@@ -XXX,XX +XXX,XX @@ summary_info += {'libpmem support': config_host.has_key('CONFIG_LIBPMEM')}
84
summary_info += {'libdaxctl support': config_host.has_key('CONFIG_LIBDAXCTL')}
85
summary_info += {'libudev': libudev.found()}
86
summary_info += {'FUSE lseek': fuse_lseek.found()}
87
+summary_info += {'Multiprocess QEMU': config_host.has_key('CONFIG_MULTIPROCESS_ALLOWED')}
88
summary(summary_info, bool_yn: true, section: 'Dependencies')
89
90
if not supported_cpus.contains(cpu)
91
diff --git a/Kconfig.host b/Kconfig.host
92
index XXXXXXX..XXXXXXX 100644
93
--- a/Kconfig.host
94
+++ b/Kconfig.host
95
@@ -XXX,XX +XXX,XX @@ config VIRTFS
96
97
config PVRDMA
98
bool
99
+
100
+config MULTIPROCESS_ALLOWED
101
+ bool
102
+ imply MULTIPROCESS
103
diff --git a/hw/Kconfig b/hw/Kconfig
104
index XXXXXXX..XXXXXXX 100644
105
--- a/hw/Kconfig
106
+++ b/hw/Kconfig
107
@@ -XXX,XX +XXX,XX @@ source pci-host/Kconfig
108
source pcmcia/Kconfig
109
source pci/Kconfig
110
source rdma/Kconfig
111
+source remote/Kconfig
112
source rtc/Kconfig
113
source scsi/Kconfig
114
source sd/Kconfig
115
diff --git a/hw/remote/Kconfig b/hw/remote/Kconfig
116
new file mode 100644
117
index XXXXXXX..XXXXXXX
118
--- /dev/null
119
+++ b/hw/remote/Kconfig
120
@@ -XXX,XX +XXX,XX @@
121
+config MULTIPROCESS
122
+ bool
123
+ depends on PCI && KVM
124
--
125
2.29.2
126
diff view generated by jsdifflib
New patch
1
From: Jagannathan Raman <jag.raman@oracle.com>
1
2
3
PCI host bridge is setup for the remote device process. It is
4
implemented using remote-pcihost object. It is an extension of the PCI
5
host bridge setup by QEMU.
6
Remote-pcihost configures a PCI bus which could be used by the remote
7
PCI device to latch on to.
8
9
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
10
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
11
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Message-id: 0871ba857abb2eafacde07e7fe66a3f12415bfb2.1611938319.git.jag.raman@oracle.com
14
15
[Added PCI_EXPRESS condition in hw/remote/Kconfig since remote-pcihost
16
needs PCIe. This solves "make check" failure on s390x. Fix suggested by
17
Philippe Mathieu-Daudé <philmd@redhat.com> and Thomas Huth
18
<thuth@redhat.com>.
19
--Stefan]
20
21
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
22
---
23
MAINTAINERS | 2 +
24
include/hw/pci-host/remote.h | 29 ++++++++++++++
25
hw/pci-host/remote.c | 75 ++++++++++++++++++++++++++++++++++++
26
hw/pci-host/Kconfig | 3 ++
27
hw/pci-host/meson.build | 1 +
28
hw/remote/Kconfig | 3 +-
29
6 files changed, 112 insertions(+), 1 deletion(-)
30
create mode 100644 include/hw/pci-host/remote.h
31
create mode 100644 hw/pci-host/remote.c
32
33
diff --git a/MAINTAINERS b/MAINTAINERS
34
index XXXXXXX..XXXXXXX 100644
35
--- a/MAINTAINERS
36
+++ b/MAINTAINERS
37
@@ -XXX,XX +XXX,XX @@ M: John G Johnson <john.g.johnson@oracle.com>
38
S: Maintained
39
F: docs/devel/multi-process.rst
40
F: docs/system/multi-process.rst
41
+F: hw/pci-host/remote.c
42
+F: include/hw/pci-host/remote.h
43
44
Build and test automation
45
-------------------------
46
diff --git a/include/hw/pci-host/remote.h b/include/hw/pci-host/remote.h
47
new file mode 100644
48
index XXXXXXX..XXXXXXX
49
--- /dev/null
50
+++ b/include/hw/pci-host/remote.h
51
@@ -XXX,XX +XXX,XX @@
52
+/*
53
+ * PCI Host for remote device
54
+ *
55
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
56
+ *
57
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
58
+ * See the COPYING file in the top-level directory.
59
+ *
60
+ */
61
+
62
+#ifndef REMOTE_PCIHOST_H
63
+#define REMOTE_PCIHOST_H
64
+
65
+#include "exec/memory.h"
66
+#include "hw/pci/pcie_host.h"
67
+
68
+#define TYPE_REMOTE_PCIHOST "remote-pcihost"
69
+OBJECT_DECLARE_SIMPLE_TYPE(RemotePCIHost, REMOTE_PCIHOST)
70
+
71
+struct RemotePCIHost {
72
+ /*< private >*/
73
+ PCIExpressHost parent_obj;
74
+ /*< public >*/
75
+
76
+ MemoryRegion *mr_pci_mem;
77
+ MemoryRegion *mr_sys_io;
78
+};
79
+
80
+#endif
81
diff --git a/hw/pci-host/remote.c b/hw/pci-host/remote.c
82
new file mode 100644
83
index XXXXXXX..XXXXXXX
84
--- /dev/null
85
+++ b/hw/pci-host/remote.c
86
@@ -XXX,XX +XXX,XX @@
87
+/*
88
+ * Remote PCI host device
89
+ *
90
+ * Unlike PCI host devices that model physical hardware, the purpose
91
+ * of this PCI host is to host multi-process QEMU devices.
92
+ *
93
+ * Multi-process QEMU extends the PCI host of a QEMU machine into a
94
+ * remote process. Any PCI device attached to the remote process is
95
+ * visible in the QEMU guest. This allows existing QEMU device models
96
+ * to be reused in the remote process.
97
+ *
98
+ * This PCI host is purely a container for PCI devices. It's fake in the
99
+ * sense that the guest never sees this PCI host and has no way of
100
+ * accessing it. Its job is just to provide the environment that QEMU
101
+ * PCI device models need when running in a remote process.
102
+ *
103
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
104
+ *
105
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
106
+ * See the COPYING file in the top-level directory.
107
+ *
108
+ */
109
+
110
+#include "qemu/osdep.h"
111
+#include "qemu-common.h"
112
+
113
+#include "hw/pci/pci.h"
114
+#include "hw/pci/pci_host.h"
115
+#include "hw/pci/pcie_host.h"
116
+#include "hw/qdev-properties.h"
117
+#include "hw/pci-host/remote.h"
118
+#include "exec/memory.h"
119
+
120
+static const char *remote_pcihost_root_bus_path(PCIHostState *host_bridge,
121
+ PCIBus *rootbus)
122
+{
123
+ return "0000:00";
124
+}
125
+
126
+static void remote_pcihost_realize(DeviceState *dev, Error **errp)
127
+{
128
+ PCIHostState *pci = PCI_HOST_BRIDGE(dev);
129
+ RemotePCIHost *s = REMOTE_PCIHOST(dev);
130
+
131
+ pci->bus = pci_root_bus_new(DEVICE(s), "remote-pci",
132
+ s->mr_pci_mem, s->mr_sys_io,
133
+ 0, TYPE_PCIE_BUS);
134
+}
135
+
136
+static void remote_pcihost_class_init(ObjectClass *klass, void *data)
137
+{
138
+ DeviceClass *dc = DEVICE_CLASS(klass);
139
+ PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
140
+
141
+ hc->root_bus_path = remote_pcihost_root_bus_path;
142
+ dc->realize = remote_pcihost_realize;
143
+
144
+ dc->user_creatable = false;
145
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
146
+ dc->fw_name = "pci";
147
+}
148
+
149
+static const TypeInfo remote_pcihost_info = {
150
+ .name = TYPE_REMOTE_PCIHOST,
151
+ .parent = TYPE_PCIE_HOST_BRIDGE,
152
+ .instance_size = sizeof(RemotePCIHost),
153
+ .class_init = remote_pcihost_class_init,
154
+};
155
+
156
+static void remote_pcihost_register(void)
157
+{
158
+ type_register_static(&remote_pcihost_info);
159
+}
160
+
161
+type_init(remote_pcihost_register)
162
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
163
index XXXXXXX..XXXXXXX 100644
164
--- a/hw/pci-host/Kconfig
165
+++ b/hw/pci-host/Kconfig
166
@@ -XXX,XX +XXX,XX @@ config PCI_POWERNV
167
select PCI_EXPRESS
168
select MSI_NONBROKEN
169
select PCIE_PORT
170
+
171
+config REMOTE_PCIHOST
172
+ bool
173
diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build
174
index XXXXXXX..XXXXXXX 100644
175
--- a/hw/pci-host/meson.build
176
+++ b/hw/pci-host/meson.build
177
@@ -XXX,XX +XXX,XX @@ pci_ss.add(when: 'CONFIG_PCI_EXPRESS_XILINX', if_true: files('xilinx-pcie.c'))
178
pci_ss.add(when: 'CONFIG_PCI_I440FX', if_true: files('i440fx.c'))
179
pci_ss.add(when: 'CONFIG_PCI_SABRE', if_true: files('sabre.c'))
180
pci_ss.add(when: 'CONFIG_XEN_IGD_PASSTHROUGH', if_true: files('xen_igd_pt.c'))
181
+pci_ss.add(when: 'CONFIG_REMOTE_PCIHOST', if_true: files('remote.c'))
182
183
# PPC devices
184
pci_ss.add(when: 'CONFIG_PREP_PCI', if_true: files('prep.c'))
185
diff --git a/hw/remote/Kconfig b/hw/remote/Kconfig
186
index XXXXXXX..XXXXXXX 100644
187
--- a/hw/remote/Kconfig
188
+++ b/hw/remote/Kconfig
189
@@ -XXX,XX +XXX,XX @@
190
config MULTIPROCESS
191
bool
192
- depends on PCI && KVM
193
+ depends on PCI && PCI_EXPRESS && KVM
194
+ select REMOTE_PCIHOST
195
--
196
2.29.2
197
diff view generated by jsdifflib
New patch
1
From: Jagannathan Raman <jag.raman@oracle.com>
1
2
3
x-remote-machine object sets up various subsystems of the remote
4
device process. Instantiate PCI host bridge object and initialize RAM, IO &
5
PCI memory regions.
6
7
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
8
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
9
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-id: c537f38d17f90453ca610c6b70cf3480274e0ba1.1611938319.git.jag.raman@oracle.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
14
MAINTAINERS | 2 ++
15
include/hw/pci-host/remote.h | 1 +
16
include/hw/remote/machine.h | 27 ++++++++++++++
17
hw/remote/machine.c | 70 ++++++++++++++++++++++++++++++++++++
18
hw/meson.build | 1 +
19
hw/remote/meson.build | 5 +++
20
6 files changed, 106 insertions(+)
21
create mode 100644 include/hw/remote/machine.h
22
create mode 100644 hw/remote/machine.c
23
create mode 100644 hw/remote/meson.build
24
25
diff --git a/MAINTAINERS b/MAINTAINERS
26
index XXXXXXX..XXXXXXX 100644
27
--- a/MAINTAINERS
28
+++ b/MAINTAINERS
29
@@ -XXX,XX +XXX,XX @@ F: docs/devel/multi-process.rst
30
F: docs/system/multi-process.rst
31
F: hw/pci-host/remote.c
32
F: include/hw/pci-host/remote.h
33
+F: hw/remote/machine.c
34
+F: include/hw/remote/machine.h
35
36
Build and test automation
37
-------------------------
38
diff --git a/include/hw/pci-host/remote.h b/include/hw/pci-host/remote.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/pci-host/remote.h
41
+++ b/include/hw/pci-host/remote.h
42
@@ -XXX,XX +XXX,XX @@ struct RemotePCIHost {
43
44
MemoryRegion *mr_pci_mem;
45
MemoryRegion *mr_sys_io;
46
+ MemoryRegion *mr_sys_mem;
47
};
48
49
#endif
50
diff --git a/include/hw/remote/machine.h b/include/hw/remote/machine.h
51
new file mode 100644
52
index XXXXXXX..XXXXXXX
53
--- /dev/null
54
+++ b/include/hw/remote/machine.h
55
@@ -XXX,XX +XXX,XX @@
56
+/*
57
+ * Remote machine configuration
58
+ *
59
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
60
+ *
61
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
62
+ * See the COPYING file in the top-level directory.
63
+ *
64
+ */
65
+
66
+#ifndef REMOTE_MACHINE_H
67
+#define REMOTE_MACHINE_H
68
+
69
+#include "qom/object.h"
70
+#include "hw/boards.h"
71
+#include "hw/pci-host/remote.h"
72
+
73
+struct RemoteMachineState {
74
+ MachineState parent_obj;
75
+
76
+ RemotePCIHost *host;
77
+};
78
+
79
+#define TYPE_REMOTE_MACHINE "x-remote-machine"
80
+OBJECT_DECLARE_SIMPLE_TYPE(RemoteMachineState, REMOTE_MACHINE)
81
+
82
+#endif
83
diff --git a/hw/remote/machine.c b/hw/remote/machine.c
84
new file mode 100644
85
index XXXXXXX..XXXXXXX
86
--- /dev/null
87
+++ b/hw/remote/machine.c
88
@@ -XXX,XX +XXX,XX @@
89
+/*
90
+ * Machine for remote device
91
+ *
92
+ * This machine type is used by the remote device process in multi-process
93
+ * QEMU. QEMU device models depend on parent busses, interrupt controllers,
94
+ * memory regions, etc. The remote machine type offers this environment so
95
+ * that QEMU device models can be used as remote devices.
96
+ *
97
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
98
+ *
99
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
100
+ * See the COPYING file in the top-level directory.
101
+ *
102
+ */
103
+
104
+#include "qemu/osdep.h"
105
+#include "qemu-common.h"
106
+
107
+#include "hw/remote/machine.h"
108
+#include "exec/address-spaces.h"
109
+#include "exec/memory.h"
110
+#include "qapi/error.h"
111
+
112
+static void remote_machine_init(MachineState *machine)
113
+{
114
+ MemoryRegion *system_memory, *system_io, *pci_memory;
115
+ RemoteMachineState *s = REMOTE_MACHINE(machine);
116
+ RemotePCIHost *rem_host;
117
+
118
+ system_memory = get_system_memory();
119
+ system_io = get_system_io();
120
+
121
+ pci_memory = g_new(MemoryRegion, 1);
122
+ memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
123
+
124
+ rem_host = REMOTE_PCIHOST(qdev_new(TYPE_REMOTE_PCIHOST));
125
+
126
+ rem_host->mr_pci_mem = pci_memory;
127
+ rem_host->mr_sys_mem = system_memory;
128
+ rem_host->mr_sys_io = system_io;
129
+
130
+ s->host = rem_host;
131
+
132
+ object_property_add_child(OBJECT(s), "remote-pcihost", OBJECT(rem_host));
133
+ memory_region_add_subregion_overlap(system_memory, 0x0, pci_memory, -1);
134
+
135
+ qdev_realize(DEVICE(rem_host), sysbus_get_default(), &error_fatal);
136
+}
137
+
138
+static void remote_machine_class_init(ObjectClass *oc, void *data)
139
+{
140
+ MachineClass *mc = MACHINE_CLASS(oc);
141
+
142
+ mc->init = remote_machine_init;
143
+ mc->desc = "Experimental remote machine";
144
+}
145
+
146
+static const TypeInfo remote_machine = {
147
+ .name = TYPE_REMOTE_MACHINE,
148
+ .parent = TYPE_MACHINE,
149
+ .instance_size = sizeof(RemoteMachineState),
150
+ .class_init = remote_machine_class_init,
151
+};
152
+
153
+static void remote_machine_register_types(void)
154
+{
155
+ type_register_static(&remote_machine);
156
+}
157
+
158
+type_init(remote_machine_register_types);
159
diff --git a/hw/meson.build b/hw/meson.build
160
index XXXXXXX..XXXXXXX 100644
161
--- a/hw/meson.build
162
+++ b/hw/meson.build
163
@@ -XXX,XX +XXX,XX @@ subdir('moxie')
164
subdir('nios2')
165
subdir('openrisc')
166
subdir('ppc')
167
+subdir('remote')
168
subdir('riscv')
169
subdir('rx')
170
subdir('s390x')
171
diff --git a/hw/remote/meson.build b/hw/remote/meson.build
172
new file mode 100644
173
index XXXXXXX..XXXXXXX
174
--- /dev/null
175
+++ b/hw/remote/meson.build
176
@@ -XXX,XX +XXX,XX @@
177
+remote_ss = ss.source_set()
178
+
179
+remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('machine.c'))
180
+
181
+softmmu_ss.add_all(when: 'CONFIG_MULTIPROCESS', if_true: remote_ss)
182
--
183
2.29.2
184
diff view generated by jsdifflib
1
From: Nir Soffer <nirsof@gmail.com>
1
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
2
2
3
Using block_resize we can test allocate_first_block() with file
3
Adds qio_channel_writev_full_all() to transmit both data and FDs.
4
descriptor opened with O_DIRECT, ensuring that it works for any size
4
Refactors existing code to use this helper.
5
larger than 4096 bytes.
6
5
7
Testing smaller sizes is tricky as the result depends on the filesystem
6
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
8
used for testing. For example on NFS any size will work since O_DIRECT
7
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
9
does not require any alignment.
8
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Acked-by: Daniel P. Berrangé <berrange@redhat.com>
11
Message-id: 480fbf1fe4152495d60596c9b665124549b426a5.1611938319.git.jag.raman@oracle.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
14
include/io/channel.h | 25 +++++++++++++++++++++++++
15
io/channel.c | 15 ++++++++++++++-
16
2 files changed, 39 insertions(+), 1 deletion(-)
10
17
11
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
18
diff --git a/include/io/channel.h b/include/io/channel.h
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
19
index XXXXXXX..XXXXXXX 100644
13
Message-id: 20190827010528.8818-3-nsoffer@redhat.com
20
--- a/include/io/channel.h
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
+++ b/include/io/channel.h
15
---
22
@@ -XXX,XX +XXX,XX @@ void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
16
tests/qemu-iotests/175 | 28 ++++++++++++++++++++++++++++
23
IOHandler *io_write,
17
tests/qemu-iotests/175.out | 8 ++++++++
24
void *opaque);
18
2 files changed, 36 insertions(+)
25
19
26
+/**
20
diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175
27
+ * qio_channel_writev_full_all:
21
index XXXXXXX..XXXXXXX 100755
28
+ * @ioc: the channel object
22
--- a/tests/qemu-iotests/175
29
+ * @iov: the array of memory regions to write data from
23
+++ b/tests/qemu-iotests/175
30
+ * @niov: the length of the @iov array
24
@@ -XXX,XX +XXX,XX @@ _filter_blocks()
31
+ * @fds: an array of file handles to send
25
-e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/"
32
+ * @nfds: number of file handles in @fds
26
}
33
+ * @errp: pointer to a NULL-initialized error object
27
34
+ *
28
+# Resize image using block_resize.
35
+ *
29
+# Parameter 1: image path
36
+ * Behaves like qio_channel_writev_full but will attempt
30
+# Parameter 2: new size
37
+ * to send all data passed (file handles and memory regions).
31
+_block_resize()
38
+ * The function will wait for all requested data
39
+ * to be written, yielding from the current coroutine
40
+ * if required.
41
+ *
42
+ * Returns: 0 if all bytes were written, or -1 on error
43
+ */
44
+
45
+int qio_channel_writev_full_all(QIOChannel *ioc,
46
+ const struct iovec *iov,
47
+ size_t niov,
48
+ int *fds, size_t nfds,
49
+ Error **errp);
50
+
51
#endif /* QIO_CHANNEL_H */
52
diff --git a/io/channel.c b/io/channel.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/io/channel.c
55
+++ b/io/channel.c
56
@@ -XXX,XX +XXX,XX @@ int qio_channel_writev_all(QIOChannel *ioc,
57
const struct iovec *iov,
58
size_t niov,
59
Error **errp)
32
+{
60
+{
33
+ local path=$1
61
+ return qio_channel_writev_full_all(ioc, iov, niov, NULL, 0, errp);
34
+ local size=$2
35
+
36
+ $QEMU -qmp stdio -nographic -nodefaults \
37
+ -blockdev file,node-name=file,filename=$path,cache.direct=on \
38
+ <<EOF
39
+{'execute': 'qmp_capabilities'}
40
+{'execute': 'block_resize', 'arguments': {'node-name': 'file', 'size': $size}}
41
+{'execute': 'quit'}
42
+EOF
43
+}
62
+}
44
+
63
+
45
# get standard environment, filters and checks
64
+int qio_channel_writev_full_all(QIOChannel *ioc,
46
. ./common.rc
65
+ const struct iovec *iov,
47
. ./common.filter
66
+ size_t niov,
48
@@ -XXX,XX +XXX,XX @@ _supported_fmt raw
67
+ int *fds, size_t nfds,
49
_supported_proto file
68
+ Error **errp)
50
_supported_os Linux
69
{
51
70
int ret = -1;
52
+_default_cache_mode none
71
struct iovec *local_iov = g_new(struct iovec, niov);
53
+_supported_cache_modes none directsync
72
@@ -XXX,XX +XXX,XX @@ int qio_channel_writev_all(QIOChannel *ioc,
73
74
while (nlocal_iov > 0) {
75
ssize_t len;
76
- len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp);
77
+ len = qio_channel_writev_full(ioc, local_iov, nlocal_iov, fds, nfds,
78
+ errp);
79
if (len == QIO_CHANNEL_ERR_BLOCK) {
80
if (qemu_in_coroutine()) {
81
qio_channel_yield(ioc, G_IO_OUT);
82
@@ -XXX,XX +XXX,XX @@ int qio_channel_writev_all(QIOChannel *ioc,
83
}
84
85
iov_discard_front(&local_iov, &nlocal_iov, len);
54
+
86
+
55
size=$((1 * 1024 * 1024))
87
+ fds = NULL;
56
88
+ nfds = 0;
57
touch "$TEST_DIR/empty"
89
}
58
@@ -XXX,XX +XXX,XX @@ for mode in off full falloc; do
90
59
stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
91
ret = 0;
60
done
61
62
+for new_size in 4096 1048576; do
63
+ echo
64
+ echo "== resize empty image with block_resize =="
65
+ _make_test_img 0 | _filter_imgfmt
66
+ _block_resize $TEST_IMG $new_size >/dev/null
67
+ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $new_size
68
+done
69
+
70
# success, all done
71
echo "*** done"
72
rm -f $seq.full
73
diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out
74
index XXXXXXX..XXXXXXX 100644
75
--- a/tests/qemu-iotests/175.out
76
+++ b/tests/qemu-iotests/175.out
77
@@ -XXX,XX +XXX,XX @@ size=1048576, max allocation
78
== creating image with preallocation falloc ==
79
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc
80
size=1048576, max allocation
81
+
82
+== resize empty image with block_resize ==
83
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0
84
+size=4096, min allocation
85
+
86
+== resize empty image with block_resize ==
87
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0
88
+size=1048576, min allocation
89
*** done
90
--
92
--
91
2.21.0
93
2.29.2
92
94
93
diff view generated by jsdifflib
1
From: Nir Soffer <nirsof@gmail.com>
1
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
2
2
3
Quoting cache mode is not needed, and most tests use unquoted values.
3
Adds qio_channel_readv_full_all_eof() and qio_channel_readv_full_all()
4
Unify all test to use the same style.
4
to read both data and FDs. Refactors existing code to use these helpers.
5
5
6
Message-id: 20190827173432.7656-1-nsoffer@redhat.com
6
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
7
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
7
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
9
Acked-by: Daniel P. Berrangé <berrange@redhat.com>
10
Message-id: b059c4cc0fb741e794d644c144cc21372cad877d.1611938319.git.jag.raman@oracle.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
12
---
10
tests/qemu-iotests/026 | 4 ++--
13
include/io/channel.h | 53 +++++++++++++++++++++++
11
tests/qemu-iotests/039 | 4 ++--
14
io/channel.c | 101 ++++++++++++++++++++++++++++++++++---------
12
tests/qemu-iotests/052 | 2 +-
15
2 files changed, 134 insertions(+), 20 deletions(-)
13
tests/qemu-iotests/091 | 4 ++--
16
14
4 files changed, 7 insertions(+), 7 deletions(-)
17
diff --git a/include/io/channel.h b/include/io/channel.h
15
18
index XXXXXXX..XXXXXXX 100644
16
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
19
--- a/include/io/channel.h
17
index XXXXXXX..XXXXXXX 100755
20
+++ b/include/io/channel.h
18
--- a/tests/qemu-iotests/026
21
@@ -XXX,XX +XXX,XX @@ void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
19
+++ b/tests/qemu-iotests/026
22
IOHandler *io_write,
20
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
23
void *opaque);
21
# Currently only qcow2 supports rebasing
24
22
_supported_fmt qcow2
25
+/**
23
_supported_proto file
26
+ * qio_channel_readv_full_all_eof:
24
-_default_cache_mode "writethrough"
27
+ * @ioc: the channel object
25
-_supported_cache_modes "writethrough" "none"
28
+ * @iov: the array of memory regions to read data to
26
+_default_cache_mode writethrough
29
+ * @niov: the length of the @iov array
27
+_supported_cache_modes writethrough none
30
+ * @fds: an array of file handles to read
28
# The refcount table tests expect a certain minimum width for refcount entries
31
+ * @nfds: number of file handles in @fds
29
# (so that the refcount table actually needs to grow); that minimum is 16 bits,
32
+ * @errp: pointer to a NULL-initialized error object
30
# being the default refcount entry width.
33
+ *
31
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
34
+ *
32
index XXXXXXX..XXXXXXX 100755
35
+ * Performs same function as qio_channel_readv_all_eof.
33
--- a/tests/qemu-iotests/039
36
+ * Additionally, attempts to read file descriptors shared
34
+++ b/tests/qemu-iotests/039
37
+ * over the channel. The function will wait for all
35
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
38
+ * requested data to be read, yielding from the current
36
_supported_fmt qcow2
39
+ * coroutine if required. data refers to both file
37
_supported_proto file
40
+ * descriptors and the iovs.
38
_supported_os Linux
41
+ *
39
-_default_cache_mode "writethrough"
42
+ * Returns: 1 if all bytes were read, 0 if end-of-file
40
-_supported_cache_modes "writethrough"
43
+ * occurs without data, or -1 on error
41
+_default_cache_mode writethrough
44
+ */
42
+_supported_cache_modes writethrough
45
+
43
46
+int qio_channel_readv_full_all_eof(QIOChannel *ioc,
44
size=128M
47
+ const struct iovec *iov,
45
48
+ size_t niov,
46
diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052
49
+ int **fds, size_t *nfds,
47
index XXXXXXX..XXXXXXX 100755
50
+ Error **errp);
48
--- a/tests/qemu-iotests/052
51
+
49
+++ b/tests/qemu-iotests/052
52
+/**
50
@@ -XXX,XX +XXX,XX @@ _supported_fmt generic
53
+ * qio_channel_readv_full_all:
51
_supported_proto file
54
+ * @ioc: the channel object
52
55
+ * @iov: the array of memory regions to read data to
53
# Don't do O_DIRECT on tmpfs
56
+ * @niov: the length of the @iov array
54
-_supported_cache_modes "writeback" "writethrough" "unsafe"
57
+ * @fds: an array of file handles to read
55
+_supported_cache_modes writeback writethrough unsafe
58
+ * @nfds: number of file handles in @fds
56
59
+ * @errp: pointer to a NULL-initialized error object
57
size=128M
60
+ *
58
_make_test_img $size
61
+ *
59
diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091
62
+ * Performs same function as qio_channel_readv_all_eof.
60
index XXXXXXX..XXXXXXX 100755
63
+ * Additionally, attempts to read file descriptors shared
61
--- a/tests/qemu-iotests/091
64
+ * over the channel. The function will wait for all
62
+++ b/tests/qemu-iotests/091
65
+ * requested data to be read, yielding from the current
63
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
66
+ * coroutine if required. data refers to both file
64
_supported_fmt qcow2
67
+ * descriptors and the iovs.
65
_supported_proto file
68
+ *
66
_supported_os Linux
69
+ * Returns: 0 if all bytes were read, or -1 on error
67
-_default_cache_mode "none"
70
+ */
68
-_supported_cache_modes "writethrough" "none" "writeback"
71
+
69
+_default_cache_mode none
72
+int qio_channel_readv_full_all(QIOChannel *ioc,
70
+_supported_cache_modes writethrough none writeback
73
+ const struct iovec *iov,
71
74
+ size_t niov,
72
size=1G
75
+ int **fds, size_t *nfds,
76
+ Error **errp);
77
+
78
/**
79
* qio_channel_writev_full_all:
80
* @ioc: the channel object
81
diff --git a/io/channel.c b/io/channel.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/io/channel.c
84
+++ b/io/channel.c
85
@@ -XXX,XX +XXX,XX @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
86
const struct iovec *iov,
87
size_t niov,
88
Error **errp)
89
+{
90
+ return qio_channel_readv_full_all_eof(ioc, iov, niov, NULL, NULL, errp);
91
+}
92
+
93
+int qio_channel_readv_all(QIOChannel *ioc,
94
+ const struct iovec *iov,
95
+ size_t niov,
96
+ Error **errp)
97
+{
98
+ return qio_channel_readv_full_all(ioc, iov, niov, NULL, NULL, errp);
99
+}
100
+
101
+int qio_channel_readv_full_all_eof(QIOChannel *ioc,
102
+ const struct iovec *iov,
103
+ size_t niov,
104
+ int **fds, size_t *nfds,
105
+ Error **errp)
106
{
107
int ret = -1;
108
struct iovec *local_iov = g_new(struct iovec, niov);
109
struct iovec *local_iov_head = local_iov;
110
unsigned int nlocal_iov = niov;
111
+ int **local_fds = fds;
112
+ size_t *local_nfds = nfds;
113
bool partial = false;
114
115
+ if (nfds) {
116
+ *nfds = 0;
117
+ }
118
+
119
+ if (fds) {
120
+ *fds = NULL;
121
+ }
122
+
123
nlocal_iov = iov_copy(local_iov, nlocal_iov,
124
iov, niov,
125
0, iov_size(iov, niov));
126
127
- while (nlocal_iov > 0) {
128
+ while ((nlocal_iov > 0) || local_fds) {
129
ssize_t len;
130
- len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp);
131
+ len = qio_channel_readv_full(ioc, local_iov, nlocal_iov, local_fds,
132
+ local_nfds, errp);
133
if (len == QIO_CHANNEL_ERR_BLOCK) {
134
if (qemu_in_coroutine()) {
135
qio_channel_yield(ioc, G_IO_IN);
136
@@ -XXX,XX +XXX,XX @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
137
qio_channel_wait(ioc, G_IO_IN);
138
}
139
continue;
140
- } else if (len < 0) {
141
- goto cleanup;
142
- } else if (len == 0) {
143
- if (partial) {
144
- error_setg(errp,
145
- "Unexpected end-of-file before all bytes were read");
146
- } else {
147
+ }
148
+
149
+ if (len == 0) {
150
+ if (local_nfds && *local_nfds) {
151
+ /*
152
+ * Got some FDs, but no data yet. This isn't an EOF
153
+ * scenario (yet), so carry on to try to read data
154
+ * on next loop iteration
155
+ */
156
+ goto next_iter;
157
+ } else if (!partial) {
158
+ /* No fds and no data - EOF before any data read */
159
ret = 0;
160
+ goto cleanup;
161
+ } else {
162
+ len = -1;
163
+ error_setg(errp,
164
+ "Unexpected end-of-file before all data were read");
165
+ /* Fallthrough into len < 0 handling */
166
+ }
167
+ }
168
+
169
+ if (len < 0) {
170
+ /* Close any FDs we previously received */
171
+ if (nfds && fds) {
172
+ size_t i;
173
+ for (i = 0; i < (*nfds); i++) {
174
+ close((*fds)[i]);
175
+ }
176
+ g_free(*fds);
177
+ *fds = NULL;
178
+ *nfds = 0;
179
}
180
goto cleanup;
181
}
182
183
+ if (nlocal_iov) {
184
+ iov_discard_front(&local_iov, &nlocal_iov, len);
185
+ }
186
+
187
+next_iter:
188
partial = true;
189
- iov_discard_front(&local_iov, &nlocal_iov, len);
190
+ local_fds = NULL;
191
+ local_nfds = NULL;
192
}
193
194
ret = 1;
195
@@ -XXX,XX +XXX,XX @@ int qio_channel_readv_all_eof(QIOChannel *ioc,
196
return ret;
197
}
198
199
-int qio_channel_readv_all(QIOChannel *ioc,
200
- const struct iovec *iov,
201
- size_t niov,
202
- Error **errp)
203
+int qio_channel_readv_full_all(QIOChannel *ioc,
204
+ const struct iovec *iov,
205
+ size_t niov,
206
+ int **fds, size_t *nfds,
207
+ Error **errp)
208
{
209
- int ret = qio_channel_readv_all_eof(ioc, iov, niov, errp);
210
+ int ret = qio_channel_readv_full_all_eof(ioc, iov, niov, fds, nfds, errp);
211
212
if (ret == 0) {
213
- ret = -1;
214
- error_setg(errp,
215
- "Unexpected end-of-file before all bytes were read");
216
- } else if (ret == 1) {
217
- ret = 0;
218
+ error_prepend(errp,
219
+ "Unexpected end-of-file before all data were read.");
220
+ return -1;
221
}
222
+ if (ret == 1) {
223
+ return 0;
224
+ }
225
+
226
return ret;
227
}
73
228
74
--
229
--
75
2.21.0
230
2.29.2
76
231
77
diff view generated by jsdifflib
New patch
1
1
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
2
3
Defines MPQemuMsg, which is the message that is sent to the remote
4
process. This message is sent over QIOChannel and is used to
5
command the remote process to perform various tasks.
6
Define transmission functions used by proxy and by remote.
7
8
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
9
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
10
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-id: 56ca8bcf95195b2b195b08f6b9565b6d7410bce5.1611938319.git.jag.raman@oracle.com
13
14
[Replace struct iovec send[2] = {0} with {} to make clang happy as
15
suggested by Peter Maydell <peter.maydell@linaro.org>.
16
--Stefan]
17
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
19
---
20
MAINTAINERS | 2 +
21
meson.build | 1 +
22
hw/remote/trace.h | 1 +
23
include/hw/remote/mpqemu-link.h | 63 ++++++++++
24
include/sysemu/iothread.h | 6 +
25
hw/remote/mpqemu-link.c | 205 ++++++++++++++++++++++++++++++++
26
iothread.c | 6 +
27
hw/remote/meson.build | 1 +
28
hw/remote/trace-events | 4 +
29
9 files changed, 289 insertions(+)
30
create mode 100644 hw/remote/trace.h
31
create mode 100644 include/hw/remote/mpqemu-link.h
32
create mode 100644 hw/remote/mpqemu-link.c
33
create mode 100644 hw/remote/trace-events
34
35
diff --git a/MAINTAINERS b/MAINTAINERS
36
index XXXXXXX..XXXXXXX 100644
37
--- a/MAINTAINERS
38
+++ b/MAINTAINERS
39
@@ -XXX,XX +XXX,XX @@ F: hw/pci-host/remote.c
40
F: include/hw/pci-host/remote.h
41
F: hw/remote/machine.c
42
F: include/hw/remote/machine.h
43
+F: hw/remote/mpqemu-link.c
44
+F: include/hw/remote/mpqemu-link.h
45
46
Build and test automation
47
-------------------------
48
diff --git a/meson.build b/meson.build
49
index XXXXXXX..XXXXXXX 100644
50
--- a/meson.build
51
+++ b/meson.build
52
@@ -XXX,XX +XXX,XX @@ if have_system
53
'net',
54
'softmmu',
55
'ui',
56
+ 'hw/remote',
57
]
58
endif
59
if have_system or have_user
60
diff --git a/hw/remote/trace.h b/hw/remote/trace.h
61
new file mode 100644
62
index XXXXXXX..XXXXXXX
63
--- /dev/null
64
+++ b/hw/remote/trace.h
65
@@ -0,0 +1 @@
66
+#include "trace/trace-hw_remote.h"
67
diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h
68
new file mode 100644
69
index XXXXXXX..XXXXXXX
70
--- /dev/null
71
+++ b/include/hw/remote/mpqemu-link.h
72
@@ -XXX,XX +XXX,XX @@
73
+/*
74
+ * Communication channel between QEMU and remote device process
75
+ *
76
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
77
+ *
78
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
79
+ * See the COPYING file in the top-level directory.
80
+ *
81
+ */
82
+
83
+#ifndef MPQEMU_LINK_H
84
+#define MPQEMU_LINK_H
85
+
86
+#include "qom/object.h"
87
+#include "qemu/thread.h"
88
+#include "io/channel.h"
89
+
90
+#define REMOTE_MAX_FDS 8
91
+
92
+#define MPQEMU_MSG_HDR_SIZE offsetof(MPQemuMsg, data.u64)
93
+
94
+/**
95
+ * MPQemuCmd:
96
+ *
97
+ * MPQemuCmd enum type to specify the command to be executed on the remote
98
+ * device.
99
+ *
100
+ * This uses a private protocol between QEMU and the remote process. vfio-user
101
+ * protocol would supersede this in the future.
102
+ *
103
+ */
104
+typedef enum {
105
+ MPQEMU_CMD_MAX,
106
+} MPQemuCmd;
107
+
108
+/**
109
+ * MPQemuMsg:
110
+ * @cmd: The remote command
111
+ * @size: Size of the data to be shared
112
+ * @data: Structured data
113
+ * @fds: File descriptors to be shared with remote device
114
+ *
115
+ * MPQemuMsg Format of the message sent to the remote device from QEMU.
116
+ *
117
+ */
118
+typedef struct {
119
+ int cmd;
120
+ size_t size;
121
+
122
+ union {
123
+ uint64_t u64;
124
+ } data;
125
+
126
+ int fds[REMOTE_MAX_FDS];
127
+ int num_fds;
128
+} MPQemuMsg;
129
+
130
+bool mpqemu_msg_send(MPQemuMsg *msg, QIOChannel *ioc, Error **errp);
131
+bool mpqemu_msg_recv(MPQemuMsg *msg, QIOChannel *ioc, Error **errp);
132
+
133
+bool mpqemu_msg_valid(MPQemuMsg *msg);
134
+
135
+#endif
136
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
137
index XXXXXXX..XXXXXXX 100644
138
--- a/include/sysemu/iothread.h
139
+++ b/include/sysemu/iothread.h
140
@@ -XXX,XX +XXX,XX @@ IOThread *iothread_create(const char *id, Error **errp);
141
void iothread_stop(IOThread *iothread);
142
void iothread_destroy(IOThread *iothread);
143
144
+/*
145
+ * Returns true if executing withing IOThread context,
146
+ * false otherwise.
147
+ */
148
+bool qemu_in_iothread(void);
149
+
150
#endif /* IOTHREAD_H */
151
diff --git a/hw/remote/mpqemu-link.c b/hw/remote/mpqemu-link.c
152
new file mode 100644
153
index XXXXXXX..XXXXXXX
154
--- /dev/null
155
+++ b/hw/remote/mpqemu-link.c
156
@@ -XXX,XX +XXX,XX @@
157
+/*
158
+ * Communication channel between QEMU and remote device process
159
+ *
160
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
161
+ *
162
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
163
+ * See the COPYING file in the top-level directory.
164
+ *
165
+ */
166
+
167
+#include "qemu/osdep.h"
168
+#include "qemu-common.h"
169
+
170
+#include "qemu/module.h"
171
+#include "hw/remote/mpqemu-link.h"
172
+#include "qapi/error.h"
173
+#include "qemu/iov.h"
174
+#include "qemu/error-report.h"
175
+#include "qemu/main-loop.h"
176
+#include "io/channel.h"
177
+#include "sysemu/iothread.h"
178
+#include "trace.h"
179
+
180
+/*
181
+ * Send message over the ioc QIOChannel.
182
+ * This function is safe to call from:
183
+ * - main loop in co-routine context. Will block the main loop if not in
184
+ * co-routine context;
185
+ * - vCPU thread with no co-routine context and if the channel is not part
186
+ * of the main loop handling;
187
+ * - IOThread within co-routine context, outside of co-routine context
188
+ * will block IOThread;
189
+ * Returns true if no errors were encountered, false otherwise.
190
+ */
191
+bool mpqemu_msg_send(MPQemuMsg *msg, QIOChannel *ioc, Error **errp)
192
+{
193
+ ERRP_GUARD();
194
+ bool iolock = qemu_mutex_iothread_locked();
195
+ bool iothread = qemu_in_iothread();
196
+ struct iovec send[2] = {};
197
+ int *fds = NULL;
198
+ size_t nfds = 0;
199
+ bool ret = false;
200
+
201
+ send[0].iov_base = msg;
202
+ send[0].iov_len = MPQEMU_MSG_HDR_SIZE;
203
+
204
+ send[1].iov_base = (void *)&msg->data;
205
+ send[1].iov_len = msg->size;
206
+
207
+ if (msg->num_fds) {
208
+ nfds = msg->num_fds;
209
+ fds = msg->fds;
210
+ }
211
+
212
+ /*
213
+ * Dont use in IOThread out of co-routine context as
214
+ * it will block IOThread.
215
+ */
216
+ assert(qemu_in_coroutine() || !iothread);
217
+
218
+ /*
219
+ * Skip unlocking/locking iothread lock when the IOThread is running
220
+ * in co-routine context. Co-routine context is asserted above
221
+ * for IOThread case.
222
+ * Also skip lock handling while in a co-routine in the main context.
223
+ */
224
+ if (iolock && !iothread && !qemu_in_coroutine()) {
225
+ qemu_mutex_unlock_iothread();
226
+ }
227
+
228
+ if (!qio_channel_writev_full_all(ioc, send, G_N_ELEMENTS(send),
229
+ fds, nfds, errp)) {
230
+ ret = true;
231
+ } else {
232
+ trace_mpqemu_send_io_error(msg->cmd, msg->size, nfds);
233
+ }
234
+
235
+ if (iolock && !iothread && !qemu_in_coroutine()) {
236
+ /* See above comment why skip locking here. */
237
+ qemu_mutex_lock_iothread();
238
+ }
239
+
240
+ return ret;
241
+}
242
+
243
+/*
244
+ * Read message from the ioc QIOChannel.
245
+ * This function is safe to call from:
246
+ * - From main loop in co-routine context. Will block the main loop if not in
247
+ * co-routine context;
248
+ * - From vCPU thread with no co-routine context and if the channel is not part
249
+ * of the main loop handling;
250
+ * - From IOThread within co-routine context, outside of co-routine context
251
+ * will block IOThread;
252
+ */
253
+static ssize_t mpqemu_read(QIOChannel *ioc, void *buf, size_t len, int **fds,
254
+ size_t *nfds, Error **errp)
255
+{
256
+ ERRP_GUARD();
257
+ struct iovec iov = { .iov_base = buf, .iov_len = len };
258
+ bool iolock = qemu_mutex_iothread_locked();
259
+ bool iothread = qemu_in_iothread();
260
+ int ret = -1;
261
+
262
+ /*
263
+ * Dont use in IOThread out of co-routine context as
264
+ * it will block IOThread.
265
+ */
266
+ assert(qemu_in_coroutine() || !iothread);
267
+
268
+ if (iolock && !iothread && !qemu_in_coroutine()) {
269
+ qemu_mutex_unlock_iothread();
270
+ }
271
+
272
+ ret = qio_channel_readv_full_all_eof(ioc, &iov, 1, fds, nfds, errp);
273
+
274
+ if (iolock && !iothread && !qemu_in_coroutine()) {
275
+ qemu_mutex_lock_iothread();
276
+ }
277
+
278
+ return (ret <= 0) ? ret : iov.iov_len;
279
+}
280
+
281
+bool mpqemu_msg_recv(MPQemuMsg *msg, QIOChannel *ioc, Error **errp)
282
+{
283
+ ERRP_GUARD();
284
+ g_autofree int *fds = NULL;
285
+ size_t nfds = 0;
286
+ ssize_t len;
287
+ bool ret = false;
288
+
289
+ len = mpqemu_read(ioc, msg, MPQEMU_MSG_HDR_SIZE, &fds, &nfds, errp);
290
+ if (len <= 0) {
291
+ goto fail;
292
+ } else if (len != MPQEMU_MSG_HDR_SIZE) {
293
+ error_setg(errp, "Message header corrupted");
294
+ goto fail;
295
+ }
296
+
297
+ if (msg->size > sizeof(msg->data)) {
298
+ error_setg(errp, "Invalid size for message");
299
+ goto fail;
300
+ }
301
+
302
+ if (!msg->size) {
303
+ goto copy_fds;
304
+ }
305
+
306
+ len = mpqemu_read(ioc, &msg->data, msg->size, NULL, NULL, errp);
307
+ if (len <= 0) {
308
+ goto fail;
309
+ }
310
+ if (len != msg->size) {
311
+ error_setg(errp, "Unable to read full message");
312
+ goto fail;
313
+ }
314
+
315
+copy_fds:
316
+ msg->num_fds = nfds;
317
+ if (nfds > G_N_ELEMENTS(msg->fds)) {
318
+ error_setg(errp,
319
+ "Overflow error: received %zu fds, more than max of %d fds",
320
+ nfds, REMOTE_MAX_FDS);
321
+ goto fail;
322
+ }
323
+ if (nfds) {
324
+ memcpy(msg->fds, fds, nfds * sizeof(int));
325
+ }
326
+
327
+ ret = true;
328
+
329
+fail:
330
+ if (*errp) {
331
+ trace_mpqemu_recv_io_error(msg->cmd, msg->size, nfds);
332
+ }
333
+ while (*errp && nfds) {
334
+ close(fds[nfds - 1]);
335
+ nfds--;
336
+ }
337
+
338
+ return ret;
339
+}
340
+
341
+bool mpqemu_msg_valid(MPQemuMsg *msg)
342
+{
343
+ if (msg->cmd >= MPQEMU_CMD_MAX && msg->cmd < 0) {
344
+ return false;
345
+ }
346
+
347
+ /* Verify FDs. */
348
+ if (msg->num_fds >= REMOTE_MAX_FDS) {
349
+ return false;
350
+ }
351
+
352
+ if (msg->num_fds > 0) {
353
+ for (int i = 0; i < msg->num_fds; i++) {
354
+ if (fcntl(msg->fds[i], F_GETFL) == -1) {
355
+ return false;
356
+ }
357
+ }
358
+ }
359
+
360
+ return true;
361
+}
362
diff --git a/iothread.c b/iothread.c
363
index XXXXXXX..XXXXXXX 100644
364
--- a/iothread.c
365
+++ b/iothread.c
366
@@ -XXX,XX +XXX,XX @@ IOThread *iothread_by_id(const char *id)
367
{
368
return IOTHREAD(object_resolve_path_type(id, TYPE_IOTHREAD, NULL));
369
}
370
+
371
+bool qemu_in_iothread(void)
372
+{
373
+ return qemu_get_current_aio_context() == qemu_get_aio_context() ?
374
+ false : true;
375
+}
376
diff --git a/hw/remote/meson.build b/hw/remote/meson.build
377
index XXXXXXX..XXXXXXX 100644
378
--- a/hw/remote/meson.build
379
+++ b/hw/remote/meson.build
380
@@ -XXX,XX +XXX,XX @@
381
remote_ss = ss.source_set()
382
383
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('machine.c'))
384
+remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('mpqemu-link.c'))
385
386
softmmu_ss.add_all(when: 'CONFIG_MULTIPROCESS', if_true: remote_ss)
387
diff --git a/hw/remote/trace-events b/hw/remote/trace-events
388
new file mode 100644
389
index XXXXXXX..XXXXXXX
390
--- /dev/null
391
+++ b/hw/remote/trace-events
392
@@ -XXX,XX +XXX,XX @@
393
+# multi-process trace events
394
+
395
+mpqemu_send_io_error(int cmd, int size, int nfds) "send command %d size %d, %d file descriptors to remote process"
396
+mpqemu_recv_io_error(int cmd, int size, int nfds) "failed to receive %d size %d, %d file descriptors to remote process"
397
--
398
2.29.2
399
diff view generated by jsdifflib
1
Compressed writes generally have to write full clusters, not just in
1
From: Jagannathan Raman <jag.raman@oracle.com>
2
theory but also in practice when it comes to vmdk's streamOptimized
3
subformat. It currently is just silently broken for writes with
4
non-zero in-cluster offsets:
5
2
6
$ qemu-img create -f vmdk -o subformat=streamOptimized foo.vmdk 1M
3
Initializes the message handler function in the remote process. It is
7
$ qemu-io -c 'write 4k 4k' -c 'read 4k 4k' foo.vmdk
4
called whenever there's an event pending on QIOChannel that registers
8
wrote 4096/4096 bytes at offset 4096
5
this function.
9
4 KiB, 1 ops; 00.01 sec (443.724 KiB/sec and 110.9309 ops/sec)
10
read failed: Invalid argument
11
6
12
(The technical reason is that vmdk_write_extent() just writes the
7
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
13
incomplete compressed data actually to offset 4k. When reading the
8
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
14
data, vmdk_read_extent() looks at offset 0 and finds the compressed data
9
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
15
size to be 0, because that is what it reads from there. This yields an
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
error.)
11
Message-id: 99d38d8b93753a6409ac2340e858858cda59ab1b.1611938319.git.jag.raman@oracle.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
14
MAINTAINERS | 1 +
15
include/hw/remote/machine.h | 9 ++++++
16
hw/remote/message.c | 57 +++++++++++++++++++++++++++++++++++++
17
hw/remote/meson.build | 1 +
18
4 files changed, 68 insertions(+)
19
create mode 100644 hw/remote/message.c
17
20
18
For incomplete writes with zero in-cluster offsets, the error path when
21
diff --git a/MAINTAINERS b/MAINTAINERS
19
reading the rest of the cluster is a bit different, but the result is
20
the same:
21
22
$ qemu-img create -f vmdk -o subformat=streamOptimized foo.vmdk 1M
23
$ qemu-io -c 'write 0k 4k' -c 'read 4k 4k' foo.vmdk
24
wrote 4096/4096 bytes at offset 0
25
4 KiB, 1 ops; 00.01 sec (362.641 KiB/sec and 90.6603 ops/sec)
26
read failed: Invalid argument
27
28
(Here, vmdk_read_extent() finds the data and then sees that the
29
uncompressed data is short.)
30
31
It is better to reject invalid writes than to make the user believe they
32
might have succeeded and then fail when trying to read it back.
33
34
Signed-off-by: Max Reitz <mreitz@redhat.com>
35
Reviewed-by: John Snow <jsnow@redhat.com>
36
Message-id: 20190815153638.4600-5-mreitz@redhat.com
37
Reviewed-by: John Snow <jsnow@redhat.com>
38
Signed-off-by: Max Reitz <mreitz@redhat.com>
39
---
40
block/vmdk.c | 10 ++++++++++
41
1 file changed, 10 insertions(+)
42
43
diff --git a/block/vmdk.c b/block/vmdk.c
44
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
45
--- a/block/vmdk.c
23
--- a/MAINTAINERS
46
+++ b/block/vmdk.c
24
+++ b/MAINTAINERS
47
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
25
@@ -XXX,XX +XXX,XX @@ F: hw/remote/machine.c
48
if (extent->compressed) {
26
F: include/hw/remote/machine.h
49
void *compressed_data;
27
F: hw/remote/mpqemu-link.c
50
28
F: include/hw/remote/mpqemu-link.h
51
+ /* Only whole clusters */
29
+F: hw/remote/message.c
52
+ if (offset_in_cluster ||
30
53
+ n_bytes > (extent->cluster_sectors * SECTOR_SIZE) ||
31
Build and test automation
54
+ (n_bytes < (extent->cluster_sectors * SECTOR_SIZE) &&
32
-------------------------
55
+ offset + n_bytes != extent->end_sector * SECTOR_SIZE))
33
diff --git a/include/hw/remote/machine.h b/include/hw/remote/machine.h
56
+ {
34
index XXXXXXX..XXXXXXX 100644
57
+ ret = -EINVAL;
35
--- a/include/hw/remote/machine.h
58
+ goto out;
36
+++ b/include/hw/remote/machine.h
37
@@ -XXX,XX +XXX,XX @@
38
#include "qom/object.h"
39
#include "hw/boards.h"
40
#include "hw/pci-host/remote.h"
41
+#include "io/channel.h"
42
43
struct RemoteMachineState {
44
MachineState parent_obj;
45
@@ -XXX,XX +XXX,XX @@ struct RemoteMachineState {
46
RemotePCIHost *host;
47
};
48
49
+/* Used to pass to co-routine device and ioc. */
50
+typedef struct RemoteCommDev {
51
+ PCIDevice *dev;
52
+ QIOChannel *ioc;
53
+} RemoteCommDev;
54
+
55
#define TYPE_REMOTE_MACHINE "x-remote-machine"
56
OBJECT_DECLARE_SIMPLE_TYPE(RemoteMachineState, REMOTE_MACHINE)
57
58
+void coroutine_fn mpqemu_remote_msg_loop_co(void *data);
59
+
60
#endif
61
diff --git a/hw/remote/message.c b/hw/remote/message.c
62
new file mode 100644
63
index XXXXXXX..XXXXXXX
64
--- /dev/null
65
+++ b/hw/remote/message.c
66
@@ -XXX,XX +XXX,XX @@
67
+/*
68
+ * Copyright © 2020, 2021 Oracle and/or its affiliates.
69
+ *
70
+ * This work is licensed under the terms of the GNU GPL-v2, version 2 or later.
71
+ *
72
+ * See the COPYING file in the top-level directory.
73
+ *
74
+ */
75
+
76
+#include "qemu/osdep.h"
77
+#include "qemu-common.h"
78
+
79
+#include "hw/remote/machine.h"
80
+#include "io/channel.h"
81
+#include "hw/remote/mpqemu-link.h"
82
+#include "qapi/error.h"
83
+#include "sysemu/runstate.h"
84
+
85
+void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
86
+{
87
+ g_autofree RemoteCommDev *com = (RemoteCommDev *)data;
88
+ PCIDevice *pci_dev = NULL;
89
+ Error *local_err = NULL;
90
+
91
+ assert(com->ioc);
92
+
93
+ pci_dev = com->dev;
94
+ for (; !local_err;) {
95
+ MPQemuMsg msg = {0};
96
+
97
+ if (!mpqemu_msg_recv(&msg, com->ioc, &local_err)) {
98
+ break;
59
+ }
99
+ }
60
+
100
+
61
if (!extent->has_marker) {
101
+ if (!mpqemu_msg_valid(&msg)) {
62
ret = -EINVAL;
102
+ error_setg(&local_err, "Received invalid message from proxy"
63
goto out;
103
+ "in remote process pid="FMT_pid"",
104
+ getpid());
105
+ break;
106
+ }
107
+
108
+ switch (msg.cmd) {
109
+ default:
110
+ error_setg(&local_err,
111
+ "Unknown command (%d) received for device %s"
112
+ " (pid="FMT_pid")",
113
+ msg.cmd, DEVICE(pci_dev)->id, getpid());
114
+ }
115
+ }
116
+
117
+ if (local_err) {
118
+ error_report_err(local_err);
119
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_ERROR);
120
+ } else {
121
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
122
+ }
123
+}
124
diff --git a/hw/remote/meson.build b/hw/remote/meson.build
125
index XXXXXXX..XXXXXXX 100644
126
--- a/hw/remote/meson.build
127
+++ b/hw/remote/meson.build
128
@@ -XXX,XX +XXX,XX @@ remote_ss = ss.source_set()
129
130
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('machine.c'))
131
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('mpqemu-link.c'))
132
+remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('message.c'))
133
134
softmmu_ss.add_all(when: 'CONFIG_MULTIPROCESS', if_true: remote_ss)
64
--
135
--
65
2.21.0
136
2.29.2
66
137
67
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Jagannathan Raman <jag.raman@oracle.com>
2
2
3
The sanitizers (especially the address sanitizer from Clang) are
3
Associate the file descriptor for a PCIDevice in remote process with
4
sometimes printing out warnings or false positives - this spoils
4
DeviceState object.
5
the output of the iotests, causing some of the tests to fail.
5
6
Thus let's skip the automatic iotests during "make check" when the
6
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
7
user configured QEMU with --enable-sanitizers.
7
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
8
8
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
9
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 20190823084203.29734-1-thuth@redhat.com
10
Message-id: f405a2ed5d7518b87bea7c59cfdf334d67e5ee51.1611938319.git.jag.raman@oracle.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
12
---
13
tests/check-block.sh | 5 +++++
13
MAINTAINERS | 1 +
14
1 file changed, 5 insertions(+)
14
hw/remote/remote-obj.c | 203 +++++++++++++++++++++++++++++++++++++++++
15
15
hw/remote/meson.build | 1 +
16
diff --git a/tests/check-block.sh b/tests/check-block.sh
16
3 files changed, 205 insertions(+)
17
index XXXXXXX..XXXXXXX 100755
17
create mode 100644 hw/remote/remote-obj.c
18
--- a/tests/check-block.sh
18
19
+++ b/tests/check-block.sh
19
diff --git a/MAINTAINERS b/MAINTAINERS
20
@@ -XXX,XX +XXX,XX @@ if grep -q "TARGET_GPROF=y" *-softmmu/config-target.mak 2>/dev/null ; then
20
index XXXXXXX..XXXXXXX 100644
21
exit 0
21
--- a/MAINTAINERS
22
fi
22
+++ b/MAINTAINERS
23
23
@@ -XXX,XX +XXX,XX @@ F: include/hw/remote/machine.h
24
+if grep -q "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null ; then
24
F: hw/remote/mpqemu-link.c
25
+ echo "Sanitizers are enabled ==> Not running the qemu-iotests."
25
F: include/hw/remote/mpqemu-link.h
26
+ exit 0
26
F: hw/remote/message.c
27
+fi
27
+F: hw/remote/remote-obj.c
28
+
28
29
if [ -z "$(find . -name 'qemu-system-*' -print)" ]; then
29
Build and test automation
30
echo "No qemu-system binary available ==> Not running the qemu-iotests."
30
-------------------------
31
exit 0
31
diff --git a/hw/remote/remote-obj.c b/hw/remote/remote-obj.c
32
new file mode 100644
33
index XXXXXXX..XXXXXXX
34
--- /dev/null
35
+++ b/hw/remote/remote-obj.c
36
@@ -XXX,XX +XXX,XX @@
37
+/*
38
+ * Copyright © 2020, 2021 Oracle and/or its affiliates.
39
+ *
40
+ * This work is licensed under the terms of the GNU GPL-v2, version 2 or later.
41
+ *
42
+ * See the COPYING file in the top-level directory.
43
+ *
44
+ */
45
+
46
+#include "qemu/osdep.h"
47
+#include "qemu-common.h"
48
+
49
+#include "qemu/error-report.h"
50
+#include "qemu/notify.h"
51
+#include "qom/object_interfaces.h"
52
+#include "hw/qdev-core.h"
53
+#include "io/channel.h"
54
+#include "hw/qdev-core.h"
55
+#include "hw/remote/machine.h"
56
+#include "io/channel-util.h"
57
+#include "qapi/error.h"
58
+#include "sysemu/sysemu.h"
59
+#include "hw/pci/pci.h"
60
+#include "qemu/sockets.h"
61
+#include "monitor/monitor.h"
62
+
63
+#define TYPE_REMOTE_OBJECT "x-remote-object"
64
+OBJECT_DECLARE_TYPE(RemoteObject, RemoteObjectClass, REMOTE_OBJECT)
65
+
66
+struct RemoteObjectClass {
67
+ ObjectClass parent_class;
68
+
69
+ unsigned int nr_devs;
70
+ unsigned int max_devs;
71
+};
72
+
73
+struct RemoteObject {
74
+ /* private */
75
+ Object parent;
76
+
77
+ Notifier machine_done;
78
+
79
+ int32_t fd;
80
+ char *devid;
81
+
82
+ QIOChannel *ioc;
83
+
84
+ DeviceState *dev;
85
+ DeviceListener listener;
86
+};
87
+
88
+static void remote_object_set_fd(Object *obj, const char *str, Error **errp)
89
+{
90
+ RemoteObject *o = REMOTE_OBJECT(obj);
91
+ int fd = -1;
92
+
93
+ fd = monitor_fd_param(monitor_cur(), str, errp);
94
+ if (fd == -1) {
95
+ error_prepend(errp, "Could not parse remote object fd %s:", str);
96
+ return;
97
+ }
98
+
99
+ if (!fd_is_socket(fd)) {
100
+ error_setg(errp, "File descriptor '%s' is not a socket", str);
101
+ close(fd);
102
+ return;
103
+ }
104
+
105
+ o->fd = fd;
106
+}
107
+
108
+static void remote_object_set_devid(Object *obj, const char *str, Error **errp)
109
+{
110
+ RemoteObject *o = REMOTE_OBJECT(obj);
111
+
112
+ g_free(o->devid);
113
+
114
+ o->devid = g_strdup(str);
115
+}
116
+
117
+static void remote_object_unrealize_listener(DeviceListener *listener,
118
+ DeviceState *dev)
119
+{
120
+ RemoteObject *o = container_of(listener, RemoteObject, listener);
121
+
122
+ if (o->dev == dev) {
123
+ object_unref(OBJECT(o));
124
+ }
125
+}
126
+
127
+static void remote_object_machine_done(Notifier *notifier, void *data)
128
+{
129
+ RemoteObject *o = container_of(notifier, RemoteObject, machine_done);
130
+ DeviceState *dev = NULL;
131
+ QIOChannel *ioc = NULL;
132
+ Coroutine *co = NULL;
133
+ RemoteCommDev *comdev = NULL;
134
+ Error *err = NULL;
135
+
136
+ dev = qdev_find_recursive(sysbus_get_default(), o->devid);
137
+ if (!dev || !object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
138
+ error_report("%s is not a PCI device", o->devid);
139
+ return;
140
+ }
141
+
142
+ ioc = qio_channel_new_fd(o->fd, &err);
143
+ if (!ioc) {
144
+ error_report_err(err);
145
+ return;
146
+ }
147
+ qio_channel_set_blocking(ioc, false, NULL);
148
+
149
+ o->dev = dev;
150
+
151
+ o->listener.unrealize = remote_object_unrealize_listener;
152
+ device_listener_register(&o->listener);
153
+
154
+ /* co-routine should free this. */
155
+ comdev = g_new0(RemoteCommDev, 1);
156
+ *comdev = (RemoteCommDev) {
157
+ .ioc = ioc,
158
+ .dev = PCI_DEVICE(dev),
159
+ };
160
+
161
+ co = qemu_coroutine_create(mpqemu_remote_msg_loop_co, comdev);
162
+ qemu_coroutine_enter(co);
163
+}
164
+
165
+static void remote_object_init(Object *obj)
166
+{
167
+ RemoteObjectClass *k = REMOTE_OBJECT_GET_CLASS(obj);
168
+ RemoteObject *o = REMOTE_OBJECT(obj);
169
+
170
+ if (k->nr_devs >= k->max_devs) {
171
+ error_report("Reached maximum number of devices: %u", k->max_devs);
172
+ return;
173
+ }
174
+
175
+ o->ioc = NULL;
176
+ o->fd = -1;
177
+ o->devid = NULL;
178
+
179
+ k->nr_devs++;
180
+
181
+ o->machine_done.notify = remote_object_machine_done;
182
+ qemu_add_machine_init_done_notifier(&o->machine_done);
183
+}
184
+
185
+static void remote_object_finalize(Object *obj)
186
+{
187
+ RemoteObjectClass *k = REMOTE_OBJECT_GET_CLASS(obj);
188
+ RemoteObject *o = REMOTE_OBJECT(obj);
189
+
190
+ device_listener_unregister(&o->listener);
191
+
192
+ if (o->ioc) {
193
+ qio_channel_shutdown(o->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
194
+ qio_channel_close(o->ioc, NULL);
195
+ }
196
+
197
+ object_unref(OBJECT(o->ioc));
198
+
199
+ k->nr_devs--;
200
+ g_free(o->devid);
201
+}
202
+
203
+static void remote_object_class_init(ObjectClass *klass, void *data)
204
+{
205
+ RemoteObjectClass *k = REMOTE_OBJECT_CLASS(klass);
206
+
207
+ /*
208
+ * Limit number of supported devices to 1. This is done to avoid devices
209
+ * from one VM accessing the RAM of another VM. This is done until we
210
+ * start using separate address spaces for individual devices.
211
+ */
212
+ k->max_devs = 1;
213
+ k->nr_devs = 0;
214
+
215
+ object_class_property_add_str(klass, "fd", NULL, remote_object_set_fd);
216
+ object_class_property_add_str(klass, "devid", NULL,
217
+ remote_object_set_devid);
218
+}
219
+
220
+static const TypeInfo remote_object_info = {
221
+ .name = TYPE_REMOTE_OBJECT,
222
+ .parent = TYPE_OBJECT,
223
+ .instance_size = sizeof(RemoteObject),
224
+ .instance_init = remote_object_init,
225
+ .instance_finalize = remote_object_finalize,
226
+ .class_size = sizeof(RemoteObjectClass),
227
+ .class_init = remote_object_class_init,
228
+ .interfaces = (InterfaceInfo[]) {
229
+ { TYPE_USER_CREATABLE },
230
+ { }
231
+ }
232
+};
233
+
234
+static void register_types(void)
235
+{
236
+ type_register_static(&remote_object_info);
237
+}
238
+
239
+type_init(register_types);
240
diff --git a/hw/remote/meson.build b/hw/remote/meson.build
241
index XXXXXXX..XXXXXXX 100644
242
--- a/hw/remote/meson.build
243
+++ b/hw/remote/meson.build
244
@@ -XXX,XX +XXX,XX @@ remote_ss = ss.source_set()
245
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('machine.c'))
246
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('mpqemu-link.c'))
247
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('message.c'))
248
+remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('remote-obj.c'))
249
250
softmmu_ss.add_all(when: 'CONFIG_MULTIPROCESS', if_true: remote_ss)
32
--
251
--
33
2.21.0
252
2.29.2
34
253
35
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Jagannathan Raman <jag.raman@oracle.com>
2
2
3
It's wrong to OR shared permissions. It may lead to crash on further
3
SyncSysMemMsg message format is defined. It is used to send
4
permission updates.
4
file descriptors of the RAM regions to remote device.
5
Also, no needs to consider previously calculated permissions, as at
5
RAM on the remote device is configured with a set of file descriptors.
6
this point we already bind all new parents and bdrv_get_cumulative_perm
6
Old RAM regions are deleted and new regions, each with an fd, is
7
result is enough. So fix the bug by just set permissions by
7
added to the RAM.
8
bdrv_get_cumulative_perm result.
8
9
9
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
10
Bug was introduced in long ago 234ac1a9025, in 2.9.
10
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
11
11
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Message-id: 20190824100740.61635-1-vsementsov@virtuozzo.com
13
Message-id: 7d2d1831d812e85f681e7a8ab99e032cf4704689.1611938319.git.jag.raman@oracle.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
---
15
---
16
block.c | 5 ++---
16
MAINTAINERS | 2 +
17
1 file changed, 2 insertions(+), 3 deletions(-)
17
include/hw/remote/memory.h | 19 ++++++++++
18
18
include/hw/remote/mpqemu-link.h | 10 +++++
19
diff --git a/block.c b/block.c
19
hw/remote/memory.c | 65 +++++++++++++++++++++++++++++++++
20
index XXXXXXX..XXXXXXX 100644
20
hw/remote/mpqemu-link.c | 11 ++++++
21
--- a/block.c
21
hw/remote/meson.build | 2 +
22
+++ b/block.c
22
6 files changed, 109 insertions(+)
23
@@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
23
create mode 100644 include/hw/remote/memory.h
24
{
24
create mode 100644 hw/remote/memory.c
25
BdrvChild *c, *next;
25
26
GSList *list = NULL, *p;
26
diff --git a/MAINTAINERS b/MAINTAINERS
27
- uint64_t old_perm, old_shared;
27
index XXXXXXX..XXXXXXX 100644
28
uint64_t perm = 0, shared = BLK_PERM_ALL;
28
--- a/MAINTAINERS
29
int ret;
29
+++ b/MAINTAINERS
30
30
@@ -XXX,XX +XXX,XX @@ F: hw/remote/mpqemu-link.c
31
@@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
31
F: include/hw/remote/mpqemu-link.h
32
bdrv_unref(from);
32
F: hw/remote/message.c
33
F: hw/remote/remote-obj.c
34
+F: include/hw/remote/memory.h
35
+F: hw/remote/memory.c
36
37
Build and test automation
38
-------------------------
39
diff --git a/include/hw/remote/memory.h b/include/hw/remote/memory.h
40
new file mode 100644
41
index XXXXXXX..XXXXXXX
42
--- /dev/null
43
+++ b/include/hw/remote/memory.h
44
@@ -XXX,XX +XXX,XX @@
45
+/*
46
+ * Memory manager for remote device
47
+ *
48
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
49
+ *
50
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
51
+ * See the COPYING file in the top-level directory.
52
+ *
53
+ */
54
+
55
+#ifndef REMOTE_MEMORY_H
56
+#define REMOTE_MEMORY_H
57
+
58
+#include "exec/hwaddr.h"
59
+#include "hw/remote/mpqemu-link.h"
60
+
61
+void remote_sysmem_reconfig(MPQemuMsg *msg, Error **errp);
62
+
63
+#endif
64
diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/include/hw/remote/mpqemu-link.h
67
+++ b/include/hw/remote/mpqemu-link.h
68
@@ -XXX,XX +XXX,XX @@
69
#include "qom/object.h"
70
#include "qemu/thread.h"
71
#include "io/channel.h"
72
+#include "exec/hwaddr.h"
73
74
#define REMOTE_MAX_FDS 8
75
76
@@ -XXX,XX +XXX,XX @@
77
*
78
*/
79
typedef enum {
80
+ MPQEMU_CMD_SYNC_SYSMEM,
81
MPQEMU_CMD_MAX,
82
} MPQemuCmd;
83
84
+typedef struct {
85
+ hwaddr gpas[REMOTE_MAX_FDS];
86
+ uint64_t sizes[REMOTE_MAX_FDS];
87
+ off_t offsets[REMOTE_MAX_FDS];
88
+} SyncSysmemMsg;
89
+
90
/**
91
* MPQemuMsg:
92
* @cmd: The remote command
93
@@ -XXX,XX +XXX,XX @@ typedef enum {
94
* MPQemuMsg Format of the message sent to the remote device from QEMU.
95
*
96
*/
97
+
98
typedef struct {
99
int cmd;
100
size_t size;
101
102
union {
103
uint64_t u64;
104
+ SyncSysmemMsg sync_sysmem;
105
} data;
106
107
int fds[REMOTE_MAX_FDS];
108
diff --git a/hw/remote/memory.c b/hw/remote/memory.c
109
new file mode 100644
110
index XXXXXXX..XXXXXXX
111
--- /dev/null
112
+++ b/hw/remote/memory.c
113
@@ -XXX,XX +XXX,XX @@
114
+/*
115
+ * Memory manager for remote device
116
+ *
117
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
118
+ *
119
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
120
+ * See the COPYING file in the top-level directory.
121
+ *
122
+ */
123
+
124
+#include "qemu/osdep.h"
125
+#include "qemu-common.h"
126
+
127
+#include "hw/remote/memory.h"
128
+#include "exec/address-spaces.h"
129
+#include "exec/ram_addr.h"
130
+#include "qapi/error.h"
131
+
132
+static void remote_sysmem_reset(void)
133
+{
134
+ MemoryRegion *sysmem, *subregion, *next;
135
+
136
+ sysmem = get_system_memory();
137
+
138
+ QTAILQ_FOREACH_SAFE(subregion, &sysmem->subregions, subregions_link, next) {
139
+ if (subregion->ram) {
140
+ memory_region_del_subregion(sysmem, subregion);
141
+ object_unparent(OBJECT(subregion));
142
+ }
143
+ }
144
+}
145
+
146
+void remote_sysmem_reconfig(MPQemuMsg *msg, Error **errp)
147
+{
148
+ ERRP_GUARD();
149
+ SyncSysmemMsg *sysmem_info = &msg->data.sync_sysmem;
150
+ MemoryRegion *sysmem, *subregion;
151
+ static unsigned int suffix;
152
+ int region;
153
+
154
+ sysmem = get_system_memory();
155
+
156
+ remote_sysmem_reset();
157
+
158
+ for (region = 0; region < msg->num_fds; region++) {
159
+ g_autofree char *name;
160
+ subregion = g_new(MemoryRegion, 1);
161
+ name = g_strdup_printf("remote-mem-%u", suffix++);
162
+ memory_region_init_ram_from_fd(subregion, NULL,
163
+ name, sysmem_info->sizes[region],
164
+ true, msg->fds[region],
165
+ sysmem_info->offsets[region],
166
+ errp);
167
+
168
+ if (*errp) {
169
+ g_free(subregion);
170
+ remote_sysmem_reset();
171
+ return;
172
+ }
173
+
174
+ memory_region_add_subregion(sysmem, sysmem_info->gpas[region],
175
+ subregion);
176
+
177
+ }
178
+}
179
diff --git a/hw/remote/mpqemu-link.c b/hw/remote/mpqemu-link.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/remote/mpqemu-link.c
182
+++ b/hw/remote/mpqemu-link.c
183
@@ -XXX,XX +XXX,XX @@ bool mpqemu_msg_valid(MPQemuMsg *msg)
184
}
33
}
185
}
34
186
35
- bdrv_get_cumulative_perm(to, &old_perm, &old_shared);
187
+ /* Verify message specific fields. */
36
- bdrv_set_perm(to, old_perm | perm, old_shared | shared);
188
+ switch (msg->cmd) {
37
+ bdrv_get_cumulative_perm(to, &perm, &shared);
189
+ case MPQEMU_CMD_SYNC_SYSMEM:
38
+ bdrv_set_perm(to, perm, shared);
190
+ if (msg->num_fds == 0 || msg->size != sizeof(SyncSysmemMsg)) {
39
191
+ return false;
40
out:
192
+ }
41
g_slist_free(list);
193
+ break;
194
+ default:
195
+ break;
196
+ }
197
+
198
return true;
199
}
200
diff --git a/hw/remote/meson.build b/hw/remote/meson.build
201
index XXXXXXX..XXXXXXX 100644
202
--- a/hw/remote/meson.build
203
+++ b/hw/remote/meson.build
204
@@ -XXX,XX +XXX,XX @@ remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('mpqemu-link.c'))
205
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('message.c'))
206
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('remote-obj.c'))
207
208
+specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('memory.c'))
209
+
210
softmmu_ss.add_all(when: 'CONFIG_MULTIPROCESS', if_true: remote_ss)
42
--
211
--
43
2.21.0
212
2.29.2
44
213
45
diff view generated by jsdifflib
1
The error message for the test case where we have a quorum node for
1
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
2
which no directory name can be generated is different: For
3
twoGbMaxExtentSparse, it complains that it cannot open the extent file.
4
For other (sub)formats, it just notes that it cannot determine the
5
backing file path. Both are fine, but just disable twoGbMaxExtentSparse
6
for simplicity's sake.
7
2
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Defines a PCI Device proxy object as a child of TYPE_PCI_DEVICE.
9
Reviewed-by: John Snow <jsnow@redhat.com>
4
10
Message-id: 20190815153638.4600-7-mreitz@redhat.com
5
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
6
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: b5186ebfedf8e557044d09a768846c59230ad3a7.1611938319.git.jag.raman@oracle.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
11
---
14
tests/qemu-iotests/110 | 3 ++-
12
MAINTAINERS | 2 +
15
1 file changed, 2 insertions(+), 1 deletion(-)
13
include/hw/remote/proxy.h | 33 +++++++++++++
14
hw/remote/proxy.c | 99 +++++++++++++++++++++++++++++++++++++++
15
hw/remote/meson.build | 1 +
16
4 files changed, 135 insertions(+)
17
create mode 100644 include/hw/remote/proxy.h
18
create mode 100644 hw/remote/proxy.c
16
19
17
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
20
diff --git a/MAINTAINERS b/MAINTAINERS
18
index XXXXXXX..XXXXXXX 100755
21
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/110
22
--- a/MAINTAINERS
20
+++ b/tests/qemu-iotests/110
23
+++ b/MAINTAINERS
21
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
24
@@ -XXX,XX +XXX,XX @@ F: hw/remote/message.c
22
# Any format supporting backing files
25
F: hw/remote/remote-obj.c
23
_supported_fmt qed qcow qcow2 vmdk
26
F: include/hw/remote/memory.h
24
_supported_proto file
27
F: hw/remote/memory.c
25
-_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
28
+F: hw/remote/proxy.c
26
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
29
+F: include/hw/remote/proxy.h
27
+ "subformat=twoGbMaxExtentSparse"
30
28
31
Build and test automation
29
TEST_IMG_REL=$(basename "$TEST_IMG")
32
-------------------------
33
diff --git a/include/hw/remote/proxy.h b/include/hw/remote/proxy.h
34
new file mode 100644
35
index XXXXXXX..XXXXXXX
36
--- /dev/null
37
+++ b/include/hw/remote/proxy.h
38
@@ -XXX,XX +XXX,XX @@
39
+/*
40
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
41
+ *
42
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
43
+ * See the COPYING file in the top-level directory.
44
+ *
45
+ */
46
+
47
+#ifndef PROXY_H
48
+#define PROXY_H
49
+
50
+#include "hw/pci/pci.h"
51
+#include "io/channel.h"
52
+
53
+#define TYPE_PCI_PROXY_DEV "x-pci-proxy-dev"
54
+OBJECT_DECLARE_SIMPLE_TYPE(PCIProxyDev, PCI_PROXY_DEV)
55
+
56
+struct PCIProxyDev {
57
+ PCIDevice parent_dev;
58
+ char *fd;
59
+
60
+ /*
61
+ * Mutex used to protect the QIOChannel fd from
62
+ * the concurrent access by the VCPUs since proxy
63
+ * blocks while awaiting for the replies from the
64
+ * process remote.
65
+ */
66
+ QemuMutex io_mutex;
67
+ QIOChannel *ioc;
68
+ Error *migration_blocker;
69
+};
70
+
71
+#endif /* PROXY_H */
72
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
73
new file mode 100644
74
index XXXXXXX..XXXXXXX
75
--- /dev/null
76
+++ b/hw/remote/proxy.c
77
@@ -XXX,XX +XXX,XX @@
78
+/*
79
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
80
+ *
81
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
82
+ * See the COPYING file in the top-level directory.
83
+ *
84
+ */
85
+
86
+#include "qemu/osdep.h"
87
+#include "qemu-common.h"
88
+
89
+#include "hw/remote/proxy.h"
90
+#include "hw/pci/pci.h"
91
+#include "qapi/error.h"
92
+#include "io/channel-util.h"
93
+#include "hw/qdev-properties.h"
94
+#include "monitor/monitor.h"
95
+#include "migration/blocker.h"
96
+#include "qemu/sockets.h"
97
+
98
+static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
99
+{
100
+ ERRP_GUARD();
101
+ PCIProxyDev *dev = PCI_PROXY_DEV(device);
102
+ int fd;
103
+
104
+ if (!dev->fd) {
105
+ error_setg(errp, "fd parameter not specified for %s",
106
+ DEVICE(device)->id);
107
+ return;
108
+ }
109
+
110
+ fd = monitor_fd_param(monitor_cur(), dev->fd, errp);
111
+ if (fd == -1) {
112
+ error_prepend(errp, "proxy: unable to parse fd %s: ", dev->fd);
113
+ return;
114
+ }
115
+
116
+ if (!fd_is_socket(fd)) {
117
+ error_setg(errp, "proxy: fd %d is not a socket", fd);
118
+ close(fd);
119
+ return;
120
+ }
121
+
122
+ dev->ioc = qio_channel_new_fd(fd, errp);
123
+
124
+ error_setg(&dev->migration_blocker, "%s does not support migration",
125
+ TYPE_PCI_PROXY_DEV);
126
+ migrate_add_blocker(dev->migration_blocker, errp);
127
+
128
+ qemu_mutex_init(&dev->io_mutex);
129
+ qio_channel_set_blocking(dev->ioc, true, NULL);
130
+}
131
+
132
+static void pci_proxy_dev_exit(PCIDevice *pdev)
133
+{
134
+ PCIProxyDev *dev = PCI_PROXY_DEV(pdev);
135
+
136
+ if (dev->ioc) {
137
+ qio_channel_close(dev->ioc, NULL);
138
+ }
139
+
140
+ migrate_del_blocker(dev->migration_blocker);
141
+
142
+ error_free(dev->migration_blocker);
143
+}
144
+
145
+static Property proxy_properties[] = {
146
+ DEFINE_PROP_STRING("fd", PCIProxyDev, fd),
147
+ DEFINE_PROP_END_OF_LIST(),
148
+};
149
+
150
+static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
151
+{
152
+ DeviceClass *dc = DEVICE_CLASS(klass);
153
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
154
+
155
+ k->realize = pci_proxy_dev_realize;
156
+ k->exit = pci_proxy_dev_exit;
157
+ device_class_set_props(dc, proxy_properties);
158
+}
159
+
160
+static const TypeInfo pci_proxy_dev_type_info = {
161
+ .name = TYPE_PCI_PROXY_DEV,
162
+ .parent = TYPE_PCI_DEVICE,
163
+ .instance_size = sizeof(PCIProxyDev),
164
+ .class_init = pci_proxy_dev_class_init,
165
+ .interfaces = (InterfaceInfo[]) {
166
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
167
+ { },
168
+ },
169
+};
170
+
171
+static void pci_proxy_dev_register_types(void)
172
+{
173
+ type_register_static(&pci_proxy_dev_type_info);
174
+}
175
+
176
+type_init(pci_proxy_dev_register_types)
177
diff --git a/hw/remote/meson.build b/hw/remote/meson.build
178
index XXXXXXX..XXXXXXX 100644
179
--- a/hw/remote/meson.build
180
+++ b/hw/remote/meson.build
181
@@ -XXX,XX +XXX,XX @@ remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('machine.c'))
182
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('mpqemu-link.c'))
183
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('message.c'))
184
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('remote-obj.c'))
185
+remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy.c'))
186
187
specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('memory.c'))
30
188
31
--
189
--
32
2.21.0
190
2.29.2
33
191
34
diff view generated by jsdifflib
1
From: Denis Plotnikov <dplotnikov@virtuozzo.com>
1
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
2
2
3
The patch allows to provide a pattern file for write
3
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
4
command. There was no similar ability before.
4
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
5
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-id: d54edb4176361eed86b903e8f27058363b6c83b3.1611938319.git.jag.raman@oracle.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
include/hw/remote/mpqemu-link.h | 4 ++++
11
hw/remote/mpqemu-link.c | 34 +++++++++++++++++++++++++++++++++
12
2 files changed, 38 insertions(+)
5
13
6
Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
14
diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h
7
Message-id: 20190820164616.4072-1-dplotnikov@virtuozzo.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
[mreitz: Keep optstring in alphabetical order]
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
qemu-io-cmds.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++---
13
1 file changed, 93 insertions(+), 6 deletions(-)
14
15
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/qemu-io-cmds.c
16
--- a/include/hw/remote/mpqemu-link.h
18
+++ b/qemu-io-cmds.c
17
+++ b/include/hw/remote/mpqemu-link.h
19
@@ -XXX,XX +XXX,XX @@ static void qemu_io_free(void *p)
18
@@ -XXX,XX +XXX,XX @@
20
qemu_vfree(p);
19
#include "qemu/thread.h"
20
#include "io/channel.h"
21
#include "exec/hwaddr.h"
22
+#include "io/channel-socket.h"
23
+#include "hw/remote/proxy.h"
24
25
#define REMOTE_MAX_FDS 8
26
27
@@ -XXX,XX +XXX,XX @@ typedef struct {
28
bool mpqemu_msg_send(MPQemuMsg *msg, QIOChannel *ioc, Error **errp);
29
bool mpqemu_msg_recv(MPQemuMsg *msg, QIOChannel *ioc, Error **errp);
30
31
+uint64_t mpqemu_msg_send_and_await_reply(MPQemuMsg *msg, PCIProxyDev *pdev,
32
+ Error **errp);
33
bool mpqemu_msg_valid(MPQemuMsg *msg);
34
35
#endif
36
diff --git a/hw/remote/mpqemu-link.c b/hw/remote/mpqemu-link.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/remote/mpqemu-link.c
39
+++ b/hw/remote/mpqemu-link.c
40
@@ -XXX,XX +XXX,XX @@ fail:
41
return ret;
21
}
42
}
22
43
23
+/*
44
+/*
24
+ * qemu_io_alloc_from_file()
45
+ * Send msg and wait for a reply with command code RET_MSG.
25
+ *
46
+ * Returns the message received of size u64 or UINT64_MAX
26
+ * Allocates the buffer and populates it with the content of the given file
47
+ * on error.
27
+ * up to @len bytes. If the file length is less than @len, then the buffer
48
+ * Called from VCPU thread in non-coroutine context.
28
+ * is populated with the file content cyclically.
49
+ * Used by the Proxy object to communicate to remote processes.
29
+ *
30
+ * @blk - the block backend where the buffer content is going to be written to
31
+ * @len - the buffer length
32
+ * @file_name - the file to read the content from
33
+ *
34
+ * Returns: the buffer pointer on success
35
+ * NULL on error
36
+ */
50
+ */
37
+static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
51
+uint64_t mpqemu_msg_send_and_await_reply(MPQemuMsg *msg, PCIProxyDev *pdev,
38
+ const char *file_name)
52
+ Error **errp)
39
+{
53
+{
40
+ char *buf, *buf_origin;
54
+ ERRP_GUARD();
41
+ FILE *f = fopen(file_name, "r");
55
+ MPQemuMsg msg_reply = {0};
42
+ int pattern_len;
56
+ uint64_t ret = UINT64_MAX;
43
+
57
+
44
+ if (!f) {
58
+ assert(!qemu_in_coroutine());
45
+ perror(file_name);
59
+
46
+ return NULL;
60
+ QEMU_LOCK_GUARD(&pdev->io_mutex);
61
+ if (!mpqemu_msg_send(msg, pdev->ioc, errp)) {
62
+ return ret;
47
+ }
63
+ }
48
+
64
+
49
+ if (qemuio_misalign) {
65
+ if (!mpqemu_msg_recv(&msg_reply, pdev->ioc, errp)) {
50
+ len += MISALIGN_OFFSET;
66
+ return ret;
51
+ }
67
+ }
52
+
68
+
53
+ buf_origin = buf = blk_blockalign(blk, len);
69
+ if (!mpqemu_msg_valid(&msg_reply)) {
54
+
70
+ error_setg(errp, "ERROR: Invalid reply received for command %d",
55
+ if (qemuio_misalign) {
71
+ msg->cmd);
56
+ buf_origin += MISALIGN_OFFSET;
72
+ return ret;
57
+ buf += MISALIGN_OFFSET;
58
+ len -= MISALIGN_OFFSET;
59
+ }
73
+ }
60
+
74
+
61
+ pattern_len = fread(buf_origin, 1, len, f);
75
+ return msg_reply.data.u64;
62
+
63
+ if (ferror(f)) {
64
+ perror(file_name);
65
+ goto error;
66
+ }
67
+
68
+ if (pattern_len == 0) {
69
+ fprintf(stderr, "%s: file is empty\n", file_name);
70
+ goto error;
71
+ }
72
+
73
+ fclose(f);
74
+
75
+ if (len > pattern_len) {
76
+ len -= pattern_len;
77
+ buf += pattern_len;
78
+
79
+ while (len > 0) {
80
+ size_t len_to_copy = MIN(pattern_len, len);
81
+
82
+ memcpy(buf, buf_origin, len_to_copy);
83
+
84
+ len -= len_to_copy;
85
+ buf += len_to_copy;
86
+ }
87
+ }
88
+
89
+ return buf_origin;
90
+
91
+error:
92
+ qemu_io_free(buf_origin);
93
+ return NULL;
94
+}
76
+}
95
+
77
+
96
static void dump_buffer(const void *buffer, int64_t offset, int64_t len)
78
bool mpqemu_msg_valid(MPQemuMsg *msg)
97
{
79
{
98
uint64_t i;
80
if (msg->cmd >= MPQEMU_CMD_MAX && msg->cmd < 0) {
99
@@ -XXX,XX +XXX,XX @@ static void write_help(void)
100
" -n, -- with -z, don't allow slow fallback\n"
101
" -p, -- ignored for backwards compatibility\n"
102
" -P, -- use different pattern to fill file\n"
103
+" -s, -- use a pattern file to fill the write buffer\n"
104
" -C, -- report statistics in a machine parsable format\n"
105
" -q, -- quiet mode, do not show I/O statistics\n"
106
" -u, -- with -z, allow unmapping\n"
107
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t write_cmd = {
108
.perm = BLK_PERM_WRITE,
109
.argmin = 2,
110
.argmax = -1,
111
- .args = "[-bcCfnquz] [-P pattern] off len",
112
+ .args = "[-bcCfnquz] [-P pattern | -s source_file] off len",
113
.oneline = "writes a number of bytes at a specified offset",
114
.help = write_help,
115
};
116
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
117
{
118
struct timespec t1, t2;
119
bool Cflag = false, qflag = false, bflag = false;
120
- bool Pflag = false, zflag = false, cflag = false;
121
+ bool Pflag = false, zflag = false, cflag = false, sflag = false;
122
int flags = 0;
123
int c, cnt, ret;
124
char *buf = NULL;
125
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
126
/* Some compilers get confused and warn if this is not initialized. */
127
int64_t total = 0;
128
int pattern = 0xcd;
129
+ const char *file_name = NULL;
130
131
- while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) {
132
+ while ((c = getopt(argc, argv, "bcCfnpP:qs:uz")) != -1) {
133
switch (c) {
134
case 'b':
135
bflag = true;
136
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
137
case 'q':
138
qflag = true;
139
break;
140
+ case 's':
141
+ sflag = true;
142
+ file_name = optarg;
143
+ break;
144
case 'u':
145
flags |= BDRV_REQ_MAY_UNMAP;
146
break;
147
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
148
return -EINVAL;
149
}
150
151
- if (zflag && Pflag) {
152
- printf("-z and -P cannot be specified at the same time\n");
153
+ if (zflag + Pflag + sflag > 1) {
154
+ printf("Only one of -z, -P, and -s "
155
+ "can be specified at the same time\n");
156
return -EINVAL;
157
}
158
159
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
160
}
161
162
if (!zflag) {
163
- buf = qemu_io_alloc(blk, count, pattern);
164
+ if (sflag) {
165
+ buf = qemu_io_alloc_from_file(blk, count, file_name);
166
+ if (!buf) {
167
+ return -EINVAL;
168
+ }
169
+ } else {
170
+ buf = qemu_io_alloc(blk, count, pattern);
171
+ }
172
}
173
174
clock_gettime(CLOCK_MONOTONIC, &t1);
175
--
81
--
176
2.21.0
82
2.29.2
177
83
178
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
2
2
3
It is possible to enable only a subset of the block drivers with the
3
The Proxy Object sends the PCI config space accesses as messages
4
"--block-drv-rw-whitelist" option of the "configure" script. All other
4
to the remote process over the communication channel
5
drivers are marked as unusable (or only included as read-only with the
5
6
"--block-drv-ro-whitelist" option). If an iotest is now using such a
6
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
7
disabled block driver, it is failing - which is bad, since at least the
7
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
8
tests in the "auto" group should be able to deal with this situation.
8
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
9
Thus let's introduce a "_require_drivers" function that can be used by
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
the shell tests to check for the availability of certain drivers first,
10
Message-id: d3c94f4618813234655356c60e6f0d0362ff42d6.1611938319.git.jag.raman@oracle.com
11
and marks the test as "not run" if one of the drivers is missing.
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
13
This patch mainly targets the test in the "auto" group which should
14
never fail in such a case, but also improves some of the other tests
15
along the way. Note that we also assume that the "qcow2" and "file"
16
drivers are always available - otherwise it does not make sense to
17
run "make check-block" at all (which only tests with qcow2 by default).
18
19
Signed-off-by: Thomas Huth <thuth@redhat.com>
20
Message-id: 20190823133552.11680-1-thuth@redhat.com
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
---
12
---
23
tests/qemu-iotests/071 | 1 +
13
include/hw/remote/mpqemu-link.h | 10 ++++++
24
tests/qemu-iotests/081 | 4 +---
14
hw/remote/message.c | 60 +++++++++++++++++++++++++++++++++
25
tests/qemu-iotests/099 | 1 +
15
hw/remote/mpqemu-link.c | 8 ++++-
26
tests/qemu-iotests/120 | 1 +
16
hw/remote/proxy.c | 55 ++++++++++++++++++++++++++++++
27
tests/qemu-iotests/162 | 4 +---
17
4 files changed, 132 insertions(+), 1 deletion(-)
28
tests/qemu-iotests/184 | 1 +
18
29
tests/qemu-iotests/186 | 1 +
19
diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h
30
tests/qemu-iotests/common.rc | 14 ++++++++++++++
20
index XXXXXXX..XXXXXXX 100644
31
8 files changed, 21 insertions(+), 6 deletions(-)
21
--- a/include/hw/remote/mpqemu-link.h
32
22
+++ b/include/hw/remote/mpqemu-link.h
33
diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
23
@@ -XXX,XX +XXX,XX @@
34
index XXXXXXX..XXXXXXX 100755
24
*/
35
--- a/tests/qemu-iotests/071
25
typedef enum {
36
+++ b/tests/qemu-iotests/071
26
MPQEMU_CMD_SYNC_SYSMEM,
37
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
27
+ MPQEMU_CMD_RET,
38
28
+ MPQEMU_CMD_PCI_CFGWRITE,
39
_supported_fmt qcow2
29
+ MPQEMU_CMD_PCI_CFGREAD,
40
_supported_proto file
30
MPQEMU_CMD_MAX,
41
+_require_drivers blkdebug blkverify
31
} MPQemuCmd;
42
32
43
do_run_qemu()
33
@@ -XXX,XX +XXX,XX @@ typedef struct {
34
off_t offsets[REMOTE_MAX_FDS];
35
} SyncSysmemMsg;
36
37
+typedef struct {
38
+ uint32_t addr;
39
+ uint32_t val;
40
+ int len;
41
+} PciConfDataMsg;
42
+
43
/**
44
* MPQemuMsg:
45
* @cmd: The remote command
46
@@ -XXX,XX +XXX,XX @@ typedef struct {
47
48
union {
49
uint64_t u64;
50
+ PciConfDataMsg pci_conf_data;
51
SyncSysmemMsg sync_sysmem;
52
} data;
53
54
diff --git a/hw/remote/message.c b/hw/remote/message.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/remote/message.c
57
+++ b/hw/remote/message.c
58
@@ -XXX,XX +XXX,XX @@
59
#include "hw/remote/mpqemu-link.h"
60
#include "qapi/error.h"
61
#include "sysemu/runstate.h"
62
+#include "hw/pci/pci.h"
63
+
64
+static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
65
+ MPQemuMsg *msg, Error **errp);
66
+static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
67
+ MPQemuMsg *msg, Error **errp);
68
69
void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
44
{
70
{
45
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
71
@@ -XXX,XX +XXX,XX @@ void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
46
index XXXXXXX..XXXXXXX 100755
72
}
47
--- a/tests/qemu-iotests/081
73
48
+++ b/tests/qemu-iotests/081
74
switch (msg.cmd) {
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
75
+ case MPQEMU_CMD_PCI_CFGWRITE:
50
_supported_fmt raw
76
+ process_config_write(com->ioc, pci_dev, &msg, &local_err);
51
_supported_proto file
77
+ break;
52
_supported_os Linux
78
+ case MPQEMU_CMD_PCI_CFGREAD:
53
+_require_drivers quorum
79
+ process_config_read(com->ioc, pci_dev, &msg, &local_err);
54
80
+ break;
55
do_run_qemu()
81
default:
82
error_setg(&local_err,
83
"Unknown command (%d) received for device %s"
84
@@ -XXX,XX +XXX,XX @@ void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
85
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
86
}
87
}
88
+
89
+static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
90
+ MPQemuMsg *msg, Error **errp)
91
+{
92
+ ERRP_GUARD();
93
+ PciConfDataMsg *conf = (PciConfDataMsg *)&msg->data.pci_conf_data;
94
+ MPQemuMsg ret = { 0 };
95
+
96
+ if ((conf->addr + sizeof(conf->val)) > pci_config_size(dev)) {
97
+ error_setg(errp, "Bad address for PCI config write, pid "FMT_pid".",
98
+ getpid());
99
+ ret.data.u64 = UINT64_MAX;
100
+ } else {
101
+ pci_default_write_config(dev, conf->addr, conf->val, conf->len);
102
+ }
103
+
104
+ ret.cmd = MPQEMU_CMD_RET;
105
+ ret.size = sizeof(ret.data.u64);
106
+
107
+ if (!mpqemu_msg_send(&ret, ioc, NULL)) {
108
+ error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
109
+ getpid());
110
+ }
111
+}
112
+
113
+static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
114
+ MPQemuMsg *msg, Error **errp)
115
+{
116
+ ERRP_GUARD();
117
+ PciConfDataMsg *conf = (PciConfDataMsg *)&msg->data.pci_conf_data;
118
+ MPQemuMsg ret = { 0 };
119
+
120
+ if ((conf->addr + sizeof(conf->val)) > pci_config_size(dev)) {
121
+ error_setg(errp, "Bad address for PCI config read, pid "FMT_pid".",
122
+ getpid());
123
+ ret.data.u64 = UINT64_MAX;
124
+ } else {
125
+ ret.data.u64 = pci_default_read_config(dev, conf->addr, conf->len);
126
+ }
127
+
128
+ ret.cmd = MPQEMU_CMD_RET;
129
+ ret.size = sizeof(ret.data.u64);
130
+
131
+ if (!mpqemu_msg_send(&ret, ioc, NULL)) {
132
+ error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
133
+ getpid());
134
+ }
135
+}
136
diff --git a/hw/remote/mpqemu-link.c b/hw/remote/mpqemu-link.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/remote/mpqemu-link.c
139
+++ b/hw/remote/mpqemu-link.c
140
@@ -XXX,XX +XXX,XX @@ uint64_t mpqemu_msg_send_and_await_reply(MPQemuMsg *msg, PCIProxyDev *pdev,
141
return ret;
142
}
143
144
- if (!mpqemu_msg_valid(&msg_reply)) {
145
+ if (!mpqemu_msg_valid(&msg_reply) || msg_reply.cmd != MPQEMU_CMD_RET) {
146
error_setg(errp, "ERROR: Invalid reply received for command %d",
147
msg->cmd);
148
return ret;
149
@@ -XXX,XX +XXX,XX @@ bool mpqemu_msg_valid(MPQemuMsg *msg)
150
return false;
151
}
152
break;
153
+ case MPQEMU_CMD_PCI_CFGWRITE:
154
+ case MPQEMU_CMD_PCI_CFGREAD:
155
+ if (msg->size != sizeof(PciConfDataMsg)) {
156
+ return false;
157
+ }
158
+ break;
159
default:
160
break;
161
}
162
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/hw/remote/proxy.c
165
+++ b/hw/remote/proxy.c
166
@@ -XXX,XX +XXX,XX @@
167
#include "monitor/monitor.h"
168
#include "migration/blocker.h"
169
#include "qemu/sockets.h"
170
+#include "hw/remote/mpqemu-link.h"
171
+#include "qemu/error-report.h"
172
173
static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
56
{
174
{
57
@@ -XXX,XX +XXX,XX @@ run_qemu()
175
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_exit(PCIDevice *pdev)
58
| _filter_qemu_io | _filter_generated_node_ids
176
error_free(dev->migration_blocker);
59
}
177
}
60
178
61
-test_quorum=$($QEMU_IMG --help|grep quorum)
179
+static void config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val,
62
-[ "$test_quorum" = "" ] && _supported_fmt quorum
180
+ int len, unsigned int op)
63
-
181
+{
64
quorum="driver=raw,file.driver=quorum,file.vote-threshold=2"
182
+ MPQemuMsg msg = { 0 };
65
quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
183
+ uint64_t ret = -EINVAL;
66
quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
184
+ Error *local_err = NULL;
67
diff --git a/tests/qemu-iotests/099 b/tests/qemu-iotests/099
185
+
68
index XXXXXXX..XXXXXXX 100755
186
+ msg.cmd = op;
69
--- a/tests/qemu-iotests/099
187
+ msg.data.pci_conf_data.addr = addr;
70
+++ b/tests/qemu-iotests/099
188
+ msg.data.pci_conf_data.val = (op == MPQEMU_CMD_PCI_CFGWRITE) ? *val : 0;
71
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
189
+ msg.data.pci_conf_data.len = len;
72
_supported_fmt qcow qcow2 qed vdi vhdx vmdk vpc
190
+ msg.size = sizeof(PciConfDataMsg);
73
_supported_proto file
191
+
74
_supported_os Linux
192
+ ret = mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err);
75
+_require_drivers blkdebug blkverify
193
+ if (local_err) {
76
_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
194
+ error_report_err(local_err);
77
"subformat=twoGbMaxExtentSparse"
195
+ }
78
196
+
79
diff --git a/tests/qemu-iotests/120 b/tests/qemu-iotests/120
197
+ if (ret == UINT64_MAX) {
80
index XXXXXXX..XXXXXXX 100755
198
+ error_report("Failed to perform PCI config %s operation",
81
--- a/tests/qemu-iotests/120
199
+ (op == MPQEMU_CMD_PCI_CFGREAD) ? "READ" : "WRITE");
82
+++ b/tests/qemu-iotests/120
200
+ }
83
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
201
+
84
_supported_fmt generic
202
+ if (op == MPQEMU_CMD_PCI_CFGREAD) {
85
_supported_proto file
203
+ *val = (uint32_t)ret;
86
_unsupported_fmt luks
204
+ }
87
+_require_drivers raw
205
+}
88
206
+
89
_make_test_img 64M
207
+static uint32_t pci_proxy_read_config(PCIDevice *d, uint32_t addr, int len)
90
208
+{
91
diff --git a/tests/qemu-iotests/162 b/tests/qemu-iotests/162
209
+ uint32_t val;
92
index XXXXXXX..XXXXXXX 100755
210
+
93
--- a/tests/qemu-iotests/162
211
+ config_op_send(PCI_PROXY_DEV(d), addr, &val, len, MPQEMU_CMD_PCI_CFGREAD);
94
+++ b/tests/qemu-iotests/162
212
+
95
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
213
+ return val;
96
. ./common.filter
214
+}
97
215
+
98
_supported_fmt generic
216
+static void pci_proxy_write_config(PCIDevice *d, uint32_t addr, uint32_t val,
99
-
217
+ int len)
100
-test_ssh=$($QEMU_IMG --help | grep '^Supported formats:.* ssh\( \|$\)')
218
+{
101
-[ "$test_ssh" = "" ] && _notrun "ssh support required"
219
+ /*
102
+_require_drivers ssh
220
+ * Some of the functions access the copy of remote device's PCI config
103
221
+ * space which is cached in the proxy device. Therefore, maintain
104
echo
222
+ * it updated.
105
echo '=== NBD ==='
223
+ */
106
diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184
224
+ pci_default_write_config(d, addr, val, len);
107
index XXXXXXX..XXXXXXX 100755
225
+
108
--- a/tests/qemu-iotests/184
226
+ config_op_send(PCI_PROXY_DEV(d), addr, &val, len, MPQEMU_CMD_PCI_CFGWRITE);
109
+++ b/tests/qemu-iotests/184
227
+}
110
@@ -XXX,XX +XXX,XX @@ trap "exit \$status" 0 1 2 3 15
228
+
111
. ./common.filter
229
static Property proxy_properties[] = {
112
230
DEFINE_PROP_STRING("fd", PCIProxyDev, fd),
113
_supported_os Linux
231
DEFINE_PROP_END_OF_LIST(),
114
+_require_drivers throttle
232
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
115
233
116
do_run_qemu()
234
k->realize = pci_proxy_dev_realize;
117
{
235
k->exit = pci_proxy_dev_exit;
118
diff --git a/tests/qemu-iotests/186 b/tests/qemu-iotests/186
236
+ k->config_read = pci_proxy_read_config;
119
index XXXXXXX..XXXXXXX 100755
237
+ k->config_write = pci_proxy_write_config;
120
--- a/tests/qemu-iotests/186
238
+
121
+++ b/tests/qemu-iotests/186
239
device_class_set_props(dc, proxy_properties);
122
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
123
124
_supported_fmt qcow2
125
_supported_proto file
126
+_require_drivers null-co
127
128
if [ "$QEMU_DEFAULT_MACHINE" != "pc" ]; then
129
_notrun "Requires a PC machine"
130
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
131
index XXXXXXX..XXXXXXX 100644
132
--- a/tests/qemu-iotests/common.rc
133
+++ b/tests/qemu-iotests/common.rc
134
@@ -XXX,XX +XXX,XX @@ _require_command()
135
[ -x "$c" ] || _notrun "$1 utility required, skipped this test"
136
}
240
}
137
241
138
+# Check that a set of drivers has been whitelisted in the QEMU binary
139
+#
140
+_require_drivers()
141
+{
142
+ available=$($QEMU -drive format=help | \
143
+ sed -e '/Supported formats:/!d' -e 's/Supported formats://')
144
+ for driver
145
+ do
146
+ if ! echo "$available" | grep -q " $driver\( \|$\)"; then
147
+ _notrun "$driver not available"
148
+ fi
149
+ done
150
+}
151
+
152
# make sure this script returns success
153
true
154
--
242
--
155
2.21.0
243
2.29.2
156
244
157
diff view generated by jsdifflib
1
iotest 126 requires backing file support, which flat vmdks cannot offer.
1
From: Jagannathan Raman <jag.raman@oracle.com>
2
Skip this test for such subformats.
2
3
3
Proxy device object implements handler for PCI BAR writes and reads.
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
The handler uses BAR_WRITE/BAR_READ message to communicate to the
5
Message-id: 20190815153638.4600-8-mreitz@redhat.com
5
remote process with the BAR address and value to be written/read.
6
Reviewed-by: John Snow <jsnow@redhat.com>
6
The remote process implements handler for BAR_WRITE/BAR_READ
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
message.
8
9
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
10
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
11
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Message-id: a8b76714a9688be5552c4c92d089bc9e8a4707ff.1611938319.git.jag.raman@oracle.com
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
15
---
9
tests/qemu-iotests/126 | 2 ++
16
include/hw/remote/mpqemu-link.h | 10 ++++
10
1 file changed, 2 insertions(+)
17
include/hw/remote/proxy.h | 9 ++++
11
18
hw/remote/message.c | 83 +++++++++++++++++++++++++++++++++
12
diff --git a/tests/qemu-iotests/126 b/tests/qemu-iotests/126
19
hw/remote/mpqemu-link.c | 6 +++
13
index XXXXXXX..XXXXXXX 100755
20
hw/remote/proxy.c | 60 ++++++++++++++++++++++++
14
--- a/tests/qemu-iotests/126
21
5 files changed, 168 insertions(+)
15
+++ b/tests/qemu-iotests/126
22
16
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
23
diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h
17
24
index XXXXXXX..XXXXXXX 100644
18
# Needs backing file support
25
--- a/include/hw/remote/mpqemu-link.h
19
_supported_fmt qcow qcow2 qed vmdk
26
+++ b/include/hw/remote/mpqemu-link.h
20
+_unsupported_imgopts "subformat=monolithicFlat" \
27
@@ -XXX,XX +XXX,XX @@ typedef enum {
21
+ "subformat=twoGbMaxExtentFlat"
28
MPQEMU_CMD_RET,
22
# This is the default protocol (and we want to test the difference between
29
MPQEMU_CMD_PCI_CFGWRITE,
23
# colons which separate a protocol prefix from the rest and colons which are
30
MPQEMU_CMD_PCI_CFGREAD,
24
# just part of the filename, so we cannot test protocols which require a prefix)
31
+ MPQEMU_CMD_BAR_WRITE,
32
+ MPQEMU_CMD_BAR_READ,
33
MPQEMU_CMD_MAX,
34
} MPQemuCmd;
35
36
@@ -XXX,XX +XXX,XX @@ typedef struct {
37
int len;
38
} PciConfDataMsg;
39
40
+typedef struct {
41
+ hwaddr addr;
42
+ uint64_t val;
43
+ unsigned size;
44
+ bool memory;
45
+} BarAccessMsg;
46
+
47
/**
48
* MPQemuMsg:
49
* @cmd: The remote command
50
@@ -XXX,XX +XXX,XX @@ typedef struct {
51
uint64_t u64;
52
PciConfDataMsg pci_conf_data;
53
SyncSysmemMsg sync_sysmem;
54
+ BarAccessMsg bar_access;
55
} data;
56
57
int fds[REMOTE_MAX_FDS];
58
diff --git a/include/hw/remote/proxy.h b/include/hw/remote/proxy.h
59
index XXXXXXX..XXXXXXX 100644
60
--- a/include/hw/remote/proxy.h
61
+++ b/include/hw/remote/proxy.h
62
@@ -XXX,XX +XXX,XX @@
63
#define TYPE_PCI_PROXY_DEV "x-pci-proxy-dev"
64
OBJECT_DECLARE_SIMPLE_TYPE(PCIProxyDev, PCI_PROXY_DEV)
65
66
+typedef struct ProxyMemoryRegion {
67
+ PCIProxyDev *dev;
68
+ MemoryRegion mr;
69
+ bool memory;
70
+ bool present;
71
+ uint8_t type;
72
+} ProxyMemoryRegion;
73
+
74
struct PCIProxyDev {
75
PCIDevice parent_dev;
76
char *fd;
77
@@ -XXX,XX +XXX,XX @@ struct PCIProxyDev {
78
QemuMutex io_mutex;
79
QIOChannel *ioc;
80
Error *migration_blocker;
81
+ ProxyMemoryRegion region[PCI_NUM_REGIONS];
82
};
83
84
#endif /* PROXY_H */
85
diff --git a/hw/remote/message.c b/hw/remote/message.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/hw/remote/message.c
88
+++ b/hw/remote/message.c
89
@@ -XXX,XX +XXX,XX @@
90
#include "qapi/error.h"
91
#include "sysemu/runstate.h"
92
#include "hw/pci/pci.h"
93
+#include "exec/memattrs.h"
94
95
static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
96
MPQemuMsg *msg, Error **errp);
97
static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
98
MPQemuMsg *msg, Error **errp);
99
+static void process_bar_write(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
100
+static void process_bar_read(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
101
102
void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
103
{
104
@@ -XXX,XX +XXX,XX @@ void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
105
case MPQEMU_CMD_PCI_CFGREAD:
106
process_config_read(com->ioc, pci_dev, &msg, &local_err);
107
break;
108
+ case MPQEMU_CMD_BAR_WRITE:
109
+ process_bar_write(com->ioc, &msg, &local_err);
110
+ break;
111
+ case MPQEMU_CMD_BAR_READ:
112
+ process_bar_read(com->ioc, &msg, &local_err);
113
+ break;
114
default:
115
error_setg(&local_err,
116
"Unknown command (%d) received for device %s"
117
@@ -XXX,XX +XXX,XX @@ static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
118
getpid());
119
}
120
}
121
+
122
+static void process_bar_write(QIOChannel *ioc, MPQemuMsg *msg, Error **errp)
123
+{
124
+ ERRP_GUARD();
125
+ BarAccessMsg *bar_access = &msg->data.bar_access;
126
+ AddressSpace *as =
127
+ bar_access->memory ? &address_space_memory : &address_space_io;
128
+ MPQemuMsg ret = { 0 };
129
+ MemTxResult res;
130
+ uint64_t val;
131
+
132
+ if (!is_power_of_2(bar_access->size) ||
133
+ (bar_access->size > sizeof(uint64_t))) {
134
+ ret.data.u64 = UINT64_MAX;
135
+ goto fail;
136
+ }
137
+
138
+ val = cpu_to_le64(bar_access->val);
139
+
140
+ res = address_space_rw(as, bar_access->addr, MEMTXATTRS_UNSPECIFIED,
141
+ (void *)&val, bar_access->size, true);
142
+
143
+ if (res != MEMTX_OK) {
144
+ error_setg(errp, "Bad address %"PRIx64" for mem write, pid "FMT_pid".",
145
+ bar_access->addr, getpid());
146
+ ret.data.u64 = -1;
147
+ }
148
+
149
+fail:
150
+ ret.cmd = MPQEMU_CMD_RET;
151
+ ret.size = sizeof(ret.data.u64);
152
+
153
+ if (!mpqemu_msg_send(&ret, ioc, NULL)) {
154
+ error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
155
+ getpid());
156
+ }
157
+}
158
+
159
+static void process_bar_read(QIOChannel *ioc, MPQemuMsg *msg, Error **errp)
160
+{
161
+ ERRP_GUARD();
162
+ BarAccessMsg *bar_access = &msg->data.bar_access;
163
+ MPQemuMsg ret = { 0 };
164
+ AddressSpace *as;
165
+ MemTxResult res;
166
+ uint64_t val = 0;
167
+
168
+ as = bar_access->memory ? &address_space_memory : &address_space_io;
169
+
170
+ if (!is_power_of_2(bar_access->size) ||
171
+ (bar_access->size > sizeof(uint64_t))) {
172
+ val = UINT64_MAX;
173
+ goto fail;
174
+ }
175
+
176
+ res = address_space_rw(as, bar_access->addr, MEMTXATTRS_UNSPECIFIED,
177
+ (void *)&val, bar_access->size, false);
178
+
179
+ if (res != MEMTX_OK) {
180
+ error_setg(errp, "Bad address %"PRIx64" for mem read, pid "FMT_pid".",
181
+ bar_access->addr, getpid());
182
+ val = UINT64_MAX;
183
+ }
184
+
185
+fail:
186
+ ret.cmd = MPQEMU_CMD_RET;
187
+ ret.data.u64 = le64_to_cpu(val);
188
+ ret.size = sizeof(ret.data.u64);
189
+
190
+ if (!mpqemu_msg_send(&ret, ioc, NULL)) {
191
+ error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
192
+ getpid());
193
+ }
194
+}
195
diff --git a/hw/remote/mpqemu-link.c b/hw/remote/mpqemu-link.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/hw/remote/mpqemu-link.c
198
+++ b/hw/remote/mpqemu-link.c
199
@@ -XXX,XX +XXX,XX @@ bool mpqemu_msg_valid(MPQemuMsg *msg)
200
return false;
201
}
202
break;
203
+ case MPQEMU_CMD_BAR_WRITE:
204
+ case MPQEMU_CMD_BAR_READ:
205
+ if ((msg->size != sizeof(BarAccessMsg)) || (msg->num_fds != 0)) {
206
+ return false;
207
+ }
208
+ break;
209
default:
210
break;
211
}
212
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
213
index XXXXXXX..XXXXXXX 100644
214
--- a/hw/remote/proxy.c
215
+++ b/hw/remote/proxy.c
216
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_register_types(void)
217
}
218
219
type_init(pci_proxy_dev_register_types)
220
+
221
+static void send_bar_access_msg(PCIProxyDev *pdev, MemoryRegion *mr,
222
+ bool write, hwaddr addr, uint64_t *val,
223
+ unsigned size, bool memory)
224
+{
225
+ MPQemuMsg msg = { 0 };
226
+ long ret = -EINVAL;
227
+ Error *local_err = NULL;
228
+
229
+ msg.size = sizeof(BarAccessMsg);
230
+ msg.data.bar_access.addr = mr->addr + addr;
231
+ msg.data.bar_access.size = size;
232
+ msg.data.bar_access.memory = memory;
233
+
234
+ if (write) {
235
+ msg.cmd = MPQEMU_CMD_BAR_WRITE;
236
+ msg.data.bar_access.val = *val;
237
+ } else {
238
+ msg.cmd = MPQEMU_CMD_BAR_READ;
239
+ }
240
+
241
+ ret = mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err);
242
+ if (local_err) {
243
+ error_report_err(local_err);
244
+ }
245
+
246
+ if (!write) {
247
+ *val = ret;
248
+ }
249
+}
250
+
251
+static void proxy_bar_write(void *opaque, hwaddr addr, uint64_t val,
252
+ unsigned size)
253
+{
254
+ ProxyMemoryRegion *pmr = opaque;
255
+
256
+ send_bar_access_msg(pmr->dev, &pmr->mr, true, addr, &val, size,
257
+ pmr->memory);
258
+}
259
+
260
+static uint64_t proxy_bar_read(void *opaque, hwaddr addr, unsigned size)
261
+{
262
+ ProxyMemoryRegion *pmr = opaque;
263
+ uint64_t val;
264
+
265
+ send_bar_access_msg(pmr->dev, &pmr->mr, false, addr, &val, size,
266
+ pmr->memory);
267
+
268
+ return val;
269
+}
270
+
271
+const MemoryRegionOps proxy_mr_ops = {
272
+ .read = proxy_bar_read,
273
+ .write = proxy_bar_write,
274
+ .endianness = DEVICE_NATIVE_ENDIAN,
275
+ .impl = {
276
+ .min_access_size = 1,
277
+ .max_access_size = 8,
278
+ },
279
+};
25
--
280
--
26
2.21.0
281
2.29.2
27
282
28
diff view generated by jsdifflib
1
This makes iotest 033 pass with e.g. subformat=monolithicFlat. It also
1
From: Jagannathan Raman <jag.raman@oracle.com>
2
turns a former error in 059 into success.
3
2
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Add ProxyMemoryListener object which is used to keep the view of the RAM
5
Message-id: 20190815153638.4600-3-mreitz@redhat.com
4
in sync between QEMU and remote process.
6
Reviewed-by: John Snow <jsnow@redhat.com>
5
A MemoryListener is registered for system-memory AddressSpace. The
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
listener sends SYNC_SYSMEM message to the remote process when memory
7
listener commits the changes to memory, the remote process receives
8
the message and processes it in the handler for SYNC_SYSMEM message.
9
10
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
11
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
12
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-id: 04fe4e6a9ca90d4f11ab6f59be7652f5b086a071.1611938319.git.jag.raman@oracle.com
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
16
---
9
block/vmdk.c | 54 ++++++++++++++++++++++++--------------
17
MAINTAINERS | 2 +
10
tests/qemu-iotests/059 | 7 +++--
18
include/hw/remote/proxy-memory-listener.h | 28 +++
11
tests/qemu-iotests/059.out | 4 ++-
19
include/hw/remote/proxy.h | 2 +
12
3 files changed, 42 insertions(+), 23 deletions(-)
20
hw/remote/message.c | 4 +
21
hw/remote/proxy-memory-listener.c | 227 ++++++++++++++++++++++
22
hw/remote/proxy.c | 6 +
23
hw/remote/meson.build | 1 +
24
7 files changed, 270 insertions(+)
25
create mode 100644 include/hw/remote/proxy-memory-listener.h
26
create mode 100644 hw/remote/proxy-memory-listener.c
13
27
14
diff --git a/block/vmdk.c b/block/vmdk.c
28
diff --git a/MAINTAINERS b/MAINTAINERS
15
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
16
--- a/block/vmdk.c
30
--- a/MAINTAINERS
17
+++ b/block/vmdk.c
31
+++ b/MAINTAINERS
18
@@ -XXX,XX +XXX,XX @@ static const char *next_line(const char *s)
32
@@ -XXX,XX +XXX,XX @@ F: include/hw/remote/memory.h
33
F: hw/remote/memory.c
34
F: hw/remote/proxy.c
35
F: include/hw/remote/proxy.h
36
+F: hw/remote/proxy-memory-listener.c
37
+F: include/hw/remote/proxy-memory-listener.h
38
39
Build and test automation
40
-------------------------
41
diff --git a/include/hw/remote/proxy-memory-listener.h b/include/hw/remote/proxy-memory-listener.h
42
new file mode 100644
43
index XXXXXXX..XXXXXXX
44
--- /dev/null
45
+++ b/include/hw/remote/proxy-memory-listener.h
46
@@ -XXX,XX +XXX,XX @@
47
+/*
48
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
49
+ *
50
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
51
+ * See the COPYING file in the top-level directory.
52
+ *
53
+ */
54
+
55
+#ifndef PROXY_MEMORY_LISTENER_H
56
+#define PROXY_MEMORY_LISTENER_H
57
+
58
+#include "exec/memory.h"
59
+#include "io/channel.h"
60
+
61
+typedef struct ProxyMemoryListener {
62
+ MemoryListener listener;
63
+
64
+ int n_mr_sections;
65
+ MemoryRegionSection *mr_sections;
66
+
67
+ QIOChannel *ioc;
68
+} ProxyMemoryListener;
69
+
70
+void proxy_memory_listener_configure(ProxyMemoryListener *proxy_listener,
71
+ QIOChannel *ioc);
72
+void proxy_memory_listener_deconfigure(ProxyMemoryListener *proxy_listener);
73
+
74
+#endif
75
diff --git a/include/hw/remote/proxy.h b/include/hw/remote/proxy.h
76
index XXXXXXX..XXXXXXX 100644
77
--- a/include/hw/remote/proxy.h
78
+++ b/include/hw/remote/proxy.h
79
@@ -XXX,XX +XXX,XX @@
80
81
#include "hw/pci/pci.h"
82
#include "io/channel.h"
83
+#include "hw/remote/proxy-memory-listener.h"
84
85
#define TYPE_PCI_PROXY_DEV "x-pci-proxy-dev"
86
OBJECT_DECLARE_SIMPLE_TYPE(PCIProxyDev, PCI_PROXY_DEV)
87
@@ -XXX,XX +XXX,XX @@ struct PCIProxyDev {
88
QemuMutex io_mutex;
89
QIOChannel *ioc;
90
Error *migration_blocker;
91
+ ProxyMemoryListener proxy_listener;
92
ProxyMemoryRegion region[PCI_NUM_REGIONS];
93
};
94
95
diff --git a/hw/remote/message.c b/hw/remote/message.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/hw/remote/message.c
98
+++ b/hw/remote/message.c
99
@@ -XXX,XX +XXX,XX @@
100
#include "sysemu/runstate.h"
101
#include "hw/pci/pci.h"
102
#include "exec/memattrs.h"
103
+#include "hw/remote/memory.h"
104
105
static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
106
MPQemuMsg *msg, Error **errp);
107
@@ -XXX,XX +XXX,XX @@ void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
108
case MPQEMU_CMD_BAR_READ:
109
process_bar_read(com->ioc, &msg, &local_err);
110
break;
111
+ case MPQEMU_CMD_SYNC_SYSMEM:
112
+ remote_sysmem_reconfig(&msg, &local_err);
113
+ break;
114
default:
115
error_setg(&local_err,
116
"Unknown command (%d) received for device %s"
117
diff --git a/hw/remote/proxy-memory-listener.c b/hw/remote/proxy-memory-listener.c
118
new file mode 100644
119
index XXXXXXX..XXXXXXX
120
--- /dev/null
121
+++ b/hw/remote/proxy-memory-listener.c
122
@@ -XXX,XX +XXX,XX @@
123
+/*
124
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
125
+ *
126
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
127
+ * See the COPYING file in the top-level directory.
128
+ *
129
+ */
130
+
131
+#include "qemu/osdep.h"
132
+#include "qemu-common.h"
133
+
134
+#include "qemu/compiler.h"
135
+#include "qemu/int128.h"
136
+#include "qemu/range.h"
137
+#include "exec/memory.h"
138
+#include "exec/cpu-common.h"
139
+#include "cpu.h"
140
+#include "exec/ram_addr.h"
141
+#include "exec/address-spaces.h"
142
+#include "qapi/error.h"
143
+#include "hw/remote/mpqemu-link.h"
144
+#include "hw/remote/proxy-memory-listener.h"
145
+
146
+/*
147
+ * TODO: get_fd_from_hostaddr(), proxy_mrs_can_merge() and
148
+ * proxy_memory_listener_commit() defined below perform tasks similar to the
149
+ * functions defined in vhost-user.c. These functions are good candidates
150
+ * for refactoring.
151
+ *
152
+ */
153
+
154
+static void proxy_memory_listener_reset(MemoryListener *listener)
155
+{
156
+ ProxyMemoryListener *proxy_listener = container_of(listener,
157
+ ProxyMemoryListener,
158
+ listener);
159
+ int mrs;
160
+
161
+ for (mrs = 0; mrs < proxy_listener->n_mr_sections; mrs++) {
162
+ memory_region_unref(proxy_listener->mr_sections[mrs].mr);
163
+ }
164
+
165
+ g_free(proxy_listener->mr_sections);
166
+ proxy_listener->mr_sections = NULL;
167
+ proxy_listener->n_mr_sections = 0;
168
+}
169
+
170
+static int get_fd_from_hostaddr(uint64_t host, ram_addr_t *offset)
171
+{
172
+ MemoryRegion *mr;
173
+ ram_addr_t off;
174
+
175
+ /**
176
+ * Assumes that the host address is a valid address as it's
177
+ * coming from the MemoryListener system. In the case host
178
+ * address is not valid, the following call would return
179
+ * the default subregion of "system_memory" region, and
180
+ * not NULL. So it's not possible to check for NULL here.
181
+ */
182
+ mr = memory_region_from_host((void *)(uintptr_t)host, &off);
183
+
184
+ if (offset) {
185
+ *offset = off;
186
+ }
187
+
188
+ return memory_region_get_fd(mr);
189
+}
190
+
191
+static bool proxy_mrs_can_merge(uint64_t host, uint64_t prev_host, size_t size)
192
+{
193
+ if (((prev_host + size) != host)) {
194
+ return false;
195
+ }
196
+
197
+ if (get_fd_from_hostaddr(host, NULL) !=
198
+ get_fd_from_hostaddr(prev_host, NULL)) {
199
+ return false;
200
+ }
201
+
202
+ return true;
203
+}
204
+
205
+static bool try_merge(ProxyMemoryListener *proxy_listener,
206
+ MemoryRegionSection *section)
207
+{
208
+ uint64_t mrs_size, mrs_gpa, mrs_page;
209
+ MemoryRegionSection *prev_sec;
210
+ bool merged = false;
211
+ uintptr_t mrs_host;
212
+ RAMBlock *mrs_rb;
213
+
214
+ if (!proxy_listener->n_mr_sections) {
215
+ return false;
216
+ }
217
+
218
+ mrs_rb = section->mr->ram_block;
219
+ mrs_page = (uint64_t)qemu_ram_pagesize(mrs_rb);
220
+ mrs_size = int128_get64(section->size);
221
+ mrs_gpa = section->offset_within_address_space;
222
+ mrs_host = (uintptr_t)memory_region_get_ram_ptr(section->mr) +
223
+ section->offset_within_region;
224
+
225
+ if (get_fd_from_hostaddr(mrs_host, NULL) < 0) {
226
+ return true;
227
+ }
228
+
229
+ mrs_host = mrs_host & ~(mrs_page - 1);
230
+ mrs_gpa = mrs_gpa & ~(mrs_page - 1);
231
+ mrs_size = ROUND_UP(mrs_size, mrs_page);
232
+
233
+ prev_sec = proxy_listener->mr_sections +
234
+ (proxy_listener->n_mr_sections - 1);
235
+ uint64_t prev_gpa_start = prev_sec->offset_within_address_space;
236
+ uint64_t prev_size = int128_get64(prev_sec->size);
237
+ uint64_t prev_gpa_end = range_get_last(prev_gpa_start, prev_size);
238
+ uint64_t prev_host_start =
239
+ (uintptr_t)memory_region_get_ram_ptr(prev_sec->mr) +
240
+ prev_sec->offset_within_region;
241
+ uint64_t prev_host_end = range_get_last(prev_host_start, prev_size);
242
+
243
+ if (mrs_gpa <= (prev_gpa_end + 1)) {
244
+ g_assert(mrs_gpa > prev_gpa_start);
245
+
246
+ if ((section->mr == prev_sec->mr) &&
247
+ proxy_mrs_can_merge(mrs_host, prev_host_start,
248
+ (mrs_gpa - prev_gpa_start))) {
249
+ uint64_t max_end = MAX(prev_host_end, mrs_host + mrs_size);
250
+ merged = true;
251
+ prev_sec->offset_within_address_space =
252
+ MIN(prev_gpa_start, mrs_gpa);
253
+ prev_sec->offset_within_region =
254
+ MIN(prev_host_start, mrs_host) -
255
+ (uintptr_t)memory_region_get_ram_ptr(prev_sec->mr);
256
+ prev_sec->size = int128_make64(max_end - MIN(prev_host_start,
257
+ mrs_host));
258
+ }
259
+ }
260
+
261
+ return merged;
262
+}
263
+
264
+static void proxy_memory_listener_region_addnop(MemoryListener *listener,
265
+ MemoryRegionSection *section)
266
+{
267
+ ProxyMemoryListener *proxy_listener = container_of(listener,
268
+ ProxyMemoryListener,
269
+ listener);
270
+
271
+ if (!memory_region_is_ram(section->mr) ||
272
+ memory_region_is_rom(section->mr)) {
273
+ return;
274
+ }
275
+
276
+ if (try_merge(proxy_listener, section)) {
277
+ return;
278
+ }
279
+
280
+ ++proxy_listener->n_mr_sections;
281
+ proxy_listener->mr_sections = g_renew(MemoryRegionSection,
282
+ proxy_listener->mr_sections,
283
+ proxy_listener->n_mr_sections);
284
+ proxy_listener->mr_sections[proxy_listener->n_mr_sections - 1] = *section;
285
+ proxy_listener->mr_sections[proxy_listener->n_mr_sections - 1].fv = NULL;
286
+ memory_region_ref(section->mr);
287
+}
288
+
289
+static void proxy_memory_listener_commit(MemoryListener *listener)
290
+{
291
+ ProxyMemoryListener *proxy_listener = container_of(listener,
292
+ ProxyMemoryListener,
293
+ listener);
294
+ MPQemuMsg msg;
295
+ MemoryRegionSection *section;
296
+ ram_addr_t offset;
297
+ uintptr_t host_addr;
298
+ int region;
299
+ Error *local_err = NULL;
300
+
301
+ memset(&msg, 0, sizeof(MPQemuMsg));
302
+
303
+ msg.cmd = MPQEMU_CMD_SYNC_SYSMEM;
304
+ msg.num_fds = proxy_listener->n_mr_sections;
305
+ msg.size = sizeof(SyncSysmemMsg);
306
+ if (msg.num_fds > REMOTE_MAX_FDS) {
307
+ error_report("Number of fds is more than %d", REMOTE_MAX_FDS);
308
+ return;
309
+ }
310
+
311
+ for (region = 0; region < proxy_listener->n_mr_sections; region++) {
312
+ section = &proxy_listener->mr_sections[region];
313
+ msg.data.sync_sysmem.gpas[region] =
314
+ section->offset_within_address_space;
315
+ msg.data.sync_sysmem.sizes[region] = int128_get64(section->size);
316
+ host_addr = (uintptr_t)memory_region_get_ram_ptr(section->mr) +
317
+ section->offset_within_region;
318
+ msg.fds[region] = get_fd_from_hostaddr(host_addr, &offset);
319
+ msg.data.sync_sysmem.offsets[region] = offset;
320
+ }
321
+ if (!mpqemu_msg_send(&msg, proxy_listener->ioc, &local_err)) {
322
+ error_report_err(local_err);
323
+ }
324
+}
325
+
326
+void proxy_memory_listener_deconfigure(ProxyMemoryListener *proxy_listener)
327
+{
328
+ memory_listener_unregister(&proxy_listener->listener);
329
+
330
+ proxy_memory_listener_reset(&proxy_listener->listener);
331
+}
332
+
333
+void proxy_memory_listener_configure(ProxyMemoryListener *proxy_listener,
334
+ QIOChannel *ioc)
335
+{
336
+ proxy_listener->n_mr_sections = 0;
337
+ proxy_listener->mr_sections = NULL;
338
+
339
+ proxy_listener->ioc = ioc;
340
+
341
+ proxy_listener->listener.begin = proxy_memory_listener_reset;
342
+ proxy_listener->listener.commit = proxy_memory_listener_commit;
343
+ proxy_listener->listener.region_add = proxy_memory_listener_region_addnop;
344
+ proxy_listener->listener.region_nop = proxy_memory_listener_region_addnop;
345
+ proxy_listener->listener.priority = 10;
346
+
347
+ memory_listener_register(&proxy_listener->listener,
348
+ &address_space_memory);
349
+}
350
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
351
index XXXXXXX..XXXXXXX 100644
352
--- a/hw/remote/proxy.c
353
+++ b/hw/remote/proxy.c
354
@@ -XXX,XX +XXX,XX @@
355
#include "qemu/sockets.h"
356
#include "hw/remote/mpqemu-link.h"
357
#include "qemu/error-report.h"
358
+#include "hw/remote/proxy-memory-listener.h"
359
+#include "qom/object.h"
360
361
static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
362
{
363
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
364
365
qemu_mutex_init(&dev->io_mutex);
366
qio_channel_set_blocking(dev->ioc, true, NULL);
367
+
368
+ proxy_memory_listener_configure(&dev->proxy_listener, dev->ioc);
19
}
369
}
20
370
21
static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
371
static void pci_proxy_dev_exit(PCIDevice *pdev)
22
- const char *desc_file_path, QDict *options,
372
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_exit(PCIDevice *pdev)
23
- Error **errp)
373
migrate_del_blocker(dev->migration_blocker);
24
+ QDict *options, Error **errp)
374
25
{
375
error_free(dev->migration_blocker);
26
int ret;
376
+
27
int matches;
377
+ proxy_memory_listener_deconfigure(&dev->proxy_listener);
28
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
29
const char *p, *np;
30
int64_t sectors = 0;
31
int64_t flat_offset;
32
+ char *desc_file_dir = NULL;
33
char *extent_path;
34
BdrvChild *extent_file;
35
BDRVVmdkState *s = bs->opaque;
36
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
37
continue;
38
}
39
40
- if (!path_is_absolute(fname) && !path_has_protocol(fname) &&
41
- !desc_file_path[0])
42
- {
43
- bdrv_refresh_filename(bs->file->bs);
44
- error_setg(errp, "Cannot use relative extent paths with VMDK "
45
- "descriptor file '%s'", bs->file->bs->filename);
46
- return -EINVAL;
47
- }
48
+ if (path_is_absolute(fname)) {
49
+ extent_path = g_strdup(fname);
50
+ } else {
51
+ if (!desc_file_dir) {
52
+ desc_file_dir = bdrv_dirname(bs->file->bs, errp);
53
+ if (!desc_file_dir) {
54
+ bdrv_refresh_filename(bs->file->bs);
55
+ error_prepend(errp, "Cannot use relative paths with VMDK "
56
+ "descriptor file '%s': ",
57
+ bs->file->bs->filename);
58
+ ret = -EINVAL;
59
+ goto out;
60
+ }
61
+ }
62
63
- extent_path = path_combine(desc_file_path, fname);
64
+ extent_path = g_strconcat(desc_file_dir, fname, NULL);
65
+ }
66
67
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
68
assert(ret < 32);
69
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
70
g_free(extent_path);
71
if (local_err) {
72
error_propagate(errp, local_err);
73
- return -EINVAL;
74
+ ret = -EINVAL;
75
+ goto out;
76
}
77
78
/* save to extents array */
79
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
80
0, 0, 0, 0, 0, &extent, errp);
81
if (ret < 0) {
82
bdrv_unref_child(bs, extent_file);
83
- return ret;
84
+ goto out;
85
}
86
extent->flat_start_offset = flat_offset << 9;
87
} else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) {
88
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
89
g_free(buf);
90
if (ret) {
91
bdrv_unref_child(bs, extent_file);
92
- return ret;
93
+ goto out;
94
}
95
extent = &s->extents[s->num_extents - 1];
96
} else if (!strcmp(type, "SESPARSE")) {
97
ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
98
if (ret) {
99
bdrv_unref_child(bs, extent_file);
100
- return ret;
101
+ goto out;
102
}
103
extent = &s->extents[s->num_extents - 1];
104
} else {
105
error_setg(errp, "Unsupported extent type '%s'", type);
106
bdrv_unref_child(bs, extent_file);
107
- return -ENOTSUP;
108
+ ret = -ENOTSUP;
109
+ goto out;
110
}
111
extent->type = g_strdup(type);
112
}
113
- return 0;
114
+
115
+ ret = 0;
116
+ goto out;
117
118
invalid:
119
np = next_line(p);
120
@@ -XXX,XX +XXX,XX @@ invalid:
121
np--;
122
}
123
error_setg(errp, "Invalid extent line: %.*s", (int)(np - p), p);
124
- return -EINVAL;
125
+ ret = -EINVAL;
126
+
127
+out:
128
+ g_free(desc_file_dir);
129
+ return ret;
130
}
378
}
131
379
132
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
380
static void config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val,
133
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
381
diff --git a/hw/remote/meson.build b/hw/remote/meson.build
134
}
382
index XXXXXXX..XXXXXXX 100644
135
s->create_type = g_strdup(ct);
383
--- a/hw/remote/meson.build
136
s->desc_offset = 0;
384
+++ b/hw/remote/meson.build
137
- ret = vmdk_parse_extents(buf, bs, bs->file->bs->exact_filename, options,
385
@@ -XXX,XX +XXX,XX @@ remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('remote-obj.c'))
138
- errp);
386
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy.c'))
139
+ ret = vmdk_parse_extents(buf, bs, options, errp);
387
140
exit:
388
specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('memory.c'))
141
return ret;
389
+specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy-memory-listener.c'))
142
}
390
143
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
391
softmmu_ss.add_all(when: 'CONFIG_MULTIPROCESS', if_true: remote_ss)
144
index XXXXXXX..XXXXXXX 100755
145
--- a/tests/qemu-iotests/059
146
+++ b/tests/qemu-iotests/059
147
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2
148
149
echo
150
echo "=== Testing monolithicFlat with internally generated JSON file name ==="
151
+# Should work, because bdrv_dirname() works fine with blkdebug
152
IMGOPTS="subformat=monolithicFlat" _make_test_img 64M
153
-$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" 2>&1 \
154
- | _filter_testdir | _filter_imgfmt
155
+$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.image.filename=$TEST_IMG,file.inject-error.0.event=read_aio" \
156
+ -c info \
157
+ 2>&1 \
158
+ | _filter_testdir | _filter_imgfmt | _filter_img_info
159
_cleanup_test_img
160
161
echo
162
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
163
index XXXXXXX..XXXXXXX 100644
164
--- a/tests/qemu-iotests/059.out
165
+++ b/tests/qemu-iotests/059.out
166
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 10240
167
168
=== Testing monolithicFlat with internally generated JSON file name ===
169
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
170
-qemu-io: can't open: Cannot use relative extent paths with VMDK descriptor file 'json:{"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "read_aio"}'
171
+format name: IMGFMT
172
+cluster size: 0 bytes
173
+vm state offset: 0 bytes
174
175
=== Testing version 3 ===
176
image: TEST_DIR/iotest-version3.IMGFMT
177
--
392
--
178
2.21.0
393
2.29.2
179
394
180
diff view generated by jsdifflib
1
From: Nir Soffer <nirsof@gmail.com>
1
From: Jagannathan Raman <jag.raman@oracle.com>
2
2
3
When creating an image with preallocation "off" or "falloc", the first
3
IOHUB object is added to manage PCI IRQs. It uses KVM_IRQFD
4
block of the image is typically not allocated. When using Gluster
4
ioctl to create irqfd to injecting PCI interrupts to the guest.
5
storage backed by XFS filesystem, reading this block using direct I/O
5
IOHUB object forwards the irqfd to the remote process. Remote process
6
succeeds regardless of request length, fooling alignment detection.
6
uses this fd to directly send interrupts to the guest, bypassing QEMU.
7
7
8
In this case we fallback to a safe value (4096) instead of the optimal
8
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
9
value (512), which may lead to unneeded data copying when aligning
9
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
10
requests. Allocating the first block avoids the fallback.
10
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-id: 51d5c3d54e28a68b002e3875c59599c9f5a424a1.1611938319.git.jag.raman@oracle.com
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
---
15
MAINTAINERS | 2 +
16
include/hw/pci/pci_ids.h | 3 +
17
include/hw/remote/iohub.h | 42 +++++++++++
18
include/hw/remote/machine.h | 2 +
19
include/hw/remote/mpqemu-link.h | 1 +
20
include/hw/remote/proxy.h | 4 ++
21
hw/remote/iohub.c | 119 ++++++++++++++++++++++++++++++++
22
hw/remote/machine.c | 10 +++
23
hw/remote/message.c | 4 ++
24
hw/remote/mpqemu-link.c | 5 ++
25
hw/remote/proxy.c | 56 +++++++++++++++
26
hw/remote/meson.build | 1 +
27
12 files changed, 249 insertions(+)
28
create mode 100644 include/hw/remote/iohub.h
29
create mode 100644 hw/remote/iohub.c
11
30
12
Since we allocate the first block even with preallocation=off, we no
31
diff --git a/MAINTAINERS b/MAINTAINERS
13
longer create images with zero disk size:
32
index XXXXXXX..XXXXXXX 100644
14
33
--- a/MAINTAINERS
15
$ ./qemu-img create -f raw test.raw 1g
34
+++ b/MAINTAINERS
16
Formatting 'test.raw', fmt=raw size=1073741824
35
@@ -XXX,XX +XXX,XX @@ F: hw/remote/proxy.c
17
36
F: include/hw/remote/proxy.h
18
$ ls -lhs test.raw
37
F: hw/remote/proxy-memory-listener.c
19
4.0K -rw-r--r--. 1 nsoffer nsoffer 1.0G Aug 16 23:48 test.raw
38
F: include/hw/remote/proxy-memory-listener.h
20
39
+F: hw/remote/iohub.c
21
And converting the image requires additional cluster:
40
+F: include/hw/remote/iohub.h
22
41
23
$ ./qemu-img measure -f raw -O qcow2 test.raw
42
Build and test automation
24
required size: 458752
43
-------------------------
25
fully allocated size: 1074135040
44
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
26
45
index XXXXXXX..XXXXXXX 100644
27
When using format like vmdk with multiple files per image, we allocate
46
--- a/include/hw/pci/pci_ids.h
28
one block per file:
47
+++ b/include/hw/pci/pci_ids.h
29
48
@@ -XXX,XX +XXX,XX @@
30
$ ./qemu-img create -f vmdk -o subformat=twoGbMaxExtentFlat test.vmdk 4g
49
#define PCI_DEVICE_ID_SUN_SIMBA 0x5000
31
Formatting 'test.vmdk', fmt=vmdk size=4294967296 compat6=off hwversion=undefined subformat=twoGbMaxExtentFlat
50
#define PCI_DEVICE_ID_SUN_SABRE 0xa000
32
51
33
$ ls -lhs test*.vmdk
52
+#define PCI_VENDOR_ID_ORACLE 0x108e
34
4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f001.vmdk
53
+#define PCI_DEVICE_ID_REMOTE_IOHUB 0xb000
35
4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f002.vmdk
54
+
36
4.0K -rw-r--r--. 1 nsoffer nsoffer 353 Aug 27 03:23 test.vmdk
55
#define PCI_VENDOR_ID_CMD 0x1095
37
56
#define PCI_DEVICE_ID_CMD_646 0x0646
38
I did quick performance test for copying disks with qemu-img convert to
57
39
new raw target image to Gluster storage with sector size of 512 bytes:
58
diff --git a/include/hw/remote/iohub.h b/include/hw/remote/iohub.h
40
41
for i in $(seq 10); do
42
rm -f dst.raw
43
sleep 10
44
time ./qemu-img convert -f raw -O raw -t none -T none src.raw dst.raw
45
done
46
47
Here is a table comparing the total time spent:
48
49
Type Before(s) After(s) Diff(%)
50
---------------------------------------
51
real 530.028 469.123 -11.4
52
user 17.204 10.768 -37.4
53
sys 17.881 7.011 -60.7
54
55
We can see very clear improvement in CPU usage.
56
57
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
58
Message-id: 20190827010528.8818-2-nsoffer@redhat.com
59
Reviewed-by: Max Reitz <mreitz@redhat.com>
60
Signed-off-by: Max Reitz <mreitz@redhat.com>
61
---
62
block/file-posix.c | 51 +++++++++++++++++++
63
tests/qemu-iotests/059.out | 2 +-
64
tests/qemu-iotests/{150.out => 150.out.qcow2} | 0
65
tests/qemu-iotests/150.out.raw | 12 +++++
66
tests/qemu-iotests/175 | 19 ++++---
67
tests/qemu-iotests/175.out | 8 +--
68
tests/qemu-iotests/178.out.qcow2 | 4 +-
69
tests/qemu-iotests/221.out | 12 +++--
70
tests/qemu-iotests/253.out | 12 +++--
71
9 files changed, 99 insertions(+), 21 deletions(-)
72
rename tests/qemu-iotests/{150.out => 150.out.qcow2} (100%)
73
create mode 100644 tests/qemu-iotests/150.out.raw
74
75
diff --git a/block/file-posix.c b/block/file-posix.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/file-posix.c
78
+++ b/block/file-posix.c
79
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_discard(void *opaque)
80
return ret;
81
}
82
83
+/*
84
+ * Help alignment probing by allocating the first block.
85
+ *
86
+ * When reading with direct I/O from unallocated area on Gluster backed by XFS,
87
+ * reading succeeds regardless of request length. In this case we fallback to
88
+ * safe alignment which is not optimal. Allocating the first block avoids this
89
+ * fallback.
90
+ *
91
+ * fd may be opened with O_DIRECT, but we don't know the buffer alignment or
92
+ * request alignment, so we use safe values.
93
+ *
94
+ * Returns: 0 on success, -errno on failure. Since this is an optimization,
95
+ * caller may ignore failures.
96
+ */
97
+static int allocate_first_block(int fd, size_t max_size)
98
+{
99
+ size_t write_size = (max_size < MAX_BLOCKSIZE)
100
+ ? BDRV_SECTOR_SIZE
101
+ : MAX_BLOCKSIZE;
102
+ size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize());
103
+ void *buf;
104
+ ssize_t n;
105
+ int ret;
106
+
107
+ buf = qemu_memalign(max_align, write_size);
108
+ memset(buf, 0, write_size);
109
+
110
+ do {
111
+ n = pwrite(fd, buf, write_size, 0);
112
+ } while (n == -1 && errno == EINTR);
113
+
114
+ ret = (n == -1) ? -errno : 0;
115
+
116
+ qemu_vfree(buf);
117
+ return ret;
118
+}
119
+
120
static int handle_aiocb_truncate(void *opaque)
121
{
122
RawPosixAIOData *aiocb = opaque;
123
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_truncate(void *opaque)
124
/* posix_fallocate() doesn't set errno. */
125
error_setg_errno(errp, -result,
126
"Could not preallocate new data");
127
+ } else if (current_length == 0) {
128
+ /*
129
+ * posix_fallocate() uses fallocate() if the filesystem
130
+ * supports it, or fallback to manually writing zeroes. If
131
+ * fallocate() was used, unaligned reads from the fallocated
132
+ * area in raw_probe_alignment() will succeed, hence we need to
133
+ * allocate the first block.
134
+ *
135
+ * Optimize future alignment probing; ignore failures.
136
+ */
137
+ allocate_first_block(fd, offset);
138
}
139
} else {
140
result = 0;
141
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_truncate(void *opaque)
142
if (ftruncate(fd, offset) != 0) {
143
result = -errno;
144
error_setg_errno(errp, -result, "Could not resize file");
145
+ } else if (current_length == 0 && offset > current_length) {
146
+ /* Optimize future alignment probing; ignore failures. */
147
+ allocate_first_block(fd, offset);
148
}
149
return result;
150
default:
151
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
152
index XXXXXXX..XXXXXXX 100644
153
--- a/tests/qemu-iotests/059.out
154
+++ b/tests/qemu-iotests/059.out
155
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMax
156
image: TEST_DIR/t.vmdk
157
file format: vmdk
158
virtual size: 0.977 TiB (1073741824000 bytes)
159
-disk size: 16 KiB
160
+disk size: 1.97 MiB
161
Format specific information:
162
cid: XXXXXXXX
163
parent cid: XXXXXXXX
164
diff --git a/tests/qemu-iotests/150.out b/tests/qemu-iotests/150.out.qcow2
165
similarity index 100%
166
rename from tests/qemu-iotests/150.out
167
rename to tests/qemu-iotests/150.out.qcow2
168
diff --git a/tests/qemu-iotests/150.out.raw b/tests/qemu-iotests/150.out.raw
169
new file mode 100644
59
new file mode 100644
170
index XXXXXXX..XXXXXXX
60
index XXXXXXX..XXXXXXX
171
--- /dev/null
61
--- /dev/null
172
+++ b/tests/qemu-iotests/150.out.raw
62
+++ b/include/hw/remote/iohub.h
173
@@ -XXX,XX +XXX,XX @@
63
@@ -XXX,XX +XXX,XX @@
174
+QA output created by 150
64
+/*
175
+
65
+ * IO Hub for remote device
176
+=== Mapping sparse conversion ===
66
+ *
177
+
67
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
178
+Offset Length File
68
+ *
179
+0 0x1000 TEST_DIR/t.IMGFMT
69
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
180
+
70
+ * See the COPYING file in the top-level directory.
181
+=== Mapping non-sparse conversion ===
71
+ *
182
+
72
+ */
183
+Offset Length File
73
+
184
+0 0x100000 TEST_DIR/t.IMGFMT
74
+#ifndef REMOTE_IOHUB_H
185
+*** done
75
+#define REMOTE_IOHUB_H
186
diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175
76
+
187
index XXXXXXX..XXXXXXX 100755
77
+#include "hw/pci/pci.h"
188
--- a/tests/qemu-iotests/175
78
+#include "qemu/event_notifier.h"
189
+++ b/tests/qemu-iotests/175
79
+#include "qemu/thread-posix.h"
190
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
80
+#include "hw/remote/mpqemu-link.h"
191
# the file size. This function hides the resulting difference in the
81
+
192
# stat -c '%b' output.
82
+#define REMOTE_IOHUB_NB_PIRQS PCI_DEVFN_MAX
193
# Parameter 1: Number of blocks an empty file occupies
83
+
194
-# Parameter 2: Image size in bytes
84
+typedef struct ResampleToken {
195
+# Parameter 2: Minimal number of blocks in an image
85
+ void *iohub;
196
+# Parameter 3: Image size in bytes
86
+ int pirq;
197
_filter_blocks()
87
+} ResampleToken;
88
+
89
+typedef struct RemoteIOHubState {
90
+ PCIDevice d;
91
+ EventNotifier irqfds[REMOTE_IOHUB_NB_PIRQS];
92
+ EventNotifier resamplefds[REMOTE_IOHUB_NB_PIRQS];
93
+ unsigned int irq_level[REMOTE_IOHUB_NB_PIRQS];
94
+ ResampleToken token[REMOTE_IOHUB_NB_PIRQS];
95
+ QemuMutex irq_level_lock[REMOTE_IOHUB_NB_PIRQS];
96
+} RemoteIOHubState;
97
+
98
+int remote_iohub_map_irq(PCIDevice *pci_dev, int intx);
99
+void remote_iohub_set_irq(void *opaque, int pirq, int level);
100
+void process_set_irqfd_msg(PCIDevice *pci_dev, MPQemuMsg *msg);
101
+
102
+void remote_iohub_init(RemoteIOHubState *iohub);
103
+void remote_iohub_finalize(RemoteIOHubState *iohub);
104
+
105
+#endif
106
diff --git a/include/hw/remote/machine.h b/include/hw/remote/machine.h
107
index XXXXXXX..XXXXXXX 100644
108
--- a/include/hw/remote/machine.h
109
+++ b/include/hw/remote/machine.h
110
@@ -XXX,XX +XXX,XX @@
111
#include "hw/boards.h"
112
#include "hw/pci-host/remote.h"
113
#include "io/channel.h"
114
+#include "hw/remote/iohub.h"
115
116
struct RemoteMachineState {
117
MachineState parent_obj;
118
119
RemotePCIHost *host;
120
+ RemoteIOHubState iohub;
121
};
122
123
/* Used to pass to co-routine device and ioc. */
124
diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h
125
index XXXXXXX..XXXXXXX 100644
126
--- a/include/hw/remote/mpqemu-link.h
127
+++ b/include/hw/remote/mpqemu-link.h
128
@@ -XXX,XX +XXX,XX @@ typedef enum {
129
MPQEMU_CMD_PCI_CFGREAD,
130
MPQEMU_CMD_BAR_WRITE,
131
MPQEMU_CMD_BAR_READ,
132
+ MPQEMU_CMD_SET_IRQFD,
133
MPQEMU_CMD_MAX,
134
} MPQemuCmd;
135
136
diff --git a/include/hw/remote/proxy.h b/include/hw/remote/proxy.h
137
index XXXXXXX..XXXXXXX 100644
138
--- a/include/hw/remote/proxy.h
139
+++ b/include/hw/remote/proxy.h
140
@@ -XXX,XX +XXX,XX @@
141
#include "hw/pci/pci.h"
142
#include "io/channel.h"
143
#include "hw/remote/proxy-memory-listener.h"
144
+#include "qemu/event_notifier.h"
145
146
#define TYPE_PCI_PROXY_DEV "x-pci-proxy-dev"
147
OBJECT_DECLARE_SIMPLE_TYPE(PCIProxyDev, PCI_PROXY_DEV)
148
@@ -XXX,XX +XXX,XX @@ struct PCIProxyDev {
149
QIOChannel *ioc;
150
Error *migration_blocker;
151
ProxyMemoryListener proxy_listener;
152
+ int virq;
153
+ EventNotifier intr;
154
+ EventNotifier resample;
155
ProxyMemoryRegion region[PCI_NUM_REGIONS];
156
};
157
158
diff --git a/hw/remote/iohub.c b/hw/remote/iohub.c
159
new file mode 100644
160
index XXXXXXX..XXXXXXX
161
--- /dev/null
162
+++ b/hw/remote/iohub.c
163
@@ -XXX,XX +XXX,XX @@
164
+/*
165
+ * Remote IO Hub
166
+ *
167
+ * Copyright © 2018, 2021 Oracle and/or its affiliates.
168
+ *
169
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
170
+ * See the COPYING file in the top-level directory.
171
+ *
172
+ */
173
+
174
+#include "qemu/osdep.h"
175
+#include "qemu-common.h"
176
+
177
+#include "hw/pci/pci.h"
178
+#include "hw/pci/pci_ids.h"
179
+#include "hw/pci/pci_bus.h"
180
+#include "qemu/thread.h"
181
+#include "hw/boards.h"
182
+#include "hw/remote/machine.h"
183
+#include "hw/remote/iohub.h"
184
+#include "qemu/main-loop.h"
185
+
186
+void remote_iohub_init(RemoteIOHubState *iohub)
187
+{
188
+ int pirq;
189
+
190
+ memset(&iohub->irqfds, 0, sizeof(iohub->irqfds));
191
+ memset(&iohub->resamplefds, 0, sizeof(iohub->resamplefds));
192
+
193
+ for (pirq = 0; pirq < REMOTE_IOHUB_NB_PIRQS; pirq++) {
194
+ qemu_mutex_init(&iohub->irq_level_lock[pirq]);
195
+ iohub->irq_level[pirq] = 0;
196
+ event_notifier_init_fd(&iohub->irqfds[pirq], -1);
197
+ event_notifier_init_fd(&iohub->resamplefds[pirq], -1);
198
+ }
199
+}
200
+
201
+void remote_iohub_finalize(RemoteIOHubState *iohub)
202
+{
203
+ int pirq;
204
+
205
+ for (pirq = 0; pirq < REMOTE_IOHUB_NB_PIRQS; pirq++) {
206
+ qemu_set_fd_handler(event_notifier_get_fd(&iohub->resamplefds[pirq]),
207
+ NULL, NULL, NULL);
208
+ event_notifier_cleanup(&iohub->irqfds[pirq]);
209
+ event_notifier_cleanup(&iohub->resamplefds[pirq]);
210
+ qemu_mutex_destroy(&iohub->irq_level_lock[pirq]);
211
+ }
212
+}
213
+
214
+int remote_iohub_map_irq(PCIDevice *pci_dev, int intx)
215
+{
216
+ return pci_dev->devfn;
217
+}
218
+
219
+void remote_iohub_set_irq(void *opaque, int pirq, int level)
220
+{
221
+ RemoteIOHubState *iohub = opaque;
222
+
223
+ assert(pirq >= 0);
224
+ assert(pirq < PCI_DEVFN_MAX);
225
+
226
+ QEMU_LOCK_GUARD(&iohub->irq_level_lock[pirq]);
227
+
228
+ if (level) {
229
+ if (++iohub->irq_level[pirq] == 1) {
230
+ event_notifier_set(&iohub->irqfds[pirq]);
231
+ }
232
+ } else if (iohub->irq_level[pirq] > 0) {
233
+ iohub->irq_level[pirq]--;
234
+ }
235
+}
236
+
237
+static void intr_resample_handler(void *opaque)
238
+{
239
+ ResampleToken *token = opaque;
240
+ RemoteIOHubState *iohub = token->iohub;
241
+ int pirq, s;
242
+
243
+ pirq = token->pirq;
244
+
245
+ s = event_notifier_test_and_clear(&iohub->resamplefds[pirq]);
246
+
247
+ assert(s >= 0);
248
+
249
+ QEMU_LOCK_GUARD(&iohub->irq_level_lock[pirq]);
250
+
251
+ if (iohub->irq_level[pirq]) {
252
+ event_notifier_set(&iohub->irqfds[pirq]);
253
+ }
254
+}
255
+
256
+void process_set_irqfd_msg(PCIDevice *pci_dev, MPQemuMsg *msg)
257
+{
258
+ RemoteMachineState *machine = REMOTE_MACHINE(current_machine);
259
+ RemoteIOHubState *iohub = &machine->iohub;
260
+ int pirq, intx;
261
+
262
+ intx = pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
263
+
264
+ pirq = remote_iohub_map_irq(pci_dev, intx);
265
+
266
+ if (event_notifier_get_fd(&iohub->irqfds[pirq]) != -1) {
267
+ qemu_set_fd_handler(event_notifier_get_fd(&iohub->resamplefds[pirq]),
268
+ NULL, NULL, NULL);
269
+ event_notifier_cleanup(&iohub->irqfds[pirq]);
270
+ event_notifier_cleanup(&iohub->resamplefds[pirq]);
271
+ memset(&iohub->token[pirq], 0, sizeof(ResampleToken));
272
+ }
273
+
274
+ event_notifier_init_fd(&iohub->irqfds[pirq], msg->fds[0]);
275
+ event_notifier_init_fd(&iohub->resamplefds[pirq], msg->fds[1]);
276
+
277
+ iohub->token[pirq].iohub = iohub;
278
+ iohub->token[pirq].pirq = pirq;
279
+
280
+ qemu_set_fd_handler(msg->fds[1], intr_resample_handler, NULL,
281
+ &iohub->token[pirq]);
282
+}
283
diff --git a/hw/remote/machine.c b/hw/remote/machine.c
284
index XXXXXXX..XXXXXXX 100644
285
--- a/hw/remote/machine.c
286
+++ b/hw/remote/machine.c
287
@@ -XXX,XX +XXX,XX @@
288
#include "exec/address-spaces.h"
289
#include "exec/memory.h"
290
#include "qapi/error.h"
291
+#include "hw/pci/pci_host.h"
292
+#include "hw/remote/iohub.h"
293
294
static void remote_machine_init(MachineState *machine)
198
{
295
{
199
extra_blocks=$1
296
MemoryRegion *system_memory, *system_io, *pci_memory;
200
- img_size=$2
297
RemoteMachineState *s = REMOTE_MACHINE(machine);
201
+ min_blocks=$2
298
RemotePCIHost *rem_host;
202
+ img_size=$3
299
+ PCIHostState *pci_host;
203
300
204
- sed -e "s/blocks=$extra_blocks\\(\$\\|[^0-9]\\)/nothing allocated/" \
301
system_memory = get_system_memory();
205
- -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/everything allocated/"
302
system_io = get_system_io();
206
+ sed -e "s/blocks=$min_blocks\\(\$\\|[^0-9]\\)/min allocation/" \
303
@@ -XXX,XX +XXX,XX @@ static void remote_machine_init(MachineState *machine)
207
+ -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/"
304
memory_region_add_subregion_overlap(system_memory, 0x0, pci_memory, -1);
305
306
qdev_realize(DEVICE(rem_host), sysbus_get_default(), &error_fatal);
307
+
308
+ pci_host = PCI_HOST_BRIDGE(rem_host);
309
+
310
+ remote_iohub_init(&s->iohub);
311
+
312
+ pci_bus_irqs(pci_host->bus, remote_iohub_set_irq, remote_iohub_map_irq,
313
+ &s->iohub, REMOTE_IOHUB_NB_PIRQS);
208
}
314
}
209
315
210
# get standard environment, filters and checks
316
static void remote_machine_class_init(ObjectClass *oc, void *data)
211
@@ -XXX,XX +XXX,XX @@ size=$((1 * 1024 * 1024))
317
diff --git a/hw/remote/message.c b/hw/remote/message.c
212
touch "$TEST_DIR/empty"
318
index XXXXXXX..XXXXXXX 100644
213
extra_blocks=$(stat -c '%b' "$TEST_DIR/empty")
319
--- a/hw/remote/message.c
214
320
+++ b/hw/remote/message.c
215
+# We always write the first byte; check how many blocks this filesystem
321
@@ -XXX,XX +XXX,XX @@
216
+# allocates to match empty image alloation.
322
#include "hw/pci/pci.h"
217
+printf "\0" > "$TEST_DIR/empty"
323
#include "exec/memattrs.h"
218
+min_blocks=$(stat -c '%b' "$TEST_DIR/empty")
324
#include "hw/remote/memory.h"
219
+
325
+#include "hw/remote/iohub.h"
220
echo
326
221
echo "== creating image with default preallocation =="
327
static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
222
_make_test_img $size | _filter_imgfmt
328
MPQemuMsg *msg, Error **errp);
223
-stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size
329
@@ -XXX,XX +XXX,XX @@ void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
224
+stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
330
case MPQEMU_CMD_SYNC_SYSMEM:
225
331
remote_sysmem_reconfig(&msg, &local_err);
226
for mode in off full falloc; do
332
break;
227
echo
333
+ case MPQEMU_CMD_SET_IRQFD:
228
echo "== creating image with preallocation $mode =="
334
+ process_set_irqfd_msg(pci_dev, &msg);
229
IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt
335
+ break;
230
- stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size
336
default:
231
+ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
337
error_setg(&local_err,
232
done
338
"Unknown command (%d) received for device %s"
233
339
diff --git a/hw/remote/mpqemu-link.c b/hw/remote/mpqemu-link.c
234
# success, all done
340
index XXXXXXX..XXXXXXX 100644
235
diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out
341
--- a/hw/remote/mpqemu-link.c
236
index XXXXXXX..XXXXXXX 100644
342
+++ b/hw/remote/mpqemu-link.c
237
--- a/tests/qemu-iotests/175.out
343
@@ -XXX,XX +XXX,XX @@ bool mpqemu_msg_valid(MPQemuMsg *msg)
238
+++ b/tests/qemu-iotests/175.out
344
return false;
239
@@ -XXX,XX +XXX,XX @@ QA output created by 175
345
}
240
346
break;
241
== creating image with default preallocation ==
347
+ case MPQEMU_CMD_SET_IRQFD:
242
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
348
+ if (msg->size || (msg->num_fds != 2)) {
243
-size=1048576, nothing allocated
349
+ return false;
244
+size=1048576, min allocation
350
+ }
245
351
+ break;
246
== creating image with preallocation off ==
352
default:
247
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off
353
break;
248
-size=1048576, nothing allocated
354
}
249
+size=1048576, min allocation
355
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
250
356
index XXXXXXX..XXXXXXX 100644
251
== creating image with preallocation full ==
357
--- a/hw/remote/proxy.c
252
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full
358
+++ b/hw/remote/proxy.c
253
-size=1048576, everything allocated
359
@@ -XXX,XX +XXX,XX @@
254
+size=1048576, max allocation
360
#include "qemu/error-report.h"
255
361
#include "hw/remote/proxy-memory-listener.h"
256
== creating image with preallocation falloc ==
362
#include "qom/object.h"
257
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc
363
+#include "qemu/event_notifier.h"
258
-size=1048576, everything allocated
364
+#include "sysemu/kvm.h"
259
+size=1048576, max allocation
365
+#include "util/event_notifier-posix.c"
260
*** done
366
+
261
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
367
+static void proxy_intx_update(PCIDevice *pci_dev)
262
index XXXXXXX..XXXXXXX 100644
368
+{
263
--- a/tests/qemu-iotests/178.out.qcow2
369
+ PCIProxyDev *dev = PCI_PROXY_DEV(pci_dev);
264
+++ b/tests/qemu-iotests/178.out.qcow2
370
+ PCIINTxRoute route;
265
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 196608
371
+ int pin = pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;
266
== raw input image with data (human) ==
372
+
267
373
+ if (dev->virq != -1) {
268
Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824
374
+ kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &dev->intr, dev->virq);
269
-required size: 393216
375
+ dev->virq = -1;
270
+required size: 458752
376
+ }
271
fully allocated size: 1074135040
377
+
272
wrote 512/512 bytes at offset 512
378
+ route = pci_device_route_intx_to_irq(pci_dev, pin);
273
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+
274
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 196608
380
+ dev->virq = route.irq;
275
381
+
276
Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824
382
+ if (dev->virq != -1) {
383
+ kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, &dev->intr,
384
+ &dev->resample, dev->virq);
385
+ }
386
+}
387
+
388
+static void setup_irqfd(PCIProxyDev *dev)
389
+{
390
+ PCIDevice *pci_dev = PCI_DEVICE(dev);
391
+ MPQemuMsg msg;
392
+ Error *local_err = NULL;
393
+
394
+ event_notifier_init(&dev->intr, 0);
395
+ event_notifier_init(&dev->resample, 0);
396
+
397
+ memset(&msg, 0, sizeof(MPQemuMsg));
398
+ msg.cmd = MPQEMU_CMD_SET_IRQFD;
399
+ msg.num_fds = 2;
400
+ msg.fds[0] = event_notifier_get_fd(&dev->intr);
401
+ msg.fds[1] = event_notifier_get_fd(&dev->resample);
402
+ msg.size = 0;
403
+
404
+ if (!mpqemu_msg_send(&msg, dev->ioc, &local_err)) {
405
+ error_report_err(local_err);
406
+ }
407
+
408
+ dev->virq = -1;
409
+
410
+ proxy_intx_update(pci_dev);
411
+
412
+ pci_device_set_intx_routing_notifier(pci_dev, proxy_intx_update);
413
+}
414
415
static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
277
{
416
{
278
- "required": 393216,
417
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
279
+ "required": 458752,
418
qio_channel_set_blocking(dev->ioc, true, NULL);
280
"fully-allocated": 1074135040
419
420
proxy_memory_listener_configure(&dev->proxy_listener, dev->ioc);
421
+
422
+ setup_irqfd(dev);
281
}
423
}
282
wrote 512/512 bytes at offset 512
424
283
diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out
425
static void pci_proxy_dev_exit(PCIDevice *pdev)
284
index XXXXXXX..XXXXXXX 100644
426
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_exit(PCIDevice *pdev)
285
--- a/tests/qemu-iotests/221.out
427
error_free(dev->migration_blocker);
286
+++ b/tests/qemu-iotests/221.out
428
287
@@ -XXX,XX +XXX,XX @@ QA output created by 221
429
proxy_memory_listener_deconfigure(&dev->proxy_listener);
288
=== Check mapping of unaligned raw image ===
430
+
289
431
+ event_notifier_cleanup(&dev->intr);
290
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65537
432
+ event_notifier_cleanup(&dev->resample);
291
-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
433
}
292
-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
434
293
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
435
static void config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val,
294
+{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
436
diff --git a/hw/remote/meson.build b/hw/remote/meson.build
295
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
437
index XXXXXXX..XXXXXXX 100644
296
+{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
438
--- a/hw/remote/meson.build
297
wrote 1/1 bytes at offset 65536
439
+++ b/hw/remote/meson.build
298
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
440
@@ -XXX,XX +XXX,XX @@ remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('mpqemu-link.c'))
299
-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
441
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('message.c'))
300
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
442
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('remote-obj.c'))
301
+{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
443
remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy.c'))
302
{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
444
+remote_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('iohub.c'))
303
{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
445
304
-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
446
specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('memory.c'))
305
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
447
specific_ss.add(when: 'CONFIG_MULTIPROCESS', if_true: files('proxy-memory-listener.c'))
306
+{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
307
{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
308
{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
309
*** done
310
diff --git a/tests/qemu-iotests/253.out b/tests/qemu-iotests/253.out
311
index XXXXXXX..XXXXXXX 100644
312
--- a/tests/qemu-iotests/253.out
313
+++ b/tests/qemu-iotests/253.out
314
@@ -XXX,XX +XXX,XX @@ QA output created by 253
315
=== Check mapping of unaligned raw image ===
316
317
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575
318
-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
319
-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
320
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
321
+{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
322
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
323
+{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
324
wrote 65535/65535 bytes at offset 983040
325
63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
326
-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
327
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
328
+{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
329
{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
330
-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
331
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
332
+{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
333
{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
334
*** done
335
--
448
--
336
2.21.0
449
2.29.2
337
450
338
diff view generated by jsdifflib
1
streamOptimized does not support writes that do not span exactly one
1
From: Jagannathan Raman <jag.raman@oracle.com>
2
cluster. Furthermore, it cannot rewrite already allocated clusters.
3
As such, many iotests do not work with it. Disable them.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Retrieve PCI configuration info about the remote device and
6
Message-id: 20190815153638.4600-6-mreitz@redhat.com
4
configure the Proxy PCI object based on the returned information
7
Reviewed-by: John Snow <jsnow@redhat.com>
5
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
7
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
8
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 85ee367bbb993aa23699b44cfedd83b4ea6d5221.1611938319.git.jag.raman@oracle.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
12
---
10
tests/qemu-iotests/002 | 1 +
13
hw/remote/proxy.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++
11
tests/qemu-iotests/003 | 1 +
14
1 file changed, 84 insertions(+)
12
tests/qemu-iotests/005 | 3 ++-
13
tests/qemu-iotests/009 | 1 +
14
tests/qemu-iotests/010 | 1 +
15
tests/qemu-iotests/011 | 1 +
16
tests/qemu-iotests/017 | 3 ++-
17
tests/qemu-iotests/018 | 3 ++-
18
tests/qemu-iotests/019 | 3 ++-
19
tests/qemu-iotests/020 | 3 ++-
20
tests/qemu-iotests/027 | 1 +
21
tests/qemu-iotests/032 | 1 +
22
tests/qemu-iotests/033 | 1 +
23
tests/qemu-iotests/034 | 3 ++-
24
tests/qemu-iotests/037 | 3 ++-
25
tests/qemu-iotests/063 | 3 ++-
26
tests/qemu-iotests/072 | 1 +
27
tests/qemu-iotests/105 | 3 ++-
28
tests/qemu-iotests/197 | 1 +
29
tests/qemu-iotests/215 | 1 +
30
tests/qemu-iotests/251 | 1 +
31
21 files changed, 30 insertions(+), 9 deletions(-)
32
15
33
diff --git a/tests/qemu-iotests/002 b/tests/qemu-iotests/002
16
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
34
index XXXXXXX..XXXXXXX 100755
17
index XXXXXXX..XXXXXXX 100644
35
--- a/tests/qemu-iotests/002
18
--- a/hw/remote/proxy.c
36
+++ b/tests/qemu-iotests/002
19
+++ b/hw/remote/proxy.c
37
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
20
@@ -XXX,XX +XXX,XX @@
38
21
#include "sysemu/kvm.h"
39
_supported_fmt generic
22
#include "util/event_notifier-posix.c"
40
_supported_proto generic
23
41
+_unsupported_imgopts "subformat=streamOptimized"
24
+static void probe_pci_info(PCIDevice *dev, Error **errp);
42
25
+
43
26
static void proxy_intx_update(PCIDevice *pci_dev)
44
size=128M
27
{
45
diff --git a/tests/qemu-iotests/003 b/tests/qemu-iotests/003
28
PCIProxyDev *dev = PCI_PROXY_DEV(pci_dev);
46
index XXXXXXX..XXXXXXX 100755
29
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
47
--- a/tests/qemu-iotests/003
30
{
48
+++ b/tests/qemu-iotests/003
31
ERRP_GUARD();
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
32
PCIProxyDev *dev = PCI_PROXY_DEV(device);
50
33
+ uint8_t *pci_conf = device->config;
51
_supported_fmt generic
34
int fd;
52
_supported_proto generic
35
53
+_unsupported_imgopts "subformat=streamOptimized"
36
if (!dev->fd) {
54
37
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
55
size=128M
38
qemu_mutex_init(&dev->io_mutex);
56
offset=67M
39
qio_channel_set_blocking(dev->ioc, true, NULL);
57
diff --git a/tests/qemu-iotests/005 b/tests/qemu-iotests/005
40
58
index XXXXXXX..XXXXXXX 100755
41
+ pci_conf[PCI_LATENCY_TIMER] = 0xff;
59
--- a/tests/qemu-iotests/005
42
+ pci_conf[PCI_INTERRUPT_PIN] = 0x01;
60
+++ b/tests/qemu-iotests/005
43
+
61
@@ -XXX,XX +XXX,XX @@ _supported_fmt generic
44
proxy_memory_listener_configure(&dev->proxy_listener, dev->ioc);
62
_supported_proto generic
45
63
_supported_os Linux
46
setup_irqfd(dev);
64
_unsupported_imgopts "subformat=twoGbMaxExtentFlat" \
47
+
65
- "subformat=twoGbMaxExtentSparse"
48
+ probe_pci_info(PCI_DEVICE(dev), errp);
66
+ "subformat=twoGbMaxExtentSparse" \
49
}
67
+ "subformat=streamOptimized"
50
68
51
static void pci_proxy_dev_exit(PCIDevice *pdev)
69
# vpc is limited to 127GB, so we can't test it here
52
@@ -XXX,XX +XXX,XX @@ const MemoryRegionOps proxy_mr_ops = {
70
if [ "$IMGFMT" = "vpc" ]; then
53
.max_access_size = 8,
71
diff --git a/tests/qemu-iotests/009 b/tests/qemu-iotests/009
54
},
72
index XXXXXXX..XXXXXXX 100755
55
};
73
--- a/tests/qemu-iotests/009
56
+
74
+++ b/tests/qemu-iotests/009
57
+static void probe_pci_info(PCIDevice *dev, Error **errp)
75
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
58
+{
76
59
+ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
77
_supported_fmt generic
60
+ uint32_t orig_val, new_val, base_class, val;
78
_supported_proto generic
61
+ PCIProxyDev *pdev = PCI_PROXY_DEV(dev);
79
+_unsupported_imgopts "subformat=streamOptimized"
62
+ DeviceClass *dc = DEVICE_CLASS(pc);
80
63
+ uint8_t type;
81
64
+ int i, size;
82
size=6G
65
+
83
diff --git a/tests/qemu-iotests/010 b/tests/qemu-iotests/010
66
+ config_op_send(pdev, PCI_VENDOR_ID, &val, 2, MPQEMU_CMD_PCI_CFGREAD);
84
index XXXXXXX..XXXXXXX 100755
67
+ pc->vendor_id = (uint16_t)val;
85
--- a/tests/qemu-iotests/010
68
+
86
+++ b/tests/qemu-iotests/010
69
+ config_op_send(pdev, PCI_DEVICE_ID, &val, 2, MPQEMU_CMD_PCI_CFGREAD);
87
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
70
+ pc->device_id = (uint16_t)val;
88
71
+
89
_supported_fmt generic
72
+ config_op_send(pdev, PCI_CLASS_DEVICE, &val, 2, MPQEMU_CMD_PCI_CFGREAD);
90
_supported_proto generic
73
+ pc->class_id = (uint16_t)val;
91
+_unsupported_imgopts "subformat=streamOptimized"
74
+
92
75
+ config_op_send(pdev, PCI_SUBSYSTEM_ID, &val, 2, MPQEMU_CMD_PCI_CFGREAD);
93
76
+ pc->subsystem_id = (uint16_t)val;
94
size=6G
77
+
95
diff --git a/tests/qemu-iotests/011 b/tests/qemu-iotests/011
78
+ base_class = pc->class_id >> 4;
96
index XXXXXXX..XXXXXXX 100755
79
+ switch (base_class) {
97
--- a/tests/qemu-iotests/011
80
+ case PCI_BASE_CLASS_BRIDGE:
98
+++ b/tests/qemu-iotests/011
81
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
99
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
82
+ break;
100
83
+ case PCI_BASE_CLASS_STORAGE:
101
_supported_fmt generic
84
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
102
_supported_proto generic
85
+ break;
103
+_unsupported_imgopts "subformat=streamOptimized"
86
+ case PCI_BASE_CLASS_NETWORK:
104
87
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
105
88
+ break;
106
size=6G
89
+ case PCI_BASE_CLASS_INPUT:
107
diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017
90
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
108
index XXXXXXX..XXXXXXX 100755
91
+ break;
109
--- a/tests/qemu-iotests/017
92
+ case PCI_BASE_CLASS_DISPLAY:
110
+++ b/tests/qemu-iotests/017
93
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
111
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
94
+ break;
112
_supported_fmt qcow qcow2 vmdk qed
95
+ case PCI_BASE_CLASS_PROCESSOR:
113
_supported_proto generic
96
+ set_bit(DEVICE_CATEGORY_CPU, dc->categories);
114
_unsupported_proto vxhs
97
+ break;
115
-_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
98
+ default:
116
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
99
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
117
+ "subformat=streamOptimized"
100
+ break;
118
101
+ }
119
TEST_OFFSETS="0 4294967296"
102
+
120
103
+ for (i = 0; i < PCI_NUM_REGIONS; i++) {
121
diff --git a/tests/qemu-iotests/018 b/tests/qemu-iotests/018
104
+ config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &orig_val, 4,
122
index XXXXXXX..XXXXXXX 100755
105
+ MPQEMU_CMD_PCI_CFGREAD);
123
--- a/tests/qemu-iotests/018
106
+ new_val = 0xffffffff;
124
+++ b/tests/qemu-iotests/018
107
+ config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &new_val, 4,
125
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
108
+ MPQEMU_CMD_PCI_CFGWRITE);
126
_supported_fmt qcow qcow2 vmdk qed
109
+ config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &new_val, 4,
127
_supported_proto file
110
+ MPQEMU_CMD_PCI_CFGREAD);
128
_supported_os Linux
111
+ size = (~(new_val & 0xFFFFFFF0)) + 1;
129
-_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
112
+ config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &orig_val, 4,
130
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" \
113
+ MPQEMU_CMD_PCI_CFGWRITE);
131
+ "streamOptimized"
114
+ type = (new_val & 0x1) ?
132
115
+ PCI_BASE_ADDRESS_SPACE_IO : PCI_BASE_ADDRESS_SPACE_MEMORY;
133
TEST_OFFSETS="0 4294967296"
116
+
134
117
+ if (size) {
135
diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019
118
+ g_autofree char *name;
136
index XXXXXXX..XXXXXXX 100755
119
+ pdev->region[i].dev = pdev;
137
--- a/tests/qemu-iotests/019
120
+ pdev->region[i].present = true;
138
+++ b/tests/qemu-iotests/019
121
+ if (type == PCI_BASE_ADDRESS_SPACE_MEMORY) {
139
@@ -XXX,XX +XXX,XX @@ _supported_proto file
122
+ pdev->region[i].memory = true;
140
_supported_os Linux
123
+ }
141
_unsupported_imgopts "subformat=monolithicFlat" \
124
+ name = g_strdup_printf("bar-region-%d", i);
142
"subformat=twoGbMaxExtentFlat" \
125
+ memory_region_init_io(&pdev->region[i].mr, OBJECT(pdev),
143
- "subformat=twoGbMaxExtentSparse"
126
+ &proxy_mr_ops, &pdev->region[i],
144
+ "subformat=twoGbMaxExtentSparse" \
127
+ name, size);
145
+ "subformat=streamOptimized"
128
+ pci_register_bar(dev, i, type, &pdev->region[i].mr);
146
129
+ }
147
TEST_OFFSETS="0 4294967296"
130
+ }
148
CLUSTER_SIZE=65536
131
+}
149
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
150
index XXXXXXX..XXXXXXX 100755
151
--- a/tests/qemu-iotests/020
152
+++ b/tests/qemu-iotests/020
153
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow qcow2 vmdk qed
154
_supported_proto file
155
_unsupported_imgopts "subformat=monolithicFlat" \
156
"subformat=twoGbMaxExtentFlat" \
157
- "subformat=twoGbMaxExtentSparse"
158
+ "subformat=twoGbMaxExtentSparse" \
159
+ "subformat=streamOptimized"
160
161
TEST_OFFSETS="0 4294967296"
162
163
diff --git a/tests/qemu-iotests/027 b/tests/qemu-iotests/027
164
index XXXXXXX..XXXXXXX 100755
165
--- a/tests/qemu-iotests/027
166
+++ b/tests/qemu-iotests/027
167
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
168
169
_supported_fmt vmdk qcow qcow2 qed
170
_supported_proto generic
171
+_unsupported_imgopts "subformat=streamOptimized"
172
173
174
size=128M
175
diff --git a/tests/qemu-iotests/032 b/tests/qemu-iotests/032
176
index XXXXXXX..XXXXXXX 100755
177
--- a/tests/qemu-iotests/032
178
+++ b/tests/qemu-iotests/032
179
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
180
# This works for any image format (though unlikely to segfault for raw)
181
_supported_fmt generic
182
_supported_proto generic
183
+_unsupported_imgopts "subformat=streamOptimized"
184
185
echo
186
echo === Prepare image ===
187
diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033
188
index XXXXXXX..XXXXXXX 100755
189
--- a/tests/qemu-iotests/033
190
+++ b/tests/qemu-iotests/033
191
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
192
193
_supported_fmt generic
194
_supported_proto generic
195
+_unsupported_imgopts "subformat=streamOptimized"
196
197
198
size=128M
199
diff --git a/tests/qemu-iotests/034 b/tests/qemu-iotests/034
200
index XXXXXXX..XXXXXXX 100755
201
--- a/tests/qemu-iotests/034
202
+++ b/tests/qemu-iotests/034
203
@@ -XXX,XX +XXX,XX @@ _supported_proto file
204
_supported_os Linux
205
_unsupported_imgopts "subformat=monolithicFlat" \
206
"subformat=twoGbMaxExtentFlat" \
207
- "subformat=twoGbMaxExtentSparse"
208
+ "subformat=twoGbMaxExtentSparse" \
209
+ "subformat=streamOptimized"
210
211
CLUSTER_SIZE=4k
212
size=128M
213
diff --git a/tests/qemu-iotests/037 b/tests/qemu-iotests/037
214
index XXXXXXX..XXXXXXX 100755
215
--- a/tests/qemu-iotests/037
216
+++ b/tests/qemu-iotests/037
217
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow qcow2 vmdk qed
218
_supported_proto file
219
_unsupported_imgopts "subformat=monolithicFlat" \
220
"subformat=twoGbMaxExtentFlat" \
221
- "subformat=twoGbMaxExtentSparse"
222
+ "subformat=twoGbMaxExtentSparse" \
223
+ "subformat=streamOptimized"
224
225
CLUSTER_SIZE=4k
226
size=128M
227
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
228
index XXXXXXX..XXXXXXX 100755
229
--- a/tests/qemu-iotests/063
230
+++ b/tests/qemu-iotests/063
231
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow qcow2 vmdk qed raw
232
_supported_proto file
233
_unsupported_imgopts "subformat=monolithicFlat" \
234
"subformat=twoGbMaxExtentFlat" \
235
- "subformat=twoGbMaxExtentSparse"
236
+ "subformat=twoGbMaxExtentSparse" \
237
+ "subformat=streamOptimized"
238
239
_make_test_img 4M
240
241
diff --git a/tests/qemu-iotests/072 b/tests/qemu-iotests/072
242
index XXXXXXX..XXXXXXX 100755
243
--- a/tests/qemu-iotests/072
244
+++ b/tests/qemu-iotests/072
245
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
246
247
_supported_fmt vpc vmdk vhdx vdi qed qcow2 qcow
248
_supported_proto file
249
+_unsupported_imgopts "subformat=streamOptimized"
250
251
IMG_SIZE=64M
252
253
diff --git a/tests/qemu-iotests/105 b/tests/qemu-iotests/105
254
index XXXXXXX..XXXXXXX 100755
255
--- a/tests/qemu-iotests/105
256
+++ b/tests/qemu-iotests/105
257
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
258
_supported_fmt qcow2 vmdk vhdx qed
259
_supported_proto generic
260
_unsupported_imgopts "subformat=twoGbMaxExtentFlat" \
261
- "subformat=twoGbMaxExtentSparse"
262
+ "subformat=twoGbMaxExtentSparse" \
263
+ "subformat=streamOptimized"
264
265
echo
266
echo "creating large image"
267
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
268
index XXXXXXX..XXXXXXX 100755
269
--- a/tests/qemu-iotests/197
270
+++ b/tests/qemu-iotests/197
271
@@ -XXX,XX +XXX,XX @@ _supported_fmt generic
272
_supported_proto generic
273
# LUKS support may be possible, but it complicates things.
274
_unsupported_fmt luks
275
+_unsupported_imgopts "subformat=streamOptimized"
276
277
echo
278
echo '=== Copy-on-read ==='
279
diff --git a/tests/qemu-iotests/215 b/tests/qemu-iotests/215
280
index XXXXXXX..XXXXXXX 100755
281
--- a/tests/qemu-iotests/215
282
+++ b/tests/qemu-iotests/215
283
@@ -XXX,XX +XXX,XX @@ _supported_fmt generic
284
_supported_proto generic
285
# LUKS support may be possible, but it complicates things.
286
_unsupported_fmt luks
287
+_unsupported_imgopts "subformat=streamOptimized"
288
289
echo
290
echo '=== Copy-on-read ==='
291
diff --git a/tests/qemu-iotests/251 b/tests/qemu-iotests/251
292
index XXXXXXX..XXXXXXX 100755
293
--- a/tests/qemu-iotests/251
294
+++ b/tests/qemu-iotests/251
295
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
296
_supported_fmt generic
297
_supported_proto file
298
_supported_os Linux
299
+_unsupported_imgopts "subformat=streamOptimized"
300
301
if [ "$IMGOPTSSYNTAX" = "true" ]; then
302
# We use json:{} filenames here, so we cannot work with additional options.
303
--
132
--
304
2.21.0
133
2.29.2
305
134
306
diff view generated by jsdifflib
1
fe646693acc changed qemu-img create's output so that it no longer prints
1
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
2
single quotes around parameter values. The subformat and adapter_type
3
filters in _filter_img_create() have never been adapted to that change.
4
2
5
Fixes: fe646693acc13ac48b98435d14149ab04dc597bc
3
Perform device reset in the remote process when QEMU performs
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
device reset. This is required to reset the internal state
7
Reviewed-by: John Snow <jsnow@redhat.com>
5
(like registers, etc...) of emulated devices
8
Message-id: 20190815153638.4600-2-mreitz@redhat.com
6
9
Reviewed-by: John Snow <jsnow@redhat.com>
7
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
9
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-id: 7cb220a51f565dc0817bd76e2f540e89c2d2b850.1611938319.git.jag.raman@oracle.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
13
---
12
tests/qemu-iotests/059.out | 16 ++++++++--------
14
include/hw/remote/mpqemu-link.h | 1 +
13
tests/qemu-iotests/common.filter | 4 ++--
15
hw/remote/message.c | 22 ++++++++++++++++++++++
14
2 files changed, 10 insertions(+), 10 deletions(-)
16
hw/remote/proxy.c | 19 +++++++++++++++++++
17
3 files changed, 42 insertions(+)
15
18
16
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
19
diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/059.out
21
--- a/include/hw/remote/mpqemu-link.h
19
+++ b/tests/qemu-iotests/059.out
22
+++ b/include/hw/remote/mpqemu-link.h
20
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
23
@@ -XXX,XX +XXX,XX @@ typedef enum {
21
qemu-io: can't open device TEST_DIR/t.vmdk: L1 size too big
24
MPQEMU_CMD_BAR_WRITE,
22
25
MPQEMU_CMD_BAR_READ,
23
=== Testing monolithicFlat creation and opening ===
26
MPQEMU_CMD_SET_IRQFD,
24
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 subformat=monolithicFlat
27
+ MPQEMU_CMD_DEVICE_RESET,
25
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
28
MPQEMU_CMD_MAX,
26
image: TEST_DIR/t.IMGFMT
29
} MPQemuCmd;
27
file format: IMGFMT
30
28
virtual size: 2 GiB (2147483648 bytes)
31
diff --git a/hw/remote/message.c b/hw/remote/message.c
29
30
=== Testing monolithicFlat with zeroed_grain ===
31
qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
32
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 subformat=monolithicFlat
33
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
34
35
=== Testing big twoGbMaxExtentFlat ===
36
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMaxExtentFlat
37
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000
38
image: TEST_DIR/t.vmdk
39
file format: vmdk
40
virtual size: 0.977 TiB (1073741824000 bytes)
41
@@ -XXX,XX +XXX,XX @@ Format specific information:
42
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Invalid extent line: RW 12582912 VMFS "dummy.IMGFMT" 1
43
44
=== Testing truncated sparse ===
45
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=107374182400 subformat=monolithicSparse
46
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=107374182400
47
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': File truncated, expecting at least 13172736 bytes
48
49
=== Converting to streamOptimized from image with small cluster size===
50
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 10240
51
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
52
53
=== Testing monolithicFlat with internally generated JSON file name ===
54
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 subformat=monolithicFlat
55
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
56
qemu-io: can't open: Cannot use relative extent paths with VMDK descriptor file 'json:{"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "read_aio"}'
57
58
=== Testing version 3 ===
59
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 64931328
60
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
61
62
=== Testing 4TB monolithicFlat creation and IO ===
63
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4398046511104 subformat=monolithicFlat
64
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4398046511104
65
image: TEST_DIR/t.IMGFMT
66
file format: IMGFMT
67
virtual size: 4 TiB (4398046511104 bytes)
68
@@ -XXX,XX +XXX,XX @@ read 1024/1024 bytes at offset 966367641600
69
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
70
71
=== Testing qemu-img map on extents ===
72
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33285996544 subformat=monolithicSparse
73
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33285996544
74
wrote 1024/1024 bytes at offset 65024
75
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
76
wrote 1024/1024 bytes at offset 2147483136
77
@@ -XXX,XX +XXX,XX @@ Offset Length Mapped to File
78
0 0x20000 0x3f0000 TEST_DIR/t.vmdk
79
0x7fff0000 0x20000 0x410000 TEST_DIR/t.vmdk
80
0x140000000 0x10000 0x430000 TEST_DIR/t.vmdk
81
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33285996544 subformat=twoGbMaxExtentSparse
82
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33285996544
83
wrote 1024/1024 bytes at offset 65024
84
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
85
wrote 1024/1024 bytes at offset 2147483136
86
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
87
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
88
--- a/tests/qemu-iotests/common.filter
33
--- a/hw/remote/message.c
89
+++ b/tests/qemu-iotests/common.filter
34
+++ b/hw/remote/message.c
90
@@ -XXX,XX +XXX,XX @@ _filter_img_create()
35
@@ -XXX,XX +XXX,XX @@
91
-e "s# compat6=\\(on\\|off\\)##g" \
36
#include "exec/memattrs.h"
92
-e "s# static=\\(on\\|off\\)##g" \
37
#include "hw/remote/memory.h"
93
-e "s# zeroed_grain=\\(on\\|off\\)##g" \
38
#include "hw/remote/iohub.h"
94
- -e "s# subformat='[^']*'##g" \
39
+#include "sysemu/reset.h"
95
- -e "s# adapter_type='[^']*'##g" \
40
96
+ -e "s# subformat=[^ ]*##g" \
41
static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
97
+ -e "s# adapter_type=[^ ]*##g" \
42
MPQemuMsg *msg, Error **errp);
98
-e "s# hwversion=[^ ]*##g" \
43
@@ -XXX,XX +XXX,XX @@ static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
99
-e "s# lazy_refcounts=\\(on\\|off\\)##g" \
44
MPQemuMsg *msg, Error **errp);
100
-e "s# block_size=[0-9]\\+##g" \
45
static void process_bar_write(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
46
static void process_bar_read(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
47
+static void process_device_reset_msg(QIOChannel *ioc, PCIDevice *dev,
48
+ Error **errp);
49
50
void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
51
{
52
@@ -XXX,XX +XXX,XX @@ void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
53
case MPQEMU_CMD_SET_IRQFD:
54
process_set_irqfd_msg(pci_dev, &msg);
55
break;
56
+ case MPQEMU_CMD_DEVICE_RESET:
57
+ process_device_reset_msg(com->ioc, pci_dev, &local_err);
58
+ break;
59
default:
60
error_setg(&local_err,
61
"Unknown command (%d) received for device %s"
62
@@ -XXX,XX +XXX,XX @@ fail:
63
getpid());
64
}
65
}
66
+
67
+static void process_device_reset_msg(QIOChannel *ioc, PCIDevice *dev,
68
+ Error **errp)
69
+{
70
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
71
+ DeviceState *s = DEVICE(dev);
72
+ MPQemuMsg ret = { 0 };
73
+
74
+ if (dc->reset) {
75
+ dc->reset(s);
76
+ }
77
+
78
+ ret.cmd = MPQEMU_CMD_RET;
79
+
80
+ mpqemu_msg_send(&ret, ioc, errp);
81
+}
82
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/remote/proxy.c
85
+++ b/hw/remote/proxy.c
86
@@ -XXX,XX +XXX,XX @@
87
#include "util/event_notifier-posix.c"
88
89
static void probe_pci_info(PCIDevice *dev, Error **errp);
90
+static void proxy_device_reset(DeviceState *dev);
91
92
static void proxy_intx_update(PCIDevice *pci_dev)
93
{
94
@@ -XXX,XX +XXX,XX @@ static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
95
k->config_read = pci_proxy_read_config;
96
k->config_write = pci_proxy_write_config;
97
98
+ dc->reset = proxy_device_reset;
99
+
100
device_class_set_props(dc, proxy_properties);
101
}
102
103
@@ -XXX,XX +XXX,XX @@ static void probe_pci_info(PCIDevice *dev, Error **errp)
104
}
105
}
106
}
107
+
108
+static void proxy_device_reset(DeviceState *dev)
109
+{
110
+ PCIProxyDev *pdev = PCI_PROXY_DEV(dev);
111
+ MPQemuMsg msg = { 0 };
112
+ Error *local_err = NULL;
113
+
114
+ msg.cmd = MPQEMU_CMD_DEVICE_RESET;
115
+ msg.size = 0;
116
+
117
+ mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err);
118
+ if (local_err) {
119
+ error_report_err(local_err);
120
+ }
121
+
122
+}
101
--
123
--
102
2.21.0
124
2.29.2
103
125
104
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: "Denis V. Lunev" <den@openvz.org>
2
2
3
Fixes: a6b257a08e3d72219f03e461a52152672fec0612
3
Original specification says that l1 table size if 64 * l1_size, which
4
("file-posix: Handle undetectable alignment")
4
is obviously wrong. The size of the l1 entry is 64 _bits_, not bytes.
5
Thus 64 is to be replaces with 8 as specification says about bytes.
6
7
There is also minor tweak, field name is renamed from l1 to l1_table,
8
which matches with the later text.
9
10
Signed-off-by: Denis V. Lunev <den@openvz.org>
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Message-id: 20210128171313.2210947-1-den@openvz.org
13
CC: Stefan Hajnoczi <stefanha@redhat.com>
14
CC: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
16
[Replace the original commit message "docs: fix mistake in dirty bitmap
17
feature description" as suggested by Eric Blake.
18
--Stefan]
19
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Message-id: 20190827101328.4062-1-stefanha@redhat.com
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
21
---
10
block/file-posix.c | 2 +-
22
docs/interop/parallels.txt | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
23
1 file changed, 1 insertion(+), 1 deletion(-)
12
24
13
diff --git a/block/file-posix.c b/block/file-posix.c
25
diff --git a/docs/interop/parallels.txt b/docs/interop/parallels.txt
14
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
15
--- a/block/file-posix.c
27
--- a/docs/interop/parallels.txt
16
+++ b/block/file-posix.c
28
+++ b/docs/interop/parallels.txt
17
@@ -XXX,XX +XXX,XX @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp)
29
@@ -XXX,XX +XXX,XX @@ of its data area are:
18
for (i = 0; i < ARRAY_SIZE(alignments); i++) {
30
28 - 31: l1_size
19
align = alignments[i];
31
The number of entries in the L1 table of the bitmap.
20
if (raw_is_io_aligned(fd, buf + align, max_align)) {
32
21
- /* Fallback to request_aligment. */
33
- variable: l1 (64 * l1_size bytes)
22
+ /* Fallback to request_alignment. */
34
+ variable: l1_table (8 * l1_size bytes)
23
s->buf_align = (align != 1) ? align : bs->bl.request_alignment;
35
L1 offset table (in bytes)
24
break;
36
25
}
37
A dirty bitmap is stored using a one-level structure for the mapping to host
26
--
38
--
27
2.21.0
39
2.29.2
28
40
29
diff view generated by jsdifflib