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