Подтвердить что ты не робот

Как получить доступ к mmaped/dev/mem без сбоя ядра Linux?

У меня есть простая программа, которая пытается получить доступ к физической памяти в пользовательском пространстве, где ядро ​​хранит первую страницу структуры. На 64-битной машине этот адрес:

  • виртуальный адрес ядра: ffffea0000000000
  • физический адрес: 0000620000000000

Я пытаюсь получить доступ к этому физическому адресу через mmap в пользовательском пространстве. Но следующий код разбивает ядро.

int *addr;
if ((fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0 ) {
    printf("Error opening file. \n");
    close(fd);
    return (-1);
}
/* mmap.  address of first struct page for 64 bit architectures 
 * is 0x0000620000000000.
 */
addr = (int *)mmap(0, num*STRUCT_PAGE_SIZE, PROT_READ, MAP_PRIVATE,
            fd, 0x0000620000000000);
printf("addr: %p \n",addr);
printf("addr: %d \n",*addr); /* CRASH. */
4b9b3361

Ответ 1

Я думаю, что нашел проблему - это касается защиты отображения памяти /dev/mem на x86.

Pl ссылается на эту статью LWN: "x86: ввести /dev/mem ограничения с опцией конфигурации" http://lwn.net/Articles/267427/

CONFIG_NONPROMISC_DEVMEM

Теперь (я тестировал это в последнем ядре 3.2.21), вариант конфигурации, по-видимому, называется CONFIG_STRICT_DEVMEM.

Я изменил конфигурацию ядра:

$ grep DEVMEM .config
# CONFIG_STRICT_DEVMEM is not set
$ 

Когда вышеуказанный prg был запущен с предыдущим ядром, с CONFIG_STRICT_DEVMEM SET: dmesg показывает:

[29537.565599] Program a.out tried to access /dev/mem between 1000000->1001000.
[29537.565663] a.out[13575]: segfault at ffffffff ip 080485bd sp bfb8d640 error 4 in a.out[8048000+1000]

Это из-за защиты ядра.

Когда ядро ​​было перестроено (с CONFIG_STRICT_DEVMEM UNSET) и запущено указанное выше prg:

# ./a.out 
mmap failed: Invalid argument
# 

Это связано с тем, что параметр 'offset' составляет > 1 МБ (неверно на x86) (это было 16 МБ).

После того, как смещение mmap будет находиться в пределах 1 МБ:

# ./a.out 
addr: 0xb7758000
*addr: 138293760 
# 

Это работает! Подробнее см. В приведенной выше статье LWN.

В архитектуре x86 с поддержкой PAT (таблица атрибутов страницы) ядро ​​по-прежнему препятствует отображению областей DRAM. Причина этого, упомянутая в источнике источника:

This check is nedded to avoid cache aliasing when PAT is enabled

Эта проверка приведет к аналогичной ошибке, указанной выше. Например:

Program a.out tried to access /dev/mem between [mem 68200000-68201000].

Это ограничение можно удалить, отключив PAT. PAT можно отключить, добавив аргумент "nopat" в командную строку ядра во время загрузки.

Ответ 2

В архитектуре x86 с поддержкой PAT (Таблица атрибутов страницы) ядро ​​может препятствовать отображению областей DRAM (даже если оно скомпилировано без установки CONFIG_NONPROMISC_DEVMEM).

Причиной этого, как указано в исходном коде ядра, является:

This check is nedded to avoid cache aliasing when PAT is enabled

Эта проверка приведет к появлению аналогичной ошибки в dmesg, как указано в ответе kaiwan выше. Например:

Program a.out tried to access /dev/mem between [mem 68200000-68201000].

Это ограничение можно удалить, отключив PAT.

PAT можно отключить, добавив аргумент nopat в командную строку ядра во время загрузки.