hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/arch/x86/kernel/jailhouse.c
....@@ -11,7 +11,10 @@
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>
16
+#include <asm/io_apic.h>
17
+#include <asm/acpi.h>
1518 #include <asm/cpu.h>
1619 #include <asm/hypervisor.h>
1720 #include <asm/i8259.h>
....@@ -19,9 +22,25 @@
1922 #include <asm/pci_x86.h>
2023 #include <asm/reboot.h>
2124 #include <asm/setup.h>
25
+#include <asm/jailhouse_para.h>
2226
23
-static __initdata struct jailhouse_setup_data setup_data;
27
+static struct jailhouse_setup_data setup_data;
28
+#define SETUP_DATA_V1_LEN (sizeof(setup_data.hdr) + sizeof(setup_data.v1))
29
+#define SETUP_DATA_V2_LEN (SETUP_DATA_V1_LEN + sizeof(setup_data.v2))
30
+
2431 static unsigned int precalibrated_tsc_khz;
32
+
33
+static void jailhouse_setup_irq(unsigned int irq)
34
+{
35
+ struct mpc_intsrc mp_irq = {
36
+ .type = MP_INTSRC,
37
+ .irqtype = mp_INT,
38
+ .irqflag = MP_IRQPOL_ACTIVE_HIGH | MP_IRQTRIG_EDGE,
39
+ .srcbusirq = irq,
40
+ .dstirq = irq,
41
+ };
42
+ mp_save_irq(&mp_irq);
43
+}
2544
2645 static uint32_t jailhouse_cpuid_base(void)
2746 {
....@@ -44,7 +63,7 @@
4463
4564 static void __init jailhouse_timer_init(void)
4665 {
47
- lapic_timer_frequency = setup_data.apic_khz * (1000 / HZ);
66
+ lapic_timer_period = setup_data.v1.apic_khz * (1000 / HZ);
4867 }
4968
5069 static unsigned long jailhouse_get_tsc(void)
....@@ -76,33 +95,28 @@
7695 .type = IOAPIC_DOMAIN_STRICT,
7796 .ops = &mp_ioapic_irqdomain_ops,
7897 };
79
- struct mpc_intsrc mp_irq = {
80
- .type = MP_INTSRC,
81
- .irqtype = mp_INT,
82
- .irqflag = MP_IRQPOL_ACTIVE_HIGH | MP_IRQTRIG_EDGE,
83
- };
8498 unsigned int cpu;
8599
86100 jailhouse_x2apic_init();
87101
88102 register_lapic_address(0xfee00000);
89103
90
- for (cpu = 0; cpu < setup_data.num_cpus; cpu++) {
91
- generic_processor_info(setup_data.cpu_ids[cpu],
104
+ for (cpu = 0; cpu < setup_data.v1.num_cpus; cpu++) {
105
+ generic_processor_info(setup_data.v1.cpu_ids[cpu],
92106 boot_cpu_apic_version);
93107 }
94108
95109 smp_found_config = 1;
96110
97
- if (setup_data.standard_ioapic) {
111
+ if (setup_data.v1.standard_ioapic) {
98112 mp_register_ioapic(0, 0xfec00000, gsi_top, &ioapic_cfg);
99113
100
- /* Register 1:1 mapping for legacy UART IRQs 3 and 4 */
101
- mp_irq.srcbusirq = mp_irq.dstirq = 3;
102
- mp_save_irq(&mp_irq);
103
-
104
- mp_irq.srcbusirq = mp_irq.dstirq = 4;
105
- mp_save_irq(&mp_irq);
114
+ if (IS_ENABLED(CONFIG_SERIAL_8250) &&
115
+ setup_data.hdr.version < 2) {
116
+ /* Register 1:1 mapping for legacy UART IRQs 3 and 4 */
117
+ jailhouse_setup_irq(3);
118
+ jailhouse_setup_irq(4);
119
+ }
106120 }
107121 }
108122
....@@ -125,9 +139,9 @@
125139 pcibios_last_bus = 0xff;
126140
127141 #ifdef CONFIG_PCI_MMCONFIG
128
- if (setup_data.pci_mmconfig_base) {
142
+ if (setup_data.v1.pci_mmconfig_base) {
129143 pci_mmconfig_add(0, 0, pcibios_last_bus,
130
- setup_data.pci_mmconfig_base);
144
+ setup_data.v1.pci_mmconfig_base);
131145 pci_mmcfg_arch_init();
132146 }
133147 #endif
....@@ -135,9 +149,57 @@
135149 return 0;
136150 }
137151
152
+#ifdef CONFIG_SERIAL_8250
153
+static inline bool jailhouse_uart_enabled(unsigned int uart_nr)
154
+{
155
+ return setup_data.v2.flags & BIT(uart_nr);
156
+}
157
+
158
+static void jailhouse_serial_fixup(int port, struct uart_port *up,
159
+ u32 *capabilities)
160
+{
161
+ static const u16 pcuart_base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
162
+ unsigned int n;
163
+
164
+ for (n = 0; n < ARRAY_SIZE(pcuart_base); n++) {
165
+ if (pcuart_base[n] != up->iobase)
166
+ continue;
167
+
168
+ if (jailhouse_uart_enabled(n)) {
169
+ pr_info("Enabling UART%u (port 0x%lx)\n", n,
170
+ up->iobase);
171
+ jailhouse_setup_irq(up->irq);
172
+ } else {
173
+ /* Deactivate UART if access isn't allowed */
174
+ up->iobase = 0;
175
+ }
176
+ break;
177
+ }
178
+}
179
+
180
+static void __init jailhouse_serial_workaround(void)
181
+{
182
+ /*
183
+ * There are flags inside setup_data that indicate availability of
184
+ * platform UARTs since setup data version 2.
185
+ *
186
+ * In case of version 1, we don't know which UARTs belong Linux. In
187
+ * this case, unconditionally register 1:1 mapping for legacy UART IRQs
188
+ * 3 and 4.
189
+ */
190
+ if (setup_data.hdr.version > 1)
191
+ serial8250_set_isa_configurator(jailhouse_serial_fixup);
192
+}
193
+#else /* !CONFIG_SERIAL_8250 */
194
+static inline void jailhouse_serial_workaround(void)
195
+{
196
+}
197
+#endif /* CONFIG_SERIAL_8250 */
198
+
138199 static void __init jailhouse_init_platform(void)
139200 {
140201 u64 pa_data = boot_params.hdr.setup_data;
202
+ unsigned long setup_data_len;
141203 struct setup_data header;
142204 void *mapping;
143205
....@@ -162,16 +224,8 @@
162224 memcpy(&header, mapping, sizeof(header));
163225 early_memunmap(mapping, sizeof(header));
164226
165
- if (header.type == SETUP_JAILHOUSE &&
166
- header.len >= sizeof(setup_data)) {
167
- pa_data += offsetof(struct setup_data, data);
168
-
169
- mapping = early_memremap(pa_data, sizeof(setup_data));
170
- memcpy(&setup_data, mapping, sizeof(setup_data));
171
- early_memunmap(mapping, sizeof(setup_data));
172
-
227
+ if (header.type == SETUP_JAILHOUSE)
173228 break;
174
- }
175229
176230 pa_data = header.next;
177231 }
....@@ -179,13 +233,28 @@
179233 if (!pa_data)
180234 panic("Jailhouse: No valid setup data found");
181235
182
- if (setup_data.compatible_version > JAILHOUSE_SETUP_REQUIRED_VERSION)
183
- panic("Jailhouse: Unsupported setup data structure");
236
+ /* setup data must at least contain the header */
237
+ if (header.len < sizeof(setup_data.hdr))
238
+ goto unsupported;
184239
185
- pmtmr_ioport = setup_data.pm_timer_address;
240
+ pa_data += offsetof(struct setup_data, data);
241
+ setup_data_len = min_t(unsigned long, sizeof(setup_data),
242
+ (unsigned long)header.len);
243
+ mapping = early_memremap(pa_data, setup_data_len);
244
+ memcpy(&setup_data, mapping, setup_data_len);
245
+ early_memunmap(mapping, setup_data_len);
246
+
247
+ if (setup_data.hdr.version == 0 ||
248
+ setup_data.hdr.compatible_version !=
249
+ JAILHOUSE_SETUP_REQUIRED_VERSION ||
250
+ (setup_data.hdr.version == 1 && header.len < SETUP_DATA_V1_LEN) ||
251
+ (setup_data.hdr.version >= 2 && header.len < SETUP_DATA_V2_LEN))
252
+ goto unsupported;
253
+
254
+ pmtmr_ioport = setup_data.v1.pm_timer_address;
186255 pr_debug("Jailhouse: PM-Timer IO Port: %#x\n", pmtmr_ioport);
187256
188
- precalibrated_tsc_khz = setup_data.tsc_khz;
257
+ precalibrated_tsc_khz = setup_data.v1.tsc_khz;
189258 setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
190259
191260 pci_probe = 0;
....@@ -195,6 +264,12 @@
195264 * are none in a non-root cell.
196265 */
197266 disable_acpi();
267
+
268
+ jailhouse_serial_workaround();
269
+ return;
270
+
271
+unsupported:
272
+ panic("Jailhouse: Unsupported setup data structure");
198273 }
199274
200275 bool jailhouse_paravirt(void)
....@@ -202,7 +277,7 @@
202277 return jailhouse_cpuid_base() != 0;
203278 }
204279
205
-static bool jailhouse_x2apic_available(void)
280
+static bool __init jailhouse_x2apic_available(void)
206281 {
207282 /*
208283 * The x2APIC is only available if the root cell enabled it. Jailhouse
....@@ -216,4 +291,5 @@
216291 .detect = jailhouse_detect,
217292 .init.init_platform = jailhouse_init_platform,
218293 .init.x2apic_available = jailhouse_x2apic_available,
294
+ .ignore_nopv = true,
219295 };