Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 1 | On this page you will find device specific information for QEMU v7 (Armv7-A) and |
| 2 | QEMU v8 (Armv8-A). |
| 3 | |
| 4 | .. _qemu_v7: |
| 5 | |
| 6 | ####### |
| 7 | QEMU v7 |
| 8 | ####### |
| 9 | The instructions here will tell how to run OP-TEE using QEMU for Armv7-A. |
| 10 | |
| 11 | Build instructions |
| 12 | ****************** |
| 13 | As long as you pick the v7 manifest, i.e., ``default.xml`` the |
| 14 | ":ref:`get_and_build_the_solution`" tells all you need to know to build and boot |
| 15 | up QEMU v7. |
| 16 | |
Etienne Carriere | f9869e1 | 2021-03-13 11:49:26 +0100 | [diff] [blame] | 17 | A usual short shell sequence to fetch, build and run OP-TEE using QEMU |
| 18 | for Armv7-A is like the one below: |
| 19 | |
| 20 | .. code-block:: bash |
| 21 | |
Jerome Forissier | 58e9427 | 2023-05-26 10:16:05 +0200 | [diff] [blame^] | 22 | $ mkdir optee |
| 23 | $ cd optee |
Etienne Carriere | f9869e1 | 2021-03-13 11:49:26 +0100 | [diff] [blame] | 24 | $ repo init -u https://github.com/OP-TEE/manifest.git |
| 25 | $ repo sync |
| 26 | $ cd build |
| 27 | $ make toolchains |
| 28 | $ make run |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 29 | |
Johannes Bauer | 1ed2e74 | 2023-02-06 00:07:22 +0100 | [diff] [blame] | 30 | .. hint:: |
| 31 | |
| 32 | If you do not want to check out the latest version of OP-TEE, but rather a |
| 33 | specific tagged version, you can use ``repo init -u |
| 34 | https://github.com/OP-TEE/manifest.git -b <branchname>``. e.g., ``repo init |
| 35 | -u https://github.com/OP-TEE/manifest.git -b 3.16.0``. You can see valid |
| 36 | branch names by inspecting the OP-TEE/manifest git repository on |
| 37 | https://github.com/OP-TEE/manifest/branches. |
| 38 | |
| 39 | To speed up your build, you can make use of the parallel make feature. For |
| 40 | example, use ``make -j32 run`` to have 32 build processes running |
| 41 | concurrently. Note that this will make it much more difficult to spot |
| 42 | errors if something fails; therefore fall back to sequential builds to view |
| 43 | build errors and produce logs for bug reports. |
| 44 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 45 | Consoles |
| 46 | ******** |
| 47 | After running ``make run`` you will end up in the QEMU console and it will also |
| 48 | spawn two UART consoles. One console containing the UART for secure world and |
| 49 | one console containing the UART for normal world. You will see that it stops |
| 50 | waiting for input on the QEMU console. To continue, do: |
| 51 | |
| 52 | .. code-block:: none |
| 53 | |
| 54 | (qemu) c |
| 55 | |
| 56 | Host-Guest folder sharing |
| 57 | ************************* |
| 58 | You can use the VirtFS QEMU feature to avoid changing rootfs CPIO archive every |
| 59 | time you need to add additional files or modify existing files. To do this, you |
| 60 | share a folder between the guest and host operating systems. To enable and use |
| 61 | this feature you have to provide additional arguments when running make, |
| 62 | example: |
| 63 | |
| 64 | .. code-block:: bash |
| 65 | |
| 66 | $ make QEMU_VIRTFS_ENABLE=y QEMU_USERNET_ENABLE=y |
| 67 | |
| 68 | .. hint:: |
| 69 | |
| 70 | You can also add ``QEMU_VIRTFS_HOST_DIR=<share>`` in case you don't want to |
| 71 | use the default sharing location (which is the root of <qemu-v7-project>). |
| 72 | |
| 73 | When QEMU with OP-TEE is up and running, you can mount the host folder in QEMU |
| 74 | (normal world UART). |
| 75 | |
| 76 | .. code-block:: none |
| 77 | |
| 78 | # mount -t 9p -o trans=virtio host <mount_point> |
| 79 | |
| 80 | ``<mount_point>`` here is folder in the QEMU where you want to mount the host |
| 81 | PC's shared folder. So if you want to mount it at ``/mnt/host`` you typically do |
| 82 | this from QEMU NW/UART. |
| 83 | |
| 84 | .. code-block:: none |
| 85 | |
| 86 | # mkdir -p /mnt/host |
| 87 | # mount -t 9p -o trans=virtio host /mnt/host |
| 88 | |
| 89 | Networking |
| 90 | ********** |
| 91 | After booting QEMU, ``eth0`` will automatically receive an IP address from |
| 92 | QEMU via DHCP using the SLiRP user networking feature. QEMU will act as a |
| 93 | gateway to the host network `SLiRP`_. |
| 94 | |
| 95 | Please note that ICMP won't work in the guest unless additional configuration is |
| 96 | made, so the ``ping`` utility won't work. |
| 97 | |
| 98 | GDB - Normal world |
| 99 | ****************** |
| 100 | If you need to debug a client application, using GDB in a remote debugging |
| 101 | configuration may be useful. Remote debugging means ``gdb`` runs on your PC, |
| 102 | where it can access the source code, while the program being debugged runs on |
| 103 | the remote system (in this case, in the QEMU environment in normal world). Here |
| 104 | is how to do that. On your PC, build with ``GDBSERVER=y``: |
| 105 | |
| 106 | .. code-block:: bash |
| 107 | |
| 108 | $ cd <qemu-v7-project>/build |
| 109 | # You **only** need to rm -rf the first time you build with the new flag. |
| 110 | # If you omit doing so, it's likely that you will see "stamp" errors in the |
| 111 | # build log. |
| 112 | $ rm -rf <qemu-v7-project>/out-br |
| 113 | $ make -j8 run GDBSERVER=y |
| 114 | |
| 115 | Boot up as usual |
| 116 | |
| 117 | .. code-block:: bash |
| 118 | |
| 119 | (qemu) c |
| 120 | |
| 121 | Inside QEMU (Normal World UART), run your application with gdbserver (for |
| 122 | example ``xtest 4002``): |
| 123 | |
| 124 | .. code-block:: none |
| 125 | |
| 126 | # gdbserver :12345 xtest 4002 |
| 127 | Process xtest created; pid = 654 |
| 128 | Listening on port 12345 |
| 129 | |
| 130 | Back on your PC, open another terminal, start GDB and connect to the target: |
| 131 | |
| 132 | .. code-block:: bash |
| 133 | |
| 134 | $ <qemu-v7-project>/out-br/host/bin/arm-buildroot-linux-gnueabihf-gdb |
| 135 | (gdb) set sysroot <qemu-v7-project>/out-br/host/arm-buildroot-linux-gnueabihf/sysroot |
| 136 | (gdb) target remote :12345 |
| 137 | |
| 138 | Now GDB is connected to the remote application. You may use GDB normally. |
| 139 | |
| 140 | .. code-block:: none |
| 141 | |
| 142 | (gdb) b main |
| 143 | (gdb) c |
| 144 | |
Joakim Bech | 37b5436 | 2019-03-06 10:33:46 +0100 | [diff] [blame] | 145 | GDB - Secure world |
| 146 | ****************** |
| 147 | TEE core debugging |
| 148 | ================== |
Erez-Shlingbaum | 7c4e017 | 2021-06-21 14:02:36 +0300 | [diff] [blame] | 149 | To debug TEE core running QEMU with GDB, you need to disable TEE ASLR with |
| 150 | ``CFG_CORE_ASLR=n`` flag. Furthermore, note that it's easier to debug if you |
| 151 | have optimization disabled. Other than that you will have four consoles that |
| 152 | you are working with. |
Joakim Bech | 37b5436 | 2019-03-06 10:33:46 +0100 | [diff] [blame] | 153 | |
| 154 | - Qemu console |
| 155 | - NW UART console |
| 156 | - SW UART console |
| 157 | - GDB console |
| 158 | |
| 159 | All of them but the GDB console are consoles you normally will see/use when |
| 160 | running OP-TEE/xtest using QEMU. The first thing is to start QEMU, i.e., |
| 161 | |
| 162 | .. code-block:: bash |
| 163 | |
| 164 | $ cd <qemu-v7-project>/build |
| 165 | # make run-only also works if you don't want to rebuild things |
Erez-Shlingbaum | 7c4e017 | 2021-06-21 14:02:36 +0300 | [diff] [blame] | 166 | $ make run CFG_CORE_ASLR=n |
Joakim Bech | 37b5436 | 2019-03-06 10:33:46 +0100 | [diff] [blame] | 167 | |
| 168 | Next launch another console for GDB and do this |
| 169 | |
| 170 | .. code-block:: bash |
| 171 | |
| 172 | $ cd <qemu-v7-project>/toolchains/aarch32/bin |
| 173 | $ ./arm-linux-gnueabihf-gdb -q |
| 174 | |
| 175 | In the GDB console connect to the QEMU GDB server, like this (the output is |
| 176 | included to show what you normally will see). |
| 177 | |
| 178 | .. code-block:: none |
| 179 | |
| 180 | (gdb) target remote localhost:1234 |
| 181 | Remote debugging using localhost:1234 |
| 182 | warning: No executable has been specified and target does not support |
| 183 | determining executable automatically. Try using the "file" command. |
| 184 | 0x00000000 in ?? () |
| 185 | |
| 186 | Still in the GDB console, load the symbols for TEE core |
| 187 | |
| 188 | .. code-block:: none |
| 189 | |
| 190 | (gdb) symbol-file <qemu-v7-project>/optee_os/out/arm/core/tee.elf |
| 191 | Reading symbols from <qemu-v7-project>/optee_os/out/arm/core/tee.elf...done. |
| 192 | |
| 193 | Now you can set a breakpoint for any symbol in OP-TEE, for example |
| 194 | |
| 195 | .. code-block:: none |
| 196 | |
| 197 | (gdb) b tee_entry_std |
| 198 | Breakpoint 1 at 0xe103012: file core/arch/arm/tee/entry_std.c, line 526. |
| 199 | |
| 200 | Last step is to initiate the boot, do that also from the GDB console |
| 201 | |
| 202 | .. code-block:: none |
| 203 | |
| 204 | (gdb) c |
| 205 | Continuing. |
| 206 | |
| 207 | At this point will see UART output in the Normal world console as well as the |
| 208 | Secure world UART console. If you now for example :ref:`optee_test_run_xtest`, |
| 209 | then you will rather soon hit the breakpoint we previously set and you will see |
| 210 | something like this in the GDB console: |
| 211 | |
| 212 | .. code-block:: none |
| 213 | |
| 214 | Continuing. |
| 215 | [Switching to Thread 2] |
| 216 | |
| 217 | Thread 2 hit Breakpoint 1, tee_entry_std (smc_args=0xe183f18 |
| 218 | <stack_thread+8216>) at core/arch/arm/tee/entry_std.c:526 |
| 219 | 526 struct optee_msg_arg *arg = NULL; /* fix gcc warning */ |
| 220 | (gdb) |
| 221 | |
| 222 | From here you can start to poke around with GDB, single step, read memory, read |
| 223 | registers, print variables and all sorts of things that you normally do with a |
| 224 | debugger. |
| 225 | |
| 226 | .. hint:: |
| 227 | |
Joakim Bech | 9e7464b | 2019-05-21 11:40:28 +0200 | [diff] [blame] | 228 | Some people find it easier to also see the source code while debugging. You |
| 229 | can enable the "TUI mode" to see the source code in GDB. To enable that, run |
| 230 | GDB with |
Joakim Bech | 37b5436 | 2019-03-06 10:33:46 +0100 | [diff] [blame] | 231 | |
| 232 | .. code-block:: bash |
| 233 | |
| 234 | $ ./arm-linux-gnueabihf-gdb -q -tui |
| 235 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 236 | .. _qemu_v8: |
| 237 | |
| 238 | ####### |
| 239 | QEMU v8 |
| 240 | ####### |
Sander Visser | 26011e8 | 2020-04-21 11:55:40 +0200 | [diff] [blame] | 241 | The instructions here will tell how to run OP-TEE using QEMU for Armv8-A. |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 242 | |
| 243 | Build instructions |
| 244 | ****************** |
| 245 | As long as you pick the v8 manifest, i.e., ``qemu_v8.xml`` the |
| 246 | ":ref:`get_and_build_the_solution`" tells all you need to know to build and boot |
| 247 | up QEMU v8. |
| 248 | |
Etienne Carriere | f9869e1 | 2021-03-13 11:49:26 +0100 | [diff] [blame] | 249 | A usual short shell sequence to fetch, build and run OP-TEE using QEMU |
| 250 | for Armv8-A is like the one below: |
| 251 | |
| 252 | .. code-block:: bash |
| 253 | |
Jerome Forissier | 58e9427 | 2023-05-26 10:16:05 +0200 | [diff] [blame^] | 254 | $ mkdir optee |
| 255 | $ cd optee |
Etienne Carriere | f9869e1 | 2021-03-13 11:49:26 +0100 | [diff] [blame] | 256 | $ repo init -u https://github.com/OP-TEE/manifest.git -m qemu_v8.xml |
| 257 | $ repo sync |
| 258 | $ cd build |
| 259 | $ make toolchains |
| 260 | $ make run |
| 261 | |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 262 | All other things (networking, GDB etc) in the v7 section above is also |
| 263 | applicable on QEMU v8 as long as you replace ``<qemu-v7-project>`` with |
| 264 | ``<qemu-v8-project>`` to get the correct paths relative to your QEMU v8 setup. |
| 265 | |
Joakim Bech | 37b5436 | 2019-03-06 10:33:46 +0100 | [diff] [blame] | 266 | .. _build/PR#340: https://github.com/OP-TEE/build/pull/340 |
| 267 | .. _Bug#4130: https://bugs.linaro.org/show_bug.cgi?id=4130#c4 |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 268 | .. _SLiRP: https://wiki.qemu.org/Documentation/Networking#User_Networking_.28SLIRP.29 |