In the linux kernel, I wrote code similar to copy_page_range (mm / memory.c) to copy memory from one process to another with COW optimization. Destination and source addresses can be offset by PAGE_SIZE , and COW is still working. However, I noticed that in the user program, when I copy from the same source address to different destination addresses, the TLB does not seem to be cleared correctly. At a high level, my user level code does the following (I copy exactly one page, 0x1000 bytes on my machine at a time):
src = 0x20000000
- Write to SRC (call the linked page
page1 ). - Syscall to copy the SRC to 0x30000000 in the assignment process. Now, the src process address 0x20000000 and the destination process address 0x30000000 point to the same page (
page1 ). - Write something else for the SRC (this should cause a page error for COW processing). Suppose the source address now points to
page2 . - Syscall to copy SRC to 0x30001000 during assignment.
At this point, two separate pages must exist: SRC 0x20000000 page2 DST 0x30000000 page1 DST 0x30001000 page2
I find that in step 3, when I write something else in src 0x20000000, a page error does not occur. When checking actual page mappings: SRC 0x20000000 page1 DST 0x30000000 page1 DST 0x30001000 page1
In my code, if I call flush_tlb_page and pass in the source address, the user code works as expected with the corresponding page displays. Therefore, I am convinced that I do not support TLB correctly. In copy_page_range kernel calls mmu_notifier_invalidate_range_start/end before and after changing the page tables. I do the same and double check that I am really passing the correct struct_mm and addresses to mmu_notifier_invalidate_range_start/end . Does this function not work when flushing tlb?
So, literally, when I finished typing this, I checked dup_mmap and realized that the main caller copy_page_range , dup_mmap (kernel / fork.c) calls flush_tlb_mm . I assume that I should call flush_cache_range and flush_tlb_range before and after my kernel code. It's right? What exactly does mmu_notifier_invalidate_range_start/end do?
source share