1 /*
2  * Copyright (c) 2019 Intel Corporation
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <cpuid.h>
7 #include <zephyr/kernel.h>
8 #include <zephyr/arch/cpu.h>
9 #include <kernel_arch_data.h>
10 #include <kernel_arch_func.h>
11 #include <zephyr/kernel_structs.h>
12 #include <kernel_internal.h>
13 #include <zephyr/arch/x86/multiboot.h>
14 #include <x86_mmu.h>
15 #include <zephyr/drivers/interrupt_controller/loapic.h>
16 #ifdef CONFIG_ACPI
17 #include <zephyr/arch/x86/cpuid.h>
18 #include <zephyr/acpi/acpi.h>
19 #endif
20 
21 /*
22  * Map of CPU logical IDs to CPU local APIC IDs. By default,
23  * we assume this simple identity mapping, as found in QEMU.
24  * The symbol is weak so that boards/SoC files can override.
25  */
26 
27 #if defined(CONFIG_ACPI)
28 __weak uint8_t x86_cpu_loapics[CONFIG_MP_MAX_NUM_CPUS];
29 #else
30 #define INIT_CPUID(n, _) n
31 __weak uint8_t x86_cpu_loapics[] = {
32 	LISTIFY(CONFIG_MP_MAX_NUM_CPUS, INIT_CPUID, (,)),};
33 #endif
34 extern char x86_ap_start[]; /* AP entry point in locore.S */
35 
36 LISTIFY(CONFIG_MP_MAX_NUM_CPUS, ACPI_CPU_INIT, (;));
37 
38 Z_GENERIC_SECTION(.boot_arg)
39 x86_boot_arg_t x86_cpu_boot_arg;
40 
41 struct x86_cpuboot x86_cpuboot[] = {
42 	LISTIFY(CONFIG_MP_MAX_NUM_CPUS, X86_CPU_BOOT_INIT, (,)),
43 };
44 
45 /*
46  * Send the INIT/STARTUP IPI sequence required to start up CPU 'cpu_num', which
47  * will enter the kernel at fn(arg), running on the specified stack.
48  */
49 
arch_cpu_start(int cpu_num,k_thread_stack_t * stack,int sz,arch_cpustart_t fn,void * arg)50 void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz,
51 		    arch_cpustart_t fn, void *arg)
52 {
53 #if CONFIG_MP_MAX_NUM_CPUS > 1
54 	uint8_t vector = ((unsigned long) x86_ap_start) >> 12;
55 	uint8_t apic_id;
56 
57 	IF_ENABLED(CONFIG_ACPI, ({
58 		ACPI_MADT_LOCAL_APIC *lapic = acpi_local_apic_get(cpu_num);
59 
60 		if (lapic != NULL) {
61 			/* We update the apic_id, __start will need it. */
62 			x86_cpu_loapics[cpu_num] = lapic->Id;
63 		} else {
64 			/* TODO: kernel need to handle the error scenario if someone config
65 			 * CONFIG_MP_MAX_NUM_CPUS more than what platform supported.
66 			 */
67 			__ASSERT(false, "CPU reached more than maximum supported!");
68 			return;
69 		}
70 	}));
71 
72 	apic_id = x86_cpu_loapics[cpu_num];
73 
74 	x86_cpuboot[cpu_num].sp = (uint64_t) K_KERNEL_STACK_BUFFER(stack) + sz;
75 	x86_cpuboot[cpu_num].stack_size = sz;
76 	x86_cpuboot[cpu_num].fn = fn;
77 	x86_cpuboot[cpu_num].arg = arg;
78 	x86_cpuboot[cpu_num].cpu_id = cpu_num;
79 
80 	z_loapic_ipi(apic_id, LOAPIC_ICR_IPI_INIT, 0);
81 	k_busy_wait(10000);
82 	z_loapic_ipi(apic_id, LOAPIC_ICR_IPI_STARTUP, vector);
83 
84 	while (x86_cpuboot[cpu_num].ready == 0) {
85 	}
86 #else
87 	ARG_UNUSED(cpu_num);
88 	ARG_UNUSED(stack);
89 	ARG_UNUSED(sz);
90 	ARG_UNUSED(fn);
91 	ARG_UNUSED(arg);
92 #endif
93 }
94 
95 /* Per-CPU initialization, C domain. On the first CPU, z_prep_c is the
96  * next step. For other CPUs it is probably smp_init_top().
97  */
z_x86_cpu_init(struct x86_cpuboot * cpuboot)98 FUNC_NORETURN void z_x86_cpu_init(struct x86_cpuboot *cpuboot)
99 {
100 #if defined(CONFIG_ACPI)
101 	__ASSERT(z_x86_cpuid_get_current_physical_apic_id() ==
102 		 x86_cpu_loapics[cpuboot->cpu_id], "APIC ID miss match!");
103 #endif
104 	x86_sse_init(NULL);
105 
106 	if (cpuboot->cpu_id == 0U) {
107 		/* Only need to do these once per boot */
108 		z_bss_zero();
109 		z_data_copy();
110 	}
111 
112 	z_loapic_enable(cpuboot->cpu_id);
113 
114 #ifdef CONFIG_USERSPACE
115 	/* Set landing site for 'syscall' instruction */
116 	z_x86_msr_write(X86_LSTAR_MSR, (uint64_t)z_x86_syscall_entry_stub);
117 
118 	/* Set segment descriptors for syscall privilege transitions */
119 	z_x86_msr_write(X86_STAR_MSR, (uint64_t)X86_STAR_UPPER << 32);
120 
121 	/* Mask applied to RFLAGS when making a syscall */
122 	z_x86_msr_write(X86_FMASK_MSR, EFLAGS_SYSCALL);
123 #endif
124 
125 	/* Enter kernel, never return */
126 	cpuboot->ready++;
127 	cpuboot->fn(cpuboot->arg);
128 
129 	CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
130 }
131