diff --git a/Runner/suites/Kernel/Baseport/cma/README.md b/Runner/suites/Kernel/Baseport/cma/README.md new file mode 100644 index 00000000..d8d5a974 --- /dev/null +++ b/Runner/suites/Kernel/Baseport/cma/README.md @@ -0,0 +1,162 @@ +# CMA (Contiguous Memory Allocator) Enablement Test + +## Overview + +This test validates CMA (Contiguous Memory Allocator) enablement, configuration, and functionality on Qualcomm platforms. CMA is essential for allocating large contiguous memory blocks required by multimedia devices like cameras, displays, and video encoders. + +## What is CMA? + +CMA (Contiguous Memory Allocator) is a Linux kernel framework that: +- Reserves a pool of physically contiguous memory at boot time +- Allows normal page allocations from this pool when not in use +- Provides large contiguous allocations when needed by devices +- Critical for DMA operations requiring physically contiguous buffers + +## Test Coverage + +### 1. CMA Kernel Configuration +- **CONFIG_CMA** - Core CMA support (mandatory) +- **CONFIG_DMA_CMA** - Core CMA support (mandatory) +- **CONFIG_CMA_DEBUG** - Core CMA support (mandatory) +- **CONFIG_CMA_DEBUGFS** - Core CMA support (mandatory) +- **CONFIG_CMA_SIZE_MBYTES** - Default CMA size configuration +- **CONFIG_CMA_SIZE_SEL_MBYTES** - CMA size selection method +- **CONFIG_CMA_AREAS** - Maximum number of CMA areas + +### 2. CMA Memory Statistics +- Total CMA memory available +- Free CMA memory +- Used CMA memory +- Usage percentage calculation +- Size validation (minimum 1MB) + +### 3. CMA Device Tree Configuration +- CMA size from device tree +- CMA alignment properties +- Reserved memory region enumeration + +### 4. CMA Initialization and Runtime +- CMA reservation messages in kernel logs +- CMA allocation/release activity +- Error and warning detection +- Runtime behavior validation + +### 5. CMA Sysfs/Debugfs Interface +- CMA debugfs (`/sys/kernel/debug/cma`) +- CMA area enumeration +- Per-area allocation statistics +- CMA statistics in `/proc/vmstat` + +## Usage + +### Run directly: +```bash +cd /path/to/Runner/suites/Kernel/Baseport/cma +./run.sh +``` + +### Run via test runner: +```bash +cd /path/to/Runner +./run-test.sh cma +``` + +## Test Results + +Generates: +- `cma.res` - Final result (PASS/FAIL) +- Console output with detailed CMA information + +## Prerequisites + +### Required: +- `CONFIG_DMA_CMA=y` `CONFIG_CMA=y` `CONFIG_CMA_DEBUG=y` `CONFIG_CMA_DEBUGFS=y` in kernel configuration +- CMA memory reserved (via device tree or kernel command line) + +### Optional: +- Debugfs mounted at `/sys/kernel/debug` (for detailed statistics) +- Root or appropriate permissions + +## Expected Output + +``` +[INFO] 1980-01-06 00:18:47 - ================================================================================ +[INFO] 1980-01-06 00:18:47 - ============ Starting cma Testcase ======================================= +[INFO] 1980-01-06 00:18:47 - ================================================================================ +[INFO] 1980-01-06 00:18:47 - === CMA Kernel Configuration Validation === +[PASS] 1980-01-06 00:18:47 - Kernel config CONFIG_CMA is enabled +[PASS] 1980-01-06 00:18:47 - Kernel config CONFIG_DMA_CMA is enabled +[PASS] 1980-01-06 00:18:47 - Kernel config CONFIG_CMA_DEBUG is enabled +[PASS] 1980-01-06 00:18:47 - Kernel config CONFIG_CMA_DEBUGFS is enabled +[PASS] 1980-01-06 00:18:47 - CMA kernel configuration validated +[INFO] 1980-01-06 00:18:47 - Checking optional CMA configurations... +[FAIL] 1980-01-06 00:18:47 - Kernel config CONFIG_CMA_SIZE_MBYTES is missing or not enabled +[INFO] 1980-01-06 00:18:47 - CONFIG_CMA_SIZE_MBYTES: not set (optional) +[PASS] 1980-01-06 00:18:47 - Kernel config CONFIG_CMA_SIZE_SEL_MBYTES is enabled +[INFO] 1980-01-06 00:18:47 - CONFIG_CMA_SIZE_SEL_MBYTES: +[FAIL] 1980-01-06 00:18:48 - Kernel config CONFIG_CMA_AREAS is missing or not enabled +[INFO] 1980-01-06 00:18:48 - CONFIG_CMA_AREAS: not set (optional) +[INFO] 1980-01-06 00:18:48 - === CMA Memory Statistics === +[INFO] 1980-01-06 00:18:48 - CMA Memory Statistics: +[INFO] 1980-01-06 00:18:48 - Total: 172 MB (176128 kB) +[INFO] 1980-01-06 00:18:48 - Free: 119 MB (122548 kB) +[INFO] 1980-01-06 00:18:48 - Used: 52 MB (53580 kB) +[INFO] 1980-01-06 00:18:48 - Usage: 30% +[PASS] 1980-01-06 00:18:48 - CMA memory statistics validated +[INFO] 1980-01-06 00:18:48 - Total reserved memory regions: 32 +[INFO] 1980-01-06 00:18:48 - === CMA Initialization and Runtime === +[PASS] 1980-01-06 00:18:48 - CMA initialization messages found in dmesg: +[INFO] 1980-01-06 00:18:48 - [ 17.510276] cma: cma_alloc(cma ffffffc0823f1b38, name: reserved, count 2, align 1) +[INFO] 1980-01-06 00:18:48 - [ 17.924390] cma: cma_alloc(cma ffffffc0823f1b38, name: reserved, count 32, align 5) +[INFO] 1980-01-06 00:18:48 - [ 17.935579] cma: cma_alloc(cma ffffffc0823f1b38, name: reserved, count 128, align 7) +[INFO] 1980-01-06 00:18:48 - [ 18.501219] cma: cma_alloc(cma ffffffc0823f1b38, name: reserved, count 2, align 1) +[INFO] 1980-01-06 00:18:48 - CMA allocation/release activity detected +[INFO] 1980-01-06 00:18:48 - Allocations: 42 +[INFO] 1980-01-06 00:18:48 - Releases: 8 +[INFO] 1980-01-06 00:18:48 - === CMA Sysfs/Debugfs Interface === +[INFO] 1980-01-06 00:18:48 - Found CMA debugfs: /sys/kernel/debug/cma +[INFO] 1980-01-06 00:18:48 - CMA area: reserved +[INFO] 1980-01-06 00:18:48 - Total CMA areas: 1 +[PASS] 1980-01-06 00:18:48 - CMA statistics in /proc/vmstat: +[INFO] 1980-01-06 00:18:48 - nr_free_cma 30637 +[INFO] 1980-01-06 00:18:48 - cma_alloc_success 21 +[INFO] 1980-01-06 00:18:48 - cma_alloc_fail 0 +[INFO] 1980-01-06 00:18:48 - ================================================================================ +[PASS] 1980-01-06 00:18:48 - cma : Test Passed +``` + +## CMA Configuration Methods + +### 1. Device Tree Configuration (Recommended) +```dts +reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x20000000>; /* 512 MB */ + alignment = <0x0 0x00400000>; /* 4 MB */ + linux,cma-default; + }; +}; +``` + +### 2. Kernel Command Line +```bash +cma=512M +``` + +### 3. Kernel Config Default +``` +CONFIG_CMA_SIZE_MBYTES=512 +``` + + + +## License + +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause diff --git a/Runner/suites/Kernel/Baseport/cma/cma.yaml b/Runner/suites/Kernel/Baseport/cma/cma.yaml new file mode 100755 index 00000000..689727fc --- /dev/null +++ b/Runner/suites/Kernel/Baseport/cma/cma.yaml @@ -0,0 +1,23 @@ +metadata: + format: Lava-Test Test Definition 1.0 + name: cma + description: "CMA (Contiguous Memory Allocator) enablement and functionality validation" + maintainer: + - vnarapar@qti.qualcomm.com + os: + - openembedded + scope: + - functional + devices: + - rb3gen2 + - qcs6490 + - qcs8300 + - qcs9100 + - sa8775p + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/Kernel/Baseport/cma + - ./run.sh + - $REPO_PATH/Runner/utils/send-to-lava.sh cma.res diff --git a/Runner/suites/Kernel/Baseport/cma/run.sh b/Runner/suites/Kernel/Baseport/cma/run.sh new file mode 100755 index 00000000..0a75e90c --- /dev/null +++ b/Runner/suites/Kernel/Baseport/cma/run.sh @@ -0,0 +1,216 @@ +#!/bin/sh + +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause + +# Robustly find and source init_env +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +INIT_ENV="" +SEARCH="$SCRIPT_DIR" +while [ "$SEARCH" != "/" ]; do + if [ -f "$SEARCH/init_env" ]; then + INIT_ENV="$SEARCH/init_env" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env (starting at $SCRIPT_DIR)" >&2 + exit 1 +fi + +if [ -z "$__INIT_ENV_LOADED" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" +fi + +# shellcheck disable=SC1090,SC1091 +. "$TOOLS/functestlib.sh" + +TESTNAME="cma" +test_path=$(find_test_case_by_name "$TESTNAME") +cd "$test_path" || exit 1 +res_file="./$TESTNAME.res" + +log_info "================================================================================" +log_info "============ Starting $TESTNAME Testcase =======================================" +log_info "================================================================================" + +pass=true + +log_info "=== CMA Kernel Configuration Validation ===" + +# Core CMA configs +CORE_CMA_CONFIGS="CONFIG_CMA CONFIG_DMA_CMA CONFIG_CMA_DEBUG CONFIG_CMA_DEBUGFS" + +if ! check_kernel_config "$CORE_CMA_CONFIGS"; then + log_fail "CMA kernel configuration not enabled" + pass=false +else + log_pass "CMA kernel configuration validated" +fi + +OPTIONAL_CMA_CONFIGS="CONFIG_CMA_SIZE_MBYTES CONFIG_CMA_SIZE_SEL_MBYTES CONFIG_CMA_AREAS" + +log_info "Checking optional CMA configurations..." +for cfg in $OPTIONAL_CMA_CONFIGS; do + if check_optional_config "$cfg" 2>/dev/null; then + log_pass " $cfg: enabled" + else + log_warn " $cfg: not enabled (optional)" + fi +done + +if check_kernel_config "CONFIG_CMA_DEBUGFS" 2>/dev/null; then + log_pass "CONFIG_CMA_DEBUGFS: enabled" + if [ ! -d "/sys/kernel/debug/cma" ]; then + if [ ! -d "/sys/kernel/debug" ]; then + log_info "CONFIG_CMA_DEBUGFS is enabled but debugfs is not mounted" + log_info "Mounting debugfs" + if mount -t debugfs debugfs /sys/kernel/debug 2>/dev/null; then + log_pass "debugfs mounted successfully" + else + log_warn "Could not mount debugfs — CMA debugfs checks will be skipped" + fi + else + log_warn "CONFIG_CMA_DEBUGFS is enabled but /sys/kernel/debug/cma not found" + fi + fi +fi + +log_info "=== CMA Memory Statistics ===" + +if [ -f "/proc/meminfo" ]; then + if grep -q "CmaTotal" /proc/meminfo; then + cma_total=$(grep "CmaTotal" /proc/meminfo | awk '{print $2}') + cma_free=$(grep "CmaFree" /proc/meminfo | awk '{print $2}') + cma_used=$((cma_total - cma_free)) + + # Convert to MB for readability + cma_total_mb=$((cma_total / 1024)) + cma_free_mb=$((cma_free / 1024)) + cma_used_mb=$((cma_used / 1024)) + + log_info "CMA Memory Statistics:" + log_info " Total: ${cma_total_mb} MB (${cma_total} kB)" + log_info " Free: ${cma_free_mb} MB (${cma_free} kB)" + log_info " Used: ${cma_used_mb} MB (${cma_used} kB)" + + # Calculate usage percentage + if [ "$cma_total" -gt 0 ]; then + usage_percent=$((cma_used * 100 / cma_total)) + log_info " Usage: ${usage_percent}%" + fi + + if [ "$cma_total" -lt 1024 ]; then + log_fail "CMA total size is very small (< 1 MB)" + pass=false + else + log_pass "CMA memory statistics validated" + fi + else + log_fail "CMA statistics not found in /proc/meminfo" + pass=false + fi +else + log_fail "/proc/meminfo not accessible" + pass=false +fi + +if [ -d "/proc/device-tree/reserved-memory" ]; then + region_count=0 + for region in /proc/device-tree/reserved-memory/*; do + if [ -d "$region" ]; then + region_count=$((region_count + 1)) + fi + done + log_info "Total reserved memory regions: $region_count" +fi + +log_info "=== CMA Initialization and Runtime ===" + +# Capture dmesg once to a temp file to avoid subshell issues (pass=false inside +# a pipe subshell would not propagate to the outer shell) and to avoid running +# dmesg multiple times. +dmesg_tmp=$(mktemp /tmp/cma_dmesg.XXXXXX 2>/dev/null || echo "/tmp/cma_dmesg_$$.tmp") +dmesg > "$dmesg_tmp" 2>/dev/null + +# Broaden CMA reservation patterns to cover multiple kernel variants: +# cma: Reserved N MiB at ... (common upstream) +# CMA: Reserved N MiB at ... (some arch variants) +# Reserved memory: created CMA memory pool at ... +# OF: reserved mem: initialized node linux,cma ... +# reserved mem.*CMA (generic DT path) +CMA_INIT_PATTERN="cma:.*reserved|reserved memory:.*cma|linux,cma|of:.*reserved mem.*cma" + +if grep -i -q -E "$CMA_INIT_PATTERN" "$dmesg_tmp" 2>/dev/null; then + log_pass "CMA initialization messages found in dmesg:" + grep -i -E "$CMA_INIT_PATTERN" "$dmesg_tmp" 2>/dev/null | tail -n 5 | while IFS= read -r line; do + log_info " $line" + done +else + log_fail "No CMA initialization messages found in dmesg" + pass=false +fi + +# CMA allocation/release activity (informational only) +if grep -i -q -E "cma.*alloc|cma.*release" "$dmesg_tmp" 2>/dev/null; then + log_info "CMA allocation/release activity detected" + alloc_count=$(grep -i -c "cma.*alloc" "$dmesg_tmp" 2>/dev/null || echo 0) + release_count=$(grep -i -c "cma.*release" "$dmesg_tmp" 2>/dev/null || echo 0) + log_info " Allocations: $alloc_count" + log_info " Releases: $release_count" +fi + +# Check for CMA errors/warnings — capture to variable (not a pipe) so pass=false works +cma_errors=$(grep -i "cma" "$dmesg_tmp" 2>/dev/null | grep -i "error\|fail\|warn" || true) +if [ -n "$cma_errors" ]; then + log_fail "CMA warnings/errors found in dmesg:" + pass=false + printf '%s\n' "$cma_errors" | tail -n 3 | while IFS= read -r line; do + log_warn " $line" + done +fi + +rm -f "$dmesg_tmp" + +log_info "=== CMA Sysfs/Debugfs Interface ===" + +if [ -d "/sys/kernel/debug/cma" ]; then + log_info "Found CMA debugfs: /sys/kernel/debug/cma" + + cma_area_count=0 + for area in /sys/kernel/debug/cma/*; do + if [ -d "$area" ]; then + area_name=$(basename "$area") + log_info " CMA area: $area_name" + cma_area_count=$((cma_area_count + 1)) + fi + done + log_info " Total CMA areas: $cma_area_count" +else + log_warn "CMA debugfs not found (may need debugfs mounted or CONFIG_CMA_DEBUGFS enabled)" +fi + +if [ -f "/proc/vmstat" ]; then + if grep -q "cma" /proc/vmstat; then + log_pass "CMA statistics in /proc/vmstat:" + grep "cma" /proc/vmstat | while IFS= read -r line; do + log_info " $line" + done + else + log_fail "CMA statistics not found in /proc/vmstat" + pass=false + fi +fi + +if $pass; then + log_pass "$TESTNAME : Test Passed" + echo "$TESTNAME PASS" > "$res_file" +else + log_fail "$TESTNAME : Test Failed" + echo "$TESTNAME FAIL" > "$res_file" +fi +log_info "================================================================================" +exit 0 \ No newline at end of file