MEM(4)

πŸ’– MEM(4) β€” mem, kmem πŸ’–

okay bestie, sit down, we're talking about the memory files β€” mem and kmem, from the Kernel Interfaces Manual. yes this is the real deal, the whole physical memory of your computer, no cap. let's go 🫢


✨ SYNOPSIS ✨

device mem

that's it. that's the whole vibe. iconic.


🌸 DESCRIPTION 🌸

so <pink>/dev/mem</pink> is literally the special file that is an interface to the physical memory of the computer. like, the actual memory. the real stuff. 🧚

byte offsets in this file? interpreted as physical memory addresses. reading and writing this file is equivalent to reading and writing memory itself β€” not a metaphor, not a vibe, that's just what it is πŸ’…. and only offsets within the bounds of /dev/mem are allowed, so don't try it.

kernel virtual memory is accessed through /dev/kmem in the exact same manner as /dev/mem. same energy, different address space. the catch? only kernel virtual addresses that are currently mapped to memory are allowed. no mapped, no entry. πŸ™ˆ

on ISA the I/O memory space begins at physical address 0x000a0000 and runs to 0x00100000. and the per-process data size for the current process is UPAGES long, ending at virtual address 0xf0000000. write that down bestie, it's on the test ⭐


πŸ‘‘ IOCTL INTERFACE πŸ‘‘

several architectures allow attributes to be associated with ranges of physical memory. these attributes can be manipulated via ioctl() calls performed on /dev/mem. the declarations and data types live in <sys/memrange.h> β€” go look, they're right there πŸ’œ

the specific attributes, and the number of programmable ranges, may vary between architectures. the full set of supported attributes is:

  • MDF_UNCACHEABLE β€” the region is not cached. no caching. none. 🚫
  • MDF_WRITECOMBINE β€” writes to the region may be combined or performed out of order. chaos mode, but sanctioned.
  • MDF_WRITETHROUGH β€” writes to the region are committed synchronously. immediately. right now. ⚑
  • MDF_WRITEBACK β€” writes to the region are committed asynchronously. whenever it gets around to it, respectfully.
  • MDF_WRITEPROTECT β€” the region cannot be written to. locked. do not perceive it. πŸ”’

memory ranges are described by struct mem_range_desc:

uint64_t        mr_base;        /* physical base address */
uint64_t        mr_len;         /* physical length of region */
int             mr_flags;       /* attributes of region */
char            mr_owner[8];

in addition to the region attributes listed above, the following flags may also be set in the mr_flags field:

  • MDF_FIXBASE β€” the region's base address cannot be changed. it is what it is, fr.
  • MDF_FIXLEN β€” the region's length cannot be changed. same energy, the length is locked in πŸ”
  • MDF_FIRMWARE β€” the region is believed to have been established by the system firmware. blame the firmware, always ✨
  • MDF_ACTIVE β€” the region is currently active. it's up, it's doing its thing πŸ’…
  • MDF_BOGUS β€” we believe the region to be invalid or otherwise erroneous. sus. we don't trust it 😭
  • MDF_FIXACTIVE β€” the region cannot be disabled. ever. periodt.
  • MDF_BUSY β€” the region is currently owned by another process and may not be altered. not yours, don't touch 🚫

operations are performed using struct mem_range_op:

struct mem_range_desc   *mo_desc;
int                     mo_arg[2];

the MEMRANGE_GET ioctl is used to retrieve current memory range attributes. if mo_arg[0] is set to 0, it will be updated with the total number of memory range descriptors. if greater than 0, the array at mo_desc will be filled with a corresponding number of descriptor structures β€” or the maximum, whichever is less. math, but make it memory πŸ“

the MEMRANGE_SET ioctl is used to add, alter and remove memory range attributes. a range with the MDF_FIXACTIVE flag may not be removed; a range with the MDF_BUSY flag may not be removed or updated. read that again. okay good.

mo_arg[0] should be set to MEMRANGE_SET_UPDATE to update an existing or establish a new range, or to MEMRANGE_SET_REMOVE to remove a range. pick one, bestie, you can't do both 🌈


πŸ’€ RETURN VALUES πŸ’€

  • [EOPNOTSUPP] β€” memory range operations are not supported on this architecture. not here, not today.
  • [ENXIO] β€” no memory range descriptors are available (e.g. firmware has not enabled any). empty. nothing. crickets πŸ¦—
  • [EINVAL] β€” the memory range supplied as an argument is invalid or overlaps another range in a fashion not supported by this architecture. you did it wrong, respectfully.
  • [EBUSY] β€” an attempt to remove or update a range failed because the range is busy. it's booked and blessed, come back later.
  • [ENOSPC] β€” an attempt to create a new range failed due to a shortage of hardware resources (e.g. descriptor slots). no room at the inn 😭
  • [ENOENT] β€” an attempt to remove a range failed because no range matches the descriptor base/length supplied. you're removing something that isn't there. ghosting πŸ‘»
  • [EPERM] β€” an attempt to remove a range failed because the range is permanently enabled. permanently. ENABLED. let it live.

πŸŽ€ FILES πŸŽ€

  • /dev/mem
  • /dev/kmem

πŸ¦‹ SEE ALSO πŸ¦‹


⭐ HISTORY ⭐

the mem and kmem files appeared in Version 6 AT&T UNIX. yes, they're that old, they're basically vintage, they ate and left no crumbs. the ioctl interface for memory range attributes was added in FreeBSD 3.2. glow up πŸ’…


πŸ™ˆ BUGS πŸ™ˆ

busy range attributes are not yet managed correctly. we know. it's a known thing. it's fine. it's not fine but it's known.
this device is required for all users of kvm(3) to operate. like, required. you need it. no device, no kvm(3), no nothing. important!!! πŸ”₯

k that's the whole page bestie, mwah πŸ’– this one's from the Debian crew, dated October 3, 2004 β€” old but gold, and it still slays. go read your memory safely, i'm obsessed with you, bye πŸŽ€βœ¨

πŸ“¦ where this page comes from