| # Getting started with device assignment |
| |
| Device assignment allows a VM to have direct access to HW without host/hyp |
| intervention. AVF uses `vfio-platform` for device assignment, and host kernel |
| support is required. |
| |
| This document explains how to setup and launch VM with device assignments. |
| |
| ## VM device assignment DTBO (a.k.a. VM DTBO) |
| |
| For device assignment, a VM device assignment DTBO (a.k.a. VM DTBO) is required. |
| VM DTBO is a device tree overlay which describes all assignable devices |
| information. Information includes physical reg, IOMMU, device properties, and |
| dependencies. |
| |
| VM DTBO allows to pass extra properties of assignable platform |
| devices to the VM (which can't be discovered from the HW) while keeping the VMM |
| device-agnostic. |
| |
| When the host boots, the bootloader provides VM DTBO to both Android and pvmfw. |
| |
| When a VM boots, the VMM selectively applies the DTBO based from provided |
| labels, describing the assigned devices. |
| |
| ## Prepare VM DTBO |
| |
| VM DTBO should be included in the dtbo partition. It should be in its own |
| entry, and not together with any host OS's. See [DTB/DTBO Paritions] for |
| partition format. |
| |
| [DTB/DTBO Paritions]: https://source.android.com/docs/core/architecture/dto/partitions |
| |
| ### Write VM DTS for VM DTBO |
| |
| DTBO is compiled from device tree source (DTS) with `dtc` tool. [DTBO syntax] |
| explains basic syntax of DTS. |
| |
| [DTBO syntax]: https://source.android.com/docs/core/architecture/dto/syntax |
| |
| Here are details and requirements: |
| |
| #### Describe assignable devices |
| |
| VM DTBO should describe assignable devices and their labels. |
| |
| * VM DTBO should have assignable devices in the `&{/}`, so it can be |
| overlaid onto VM DT. Assignable devices should be backed by physical device. |
| * We only support overlaying onto root node (i.e. `&{/}`) to prevent |
| unexpected modification of VM DT. |
| * VM DTBO should have labels for assignable devices, so AVF can recognize |
| assignable device list. Labels should point to valid 'overlayable' nodes. |
| * Overlayable node is a node that would be applied to the base device tree |
| when DTBO is applied. |
| |
| #### Describe physical devices and physical IOMMUs |
| |
| VM DTBO should describe a `/host` node which describes physical devices and |
| physical IOMMUs. The `/host` node only describes information for verification of |
| assigned devices, and wouldn't be applied to VM DT. Here are details: |
| |
| * Physical IOMMU nodes |
| * IOMMU nodes must have a phandle to be referenced by a physical device node. |
| * IOMMU nodes must have `<android,pvmfw,token>` property. The property |
| describes the IOMMU token. An IOMMU token is a hypervisor-specific `<u64>` |
| which uniquely identifies a physical IOMMU. IOMMU token must be constant |
| across the VM boot for provisioning by pvmfw remains valid. The token must |
| be kept up-to-date across hypervisor updates. |
| * IOMMU nodes should be multi-master IOMMUs. (i.e. `#iommu-cells = <1>`) |
| * Other `#iommu-cells` values aren't supported for now. |
| * See: [Device tree binding for IOMMUs][IOMMU] |
| * Physical device nodes |
| * Physical device nodes must have a `<android,pvmfw,target>` property that |
| references an overlayable node. The overlayable node contains the properties |
| that would be included in VM DT. |
| * Physical device nodes must have `<reg>` property to provide physical |
| regions. |
| * Physical device nodes can optionally contain `<iommus>` property. The |
| property is a prop-encoded-array and contains a number of |
| (iommu phandle, SID) pairs. |
| * IOMMU can be shared among devices, but should use distinct SIDs. Sharing |
| the same IOMMU-SID pair among multiple devices isn't supported for now. |
| |
| [IOMMU]: https://www.kernel.org/doc/Documentation/devicetree/bindings/iommu/iommu.txt |
| |
| #### Describe dependencies |
| |
| VM DTBO may have dependencies via phandle references. When a device node is |
| assigned, dependencies of the node are also applied to VM DT. |
| |
| When dependencies are applied, siblings or children nodes of dependencies are |
| ignored unless explicitly referenced. |
| |
| #### VM DTBO example |
| |
| Here's a simple example device tree source with four assignable devices nodes. |
| |
| ```dts |
| /dts-v1/; |
| /plugin/; |
| |
| / { |
| // host node describes physical devices and IOMMUs, and wouldn't be applied to VM DT |
| host { |
| #address-cells = <0x2>; |
| #size-cells = <0x1>; |
| rng { |
| reg = <0x0 0x12f00000 0x1000>; |
| iommus = <&iommu0 0x3>; |
| android,pvmfw,target = <&rng>; |
| }; |
| light { |
| reg = <0x0 0x00f00000 0x1000>, <0x0 0x00f10000 0x1000>; |
| iommus = <&iommu1 0x4>, <&iommu2 0x5>; |
| android,pvmfw,target = <&light>; |
| }; |
| led { |
| reg = <0x0 0x12000000 0x1000>; |
| iommus = <&iommu1 0x3>; |
| android,pvmfw,target = <&led>; |
| }; |
| bus0 { |
| #address-cells = <0x1>; |
| #size-cells = <0x1>; |
| backlight { |
| reg = <0x300 0x100>; |
| android,pvmfw,target = <&backlight>; |
| }; |
| }; |
| iommu0: iommu0 { |
| #iommu-cells = <0x1>; |
| android,pvmfw,token = <0x0 0x12e40000>; |
| }; |
| iommu1: iommu1 { |
| #iommu-cells = <0x1>; |
| android,pvmfw,token = <0x0 0x40000>; |
| }; |
| iommu2: iommu2 { |
| #iommu-cells = <0x1>; |
| android,pvmfw,token = <0x0 0x50000>; |
| }; |
| }; |
| }; |
| |
| // Beginning of the assignable devices. Assigned devices would be applied to VM DT |
| &{/} { // We only allows to overlay to root node |
| rng: rng { |
| compatible = "android,rng"; |
| android,rng,ignore-gctrl-reset; |
| }; |
| light: light { |
| compatible = "android,light"; |
| version = <0x1 0x2>; |
| }; |
| led: led { |
| compatible = "android,led"; |
| prop = <0x555>; |
| }; |
| bus0 { |
| backlight: backlight { |
| compatible = "android,backlight"; |
| android,backlight,ignore-gctrl-reset; |
| }; |
| }; |
| }; |
| ``` |
| |
| If you compile the above with `dtc -@`, then you'll get `__symbols__` for free. |
| `__symbol__` has label of nodes, and it's required for the next step. |
| |
| ```dts |
| // generated __symbols__ |
| __symbols__ { |
| iommu0 = "/host/iommu0"; |
| iommu1 = "/host/iommu1"; |
| iommu2 = "/host/iommu2"; |
| rng = "/fragment@rng/__overlay__/rng"; |
| light = "/fragment@sensor/__overlay__/light"; |
| led = "/fragment@led/__overlay__/led"; |
| backlight = "/fragment@backlight/__overlay__/bus0/backlight"; |
| }; |
| ``` |
| |
| ## Prepare AVF assignable devices XML |
| |
| AVF requires assignable device information to unbind from the host device driver |
| and bind to VFIO driver. The information should be provided in an XML file at |
| `/vendor/etc/avf/assignable_devices.xml`. |
| |
| Here's example. |
| |
| ```xml |
| <devices> |
| <device> |
| <kind>sensor</kind> |
| <dtbo_label>light</dtbo_label> |
| <sysfs_path>/sys/bus/platform/devices/16d00000.light</sysfs_path> |
| </device> |
| </devices> |
| ``` |
| |
| * `<kind>`: Device kind. Currently only used for debugging purposes and not used |
| for device assignment. |
| * `<dtbo_label>`: Label in the VM DTBO (i.e. symbol in `__symbols__`). Must be |
| non-empty and unique in the XML. |
| * `<sysfs_path>`: Sysfs path of the device in host, used to bind to the VFIO |
| driver. Must be non-empty and unique in the XML. |
| |
| ### List support assignable devices |
| |
| In order to query list of the devices that can be assigned to a pVM, run the |
| following command: |
| |
| ```bash |
| adb shell /apex/com.android.virt/bin/vm info |
| ``` |
| |
| All supported assignable devices will be located under the "Assignable devices:" |
| section of the output. |
| |
| ## Boot with VM DTBO |
| |
| Bootloader should provide VM DTBO to both Android and pvmfw. |
| |
| ### Provide VM DTBO index in dtbo.img |
| |
| Bootloader should provide the VM DTBO index with sysprop |
| `ro.boot.hypervisor.vm_dtbo_idx.`. DTBO index represents DTBO location in |
| dtbo.img. |
| |
| ### Provide VM DTBO in the pvmfw config |
| |
| For protected VM, bootloader must provide VM DTBO to the pvmfw. pvmfw sanitizes |
| incoming device tree with the VM DTBO. |
| |
| For more detail about providing VM DTBO in pvmfw, |
| see: [pvmfw/README.md](../guest/pvmfw/README.md#configuration-data-format) |
| |
| |
| ## Launch VM with device assignment |
| |
| We don't support client API yet in Android V, but you can use CLI to test device |
| assignment. Note that host kernel support is required. |
| |
| Specify `--devices ${sysfs_path}` when booting VM. The parameter can be repeated |
| multiple times for specifying multiple devices. |
| |
| Here's an example: |
| |
| ```sh |
| adb shell /apex/com.android.virt/bin/vm run-microdroid --devices /sys/bus/platform/devices/16d00000.light |
| ``` |