Tôi có một thiết bị cần một khối bộ nhớ chỉ dành riêng cho nó mà không cần hệ điều hành can thiệp. Có cách nào để nói với BIOS hoặc HĐH rằng một khối bộ nhớ được bảo lưu và không được sử dụng nó?
Tôi đang sử dụng thiết bị này trên máy openSUSE.
Tôi có một thiết bị cần một khối bộ nhớ chỉ dành riêng cho nó mà không cần hệ điều hành can thiệp. Có cách nào để nói với BIOS hoặc HĐH rằng một khối bộ nhớ được bảo lưu và không được sử dụng nó?
Tôi đang sử dụng thiết bị này trên máy openSUSE.
Câu trả lời:
Những gì bạn đang yêu cầu được gọi là DMA. Bạn cần phải viết một trình điều khiển để dự trữ bộ nhớ này.
Vâng, tôi nhận ra rằng bạn nói rằng bạn không muốn HĐH can thiệp và trình điều khiển trở thành một phần của HĐH, nhưng không có sự bảo lưu của trình điều khiển, hạt nhân tin rằng tất cả bộ nhớ thuộc về nó. (Trừ khi bạn bảo hạt nhân bỏ qua khối bộ nhớ, theo câu trả lời của Aaron, nghĩa là vậy.)
Chương 15 (PDF) của " Trình điều khiển thiết bị Linux, 3 / e " của Rubini, Corbet và Kroah-Hartmann bao gồm DMA và các chủ đề liên quan.
Nếu bạn muốn có phiên bản HTML này, tôi đã tìm thấy phiên bản thứ hai của chương ở nơi khác trực tuyến. Coi chừng rằng phiên bản thứ 2 đã hơn một thập kỷ, xuất hiện khi kernel 2.4 mới. Đã có rất nhiều công việc trên hệ thống con quản lý bộ nhớ của kernel kể từ những ngày đó, vì vậy nó có thể không còn áp dụng tốt nữa.
Nếu bạn muốn HĐH hoàn toàn bỏ qua nó, bạn cần tạo một lỗ nhớ bằng cách sử dụng " memmap
." Xem tài liệu tham khảo này . Ví dụ: nếu bạn muốn 512M ở hàng rào 2GB, bạn có thể đặt " memmap=512M$2G
" trên dòng lệnh kernel.
Bạn sẽ cần kiểm tra dmesg
để tìm một lỗ tiếp giáp để đánh cắp để bạn không dậm chân trên bất kỳ thiết bị nào; đó là cụ thể cho bo mạch chủ + thẻ của bạn.
Đây không phải là cách được đề xuất để thực hiện - hãy xem câu trả lời của Warren Young để biết cách thực hiện đúng (trình điều khiển kernel + DMA). Tôi đang trả lời chính xác câu hỏi bạn đã hỏi. Nếu bạn dự định làm điều này cho người dùng cuối, họ sẽ ghét bạn nếu bạn làm điều này với họ ... hãy tin tôi, đó là lý do duy nhất tôi biết câu trả lời này.
Chỉnh sửa: Nếu bạn đang sử dụng grub2 w / grubby (ví dụ: CentOS 7), bạn cần đảm bảo thoát khỏi $ . Nên có một \
trước $
. Thí dụ:
$ sudo -v
$ sudo grubby --update-kernel=ALL --args=memmap='128M\\$0x57EF0000'
$ sudo grubby --info $(sudo grubby --default-kernel) | grep memmap
args="ro crashkernel=auto ... memmap=128M\$0x57EF0000"
uint8_t *ptr = 0x8000000
" với ví dụ của tôi? Hoặc điều đó có thể segfault ... Huh, tôi thực sự không biết. Một lần nữa, tôi biết câu trả lời vì tôi là người dùng cuối của thẻ PCI được thiết kế kém, nơi tôi phải phân bổ thủ công bộ đệm dưới vạch 4G và sau đó cho tài xế biết chỗ đó ở đâu; nó có thể không thể từ người dùng.
MMAP_FIXED | MMAP_ANON
. Không có thiết bị DMA tùy chỉnh ở đây để chơi, tôi không thể nói nếu nó thực sự làm những gì OP muốn, nhưng hộp CentOS của tôi đã vui vẻ cho tôi một khối 8 MB ở 512 MB khi tôi nói memmap=8M$512M
trong GRUB. Nó thậm chí không yêu cầu quyền truy cập root, vì tôi đã sợ nó có thể. Nhưng ngay cả khi điều này làm đúng, tôi vẫn nghĩ rằng có lẽ bạn sẽ cần một trình điều khiển để xử lý các ngắt và như vậy.
mmap()
các trang không có giá trị trước khi mã người dùng được nhìn thấy chúng. Nó được thực hiện để bảo mật, do đó dữ liệu không bị rò rỉ từ quá trình này sang quá trình tiếp theo. Một lý do khác để sử dụng trình điều khiển, vì bạn có thể cần phải bảo toàn nội dung của bộ đệm DMA tại thời điểm tải trình điều khiển. Ồ, nhân tiện, mmap()
cuộc gọi được định vị tùy ý thành công ngay cả khi không có memmap
tùy chọn khởi động kernel, ít nhất là không có ai đang sử dụng bộ nhớ ở nơi bạn hỏi. Tùy chọn khởi động chắc chắn làm tăng cơ hội thành công, nhưng nó không thực sự cần thiết.
Để dự trữ một khối bộ nhớ từ kernel trong Linux dựa trên ARM, bạn cũng có thể sử dụng một reserved-memory
nút trong tệp cây (dts) của thiết bị. Trong tài liệu kernel (xem tại đây ), có một ví dụ:
memory {
reg = <0x40000000 0x40000000>;
};
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
/* global autoconfigured region for contiguous allocations */
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x4000000>;
alignment = <0x2000>;
linux,cma-default;
};
display_reserved: framebuffer@78000000 {
reg = <0x78000000 0x800000>;
};
multimedia_reserved: multimedia@77000000 {
compatible = "acme,multimedia-memory";
reg = <0x77000000 0x4000000>;
};
};
Đầu tiên nhập lệnh này, để kiểm tra cài đặt hiện tại của bạn:
sysctl vm.min_free_kbytes
Để thay đổi giá trị đặt, chỉnh sửa /etc/sysctl.conf
. Tìm dòng:
vm.min_free_kbytes=12888
Nếu nó không tồn tại, hãy tạo nó (cùng với giá trị mong muốn của bạn). Các giá trị sau được chấp nhận:
8192
12288
16384
20480
8M là cực kỳ bảo thủ; Nó có thể ngồi thoải mái 16M. Khi bạn thay đổi giá trị, hãy chạy cái này và không cần khởi động lại:
sudo sysctl -p