В микропроцессоре 80386 и более поздних версиях виртуальный режим 8086 (также называемый виртуальным реальным режимом , V86-режимом или VM86 ) позволяет выполнять приложения реального режима , которые не могут работать напрямую в защищенном режиме , пока процессор работает под управлением операционной системы защищенного режима. Это аппаратная технология виртуализации , которая позволяла эмулировать несколько процессоров 8086 чипом 386. Она возникла из болезненного опыта с защищенным режимом 80286 , который сам по себе не подходил для одновременного запуска приложений реального режима. [1] Джон Кроуфорд разработал бит виртуального режима в наборе регистров, проложив путь к этой среде. [2]
Режим VM86 использует схему сегментации, идентичную схеме реального режима (из соображений совместимости), которая создает 20-битные линейные адреса таким же образом, как создаются 20-битные физические адреса в реальном режиме, но подчиняется механизму страничного обмена памятью защищенного режима .
Виртуальный режим 8086 — это режим для задачи защищенного режима . Следовательно, процессор может переключаться между задачами VM86 и не-VM86, позволяя использовать многозадачные устаревшие приложения ( DOS ).
Чтобы использовать виртуальный режим 8086, операционная система устанавливает монитор виртуального режима 8086, который представляет собой программу, управляющую программой реального режима и эмулирующую или фильтрующую доступ к системным аппаратным и программным ресурсам. Монитор должен работать на уровне привилегий 0 и в защищенном режиме. Только программа 8086 работает в режиме VM86 и на уровне привилегий 3. Когда программа реального режима пытается выполнить действия, такие как доступ к определенным портам ввода-вывода для использования аппаратных устройств или доступ к определенным областям в своем пространстве памяти, ЦП перехватывает эти события и вызывает монитор V86, который проверяет, что программа реального режима пытается сделать, и либо действует как прокси для взаимодействия с оборудованием, либо эмулирует предполагаемую функцию, к которой программа реального режима пыталась получить доступ, либо завершает программу реального режима, если она пытается сделать что-то, что не может быть разрешено или адекватно поддерживаться (например, перезагрузить машину, установить видеодисплей в режим, который не поддерживается оборудованием и не эмулируется, или перезаписать код операционной системы).
Монитор V86 также может мягко отказать в разрешении, эмулируя сбой запрошенной операции — например, он может заставить дисковод всегда выглядеть неготовым, когда на самом деле он даже не проверял дисковод, а просто не разрешает программе реального режима получить к нему доступ. Кроме того, монитор V86 может делать такие вещи, как отображение страниц памяти, перехват вызовов и прерываний и вытеснение программы реального режима, позволяя программам реального режима быть многозадачными, как программы защищенного режима. Перехватывая аппаратный и программный ввод-вывод программы реального режима и отслеживая состояние, которое ожидает программа V86, он может позволить нескольким программам совместно использовать одно и то же оборудование, не мешая друг другу. [a] Таким образом, режим V86 предоставляет возможность программам реального режима, разработанным для однозадачной среды (например, DOS [b] ), работать одновременно в многозадачной среде.
Он используется для выполнения определенных программ DOS в FlexOS 386 (с 1987 г.), Concurrent DOS 386 (с 1987 г.), Windows/386 2.10 (с 1987 г.), DESQview 386 (с 1988 г.), Windows 3.x (с 1990 г.), Multiuser DOS (с 1991 г.), Windows for Workgroups 3.1x (с 1992 г.), OS/2 2.x (с 1992 г.), 4690 OS (с 1993 г.), REAL/32 (с 1995 г.), работающих в 386 Enhanced Mode , а также в Windows 95 , 98 , 98 SE и ME через виртуальные машины DOS , в SCO UNIX через Merge и в Linux через DOSEMU . (Другие программы DOS , которые используют защищенный режим, выполняются с использованием пользовательского режима под эмулятором.) NTVDM в x86 Windows NT операционные системы также используют режим VM86, [3] но с очень ограниченным прямым аппаратным доступом. Некоторые загрузчики (например, GRUB ) используют защищенный режим и выполняют вызовы прерываний BIOS в режиме Virtual 8086. [4] [5]
Наиболее распространенной проблемой при запуске кода 8086 из защищенного режима является адресация памяти , которая полностью отличается в защищенном режиме и реальном режиме . Как уже упоминалось, при работе в режиме VM86 механизм сегментации перенастраивается для работы так же, как в реальном режиме, но механизм страничного обмена по-прежнему активен и прозрачен для кода реального режима; таким образом, защита памяти по-прежнему применима, как и изоляция адресного пространства.
При возникновении прерываний (аппаратных, программных и инструкций int) процессор отключает режим VM86 и возвращается к работе в полностью защищенном режиме для обработки прерывания. Также перед обслуживанием прерывания регистры DS, ES, FS и GS помещаются в новый стек и обнуляются.
Архитектура Pentium добавила ряд улучшений к виртуальному режиму 8086. Однако они были задокументированы Intel только начиная с последующей P6 (микроархитектура) ; [6] их более позднее официальное название — Virtual-8086 Mode Extensions, сокращенно VME [7] (в более старой документации может использоваться «Virtual 8086 mode enhancements» в качестве расширения аббревиатуры VME). [6] Некоторые более поздние чипы Intel 486 также поддерживают его. [8] [9] Улучшения в основном касаются накладных расходов виртуализации 8086, с особым акцентом на (виртуальные) прерывания. [6] [10] До того, как расширения были публично задокументированы в документации P6, официальная документация ссылалась на знаменитое Приложение H , которое было исключено из публичной документации и предоставлено только избранным партнерам в соответствии с NDA .
Активация VME выполняется установкой бита номер 0 (0x1 в значении) CR4 . Поскольку улучшения ускорения прерываний VME были признаны полезными для задач, не защищенных VM86, их также можно включить отдельно, установив только бит номер 1 (0x2 в значении), который называется PVI (виртуальные прерывания защищенного режима). [6] [9] Определение того, поддерживает ли процессор VME (включая PVI), выполняется с помощью инструкции CPUID с начальным значением EAX 0x1, путем проверки значения второго бита (бит номер 1, 0x2 в значении) в регистре EDX, который устанавливается, если процессор поддерживает VME. [11] [6] В Linux этот последний бит сообщается как флаг vme в файле /proc/ cpuinfo в разделе «flags».
В виртуальном режиме 8086 основная идея заключается в том, что когда IOPL меньше 3, инструкции PUSHF/POPF/STI/CLI/INT/IRET будут обрабатывать значение VIF в реальном 32-битном регистре EFLAGS как значение IF в имитируемом 16-битном регистре FLAGS (32-битный PUSHFD/POPFD продолжает ошибку GP). VIP вызовет ошибку GP при установке имитируемого IF, указывая ОС на обработку любых ожидающих прерываний. PVI — та же идея, но влияет только на инструкции CLI/STI.
Было обнаружено, что процессоры AMD Ryzen первого поколения имеют неисправную реализацию VME. [12] Во втором поколении Ryzen (серия 2000) эта проблема была устранена. [13]
Режим Virtual 8086 недоступен в длинном режиме x86-64 , хотя он по-прежнему присутствует на процессорах с поддержкой x86-64, работающих в устаревшем режиме .
Intel VT-x возвращает возможность запуска виртуального режима 8086 из длинного режима x86-64, но это необходимо сделать путем перевода (физического) процессора в корневой режим VMX и запуска логического (виртуального) процессора, работающего в виртуальном режиме 8086. [14]
Процессоры Westmere и более поздние процессоры Intel обычно [15] могут запускать виртуальный процессор непосредственно в реальном режиме, используя функцию «неограниченного гостя» (которая сама по себе требует расширенных таблиц страниц ); этот метод устраняет необходимость прибегать к вложенному виртуальному режиму 8086 просто для запуска устаревшего BIOS для загрузки. [16] [17]
AMD-V также может использовать виртуальный режим 8086 в гостевых системах, но он также может просто запустить гостевую систему в «реальном режиме с подкачкой», выполнив следующие шаги: вы создаете гостевую систему в режиме SVM (Secure Virtual Machine) с CR0.PE=0, но CR0.PG=1 (то есть с отключенным защищенным режимом, но включенным подкачкой), что обычно невозможно, но разрешено для гостевых систем SVM, если хост перехватывает ошибки страниц. [18]
{{cite journal}}
: Цитировать журнал требует |journal=
( помощь )запись VM разрешена только для гостей с включенным подкачкой, которые находятся в защищенном режиме или в режиме virtual-8086. Выполнение гостя в других режимах работы процессора должно быть специально обработано VMM; см. также CS 686: Специальная тема: Intel EM64T и расширения VT (весна 2007 г.), урок 24, как это сделать из Linux (не то чтобы код сильно устарел, поэтому может не работать как есть с текущими ядрами), более современный код можно найти здесь. Также имейте в виду, что этот пример кода сложнее, чем строгая загрузка логического процессора в виртуальном режиме 8086; его конечная цель — сделать несколько вызовов BIOS в реальном режиме.
Список процессоров Intel, которые поддерживают VT-x, но не EPT
Для облегчения виртуализации реального режима инструкция VMRUN может законно загружать гостевое значение CR0 с PE = 0, но PG = 1. Аналогично, инструкции RSM разрешено возвращаться в страничный реальный режим. Этот режим процессора ведет себя во всех отношениях как реальный режим, за исключением того, что применяется подкачка. Цель состоит в том, чтобы VMM запускал гостя в странично-реальном режиме на CPL0 и с перехваченными ошибками страниц. VMM отвечает за настройку теневой таблицы страниц, которая сопоставляет гостевую физическую память с соответствующими системными физическими адресами. Поведение запуска гостя в страничном реальном режиме без перехвата ошибок страниц в VMM не определено.