smp.c
ubixos/smp.h
ubixos/spinlock.h
ubixos/kpanic.h
lib/kprintf.h
lib/string.h
sys/io.h
ubixos/kpanic.h
ubixos/spinlock.h
ubixos/smp.h
ubixos/types.h
sys/_types.h
lib/string.h
lib/kprintf.h
src/sys/kernel/smp.c
sys/io.h
gdt_descr
void void ap_trampoline_end () ap_trampoline_end apicMagic
void void ap_trampoline_start () ap_trampoline_start
void void apicMagic (void) apicMagic void ap_trampoline_end ap_trampoline_start apicRead apicWrite kprintf memcpy smpInit
unsigned int static unsigned int apicRead (address) apicRead address apicMagic cpuInfo
void static void apicWrite (unsigned int address, unsigned int data) apicWrite unsigned int address unsigned int data apicMagic
asm
(".globl cpuid \n""cpuid: \n"" pushl %ebx \n"" pushl %edi \n"" movl 12(%esp),%eax \n"" movl 16(%esp),%edi \n"" cpuid \n"" movl %eax,0(%edi) \n"" movl %ebx,4(%edi) \n"" movl %ecx,8(%edi) \n"" movl %edx,12(%edi) \n"" popl %edi \n"" popl %ebx \n"" ret \n")
asm
".globl cpuid \n""cpuid: \n"" pushl %ebx \n"" pushl %edi \n"" movl 12 (%esp)
%eax\n""movl 16 (%esp)
%edi\n""cpuid\n""movl% eax
0(%edi)\n""movl% ebx
4(%edi)\n""movl% ecx
8(%edi)\n""movl% edx
12(%edi)\n""popl%edi\n""popl%ebx\n""ret\n"
void void c_ap_boot (void) c_ap_boot void cpu1_thread cpu2_thread cpu3_thread cpuInfo initSpinLock outportByte spinLockLocked xe9
void void cpu0_thread (void) cpu0_thread void kernel_function vram
void void cpu1_thread (void) cpu1_thread void kernel_function vram c_ap_boot
void void cpu2_thread (void) cpu2_thread void kernel_function vram c_ap_boot
void void cpu3_thread (void) cpu3_thread void kernel_function vram c_ap_boot
void void cpuidDetect () cpuidDetect getEflags kpanic setEflags smpInit
uInt8 uInt8 cpuInfo () cpuInfo cpuinfo_t::apic_id cpuinfo_t::apic_ver apicRead cpuinfo_t::brand cpuid cpuinfo cpuInfoLock cpus cpuinfo_t::feature getEflags cpuinfo_t::id cpuinfo_t::ident kpanic cpuinfo_t::max cpuinfo_t::ok setDr3 setEflags cpuinfo_t::signature spinLock spinUnlock x20 x30 c_ap_boot smpInit
void static void GDT_fixer () GDT_fixer gdt_descr::limit smpInit
__inline__ uInt32 static __inline__ uInt32 getDr3 (void) getDr3 void kernel_function
uInt32 uInt32 getEflags () getEflags cpuidDetect cpuInfo
uInt8 uInt8 kernel_function (void) kernel_function void getDr3 cpuinfo_t::id spinLock spinUnlock cpu0_thread cpu1_thread cpu2_thread cpu3_thread
__inline__ void static __inline__ void setDr3 (void *dr3) setDr3 void * dr3 cpuInfo
void void setEflags (uInt32 eflags) setEflags uInt32 eflags cpuidDetect cpuInfo
void void smpInit () smpInit apicMagic cpuidDetect cpuInfo GDT_fixer initSpinLock spinLock spinUnlock
spinLock_t spinLock_t bkl bkl SPIN_LOCK_INITIALIZER
cpuinfo_t struct cpuinfo_t cpuinfo[8] [8] cpuinfo cpuInfo
spinLock_t spinLock_t cpuInfoLock cpuInfoLock SPIN_LOCK_INITIALIZER cpuInfo
uInt32 uInt32 cpus cpus 0 cpuInfo
spinLock_t spinLock_t initSpinLock initSpinLock SPIN_LOCK_INITIALIZER c_ap_boot smpInit
uInt8 * uInt8* vram vram (uInt8 *)0xB8000 cpu0_thread cpu1_thread cpu2_thread cpu3_thread

    /*****************************************************************************************
    Copyright(c)2002TheUbixOSProject
    Allrightsreserved.

    Redistributionanduseinsourceandbinaryforms,withorwithoutmodification,are
    permittedprovidedthatthefollowingconditionsaremet:

    Redistributionsofsourcecodemustretaintheabovecopyrightnotice,thislistof
    conditions,thefollowingdisclaimerandthelistofauthors.Redistributionsinbinary
    formmustreproducetheabovecopyrightnotice,thislistofconditions,thefollowing
    disclaimerandthelistofauthorsinthedocumentationand/orothermaterialsprovided
    withthedistribution.NeitherthenameoftheUbixOSProjectnorthenamesofits
    contributorsmaybeusedtoendorseorpromoteproductsderivedfromthissoftware
    withoutspecificpriorwrittenpermission.

    THISSOFTWAREISPROVIDEDBYTHECOPYRIGHTHOLDERSANDCONTRIBUTORS"ASIS"ANDANY
    EXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THEIMPLIEDWARRANTIESOF
    MERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSEAREDISCLAIMED.INNOEVENTSHALL
    THECOPYRIGHTOWNERORCONTRIBUTORSBELIABLEFORANYDIRECT,INDIRECT,INCIDENTAL,
    SPECIAL,EXEMPLARY,ORCONSEQUENTIALDAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENT
    OFSUBSTITUTEGOODSORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)
    HOWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,OR
    TORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUTOFTHEUSEOFTHIS
    SOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOFSUCHDAMAGE.

    $Id: smp_8c.xml 88 2016-01-12 00:11:29Z reddawg $

    *****************************************************************************************/

    #include<ubixos/smp.h>
    #include<ubixos/spinlock.h>
    #include<ubixos/kpanic.h>
    #include<lib/kprintf.h>
    #include<lib/string.h>
    #include<sys/io.h>

    staticspinLock_tinitSpinLock=SPIN_LOCK_INITIALIZER;
    staticspinLock_tcpuInfoLock=SPIN_LOCK_INITIALIZER;
    staticuInt32cpus=0;
    structcpuinfo_tcpuinfo[8];

    uInt8kernel_function(void);
    uInt8*vram=(uInt8*)0xB8000;

    staticinlineunsignedintapicRead(address){
    return*(volatileunsignedint*)(0xFEE00000+address);
    }

    staticinlinevoidapicWrite(unsignedintaddress,unsignedintdata){
    *(volatileunsignedint*)(0xFEE00000+address)=data;
    }

    static__inline__voidsetDr3(void*dr3){
    registeruInt32value=(uInt32)dr3;
    __asm____volatile__("mov%0,%%dr3"::"r"(value));
    }

    static__inline__uInt32getDr3(void){
    registeruInt32value;
    __asm____volatile__("mov%%dr3,%0":"=r"(value));
    returnvalue;
    }

    structgdt_descr{
    uInt16limit;
    uInt32*base__attribute__((packed));
    };

    staticvoidGDT_fixer(){
    structgdt_descrgdt_descr;
    uInt32*gdt=(uInt32*)0x20000;//128KB

    gdt[0]=0;
    gdt[1]=0;
    gdt[2]=0x0000ffff;//seg0x8--DPL04GBcode
    gdt[3]=0x00cf9a00;
    gdt[4]=0x0000ffff;//seg0x10--DPL04GBdata
    gdt[5]=0x00cf9200;
    gdt[6]=0x0000ffff;//seg0x1b--DPL34GBcode
    gdt[7]=0x00cffa00;
    gdt[8]=0x0000ffff;//seg0x23--DPL34GBdata
    gdt[9]=0x00cff200;

    gdt_descr.limit=32*4;
    gdt_descr.base=gdt;

    /*
    asm("lgdt%0;"::"m"(gdt_descr));
    __asm____volatile__("ljmp%0,$1f;1:"::"i"(0x08));
    __asm____volatile__("movw%w0,%%ds"::"r"(0x10));
    __asm____volatile__("movw%w0,%%es"::"r"(0x10));
    __asm____volatile__("movw%w0,%%ss"::"r"(0x10));
    */
    }

    voidcpu0_thread(void){
    for(;;){
    vram[40+640]=kernel_function();
    vram[42+640]++;
    }
    }
    voidcpu1_thread(void){
    for(;;){
    vram[60+640]=kernel_function();
    vram[62+640]++;
    }
    }
    voidcpu2_thread(void){
    for(;;){
    vram[80+640]=kernel_function();
    vram[82+640]++;
    }
    }
    voidcpu3_thread(void){
    for(;;){
    vram[100+640]=kernel_function();
    vram[102+640]++;
    }
    }

    staticspinLock_tbkl=SPIN_LOCK_INITIALIZER;
    uInt8kernel_function(void){
    structcpuinfo_t*cpu;

    spinLock(&bkl);

    cpu=(structcpuinfo_t*)getDr3();

    spinUnlock(&bkl);

    return('0'+cpu->id);
    }

    voidc_ap_boot(void){

    while(spinLockLocked(&initSpinLock));

    switch(cpuInfo()){
    case1:
    cpu1_thread();
    break;
    case2:
    cpu2_thread();
    break;
    case3:
    cpu3_thread();
    break;
    }

    outportByte(0xe9,'5');

    for(;;){
    asm("nop");
    }
    }

    voidsmpInit(){
    spinLock(&initSpinLock);
    GDT_fixer();
    cpuidDetect();
    cpuInfo();
    apicMagic();
    spinUnlock(&initSpinLock);

    //cpu0_thread();

    }

    voidcpuidDetect(){
    if(!(getEflags()&(1<<21))){
    setEflags(getEflags()|(1<<21));
    if(!(getEflags()&(1<<21))){
    kpanic("CPUdoesn'tsupportCPUID,getanewermachine\n");
    }
    }
    }

    uInt8cpuInfo(){
    uInt32data[4],i;

    if(!(getEflags()&(1<<21))){//Ifthecpuidbitineflagsnotset..
    setEflags(getEflags()|(1<<21));//..tryandsetittoseeifitcomeson..
    if(!(getEflags()&(1<<21))){//Itdidn't..ThisCPUsuck
    kpanic("CPUdoesn'tsupportCPUID,getanewermachine\n");
    }
    }

    spinLock(&cpuInfoLock);
    cpuinfo[cpus].ok=1;
    cpuinfo[cpus].apic_id=apicRead(0x20)>>24;
    cpuinfo[cpus].apic_ver=apicRead(0x30)&0xFF;

    cpuid(0,data);
    *(uInt32*)&cpuinfo[cpus].ident[0]=data[1];
    *(uInt32*)&cpuinfo[cpus].ident[4]=data[3];
    *(uInt32*)&cpuinfo[cpus].ident[8]=data[2];
    cpuinfo[cpus].ident[17]=0;
    cpuinfo[cpus].max=data[0];

    cpuid(1,data);
    cpuinfo[cpus].signature=data[0];
    cpuinfo[cpus].feature=data[3];

    cpuid(0x80000000,data);
    if(data[0]>=0x80000004){
    for(i=0;i<3;i++){
    cpuid(0x80000002+i,data);

    *(unsignedint*)&cpuinfo[cpus].brand[16*i+0]=data[0];
    *(unsignedint*)&cpuinfo[cpus].brand[16*i+4]=data[1];
    *(unsignedint*)&cpuinfo[cpus].brand[16*i+8]=data[2];
    *(unsignedint*)&cpuinfo[cpus].brand[16*i+12]=data[3];
    }
    cpuinfo[cpus].brand[48]=0;
    }else{
    cpuinfo[cpus].brand[0]=0;
    }

    setDr3(&cpuinfo[cpus]);//DR3alwayspointstothecpu-structforthatCPU(shouldbethread-structofcurrentthread)
    cpuinfo[cpus].id=cpus;

    cpus++;

    spinUnlock(&cpuInfoLock);

    return(cpus-1);
    }

    externvoidap_trampoline_start(),ap_trampoline_end();
    voidapicMagic(void){
    uInt32tmp;

    kprintf("Copying%ubytesfrom0x%xto0x00\n",ap_trampoline_end-ap_trampoline_start,ap_trampoline_start);
    memcpy(0x0,(char*)ap_trampoline_start,ap_trampoline_end-ap_trampoline_start);
    apicWrite(0x280,0);
    apicRead(0x280);

    apicWrite(0x300,0x000C4500);//INITIPItoallCPUs
    for(tmp=0;tmp<800000;tmp++)asm("nop");//Sleepalittle(shouldbe10ms)
    apicWrite(0x300,0x000C4600);//INITSIPItoallCPUs
    for(tmp=0;tmp<800000;tmp++)asm("nop");//Sleepalittle(shouldbe200ms)
    apicWrite(0x300,0x000C4600);//SecondINITSIPI
    for(tmp=0;tmp<800000;tmp++)asm("nop");//Sleepalittle(shouldbe200ms)
    }

    uInt32getEflags(){
    uInt32eflags=0x0;
    asm(
    "pushfl\n"
    "popl%%eax\n"
    :"=a"(eflags)
    );
    return(eflags);
    }

    voidsetEflags(uInt32eflags){
    asm(
    "pushl%%eax\n"
    "popfl\n"
    :
    :"a"(eflags)
    );
    }

    asm(
    ".globlcpuid\n"
    "cpuid:\n"
    "pushl%ebx\n"
    "pushl%edi\n"
    "movl12(%esp),%eax\n"
    "movl16(%esp),%edi\n"
    "cpuid\n"
    "movl%eax,0(%edi)\n"
    "movl%ebx,4(%edi)\n"
    "movl%ecx,8(%edi)\n"
    "movl%edx,12(%edi)\n"
    "popl%edi\n"
    "popl%ebx\n"
    "ret\n"
    );

    /***
    END
    ***/