Page 1 of 2

Pseudo VM86 Monitor

Posted: Mon Jun 18, 2007 8:07 pm
by astrocrep
I do NOT plan on running 16bit code in my OS, I also do not plan on executing 16bit drivers in my OS. However, I do need 16bit vm86 for VESA.

What I was think is creating a Task, with the vm86 flag set, that basically does:

Code: Select all


void *fncINT0x10() = ... //Address stored at int 0x10 Vector.
void set_640x480x16
{
 _AX = 0x12;
 fncINT0x10();
}
 
Would that work? I don't see why not. I do not need to emulate the int instruction, I can just bypass it and jump to the code pointer.

I really do Not plan on using vm86 for anything more than that.

What do you think?

Thanks,
Rich

Posted: Mon Jun 18, 2007 11:53 pm
by distantvoices
Alas, to my great unhappiness, i have to tell you, that you 're gonna need a vm86 monitor to catch all the privileged instructions: in, out, push, pop, int ... they all occur, even in 16 bit bios code, which you're definitely gonna call to switch to any vbe/vesa graphics mode.

Besides, depending on your memory setup, you'll have to do a lot more stuff to get the vm86 task up and running.

Hint: google for "tim robinson vm86 tutorial" to get some fine stuff about vm86 monitors.

Stay safe.

Re: Pseudo VM86 Monitor

Posted: Tue Jun 19, 2007 12:05 am
by Brendan
Hi,
astrocrep wrote:I do NOT plan on running 16bit code in my OS, I also do not plan on executing 16bit drivers in my OS. However, I do need 16bit vm86 for VESA.
In this case you'd need to setup a real mode compatible environment - e.g. a dummy IDT, identity map the video card's ROM at 0x000C0000, setup a real mode stack, etc. You'd also need a VM86 monitor, which mostly means handling some things in your general protection fault handler (emulating CLI, STI, I/O port instructions, etc) and working out what happens with IRQs (IIRC there's 2 different mechanisms for this).

There's an alternative though - you can run an emulator. For example, several open source projects use something called "x86emu" to initialize and use real mode video BIOS code.

There's also another alternative - setup the video mode before you switch to protected mode. ;)


Cheers,

Brendan

Posted: Tue Jun 19, 2007 2:35 am
by Aali
you dont need to worry about IRQ's for video BIOS code though
just in/out, pushf/popf, etc

Posted: Tue Jun 19, 2007 5:05 am
by astrocrep
Ok, so the first 4mb is identity mapped. Though, I don't understand why I am going to need push/pop and in/out. Are they something the video init code calls?

I know the small amount of code that will actually go through the vm86 will just be pseudo int calls to set the video mode or get vesa info, and niether of those commands need push/pop or in/out.

Thanks,
Rich

Posted: Tue Jun 19, 2007 11:14 am
by inflater
astrocrep wrote:Ok, so the first 4mb is identity mapped. Though, I don't understand why I am going to need push/pop and in/out. Are they something the video init code calls?

I know the small amount of code that will actually go through the vm86 will just be pseudo int calls to set the video mode or get vesa info, and niether of those commands need push/pop or in/out.

Thanks,
Rich
Wouldn't be easier to switch to real mode for now and then jump back to protected mode? I can send some code (in assembly though) but it may not be compatible with your OS.

inflater

Posted: Tue Jun 19, 2007 11:46 am
by astrocrep
Humm...

That seems pretty interesting...

However, If my instruction pointer is somewhere off at physical 1.1mb mark, how to I get it to run code down at some lower mark, say 300k mark? Also how can I be sure I don't clobber my existing setup. Would it really be just as easy as switching off the PM BIT, running the interrupt, and then loading the PM BIT back on? Or do I need to rebuild paging and setup my gdt/ldt/idt again?

Yea, I would be really interested in seeing some code.

Thanks,
Rich

Posted: Tue Jun 19, 2007 12:55 pm
by inflater
astrocrep wrote:Humm...

That seems pretty interesting...

However, If my instruction pointer is somewhere off at physical 1.1mb mark, how to I get it to run code down at some lower mark, say 300k mark? Also how can I be sure I don't clobber my existing setup. Would it really be just as easy as switching off the PM BIT, running the interrupt, and then loading the PM BIT back on? Or do I need to rebuild paging and setup my gdt/ldt/idt again?

Yea, I would be really interested in seeing some code.

Thanks,
Rich
*cough**cough*Paging?*cough*
I never implemented paging in my OS (well I am just learning protected mode segmentation, and comparing the differences between real mode), so you will have to setup your GDT and IDT (and paging too) all over again, if you want to switch to real mode. But I suggest that you really call INT 10h with VESA before entering protected mode...

Here is some code (again, not my code, but may help you) attached.

inflater

Posted: Tue Jun 19, 2007 1:05 pm
by Aali
well, you have to realize that your vm86 monitor must be able to take care of the actual video BIOS code

"int 10" or whatever doesn't do any sort of magic, it just looks up entry #10 in the real mode IDT and loads CS:IP from there (you must of course emulate this behaviour too)

these new CS:IP values usually point to the relevant function in the BIOS code, which in turn does the hardware interfacing which of course needs in/out

pushf/popf was just another example of something you must emulate (because the real mode code is usually not allowed to modify certain flags)

Posted: Tue Jun 19, 2007 1:08 pm
by astrocrep
What I still don't get is how edo I get the 16bit code below the 1mb mark?

Or does that not matter?

Thanks
-Rich

Posted: Tue Jun 19, 2007 1:47 pm
by jnc100
astrocrep wrote:What I still don't get is how edo I get the 16bit code below the 1mb mark?
One of the good things about v8086 is you can use paging. Say you create a simple real mode task that is linked to run at real-mode address 0x1000:0x0000. All you have to do is load it anywhere in physical memory, create a new page directory for your v8086 task and one page table for the lowest 4MB, map the program to virtual address 0x10000, map the first 4kB of physical memory and 640kB - 1MB linearly and run the task. This means you can have multiple v8086 tasks running at once, all from the same linear address. Obviously you still need a v8086 monitor. pcmattman posted one a while back that seemed quite decent.

If you want to do it by dropping back to real mode, then I guess you'll need to memcpy the executable from wherever you load it to its load address under 1MB before you drop back.

Regards,
John.

Posted: Tue Jun 19, 2007 9:09 pm
by slasher
I have VM86 working just for use with VESA. I didn't implement a full monitor, just a special check in the general fault handler to see if the error occurred while in vm86 mode.

If the error ocurred in vm86 mode then the running process is killed and the parent(the one that spawned the vm86 process) is signalled that the vm86 task has completed.
I mark int 0x40 in the TSS iomap(think that is what its called) so that a call to int 0x40 from vm86 mode triggers a gp fault.

Basically, only my vesa code needs this, so a full blown vm86 monitor was unnecessary.

I'll give a full explanation of how I did it,Once I gather all the relevant lines of code.

p.s. This method works on real pc,vmware and Bochs. It seems not to work in qemu.(dont know why)

Posted: Wed Jun 20, 2007 3:05 am
by bluecode
Why did none of you mention Virtual-8086-Mode Extensions? With that you don't need a virtual-8086-monitor. 8) :idea:

Posted: Wed Jun 20, 2007 3:12 am
by Combuster
bluecode wrote:Why did none of you mention Virtual-8086-Mode Extensions? With that you don't need a virtual-8086-monitor. 8) :idea:
You'll still need it for when a program wants to exit v8086 mode

Posted: Thu Jun 21, 2007 9:45 am
by bluecode
Combuster wrote:
bluecode wrote:Why did none of you mention Virtual-8086-Mode Extensions? With that you don't need a virtual-8086-monitor. 8) :idea:
You'll still need it for when a program wants to exit v8086 mode
Not really, you can redirect a vm-interrupt to the protected mode idt and place a task gate in that idt entry. That's what I did.