Virtual Monitor
跳到导航
跳到搜索
Virtual Monitor是在虚拟8086模式中设置和控制任务所需的一段代码。
要求
相关工作
嗯,你主要有两种风格: 要么你可以创建一个独立的任务,它将在你的操作系统中在V86模式下作为其他任务单独运行,或者你可以暂时从当前任务切换到V86模式,执行一个简单的命令,然后回来。
你需要知道的是,有些操作在V86模式下是被禁止的,但是像BIOS或DOS程序这样的遗留代码仍然会发出它们。 因此,你需要挂接GPF处理程序,以便它检测到来自虚拟模式任务的错误操作,并将其推迟到monitor执行。 如何设置虚拟任务?
VM任务的设置与操作系统中任何“普通”进程的设置有一些区别:
- 如果使用分页,则需要确保将BIOS、实模式IVT和任何与BIOS相关的数据(例如,0xb8000处的视频RAM)映射到预期的虚拟地址。 这可以简单地通过Identity Paging这个过程的第一兆字节的地址空间来完成,或者你可能希望将这些位置的私有副本提供给不同的VM任务。
- 在任务控制块(TCB-Task Control Block)中,当你为初始运行在堆栈映像上设置寄存器时,你必须初始化一些附加标志(请参阅Tim Robinson的教程)。 确保至少有EFLAGS=VM|IF,即0x20202。 ip/cs值必须位于可以通过实模式访问的区域内,并且最好使堆栈与某些0xffff地址对齐。
- 你还需要设置一些额外的字段:段寄存器,处理器返回vm86进程时会弹出堆栈。最好你也为vm86任务创建一个堆栈映像结构:比如vm86_context_t。
- 如果你想要允许V86代码在没有GPF的情况下访问端口,则需要将TSS扩展8192字节(足够65,536个端口,每个端口一位),将I/O映射字段指向位图的开头,并将所有位设置为零。
第二点注意: 对于从0x100000到0x1fffef (iirc) 的区域,你可以映射任何你想要的页面。 只有第一个mb需要进行身份映射。
- 任务控制块(Task Control Block)
- 内核用于记录任务信息的结构: 处理器注册转储,页面目录,运行时间,优先级等。
一般保护故障(GPF-General Protection Faults)的作用
基本上,每当CPU需要Virtual Monitor的干预时,它都会引发GPF异常。一旦检测到异常是由虚拟任务引起的,就调用Monitor的GPF处理程序。
在那里,你需要阅读当前尝试的指令 (注意诸如ES:,REPNE等前缀),并决定如何模仿它...
需要支持的操作码包括:
- 0x9C(pushf)和 0x9D(popf)
- 0xCD(int nn)和 0xCF(iret)
- INx/OUTx (0xE4-0xE7,0x6C-0x6F,0xEC-0xEF),除非你相应地设置了io权限bitmap/iopl
- 0xFA(cli)和0xFB(sti)
我应该如何继续?
你的Monitor将不得不执行例如伪造中断,检查指令等操作。 一个好的做法是编写两个“核心”函数,这些函数将执行简单的操作,比如在虚拟任务的堆栈上推送一个值,在给定的段读取一个字:偏移量(比如实模式),从虚拟CS:IP获取当前执行的字节,等等。
例如,Chris Giese的Monitor中的此类方法列表包括
- unsigned peekb(unsigned seg, unsigned off); 它将返回位于seg:off的字节
- unsigned peekw(unsigned seg, unsigned off); 同上返回word字
- void pokeb(unsigned seg, unsigned off, unsigned val); 它将向seg:off写入一个字节
- void pokew(unsigned seg, unsigned off, unsigned val); 同上写入word
- void v86_push16(uregs_t *regs, unsigned value); 这将调整寄存器映像,在堆栈上推送一个(16位)值。
- void v86_int(uregs_t *regs, unsigned int_num); 它实际上在vmode中调用INT。
没有IF相关指令的硬件中断
你可以使用两种intel认同的技巧:
- 初始化时设置IOPL=3。 这不会影响IN/OUT指令,而是允许VM任务自己弄IF标志。 注意irq和软件中断将直接进入IDT (例如,IVT被忽略), 因此,你可能需要在pm IRQ处理程序中编写代码,根据该IVT编辑CS:IP值。
- 使用 “虚拟模式扩展(Virtual Mode Extensions)”,这将允许你给TSS一个 “中断重定向位图(interrupt redirection bitmap)”,告诉哪个中断应该使用IVT在虚拟模式下处理,哪个中断应该使用IDT在保护模式下处理。 不过,在QEMU上不能使用VME。
另见
外部链接
- http://alexfru.chat.ru/epm.html#v86monitor
- http://osdev.berlios.de/v86.html - TimRobinson's vm86-tutorial (dead link, available on archive.org at https://web.archive.org/web/20090719085533/http://osdev.berlios.de/v86.html)
- http://my.execpc.com/~geezer/osd/pmode/v86mm.zip - Chris Giese's YAV86MM
- http://oslib.cvs.sourceforge.net/viewvc/oslib/oslib/xlib/vm86.c?view=markup - OSLib's basic vm86 code (pages-tuning required)