Page 1 of 2

virtual mode monitor

Posted: Mon Jul 09, 2007 5:29 pm
by xyjamepa
Hi...

I'm working on my virtual mode monitor,and virtual mode uses
(segments:offset pairs) for its addresses so would some one please
explain to me how to convert this address to a liner one,some math would be good also some code might help.


Thanx.

Posted: Mon Jul 09, 2007 7:18 pm
by frank
(segment * 0x10 (16 decimal)) + offset = linear

Posted: Mon Jul 09, 2007 8:29 pm
by xyjamepa
Hi...

First of all I'm using hardware multitasking,that means one tss
for each task,my virtual task runs at ring 0.
Okay now I have more questions:
do I need a special tss for GPF_handler?
when we are in virtual task and a GPF happens we do this steps,mI right?
*checking that the byte at cs:ip is 0xCD
*putting new ip,cs and FLAGS regs on the virtual task stack,why
do we need to do that?
*decrement the virtual task value of sp by 6 bytes,why do we need that?

Thanx.

Posted: Tue Jul 10, 2007 1:23 am
by urxae
abuashraf wrote:First of all I'm using hardware multitasking,that means one tss for each task,my virtual task runs at ring 0.
Okay now I have more questions:
do I need a special tss for GPF_handler?
I don't think so, when a GPF occurs it'll just look up the appropriate PM interrupt and invoke that. As long as that points to a PM routine that does the right thing (and the values in the TSS for SS0:ESP0 are valid) it should be fine. AFAIK there doesn't need to be any difference to software task switching here, since no task switching needs to be involved.
when we are in virtual task and a GPF happens we do this steps,mI right?
*checking that the byte at cs:ip is 0xCD
And IIRC there are some other values (=instructions) to check for and emulate. But assuming the byte was 0xCD:
*putting new ip,cs and FLAGS regs on the virtual task stack,why
do we need to do that?
*decrement the virtual task value of sp by 6 bytes,why do we need that?
Because you need to pretend the interrupt fired in real mode, and this is what an interrupt in real mode would push onto the stack. And the IP pushed should be incremented by 2 (the length of the INT imm8 instruction) so that when the interrupt returns it'll return after that instruction.

Also, don't forget to change the CS:IP the PM interrupt (i.e. the GPF) pushed onto the stack to point to the real mode interrupt handler so execution will continue there on IRET, and not keep looping (GPF, fake push onto VM86 stack, IRET, GPF, fake push, IRET, lather, rinse, repeat)...


Disclaimer: I have never actually written a VM86 monitor.

Posted: Tue Jul 10, 2007 9:27 am
by frank
There is a VM86 monitor you can use here

Here is a good explanation of virtual mode
http://osdev.berlios.de/v86.html

Posted: Tue Jul 10, 2007 10:42 am
by xyjamepa
Hi...

Right now I'm a littel bit confused about the virtual mode monitor,
so I'll till you what I understand,and if I'm wrong would you please correct me:
let's assume we are in a virtual task executing some code,when we get to an instruction such as int ,the processor raises a GPF here we goes to our
isrs_handler to handle this exception,we check the VM bit in EFLAGS register to see if we are in virtual mode,if so then we start our virtual mode monitor.


Thanx.

Posted: Tue Jul 10, 2007 5:45 pm
by pcmattman
Yes, and then the virtual mode monitor emulates the instruction...

Privileged instructions are outlined in the intel manual... You'll need to write wrappers for each one. The VM86 tutorial frank is talking about has a complete example of a virtual mode monitor.

Posted: Tue Jul 10, 2007 10:57 pm
by xyjamepa
Hi...

Okay finally I implemented a simple virtual mode monitor :) ,so now I can use BIOS INTs inside my os,but now I don't know how to go back to
protected mode,I use "lcall" to switch to another task and in the new task I use "iret" to go back to the original task,so I used iret but it didn't work.

what do you advice me guys?

Thanx.

Posted: Wed Jul 11, 2007 12:07 am
by pcmattman
Make some interrupt kill the task and reschedule.

You can do this in your INT emulator by checking which number it is and if it's your 'quit' one, do the quitting. I use 0x80 (because that's my OS syscall interrupt).

Posted: Wed Jul 11, 2007 10:41 am
by xyjamepa
Hi...

Let's assume I want my int number quiting be 0x80,so I check for this number and if I found it I make some interrupt kill the task and reschedule.

But would you please till me how can I do that with more details.

Thanx.

Posted: Wed Jul 11, 2007 12:36 pm
by Combuster

Code: Select all

syscall_handler()
{
    remove_thread(currentthread);
    schedule();
}
:roll:

Would you please specify what you do not understand about that?

Posted: Wed Jul 11, 2007 9:08 pm
by pcmattman
abuashraf wrote:Hi...

Let's assume I want my int number quiting be 0x80,so I check for this number and if I found it I make some interrupt kill the task and reschedule.

But would you please till me how can I do that with more details.

Thanx.

Code: Select all

				// 0xCD: INT n
				case 0xCD:
				
					// int80 = kill current task
					if( ip[1] == 0x80 )
					{
						// kill the current process
						kill( currpid() );
						
						// reschedule - this will change the ESP we return to... in a hardware multitasker this is a bit harder...
						resched();
						
						// return to the new task
						return;
					}
Of course, that's soft multitasking, but in hardware it couldn't be much harder.

In hardware I'd suggest modifying EFLAGS so the VM bit isn't set, that way any code executed after "int 0x80" is executed as 32-bit code, not 16-bit code. Then you can do your 'lcall' or whatever to switch tasks.

Posted: Wed Jul 11, 2007 11:17 pm
by xyjamepa
Hi...

I tried what pcmattman said,when ip[1]=0x80 r->eflags=0x202L
so here I should be out of virtual mode ,after that
I made a far jump to the selector of the main(),but unfortunately
I got debug exception.

Thanx.

Posted: Thu Jul 12, 2007 11:59 am
by xyjamepa
guys...would some one please till me how to get out
of virtual mode ....


Thanx.

Posted: Thu Jul 12, 2007 12:14 pm
by Combuster
any interrupt will do - either a software int by having the running task call int xx, an exception, or an external interrupt. Polls say the first option is the best way to go.