2011-11-21 37 views
5

Tôi đang cố gắng sử dụng mmap trong không gian người dùng để đọc bộ nhớ vật lý nơi 'mem_map' bắt đầu. Đó là một mảng chứa tất cả các trang vật lý. Đây là một máy i386 chạy 3.0 hạt nhân.mmap: Thao tác không được phép

Mã này là như thế này:

.... 

//define page size 
// 
#define PAGE_SIZE 0x1000 //4096 bytes 
#define PAGE_MASK (PAGE_SIZE - 1) 

.... 

    /* open /dev/mem file*/ 
    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { 
     printf("/dev/mem could not be opened.\n"); 
    perror("open"); 
     exit(1); 
    } else { 
    printf("/dev/mem opened.\n"); 
    } 

    /* Map one page */ 
    printf(" mem_map is at physical addr: 0x%x\n", mem_map_phy_addr); 

    map_base = mmap(0, PAGE_SIZE, PROT_READ, MAP_SHARED, fd, (mem_map_phy_addr & ~PAGE_MASK)); //mem_map_phy_addr is at 0x356f2000 

    if(map_base == (void *) -1) { 
    printf("Memory map failed. err num = %d\n",errno); 
    perror("mmap"); //failed here 
    } else { 
    printf("Memory mapped at address %p.\n", map_base); 
    } 

Tôi chạy này là một gốc. Đầu ra là:

/dev/mem opened. 
mem_map is at physical addr: 0x356f2000 
Memory map failed. err num = 1 
mmap: Operation not permitted 

Để chắc chắn, tôi googled vấn đề và thêm dòng sau vào tập tin /etc/sysctl.conf tôi:

vm.mmap_min_addr = 0 

Nhưng điều này không làm việc, hoặc.

Bất cứ ai cũng biết tại sao hoạt động mem_map như thế này không được phép và cách tôi có thể thực hiện được?

Cảm ơn.

+2

FYI, nó là không chính xác để sử dụng 'x & ~ PAGE_MASK'. Trên các hệ thống 64 bit, điều này sẽ cắt địa chỉ thành 32 bit. Bạn phải chuyển sang 'uintptr_t' hoặc loại tương đương rộng trước khi lấy phần bổ sung. –

+0

Bạn có chạy lệnh sysctl để đặt giá trị cho mmap_min_addr hoặc chỉ chỉnh sửa tệp conf không? Bạn phải làm cả hai. –

+0

vâng, tôi đã làm "sysctl -p" sau đó. – user899159

Trả lời

8

Có vẻ như hạt nhân đã được biên dịch với CONFIG_STRICT_DEVMEM được bật. Đây là tính năng bảo mật để ngăn không cho người dùng truy cập vào bộ nhớ vật lý (có thể nhạy cảm) trên 1MB (IIRC). Bạn có thể vô hiệu hóa tính năng này với sysctl dev.mem.restricted.

+0

Có, my .config có CONFIG_STRICT_DEVMEM = y. Làm cách nào để sử dụng "sysctl dev.mem.restricted"? Tôi đã thử và lỗi là:/proc/sys/dev/mem/restricted: Không có tập tin hoặc thư mục như vậy. – user899159

+0

Tôi đoán bạn sẽ phải biên dịch lại hạt nhân với tùy chọn bị tắt. –

+0

Ok, tôi đã biên dịch lại hạt nhân bằng CONFIG_STRICT_DEVMEM bị tắt. Bây giờ tôi có một lỗi mới:/dev/mem được mở. mem_map tại địa chỉ thực: 0x356db000 Bản đồ bộ nhớ không thành công. err num = 22 mmap: Đối số không hợp lệ. Điều này không xảy ra nếu tôi cố gắng ánh xạ địa chỉ thực tại 0. Bất kỳ đề xuất nào? - Cảm ơn. – user899159

0

Tôi gặp sự cố tương tự xảy ra khi tôi đang thử sử dụng flashrom trên một Hội đồng APU2c4 với Arch Linux.

Tùy chọn sysctl dev.mem.restricted không có sẵn trong hệ thống của tôi và sử dụng hạt nhân tự biên dịch không có tùy chọn cho tôi.

tôi làm việc xung quanh vấn đề bằng cách thiết lập iomem Kernelparameter để relaxed qua Grub:

# /boot/grub/grub.cfg 
linux /boot/vmlinuz-linux iomem=relaxed 

Tất nhiên khởi động lại là nessesary cho giải pháp này.

tham khảo:
https://www.reddit.com/r/libreboot/comments/6wvyry/flashrom_failures_to_access/
https://www.flashrom.org/FAQ
https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt