2011-12-05 41 views
6

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

  1. Viết thư cho SRC (gọi liên quan trang page1).
  2. 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).
  3. 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.
  4. 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_rangeflush_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ì?

Trả lời

8

Có, nếu bạn đang làm điều gì đó thay đổi bảng trang, bạn cần phải đảm bảo rằng TLB bị vô hiệu khi được yêu cầu.

mmu_notifier_invalidate_range_start/end chỉ cần gọi móc thông báo MMU; các hook này chỉ tồn tại để mã kernel khác có thể được thông báo khi TLB invalidation xảy ra. Các địa điểm duy nhất thiết lập trình thông báo MMU là

  • KVM (ảo hóa hỗ trợ phần cứng) sử dụng chúng để xử lý việc hoán đổi trang; nó cần phải biết về sự vô hiệu hóa của máy chủ TLB để giữ MMU khách ảo hóa đồng bộ với máy chủ.
  • GRU (trình điều khiển phần cứng chuyên dụng trong các hệ thống SGI lớn) sử dụng trình thông báo MMU để giữ các bảng ánh xạ trong phần cứng GRU đồng bộ với CPU MMU.

Nhưng khá nhiều nơi bạn đang gọi đến trình thông báo MMU, bạn cũng nên gọi các chức năng quay số TLB nếu hạt nhân chưa làm việc đó cho bạn.

+0

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

Các vấn đề liên quan