2011-08-20 13 views
19

Câu hỏi của tôi là: làm cách nào để xác định khi nào an toàn để tắt tính năng lưu vào bộ nhớ cache khi tôi đang sử dụng đúng [pci_]dma_sync_single_for_{cpu,device} trong trình điều khiển thiết bị của mình?Quản lý kết hợp bộ nhớ cache DMA

Tôi đang làm việc trên trình điều khiển thiết bị cho thiết bị ghi trực tiếp vào RAM qua PCI Express (DMA) và quan tâm đến việc quản lý kết hợp bộ nhớ cache. Có một bit điều khiển tôi có thể thiết lập khi khởi động DMA để kích hoạt hoặc vô hiệu hóa bộ nhớ cache snooping trong DMA, rõ ràng cho hiệu suất tôi muốn để tắt cache snooping nếu có thể.

Trong quy trình ngắt, tôi gọi pci_dma_sync_single_for_cpu()..._for_device() khi thích hợp, khi chuyển bộ đệm DMA, nhưng trên Linux 32-bit 2.6.18 (RHEL 5) thì các lệnh này là macro mở rộng thành không có gì ... giải thích lý do tại sao thiết bị của tôi trả về rác khi bộ nhớ cache snooping bị tắt trên hạt nhân này!

Tôi đã rà soát qua lịch sử của các nguồn hạt nhân, và có vẻ như cho đến 2.6.25 chỉ 64 bit x86 có móc để đồng bộ hóa DMA. Từ 2.6.26 có vẻ là một cơ chế đồng bộ thống nhất chung cho đồng bộ hóa DMA (hiện tại trong include/asm-generic/dma-mapping-common.h) qua các trường sync_single_for_{cpu,device} của dma_map_ops, nhưng cho đến nay tôi đã không tìm thấy bất kỳ định nghĩa nào về các hoạt động này.

+0

Đã có một số điều LWN về DMA và sự mạch lạc bộ nhớ cache bạn có thể muốn nhìn xung quanh trên lwn.net – Spudd86

+1

Bạn đã đo hiệu suất đạt được bạn sẽ có được bằng cách tắt bộ nhớ cache snooping , không chỉ về việc chuyển giao mà còn trên toàn bộ ứng dụng? Sự kết hợp DMA rất thuận tiện và suy nghĩ về việc tương tác với phần cứng dễ dàng hơn nhiều đến nỗi tôi sẽ đo lường cẩn thận trước khi tắt nó đi. –

Trả lời

15

Tôi thực sự ngạc nhiên không ai có thể trả lời câu này, vì vậy ở đây chúng tôi đi trên một câu trả lời cụ thể phi Linux (Tôi không có đủ kiến ​​thức về hạt nhân Linux chính nó cụ thể hơn) ...

cache snooping đơn giản chỉ yêu cầu bộ điều khiển DMA gửi yêu cầu vô hiệu hóa bộ nhớ cache tới tất cả các CPU cho bộ nhớ đang được DMA vào. Điều này rõ ràng là thêm tải vào bus coherency cache, và nó đặc biệt nặng với các bộ xử lý bổ sung vì không phải tất cả các CPU sẽ có một kết nối hop đơn với bộ điều khiển DMA phát hành snoop. Do đó, câu trả lời đơn giản cho "khi an toàn để vô hiệu hóa bộ nhớ cache snooping" là khi bộ nhớ được DMA vào hoặc không tồn tại trong bất kỳ bộ nhớ cache CPU HOẶC các dòng bộ nhớ cache của nó được đánh dấu là không hợp lệ. Nói cách khác, bất kỳ nỗ lực nào để đọc từ vùng DMAed sẽ luôn luôn dẫn đến đọc từ bộ nhớ chính.

Vậy làm thế nào để bạn đảm bảo đọc từ vùng DMA sẽ luôn chuyển sang bộ nhớ chính?

Quay trở lại những ngày trước khi chúng tôi có tính năng ưa thích như DMA snooping bộ nhớ cache, những gì chúng tôi đã từng làm là đường ống dẫn bộ nhớ DMA bằng cách cho ăn nó thông qua một loạt các giai đoạn chia tay như sau:

Giai đoạn 1: Thêm " dơ bẩn "vùng bộ nhớ DMA đến" bẩn và cần phải được làm sạch "danh sách bộ nhớ DMA.

Giai đoạn 2: Lần sau thiết bị ngắt với dữ liệu DMA mới, cấp bộ đệm CPU cục bộ không hợp lệ cho các phân đoạn DMA trong danh sách "bẩn và cần được làm sạch" cho tất cả các CPU có thể truy cập các khối đó (thường mỗi CPU chạy danh sách riêng của nó được tạo thành từ các khối bộ nhớ cục bộ). Di chuyển các phân đoạn đã nói vào danh sách "sạch".

Giai đoạn 3: DMA gián đoạn tiếp theo (dĩ nhiên bạn chắc chắn sẽ không xảy ra trước khi bộ nhớ cache đã hết hiệu lực), lấy vùng mới từ danh sách "sạch" và báo cho thiết bị biết rằng DMA tiếp theo của nó sẽ đi vào đó. Tái chế bất kỳ khối bẩn nào.

Giai đoạn 4: Lặp lại.

Vì đây là công việc nhiều hơn nên nó có một số lợi thế lớn. Thứ nhất, bạn có thể ghim xử lý DMA với một CPU đơn (thường là CPU0 chính) hoặc một nút SMP đơn lẻ, có nghĩa là chỉ một CPU/nút duy nhất cần phải lo lắng về việc mất hiệu lực bộ nhớ cache.Thứ hai, bạn cung cấp cho các hệ thống con bộ nhớ nhiều cơ hội hơn để ẩn thời gian trễ bộ nhớ cho bạn bằng cách giãn ra các hoạt động theo thời gian và trải rộng tải trên bus kết hợp bộ nhớ cache. Chìa khóa để thực hiện thường là thử và thực hiện bất kỳ DMA nào xảy ra trên CPU gần với bộ điều khiển DMA có liên quan nhất có thể và vào bộ nhớ càng gần CPU càng tốt.

Nếu bạn luôn luôn đưa DMA mới vào bộ nhớ cho không gian người dùng và/hoặc các CPU khác, chỉ cần nạp bộ nhớ mới mua vào ở phía trước của đường ống bộ đệm không hợp lệ bộ nhớ cache async. Một số hệ điều hành (không chắc chắn về Linux) có một thói quen được tối ưu hóa để đặt trước bộ nhớ zeroed, do đó hệ điều hành cơ bản không có bộ nhớ trong nền và giữ một bộ nhớ cache nhanh chóng xung quanh - nó sẽ trả cho bạn để giữ cho các yêu cầu bộ nhớ mới bên dưới. cực kỳ chậm. Tôi không biết về bất kỳ nền tảng nào được tạo ra trong mười năm qua sử dụng phần cứng bộ nhớ bị hỏng, do đó bạn phải giả định rằng tất cả bộ nhớ mới có thể chứa các dòng bộ nhớ cache hợp lệ cần vô hiệu.

Tôi đánh giá cao câu trả lời này chỉ một nửa câu hỏi của bạn, nhưng tốt hơn là không có gì. Chúc may mắn!

Niall

4

Có lẽ một chút quá hạn, nhưng:

Nếu bạn vô hiệu hóa bộ nhớ cache snooping, phần cứng sẽ không còn chăm sóc bản mạch lạc bộ nhớ cache. Do đó, hạt nhân cần phải làm điều này chính nó. Trong vài ngày qua, tôi đã dành một số tiem xem xét các biến thể X86 của [pci_] dma_sync_single_for_ {cpu, device}. Tôi đã tìm thấy không có dấu hiệu cho thấy họ thực hiện bất kỳ nỗ lực để duy trì tính mạch lạc. Điều này có vẻ phù hợp với thực tế là cache snooping được mặc định bật trong thông số PCI (e).

Do đó, nếu bạn tắt tính năng lưu vào bộ nhớ cache, bạn sẽ phải duy trì tính nhất quán trong trình điều khiển của mình. Có thể bằng cách gọi clflush_cache_range() (X86) hoặc tương tự?

Refs: