Deferred system RAM

Deferred system RAM allows you to add one or more contiguous regions of the physical address space to the System RAM managed by the Virtual Memory Manager (VMM) at runtime. This is useful in scenarios where initializing a large amount of ECC (error correction code) memory significantly lengthens boot time of the first process (and therefore, subsequent processes). Instead, you can initialize a smaller amount of ECC RAM to boot the kernel and run essential processes, and defer the ECC initialization of the remaining RAM afterwards.

Using deferred system RAM can take a significant amount of time and interfere with other VMM-based operations (e.g., mmap()). Therefore, you should minimize or avoid VMM-based and time-sensitive operations when using this functionality.

Any RAM being added must meet the requirements of system RAM, which include:
  • readable, writable, and cacheable
  • cache-coherent
  • initialized and ready for immediate use
  • suitable for use as a DMA source or destination by all DMA-capable devices under the control of QNX

_mem_pmem_add and mem_pmem_add_t

To add RAM using the deferred system RAM mechanism, you must send a mem_pmem_add_t structure to the memory manager server via the MEMMGR_COID connection. The RAM shouldn't have any mappings to it at the time it's added.

The syntax for _mem_pmem_add and mem_pmem_add_t is as follows:

struct _mem_pmem_add {
 _Uint16t      type;
 _Uint16t      zero1;
 _Uint32t      zero2;
 _Uint64t      addr;
 _Uint64t      len;
};

typedef union {
 struct _mem_pmem_add   i;
} mem_pmem_add_t;
type
The message type; set to _MEM_PMEM_ADD.
zero1, zero2
Unused; set to zero.
addr
The base address of the region of RAM to be added. This must be a zone-aligned value, where a zone (also referred to as a contiguous physical memory block) is 16 MiB (16 * 1024 * 1024).
Note:
QNX only supports physical addresses in the range [0, 16TiB[.
len
The length of the region of RAM to be added. This must be an integral multiple of a zone.

Deferred system RAM uses the contiguous physical address range to be added, where:

  • The ability check is done on the unrounded range.
  • The address range is rounded before it's considered for adding to system RAM, where end = start + len. If end isn't the address of the highest byte of a page, then round end down to the next lower page address by clearing the bottom 12 bits, and then subtracting 1. If start is not a page-aligned address, it's rounded up to the next higher page-aligned address.
Note:
The requesting process must have the PROCMGR_AID_MEM_ADD ability enabled.

If the region is successfully added, the return value is 0 (EOK).

Example

The following example demonstrates how to use the deferred system RAM functionality by:

  1. initializing the message by setting it to 0, or using a designated initializer.
  2. initializing the type, addr, and len fields such that:
    • the type is _MEM_PMEM_ADD.
    • the len is a multiple of the size of a zone.
  3. sending the message to the memory manager via MEMMGR_COID.
  4. returning errors returned by MsgSend_r().
#include <sys/memmsg.h>

int deferred_sysram_add_ram(const uint64_t base_addr, const uint64_t len)
{
    // Note that everything else in the struct will be zeroed
    const mem_pmem_add_t msg = {
        .i.type = _MEM_PMEM_ADD,
        .i.addr = base_addr,
        .i.len  = len,
    };

    const int rv = MsgSend_r(MEMMGR_COID, &msg, sizeof(msg), NULL, 0);
    return rv;
}

Using deferred system RAM at startup

The following steps show you how to use deferred system RAM with your program:

  1. Before making any changes, observe the contents of the asinfo section:
     / # pidin syspage=asinfo
    Header size=0x000000f0, Total Size=0x00000980, Version=2.0, #Cpu=2, Type=4352
    Section:asinfo offset:0x000005c0 size:0x00000240 elsize:0x00000018
      0000) 0000000000000000-000000000000ffff o:ffff /io
      0018) 0000000000000000-000fffffffffffff o:ffff /memory
      0030) 0000000000000000-00000000ffffffff o:0018 /memory/below4G
      0048) 0000000000000000-0000000000ffffff o:0018 /memory/isa
      0060) 0000000006000000-00000000ffefffff o:0018 /memory/device
      0078) 00000000fff00000-00000000ffffffff o:0018 /memory/rom
      0090) 0000000000000000-000000000009fbff o:0048 /memory/isa/ram
      00a8) 0000000000100000-0000000000ffffff o:0048 /memory/isa/ram
      00c0) 0000000001000000-0000000005ffffff o:0030 /memory/below4G/ram
      00d8) 0000000006000000-00000000bffdffff o:0060 /memory/device/ram
      00f0) 0000000100000000-000000023fffffff o:0018 /memory/ram
      0108) 00000000000f5a60-00000000000f5a73 o:0018 /memory/acpi_rsdp
      0120) 00000000fee00000-00000000fee003ef o:0018 /memory/lapic
      0138) 0000000000835348-0000000000e2e043 o:0018 /memory/imagefs
      0150) 0000000000800200-0000000000835347 o:0018 /memory/startup
      0168) 0000000000835348-0000000000e2e043 o:0018 /memory/bootram
      0180) 0000000000001000-000000000009efff o:0090 /memory/isa/ram/sysram
      0198) 0000000000100000-000000000010ffff o:00a8 /memory/isa/ram/sysram
      01b0) 0000000000117000-0000000000117fff o:00a8 /memory/isa/ram/sysram
      01c8) 000000000011f000-0000000000834fff o:00a8 /memory/isa/ram/sysram
      01e0) 0000000000e2f000-0000000000ffffff o:00a8 /memory/isa/ram/sysram
      01f8) 0000000001000000-0000000005ffffff o:00c0 /memory/below4G/ram/sysram
      0210) 0000000006000000-00000000bffdffff o:00d8 /memory/device/ram/sysram
      0228) 0000000100000000-0000000239fc2fff o:00f0 /memory/ram/sysram
  2. Check how much memory is free:
     / # ls -ld /proc
    dr-xr-xr-x  2 root root 8478986240 2026-05-11 14:38 proc
     / #

    In this example, 8478986240 bytes are free (i.e., just under 8 GB).

  3. Add the following -R option to the startup command line to set aside a 4G contiguous region of system RAM that has a physical start address that is 16MB aligned. Create an asinfo entry for it named extra_ram:
    -R 4G,16M,extra_ram
  4. Reboot your system and show the contents of the asinfo section again:
     / # pidin syspage=asinfo
    Header size=0x000000f0, Total Size=0x00000998, Version=2.0, #Cpu=2, Type=4352
    Section:asinfo offset:0x000005c0 size:0x00000258 elsize:0x00000018
      0000) 0000000000000000-000000000000ffff o:ffff /io
      0018) 0000000000000000-000fffffffffffff o:ffff /memory
      0030) 0000000000000000-00000000ffffffff o:0018 /memory/below4G
      0048) 0000000000000000-0000000000ffffff o:0018 /memory/isa
      0060) 0000000006000000-00000000ffefffff o:0018 /memory/device
      0078) 00000000fff00000-00000000ffffffff o:0018 /memory/rom
      0090) 0000000000000000-000000000009fbff o:0048 /memory/isa/ram
      00a8) 0000000000100000-0000000000ffffff o:0048 /memory/isa/ram
      00c0) 0000000001000000-0000000005ffffff o:0030 /memory/below4G/ram
      00d8) 0000000006000000-00000000bffdffff o:0060 /memory/device/ram
      00f0) 0000000100000000-000000023fffffff o:0018 /memory/ram
      0108) 00000000000f5a60-00000000000f5a73 o:0018 /memory/acpi_rsdp
      0120) 00000000fee00000-00000000fee003ef o:0018 /memory/lapic
      0138) 0000000000835348-0000000000e2e043 o:0018 /memory/imagefs
      0150) 0000000000800200-0000000000835347 o:0018 /memory/startup
      0168) 0000000000835348-0000000000e2e043 o:0018 /memory/bootram
      0180) 0000000140000000-000000023fffffff o:00f0 /memory/ram/extra_ram
      0198) 0000000000001000-000000000009efff o:0090 /memory/isa/ram/sysram
      01b0) 0000000000100000-000000000010ffff o:00a8 /memory/isa/ram/sysram
      01c8) 0000000000117000-0000000000117fff o:00a8 /memory/isa/ram/sysram
      01e0) 000000000011f000-0000000000834fff o:00a8 /memory/isa/ram/sysram
      01f8) 0000000000e2f000-0000000000ffffff o:00a8 /memory/isa/ram/sysram
      0210) 0000000001000000-0000000005ffffff o:00c0 /memory/below4G/ram/sysram
      0228) 0000000006000000-00000000b9fa2fff o:00d8 /memory/device/ram/sysram
      0240) 0000000100000000-000000013fffffff o:00f0 /memory/ram/sysram

    Note the asinfo at offset 0x0180 with the name extra_ram. The range starts at physical address 0x0000'0001'4000'0000, which is a multiple of 16MB (i.e., 0x0100'0000), and ends at 0x0000'0002'3fff'ffff. Therefore, the range is 4 GB, where:

    (0x0000'0002'3fff'ffff - 0x0000'0001'4000'0000 + 1) / 1024 / 1024 / 1024 = 4 GB
    Notice that there's less system RAM available:
     / # ls -ld /proc
    dr-xr-xr-x  2 root root 4184031232 2026-05-11 14:40 proc
     / #
  5. Run your program that adds extra_ram as deferred system RAM. For this example, the program is named add_deferred_sysram, and it exits with 0 only on success:
    / # add_deferred_sysram
    / # echo $?
    0
    / #
    Notice that after running your program, more system RAM is available:
     / # ls -ld /proc
    dr-xr-xr-x  2 root root 8478998528 2026-05-11 14:41 proc
     / #
Page updated: