Jaewan Kim | fff9435 | 2024-02-13 11:29:19 +0900 | [diff] [blame] | 1 | # Getting started with device assignment |
| 2 | |
| 3 | Device assignment allows a VM to have direct access to HW without host/hyp |
| 4 | intervention. AVF uses `vfio-platform` for device assignment, and host kernel |
| 5 | support is required. |
| 6 | |
| 7 | This document explains how to setup and launch VM with device assignments. |
| 8 | |
| 9 | ## VM device assignment DTBO (a.k.a. VM DTBO) |
| 10 | |
| 11 | For device assignment, a VM device assignment DTBO (a.k.a. VM DTBO) is required. |
| 12 | VM DTBO is a device tree overlay which describes all assignable devices |
| 13 | information. Information includes physical reg, IOMMU, device properties, and |
| 14 | dependencies. |
| 15 | |
| 16 | VM DTBO allows to pass extra properties of assignable platform |
| 17 | devices to the VM (which can't be discovered from the HW) while keeping the VMM |
| 18 | device-agnostic. |
| 19 | |
| 20 | When the host boots, the bootloader provides VM DTBO to both Android and pvmfw. |
| 21 | |
| 22 | When a VM boots, the VMM selectively applies the DTBO based from provided |
| 23 | labels, describing the assigned devices. |
| 24 | |
| 25 | ## Prepare VM DTBO |
| 26 | |
| 27 | VM DTBO should be included in the dtbo partition. It should be in its own |
| 28 | entry, and not together with any host OS's. See [DTB/DTBO Paritions] for |
| 29 | partition format. |
| 30 | |
| 31 | [DTB/DTBO Paritions]: https://source.android.com/docs/core/architecture/dto/partitions |
| 32 | |
| 33 | ### Write VM DTS for VM DTBO |
| 34 | |
| 35 | DTBO is compiled from device tree source (DTS) with `dtc` tool. [DTBO syntax] |
| 36 | explains basic syntax of DTS. |
| 37 | |
| 38 | [DTBO syntax]: https://source.android.com/docs/core/architecture/dto/syntax |
| 39 | |
| 40 | Here are details and requirements: |
| 41 | |
| 42 | #### Describe assignable devices |
| 43 | |
| 44 | VM DTBO should describe assignable devices and their labels. |
| 45 | |
| 46 | * VM DTBO should have assignable devices in the `&{/}`, so it can be |
| 47 | overlaid onto VM DT. Assignable devices should be backed by physical device. |
| 48 | * We only support overlaying onto root node (i.e. `&{/}`) to prevent |
| 49 | unexpected modification of VM DT. |
| 50 | * VM DTBO should have labels for assignable devices, so AVF can recognize |
| 51 | assignable device list. Labels should point to valid 'overlayable' nodes. |
| 52 | * Overlayable node is a node that would be applied to the base device tree |
| 53 | when DTBO is applied. |
| 54 | |
| 55 | #### Describe physical devices and physical IOMMUs |
| 56 | |
| 57 | VM DTBO should describe a `/host` node which describes physical devices and |
| 58 | physical IOMMUs. The `/host` node only describes information for verification of |
| 59 | assigned devices, and wouldn't be applied to VM DT. Here are details: |
| 60 | |
| 61 | * Physical IOMMU nodes |
| 62 | * IOMMU nodes must have a phandle to be referenced by a physical device node. |
| 63 | * IOMMU nodes must have `<android,pvmfw,token>` property. The property |
| 64 | describes the IOMMU token. An IOMMU token is a hypervisor-specific `<u64>` |
| 65 | which uniquely identifies a physical IOMMU. IOMMU token must be constant |
| 66 | across the VM boot for provisioning by pvmfw remains valid. The token must |
| 67 | be kept up-to-date across hypervisor updates. |
| 68 | * IOMMU nodes should be multi-master IOMMUs. (i.e. `#iommu-cells = <1>`) |
| 69 | * Other `#iommu-cells` values aren't supported for now. |
| 70 | * See: [Device tree binding for IOMMUs][IOMMU] |
| 71 | * Physical device nodes |
| 72 | * Physical device nodes must have a `<android,pvmfw,target>` property that |
| 73 | references an overlayable node. The overlayable node contains the properties |
| 74 | that would be included in VM DT. |
| 75 | * Physical device nodes must have `<reg>` property to provide physical |
| 76 | regions. |
| 77 | * Physical device nodes can optionally contain `<iommus>` property. The |
| 78 | property is a prop-encoded-array and contains a number of |
| 79 | (iommu phandle, SID) pairs. |
| 80 | * IOMMU can be shared among devices, but should use distinct SIDs. Sharing |
| 81 | the same IOMMU-SID pair among multiple devices isn't supported for now. |
| 82 | |
| 83 | [IOMMU]: https://www.kernel.org/doc/Documentation/devicetree/bindings/iommu/iommu.txt |
| 84 | |
| 85 | #### Describe dependencies |
| 86 | |
| 87 | VM DTBO may have dependencies via phandle references. When a device node is |
| 88 | assigned, dependencies of the node are also applied to VM DT. |
| 89 | |
| 90 | When dependencies are applied, siblings or children nodes of dependencies are |
| 91 | ignored unless explicitly referenced. |
| 92 | |
| 93 | #### VM DTBO example |
| 94 | |
| 95 | Here's a simple example device tree source with four assignable devices nodes. |
| 96 | |
| 97 | ```dts |
| 98 | /dts-v1/; |
| 99 | /plugin/; |
| 100 | |
| 101 | / { |
| 102 | // host node describes physical devices and IOMMUs, and wouldn't be applied to VM DT |
| 103 | host { |
| 104 | #address-cells = <0x2>; |
| 105 | #size-cells = <0x1>; |
| 106 | rng { |
| 107 | reg = <0x0 0x12f00000 0x1000>; |
| 108 | iommus = <&iommu0 0x3>; |
| 109 | android,pvmfw,target = <&rng>; |
| 110 | }; |
| 111 | light { |
| 112 | reg = <0x0 0x00f00000 0x1000>, <0x0 0x00f10000 0x1000>; |
| 113 | iommus = <&iommu1 0x4>, <&iommu2 0x5>; |
| 114 | android,pvmfw,target = <&light>; |
| 115 | }; |
| 116 | led { |
| 117 | reg = <0x0 0x12000000 0x1000>; |
| 118 | iommus = <&iommu1 0x3>; |
| 119 | android,pvmfw,target = <&led>; |
| 120 | }; |
| 121 | bus0 { |
| 122 | #address-cells = <0x1>; |
| 123 | #size-cells = <0x1>; |
| 124 | backlight { |
| 125 | reg = <0x300 0x100>; |
| 126 | android,pvmfw,target = <&backlight>; |
| 127 | }; |
| 128 | }; |
| 129 | iommu0: iommu0 { |
| 130 | #iommu-cells = <0x1>; |
| 131 | android,pvmfw,token = <0x0 0x12e40000>; |
| 132 | }; |
| 133 | iommu1: iommu1 { |
| 134 | #iommu-cells = <0x1>; |
| 135 | android,pvmfw,token = <0x0 0x40000>; |
| 136 | }; |
| 137 | iommu2: iommu2 { |
| 138 | #iommu-cells = <0x1>; |
| 139 | android,pvmfw,token = <0x0 0x50000>; |
| 140 | }; |
| 141 | }; |
| 142 | }; |
| 143 | |
| 144 | // Beginning of the assignable devices. Assigned devices would be applied to VM DT |
| 145 | &{/} { // We only allows to overlay to root node |
| 146 | rng: rng { |
| 147 | compatible = "android,rng"; |
| 148 | android,rng,ignore-gctrl-reset; |
| 149 | }; |
| 150 | light: light { |
| 151 | compatible = "android,light"; |
| 152 | version = <0x1 0x2>; |
| 153 | }; |
| 154 | led: led { |
| 155 | compatible = "android,led"; |
| 156 | prop = <0x555>; |
| 157 | }; |
| 158 | bus0 { |
| 159 | backlight: backlight { |
| 160 | compatible = "android,backlight"; |
| 161 | android,backlight,ignore-gctrl-reset; |
| 162 | }; |
| 163 | }; |
| 164 | }; |
| 165 | ``` |
| 166 | |
| 167 | If you compile the above with `dtc -@`, then you'll get `__symbols__` for free. |
Jaewan Kim | 80ef9fa | 2024-02-25 16:08:14 +0000 | [diff] [blame] | 168 | `__symbol__` has label of nodes, and it's required for the next step. |
Jaewan Kim | fff9435 | 2024-02-13 11:29:19 +0900 | [diff] [blame] | 169 | |
| 170 | ```dts |
Jaewan Kim | 80ef9fa | 2024-02-25 16:08:14 +0000 | [diff] [blame] | 171 | // generated __symbols__ |
Jaewan Kim | fff9435 | 2024-02-13 11:29:19 +0900 | [diff] [blame] | 172 | __symbols__ { |
| 173 | iommu0 = "/host/iommu0"; |
| 174 | iommu1 = "/host/iommu1"; |
| 175 | iommu2 = "/host/iommu2"; |
| 176 | rng = "/fragment@rng/__overlay__/rng"; |
| 177 | light = "/fragment@sensor/__overlay__/light"; |
| 178 | led = "/fragment@led/__overlay__/led"; |
| 179 | backlight = "/fragment@backlight/__overlay__/bus0/backlight"; |
| 180 | }; |
| 181 | ``` |
| 182 | |
| 183 | ## Prepare AVF assignable devices XML |
| 184 | |
| 185 | AVF requires assignable device information to unbind from the host device driver |
| 186 | and bind to VFIO driver. The information should be provided in an XML file at |
| 187 | `/vendor/etc/avf/assignable_devices.xml`. |
| 188 | |
| 189 | Here's example. |
| 190 | |
| 191 | ```xml |
| 192 | <devices> |
| 193 | <device> |
| 194 | <kind>sensor</kind> |
| 195 | <dtbo_label>light</dtbo_label> |
| 196 | <sysfs_path>/sys/bus/platform/devices/16d00000.light</sysfs_path> |
| 197 | </device> |
| 198 | </devices> |
| 199 | ``` |
| 200 | |
| 201 | * `<kind>`: Device kind. Currently only used for debugging purposes and not used |
| 202 | for device assignment. |
Jaewan Kim | 80ef9fa | 2024-02-25 16:08:14 +0000 | [diff] [blame] | 203 | * `<dtbo_label>`: Label in the VM DTBO (i.e. symbol in `__symbols__`). Must be |
| 204 | non-empty and unique in the XML. |
Jaewan Kim | fff9435 | 2024-02-13 11:29:19 +0900 | [diff] [blame] | 205 | * `<sysfs_path>`: Sysfs path of the device in host, used to bind to the VFIO |
Jaewan Kim | 80ef9fa | 2024-02-25 16:08:14 +0000 | [diff] [blame] | 206 | driver. Must be non-empty and unique in the XML. |
Jaewan Kim | fff9435 | 2024-02-13 11:29:19 +0900 | [diff] [blame] | 207 | |
Nikita Ioffe | 377c64a | 2024-09-12 15:23:53 +0000 | [diff] [blame] | 208 | ### List support assignable devices |
| 209 | |
| 210 | In order to query list of the devices that can be assigned to a pVM, run the |
| 211 | following command: |
| 212 | |
| 213 | ```bash |
| 214 | adb shell /apex/com.android.virt/bin/vm info |
| 215 | ``` |
| 216 | |
| 217 | All supported assignable devices will be located under the "Assignable devices:" |
| 218 | section of the output. |
| 219 | |
Jaewan Kim | fff9435 | 2024-02-13 11:29:19 +0900 | [diff] [blame] | 220 | ## Boot with VM DTBO |
| 221 | |
| 222 | Bootloader should provide VM DTBO to both Android and pvmfw. |
| 223 | |
| 224 | ### Provide VM DTBO index in dtbo.img |
| 225 | |
| 226 | Bootloader should provide the VM DTBO index with sysprop |
| 227 | `ro.boot.hypervisor.vm_dtbo_idx.`. DTBO index represents DTBO location in |
| 228 | dtbo.img. |
| 229 | |
| 230 | ### Provide VM DTBO in the pvmfw config |
| 231 | |
| 232 | For protected VM, bootloader must provide VM DTBO to the pvmfw. pvmfw sanitizes |
| 233 | incoming device tree with the VM DTBO. |
| 234 | |
| 235 | For more detail about providing VM DTBO in pvmfw, |
Jiyong Park | 239b877 | 2024-07-22 12:29:33 +0900 | [diff] [blame] | 236 | see: [pvmfw/README.md](../guest/pvmfw/README.md#configuration-data-format) |
Jaewan Kim | fff9435 | 2024-02-13 11:29:19 +0900 | [diff] [blame] | 237 | |
| 238 | |
| 239 | ## Launch VM with device assignment |
| 240 | |
| 241 | We don't support client API yet in Android V, but you can use CLI to test device |
| 242 | assignment. Note that host kernel support is required. |
| 243 | |
| 244 | Specify `--devices ${sysfs_path}` when booting VM. The parameter can be repeated |
| 245 | multiple times for specifying multiple devices. |
| 246 | |
| 247 | Here's an example: |
| 248 | |
| 249 | ```sh |
| 250 | adb shell /apex/com.android.virt/bin/vm run-microdroid --devices /sys/bus/platform/devices/16d00000.light |
Jiyong Park | 239b877 | 2024-07-22 12:29:33 +0900 | [diff] [blame] | 251 | ``` |