Предполагая, что мы говорим о x86/x64: как только пейджинг включен - это делается путем установки бита PG (бит 31) CR0, и это происходит очень рано при загрузке - все адреса утверждаются исполняемым кодом, включая адреса OF кода, интерпретируются как виртуальные адреса.
Дело не в том, что процессор генерирует виртуальные адреса каким-то образом, отличным от физического, просто, если этот бит включен, он позволяет преобразовывать адреса, и с тех пор каждый адрес, который выходит из кода, интерпретируется. MMU как виртуальный адрес.
Режим пользователя и ядра не имеет значения, контекст процесса или системы не имеет значения. Все адреса являются виртуальными и переводятся через таблицы страниц в ОЗУ (физические) адреса. И запись таблицы страниц может иметь бит "страница присутствует", что означает, что ссылка может вызвать ошибку страницы.
Тут сразу приходит на ум только одно исключение: регистр CR3 содержит физический адрес таблицы страниц верхнего уровня (таблица PML4 в x64). И, конечно, код, который управляет записями таблицы страниц и т.д., Должен иметь дело с физическими адресами. Но эти физические адреса никогда не утверждаются, используются в качестве цели операции выборки или сохранения при запуске кода; они просто рассчитываются, хранятся и извлекаются.
Нет способа "избежать" этого и временно утвердить физические адреса. (Если вы отключите бит PG, следующая инструкция в вашем потоке инструкций не будет выполнена, если только ее виртуальные и физические адреса не совпадают! Аналогичные проблемы для указателя стека и всех других сохраненных адресов, в которых нуждается ваш код ...)
Если вам нужно сослаться на конкретный физический адрес, вы выделяете ранее неиспользуемую виртуальную страницу и настраиваете соответствующую запись таблицы страниц, чтобы указать нужный номер физической страницы. Вот как код драйвера получает доступ к "регистру" ввода / вывода, когда включена виртуальная адресация.