From ec6d07e29d1d55afe9d2c6f7f25e9fed20819af6 Mon Sep 17 00:00:00 2001 From: Michal Idziorek Date: Sat, 16 May 2015 04:46:12 +0200 Subject: started reactivating multiple processors --- kernel/acpi.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/acpi.h | 2 + kernel/kernel.c | 36 ++++++------ kernel/mp.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/mp.h | 2 + kernel/smp.c | 101 ++++++++++++++++++++++++++++++++ kernel/smp.h | 20 +++++++ 7 files changed, 491 insertions(+), 18 deletions(-) create mode 100644 kernel/acpi.c create mode 100644 kernel/acpi.h create mode 100644 kernel/mp.c create mode 100644 kernel/mp.h create mode 100644 kernel/smp.c create mode 100644 kernel/smp.h (limited to 'kernel') diff --git a/kernel/acpi.c b/kernel/acpi.c new file mode 100644 index 0000000..3aec83b --- /dev/null +++ b/kernel/acpi.c @@ -0,0 +1,170 @@ +// Advanced Configuration and Power Interface +// http://wiki.xomb.org/index.php?title=ACPI_Tables + +#define FOOLOS_MODULE_NAME "acpi" + +#include "lib/logger/log.h" +#include +#include "lib/string/string.h" +#include "smp.h" + + +typedef struct acpi_rsdt_struct +{ + char sig[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oemid[6]; + char oemtabid[8]; + uint32_t oemrevision; + uint32_t vendor; + uint32_t rev; +}acpi_rsdt; + +typedef struct aspi_rsdp_struct +{ + char sig[8]; //signature + uint8_t checksum; + char oem[6]; + uint8_t revision; + + uint32_t ptr_rsdt; + uint32_t length; + + uint64_t ptr_xsdt; //same info but with 64bit pointers (preferred) + uint8_t checksum_ext; + uint8_t reserved[3]; + +}acpi_rsdp; + +typedef struct +{ + char sig[4]; + uint32_t length; + uint8_t rev; + uint8_t checksum; + char oemid[6]; + char oemtableid[8]; + char oemrev[4]; + char creatorid[4]; + char creatorrev[4]; + uint32_t apic_local; + uint32_t flags; + +}acpi_madt; + +uint8_t *apci_get_next_entry(uint8_t *addr,smp_processors *procdata) +{ + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"Examining MADT Entry at 0x%08X",addr); + + if(*addr==0) + { + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: LocalAPIC"); + // usable + if(addr[4]&1) + { + if(procdata->processors>=SMP_MAX_PROC){ + + panic(FOOLOS_MODULE_NAME,"we do not support that many processors. recompile with higher SMP_MAX_PROC."); + } + + procdata->local_apic_id[procdata->processors]=addr[3]; + procdata->processors++; + } + + } + else if(*addr==1) + { + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: IO APIC"); + } + else if(*addr==2)log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: Interrupt Source Override"); + else log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: type:0x%X",*addr); + + return addr+addr[1]; +} + + +void acpi_check_madt(uint32_t *madt,smp_processors *procdata) +{ + acpi_madt *table=(acpi_madt *)*madt; + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"Looking for MADT Table at %08X.",table); + if(strcmp("APIC",table->sig,4)) + { + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Found MADT Table at 0x%08X",table); + uint8_t *end=(uint8_t *)table; + end+=table->length; + + uint8_t *entry=(uint8_t *)table; + entry+=sizeof(acpi_madt); + + procdata->local_apic_address=table->apic_local; + + while(entrysig,4)) + panic(FOOLOS_MODULE_NAME,"Signature MISMATCH!"); + + int entries=(rsdt->length-sizeof(acpi_rsdt))/4; + uint32_t *first=(uint32_t *)rsdt; + first+=sizeof(acpi_rsdt)/4; + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Entries: %d",entries); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Looking for MADT Table"); + for(int i=0;iprocessors=0; + procdata->boot=0; + + while(search<=(char *)0xfffff) + { + if(strcmp("RSD PTR ",search,8)) // notice trailing space in "RSD PTR " + { + uint8_t checksum=0; + for(int i=0;i<20;i++) + checksum+=search[i]; + + if(checksum==0) + { + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"RSDP Table found at 0x%08X",search); + acpi_rsdp *rsdp=(acpi_rsdp *)search; + acpi_read_rsdt(rsdp->ptr_rsdt,procdata); + return true; + } + } + + search++; + + if(search==0xa0000)search=0xe0000; + + } + return false; +} diff --git a/kernel/acpi.h b/kernel/acpi.h new file mode 100644 index 0000000..b7c7342 --- /dev/null +++ b/kernel/acpi.h @@ -0,0 +1,2 @@ +#include "smp.h" +bool acpi_find(smp_processors *procdata); diff --git a/kernel/kernel.c b/kernel/kernel.c index 5f6981b..e5369f4 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -14,6 +14,7 @@ #include "timer.h" #include "mem.h" #include "vmem.h" +#include "mp.h" #include "interrupts.h" #include "multiboot.h" @@ -69,6 +70,23 @@ void kernel_main(uint32_t eax,uint32_t ebx) // uint32_t kernel_blocks=mem_init(info); + // + // Gather Info about other processors. (APs = application processors) + // ACPI or MP + // + smp_processors procdata; + + if(!acpi_find(&procdata)) + if(!mp_find(&procdata)) + panic(FOOLOS_MODULE_NAME,"ACPI and MP search failed! I do not want to continue!"); + // + // Start the other Processors (before paging) + // + smp_log_procdata(&procdata); + //TODO: !!! Check commented out sleep ()!!! + //smp_start_aps(&procdata,0x80000); // starts at 0x80000 + // but it will be copied over mbr + while(1); // // Activate Virtual Memory (paging) @@ -91,24 +109,6 @@ void kernel_main(uint32_t eax,uint32_t ebx) //pci_init(); - // - // Gather Info about other processors. (APs) - // ACPI or MP - // - // - /* - smp_processors procdata; - - if(!acpi_find(&procdata)) - if(!mp_find(&procdata)) - panic(FOOLOS_MODULE_NAME,"ACPI and MP search failed! I do not want to continue!"); - */ - // - // Start the other Processors (also before paging for some reason!) - // - //smp_log_procdata(&procdata); - //smp_start_aps(&procdata,0x80000); // starts at 0x80000 - // but it will be copied over mbr // // Mount Root EXT2 ramimage diff --git a/kernel/mp.c b/kernel/mp.c new file mode 100644 index 0000000..8312821 --- /dev/null +++ b/kernel/mp.c @@ -0,0 +1,178 @@ +#define FOOLOS_MODULE_NAME "mp" + +#include "x86.h" +#include "lib/logger/log.h" // logger facilities +#include "lib/string/string.h" +#include "smp.h" + + + +typedef struct mp_fps_struct +{ + uint32_t sig; //signature "_MP_" + uint32_t conf; //pointer to config struct + uint8_t length; //should be 1 + uint8_t version; // 1=1.1, 4=1.4 + + uint8_t checksum; + + uint8_t features1; + uint8_t features2; + + uint8_t res1; //reserved + uint8_t res2; + uint8_t res3; + +}mp_fps; + +typedef struct mp_config_struct +{ + uint32_t sig; //signature "PCMP" + uint16_t length; //base table length + uint8_t version; //revision 1=1.1 4=1.4 + uint8_t checksum; + + uint32_t oemid1; //OEM id (ascii) + uint32_t oemid2; + + uint32_t prodid1; //Product id (ascii) + uint32_t prodid2; + uint32_t prodid3; + + uint32_t oem_table; //pointer (optional) + uint16_t oem_size; //size of this table + uint16_t entries; //entry count (following the header) + uint32_t local_apic; //local apic address (same for every cpu) + uint16_t length_ext; //extended table length (optional) + uint8_t check_ext; //checksum for ext. table + +}mp_config; + + + +typedef struct proc_struct +{ + uint8_t type; //0=processor + uint8_t apic_id; + uint8_t apic_ver; + uint8_t cpu_bits; + uint32_t cpu_sig; + uint32_t cpu_flags; + +}proc_entry; + +//entries are sorted. (otherwise ignore. bochs!) +uint8_t *walk_mp_table(uint8_t *start_addr,smp_processors *smp) +{ + + if(*start_addr==0x0||*start_addr==0x2) + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"entry type: %d",*start_addr); + + // that is a processor + if(*start_addr==0x00) + { + proc_entry *pro=start_addr; + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"local apic id: %02X",pro->apic_id); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"cpu enabled bit: %s",pro->cpu_bits&1?"yes":"no"); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"bootstrap cpu bit: %s",pro->cpu_bits&2?"yes":"no"); + + // that is a enabled processor + if(pro->cpu_bits&1) + { + if(smp->processors>=SMP_MAX_PROC) + panic(FOOLOS_MODULE_NAME,"we do not support that many processors. recompile with higher SMP_MAX_PROC."); + + smp->local_apic_id[smp->processors]=pro->apic_id; + // that is the bootstrap processor + if(pro->cpu_bits&2)smp->boot=smp->processors; + smp->processors++; + + } + + return start_addr+20; + } + + return start_addr+8; +} + +void do_mp_conf(mp_config *addr,smp_processors *procdata) +{ + char buf[]="XXXX"; + uint32_t *buf_addr=buf; + *buf_addr=addr->sig; + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"mp_config table addr: %08X",addr); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"mp_config signature: %s",buf); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"mp_config version: %02X",addr->version); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"mp_config # of entries: %d",addr->entries); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"mp_config local apic addr: 0x%08X",addr->local_apic); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"mp_config tabel length: %d",addr->length); + + uint8_t *start_addr=addr; + start_addr+=44; + + procdata->processors=0; + procdata->local_apic_address=addr->local_apic; + + + for(int i=0;ientries;i++) + { + start_addr=walk_mp_table(start_addr,procdata); + } + + + + +} +bool do_mp_fps(mp_fps *addr,smp_processors *procdata) +{ + + if(addr->length!=1)return false; + if(addr->version!=1&&addr->version!=4)return false; + + char buf[]="XXXX"; + uint32_t *buf_addr=buf; + *buf_addr=addr->sig; + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"signature: %s",buf); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"conf: %08X",addr->conf); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"ver: %02X",addr->version); + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"f1: %02X",addr->features1); + + if(addr->features1!=0)panic(FOOLOS_MODULE_NAME,"Intel default config not supported yet!"); + do_mp_conf(addr->conf,procdata); + + return true; +} + +// todo: check checksum,version etc. and narrow down search +bool mp_find(smp_processors *procdata) +{ + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Looking for Mp Floating Ponter Struct..."); + uint8_t *addr=0x8000; + while(addr<=0xfffff) + { + if(strcmp("_MP_",addr,4)) + { + // log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Found at 0x%04X",addr); + if(do_mp_fps(addr,procdata))return true; + } + addr++; + } + + addr=0x190000-1025; + while(addr<=0x190000+1024) + { + if(strcmp("_MP_",addr,4)) + { + // log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Found at 0x%04X",addr); + if(do_mp_fps(addr,procdata))return true; + } + addr++; + } + + return false; + +} + diff --git a/kernel/mp.h b/kernel/mp.h new file mode 100644 index 0000000..fc7f036 --- /dev/null +++ b/kernel/mp.h @@ -0,0 +1,2 @@ +#include "smp.h" +bool mp_find(smp_processors *procdata); diff --git a/kernel/smp.c b/kernel/smp.c new file mode 100644 index 0000000..8d122ee --- /dev/null +++ b/kernel/smp.c @@ -0,0 +1,101 @@ +#define FOOLOS_MODULE_NAME "smp" + +#include "lib/logger/log.h" +#include +#include "smp.h" +#include "mem.h" +#include "spinlock.h" +#include "x86.h" + +#define FOOLOS_APIC_SPUR_INT 0x00f0 +#define FOOLOS_APIC_INT_COMMAND_LOW 0x0300 +#define FOOLOS_APIC_INT_COMMAND_HIGH 0x0310 + +// some multiprocessor shit that should move away TODO +uint32_t c1,c2,c3; +volatile uint8_t proc; +uint32_t cpu_counter[SMP_MAX_PROC]; + +void smp_main() +{ + /// TODO + /////// SYMMETRIC MULTIPROCESSING, APS get caought here, move it away /// + // catch the APs (Application Processors) +// if(mp==1) + { + uint32_t ebp=pmmngr_alloc_block()+4095; + + asm volatile("mov %0, %%ebp"::"r"(ebp)); + asm volatile("mov %ebp, %esp"); + asm volatile("jmp kernel_ap"); + } + + proc=c1=c2=c3=0; + for(int i=0;iprocessors;i++) + { + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"cpu %d, apic_id: 0x%X, bps: %s, apic_addr:0x%08X",i,procdata->local_apic_id[i],i==procdata->boot?"yes":"no",procdata->local_apic_address); + } + +} + +// this will start all our application processors! +void smp_start_aps(smp_processors *pros,uint8_t *start_sel) +{ + + //lets copy the code to the bootsector ! + + uint8_t *dest=0x7000; + for(int i=0;i<0x100;i++) + { + dest[i]=start_sel[i]; + + } + + //bsp (boot processor) enables its local apic + uint32_t *reg=pros->local_apic_address+FOOLOS_APIC_SPUR_INT; + *reg=0xffffffff; // all bits 1 and interrupt 255 + + for(int i=0;iprocessors;i++) + { + if(pros->boot==i)continue; + + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"starting cpu %d",i); + + uint8_t dest=pros->local_apic_id[i]; + + reg=pros->local_apic_address+FOOLOS_APIC_INT_COMMAND_HIGH; + *reg=dest<<24; // destination apic. + + reg=pros->local_apic_address+FOOLOS_APIC_INT_COMMAND_LOW; + *reg=(5<<8)|(1<<14); // 101 INIT + + // do we really neet this? + // todo: use some real sleep (not implemented yet :( ) + //sleep(30); + + // start proc 0x7 = 0x7000; etc.. + *reg=(6<<8)|(1<<14)|0x7; // 110 SIPI + } +} + + diff --git a/kernel/smp.h b/kernel/smp.h new file mode 100644 index 0000000..8737ffc --- /dev/null +++ b/kernel/smp.h @@ -0,0 +1,20 @@ +#ifndef SMP_H +#define SMP_H + +#define SMP_MAX_PROC 32 + +typedef struct +{ + + uint8_t boot; //which processor in array is bsp + // (boot strap processor) + + uint8_t processors; // total number of usable processors + + uint32_t local_apic_address;// same for every processor + + uint32_t local_apic_id[SMP_MAX_PROC]; // unique for every processor + +}smp_processors; + +#endif -- cgit v1.2.3