; MP ISRs
%if USE_MP
+ SETISR 0xED ; 0xED Inter-processor HALT
SETISR 0xEE ; 0xEE Timer
SETISR 0xEF ; 0xEF Spurious Interrupt
%endif
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]
*/
#include <acess.h>
#include <proc.h>
+#include <mm_virt.h>
// === CONSTANTS ===
#define MAX_BACKTRACE 8 //!< Maximum distance to trace the stack backwards
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));
// 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);
/*
* Acess 2 Kernel
- * By John Hodge (thePowersGang)
+ * - By John Hodge (thePowersGang)
+ *
+ * kpanic.c
* - x86 Kernel Panic Handler
*/
#include <acess.h>
+#include <proc.h>
-
-
+// === 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;
};
#define NUM_REGVALUES (sizeof(caRegValues)/sizeof(caRegValues[0]))
-// === PROTOTYPES ===
-void KernelPanic_SetMode(void);
-void KernelPanic_PutChar(char Ch);
+// === GLOBALS ===
+ int giKP_Pos = 0;
// === CODE ===
/**
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++ )
#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)
{
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;
}
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 );
}
// 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 ) {
}
// 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;
}
{
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");
pop es
pop ds
popa
- add esp, 4 ; CPU ID
- ; No Error code / int num
+ add esp, 8 ; CPU ID / Error Code
iret
%endif
; --------------
xor eax, eax
mov ebx, [esp+4]
int 0xAC
+
+; vim: ft=nasm, ts=8
#include <hal_proc.h>
// === FLAGS ===
-#define DEBUG_TRACE_SWITCH 0
+#define DEBUG_TRACE_SWITCH 1
#define DEBUG_DISABLE_DOUBLEFAULT 1
#define DEBUG_VERY_SLOW_SWITCH 0
Uint8 State; // 0: Unavaliable, 1: Idle, 2: Active
Uint16 Resvd;
tThread *Current;
- tThread *IdleThread;
} tCPU;
// === IMPORTS ===
//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);
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)
}
#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);
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)
{
// 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();
}
}
// Create Idle Task
tid = Proc_NewKThread(Proc_IdleThread, &gaCPUs[i]);
- gaCPUs[i].IdleThread = Threads_GetThread(tid);
// Start the AP
if( i != giProc_BootProcessorID ) {
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
// Set current task
gaCPUs[0].Current = &gThreadZero;
-// while( gaCPUs[0].IdleThread == NULL )
-// Threads_Yield();
-
// Start Interrupts (and hence scheduler)
__asm__ __volatile__("sti");
#endif
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
__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;
.hlt:
;hlt
jmp .hlt
+[extern Proc_Reschedule]
[global APStartup]
APStartup:
;xchg bx, bx ; MAGIC BREAK!
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]
; 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
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
Kernel_Stack_Top:
gInitAPStacks:
times 32*MAX_CPUS dd 0
-
+
+; vim: ft=nasm ts=8
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)",
cinfo->RootHub = USB_RegisterHost(&gUHCI_HostDef, cinfo, 2);
LOG("cinfo->RootHub = %p", cinfo->RootHub);
- UHCI_CheckPortUpdate(cinfo);
-
i ++;
}
ret = !(td->Control & (1 << 23));
if(ret) {
td->_info.Callback = NULL;
- td->Link = 1;
+ td->Link = 0;
}
return ret;
}
}
link = td->Link;
if( td->_info.Callback != INVLPTR )
- td->Link = 1;
+ td->Link = 0;
}
if(frame == 0)