diff options
Diffstat (limited to 'meta-agl-jailhouse/recipes-kernel/linux')
35 files changed, 0 insertions, 3889 deletions
diff --git a/meta-agl-jailhouse/recipes-kernel/linux/linux-jailhouse-5.4.inc b/meta-agl-jailhouse/recipes-kernel/linux/linux-jailhouse-5.4.inc deleted file mode 100644 index 4b571ffd..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux-jailhouse-5.4.inc +++ /dev/null @@ -1,39 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux-yocto_5.4%.bbappend b/meta-agl-jailhouse/recipes-kernel/linux/linux-yocto_5.4%.bbappend deleted file mode 100644 index b13f1eb1..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux-yocto_5.4%.bbappend +++ /dev/null @@ -1 +0,0 @@ -require recipes-kernel/linux/linux-jailhouse-5.4.inc diff --git a/meta-agl-jailhouse/recipes-kernel/linux/linux/0001-x86-jailhouse-Improve-setup-data-version-comparison.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0001-x86-jailhouse-Improve-setup-data-version-comparison.patch deleted file mode 100644 index 6b5032df..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0001-x86-jailhouse-Improve-setup-data-version-comparison.patch +++ /dev/null @@ -1,198 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch deleted file mode 100644 index d1db6c71..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch +++ /dev/null @@ -1,200 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0003-jailhouse-Add-simple-debug-console-via-the-hyperviso.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0003-jailhouse-Add-simple-debug-console-via-the-hyperviso.patch deleted file mode 100644 index 289f54ac..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0003-jailhouse-Add-simple-debug-console-via-the-hyperviso.patch +++ /dev/null @@ -1,174 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0004-arm-Export-__boot_cpu_mode-for-use-in-Jailhouse-driv.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0004-arm-Export-__boot_cpu_mode-for-use-in-Jailhouse-driv.patch deleted file mode 100644 index 6e4470f0..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0004-arm-Export-__boot_cpu_mode-for-use-in-Jailhouse-driv.patch +++ /dev/null @@ -1,43 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0005-mm-Re-export-ioremap_page_range.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0005-mm-Re-export-ioremap_page_range.patch deleted file mode 100644 index e6bf1c35..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0005-mm-Re-export-ioremap_page_range.patch +++ /dev/null @@ -1,25 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0006-arm-arm64-export-__hyp_stub_vectors.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0006-arm-arm64-export-__hyp_stub_vectors.patch deleted file mode 100644 index 42f3ea48..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0006-arm-arm64-export-__hyp_stub_vectors.patch +++ /dev/null @@ -1,57 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0007-x86-Export-lapic_timer_period.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0007-x86-Export-lapic_timer_period.patch deleted file mode 100644 index 9b2a2f2c..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0007-x86-Export-lapic_timer_period.patch +++ /dev/null @@ -1,28 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0008-arm64-dts-marvell-armada-37xx-Set-pci-domain.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0008-arm64-dts-marvell-armada-37xx-Set-pci-domain.patch deleted file mode 100644 index 963989cf..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0008-arm64-dts-marvell-armada-37xx-Set-pci-domain.patch +++ /dev/null @@ -1,31 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0009-arm64-dts-marvell-armada-8030-mcbin-Set-pci-domain.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0009-arm64-dts-marvell-armada-8030-mcbin-Set-pci-domain.patch deleted file mode 100644 index 8e99fa12..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0009-arm64-dts-marvell-armada-8030-mcbin-Set-pci-domain.patch +++ /dev/null @@ -1,31 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0010-uio-Enable-read-only-mappings.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0010-uio-Enable-read-only-mappings.patch deleted file mode 100644 index 2fa65641..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0010-uio-Enable-read-only-mappings.patch +++ /dev/null @@ -1,57 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0011-ivshmem-Add-header-file.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0011-ivshmem-Add-header-file.patch deleted file mode 100644 index f143d150..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0011-ivshmem-Add-header-file.patch +++ /dev/null @@ -1,52 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0012-uio-Add-driver-for-inter-VM-shared-memory-device.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0012-uio-Add-driver-for-inter-VM-shared-memory-device.patch deleted file mode 100644 index f98670c3..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0012-uio-Add-driver-for-inter-VM-shared-memory-device.patch +++ /dev/null @@ -1,311 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0013-ivshmem-net-virtual-network-device-for-Jailhouse.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0013-ivshmem-net-virtual-network-device-for-Jailhouse.patch deleted file mode 100644 index ae5ac475..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0013-ivshmem-net-virtual-network-device-for-Jailhouse.patch +++ /dev/null @@ -1,968 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0014-ivshmem-net-Map-shmem-region-as-RAM.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0014-ivshmem-net-Map-shmem-region-as-RAM.patch deleted file mode 100644 index de66d7a7..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0014-ivshmem-net-Map-shmem-region-as-RAM.patch +++ /dev/null @@ -1,30 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0015-ivshmem-net-fix-race-in-state-machine.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0015-ivshmem-net-fix-race-in-state-machine.patch deleted file mode 100644 index ecb5c485..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0015-ivshmem-net-fix-race-in-state-machine.patch +++ /dev/null @@ -1,140 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0016-ivshmem-net-Remove-unused-variable.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0016-ivshmem-net-Remove-unused-variable.patch deleted file mode 100644 index dfaca493..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0016-ivshmem-net-Remove-unused-variable.patch +++ /dev/null @@ -1,28 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0017-ivshmem-net-Enable-INTx.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0017-ivshmem-net-Enable-INTx.patch deleted file mode 100644 index e0f4be44..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0017-ivshmem-net-Enable-INTx.patch +++ /dev/null @@ -1,55 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0018-ivshmem-net-Improve-identification-of-resources.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0018-ivshmem-net-Improve-identification-of-resources.patch deleted file mode 100644 index e51b94aa..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0018-ivshmem-net-Improve-identification-of-resources.patch +++ /dev/null @@ -1,59 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0019-ivshmem-net-Switch-to-reset-state-on-each-net-stop-a.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0019-ivshmem-net-Switch-to-reset-state-on-each-net-stop-a.patch deleted file mode 100644 index 512bcaf2..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0019-ivshmem-net-Switch-to-reset-state-on-each-net-stop-a.patch +++ /dev/null @@ -1,47 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0020-ivshmem-net-Add-ethtool-register-dump.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0020-ivshmem-net-Add-ethtool-register-dump.patch deleted file mode 100644 index d0a562a7..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0020-ivshmem-net-Add-ethtool-register-dump.patch +++ /dev/null @@ -1,61 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0021-ivshmem-net-Fix-stuck-state-machine-during-setup.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0021-ivshmem-net-Fix-stuck-state-machine-during-setup.patch deleted file mode 100644 index 4e40341e..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0021-ivshmem-net-Fix-stuck-state-machine-during-setup.patch +++ /dev/null @@ -1,30 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0022-ivshmem-net-Switch-to-relative-descriptor-addresses.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0022-ivshmem-net-Switch-to-relative-descriptor-addresses.patch deleted file mode 100644 index aca00e26..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0022-ivshmem-net-Switch-to-relative-descriptor-addresses.patch +++ /dev/null @@ -1,49 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0023-ivshmem-net-Switch-to-pci_alloc_irq_vectors.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0023-ivshmem-net-Switch-to-pci_alloc_irq_vectors.patch deleted file mode 100644 index fcc2cac3..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0023-ivshmem-net-Switch-to-pci_alloc_irq_vectors.patch +++ /dev/null @@ -1,146 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0024-ivshmem-net-fill-in-and-check-used-descriptor-chain-.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0024-ivshmem-net-fill-in-and-check-used-descriptor-chain-.patch deleted file mode 100644 index 7620d682..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0024-ivshmem-net-fill-in-and-check-used-descriptor-chain-.patch +++ /dev/null @@ -1,70 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0025-ivshmem-net-slightly-improve-debug-output.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0025-ivshmem-net-slightly-improve-debug-output.patch deleted file mode 100644 index cc20c2fd..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0025-ivshmem-net-slightly-improve-debug-output.patch +++ /dev/null @@ -1,29 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0026-ivshmem-net-set-and-check-descriptor-flags.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0026-ivshmem-net-set-and-check-descriptor-flags.patch deleted file mode 100644 index a7d7ab24..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0026-ivshmem-net-set-and-check-descriptor-flags.patch +++ /dev/null @@ -1,43 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0027-ivshmem-net-add-MAC-changing-interface.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0027-ivshmem-net-add-MAC-changing-interface.patch deleted file mode 100644 index 61172afd..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0027-ivshmem-net-add-MAC-changing-interface.patch +++ /dev/null @@ -1,41 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0028-ivshmem-net-Silence-compiler-warning.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0028-ivshmem-net-Silence-compiler-warning.patch deleted file mode 100644 index 6a1c212f..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0028-ivshmem-net-Silence-compiler-warning.patch +++ /dev/null @@ -1,28 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0029-ivshmem-net-Fix-bogus-transition-to-RESET-state.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0029-ivshmem-net-Fix-bogus-transition-to-RESET-state.patch deleted file mode 100644 index 335c6bdb..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0029-ivshmem-net-Fix-bogus-transition-to-RESET-state.patch +++ /dev/null @@ -1,31 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0030-ivshmem-net-Refactor-and-comment-ivshm_net_state_cha.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0030-ivshmem-net-Refactor-and-comment-ivshm_net_state_cha.patch deleted file mode 100644 index 42ca05a0..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0030-ivshmem-net-Refactor-and-comment-ivshm_net_state_cha.patch +++ /dev/null @@ -1,68 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0031-ivshmem-net-Switch-to-netdev_xmit_more-helper.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0031-ivshmem-net-Switch-to-netdev_xmit_more-helper.patch deleted file mode 100644 index bedbc59f..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0031-ivshmem-net-Switch-to-netdev_xmit_more-helper.patch +++ /dev/null @@ -1,59 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/0032-ivshmem-net-Adjust-to-reworked-version-of-ivshmem-in.patch b/meta-agl-jailhouse/recipes-kernel/linux/linux/0032-ivshmem-net-Adjust-to-reworked-version-of-ivshmem-in.patch deleted file mode 100644 index dc10cd2f..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/0032-ivshmem-net-Adjust-to-reworked-version-of-ivshmem-in.patch +++ /dev/null @@ -1,650 +0,0 @@ -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-jailhouse/recipes-kernel/linux/linux/jailhouse.cfg b/meta-agl-jailhouse/recipes-kernel/linux/linux/jailhouse.cfg deleted file mode 100644 index d417e556..00000000 --- a/meta-agl-jailhouse/recipes-kernel/linux/linux/jailhouse.cfg +++ /dev/null @@ -1,10 +0,0 @@ -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 |