[EDIT - uint32 = unsigned long - something which points to my main Win32 dev environment being c#!]
Sorry to appear with a multitasking question *again* but, well...
I have set up a TSS for my outgoing task (the kernel itself), and have loaded the TSS descriptor - this works fine. I then set up another task which is simply:
Code: Select all
void task()
{
for(;;);
}
Code: Select all
gdt_set_descriptor(4, (uint32)&tss[1], 0x67, 0x89, 0x00);
I then drop to an assembly function called mt_switch which does the following:
Code: Select all
[global _mt_switch]
_mt_switch:
jmp dword 0x20:0x00
jmp $
The thing is, the CPU appears to switch the task, but then triple faults as soon as it enters it. Bochs gives the following code as the culprit:
Code: Select all
add byte ptr ds:[eax], al:0000
I wondered if it was my timer interrupt causing the fault initially, but it happens even if I cli before the task switch.
Does anyone have any ideas about what is happening? The full code is listed below. If you need the code for any other functions to diagnose this, I'll post them.
Cheers,
Adam
Code: Select all
void mt_install()
{
//install multitasking support
memsetd((void*)&tss[0], 0, 0x100/4);
lldt(0); //loads ldtr with null
tss[0].trace_bitmap = tss[1].trace_bitmap = 0;
tss[0].io_map_addr = tss[1].io_map_addr = 0; /* I/O map just after the TSS */
tss[0].ldtr = tss[1].ldtr = 0x00; /* ldtr = 0 */
printf("Task is at 0x%x", &task); /*this printed value and the value of eip after the triple fault appear to match*/
tss[1].fs = tss[1].gs = 0x10; /* fs=gs=0 */
tss[1].ds = tss[1].es = tss[1].ss = 0x10; /* ds=es=ss = data segment */
tss[1].esp = (uint32)task_stack + 1024; /* sp points to task stack top - task_stack is declared as char task_stack[1024];*/
tss[1].cs = 0x08;
tss[1].eip = (uint32)&task; /* cs:eip point to task() */
tss[1].cr3 = (uint32)read_cr3; //use kernel page dir
tss[1].eflags = (uint32)0x0202;
//params = gdt entry, base, limit, access, granularity.
mmu_gdt_set_descriptor(3, (uint32)&tss[0], 0x67, 0x89, 0x00);
mmu_gdt_set_descriptor(4, (uint32)&tss[1], 0x67, 0x89, 0x00);
set_task_register(0x03*0x08); //does an ltr(0x18) - blank kernel tss
mt_switch(); //does a jmp 0x20:0x00
}