diff options
Diffstat (limited to 'meta-agl-jailhouse/recipes-kernel/linux/linux/0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch')
-rw-r--r-- | meta-agl-jailhouse/recipes-kernel/linux/linux/0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch | 200 |
1 files changed, 200 insertions, 0 deletions
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 new file mode 100644 index 00000000..d1db6c71 --- /dev/null +++ b/meta-agl-jailhouse/recipes-kernel/linux/linux/0002-x86-jailhouse-Only-enable-platform-UARTs-if-availabl.patch @@ -0,0 +1,200 @@ +From 7f87114a29351547ffb9bd16c4cafb37524806c6 Mon Sep 17 00:00:00 2001 +From: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de> +Date: Thu, 10 Oct 2019 12:21:02 +0200 +Subject: [PATCH 02/32] x86/jailhouse: Only enable platform UARTs if available + +ACPI tables aren't available if Linux runs as guest of the hypervisor +Jailhouse. This makes the 8250 driver probe for all platform UARTs as it +assumes that all UARTs are present in case of !ACPI. Jailhouse will stop +execution of Linux guest due to port access violation. + +So far, these access violations were solved by tuning the 8250.nr_uarts +cmdline parameter, but this has limitations: Only consecutive platform +UARTs can be mapped to Linux, and only in the sequence 0x3f8, 0x2f8, +0x3e8, 0x2e8. + +Beginning from setup_data version 2, Jailhouse will place information of +available platform UARTs in setup_data. This allows for selective +activation of platform UARTs. + +Query setup_data version and only activate available UARTS. This +patch comes with backward compatibility, and will still support older +setup_data versions. In case of older setup_data versions, Linux falls +back to the old behaviour. + +Signed-off-by: Ralf Ramsauer <ralf.ramsauer@oth-regensburg.de> +Signed-off-by: Borislav Petkov <bp@suse.de> +Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com> +Cc: Baoquan He <bhe@redhat.com> +Cc: "H. Peter Anvin" <hpa@zytor.com> +Cc: Ingo Molnar <mingo@redhat.com> +Cc: jailhouse-dev@googlegroups.com +Cc: Juergen Gross <jgross@suse.com> +Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: x86-ml <x86@kernel.org> +Link: https://lkml.kernel.org/r/20191010102102.421035-3-ralf.ramsauer@oth-regensburg.de +--- + arch/x86/include/uapi/asm/bootparam.h | 3 ++ + arch/x86/kernel/jailhouse.c | 85 +++++++++++++++++++++++++++++------ + 2 files changed, 75 insertions(+), 13 deletions(-) + +diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h +index 43be437c9c71..db1e24e56e94 100644 +--- a/arch/x86/include/uapi/asm/bootparam.h ++++ b/arch/x86/include/uapi/asm/bootparam.h +@@ -152,6 +152,9 @@ struct jailhouse_setup_data { + __u8 standard_ioapic; + __u8 cpu_ids[255]; + } __attribute__((packed)) v1; ++ struct { ++ __u32 flags; ++ } __attribute__((packed)) v2; + } __attribute__((packed)); + + /* The so-called "zeropage" */ +diff --git a/arch/x86/kernel/jailhouse.c b/arch/x86/kernel/jailhouse.c +index cf4eb37ad97b..6eb8b50ea07e 100644 +--- a/arch/x86/kernel/jailhouse.c ++++ b/arch/x86/kernel/jailhouse.c +@@ -11,6 +11,7 @@ + #include <linux/acpi_pmtmr.h> + #include <linux/kernel.h> + #include <linux/reboot.h> ++#include <linux/serial_8250.h> + #include <asm/apic.h> + #include <asm/cpu.h> + #include <asm/hypervisor.h> +@@ -21,11 +22,24 @@ + #include <asm/setup.h> + #include <asm/jailhouse_para.h> + +-static __initdata struct jailhouse_setup_data setup_data; ++static struct jailhouse_setup_data setup_data; + #define SETUP_DATA_V1_LEN (sizeof(setup_data.hdr) + sizeof(setup_data.v1)) ++#define SETUP_DATA_V2_LEN (SETUP_DATA_V1_LEN + sizeof(setup_data.v2)) + + static unsigned int precalibrated_tsc_khz; + ++static void jailhouse_setup_irq(unsigned int irq) ++{ ++ struct mpc_intsrc mp_irq = { ++ .type = MP_INTSRC, ++ .irqtype = mp_INT, ++ .irqflag = MP_IRQPOL_ACTIVE_HIGH | MP_IRQTRIG_EDGE, ++ .srcbusirq = irq, ++ .dstirq = irq, ++ }; ++ mp_save_irq(&mp_irq); ++} ++ + static uint32_t jailhouse_cpuid_base(void) + { + if (boot_cpu_data.cpuid_level < 0 || +@@ -79,11 +93,6 @@ static void __init jailhouse_get_smp_config(unsigned int early) + .type = IOAPIC_DOMAIN_STRICT, + .ops = &mp_ioapic_irqdomain_ops, + }; +- struct mpc_intsrc mp_irq = { +- .type = MP_INTSRC, +- .irqtype = mp_INT, +- .irqflag = MP_IRQPOL_ACTIVE_HIGH | MP_IRQTRIG_EDGE, +- }; + unsigned int cpu; + + jailhouse_x2apic_init(); +@@ -100,12 +109,12 @@ static void __init jailhouse_get_smp_config(unsigned int early) + if (setup_data.v1.standard_ioapic) { + mp_register_ioapic(0, 0xfec00000, gsi_top, &ioapic_cfg); + +- /* Register 1:1 mapping for legacy UART IRQs 3 and 4 */ +- mp_irq.srcbusirq = mp_irq.dstirq = 3; +- mp_save_irq(&mp_irq); +- +- mp_irq.srcbusirq = mp_irq.dstirq = 4; +- mp_save_irq(&mp_irq); ++ if (IS_ENABLED(CONFIG_SERIAL_8250) && ++ setup_data.hdr.version < 2) { ++ /* Register 1:1 mapping for legacy UART IRQs 3 and 4 */ ++ jailhouse_setup_irq(3); ++ jailhouse_setup_irq(4); ++ } + } + } + +@@ -138,6 +147,53 @@ static int __init jailhouse_pci_arch_init(void) + return 0; + } + ++#ifdef CONFIG_SERIAL_8250 ++static inline bool jailhouse_uart_enabled(unsigned int uart_nr) ++{ ++ return setup_data.v2.flags & BIT(uart_nr); ++} ++ ++static void jailhouse_serial_fixup(int port, struct uart_port *up, ++ u32 *capabilities) ++{ ++ static const u16 pcuart_base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8}; ++ unsigned int n; ++ ++ for (n = 0; n < ARRAY_SIZE(pcuart_base); n++) { ++ if (pcuart_base[n] != up->iobase) ++ continue; ++ ++ if (jailhouse_uart_enabled(n)) { ++ pr_info("Enabling UART%u (port 0x%lx)\n", n, ++ up->iobase); ++ jailhouse_setup_irq(up->irq); ++ } else { ++ /* Deactivate UART if access isn't allowed */ ++ up->iobase = 0; ++ } ++ break; ++ } ++} ++ ++static void __init jailhouse_serial_workaround(void) ++{ ++ /* ++ * There are flags inside setup_data that indicate availability of ++ * platform UARTs since setup data version 2. ++ * ++ * In case of version 1, we don't know which UARTs belong Linux. In ++ * this case, unconditionally register 1:1 mapping for legacy UART IRQs ++ * 3 and 4. ++ */ ++ if (setup_data.hdr.version > 1) ++ serial8250_set_isa_configurator(jailhouse_serial_fixup); ++} ++#else /* !CONFIG_SERIAL_8250 */ ++static inline void jailhouse_serial_workaround(void) ++{ ++} ++#endif /* CONFIG_SERIAL_8250 */ ++ + static void __init jailhouse_init_platform(void) + { + u64 pa_data = boot_params.hdr.setup_data; +@@ -189,7 +245,8 @@ static void __init jailhouse_init_platform(void) + if (setup_data.hdr.version == 0 || + setup_data.hdr.compatible_version != + JAILHOUSE_SETUP_REQUIRED_VERSION || +- (setup_data.hdr.version >= 1 && header.len < SETUP_DATA_V1_LEN)) ++ (setup_data.hdr.version == 1 && header.len < SETUP_DATA_V1_LEN) || ++ (setup_data.hdr.version >= 2 && header.len < SETUP_DATA_V2_LEN)) + goto unsupported; + + pmtmr_ioport = setup_data.v1.pm_timer_address; +@@ -205,6 +262,8 @@ static void __init jailhouse_init_platform(void) + * are none in a non-root cell. + */ + disable_acpi(); ++ ++ jailhouse_serial_workaround(); + return; + + unsupported: +-- +2.11.0 + |