[SMP] Boot Application Processors
This commit is contained in:
parent
f356cc8f95
commit
6a2bef5517
@ -4,6 +4,9 @@
|
||||
#include <msr.h>
|
||||
#include <sse.h>
|
||||
#include <scheduler.h>
|
||||
#include <mem.h>
|
||||
#include <gdt.h>
|
||||
#include <string.h>
|
||||
|
||||
cpu_t cpus[MAX_NUMCPU];
|
||||
unsigned int num_cpu = 0;
|
||||
@ -19,6 +22,11 @@ void cpu_add(uint64_t id, uint64_t apic)
|
||||
cpu->id = id;
|
||||
cpu->apic_id = apic;
|
||||
cpu->is_bsp = (num_cpu)?0:1;
|
||||
|
||||
cpu->current_thread = 0;
|
||||
cpu->current_state = (num_cpu)?CPU_STOPPED:CPU_STARTED;
|
||||
cpu->kernel_stack = (num_cpu)?kmalloc(PAGE_SIZE) + PAGE_SIZE:0;
|
||||
|
||||
num_cpu++;
|
||||
}
|
||||
|
||||
@ -44,6 +52,15 @@ void cpu_init()
|
||||
asm("swapgs");
|
||||
init_cpu();
|
||||
|
||||
vmm_set_page(0, TRAMPOLINE_ADDR, TRAMPOLINE_ADDR, PAGE_PRESENT | PAGE_WRITE);
|
||||
memcpy((void *)TRAMPOLINE_ADDR, &trampoline, PAGE_SIZE);
|
||||
vmm_set_page(0, V2P(&BootGDT), V2P(&BootGDT), PAGE_PRESENT);
|
||||
for(unsigned int i = 0; i < num_cpu; i++)
|
||||
{
|
||||
ap_init(&cpus[i]);
|
||||
}
|
||||
vmm_set_page(0, TRAMPOLINE_ADDR, 0, 0);
|
||||
|
||||
debug_info("CPU - Status\n");
|
||||
for(unsigned int i = 0; i < num_cpu; i++)
|
||||
{
|
||||
|
50
kernel/cpu/smp.c
Normal file
50
kernel/cpu/smp.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include <stdint.h>
|
||||
#include <int.h>
|
||||
#include <mem.h>
|
||||
#include <debug.h>
|
||||
#include <cpu.h>
|
||||
#include <string.h>
|
||||
#include <apic.h>
|
||||
#include <pit.h>
|
||||
|
||||
extern uint64_t smp_stack_top;
|
||||
extern uint64_t ap_gs_base;
|
||||
|
||||
void ap_init(cpu_t *cpu)
|
||||
{
|
||||
debug_info("SMP - Starting up processor %x\n", cpu->id);
|
||||
if(!cpu->current_state == CPU_STOPPED)
|
||||
return;
|
||||
// Send INIT command
|
||||
apic_interrupt(cpu->id, APIC_INT_LEVEL_ASSERT, APIC_INT_TYPE_INIT, 0);
|
||||
// Wait 10 ms
|
||||
pit_delay(10);
|
||||
|
||||
// Write cpu data position to trampoline
|
||||
ap_gs_base = (uint64_t) cpu;
|
||||
|
||||
cpu->current_state = CPU_SIPI_SENT;
|
||||
apic_interrupt(cpu->id, APIC_INT_LEVEL_ASSERT, APIC_INT_TYPE_STARTUP, TRAMPOLINE_ADDR/PAGE_SIZE);
|
||||
pit_delay(10);
|
||||
|
||||
if(cpu->current_state != CPU_SIPI_REC)
|
||||
{
|
||||
cpu->current_state = CPU_SIPI_SENT;
|
||||
apic_interrupt(cpu->id, APIC_INT_LEVEL_ASSERT, APIC_INT_TYPE_STARTUP, TRAMPOLINE_ADDR/PAGE_SIZE);
|
||||
pit_delay(100);
|
||||
}
|
||||
|
||||
if(cpu->current_state != CPU_SIPI_REC)
|
||||
{
|
||||
debug_error("SMP - Starting cpu %x failed\n", cpu->id);
|
||||
cpu->current_state = CPU_FAILED;
|
||||
return;
|
||||
}
|
||||
cpu->current_state = CPU_STARTED;
|
||||
}
|
||||
|
||||
void ap_start()
|
||||
{
|
||||
debug_ok("STARTED CPU:%x\n", get_cpu()->id);
|
||||
for(;;)asm("hlt");
|
||||
}
|
110
kernel/cpu/trampoline.S
Normal file
110
kernel/cpu/trampoline.S
Normal file
@ -0,0 +1,110 @@
|
||||
#include <mem.h>
|
||||
#include <cpu.h>
|
||||
#include <msr.h>
|
||||
#define TRAMPOLINE_OFFSET TRAMPOLINE_ADDR - trampoline
|
||||
|
||||
.intel_syntax noprefix
|
||||
.global trampoline
|
||||
.section .text
|
||||
.code16
|
||||
trampoline:
|
||||
|
||||
cli
|
||||
mov ax, 0x0
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
lidt [ap_boot_idt + TRAMPOLINE_OFFSET]
|
||||
lgdt [ap_boot_gdtp + TRAMPOLINE_OFFSET]
|
||||
|
||||
mov eax, cr0
|
||||
or al, 0x1
|
||||
mov cr0, eax
|
||||
|
||||
jmp 0x8:start_32 + TRAMPOLINE_OFFSET
|
||||
|
||||
.code32
|
||||
start_32:
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
mov eax, cr4
|
||||
or eax, 1<<5
|
||||
mov cr4, eax
|
||||
|
||||
mov eax, offset V2P(BootP4)
|
||||
mov cr3, eax
|
||||
|
||||
mov ecx, 0xC0000080
|
||||
rdmsr
|
||||
or eax, 1<<8
|
||||
wrmsr
|
||||
|
||||
mov eax, cr0
|
||||
or eax, 1<<31
|
||||
mov cr0, eax
|
||||
|
||||
lgdt V2P(BootGDTp)
|
||||
|
||||
mov ax, 0x10
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov ss, ax
|
||||
|
||||
jmp 0x8:start_64 + TRAMPOLINE_OFFSET
|
||||
.code64
|
||||
start_64:
|
||||
movabs rax, offset start_longmode
|
||||
jmp rax
|
||||
start_longmode:
|
||||
|
||||
movabs rax, ap_gs_base
|
||||
mov rdx, rax
|
||||
shr rdx, 32
|
||||
mov ecx, MSR_REG_KERNEL_GS
|
||||
wrmsr
|
||||
swapgs
|
||||
|
||||
movq [gs:GS_OFFSET_STATE], CPU_SIPI_REC
|
||||
.ap_sync_loop:
|
||||
cmpq [gs:GS_OFFSET_STATE], CPU_SIPI_REC
|
||||
je .ap_sync_loop
|
||||
|
||||
mov rsp, gs:GS_OFFSET_STACK
|
||||
push 0
|
||||
mov rbp, rsp
|
||||
push 0
|
||||
popf
|
||||
|
||||
.extern ap_start
|
||||
call ap_start
|
||||
|
||||
|
||||
.align 16
|
||||
ap_boot_gdt:
|
||||
.long 0x00000000, 0x00000000
|
||||
.long 0x0000FFFF, 0x00CF9A00
|
||||
.long 0x0000FFFF, 0x00CF9200
|
||||
.align 16
|
||||
ap_boot_gdtp:
|
||||
.short 3*8-1
|
||||
.long ap_boot_gdt + TRAMPOLINE_OFFSET
|
||||
|
||||
.align 16
|
||||
ap_boot_idt:
|
||||
.short 0
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.global ap_gs_base
|
||||
ap_gs_base:
|
||||
.long 0x00000000, 0x00000000
|
||||
trampoline_end:
|
||||
nop
|
@ -2,7 +2,17 @@
|
||||
|
||||
#define MAX_NUMCPU 64
|
||||
|
||||
#define CPU_STOPPED 0
|
||||
#define CPU_SIPI_SENT 1
|
||||
#define CPU_SIPI_REC 2
|
||||
#define CPU_STARTED 3
|
||||
#define CPU_FAILED 4
|
||||
|
||||
#define TRAMPOLINE_ADDR 0x1000
|
||||
|
||||
#define GS_OFFSET_CPU 0
|
||||
#define GS_OFFSET_STATE 40
|
||||
#define GS_OFFSET_STACK 48
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <stdint.h>
|
||||
@ -17,6 +27,8 @@ typedef struct cpu_t
|
||||
uint64_t apic_id;
|
||||
uint64_t apic_ticks_per_us;
|
||||
uint64_t is_bsp;
|
||||
uint64_t current_state; // 40
|
||||
void *kernel_stack; // 48
|
||||
thread_t *current_thread;
|
||||
thread_t *last_thread;
|
||||
process_t *current_process;
|
||||
@ -31,7 +43,11 @@ extern unsigned int num_cpu;
|
||||
void acpi_init();
|
||||
void cpu_add(uint64_t id, uint64_t apic);
|
||||
void cpu_init();
|
||||
void init_cpu();
|
||||
cpu_t *get_cpu();
|
||||
void ap_init(cpu_t *cpu);
|
||||
|
||||
void trampoline();
|
||||
#endif
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user