1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
|
# qemu(1)
All the examples & notes use `qemu-system-x86_64` but in most cases
this can be swapped with the system emulator for other architectures.
## Keybindings
Graphic mode:
```markdown
Ctrl+Alt+g release mouse capture from VM
Ctrl+Alt+1 switch to display of VM
Ctrl+Alt+2 switch to qemu monitor
```
No graphic mode:
```markdown
Ctrl+a h print help
Ctrl+a x exit emulator
Ctrl+a c switch between monitor and console
```
## VM config snippet
Following command-line gives a good starting point to assemble a VM:
```
qemu-system-x86_64 \
-cpu host -enable-kvm -smp 4 \
-m 8G \
-vga virtio -display sdl,gl=on \
-boot menu=on \
-cdrom <iso> \
-hda <disk> \
-device qemu-xhci,id=xhci \
-device usb-host,bus=xhci.0,vendorid=0x05e1,productid=0x0408,id=capture-card
```
### CPU & RAM
```bash
# Emulate host CPU in guest VM, enabling all supported host featured (requires KVM).
# List available CPUs `qemu-system-x86_64 -cpu help`.
-cpu host
# Enable KVM instead software emulation.
-enable-kvm
# Configure number of guest CPUs.
-smp <N>
# Configure size of guest RAM.
-m 8G
```
### Graphic & Display
```bash
# Use sdl window as display and enable openGL context.
-display sdl,gl=on
# Use vnc server as display (eg on display `:42` here).
-display vnc=localhost:42
# Confifure virtio as 3D video graphic accelerator (requires virgl in guest).
-vga virtio
```
### Boot Menu
```bash
# Enables boot menu to select boot device (enter with `ESC`).
-boot menu=on
```
### Block devices
```bash
# Attach cdrom drive with iso to a VM.
-cdrom <iso>
# Attach disk drive to a VM.
-hda <disk>
# Generic way to configure & attach a drive to a VM.
-drive file=<file>,format=qcow2
```
#### Create a disk with [`qemu-img`][doc-qemu-img]
To create a `qcow2` disk (qemu copy-on-write) of size `10G`:
```bash
qemu-img create -f qcow2 disk.qcow2 10G
```
The disk does not contain any `partitions` or a `partition table`.
We can format the disk from __within the **guest**__ as following example:
```bash
# Create `gpt` partition table.
sudo parted /dev/sda mktable gpt
# Create two equally sized primary partitions.
sudo parted /dev/sda mkpart primary 0% 50%
sudo parted /dev/sda mkpart primary 50% 100%
# Create filesystem on each partition.
sudo mkfs.ext3 /dev/sda1
sudo mkfs.ext4 /dev/sda2
lsblk -f /dev/sda
NAME FSTYPE LABEL UUID FSAVAIL FSUSE% MOUNTPOINT
sda
├─sda1 ext3 ....
└─sda2 ext4 ....
```
### USB
#### Host Controller
```bash
# Add XHCI USB controller to the VM (supports USB 3.0, 2.0, 1.1).
# `id=xhci` creates a usb bus named `xhci`.
-device qemu-xhci,id=xhci
```
#### USB Device
```bash
# Pass-through USB device from host identified by vendorid & productid and
# attach to usb bus `xhci.0` (defined with controller `id`).
-device usb-host,bus=xhci.0,vendorid=0x05e1,productid=0x0408
```
## Debugging
```bash
# Open gdbstub on tcp `<port>` (`-s` shorthand for `-gdb tcp::1234`).
-gdb tcp::<port>
# Freeze guest CPU at startup and wait for debugger connection.
-S
```
## IO redirection
```bash
# Create raw tcp server for `serial IO` and wait until a client connects
# before executing the guest.
-serial tcp:localhost:12345,server,wait
# Create telnet server for `serial IO` and wait until a client connects
# before executing the guest.
-serial telnet:localhost:12345,server,wait
# Configure redirection for the QEMU `mointor`, arguments similar to `-serial`
# above.
-monitor ...
```
> In `server` mode use `nowait` to execute guest without waiting for a client
> connection.
## Network
```bash
# Redirect host tcp port `1234` to guest port `4321`.
-nic user,hostfwd=tcp:localhost:1234-:4321
```
## Shared drives
```bash
# Attach a `virtio-9p-pci` device to the VM.
# The guest requires 9p support and can mount the shared drive as:
# mount -t 9p -o trans=virtio someName /mnt
-virtfs local,id=someName,path=<someHostPath>,mount_tag=someName,security_model=none
```
## Debug logging
```bash
# List debug items.
-d help
# Write debug log to file instead stderr.
-D <file>
# Examples
-d in_asm Log executed guest instructions.
```
## Tracing
```bash
# List name of all trace points.
-trace help
# Enable trace points matching pattern and optionally write trace to file.
-trace <pattern>[,file=<file>]
# Enable trace points for all events listed in the <events> file.
# File must contain one event/pattern per line.
-trace events=<events>
```
## VM snapshots
VM snapshots require that there is at least on `qcow2` disk attached to the VM
([VM Snapshots][doc-qemu-snapshot]).
Commands for qemu [Monitor][doc-qemu-monitor] or [QMP][doc-qemu-qmp]:
```bash
# List available snapshots.
info snapshots
# Create/Load/Delete snapshot with name <tag>.
savevm <tag>
loadvm <tag>
delvm <tag>
```
The snapshot can also be directly specified when invoking qemu as:
```bash
qemu-system-x86_64 \
-loadvm <tag> \
...
```
## VM Migration
`Online` migration example:
```bash
# Start machine 1 on host ABC.
qemu-system-x86_64 -monitor stdio -cdrom <iso>
# Prepare machine 2 on host DEF as migration target.
# Listen for any connection on port 12345.
qemu-system-x86_64 -monitor stdio -incoming tcp:0.0.0.0:12345
# Start migration from the machine 1 monitor console.
(qemu) migrate tcp:DEF:12345
```
Save to external file example:
```bash
```bash
# Start machine 1.
qemu-system-x86_64 -monitor stdio -cdrom <iso>
# Save VM state to file.
(qemu) migrate "exec:gzip -c > vm.gz"
# Load VM from file.
qemu-system-x86_64 -monitor stdio -incoming "exec: gzip -d -c vm.gz"
```
> The migration source machine and the migration target machine should be
> launched with the **same** parameters.
## Appendix: Direct `Kernel` boot
Example command line to directly boot a `Kernel` with an `initrd` ramdisk.
```bash
qemu-system-x86_64 \
-cpu host \
-enable-kvm \
-kernel <dir>/arch/x86/boot/bzImage \
-append "earlyprintk=ttyS0 console=ttyS0 nokaslr init=/init debug" \
-initrd <dir>/initramfs.cpio.gz \
...
```
Instructions to build a minimal [`Kernel` and `initrd`][blog-qemu-dbg].
## Appendix: Cheap instruction tracer
```make
{{ #include qemu-src/Makefile }}
```
```x86asm
{{ #include qemu-src/test.s }}
```
## References
- [QEMU USB][doc-qemu-usb]
- [QEMU IMG][doc-qemu-img]
- [QEMU Tools][doc-qemu-tools]
- [QEMU System][doc-qemu-system]
- [QEMU Invocation (command line args)][doc-qemu-invocation]
- [QEMU Monitor][doc-qemu-monitor]
- [QEMU machine protocol (QMP)][doc-qemu-qmp]
- [QEMU VM Snapshots][doc-qemu-snapshot]
[doc-qemu-usb]: https://github.com/qemu/qemu/blob/master/docs/usb2.txt
[doc-qemu-img]: https://qemu-project.gitlab.io/qemu/tools/qemu-img.html
[doc-qemu-tools]: https://qemu-project.gitlab.io/qemu/tools/index.html
[doc-qemu-system]: https://qemu-project.gitlab.io/qemu/system/index.html
[doc-qemu-invocation]: https://qemu-project.gitlab.io/qemu/system/invocation.html
[doc-qemu-monitor]: https://qemu-project.gitlab.io/qemu/system/monitor.html
[doc-qemu-qmp]: https://qemu-project.gitlab.io/qemu/interop/qemu-qmp-ref.html
[doc-qemu-snapshot]: https://qemu-project.gitlab.io/qemu/system/images.html#vm-005fsnapshots
[blog-qemu-dbg]: https://blog.memzero.de/kernel-debugging-qemu
|