Skip to content

Commit 7a56b81

Browse files
rralfsuryasaimadhu
authored andcommitted
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 <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Reviewed-by: Jan Kiszka <[email protected]> Cc: Baoquan He <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: [email protected] Cc: Juergen Gross <[email protected]> Cc: "Kirill A. Shutemov" <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: x86-ml <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 0935e5f commit 7a56b81

File tree

2 files changed

+75
-13
lines changed

2 files changed

+75
-13
lines changed

arch/x86/include/uapi/asm/bootparam.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ struct jailhouse_setup_data {
152152
__u8 standard_ioapic;
153153
__u8 cpu_ids[255];
154154
} __attribute__((packed)) v1;
155+
struct {
156+
__u32 flags;
157+
} __attribute__((packed)) v2;
155158
} __attribute__((packed));
156159

157160
/* The so-called "zeropage" */

arch/x86/kernel/jailhouse.c

Lines changed: 72 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/acpi_pmtmr.h>
1212
#include <linux/kernel.h>
1313
#include <linux/reboot.h>
14+
#include <linux/serial_8250.h>
1415
#include <asm/apic.h>
1516
#include <asm/cpu.h>
1617
#include <asm/hypervisor.h>
@@ -21,11 +22,24 @@
2122
#include <asm/setup.h>
2223
#include <asm/jailhouse_para.h>
2324

24-
static __initdata struct jailhouse_setup_data setup_data;
25+
static struct jailhouse_setup_data setup_data;
2526
#define SETUP_DATA_V1_LEN (sizeof(setup_data.hdr) + sizeof(setup_data.v1))
27+
#define SETUP_DATA_V2_LEN (SETUP_DATA_V1_LEN + sizeof(setup_data.v2))
2628

2729
static unsigned int precalibrated_tsc_khz;
2830

31+
static void jailhouse_setup_irq(unsigned int irq)
32+
{
33+
struct mpc_intsrc mp_irq = {
34+
.type = MP_INTSRC,
35+
.irqtype = mp_INT,
36+
.irqflag = MP_IRQPOL_ACTIVE_HIGH | MP_IRQTRIG_EDGE,
37+
.srcbusirq = irq,
38+
.dstirq = irq,
39+
};
40+
mp_save_irq(&mp_irq);
41+
}
42+
2943
static uint32_t jailhouse_cpuid_base(void)
3044
{
3145
if (boot_cpu_data.cpuid_level < 0 ||
@@ -79,11 +93,6 @@ static void __init jailhouse_get_smp_config(unsigned int early)
7993
.type = IOAPIC_DOMAIN_STRICT,
8094
.ops = &mp_ioapic_irqdomain_ops,
8195
};
82-
struct mpc_intsrc mp_irq = {
83-
.type = MP_INTSRC,
84-
.irqtype = mp_INT,
85-
.irqflag = MP_IRQPOL_ACTIVE_HIGH | MP_IRQTRIG_EDGE,
86-
};
8796
unsigned int cpu;
8897

8998
jailhouse_x2apic_init();
@@ -100,12 +109,12 @@ static void __init jailhouse_get_smp_config(unsigned int early)
100109
if (setup_data.v1.standard_ioapic) {
101110
mp_register_ioapic(0, 0xfec00000, gsi_top, &ioapic_cfg);
102111

103-
/* Register 1:1 mapping for legacy UART IRQs 3 and 4 */
104-
mp_irq.srcbusirq = mp_irq.dstirq = 3;
105-
mp_save_irq(&mp_irq);
106-
107-
mp_irq.srcbusirq = mp_irq.dstirq = 4;
108-
mp_save_irq(&mp_irq);
112+
if (IS_ENABLED(CONFIG_SERIAL_8250) &&
113+
setup_data.hdr.version < 2) {
114+
/* Register 1:1 mapping for legacy UART IRQs 3 and 4 */
115+
jailhouse_setup_irq(3);
116+
jailhouse_setup_irq(4);
117+
}
109118
}
110119
}
111120

@@ -138,6 +147,53 @@ static int __init jailhouse_pci_arch_init(void)
138147
return 0;
139148
}
140149

150+
#ifdef CONFIG_SERIAL_8250
151+
static inline bool jailhouse_uart_enabled(unsigned int uart_nr)
152+
{
153+
return setup_data.v2.flags & BIT(uart_nr);
154+
}
155+
156+
static void jailhouse_serial_fixup(int port, struct uart_port *up,
157+
u32 *capabilities)
158+
{
159+
static const u16 pcuart_base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
160+
unsigned int n;
161+
162+
for (n = 0; n < ARRAY_SIZE(pcuart_base); n++) {
163+
if (pcuart_base[n] != up->iobase)
164+
continue;
165+
166+
if (jailhouse_uart_enabled(n)) {
167+
pr_info("Enabling UART%u (port 0x%lx)\n", n,
168+
up->iobase);
169+
jailhouse_setup_irq(up->irq);
170+
} else {
171+
/* Deactivate UART if access isn't allowed */
172+
up->iobase = 0;
173+
}
174+
break;
175+
}
176+
}
177+
178+
static void __init jailhouse_serial_workaround(void)
179+
{
180+
/*
181+
* There are flags inside setup_data that indicate availability of
182+
* platform UARTs since setup data version 2.
183+
*
184+
* In case of version 1, we don't know which UARTs belong Linux. In
185+
* this case, unconditionally register 1:1 mapping for legacy UART IRQs
186+
* 3 and 4.
187+
*/
188+
if (setup_data.hdr.version > 1)
189+
serial8250_set_isa_configurator(jailhouse_serial_fixup);
190+
}
191+
#else /* !CONFIG_SERIAL_8250 */
192+
static inline void jailhouse_serial_workaround(void)
193+
{
194+
}
195+
#endif /* CONFIG_SERIAL_8250 */
196+
141197
static void __init jailhouse_init_platform(void)
142198
{
143199
u64 pa_data = boot_params.hdr.setup_data;
@@ -189,7 +245,8 @@ static void __init jailhouse_init_platform(void)
189245
if (setup_data.hdr.version == 0 ||
190246
setup_data.hdr.compatible_version !=
191247
JAILHOUSE_SETUP_REQUIRED_VERSION ||
192-
(setup_data.hdr.version >= 1 && header.len < SETUP_DATA_V1_LEN))
248+
(setup_data.hdr.version == 1 && header.len < SETUP_DATA_V1_LEN) ||
249+
(setup_data.hdr.version >= 2 && header.len < SETUP_DATA_V2_LEN))
193250
goto unsupported;
194251

195252
pmtmr_ioport = setup_data.v1.pm_timer_address;
@@ -205,6 +262,8 @@ static void __init jailhouse_init_platform(void)
205262
* are none in a non-root cell.
206263
*/
207264
disable_acpi();
265+
266+
jailhouse_serial_workaround();
208267
return;
209268

210269
unsupported:

0 commit comments

Comments
 (0)