> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure and manage memory

The Qualcomm<sup>®</sup> Linux kernel baseline supports all memory management features and allocators. The following information outlines customizing the memory map and performing heap management.

For more information about Linux kernel memory management, see [Memory management](https://docs.kernel.org/core-api/index.html#memory-management).

**Memory map**

Memory map describes the areas that are reserved for subsystems, such as modem, camera, aDSP, and cDSP during kernel boot.

The memory map sets `no-map` for the carved out regions in the DTSI, making them inaccessible to the kernel.

Configurable carved-out regions are defined in the `arch/arm64/boot/dts/qcom/kodiak.dtsi` file under the `reserved-memory` node.

```text theme={null}
reserved-memory {
               cdsp_secure_heap_mem: cdsp-secure-heap@81800000 {
                        reg = <0x0 0x81800000 0x0 0x1e00000>;
                        no-map;
               };

               camera_mem: camera@84300000 {
                        reg = <0x0 0x84300000 0x0 0x500000>;
                        no-map;
               };

               wpss_mem: wpss@0x84800000 {
                        reg = <0x0 0x84800000 0x0 0x1900000>;
                        no-map;
               };

               adsp_mem: adsp@86100000 {
                        reg = <0x0 0x86100000 0x0 0x2800000>;
                        no-map;
               };
};
```

<Note>
  For Qualcomm SoCs, see the SoC-specific Qualcomm DTSI files to get this information.
</Note>

The following early boot log shows carved out region creation for different subsystems:

```text theme={null}
[    0.000000] OF: reserved mem: 0x0000000081800000..0x00000000835fffff (30720 KiB) nomap non-reusable cdsp-secure-heap@81800000
[    0.000000] OF: reserved mem: 0x0000000084300000..0x00000000847fffff (5120 KiB) nomap non-reusable camera@84300000
[    0.000000] OF: reserved mem: 0x0000000084800000..0x00000000860fffff (25600 KiB) nomap non-reusable wpss@0x84800000
[    0.000000] OF: reserved mem: 0x0000000086100000..0x00000000888fffff (40960 KiB) nomap non-reusable adsp@86100000
```

## Contiguous memory allocator

Qualcomm Linux distribution supports CMA to allocate large physically contiguous memory. CMA reserves a large physically contiguous memory area at boot time and provides physically continuous memory to CMA allocation. When not in use, CMA memory is available to the kernel buddy allocator for movable allocations.

To change the size of the default CMA region, run `cma=size_in_MB` in the kernel command-line arguments. For more information on how to use the kernel parameter, see the following example:

```text theme={null}
cma=nn[MG]@[start[MG][-end[MG]]]
                        [KNL,CMA]
                        Sets the size of kernel global memory area for
                        contiguous memory allocations and optionally the
                        placement constraint by the physical address range of
                        memory allocations. A value of 0 disables CMA
                        altogether. For more information, see
                        kernel/dma/contiguous.c
```

The custom CMA regions are defined under the `reserved-memory` node with a `shared-dma-pool` compatible tag indicating the CMA region:

```text theme={null}
adsp_heap_mem: adsp-heap {
                        compatible = "shared-dma-pool";
                        alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
                        reusable;
                        alignment = <0x0 0x400000>;
                        size = <0x0 0xc00000>;
               };
```

The following is the sample log for an aDSP CMA memory region reserved on boot:

```text theme={null}
[    0.000000] OF: reserved mem: initialized node adsp-heap, compatible id shared-dma-pool
[    0.000000] OF: reserved mem: 0x00000000ff000000..0x00000000ffbfffff (12288 KiB) map reusable adsp-heap
```

### **Supported heaps**

The following table lists the heaps that are supported by default on the Qualcomm Linux distribution:

**Table: Default supported heaps**

| **Heap name** |       **Dev node**      |                                     **Description**                                     |                                                          **Usage**                                                         |
| :-----------: | :---------------------: | :-------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------: |
|     System    |  /dev/dma\_heap/system  |                       The kernel creates the default DMA-BUF heap.                      | All generic use cases must follow the system heap that uses the common Linux memory management buddy allocator underneath. |
|    Reserved   | /dev/dma\_heap/reserved | The default CMA-type heap created in the system uses the default *reserved* CMA region. |                           If you need contiguous memory due to any constraints, use the CMA heap.                          |

### **Use DMA-BUF heaps**

DMA-BUF heaps are supported on the Qualcomm Linux distribution to assign custom CMA heaps. With DMA-BUF heaps, a device file is present for each heap in the `/dev/dma_heap` file system. Apart from the system heap and the common CMA reserved heap, you can create your own CMA-type DMA-BUF heaps.

The following is a sample program that demonstrates how to use the DMA-BUF system heap created by the Qualcomm Linux kernel in `/dev/dma_heap/system:`

```text theme={null}
include <stdio.h>
include <stdlib.h>
include <fcntl.h>
include <errno.h>
include <unistd.h>
include <sys/ioctl.h>
include <linux/dma-buf.h>
#include <linux/dma-heap.h>

define DMA_HEAP_NAME "system"
define SZ_4 0x00000004  // to allocate a 4K buffer

int main()
{
int fd, dma_buf_fd;

struct dma_heap_allocation_data dma_alloc_data = {
   .len = SZ_4,
   .fd_flags = O_RDWR | O_CLOEXEC,
};

struct dma_buf_sync sync_start = {
   .flags = DMA_BUF_SYNC_START,
};
struct dma_buf_sync sync_end = {
   .flags = DMA_BUF_SYNC_END,
};

fd = open("/dev/dma_heap/system", O_RDWR);
if (fd < 0) {
   perror("open");
   return errno;
}

dma_buf_fd = ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &dma_alloc_data);
if (dma_buf_fd < 0) {
   perror("ioctl");
   return errno;
}
printf("Allocated DMA buffer with fd %d\n", dma_buf_fd);

if (ioctl(dma_buf_fd, DMA_BUF_IOCTL_SYNC, &sync_start)) {
   perror("ioctl DMA_BUF_IOCTL_SYNC start");
   return errno;
}

//        Do something with the buffer here

if (ioctl(dma_buf_fd, DMA_BUF_IOCTL_SYNC, &sync_end))
{
   perror("ioctl DMA_BUF_IOCTL_SYNC end");
   return errno;
}

if (close(dma_buf_fd)) {
   perror("close");
   return errno;
}

if (close(fd)) {
   perror("close");
   return errno;
}

return 0;
}
```

### **Configure ZRAM as a swap device**

ZRAM is a compressed swap mechanism that creates a virtual block device in RAM. ZRAM is enabled as a module within the kernel defconfig.

ZRAM is configured in the Yocto build in the `recipes-extended/zram/zram/zram-swap-init-update` file.

To enable or configure ZRAM, do the following:

```text theme={null}
# check if zram module is loaded
  lsmod | grep zram

# else load it
  modprobe zram

# Configure /dev/zram0 size according to your RAM size
  echo 128M > /sys/block/zram0/disksize

# activate swap
  mkswap /dev/zram0
  swapon /dev/zram0
```

To configure ZRAM as a swap device, see [zram: Compressed RAM-based block devices](https://www.kernel.org/doc/html/v6.18/admin-guide/blockdev/zram.html).

### **Extend the memory map**

To extend the memory map, adjust the addresses and sizes of memory regions in a DTSI file.

Use the following information to extend the carved out regions:

Add the carved out region in the `arch/arm64/boot/dts/qcom/<SoC>-<board>-<variant>.dts` file in the **reserved-memory** node using the following syntax:

```text theme={null}
my_carveout_mem: my_carveout_mem@address {
      reg= <0x0 0xbase_address 0x0 0xsize>;
      no-map;
}
```

For example:

```text theme={null}
my_carveout_mem: my_carveout_mem@d0800000 {
      reg= <0x0 0xd0800000 0x0 0x100000>;
      no-map;
}
```

**Table: Syntax for carved out region**

|         **Variable**        |                                                                  **Description**                                                                 |
| :-------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------: |
| my\_carveout\_mem\@d0800000 |         Indicates the name of the device node. The convention mandates that you append the base address of the memory region to the name.        |
|      my\_carveout\_mem      | Indicates the label assigned to this node that can be used to reference this node from within the other nodes in the device tree using phandles. |
|             reg             |                       Indicates the property, which is a 64‑bit value that defines the base and size of the memory region.                       |
|            no-map           |                   Indicates that this region is carved out and the kernel should remove the mapping from its addressable range.                  |

<Note>
  * None of the regions should overlap. If you must increase a region size, shift all other subsequent regions, and configure them in the device tree to avoid overlapping.
  * The kernel expects all memory region boundaries defined for kernel usage to be 1 MB.
  * Existing carved out regions are protected by trusted firmware from kernel access. Decreasing their size or deleting them may result in an external abort, leading to a kernel crash.
</Note>

**Add CMA region**

To add the CMA region in the `arch/arm64/boot/dts/qcom/<SoC>-<board>-<variant>.dts` file under **reserved-memory** node, use the following syntax:

```text theme={null}
my_cma_mem: my_cma {
   compatible = "shared-dma-pool";
   alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
   reusable;
   alignment = <0x0 0x400000>;
   size = <0x0 0x1400000>;
};
```

**Table : Syntax for adding CMA region**

|  **Parameters** |                                                                          **Description**                                                                          |
| :-------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|   my\_cma\_mem  |                             Label for the CMA node and can be accessed as a phandle. The label `my_cma` is the name of the CMA region.                            |
| shared-dma-pool |                                                             Indicates that this region is a CMA area.                                                             |
|   alloc-ranges  |          Indicates if the region should be within a certain memory limit, as some devices can not access memory regions beyond the 32‑bit address limit.          |
|     reusable    |                                            Indicates that the kernel can use the memory in this region when it’s free.                                            |
|    alignment    |                                                        Indicates any alignment requirements in this region.                                                       |
|       size      |                                                                 Indicates the size of the region.                                                                 |
|       reg       | This is an optional attribute that indicates the fixed region for memory allocation, in the absence of which memory is dynamically allocated at a random address. |
