Проверьте это с busybox devmem
busybox devmem
это крошечная утилита CLI, которая mmaps /dev/mem
.
Вы можете получить его в Ubuntu с помощью: sudo apt-get install busybox
Использование: прочитать 4 байта с физического адреса 0x12345678
:
sudo busybox devmem 0x12345678
Пишите 0x9abcdef0
по этому адресу:
sudo busybox devmem 0x12345678 w 0x9abcdef0
Источник: https://github.com/mirror/busybox/blob/1_27_2/miscutils/devmem.c#L85
MAP_SHARED
Когда mmapping /dev/mem
, вы, вероятно, хотите использовать:
open("/dev/mem", O_RDWR | O_SYNC); mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...)
MAP_SHARED
заставляет записи идти в физическую память немедленно, что облегчает наблюдение и имеет больше смысла для записи аппаратного регистра.
CONFIG_STRICT_DEVMEM
а также nopat
Чтобы использовать /dev/mem
для просмотра и изменения обычной оперативной памяти в ядре v4.9, вы должны:
- отключить
CONFIG_STRICT_DEVMEM
(установлено по умолчанию в Ubuntu 17.04) - передать параметр
nopat
командной строки ядра для x86
Порты ввода-вывода по-прежнему работают без них.
Смотрите также: https://stackoverflow.com/questions/39134990/mmap-of-dev-mem-fails-with-invalid-argument-for-virt-to-phys-address-but-addre/45127582#45127582
Сброс кеша
Если вы попытаетесь выполнить запись в ОЗУ, а не в регистр, память может быть кэширована ЦП: https://stackoverflow.com/questions/22701352/how-to-flush-the-cpu-cache-for-a-region -of-address-space-in-linux, и я не вижу очень переносимого / простого способа очистить его или пометить регион как не кэшируемый:
Так, может быть, /dev/mem
нельзя надежно использовать для передачи буферов памяти на устройства?
К сожалению, в QEMU этого не наблюдается, поскольку QEMU не моделирует кэши.
Как это проверить
Теперь самое интересное. Вот несколько классных настроек:
- Пользовательская память
- выделить
volatile
переменную в пользовательском процессе - получить физический адрес с помощью
/proc/<pid>/maps
+/proc/<pid>/pagemap
- физический адрес с
devmem2
, и наблюдайте, как пользовательский процесс реагирует:
- Ядро памяти
- выделить память ядра с
kmalloc
- получить физический адрес
virt_to_phys
и передать его обратно пользователю - изменить физический адрес с
devmem2
- запросить значение из модуля ядра
- IO mem и устройство виртуальной платформы QEMU
- создать платформенное устройство с известными физическими адресами регистра
- использовать
devmem2
для записи в реестр - часы
printf
выходят из виртуального устройства в ответ