Move SMP and other arch specific stuff into arch specific folders
This commit is contained in:
parent
7706e629c6
commit
2213707c6a
5 changed files with 180 additions and 1 deletions
|
|
@ -8,7 +8,7 @@
|
||||||
#define KERNELGSBASE 0xC0000102
|
#define KERNELGSBASE 0xC0000102
|
||||||
|
|
||||||
typedef struct cpu_state {
|
typedef struct cpu_state {
|
||||||
uint32_t lapic_id;
|
uint32_t id;
|
||||||
uint64_t lapic_timer_ticks;
|
uint64_t lapic_timer_ticks;
|
||||||
struct thread *head;
|
struct thread *head;
|
||||||
struct thread *base;
|
struct thread *base;
|
||||||
|
|
@ -22,5 +22,6 @@ typedef struct cpu_state {
|
||||||
void smp_init();
|
void smp_init();
|
||||||
cpu_state *get_cpu_struct();
|
cpu_state *get_cpu_struct();
|
||||||
uint64_t get_cpu_count();
|
uint64_t get_cpu_count();
|
||||||
|
void bsp_early_init();
|
||||||
bool get_cpu_struct_initialized();
|
bool get_cpu_struct_initialized();
|
||||||
|
|
||||||
0
src/arch/amd64/hal/amd64_smp.c
Normal file
0
src/arch/amd64/hal/amd64_smp.c
Normal file
63
src/arch/amd64/io.c
Normal file
63
src/arch/amd64/io.c
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint64_t rdmsr(uint64_t msr){
|
||||||
|
uint32_t low, high;
|
||||||
|
asm volatile (
|
||||||
|
"rdmsr"
|
||||||
|
: "=a"(low), "=d"(high)
|
||||||
|
: "c"(msr)
|
||||||
|
);
|
||||||
|
return ((uint64_t)high << 32) | low;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrmsr(uint64_t msr, uint64_t value){
|
||||||
|
uint32_t low = value & 0xFFFFFFFF;
|
||||||
|
uint32_t high = value >> 32;
|
||||||
|
asm volatile (
|
||||||
|
"wrmsr"
|
||||||
|
:
|
||||||
|
: "c"(msr), "a"(low), "d"(high)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void outb(uint16_t port, uint8_t val){
|
||||||
|
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void outw(uint16_t port, uint16_t val){
|
||||||
|
asm volatile ( "outw %0, %1" : : "a"(val), "Nd"(port) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void outl(uint16_t port, uint32_t val){
|
||||||
|
asm volatile ( "outl %0, %1" : : "a"(val), "Nd"(port) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t inb(uint16_t port){
|
||||||
|
uint8_t ret;
|
||||||
|
asm volatile ( "inb %1, %0"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "Nd"(port)
|
||||||
|
: "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t inw(uint16_t port){
|
||||||
|
uint16_t ret;
|
||||||
|
asm volatile ( "inw %1, %0"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "Nd"(port)
|
||||||
|
: "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t inl(uint16_t port){
|
||||||
|
uint32_t ret;
|
||||||
|
asm volatile ( "inl %1, %0"
|
||||||
|
: "=a"(ret)
|
||||||
|
: "Nd"(port)
|
||||||
|
: "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
115
src/smp.c
Normal file
115
src/smp.c
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limine.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <kprint.h>
|
||||||
|
#include <neobbo.h>
|
||||||
|
#include <arch/amd64/hal/gdt.h>
|
||||||
|
#include <smp.h>
|
||||||
|
#include <arch/amd64/hal/apic.h>
|
||||||
|
#include <arch/amd64/hal/idt.h>
|
||||||
|
#include <mm/vmm.h>
|
||||||
|
#include <mm/kmalloc.h>
|
||||||
|
#include <lock.h>
|
||||||
|
#include <arch/amd64/io.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern void s_load_idt();
|
||||||
|
extern void s_load_gdt();
|
||||||
|
extern volatile struct limine_mp_request smp_request;
|
||||||
|
|
||||||
|
/* Returns the CPU structure for this particular CPU */
|
||||||
|
cpu_state *get_cpu_struct(){
|
||||||
|
return (cpu_state*)rdmsr(GSBASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t get_cpu_count(){
|
||||||
|
if(smp_request.response != NULL){
|
||||||
|
return smp_request.response->cpu_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_cpu_struct_initialized(){
|
||||||
|
if(rdmsr(GSBASE) < get_kinfo()->hhdmoffset){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_flag ap_init_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
|
void ap_init(struct limine_mp_info *smp_info){
|
||||||
|
|
||||||
|
acquire_spinlock(&ap_init_lock);
|
||||||
|
|
||||||
|
/* Load the GDT */
|
||||||
|
s_load_gdt();
|
||||||
|
|
||||||
|
/* Load the IDT */
|
||||||
|
s_load_idt();
|
||||||
|
|
||||||
|
/* Set the CR3 context */
|
||||||
|
extern uint64_t *kernel_page_map;
|
||||||
|
|
||||||
|
vmm_set_ctx(kernel_page_map);
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"movq %%cr3, %%rax\n\
|
||||||
|
movq %%rax, %%cr3\n"
|
||||||
|
: : : "rax"
|
||||||
|
);
|
||||||
|
|
||||||
|
cpu_state *cpu_struct = (cpu_state*)kzalloc(sizeof(cpu_state));
|
||||||
|
|
||||||
|
cpu_struct->id = smp_info->lapic_id;
|
||||||
|
|
||||||
|
wrmsr(KERNELGSBASE, (uint64_t)cpu_struct);
|
||||||
|
wrmsr(GSBASE, (uint64_t)cpu_struct);
|
||||||
|
|
||||||
|
/* Initialize APIC & APIC timer */
|
||||||
|
ap_apic_init();
|
||||||
|
|
||||||
|
free_spinlock(&ap_init_lock);
|
||||||
|
|
||||||
|
for(;;);
|
||||||
|
|
||||||
|
scheduler_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static cpu_state bsp_cpu;
|
||||||
|
|
||||||
|
void smp_init(){
|
||||||
|
|
||||||
|
struct limine_mp_response *smp_response = smp_request.response;
|
||||||
|
|
||||||
|
kprintf("smp: {d} CPUs\n", smp_response->cpu_count);
|
||||||
|
|
||||||
|
for(uint64_t i = 0; i < smp_response->cpu_count; i++){
|
||||||
|
/* Pointer to smp_info is passed in RDI by Limine, so no need to pass any arguments here */
|
||||||
|
smp_response->cpus[i]->goto_address = &ap_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsp_cpu.scheduler_context = (struct context*)kmalloc(sizeof(struct context));
|
||||||
|
|
||||||
|
/* If one of the APs has halted, then halt the BSP */
|
||||||
|
extern bool kernel_killed;
|
||||||
|
if(kernel_killed == true){
|
||||||
|
kkill();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp_early_init(){
|
||||||
|
|
||||||
|
assert(smp_request.response != NULL && "Failed to get SMP request");
|
||||||
|
|
||||||
|
struct limine_mp_response *smp_response = smp_request.response;
|
||||||
|
|
||||||
|
bsp_cpu.id = smp_response->cpus[0]->lapic_id;
|
||||||
|
wrmsr(KERNELGSBASE, (uint64_t)&bsp_cpu);
|
||||||
|
wrmsr(GSBASE, (uint64_t)&bsp_cpu);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue