Why mmap() Fails on Raspberry Pi 5 When Reducing Map Size: Page Alignment Explained
If you are working with direct hardware memory mapping on the Raspberry Pi 5 via /dev/gpiomem0, you might encounter a deeply counter-intuitive behavior: calling mmap() with a requested size of 0x2c001 bytes succeeds, but reducing that size by just 1 byte to 0x2c000 causes mmap() to fail and return MAP_FAILED (0xffffffffffffffff).
The Short Answer
This issue occurs due to the interaction between kernel memory page rounding and device driver size validation:
- The Raspberry Pi 5 Linux kernel uses a 16 KB (16,384 bytes /
0x4000) page size. - When you pass
0x2c001tommap(), the kernel automatically rounds the allocation size up to the next page boundary:0x30000(12 pages). - When you pass
0x2c000, the value is already page-aligned (11 pages exact), so the kernel does not round it up. - The
/dev/gpiomem0driver requires a minimum mapping length that spans more than 11 pages (e.g., 12 pages /0x30000bytes) to cover all required peripheral registers. Because0x2c000falls short of the driver's required length, the driver rejects the call with-EINVAL.
Under the Hood: Page Granularity on the Raspberry Pi 5
Memory mapping operates on page granularity. While traditional 32-bit Raspberry Pi boards and standard x86_64 systems use 4 KB pages (0x1000 bytes), the 64-bit OS kernel shipped with the Raspberry Pi 5 (running the BCM2712 / RP1 architecture) is configured with 16 KB pages (0x4000) for improved memory controller throughput.
Here is how the kernel handles your two requested sizes:
Case 1: mapsize = 0x2c001 (180,225 bytes)
The kernel calculates page boundaries as follows: