Выбрать главу

Но стоп, - скажет здесь читатель, - а что же будет, если мы запустим две операционные системы и одна из них решит отобрать для своих целей кусочек физического, а не виртуального пространства памяти другой операционной системы, отобразив его в своей таблице трансляции? В обычных условиях это фатальная ошибка, которая быстро приведет две совместно работающие операционки к краху. Но если у нас есть VMM, то ситуация в корне меняется, ибо мы теперь можем запущенную операционную систему «одурачить», перехватив соответствующее обращение и подсунув ей не настоящий CR3, а специально подготовленную «пустышку». ОС, наивно полагая, что она полностью контролирует виртуальную память компьютера, на самом деле будет всего лишь изменять никак не связанную с настоящей таблицей трансляции область оперативной памяти. А обращения к ней, используя стандартные же механизмы виртуальной памяти, будет перехватывать все тот же VMM и синхронизировать в соответствии с ними настоящую таблицу трансляции. Красиво придумано, не правда ли? Собственно виртуальной машины у нас нет, просто мы тщательно контролируем работу операционной системы и при необходимости ловко манипулируем ею.

Набор ситуаций, «прерывающих» выполнение обычных программ и приводящих к вызову VMM, довольно гибко настраивается - вовсе не обязательно, скажем, реагировать на все обращения операционных систем к компьютерным портам ввода-вывода: достаточно указать, какие порты для какой операционной системы будут «выбрасывать» ее к VMM, а какие - работать как если бы VMM не существовало в природе. Причем догадаться о том, что ОС запущена «под неусыпным контролем», практически невозможно: VMM может, например, точно таким же образом фальсифицировать обращения к CPUID (информация о процессоре и поддерживаемых им технологиях), после чего запущенная на Pentium D операционная система будет искренне полагать, что работает, скажем, на Pentium 3 и что никакой поддержки технологий виртуализации этот процессор не предоставляет.

Фальсифицируется все - даже время. Для «подделки» данных счетчика тактов TSC (Time Stamp Counter) в Vanderpool, например, предусмотрен даже не один, а целых два способа - автоматический (к значению TSC прибавляется заданная VMM константа) и «ручной» (перехватываются обращения к RDTSC); аналогично нетрудно перехватить и обращение ОС к системному таймеру с запросом текущего времени. Эдакое «1984» в рамках одного конкретно взятого процессора с VMM в роли Министерства Правды.

В качестве завершающего штриха в описании Vanderpool Technology (VT) приведем блок-схему, поясняющую функционирование технологии и назначение десяти (да-да, всего десяти!) входящих в нее инструкций (рис. 2). Заметим также, что все вышесказанное относилось к варианту VT-x для x86-совместимых процессоров. Кроме нее существует слегка отличающаяся VT-i для процессоров Itanium, но работает она по тем же самым принципам, так что останавливаться на ней я не буду.

***
AMD Pacifica: «мы пойдем своим путем!»

Компьютерный мир помешался на совместимости: процессоры Intel и AMD сегодня поддерживают практически идентичные наборы инструкций, а «заклятые друзья» ревниво следят за тем, чтобы процессор конкурента никаких заметных преимуществ перед «родным» процессором не имел. Так, AMD скопировала у Intel набор инструкций SSE (1/2/3); Intel у AMD - 64-битную технологию AMD64 и входящий в ее состав NX-бит: называются они по-разному (SSE у AMD превратилась в 3Dnow! Professional; AMD64 у Intel - в EM64T), но большого значения для ПО это, по сути дела, не имеет. Просто есть некий софт (оптимизированный под SSE ли, под AMD64 - неважно), и производители процессоров стараются сделать все возможное, чтобы этот софт (независимо от того, для какого процессора он разрабатывался) мог запускаться и на их CPU. Из-за этих-то пресловутых требований совместимости до сих пор живет архитектура x86, создававшаяся скорее для микропроцессоров («ноги» i8086 растут из предназначавшегося для калькуляторов i8080) и крайне неудобная для любых современных процессоров (что Athlon, что Pentium вынуждены ее «на лету» преобразовывать в более подходящий для обработки формат). «Хоронили» ее по меньшей мере трижды - в связи с выходом процессоров «правильных» архитектур. Однако ж некогда процветавшие ветви RISC-машин сегодня зачахли, архитектура VLIW не получила должного распространения, а x86 и поныне «живее всех ее хоронивших» - колоссальный парк ПО, накопленного для этой архитектуры, сделал ее практически «непотопляемой». И в свете этого полная несовместимость технологий виртуализации от AMD и от Intel звучит как гром среди ясного неба.

Концептуально - перед нами все тот же выделенный менеджер виртуальных машин с широкими возможностями для перехвата управления у обычных операционных систем и неограниченными правами доступа. Практически - Pacifica проще, функционально богаче и «дружественнее» к разработчику VMM3 (рис. 3). Судите сами: например, можно отказаться от хитроумной и трудоемкой технологии подмены таблиц трансляции виртуальной памяти, используя двухуровневые таблицы. Обычно в таблице трансляции виртуальной памяти записываются физические адреса, но ведь там можно хранить и виртуальные адреса «второго уровня», для которых тоже будет существовать своя, определяемая исключительно VMM, таблица. То есть так же, как операционная система обеспечивает запущенным в ней программам персональные «линейные» участки виртуальной памяти, VMM просто-напросто предоставляет каждой из запущенных операционок свою «виртуальную физическую» оперативную память. И точно так же, как обычная программа не замечает подвоха в работе оперативной памяти, «одураченная» операционная система не будет подозревать, что работает она не в физическом, а в виртуальном адресном пространстве. Не нужно ничего отлавливать, перехватывать и синхронизировать - все происходит в автоматическом режиме, без малейших усилий со стороны VMM. Не совсем понятно, почему Intel отказалась от этого очевидного и радикально упрощающего жизнь программистам шага, однако в текущем варианте несчастные программисты у Intel фактически вынуждены будут дублировать основную функциональность ядра операционной системы (в вопросах, касающихся управления памятью).

Вторая принципиальная «фича» AMD’шной виртуализации - это Tagged TLB, тегированный кэш трансляции виртуальных адресов. TLB представляет собой буфер, позволяющий процессору не заниматься каждый раз чрезвычайно трудоемкой и медленной процедурой преобразования виртуального адреса в физический, а сделать это единожды и впоследствии быстро обращаться к уже вычисленным парам соответствия «виртуальная память - память реальная». Понятно, что при каждом переключении от одной программы к другой (не говоря уже о переключении от одной операционной системы к VMM и обратно), когда процессору приходится переключаться между разными виртуальными пространствами памяти, этот буфер со всей ранее накопленной информацией приходится сбрасывать - в новом виртуальном пространстве старым виртуальным адресам будут соответствовать совсем другие «физические». А значит, каждое переключение к VMM и обратно - это вопиющее расточительство процессорных ресурсов, десятки и сотни тысяч потраченных на восстановление потерянной информации тактов. В реализации AMD буфер TLB запоминает, какой из виртуальных операционных систем какой адрес принадлежит. В обычной ситуации запоминать эту информацию бессмысленно - при переключении задач TLB все равно быстро заполнится новыми адресами, вытесняющими старые; а вот для быстрого переключения от OS к VMM и обратно (когда, возможно, работа VMM не займет и сотни тактов процессорного времени) подобная оптимизация приходится как нельзя более кстати.