Когда я вручную изменяю биты флага записи таблицы страниц (pte) в ядре Linux, почему модификация флага иногда возвращается обратно?

Вопрос:

Для контекста мой код предназначен для того, чтобы брать процесс и намеренно вызывать дополнительные ошибки страницы. Я начинаю с ручного изменения pte_flags записей таблицы страниц, отключив их текущий бит, а затем включив свой собственный специальный бит, находящийся в бите флага страницы _PAGE_SOFTW2 (arch/x86/include/asm/pgtable_types.h), чтобы отметить это. Я перепутал с пт.

Это приведет к ошибке страницы позже, если к странице будет осуществлен доступ снова. Как только это происходит, я сразу же сбрасываю биты, чтобы страница помечалась как присутствующая. Иногда кажется, что мой сброс не длится даже при следующем вызове функции.

Любые идеи, почему мои битовые модификации не сохраняются?

Примеры кода:

Вот как я сбрасываю биты после использования walk_page_range() из mm/pagewalk.c:

set_pte(pte, pte_set_flags(*pte, _PAGE_PRESENT));       
set_pte(pte, pte_clear_flags(*pte,_PAGE_MY_BIT));

Вот один из примеров операторов printk, демонстрирующих проблему.

// In do_page_fault I detect that my _PAGE_MY_BIT is set in the flags and flip it (424 -> 25)
[   44.473337] 1636 mpv/lua script  do_page_fault: Before: address 5555556acd30 pte 3f274c424 flags 424 
[   44.474116] 1636 mpv/lua script  do_page_fault: After: address 5555556acd30 pte 3f274c025 flags 25

// Just a few lines later, do_page_fault calls do_user_addr_fault and I print the same pte_flag
[   44.474950] 1636 mpv/lua script do_user_addr_fault: address 5555556acd30 pte 3f274c424 flags 424 

do_page_fault в arch/x86/mm/fault.c:

prefetchw(&current->mm->mmap_sem);
trace_page_fault_entries(regs, hw_error_code, address);

if (unlikely(kmmio_fault(regs, address)))
    return;

reset_the_pte(current, address, __func__);   // My function to flip the bits

/* Was the fault on kernel-controlled part of the address space? */
if (unlikely(fault_in_kernel_space(address)))
    do_kern_addr_fault(regs, hw_error_code, address);
else
    do_user_addr_fault(pte, regs, hw_error_code, address);

Возможные ответы:

1) В соответствии с этим, точки могут быть изменены с помощью pte_modify вместо pte_set_flags. Это лучший метод или они оба имеют одинаковую функциональность, а pte_modify немного более ограничивающий?

2) Может ли быть переключение контекста на другой процесс между моей функцией сброса и do_user_addr_fault, что может как-то повлиять на мой pte?

3) Если бы эта pte/страница была разделена памятью с другим процессом, повлияло бы это на мой сброс?


person wxz    schedule 30.05.2020    source источник
comment
У меня не было возможности проверить это, но есть шанс, что мне также придется изменить флаги страниц в структуре page-›flags (дополнительная информация о флагах страниц в include/linux/page_flags.h) в дополнение к сами флаги pte.   -  person wxz    schedule 09.09.2020