1Passthrough a device described in the Device Tree to a guest
2============================================================
3
4The example will use the secondary network card for the midway server.
5
61) Mark the device to let Xen know the device will be used for passthrough.
7This is done in the device tree node describing the device by adding the
8property "xen,passthrough". The command to do it in U-Boot is:
9
10    fdt set /soc/ethernet@fff51000 xen,passthrough
11
122) Create a partial device tree describing the device. The IRQ are mapped
131:1 to the guest (i.e VIRQ == IRQ). For MMIO, you will have to find a hole
14in the guest memory layout (see xen/include/public/arch-arm.h, note that
15the layout is not stable and can change between versions of Xen). Please
16be aware that passing a partial device tree to a VM is a powerful tool,
17use it with care. In production, only allow assignment of devices which
18have been previously tested and known to work correctly when given to
19guests.
20
21/dts-v1/;
22
23/ {
24    /* #*cells are here to keep DTC happy */
25    #address-cells = <2>;
26    #size-cells = <2>;
27
28    aliases {
29        net = &mac0;
30    };
31
32    passthrough {
33        compatible = "simple-bus";
34        ranges;
35        #address-cells = <2>;
36        #size-cells = <2>;
37        mac0: ethernet@10000000 {
38            compatible = "calxeda,hb-xgmac";
39            reg = <0 0x10000000 0 0x1000>;
40            interrupts = <0 80 4  0 81 4  0 82 4>;
41        };
42    };
43};
44
45Note:
46    * The interrupt-parent property will be added by the toolstack in the
47    root node;
48    * The following properties are mandatory with the /passthrough node:
49        - compatible: It should always contain "simple-bus"
50        - ranges
51        - #address-cells
52        - #size-cells
53    * See http://www.devicetree.org/Device_Tree_Usage for more
54    information about device tree.
55    * In this example, the device MMIO region is placed at a different
56    address (0x10000000) compared to the host address (0xfff51000)
57
583) Compile the partial guest device with dtc (Device Tree Compiler).
59For our purpose, the compiled file will be called guest-midway.dtb and
60placed in /root in DOM0.
61
623) Add the following options in the guest configuration file:
63
64device_tree = "/root/guest-midway.dtb"
65dtdev = [ "/soc/ethernet@fff51000" ]
66irqs = [ 112, 113, 114 ]
67iomem = [ "0xfff51,1@0x10000" ]
68
69Please refer to your platform docs for the MMIO ranges and interrupts.
70
71They can also be calculated from the original device tree (not
72recommended). You can read about the "interrupts" property format in the
73device tree bindings of the interrupt controller of your platform. For
74example, in the case of GICv2 see [arm,gic.txt]; in the case of GICv3
75see [arm,gic-v3.txt] in the Linux repository. For both GICv2 and GICv3
76the "interrupts" property format is the same: the first cell is the
77interrupt type, and the second cell is the interrupt number.  Given that
78SPI numbers start from 32, in this example 80 + 32 = 112.
79
80See man [xl.cfg] for the iomem format. The reg property is just a pair
81of address, then size numbers, each of them can occupy 1 or 2 cells.
82
83
84Dom0-less Device Passthrough
85============================
86
87The partial device tree for dom0-less guests should have the following
88properties for each node corresponding to a physical device to assign to
89the guest:
90
91- xen,reg
92
93  The xen,reg property is an array of:
94
95    <phys_addr size guest_addr>
96
97  They specify the physical address and size of the device memory
98  ranges together with the corresponding guest address to map them to.
99  The size of `phys_addr' and `guest_addr' is determined by
100  #address-cells, the size of `size' is determined by #size-cells, of
101  the partial device tree.
102  The memory will be mapped as device memory in the guest (Device-nGnRE).
103
104- xen,path
105
106  A string property representing the path in the host device tree to the
107  corresponding device node.
108
109- xen,force-assign-without-iommu
110
111  If xen,force-assign-without-iommu is present, Xen allows to assign a
112  device even if it is not behind an IOMMU. This renders your platform
113  *unsafe* if the device is DMA-capable.
114
115In addition, a special /gic node is expected as a placeholder for the
116full GIC node that will be added by Xen for the guest. /gic can be
117referenced by other properties in the device tree fragment. For
118instance, it can be referenced by interrupt-parent under a device node.
119Xen will take care of replacing the "gic" placeholder node for a
120complete GIC node while retaining all the references correctly. The new
121GIC node created by Xen is a regular interrupt-controller@<unit> node.
122
123    gic: gic {
124        #interrupt-cells = <0x3>;
125        interrupt-controller;
126    };
127
128Note that the #interrupt-cells and interrupt-controller properties are
129not actually required, however, DTC expects them to be present if gic is
130referenced by interrupt-parent or similar.
131
132
133Example
134=======
135
136The following is a real-world example of a device tree fragment to
137assign a network card to a dom0-less guest on Xilinx Ultrascale+ MPSoC:
138
139/dts-v1/;
140
141/ {
142    #address-cells = <2>;
143    #size-cells = <1>;
144
145    gic: gic {
146        #interrupt-cells = <3>;
147        interrupt-controller;
148    };
149
150    passthrough {
151        compatible = "simple-bus";
152        ranges;
153        #address-cells = <2>;
154        #size-cells = <1>;
155
156        misc_clk: misc_clk {
157            #clock-cells = <0>;
158            clock-frequency = <0x7735940>;
159            compatible = "fixed-clock";
160        };
161
162        ethernet@ff0e0000 {
163            compatible = "cdns,zynqmp-gem";
164            status = "okay";
165            reg = <0x0 0xff0e0000 0x1000>;
166            clock-names = "pclk", "hclk", "tx_clk", "rx_clk";
167            #address-cells = <1>;
168            #size-cells = <0>;
169            clocks = <&misc_clk &misc_clk &misc_clk &misc_clk>;
170            phy-mode = "rgmii-id";
171            xlnx,ptp-enet-clock = <0>;
172            local-mac-address = [00 0a 35 00 22 01];
173            interrupt-parent = <&gic>;
174            interrupts = <0 63 0x4 0 63 0x4>;
175            xen,path = "/amba/ethernet@ff0e0000";
176            xen,reg = <0x0 0xff0e0000 0x1000 0x0 0xff0e0000>;
177
178            phy@c {
179                reg = <0xc>;
180                ti,rx-internal-delay = <0x8>;
181                ti,tx-internal-delay = <0xa>;
182                ti,fifo-depth = <0x1>;
183                ti,rxctrl-strap-worka;
184            };
185        };
186    };
187};
188
189
190[arm,gic.txt]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
191[arm,gic-v3.txt]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
192[xl.cfg]: https://xenbits.xen.org/docs/unstable/man/xl.cfg.5.html
193