Entering V8086 Mode
Posted: Sat Aug 11, 2007 9:39 pm
Ok, so in my little kernel I have setup some basic multitasking, it can currently only handle tasks in ring 0, but thats not a problem for the moment.
I'm trying to setup a v8086 task (so that I can call int 10h) but all I can seem to get is an invalid opcode exception... I know my multitasking code works for 32bit pmode tasks, so I think the problem must be in how I setup the v8086 task...
In my init thread, I do this to call int 10h with 10c (132x60 text mode):
cpu.Interrupt looks like this:
and InitThreadv86 (where I suspect the problem is):
I switch tasks like this:
Oh, and the output I get from my OS in bochs:
Sorry for the large amount of code posted, but I've been trying to get this working all day and am getting nowhere (now I'll wait for you gurus to spot hundreds of errors and make me seem stupid (please! any help would be appreciated))...
I'm trying to setup a v8086 task (so that I can call int 10h) but all I can seem to get is an invalid opcode exception... I know my multitasking code works for 32bit pmode tasks, so I think the problem must be in how I setup the v8086 task...
In my init thread, I do this to call int 10h with 10c (132x60 text mode):
Code: Select all
struct regs *r = (struct regs *)mem.Calloc(sizeof(struct regs));
r->eax = 0x10c;
cpu.Interrupt(0x10, r);
mem.Free(r);
Code: Select all
void ia32CPU::Interrupt(int num, struct regs *r)
{
unsigned char *code = (unsigned char *)0x10000;
*code++ = 0xCD; // INT
*code++ = num;
*code++ = 0xCD; // INT
*code++ = 0x80; // 0x80 = Kill task
*code++ = 0xEB; // Infinite...
*code++ = 0xFE; // ...Loop
struct threadStruct *v8086thread = (struct threadStruct *)mem.Calloc(sizeof(struct threadStruct));
scheduler.CreateThread(scheduler._kernelProcess, v8086thread, 0x1000);
mem.Copy(&((ia32ThreadData *)v8086thread->archdata)->v8086regs, r, sizeof(struct threadStruct));
r->cs = r->ds = r->es = r->fs = r->gs = r->ss = 0x1000;
r->eip = 0;
tasks.InitThreadv86(v8086thread, r);
v8086thread->name = "V8086 Thread";
scheduler.AddSchedule(v8086thread);
while (v8086thread->state != TS_DEAD) ;
mem.Copy(r, &((ia32ThreadData *)v8086thread->archdata)->v8086regs, sizeof(struct threadStruct));
mem.Free(v8086thread);
}
Code: Select all
void ia32Tasks::InitThreadv86(struct threadStruct *thread, struct regs *r)
{
struct ia32ThreadData *adata = (struct ia32ThreadData *)mem.Calloc(sizeof(struct ia32ThreadData));
unsigned int *stack = (unsigned int *)0x1FFF8;
*--stack = r->gs;
*--stack = r->fs;
*--stack = r->ds;
*--stack = r->es;
*--stack = GDT_KDATA;
*--stack = r->eip;
*--stack = 0x20202; // EFLAGS
*--stack = r->ebp;
*--stack = 0xFFF8; // ESP
*--stack = r->edi;
*--stack = r->esi;
*--stack = r->edx;
*--stack = r->ecx;
*--stack = r->ebx;
*--stack = r->eax;
*--stack = 0x10;
*--stack = 0x10;
*--stack = 0x10;
*--stack = 0x10;
adata->stack = stack;
adata->esp = (unsigned int)stack;
adata->v8086 = false;
thread->archdata = (void *)adata;
}
Code: Select all
void ia32Tasks::Switch(struct threadStruct *old, struct threadStruct *thread)
{
if ((old != null) && (((struct ia32ThreadData*)old->archdata)->v8086))
return;
cpu.BeginAtomic();
//console.WriteLine("Switch from (%s::%s) to (%s::%s)",
// (old == null) ? "null" : old->proc->name,
// (old == null) ? "null" : old->name,
// thread->proc->name, thread->name);
struct ia32ThreadData *data = (struct ia32ThreadData *)thread->archdata;
oldesp = (old != null) ? &((struct ia32ThreadData*)old->archdata)->esp : null;
newesp = data->esp;
if (thread->proc->system)
{
if (data->v8086)
globalTSS.esp = 0x1000;
else
globalTSS.esp = null;
globalTSS.ss = null;
}
else
{
globalTSS.esp = newesp;
globalTSS.ss = GDT_UDATA;
}
cpu.EndAtomic();
//write_cr3((unsigned long)data->pageDirectory);
taskDoSwitch();
}
Code: Select all
extern oldesp, newesp
global taskDoSwitch
taskDoSwitch:
pushf ; Save registers
pusha
push ds
push es
push fs
push gs
mov eax, [oldesp] ; Check if oldesp is null
cmp eax, 0
je switch
mov [eax], esp ; Save old esp value
switch:
mov esp, [newesp] ; Switch to the new task
pop gs
pop fs
pop es
pop ds
popa ; Restore registers
popf
ret
Code: Select all
Fatal Error
An error has occured which the system cannot recover from. Please reboot the sys
tem and report any information shown below should the problem persist
Invalid Opcode Exception
GS 0x10 FS 0x10 ES 0x10 DS 0x10
EDI 0x10C ESI 0x0 EBP 0x0 ESP 0x1FFCC EBX 0x0 EDX 0x0 ECX 0xFFF8 EAX 0x0
INT 6h/6 ERR 0
EIP 0x3 CS 0x8 EFLAGS 0x10282 USRESP 0x0 SS 0x10