summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMichal Idziorek <m.i@gmx.at>2015-05-16 04:46:12 +0200
committerMichal Idziorek <m.i@gmx.at>2015-05-16 04:46:12 +0200
commitec6d07e29d1d55afe9d2c6f7f25e9fed20819af6 (patch)
treead990d16626fdd0835d1ae0d6252a7833de13588 /kernel
parentda62d2a7efc756870143ecda6566b0bea91b817f (diff)
started reactivating multiple processors
Diffstat (limited to 'kernel')
-rw-r--r--kernel/acpi.c170
-rw-r--r--kernel/acpi.h2
-rw-r--r--kernel/kernel.c36
-rw-r--r--kernel/mp.c178
-rw-r--r--kernel/mp.h2
-rw-r--r--kernel/smp.c101
-rw-r--r--kernel/smp.h20
7 files changed, 491 insertions, 18 deletions
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 <stdint.h>
+#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(entry<end)
+ {
+ entry=apci_get_next_entry(entry,procdata);
+ }
+
+
+ }
+}
+
+void acpi_read_rsdt(acpi_rsdt *rsdt,smp_processors *procdata)
+{
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Reading RSDT Table at 0x%08X",rsdt);
+
+ if(!strcmp("RSDT",rsdt->sig,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;i<entries;i++)
+ {
+
+ acpi_check_madt(first,procdata);
+ first++;
+ }
+
+}
+
+// search for the RSDB table in
+// 0x7ffff - 0x9ffff (max)
+// 0xe0000 - 0xfffff
+
+bool acpi_find(smp_processors *procdata)
+{
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Looking for RSDP Table");
+ char *search=(char *)0x9f000; //will be 16 bit aligned;
+ procdata->processors=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;i<addr->entries;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 <stdint.h>
+#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;i<SMP_MAX_PROC;i++)cpu_counter[i]=0;
+}
+
+
+void kernel_ap()
+{
+ proc++;
+ uint8_t p=proc;
+ while(1)
+ {
+ cpu_counter[p]++;
+
+ lock_spin(0);
+ if(cpu_counter[p]%1000000==0)log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"cpu[%d] %d",p,cpu_counter[p]);
+ lock_release(0);
+ }
+}
+void smp_log_procdata(smp_processors *procdata)
+{
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"---- smp -----");
+ for(int i=0;i<procdata->processors;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;i<pros->processors;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