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