diff options
Diffstat (limited to 'meta-agl-devel/meta-agl-jailhouse')
50 files changed, 5698 insertions, 0 deletions
diff --git a/meta-agl-devel/meta-agl-jailhouse/README.md b/meta-agl-devel/meta-agl-jailhouse/README.md new file mode 100644 index 00000000..c4a32bfd --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/README.md @@ -0,0 +1,43 @@ +# Jailhouse support layer + +Yocto layer that enables use of the Jailhouse partitioning hypervisor - <https://github.com/siemens/jailhouse>. + +## How to use + +The AGL feature `agl-jailhouse` has to be enabled. That needs to be done when including aglsetup.sh, for example: + + source meta-agl/scripts/aglsetup.sh -m raspberrypi4 agl-demo agl-netboot agl-appfw-smack agl-jailhouse + +That will enable this layer and include the `jailhouse` package in the image. + +Then, in the target system, the cell configurations (*.cell) are placed in `/usr/share/jailhouse/cells/` and the demo inmates (bare-metal applications to run in a non-root cell) are located in `/usr/share/jailhouse/inmates`. + +## Raspberry Pi 4 example + +Use this commands to enable Jailhouse and run the GIC demo inmate in a non-root cell. After issuing these commands, the GIC demo will be mesauring jitter of a timer and print the output on the serial console of the RPi. + + jailhouse enable /usr/share/jailhouse/cells/rpi4.cell + jailhouse cell create /usr/share/jailhouse/cells/rpi4-inmate-demo.cell + jailhouse cell load inmate-demo /usr/share/jailhouse/inmates/gic-demo.bin + jailhouse cell start inmate-demo + +## Dependencies + +This layer depends on: + +* URI: git://git.yoctoproject.org/meta-arm + * branch: dunfell + * revision: 0bd9c740267c0926e89bcfdb489790b7bf1fbd4b + * note: actually only required on the Raspberry Pi 4 target + +## Supported targets + +* Raspberry Pi 4 + * All (1G-8G) memory variants. But note that there is 256M reserved for Jailhouse and 256MiB for GPU in AGL, so the smaller variants are not recommended. + +* QEMU x86-64 + * Work in progress. Requires KVM. Nested virtualization must be enabled on the host. Currently, the right configuration of QEMU and Jailhouse to work out-of-box is being worked on. + + + + diff --git a/meta-agl-devel/meta-agl-jailhouse/conf/layer.conf b/meta-agl-devel/meta-agl-jailhouse/conf/layer.conf new file mode 100644 index 00000000..2031e788 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/conf/layer.conf @@ -0,0 +1,23 @@ +# We have a conf and classes directory, append to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have a recipes directory, add to BBFILES +BBFILES += "${LAYERDIR}/recipes*/*/*.bb ${LAYERDIR}/recipes*/*/*.bbappend" + +BBFILE_COLLECTIONS += "agl-jailhouse" +BBFILE_PATTERN_agl-jailhouse := "^${LAYERDIR}/" +BBFILE_PRIORITY_agl-jailhouse = "61" + +# This should only be incremented on significant changes that will +# cause compatibility issues with other layers +LAYERVERSION_agl-jailhouse = "1" +LAYERSERIES_COMPAT_agl-jailhouse = "dunfell" + +# This is only needed for Raspberry Pi +# TODO: can this be expressed dynamically? +LAYERDEPENDS_agl-jailhouse = "meta-arm" + +BBFILES_DYNAMIC += " \ + raspberrypi:${LAYERDIR}/dynamic-layers/raspberrypi/*/*/*.bbappend \ +" + diff --git a/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-bsp/bootfiles/rpi-config_git.bbappend b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-bsp/bootfiles/rpi-config_git.bbappend new file mode 100644 index 00000000..687980cf --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-bsp/bootfiles/rpi-config_git.bbappend @@ -0,0 +1,31 @@ + +do_deploy_append_raspberrypi4() { + # if ARMSTUB is set, it should be set in config.txt by earlier recipes, so replace it + if [ -n "${ARMSTUB}" ]; then + sed -i 's/^armstub=.*/armstub=bl31.bin/' ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + + if ! grep '^enable_gic' config.txt; then + sed -i 's/^enable_gic=.*/enable_gic=1/' ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + else + echo "enable_gic=1" >> ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + fi + + # otherwise, set it + else + echo "# ARM stub configuration" >> ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + echo "armstub=bl31.bin" >> ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + echo "enable_gic=1" >> ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + fi + + sed -i -e "s#dtoverlay=mcp2515.*##g" ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + echo "# Enable CAN (Waveshare RS485 CAN HAT)" >> ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + echo "dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=25,spimaxfrequency=1000000" >> ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + + # memory reserved for Jailhouse + echo "dtoverlay=jailhouse-memory" >> ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + echo "dtoverlay=jailhouse-memory,start=0xe0000000,size=0x200000" >> ${DEPLOYDIR}/bcm2835-bootfiles/config.txt + + +} + + diff --git a/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-bsp/trusted-firmware-a/trusted-firmware-a_%.bbappend b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-bsp/trusted-firmware-a/trusted-firmware-a_%.bbappend new file mode 100644 index 00000000..158eb6e8 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-bsp/trusted-firmware-a/trusted-firmware-a_%.bbappend @@ -0,0 +1,21 @@ +COMPATIBLE_MACHINE = "raspberrypi4" +TFA_BUILD_TARGET = "bl31" +TFA_PLATFORM = "rpi4" + +# Skip installing the binary into /lib/firmware. We only need it on the boot +# partition that is generated from the files in DEPLOYDIR +do_install[noexec] = "1" + +FILES_${PN} = "" + +do_deploy() { + if ${@"true" if d.getVar('TFA_DEBUG') == '1' else "false"}; then + BUILD_PLAT=${B}/${BUILD_DIR}/debug/ + else + BUILD_PLAT=${B}/${BUILD_DIR}/release/ + fi + + install -d ${DEPLOYDIR}/bcm2835-bootfiles + cp ${BUILD_PLAT}/bl31.bin ${DEPLOYDIR}/bcm2835-bootfiles/bl31.bin +} + diff --git a/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-extended/jailhouse/jailhouse_%.bbappend b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-extended/jailhouse/jailhouse_%.bbappend new file mode 100644 index 00000000..1d8ea6b7 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-extended/jailhouse/jailhouse_%.bbappend @@ -0,0 +1,2 @@ +DEPENDS_append_raspberrypi4 = " trusted-firmware-a" + diff --git a/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-kernel/linux/linux-raspberrypi/0001-dt-dtoverlays-Add-jailhouse-memory-DT-overlay.patch b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-kernel/linux/linux-raspberrypi/0001-dt-dtoverlays-Add-jailhouse-memory-DT-overlay.patch new file mode 100644 index 00000000..1b6373cc --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-kernel/linux/linux-raspberrypi/0001-dt-dtoverlays-Add-jailhouse-memory-DT-overlay.patch @@ -0,0 +1,87 @@ +From c6319fb59e0cd5b6d3d4e3401abd9c2057059a74 Mon Sep 17 00:00:00 2001 +From: Jakub Luzny <jakub@luzny.cz> +Date: Tue, 11 Aug 2020 10:40:18 +0200 +Subject: [PATCH] dt/dtoverlays: Add jailhouse-memory DT overlay + +It is meant to reserve memory that can be used by the Jailhouse partitioning +hypervisor. More regions can be reserved. + +Upstream-Status: Inappropriate [Jailhouse specific] + +Signed-off-by: Jakub Luzny <jakub@luzny.cz> +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 7 +++++ + .../boot/dts/overlays/jailhouse-memory-overlay.dts | 30 ++++++++++++++++++++++ + 3 files changed, 38 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/jailhouse-memory-overlay.dts + +diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile +index fa6db6eed3e2..38c61c67606d 100644 +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -92,6 +92,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + iqaudio-dacplus.dtbo \ + iqaudio-digi-wm8804-audio.dtbo \ + irs1125.dtbo \ ++ jailhouse-memory.dtbo \ + jedec-spi-nor.dtbo \ + justboom-both.dtbo \ + justboom-dac.dtbo \ +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index 69892d01faae..4a62f204b4f9 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1528,6 +1528,13 @@ Load: dtoverlay=irs1125 + Params: <None> + + ++Name: jailhouse-memory ++Info: Reserves memory for use by the Jailhouse hypervisor ++Load: dtoverlay=jailhouse-memory,<param>=<val> ++Params: start Start of the reserved memory area (default 0x20000000) ++ size Size of the reserved memory area (default 0x10000000) ++ ++ + Name: jedec-spi-nor + Info: Adds support for JEDEC-compliant SPI NOR flash devices. (Note: The + "jedec,spi-nor" kernel driver was formerly known as "m25p80".) +diff --git a/arch/arm/boot/dts/overlays/jailhouse-memory-overlay.dts b/arch/arm/boot/dts/overlays/jailhouse-memory-overlay.dts +new file mode 100644 +index 000000000000..26c3ce6b9e3d +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/jailhouse-memory-overlay.dts +@@ -0,0 +1,30 @@ ++// Reserves memory for use by the Jailhouse hypervisor ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ++ ranges; ++ ++ jailhouse_memory: jailhouse@20000000 { ++ reg = <0x0 0x20000000 0x10000000>; ++ no-map; ++ }; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ start = <&jailhouse_memory>,"reg#0"; ++ size = <&jailhouse_memory>,"reg:8"; ++ }; ++}; +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-kernel/linux/linux-raspberrypi_5.4%.bbappend b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-kernel/linux/linux-raspberrypi_5.4%.bbappend new file mode 100644 index 00000000..1456fdc8 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/dynamic-layers/raspberrypi/recipes-kernel/linux/linux-raspberrypi_5.4%.bbappend @@ -0,0 +1,9 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI += "file://0001-dt-dtoverlays-Add-jailhouse-memory-DT-overlay.patch" + + +LINUX_VERSION = "5.4.51" +SRCREV = "2c8ec3bb4403a7c76c22ec6d3d5fc4b2a366024e" + +require recipes-kernel/linux/linux-jailhouse-5.4.inc diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-apic-demo.c b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-apic-demo.c new file mode 100644 index 00000000..f49cd3a4 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-apic-demo.c @@ -0,0 +1,78 @@ +/* + * Jailhouse, a Linux-based partitioning hypervisor + * + * Minimal configuration for demo inmates, 1 CPU, 1 MB RAM, 1 serial port + * + * Copyright (c) Siemens AG, 2013 + * + * Authors: + * Jan Kiszka <jan.kiszka@siemens.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include <jailhouse/types.h> +#include <jailhouse/cell-config.h> + +struct { + struct jailhouse_cell_desc cell; + __u64 cpus[1]; + struct jailhouse_memory mem_regions[2]; + struct jailhouse_cache cache_regions[1]; + struct jailhouse_pio pio_regions[1];//[2]->[1] stop @0x3f8 +} __attribute__((packed)) config = { + .cell = { + .signature = JAILHOUSE_CELL_DESC_SIGNATURE, + .revision = JAILHOUSE_CONFIG_REVISION, + .name = "agl-apic-demo", + .flags = JAILHOUSE_CELL_VIRTUAL_CONSOLE_PERMITTED, + + .cpu_set_size = sizeof(config.cpus), + .num_memory_regions = ARRAY_SIZE(config.mem_regions), + .num_cache_regions = ARRAY_SIZE(config.cache_regions), + .num_irqchips = 0, + .num_pio_regions = ARRAY_SIZE(config.pio_regions), + .num_pci_devices = 0, + + .console = { + .type = JAILHOUSE_CON_TYPE_8250, + .flags = JAILHOUSE_CON_ACCESS_PIO, + .address = 0x2f8, /* ######## ttyS0 is host -> ttyS1 */ + }, + }, + + .cpus = { + 0x8, + }, + + .mem_regions = { + /* RAM */ { /* JH_memory: 0x22600000-0x271fffff */ + .phys_start = 0x26e00000 , /* agl-linux-x86: 0x22600000-0x26e00000 */ + .virt_start = 0, /* agl-ivshmem: 0x26e00000- (end of ivshmem cell) */ + .size = 0x00100000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE, + }, + /* communication region */ { + .virt_start = 0x00100000, + .size = 0x00001000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_COMM_REGION, + }, + }, + + .cache_regions = { + { + .start = 0, + .size = 2, + .type = JAILHOUSE_CACHE_L3, + }, + }, + + .pio_regions = { + PIO_RANGE(0x2f8, 8), /* serial 2 */ +// PIO_RANGE(0x3f8, 8), /* serial 1 */ + PIO_RANGE(0xe010, 8), /* OXPCIe952 serial */ + }, +}; diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-ivshmem-demo.c b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-ivshmem-demo.c new file mode 100644 index 00000000..79feb6c5 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-ivshmem-demo.c @@ -0,0 +1,119 @@ +/* + * Jailhouse, a Linux-based partitioning hypervisor + * + * Minimal configuration for ivshmem inmate demo: + * 1 CPU, 1MB RAM, serial ports, 4K shmem + * + * Copyright (c) Siemens AG, 2013, 2014 + * + * Authors: + * Henning Schild <henning.schild@siemens.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include <jailhouse/types.h> +#include <jailhouse/cell-config.h> + +struct { + struct jailhouse_cell_desc cell; + __u64 cpus[1]; + struct jailhouse_memory mem_regions[7]; + struct jailhouse_pio pio_regions[1]; + struct jailhouse_pci_device pci_devices[1]; + struct jailhouse_pci_capability pci_caps[0]; +} __attribute__((packed)) config = { + .cell = { + .signature = JAILHOUSE_CELL_DESC_SIGNATURE, + .revision = JAILHOUSE_CONFIG_REVISION, + .name = "ivshmem-demo", + .flags = JAILHOUSE_CELL_PASSIVE_COMMREG | + JAILHOUSE_CELL_VIRTUAL_CONSOLE_PERMITTED, + + .cpu_set_size = sizeof(config.cpus), + .num_memory_regions = ARRAY_SIZE(config.mem_regions), + .num_irqchips = 0, + .num_pio_regions = ARRAY_SIZE(config.pio_regions), + .num_pci_devices = ARRAY_SIZE(config.pci_devices), + .num_pci_caps = ARRAY_SIZE(config.pci_caps), + + .console = { + .type = JAILHOUSE_CON_TYPE_8250, + .flags = JAILHOUSE_CON_ACCESS_PIO, + .address = 0x2f8,/* ######## ttyS0 is host -> ttyS1 */ + }, + }, + + .cpus = { + 0b0010, + }, + + .mem_regions = { + /* IVSHMEM shared memory regions (demo) */ + { + .phys_start = 0x271f0000, + .virt_start = 0x271f0000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x271f1000, + .virt_start = 0x271f1000, + .size = 0x9000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x271fa000, + .virt_start = 0x271fa000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x271fc000, + .virt_start = 0x271fc000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x271fe000, + .virt_start = 0x271fe000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + /* RAM */ { + .phys_start = 0x27200000,/* to 0x27300000 */ + .virt_start = 0, + .size = 0x00100000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE, + }, + /* communication region */ { + .virt_start = 0x00100000, + .size = 0x00001000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_COMM_REGION, + }, + }, + + .pio_regions = { + PIO_RANGE(0x2f8, 8), /* serial 2 */ +// PIO_RANGE(0x3f8, 8), /* serial 1 */ + }, + + .pci_devices = { + { + .type = JAILHOUSE_PCI_TYPE_IVSHMEM, + .domain = 0x0000, + .bdf = 0x0e << 3, + .bar_mask = JAILHOUSE_IVSHMEM_BAR_MASK_MSIX, + .num_msix_vectors = 16, + .shmem_regions_start = 0, + .shmem_dev_id = 1, + .shmem_peers = 3, + .shmem_protocol = JAILHOUSE_SHMEM_PROTO_UNDEFINED, + }, + }, +}; diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-linux-x86-demo.c b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-linux-x86-demo.c new file mode 100644 index 00000000..06085df5 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-linux-x86-demo.c @@ -0,0 +1,246 @@ +/* + * Jailhouse, a Linux-based partitioning hypervisor + * + * Configuration for Linux inmate, 1 CPU, 74 MB RAM, ~1MB shmem, serial ports + * + * Copyright (c) Siemens AG, 2013-2015 + * + * Authors: + * Jan Kiszka <jan.kiszka@siemens.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include <jailhouse/types.h> +#include <jailhouse/cell-config.h> + +struct { + struct jailhouse_cell_desc cell; + __u64 cpus[1]; + struct jailhouse_memory mem_regions[20]; + struct jailhouse_cache cache_regions[1]; + struct jailhouse_irqchip irqchips[1]; + struct jailhouse_pio pio_regions[1]; + struct jailhouse_pci_device pci_devices[4]; + struct jailhouse_pci_capability pci_caps[6]; +} __attribute__((packed)) config = { + .cell = { + .signature = JAILHOUSE_CELL_DESC_SIGNATURE, + .revision = JAILHOUSE_CONFIG_REVISION, + .name = "linux-x86-demo", + .flags = JAILHOUSE_CELL_PASSIVE_COMMREG | + JAILHOUSE_CELL_VIRTUAL_CONSOLE_PERMITTED, + + .cpu_set_size = sizeof(config.cpus), + .num_memory_regions = ARRAY_SIZE(config.mem_regions), + .num_cache_regions = ARRAY_SIZE(config.cache_regions), + .num_irqchips = ARRAY_SIZE(config.irqchips), + .num_pio_regions = ARRAY_SIZE(config.pio_regions), + .num_pci_devices = ARRAY_SIZE(config.pci_devices), + .num_pci_caps = ARRAY_SIZE(config.pci_caps), + }, + + .cpus = { + 0b1100, + }, + + .mem_regions = { + /* IVSHMEM shared memory region (virtio-blk front) */ + { + .phys_start = 0x27000000, /* to 0x27001000 */ + .virt_start = 0x27000000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x27001000,/* to 0x270e0000 */ + .virt_start = 0x27001000, + .size = 0xdf000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + { 0 }, + { 0 }, + /* IVSHMEM shared memory region (virtio-con front) */ + { + .phys_start = 0x270e0000,/* to 0x270e1000 */ + .virt_start = 0x270e0000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x270e1000,/*to 0x270f0000 */ + .virt_start = 0x270e1000, + .size = 0xf000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + { 0 }, + { 0 }, + /* IVSHMEM shared memory regions (demo) */ + { + .phys_start = 0x270f0000,/*to 0x270f1000 */ + .virt_start = 0x270f0000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x270f1000,/*to 0x270fa000 */ + .virt_start = 0x270f1000, + .size = 0x9000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x270fa000,/* to 0x270fc000 */ + .virt_start = 0x270fa000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x270fc000,/* to 0x270fe000*/ + .virt_start = 0x270fc000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { + .phys_start = 0x270fe000,/* to 0x27100000 */ + .virt_start = 0x270fe000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + /* IVSHMEM shared memory regions (networking) */ + JAILHOUSE_SHMEM_NET_REGIONS(0x27100000, 1), + /* low RAM */ { + .phys_start = 0x22600000,/* to 0x22700000*/ + .virt_start = 0, + .size = 0x00100000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA | + JAILHOUSE_MEM_LOADABLE, + }, + /* communication region */ { + /*.phys_start = ? */ + .virt_start = 0x00100000, + .size = 0x00001000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_COMM_REGION, + }, + /* high RAM */ { + .phys_start = 0x22700000,/*to 0x26e00000 */ + .virt_start = 0x00200000, + .size = 0x4700000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA | + JAILHOUSE_MEM_LOADABLE, + }, + }, + + .cache_regions = { + { + .start = 0, + .size = 2, + .type = JAILHOUSE_CACHE_L3, + }, + }, + + .irqchips = { + /* IOAPIC */ { + .address = 0xfec00000, + .id = 0xff00, + .pin_bitmap = { + (1 << 3) | (1 << 4), + }, + }, + }, + + .pio_regions = { + PIO_RANGE(0x2f8, 8), /* serial 2 */ +// PIO_RANGE(0x3f8, 8), /* serial 1 */ + PIO_RANGE(0xe010, 8), /* OXPCIe952 serial1 */ + }, + + .pci_devices = { + { + .type = JAILHOUSE_PCI_TYPE_IVSHMEM, + .domain = 0x0, + .bdf = 0x0c << 3, + .bar_mask = JAILHOUSE_IVSHMEM_BAR_MASK_MSIX, + .num_msix_vectors = 2, + .shmem_regions_start = 0, + .shmem_dev_id = 1, + .shmem_peers = 2, + .shmem_protocol = JAILHOUSE_SHMEM_PROTO_VIRTIO_FRONT + + VIRTIO_DEV_BLOCK, + }, + { + .type = JAILHOUSE_PCI_TYPE_IVSHMEM, + .domain = 0x0, + .bdf = 0x0d << 3, + .bar_mask = JAILHOUSE_IVSHMEM_BAR_MASK_MSIX, + .num_msix_vectors = 3, + .shmem_regions_start = 4, + .shmem_dev_id = 1, + .shmem_peers = 2, + .shmem_protocol = JAILHOUSE_SHMEM_PROTO_VIRTIO_FRONT + + VIRTIO_DEV_CONSOLE, + }, + { + .type = JAILHOUSE_PCI_TYPE_IVSHMEM, + .domain = 0x0, + .bdf = 0x0e << 3, + .bar_mask = JAILHOUSE_IVSHMEM_BAR_MASK_MSIX, + .num_msix_vectors = 16, + .shmem_regions_start = 8, + .shmem_dev_id = 2, + .shmem_peers = 3, + .shmem_protocol = JAILHOUSE_SHMEM_PROTO_UNDEFINED, + }, + { + .type = JAILHOUSE_PCI_TYPE_IVSHMEM, + .domain = 0x0, + .bdf = 0x0f << 3, + .bar_mask = JAILHOUSE_IVSHMEM_BAR_MASK_MSIX, + .num_msix_vectors = 2, + .shmem_regions_start = 13, + .shmem_dev_id = 1, + .shmem_peers = 2, + .shmem_protocol = JAILHOUSE_SHMEM_PROTO_VETH, + }, + }, + + .pci_caps = { + { + .id = PCI_CAP_ID_MSI, + .start = 0xd0, + .len = 14, + .flags = JAILHOUSE_PCICAPS_WRITE, + }, + { + .id = PCI_CAP_ID_EXP, + .start = 0xe0, + .len = 20, + .flags = JAILHOUSE_PCICAPS_WRITE, + }, + { + .id = PCI_CAP_ID_MSIX, + .start = 0xa0, + .len = 12, + .flags = JAILHOUSE_PCICAPS_WRITE, + }, + { + .id = PCI_EXT_CAP_ID_ERR | JAILHOUSE_PCI_EXT_CAP, + .start = 0x100, + .len = 4, + .flags = 0, + }, + { + .id = PCI_EXT_CAP_ID_DSN | JAILHOUSE_PCI_EXT_CAP, + .start = 0x140, + .len = 4, + .flags = 0, + }, + } +}; diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-pci-demo.c b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-pci-demo.c new file mode 100644 index 00000000..59d42323 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/agl-pci-demo.c @@ -0,0 +1,103 @@ +/* + * Jailhouse, a Linux-based partitioning hypervisor + * + * Minimal configuration for PCI demo inmate: + * 1 CPU, 1 MB RAM, serial ports, 1 Intel HDA PCI device + * + * Copyright (c) Siemens AG, 2014 + * + * Authors: + * Jan Kiszka <jan.kiszka@siemens.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include <jailhouse/types.h> +#include <jailhouse/cell-config.h> + +struct { + struct jailhouse_cell_desc cell; + __u64 cpus[1]; + struct jailhouse_memory mem_regions[3]; + struct jailhouse_pio pio_regions[1]; /* ttyS0 is host -> ttyS1 */ + struct jailhouse_pci_device pci_devices[1]; + struct jailhouse_pci_capability pci_caps[1]; +} __attribute__((packed)) config = { + .cell = { + .signature = JAILHOUSE_CELL_DESC_SIGNATURE, + .revision = JAILHOUSE_CONFIG_REVISION, + .name = "agl-pci-demo", + .flags = JAILHOUSE_CELL_PASSIVE_COMMREG | + JAILHOUSE_CELL_VIRTUAL_CONSOLE_PERMITTED, + + .cpu_set_size = sizeof(config.cpus), + .num_memory_regions = ARRAY_SIZE(config.mem_regions), + .num_irqchips = 0, + .num_pio_regions = ARRAY_SIZE(config.pio_regions), + .num_pci_devices = ARRAY_SIZE(config.pci_devices), + .num_pci_caps = ARRAY_SIZE(config.pci_caps), + + + .console = { + .type = JAILHOUSE_CON_TYPE_8250, + .flags = JAILHOUSE_CON_ACCESS_PIO, + .address = 0x2f8, + }, + }, + + .cpus = { + 0x4, + }, + + .mem_regions = { + /* RAM */ { + .phys_start = 0x26f00000,/*to 0x27000000| apic-demo @0x26e00000-@0x26f00000 */ + .virt_start = 0, + .size = 0x00100000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE, + }, + /* communication region */ { + .virt_start = 0x00100000, + .size = 0x00001000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_COMM_REGION, + }, + /* HDA BAR0 */ { + .phys_start = 0xfebd4000, + .virt_start = 0xfebd4000, + .size = 0x00004000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + }, + + + .pio_regions = { + PIO_RANGE(0x2f8, 8), /* serial 2 */ + //PIO_RANGE(0x3f8, 8), /* serial 1 */ + PIO_RANGE(0xe010, 8), /* OXPCIe952 serial2 */ + }, + + + .pci_devices = { + { /* Intel HDA @00:1b.0 */ + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .domain = 0x0000, + .bdf = 0x00d8, + .caps_start = 0, + .num_caps = 1, + .num_msi_vectors = 1, + .msi_64bits = 1, + }, + }, + + .pci_caps = { + { /* Intel HDA @00:1b.0 */ + .id = PCI_CAP_ID_MSI, + .start = 0x60, + .len = 14, + .flags = JAILHOUSE_PCICAPS_WRITE, + }, + }, +}; diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/qemu-agl.c b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/qemu-agl.c new file mode 100644 index 00000000..cf193c08 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/files/qemu-agl.c @@ -0,0 +1,637 @@ +/* + * Jailhouse, a Linux-based partitioning hypervisor + * + * Copyright (c) Siemens AG, 2014-2017 + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Alternatively, you can use or redistribute this file under the following + * BSD license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * Configuration for QEMU Standard PC (Q35 + ICH9, 2009) + * created with '/usr/libexec/jailhouse/jailhouse config create -c ttyS1 qemu-agl.c' + * + * NOTE: This config expects the following to be appended to your kernel cmdline + * "memmap=0x5200000$0x22000000" + */ + +#include <jailhouse/types.h> +#include <jailhouse/cell-config.h> + +struct { + struct jailhouse_system header; + __u64 cpus[1]; + struct jailhouse_memory mem_regions[17]; + struct jailhouse_irqchip irqchips[1]; + struct jailhouse_pio pio_regions[14]; + struct jailhouse_pci_device pci_devices[13]; + struct jailhouse_pci_capability pci_caps[14]; +} __attribute__((packed)) config = { + .header = { + .signature = JAILHOUSE_SYSTEM_SIGNATURE, + .revision = JAILHOUSE_CONFIG_REVISION, + .flags = JAILHOUSE_SYS_VIRTUAL_DEBUG_CONSOLE, + .hypervisor_memory = { + .phys_start = 0x22000000, + .size = 0x600000, + }, + .debug_console = { + .address = 0x2f8, + .type = JAILHOUSE_CON_TYPE_8250, + .flags = JAILHOUSE_CON_ACCESS_PIO | + JAILHOUSE_CON_REGDIST_1, + }, + .platform_info = { + .pci_mmconfig_base = 0xb0000000, + .pci_mmconfig_end_bus = 0xff, + .iommu_units = { + { + .type = JAILHOUSE_IOMMU_INTEL, + .base = 0xfed90000, + .size = 0x1000, + }, + }, + .x86 = { + .pm_timer_address = 0x608, + .vtd_interrupt_limit = 256, + }, + }, + .root_cell = { + .name = "RootCell", + .cpu_set_size = sizeof(config.cpus), + .num_memory_regions = ARRAY_SIZE(config.mem_regions), + .num_irqchips = ARRAY_SIZE(config.irqchips), + .num_pio_regions = ARRAY_SIZE(config.pio_regions), + .num_pci_devices = ARRAY_SIZE(config.pci_devices), + .num_pci_caps = ARRAY_SIZE(config.pci_caps), + }, + }, + + .cpus = { + 0x000000000000000f, + }, + + .mem_regions = { + /* MemRegion: 00000000-0009fbff : System RAM */ + { + .phys_start = 0x0, + .virt_start = 0x0, + .size = 0xa0000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA, + }, + /* MemRegion: 00100000-201fffff : System RAM */ + { + .phys_start = 0x100000, + .virt_start = 0x100000, + .size = 0x20100000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA, + }, + /* MemRegion: 20200000-21ffffff : Kernel */ + { + .phys_start = 0x20200000, + .virt_start = 0x20200000, + .size = 0x1e00000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA, + }, + /* MemRegion: 27200000-31ffffff : System RAM */ + { + .phys_start = 0x27200000, + .virt_start = 0x27200000, + .size = 0xae00000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA, + }, + /* MemRegion: 32000000-33ffffff : RAM buffer */ + { + .phys_start = 0x32000000, + .virt_start = 0x32000000, + .size = 0x2000000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA, + }, + /* MemRegion: fe000000-fe7fffff : 0000:00:01.0 */ + { + .phys_start = 0xfe000000, + .virt_start = 0xfe000000, + .size = 0x800000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: fe800000-fe803fff : virtio-pci-modern */ + { + .phys_start = 0xfe800000, + .virt_start = 0xfe800000, + .size = 0x4000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: fe804000-fe807fff : virtio-pci-modern */ + { + .phys_start = 0xfe804000, + .virt_start = 0xfe804000, + .size = 0x4000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: fe808000-fe80bfff : virtio-pci-modern */ + { + .phys_start = 0xfe808000, + .virt_start = 0xfe808000, + .size = 0x4000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: fe80c000-fe80ffff : virtio-pci-modern */ + { + .phys_start = 0xfe80c000, + .virt_start = 0xfe80c000, + .size = 0x4000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: feb80000-febbffff : 0000:00:02.0 */ + { + .phys_start = 0xfeb80000, + .virt_start = 0xfeb80000, + .size = 0x40000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: febd0000-febd3fff : ICH HD audio */ + { + .phys_start = 0xfebd0000, + .virt_start = 0xfebd0000, + .size = 0x4000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: febd7000-febd7fff : ehci_hcd */ + { + .phys_start = 0xfebd7000, + .virt_start = 0xfebd7000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: febd8000-febd8fff : ahci */ + { + .phys_start = 0xfebd8000, + .virt_start = 0xfebd8000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: fed00000-fed003ff : PNP0103:00 */ + { + .phys_start = 0xfed00000, + .virt_start = 0xfed00000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: 000c0000-000dffff : ROMs */ + { + .phys_start = 0xc0000, + .virt_start = 0xc0000, + .size = 0x20000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + /* MemRegion: 22600000-271fffff : JAILHOUSE Inmate Memory */ + { + .phys_start = 0x22600000, + .virt_start = 0x22600000, + .size = 0x4c00000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + }, + + .irqchips = { + /* IOAPIC 0, GSI base 0 */ + { + .address = 0xfec00000, + .id = 0xff00, + .pin_bitmap = { + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff + }, + }, + }, + + .pio_regions = { + /* Port I/O: 0000-001f : dma1 */ + /* PIO_RANGE(0x0, 0x20), */ + /* Port I/O: 0020-0021 : pic1 */ + /* PIO_RANGE(0x20, 0x2), */ + /* Port I/O: 0040-0043 : timer0 */ + PIO_RANGE(0x40, 0x4), + /* Port I/O: 0050-0053 : timer1 */ + /* PIO_RANGE(0x50, 0x4), */ + /* Port I/O: 0060-0060 : keyboard */ + PIO_RANGE(0x60, 0x1), + /* Port I/O: 0064-0064 : keyboard */ + PIO_RANGE(0x64, 0x1), + /* Port I/O: 0070-0077 : rtc0 */ + PIO_RANGE(0x70, 0x8), + /* Port I/O: 0080-008f : dma page reg */ + /* PIO_RANGE(0x80, 0x10), */ + /* Port I/O: 00a0-00a1 : pic2 */ + /* PIO_RANGE(0xa0, 0x2), */ + /* Port I/O: 00c0-00df : dma2 */ + /* PIO_RANGE(0xc0, 0x20), */ + /* Port I/O: 00f0-00ff : fpu */ + /* PIO_RANGE(0xf0, 0x10), */ + /* Port I/O: 02f8-02ff : serial */ + PIO_RANGE(0x2f8, 0x8), + /* Port I/O: 0378-037a : parport0 */ + /* PIO_RANGE(0x378, 0x3), */ + /* Port I/O: 03c0-03df : vga+ */ + PIO_RANGE(0x3c0, 0x20), + /* Port I/O: 03f8-03ff : serial */ + PIO_RANGE(0x3f8, 0x8), + /* Port I/O: 0510-051b : QEMU0002:00 */ + /* PIO_RANGE(0x510, 0xc), */ + /* Port I/O: 0600-0603 : ACPI PM1a_EVT_BLK */ + /* PIO_RANGE(0x600, 0x4), */ + /* Port I/O: 0604-0605 : ACPI PM1a_CNT_BLK */ + /* PIO_RANGE(0x604, 0x2), */ + /* Port I/O: 0608-060b : ACPI PM_TMR */ + /* PIO_RANGE(0x608, 0x4), */ + /* Port I/O: 0620-062f : ACPI GPE0_BLK */ + /* PIO_RANGE(0x620, 0x10), */ + /* Port I/O: 0700-073f : i801_smbus */ + /* PIO_RANGE(0x700, 0x40), */ + /* Port I/O: c000-c07f : 0000:00:04.0 */ + PIO_RANGE(0xc000, 0x80), + /* Port I/O: c0c0-c0df : 0000:00:02.0 */ + PIO_RANGE(0xc0c0, 0x20), + /* Port I/O: c0e0-c0ff : 0000:00:03.0 */ + PIO_RANGE(0xc0e0, 0x20), + /* Port I/O: c100-c11f : 0000:00:1d.0 */ + PIO_RANGE(0xc100, 0x20), + /* Port I/O: c120-c13f : 0000:00:1d.1 */ + PIO_RANGE(0xc120, 0x20), + /* Port I/O: c140-c15f : 0000:00:1d.2 */ + PIO_RANGE(0xc140, 0x20), + /* Port I/O: c160-c17f : 0000:00:1f.2 */ + PIO_RANGE(0xc160, 0x20), + }, + + .pci_devices = { + /* PCIDevice: 00:00.0 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0x0, + .bar_mask = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, + }, + .caps_start = 0, + .num_caps = 0, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + /* PCIDevice: 00:01.0 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0x8, + .bar_mask = { + 0xff800000, 0x00000000, 0xffffc000, + 0xffffffff, 0xfffff000, 0x00000000, + }, + .caps_start = 0, + .num_caps = 6, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 3, + .msix_region_size = 0x1000, + .msix_address = 0xfebd4000, + }, + /* PCIDevice: 00:02.0 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0x10, + .bar_mask = { + 0xffffffe0, 0xfffff000, 0x00000000, + 0x00000000, 0xffffc000, 0xffffffff, + }, + .caps_start = 0, + .num_caps = 6, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 3, + .msix_region_size = 0x1000, + .msix_address = 0xfebd5000, + }, + /* PCIDevice: 00:03.0 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0x18, + .bar_mask = { + 0xffffffe0, 0x00000000, 0x00000000, + 0x00000000, 0xffffc000, 0xffffffff, + }, + .caps_start = 6, + .num_caps = 5, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + /* PCIDevice: 00:04.0 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0x20, + .bar_mask = { + 0xffffff80, 0xfffff000, 0x00000000, + 0x00000000, 0xffffc000, 0xffffffff, + }, + .caps_start = 0, + .num_caps = 6, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 2, + .msix_region_size = 0x1000, + .msix_address = 0xfebd6000, + }, + /* PCIDevice: 00:1b.0 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0xd8, + .bar_mask = { + 0xffffc000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, + }, + .caps_start = 11, + .num_caps = 1, + .num_msi_vectors = 1, + .msi_64bits = 1, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + /* PCIDevice: 00:1d.0 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0xe8, + .bar_mask = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffe0, 0x00000000, + }, + .caps_start = 0, + .num_caps = 0, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + /* PCIDevice: 00:1d.1 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0xe9, + .bar_mask = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffe0, 0x00000000, + }, + .caps_start = 0, + .num_caps = 0, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + /* PCIDevice: 00:1d.2 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0xea, + .bar_mask = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffe0, 0x00000000, + }, + .caps_start = 0, + .num_caps = 0, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + /* PCIDevice: 00:1d.7 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0xef, + .bar_mask = { + 0xfffff000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, + }, + .caps_start = 0, + .num_caps = 0, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + /* PCIDevice: 00:1f.0 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0xf8, + .bar_mask = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, + }, + .caps_start = 0, + .num_caps = 0, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + /* PCIDevice: 00:1f.2 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0xfa, + .bar_mask = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffe0, 0xfffff000, + }, + .caps_start = 12, + .num_caps = 2, + .num_msi_vectors = 1, + .msi_64bits = 1, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + /* PCIDevice: 00:1f.3 */ + { + .type = JAILHOUSE_PCI_TYPE_DEVICE, + .iommu = 0, + .domain = 0x0, + .bdf = 0xfb, + .bar_mask = { + 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffc0, 0x00000000, + }, + .caps_start = 0, + .num_caps = 0, + .num_msi_vectors = 0, + .msi_64bits = 0, + .msi_maskable = 0, + .num_msix_vectors = 0, + .msix_region_size = 0x0, + .msix_address = 0x0, + }, + }, + + .pci_caps = { + /* PCIDevice: 00:01.0 */ + /* PCIDevice: 00:02.0 */ + /* PCIDevice: 00:04.0 */ + { + .id = PCI_CAP_ID_MSIX, + .start = 0x98, + .len = 0xc, + .flags = JAILHOUSE_PCICAPS_WRITE, + }, + { + .id = PCI_CAP_ID_VNDR, + .start = 0x84, + .len = 0x2, + .flags = 0, + }, + { + .id = PCI_CAP_ID_VNDR, + .start = 0x70, + .len = 0x2, + .flags = 0, + }, + { + .id = PCI_CAP_ID_VNDR, + .start = 0x60, + .len = 0x2, + .flags = 0, + }, + { + .id = PCI_CAP_ID_VNDR, + .start = 0x50, + .len = 0x2, + .flags = 0, + }, + { + .id = PCI_CAP_ID_VNDR, + .start = 0x40, + .len = 0x2, + .flags = 0, + }, + /* PCIDevice: 00:03.0 */ + { + .id = PCI_CAP_ID_VNDR, + .start = 0x84, + .len = 0x2, + .flags = 0, + }, + { + .id = PCI_CAP_ID_VNDR, + .start = 0x70, + .len = 0x2, + .flags = 0, + }, + { + .id = PCI_CAP_ID_VNDR, + .start = 0x60, + .len = 0x2, + .flags = 0, + }, + { + .id = PCI_CAP_ID_VNDR, + .start = 0x50, + .len = 0x2, + .flags = 0, + }, + { + .id = PCI_CAP_ID_VNDR, + .start = 0x40, + .len = 0x2, + .flags = 0, + }, + /* PCIDevice: 00:1b.0 */ + { + .id = PCI_CAP_ID_MSI, + .start = 0x60, + .len = 0xe, + .flags = JAILHOUSE_PCICAPS_WRITE, + }, + /* PCIDevice: 00:1f.2 */ + { + .id = PCI_CAP_ID_MSI, + .start = 0x80, + .len = 0xe, + .flags = JAILHOUSE_PCICAPS_WRITE, + }, + { + .id = PCI_CAP_ID_SATA, + .start = 0xa8, + .len = 0x2, + .flags = 0, + }, + }, +}; diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/jailhouse-arch.inc b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/jailhouse-arch.inc new file mode 100644 index 00000000..498b25ed --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/jailhouse-arch.inc @@ -0,0 +1,22 @@ +# Set jailhouse architecture JH_ARCH variable +# +# return value must match one of architectures supported by jailhouse +# +valid_jh_archs = "x86 arm" + +def map_jh_arch(a, d): + import re + + valid_jh_archs = d.getVar('valid_jh_archs', True).split() + + if re.match('(i.86|athlon|x86.64)$', a): return 'x86' + elif re.match('armeb$', a): return 'arm' + elif re.match('aarch64$', a): return 'arm64' + elif re.match('aarch64_be$', a): return 'arm64' + elif a in valid_jh_archs: return a + else: + bb.error("cannot map '%s' to a jailhouse supported architecture" % a) + +export JH_ARCH = "${@map_jh_arch(d.getVar('TARGET_ARCH', True), d)}" + +COMPATIBLE_HOST = "(i.86|x86_64|arm|aarch64).*-linux" diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/jailhouse/0001-configs-arm64-Add-support-for-RPi4-with-more-than-1G.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/jailhouse/0001-configs-arm64-Add-support-for-RPi4-with-more-than-1G.patch new file mode 100644 index 00000000..21d5f2f1 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/jailhouse/0001-configs-arm64-Add-support-for-RPi4-with-more-than-1G.patch @@ -0,0 +1,290 @@ +From 4f86ca866119669a75f02ea10fa502f051f8240c Mon Sep 17 00:00:00 2001 +From: Jakub Luzny <jakub@luzny.cz> +Date: Tue, 11 Aug 2020 11:45:02 +0200 +Subject: [PATCH] configs: arm64: Add support for RPi4 with more than 1G of + memory + +Add the required memory regions to support 2G, 4G and 8G RAM variants +of the Raspberry Pi 4. Tested on all the bigger variants, not on 1G, as I don't +have one on hand and it's not available anymore. + +Also moved the memory used by Jailhouse for the hypervisor and cells from +0x30000000 to 0x20000000 to avoid conflict with GPU memory. That is fine for +gpu_mem setting of up to 256. The memory is supposed to be reserved using +reserved-memory node in the device tree. To support variants with >2G RAM, +another region for PCI MMIO space has to be also reserved. + +Upstream-Status: Submitted [jailhouse-dev@googlegroups.com] + +Signed-off-by: Jakub Luzny <jakub@luzny.cz> +--- + configs/arm64/rpi4-inmate-demo.c | 22 ++++++------ + configs/arm64/rpi4-linux-demo.c | 28 +++++++-------- + configs/arm64/rpi4.c | 62 +++++++++++++++++++++++--------- + 3 files changed, 71 insertions(+), 41 deletions(-) + +diff --git a/configs/arm64/rpi4-inmate-demo.c b/configs/arm64/rpi4-inmate-demo.c +index 62442e7c..09dfc1f0 100644 +--- a/configs/arm64/rpi4-inmate-demo.c ++++ b/configs/arm64/rpi4-inmate-demo.c +@@ -51,34 +51,34 @@ struct { + .mem_regions = { + /* IVSHMEM shared memory regions (demo) */ + { +- .phys_start = 0x3faf0000, +- .virt_start = 0x3faf0000, ++ .phys_start = 0x2faf0000, ++ .virt_start = 0x2faf0000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { +- .phys_start = 0x3faf1000, +- .virt_start = 0x3faf1000, ++ .phys_start = 0x2faf1000, ++ .virt_start = 0x2faf1000, + .size = 0x9000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + { +- .phys_start = 0x3fafa000, +- .virt_start = 0x3fafa000, ++ .phys_start = 0x2fafa000, ++ .virt_start = 0x2fafa000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { +- .phys_start = 0x3fafc000, +- .virt_start = 0x3fafc000, ++ .phys_start = 0x2fafc000, ++ .virt_start = 0x2fafc000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + { +- .phys_start = 0x3fafe000, +- .virt_start = 0x3fafe000, ++ .phys_start = 0x2fafe000, ++ .virt_start = 0x2fafe000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, +@@ -91,7 +91,7 @@ struct { + JAILHOUSE_MEM_IO_32 | JAILHOUSE_MEM_ROOTSHARED, + }, + /* RAM */ { +- .phys_start = 0x3fa00000, ++ .phys_start = 0x2fa00000, + .virt_start = 0, + .size = 0x00010000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | +diff --git a/configs/arm64/rpi4-linux-demo.c b/configs/arm64/rpi4-linux-demo.c +index 9e7fad26..cf36fa22 100644 +--- a/configs/arm64/rpi4-linux-demo.c ++++ b/configs/arm64/rpi4-linux-demo.c +@@ -52,39 +52,39 @@ struct { + .mem_regions = { + /* IVSHMEM shared memory regions (demo) */ + { +- .phys_start = 0x3faf0000, +- .virt_start = 0x3faf0000, ++ .phys_start = 0x2faf0000, ++ .virt_start = 0x2faf0000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { +- .phys_start = 0x3faf1000, +- .virt_start = 0x3faf1000, ++ .phys_start = 0x2faf1000, ++ .virt_start = 0x2faf1000, + .size = 0x9000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + { +- .phys_start = 0x3fafa000, +- .virt_start = 0x3fafa000, ++ .phys_start = 0x2fafa000, ++ .virt_start = 0x2fafa000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { +- .phys_start = 0x3fafc000, +- .virt_start = 0x3fafc000, ++ .phys_start = 0x2fafc000, ++ .virt_start = 0x2fafc000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_ROOTSHARED, + }, + { +- .phys_start = 0x3fafe000, +- .virt_start = 0x3fafe000, ++ .phys_start = 0x2fafe000, ++ .virt_start = 0x2fafe000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_ROOTSHARED, + }, + /* IVSHMEM shared memory region */ +- JAILHOUSE_SHMEM_NET_REGIONS(0x3fb00000, 1), ++ JAILHOUSE_SHMEM_NET_REGIONS(0x2fb00000, 1), + /* UART */ { + .phys_start = 0xfe215040, + .virt_start = 0xfe215040, +@@ -94,15 +94,15 @@ struct { + JAILHOUSE_MEM_IO_32 | JAILHOUSE_MEM_ROOTSHARED, + }, + /* RAM */ { +- .phys_start = 0x3f900000, ++ .phys_start = 0x2f900000, + .virt_start = 0, + .size = 0x10000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE, + }, + /* RAM */ { +- .phys_start = 0x30000000, +- .virt_start = 0x30000000, ++ .phys_start = 0x20000000, ++ .virt_start = 0x20000000, + .size = 0x8000000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_DMA | +diff --git a/configs/arm64/rpi4.c b/configs/arm64/rpi4.c +index 92463184..c25bd8d2 100644 +--- a/configs/arm64/rpi4.c ++++ b/configs/arm64/rpi4.c +@@ -1,7 +1,7 @@ + /* + * Jailhouse, a Linux-based partitioning hypervisor + * +- * Test configuration for Raspberry Pi 4 (32-bit, quad-core Cortex-A72, 1GB RAM) ++ * Test configuration for Raspberry Pi 4 (32-bit, quad-core Cortex-A72, 1GB, 2GB, 4GB or 8GB RAM) + * + * Copyright (c) Siemens AG, 2020 + * +@@ -10,6 +10,9 @@ + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. ++ * ++ * Reservation via device tree: reg = <0x0 0x20000000 0x10000000>; ++ * reg = <0x0 0xe0000000 0x200000>; + */ + + #include <jailhouse/types.h> +@@ -18,7 +21,7 @@ + struct { + struct jailhouse_system header; + __u64 cpus[1]; +- struct jailhouse_memory mem_regions[12]; ++ struct jailhouse_memory mem_regions[15]; + struct jailhouse_irqchip irqchips[2]; + struct jailhouse_pci_device pci_devices[2]; + } __attribute__((packed)) config = { +@@ -27,7 +30,7 @@ struct { + .revision = JAILHOUSE_CONFIG_REVISION, + .flags = JAILHOUSE_SYS_VIRTUAL_DEBUG_CONSOLE, + .hypervisor_memory = { +- .phys_start = 0x3fc00000, ++ .phys_start = 0x2fc00000, + .size = 0x00400000, + }, + .debug_console = { +@@ -70,37 +73,37 @@ struct { + .mem_regions = { + /* IVSHMEM shared memory regions for 00:00.0 (demo) */ + { +- .phys_start = 0x3faf0000, +- .virt_start = 0x3faf0000, ++ .phys_start = 0x2faf0000, ++ .virt_start = 0x2faf0000, + .size = 0x1000, + .flags = JAILHOUSE_MEM_READ, + }, + { +- .phys_start = 0x3faf1000, +- .virt_start = 0x3faf1000, ++ .phys_start = 0x2faf1000, ++ .virt_start = 0x2faf1000, + .size = 0x9000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + { +- .phys_start = 0x3fafa000, +- .virt_start = 0x3fafa000, ++ .phys_start = 0x2fafa000, ++ .virt_start = 0x2fafa000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE, + }, + { +- .phys_start = 0x3fafc000, +- .virt_start = 0x3fafc000, ++ .phys_start = 0x2fafc000, ++ .virt_start = 0x2fafc000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ, + }, + { +- .phys_start = 0x3fafe000, +- .virt_start = 0x3fafe000, ++ .phys_start = 0x2fafe000, ++ .virt_start = 0x2fafe000, + .size = 0x2000, + .flags = JAILHOUSE_MEM_READ, + }, + /* IVSHMEM shared memory regions for 00:01.0 (networking) */ +- JAILHOUSE_SHMEM_NET_REGIONS(0x3fb00000, 0), ++ JAILHOUSE_SHMEM_NET_REGIONS(0x2fb00000, 0), + /* MMIO 1 (permissive) */ { + .phys_start = 0xfd500000, + .virt_start = 0xfd500000, +@@ -115,10 +118,37 @@ struct { + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_IO, + }, +- /* RAM */ { ++ /* RAM (0M-~762M) */ { + .phys_start = 0x0, + .virt_start = 0x0, +- .size = 0x3fa10000, ++ .size = 0x2fa10000, ++ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | ++ JAILHOUSE_MEM_EXECUTE, ++ }, ++ ++ /* ~6M reserved for the hypervisor and the shared memory regions */ ++ ++ /* RAM (768M-3584M) */ { ++ .phys_start = 0x30000000, ++ .virt_start = 0x30000000, ++ .size = 0xb0000000, ++ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | ++ JAILHOUSE_MEM_EXECUTE, ++ }, ++ ++ /* 2M reserved for PCI MMIO space */ ++ ++ /* RAM (3586M-4032M) */ { ++ .phys_start = 0xe0200000, ++ .virt_start = 0xe0200000, ++ .size = 0x1be00000, ++ .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | ++ JAILHOUSE_MEM_EXECUTE, ++ }, ++ /* RAM (4096M-8192M) */ { ++ .phys_start = 0x100000000, ++ .virt_start = 0x100000000, ++ .size = 0x100000000, + .flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE | + JAILHOUSE_MEM_EXECUTE, + }, +-- +2.27.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/jailhouse_git.bb b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/jailhouse_git.bb new file mode 100644 index 00000000..462f0a77 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-extended/jailhouse/jailhouse_git.bb @@ -0,0 +1,98 @@ +SUMMARY = "Linux-based partitioning hypervisor" +DESCRIPTION = "Jailhouse is a partitioning Hypervisor based on Linux. It is able to run bare-metal applications or (adapted) \ +operating systems besides Linux. For this purpose, it configures CPU and device virtualization features of the hardware \ +platform in a way that none of these domains, called 'cells' here, can interfere with each other in an unacceptable way." +HOMEPAGE = "https://github.com/siemens/jailhouse" +SECTION = "jailhouse" +LICENSE = "GPL-2.0 & BSD-2-Clause" + +LIC_FILES_CHKSUM = " \ + file://COPYING;md5=9fa7f895f96bde2d47fd5b7d95b6ba4d \ +" + +SRCREV = "4ce7658dddfd5a1682a379d5ac46657e93fe1ff0" +PV = "0.12+git${SRCPV}" + +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI = "git://github.com/siemens/jailhouse \ + file://0001-configs-arm64-Add-support-for-RPi4-with-more-than-1G.patch \ + " + +SRC_URI += "file://qemu-agl.c \ + file://agl-apic-demo.c \ + file://agl-pci-demo.c \ + file://agl-ivshmem-demo.c \ + file://agl-linux-x86-demo.c \ + " + +DEPENDS = "virtual/kernel dtc-native python3-mako-native make-native" + +require jailhouse-arch.inc +inherit module python3native bash-completion setuptools3 + +S = "${WORKDIR}/git" +B = "${S}" + +JH_DATADIR ?= "${datadir}/jailhouse" +JH_EXEC_DIR ?= "${libexecdir}/jailhouse" +CELL_DIR ?= "${JH_DATADIR}/cells" +INMATES_DIR ?= "${JH_DATADIR}/inmates" +DTS_DIR ?= "${JH_DATADIR}/cells/dts" + +JH_CELL_FILES ?= "*.cell" + +EXTRA_OEMAKE = "ARCH=${JH_ARCH} CROSS_COMPILE=${TARGET_PREFIX} CC="${CC}" KDIR=${STAGING_KERNEL_BUILDDIR}" + +do_configure() { + + # copy ${WORKDIR}/qemu-agl.c ${S}/configs/x86/ <--- folder where the cells are defined in the source tree to be compiled + cp ${WORKDIR}/qemu-agl.c ${S}/configs/${JH_ARCH} + cp ${WORKDIR}/agl-apic-demo.c ${S}/configs/x86/ + cp ${WORKDIR}/agl-pci-demo.c ${S}/configs/x86/ + cp ${WORKDIR}/agl-linux-x86-demo.c ${S}/configs/x86/ + cp ${WORKDIR}/agl-ivshmem-demo.c ${S}/configs/x86/ + + sed -i '1s|^#!/usr/bin/env python$|#!/usr/bin/env python3|' ${B}/tools/${BPN}-* +} + +do_compile() { + oe_runmake +} + +do_install() { + # Install pyjailhouse python modules needed by the tools + distutils3_do_install + + # We want to install the python tools, but we do not want to use pip... + # At least with v0.10, we can work around this with + # 'PIP=":" PYTHON_PIP_USEABLE=yes' + oe_runmake PIP=: PYTHON=python3 PYTHON_PIP_USEABLE=yes DESTDIR=${D} install + + install -d ${D}${CELL_DIR} + + + install -m 0644 ${B}/configs/${JH_ARCH}/${JH_CELL_FILES} ${D}${CELL_DIR}/ + + install -d ${D}${INMATES_DIR} + install -m 0644 ${B}/inmates/demos/${JH_ARCH}/*.bin ${D}${INMATES_DIR} + + if [ ${JH_ARCH} != "x86" ]; then + install -d ${D}${DTS_DIR} + install -m 0644 ${B}/configs/${JH_ARCH}/dts/*.dtb ${D}${DTS_DIR} + fi +} + +PACKAGE_BEFORE_PN = "kernel-module-jailhouse pyjailhouse ${PN}-tools ${PN}-demos" +FILES_${PN} = "${base_libdir}/firmware ${libexecdir} ${sbindir} ${JH_DATADIR}" +FILES_pyjailhouse = "${PYTHON_SITEPACKAGES_DIR}" +FILES_${PN}-tools = "${libexecdir}/${BPN}/${BPN}-* ${JH_DATADIR}/*.tmpl" +FILES_${PN}-demos = "${JH_DATADIR}/ ${sbindir}/ivshmem-demo" + +RDEPENDS_${PN}-tools = "pyjailhouse python3-mmap python3-math python3-datetime python3-curses python3-compression python3-mako" +RDEPENDS_pyjailhouse = "python3-core python3-ctypes python3-fcntl" +RDEPENDS_${PN}-demos = "jailhouse" + +RRECOMMENDS_${PN} = "${PN}-tools" + +KERNEL_MODULE_AUTOLOAD += "jailhouse" diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux-jailhouse-5.4.inc b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux-jailhouse-5.4.inc new file mode 100644 index 00000000..4b571ffd --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux-jailhouse-5.4.inc @@ -0,0 +1,39 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/linux:" + +SRC_URI_append = " file://jailhouse.cfg" + +SRC_URI_append = " \ +file://0001-x86-jailhouse-Improve-setup-data-version-comparison.patch \ +file://0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch \ +file://0003-jailhouse-Add-simple-debug-console-via-the-hyperviso.patch \ +file://0004-arm-Export-__boot_cpu_mode-for-use-in-Jailhouse-driv.patch \ +file://0005-mm-Re-export-ioremap_page_range.patch \ +file://0006-arm-arm64-export-__hyp_stub_vectors.patch \ +file://0007-x86-Export-lapic_timer_period.patch \ +file://0008-arm64-dts-marvell-armada-37xx-Set-pci-domain.patch \ +file://0009-arm64-dts-marvell-armada-8030-mcbin-Set-pci-domain.patch \ +file://0010-uio-Enable-read-only-mappings.patch \ +file://0011-ivshmem-Add-header-file.patch \ +file://0012-uio-Add-driver-for-inter-VM-shared-memory-device.patch \ +file://0013-ivshmem-net-virtual-network-device-for-Jailhouse.patch \ +file://0014-ivshmem-net-Map-shmem-region-as-RAM.patch \ +file://0015-ivshmem-net-fix-race-in-state-machine.patch \ +file://0016-ivshmem-net-Remove-unused-variable.patch \ +file://0017-ivshmem-net-Enable-INTx.patch \ +file://0018-ivshmem-net-Improve-identification-of-resources.patch \ +file://0019-ivshmem-net-Switch-to-reset-state-on-each-net-stop-a.patch \ +file://0020-ivshmem-net-Add-ethtool-register-dump.patch \ +file://0021-ivshmem-net-Fix-stuck-state-machine-during-setup.patch \ +file://0022-ivshmem-net-Switch-to-relative-descriptor-addresses.patch \ +file://0023-ivshmem-net-Switch-to-pci_alloc_irq_vectors.patch \ +file://0024-ivshmem-net-fill-in-and-check-used-descriptor-chain-.patch \ +file://0025-ivshmem-net-slightly-improve-debug-output.patch \ +file://0026-ivshmem-net-set-and-check-descriptor-flags.patch \ +file://0027-ivshmem-net-add-MAC-changing-interface.patch \ +file://0028-ivshmem-net-Silence-compiler-warning.patch \ +file://0029-ivshmem-net-Fix-bogus-transition-to-RESET-state.patch \ +file://0030-ivshmem-net-Refactor-and-comment-ivshm_net_state_cha.patch \ +file://0031-ivshmem-net-Switch-to-netdev_xmit_more-helper.patch \ +file://0032-ivshmem-net-Adjust-to-reworked-version-of-ivshmem-in.patch \ +" + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux-yocto_5.4%.bbappend b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux-yocto_5.4%.bbappend new file mode 100644 index 00000000..b13f1eb1 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux-yocto_5.4%.bbappend @@ -0,0 +1 @@ +require recipes-kernel/linux/linux-jailhouse-5.4.inc diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0001-x86-jailhouse-Improve-setup-data-version-comparison.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0001-x86-jailhouse-Improve-setup-data-version-comparison.patch new file mode 100644 index 00000000..6b5032df --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0001-x86-jailhouse-Improve-setup-data-version-comparison.patch @@ -0,0 +1,198 @@ +From d47ad4c29f1cd34aff896a88b3dfc4a861a15a6a Mon Sep 17 00:00:00 2001 +From: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de> +Date: Thu, 10 Oct 2019 12:21:01 +0200 +Subject: [PATCH 01/32] x86/jailhouse: Improve setup data version comparison + +Soon, setup_data will contain information on passed-through platform +UARTs. This requires some preparational work for the sanity check of the +header and the check of the version. + +Use the following strategy: + + 1. Ensure that the header declares at least enough space for the + version and the compatible_version as it must hold that fields for + any version. The location and semantics of header+version fields + will never change. + + 2. Copy over data -- as much as as possible. The length is either + limited by the header length or the length of setup_data. + + 3. Things are now in place -- sanity check if the header length + complies the actual version. + +For future versions of the setup_data, only step 3 requires alignment. + +Signed-off-by: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de> +Signed-off-by: Borislav Petkov <bp@suse.de> +Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com> +Cc: Baoquan He <bhe@redhat.com> +Cc: "H. Peter Anvin" <hpa@zytor.com> +Cc: Ingo Molnar <mingo@redhat.com> +Cc: jailhouse-dev@googlegroups.com +Cc: Juergen Gross <jgross@suse.com> +Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: x86-ml <x86@kernel.org> +Link: https://lkml.kernel.org/r/20191010102102.421035-2-ralf.ramsauer@oth-regensburg.de +--- + arch/x86/include/uapi/asm/bootparam.h | 22 ++++++++------- + arch/x86/kernel/jailhouse.c | 51 ++++++++++++++++++++++------------- + 2 files changed, 45 insertions(+), 28 deletions(-) + +diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h +index c895df5482c5..43be437c9c71 100644 +--- a/arch/x86/include/uapi/asm/bootparam.h ++++ b/arch/x86/include/uapi/asm/bootparam.h +@@ -139,15 +139,19 @@ struct boot_e820_entry { + * setup data structure. + */ + struct jailhouse_setup_data { +- __u16 version; +- __u16 compatible_version; +- __u16 pm_timer_address; +- __u16 num_cpus; +- __u64 pci_mmconfig_base; +- __u32 tsc_khz; +- __u32 apic_khz; +- __u8 standard_ioapic; +- __u8 cpu_ids[255]; ++ struct { ++ __u16 version; ++ __u16 compatible_version; ++ } __attribute__((packed)) hdr; ++ struct { ++ __u16 pm_timer_address; ++ __u16 num_cpus; ++ __u64 pci_mmconfig_base; ++ __u32 tsc_khz; ++ __u32 apic_khz; ++ __u8 standard_ioapic; ++ __u8 cpu_ids[255]; ++ } __attribute__((packed)) v1; + } __attribute__((packed)); + + /* The so-called "zeropage" */ +diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c +index 3ad34f01de2a..cf4eb37ad97b 100644 +--- a/arch/x86/kernel/jailhouse.c ++++ b/arch/x86/kernel/jailhouse.c +@@ -22,6 +22,8 @@ + #include <asm/jailhouse_para.h> + + static __initdata struct jailhouse_setup_data setup_data; ++#define SETUP_DATA_V1_LEN (sizeof(setup_data.hdr) + sizeof(setup_data.v1)) ++ + static unsigned int precalibrated_tsc_khz; + + static uint32_t jailhouse_cpuid_base(void) +@@ -45,7 +47,7 @@ static void jailhouse_get_wallclock(struct timespec64 *now) + + static void __init jailhouse_timer_init(void) + { +- lapic_timer_period = setup_data.apic_khz * (1000 / HZ); ++ lapic_timer_period = setup_data.v1.apic_khz * (1000 / HZ); + } + + static unsigned long jailhouse_get_tsc(void) +@@ -88,14 +90,14 @@ static void __init jailhouse_get_smp_config(unsigned int early) + + register_lapic_address(0xfee00000); + +- for (cpu = 0; cpu < setup_data.num_cpus; cpu++) { +- generic_processor_info(setup_data.cpu_ids[cpu], ++ for (cpu = 0; cpu < setup_data.v1.num_cpus; cpu++) { ++ generic_processor_info(setup_data.v1.cpu_ids[cpu], + boot_cpu_apic_version); + } + + smp_found_config = 1; + +- if (setup_data.standard_ioapic) { ++ if (setup_data.v1.standard_ioapic) { + mp_register_ioapic(0, 0xfec00000, gsi_top, &ioapic_cfg); + + /* Register 1:1 mapping for legacy UART IRQs 3 and 4 */ +@@ -126,9 +128,9 @@ static int __init jailhouse_pci_arch_init(void) + pcibios_last_bus = 0xff; + + #ifdef CONFIG_PCI_MMCONFIG +- if (setup_data.pci_mmconfig_base) { ++ if (setup_data.v1.pci_mmconfig_base) { + pci_mmconfig_add(0, 0, pcibios_last_bus, +- setup_data.pci_mmconfig_base); ++ setup_data.v1.pci_mmconfig_base); + pci_mmcfg_arch_init(); + } + #endif +@@ -139,6 +141,7 @@ static int __init jailhouse_pci_arch_init(void) + static void __init jailhouse_init_platform(void) + { + u64 pa_data = boot_params.hdr.setup_data; ++ unsigned long setup_data_len; + struct setup_data header; + void *mapping; + +@@ -163,16 +166,8 @@ static void __init jailhouse_init_platform(void) + memcpy(&header, mapping, sizeof(header)); + early_memunmap(mapping, sizeof(header)); + +- if (header.type == SETUP_JAILHOUSE && +- header.len >= sizeof(setup_data)) { +- pa_data += offsetof(struct setup_data, data); +- +- mapping = early_memremap(pa_data, sizeof(setup_data)); +- memcpy(&setup_data, mapping, sizeof(setup_data)); +- early_memunmap(mapping, sizeof(setup_data)); +- ++ if (header.type == SETUP_JAILHOUSE) + break; +- } + + pa_data = header.next; + } +@@ -180,13 +175,27 @@ static void __init jailhouse_init_platform(void) + if (!pa_data) + panic("Jailhouse: No valid setup data found"); + +- if (setup_data.compatible_version > JAILHOUSE_SETUP_REQUIRED_VERSION) +- panic("Jailhouse: Unsupported setup data structure"); ++ /* setup data must at least contain the header */ ++ if (header.len < sizeof(setup_data.hdr)) ++ goto unsupported; + +- pmtmr_ioport = setup_data.pm_timer_address; ++ pa_data += offsetof(struct setup_data, data); ++ setup_data_len = min_t(unsigned long, sizeof(setup_data), ++ (unsigned long)header.len); ++ mapping = early_memremap(pa_data, setup_data_len); ++ memcpy(&setup_data, mapping, setup_data_len); ++ early_memunmap(mapping, setup_data_len); ++ ++ if (setup_data.hdr.version == 0 || ++ setup_data.hdr.compatible_version != ++ JAILHOUSE_SETUP_REQUIRED_VERSION || ++ (setup_data.hdr.version >= 1 && header.len < SETUP_DATA_V1_LEN)) ++ goto unsupported; ++ ++ pmtmr_ioport = setup_data.v1.pm_timer_address; + pr_debug("Jailhouse: PM-Timer IO Port: %#x\n", pmtmr_ioport); + +- precalibrated_tsc_khz = setup_data.tsc_khz; ++ precalibrated_tsc_khz = setup_data.v1.tsc_khz; + setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ); + + pci_probe = 0; +@@ -196,6 +205,10 @@ static void __init jailhouse_init_platform(void) + * are none in a non-root cell. + */ + disable_acpi(); ++ return; ++ ++unsupported: ++ panic("Jailhouse: Unsupported setup data structure"); + } + + bool jailhouse_paravirt(void) +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch new file mode 100644 index 00000000..d1db6c71 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch @@ -0,0 +1,200 @@ +From 7f87114a29351547ffb9bd16c4cafb37524806c6 Mon Sep 17 00:00:00 2001 +From: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de> +Date: Thu, 10 Oct 2019 12:21:02 +0200 +Subject: [PATCH 02/32] x86/jailhouse: Only enable platform UARTs if available + +ACPI tables aren't available if Linux runs as guest of the hypervisor +Jailhouse. This makes the 8250 driver probe for all platform UARTs as it +assumes that all UARTs are present in case of !ACPI. Jailhouse will stop +execution of Linux guest due to port access violation. + +So far, these access violations were solved by tuning the 8250.nr_uarts +cmdline parameter, but this has limitations: Only consecutive platform +UARTs can be mapped to Linux, and only in the sequence 0x3f8, 0x2f8, +0x3e8, 0x2e8. + +Beginning from setup_data version 2, Jailhouse will place information of +available platform UARTs in setup_data. This allows for selective +activation of platform UARTs. + +Query setup_data version and only activate available UARTS. This +patch comes with backward compatibility, and will still support older +setup_data versions. In case of older setup_data versions, Linux falls +back to the old behaviour. + +Signed-off-by: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de> +Signed-off-by: Borislav Petkov <bp@suse.de> +Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com> +Cc: Baoquan He <bhe@redhat.com> +Cc: "H. Peter Anvin" <hpa@zytor.com> +Cc: Ingo Molnar <mingo@redhat.com> +Cc: jailhouse-dev@googlegroups.com +Cc: Juergen Gross <jgross@suse.com> +Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: x86-ml <x86@kernel.org> +Link: https://lkml.kernel.org/r/20191010102102.421035-3-ralf.ramsauer@oth-regensburg.de +--- + arch/x86/include/uapi/asm/bootparam.h | 3 ++ + arch/x86/kernel/jailhouse.c | 85 +++++++++++++++++++++++++++++------ + 2 files changed, 75 insertions(+), 13 deletions(-) + +diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h +index 43be437c9c71..db1e24e56e94 100644 +--- a/arch/x86/include/uapi/asm/bootparam.h ++++ b/arch/x86/include/uapi/asm/bootparam.h +@@ -152,6 +152,9 @@ struct jailhouse_setup_data { + __u8 standard_ioapic; + __u8 cpu_ids[255]; + } __attribute__((packed)) v1; ++ struct { ++ __u32 flags; ++ } __attribute__((packed)) v2; + } __attribute__((packed)); + + /* The so-called "zeropage" */ +diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c +index cf4eb37ad97b..6eb8b50ea07e 100644 +--- a/arch/x86/kernel/jailhouse.c ++++ b/arch/x86/kernel/jailhouse.c +@@ -11,6 +11,7 @@ + #include <linux/acpi_pmtmr.h> + #include <linux/kernel.h> + #include <linux/reboot.h> ++#include <linux/serial_8250.h> + #include <asm/apic.h> + #include <asm/cpu.h> + #include <asm/hypervisor.h> +@@ -21,11 +22,24 @@ + #include <asm/setup.h> + #include <asm/jailhouse_para.h> + +-static __initdata struct jailhouse_setup_data setup_data; ++static struct jailhouse_setup_data setup_data; + #define SETUP_DATA_V1_LEN (sizeof(setup_data.hdr) + sizeof(setup_data.v1)) ++#define SETUP_DATA_V2_LEN (SETUP_DATA_V1_LEN + sizeof(setup_data.v2)) + + static unsigned int precalibrated_tsc_khz; + ++static void jailhouse_setup_irq(unsigned int irq) ++{ ++ struct mpc_intsrc mp_irq = { ++ .type = MP_INTSRC, ++ .irqtype = mp_INT, ++ .irqflag = MP_IRQPOL_ACTIVE_HIGH | MP_IRQTRIG_EDGE, ++ .srcbusirq = irq, ++ .dstirq = irq, ++ }; ++ mp_save_irq(&mp_irq); ++} ++ + static uint32_t jailhouse_cpuid_base(void) + { + if (boot_cpu_data.cpuid_level < 0 || +@@ -79,11 +93,6 @@ static void __init jailhouse_get_smp_config(unsigned int early) + .type = IOAPIC_DOMAIN_STRICT, + .ops = &mp_ioapic_irqdomain_ops, + }; +- struct mpc_intsrc mp_irq = { +- .type = MP_INTSRC, +- .irqtype = mp_INT, +- .irqflag = MP_IRQPOL_ACTIVE_HIGH | MP_IRQTRIG_EDGE, +- }; + unsigned int cpu; + + jailhouse_x2apic_init(); +@@ -100,12 +109,12 @@ static void __init jailhouse_get_smp_config(unsigned int early) + if (setup_data.v1.standard_ioapic) { + mp_register_ioapic(0, 0xfec00000, gsi_top, &ioapic_cfg); + +- /* Register 1:1 mapping for legacy UART IRQs 3 and 4 */ +- mp_irq.srcbusirq = mp_irq.dstirq = 3; +- mp_save_irq(&mp_irq); +- +- mp_irq.srcbusirq = mp_irq.dstirq = 4; +- mp_save_irq(&mp_irq); ++ if (IS_ENABLED(CONFIG_SERIAL_8250) && ++ setup_data.hdr.version < 2) { ++ /* Register 1:1 mapping for legacy UART IRQs 3 and 4 */ ++ jailhouse_setup_irq(3); ++ jailhouse_setup_irq(4); ++ } + } + } + +@@ -138,6 +147,53 @@ static int __init jailhouse_pci_arch_init(void) + return 0; + } + ++#ifdef CONFIG_SERIAL_8250 ++static inline bool jailhouse_uart_enabled(unsigned int uart_nr) ++{ ++ return setup_data.v2.flags & BIT(uart_nr); ++} ++ ++static void jailhouse_serial_fixup(int port, struct uart_port *up, ++ u32 *capabilities) ++{ ++ static const u16 pcuart_base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8}; ++ unsigned int n; ++ ++ for (n = 0; n < ARRAY_SIZE(pcuart_base); n++) { ++ if (pcuart_base[n] != up->iobase) ++ continue; ++ ++ if (jailhouse_uart_enabled(n)) { ++ pr_info("Enabling UART%u (port 0x%lx)\n", n, ++ up->iobase); ++ jailhouse_setup_irq(up->irq); ++ } else { ++ /* Deactivate UART if access isn't allowed */ ++ up->iobase = 0; ++ } ++ break; ++ } ++} ++ ++static void __init jailhouse_serial_workaround(void) ++{ ++ /* ++ * There are flags inside setup_data that indicate availability of ++ * platform UARTs since setup data version 2. ++ * ++ * In case of version 1, we don't know which UARTs belong Linux. In ++ * this case, unconditionally register 1:1 mapping for legacy UART IRQs ++ * 3 and 4. ++ */ ++ if (setup_data.hdr.version > 1) ++ serial8250_set_isa_configurator(jailhouse_serial_fixup); ++} ++#else /* !CONFIG_SERIAL_8250 */ ++static inline void jailhouse_serial_workaround(void) ++{ ++} ++#endif /* CONFIG_SERIAL_8250 */ ++ + static void __init jailhouse_init_platform(void) + { + u64 pa_data = boot_params.hdr.setup_data; +@@ -189,7 +245,8 @@ static void __init jailhouse_init_platform(void) + if (setup_data.hdr.version == 0 || + setup_data.hdr.compatible_version != + JAILHOUSE_SETUP_REQUIRED_VERSION || +- (setup_data.hdr.version >= 1 && header.len < SETUP_DATA_V1_LEN)) ++ (setup_data.hdr.version == 1 && header.len < SETUP_DATA_V1_LEN) || ++ (setup_data.hdr.version >= 2 && header.len < SETUP_DATA_V2_LEN)) + goto unsupported; + + pmtmr_ioport = setup_data.v1.pm_timer_address; +@@ -205,6 +262,8 @@ static void __init jailhouse_init_platform(void) + * are none in a non-root cell. + */ + disable_acpi(); ++ ++ jailhouse_serial_workaround(); + return; + + unsupported: +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0003-jailhouse-Add-simple-debug-console-via-the-hyperviso.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0003-jailhouse-Add-simple-debug-console-via-the-hyperviso.patch new file mode 100644 index 00000000..289f54ac --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0003-jailhouse-Add-simple-debug-console-via-the-hyperviso.patch @@ -0,0 +1,174 @@ +From faa349f4d096554c6d5bfe74634599d2e26f64a7 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 11 Sep 2016 23:30:04 +0200 +Subject: [PATCH 03/32] jailhouse: Add simple debug console via the hypervisor + +Jailhouse allows explicitly enabled cells to write character-wise +messages to the hypervisor debug console. Make use of this for a +platform-agnostic boot diagnosis channel, specifically for non-root +cells. This also comes with earlycon support. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + MAINTAINERS | 1 + + drivers/virt/Kconfig | 11 +++++ + drivers/virt/Makefile | 1 + + drivers/virt/jailhouse_dbgcon.c | 103 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 116 insertions(+) + create mode 100644 drivers/virt/jailhouse_dbgcon.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 9d3a5c54a41d..07cb4d674c93 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -8761,6 +8761,7 @@ L: jailhouse-dev@googlegroups.com + S: Maintained + F: arch/x86/kernel/jailhouse.c + F: arch/x86/include/asm/jailhouse_para.h ++F: drivers/virt/jailhouse_dbgcon.c + + JC42.4 TEMPERATURE SENSOR DRIVER + M: Guenter Roeck <linux@roeck-us.net> +diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig +index 363af2eaf2ba..99c5eaca6952 100644 +--- a/drivers/virt/Kconfig ++++ b/drivers/virt/Kconfig +@@ -31,5 +31,16 @@ config FSL_HV_MANAGER + 4) A kernel interface for receiving callbacks when a managed + partition shuts down. + ++config JAILHOUSE_DBGCON ++ tristate "Jailhouse console driver" ++ depends on X86 || ARM || ARM64 ++ help ++ The Jailhouse hypervisor provides a simple write-only console for ++ debugging the bootstrap process of its cells. This driver registers ++ a console with the kernel to make use of it. ++ ++ Note that Jailhouse has to be configured to permit a cell the usage ++ of the console interface. ++ + source "drivers/virt/vboxguest/Kconfig" + endif +diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile +index fd331247c27a..89e86a1d0f19 100644 +--- a/drivers/virt/Makefile ++++ b/drivers/virt/Makefile +@@ -4,4 +4,5 @@ + # + + obj-$(CONFIG_FSL_HV_MANAGER) += fsl_hypervisor.o ++obj-$(CONFIG_JAILHOUSE_DBGCON) += jailhouse_dbgcon.o + obj-y += vboxguest/ +diff --git a/drivers/virt/jailhouse_dbgcon.c b/drivers/virt/jailhouse_dbgcon.c +new file mode 100644 +index 000000000000..1fd201ea1460 +--- /dev/null ++++ b/drivers/virt/jailhouse_dbgcon.c +@@ -0,0 +1,103 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Console driver for running over the Jailhouse partitioning hypervisor ++ * ++ * Copyright (c) Siemens AG, 2016-2018 ++ * ++ * Authors: ++ * Jan Kiszka <jan.kiszka@siemens.com> ++ */ ++ ++#include <linux/console.h> ++#include <linux/hypervisor.h> ++#include <linux/module.h> ++#include <linux/serial_core.h> ++#ifdef CONFIG_X86 ++#include <asm/alternative.h> ++#endif ++#ifdef CONFIG_ARM ++#include <asm/opcodes-virt.h> ++#endif ++ ++#define JAILHOUSE_HC_DEBUG_CONSOLE_PUTC 8 ++ ++static void hypervisor_putc(char c) ++{ ++#if defined(CONFIG_X86) ++ int result; ++ ++ asm volatile( ++ ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", ++ X86_FEATURE_VMMCALL) ++ : "=a" (result) ++ : "a" (JAILHOUSE_HC_DEBUG_CONSOLE_PUTC), "D" (c) ++ : "memory"); ++#elif defined(CONFIG_ARM) ++ register u32 num_res asm("r0") = JAILHOUSE_HC_DEBUG_CONSOLE_PUTC; ++ register u32 arg1 asm("r1") = c; ++ ++ asm volatile( ++ __HVC(0x4a48) ++ : "=r" (num_res) ++ : "r" (num_res), "r" (arg1) ++ : "memory"); ++#elif defined(CONFIG_ARM64) ++ register u64 num_res asm("x0") = JAILHOUSE_HC_DEBUG_CONSOLE_PUTC; ++ register u64 arg1 asm("x1") = c; ++ ++ asm volatile( ++ "hvc #0x4a48\n\t" ++ : "=r" (num_res) ++ : "r" (num_res), "r" (arg1) ++ : "memory"); ++#else ++#error Unsupported architecture. ++#endif ++} ++ ++static void jailhouse_dbgcon_write(struct console *con, const char *s, ++ unsigned count) ++{ ++ while (count > 0) { ++ hypervisor_putc(*s); ++ count--; ++ s++; ++ } ++} ++ ++static int __init early_jailhouse_dbgcon_setup(struct earlycon_device *device, ++ const char *options) ++{ ++ device->con->write = jailhouse_dbgcon_write; ++ return 0; ++} ++ ++EARLYCON_DECLARE(jailhouse, early_jailhouse_dbgcon_setup); ++ ++static struct console jailhouse_dbgcon = { ++ .name = "jailhouse", ++ .write = jailhouse_dbgcon_write, ++ .flags = CON_PRINTBUFFER | CON_ANYTIME, ++ .index = -1, ++}; ++ ++static int __init jailhouse_dbgcon_init(void) ++{ ++ if (!jailhouse_paravirt()) ++ return -ENODEV; ++ ++ register_console(&jailhouse_dbgcon); ++ return 0; ++} ++ ++static void __exit jailhouse_dbgcon_exit(void) ++{ ++ unregister_console(&jailhouse_dbgcon); ++} ++ ++module_init(jailhouse_dbgcon_init); ++module_exit(jailhouse_dbgcon_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Jailhouse debug console driver"); ++MODULE_AUTHOR("Jan Kiszka <jan.kiszka@siemens.com>"); +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0004-arm-Export-__boot_cpu_mode-for-use-in-Jailhouse-driv.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0004-arm-Export-__boot_cpu_mode-for-use-in-Jailhouse-driv.patch new file mode 100644 index 00000000..6e4470f0 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0004-arm-Export-__boot_cpu_mode-for-use-in-Jailhouse-driv.patch @@ -0,0 +1,43 @@ +From 56e5aace5a675af0557b87a137b98e40454d8e22 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 3 Jul 2016 10:02:40 +0200 +Subject: [PATCH 04/32] arm: Export __boot_cpu_mode for use in Jailhouse driver + module + +Onlining a CPU while Jailhouse was running sets BOOT_CPU_MODE_MISMATCH +because the kernel detect that the CPU will now only come up in SVC +mode. Therefore, we need to fix up the flag after disabling Jailhouse +again. + +Moreover, exporting the symbol allows to use is_hyp_mode_available() in +the driver, thus prevents us from crashing during Jailhouse activation +when there is no hyp stub installed. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + arch/arm/kernel/armksyms.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c +index 98bdea51089d..f2fa635bccf7 100644 +--- a/arch/arm/kernel/armksyms.c ++++ b/arch/arm/kernel/armksyms.c +@@ -17,6 +17,7 @@ + + #include <asm/checksum.h> + #include <asm/ftrace.h> ++#include <asm/virt.h> + + /* + * libgcc functions - functions that are used internally by the +@@ -176,3 +177,7 @@ EXPORT_SYMBOL(__pv_offset); + EXPORT_SYMBOL(__arm_smccc_smc); + EXPORT_SYMBOL(__arm_smccc_hvc); + #endif ++ ++#ifdef CONFIG_ARM_VIRT_EXT ++EXPORT_SYMBOL_GPL(__boot_cpu_mode); ++#endif +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0005-mm-Re-export-ioremap_page_range.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0005-mm-Re-export-ioremap_page_range.patch new file mode 100644 index 00000000..e6bf1c35 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0005-mm-Re-export-ioremap_page_range.patch @@ -0,0 +1,25 @@ +From cf5d27beb6aad2b69d716b0aee08f43619c338a9 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Tue, 7 Feb 2017 17:52:00 +0100 +Subject: [PATCH 05/32] mm: Re-export ioremap_page_range + +We need this in Jailhouse to map at specific virtual addresses, at +least for the moment. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + lib/ioremap.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/ioremap.c b/lib/ioremap.c +index 0a2ffadc6d71..baefdda8f32c 100644 +--- a/lib/ioremap.c ++++ b/lib/ioremap.c +@@ -231,3 +231,4 @@ int ioremap_page_range(unsigned long addr, + + return err; + } ++EXPORT_SYMBOL_GPL(ioremap_page_range); +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0006-arm-arm64-export-__hyp_stub_vectors.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0006-arm-arm64-export-__hyp_stub_vectors.patch new file mode 100644 index 00000000..42f3ea48 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0006-arm-arm64-export-__hyp_stub_vectors.patch @@ -0,0 +1,57 @@ +From 27588702a6792ff86a57317ef60d6e218796598e Mon Sep 17 00:00:00 2001 +From: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de> +Date: Wed, 7 Jun 2017 15:48:43 +0200 +Subject: [PATCH 06/32] arm, arm64: export __hyp_stub_vectors + +HVC_GET_VECTORS got removed. External hypervisors, like Jailhouse, need +this address when they are deactivated, in order to restore original +state. + +Signed-off-by: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de> +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + arch/arm/kernel/hyp-stub.S | 2 ++ + arch/arm64/kernel/hyp-stub.S | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S +index ae5020302de4..463366ccd2c9 100644 +--- a/arch/arm/kernel/hyp-stub.S ++++ b/arch/arm/kernel/hyp-stub.S +@@ -6,6 +6,7 @@ + #include <linux/init.h> + #include <linux/irqchip/arm-gic-v3.h> + #include <linux/linkage.h> ++#include <asm-generic/export.h> + #include <asm/assembler.h> + #include <asm/virt.h> + +@@ -269,4 +270,5 @@ __hyp_stub_trap: W(b) __hyp_stub_do_trap + __hyp_stub_irq: W(b) . + __hyp_stub_fiq: W(b) . + ENDPROC(__hyp_stub_vectors) ++EXPORT_SYMBOL_GPL(__hyp_stub_vectors) + +diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S +index 73d46070b315..ef2503bba71d 100644 +--- a/arch/arm64/kernel/hyp-stub.S ++++ b/arch/arm64/kernel/hyp-stub.S +@@ -10,6 +10,7 @@ + #include <linux/linkage.h> + #include <linux/irqchip/arm-gic-v3.h> + ++#include <asm-generic/export.h> + #include <asm/assembler.h> + #include <asm/kvm_arm.h> + #include <asm/kvm_asm.h> +@@ -42,6 +43,7 @@ ENTRY(__hyp_stub_vectors) + ventry el1_fiq_invalid // FIQ 32-bit EL1 + ventry el1_error_invalid // Error 32-bit EL1 + ENDPROC(__hyp_stub_vectors) ++EXPORT_SYMBOL_GPL(__hyp_stub_vectors) + + .align 11 + +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0007-x86-Export-lapic_timer_period.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0007-x86-Export-lapic_timer_period.patch new file mode 100644 index 00000000..9b2a2f2c --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0007-x86-Export-lapic_timer_period.patch @@ -0,0 +1,28 @@ +From 3f87075ce9d3e04e8e43de2e88dd7728b3777eb8 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Thu, 23 Nov 2017 07:12:57 +0100 +Subject: [PATCH 07/32] x86: Export lapic_timer_period + +Required for the Jailhouse driver in order to forward the calibration +value to other cells. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + arch/x86/kernel/apic/apic.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c +index 2b0faf86da1b..0428ad289899 100644 +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -196,6 +196,7 @@ static struct resource lapic_resource = { + }; + + unsigned int lapic_timer_period = 0; ++EXPORT_SYMBOL_GPL(lapic_timer_period); + + static void apic_pm_activate(void); + +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0008-arm64-dts-marvell-armada-37xx-Set-pci-domain.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0008-arm64-dts-marvell-armada-37xx-Set-pci-domain.patch new file mode 100644 index 00000000..963989cf --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0008-arm64-dts-marvell-armada-37xx-Set-pci-domain.patch @@ -0,0 +1,31 @@ +From 764a3a5da899b596474edf916b44dfc034443445 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Mon, 17 Sep 2018 08:08:08 +0200 +Subject: [PATCH 08/32] arm64: dts: marvell: armada-37xx: Set pci-domain + +This is a nop for normal operation but allows the device tree overlay +that the Jailhouse hypervisor injects to use pci-domain as well +(linux,pci-domain has to be applied consistently in a system). That will +assign a stable PCI domain to the secondary, virtual host controller of +Jailhouse. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +index 000c135e39b7..d839cea9d361 100644 +--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +@@ -482,6 +482,7 @@ + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x00 0xff>; ++ linux,pci-domain = <0>; + interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <1>; + msi-parent = <&pcie0>; +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0009-arm64-dts-marvell-armada-8030-mcbin-Set-pci-domain.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0009-arm64-dts-marvell-armada-8030-mcbin-Set-pci-domain.patch new file mode 100644 index 00000000..8e99fa12 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0009-arm64-dts-marvell-armada-8030-mcbin-Set-pci-domain.patch @@ -0,0 +1,31 @@ +From 1f916502347d2b902002b430cffe18b11685f211 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 30 Sep 2018 21:22:32 +0200 +Subject: [PATCH 09/32] arm64: dts: marvell: armada-8030-mcbin: Set pci-domain + +This is a nop for normal operation but allows the device tree overlay +that the Jailhouse hypervisor injects to use pci-domain as well +(linux,pci-domain has to be applied consistently in a system). That will +assign a stable PCI domain to the secondary, virtual host controller of +Jailhouse. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi +index d250f4b2bfed..58bac50b06eb 100644 +--- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi ++++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi +@@ -174,6 +174,7 @@ + }; + + &cp0_pcie0 { ++ linux,pci-domain = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_pcie_pins>; + num-lanes = <4>; +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0010-uio-Enable-read-only-mappings.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0010-uio-Enable-read-only-mappings.patch new file mode 100644 index 00000000..2fa65641 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0010-uio-Enable-read-only-mappings.patch @@ -0,0 +1,57 @@ +From 9c8885c6e020451e4a4578be9db318e5c07227ea Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Tue, 4 Jun 2019 14:40:09 +0200 +Subject: [PATCH 10/32] uio: Enable read-only mappings + +This allows to tag memory regions read-only, denying userspace to map +them writable. Default remains read/write. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/uio/uio.c | 9 +++++++++ + include/linux/uio_driver.h | 2 ++ + 2 files changed, 11 insertions(+) + +diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c +index a57698985f9c..ac18542ee4fe 100644 +--- a/drivers/uio/uio.c ++++ b/drivers/uio/uio.c +@@ -790,6 +790,15 @@ static int uio_mmap(struct file *filep, struct vm_area_struct *vma) + goto out; + } + ++ if (idev->info->mem[mi].readonly) { ++ if (vma->vm_flags & VM_WRITE) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ vma->vm_flags &= ~VM_MAYWRITE; ++ } ++ + if (idev->info->mmap) { + ret = idev->info->mmap(idev->info, vma); + goto out; +diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h +index 01081c4726c0..ebfc06e36ca2 100644 +--- a/include/linux/uio_driver.h ++++ b/include/linux/uio_driver.h +@@ -31,6 +31,7 @@ struct uio_map; + * @offs: offset of device memory within the page + * @size: size of IO (multiple of page size) + * @memtype: type of memory addr points to ++ * @readonly: true of region is read-only + * @internal_addr: ioremap-ped version of addr, for driver internal use + * @map: for use by the UIO core only. + */ +@@ -40,6 +41,7 @@ struct uio_mem { + unsigned long offs; + resource_size_t size; + int memtype; ++ bool readonly; + void __iomem *internal_addr; + struct uio_map *map; + }; +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0011-ivshmem-Add-header-file.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0011-ivshmem-Add-header-file.patch new file mode 100644 index 00000000..f143d150 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0011-ivshmem-Add-header-file.patch @@ -0,0 +1,52 @@ +From 61d003be018fb5b874e6ffbf746684c53556c00e Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Tue, 1 Oct 2019 12:33:25 +0200 +Subject: [PATCH 11/32] ivshmem: Add header file + +Common defines and structures for the ivshmem device. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + include/linux/ivshmem.h | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + create mode 100644 include/linux/ivshmem.h + +diff --git a/include/linux/ivshmem.h b/include/linux/ivshmem.h +new file mode 100644 +index 000000000000..bad8547f071b +--- /dev/null ++++ b/include/linux/ivshmem.h +@@ -0,0 +1,30 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++#ifndef _LINUX_IVSHMEM_H ++#define _LINUX_IVSHMEM_H ++ ++#include <linux/types.h> ++ ++#define IVSHM_PROTO_UNDEFINED 0x0000 ++#define IVSHM_PROTO_NET 0x0001 ++#define IVSHM_PROTO_VIRTIO_FRONT 0x8000 ++#define IVSHM_PROTO_VIRTIO_BACK 0xc000 ++#define IVSHM_PROTO_VIRTIO_DEVID_MASK 0x7fff ++ ++#define IVSHM_CFG_PRIV_CNTL 0x03 ++# define IVSHM_PRIV_CNTL_ONESHOT_INT BIT(0) ++#define IVSHM_CFG_STATE_TAB_SZ 0x04 ++#define IVSHM_CFG_RW_SECTION_SZ 0x08 ++#define IVSHM_CFG_OUTPUT_SECTION_SZ 0x10 ++#define IVSHM_CFG_ADDRESS 0x18 ++ ++struct ivshm_regs { ++ u32 id; ++ u32 max_peers; ++ u32 int_control; ++ u32 doorbell; ++ u32 state; ++}; ++ ++#define IVSHM_INT_ENABLE BIT(0) ++ ++#endif /* _LINUX_IVSHMEM_H */ +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0012-uio-Add-driver-for-inter-VM-shared-memory-device.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0012-uio-Add-driver-for-inter-VM-shared-memory-device.patch new file mode 100644 index 00000000..f98670c3 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0012-uio-Add-driver-for-inter-VM-shared-memory-device.patch @@ -0,0 +1,311 @@ +From 205cdad2dc9fc8a6a7204b2a71408b43085dd45f Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Tue, 4 Jun 2019 18:40:25 +0200 +Subject: [PATCH 12/32] uio: Add driver for inter-VM shared memory device + +This adds a UIO driver the ivshmem device, found in QEMU and the +Jailhouse hypervisor. It exposes the MMIO register region and all shared +memory section to userspace. Interrupts are configured in one-shot mode +so that userspace needs to re-enable them after each event via the +Interrupt Control register. The driver registers all possible MSI-X +vectors, coalescing them into the single notifier UIO provides. + +Note: Specification work for the interface is ongoing, so details may +still change. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/uio/Kconfig | 7 ++ + drivers/uio/Makefile | 1 + + drivers/uio/uio_ivshmem.c | 241 ++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/pci_ids.h | 1 + + 4 files changed, 250 insertions(+) + create mode 100644 drivers/uio/uio_ivshmem.c + +diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig +index 202ee81cfc2b..a130500f46b8 100644 +--- a/drivers/uio/Kconfig ++++ b/drivers/uio/Kconfig +@@ -165,4 +165,11 @@ config UIO_HV_GENERIC + to network and storage devices from userspace. + + If you compile this as a module, it will be called uio_hv_generic. ++ ++config UIO_IVSHMEM ++ tristate "Inter-VM Shared Memory driver" ++ depends on PCI ++ help ++ Userspace I/O driver for the inter-VM shared memory PCI device ++ as provided by QEMU and the Jailhouse hypervisor. + endif +diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile +index c285dd2a4539..3911fefb2a7e 100644 +--- a/drivers/uio/Makefile ++++ b/drivers/uio/Makefile +@@ -11,3 +11,4 @@ obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o + obj-$(CONFIG_UIO_MF624) += uio_mf624.o + obj-$(CONFIG_UIO_FSL_ELBC_GPCM) += uio_fsl_elbc_gpcm.o + obj-$(CONFIG_UIO_HV_GENERIC) += uio_hv_generic.o ++obj-$(CONFIG_UIO_IVSHMEM) += uio_ivshmem.o +diff --git a/drivers/uio/uio_ivshmem.c b/drivers/uio/uio_ivshmem.c +new file mode 100644 +index 000000000000..0c16d428c6ed +--- /dev/null ++++ b/drivers/uio/uio_ivshmem.c +@@ -0,0 +1,241 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * UIO driver for Inter-VM shared memory PCI device ++ * ++ * Copyright (c) Siemens AG, 2019 ++ * ++ * Authors: ++ * Jan Kiszka <jan.kiszka@siemens.com> ++ */ ++ ++#include <linux/ivshmem.h> ++#include <linux/module.h> ++#include <linux/pci.h> ++#include <linux/uio_driver.h> ++ ++#define DRV_NAME "uio_ivshmem" ++ ++struct ivshm_dev { ++ struct uio_info info; ++ struct pci_dev *pdev; ++ struct ivshm_regs __iomem *regs; ++ int vectors; ++}; ++ ++static irqreturn_t ivshm_irq_handler(int irq, void *dev_id) ++{ ++ struct ivshm_dev *ivshm_dev = (struct ivshm_dev *)dev_id; ++ ++ /* nothing else to do, we configured one-shot interrupt mode */ ++ uio_event_notify(&ivshm_dev->info); ++ ++ return IRQ_HANDLED; ++} ++ ++static u64 get_config_qword(struct pci_dev *pdev, unsigned int pos) ++{ ++ u32 lo, hi; ++ ++ pci_read_config_dword(pdev, pos, &lo); ++ pci_read_config_dword(pdev, pos + 4, &hi); ++ return lo | ((u64)hi << 32); ++} ++ ++static int ivshm_release(struct uio_info *info, struct inode *inode) ++{ ++ struct ivshm_dev *ivshm_dev = ++ container_of(info, struct ivshm_dev, info); ++ ++ writel(0, &ivshm_dev->regs->state); ++ return 0; ++} ++ ++static int ivshm_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++{ ++ resource_size_t rw_section_sz, output_section_sz; ++ struct ivshm_dev *ivshm_dev; ++ phys_addr_t section_addr; ++ int err, vendor_cap, i; ++ unsigned int cap_pos; ++ struct uio_mem *mem; ++ char *device_name; ++ u32 dword; ++ ++ ivshm_dev = devm_kzalloc(&pdev->dev, sizeof(struct ivshm_dev), ++ GFP_KERNEL); ++ if (!ivshm_dev) ++ return -ENOMEM; ++ ++ err = pcim_enable_device(pdev); ++ if (err) ++ return err; ++ ++ device_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s[%s]", DRV_NAME, ++ dev_name(&pdev->dev)); ++ if (!device_name) ++ return -ENOMEM; ++ ++ ivshm_dev->info.name = device_name; ++ ivshm_dev->info.version = "1"; ++ ivshm_dev->info.release = ivshm_release; ++ ++ err = pcim_iomap_regions(pdev, BIT(0), device_name); ++ if (err) ++ return err; ++ ivshm_dev->regs = pcim_iomap_table(pdev)[0]; ++ ++ mem = &ivshm_dev->info.mem[0]; ++ ++ mem->name = "registers"; ++ mem->addr = pci_resource_start(pdev, 0); ++ if (!mem->addr) ++ return -ENODEV; ++ mem->size = pci_resource_len(pdev, 0); ++ mem->memtype = UIO_MEM_PHYS; ++ ++ vendor_cap = pci_find_capability(pdev, PCI_CAP_ID_VNDR); ++ if (vendor_cap < 0) ++ return -ENODEV; ++ ++ if (pci_resource_len(pdev, 2) > 0) { ++ section_addr = pci_resource_start(pdev, 2); ++ } else { ++ cap_pos = vendor_cap + IVSHM_CFG_ADDRESS; ++ section_addr = get_config_qword(pdev, cap_pos); ++ } ++ ++ mem++; ++ mem->name = "state_table"; ++ mem->addr = section_addr; ++ cap_pos = vendor_cap + IVSHM_CFG_STATE_TAB_SZ; ++ pci_read_config_dword(pdev, cap_pos, &dword); ++ mem->size = dword; ++ mem->memtype = UIO_MEM_IOVA; ++ mem->readonly = true; ++ if (!devm_request_mem_region(&pdev->dev, mem->addr, mem->size, ++ device_name)) ++ return -EBUSY; ++ dev_info(&pdev->dev, "%s at %pa, size %pa\n", mem->name, &mem->addr, ++ &mem->size); ++ ++ cap_pos = vendor_cap + IVSHM_CFG_RW_SECTION_SZ; ++ rw_section_sz = get_config_qword(pdev, cap_pos); ++ if (rw_section_sz > 0) { ++ section_addr += mem->size; ++ ++ mem++; ++ mem->name = "rw_section"; ++ mem->addr = section_addr; ++ mem->size = rw_section_sz; ++ mem->memtype = UIO_MEM_IOVA; ++ if (!devm_request_mem_region(&pdev->dev, mem->addr, mem->size, ++ device_name)) ++ return -EBUSY; ++ dev_info(&pdev->dev, "%s at %pa, size %pa\n", mem->name, ++ &mem->addr, &mem->size); ++ } ++ ++ cap_pos = vendor_cap + IVSHM_CFG_OUTPUT_SECTION_SZ; ++ output_section_sz = get_config_qword(pdev, cap_pos); ++ if (output_section_sz > 0) { ++ section_addr += mem->size; ++ ++ mem++; ++ mem->name = "input_sections"; ++ mem->addr = section_addr; ++ mem->size = ++ readl(&ivshm_dev->regs->max_peers) * output_section_sz; ++ mem->memtype = UIO_MEM_IOVA; ++ mem->readonly = true; ++ if (!devm_request_mem_region(&pdev->dev, mem->addr, mem->size, ++ device_name)) ++ return -EBUSY; ++ dev_info(&pdev->dev, "%s at %pa, size %pa\n", mem->name, ++ &mem->addr, &mem->size); ++ ++ mem++; ++ mem->name = "output_section"; ++ mem->addr = section_addr + ++ readl(&ivshm_dev->regs->id) * output_section_sz; ++ mem->size = output_section_sz; ++ mem->memtype = UIO_MEM_IOVA; ++ dev_info(&pdev->dev, "%s at %pa, size %pa\n", mem->name, ++ &mem->addr, &mem->size); ++ } ++ ++ pci_write_config_byte(pdev, vendor_cap + IVSHM_CFG_PRIV_CNTL, ++ IVSHM_PRIV_CNTL_ONESHOT_INT); ++ ++ /* ++ * Grab all vectors although we can only coalesce them into a single ++ * notifier. This avoids missing any event. ++ */ ++ ivshm_dev->vectors = pci_msix_vec_count(pdev); ++ if (ivshm_dev->vectors < 0) ++ ivshm_dev->vectors = 1; ++ ++ err = pci_alloc_irq_vectors(pdev, ivshm_dev->vectors, ++ ivshm_dev->vectors, ++ PCI_IRQ_LEGACY | PCI_IRQ_MSIX); ++ if (err < 0) ++ return err; ++ ++ for (i = 0; i < ivshm_dev->vectors; i++) { ++ err = request_irq(pci_irq_vector(pdev, i), ivshm_irq_handler, ++ IRQF_SHARED, ivshm_dev->info.name, ivshm_dev); ++ if (err) ++ goto error; ++ } ++ ++ ivshm_dev->info.irq = UIO_IRQ_CUSTOM; ++ ++ err = uio_register_device(&pdev->dev, &ivshm_dev->info); ++ if (err) ++ goto error; ++ ++ pci_set_master(pdev); ++ ++ pci_set_drvdata(pdev, ivshm_dev); ++ ++ return 0; ++ ++error: ++ while (--i > 0) ++ free_irq(pci_irq_vector(pdev, i), ivshm_dev); ++ pci_free_irq_vectors(pdev); ++ return err; ++} ++ ++static void ivshm_remove(struct pci_dev *pdev) ++{ ++ struct ivshm_dev *ivshm_dev = pci_get_drvdata(pdev); ++ int i; ++ ++ writel(0, &ivshm_dev->regs->int_control); ++ pci_clear_master(pdev); ++ ++ uio_unregister_device(&ivshm_dev->info); ++ ++ for (i = 0; i < ivshm_dev->vectors; i++) ++ free_irq(pci_irq_vector(pdev, i), ivshm_dev); ++ ++ pci_free_irq_vectors(pdev); ++} ++ ++static const struct pci_device_id ivshm_device_id_table[] = { ++ { PCI_DEVICE(PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_IVSHMEM), ++ (PCI_CLASS_OTHERS << 16) | IVSHM_PROTO_UNDEFINED, 0xffffff }, ++ { 0 } ++}; ++MODULE_DEVICE_TABLE(pci, ivshm_device_id_table); ++ ++static struct pci_driver uio_ivshm_driver = { ++ .name = DRV_NAME, ++ .id_table = ivshm_device_id_table, ++ .probe = ivshm_probe, ++ .remove = ivshm_remove, ++}; ++module_pci_driver(uio_ivshm_driver); ++ ++MODULE_AUTHOR("Jan Kiszka <jan.kiszka@siemens.com>"); ++MODULE_LICENSE("GPL v2"); +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index 21a572469a4e..e450458c8ba8 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -1477,6 +1477,7 @@ + + #define PCI_VENDOR_ID_SIEMENS 0x110A + #define PCI_DEVICE_ID_SIEMENS_DSCC4 0x2102 ++#define PCI_DEVICE_ID_IVSHMEM 0x4106 + + #define PCI_VENDOR_ID_VORTEX 0x1119 + #define PCI_DEVICE_ID_VORTEX_GDT60x0 0x0000 +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0013-ivshmem-net-virtual-network-device-for-Jailhouse.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0013-ivshmem-net-virtual-network-device-for-Jailhouse.patch new file mode 100644 index 00000000..ae5ac475 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0013-ivshmem-net-virtual-network-device-for-Jailhouse.patch @@ -0,0 +1,968 @@ +From fa0e2362149bb814d6b7431a7c42989d33002f60 Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Thu, 26 May 2016 16:04:02 +0100 +Subject: [PATCH 13/32] ivshmem-net: virtual network device for Jailhouse + +Work in progress. +--- + drivers/net/Kconfig | 4 + + drivers/net/Makefile | 2 + + drivers/net/ivshmem-net.c | 923 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 929 insertions(+) + create mode 100644 drivers/net/ivshmem-net.c + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index df1c7989e13d..8c65f55163e3 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -527,4 +527,8 @@ config NET_FAILOVER + a VM with direct attached VF by failing over to the paravirtual + datapath when the VF is unplugged. + ++config IVSHMEM_NET ++ tristate "IVSHMEM virtual network device" ++ depends on PCI ++ + endif # NETDEVICES +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index 0d3ba056cda3..5041c293d4d0 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -79,3 +79,5 @@ thunderbolt-net-y += thunderbolt.o + obj-$(CONFIG_THUNDERBOLT_NET) += thunderbolt-net.o + obj-$(CONFIG_NETDEVSIM) += netdevsim/ + obj-$(CONFIG_NET_FAILOVER) += net_failover.o ++ ++obj-$(CONFIG_IVSHMEM_NET) += ivshmem-net.o +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +new file mode 100644 +index 000000000000..b676bed2cc2e +--- /dev/null ++++ b/drivers/net/ivshmem-net.c +@@ -0,0 +1,923 @@ ++/* ++ * Copyright 2016 Mans Rullgard <mans@mansr.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/pci.h> ++#include <linux/io.h> ++#include <linux/bitops.h> ++#include <linux/interrupt.h> ++#include <linux/netdevice.h> ++#include <linux/etherdevice.h> ++#include <linux/rtnetlink.h> ++#include <linux/virtio_ring.h> ++ ++#define DRV_NAME "ivshmem-net" ++ ++#define JAILHOUSE_CFG_SHMEM_PTR 0x40 ++#define JAILHOUSE_CFG_SHMEM_SZ 0x48 ++ ++#define IVSHM_NET_STATE_RESET 0 ++#define IVSHM_NET_STATE_INIT 1 ++#define IVSHM_NET_STATE_READY 2 ++#define IVSHM_NET_STATE_RUN 3 ++ ++#define IVSHM_NET_MTU_MIN 256 ++#define IVSHM_NET_MTU_MAX 65535 ++#define IVSHM_NET_MTU_DEF 16384 ++ ++#define IVSHM_NET_FRAME_SIZE(s) ALIGN(18 + (s), SMP_CACHE_BYTES) ++ ++#define IVSHM_NET_VQ_ALIGN 64 ++ ++struct ivshmem_regs { ++ u32 imask; ++ u32 istat; ++ u32 ivpos; ++ u32 doorbell; ++ u32 lstate; ++ u32 rstate; ++}; ++ ++struct ivshm_net_queue { ++ struct vring vr; ++ u32 free_head; ++ u32 num_free; ++ u32 num_added; ++ u16 last_avail_idx; ++ u16 last_used_idx; ++ ++ void *data; ++ void *end; ++ u32 size; ++ u32 head; ++ u32 tail; ++}; ++ ++struct ivshm_net_stats { ++ u32 interrupts; ++ u32 tx_packets; ++ u32 tx_notify; ++ u32 tx_pause; ++ u32 rx_packets; ++ u32 rx_notify; ++ u32 napi_poll; ++ u32 napi_complete; ++ u32 napi_poll_n[10]; ++}; ++ ++struct ivshm_net { ++ struct ivshm_net_queue rx; ++ struct ivshm_net_queue tx; ++ ++ u32 vrsize; ++ u32 qlen; ++ u32 qsize; ++ ++ spinlock_t tx_free_lock; ++ spinlock_t tx_clean_lock; ++ ++ struct napi_struct napi; ++ ++ u32 lstate; ++ u32 rstate; ++ ++ struct workqueue_struct *state_wq; ++ struct work_struct state_work; ++ ++ struct ivshm_net_stats stats; ++ ++ struct ivshmem_regs __iomem *ivshm_regs; ++ void *shm; ++ phys_addr_t shmaddr; ++ resource_size_t shmlen; ++ u32 peer_id; ++ ++ struct pci_dev *pdev; ++ struct msix_entry msix; ++ bool using_msix; ++}; ++ ++static void *ivshm_net_desc_data(struct ivshm_net *in, ++ struct ivshm_net_queue *q, ++ struct vring_desc *desc, ++ u32 *len) ++{ ++ u64 addr = READ_ONCE(desc->addr); ++ u32 dlen = READ_ONCE(desc->len); ++ void *data; ++ ++ if (addr < in->shmaddr || desc->addr > in->shmaddr + in->shmlen) ++ return NULL; ++ ++ data = in->shm + (addr - in->shmaddr); ++ ++ if (data < q->data || data >= q->end) ++ return NULL; ++ ++ if (dlen > q->end - data) ++ return NULL; ++ ++ *len = dlen; ++ ++ return data; ++} ++ ++static void ivshm_net_init_queue(struct ivshm_net *in, ++ struct ivshm_net_queue *q, ++ void *mem, unsigned int len) ++{ ++ memset(q, 0, sizeof(*q)); ++ ++ vring_init(&q->vr, len, mem, IVSHM_NET_VQ_ALIGN); ++ q->data = mem + in->vrsize; ++ q->end = q->data + in->qsize; ++ q->size = in->qsize; ++} ++ ++static void ivshm_net_init_queues(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ int ivpos = readl(&in->ivshm_regs->ivpos); ++ void *tx; ++ void *rx; ++ int i; ++ ++ tx = in->shm + ivpos * in->shmlen / 2; ++ rx = in->shm + !ivpos * in->shmlen / 2; ++ ++ memset(tx, 0, in->shmlen / 2); ++ ++ ivshm_net_init_queue(in, &in->rx, rx, in->qlen); ++ ivshm_net_init_queue(in, &in->tx, tx, in->qlen); ++ ++ swap(in->rx.vr.used, in->tx.vr.used); ++ ++ in->tx.num_free = in->tx.vr.num; ++ ++ for (i = 0; i < in->tx.vr.num - 1; i++) ++ in->tx.vr.desc[i].next = i + 1; ++} ++ ++static int ivshm_net_calc_qsize(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ unsigned int vrsize; ++ unsigned int qsize; ++ unsigned int qlen; ++ ++ for (qlen = 4096; qlen > 32; qlen >>= 1) { ++ vrsize = vring_size(qlen, IVSHM_NET_VQ_ALIGN); ++ vrsize = ALIGN(vrsize, IVSHM_NET_VQ_ALIGN); ++ if (vrsize < in->shmlen / 16) ++ break; ++ } ++ ++ if (vrsize > in->shmlen / 2) ++ return -EINVAL; ++ ++ qsize = in->shmlen / 2 - vrsize; ++ ++ if (qsize < 4 * IVSHM_NET_MTU_MIN) ++ return -EINVAL; ++ ++ in->vrsize = vrsize; ++ in->qlen = qlen; ++ in->qsize = qsize; ++ ++ return 0; ++} ++ ++static void ivshm_net_notify_tx(struct ivshm_net *in, unsigned int num) ++{ ++ u16 evt, old, new; ++ ++ virt_mb(); ++ ++ evt = READ_ONCE(vring_avail_event(&in->tx.vr)); ++ old = in->tx.last_avail_idx - num; ++ new = in->tx.last_avail_idx; ++ ++ if (vring_need_event(evt, new, old)) { ++ writel(in->peer_id << 16, &in->ivshm_regs->doorbell); ++ in->stats.tx_notify++; ++ } ++} ++ ++static void ivshm_net_enable_rx_irq(struct ivshm_net *in) ++{ ++ vring_avail_event(&in->rx.vr) = in->rx.last_avail_idx; ++ virt_wmb(); ++} ++ ++static void ivshm_net_notify_rx(struct ivshm_net *in, unsigned int num) ++{ ++ u16 evt, old, new; ++ ++ virt_mb(); ++ ++ evt = vring_used_event(&in->rx.vr); ++ old = in->rx.last_used_idx - num; ++ new = in->rx.last_used_idx; ++ ++ if (vring_need_event(evt, new, old)) { ++ writel(in->peer_id << 16, &in->ivshm_regs->doorbell); ++ in->stats.rx_notify++; ++ } ++} ++ ++static void ivshm_net_enable_tx_irq(struct ivshm_net *in) ++{ ++ vring_used_event(&in->tx.vr) = in->tx.last_used_idx; ++ virt_wmb(); ++} ++ ++static bool ivshm_net_rx_avail(struct ivshm_net *in) ++{ ++ virt_mb(); ++ return READ_ONCE(in->rx.vr.avail->idx) != in->rx.last_avail_idx; ++} ++ ++static size_t ivshm_net_tx_space(struct ivshm_net *in) ++{ ++ struct ivshm_net_queue *tx = &in->tx; ++ u32 tail = tx->tail; ++ u32 head = tx->head; ++ u32 space; ++ ++ if (head < tail) ++ space = tail - head; ++ else ++ space = max(tx->size - head, tail); ++ ++ return space; ++} ++ ++static bool ivshm_net_tx_ok(struct ivshm_net *in, unsigned int mtu) ++{ ++ return in->tx.num_free >= 2 && ++ ivshm_net_tx_space(in) >= 2 * IVSHM_NET_FRAME_SIZE(mtu); ++} ++ ++static u32 ivshm_net_tx_advance(struct ivshm_net_queue *q, u32 *pos, u32 len) ++{ ++ u32 p = *pos; ++ ++ len = IVSHM_NET_FRAME_SIZE(len); ++ ++ if (q->size - p < len) ++ p = 0; ++ *pos = p + len; ++ ++ return p; ++} ++ ++static int ivshm_net_tx_frame(struct net_device *ndev, struct sk_buff *skb) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ struct ivshm_net_queue *tx = &in->tx; ++ struct vring *vr = &tx->vr; ++ struct vring_desc *desc; ++ unsigned int desc_idx; ++ unsigned int avail; ++ u32 head; ++ void *buf; ++ ++ BUG_ON(tx->num_free < 1); ++ ++ spin_lock(&in->tx_free_lock); ++ desc_idx = tx->free_head; ++ desc = &vr->desc[desc_idx]; ++ tx->free_head = desc->next; ++ tx->num_free--; ++ spin_unlock(&in->tx_free_lock); ++ ++ head = ivshm_net_tx_advance(tx, &tx->head, skb->len); ++ ++ buf = tx->data + head; ++ skb_copy_and_csum_dev(skb, buf); ++ ++ desc->addr = in->shmaddr + (buf - in->shm); ++ desc->len = skb->len; ++ ++ avail = tx->last_avail_idx++ & (vr->num - 1); ++ vr->avail->ring[avail] = desc_idx; ++ tx->num_added++; ++ ++ if (!skb->xmit_more) { ++ virt_store_release(&vr->avail->idx, tx->last_avail_idx); ++ ivshm_net_notify_tx(in, tx->num_added); ++ tx->num_added = 0; ++ } ++ ++ return 0; ++} ++ ++static void ivshm_net_tx_clean(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ struct ivshm_net_queue *tx = &in->tx; ++ struct vring *vr = &tx->vr; ++ struct vring_desc *desc; ++ struct vring_desc *fdesc; ++ unsigned int used; ++ unsigned int num; ++ u16 used_idx; ++ u16 last; ++ u32 fhead; ++ ++ if (!spin_trylock(&in->tx_clean_lock)) ++ return; ++ ++ used_idx = virt_load_acquire(&vr->used->idx); ++ last = tx->last_used_idx; ++ ++ fdesc = NULL; ++ num = 0; ++ ++ while (last != used_idx) { ++ void *data; ++ u32 len; ++ u32 tail; ++ ++ used = vr->used->ring[last & (vr->num - 1)].id; ++ if (used >= vr->num) { ++ netdev_err(ndev, "invalid tx used %d\n", used); ++ break; ++ } ++ ++ desc = &vr->desc[used]; ++ ++ data = ivshm_net_desc_data(in, &in->tx, desc, &len); ++ if (!data) { ++ netdev_err(ndev, "bad tx descriptor\n"); ++ break; ++ } ++ ++ tail = ivshm_net_tx_advance(tx, &tx->tail, len); ++ if (data != tx->data + tail) { ++ netdev_err(ndev, "bad tx descriptor\n"); ++ break; ++ } ++ ++ if (!num) ++ fdesc = desc; ++ else ++ desc->next = fhead; ++ ++ fhead = used; ++ last++; ++ num++; ++ } ++ ++ tx->last_used_idx = last; ++ ++ spin_unlock(&in->tx_clean_lock); ++ ++ if (num) { ++ spin_lock(&in->tx_free_lock); ++ fdesc->next = tx->free_head; ++ tx->free_head = fhead; ++ tx->num_free += num; ++ BUG_ON(tx->num_free > vr->num); ++ spin_unlock(&in->tx_free_lock); ++ } ++} ++ ++static struct vring_desc *ivshm_net_rx_desc(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ struct ivshm_net_queue *rx = &in->rx; ++ struct vring *vr = &rx->vr; ++ unsigned int avail; ++ u16 avail_idx; ++ ++ avail_idx = virt_load_acquire(&vr->avail->idx); ++ ++ if (avail_idx == rx->last_avail_idx) ++ return NULL; ++ ++ avail = vr->avail->ring[rx->last_avail_idx++ & (vr->num - 1)]; ++ if (avail >= vr->num) { ++ netdev_err(ndev, "invalid rx avail %d\n", avail); ++ return NULL; ++ } ++ ++ return &vr->desc[avail]; ++} ++ ++static void ivshm_net_rx_finish(struct ivshm_net *in, struct vring_desc *desc) ++{ ++ struct ivshm_net_queue *rx = &in->rx; ++ struct vring *vr = &rx->vr; ++ unsigned int desc_id = desc - vr->desc; ++ unsigned int used; ++ ++ used = rx->last_used_idx++ & (vr->num - 1); ++ vr->used->ring[used].id = desc_id; ++ ++ virt_store_release(&vr->used->idx, rx->last_used_idx); ++} ++ ++static int ivshm_net_poll(struct napi_struct *napi, int budget) ++{ ++ struct net_device *ndev = napi->dev; ++ struct ivshm_net *in = container_of(napi, struct ivshm_net, napi); ++ int received = 0; ++ ++ in->stats.napi_poll++; ++ ++ ivshm_net_tx_clean(ndev); ++ ++ while (received < budget) { ++ struct vring_desc *desc; ++ struct sk_buff *skb; ++ void *data; ++ u32 len; ++ ++ desc = ivshm_net_rx_desc(ndev); ++ if (!desc) ++ break; ++ ++ data = ivshm_net_desc_data(in, &in->rx, desc, &len); ++ if (!data) { ++ netdev_err(ndev, "bad rx descriptor\n"); ++ break; ++ } ++ ++ skb = napi_alloc_skb(napi, len); ++ ++ if (skb) { ++ memcpy(skb_put(skb, len), data, len); ++ skb->protocol = eth_type_trans(skb, ndev); ++ napi_gro_receive(napi, skb); ++ } ++ ++ ndev->stats.rx_packets++; ++ ndev->stats.rx_bytes += len; ++ ++ ivshm_net_rx_finish(in, desc); ++ received++; ++ } ++ ++ if (received < budget) { ++ in->stats.napi_complete++; ++ napi_complete_done(napi, received); ++ ivshm_net_enable_rx_irq(in); ++ if (ivshm_net_rx_avail(in)) ++ napi_schedule(napi); ++ } ++ ++ if (received) ++ ivshm_net_notify_rx(in, received); ++ ++ in->stats.rx_packets += received; ++ in->stats.napi_poll_n[received ? 1 + min(ilog2(received), 8) : 0]++; ++ ++ if (ivshm_net_tx_ok(in, ndev->mtu)) ++ netif_wake_queue(ndev); ++ ++ return received; ++} ++ ++static netdev_tx_t ivshm_net_xmit(struct sk_buff *skb, struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ ++ ivshm_net_tx_clean(ndev); ++ ++ if (!ivshm_net_tx_ok(in, ndev->mtu)) { ++ ivshm_net_enable_tx_irq(in); ++ netif_stop_queue(ndev); ++ skb->xmit_more = 0; ++ in->stats.tx_pause++; ++ } ++ ++ ivshm_net_tx_frame(ndev, skb); ++ ++ in->stats.tx_packets++; ++ ndev->stats.tx_packets++; ++ ndev->stats.tx_bytes += skb->len; ++ ++ dev_consume_skb_any(skb); ++ ++ return NETDEV_TX_OK; ++} ++ ++static void ivshm_net_set_state(struct ivshm_net *in, u32 state) ++{ ++ virt_wmb(); ++ WRITE_ONCE(in->lstate, state); ++ writel(state, &in->ivshm_regs->lstate); ++} ++ ++static void ivshm_net_run(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ ++ netif_start_queue(ndev); ++ napi_enable(&in->napi); ++ napi_schedule(&in->napi); ++ ivshm_net_set_state(in, IVSHM_NET_STATE_RUN); ++} ++ ++static void ivshm_net_state_change(struct work_struct *work) ++{ ++ struct ivshm_net *in = container_of(work, struct ivshm_net, state_work); ++ struct net_device *ndev = in->napi.dev; ++ u32 rstate = readl(&in->ivshm_regs->rstate); ++ ++ ++ switch (in->lstate) { ++ case IVSHM_NET_STATE_RESET: ++ if (rstate < IVSHM_NET_STATE_READY) ++ ivshm_net_set_state(in, IVSHM_NET_STATE_INIT); ++ break; ++ ++ case IVSHM_NET_STATE_INIT: ++ if (rstate > IVSHM_NET_STATE_RESET) { ++ ivshm_net_init_queues(ndev); ++ ivshm_net_set_state(in, IVSHM_NET_STATE_READY); ++ ++ rtnl_lock(); ++ call_netdevice_notifiers(NETDEV_CHANGEADDR, ndev); ++ rtnl_unlock(); ++ } ++ break; ++ ++ case IVSHM_NET_STATE_READY: ++ if (rstate >= IVSHM_NET_STATE_READY) { ++ netif_carrier_on(ndev); ++ if (ndev->flags & IFF_UP) ++ ivshm_net_run(ndev); ++ } else { ++ netif_carrier_off(ndev); ++ ivshm_net_set_state(in, IVSHM_NET_STATE_RESET); ++ } ++ break; ++ ++ case IVSHM_NET_STATE_RUN: ++ if (rstate < IVSHM_NET_STATE_READY) { ++ netif_stop_queue(ndev); ++ napi_disable(&in->napi); ++ netif_carrier_off(ndev); ++ ivshm_net_set_state(in, IVSHM_NET_STATE_RESET); ++ } ++ break; ++ } ++ ++ virt_wmb(); ++ WRITE_ONCE(in->rstate, rstate); ++} ++ ++static bool ivshm_net_check_state(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ u32 rstate = readl(&in->ivshm_regs->rstate); ++ ++ if (rstate != READ_ONCE(in->rstate) || ++ in->lstate != IVSHM_NET_STATE_RUN) { ++ queue_work(in->state_wq, &in->state_work); ++ return false; ++ } ++ ++ return true; ++} ++ ++static irqreturn_t ivshm_net_int(int irq, void *data) ++{ ++ struct net_device *ndev = data; ++ struct ivshm_net *in = netdev_priv(ndev); ++ ++ in->stats.interrupts++; ++ ++ ivshm_net_check_state(ndev); ++ napi_schedule_irqoff(&in->napi); ++ ++ return IRQ_HANDLED; ++} ++ ++static int ivshm_net_open(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ ++ netdev_reset_queue(ndev); ++ ndev->operstate = IF_OPER_UP; ++ ++ if (in->lstate == IVSHM_NET_STATE_READY) ++ ivshm_net_run(ndev); ++ ++ return 0; ++} ++ ++static int ivshm_net_stop(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ ++ ndev->operstate = IF_OPER_DOWN; ++ ++ if (in->lstate == IVSHM_NET_STATE_RUN) { ++ napi_disable(&in->napi); ++ netif_stop_queue(ndev); ++ ivshm_net_set_state(in, IVSHM_NET_STATE_READY); ++ } ++ ++ return 0; ++} ++ ++static int ivshm_net_change_mtu(struct net_device *ndev, int mtu) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ struct ivshm_net_queue *tx = &in->tx; ++ ++ if (mtu < IVSHM_NET_MTU_MIN || mtu > IVSHM_NET_MTU_MAX) ++ return -EINVAL; ++ ++ if (in->tx.size / mtu < 4) ++ return -EINVAL; ++ ++ if (ivshm_net_tx_space(in) < 2 * IVSHM_NET_FRAME_SIZE(mtu)) ++ return -EBUSY; ++ ++ if (in->tx.size - tx->head < IVSHM_NET_FRAME_SIZE(mtu) && ++ tx->head < tx->tail) ++ return -EBUSY; ++ ++ netif_tx_lock_bh(ndev); ++ if (in->tx.size - tx->head < IVSHM_NET_FRAME_SIZE(mtu)) ++ tx->head = 0; ++ netif_tx_unlock_bh(ndev); ++ ++ ndev->mtu = mtu; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++static void ivshm_net_poll_controller(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ ++ napi_schedule(&in->napi); ++} ++#endif ++ ++static const struct net_device_ops ivshm_net_ops = { ++ .ndo_open = ivshm_net_open, ++ .ndo_stop = ivshm_net_stop, ++ .ndo_start_xmit = ivshm_net_xmit, ++ .ndo_change_mtu = ivshm_net_change_mtu, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = ivshm_net_poll_controller, ++#endif ++}; ++ ++static const char ivshm_net_stats[][ETH_GSTRING_LEN] = { ++ "interrupts", ++ "tx_packets", ++ "tx_notify", ++ "tx_pause", ++ "rx_packets", ++ "rx_notify", ++ "napi_poll", ++ "napi_complete", ++ "napi_poll_0", ++ "napi_poll_1", ++ "napi_poll_2", ++ "napi_poll_4", ++ "napi_poll_8", ++ "napi_poll_16", ++ "napi_poll_32", ++ "napi_poll_64", ++ "napi_poll_128", ++ "napi_poll_256", ++}; ++ ++#define NUM_STATS ARRAY_SIZE(ivshm_net_stats) ++ ++static int ivshm_net_get_sset_count(struct net_device *ndev, int sset) ++{ ++ if (sset == ETH_SS_STATS) ++ return NUM_STATS; ++ ++ return -EOPNOTSUPP; ++} ++ ++static void ivshm_net_get_strings(struct net_device *ndev, u32 sset, u8 *buf) ++{ ++ if (sset == ETH_SS_STATS) ++ memcpy(buf, &ivshm_net_stats, sizeof(ivshm_net_stats)); ++} ++ ++static void ivshm_net_get_ethtool_stats(struct net_device *ndev, ++ struct ethtool_stats *estats, u64 *st) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ unsigned int n = 0; ++ unsigned int i; ++ ++ st[n++] = in->stats.interrupts; ++ st[n++] = in->stats.tx_packets; ++ st[n++] = in->stats.tx_notify; ++ st[n++] = in->stats.tx_pause; ++ st[n++] = in->stats.rx_packets; ++ st[n++] = in->stats.rx_notify; ++ st[n++] = in->stats.napi_poll; ++ st[n++] = in->stats.napi_complete; ++ ++ for (i = 0; i < ARRAY_SIZE(in->stats.napi_poll_n); i++) ++ st[n++] = in->stats.napi_poll_n[i]; ++ ++ memset(&in->stats, 0, sizeof(in->stats)); ++} ++ ++static const struct ethtool_ops ivshm_net_ethtool_ops = { ++ .get_sset_count = ivshm_net_get_sset_count, ++ .get_strings = ivshm_net_get_strings, ++ .get_ethtool_stats = ivshm_net_get_ethtool_stats, ++}; ++ ++static int ivshm_net_probe(struct pci_dev *pdev, ++ const struct pci_device_id *id) ++{ ++ struct net_device *ndev; ++ struct ivshm_net *in; ++ struct ivshmem_regs __iomem *regs; ++ resource_size_t shmaddr; ++ resource_size_t shmlen; ++ int interrupt; ++ void *shm; ++ u32 ivpos; ++ int err; ++ ++ err = pcim_enable_device(pdev); ++ if (err) { ++ dev_err(&pdev->dev, "pci_enable_device: %d\n", err); ++ return err; ++ } ++ ++ err = pcim_iomap_regions(pdev, BIT(0), DRV_NAME); ++ if (err) { ++ dev_err(&pdev->dev, "pcim_iomap_regions: %d\n", err); ++ return err; ++ } ++ ++ regs = pcim_iomap_table(pdev)[0]; ++ ++ shmlen = pci_resource_len(pdev, 2); ++ ++ if (shmlen) { ++ shmaddr = pci_resource_start(pdev, 2); ++ } else { ++ union { u64 v; u32 hl[2]; } val; ++ ++ pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_PTR, ++ &val.hl[0]); ++ pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_PTR + 4, ++ &val.hl[1]); ++ shmaddr = val.v; ++ ++ pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_SZ, ++ &val.hl[0]); ++ pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_SZ + 4, ++ &val.hl[1]); ++ shmlen = val.v; ++ } ++ ++ ++ if (!devm_request_mem_region(&pdev->dev, shmaddr, shmlen, DRV_NAME)) ++ return -EBUSY; ++ ++ shm = devm_memremap(&pdev->dev, shmaddr, shmlen, MEMREMAP_WC); ++ if (!shm) ++ return -ENOMEM; ++ ++ ivpos = readl(®s->ivpos); ++ if (ivpos > 1) { ++ dev_err(&pdev->dev, "invalid IVPosition %d\n", ivpos); ++ return -EINVAL; ++ } ++ ++ dev_info(&pdev->dev, "shared memory size %pa\n", &shmlen); ++ ++ ndev = alloc_etherdev(sizeof(*in)); ++ if (!ndev) ++ return -ENOMEM; ++ ++ pci_set_drvdata(pdev, ndev); ++ SET_NETDEV_DEV(ndev, &pdev->dev); ++ ++ in = netdev_priv(ndev); ++ in->ivshm_regs = regs; ++ in->shm = shm; ++ in->shmaddr = shmaddr; ++ in->shmlen = shmlen; ++ in->peer_id = !ivpos; ++ in->pdev = pdev; ++ spin_lock_init(&in->tx_free_lock); ++ spin_lock_init(&in->tx_clean_lock); ++ ++ err = ivshm_net_calc_qsize(ndev); ++ if (err) ++ goto err_free; ++ ++ in->state_wq = alloc_ordered_workqueue(DRV_NAME, 0); ++ if (!in->state_wq) ++ goto err_free; ++ ++ INIT_WORK(&in->state_work, ivshm_net_state_change); ++ ++ eth_random_addr(ndev->dev_addr); ++ ndev->netdev_ops = &ivshm_net_ops; ++ ndev->ethtool_ops = &ivshm_net_ethtool_ops; ++ ndev->mtu = min_t(u32, IVSHM_NET_MTU_DEF, in->qsize / 16); ++ ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG; ++ ndev->features = ndev->hw_features; ++ ++ netif_carrier_off(ndev); ++ netif_napi_add(ndev, &in->napi, ivshm_net_poll, NAPI_POLL_WEIGHT); ++ ++ err = register_netdev(ndev); ++ if (err) ++ goto err_wq; ++ ++ err = pci_enable_msix(pdev, &in->msix, 1); ++ if (!err) { ++ interrupt = in->msix.vector; ++ in->using_msix = true; ++ } else { ++ interrupt = pdev->irq; ++ in->using_msix = false; ++ } ++ ++ err = request_irq(interrupt, ivshm_net_int, 0, DRV_NAME, ndev); ++ if (err) ++ goto err_int; ++ ++ pci_set_master(pdev); ++ ++ writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate); ++ ++ return 0; ++ ++err_int: ++ if (in->using_msix) ++ pci_disable_msix(pdev); ++ unregister_netdev(ndev); ++err_wq: ++ destroy_workqueue(in->state_wq); ++err_free: ++ free_netdev(ndev); ++ ++ return err; ++} ++ ++static void ivshm_net_remove(struct pci_dev *pdev) ++{ ++ struct net_device *ndev = pci_get_drvdata(pdev); ++ struct ivshm_net *in = netdev_priv(ndev); ++ ++ if (in->using_msix) { ++ free_irq(in->msix.vector, ndev); ++ pci_disable_msix(pdev); ++ } else { ++ free_irq(pdev->irq, ndev); ++ } ++ ++ unregister_netdev(ndev); ++ cancel_work_sync(&in->state_work); ++ destroy_workqueue(in->state_wq); ++ free_netdev(ndev); ++} ++ ++static const struct pci_device_id ivshm_net_id_table[] = { ++ { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, 0x1110), ++ (PCI_CLASS_OTHERS << 16) | (0x01 << 8), 0xffff00 }, ++ { 0 } ++}; ++MODULE_DEVICE_TABLE(pci, ivshm_net_id_table); ++ ++static struct pci_driver ivshm_net_driver = { ++ .name = DRV_NAME, ++ .id_table = ivshm_net_id_table, ++ .probe = ivshm_net_probe, ++ .remove = ivshm_net_remove, ++}; ++module_pci_driver(ivshm_net_driver); ++ ++MODULE_AUTHOR("Mans Rullgard <mans@mansr.com>"); ++MODULE_LICENSE("GPL"); +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0014-ivshmem-net-Map-shmem-region-as-RAM.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0014-ivshmem-net-Map-shmem-region-as-RAM.patch new file mode 100644 index 00000000..de66d7a7 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0014-ivshmem-net-Map-shmem-region-as-RAM.patch @@ -0,0 +1,30 @@ +From b70f2ecb71b212225f403a8f26d3d5bdca70a107 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Thu, 24 Nov 2016 08:27:45 +0100 +Subject: [PATCH 14/32] ivshmem-net: Map shmem region as RAM + +No need for special caching, simply map the shared memory region like +RAM, thus write-back. This gives us another order of magnitude in +throughput. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index b676bed2cc2e..a535cb71adde 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -802,7 +802,7 @@ static int ivshm_net_probe(struct pci_dev *pdev, + if (!devm_request_mem_region(&pdev->dev, shmaddr, shmlen, DRV_NAME)) + return -EBUSY; + +- shm = devm_memremap(&pdev->dev, shmaddr, shmlen, MEMREMAP_WC); ++ shm = devm_memremap(&pdev->dev, shmaddr, shmlen, MEMREMAP_WB); + if (!shm) + return -ENOMEM; + +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0015-ivshmem-net-fix-race-in-state-machine.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0015-ivshmem-net-fix-race-in-state-machine.patch new file mode 100644 index 00000000..ecb5c485 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0015-ivshmem-net-fix-race-in-state-machine.patch @@ -0,0 +1,140 @@ +From 1349a457e5e33580fb26afab087e6b932b1a4372 Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Thu, 24 Nov 2016 18:46:41 +0000 +Subject: [PATCH 15/32] ivshmem-net: fix race in state machine + +--- + drivers/net/ivshmem-net.c | 60 ++++++++++++++++++++++++----------------------- + 1 file changed, 31 insertions(+), 29 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index a535cb71adde..acd00e47acd7 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -36,6 +36,8 @@ + #define IVSHM_NET_STATE_READY 2 + #define IVSHM_NET_STATE_RUN 3 + ++#define IVSHM_NET_FLAG_RUN 0 ++ + #define IVSHM_NET_MTU_MIN 256 + #define IVSHM_NET_MTU_MAX 65535 + #define IVSHM_NET_MTU_DEF 16384 +@@ -96,6 +98,8 @@ struct ivshm_net { + u32 lstate; + u32 rstate; + ++ unsigned long flags; ++ + struct workqueue_struct *state_wq; + struct work_struct state_work; + +@@ -529,12 +533,32 @@ static void ivshm_net_run(struct net_device *ndev) + { + struct ivshm_net *in = netdev_priv(ndev); + ++ if (in->lstate < IVSHM_NET_STATE_READY) ++ return; ++ ++ if (!netif_running(ndev)) ++ return; ++ ++ if (test_and_set_bit(IVSHM_NET_FLAG_RUN, &in->flags)) ++ return; ++ + netif_start_queue(ndev); + napi_enable(&in->napi); + napi_schedule(&in->napi); + ivshm_net_set_state(in, IVSHM_NET_STATE_RUN); + } + ++static void ivshm_net_do_stop(struct net_device *ndev) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ ++ if (!test_and_clear_bit(IVSHM_NET_FLAG_RUN, &in->flags)) ++ return; ++ ++ netif_stop_queue(ndev); ++ napi_disable(&in->napi); ++} ++ + static void ivshm_net_state_change(struct work_struct *work) + { + struct ivshm_net *in = container_of(work, struct ivshm_net, state_work); +@@ -560,21 +584,13 @@ static void ivshm_net_state_change(struct work_struct *work) + break; + + case IVSHM_NET_STATE_READY: ++ case IVSHM_NET_STATE_RUN: + if (rstate >= IVSHM_NET_STATE_READY) { + netif_carrier_on(ndev); +- if (ndev->flags & IFF_UP) +- ivshm_net_run(ndev); ++ ivshm_net_run(ndev); + } else { + netif_carrier_off(ndev); +- ivshm_net_set_state(in, IVSHM_NET_STATE_RESET); +- } +- break; +- +- case IVSHM_NET_STATE_RUN: +- if (rstate < IVSHM_NET_STATE_READY) { +- netif_stop_queue(ndev); +- napi_disable(&in->napi); +- netif_carrier_off(ndev); ++ ivshm_net_do_stop(ndev); + ivshm_net_set_state(in, IVSHM_NET_STATE_RESET); + } + break; +@@ -584,18 +600,13 @@ static void ivshm_net_state_change(struct work_struct *work) + WRITE_ONCE(in->rstate, rstate); + } + +-static bool ivshm_net_check_state(struct net_device *ndev) ++static void ivshm_net_check_state(struct net_device *ndev) + { + struct ivshm_net *in = netdev_priv(ndev); + u32 rstate = readl(&in->ivshm_regs->rstate); + +- if (rstate != READ_ONCE(in->rstate) || +- in->lstate != IVSHM_NET_STATE_RUN) { ++ if (rstate != in->rstate || !test_bit(IVSHM_NET_FLAG_RUN, &in->flags)) + queue_work(in->state_wq, &in->state_work); +- return false; +- } +- +- return true; + } + + static irqreturn_t ivshm_net_int(int irq, void *data) +@@ -617,24 +628,15 @@ static int ivshm_net_open(struct net_device *ndev) + + netdev_reset_queue(ndev); + ndev->operstate = IF_OPER_UP; +- +- if (in->lstate == IVSHM_NET_STATE_READY) +- ivshm_net_run(ndev); ++ ivshm_net_run(ndev); + + return 0; + } + + static int ivshm_net_stop(struct net_device *ndev) + { +- struct ivshm_net *in = netdev_priv(ndev); +- + ndev->operstate = IF_OPER_DOWN; +- +- if (in->lstate == IVSHM_NET_STATE_RUN) { +- napi_disable(&in->napi); +- netif_stop_queue(ndev); +- ivshm_net_set_state(in, IVSHM_NET_STATE_READY); +- } ++ ivshm_net_do_stop(ndev); + + return 0; + } +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0016-ivshmem-net-Remove-unused-variable.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0016-ivshmem-net-Remove-unused-variable.patch new file mode 100644 index 00000000..dfaca493 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0016-ivshmem-net-Remove-unused-variable.patch @@ -0,0 +1,28 @@ +From 85362cf2e682d196fc3a88d05e21f0603cb0c48a Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Fri, 25 Nov 2016 17:31:51 +0100 +Subject: [PATCH 16/32] ivshmem-net: Remove unused variable + +Became unused by previous change. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index acd00e47acd7..ccef65d0f038 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -624,8 +624,6 @@ static irqreturn_t ivshm_net_int(int irq, void *data) + + static int ivshm_net_open(struct net_device *ndev) + { +- struct ivshm_net *in = netdev_priv(ndev); +- + netdev_reset_queue(ndev); + ndev->operstate = IF_OPER_UP; + ivshm_net_run(ndev); +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0017-ivshmem-net-Enable-INTx.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0017-ivshmem-net-Enable-INTx.patch new file mode 100644 index 00000000..e0f4be44 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0017-ivshmem-net-Enable-INTx.patch @@ -0,0 +1,55 @@ +From 9683ab979a373932e9c332d2db8115b6c23303d0 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 27 Nov 2016 15:15:51 +0100 +Subject: [PATCH 17/32] ivshmem-net: Enable INTx + +Activate INTx notification when it has to be used instead of MSI-X, +disable it after use. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index ccef65d0f038..591d04195e57 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -31,6 +31,8 @@ + #define JAILHOUSE_CFG_SHMEM_PTR 0x40 + #define JAILHOUSE_CFG_SHMEM_SZ 0x48 + ++#define IVSHMEM_INTX_ENABLE 0x1 ++ + #define IVSHM_NET_STATE_RESET 0 + #define IVSHM_NET_STATE_INIT 1 + #define IVSHM_NET_STATE_READY 2 +@@ -47,7 +49,7 @@ + #define IVSHM_NET_VQ_ALIGN 64 + + struct ivshmem_regs { +- u32 imask; ++ u32 intxctrl; + u32 istat; + u32 ivpos; + u32 doorbell; +@@ -869,6 +871,8 @@ static int ivshm_net_probe(struct pci_dev *pdev, + goto err_int; + + pci_set_master(pdev); ++ if (!in->using_msix) ++ writel(IVSHMEM_INTX_ENABLE, &in->ivshm_regs->intxctrl); + + writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate); + +@@ -895,6 +899,7 @@ static void ivshm_net_remove(struct pci_dev *pdev) + free_irq(in->msix.vector, ndev); + pci_disable_msix(pdev); + } else { ++ writel(0, &in->ivshm_regs->intxctrl); + free_irq(pdev->irq, ndev); + } + +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0018-ivshmem-net-Improve-identification-of-resources.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0018-ivshmem-net-Improve-identification-of-resources.patch new file mode 100644 index 00000000..e51b94aa --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0018-ivshmem-net-Improve-identification-of-resources.patch @@ -0,0 +1,59 @@ +From d60c7b69f68961c6868ca870d645ed7d4f73e751 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Wed, 21 Dec 2016 08:20:18 +0100 +Subject: [PATCH 18/32] ivshmem-net: Improve identification of resources + +Pass a device name consisting of driver name and PCI ID to request_irq +and alloc_ordered_workqueue. This helps correlating resources with +devices in case there are multiple of them. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 591d04195e57..cff6aa0be71d 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -762,6 +762,7 @@ static int ivshm_net_probe(struct pci_dev *pdev, + resource_size_t shmaddr; + resource_size_t shmlen; + int interrupt; ++ char *device_name; + void *shm; + u32 ivpos; + int err; +@@ -814,7 +815,10 @@ static int ivshm_net_probe(struct pci_dev *pdev, + return -EINVAL; + } + +- dev_info(&pdev->dev, "shared memory size %pa\n", &shmlen); ++ device_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s[%s]", DRV_NAME, ++ dev_name(&pdev->dev)); ++ if (!device_name) ++ return -ENOMEM; + + ndev = alloc_etherdev(sizeof(*in)); + if (!ndev) +@@ -837,7 +841,7 @@ static int ivshm_net_probe(struct pci_dev *pdev, + if (err) + goto err_free; + +- in->state_wq = alloc_ordered_workqueue(DRV_NAME, 0); ++ in->state_wq = alloc_ordered_workqueue(device_name, 0); + if (!in->state_wq) + goto err_free; + +@@ -866,7 +870,7 @@ static int ivshm_net_probe(struct pci_dev *pdev, + in->using_msix = false; + } + +- err = request_irq(interrupt, ivshm_net_int, 0, DRV_NAME, ndev); ++ err = request_irq(interrupt, ivshm_net_int, 0, device_name, ndev); + if (err) + goto err_int; + +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0019-ivshmem-net-Switch-to-reset-state-on-each-net-stop-a.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0019-ivshmem-net-Switch-to-reset-state-on-each-net-stop-a.patch new file mode 100644 index 00000000..512bcaf2 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0019-ivshmem-net-Switch-to-reset-state-on-each-net-stop-a.patch @@ -0,0 +1,47 @@ +From a16c80c305b2e11fe3efd0905bbe7db8388bf545 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 1 Jan 2017 15:43:37 +0100 +Subject: [PATCH 19/32] ivshmem-net: Switch to reset state on each net stop and + on driver removal + +Improves the state signaling to the remote side after ifconfig down and +driver removal. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index cff6aa0be71d..09484d652add 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -554,6 +554,8 @@ static void ivshm_net_do_stop(struct net_device *ndev) + { + struct ivshm_net *in = netdev_priv(ndev); + ++ ivshm_net_set_state(in, IVSHM_NET_STATE_RESET); ++ + if (!test_and_clear_bit(IVSHM_NET_FLAG_RUN, &in->flags)) + return; + +@@ -593,7 +595,6 @@ static void ivshm_net_state_change(struct work_struct *work) + } else { + netif_carrier_off(ndev); + ivshm_net_do_stop(ndev); +- ivshm_net_set_state(in, IVSHM_NET_STATE_RESET); + } + break; + } +@@ -899,6 +900,8 @@ static void ivshm_net_remove(struct pci_dev *pdev) + struct net_device *ndev = pci_get_drvdata(pdev); + struct ivshm_net *in = netdev_priv(ndev); + ++ writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate); ++ + if (in->using_msix) { + free_irq(in->msix.vector, ndev); + pci_disable_msix(pdev); +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0020-ivshmem-net-Add-ethtool-register-dump.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0020-ivshmem-net-Add-ethtool-register-dump.patch new file mode 100644 index 00000000..d0a562a7 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0020-ivshmem-net-Add-ethtool-register-dump.patch @@ -0,0 +1,61 @@ +From 98f68e69e2e950b44e7324bbcc94700705193443 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 1 Jan 2017 15:46:26 +0100 +Subject: [PATCH 20/32] ivshmem-net: Add ethtool register dump + +Helps debugging inconsistent states. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 09484d652add..c52727ef40c1 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -748,10 +748,41 @@ static void ivshm_net_get_ethtool_stats(struct net_device *ndev, + memset(&in->stats, 0, sizeof(in->stats)); + } + ++#define IVSHM_NET_REGS_LEN (3 * sizeof(u32) + 6 * sizeof(u16)) ++ ++static int ivshm_net_get_regs_len(struct net_device *ndev) ++{ ++ return IVSHM_NET_REGS_LEN; ++} ++ ++static void ivshm_net_get_regs(struct net_device *ndev, ++ struct ethtool_regs *regs, void *p) ++{ ++ struct ivshm_net *in = netdev_priv(ndev); ++ u32 *reg32 = p; ++ u16 *reg16; ++ ++ *reg32++ = in->lstate; ++ *reg32++ = in->rstate; ++ *reg32++ = in->qlen; ++ ++ reg16 = (u16 *)reg32; ++ ++ *reg16++ = in->tx.vr.avail ? in->tx.vr.avail->idx : 0; ++ *reg16++ = in->tx.vr.used ? in->tx.vr.used->idx : 0; ++ *reg16++ = in->tx.vr.avail ? vring_avail_event(&in->tx.vr) : 0; ++ ++ *reg16++ = in->rx.vr.avail ? in->rx.vr.avail->idx : 0; ++ *reg16++ = in->rx.vr.used ? in->rx.vr.used->idx : 0; ++ *reg16++ = in->rx.vr.avail ? vring_avail_event(&in->rx.vr) : 0; ++} ++ + static const struct ethtool_ops ivshm_net_ethtool_ops = { + .get_sset_count = ivshm_net_get_sset_count, + .get_strings = ivshm_net_get_strings, + .get_ethtool_stats = ivshm_net_get_ethtool_stats, ++ .get_regs_len = ivshm_net_get_regs_len, ++ .get_regs = ivshm_net_get_regs, + }; + + static int ivshm_net_probe(struct pci_dev *pdev, +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0021-ivshmem-net-Fix-stuck-state-machine-during-setup.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0021-ivshmem-net-Fix-stuck-state-machine-during-setup.patch new file mode 100644 index 00000000..4e40341e --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0021-ivshmem-net-Fix-stuck-state-machine-during-setup.patch @@ -0,0 +1,30 @@ +From b8d8821cfa8aa53aa29c0b230330afcd79ee7f60 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 1 Jan 2017 15:54:55 +0100 +Subject: [PATCH 21/32] ivshmem-net: Fix stuck state machine during setup + +If the remote side is already in INIT state (or even higher) and has a +cached rstate of RESET, we won't make progress when signaling RESET +again because the remote side won't send a state update. Fix this by +enforcing a local check after probe completion. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index c52727ef40c1..9f307ec4d677 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -911,6 +911,7 @@ static int ivshm_net_probe(struct pci_dev *pdev, + writel(IVSHMEM_INTX_ENABLE, &in->ivshm_regs->intxctrl); + + writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate); ++ ivshm_net_check_state(ndev); + + return 0; + +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0022-ivshmem-net-Switch-to-relative-descriptor-addresses.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0022-ivshmem-net-Switch-to-relative-descriptor-addresses.patch new file mode 100644 index 00000000..aca00e26 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0022-ivshmem-net-Switch-to-relative-descriptor-addresses.patch @@ -0,0 +1,49 @@ +From d1a0011e9857e105e38d9a0ea6fd7b8e7e6d8dc9 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Tue, 3 Jan 2017 08:50:01 +0100 +Subject: [PATCH 22/32] ivshmem-net: Switch to relative descriptor addresses + +Make sure that we do not depend on identity-mapped shared memory +regions. + +This also fixes an off-by-one in the range check of ivshm_net_desc_data. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 9f307ec4d677..0e770ca293a4 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -123,14 +123,14 @@ static void *ivshm_net_desc_data(struct ivshm_net *in, + struct vring_desc *desc, + u32 *len) + { +- u64 addr = READ_ONCE(desc->addr); ++ u64 offs = READ_ONCE(desc->addr); + u32 dlen = READ_ONCE(desc->len); + void *data; + +- if (addr < in->shmaddr || desc->addr > in->shmaddr + in->shmlen) ++ if (offs >= in->shmlen) + return NULL; + +- data = in->shm + (addr - in->shmaddr); ++ data = in->shm + offs; + + if (data < q->data || data >= q->end) + return NULL; +@@ -317,7 +317,7 @@ static int ivshm_net_tx_frame(struct net_device *ndev, struct sk_buff *skb) + buf = tx->data + head; + skb_copy_and_csum_dev(skb, buf); + +- desc->addr = in->shmaddr + (buf - in->shm); ++ desc->addr = buf - in->shm; + desc->len = skb->len; + + avail = tx->last_avail_idx++ & (vr->num - 1); +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0023-ivshmem-net-Switch-to-pci_alloc_irq_vectors.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0023-ivshmem-net-Switch-to-pci_alloc_irq_vectors.patch new file mode 100644 index 00000000..fcc2cac3 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0023-ivshmem-net-Switch-to-pci_alloc_irq_vectors.patch @@ -0,0 +1,146 @@ +From 77920ddb91fa49f7085875d29dd2a2c7e783af3a Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Tue, 23 May 2017 17:41:00 +0200 +Subject: [PATCH 23/32] ivshmem-net: Switch to pci_alloc_irq_vectors + +Required by 4.12, and it also simplifies our code. Needs to be folded +into the initial patch eventually. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 66 ++++++++++++++++++++--------------------------- + 1 file changed, 28 insertions(+), 38 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 0e770ca293a4..fd7d78b84576 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -114,8 +114,6 @@ struct ivshm_net { + u32 peer_id; + + struct pci_dev *pdev; +- struct msix_entry msix; +- bool using_msix; + }; + + static void *ivshm_net_desc_data(struct ivshm_net *in, +@@ -793,22 +791,21 @@ static int ivshm_net_probe(struct pci_dev *pdev, + struct ivshmem_regs __iomem *regs; + resource_size_t shmaddr; + resource_size_t shmlen; +- int interrupt; + char *device_name; + void *shm; + u32 ivpos; +- int err; ++ int ret; + +- err = pcim_enable_device(pdev); +- if (err) { +- dev_err(&pdev->dev, "pci_enable_device: %d\n", err); +- return err; ++ ret = pcim_enable_device(pdev); ++ if (ret) { ++ dev_err(&pdev->dev, "pci_enable_device: %d\n", ret); ++ return ret; + } + +- err = pcim_iomap_regions(pdev, BIT(0), DRV_NAME); +- if (err) { +- dev_err(&pdev->dev, "pcim_iomap_regions: %d\n", err); +- return err; ++ ret = pcim_iomap_regions(pdev, BIT(0), DRV_NAME); ++ if (ret) { ++ dev_err(&pdev->dev, "pcim_iomap_regions: %d\n", ret); ++ return ret; + } + + regs = pcim_iomap_table(pdev)[0]; +@@ -869,8 +866,8 @@ static int ivshm_net_probe(struct pci_dev *pdev, + spin_lock_init(&in->tx_free_lock); + spin_lock_init(&in->tx_clean_lock); + +- err = ivshm_net_calc_qsize(ndev); +- if (err) ++ ret = ivshm_net_calc_qsize(ndev); ++ if (ret) + goto err_free; + + in->state_wq = alloc_ordered_workqueue(device_name, 0); +@@ -889,25 +886,21 @@ static int ivshm_net_probe(struct pci_dev *pdev, + netif_carrier_off(ndev); + netif_napi_add(ndev, &in->napi, ivshm_net_poll, NAPI_POLL_WEIGHT); + +- err = register_netdev(ndev); +- if (err) ++ ret = register_netdev(ndev); ++ if (ret) + goto err_wq; + +- err = pci_enable_msix(pdev, &in->msix, 1); +- if (!err) { +- interrupt = in->msix.vector; +- in->using_msix = true; +- } else { +- interrupt = pdev->irq; +- in->using_msix = false; +- } ++ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY | PCI_IRQ_MSIX); ++ if (ret < 0) ++ goto err_alloc_irq; + +- err = request_irq(interrupt, ivshm_net_int, 0, device_name, ndev); +- if (err) +- goto err_int; ++ ret = request_irq(pci_irq_vector(pdev, 0), ivshm_net_int, 0, ++ device_name, ndev); ++ if (ret) ++ goto err_request_irq; + + pci_set_master(pdev); +- if (!in->using_msix) ++ if (!pdev->msix_enabled) + writel(IVSHMEM_INTX_ENABLE, &in->ivshm_regs->intxctrl); + + writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate); +@@ -915,16 +908,16 @@ static int ivshm_net_probe(struct pci_dev *pdev, + + return 0; + +-err_int: +- if (in->using_msix) +- pci_disable_msix(pdev); ++err_request_irq: ++ pci_free_irq_vectors(pdev); ++err_alloc_irq: + unregister_netdev(ndev); + err_wq: + destroy_workqueue(in->state_wq); + err_free: + free_netdev(ndev); + +- return err; ++ return ret; + } + + static void ivshm_net_remove(struct pci_dev *pdev) +@@ -934,13 +927,10 @@ static void ivshm_net_remove(struct pci_dev *pdev) + + writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate); + +- if (in->using_msix) { +- free_irq(in->msix.vector, ndev); +- pci_disable_msix(pdev); +- } else { ++ if (!pdev->msix_enabled) + writel(0, &in->ivshm_regs->intxctrl); +- free_irq(pdev->irq, ndev); +- } ++ free_irq(pci_irq_vector(pdev, 0), ndev); ++ pci_free_irq_vectors(pdev); + + unregister_netdev(ndev); + cancel_work_sync(&in->state_work); +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0024-ivshmem-net-fill-in-and-check-used-descriptor-chain-.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0024-ivshmem-net-fill-in-and-check-used-descriptor-chain-.patch new file mode 100644 index 00000000..7620d682 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0024-ivshmem-net-fill-in-and-check-used-descriptor-chain-.patch @@ -0,0 +1,70 @@ +From be71104c3d4d682f88a4e56e408683b2e8edaef5 Mon Sep 17 00:00:00 2001 +From: Henning Schild <henning.schild@siemens.com> +Date: Mon, 18 Sep 2017 18:02:08 +0200 +Subject: [PATCH 24/32] ivshmem-net: fill in and check used descriptor chain + len + +We are using chains of len==1 make that explicit and expect that from +the remote. + +Signed-off-by: Henning Schild <henning.schild@siemens.com> +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index fd7d78b84576..556670e779e7 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -335,10 +335,10 @@ static void ivshm_net_tx_clean(struct net_device *ndev) + { + struct ivshm_net *in = netdev_priv(ndev); + struct ivshm_net_queue *tx = &in->tx; ++ struct vring_used_elem *used; + struct vring *vr = &tx->vr; + struct vring_desc *desc; + struct vring_desc *fdesc; +- unsigned int used; + unsigned int num; + u16 used_idx; + u16 last; +@@ -358,13 +358,14 @@ static void ivshm_net_tx_clean(struct net_device *ndev) + u32 len; + u32 tail; + +- used = vr->used->ring[last & (vr->num - 1)].id; +- if (used >= vr->num) { +- netdev_err(ndev, "invalid tx used %d\n", used); ++ used = vr->used->ring + (last % vr->num); ++ if (used->id >= vr->num || used->len != 1) { ++ netdev_err(ndev, "invalid tx used->id %d ->len %d\n", ++ used->id, used->len); + break; + } + +- desc = &vr->desc[used]; ++ desc = &vr->desc[used->id]; + + data = ivshm_net_desc_data(in, &in->tx, desc, &len); + if (!data) { +@@ -383,7 +384,7 @@ static void ivshm_net_tx_clean(struct net_device *ndev) + else + desc->next = fhead; + +- fhead = used; ++ fhead = used->id; + last++; + num++; + } +@@ -433,6 +434,7 @@ static void ivshm_net_rx_finish(struct ivshm_net *in, struct vring_desc *desc) + + used = rx->last_used_idx++ & (vr->num - 1); + vr->used->ring[used].id = desc_id; ++ vr->used->ring[used].len = 1; + + virt_store_release(&vr->used->idx, rx->last_used_idx); + } +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0025-ivshmem-net-slightly-improve-debug-output.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0025-ivshmem-net-slightly-improve-debug-output.patch new file mode 100644 index 00000000..cc20c2fd --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0025-ivshmem-net-slightly-improve-debug-output.patch @@ -0,0 +1,29 @@ +From 5776a8083d73bd137a74ab33f0f7652a2c6ee83a Mon Sep 17 00:00:00 2001 +From: Henning Schild <henning.schild@siemens.com> +Date: Mon, 18 Sep 2017 18:02:10 +0200 +Subject: [PATCH 25/32] ivshmem-net: slightly improve debug output + +There where two lines with the same error message, change one of them. + +Signed-off-by: Henning Schild <henning.schild@siemens.com> +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 556670e779e7..abc50553e644 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -369,7 +369,7 @@ static void ivshm_net_tx_clean(struct net_device *ndev) + + data = ivshm_net_desc_data(in, &in->tx, desc, &len); + if (!data) { +- netdev_err(ndev, "bad tx descriptor\n"); ++ netdev_err(ndev, "bad tx descriptor, data == NULL\n"); + break; + } + +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0026-ivshmem-net-set-and-check-descriptor-flags.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0026-ivshmem-net-set-and-check-descriptor-flags.patch new file mode 100644 index 00000000..a7d7ab24 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0026-ivshmem-net-set-and-check-descriptor-flags.patch @@ -0,0 +1,43 @@ +From 6b095510765e054c4ee641f115ab72798d97ac21 Mon Sep 17 00:00:00 2001 +From: Henning Schild <henning.schild@siemens.com> +Date: Mon, 18 Sep 2017 18:02:11 +0200 +Subject: [PATCH 26/32] ivshmem-net: set and check descriptor flags + +We do not support the use of any flags. Make sure the remote does not +confuse us using flags. + +Signed-off-by: Henning Schild <henning.schild@siemens.com> +[Jan: Remove wrong removal of next field initialization] +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index abc50553e644..9ecf1d0f0d2d 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -123,8 +123,12 @@ static void *ivshm_net_desc_data(struct ivshm_net *in, + { + u64 offs = READ_ONCE(desc->addr); + u32 dlen = READ_ONCE(desc->len); ++ u16 flags = READ_ONCE(desc->flags); + void *data; + ++ if (flags) ++ return NULL; ++ + if (offs >= in->shmlen) + return NULL; + +@@ -317,6 +321,7 @@ static int ivshm_net_tx_frame(struct net_device *ndev, struct sk_buff *skb) + + desc->addr = buf - in->shm; + desc->len = skb->len; ++ desc->flags = 0; + + avail = tx->last_avail_idx++ & (vr->num - 1); + vr->avail->ring[avail] = desc_idx; +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0027-ivshmem-net-add-MAC-changing-interface.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0027-ivshmem-net-add-MAC-changing-interface.patch new file mode 100644 index 00000000..61172afd --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0027-ivshmem-net-add-MAC-changing-interface.patch @@ -0,0 +1,41 @@ +From 73b98d39ceacd025ae4aaff1b2cbb537e852a03e Mon Sep 17 00:00:00 2001 +From: Henning Schild <henning.schild@siemens.com> +Date: Wed, 27 Sep 2017 12:59:49 +0200 +Subject: [PATCH 27/32] ivshmem-net: add MAC changing interface + +Allow ifconfig, ip and other such tools to change the MAC of the +virtual NIC. + +Signed-off-by: Henning Schild <henning.schild@siemens.com> +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 9ecf1d0f0d2d..712dde0ee6f9 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -685,12 +685,14 @@ static void ivshm_net_poll_controller(struct net_device *ndev) + #endif + + static const struct net_device_ops ivshm_net_ops = { +- .ndo_open = ivshm_net_open, +- .ndo_stop = ivshm_net_stop, +- .ndo_start_xmit = ivshm_net_xmit, +- .ndo_change_mtu = ivshm_net_change_mtu, ++ .ndo_open = ivshm_net_open, ++ .ndo_stop = ivshm_net_stop, ++ .ndo_start_xmit = ivshm_net_xmit, ++ .ndo_change_mtu = ivshm_net_change_mtu, ++ .ndo_set_mac_address = eth_mac_addr, ++ .ndo_validate_addr = eth_validate_addr, + #ifdef CONFIG_NET_POLL_CONTROLLER +- .ndo_poll_controller = ivshm_net_poll_controller, ++ .ndo_poll_controller = ivshm_net_poll_controller, + #endif + }; + +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0028-ivshmem-net-Silence-compiler-warning.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0028-ivshmem-net-Silence-compiler-warning.patch new file mode 100644 index 00000000..6a1c212f --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0028-ivshmem-net-Silence-compiler-warning.patch @@ -0,0 +1,28 @@ +From fbefa0a6dcc6011aef4444c771f300c40fca30f1 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Tue, 3 Oct 2017 12:24:59 +0200 +Subject: [PATCH 28/32] ivshmem-net: Silence compiler warning + +At least Linaro's gcc 6.3 does not see the initialization and usage +dependency of fhead and num. Let's silence this false positive. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 712dde0ee6f9..6fa7a6c81bf1 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -356,6 +356,7 @@ static void ivshm_net_tx_clean(struct net_device *ndev) + last = tx->last_used_idx; + + fdesc = NULL; ++ fhead = 0; + num = 0; + + while (last != used_idx) { +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0029-ivshmem-net-Fix-bogus-transition-to-RESET-state.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0029-ivshmem-net-Fix-bogus-transition-to-RESET-state.patch new file mode 100644 index 00000000..335c6bdb --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0029-ivshmem-net-Fix-bogus-transition-to-RESET-state.patch @@ -0,0 +1,31 @@ +From 1a0998da61deead1dbb38393fedaefee69f59044 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 4 Mar 2018 13:16:04 +0100 +Subject: [PATCH 29/32] ivshmem-net: Fix bogus transition to RESET state + +If we are in READY but the remote is still in INIT, we so far fell back +to RESET which caused the setup to get stuck. Fix this by only +transitioning from READY/RUN to RESET in ivshm_net_state_change if the +remote is in RESET as well. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 6fa7a6c81bf1..0c503194b4ec 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -598,7 +598,7 @@ static void ivshm_net_state_change(struct work_struct *work) + if (rstate >= IVSHM_NET_STATE_READY) { + netif_carrier_on(ndev); + ivshm_net_run(ndev); +- } else { ++ } else if (rstate == IVSHM_NET_STATE_RESET) { + netif_carrier_off(ndev); + ivshm_net_do_stop(ndev); + } +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0030-ivshmem-net-Refactor-and-comment-ivshm_net_state_cha.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0030-ivshmem-net-Refactor-and-comment-ivshm_net_state_cha.patch new file mode 100644 index 00000000..42ca05a0 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0030-ivshmem-net-Refactor-and-comment-ivshm_net_state_cha.patch @@ -0,0 +1,68 @@ +From a3ee1ba8e4948ac4e6e4eae3061b72b3bf867122 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 4 Mar 2018 13:50:24 +0100 +Subject: [PATCH 30/32] ivshmem-net: Refactor and comment + ivshm_net_state_change + +This should make the state transitioning logic clearer. Also avoid the +harmless but redundant netif_carrier_on/ivshm_net_run in RUN state. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 0c503194b4ec..aba77c232c48 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -575,14 +575,21 @@ static void ivshm_net_state_change(struct work_struct *work) + struct net_device *ndev = in->napi.dev; + u32 rstate = readl(&in->ivshm_regs->rstate); + +- + switch (in->lstate) { + case IVSHM_NET_STATE_RESET: ++ /* ++ * Wait for the remote to leave READY/RUN before transitioning ++ * to INIT. ++ */ + if (rstate < IVSHM_NET_STATE_READY) + ivshm_net_set_state(in, IVSHM_NET_STATE_INIT); + break; + + case IVSHM_NET_STATE_INIT: ++ /* ++ * Wait for the remote to leave RESET before performing the ++ * initialization and moving to READY. ++ */ + if (rstate > IVSHM_NET_STATE_RESET) { + ivshm_net_init_queues(ndev); + ivshm_net_set_state(in, IVSHM_NET_STATE_READY); +@@ -594,11 +601,21 @@ static void ivshm_net_state_change(struct work_struct *work) + break; + + case IVSHM_NET_STATE_READY: +- case IVSHM_NET_STATE_RUN: ++ /* ++ * Link is up and we are running once the remote is in READY or ++ * RUN. ++ */ + if (rstate >= IVSHM_NET_STATE_READY) { + netif_carrier_on(ndev); + ivshm_net_run(ndev); +- } else if (rstate == IVSHM_NET_STATE_RESET) { ++ break; ++ } ++ /* fall through */ ++ case IVSHM_NET_STATE_RUN: ++ /* ++ * If the remote goes to RESET, we need to follow immediately. ++ */ ++ if (rstate == IVSHM_NET_STATE_RESET) { + netif_carrier_off(ndev); + ivshm_net_do_stop(ndev); + } +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0031-ivshmem-net-Switch-to-netdev_xmit_more-helper.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0031-ivshmem-net-Switch-to-netdev_xmit_more-helper.patch new file mode 100644 index 00000000..bedbc59f --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0031-ivshmem-net-Switch-to-netdev_xmit_more-helper.patch @@ -0,0 +1,59 @@ +From 6c86f9ef9fa5029b8f87867f47fe51d6cc1960a5 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Sun, 2 Jun 2019 11:58:20 +0200 +Subject: [PATCH 31/32] ivshmem-net: Switch to netdev_xmit_more helper + +The skb field has been removed by 4f296edeb9d4. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index aba77c232c48..9946cef63c1f 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -294,7 +294,8 @@ static u32 ivshm_net_tx_advance(struct ivshm_net_queue *q, u32 *pos, u32 len) + return p; + } + +-static int ivshm_net_tx_frame(struct net_device *ndev, struct sk_buff *skb) ++static int ivshm_net_tx_frame(struct net_device *ndev, struct sk_buff *skb, ++ bool xmit_more) + { + struct ivshm_net *in = netdev_priv(ndev); + struct ivshm_net_queue *tx = &in->tx; +@@ -327,7 +328,7 @@ static int ivshm_net_tx_frame(struct net_device *ndev, struct sk_buff *skb) + vr->avail->ring[avail] = desc_idx; + tx->num_added++; + +- if (!skb->xmit_more) { ++ if (!xmit_more) { + virt_store_release(&vr->avail->idx, tx->last_avail_idx); + ivshm_net_notify_tx(in, tx->num_added); + tx->num_added = 0; +@@ -509,17 +510,18 @@ static int ivshm_net_poll(struct napi_struct *napi, int budget) + static netdev_tx_t ivshm_net_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct ivshm_net *in = netdev_priv(ndev); ++ bool xmit_more = netdev_xmit_more(); + + ivshm_net_tx_clean(ndev); + + if (!ivshm_net_tx_ok(in, ndev->mtu)) { + ivshm_net_enable_tx_irq(in); + netif_stop_queue(ndev); +- skb->xmit_more = 0; ++ xmit_more = false; + in->stats.tx_pause++; + } + +- ivshm_net_tx_frame(ndev, skb); ++ ivshm_net_tx_frame(ndev, skb, xmit_more); + + in->stats.tx_packets++; + ndev->stats.tx_packets++; +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0032-ivshmem-net-Adjust-to-reworked-version-of-ivshmem-in.patch b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0032-ivshmem-net-Adjust-to-reworked-version-of-ivshmem-in.patch new file mode 100644 index 00000000..dc10cd2f --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/0032-ivshmem-net-Adjust-to-reworked-version-of-ivshmem-in.patch @@ -0,0 +1,650 @@ +From 9caa6a8cab0d7f46475990aaeb7dcc7721547ef0 Mon Sep 17 00:00:00 2001 +From: Jan Kiszka <jan.kiszka@siemens.com> +Date: Mon, 5 Dec 2016 15:43:53 +0100 +Subject: [PATCH 32/32] ivshmem-net: Adjust to reworked version of ivshmem in + Jailhouse + +This contains the changes required to work with the new revision of +ivshmem in Jailhouse, namely: + +- changed PCI vendor and device ID +- vendor capability to communicate region location +- new MMIO register layout +- common interrupt control register +- state table support, removal of rstate register +- unidirectional shared memory regions +- vector value has to be written to doorbell register +- support for multiple vectors, used to split config from tx-rx + +Note: Specification work for the interface is ongoing, so details may +still change. + +Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> +--- + drivers/net/ivshmem-net.c | 335 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 223 insertions(+), 112 deletions(-) + +diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c +index 9946cef63c1f..18d5a15dbec2 100644 +--- a/drivers/net/ivshmem-net.c ++++ b/drivers/net/ivshmem-net.c +@@ -1,5 +1,6 @@ + /* + * Copyright 2016 Mans Rullgard <mans@mansr.com> ++ * Copyright (c) Siemens AG, 2016-2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -15,6 +16,7 @@ + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + ++#include <linux/ivshmem.h> + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/pci.h> +@@ -28,34 +30,28 @@ + + #define DRV_NAME "ivshmem-net" + +-#define JAILHOUSE_CFG_SHMEM_PTR 0x40 +-#define JAILHOUSE_CFG_SHMEM_SZ 0x48 ++#define IVSHM_NET_STATE_RESET 0 ++#define IVSHM_NET_STATE_INIT 1 ++#define IVSHM_NET_STATE_READY 2 ++#define IVSHM_NET_STATE_RUN 3 + +-#define IVSHMEM_INTX_ENABLE 0x1 ++#define IVSHM_NET_FLAG_RUN 0 + +-#define IVSHM_NET_STATE_RESET 0 +-#define IVSHM_NET_STATE_INIT 1 +-#define IVSHM_NET_STATE_READY 2 +-#define IVSHM_NET_STATE_RUN 3 +- +-#define IVSHM_NET_FLAG_RUN 0 +- +-#define IVSHM_NET_MTU_MIN 256 +-#define IVSHM_NET_MTU_MAX 65535 +-#define IVSHM_NET_MTU_DEF 16384 ++#define IVSHM_NET_MTU_MIN 256 ++#define IVSHM_NET_MTU_MAX 65535 ++#define IVSHM_NET_MTU_DEF 16384 + + #define IVSHM_NET_FRAME_SIZE(s) ALIGN(18 + (s), SMP_CACHE_BYTES) + + #define IVSHM_NET_VQ_ALIGN 64 + +-struct ivshmem_regs { +- u32 intxctrl; +- u32 istat; +- u32 ivpos; +- u32 doorbell; +- u32 lstate; +- u32 rstate; +-}; ++#define IVSHM_NET_SECTION_TX 0 ++#define IVSHM_NET_SECTION_RX 1 ++ ++#define IVSHM_NET_MSIX_STATE 0 ++#define IVSHM_NET_MSIX_TX_RX 1 ++ ++#define IVSHM_NET_NUM_VECTORS 2 + + struct ivshm_net_queue { + struct vring vr; +@@ -73,7 +69,7 @@ struct ivshm_net_queue { + }; + + struct ivshm_net_stats { +- u32 interrupts; ++ u32 tx_rx_interrupts; + u32 tx_packets; + u32 tx_notify; + u32 tx_pause; +@@ -97,8 +93,9 @@ struct ivshm_net { + + struct napi_struct napi; + +- u32 lstate; +- u32 rstate; ++ u32 state; ++ u32 last_peer_state; ++ u32 *state_table; + + unsigned long flags; + +@@ -107,17 +104,19 @@ struct ivshm_net { + + struct ivshm_net_stats stats; + +- struct ivshmem_regs __iomem *ivshm_regs; +- void *shm; +- phys_addr_t shmaddr; ++ struct ivshm_regs __iomem *ivshm_regs; ++ void *shm[2]; + resource_size_t shmlen; + u32 peer_id; + ++ u32 tx_rx_vector; ++ + struct pci_dev *pdev; + }; + + static void *ivshm_net_desc_data(struct ivshm_net *in, + struct ivshm_net_queue *q, ++ unsigned int region, + struct vring_desc *desc, + u32 *len) + { +@@ -132,7 +131,7 @@ static void *ivshm_net_desc_data(struct ivshm_net *in, + if (offs >= in->shmlen) + return NULL; + +- data = in->shm + offs; ++ data = in->shm[region] + offs; + + if (data < q->data || data >= q->end) + return NULL; +@@ -160,18 +159,17 @@ static void ivshm_net_init_queue(struct ivshm_net *in, + static void ivshm_net_init_queues(struct net_device *ndev) + { + struct ivshm_net *in = netdev_priv(ndev); +- int ivpos = readl(&in->ivshm_regs->ivpos); + void *tx; + void *rx; + int i; + +- tx = in->shm + ivpos * in->shmlen / 2; +- rx = in->shm + !ivpos * in->shmlen / 2; ++ tx = in->shm[IVSHM_NET_SECTION_TX]; ++ rx = in->shm[IVSHM_NET_SECTION_RX]; + +- memset(tx, 0, in->shmlen / 2); ++ memset(tx, 0, in->shmlen); + +- ivshm_net_init_queue(in, &in->rx, rx, in->qlen); + ivshm_net_init_queue(in, &in->tx, tx, in->qlen); ++ ivshm_net_init_queue(in, &in->rx, rx, in->qlen); + + swap(in->rx.vr.used, in->tx.vr.used); + +@@ -191,14 +189,14 @@ static int ivshm_net_calc_qsize(struct net_device *ndev) + for (qlen = 4096; qlen > 32; qlen >>= 1) { + vrsize = vring_size(qlen, IVSHM_NET_VQ_ALIGN); + vrsize = ALIGN(vrsize, IVSHM_NET_VQ_ALIGN); +- if (vrsize < in->shmlen / 16) ++ if (vrsize < in->shmlen / 8) + break; + } + +- if (vrsize > in->shmlen / 2) ++ if (vrsize > in->shmlen) + return -EINVAL; + +- qsize = in->shmlen / 2 - vrsize; ++ qsize = in->shmlen - vrsize; + + if (qsize < 4 * IVSHM_NET_MTU_MIN) + return -EINVAL; +@@ -221,7 +219,8 @@ static void ivshm_net_notify_tx(struct ivshm_net *in, unsigned int num) + new = in->tx.last_avail_idx; + + if (vring_need_event(evt, new, old)) { +- writel(in->peer_id << 16, &in->ivshm_regs->doorbell); ++ writel(in->tx_rx_vector | (in->peer_id << 16), ++ &in->ivshm_regs->doorbell); + in->stats.tx_notify++; + } + } +@@ -243,7 +242,8 @@ static void ivshm_net_notify_rx(struct ivshm_net *in, unsigned int num) + new = in->rx.last_used_idx; + + if (vring_need_event(evt, new, old)) { +- writel(in->peer_id << 16, &in->ivshm_regs->doorbell); ++ writel(in->tx_rx_vector | (in->peer_id << 16), ++ &in->ivshm_regs->doorbell); + in->stats.rx_notify++; + } + } +@@ -320,7 +320,7 @@ static int ivshm_net_tx_frame(struct net_device *ndev, struct sk_buff *skb, + buf = tx->data + head; + skb_copy_and_csum_dev(skb, buf); + +- desc->addr = buf - in->shm; ++ desc->addr = buf - in->shm[IVSHM_NET_SECTION_TX]; + desc->len = skb->len; + desc->flags = 0; + +@@ -374,7 +374,8 @@ static void ivshm_net_tx_clean(struct net_device *ndev) + + desc = &vr->desc[used->id]; + +- data = ivshm_net_desc_data(in, &in->tx, desc, &len); ++ data = ivshm_net_desc_data(in, &in->tx, IVSHM_NET_SECTION_TX, ++ desc, &len); + if (!data) { + netdev_err(ndev, "bad tx descriptor, data == NULL\n"); + break; +@@ -466,7 +467,8 @@ static int ivshm_net_poll(struct napi_struct *napi, int budget) + if (!desc) + break; + +- data = ivshm_net_desc_data(in, &in->rx, desc, &len); ++ data = ivshm_net_desc_data(in, &in->rx, IVSHM_NET_SECTION_RX, ++ desc, &len); + if (!data) { + netdev_err(ndev, "bad rx descriptor\n"); + break; +@@ -535,15 +537,15 @@ static netdev_tx_t ivshm_net_xmit(struct sk_buff *skb, struct net_device *ndev) + static void ivshm_net_set_state(struct ivshm_net *in, u32 state) + { + virt_wmb(); +- WRITE_ONCE(in->lstate, state); +- writel(state, &in->ivshm_regs->lstate); ++ WRITE_ONCE(in->state, state); ++ writel(state, &in->ivshm_regs->state); + } + + static void ivshm_net_run(struct net_device *ndev) + { + struct ivshm_net *in = netdev_priv(ndev); + +- if (in->lstate < IVSHM_NET_STATE_READY) ++ if (in->state < IVSHM_NET_STATE_READY) + return; + + if (!netif_running(ndev)) +@@ -575,15 +577,15 @@ static void ivshm_net_state_change(struct work_struct *work) + { + struct ivshm_net *in = container_of(work, struct ivshm_net, state_work); + struct net_device *ndev = in->napi.dev; +- u32 rstate = readl(&in->ivshm_regs->rstate); ++ u32 peer_state = READ_ONCE(in->state_table[in->peer_id]); + +- switch (in->lstate) { ++ switch (in->state) { + case IVSHM_NET_STATE_RESET: + /* + * Wait for the remote to leave READY/RUN before transitioning + * to INIT. + */ +- if (rstate < IVSHM_NET_STATE_READY) ++ if (peer_state < IVSHM_NET_STATE_READY) + ivshm_net_set_state(in, IVSHM_NET_STATE_INIT); + break; + +@@ -592,7 +594,7 @@ static void ivshm_net_state_change(struct work_struct *work) + * Wait for the remote to leave RESET before performing the + * initialization and moving to READY. + */ +- if (rstate > IVSHM_NET_STATE_RESET) { ++ if (peer_state > IVSHM_NET_STATE_RESET) { + ivshm_net_init_queues(ndev); + ivshm_net_set_state(in, IVSHM_NET_STATE_READY); + +@@ -607,7 +609,7 @@ static void ivshm_net_state_change(struct work_struct *work) + * Link is up and we are running once the remote is in READY or + * RUN. + */ +- if (rstate >= IVSHM_NET_STATE_READY) { ++ if (peer_state >= IVSHM_NET_STATE_READY) { + netif_carrier_on(ndev); + ivshm_net_run(ndev); + break; +@@ -617,7 +619,7 @@ static void ivshm_net_state_change(struct work_struct *work) + /* + * If the remote goes to RESET, we need to follow immediately. + */ +- if (rstate == IVSHM_NET_STATE_RESET) { ++ if (peer_state == IVSHM_NET_STATE_RESET) { + netif_carrier_off(ndev); + ivshm_net_do_stop(ndev); + } +@@ -625,31 +627,44 @@ static void ivshm_net_state_change(struct work_struct *work) + } + + virt_wmb(); +- WRITE_ONCE(in->rstate, rstate); ++ WRITE_ONCE(in->last_peer_state, peer_state); + } + +-static void ivshm_net_check_state(struct net_device *ndev) ++static void ivshm_net_check_state(struct ivshm_net *in) + { +- struct ivshm_net *in = netdev_priv(ndev); +- u32 rstate = readl(&in->ivshm_regs->rstate); +- +- if (rstate != in->rstate || !test_bit(IVSHM_NET_FLAG_RUN, &in->flags)) ++ if (in->state_table[in->peer_id] != in->last_peer_state || ++ !test_bit(IVSHM_NET_FLAG_RUN, &in->flags)) + queue_work(in->state_wq, &in->state_work); + } + +-static irqreturn_t ivshm_net_int(int irq, void *data) ++static irqreturn_t ivshm_net_int_state(int irq, void *data) + { +- struct net_device *ndev = data; +- struct ivshm_net *in = netdev_priv(ndev); ++ struct ivshm_net *in = data; ++ ++ ivshm_net_check_state(in); ++ ++ return IRQ_HANDLED; ++} + +- in->stats.interrupts++; ++static irqreturn_t ivshm_net_int_tx_rx(int irq, void *data) ++{ ++ struct ivshm_net *in = data; ++ ++ in->stats.tx_rx_interrupts++; + +- ivshm_net_check_state(ndev); + napi_schedule_irqoff(&in->napi); + + return IRQ_HANDLED; + } + ++static irqreturn_t ivshm_net_intx(int irq, void *data) ++{ ++ ivshm_net_int_state(irq, data); ++ ivshm_net_int_tx_rx(irq, data); ++ ++ return IRQ_HANDLED; ++} ++ + static int ivshm_net_open(struct net_device *ndev) + { + netdev_reset_queue(ndev); +@@ -717,7 +732,7 @@ static const struct net_device_ops ivshm_net_ops = { + }; + + static const char ivshm_net_stats[][ETH_GSTRING_LEN] = { +- "interrupts", ++ "tx_rx_interrupts", + "tx_packets", + "tx_notify", + "tx_pause", +@@ -760,7 +775,7 @@ static void ivshm_net_get_ethtool_stats(struct net_device *ndev, + unsigned int n = 0; + unsigned int i; + +- st[n++] = in->stats.interrupts; ++ st[n++] = in->stats.tx_rx_interrupts; + st[n++] = in->stats.tx_packets; + st[n++] = in->stats.tx_notify; + st[n++] = in->stats.tx_pause; +@@ -789,8 +804,8 @@ static void ivshm_net_get_regs(struct net_device *ndev, + u32 *reg32 = p; + u16 *reg16; + +- *reg32++ = in->lstate; +- *reg32++ = in->rstate; ++ *reg32++ = in->state; ++ *reg32++ = in->last_peer_state; + *reg32++ = in->qlen; + + reg16 = (u16 *)reg32; +@@ -812,17 +827,28 @@ static const struct ethtool_ops ivshm_net_ethtool_ops = { + .get_regs = ivshm_net_get_regs, + }; + ++static u64 get_config_qword(struct pci_dev *pdev, unsigned int pos) ++{ ++ u32 lo, hi; ++ ++ pci_read_config_dword(pdev, pos, &lo); ++ pci_read_config_dword(pdev, pos + 4, &hi); ++ return lo | ((u64)hi << 32); ++} ++ + static int ivshm_net_probe(struct pci_dev *pdev, +- const struct pci_device_id *id) ++ const struct pci_device_id *pci_id) + { ++ phys_addr_t output_sections_addr, section_addr; ++ resource_size_t section_sz, output_section_sz; ++ void *state_table, *output_sections; ++ struct ivshm_regs __iomem *regs; + struct net_device *ndev; + struct ivshm_net *in; +- struct ivshmem_regs __iomem *regs; +- resource_size_t shmaddr; +- resource_size_t shmlen; ++ unsigned int cap_pos; + char *device_name; +- void *shm; +- u32 ivpos; ++ int vendor_cap; ++ u32 id, dword; + int ret; + + ret = pcim_enable_device(pdev); +@@ -839,40 +865,75 @@ static int ivshm_net_probe(struct pci_dev *pdev, + + regs = pcim_iomap_table(pdev)[0]; + +- shmlen = pci_resource_len(pdev, 2); ++ id = readl(®s->id); ++ if (id > 1) { ++ dev_err(&pdev->dev, "invalid ID %d\n", id); ++ return -EINVAL; ++ } ++ if (readl(®s->max_peers) > 2) { ++ dev_err(&pdev->dev, "only 2 peers supported\n"); ++ return -EINVAL; ++ } ++ ++ vendor_cap = pci_find_capability(pdev, PCI_CAP_ID_VNDR); ++ if (vendor_cap < 0) { ++ dev_err(&pdev->dev, "missing vendor capability\n"); ++ return -EINVAL; ++ } + +- if (shmlen) { +- shmaddr = pci_resource_start(pdev, 2); ++ if (pci_resource_len(pdev, 2) > 0) { ++ section_addr = pci_resource_start(pdev, 2); + } else { +- union { u64 v; u32 hl[2]; } val; +- +- pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_PTR, +- &val.hl[0]); +- pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_PTR + 4, +- &val.hl[1]); +- shmaddr = val.v; +- +- pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_SZ, +- &val.hl[0]); +- pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_SZ + 4, +- &val.hl[1]); +- shmlen = val.v; ++ cap_pos = vendor_cap + IVSHM_CFG_ADDRESS; ++ section_addr = get_config_qword(pdev, cap_pos); + } + ++ cap_pos = vendor_cap + IVSHM_CFG_STATE_TAB_SZ; ++ pci_read_config_dword(pdev, cap_pos, &dword); ++ section_sz = dword; + +- if (!devm_request_mem_region(&pdev->dev, shmaddr, shmlen, DRV_NAME)) ++ if (!devm_request_mem_region(&pdev->dev, section_addr, section_sz, ++ DRV_NAME)) + return -EBUSY; + +- shm = devm_memremap(&pdev->dev, shmaddr, shmlen, MEMREMAP_WB); +- if (!shm) ++ state_table = devm_memremap(&pdev->dev, section_addr, section_sz, ++ MEMREMAP_WB); ++ if (!state_table) + return -ENOMEM; + +- ivpos = readl(®s->ivpos); +- if (ivpos > 1) { +- dev_err(&pdev->dev, "invalid IVPosition %d\n", ivpos); ++ output_sections_addr = section_addr + section_sz; ++ ++ cap_pos = vendor_cap + IVSHM_CFG_RW_SECTION_SZ; ++ section_sz = get_config_qword(pdev, cap_pos); ++ if (section_sz > 0) { ++ dev_info(&pdev->dev, "R/W section detected - " ++ "unused by this driver version\n"); ++ output_sections_addr += section_sz; ++ } ++ ++ cap_pos = vendor_cap + IVSHM_CFG_OUTPUT_SECTION_SZ; ++ output_section_sz = get_config_qword(pdev, cap_pos); ++ if (output_section_sz == 0) { ++ dev_err(&pdev->dev, "Missing input/output sections\n"); + return -EINVAL; + } + ++ if (!devm_request_mem_region(&pdev->dev, output_sections_addr, ++ output_section_sz * 2, DRV_NAME)) ++ return -EBUSY; ++ ++ output_sections = devm_memremap(&pdev->dev, output_sections_addr, ++ output_section_sz * 2, MEMREMAP_WB); ++ if (!output_sections) ++ return -ENOMEM; ++ ++ section_addr = output_sections_addr + output_section_sz * id; ++ dev_info(&pdev->dev, "TX memory at %pa, size %pa\n", ++ §ion_addr, &output_section_sz); ++ section_addr = output_sections_addr + output_section_sz * !id; ++ dev_info(&pdev->dev, "RX memory at %pa, size %pa\n", ++ §ion_addr, &output_section_sz); ++ + device_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s[%s]", DRV_NAME, + dev_name(&pdev->dev)); + if (!device_name) +@@ -887,10 +948,16 @@ static int ivshm_net_probe(struct pci_dev *pdev, + + in = netdev_priv(ndev); + in->ivshm_regs = regs; +- in->shm = shm; +- in->shmaddr = shmaddr; +- in->shmlen = shmlen; +- in->peer_id = !ivpos; ++ in->state_table = state_table; ++ ++ in->shm[IVSHM_NET_SECTION_TX] = ++ output_sections + output_section_sz * id; ++ in->shm[IVSHM_NET_SECTION_RX] = ++ output_sections + output_section_sz * !id; ++ ++ in->shmlen = output_section_sz; ++ ++ in->peer_id = !id; + in->pdev = pdev; + spin_lock_init(&in->tx_free_lock); + spin_lock_init(&in->tx_clean_lock); +@@ -919,24 +986,64 @@ static int ivshm_net_probe(struct pci_dev *pdev, + if (ret) + goto err_wq; + +- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY | PCI_IRQ_MSIX); ++ ret = pci_alloc_irq_vectors(pdev, 1, 2, PCI_IRQ_LEGACY | PCI_IRQ_MSIX); + if (ret < 0) + goto err_alloc_irq; + +- ret = request_irq(pci_irq_vector(pdev, 0), ivshm_net_int, 0, +- device_name, ndev); +- if (ret) +- goto err_request_irq; ++ if (pdev->msix_enabled) { ++ if (ret != 2) { ++ ret = -EBUSY; ++ goto err_request_irq; ++ } ++ ++ device_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "%s-state[%s]", DRV_NAME, ++ dev_name(&pdev->dev)); ++ if (!device_name) { ++ ret = -ENOMEM; ++ goto err_request_irq; ++ } ++ ++ ret = request_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_STATE), ++ ivshm_net_int_state, 0, device_name, in); ++ if (ret) ++ goto err_request_irq; ++ ++ device_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "%s-tx-rx[%s]", DRV_NAME, ++ dev_name(&pdev->dev)); ++ if (!device_name) { ++ ret = -ENOMEM; ++ goto err_request_irq2; ++ } ++ ++ ret = request_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_TX_RX), ++ ivshm_net_int_tx_rx, 0, device_name, in); ++ if (ret) ++ goto err_request_irq2; ++ ++ in->tx_rx_vector = IVSHM_NET_MSIX_TX_RX; ++ } else { ++ ret = request_irq(pci_irq_vector(pdev, 0), ivshm_net_intx, 0, ++ device_name, in); ++ if (ret) ++ goto err_request_irq; ++ ++ in->tx_rx_vector = 0; ++ } + + pci_set_master(pdev); +- if (!pdev->msix_enabled) +- writel(IVSHMEM_INTX_ENABLE, &in->ivshm_regs->intxctrl); + +- writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate); +- ivshm_net_check_state(ndev); ++ pci_write_config_byte(pdev, vendor_cap + IVSHM_CFG_PRIV_CNTL, 0); ++ writel(IVSHM_INT_ENABLE, &in->ivshm_regs->int_control); ++ ++ writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->state); ++ ivshm_net_check_state(in); + + return 0; + ++err_request_irq2: ++ free_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_STATE), in); + err_request_irq: + pci_free_irq_vectors(pdev); + err_alloc_irq: +@@ -954,11 +1061,15 @@ static void ivshm_net_remove(struct pci_dev *pdev) + struct net_device *ndev = pci_get_drvdata(pdev); + struct ivshm_net *in = netdev_priv(ndev); + +- writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate); ++ writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->state); ++ writel(0, &in->ivshm_regs->int_control); + +- if (!pdev->msix_enabled) +- writel(0, &in->ivshm_regs->intxctrl); +- free_irq(pci_irq_vector(pdev, 0), ndev); ++ if (pdev->msix_enabled) { ++ free_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_STATE), in); ++ free_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_TX_RX), in); ++ } else { ++ free_irq(pci_irq_vector(pdev, 0), in); ++ } + pci_free_irq_vectors(pdev); + + unregister_netdev(ndev); +@@ -968,8 +1079,8 @@ static void ivshm_net_remove(struct pci_dev *pdev) + } + + static const struct pci_device_id ivshm_net_id_table[] = { +- { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, 0x1110), +- (PCI_CLASS_OTHERS << 16) | (0x01 << 8), 0xffff00 }, ++ { PCI_DEVICE(PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_IVSHMEM), ++ (PCI_CLASS_OTHERS << 16) | IVSHM_PROTO_NET, 0xffffff }, + { 0 } + }; + MODULE_DEVICE_TABLE(pci, ivshm_net_id_table); +-- +2.11.0 + diff --git a/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/jailhouse.cfg b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/jailhouse.cfg new file mode 100644 index 00000000..d417e556 --- /dev/null +++ b/meta-agl-devel/meta-agl-jailhouse/recipes-kernel/linux/linux/jailhouse.cfg @@ -0,0 +1,10 @@ +CONFIG_HOTPLUG_CPU=y +CONFIG_PCI_HOST_GENERIC=y + +CONFIG_HOTPLUG_PCI=y +CONFIG_IVSHMEM_NET=y + +CONFIG_UIO=y +CONFIG_UIO_IVSHMEM=y +CONFIG_VIRT_DRIVERS=y +CONFIG_JAILHOUSE_DBGCON=y |