1# QEMU
2
3Zircon can [run under
4emulation](https://fuchsia.googlesource.com/docs/+/master/getting_started.md#Boot-from-QEMU)
5using QEMU. QEMU can either be installed via prebuilt binaries, or built
6locally.
7
8## Install Prebuilt QEMU
9
10QEMU is downloaded by the script that is used to download all Zircon
11prebuilts, including toolchains:
12
13```
14./scripts/download-prebuilt
15```
16
17This will download QEMU to the `prebuilt/downloads/qemu` directory. You
18can either add `prebuilt/downloads/qemu/bin` to your PATH, or specify
19`prebuilt/downloads/qemu/bin` using the -q flag to the run-zircon scripts
20(see below).
21
22## Build QEMU
23
24### Install Prerequisites
25
26Building QEMU on macOS requires a few packages. As of macOS 10.12.1:
27
28```
29# Using http://brew.sh
30brew install pkg-config glib automake libtool
31
32# Or use http://macports.org ("port install ...") or build manually
33```
34
35### Build
36
37```
38cd $SRC
39git clone --recursive https://fuchsia.googlesource.com/third_party/qemu
40cd qemu
41./configure --target-list=aarch64-softmmu,x86_64-softmmu
42make -j32
43sudo make install
44```
45
46If you don't want to install in /usr/local (the default), which will require you
47to be root, add --prefix=/path/to/install (perhaps $HOME/qemu). Then you'll
48either need to add /path/to/install/bin to your PATH or use -q /path/to/install
49when invoking run-zircon-{arch}.
50
51## Run Zircon under QEMU
52
53```
54# for aarch64
55./scripts/run-zircon-arm64
56
57# for x86
58./scripts/run-zircon-x64
59```
60
61If QEMU is not on your path, use -q <directory> to specify its location.
62
63The -h flag will list a number of options, including things like -b to rebuild
64first if necessary and -g to run with a graphical framebuffer.
65
66To exit qemu, enter Ctrl-a x. Use Ctrl-a h to see other commands.
67
68## Enabling Networking under QEMU
69
70The run-zircon script, when given the -N argument will attempt to create
71a network interface using the Linux tun/tap network device named "qemu".  QEMU
72does not need to be run with any special privileges for this, but you need to
73create a persistent tun/tap device ahead of time (which does require you be root):
74
75On Linux:
76
77```
78sudo apt-get install uml-utilities
79sudo tunctl -u $USER -t qemu
80sudo ifconfig qemu up
81```
82
83This is sufficient to enable link local IPv6 (as the loglistener tool uses).
84
85On macOS:
86
87macOS does not support tun/tap devices out of the box; however, there is a widely
88used set of kernel extensions called tuntaposx which can be downloaded
89[here](http://tuntaposx.sourceforge.net/download.xhtml). Once the installer
90completes, the extensions will create up to 16 tun/tap devices. The
91run-zircon-x64 script uses /dev/tap0.
92
93```
94sudo chown $USER /dev/tap0
95
96# Run zircon in QEMU, which will open /dev/tap0
97./scripts/run-zircon-x86 -N
98
99# (In a different window) bring up tap0 with a link local IPv6 address
100sudo ifconfig tap0 inet6 fc00::/7 up
101```
102
103**NOTE**: One caveat with tuntaposx is that the network interface will
104automatically go down when QEMU exits and closes the network device. So the
105network interface needs to be brought back up each time QEMU is restarted. To
106automate this, you can use the -u flag to run a script on qemu startup. An
107example startup script containing the above command is located in
108scripts/qemu-ifup-macos, so QEMU can be started with:
109
110```
111./scripts/run-zircon-x64 -Nu ./scripts/qemu-ifup-macos
112```
113
114## Using Emulated Disk under QEMU
115
116Please follow the minfs instructions on how to create a disk image
117[here][minfs-create-image].
118
119After creating the image, you can run zircon in QEMU with the disk image:
120```
121./scripts/run-zircon-x64 -d [-D <disk_image_path (default: "blk.bin")>]
122```
123
124
125## Debugging the kernel with GDB
126
127### Sample session
128
129Here is a sample session to get you started.
130
131In the shell you're running QEMU in:
132
133```
134shell1$ ./scripts/run-zircon-x64 -- -s -S
135[... some QEMU start up text ...]
136```
137
138This will start QEMU but freeze the system at startup,
139waiting for you to resume it with "continue" in GDB.
140If you want to run QEMU without GDB, but be able to attach with GDB later
141then start QEMU without "-S" in the above example:
142
143```
144shell1$ ./scripts/run-zircon-x64 -- -s
145[... some QEMU start up text ...]
146```
147
148And then in the shell you're running GDB in:
149[Commands here are fully spelled out, but remember most can be abbreviated.]
150
151```
152shell2$ gdb build-x86/zircon.elf
153(gdb) target extended-remote :1234
154Remote debugging using :1234
1550x000000000000fff0 in ?? ()
156(gdb) # Don't try to do too much at this point.
157(gdb) # GDB can't handle architecture switching in one session,
158(gdb) # and at this point the architecture is 16-bit x86.
159(gdb) break lk_main
160Breakpoint 1 at 0xffffffff8010cb58: file kernel/top/main.c, line 59.
161(gdb) continue
162Continuing.
163
164Breakpoint 1, lk_main (arg0=1, arg1=18446744071568293116, arg2=0, arg3=0)
165    at kernel/top/main.c:59
16659	{
167(gdb) continue
168```
169
170At this point Zircon boots and back in shell1 you'll be at the Zircon
171prompt.
172
173```
174mxsh>
175```
176
177If you Ctrl-C in shell2 at this point you can get back to GDB.
178
179```
180(gdb) # Having just done "continue"
181^C
182Program received signal SIGINT, Interrupt.
183arch_idle () at kernel/arch/x86/64/ops.S:32
18432	    ret
185(gdb) info threads
186  Id   Target Id         Frame
187  4    Thread 4 (CPU#3 [halted ]) arch_idle () at kernel/arch/x86/64/ops.S:32
188  3    Thread 3 (CPU#2 [halted ]) arch_idle () at kernel/arch/x86/64/ops.S:32
189  2    Thread 2 (CPU#1 [halted ]) arch_idle () at kernel/arch/x86/64/ops.S:32
190* 1    Thread 1 (CPU#0 [halted ]) arch_idle () at kernel/arch/x86/64/ops.S:32
191```
192
193QEMU reports one thread to GDB for each CPU.
194
195### The zircon.elf-gdb.py script
196
197The scripts/zircon.elf-gdb.py script is automagically loaded by gdb.
198It provides several things:
199
200- Pretty-printers for zircon objects (alas none at the moment).
201
202- Several zircon specific commands, all with a "zircon" prefix. To see them:
203```
204(gdb) help info zircon
205(gdb) help set zircon
206(gdb) help show zircon
207```
208
209- Enhanced unwinder support for automagic unwinding through kernel faults.
210
211Heads up: This script isn't always updated as zircon changes.
212
213### Terminating the session
214
215To terminate QEMU you can send commands to QEMU from GDB:
216
217```
218(gdb) monitor quit
219(gdb) quit
220```
221
222### Interacting with QEMU from Gdb
223
224To see the list of QEMU commands you can execute from GDB:
225
226```
227(gdb) monitor help
228```
229
230### Saving system state for debugging
231
232If you have a crash that is difficult to debug, or that you need help
233with debugging, it's possible to save system state akin to a core dump.
234
235```
236bash$ qemu-img create -f qcow2 /tmp/my_snapshots.qcow2 32M
237```
238
239will create a "32M" block storage device.  Next launch QEMU and tell it
240about the device, but don't tell it to attach the device to the guest system.
241This is OK; we don't plan on using it to back up the disk state, we just want
242a core dump.  Note: all of this can be skipped if you are already emulating
243a block device and it is using the qcow2 format.
244
245```
246bash$ qemu <normal_launch_args> -drive if=none,format=qcow2,file=/tmp/my_snapshots.qcow2
247```
248
249When you get to a point where you want to save the core state, drop to the QEMU
250console using <C-a><C-c>.  You should get the (qemu) prompt at this point.
251From here, just say:
252
253```
254(qemu) savevm my_backup_tag_name
255```
256
257Later on, from an identical machine (one launched with the same args as before),
258you can drop to the console and run:
259
260```
261(qemu) loadvm my_backup_tag_name
262```
263
264to restore the state.  Alternatively, you can do it from the cmd line with:
265
266```
267bash$ qemu <normal_launch_args> -drive if=none,format=qcow2,file=/tmp/my_snapshots.qcow2 -loadvm my_backup_tag_name
268```
269
270In theory, you could package up the qcow2 image along with your build output
271directory and anyone should be able to restore your state and start to poke
272at stuff from the QEMU console.
273
274
275[minfs-create-image]: https://fuchsia.googlesource.com/zircon/+/master/docs/minfs.md#Host-Device-QEMU-Only
276