Да, они требуют машинного кода и всех операндов памяти.
Разве ЦП не должен обращаться к страницам памяти последовательно, то есть сначала читать инструкцию, а затем обращаться к операнду памяти?
Да, это логично, что происходит, но исключение ошибки страницы прерывает этот двухэтапный процесс и отбрасывает любой прогресс. Процессор не может вспомнить, какую инструкцию он выполнял в середине, когда произошел сбой страницы.
Когда обработчик сбоя страницы возвращается после обработки допустимого сбоя страницы, RIP = адрес ошибочной инструкции, поэтому процессор повторяет ее выполнение с нуля .
Для ОС было бы законно изменить машинный код неисправной инструкции и ожидать его выполнить другую команду после iret
из обработчика ошибок страницы (или любого другого обработчика исключений или прерываний). Таким образом, AFAIK архитектурно требует, чтобы процессор повторял выборку кода из CS: RIP в случае, о котором вы говорите. (Предполагая, что он даже возвращается к отказавшему CS: RIP вместо планирования другого процесса в ожидании сбоя диска на жесткой странице или доставки SIGSEGV обработчику сигнала при ошибке неверной страницы.)
Возможно, это также архитектурно необходим для входа / выхода гипервизора. И даже если это явно не запрещено на бумаге, это не то, как работают процессоры.
@ torek комментирует, что Некоторые (CIS C) микропроцессоры частично декодируют инструкции и выдают состояние микрорегистра при сбое страницы , но x86 не такой.
Некоторые инструкции прерываются и могут выполнять частичный прогресс, например rep movs
(memcpy в банке) и другие строковые инструкции, или собирать хранилища load / scatter , Но единственным механизмом является обновление архитектурных регистров, таких как RCX / RSI / RDI для строковых операций, или регистров назначения и маски для сборок (например, руководство для AVX2 vpgatherdd
). Отсутствие кода операции / декодирования приводит к некоторому скрытому внутреннему регистру и перезапускает его после iret из обработчика ошибок страницы. Это инструкции, которые осуществляют несколько отдельных обращений к данным.
Также имейте в виду, что x86 (как и большинство ISA) гарантирует, что инструкции являются атомами c по отношению к ним. прерывания / исключения: они либо полностью происходят, либо не происходят вообще, до прерывания. Прерывание инструкции по сборке во время работы . Так, например, add [mem], reg
потребуется, чтобы сбросить нагрузку, если часть хранилища вышла из строя, даже без префикса lock
.
Наихудшее число присутствующих гостевых страниц пространства пользователя для продвижения вперед может быть 6 (плюс отдельные поддеревья таблицы страниц гостевого ядра для каждого из них):
movsq
или movsw
2-байтовая инструкция, охватывающая границу страницы, поэтому для его декодирования необходимы обе страницы. - операнд источника qword
[rsi]
также разделитель страниц - операнд назначения qword
[rdi]
также разделитель страниц
Если какая-либо из этих 6 страниц окажется неисправной, мы вернемся к исходной точке.
rep movsd
также является 2-байтовой инструкцией, и для выполнения шага на ее шаге потребуется то же самое требование. Подобные случаи, такие как push [mem]
или pop [mem]
, могут быть построены с неправильно выровненным стеком.
Одна из причин (или побочных преимуществ) для / создания прерываний сборочных нагрузок / хранилищ разброса (обновление вектора маски) с их прогрессом), чтобы избежать увеличения этого минимального следа для выполнения одной инструкции. Также для повышения эффективности обработки нескольких сбоев во время одной сборки или разброса.
@ Брэндон отмечает в комментариях, что гостю потребуются его таблицы страниц в памяти , а пользователю - Разделение пространства страницы также может быть разделением на 1 ГБ, поэтому обе стороны находятся в разных поддеревьях верхнего уровня PML4. Для продвижения по странице HW необходимо коснуться всех этих страниц таблицы гостевых страниц. Такая патологическая ситуация вряд ли случится случайно.
TLB (и внутренние устройства просмотра страниц) позволяют кэшировать некоторые данные таблицы страниц и не обязаны перезапускать просмотр страницы с нуля, если ОС не выполнила invlpg
или установить новый каталог страниц верхнего уровня CR3. Ничто из этого не является необходимым при изменении страницы с отсутствия на настоящее; x86 на бумаге гарантирует, что он не нужен (поэтому «отрицательное кэширование» отсутствующих PTE не разрешено, по крайней мере, невидимо для программного обеспечения). Таким образом, ЦП может не выполнять VMexit, даже если некоторые из страниц таблицы гостевых физических страниц фактически отсутствуют.
Счетчики производительности PMU могут быть включены и настроены так, что инструкция также требует событие perf для записи в буфер PEBS для этой инструкции. С маской счетчика, сконфигурированной для подсчета только инструкций пользовательского пространства, а не ядра, вполне возможно, что он продолжает пытаться переполнить счетчик и сохранять сэмпл в буфере каждый раз, когда вы возвращаетесь в пользовательское пространство, вызывая ошибку страницы.