# Features impacting performance

The Qualcomm^®^ Linux^®^ kernel includes features such as the CPU scheduler, CPU frequency governor, dynamic voltage and frequency scaling (DVFS), and memory management. This guide provides an overview of each feature and related reference links. Additionally, Qualcomm uses a feature called Userspace Resource Manager (URM) to enhance the performance of Qualcomm Linux.

## Understand the CPU scheduler

The CPU scheduler manages how the CPU time is distributed among the
processes running on Linux systems.

The CPU scheduler uses [An earliest eligible virtual deadline first (EEVDF) CPU scheduler for Linux](https://lwn.net/Articles/925371/), which is provided by the Linux kernel. The EEVDF CPU scheduler uses [Per-entity load tracking \[LWN.net\]](https://lwn.net/Articles/531853/) to monitor the task load.

[Utilization clamping (UCLAMP or util clamp)](https://docs.kernel.org/scheduler/sched-util-clamp.html) is a scheduler that helps manage performance requirements for tasks.

For more information, see [Customize CPU scheduler](https://docs.qualcomm.com/doc/80-80022-10/topic/18-customize.html#customize-scheduler).

## Understand the CPU frequency governor

A CPU frequency governor adjusts the CPU frequency based on the task
load. The CPU scheduler provides the necessary inputs for this process.

Qualcomm Linux uses the `schedutil` governor, provided by
the Linux kernel.

This governor increases the CPU frequency when the system is heavily loaded
and reduces it when the load is low, ensuring an optimal balance between
power consumption and performance.

For more information, see the following:

- [CPU frequency and voltage scaling code in the Linux kernel](https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt)
- [Configure CPU](https://docs.qualcomm.com/doc/80-80022-10/topic/14-configure.html#cpu)
- [Customize the CPU frequency governor](https://docs.qualcomm.com/doc/80-80022-10/topic/18-customize.html#cpu-frequency-governor)

## Understand DVFS governors

DVFS governors control the frequencies of CPU caches (L3), the last
level cache controller (LLCC), and the DDR based on the system workload.

These governors increase the frequency when the workload is high and
decrease it when the workload is low, ensuring an optimal balance
between power consumption and performance.

Qualcomm Linux supports the following two types of DVFS governors for L3 cache:

- LLCC
- DDR

### Configure the static map DVFS governor

This governor aligns the frequencies of the CPU L3 cache and the DDR with
the current CPU frequency to balance the power and the performance requirements.

For example, if the CPU frequency is at its maximum, the L3 cache and
DDR frequencies must also be at their maximum levels.

The static mapping is available in the source code at
`arch/arm64/boot/dts/qcom/<target>.dtsi`.

For customization options, see [Customize static map DVFS governor](https://docs.qualcomm.com/doc/80-80022-10/topic/18-customize.html#section-u1x-jps-51c-caharris-03-20-24-2005-37-832).

### Understand the BWMON governor

The bandwidth monitoring (BWMON) governor dynamically adjusts the
frequencies of the LLCC and DDR based on the measured traffic flow from
the CPU to the LLCC and then to the DDR.

The BWMON hardware block measures this traffic. It monitors the data
throughput between memory and the other subsystems within a specified
sampling window and uses this information to scale the LLCC and DDR
frequencies to meet the required bandwidth.

The BWMON governor driver is available in the source code at
`drivers/soc/qcom/icc-bwmon.c`.

For more information, see the following:

- [\[PATCH v3 0/4\] soc/arm64: qcom: Add initial version of
bwmon](https://lwn.net/ml/linux-kernel/20220531105137.110050-1-krzysztof.kozlowski@linaro.org/)
- [Customize BWMON governor](https://docs.qualcomm.com/doc/80-80022-10/topic/18-customize.html#section-qxs-4ps-51c-caharris-03-20-24-2007-2-926)

## Understand the Userspace Resource Manager

The Userspace Resource Manager (URM) is an open-source, lightweight, and extensible framework designed to intelligently manage and provision system resources from userspace.

Modern workloads vary significantly across segments such as servers, compute, XR, mobile, and IoT, with each use case exhibiting distinct characteristics. Some workloads demand high CPU frequencies, others require sustained GPU throughput, while many depend on efficient caching or increased memory bandwidth.
At the same time, these workloads run on a wide range of hardware platforms with varying capabilities, power envelopes, and user expectations. Consequently, a uniform tuning approach is insufficient to meet the diverse performance and power requirements of such environments.

URM addresses these challenges by providing the following capabilities:

- Enabling application-level tuning
- Enabling use case and workload-level tuning
- Providing signal and tuning APIs

URM automatically detects use cases and applies tuning parameters specified in per-application or use case YAML configuration files. Use case detection can be customized through extensions.

URM can also modify system behavior to efficiently manage intermittent workloads. The Signal API or Tune API can be invoked within specific code segments to temporarily boost or limit system resources. For example, a critical code path can be executed at a higher CPU frequency for a defined duration.
URM efficiently handles concurrent requests from multiple clients. When multiple requests target the same resource, URM aggregates them to determine and apply the optimal performance level required by the device.

For more information, see [Userspace Resource Manager](https://qualcomm.github.io/userspace-resource-manager/) and [Userspace Resource Manager Extensions](https://github.com/qualcomm/userspace-resource-manager-extensions/).

## Understand memory management

RAM is used for all memory allocations made by Qualcomm Linux. RAM must be managed to meet performance requirements and ensure smooth application behavior. The following figure shows memory partitioning:

<!--?xml version="1.0" encoding="UTF-8"?-->
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="600" height="342.89" viewbox="0 0 600 342.89" aria-label="This figure shows memory partitioning in systems supporting both Linux and non-Linux environments.">
  <defs>
    <style>.svg-1 .cls-1 { letter-spacing: -.01em }
.svg-1 .cls-2 { fill: #007884 }
.svg-1 .cls-3 { letter-spacing: 0em }
.svg-1 .cls-4 { stroke-dasharray: 5.03 5.03 }
.svg-1 .cls-4,.svg-1 .cls-5,.svg-1 .cls-6 { fill: none; stroke: #7c8aa3; stroke-miterlimit: 10 }
.svg-1 .cls-7 { letter-spacing: 0em }
.svg-1 .cls-8 { fill: #d2d7e1 }
.svg-1 .cls-9 { letter-spacing: 0em }
.svg-1 .cls-5 { stroke-dasharray: 5 }
.svg-1 .cls-10 { font-family: RobotoFlex-Bold, "Roboto Flex"; font-size: 18px; font-variation-settings: "opsz" 14, "wght" 700, "GRAD" 0, "wdth" 100, "slnt" 0, "XOPQ" 96, "YOPQ" 79, "XTRA" 468, "YTUC" 712, "YTLC" 514, "YTAS" 750, "YTDE" -203, "YTFI" 738; font-weight: 700 }
.svg-1 .cls-11 { letter-spacing: 0em }
.svg-1 .cls-12 { fill: #fff; font-family: RobotoFlex-Regular, "Roboto Flex"; font-variation-settings: "opsz" 14, "wght" 400, "GRAD" 0, "wdth" 100, "slnt" 0, "XOPQ" 96, "YOPQ" 79, "XTRA" 468, "YTUC" 712, "YTLC" 514, "YTAS" 750, "YTDE" -203, "YTFI" 738 }
.svg-1 .cls-12,.svg-1 .cls-13 { font-size: 16px }
.svg-1 .cls-14 { fill: #fafafa }
.svg-1 .cls-13 { font-family: RobotoFlex-Medium, "Roboto Flex"; font-variation-settings: "opsz" 14, "wght" 500, "GRAD" 0, "wdth" 100, "slnt" 0, "XOPQ" 96, "YOPQ" 79, "XTRA" 468, "YTUC" 712, "YTLC" 514, "YTAS" 750, "YTDE" -203, "YTFI" 738; font-weight: 500 }</style>
  </defs>
  <g>
    <rect class="cls-14" x=".5" y=".5" width="599" height="341.89" rx="7.5" ry="7.5"></rect>
    <path class="cls-8" d="M592,1c3.86,0,7,3.14,7,7v326.89c0,3.86-3.14,7-7,7H8c-3.86,0-7-3.14-7-7V8c0-3.86,3.14-7,7-7h584M592,0H8C3.58,0,0,3.58,0,8v326.89c0,4.42,3.58,8,8,8h584c4.42,0,8-3.58,8-8V8c0-4.42-3.58-8-8-8h0Z"></path>
  </g>
  <rect class="cls-2" x="44.29" y="65.63" width="140.17" height="201.22" rx="4" ry="4"></rect>
  <rect class="cls-2" x="243.32" y="99.2" width="148.86" height="75.98" rx="4" ry="4"></rect>
  <rect class="cls-2" x="406.8" y="99.2" width="148.86" height="75.98" rx="4" ry="4"></rect>
  <rect class="cls-2" x="243.32" y="190.87" width="148.86" height="75.98" rx="4" ry="4"></rect>
  <rect class="cls-2" x="406.8" y="190.87" width="148.86" height="75.98" rx="4" ry="4"></rect>
  <rect class="cls-5" x="15.01" y="36.39" width="569.97" height="291.53" rx="4" ry="4"></rect>
  <g>
    <line class="cls-6" x1="213.76" y1="36.39" x2="213.76" y2="38.89"></line>
    <line class="cls-4" x1="213.76" y1="43.92" x2="213.76" y2="322.9"></line>
    <line class="cls-6" x1="213.76" y1="325.42" x2="213.76" y2="327.92"></line>
  </g>
  <text class="cls-10" transform="translate(544.81 28.28)"><tspan x="0" y="0">RAM</tspan></text>
  <text class="cls-13" transform="translate(299.03 80.47)"><tspan x="0" y="0">Memo</tspan><tspan class="cls-11" x="46.12" y="0">r</tspan><tspan x="51.84" y="0">y </tspan><tspan class="cls-7" x="63.41" y="0">t</tspan><tspan x="68.43" y="0">otal (system RAM)</tspan></text>
  <text class="cls-12" transform="translate(295.28 131.88)"><tspan class="cls-1" x="0" y="0">K</tspan><tspan x="9.69" y="0">ernel</tspan><tspan x="3" y="19.2">static</tspan></text>
  <text class="cls-12" transform="translate(458.76 131.88)"><tspan class="cls-1" x="0" y="0">K</tspan><tspan x="9.69" y="0">ernel</tspan><tspan x="-7.56" y="19.2">dynamic</tspan></text>
  <text class="cls-12" transform="translate(465.75 223.55)"><tspan class="cls-1" x="0" y="0">F</tspan><tspan class="cls-9" x="8.62" y="0">r</tspan><tspan x="13.95" y="0">ee</tspan><tspan x="-13.58" y="19.2">memo</tspan><tspan class="cls-11" x="31.56" y="19.2">r</tspan><tspan x="37.17" y="19.2">y</tspan></text>
  <text class="cls-12" transform="translate(278.28 223.55)"><tspan x="0" y="0">User space</tspan><tspan x="11.39" y="19.2">p</tspan><tspan class="cls-7" x="20.53" y="19.2">r</tspan><tspan x="25.84" y="19.2">ocess</tspan></text>
  <text class="cls-12" transform="translate(81.8 171.29)"><tspan x="0" y="0">Rese</tspan><tspan class="cls-11" x="34.66" y="0">r</tspan><tspan class="cls-3" x="40.27" y="0">v</tspan><tspan x="47.52" y="0">ed</tspan></text>
  <text class="cls-13" transform="translate(243.32 313.14)"><tspan x="0" y="0">Linux</tspan></text>
  <text class="cls-13" transform="translate(106.7 313.14)"><tspan x="0" y="0">Non-Linux</tspan></text>
</svg>

**Figure : Memory partitioning**

The figure shows RAM allocation in systems supporting both Linux and non-Linux environments.

- System RAM is partitioned between non-Linux and Linux components.
- Non-Linux section includes a large block labeled Reserved, indicating memory allocated for non-Linux operations.
- Linux section is divided into four blocks under Memory total (system RAM):

    - Kernel static
    - Kernel dynamic
    - User space process
    - Free memory

Certain sections of RAM are managed independent of the Linux system. For
example, firmware such as modem, video, and audio run from these
specific RAM partitions. The Linux kernel manages all other RAM
partitions.

The Linux kernel features its own memory management subsystem, which
includes:

- Implementation of virtual memory and demand paging
- Allocation of memory to both kernel internal structures and userspace programs
- Mapping of files into the address space of the processes
- Other memory management operations

### Configure RAM memory partitioning

The following table describes various types of memory allocations.

Note

The commands specified in the following table should be run on the device.

| RAM classification | Memory segment | Allocation types | Description |
| --- | --- | --- | --- |
| Non-Linux | None | None | <ul class="simple"><br><li><p>Memory is reserved in the form of carveouts by various<br>subsystems other than Linux.</p></li><br><li><p>These carveouts are specified in the respective DTSI<br>files.</p></li><br></ul> |
| Linux (system RAM) | Kernel static | Vmlinux + kernel page structures | <ul><br><li><p>The kernel reserves this memory at boot time for its own<br>usage.</p></li><br><li><p>Vmlinux is the memory used to store the vmlinux image.</p></li><br><li><p>The size and breakdown of the vmlinux image can be<br>obtained from the <code class="docutils literal notranslate"><span class="pre">dmesg</span></code> logs at boot:</p><br><blockquote><br><div><p>Memory: 3061872K/4134912K available (28800K kernel code, 2090K rwdata, 10688K rodata, 3072K init, 969K bss, 679824K reserved, 393216K cma-reserved)</p><br><p>Kernel code + rwdata + rodata + init +bss indicates vmlinux kernel image size (28800k + 2090k + 10688k + 3072k + 969k)</p><br></div></blockquote><br></li><br><li><p>The kernel page structure is the memory used by the<br>kernel to maintain page structures for every page of RAM.<br>This is calculated as 16&nbsp;MB per GB of RAM size.</p></li><br></ul> |
| Linux (system RAM) | Kernel dynamic | Slab | <ul class="simple"><br><li><p>The slab is used by the kernel for faster and more<br>efficient memory usage of frequently used data<br>structures.</p></li><br><li><p>To check the memory usage of the slab, run the following<br>command:</p></li><br></ul><br><br>cat /proc/meminfo | grep -i slab<br>    Copy to clipboard<br><ul class="simple"><br><li><p>To view the breakdown of various slabs and their<br>usage, enable <code class="docutils literal notranslate"><span class="pre">CONFIG_SLUB_DEBUG</span></code> in the kernel<br>configuration, and then run the following command:</p></li><br></ul><br><br>cat /proc/slabinfo<br>    Copy to clipboard |
| Linux (system RAM) | Kernel dynamic | Kernel stack | <ul class="simple"><br><li><p>The kernel stack stores the call stack of every process.</p></li><br><li><p>To check the memory usage of the kernel stack, run the<br>following command:</p></li><br></ul><br><br>cat /proc/meminfo | grep -i kernelstack<br>    Copy to clipboard |
| Linux (system RAM) | Kernel dynamic | PageTables | <ul class="simple"><br><li><p>The kernel uses memory to store PageTables that map<br>virtual addresses to physical addresses.</p></li><br><li><p>To check the memory usage of PageTables, run the<br>following command:</p></li><br></ul><br><br>cat /proc/meminfo | grep -i PageTables<br>    Copy to clipboard |
| Linux (system RAM) | Kernel dynamic | Modules | <ul class="simple"><br><li><p>Represents the kernel entities that are dynamically<br>loaded into the kernel in the form of kernel modules.</p></li><br><li><p>To display the list of loaded kernel modules and their<br>memory usage, run the following command:</p></li><br></ul><br><br>cat /proc/modules<br>    Copy to clipboard |
| Linux (system RAM) | Kernel dynamic | Vmalloc | <ul class="simple"><br><li><p>Used to allocate contiguous memory.</p></li><br><li><p>To check the Vmalloc memory breakup, run the following command:</p></li><br></ul><br><br>cat /proc/vmallocinfo<br>    Copy to clipboard |
| Linux (system RAM) | Kernel dynamic | Cached (kernel + userspace) | <ul class="simple"><br><li><p>The amount of file-backed memory that resides in RAM.</p></li><br><li><p>To check the cached memory usage, run the following<br>command:</p></li><br></ul><br><br>cat /proc/meminfo | grep -i cached<br>    Copy to clipboard |
| Linux (system RAM) | Kernel dynamic | Buffers | <ul class="simple"><br><li><p>Buffers are of fixed size and contain blocks of<br>information either read from disk or written to disk.</p></li><br><li><p>To check the buffer memory usage, run the following<br>command:</p></li><br></ul><br><br>cat /proc/meminfo | grep -i Buffers<br>    Copy to clipboard |
| Linux (system RAM) | Kernel dynamic | Shmem | <ul class="simple"><br><li><p>Shared memory is a common block of memory that's mapped<br>into the address spaces of two or more processes.</p></li><br><li><p>To check the shared memory usage, run the following<br>command:</p></li><br></ul><br><br>cat /proc/meminfo | grep -i shmem<br>    Copy to clipboard |
| Linux (system RAM) | User space | ZUSED (ZRAM) | An anonymous memory post compression by ZRAM. |
| Linux (system RAM) | User space | CMA | <ul class="simple"><br><li><p>A contiguous physical memory is typically mapped to<br>other IPs such as video and display. However, it's<br>allocated to the runtime.</p></li><br><li><p>The free memory that the system can use is reduced with<br>the usage of more CMA reservations. Only the movable<br>allocations, such as userspace process allocations can<br>use the CMA reserved free memory. However, it can't be<br>used for the kernel allocations.</p></li><br></ul> |
| Linux (system RAM) | User space | ANON | <ul class="simple"><br><li><p>Memory that userspace applications allocate using<br><code class="docutils literal notranslate"><span class="pre">malloc()</span></code> or <code class="docutils literal notranslate"><span class="pre">new()</span></code> function calls.</p></li><br><li><p>To check the ANON memory breakup for a process, run the<br>following command:</p></li><br></ul><br><br><br>> <br>> <br>> cat /proc/<pid>/smaps<br>>     Copy to clipboard |
| Linux (system RAM) | User space | ION | <ul class="simple"><br><li><p>ION memory allows sharing buffers between hardware IPs<br>such as video, camera, and Qualcomm Linux.</p></li><br><li><p>ION manages one or more memory pools, which can be set<br>aside at boot time to combat fragmentation.</p></li><br><li><p>To check the ION memory usage, run the following<br>commands:</p></li><br></ul><br><br>mount -t debugfs none /sys/kernel/debug<br>    Copy to clipboard<br><br><br>cat /sys/kernel/debug/dma_buf/bufinfo | grep bytes<br>    Copy to clipboard |
| Linux (system RAM) | User space | KGSL | <ul class="simple"><br><li><p>Memory allocated by the graphics driver.</p></li><br><li><p>To check the overall kernel graphics support layer (KGSL)<br>memory usage, run the following command:</p></li><br></ul><br><br><br>> <br>> <br>> cat /sys/class/kgsl/kgsl/page_alloc<br>>     Copy to clipboard<br><br><ul class="simple"><br><li><p>To check the process level breakup, run the following<br>command:</p></li><br></ul><br><br><br>> <br>> <br>> cat /sys/class/kgsl/kgsl/proc/<pid>/kernel<br>>     Copy to clipboard |
| Linux (system RAM) | Free memory | None | <ul><br><li><p>Free memory is the memory that's not yet used and is<br>available for any allocation.</p></li><br><li><p>To check the available memory, run the following command:</p><br><div class="highlight-default notranslate"><div class="highlight"><pre class="pre codeblock"><code>cat /proc/meminfo | grep -i MemFree<br></code><span class="copyclip"><svg xmlns="http://www.w3.org/2000/svg" class="copyclipicon" width="25px" height="25px" viewbox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><title>Copy to clipboard</title><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg></span></pre></div><br></div><br></li><br></ul> |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |

## Understand the real-time (RT) kernel

A real-time system is a deterministic system, where response to an event
is expected in a set time.

A system is classified as compatible with RT if:

- It's devoid of unbounded latency.
- The maximum response time is calculated with precision.
- It meets the set criteria for scheduling of tasks (latency and
deadline).

Linux can be configured as a real-time operating system (RTOS) in which
real-time tasks have well-defined periodic execution cycles (cycle
time) and meet execution criteria within specified limits (jitter).

To install the patches, see [Versions of PREEMPT_RT
patches](https://wiki.linuxfoundation.org/realtime/start).

Note

The real-time support is for kernelspace process and not for userspace.

Note

This section isn't applicable for QCS5430.

<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->

<!-- Generated by Microsoft Visio, SVG Export RT-kernel-build-sequence.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="11.0625in" height="1.68056in" viewbox="0 0 796.5 121" xml:space="preserve" color-interpolation-filters="sRGB" class="st8" aria-label="Representation of RT kernel build sequence."><v:documentproperties v:langid="1033" v:viewmarkup="false">	<v:userdefs>		<v:ud v:nameu="msvSubprocessMaster" v:prompt="" v:val="VT4(Rectangle)"></v:ud>		<v:ud v:nameu="msvNoAutoConnect" v:val="VT0(1):26"></v:ud>	</v:userdefs></v:documentproperties>
<style>.svg-2 .st1 { fill: #fafafa; stroke: #d2d7e1; stroke-width: 1.5 }
.svg-2 .st2 { marker-end: url("#1-mrkr4-8"); stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.5 }
.svg-2 .st3 { fill: #000000; fill-opacity: 1; stroke: #000000; stroke-opacity: 1; stroke-width: 0.37313432835821 }
.svg-2 .st4 { fill: #6280cc; stroke: #6280cc; stroke-opacity: 0; stroke-width: 2.5 }
.svg-2 .st5 { fill: none; stroke: none; stroke-width: 2.5 }
.svg-2 .st6 { fill: #ffffff; font-family: Roboto Flex, Qualcomm-Next, sans-serif; font-size: 1.16666em }
.svg-2 .st7 { font-size: 1em }
.svg-2 .st8 { fill: none; fill-rule: evenodd; font-size: 12px; overflow: visible; stroke-linecap: square; stroke-miterlimit: 3 }</style>
<defs id="Markers">	<g id="lend4">		<path d="M 2 1 L 0 0 L 2 -1 L 2 1 " style="stroke:none"></path>	</g>	<marker id="1-mrkr4-8" class="st3" v:arrowtype="4" v:arrowsize="2" v:setback="5.36" refx="-5.36" orient="auto" markerunits="strokeWidth" overflow="visible">		<use xlink:href="#lend4" transform="scale(-2.68,-2.68) "></use>	</marker></defs><g v:mid="0" v:index="1" v:groupcontext="foregroundPage">	<v:userdefs>		<v:ud v:nameu="msvThemeOrder" v:val="VT0(0):26"></v:ud>	</v:userdefs>	<title>Page-1</title>	<v:pageproperties v:drawingscale="1" v:pagescale="1" v:drawingunits="0" v:shadowoffsetx="9" v:shadowoffsety="-9"></v:pageproperties>	<g id="shape1057-1" v:mid="1057" v:groupcontext="shape" transform="translate(19.5,-19.5)">		<title>Rectangle</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="39" width="757.5" height="82" rx="4" ry="4" class="st1"></rect>	</g>	<g id="shape1047-3" v:mid="1047" v:groupcontext="shape" transform="translate(177.472,-60.891) rotate(-0.00602379)">		<title>Sheet.1047</title>		<path d="M0 121 L39.2 121" class="st2"></path>	</g>	<g id="shape1045-9" v:mid="1045" v:groupcontext="shape" transform="translate(29.4085,-29.9018) rotate(0.3)">		<title>Rectangle.12</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="59.014" width="151.263" height="61.986" rx="3" ry="3" class="st4"></rect>	</g>	<g id="shape1046-11" v:mid="1046" v:groupcontext="shape" transform="translate(63.7851,-41.4924)">		<title>Sheet.1046</title>		<desc>Set up workspace</desc>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="40.7827" cy="101.992" width="81.57" height="38.0152"></v:textrect>		<rect x="0" y="82.9848" width="81.5655" height="38.0152" class="st5"></rect>		<text x="21.12" y="97.79" class="st6" v:langid="1033"><v:paragraph v:horizalign="1" v:bulletsize="0.166667"></v:paragraph><v:tablist></v:tablist>Set up<v:newlinechar></v:newlinechar><tspan x="5.16" dy="1.2em" class="st7"> </tspan>workspace</text>		</g>	<g id="shape1037-15" v:mid="1037" v:groupcontext="shape" transform="translate(225.2,-30.2467) rotate(0.3)">		<title>Rectangle.1004</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="59.7039" width="151.263" height="61.2961" rx="3" ry="3" class="st4"></rect>	</g>	<g id="shape1042-17" v:mid="1042" v:groupcontext="shape" transform="translate(260.052,-42.9924)">		<title>Sheet.1042</title>		<desc>Enable RT kernel</desc>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="40.3056" cy="103.492" width="80.62" height="35.0152"></v:textrect>		<rect x="0" y="85.9848" width="80.6111" height="35.0152" class="st5"></rect>		<text x="9.1" y="99.29" class="st6" v:langid="1033"><v:paragraph v:horizalign="1" v:bulletsize="0.166667"></v:paragraph><v:tablist></v:tablist>Enable RT <v:newlinechar></v:newlinechar><tspan x="21.41" dy="1.2em" class="st7">kernel</tspan></text>		</g>	<g id="shape1038-21" v:mid="1038" v:groupcontext="shape" transform="translate(420.988,-30.2467) rotate(0.3)">		<title>Rectangle.1005</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="59.7039" width="151.263" height="61.2961" rx="3" ry="3" class="st4"></rect>	</g>	<g id="shape1041-23" v:mid="1041" v:groupcontext="shape" transform="translate(460.289,-42.5745)">		<title>Sheet.1041</title>		<desc>Configure RT kernel</desc>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="35.8567" cy="103.075" width="71.72" height="35.851"></v:textrect>		<rect x="0" y="85.149" width="71.7135" height="35.851" class="st5"></rect>		<text x="5.45" y="98.87" class="st6" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>Configure<v:newlinechar></v:newlinechar><tspan x="6.74" dy="1.2em" class="st7">RT kernel</tspan></text>		</g>	<g id="shape1039-27" v:mid="1039" v:groupcontext="shape" transform="translate(616.776,-30.2467) rotate(0.3)">		<title>Rectangle.1006</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="59.7039" width="151.263" height="61.2961" rx="3" ry="3" class="st4"></rect>	</g>	<g id="shape1040-29" v:mid="1040" v:groupcontext="shape" transform="translate(643.537,-40.1277)">		<title>Sheet.1040</title>		<desc>Verify kernel configurations</desc>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="49.2313" cy="100.628" width="98.47" height="40.7446"></v:textrect>		<rect x="0" y="80.2554" width="98.4627" height="40.7446" class="st5"></rect>		<text x="10.63" y="96.43" class="st6" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>Verify kernel <tspan x="4.17" dy="1.2em" class="st7">configurations</tspan></text>		</g>	<g id="shape1053-33" v:mid="1053" v:groupcontext="shape" transform="translate(373.836,-60.0849) rotate(-1.01902)">		<title>Sheet.1053</title>		<path d="M0 121 L36.49 121" class="st2"></path>	</g>	<g id="shape1055-38" v:mid="1055" v:groupcontext="shape" transform="translate(569.625,-60.0849) rotate(-1.01902)">		<title>Sheet.1055</title>		<path d="M0 121 L36.49 121" class="st2"></path>	</g></g>
</svg>

**Figure : Build sequence**

### Set up the workspace

The Qualcomm Linux kernel supports the LTS RT kernel (6.18.x), which is maintained
through the Yocto recipe in the `meta-qcom` layer in the
`recipes-kernel/linux/linux-qcom-rt_6.18.bb` file.

For more information about cloning the workspace and getting all Qualcomm Linux meta layers to
use Qualcomm RT Linux, see [Sync](https://docs.qualcomm.com/doc/80-80022-254/topic/build_from_source_github_intro.html#sync).

### Enable the RT kernel

The Qualcomm Linux `meta-qcom` layer supports `linux-qcom-rt_6.18.bb` recipe that fetches and builds the Qualcomm Linux kernel for the supported machines by default.

The `meta-qcom` layer applies the changes on top of the
existing layer. During the kernel build, `meta-qcom` layer
enables  `PREEMPT_RT` using `rt.config` based on the kernel version,
and allows real-time configurations.

Note

- Use `linux-qcom-rt_6.18.bb <https://github.com/qualcomm-linux/meta-qcom/blob/master/recipes-kernel/linux/linux-qcom-rt_6.18.bb>` for QLI.2.0 .
- Use `linux-qcom-next-rt_git.bb <https://github.com/qualcomm-linux/meta-qcom/blob/master/recipes-kernel/linux/linux-qcom-next-rt_git.bb>` for `qcom-next`.

For more information about supported machines, see [Build critical release tags](https://docs.qualcomm.com/doc/80-80022-300/topic/build_critical_release_tags.html).

### Customize the RT kernel

- If you are carrying any changes for the RT kernel, maintain them in the recipe as shown below:

    - Maintain the patch file under
`recipes-kernel/linux/linux-qcom-6.18/<your_patch_file>.patch`
    - Append the patch file to `SRC_URI` in the `recipes-kernel/linux/linux-qcom-rt_6.18.bb` file.

SRC_URI += " \
              file://<your_patch_file>.patch \
      "
    Copy to clipboard

- To apply any external configurations on the RT kernel:

    - Maintain the configuration file in the
`recipes-kernel/linux/linux-qcom-6.18/configs/<your_config>.cfg` recipe.
    - Append the configuration file to `SRC_URI` in the `recipes-kernel/linux/linux-qcom-rt_6.18.bb` file.

SRC_URI += " \
                file://configs/qcom_rt.cfg \
        "
        Copy to clipboard
- To modify the kernel command-line, add the command-line parameters into the `meta-qcom/ci/base.yml` file to `KERNEL_CMDLINE_EXTRA` variable.

KERNEL_CMDLINE_EXTRA:append = " qcom_scm.download_mode=1 <new_parameter>"
        Copy to clipboard

### Configure kernel settings for the RT kernel

Optional and mandatory kernel configurations are used in the RT kernel.

To enable full preemption in the RT kernel, use `CONFIG_PREEMPT_RT`.

The `CONFIG_PREEMPT_RT` flag is enabled by default as part of the
`rt.config` used in `linux-qcom-rt_6.18.bb` recipe.

The following example shows the kernel configuration:

zcat proc/config.gz | grep CONFIG_PREEMPT
    # CONFIG_PREEMPT_NONE is not set
    # CONFIG_PREEMPT_VOLUNTARY is not set
    # CONFIG_PREEMPT is not set
    CONFIG_PREEMPT_RT=y
    Copy to clipboard

Set the following kernel configuration options when affining the RT
task:

- `CONFIG_NO_HZ_COMMON` - When enabled, it configures the kernel
infrastructure for tickless operation.
- `CONFIG_NO_HZ_FULL` - When enabled, it configures the kernel to
avoid sending scheduling-clock interrupts to CPUs with a single
runnable task.
- `CONFIG_CPUSETS` - Use the `CONFIG_CPUSETS` configuration option
to enable `cpuset`, where the CPU is grouped to form a set.

<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->

<!-- Generated by Microsoft Visio, SVG Export compile-RT-kernel.svg Page-1 -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="11.0278in" height="2.04638in" viewbox="0 0 794 147.339" xml:space="preserve" color-interpolation-filters="sRGB" class="st7" aria-label="Representation of RT kernel verification."><v:documentproperties v:langid="1033" v:viewmarkup="false">	<v:userdefs>		<v:ud v:nameu="msvSubprocessMaster" v:prompt="" v:val="VT4(Rectangle)"></v:ud>		<v:ud v:nameu="msvNoAutoConnect" v:val="VT0(1):26"></v:ud>	</v:userdefs></v:documentproperties>
<style>.svg-3 .st1 { fill: #fafafa; stroke: #d2d7e1; stroke-width: 1.5 }
.svg-3 .st2 { fill: #6280cc; stroke: #6280cc; stroke-width: 0.75 }
.svg-3 .st3 { fill: none; stroke: none; stroke-width: 2.5 }
.svg-3 .st4 { fill: #ffffff; font-family: Roboto Flex, Qualcomm-Next, sans-serif; font-size: 1.16666em }
.svg-3 .st5 { marker-end: url("#2-mrkr4-23"); stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.75 }
.svg-3 .st6 { fill: #000000; fill-opacity: 1; stroke: #000000; stroke-opacity: 1; stroke-width: 0.40983606557377 }
.svg-3 .st7 { fill: none; fill-rule: evenodd; font-size: 12px; overflow: visible; stroke-linecap: square; stroke-miterlimit: 3 }</style>
<defs id="Markers">	<g id="lend4">		<path d="M 2 1 L 0 0 L 2 -1 L 2 1 " style="stroke:none"></path>	</g>	<marker id="2-mrkr4-23" class="st6" v:arrowtype="4" v:arrowsize="2" v:setback="4.88" refx="-4.88" orient="auto" markerunits="strokeWidth" overflow="visible">		<use xlink:href="#lend4" transform="scale(-2.44,-2.44) "></use>	</marker></defs><g v:mid="0" v:index="1" v:groupcontext="foregroundPage">	<v:userdefs>		<v:ud v:nameu="msvThemeOrder" v:val="VT0(0):26"></v:ud>	</v:userdefs>	<title>Page-1</title>	<v:pageproperties v:drawingscale="1" v:pagescale="1" v:drawingunits="0" v:shadowoffsetx="9" v:shadowoffsety="-9"></v:pageproperties>	<g id="shape1012-1" v:mid="1012" v:groupcontext="shape" transform="translate(19.5,-25.7966)">		<title>Rectangle.1012</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="47.1861" width="755" height="100.153" rx="4" ry="4" class="st1"></rect>	</g>	<g id="shape1003-3" v:mid="1003" v:groupcontext="shape" transform="translate(607.142,-39.1556) rotate(0.3)">		<title>Rectangle.1006</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="76.1386" width="152.753" height="71.2005" rx="2.88" ry="2.88" class="st2"></rect>	</g>	<g id="shape1002-5" v:mid="1002" v:groupcontext="shape" transform="translate(416.204,-40.185) rotate(0.3)">		<title>Rectangle.1005</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="76.1386" width="152.753" height="71.2005" rx="2.88" ry="2.88" class="st2"></rect>	</g>	<g id="shape1001-7" v:mid="1001" v:groupcontext="shape" transform="translate(225.265,-41.2143) rotate(0.3)">		<title>Rectangle.1004</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="76.1386" width="152.753" height="71.2005" rx="2.88" ry="2.88" class="st2"></rect>	</g>	<g id="shape1004-9" v:mid="1004" v:groupcontext="shape" transform="translate(606.609,-29.48)">		<title>Sheet.1004</title>		<desc>Tune RT kernel</desc>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="76.3765" cy="100.816" width="152.76" height="93.0467"></v:textrect>		<rect x="0" y="54.2924" width="152.753" height="93.0467" class="st3"></rect>		<text x="29.92" y="105.02" class="st4" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>Tune RT kernel</text>		</g>	<g id="shape1005-12" v:mid="1005" v:groupcontext="shape" transform="translate(421.974,-20.5)">		<title>Sheet.1005</title>		<desc>Debug RT kernel</desc>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="70.0118" cy="94.1696" width="140.03" height="106.339"></v:textrect>		<rect x="0" y="41" width="140.024" height="106.339" class="st3"></rect>		<text x="19.15" y="98.37" class="st4" v:langid="1033"><v:paragraph v:horizalign="1"></v:paragraph><v:tablist></v:tablist>Debug RT kernel</text>		</g>	<g id="shape1006-15" v:mid="1006" v:groupcontext="shape" transform="translate(224.719,-39.3528)">		<title>Sheet.1006</title>		<desc>Test RT kernel</desc>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="76.3765" cy="109.954" width="152.76" height="74.7697"></v:textrect>		<rect x="0" y="72.5694" width="152.753" height="74.7697" class="st3"></rect>		<text x="31.75" y="114.15" class="st4" v:langid="1033"><v:paragraph v:horizalign="1" v:bulletsize="0.166667"></v:paragraph><v:tablist></v:tablist>Test RT kernel</text>		</g>	<g id="shape1007-18" v:mid="1007" v:groupcontext="shape" transform="translate(378.229,-74.2937) rotate(0.313268)">		<title>Sheet.1007</title>		<path d="M0 147.34 L29.65 147.34" class="st5"></path>	</g>	<g id="shape1008-24" v:mid="1008" v:groupcontext="shape" transform="translate(569.167,-73.2498) rotate(0.313268)">		<title>Sheet.1008</title>		<path d="M0 147.34 L29.65 147.34" class="st5"></path>	</g>	<g id="shape1009-29" v:mid="1009" v:groupcontext="shape" transform="translate(34.3126,-41.1898) rotate(0.3)">		<title>Rectangle.12</title>		<v:userdefs>			<v:ud v:nameu="visVersion" v:val="VT0(15):26"></v:ud>		</v:userdefs>		<rect x="0" y="75.2824" width="152.753" height="72.0568" rx="2.88" ry="2.88" class="st2"></rect>	</g>	<g id="shape1010-31" v:mid="1010" v:groupcontext="shape" transform="translate(33.7706,-39.2787)">		<title>Sheet.1010</title>		<desc>Build RT kernel</desc>		<v:textblock v:margins="rect(4,4,4,4)"></v:textblock>		<v:textrect cx="76.3765" cy="109.954" width="152.76" height="74.7697"></v:textrect>		<rect x="0" y="72.5694" width="152.753" height="74.7697" class="st3"></rect>		<text x="29.97" y="114.15" class="st4" v:langid="1033"><v:paragraph v:horizalign="1" v:bulletsize="0.166667"></v:paragraph><v:tablist></v:tablist>Build RT kernel</text>		</g>	<g id="shape1011-34" v:mid="1011" v:groupcontext="shape" transform="translate(187.329,-72.9171) rotate(0.313268)">		<title>Sheet.1011</title>		<path d="M0 147.34 L29.65 147.34" class="st5"></path>	</g></g>
</svg>

**Figure: RT kernel verification**

### Build the RT kernel

To build the RT kernel, run the following commands:

1. To ensure that you are in the KAS shell, run the following command:

> 
> 
> kas shell meta-qcom/ci/qcs6490-rb3gen2-core-kit.yml:meta-qcom/ci/linux-qcom-rt-6.18.yml:meta-qcom/ci/qcom-distro-kvm.yml:meta-qcom/ci/lock.yml
>     Copy to clipboard

Note

The `qcom-distro-kvm.yml` configuration is supported
with KVM only for QLI 2.0. The RT kernel (`PREEMPT_RT`)
is hypervisor-agnostic.

KVM is selected as the default hypervisor for QLI 2.0 due to
the following reasons:

- **Upstream community support** — KVM and its drivers are
part of the mainline Linux kernel, enabling broader
ecosystem contributions and long-term support.
- **Standard VirtIO support** — KVM supports all upstream
VirtIO devices and is compatible with standard VMMs such
as QEMU.
- **Open development** — Active upstream community with
broader developer familiarity.

The kas build command automatically includes
`xbl_config_kvm.elf` in the generated `qcomflash`
package. No manual UEFI BDS configuration is required.

Note

Copy the kas lock file from meta-qcom-releases to meta-qcom, see [Build a BSP image](https://docs.qualcomm.com/doc/80-80022-254/topic/build_from_source_github_intro.html#build-a-bsp-image).

2. To compile the BitBake Qualcomm Linux multimedia image, run the following command:

> 
> 
> bitbake qcom-multimedia-image
>     Copy to clipboard

### Tune the RT kernel

Tune the RT kernel to achieve a deterministic latency for RT tasks in the
device.

Set the CPU cores that run RT tasks to run at maximum operating
frequency while preventing thermal mitigation of CPU frequency. For
example, in an idle sleep scenario, RT tasks face scheduling latency due
to CPU wake time delay.

To configure the system before running the tests, do the following for QCS6490, Qualcomm Dragonwing^™^ IQ-9075, and Qualcomm Dragonwing^™^ IQ-615 Development Kit:

1. Disable the timer migration, using the following command:

echo 0 > /proc/sys/kernel/timer_migration
        Copy to clipboard
2. Affine all kernel work queues in `/sys/devices/virtual/workqueue/*` to the housekeeping CPUs, using the following command:

for wq in /sys/devices/virtual/workqueue/*; do
           [ -w "$wq/cpumask" ] && echo 7F > "$wq/cpumask"
        done
        7F = CPUs 0-6 (binary 0111 1111)
        Copy to clipboard
3. Set CPU frequency governor to performance, using the following command:

for policy in /sys/devices/system/cpu/cpufreq/policy*; do
           [ -w "$policy/scaling_governor" ] && echo performance > "$policy/scaling_governor"
        done
        Copy to clipboard
4. Disable RT accounting/throttling, using the following command:

echo -1 > /proc/sys/kernel/sched_rt_runtime_us
        Copy to clipboard
5. Set IRQ affinity to housekeeping CPUs, using the following command:

ALLOW_CPUS="0,1,2,3,4,5,6"
        cpu_list_to_mask() {
           MASK=0
           for cpu in $(echo $1 | tr ',' ' '); do
              MASK=$((MASK | (1 << cpu)))
           done
           printf "%x\n" "$MASK"
        }
        MASK=$(cpu_list_to_mask "$ALLOW_CPUS")
        echo "Setting IRQ affinity to CPUs: $ALLOW_CPUS (mask=0x$MASK)"
        for irq in /proc/irq/[0-9]*; do
           smp_file="$irq/smp_affinity"
           [ -w "$smp_file" ] && echo "$MASK" > "$smp_file" 2>/dev/null
        done
        Copy to clipboard

To configure the system before running the tests, do the following for the DragonwingTM IQ-8275 Development Kit:

1. Disable the timer migration, using the following command:

echo 0 > /proc/sys/kernel/timer_migration
        Copy to clipboard
2. Affine all kernel work queues in `/sys/devices/virtual/workqueue/*` to the housekeeping CPUs, using the following command:

for wq in /sys/devices/virtual/workqueue/*; do
           [ -w "$wq/cpumask" ] && echo F7 > "$wq/cpumask"
        done
        # F7 = CPUs 0–2,4-7 (binary 1111 0111)
        Copy to clipboard
3. Set CPU frequency governor to performance, using the following command:

for policy in /sys/devices/system/cpu/cpufreq/policy*; do
           [ -w "$policy/scaling_governor" ] && echo performance > "$policy/scaling_governor"
        done
        Copy to clipboard
4. Disable RT accounting/throttling, using the following command:

echo -1 > /proc/sys/kernel/sched_rt_runtime_us
        Copy to clipboard
5. Set IRQ affinity to housekeeping CPUs, using the following command:

ALLOW_CPUS="0,1,2,4,5,6,7"
        cpu_list_to_mask() {
           MASK=0
           for cpu in $(echo $1 | tr ',' ' '); do
              MASK=$((MASK | (1 << cpu)))
           done
           printf "%x\n" "$MASK"
        }
        MASK=$(cpu_list_to_mask "$ALLOW_CPUS")
        echo "Setting IRQ affinity to CPUs: $ALLOW_CPUS (mask=0x$MASK)"
        for irq in /proc/irq/[0-9]*; do
           smp_file="$irq/smp_affinity"
           [ -w "$smp_file" ] && echo "$MASK" > "$smp_file" 2>/dev/null
        done
        Copy to clipboard

The following example shows how to add a kernel command-line parameter
to disable RCU callbacks (**rcu\_nocbs**) in `meta-qcom/conf/machine/<machine-name.conf>`:

- CPU cores 7
- IRQ affine to core 0-6
- RCU no call back 7

QCOM_RT_CPU        = "7"
    QCOM_IRQAFF        = "0-6"
    QCOM_RCU_NOCBS     = "7"
    QCOM_RCU_EXPEDITED = "1"
    QCOM_CPUIDLE_OFF   = "1"
    Copy to clipboard

### Test the RT kernel

A suite of tests is available in the Linux foundation RT test suite. The RT Linux kernel test obtains the following information:

- Real-time performance of the RT Linux kernel
- RT Linux kernel latencies and key performance indicators (KPIs)

Note

Don't reboot the system during the RT Linux kernel test as it runs for over 24 hours.

Cyclictest tool is used for benchmarking the RT Linux kernel systems. It's used to evaluate the relative performance of the real-time systems. The Qualcomm Linux build has the cyclictest tool. For more information, see [Cyclictest](https://wiki.linuxfoundation.org/realtime/documentation/howto/tools/cyclictest/start).

This guide describes the following cyclictests:

- Cyclictest with no-load: System load isn't added to perform this test.
- Cyclictest with stress-ng (next-generation): Specific percentage of load is added to perform this test to measure the worst case system latencies. For more information about stress-ng, see Ubuntu Wiki - stress-ng.

1. Run the following cyclic test for QCS6490, Qualcomm Dragonwing^™^ IQ-9075, and Qualcomm Dragonwing^™^ IQ-615 development kits:

cyclictest -a 7 -t 1 -m -l 100000000 -i 1000 -p 99 -h 100
        # -a 7 → pin threads to CPU 7 (RT cores)
        # -t 1 → 1 threads
        # -m → lock memory (avoid page faults)
        # -l 100000000 → long run
        # -i 1000 → 1 ms interval
        # -p 99 → RT priority
        # -h 100 → histogram up to 100 µs
        Copy to clipboard
2. Run the following cyclic test for the Dragonwing™ IQ-8275 Development Kit:

cyclictest -a 3 -t 1 -m -l 100000000 -i 1000 -p 99 -h 100
        Copy to clipboard

To access the RT test suite source code, see [rt-tests/rt-tests.git](https://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git/).
For more information, see [RT-Tests](https://wiki.linuxfoundation.org/realtime/documentation/howto/tools/rt-tests).

3. Note the latencies.

To run cyclic test with stress-ng on QCS6490, Qualcomm Dragonwing IQ-9075, and Qualcomm Dragonwing™ IQ-615 , do the following:

1. Set the target CPU load, Define the desired CPU load percentage. If not specified, the default load is 60%:

LOAD=60
        Copy to clipboard
2. Run stress-ng on selected CPU cores in the background. Apply CPU load on cores 0, 1, 2, 4, 5, 6, and 7 using stress-ng. Each instance runs for one day and is pinned to a specific CPU core.

for cpu in 0 1 2 3 4 5 6; do
            taskset -c $cpu stress-ng --cpu 1 --cpu-load "$LOAD" \
            --temp-path . -t 1d &
        done
        Copy to clipboard
3. Run the cyclic latency test. Execute cyclictest with high priority to measure scheduling latency. The test runs for approximately 27.78 hours.

cyclictest -a 7 -t 1 -m -l 100000000 -i 1000 -p 99 -h 100 --mainaffinity 6
        Copy to clipboard
4. Note the worst-case latencies.

To run cyclic test with stress-ng on Dragonwing IQ-8275, do the following:

1. Set the target CPU load, Define the desired CPU load percentage. If not specified, the default load is 60%:

LOAD=60
        Copy to clipboard
2. Run stress-ng on selected CPU cores in the background. Apply CPU load on cores 0, 1, 2, 4, 5, 6, and 7 using stress-ng. Each instance runs for one day and is pinned to a specific CPU core.

for cpu in 0 1 2 4 5 6 7; do
             taskset -c $cpu stress-ng --cpu 1 --cpu-load "$LOAD" \
             --temp-path . -t 1d &
        done
        Copy to clipboard
3. Run the cyclic latency test. Execute cyclictest with high priority to measure scheduling latency. The test runs for approximately 27.78 hours.

cyclictest -a 3 -t 1 -m -l 100000000 -i 1000 -p 99 -h 100 --mainaffinity 2
        Copy to clipboard
4. Note the worst-case latencies.

#### RT test results

| Device | Distro and image | Cyclictest use case | Results | Comments |
| --- | --- | --- | --- | --- |
| QCS6490 RT core: Best core - 7 Boot Flow - KVM | `performance_linux-qcom-rt-6.18_qcom-distro-kvm and qcom-multimedia-image` | No load | `T: 0 ( 1687) P:99 I:1000 C:100000000 Min: 1 Act: 2 Avg: 1 Max: 5` | Completed; latencies are inline &lt; 20 µs |
| QCS6490 RT core: Best core - 7 Boot Flow - KVM | `performance_linux-qcom-rt-6.18_qcom-distro-kvm and qcom-multimedia-image` | Stress-NG | `T: 0 ( 1853) P:99 I:1000 C:100000000 Min: 1 Act: 2 Avg: 1 Max: 10` | Completed; latencies are inline &lt; 20 µs |
| Dragonwing IQ-615 RT core: Best core - 7 Boot Flow - KVM | `performance_linux-qcom-rt-6.18_qcom-distro-kvm and qcom-multimedia-image` | No load | `T: 0 (23693) P:99 I:1000 C: 100000000 Min: 1 Act: 2 Avg: 2 Max: 9` | Completed; latencies are inline &lt; 20 µs |
| Dragonwing IQ-615 RT core: Best core - 7 Boot Flow - KVM | `performance_linux-qcom-rt-6.18_qcom-distro-kvm and qcom-multimedia-image` | Stress-NG | `T: 0 (1590198) P:99 I:1000 C:100000000 Min: 1 Act: 2 Avg: 2 Max: 7` | Completed; latencies are inline &lt; 20 µs |
|  |  |  |  |  |

## Next steps

- [Customize for performance tuning](https://docs.qualcomm.com/doc/80-80022-10/topic/18-customize.html#customize)
- [Analyze performance with tools](https://docs.qualcomm.com/doc/80-80022-10/topic/13-performance_tools.html#performance-tools)

Last Published: May 20, 2026

[Previous Topic
Get started with performance tuning and optimization](https://docs.qualcomm.com/bundle/publicresource/80-80022-10/topics/get-started.md) [Next Topic
Analyze performance with tools](https://docs.qualcomm.com/bundle/publicresource/80-80022-10/topics/13-performance_tools.md)

Source: [https://docs.qualcomm.com/doc/80-80022-10/topic/2-performance-features.html](https://docs.qualcomm.com/doc/80-80022-10/topic/2-performance-features.html)