diff --git a/src/sys/include/ubixos/smp.h b/src/sys/include/ubixos/smp.h new file mode 100644 index 0000000..a56a4d1 --- /dev/null +++ b/src/sys/include/ubixos/smp.h @@ -0,0 +1,60 @@ +/***************************************************************************************** + Copyright (c) 2002 The UbixOS Project + All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions, the following disclaimer and the list of authors. Redistributions in binary +form must reproduce the above copyright notice, this list of conditions, the following +disclaimer and the list of authors in the documentation and/or other materials provided +with the distribution. Neither the name of the UbixOS Project nor the names of its +contributors may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + $Id$ + +*****************************************************************************************/ + +#ifndef _SMP_H +#define _SMP_H + +#include + +struct cpuinfo_t { + uInt8 id; + uInt8 ok; // 1=Ok, 0=Bad + uInt8 apic_id,apic_ver; + uInt32 signature; // Family, Model, Stepping + uInt32 feature; + uInt32 max; + char brand[49]; // Brand name + char ident[17]; + }; + + +void smpInit(); +void cpuidDetect(); +uInt8 cpuInfo(); +uInt32 getEflags(); +void setEflags(uInt32); +void cpuid(uInt32,uInt32 *); +void apicMagic(); + +#endif + +/*** + END + ***/ + diff --git a/src/sys/include/ubixos/spinlock.h b/src/sys/include/ubixos/spinlock.h index 7da67ff..14b41c6 100644 --- a/src/sys/include/ubixos/spinlock.h +++ b/src/sys/include/ubixos/spinlock.h @@ -1,25 +1,31 @@ -/************************************************************************************** +/***************************************************************************************** Copyright (c) 2002 The UbixOS Project All rights reserved. -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: -Redistributions of source code must retain the above copyright notice, this list of conditions, the following disclaimer and the list of authors. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions, the following disclaimer and the list of authors -in the documentation and/or other materials provided with the distribution. Neither the name of the UbixOS Project nor the names of its -contributors may be used to endorse or promote products derived from this software without specific prior written permission. +Redistributions of source code must retain the above copyright notice, this list of +conditions, the following disclaimer and the list of authors. Redistributions in binary +form must reproduce the above copyright notice, this list of conditions, the following +disclaimer and the list of authors in the documentation and/or other materials provided +with the distribution. Neither the name of the UbixOS Project nor the names of its +contributors may be used to endorse or promote products derived from this software +without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. $Id$ -**************************************************************************************/ +*****************************************************************************************/ #ifndef _SPINLOCK_H #define _SPINLOCK_H diff --git a/src/sys/init/main.c b/src/sys/init/main.c index 86445ed..fae1485 100644 --- a/src/sys/init/main.c +++ b/src/sys/init/main.c @@ -24,6 +24,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. $Log$ + Revision 1.15 2004/04/30 17:04:23 reddawg + Ok GUI is back on + Revision 1.14 2004/04/30 16:58:37 reddawg Turned On PCI Detections @@ -74,6 +77,7 @@ #include #include #include +#include char kernelStack[8192]; // Stack Space For Our Kernel @@ -97,7 +101,6 @@ // Clear the screen so we have a nice pretty starting place for the os to spew its info clearScreen(); - // Initialize the kernels vital systems // This initialization is for the systems memory and memory map for the os to allocate with if (vmmInit() != 0x0) { @@ -134,9 +137,11 @@ if (keyboardInit() != 0x0) { kpanic("Error: Initializing Keyboard\n"); } + /* if (pciInit() != 0x0) { kpanic("Error: Initializing PCI\n"); } + */ if (timeInit() != 0x0) { kpanic("Error: Initializing TIME\n"); } @@ -162,8 +167,8 @@ kprintf("Starting Os\n"); //netInit(); execThread(idleTask,(uInt32)(kmalloc(0x2000,sysID)+0x2000),0x0,"Idle Thread"); - execFile("init@sys",0x0,0x0,0x0); - //execFile("shell@sys",0x0,0x0,0x0); + //execFile("init@sys",0x0,0x0,0x0); + execFile("shell@sys",0x0,0x0,0x0); irqEnable(0x0); sched(); return(0x0); @@ -187,6 +192,7 @@ ************************************************************************/ void _start(void) { asm ("pushl $2; popf"); + smpInit(); asm volatile( "lgdtl (loadGDT) \n" "movw $0x10,%%ax \n" // Select Ring 0 Data Segment diff --git a/src/sys/kernel/Makefile b/src/sys/kernel/Makefile index 3d1063e..e9676bd 100644 --- a/src/sys/kernel/Makefile +++ b/src/sys/kernel/Makefile @@ -6,7 +6,7 @@ include ../Makefile.inc # Objects -OBJS = spinlock.o bioscall.o ld.o time.o fork.o syscall.o elf.o file.o idletask.o exec.o sched.o kpanic.o vitals.o ubthread.o +OBJS = ap-boot.o smp.o spinlock.o bioscall.o ld.o time.o fork.o syscall.o elf.o file.o idletask.o exec.o sched.o kpanic.o vitals.o ubthread.o all: $(OBJS) @@ -20,7 +20,7 @@ .c.s: $(CC) ${CFLAGS} -Wall -fomit-frame-pointer -O -I../include -S -o $@ $< .S.o: - $(CC) ${CFLAGS} -Wall -fomit-frame-pointer -c -o $@ $< + $(CC) ${CFLAGS} -Wall -fomit-frame-pointer -O -I../include -c -o $@ $< # Clean up the junk clean: diff --git a/src/sys/kernel/ap-boot.S b/src/sys/kernel/ap-boot.S new file mode 100644 index 0000000..2645aff --- /dev/null +++ b/src/sys/kernel/ap-boot.S @@ -0,0 +1,105 @@ +/* + * Okay, this file contains the code that's going to bootstrap the AP cpus + */ + + + .globl ap_trampoline_start,ap_trampoline_end + .text + .code16 +ap_trampoline_start: + cli + cld + + movw %cs,%ax // The CPU knows its CS already, so lets use it for the other segments + movw %ax,%ds + movw %ax,%es + movw %ax,%ss + + // Do some bochs-specific bullshit + mov $0x31,%al // '1' + mov $0xe9,%dx + outb %al,%dx + //lgdt ap_gdt; + lgdt ap_trampoline_gdt_limit - ap_trampoline_start + movl %cr0,%eax + orl $0x1,%eax + movl %eax,%cr0 // PMODE! + +.code32 + .byte 0x66 + ljmp $0x08,$(ap_trampoline_32 - ap_trampoline_start) // 0x08 == KERNEL_CS + +ap_trampoline_32: + mov $0x32,%al // '2' + mov $0xe9,%dx + outb %al,%dx + + mov $0x10,%ax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + mov %ax,%gs + mov %ax,%ss + + // Spinlock + mov ap_trampoline_spl - ap_trampoline_start,%edi +ap_spl: + //cmp $1,(%edi) + //je ap_spl + + mov $1,%eax // Value to be set + xchgl (%edi),%eax + cmp $0,%eax + je ap_spl + // /Spinlock + + mov $0x30,%al // '0' + mov $0xe9,%dx + outb %al,%dx + + mov ap_trampoline_stackptr - ap_trampoline_start,%ebx + mov %ebx,%esp + add $0x1000,%ebx + mov %ebx,ap_trampoline_stackptr - ap_trampoline_start + + mov $0x31,%al // '1' + mov $0xe9,%dx + outb %al,%dx + + // spinunlock + mov $0,%eax + mov ap_trampoline_spl - ap_trampoline_start,%edi + xchgl (%edi),%eax + // /spinunlock + + mov $0x33,%al // '3' + mov $0xe9,%dx + outb %al,%dx + + mov ap_trampoline_epoint,%eax + call *%eax +1: + hlt + jmp 1b // Halt if we ever get here somehow + + // Stack.. This sucks, since CPU initialization isn't serialized +ap_trampoline_stackptr: + .long 0x10000 // 256KB +ap_trampoline_epoint: + .long c_ap_boot + +ap_trampoline_spl: + .long 0 +ap_gdt: + .long ubixGDT + + // GDT +ap_trampoline_gdt: + .word 0 +ap_trampoline_gdt_limit: + .word 128 // Room for 32 descriptors +ap_trampoline_gdt_base: + .long 0x20000 // 128KB (move this later) + + +ap_trampoline_end: diff --git a/src/sys/kernel/smp.c b/src/sys/kernel/smp.c new file mode 100644 index 0000000..6208f6f --- /dev/null +++ b/src/sys/kernel/smp.c @@ -0,0 +1,294 @@ +/***************************************************************************************** + Copyright (c) 2002 The UbixOS Project + All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions, the following disclaimer and the list of authors. Redistributions in binary +form must reproduce the above copyright notice, this list of conditions, the following +disclaimer and the list of authors in the documentation and/or other materials provided +with the distribution. Neither the name of the UbixOS Project nor the names of its +contributors may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + $Log$ + Revision 1.1 2004/05/02 03:19:51 reddawg + Added Spinlock Provision For SMP + + + $Id$ + +*****************************************************************************************/ + +#include +#include +#include +#include +#include +#include + +static spinLock_t initSpinLock = SPIN_LOCK_INITIALIZER; +static spinLock_t cpuInfoLock = SPIN_LOCK_INITIALIZER; +static uInt32 cpus = 0; +struct cpuinfo_t cpuinfo[8]; + +uInt8 kernel_function(void); +uInt8 *vram = (uInt8 *)0xB8000; + +static inline unsigned int apicRead(address) { + return *(volatile unsigned int *) (0xFEE00000 + address); + } + +static inline void apicWrite(unsigned int address,unsigned int data) { + *(volatile unsigned int *) (0xFEE00000 + address) = data; + } + +static __inline__ void setDr3 (void *dr3) { + register uInt32 value = (uInt32)dr3; + __asm__ __volatile__ ("mov %0, %%dr3" :: "r" (value)); + } + +static __inline__ uInt32 getDr3 (void) { + register uInt32 value; + __asm__ __volatile__ ("mov %%dr3, %0" : "=r" (value)); + return value; + } + +struct gdt_descr { + uInt16 limit; + uInt32 *base __attribute__ ((packed)); +}; + +static void GDT_fixer() { + struct gdt_descr gdt_descr; + uInt32 *gdt = (uInt32 *)0x20000; // 128KB + + gdt[0] = 0; + gdt[1] = 0; + gdt[2] = 0x0000ffff; // seg 0x8 -- DPL 0 4GB code + gdt[3] = 0x00cf9a00; + gdt[4] = 0x0000ffff; // seg 0x10 -- DPL 0 4GB data + gdt[5] = 0x00cf9200; + gdt[6] = 0x0000ffff; // seg 0x1b -- DPL 3 4GB code + gdt[7] = 0x00cffa00; + gdt[8] = 0x0000ffff; // seg 0x23 -- DPL 3 4GB data + 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)); +} + + +void cpu0_thread(void) { + for(;;) { + vram[40+640] = kernel_function(); + vram[42+640]++; + } +} +void cpu1_thread(void) { + for(;;) { + vram[60+640] = kernel_function(); + vram[62+640]++; + } +} +void cpu2_thread(void) { + for(;;) { + vram[80+640] = kernel_function(); + vram[82+640]++; + } +} +void cpu3_thread(void) { + for(;;) { + vram[100+640] = kernel_function(); + vram[102+640]++; + } +} + +static spinLock_t bkl = SPIN_LOCK_INITIALIZER; +uInt8 kernel_function(void) { + struct cpuinfo_t *cpu; + + spinLock(&bkl); + + + cpu = (struct cpuinfo_t *)getDr3(); + + spinUnlock(&bkl); + + return('0' + cpu->id); +} + + +void c_ap_boot(void) { + + while(spinLockLocked(&initSpinLock)); + + switch(cpuInfo()) { + case 1: + cpu1_thread(); + break; + case 2: + cpu2_thread(); + break; + case 3: + cpu3_thread(); + break; + } + + outportByte(0xe9,'5'); + + for(;;) { + asm("nop"); + } +} + + +void smpInit() { + spinLock(&initSpinLock); + GDT_fixer(); + cpuidDetect(); + cpuInfo(); + apicMagic(); + spinUnlock(&initSpinLock); + + //cpu0_thread(); + + } + +void cpuidDetect() { + if (!(getEflags() & (1<<21)) ) { + setEflags(getEflags() | (1<<21)); + if( !(getEflags() & (1<<21)) ) { + kpanic("CPU doesn't support CPUID, get a newer machine\n"); + } + } + } + +uInt8 cpuInfo() { + uInt32 data[4],i; + + if( !(getEflags() & (1<<21)) ) { // If the cpuid bit in eflags not set.. + setEflags(getEflags() | (1<<21)); // ..try and set it to see if it comes on.. + if( !(getEflags() & (1<<21)) ) { // It didn't.. This CPU suck + kpanic("CPU doesn't support CPUID, get a newer machine\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); + + *(unsigned int *)&cpuinfo[cpus].brand[16*i+0] = data[0]; + *(unsigned int *)&cpuinfo[cpus].brand[16*i+4] = data[1]; + *(unsigned int *)&cpuinfo[cpus].brand[16*i+8] = data[2]; + *(unsigned int *)&cpuinfo[cpus].brand[16*i+12] = data[3]; + } + cpuinfo[cpus].brand[48] = 0; + } else { + cpuinfo[cpus].brand[0] = 0; + } + + setDr3(&cpuinfo[cpus]); // DR3 always points to the cpu-struct for that CPU (should be thread-struct of current thread) + cpuinfo[cpus].id = cpus; + + cpus++; + + spinUnlock(&cpuInfoLock); + + return(cpus - 1); + } + +extern void ap_trampoline_start(),ap_trampoline_end(); +void apicMagic(void) { + uInt32 tmp; + + kprintf("Copying %u bytes from 0x%x to 0x00\n",ap_trampoline_end - ap_trampoline_start,ap_trampoline_start); + kmemcpy(0x0,(char *)ap_trampoline_start,ap_trampoline_end - ap_trampoline_start); + apicWrite(0x280,0); + apicRead(0x280); + + apicWrite(0x300,0x000C4500); // INIT IPI to all CPUs + for(tmp=0;tmp<800000;tmp++) asm("nop"); // Sleep a little (should be 10ms) + apicWrite(0x300,0x000C4600); // INIT SIPI to all CPUs + for(tmp=0;tmp<800000;tmp++) asm("nop"); // Sleep a little (should be 200ms) + apicWrite(0x300,0x000C4600); // Second INIT SIPI + for(tmp=0;tmp<800000;tmp++) asm("nop"); // Sleep a little (should be 200ms) + } + + + +uInt32 getEflags() { + uInt32 eflags = 0x0; + asm( + "pushfl \n" + "popl %%eax \n" + : "=a" (eflags) + ); + return(eflags); + } + +void setEflags(uInt32 eflags) { + asm( + "pushl %%eax \n" + "popfl \n" + : + : "a" (eflags) + ); + } + +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" + ); + +/*** + END + ***/ + diff --git a/src/sys/kernel/spinlock.c b/src/sys/kernel/spinlock.c index 6cf460f..2e184f1 100644 --- a/src/sys/kernel/spinlock.c +++ b/src/sys/kernel/spinlock.c @@ -24,6 +24,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. $Log$ + Revision 1.1 2004/05/02 03:19:51 reddawg + Added Spinlock Provision For SMP + $Id$ @@ -35,7 +38,7 @@ *lock = SPIN_LOCK_INITIALIZER; } -inline void spin_unlock(spinLock_t *lock) { +inline void spinUnlock(spinLock_t *lock) { register int unlocked; __asm__ __volatile ( "xchgl %0, %1"