arch/x86: (Intel64) implement SMP support
Add duplicate per-CPU data structures (x86_cpuboot, tss, stacks, etc.) for up to 4 total CPUs, add code in locore and z_arch_start_cpu(). The test board, qemu_x86_long, now defaults to 2 CPUs. Signed-off-by: Charles E. Youse <charles.youse@intel.com>
This commit is contained in:
parent
2808908816
commit
3eb1a8b59a
7 changed files with 239 additions and 7 deletions
|
@ -8,24 +8,106 @@
|
|||
#include <kernel_arch_func.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <arch/x86/multiboot.h>
|
||||
#include <drivers/interrupt_controller/loapic.h>
|
||||
|
||||
/*
|
||||
* Map of CPU logical IDs to CPU local APIC IDs. By default,
|
||||
* we assume this simple identity mapping, as found in QEMU.
|
||||
* The symbol is weak so that boards/SoC files can override.
|
||||
*/
|
||||
|
||||
__weak u8_t x86_cpu_loapics[] = { 0, 1, 2, 3 };
|
||||
|
||||
extern FUNC_NORETURN void z_x86_prep_c(int, struct multiboot_info *);
|
||||
|
||||
extern char x86_ap_start[]; /* AP entry point in locore.S */
|
||||
|
||||
extern u8_t _exception_stack[];
|
||||
extern u8_t _exception_stack1[];
|
||||
extern u8_t _exception_stack2[];
|
||||
extern u8_t _exception_stack3[];
|
||||
|
||||
Z_GENERIC_SECTION(.tss)
|
||||
struct x86_tss64 tss0 = {
|
||||
.ist1 = (u64_t) _interrupt_stack + CONFIG_ISR_STACK_SIZE,
|
||||
.ist7 = (u64_t) _exception_stack + CONFIG_EXCEPTION_STACK_SIZE,
|
||||
.iomapb = 0xFFFF, /* no I/O access bitmap */
|
||||
.iomapb = 0xFFFF,
|
||||
.cpu = &(_kernel.cpus[0])
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SMP) && (CONFIG_MP_NUM_CPUS > 1)
|
||||
Z_GENERIC_SECTION(.tss)
|
||||
struct x86_tss64 tss1 = {
|
||||
.ist1 = (u64_t) _interrupt_stack1 + CONFIG_ISR_STACK_SIZE,
|
||||
.ist7 = (u64_t) _exception_stack1 + CONFIG_EXCEPTION_STACK_SIZE,
|
||||
.iomapb = 0xFFFF,
|
||||
.cpu = &(_kernel.cpus[1])
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SMP) && (CONFIG_MP_NUM_CPUS > 2)
|
||||
Z_GENERIC_SECTION(.tss)
|
||||
struct x86_tss64 tss2 = {
|
||||
.ist1 = (u64_t) _interrupt_stack2 + CONFIG_ISR_STACK_SIZE,
|
||||
.ist7 = (u64_t) _exception_stack2 + CONFIG_EXCEPTION_STACK_SIZE,
|
||||
.iomapb = 0xFFFF,
|
||||
.cpu = &(_kernel.cpus[2])
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SMP) && (CONFIG_MP_NUM_CPUS > 3)
|
||||
Z_GENERIC_SECTION(.tss)
|
||||
struct x86_tss64 tss3 = {
|
||||
.ist1 = (u64_t) _interrupt_stack3 + CONFIG_ISR_STACK_SIZE,
|
||||
.ist7 = (u64_t) _exception_stack3 + CONFIG_EXCEPTION_STACK_SIZE,
|
||||
.iomapb = 0xFFFF,
|
||||
.cpu = &(_kernel.cpus[3])
|
||||
};
|
||||
#endif
|
||||
|
||||
struct x86_cpuboot x86_cpuboot[] = {
|
||||
{
|
||||
.tr = X86_KERNEL_CPU0_TR,
|
||||
.gs = X86_KERNEL_CPU0_GS,
|
||||
.sp = (u64_t) _interrupt_stack + CONFIG_ISR_STACK_SIZE,
|
||||
.fn = z_x86_prep_c
|
||||
}
|
||||
},
|
||||
#if defined(CONFIG_SMP) && (CONFIG_MP_NUM_CPUS > 1)
|
||||
{
|
||||
.tr = X86_KERNEL_CPU1_TR,
|
||||
.gs = X86_KERNEL_CPU1_GS,
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_SMP) && (CONFIG_MP_NUM_CPUS > 2)
|
||||
{
|
||||
.tr = X86_KERNEL_CPU2_TR,
|
||||
.gs = X86_KERNEL_CPU2_GS,
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_SMP) && (CONFIG_MP_NUM_CPUS > 3)
|
||||
{
|
||||
.tr = X86_KERNEL_CPU3_TR,
|
||||
.gs = X86_KERNEL_CPU3_GS,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Send the INIT/STARTUP IPI sequence required to start up CPU 'cpu_num', which
|
||||
* will enter the kernel at fn(---, arg), running on the specified stack.
|
||||
*/
|
||||
|
||||
void z_arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
|
||||
void (*fn)(int key, void *data), void *arg)
|
||||
{
|
||||
u8_t vector = ((unsigned long) x86_ap_start) >> 12;
|
||||
u8_t apic_id = x86_cpu_loapics[cpu_num];
|
||||
|
||||
x86_cpuboot[cpu_num].sp = (u64_t) Z_THREAD_STACK_BUFFER(stack) + sz;
|
||||
x86_cpuboot[cpu_num].fn = fn;
|
||||
x86_cpuboot[cpu_num].arg = arg;
|
||||
|
||||
z_loapic_ipi(apic_id, LOAPIC_ICR_IPI_INIT, 0);
|
||||
k_busy_wait(10000);
|
||||
z_loapic_ipi(apic_id, LOAPIC_ICR_IPI_STARTUP, vector);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue