1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Jailhouse paravirt_ops implementation |
4 | * |
5 | * Copyright (c) Siemens AG, 2015-2017 |
6 | * |
7 | * Authors: |
8 | * Jan Kiszka <jan.kiszka@siemens.com> |
9 | */ |
10 | |
11 | #include <linux/acpi_pmtmr.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/reboot.h> |
14 | #include <linux/serial_8250.h> |
15 | #include <asm/apic.h> |
16 | #include <asm/io_apic.h> |
17 | #include <asm/acpi.h> |
18 | #include <asm/cpu.h> |
19 | #include <asm/hypervisor.h> |
20 | #include <asm/i8259.h> |
21 | #include <asm/irqdomain.h> |
22 | #include <asm/pci_x86.h> |
23 | #include <asm/reboot.h> |
24 | #include <asm/setup.h> |
25 | #include <asm/jailhouse_para.h> |
26 | |
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 | |
31 | 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(m: &mp_irq); |
43 | } |
44 | |
45 | static uint32_t jailhouse_cpuid_base(void) |
46 | { |
47 | if (boot_cpu_data.cpuid_level < 0 || |
48 | !boot_cpu_has(X86_FEATURE_HYPERVISOR)) |
49 | return 0; |
50 | |
51 | return hypervisor_cpuid_base(sig: "Jailhouse\0\0\0" , leaves: 0); |
52 | } |
53 | |
54 | static uint32_t __init jailhouse_detect(void) |
55 | { |
56 | return jailhouse_cpuid_base(); |
57 | } |
58 | |
59 | static void jailhouse_get_wallclock(struct timespec64 *now) |
60 | { |
61 | memset(now, 0, sizeof(*now)); |
62 | } |
63 | |
64 | static void __init jailhouse_timer_init(void) |
65 | { |
66 | lapic_timer_period = setup_data.v1.apic_khz * (1000 / HZ); |
67 | } |
68 | |
69 | static unsigned long jailhouse_get_tsc(void) |
70 | { |
71 | return precalibrated_tsc_khz; |
72 | } |
73 | |
74 | static void __init jailhouse_x2apic_init(void) |
75 | { |
76 | #ifdef CONFIG_X86_X2APIC |
77 | if (!x2apic_enabled()) |
78 | return; |
79 | /* |
80 | * We do not have access to IR inside Jailhouse non-root cells. So |
81 | * we have to run in physical mode. |
82 | */ |
83 | x2apic_phys = 1; |
84 | /* |
85 | * This will trigger the switch to apic_x2apic_phys. Empty OEM IDs |
86 | * ensure that only this APIC driver picks up the call. |
87 | */ |
88 | default_acpi_madt_oem_check("" , "" ); |
89 | #endif |
90 | } |
91 | |
92 | static void __init jailhouse_get_smp_config(unsigned int early) |
93 | { |
94 | struct ioapic_domain_cfg ioapic_cfg = { |
95 | .type = IOAPIC_DOMAIN_STRICT, |
96 | .ops = &mp_ioapic_irqdomain_ops, |
97 | }; |
98 | unsigned int cpu; |
99 | |
100 | jailhouse_x2apic_init(); |
101 | |
102 | register_lapic_address(address: 0xfee00000); |
103 | |
104 | for (cpu = 0; cpu < setup_data.v1.num_cpus; cpu++) |
105 | generic_processor_info(apicid: setup_data.v1.cpu_ids[cpu]); |
106 | |
107 | smp_found_config = 1; |
108 | |
109 | if (setup_data.v1.standard_ioapic) { |
110 | mp_register_ioapic(id: 0, address: 0xfec00000, gsi_base: gsi_top, cfg: &ioapic_cfg); |
111 | |
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(irq: 3); |
116 | jailhouse_setup_irq(irq: 4); |
117 | } |
118 | } |
119 | } |
120 | |
121 | static void jailhouse_no_restart(void) |
122 | { |
123 | pr_notice("Jailhouse: Restart not supported, halting\n" ); |
124 | machine_halt(); |
125 | } |
126 | |
127 | static int __init jailhouse_pci_arch_init(void) |
128 | { |
129 | pci_direct_init(type: 1); |
130 | |
131 | /* |
132 | * There are no bridges on the virtual PCI root bus under Jailhouse, |
133 | * thus no other way to discover all devices than a full scan. |
134 | * Respect any overrides via the command line, though. |
135 | */ |
136 | if (pcibios_last_bus < 0) |
137 | pcibios_last_bus = 0xff; |
138 | |
139 | #ifdef CONFIG_PCI_MMCONFIG |
140 | if (setup_data.v1.pci_mmconfig_base) { |
141 | pci_mmconfig_add(segment: 0, start: 0, end: pcibios_last_bus, |
142 | addr: setup_data.v1.pci_mmconfig_base); |
143 | pci_mmcfg_arch_init(); |
144 | } |
145 | #endif |
146 | |
147 | return 0; |
148 | } |
149 | |
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(uart_nr: n)) { |
167 | pr_info("Enabling UART%u (port 0x%lx)\n" , n, |
168 | up->iobase); |
169 | jailhouse_setup_irq(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(v: 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 | |
197 | static void __init jailhouse_init_platform(void) |
198 | { |
199 | u64 pa_data = boot_params.hdr.setup_data; |
200 | unsigned long setup_data_len; |
201 | struct setup_data ; |
202 | void *mapping; |
203 | |
204 | x86_init.irqs.pre_vector_init = x86_init_noop; |
205 | x86_init.timers.timer_init = jailhouse_timer_init; |
206 | x86_init.mpparse.get_smp_config = jailhouse_get_smp_config; |
207 | x86_init.pci.arch_init = jailhouse_pci_arch_init; |
208 | |
209 | x86_platform.calibrate_cpu = jailhouse_get_tsc; |
210 | x86_platform.calibrate_tsc = jailhouse_get_tsc; |
211 | x86_platform.get_wallclock = jailhouse_get_wallclock; |
212 | x86_platform.legacy.rtc = 0; |
213 | x86_platform.legacy.warm_reset = 0; |
214 | x86_platform.legacy.i8042 = X86_LEGACY_I8042_PLATFORM_ABSENT; |
215 | |
216 | legacy_pic = &null_legacy_pic; |
217 | |
218 | machine_ops.emergency_restart = jailhouse_no_restart; |
219 | |
220 | while (pa_data) { |
221 | mapping = early_memremap(phys_addr: pa_data, size: sizeof(header)); |
222 | memcpy(&header, mapping, sizeof(header)); |
223 | early_memunmap(addr: mapping, size: sizeof(header)); |
224 | |
225 | if (header.type == SETUP_JAILHOUSE) |
226 | break; |
227 | |
228 | pa_data = header.next; |
229 | } |
230 | |
231 | if (!pa_data) |
232 | panic(fmt: "Jailhouse: No valid setup data found" ); |
233 | |
234 | /* setup data must at least contain the header */ |
235 | if (header.len < sizeof(setup_data.hdr)) |
236 | goto unsupported; |
237 | |
238 | pa_data += offsetof(struct setup_data, data); |
239 | setup_data_len = min_t(unsigned long, sizeof(setup_data), |
240 | (unsigned long)header.len); |
241 | mapping = early_memremap(phys_addr: pa_data, size: setup_data_len); |
242 | memcpy(&setup_data, mapping, setup_data_len); |
243 | early_memunmap(addr: mapping, size: setup_data_len); |
244 | |
245 | if (setup_data.hdr.version == 0 || |
246 | setup_data.hdr.compatible_version != |
247 | JAILHOUSE_SETUP_REQUIRED_VERSION || |
248 | (setup_data.hdr.version == 1 && header.len < SETUP_DATA_V1_LEN) || |
249 | (setup_data.hdr.version >= 2 && header.len < SETUP_DATA_V2_LEN)) |
250 | goto unsupported; |
251 | |
252 | pmtmr_ioport = setup_data.v1.pm_timer_address; |
253 | pr_debug("Jailhouse: PM-Timer IO Port: %#x\n" , pmtmr_ioport); |
254 | |
255 | precalibrated_tsc_khz = setup_data.v1.tsc_khz; |
256 | setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ); |
257 | |
258 | pci_probe = 0; |
259 | |
260 | /* |
261 | * Avoid that the kernel complains about missing ACPI tables - there |
262 | * are none in a non-root cell. |
263 | */ |
264 | disable_acpi(); |
265 | |
266 | jailhouse_serial_workaround(); |
267 | return; |
268 | |
269 | unsupported: |
270 | panic(fmt: "Jailhouse: Unsupported setup data structure" ); |
271 | } |
272 | |
273 | bool jailhouse_paravirt(void) |
274 | { |
275 | return jailhouse_cpuid_base() != 0; |
276 | } |
277 | |
278 | static bool __init jailhouse_x2apic_available(void) |
279 | { |
280 | /* |
281 | * The x2APIC is only available if the root cell enabled it. Jailhouse |
282 | * does not support switching between xAPIC and x2APIC. |
283 | */ |
284 | return x2apic_enabled(); |
285 | } |
286 | |
287 | const struct hypervisor_x86 x86_hyper_jailhouse __refconst = { |
288 | .name = "Jailhouse" , |
289 | .detect = jailhouse_detect, |
290 | .init.init_platform = jailhouse_init_platform, |
291 | .init.x2apic_available = jailhouse_x2apic_available, |
292 | .ignore_nopv = true, |
293 | }; |
294 | |