В текущей версии Linux см. arch/x86/entry/calling.h
для asm .macro SWITCH_TO_USER_CR3_NOSTACK
и другие сведения о том, как Linux переключается между ядром и пользовательским CR3.И более ранний комментарий к константам, которые он использует:
/*
* PAGE_TABLE_ISOLATION PGDs are 8k. Flip bit 12 to switch between the two
* halves:
*/
#define PTI_USER_PGTABLE_BIT PAGE_SHIFT
#define PTI_USER_PGTABLE_MASK (1 << PTI_USER_PGTABLE_BIT)
#define PTI_USER_PCID_BIT X86_CR3_PTI_PCID_USER_BIT
#define PTI_USER_PCID_MASK (1 << PTI_USER_PCID_BIT)
#define PTI_USER_PGTABLE_AND_PCID_MASK (PTI_USER_PCID_MASK | PTI_USER_PGTABLE_MASK)
Похоже, что ядро CR3 всегда является младшим, поэтому установка бита 12 в текущем CR3 всегда заставляет его указывать пользователюкаталог страницы пробела. (Если текущая задача имеет пространство пользователя и если PTI включен. Эти макросы asm используются только в кодовых путях, которые собираются вернуться в пространство пользователя.)
.macro SWITCH_TO_USER_CR3_NOSTACK scratch_reg:req scratch_reg2:req
...
mov %cr3, \scratch_reg
...
.Lwrcr3_\@:
/* Flip the PGD to the user version */
orq $(PTI_USER_PGTABLE_MASK), \scratch_reg
mov \scratch_reg, %cr3
Эти макросы используются в entry_64.S
, entry_64_compat.S
и entry_32.S
в путях, которые возвращаются в пользовательское пространство.
Возможно, естьболее чистый способ доступа к таблицам страниц в пространстве пользователя из C.
Лучше всего было бы взглянуть на обработчик ошибок страницы, чтобы узнать, как он обращается к таблице страниц процесса.(Или реализация mmap
MAP_POPULATE
).