# Đặt cấu hình và quản lý bộ nhớ

Nền tảng Qualcomm^®^ Linux kernel hỗ trợ mọi tính năng quản lý và cấp phát bộ nhớ. Thông tin sau đây trình bày cách tùy chỉnh sơ đồ bộ nhớ và thực hiện quản lý heap.

Để biết thêm thông tin về quản lý bộ nhớ Linux kernel, hãy xem [Memory management](https://www.kernel.org/doc/html/next/core-api/index.html#memory-management).

**Sơ đồ bộ nhớ**

Sơ đồ bộ nhớ mô tả các vùng dành riêng cho các hệ thống con, chẳng hạn như modem, camera, aDSP và cDSP trong quá trình khởi động kernel.

Sơ đồ bộ nhớ đặt `no-map` cho các vùng carved out trong DTSI, để kernel không thể truy cập được vào các vùng đó.

Các vùng carved-out có thể đặt cấu hình được định nghĩa trong tệp `arch/arm64/boot/dts/qcom/qcs6490.dtsi` trong node `reserved-memory`.

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;
                   };
    };
    Copy to clipboard

Ghi chú

Đối với Qualcomm SoC, hãy xem các tệp Qualcomm DTSI dành riêng cho SoC để biết thông tin này.

Log khởi động sau đây mô tả quá trình tạo vùng nhớ carved out cho các hệ thống con khác nhau:

[    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
    Copy to clipboard

## Trình cấp phát bộ nhớ liên tục

Bản phân phối Qualcomm Linux hỗ trợ CMA để cấp phát bộ nhớ vật lý liên tục lớn. CMA dành riêng một vùng bộ nhớ vật lý liên tục lớn tại thời điểm khởi động và cung cấp bộ nhớ vật lý liên tục cho quá trình cấp phát CMA. Khi bộ nhớ CMA không được sử dụng, trình cấp phát kernel buddy có thể dùng bộ nhớ này để cấp phát di động.

Để thay đổi kích thước của vùng CMA mặc định, hãy chạy `cma=size_in_MB` trong đối số dòng lệnh của kernel. Để biết thêm thông tin về cách sử dụng tham số kernel, hãy xem ví dụ sau:

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
    Copy to clipboard

Các vùng CMA tùy chỉnh được định nghĩa trong node `reserved-memory` với thẻ tương thích `shared-dma-pool` để chỉ vùng CMA:

adsp_heap_mem: adsp-heap {
                            compatible = "shared-dma-pool";
                            alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
                            reusable;
                            alignment = <0x0 0x400000>;
                            size = <0x0 0xc00000>;
                   };
    Copy to clipboard

Sau đây là log mẫu cho vùng bộ nhớ aDSP CMA được dành riêng khi khởi động:

[    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
    Copy to clipboard

### Thêm heap CMA tùy chỉnh

Để tạo các vùng CMA tùy chỉnh bằng heap DMA-BUF, hãy sử dụng DMA-BUF framework có sẵn trong Qualcomm Linux kernel.

Qualcomm Linux kernel xuất API `cma_heap_add()` cho các heap DMA-BUF tùy chỉnh.

/**
    * cma_heap_add - adds a CMA heap to dmabuf heaps
    * @cma:       pointer to the CMA pool to register the heap for
    * @data:      unused
    *
    * Returns 0 on success. Else, returns errno.
    */
    
    int cma_heap_add(struct cma *cma, void *data);
    Copy to clipboard

Heap DMA-BUF được xuất sang không gian người dùng, có tên trùng với phandle của vùng CMA trong device tree.

Để thêm một heap CMA tùy chỉnh, hãy thực hiện như sau:

1. Để tạo một vùng CMA tùy chỉnh, hãy xem [Bộ cấp phát bộ nhớ liên tục](https://docs.qualcomm.com/doc/80-70020-3VI/topic/memory.html#memory-contiguous).
2. Trong driver mà bạn đang thêm một heap tùy chỉnh:

    1. Phân tích device tree để xác định vùng CMA mới thêm.
    2. Thêm một heap DMA-BUF liên kết với driver.

int create_my_cma_heap(struct device *dev)
            {
               int rc = 0, idx = 0;
            
               rc = of_reserved_mem_device_init_by_idx(dev, dev->of_node, 0);  // Parse the devicetree for the cma region
            
               if (rc) {
                        pr_err("No reserved DMA memory, ret=%d\n", rc);
                        rc = -EINVAL;
                        goto err;
               }
            
               rc = cma_heap_add(dev->cma_area, NULL);  // Add a dmabuf heap associated with the cma region
            
               if (rc) {
                        pr_err("cma_heap_add failed, ret=%d\n", rc);
                        rc = -EINVAL;
                        goto err;
               }
            
            err:
               return rc;
            }
            Copy to clipboard

Ghi chú

Điều chỉnh các vùng CMA theo kích thước và địa chỉ cơ sở 4 MB để hỗ trợ việc chuyển đổi trang. Việc chuyển đổi diễn ra trên 2 trang ^pageblock\_order^ ở cấp độ page-block. Thứ tự page-block là 10 trong Qualcomm Linux kernel.

### Heap được hỗ trợ

Bảng sau đây liệt kê các heap được hỗ trợ theo mặc định trên bản phân phối Qualcomm Linux:

Bảng: Heap mặc định được hỗ trợ

| Tên heap | Dev node | Mô tả | Sử dụng |
| --- | --- | --- | --- |
| Hệ thống | /dev/dma_heap/system<br>    Copy to clipboard | Kernel tạo ra heap DMA-BUF mặc định. | Tất cả các use case chung phải tuân theo heap hệ thống sử dụng trình cấp phát buddy quản lý bộ nhớ Linux chung bên dưới. |
| Được dành riêng | /dev/dma_heap/reserved<br>    Copy to clipboard | Heap loại CMA mặc định được tạo trong hệ thống sử dụng vùng CMA *dành riêng* mặc định. | Nếu bạn cần bộ nhớ liên tục do bất kỳ ràng buộc nào, hãy sử dụng heap CMA. |
| Heap CMA tùy chỉnh | /dev/dma_heap/my_cma_heap<br>    Copy to clipboard | Heap loại CMA do người dùng định nghĩa. | Nếu bạn muốn tạo heap loại CMA của riêng mình cho các heap CMA tùy chỉnh cụ thể. |

### Sử dụng heap DMA-BUF

Heap DMA-BUF được hỗ trợ trên bản phân phối Qualcomm Linux để gán heap CMA tùy chỉnh. Với heap DMA-BUF, sẽ có một tệp thiết bị cho mỗi heap trong hệ thống tệp `/dev/dma_heap`. Ngoài heap hệ thống và heap dành riêng cho CMA chung, bạn có thể tạo heap DMA-BUF loại CMA của riêng mình.

Sau đây là một chương trình mẫu minh họa cách sử dụng heap hệ thống DMA-BUF được tạo bằng Qualcomm Linux kernel trong `/dev/dma_heap/system:`

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;
    }
    Copy to clipboard

### Đặt cấu hình ZRAM làm thiết bị swap

ZRAM là cơ chế swap có nén tạo ra thiết bị khối ảo trong RAM. ZRAM được bật như một mô-đun trong kernel defconfig.

ZRAM được đặt cấu hình trong hệ thống build Yocto trong tệp `recipes-extended/zram/zram/zram-swap-init-update`.

Để kích hoạt hoặc đặt cấu hình ZRAM, hãy thực hiện như sau:

# 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
    Copy to clipboard

Để đặt cấu hình ZRAM làm thiết bị swap, hãy xem [zram: Compressed RAM-based block devices](https://www.kernel.org/doc/html/v6.6/admin-guide/blockdev/zram.html).

### Mở rộng sơ đồ bộ nhớ

Để mở rộng sơ đồ bộ nhớ, hãy điều chỉnh địa chỉ và kích thước của vùng bộ nhớ trong tệp DTSI.

Sử dụng thông tin sau để mở rộng các vùng carved out:

Thêm vùng nhớ carved out  trong tệp `arch/arm64/boot/dts/qcom/<SoC>-<board>-<variant>.dts` vào node **reserved-memory** bằng cú pháp sau:

my_carveout_mem: my_carveout_mem@address {
          reg= <0x0 0xbase_address 0x0 0xsize>;
          no-map;
    }
    Copy to clipboard

Ví dụ:

my_carveout_mem: my_carveout_mem@d0800000 {
          reg= <0x0 0xd0800000 0x0 0x100000>;
          no-map;
    }
    Copy to clipboard

Bảng: Cú pháp của vùng  carved out

| Biến | Mô tả |
| --- | --- |
| my_carveout_mem@d0800000<br>    Copy to clipboard | Cho biết tên của node thiết bị. Quy ước này yêu cầu bạn phải thêm địa chỉ cơ sở của vùng bộ nhớ vào tên. |
| my_carveout_mem<br>    Copy to clipboard | Chỉ ra nhãn được gán cho node này để có thể được dùng để tham chiếu từ bên trong các node khác trong device tree bằng cách sử dụng phandle. |
| reg<br>    Copy to clipboard | Chỉ ra thuộc tính là giá trị 64 bit định nghĩa địa chỉ cơ sở và kích thước của vùng bộ nhớ. |
| no-map<br>    Copy to clipboard | Chỉ ra rằng vùng carved out và kernel phải xóa ánh xạ khỏi phạm vi địa chỉ có thể truy cập. |

Ghi chú

- Không có vùng nhớ nào được chồng chéo. Nếu bạn phải tăng kích thước vùng nhớ, hãy dịch chuyển tất cả các vùng nhớ kế tiếp và đặt cấu hình chúng trong device tree để tránh chồng chéo.
- Kernel yêu cầu tất cả các ranh giới vùng bộ nhớ được định nghĩa để sử dụng ở kernel phải có kích thước là 1 MB.
- Các vùng carved out hiện có được firmware đáng tin cậy bảo vệ để ngăn truy cập từ  kernel. Việc giảm kích thước hoặc xóa các vùng đó có thể dẫn đến external abort, và dẫn đến lỗi kernel crash.

**Thêm vùng CMA**

Để thêm vùng CMA vào tệp `arch/arm64/boot/dts/qcom/<SoC>-<board>-<variant>.dts` dưới node **reserved-memory**, hãy sử dụng cú pháp sau:

my_cma_mem: my_cma {
       compatible = "shared-dma-pool";
       alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
       reusable;
       alignment = <0x0 0x400000>;
       size = <0x0 0x1400000>;
    };
    Copy to clipboard

Bảng: Cú pháp để thêm vùng CMA

| Tham số | Mô tả |
| --- | --- |
| my_cma_mem<br>    Copy to clipboard | Gắn nhãn cho node CMA và có thể truy cập được như một phandle. Nhãn `my_cma` là tên của vùng CMA. |
| shared-dma-pool<br>    Copy to clipboard | Chỉ ra rằng vùng này là khu vực CMA. |
| alloc-ranges<br>    Copy to clipboard | Chỉ ra liệu vùng này có nằm trong giới hạn bộ nhớ nhất định hay không, vì một số thiết bị không thể truy cập vào vùng bộ nhớ vượt quá giới hạn địa chỉ 32 bit. |
| reusable<br>    Copy to clipboard | Chỉ ra rằng kernel có thể sử dụng bộ nhớ trong vùng này khi bộ nhớ trống. |
| alignment<br>    Copy to clipboard | Chỉ ra bất kỳ yêu cầu căn chỉnh nào trong vùng này. |
| size<br>    Copy to clipboard | Chỉ ra kích thước của vùng. |
| reg<br>    Copy to clipboard | Đây là thuộc tính tùy chọn chỉ ra vùng cố định để phân bổ bộ nhớ. Nếu không có vùng này, bộ nhớ sẽ được phân bổ động tại một địa chỉ ngẫu nhiên. |

Last Published: Jan 01, 2026

[Previous Topic
Đặt cấu hình các hệ thống con bộ xử lý từ xa (remoteproc)](https://docs.qualcomm.com/bundle/publicresource/80-70020-3VI/topics/remoteproc-overview.md) [Next Topic
Đặt cấu hình trình lập lịch](https://docs.qualcomm.com/bundle/publicresource/80-70020-3VI/topics/scheduler.md)