Trong hạt nhân Linux, tôi đã viết mã tương tự copy_page_range
(mm/memory.c) để sao chép bộ nhớ từ quy trình này sang quy trình khác với tối ưu hóa COW. Địa chỉ đích và nguồn có thể được bù đắp bằng PAGE_SIZE
và COW vẫn hoạt động. Tuy nhiên, tôi nhận thấy rằng trong một chương trình người dùng khi tôi sao chép từ cùng một địa chỉ nguồn đến các địa chỉ đích khác nhau, TLB dường như không bị xóa hoàn toàn. Ở mức độ cao, mã cấp người dùng của tôi làm như sau (tôi sao chép chính xác một trang, 0x1000 byte trên máy tính của tôi, tại một thời điểm):Hạt nhân Linux Vô hiệu hóa mục nhập TLB
SRC = 0x20000000
- Viết thư cho SRC (gọi liên quan trang
page1
). - Syscall để sao chép SRC vào 0x30000000 trong quá trình đích. Bây giờ, địa chỉ quá trình src 0x20000000 và địa chỉ quá trình đích 0x30000000 trỏ đến cùng một trang (
page1
). - Viết điều gì đó khác với SRC (điều này sẽ kích hoạt lỗi trang để xử lý COW). Giả sử địa chỉ nguồn hiện trỏ đến
page2
. - Syscall để sao chép SRC vào 0x30001000 trong quá trình đích.
Tại thời điểm này, hai trang riêng biệt nên tồn tại: SRC 0x20000000 page2
DST 0x30000000 page1
DST 0x30001000 page2
Tôi thấy rằng ở bước 3, khi tôi viết một cái gì đó khác nhau vào src 0x20000000, không có trang lỗi được tạo ra. Sau khi kiểm tra, các ánh xạ trang thực tế là: SRC 0x20000000 page1
DST 0x30000000 page1
DST 0x30001000 page1
Trong mã của tôi, nếu tôi gọi flush_tlb_page
và vượt qua các địa chỉ nguồn, mã người sử dụng làm việc như mong đợi với ánh xạ trang thích hợp . Vì vậy, tôi tin rằng tôi không duy trì TLB một cách chính xác. Trong copy_page_range
, hạt nhân gọi mmu_notifier_invalidate_range_start/end
trước và sau khi thay đổi bảng trang. Tôi đang làm chính xác điều tương tự và đã kiểm tra gấp đôi Tôi thực sự đi đúng struct_mm và địa chỉ để mmu_notifier_invalidate_range_start/end
. Có chức năng này không xử lý flushing tlb? Ok, vì vậy theo nghĩa đen khi tôi nhập xong, tôi đã kiểm tra dup_mmap
và nhận ra rằng người gọi chính là copy_page_range
, dup_mmap
(hạt nhân/ngã ba.c), gọi số flush_tlb_mm
. Tôi đoán tôi nên gọi flush_cache_range
và flush_tlb_range
trước và sau mã hạt nhân của tôi. Điều này có đúng không? Chính xác thì mmu_notifier_invalidate_range_start/end
làm gì?
bạn có thể giải thích một chút về mmu_notifiers không? Tôi đang mắc kẹt trên cho dù các móc được sử dụng chỉ bởi hạt nhân để thông báo kvm/vmm hoặc ngược lại cũng đúng? cho dù các móc này được sử dụng cho tất cả các trang hay chỉ những trang đang được VMM sử dụng. nếu có thì chúng được đăng ký như thế nào? – shami