Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Runner/suites/Kernel/Scheduler/PELT_config/PELT_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
metadata:
name: pelt-config
format: "Lava-Test Test Definition 1.0"
description: "Validates kernel configuration required for PELT (Per-Entity Load Tracking) scheduler"
maintainer:
- vnarapar@qti.qualcomm.com
os:
- linux
scope:
- functional
devices:
- rb3gen2
- qcs6490
- qcs8300
- qcs9100
- sa8775p

run:
steps:
- REPO_PATH=$PWD
- cd "$REPO_PATH/Runner/suites/Kernel/Scheduler/PELT_config" || true
- ./run.sh || true
- $REPO_PATH/Runner/utils/send-to-lava.sh PELT_config.res || true
37 changes: 37 additions & 0 deletions Runner/suites/Kernel/Scheduler/PELT_config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# PELT_config — PELT Kernel Configuration Validation

## Overview

Validates that the kernel is built with the configurations required for
**PELT (Per-Entity Load Tracking)**, the Linux CFS scheduler mechanism that
tracks CPU utilization per scheduling entity (tasks and task groups).

## What Is Tested

| Config | Required | Purpose |
|---|---|---|
| `CONFIG_SMP` | Yes | Multi-CPU support — PELT load balancing is SMP-only |
| `CONFIG_FAIR_GROUP_SCHED` | Yes | Per-entity load tracking across scheduling groups |
| `CONFIG_SCHED_DEBUG` | Optional | Enables `/sys/kernel/debug/sched` and `/proc/<pid>/sched` |
| `CONFIG_CFS_BANDWIDTH` | Optional | CFS bandwidth control (uses PELT util signals) |
| `CONFIG_NO_HZ_COMMON` | Optional | Tickless kernel — affects PELT decay accuracy |
| `CONFIG_SCHED_AUTOGROUP` | Optional | Automatic task group creation |
| `CONFIG_CGROUP_SCHED` | Optional | cgroup-based scheduling (PELT tracks per cgroup) |
| `CONFIG_CPU_FREQ_GOV_SCHEDUTIL` | Optional | schedutil governor — consumes PELT util_avg |

## Pass / Fail / Skip Criteria

- **SKIP**: `/proc/config.gz` not present (CONFIG_IKCONFIG not enabled)
- **FAIL**: `CONFIG_SMP` or `CONFIG_FAIR_GROUP_SCHED` not enabled
- **PASS**: All required configs enabled (optional configs logged as warnings only)

## Usage

```sh
./run.sh
```

## Dependencies

- `/proc/config.gz` (CONFIG_IKCONFIG + CONFIG_IKCONFIG_PROC)
- `grep`, `zgrep` or `gzip` (provided by functestlib)
84 changes: 84 additions & 0 deletions Runner/suites/Kernel/Scheduler/PELT_config/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/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="PELT_config"
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 "================================================================================"
log_info "Validates kernel configuration required for PELT (Per-Entity Load Tracking)"

check_dependencies grep

pass=true

if [ ! -f /proc/config.gz ]; then
log_warn "/proc/config.gz not found — skipping kernel config checks"
log_warn "Enable CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC for config validation"
echo "$TESTNAME SKIP" > "$res_file"
exit 0
fi

log_info "=== Core PELT / CFS Kernel Configs ==="

if [ ! -f /proc/config.gz ]; then
log_warn "/proc/config.gz not found — kernel config checks will be skipped"
log_warn "Ensure CONFIG_IKCONFIG and CONFIG_IKCONFIG_PROC are enabled in the kernel"
else
CORE_CONFIGS="CONFIG_FAIR_GROUP_SCHED CONFIG_SMP"

if ! check_kernel_config "$CORE_CONFIGS"; then
log_fail "Core DMA-BUF kernel config validation failed"
pass=false
else
log_pass "Core DMA-BUF configs available"
fi

OPTIONAL_CONFIGS="CONFIG_SCHED_DEBUG CONFIG_CFS_BANDWIDTH CONFIG_NO_HZ_COMMON CONFIG_SCHED_AUTOGROUP CONFIG_CGROUP_SCHED CONFIG_CPU_FREQ_GOV_SCHEDUTIL"

log_info "Checking optional DMA-BUF configurations..."
for cfg in $OPTIONAL_CONFIGS; do
check_optional_config "$cfg"
done
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 "-------------------Completed $TESTNAME Testcase----------------------------"
exit 0
23 changes: 23 additions & 0 deletions Runner/suites/Kernel/Scheduler/PELT_decay/PELT_decay.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
metadata:
name: pelt-decay
format: "Lava-Test Test Definition 1.0"
description: "Validates PELT exponential decay: util_avg must decrease after CPU load stops"
maintainer:
- vnarapar@qti.qualcomm.com
os:
- linux
scope:
- functional
devices:
- rb3gen2
- qcs6490
- qcs8300
- qcs9100
- sa8775p

run:
steps:
- REPO_PATH=$PWD
- cd "$REPO_PATH/Runner/suites/Kernel/Scheduler/PELT_decay" || true
- ./run.sh || true
- $REPO_PATH/Runner/utils/send-to-lava.sh PELT_decay.res || true
97 changes: 97 additions & 0 deletions Runner/suites/Kernel/Scheduler/PELT_decay/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# PELT_decay — PELT Exponential Decay Validation

## Overview

Validates that **PELT (Per-Entity Load Tracking) exponential decay** is
functioning correctly in the kernel. PELT uses a geometric series with a
~32 ms half-life to track CPU utilization. After a task stops running,
its `util_avg` must decay toward zero — this is the mechanism that allows
the scheduler and cpufreq governors to reduce CPU frequency after load drops.

This is the **only** testcase in the PELT suite that explicitly validates
decay. The other tests (`PELT_load_tracking`, `PELT_schedutil`) only validate
accumulation (load going up), not the decay direction.

## PELT Decay Theory

```
util_avg(t) = util_avg(t0) × 0.5^( Δt / 32ms )

Half-life = 32 ms (one PELT period = 1024 µs)
After 100ms idle: util_avg → 11.5% of peak
After 200ms idle: util_avg → 1.3% of peak
After 1000ms idle: util_avg → ~0% of peak (< 0.001%)
```

## Two Validation Methods

### Method 1: `/proc/self/sched` `se.avg.util_avg` (Primary)

**Requires:** `CONFIG_SCHED_DEBUG`

The test script itself performs a CPU-bound busy loop for ~3 seconds,
saturating its own PELT `util_avg`. It then reads `util_avg` immediately
after the loop (should be high), sleeps 1 second, and reads again (should
be near zero).

```
1. Read baseline util_avg (shell is idle → low)
2. Run arithmetic busy loop for ~3s (saturates util_avg → near 1024)
3. Read peak util_avg (should be > 100/1024)
4. Sleep 1 second (~31 PELT half-lives → >99.9% theoretical decay)
5. Read decayed util_avg (should be < peak/2)
6. Assert: decayed_util < peak_util / 2
```

**Pass threshold:** `decayed_util < peak_util / 2` (50% decay after 1s).
This is extremely conservative — theoretical decay after 1s is >99.9%.

### Method 2: schedutil Frequency Proxy (Secondary)

**Requires:** `schedutil` cpufreq governor active

`schedutil` translates PELT `util_avg` into CPU frequency requests. When
`util_avg` decays after load stops, `schedutil` should lower the frequency.

```
1. Record idle frequency
2. Spawn background busy loop for 3s → record peak frequency
3. Kill load, wait 2 seconds
4. Record post-decay frequency
5. Assert: post_decay_freq < load_freq
```

This method is **informational** — a warning is issued if frequency does
not drop, but it does not cause a FAIL (thermal floors, rate_limit_us, or
platform-specific governor behaviour can prevent immediate frequency drop).

## Pass / Fail / Skip Criteria

| Condition | Result |
|---|---|
| Neither method available | SKIP |
| Method 1 available, decay ≥ 50% after 1s | PASS |
| Method 1 available, decay < 50% after 1s | FAIL |
| Method 2 only, frequency dropped after load | PASS (informational) |
| Method 2 only, frequency did not drop | WARN (not FAIL) |

## Why Existing Tests Don't Cover Decay

| Test | What it measures | Decay? |
|---|---|---|
| `PELT_schedstat` | `rq_cpu_time` (monotonic counter, never decays) | ✗ |
| `PELT_load_tracking` | `rq_cpu_time` increases under load | ✗ |
| `PELT_schedutil` | Frequency rises under load | ✗ (rise only) |
| **`PELT_decay`** | `util_avg` decreases after load stops | **✓** |

## Usage

```sh
./run.sh
```

## Dependencies

- `/proc/self/sched` — `CONFIG_SCHED_DEBUG` (Method 1)
- `schedutil` governor — `CONFIG_CPU_FREQ_GOV_SCHEDUTIL` (Method 2)
- `grep`, `awk`, `cat`, `date`
Loading
Loading