http://code.google.com/p/onyxkernel/wik ... ltitasking, which I know worked before.
Either way, some background --
It's a long mode OS -- however, the ELF64 is objcopy'd to a ELF32 to be loaded by GRUB (legacy).
Switch.S:
Code: Select all
.global Switch
.type Switch, @function
Switch:
push %r15
push %r14
push %r13
push %r12
push %r11
push %r10
push %r9
push %r8
push %rdx
push %rcx
push %rbx
push %rax
push %rbp
push %rsi
push %rdi
mov %rsp, %rdi
call puthex
movq %ds, %rbx
pushq %rbx
movq %es, %rbx
pushq %rbx
pushq %fs
pushq %gs
// Load the kernel data segment.
movw $0x10, %bp
movl %ebp, %ds
movl %ebp, %es
movl %ebp, %fs
movl %ebp, %gs
// AMD system V calling convention mandates first integer parameter is passed in %rdi
movq %rsp, %rdi // stack => rdi
call SwitchProcess
movq %rax, %rsp
mov $0x20, %al
outb %al, $0x20
mov $('I'), %rdi
call VT_PutChar
popq %gs
popq %fs
popq %rbx
movq %rbx, %es
popq %rbx
movq %rbx, %ds
pop %rdi
pop %rsi
pop %rbp
pop %rax
pop %rbx
pop %rcx
pop %rdx
pop %r8
pop %r9
pop %r10
pop %r11
pop %r12
pop %r13
pop %r14
pop %r15
// Return to where we came from.
mov %rsp, %rdi
call puthex
iretq
SwitchProcess:
Code: Select all
uint64_t SwitchProcess(uint64_t context)
{
TaskList[CurrentPID].StackPointer = context; // save the old context into current task
switch(CurrentPID)
{
case 0:
CurrentPID = 1;
break;
case 1:
CurrentPID = 0;
break;
}
return TaskList[CurrentPID].StackPointer; // Return new task's context.
}
CreateTask:
Code: Select all
void CreateTask(int id, char name[64], void (*thread)())
{
uint64_t* stack;
Task_type *Task = (Task_type*)HAL_DMemAllocateChunk(sizeof(Task_type));
Task->StackPointer = HAL_AllocatePage() + 0x800; // Allocate 4 kilobytes of space
memset((void*)((uint64_t)Task->StackPointer - 0x800), 0x00, 0x1000);
stack = (uint64_t*)Task->StackPointer;
// Expand down stack
// processor data
*--stack = 0x10; // SS
*--stack = 0; // UserESP
*--stack = 0x202; // RFLAGS
*--stack = 0x08; // CS
*--stack = (uint64_t)thread; // RIP
*--stack = 15; // R15
*--stack = 14; // R14
*--stack = 13; // R13
*--stack = 12; // R12
*--stack = 11; // R11
*--stack = 10; // R10
*--stack = 9; // R9
*--stack = 8; // R8
*--stack = 0xD; // RDX
*--stack = 0xC; // RCX
*--stack = 0xB; // RBX
*--stack = 0xA; // RAX
*--stack = 0xA0; // RSP
*--stack = 0xB0; // RBP
*--stack = 0xC0; // RSI
*--stack = 0xD0; // RDI
// data segments
*--stack = 0x10; // DS
*--stack = 0x10; // ES
*--stack = 0x10; // FS
*--stack = 0x10; // GS
Task->State = 1;
Task->StackPointer = (uint64_t)stack;
Task->Thread = thread;
// strcpy((char*)Task->Name, (char*)name);
printk("<%x>\n", (uint64_t)Task->StackPointer);
SetTaskInList(id, Task);
SetCurrentProcessID(id);
}
Code: Select all
void Idle();
void Idle2();
CreateTask(0, (char*)"Idle", Idle);
CreateTask(1, (char*)"Idle2", Idle2);
SetCurrentProcessID(0);
void Switch();
HAL_IDTSetGate(32, (uint64_t)Switch, 0x08, 0x8E);
asm("sti");
Any help?
I've used a bunch of hlt's and determined that the problem happens *at* the IRET.
Thanks for the help!
EDIT: Edited title and code to reflect changes
PS: You may be thinking -- where have I seen this question before..? Didn't this guy already ask these?
Yes! But that was a 32-bit OS, full of messy code C/P from tutorials -- this one is mostly from scratch, aside from this multitasking thing.