From 4c717bb526a0a7b1aa44ed7fc4f07a6b7da5d2f9 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 4 Dec 2011 22:13:41 +0800 Subject: [PATCH] Kernel - Fixing and breaking SMP related stuff --- Kernel/arch/x86/desctab.asm | 14 ++++++- Kernel/arch/x86/errors.c | 2 + Kernel/arch/x86/include/mm_virt.h | 4 ++ Kernel/arch/x86/kpanic.c | 34 +++++++++++++---- Kernel/arch/x86/mm_virt.c | 27 ++++++-------- Kernel/arch/x86/proc.asm | 5 ++- Kernel/arch/x86/proc.c | 61 ++++++++++++++++++------------- Kernel/arch/x86/start.asm | 15 +++++--- Modules/USB/Core/usb_lowlevel.c | 7 ++++ Modules/USB/UHCI/uhci.c | 6 +-- 10 files changed, 112 insertions(+), 63 deletions(-) diff --git a/Kernel/arch/x86/desctab.asm b/Kernel/arch/x86/desctab.asm index fa7b84b2..0c19fc0a 100644 --- a/Kernel/arch/x86/desctab.asm +++ b/Kernel/arch/x86/desctab.asm @@ -89,6 +89,7 @@ Desctab_Install: ; MP ISRs %if USE_MP + SETISR 0xED ; 0xED Inter-processor HALT SETISR 0xEE ; 0xEE Timer SETISR 0xEF ; 0xEF Spurious Interrupt %endif @@ -206,12 +207,21 @@ ISR_NOERR 31; 31: Reserved DEF_SYSCALL 0xAC ; Acess System Call %if USE_MP +[global Isr0xED] +; 0xED - Interprocessor HALT +Isr0xED: + cli +.jmp: hlt + jmp .jmp + [global Isr0xEE] [extern SchedulerBase] ; AP's Timer Interrupt Isr0xEE: - push 0 ; Line up with interrupt number - xchg bx, bx ; MAGIC BREAK + push eax ; Line up with interrupt number + mov eax, dr1 ; CPU Number + push eax + mov eax, [esp-4] ; Load EAX back jmp SchedulerBase ; Spurious Interrupt [global Isr0xEF] diff --git a/Kernel/arch/x86/errors.c b/Kernel/arch/x86/errors.c index c66e49d1..d73fcea4 100644 --- a/Kernel/arch/x86/errors.c +++ b/Kernel/arch/x86/errors.c @@ -5,6 +5,7 @@ */ #include #include +#include // === CONSTANTS === #define MAX_BACKTRACE 8 //!< Maximum distance to trace the stack backwards @@ -233,6 +234,7 @@ void Error_Backtrace(Uint eip, Uint ebp) while( MM_GetPhysAddr(ebp) && i < MAX_BACKTRACE ) { + if( ebp >= MM_KERNEL_STACKS_END ) break; //str = Debug_GetSymbol(*(Uint*)(ebp+4), &delta); if(str == NULL) LogF(" >> 0x%x", *(Uint*)(ebp+4)); diff --git a/Kernel/arch/x86/include/mm_virt.h b/Kernel/arch/x86/include/mm_virt.h index 4a11e716..31642c64 100644 --- a/Kernel/arch/x86/include/mm_virt.h +++ b/Kernel/arch/x86/include/mm_virt.h @@ -39,6 +39,10 @@ // 1024 items per page #define MM_REFCOUNT_BASE 0xE4000000 +#define MM_KERNEL_STACKS 0xF0000000 +#define MM_KERNEL_STACK_SIZE 0x00008000 +#define MM_KERNEL_STACKS_END 0xFC000000 + // === FUNCTIONS === extern void MM_FinishVirtualInit(void); extern void MM_SetCR3(Uint CR3); diff --git a/Kernel/arch/x86/kpanic.c b/Kernel/arch/x86/kpanic.c index ccb10737..6a7b9b0f 100644 --- a/Kernel/arch/x86/kpanic.c +++ b/Kernel/arch/x86/kpanic.c @@ -1,23 +1,34 @@ /* * Acess 2 Kernel - * By John Hodge (thePowersGang) + * - By John Hodge (thePowersGang) + * + * kpanic.c * - x86 Kernel Panic Handler */ #include +#include - - +// === CONSTANTS === #define FB ((Uint16 *)(KERNEL_BASE|0xB8000)) #define BGC 0x4F00 // White on Red //#define BGC 0xC000 // Black on Bright Red //#define BGC 0x1F00 // White on Blue (BSOD!) +// === IMPORTS === extern Uint32 GetEIP(void); extern void Error_Backtrace(Uint32 eip, Uint32 ebp); +#if USE_MP +extern void MP_SendIPIVector(int CPU, Uint8 Vector); +extern int giNumCPUs; +extern int GetCPUNum(void); +#endif - int giKP_Pos = 0; +// === PROTOTYPES === +void KernelPanic_SetMode(void); +void KernelPanic_PutChar(char Ch); +// === CONSTANTS === const struct { Uint16 IdxPort; Uint16 DatPort; @@ -57,9 +68,8 @@ const struct { }; #define NUM_REGVALUES (sizeof(caRegValues)/sizeof(caRegValues[0])) -// === PROTOTYPES === -void KernelPanic_SetMode(void); -void KernelPanic_PutChar(char Ch); +// === GLOBALS === + int giKP_Pos = 0; // === CODE === /** @@ -89,6 +99,16 @@ void KernelPanic_SetMode(void) inb(0x3DA); outb(0x3C0, 0x20); #endif + + #if USE_MP + // Send halt to all processors + for( i = 0; i < giNumCPUs; i ++ ) + { + if(i == GetCPUNum()) continue ; + FB[i] = BGC|'A'+i; + MP_SendIPIVector(i, 0xED); + } + #endif // Clear Screen for( i = 0; i < 80*25; i++ ) diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index af3d4bf0..73e19d3b 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -19,11 +19,8 @@ #define TAB 22 -#define KERNEL_STACKS 0xF0000000 -#define KERNEL_STACK_SIZE 0x00008000 -#define KERNEL_STACKS_END 0xFC000000 #define WORKER_STACKS 0x00100000 // Thread0 Only! -#define WORKER_STACK_SIZE KERNEL_STACK_SIZE +#define WORKER_STACK_SIZE MM_KERNEL_STACK_SIZE #define WORKER_STACKS_END 0xB0000000 #define NUM_WORKER_STACKS ((WORKER_STACKS_END-WORKER_STACKS)/WORKER_STACK_SIZE) @@ -125,7 +122,7 @@ void MM_InstallVirtual(void) { if( gaPageDir[ i ] ) continue; // Skip stack tables, they are process unique - if( i > KERNEL_STACKS >> 22 && i < KERNEL_STACKS_END >> 22) { + if( i > MM_KERNEL_STACKS >> 22 && i < MM_KERNEL_STACKS_END >> 22) { gaPageDir[ i ] = 0; continue; } @@ -515,7 +512,7 @@ tPAddr MM_Clone(void) Uint i, j; tVAddr ret; Uint page = 0; - tVAddr kStackBase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE; + tVAddr kStackBase = Proc_GetCurThread()->KernelStack - MM_KERNEL_STACK_SIZE; void *tmp; Mutex_Acquire( &glTempFractal ); @@ -587,9 +584,7 @@ tPAddr MM_Clone(void) } // Allocate kernel stack - for(i = KERNEL_STACKS >> 22; - i < KERNEL_STACKS_END >> 22; - i ++ ) + for(i = MM_KERNEL_STACKS >> 22; i < MM_KERNEL_STACKS_END >> 22; i ++ ) { // Check if directory is allocated if( (gaPageDir[i] & 1) == 0 ) { @@ -616,7 +611,7 @@ tPAddr MM_Clone(void) } // We don't care about other kernel stacks - if( ((i*1024+j)*4096 & ~(KERNEL_STACK_SIZE-1)) != kStackBase ) { + if( ((i*1024+j)*4096 & ~(MM_KERNEL_STACK_SIZE-1)) != kStackBase ) { gaTmpTable[i*1024+j] = 0; continue; } @@ -647,27 +642,27 @@ tVAddr MM_NewKStack(void) { tVAddr base; Uint i; - for(base = KERNEL_STACKS; base < KERNEL_STACKS_END; base += KERNEL_STACK_SIZE) + for(base = MM_KERNEL_STACKS; base < MM_KERNEL_STACKS_END; base += MM_KERNEL_STACK_SIZE) { // Check if space is free if(MM_GetPhysAddr(base) != 0) continue; // Allocate - //for(i = KERNEL_STACK_SIZE; i -= 0x1000 ; ) - for(i = 0; i < KERNEL_STACK_SIZE; i += 0x1000 ) + //for(i = MM_KERNEL_STACK_SIZE; i -= 0x1000 ; ) + for(i = 0; i < MM_KERNEL_STACK_SIZE; i += 0x1000 ) { if( MM_Allocate(base+i) == 0 ) { // On error, print a warning and return error Warning("MM_NewKStack - Out of memory"); // - Clean up - //for( i += 0x1000 ; i < KERNEL_STACK_SIZE; i += 0x1000 ) + //for( i += 0x1000 ; i < MM_KERNEL_STACK_SIZE; i += 0x1000 ) // MM_Deallocate(base+i); return 0; } } // Success -// Log("MM_NewKStack - Allocated %p", base + KERNEL_STACK_SIZE); - return base+KERNEL_STACK_SIZE; +// Log("MM_NewKStack - Allocated %p", base + MM_KERNEL_STACK_SIZE); + return base+MM_KERNEL_STACK_SIZE; } // No stacks left Log_Warning("MMVirt", "MM_NewKStack - No address space left"); diff --git a/Kernel/arch/x86/proc.asm b/Kernel/arch/x86/proc.asm index 4e7d1604..74a25d46 100644 --- a/Kernel/arch/x86/proc.asm +++ b/Kernel/arch/x86/proc.asm @@ -162,8 +162,7 @@ SetAPICTimerCount: pop es pop ds popa - add esp, 4 ; CPU ID - ; No Error code / int num + add esp, 8 ; CPU ID / Error Code iret %endif ; -------------- @@ -376,3 +375,5 @@ User_Syscall_Exit: xor eax, eax mov ebx, [esp+4] int 0xAC + +; vim: ft=nasm, ts=8 diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index dfde3591..9e8aa385 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -14,7 +14,7 @@ #include // === FLAGS === -#define DEBUG_TRACE_SWITCH 0 +#define DEBUG_TRACE_SWITCH 1 #define DEBUG_DISABLE_DOUBLEFAULT 1 #define DEBUG_VERY_SLOW_SWITCH 0 @@ -34,7 +34,6 @@ typedef struct sCPU Uint8 State; // 0: Unavaliable, 1: Idle, 2: Active Uint16 Resvd; tThread *Current; - tThread *IdleThread; } tCPU; // === IMPORTS === @@ -66,6 +65,7 @@ extern void Proc_DisableSSE(void); //void ArchThreads_Init(void); #if USE_MP void MP_StartAP(int CPU); +void MP_SendIPIVector(int CPU, Uint8 Vector); void MP_SendIPI(Uint8 APICID, int Vector, int DeliveryMode); #endif void Proc_IdleThread(void *Ptr); @@ -331,8 +331,8 @@ void ArchThreads_Init(void) Log("APIC Count %i", giMP_TimerCount); { Uint64 freq = giMP_TimerCount; - freq /= TIMER_DIVISOR; freq *= TIMER_BASE; + freq /= TIMER_DIVISOR; if( (freq /= 1000) < 2*1000) Log("Bus Frequency %i KHz", freq); else if( (freq /= 1000) < 2*1000) @@ -383,9 +383,12 @@ void ArchThreads_Init(void) } #if USE_MP +/** + * \brief Start an AP + */ void MP_StartAP(int CPU) { - Log("Starting AP %i (APIC %i)", CPU, gaCPUs[CPU].APICID); + Log_Log("Proc", "Starting AP %i (APIC %i)", CPU, gaCPUs[CPU].APICID); // Set location of AP startup code and mark for a warm restart *(Uint16*)(KERNEL_BASE|0x467) = (Uint)&APWait - (KERNEL_BASE|0xFFFF0); @@ -409,11 +412,17 @@ void MP_StartAP(int CPU) giNumInitingCPUs ++; } +void MP_SendIPIVector(int CPU, Uint8 Vector) +{ + MP_SendIPI(gaCPUs[CPU].APICID, Vector, 0); +} + /** * \brief Send an Inter-Processor Interrupt * \param APICID Processor's Local APIC ID * \param Vector Argument of some kind - * \param DeliveryMode Type of signal? + * \param DeliveryMode Type of signal + * \note 3A 10.5 "APIC/Handling Local Interrupts" */ void MP_SendIPI(Uint8 APICID, int Vector, int DeliveryMode) { @@ -421,23 +430,24 @@ void MP_SendIPI(Uint8 APICID, int Vector, int DeliveryMode) // Hi val = (Uint)APICID << 24; - Log("*%p = 0x%08x", &gpMP_LocalAPIC->ICR[1], val); +// Log("%p = 0x%08x", &gpMP_LocalAPIC->ICR[1], val); gpMP_LocalAPIC->ICR[1].Val = val; // Low (and send) val = ((DeliveryMode & 7) << 8) | (Vector & 0xFF); - Log("*%p = 0x%08x", &gpMP_LocalAPIC->ICR[0], val); +// Log("%p = 0x%08x", &gpMP_LocalAPIC->ICR[0], val); gpMP_LocalAPIC->ICR[0].Val = val; } #endif void Proc_IdleThread(void *Ptr) { - tCPU *cpu = Ptr; - cpu->IdleThread->ThreadName = strdup("Idle Thread"); - Threads_SetPriority( cpu->IdleThread, -1 ); // Never called randomly - cpu->IdleThread->Quantum = 1; // 1 slice quantum + tCPU *cpu = &gaCPUs[GetCPUNum()]; + cpu->Current->ThreadName = strdup("Idle Thread"); + Threads_SetPriority( cpu->Current, -1 ); // Never called randomly + cpu->Current->Quantum = 1; // 1 slice quantum for(;;) { - HALT(); + __asm__ __volatile__ ("sti"); // Make sure interrupts are enabled + __asm__ __volatile__ ("hlt"); // Make sure interrupts are enabled Proc_Reschedule(); } } @@ -461,7 +471,6 @@ void Proc_Start(void) // Create Idle Task tid = Proc_NewKThread(Proc_IdleThread, &gaCPUs[i]); - gaCPUs[i].IdleThread = Threads_GetThread(tid); // Start the AP if( i != giProc_BootProcessorID ) { @@ -473,7 +482,7 @@ void Proc_Start(void) gaCPUs[0].Current = &gThreadZero; // Start interrupts and wait for APs to come up - Log("Waiting for APs to come up\n"); + Log_Debug("Proc", "Waiting for APs to come up"); __asm__ __volatile__ ("sti"); while( giNumInitingCPUs ) __asm__ __volatile__ ("hlt"); #else @@ -484,9 +493,6 @@ void Proc_Start(void) // Set current task gaCPUs[0].Current = &gThreadZero; -// while( gaCPUs[0].IdleThread == NULL ) -// Threads_Yield(); - // Start Interrupts (and hence scheduler) __asm__ __volatile__("sti"); #endif @@ -906,18 +912,21 @@ void Proc_Reschedule(void) nextthread = Threads_GetNextToRun(cpu, curthread); - if(!nextthread) - nextthread = gaCPUs[cpu].IdleThread; if(!nextthread || nextthread == curthread) return ; #if DEBUG_TRACE_SWITCH - LogF("\nSwitching to task %i, CR3 = 0x%x, EIP = %p, ESP = %p\n", - nextthread->TID, - nextthread->MemState.CR3, - nextthread->SavedState.EIP, - nextthread->SavedState.ESP - ); + // HACK: Ignores switches to the idle threads + if( nextthread->TID == 0 || nextthread->TID > giNumCPUs ) + { + LogF("\nSwitching CPU %i to %p (%i %s) - CR3 = 0x%x, EIP = %p, ESP = %p\n", + GetCPUNum(), + nextthread, nextthread->TID, nextthread->ThreadName, + nextthread->MemState.CR3, + nextthread->SavedState.EIP, + nextthread->SavedState.ESP + ); + } #endif // Update CPU state @@ -926,7 +935,7 @@ void Proc_Reschedule(void) __asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(nextthread) ); // Save FPU/MMX/XMM/SSE state - if( curthread->SavedState.SSE ) + if( curthread && curthread->SavedState.SSE ) { Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF ); curthread->SavedState.bSSEModified = 0; diff --git a/Kernel/arch/x86/start.asm b/Kernel/arch/x86/start.asm index d504a5df..68bdc55d 100644 --- a/Kernel/arch/x86/start.asm +++ b/Kernel/arch/x86/start.asm @@ -120,6 +120,7 @@ APWait: .hlt: ;hlt jmp .hlt +[extern Proc_Reschedule] [global APStartup] APStartup: ;xchg bx, bx ; MAGIC BREAK! @@ -160,11 +161,13 @@ APStartup: mov ebx, [ebp+0x20] ; Read ID shr ebx, 24 ;xchg bx, bx ; MAGIC BREAK - ; CL is now local APIC ID + ; BL is now local APIC ID mov cl, BYTE [gaAPIC_to_CPU+ebx] xor ebx, ebx mov bl, cl ; BL is now the CPU ID + mov dr1, ebx ; Save the CPU number to a debug register + ; Mark the CPU as up mov BYTE [gaCPUs+ebx*8+1], 1 ; Decrement the remaining CPU count dec DWORD [giNumInitingCPUs] @@ -179,8 +182,6 @@ APStartup: ; Set TSS lea ecx, [ebx*8+0x30] ltr cx - ; Save the CPU number to a debug register - mov dr1, ebx ;xchg bx, bx ; MAGIC_BREAK ; Enable Local APIC @@ -196,9 +197,10 @@ APStartup: mov DWORD [ebp+0x0B0], 0 ; Send an EOI (just in case) ; CPU is now marked as initialised - sti - ;xchg bx, bx ; MAGIC BREAK + .hlt: + sti + call Proc_Reschedule hlt jmp .hlt %endif @@ -252,4 +254,5 @@ ALIGN 4096 Kernel_Stack_Top: gInitAPStacks: times 32*MAX_CPUS dd 0 - + +; vim: ft=nasm ts=8 diff --git a/Modules/USB/Core/usb_lowlevel.c b/Modules/USB/Core/usb_lowlevel.c index 65365d3b..0e53bad9 100644 --- a/Modules/USB/Core/usb_lowlevel.c +++ b/Modules/USB/Core/usb_lowlevel.c @@ -122,8 +122,15 @@ char *USB_int_GetDeviceString(tUSBDevice *Dev, int Endpoint, int Index) struct sDescriptor_String str; int src_len, new_len; char *ret; + + if(Index == 0) return strdup(""); USB_int_ReadDescriptor(Dev, Endpoint, 3, Index, sizeof(str), &str); + if(str.Length < 2) { + Log_Error("USB", "String %p:%i:%i:%i descriptor is undersized (%i)", + Dev->Host, Dev->Address, Endpoint, Index, str.Length); + return NULL; + } // if(str.Length > sizeof(str)) { // // IMPOSSIBLE! // Log_Error("USB", "String is %i bytes, which is over prealloc size (%i)", diff --git a/Modules/USB/UHCI/uhci.c b/Modules/USB/UHCI/uhci.c index 5ea35661..9ef8b0bc 100644 --- a/Modules/USB/UHCI/uhci.c +++ b/Modules/USB/UHCI/uhci.c @@ -97,8 +97,6 @@ int UHCI_Initialise(char **Arguments) cinfo->RootHub = USB_RegisterHost(&gUHCI_HostDef, cinfo, 2); LOG("cinfo->RootHub = %p", cinfo->RootHub); - UHCI_CheckPortUpdate(cinfo); - i ++; } @@ -271,7 +269,7 @@ int UHCI_IsTransferComplete(void *Ptr, void *Handle) ret = !(td->Control & (1 << 23)); if(ret) { td->_info.Callback = NULL; - td->Link = 1; + td->Link = 0; } return ret; } @@ -399,7 +397,7 @@ void UHCI_InterruptHandler(int IRQ, void *Ptr) } link = td->Link; if( td->_info.Callback != INVLPTR ) - td->Link = 1; + td->Link = 0; } if(frame == 0) -- 2.20.1