Skip to content

Commit fe90ecc

Browse files
Refactor documentation for building Linux kernel images and profiling with Streamline, enhancing clarity in section titles, instructions, and descriptions.
1 parent b7f18b7 commit fe90ecc

5 files changed

Lines changed: 53 additions & 53 deletions

File tree

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

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

9-
## Prepare to build Linux image with Buildroot
9+
## Prepare to build a Linux image with Buildroot
1010

1111
Before you build a Linux image with [Buildroot](https://github.com/buildroot/buildroot), make sure your development environment includes all the required packages. These tools and libraries are essential for compiling, configuring, and assembling embedded Linux images on Arm platforms. Installing them now helps you avoid build errors and ensures a smooth workflow.
1212

13-
## Install required packages for Buildroot
13+
## Install the required packages for Buildroot
1414

15-
Run the following commands on your aarch64-based Linux system to update your package list and install the necessary dependencies:
15+
Run the following commands on your AArch64-based Linux system to update your package list and install the necessary dependencies:
1616

1717
```bash
1818
sudo apt update
@@ -43,7 +43,7 @@ If you're not using a Raspberry Pi 3B+ for this Learning Path, select the defaul
4343
make menuconfig
4444
```
4545

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)
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.")
4747

4848
Change the Buildroot configuration to enable debugging symbols and SSH access:
4949

@@ -67,7 +67,6 @@ Target packages --->
6767
[*] openssh
6868
[*] server
6969
[*] key utilities
70-
```
7170
You might need to update your default `sshd_config` file to match your network requirements. To do this, set the **Root filesystem overlay directories** option in the **System configuration** menu. Add a directory containing your customized `sshd_config` file. This ensures your SSH server uses the correct settings when the image boots.
7271
7372
By default, Linux kernel images are stripped of debugging information. To make the image debuggable for profiling, you need to adjust the kernel build settings.

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

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

9-
## Create an out-of-tree Linux kernel module
9+
## Develop a cache-unfriendly Linux kernel module
1010

1111
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.
1212

13-
To build the Linux kernel module, start by creating a new directory, for example `example_module`. Inside this directory, add two files: `mychardrv.c` and `Makefile`.
13+
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

1515
## Makefile
1616

17+
To build your Linux kernel module for Arm, you need a Makefile that instructs the build system how to compile and link your code against the kernel source. The Makefile below is designed for use with Buildroot and cross-compiles your module for the aarch64 architecture. Update the `BUILDROOT_OUT` variable to match your Buildroot output directory before running the build:
18+
1719
```makefile
1820
obj-m += mychardrv.o
1921
BUILDROOT_OUT := $(BUILDROOT_HOME)/output # Change this to your buildroot output directory
@@ -28,12 +30,11 @@ clean:
2830
$(MAKE) -C $(KDIR) M=$(PWD) clean
2931
```
3032

31-
{{% notice Note %}}
32-
Change `BUILDROOT_OUT` to the correct buildroot output directory on your host machine.
33-
{{% /notice %}}
3433

3534
## mychardrv.c
3635

36+
The `mychardrv.c` file contains the source code for your custom Linux kernel module. This module implements a simple character device that demonstrates cache-unfriendly behavior by traversing a two-dimensional array in column-major order. The code below allocates and initializes the array, performs the cache-unfriendly traversal, and exposes a write interface for user input. You’ll use this module to generate measurable performance bottlenecks for analysis with Arm Streamline.
37+
3738
```c
3839
// SPDX-License-Identifier: GPL-2.0
3940
#include "linux/printk.h"
@@ -203,55 +204,54 @@ MODULE_DESCRIPTION("A simple char driver with cache misses issue");
203204
204205
The module above receives the size of a 2D array as a string through the `char_dev_write()` function, converts it to an integer, and passes it to the `char_dev_cache_traverse()` function. This function then creates the 2D array, initializes it with simple data, traverses it in a column-major (cache-unfriendly) order, computes the sum of its elements, and prints the result to the kernel log. The cache-unfriendly aspects allows you to inspect a bottleneck using Streamline in the next section.
205206
206-
## Building and Running the Kernel Module
207+
## Build and run the kernel module
207208
208-
1. To compile the kernel module, run make inside the example_module directory. This will generate 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`.
209210
210-
2. Transfer the .ko file to the target using scp command and then insert it using insmod command. After inserting the module, you create a character device node using mknod command. Finally, you can test the module by writing a size value (e.g., 10000) to the device file and measuring the time taken for the operation using the `time` command.
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.
211212
212-
```bash
213+
```bash
213214
scp mychardrv.ko root@<target-ip>:/root/
214-
```
215+
```
215216

216-
{{% notice Note %}}
217-
Replace \<target-ip> with your target's IP address
218-
{{% /notice %}}
217+
{{% notice Note %}} Replace \<target-ip> with your target's IP address
218+
{{% /notice %}}
219219

220-
3. SSH onto your target device:
220+
SSH onto your target device:
221221

222-
```bash
222+
```bash
223223
ssh root@<your-target-ip>
224-
```
224+
```
225225

226-
4. Execute the following commads on the target to run the module:
227-
```bash
226+
Execute the following commads on the target to run the module:
227+
```bash
228228
insmod /root/mychardrv.ko
229229
mknod /dev/mychardrv c 42 0
230-
```
230+
```
231231

232-
{{% notice Note %}}
232+
{{% notice Note %}}
233233
42 and 0 are the major and minor number specified in the module code above
234-
{{% /notice %}}
234+
{{% /notice %}}
235235

236-
4. To verify that the module is active, run `dmesg` and the output should match the below:
236+
To verify that the module is active, run `dmesg` and the output should match the below:
237237

238-
```bash
238+
```bash
239239
dmesg
240-
```
240+
```
241241

242-
```output
242+
```output
243243
[12381.654983] mychardrv is open - Major(42) Minor(0)
244-
```
244+
```
245245

246-
5. To make sure it's working as expected you can use the following command:
246+
To make sure it's working as expected you can use the following command:
247247

248-
```bash { output_lines = "2-4" }
248+
```bash { output_lines = "2-4" }
249249
time echo '10000' > /dev/mychardrv
250250
# real 0m 38.04s
251251
# user 0m 0.00s
252252
# sys 0m 38.03s
253-
```
253+
```
254254

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.
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.
256256

257257
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!

0 commit comments

Comments
 (0)