Linux Reserved Memory

One of the common requirements on Xilinx Zynq SoC/MPSoC based system is to reserve memory regions for special usage, excluding it from the usage of Linux kernel and making it available only for a custom device driver. This feature is covered by the reserved-memory framework and is closely related to the DMA-API and CMA frameworks within the kernel.

This article is intended to showcase and explain some of the use cases available, and has been tested using Petalinux build tool, but can be exported for the Yocto or OSL workflows, as the steps refer only to the DTS file customization and a custom device driver where the memory is allocated.

Table of Contents

Reserved memory

To reserve a memory range from system address space, the reserved-memory node can be used in the device-tree configuration. Each child node defines a specific memory space and can be configured according the different parameters available for the reserved memory nodes as described in the kernel docs. The reserved memory spaces can then be assigned to a specific device driver through the memory-region parameter.

Device-tree nodes within system-top.dts file for a 64-bit Cortex-A53 MPSoC:
Or similar device-tree nodes for customization in the more recent Yocto-based Petalinux project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi for a 32-bit Cortex-A9 Zynq:

In the device driver, the properties of the memory region can be handled parsing the device tree nodes, and once the physical address and size are known the memory region can be mapped using memremap/ioremap calls. Below the code referred to the reserved memory allocation:

As the reserved memory region has been excluded for the common usage by the kernel and marked as no-map, the iomem information (/proc/iomem) shows that the System RAM is less than the amount of memory in the board.

Once the device is loaded, the allocation can be confirmed:

Reserved memory through DMA API

Commonly the reserved memory spaces are being used with DMA engines, so integrating both frameworks can be useful from the device driver point of view. For that particular purspose the compatible property can be set as shared-dma-pool, generating a DMA memory pool reserved for a particular device driver.
This way the device driver only need to use the DMA API in the regular way, but instead of using the default CMA memory pool it will use the reserved memory region for this particular device.

Kernel bootlog:
Kernel log after loading the device driver :

Reserved memory for CMA

Sometimes the reserved memory region does not require to be assigned to an specific device driver and is only intended to have a bigger CMA memory pool than the default one. For that particular use case, an extra property can be used to point to the kernel to use the reserved memory region as the default CMA memory pool.

The kernel bootlog confirms the custom CMA memory pool allocation:

Petalinux example

These use cases can be tested using the Petalinux build tool following the steps above:
  1. Generate a petalinux project using a BSP package (ZC702 for Zynq-7000 or ZCU102 for Zynq MPSoC)
  2. Modify the dts file to include the reserved memory node
  3. Create a driver module and modify the default content of the driver
  4. Build the project and launch it on QEMU

Related Links