[SMP] Cpu initialization cleanup

This commit is contained in:
Thomas Lovén 2016-11-20 00:23:47 +01:00
parent 664379b35c
commit f356cc8f95
11 changed files with 126 additions and 43 deletions

View File

@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#include <multiboot.h> #include <multiboot.h>
#include <int.h> #include <int.h>
#include <cpu.h>
RSDP_st *find_rsdp() RSDP_st *find_rsdp()
{ {
@ -80,6 +81,8 @@ void parse_MADT(SDT_header *header)
if(f->proc.flags & 0x1) if(f->proc.flags & 0x1)
{ {
debug(" enabled"); debug(" enabled");
// Add processor and LAPIC to list
cpu_add(f->proc.proc_ID, f->proc.APIC_ID);
} }
debug("\n"); debug("\n");
break; break;

View File

@ -1,15 +1,15 @@
#include <gdt.h> #include <gdt.h>
#include <stdint.h> #include <stdint.h>
#include <debug.h> #include <debug.h>
#include <cpu.h>
uint64_t gdt[5]; #define GDT cpu->gdt
struct gdtp_st gdt_p; #define GDTP cpu->gdt_p
#define GDT gdt
#define GDTP gdt_p
void gdt_init() void gdt_init()
{ {
cpu_t *cpu = get_cpu();
GDT[0] = 0; GDT[0] = 0;
GDT[SEG_KCODE/8] = (uint64_t)(GDT_PRESENT | GDT_CODEDATA | GDT_WRITE | GDT_EXECUTE | GDT_64BIT); GDT[SEG_KCODE/8] = (uint64_t)(GDT_PRESENT | GDT_CODEDATA | GDT_WRITE | GDT_EXECUTE | GDT_64BIT);

View File

@ -1,23 +1,17 @@
#include <debug.h> #include <debug.h>
#include <int.h>
#include <multiboot.h> #include <multiboot.h>
#include <mem.h> #include <mem.h>
#include <gdt.h>
#include <scheduler.h> #include <scheduler.h>
#include <thread.h> #include <thread.h>
#include <process.h> #include <process.h>
#include <cpuid.h> #include <cpu.h>
#include <acpi.h>
#include <apic.h>
#include <sse.h>
#include <timer.h> #include <timer.h>
#include <pit.h>
void thread_function() void thread_function()
{ {
while(1) while(1)
{ {
debug((char *)0x10000); ;
} }
} }
@ -32,16 +26,9 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
multiboot_init(multiboot_magic, P2V(multiboot_data)); multiboot_init(multiboot_magic, P2V(multiboot_data));
vmm_init(); vmm_init();
pmm_init(); pmm_init();
gdt_init(); cpu_init();
scheduler_init();
pic_init();
acpi_init();
apic_init();
ioapic_init();
sse_init();
pit_init(); pit_init();
process_t *p1 = process_spawn(0); process_t *p1 = process_spawn(0);
process_t *p2 = process_spawn(p1); process_t *p2 = process_spawn(p1);

52
kernel/cpu/cpu.c Normal file
View File

@ -0,0 +1,52 @@
#include <cpu.h>
#include <debug.h>
#include <apic.h>
#include <msr.h>
#include <sse.h>
#include <scheduler.h>
cpu_t cpus[MAX_NUMCPU];
unsigned int num_cpu = 0;
void cpu_add(uint64_t id, uint64_t apic)
{
if(num_cpu >= MAX_NUMCPU)
return;
cpu_t *cpu = &cpus[num_cpu];
memset(cpu, 0, sizeof(cpu_t));
cpu->cpu = (uint64_t)cpu;
cpu->id = id;
cpu->apic_id = apic;
cpu->is_bsp = (num_cpu)?0:1;
num_cpu++;
}
void init_cpu()
{
cpu_t *cpu = get_cpu();
debug_info("CPU - Initializing CPU %x\n", cpu->id);
interrupt_init();
apic_init();
gdt_init();
sse_init();
scheduler_init();
}
void cpu_init()
{
acpi_init();
pic_init();
ioapic_init();
msr_write(MSR_REG_KERNEL_GS, cpus[0].cpu);
asm("swapgs");
init_cpu();
debug_info("CPU - Status\n");
for(unsigned int i = 0; i < num_cpu; i++)
{
debug(" CPU id:%x lapic:%x\n", cpus[i].id, cpus[i].apic_id);
}
}

6
kernel/cpu/get_cpu.S Normal file
View File

@ -0,0 +1,6 @@
#include <cpu.h>
.intel_syntax noprefix
.global get_cpu
get_cpu:
mov rax, gs:GS_OFFSET_CPU
ret

37
kernel/include/cpu.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#define MAX_NUMCPU 64
#define GS_OFFSET_CPU 0
#ifndef __ASSEMBLER__
#include <stdint.h>
#include <gdt.h>
#include <process.h>
#include <thread.h>
typedef struct cpu_t
{
uint64_t cpu;
uint64_t id;
uint64_t apic_id;
uint64_t apic_ticks_per_us;
uint64_t is_bsp;
thread_t *current_thread;
thread_t *last_thread;
process_t *current_process;
uint64_t gdt[5];
struct gdtp_st gdt_p;
thread_t *scheduler;
}__attribute__((packed)) cpu_t;
extern cpu_t cpus[];
extern unsigned int num_cpu;
void acpi_init();
void cpu_add(uint64_t id, uint64_t apic);
void cpu_init();
cpu_t *get_cpu();
#endif

View File

@ -3,6 +3,7 @@ typedef struct process_st process_t;
#include <stdint.h> #include <stdint.h>
#include <thread.h> #include <thread.h>
#include <mem.h> #include <mem.h>
#include <cpu.h>
typedef struct process_st typedef struct process_st
{ {
@ -23,9 +24,8 @@ typedef struct process_st
#define process_alive(proc) ((proc)->state == PROC_STATE_READY || (proc)->state == PROC_STATE_RUNNING) #define process_alive(proc) ((proc)->state == PROC_STATE_READY || (proc)->state == PROC_STATE_RUNNING)
process_t *current_process; #define get_current_process() (get_cpu()->current_process)
#define get_current_process() (current_process) #define set_current_process(proc) (get_cpu()->current_process = (proc))
#define set_current_process(proc) (current_process = (proc))
process_t *process_spawn(process_t *parent); process_t *process_spawn(process_t *parent);
void process_attach(process_t *proc, thread_t *th); void process_attach(process_t *proc, thread_t *th);

View File

@ -4,6 +4,7 @@ typedef struct thread_st thread_t;
#include <list.h> #include <list.h>
#include <process.h> #include <process.h>
#include <int.h> #include <int.h>
#include <cpu.h>
#define THREAD_STACK_SIZE 0x1000-sizeof(thread_t) #define THREAD_STACK_SIZE 0x1000-sizeof(thread_t)
@ -40,9 +41,8 @@ typedef struct thread_stack_st
thread_t tcb; thread_t tcb;
} thread_stack_t; } thread_stack_t;
thread_t *current_thread; #define get_current_thread() (get_cpu()->current_thread)
#define get_current_thread() (current_thread) #define set_current_thread(new) (get_cpu()->current_thread = (new))
#define set_current_thread(new) (current_thread = (new))
thread_t *new_thread(void (*func)(void)); thread_t *new_thread(void (*func)(void));
void switch_thread(thread_t *old, thread_t *new); void switch_thread(thread_t *old, thread_t *new);

View File

@ -46,8 +46,6 @@
#define APIC(reg) apic[reg/4] #define APIC(reg) apic[reg/4]
uint32_t volatile *apic = P2V(APIC_BASE); uint32_t volatile *apic = P2V(APIC_BASE);
uint32_t apic_ticks_per_us;
void apic_interrupt(uint8_t destination, uint8_t level, uint8_t type, uint8_t vector) void apic_interrupt(uint8_t destination, uint8_t level, uint8_t type, uint8_t vector)
{ {
uint64_t data = ((level & 0x1)<<14) | ((type & 0x7)<<8) | vector; uint64_t data = ((level & 0x1)<<14) | ((type & 0x7)<<8) | vector;
@ -69,7 +67,7 @@ registers_t *apic_timer_handler(registers_t *r)
void apic_timer(uint64_t us) void apic_timer(uint64_t us)
{ {
APIC(R_TIMER_DIV) = TIMER_DIV1; APIC(R_TIMER_DIV) = TIMER_DIV1;
APIC(R_TIMER_INIT) = us*apic_ticks_per_us; APIC(R_TIMER_INIT) = us*get_cpu()->apic_ticks_per_us;
APIC(R_TIMER_LVT) = TIMER_LVT_ONESHOT | INT_APIC_TIMER; APIC(R_TIMER_LVT) = TIMER_LVT_ONESHOT | INT_APIC_TIMER;
} }
void apic_timer_stop() void apic_timer_stop()
@ -91,7 +89,6 @@ uint32_t calibrate_apic_timer(uint32_t resolution)
void apic_init() void apic_init()
{ {
debug_info("APIC - APIC_BASE MSR: %x\n", msr_read(MSR_APIC_BASE));
// Enable APIC by setting the enable bit in the APIC MSR // Enable APIC by setting the enable bit in the APIC MSR
msr_write(MSR_APIC_BASE, msr_read(MSR_APIC_BASE) | APIC_MSR_ENABLE); msr_write(MSR_APIC_BASE, msr_read(MSR_APIC_BASE) | APIC_MSR_ENABLE);
@ -106,9 +103,7 @@ void apic_init()
APIC(R_EOI) = 0; APIC(R_EOI) = 0;
// Calibrate timer // Calibrate timer
apic_ticks_per_us = calibrate_apic_timer(100); get_cpu()->apic_ticks_per_us = calibrate_apic_timer(100);
debug_info("APIC - ticks per us:%d\n", apic_ticks_per_us);
debug(" corresponds to processor frequency: %d MHz\n", apic_ticks_per_us);
// Register temporary timer handler to go off every 10 ms // Register temporary timer handler to go off every 10 ms
register_int_handler(INT_APIC_TIMER, apic_timer_handler); register_int_handler(INT_APIC_TIMER, apic_timer_handler);

View File

@ -7,9 +7,10 @@
LIST(thread_t, ready_queue); LIST(thread_t, ready_queue);
thread_t *scheduler_th; thread_t *scheduler_th;
thread_t *last_thread = 0; #define get_last_thread() (get_cpu()->last_thread)
#define get_last_thread() (last_thread) #define set_last_thread(new) (get_cpu()->last_thread = (new))
#define set_last_thread(new) (last_thread = (new))
int scheduler_started = 0;
void scheduler_insert(thread_t *th) void scheduler_insert(thread_t *th)
{ {
@ -66,7 +67,7 @@ void scheduler()
switch_process(new->process); switch_process(new->process);
sse_restore(new->sse_registers); sse_restore(new->sse_registers);
apic_timer(1000000); apic_timer(1000000);
switch_thread(scheduler_th, new); switch_thread(get_cpu()->scheduler, new);
} }
} }
@ -75,7 +76,7 @@ void schedule()
// This function handles swithing to the next thread in the ready queue // This function handles swithing to the next thread in the ready queue
thread_t *old = get_current_thread(); thread_t *old = get_current_thread();
if(old == scheduler_th) if(old == get_cpu()->scheduler)
return; return;
if(old) if(old)
@ -84,11 +85,15 @@ void schedule()
} }
switch_process(0); switch_process(0);
switch_thread(old, scheduler_th); switch_thread(old, get_cpu()->scheduler);
} }
void scheduler_init() void scheduler_init()
{
if(!scheduler_started)
{ {
LIST_HEAD_INIT(ready_queue); LIST_HEAD_INIT(ready_queue);
scheduler_th = new_thread(scheduler); scheduler_started = 1;
}
get_cpu()->scheduler = new_thread(scheduler);
} }

View File

@ -6,8 +6,6 @@
#include <debug.h> #include <debug.h>
#include <registers.h> #include <registers.h>
thread_t *current_thread = 0;
uint64_t tid = 1; uint64_t tid = 1;