Skip to content

Commit 08fa551

Browse files
Refactor documentation for profiling Linux kernel modules with Arm Streamline, enhancing clarity in descriptions, instructions, and structure across multiple sections.
1 parent 0199238 commit 08fa551

8 files changed

Lines changed: 54 additions & 52 deletions

File tree

content/learning-paths/embedded-and-microcontrollers/streamline-kernel-module/1_overview.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@ layout: learningpathall
77
---
88

99
## Overview
10-
11-
Performance tuning is not limited to user-space applications as kernel modules can also benefit from careful analysis. [Arm Streamline](https://developer.arm.com/Tools%20and%20Software/Streamline%20Performance%20Analyzer) is a powerful software profiling tool that helps developers understand performance bottlenecks, hotspots, and memory usage, even inside the Linux kernel. This Learning Path explains how to use Arm Streamline to profile a simple kernel module.
10+
Performance tuning is just as important for kernel modules as it is for user-space applications. Arm Streamline is a powerful profiling tool that helps you find performance bottlenecks, hotspots, and memory issues - even inside the Linux kernel. In this Learning Path, you'll learn how to use Arm Streamline to profile a simple kernel module on Arm-based systems. You'll see how profiling can reveal optimization opportunities and help you improve your module's efficiency.
1211
## Benefits of profiling Linux kernel modules with Arm Streamline
1312

1413
Kernel modules often operate in performance-critical paths, such as device drivers or networking subsystems. Even a small inefficiency in a module can affect the overall system performance.
1514

16-
Profiling enables you to:
15+
Profiling enables you to do the following:
1716

1817
- Identify hotspots (functions consuming most CPU cycles)
1918
- Measure cache and memory behavior

content/learning-paths/embedded-and-microcontrollers/streamline-kernel-module/2_build_kernel_image.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ These packages ensure that Buildroot can configure, compile, and assemble all th
2626

2727
## Build a debuggable kernel image
2828

29-
For this Learning Path you'll build a Linux image for Raspberry Pi 3B+ with a debuggable Linux kernel. You'll profile Linux kernel modules built out-of-tree and Linux device drivers built in the Linux source code tree.
29+
For this Learning Path you'll build a Linux image for Raspberry Pi 3B+ with a debuggable Linux kernel. You'll profile Linux kernel modules built out-of-tree and Linux device drivers built in the Linux source code tree.
30+
31+
{{% notice Note on using a different board%}}
32+
If you're not using a Raspberry Pi 3B+ for this Learning Path, select the default configuration that matches your hardware. Replace `raspberrypi3_64_defconfig` with the appropriate file from the `$(BUILDROOT_HOME)/configs` directory. This ensures Buildroot generates an image compatible with your target board.{{% /notice %}}
3033

3134
Start by cloning the Buildroot repository and initialize the build system with the default configurations:
3235

@@ -35,17 +38,12 @@ git clone https://github.com/buildroot/buildroot.git
3538
cd buildroot
3639
export BUILDROOT_HOME=$(pwd)
3740
make raspberrypi3_64_defconfig
38-
```
39-
{{% notice Note on using a different board%}}
40-
If you're not using a Raspberry Pi 3B+ for this Learning Path, select the default configuration that matches your hardware. Replace `raspberrypi3_64_defconfig` with the appropriate file from the `$(BUILDROOT_HOME)/configs` directory. This ensures Buildroot generates an image compatible with your target board.{{% /notice %}}
41-
42-
```
4341
make menuconfig
4442
```
4543

46-
![Buildroot menuconfig interface showing configuration options. The screen displays a blue dialog box with white text and a highlighted menu. The main menu lists Build options, System configuration, Kernel, and Target packages. The Build options section is selected, and sub-options include build packages with debugging symbols, gcc debug level set to debug level 3, and build packages with runtime debugging info. The environment is a text-based terminal interface, typical for embedded Linux development. The tone is technical and instructional, guiding users through enabling debugging features in Buildroot. alt-text#center](./images/menuconfig.png "Buildroot menuconfig interface showing configuration options.")
44+
![Buildroot menuconfig interface showing configuration options. The screen displays a blue dialog box with white text and a highlighted menu. The main menu lists Build options, System configuration, Kernel, and Target packages. The Build options section is selected, and sub-options include build packages with debugging symbols, gcc debug level set to debug level 3, and build packages with runtime debugging info. The environment is a text-based terminal interface, typical for embedded Linux development. The tone is technical and instructional, guiding users through enabling debugging features in Buildroot. alt-text#center](./images/menuconfig.png "Buildroot menuconfig interface showing configuration options")
4745

48-
Change the Buildroot configuration to enable debugging symbols and SSH access:
46+
Now change the Buildroot configuration to enable debugging symbols and SSH access:
4947

5048
```plaintext
5149
Build options --->
@@ -77,7 +75,7 @@ Open the kernel configuration menu using the following:
7775
make linux-menuconfig
7876
```
7977

80-
In the menu, navigate to **Kernel hacking** and ensure that debugging options are enabled. Uncheck any option that reduces debugging information. This step preserves the symbols needed for effective kernel debugging and profiling.
78+
In the menu, navigate to **Kernel hacking** and ensure that debugging options are enabled. Uncheck any option that reduces debugging information. This step preserves the symbols needed for effective kernel debugging and profiling:
8179

8280
```plaintext
8381
Kernel hacking --->
@@ -114,4 +112,4 @@ For details on flashing the SD card image, see the article [Writing an SD Card I
114112

115113
## What you've accomplished and what's next
116114

117-
You've successfully built a custom Linux image with debugging features enabled and flashed it to your Raspberry Pi. This milestone means your development board is now running a kernel that's ready for profiling and advanced debugging. Great job reaching this point! Setting up a debuggable environment is a significant step in embedded Linux development. Next, you'll write and profile your own kernel module, building on the solid foundation you've established.
115+
You've now successfully built a custom Linux image with debugging features enabled and flashed it to your Raspberry Pi. This milestone means your development board is now running a kernel that's ready for profiling and advanced debugging. Great job! Setting up a debuggable environment is a significant step in embedded Linux development. Next, you'll write and profile your own kernel module, building on the solid foundation you've established.

content/learning-paths/embedded-and-microcontrollers/streamline-kernel-module/3_oot_module.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ weight: 4
66
layout: learningpathall
77
---
88

9-
## Develop a cache-unfriendly Linux kernel module
9+
## Develop a cache-unfriendly Linux kernel module to analyze with Arm Streamline
1010

11-
You'll now create an example Linux kernel module (character device) that demonstrates a cache miss issue caused by traversing a 2D array in column-major order. This access pattern is not cache-friendly, as it skips over most of the neighboring elements in memory during each iteration.
11+
You'll create a simple Linux kernel module that acts as a character device and intentionally causes cache misses. It does this by traversing a two-dimensional array in column-major order, which is inefficient for the CPU cache because it jumps between non-adjacent memory locations. This pattern helps you see how cache-unfriendly code can slow down performance, making it easier to analyze with Arm Streamline.
1212

1313
To build the Linux kernel module, start by creating a new directory, for example `example_module`. Inside this directory, add two files: `Makefile` and `mychardrv.c`.
1414

@@ -206,9 +206,9 @@ The module above receives the size of a 2D array as a string through the `char_d
206206
207207
## Build and run the kernel module
208208
209-
To compile the kernel module, run make inside the example_module directory. This generates the output file `mychardrv.ko`.
209+
To compile the kernel module, run `make` inside the `example_module` directory. This generates the output file `mychardrv.ko`.
210210
211-
Transfer the kernel module (`mychardrv.ko`) to your target device using the `scp` command. Then, insert the module with `insmod` and create the character device node with `mknod`. To test the module, write a size value (such as 10000) to the device file and use the `time` command to measure how long the operation takes. This lets you see the performance impact of the cache-unfriendly access pattern in a clear, hands-on way.
211+
Transfer the kernel module (`mychardrv.ko`) to your target device using the `scp` command. Then, insert the module with `insmod` and create the character device node with `mknod`. To test the module, write a size value (such as 10000) to the device file and use the `time` command to measure how long the operation takes. This lets you see the performance impact of the cache-unfriendly access pattern in a clear, hands-on way:
212212
213213
```bash
214214
scp mychardrv.ko root@<target-ip>:/root/
@@ -230,10 +230,11 @@ Execute the following commads on the target to run the module:
230230
```
231231

232232
{{% notice Note %}}
233-
42 and 0 are the major and minor number specified in the module code above
233+
42 and 0 are the major and minor number specified in the module code above.
234234
{{% /notice %}}
235235

236-
To verify that the module is active, run `dmesg` and the output should match the below:
236+
To confirm that your kernel module is loaded and running, use the `dmesg` command. You should see a message like this in the output:
237+
237238

238239
```bash
239240
dmesg
@@ -251,7 +252,6 @@ To make sure it's working as expected you can use the following command:
251252
# user 0m 0.00s
252253
# sys 0m 38.03s
253254
```
255+
The command above sends the value 10000 to your kernel module, which sets the size of the 2D array it creates and traverses. Because the module accesses the array in a cache-unfriendly way, the `echo` command takes a noticeable amount of time to finish - it's about 38 seconds in this example. This delay is expected and highlights the performance impact of inefficient memory access patterns, making it easy to analyze with Arm Streamline.
254256

255-
The command above passes 10000 to the module, which specifies the size of the 2D array to be created and traversed. The **echo** command takes a long time to complete (around 38 seconds) due to the cache-unfriendly traversal implemented in the `char_dev_cache_traverse()` function.
256-
257-
Great job building and running your kernel module! Now that you have a working example, you're ready to take the next step: profiling it with Arm Streamline. In the following section, you'll use Streamline to capture runtime behavior, identify performance bottlenecks, and see firsthand how cache-unfriendly access patterns impact your module. Get ready to gain valuable insights and optimize your code!
257+
You have successfully built and run your kernel module. In the next section, you'll profile it using Arm Streamline to capture runtime behavior, identify performance bottlenecks, and observe the effects of cache-unfriendly access patterns. This analysis will help you understand and optimize your code.

0 commit comments

Comments
 (0)