查看“Virtual Monitor”的源代码
←
Virtual Monitor
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
Virtual Monitor是在[[Virtual 8086 Mode|虚拟8086模式]]中设置和控制任务所需的一段代码。 == 要求 == * 必须启用[[Protected mode|保护模式]] * 必须支持[[Interrupt Service Routines|中断服务例程]],更具体地说,必须支持GPF(一般保护异常)的工作异常处理程序。 == 相关工作 == 嗯,你主要有两种风格: 要么你可以创建一个独立的任务,它将在你的操作系统中在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将不得不执行例如伪造中断,检查指令等操作。 一个好的做法是编写两个“核心”函数,这些函数将执行简单的操作,比如在虚拟任务的堆栈上推送一个值,在给定的段读取一个字:偏移量(比如[[Real Mode|实模式]]),从虚拟CS:IP获取当前执行的字节,等等。 例如,Chris Giese的Monitor中的此类方法列表包括 * <tt>unsigned peekb(unsigned seg, unsigned off);</tt> 它将返回位于seg:off的字节 * <tt>unsigned peekw(unsigned seg, unsigned off);</tt> 同上返回word字 * <tt>void pokeb(unsigned seg, unsigned off, unsigned val);</tt> 它将向seg:off写入一个字节 * <tt>void pokew(unsigned seg, unsigned off, unsigned val);</tt> 同上写入word * <tt>void v86_push16(uregs_t *regs, unsigned value);</tt> 这将调整寄存器映像,在堆栈上推送一个(16位)值。 * <tt>void v86_int(uregs_t *regs, unsigned int_num);</tt> 它实际上在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) === 论坛 === * [[Topic:9943|Problem with v86 mode and INT n instruction]] * [[Topic:10287|Issues while implementing VM86 support]] [[Category:X86 CPU]]
返回至“
Virtual Monitor
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
变体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息