-
Notifications
You must be signed in to change notification settings - Fork 35
pelt scheduler: add new tests to validate pelt #447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 | ||
| - $REPO_PATH/Runner/utils/send-to-lava.sh PELT_config.res |
| 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) |
| 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)" | ||
|
|
||
| if ! check_dependencies grep; then | ||
| echo "$TESTNAME SKIP" > "$res_file" | ||
| exit 0 | ||
| fi | ||
|
|
||
| pass="true" | ||
|
|
||
| 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" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keep CONFIG_SMP required and move CONFIG_FAIR_GROUP_SCHED to optional unless the test is specifically validating group-scheduler PELT |
||
|
|
||
| if ! check_kernel_config "$CORE_CONFIGS"; then | ||
| log_fail "Core Scheduler kernel config validation failed" | ||
| pass=false | ||
| else | ||
| log_pass "Core Scheduler 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 Scheduler configurations..." | ||
| for cfg in $OPTIONAL_CONFIGS; do | ||
| if zgrep -qE "^${cfg}=(y|m)" /proc/config.gz 2>/dev/null; then | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use check_optional_config function from functestlib.sh |
||
| log_pass " Optional config $cfg is enabled" | ||
| else | ||
| log_info " Optional config $cfg is not enabled (optional)" | ||
| fi | ||
| done | ||
| fi | ||
|
|
||
| if [ "$pass" = "true" ]; 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 | ||
| 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 | ||
| - $REPO_PATH/Runner/utils/send-to-lava.sh PELT_decay.res |
| 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` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uses zgrep but dependency check only checks grep. Also better to log_skip with proper message to console for better debugging.