Difference between revisions of "R-Car/Virtualization/VFIO"

From eLinux.org
Jump to: navigation, search
(GPIO Pass-Through / Host Side)
 
(GPIO Pass-Through / Guest Side)
Line 32: Line 32:
 
iommu: Adding device e6055400.gpio to group 0
 
iommu: Adding device e6055400.gpio to group 0
 
vfio-platform e6055400.gpio: Adding kernel taint for vfio-noiommu group on device
 
vfio-platform e6055400.gpio: Adding kernel taint for vfio-noiommu group on device
 +
</pre>
 +
 +
== Guest Side ==
 +
 +
* Build a guest kernel using:
 +
** Repository: git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git
 +
** Branch: "topic/rcar3-virt-gpio-passthrough"
 +
** Config: "virt_defconfig"
 +
 +
* Build QEMU using:
 +
** Repository: https://github.com/geertu/qemu.git
 +
** Branch: "TBD"
 +
 +
* When starting QEMU, specify pass-through of the GPIO6 platform device.  The device specifier consists of three parts:
 +
*; $1a
 +
*: the device's node name, or
 +
*; $1b
 +
*: the full path to the device's node in sysfs,
 +
*; $2
 +
*: the manufacturer part of the device's compatible value,
 +
*; $3
 +
*: the model part of the device's compatible value.
 +
I.e.:
 +
<pre>
 +
-device vfio-platform,host=$1a,manufacturer=$2,model=$3
 +
-device vfio-platform,host=e6055400.gpio,manufacturer=renesas,model=rcar-gen3-gpio
 +
-device vfio-platform,sysfsdev=$1b,manufacturer=$2,model=$3
 +
-device vfio-platform,sysfsdev=/sys/bus/platform/devices/e6055400.gpio,manufacturer=renesas,model=rcar-gen3-gpio
 +
</pre>
 +
 +
Full command line:
 +
<pre>
 +
$ qemu-system-aarch64 -enable-kvm -M virt -cpu cortex-a57 -m 1024 -nographic \
 +
        -kernel /path/to/guest/kernel/Image \
 +
        -device vfio-platform,host=e6055400.gpio,manufacturer=renesas,model=rcar-gen3-gpio
 +
</pre>
 +
 +
Host kernel output:
 +
<pre>
 +
vfio-platform e6055400.gpio: no reset function found!
 +
vfio-platform e6055400.gpio: vfio-noiommu device opened by user (qemu-system-aar:3003)
 +
</pre>
 +
 +
Guest kernel output:
 +
<pre>
 +
Booting Linux on physical CPU 0x0000000000 [0x411fd073]
 +
...
 +
gpio_rcar c000000.e6055400.gpio: missing clock, ignoring
 +
gpio_rcar c000000.e6055400.gpio: missing IRQ, ignoring
 +
gpio_rcar c000000.e6055400.gpio: driving 32 GPIOs
 +
...
 +
</pre>
 +
 +
* Analysis of "/sys/firmware/devicetree/base" using "dtx_diff" shows that "e6055400.gpio@0" has been added as a subnode to the existing "platform@c000000" node:
 +
<pre>
 +
--- /sys/firmware/devicetree/base.orig
 +
+++ /sys/firmware/devicetree/base
 +
@@ -124,6 +124,13 @@
 +
                compatible = "qemu,platform", "simple-bus";
 +
                interrupt-parent = <0x8001>;
 +
                ranges = <0x0 0x0 0xc000000 0x2000000>;
 +
+
 +
+              e6055400.gpio@0 {
 +
+                      #gpio-cells = <0x2>;
 +
+                      compatible = "renesas,rcar-gen3-gpio";
 +
+                      gpio-controller;
 +
+                      reg = <0x0 0x50>;
 +
+              };
 +
        };
 +
 +
        pmu {
 +
</pre>
 +
 +
* Export GPIOs used for LEDs, and turn all LEDs off:
 +
<pre>
 +
base=$(cat /sys/class/gpio/gpiochip*/base)
 +
for i in $(seq 11 13); do
 +
    echo $(($base + $i)) > /sys/class/gpio/export
 +
    echo low > /sys/class/gpio/gpio$(($base + $i))/direction
 +
done
 +
</pre>
 +
 +
* Cycle through all LEDs, letting them blink once:
 +
<pre>
 +
for i in $(seq 11 13); do
 +
    echo high > /sys/class/gpio/gpio$(($base + $i))/direction
 +
    sleep 1
 +
    echo low > /sys/class/gpio/gpio$(($base + $i))/direction
 +
done
 
</pre>
 
</pre>

Revision as of 05:28, 9 February 2018

Device Pass-Through Using VFIO

Platform Device Pass-Through Proof-of-Concept

This is a proof-of-concept showing how to provide guest access to an R-Car GPIO controller block on the Renesas Salvator-XS board.

Host Side

  • Configure workarounds for missing functionality:
$ echo 0 > /sys/module/vfio_platform/parameters/reset_required
$ echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode
  • Unbind GPIO6 from the "gpio-rcar" driver:
$ echo e6055400.gpio > /sys/bus/platform/drivers/gpio_rcar/unbind
gpio gpiochip6: REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED
  • Bind GPIO6 to the "vfio-platform" driver, for pass-through to guests:
$ echo vfio-platform > /sys/bus/platform/devices/e6055400.gpio/driver_override
$ echo e6055400.gpio > /sys/bus/platform/drivers/vfio-platform/bind
iommu: Adding device e6055400.gpio to group 0
vfio-platform e6055400.gpio: Adding kernel taint for vfio-noiommu group on device

Guest Side

  • When starting QEMU, specify pass-through of the GPIO6 platform device. The device specifier consists of three parts:
    $1a
    the device's node name, or
    $1b
    the full path to the device's node in sysfs,
    $2
    the manufacturer part of the device's compatible value,
    $3
    the model part of the device's compatible value.

I.e.:

-device vfio-platform,host=$1a,manufacturer=$2,model=$3
-device vfio-platform,host=e6055400.gpio,manufacturer=renesas,model=rcar-gen3-gpio
-device vfio-platform,sysfsdev=$1b,manufacturer=$2,model=$3
-device vfio-platform,sysfsdev=/sys/bus/platform/devices/e6055400.gpio,manufacturer=renesas,model=rcar-gen3-gpio

Full command line:

$ qemu-system-aarch64 -enable-kvm -M virt -cpu cortex-a57 -m 1024 -nographic \
        -kernel /path/to/guest/kernel/Image \
        -device vfio-platform,host=e6055400.gpio,manufacturer=renesas,model=rcar-gen3-gpio

Host kernel output:

vfio-platform e6055400.gpio: no reset function found!
vfio-platform e6055400.gpio: vfio-noiommu device opened by user (qemu-system-aar:3003)

Guest kernel output:

Booting Linux on physical CPU 0x0000000000 [0x411fd073]
...
gpio_rcar c000000.e6055400.gpio: missing clock, ignoring
gpio_rcar c000000.e6055400.gpio: missing IRQ, ignoring
gpio_rcar c000000.e6055400.gpio: driving 32 GPIOs
...
  • Analysis of "/sys/firmware/devicetree/base" using "dtx_diff" shows that "e6055400.gpio@0" has been added as a subnode to the existing "platform@c000000" node:
--- /sys/firmware/devicetree/base.orig
+++ /sys/firmware/devicetree/base
@@ -124,6 +124,13 @@
                compatible = "qemu,platform", "simple-bus";
                interrupt-parent = <0x8001>;
                ranges = <0x0 0x0 0xc000000 0x2000000>;
+
+               e6055400.gpio@0 {
+                       #gpio-cells = <0x2>;
+                       compatible = "renesas,rcar-gen3-gpio";
+                       gpio-controller;
+                       reg = <0x0 0x50>;
+               };
        };

        pmu {
  • Export GPIOs used for LEDs, and turn all LEDs off:
base=$(cat /sys/class/gpio/gpiochip*/base)
for i in $(seq 11 13); do
    echo $(($base + $i)) > /sys/class/gpio/export
    echo low > /sys/class/gpio/gpio$(($base + $i))/direction
done
  • Cycle through all LEDs, letting them blink once:
for i in $(seq 11 13); do
    echo high > /sys/class/gpio/gpio$(($base + $i))/direction
    sleep 1
    echo low > /sys/class/gpio/gpio$(($base + $i))/direction
done