From 4d7142aad039e0e20acd3742c04cc4da6eb9cf25 Mon Sep 17 00:00:00 2001 From: Alexander Aksenov Date: Wed, 13 Dec 2017 15:57:36 +0300 Subject: [PATCH] Kernel integration: add Porting Guide Change-Id: If664459bbdd6227b8fcf51af8964493e11f848e3 Signed-off-by: Alexander Aksenov --- kernel_integration/README | 44 +++++ kernel_integration/README.md | 41 ---- kernel_integration/docs/Makefile | 12 ++ kernel_integration/docs/PortingGuide.md | 327 ++++++++++++++++++++++++++++++++ kernel_integration/docs/hdesign.png | Bin 0 -> 42265 bytes kernel_integration/docs/readme.css | 36 ++++ 6 files changed, 419 insertions(+), 41 deletions(-) create mode 100644 kernel_integration/README delete mode 100644 kernel_integration/README.md create mode 100644 kernel_integration/docs/Makefile create mode 100644 kernel_integration/docs/PortingGuide.md create mode 100644 kernel_integration/docs/hdesign.png create mode 100644 kernel_integration/docs/readme.css diff --git a/kernel_integration/README b/kernel_integration/README new file mode 100644 index 0000000..3807631 --- /dev/null +++ b/kernel_integration/README @@ -0,0 +1,44 @@ +SWAP integration help +--------------------- + +Full guide see at docs/ + + +If kernel supports module using and doesn't have kernel memory protection - +build modules as a common Tizen package, otherwise do the following: + + +1) Check and apply kernel hooks: +1.1) Check if hooks were already ported to the kernel: + + $ ls /include/swap + +Expected result like: + hook_energy.h + hook_file_ops.h + hook_signal.h + hook_switch_to.h + hook_syscall.h + hook_syscall_priv.h + hook_taskdata.h + hook_usaux.h + +If the directory doesn't exists or empty, follow the next steps to apply patches; + +1.2) Apply kernel hooks patches from /kernel_integration/patches/*.patch + +1.3) First, try to do it with git am: + + $ cd linux-kernel + $ git am /kernel_integration/patches/*.patch + +1.4) If there are conflicts, apply patches manually. + +2. Synchronize swap-modules sources +At this point you have kernel with SWAP kernel hooks applied. +Run script to sync swap-modules sources to then kernel: + + $ ./sync_swap_to_kernel.sh + +3. Test swap-modules +Now you have kernel with swap-modules, test it using SWAP Test System diff --git a/kernel_integration/README.md b/kernel_integration/README.md deleted file mode 100644 index 6415fd0..0000000 --- a/kernel_integration/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# How-to integrate swap-modules to kernel. - - -## Two cases are possible: -### 1. swap-modules to kernel initial integration, do the following steps: - * #### prepare kernel for swap-modules integration: - - ```sh - $ cd - $ git am /kernel_integration/patches/*.patch - ``` - In case of patch conflicts you have to solve it manually - - * #### sync swap-modules to kernel: - - ```sh - $ ./sync_swap_to_kernel.sh - ``` - - * #### add options to config: - ```sh - # - # SWAP subsystem for Dynamic Analyzer - # - CONFIG_SWAP_DA=y - CONFIG_SWAP_KERNEL_IMMUTABLE=y - CONFIG_SWAP_HOOK_TASKDATA=y - CONFIG_SWAP_HOOK_USAUX=y - CONFIG_SWAP_HOOK_SYSCALL=y - CONFIG_SWAP_HOOK_SWITCH_TO=y - CONFIG_SWAP_HOOK_ENERGY=y - CONFIG_SWAP_HOOK_FILE_OPS=y - CONFIG_SWAP_HOOK_SIGNAL=y - ``` - - -### 2. swap-modules changes synchronization to kernel, do the following step: - -```sh -$ ./sync_swap_to_kernel.sh -``` diff --git a/kernel_integration/docs/Makefile b/kernel_integration/docs/Makefile new file mode 100644 index 0000000..0acf394 --- /dev/null +++ b/kernel_integration/docs/Makefile @@ -0,0 +1,12 @@ +all: html_readme pdf_readme + +html_readme: + pandoc -f markdown+pipe_tables -t html5 --css readme.css -s PortingGuide.md -o PortingGuide.html + +pdf_readme: + pandoc -f markdown+pipe_tables -s PortingGuide.md -o PortingGuide.pdf + +clean: + rm PortingGuide.html PortingGuide.pdf + +.PHONY: all html_readme pdf_readme clean diff --git a/kernel_integration/docs/PortingGuide.md b/kernel_integration/docs/PortingGuide.md new file mode 100644 index 0000000..8f30a91 --- /dev/null +++ b/kernel_integration/docs/PortingGuide.md @@ -0,0 +1,327 @@ +%SWAP Porting guide + +# Table of Contents +* [Introduction to SWAP](#introduction-to-swap) +* [SWAP architecture and components](#swap-architecture-and-components) +* [SWAP porting procedure](#swap-porting-procedure) + * [Kernel with memory protection or without kernel modules support](#kernel-with-memory-protection-or-without-kernel-modules-support) + * [Checking and applying SWAP kernel hooks](#applying-swap-kernel-hooks) + * [Checking SWAP kernel hooks existance in kernel](#checking-swap-kernel-hooks-existance-in-kernel) + * [Applying SWAP kernel hooks by GIT](#applying-swap-kernel-hooks-by-git) + * [Applying SWAP kernel hooks manually](#applying-swap-kernel-hooks-manually) + * [SWAP modules and kernel sources synchronization](#swap-modules-and-kernel-sources-synchronization) + * [Manual synchronization](#manual-synchronization) + * [Usign sync script](#using-sync-script) +* [Testing SWAP](#testing-swap) + +# Introduction to SWAP + +**SWAP** is a Tizen dynamic binary instrumentation tool, it allows developers +to trace and profile their applications. The tool supports a number of Tizen +devices and emulators and is supplied as a part of their firmware. To check if +your device contains SWAP, you can check whether the **swap-manager** package +is installed: + +``` bash +$ rpm -q swap-manager +``` + +If the output looks like the following then SWAP is installed: +``` bash +swap-manager-3.0-7.6.i686 +``` + +So, if your device or emulator contains SWAP, you can start using it. + + +SWAP is located on the target device, it is responsible for gathering run time +data about the developer's application. When it works it is connected with a +host side tool and communicates with it in a format described at SWAP protocol. +SWAP host side tool controls SWAP execution, provides it with a profiling +session options and receives gathered data. There are two SWAP host-side tools: +[Dynamic Analyzer](https://developer.tizen.org/development/tizen-studio/native-tools/debugging-your-app/dynamic-analyzer) +GUI tool and SWAP Python console tool, which is provided with the +**swap-manager** (located at git repo: git://git.tizen.org/platform/core/system/swap-manager). + +SWAP contains several useful features for developers: + +* Function profiling. This feature allows the developer to trace functions of +interest of his application, it is based on uprobe mechanism. The developer +specifies which functions in which binary files he wants to trace and when +control flow reaches one, the event related information is collected: function +address, timestamp, arguments etc. is generated. +* Profiling of OpenGL and system APIs related to memory management, file +operations, network and threading. This feature provides the developer +information about application's system resources usage. +* Leak Sanitizer. This feature generates report about memory leaks in the +application. For more information check Leak Sanitizer documentation. +* Context switches profiling. This feature adds data about context switching to +the trace. +* Sampling. Used for process sampling with the specified period. + +# SWAP architecture and components + +![SWAP design and workflow diagram](hdesign.png) + +SWAP consists of the several components: user-space daemon, kernel modules and +SWAP library. + +* SWAP probe library is loaded at the target process memory area, used for +profiling system APIs and LSan analytic without using the expensive uprobe +mechanism. +* The daemon is used for communication between SWAP and host side. It is also +responsible for executing and killing applications, transferring data between +kernel- and user-space, communication with the SWAP library instances at the +target application's memory areas, and sending gathered data to host side. +* SWAP kernel modules provides kprobe and uprobe functionality and sampling +feature. + +SWAP probe library (**swap-probe**) and SWAP daemon (**swap-manager**) are +user-space components of the SWAP tool. They are built as common Tizen packages, +so they do not need any porting. + +SWAP Linux kernel modules (**swap-modules**) are kernel-space components of the +SWAP tool, and in some cases they require special porting activities. + +# SWAP porting procedure + +**Kernel sources should be managed by GIT to make the following guide works.** + +For **swap-probe** and **swap-manager** projects usually no extra activities are +needed during supporting new device. + +For **swap-modules** there are two possible cases of distribution: + +* If kernel supports modules and doesn't have any kernel memory protection, +then no special porting activity is needed; +* If kernel doesn't support modules or it has a kernel memory protection, then +**swap-modules** are distributed as a part of kernel sources. In case the +developer needs to apply hooks on kernel and synchronize **swap-modules** +sources with the kernel ones. + +Only the last case leads to additional developer activities, it will be +described further in details. + +## Kernel with memory protection or without kernel modules support + +In this case the developer should do the following: + +* Check and apply SWAP kernel hooks on demand; +* Synchronize SWAP modules and kernel sources. + +### Checking and applying SWAP kernel hooks + +SWAP modules need information about some kernel events. Commonly, the modules +receive this data arming kprobes on the functions of interest, but if the kernel +memory is protected then the only way to get these events data is kernel hooks +implementation. Kprobe provides more flexibility for **swap-modules** while +hooks are faster. + +#### Checking SWAP kernel hooks existance in kernel + +If SWAP was already ported to the kernel that means that the kernel hooks are +already exist in kernel sources, and the developer shouldn't apply patches with +them once again. + +To check if the kernel source code already contains SWAP hooks, check that +directory *\/include/swap* exists and is not empty: + +``` bash +$ ls linux-kernel/include/swap/ +``` + +If result looks like the following, hooks are already applied: + +``` bash +hook_energy.h hook_file_ops.h hook_signal.h hook_switch_to.h hook_syscall.h +hook_syscall_priv.h hook_taskdata.h hook_usaux.h +``` + +If the directory doesn't exists or empty then the patches should be applied. + +#### Applying SWAP kernel hooks by GIT + +All the necessary patches are contained at *\/kernel_integration/patches/* +directory. To apply these patches, the developer should execute ```git am``` +from the kernel sources directory passing *\/kernel_integration/patches/\*.patch* +as its argument: + +``` bash +$ cd linux-kernel +$ git am swap-modules/kernel_integration/patches/*.patch +``` + +As far as there is a number of different kernels, the patches will not be +applied without conflicts for all of them in some cases it is needed to apply +these patches manually + +#### Applying SWAP kernel hooks manually + +All the necessary kernel patches are located at *\/kernel_integration/patches/*, +here is their list: + +| File | Description | +| ------------------------------------------------ | ------------------------------------------------------------ | +| 0001-Prepare-kernel-for-swap-modules-integration | Prepares **swap-modules** integration to kernel build system | +| 0002-Prepare-kernel-for-swap-hooks-integration | Prepares **swap-modules** hooks integration to kernel build | +| 0003-SWAP-DA-arm64-Add-CONFIG_SWAP_HOOK_SYSCALL | Add syscall hook for ARM64 | +| 0004-SWAP-DA-add-CONFIG_SWAP_HOOK_TASKDATA | Add hook for Task Data support | +| 0005-SWAP-DA-arm64-add-CONFIG_SWAP_HOOK_USAUX | Add SWAP auxiliary hooks for ARM64 | +| 0006-SWAP-DA-add-CONFIG_SWAP_HOOK_SWITCH_TO | Add hook on context switching | +| 0007-SWAP-DA-add-CONFIG_SWAP_HOOK_ENERGY | Add necessary SWAP energy hooks | +| 0008-SWAP-DA-add-CONFIG_SWAP_HOOK_FILE_OPS | Add file operations hook | +| 0009-SWAP-DA-add-CONFIG_SWAP_HOOK_SIGNAL | Add SWAP signal hook | + +These patches are git-formatted. The patches may not always be applied without +conflicts. In that cases, the developer should resolve them manually. Patch +changes should be applied one by one starting from +*0001-Prepare-kernel-for-swap-modules-integration.patch*, +finishing with *0009-SWAP-DA-add-CONFIG_SWAP_HOOK_SIGNAL.patch*. +All the necessary information, like files that change, code that surrounds +changes etc. is provided in *.patch files. + +## SWAP modules and kernel sources synchronization + +### Manual synchronization + +**swap-modules** synchronization can be done manually. To do this, the developer +should do the following: + +1. Synchronize **swap-modules** + * Remove existent **swap-modules** from kernel, if any: +``` bash +$ rm -r /kernel/swap/modules/ +OR +$ rm -r /kernel/swap/module/ +``` + + * Copy **swap-modules** modules directory to *\/kernel/swap/modules*: +``` bash +$ cp -r /modules/ /kernel/swap/modules/ +``` + * Make *Makefile*s from *Kbuild* + * Rename *Kbuild* files with *Makefile* + * For core *Makefile* in *modules* directory: + * Remove ```EXTRA_CFLAGS```, ```extra_cflags``` and ```ks_manager``` from *Makefile*s + * Replace ```obj-m :=``` with ```obj-y +=``` + * For other *Makefile*s: + * Remove ```KBUILD_EXTRA_SYMBOLS``` + * Replace ```obj-m``` with ```obj-y``` + * Remove ```$(extra-cflags)``` + * Remove ```EXTRA_CFLAGS = ``` + * Replace ```EXTRA_CFLAGS``` with ```ccflags-y``` + * Add architecture-dependent include paths: + +``` bash +ccflags-y := -I + +ifeq (\$(CONFIG_ARM), y) + link = arm +endif + +ifeq (\$(CONFIG_ARM64), y) + link = arm64 +endif + +ifeq (\$(CONFIG_X86), y) + link = x86 +endif + +ccflags-y += -I/kprobe/arch/\$(link) \ + -I/uprobe/arch/\$(link) +``` + +2. Update hooks + * Remove current hooks, if any: +``` bash +$ rm -r /include/swap/ +$ rm -r /kernel/swap/hooks/ +OR +$ rm -r /kernel/swap/hook/ +``` + + * Copy new hooks: +``` bash +$ cp -r /kernel_integration/hooks/include/swap/ \ + /include/ +$ cp -r /kernel_integration/hooks/kernel/swap/hooks/ \ + /kernel/swap/ +``` + * Copy ```Kconfig``` to *\/kernel/swap/*: +``` bash +$ cp /kernel_integration/hooks/kernel/swap/Kconfig \ + /kernel/swap/ +``` + + * Copy ```Makefile``` to *\/kernel/swap/*: +``` bash +$ cp /kernel_integration/hooks/kernel/swap/Makefile \ + /kernel/swap/ +``` + +3. Make commit +``` bash +$ git add /kernel/swap/. +$ git add /include/swap/. +$ git commit +``` + +Now **swap-modules** sources are fully synchronized to the kernel. + +### Using sync script + +There is a special script that synchronizes **swap-modules** sources to the +kernel sources. It is located at *\/kernel_integration/sync_swap_to_kernel.sh* +and takes SWAP modules directory, kernel sources directory and kernel config +file as its arguments. You can execute it, for example, as a following: + +``` bash +$ swap-modules/kernel_integration/sync_swap_to_kernel.sh \ + \ + \ + /arch/arm/configs/tizen_defconfig +``` + +The last argument, kernel config, is optional. It is used to modify kernel +config to use SWAP and its kernel hooks. If this option is not specified, the +developer should manually add it to the end of the config file, which is used +for kernel building, the following: + +``` bash +# +# SWAP subsystem for Dynamic Analyzer +# +CONFIG_SWAP_DA=y +CONFIG_SWAP_KERNEL_IMMUTABLE=y +CONFIG_SWAP_HOOK_TASKDATA=y +CONFIG_SWAP_HOOK_USAUX=y +CONFIG_SWAP_HOOK_SYSCALL=y +CONFIG_SWAP_HOOK_SWITCH_TO=y +CONFIG_SWAP_HOOK_ENERGY=y +CONFIG_SWAP_HOOK_FILE_OPS=y +CONFIG_SWAP_HOOK_SIGNAL=y +``` + +After the script has finished the kernel will contain SWAP modules sources same +as the sources in **swap-modules** directory, specified as the first argument. +These changes will be committed in the last kernel commit with message +***"SWAP: sync"***. + +# Testing SWAP + +After porting has been done, SWAP should be tested. To do this, first of all +necessary binaries should be prepared: + +1. Prepare **swap-modules** binaries. There are two possible cases: + * if **swap-modules** are provided as a standalone package, build them with a + proper build root using GBS; + * if **swap-modules** are provided as a part of the kernel, then prepare a + firmware using modified kernel with **swap-modules** and flash it to the + target. + +2. Prepare **swap-manager** and **swap-probe** binaries. Build them with a +proper build root using GBS; +3. Push prepared rpm packages to the target and install them; +4. Execute **SWAP Test System**. To get more information about it, please refer +to the *SWAP Test documentation*, it is located at ***swap-test*** project +(git://git.tizen.org/test/swap-test). diff --git a/kernel_integration/docs/hdesign.png b/kernel_integration/docs/hdesign.png new file mode 100644 index 0000000000000000000000000000000000000000..8a254e3b87680c3ea0ee74854348159d3577b1ee GIT binary patch literal 42265 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 literal 0 HcmV?d00001 diff --git a/kernel_integration/docs/readme.css b/kernel_integration/docs/readme.css new file mode 100644 index 0000000..87864eb --- /dev/null +++ b/kernel_integration/docs/readme.css @@ -0,0 +1,36 @@ +body { + font-family: Arial, Helvetica, sans-serif; +} + +table { + border-collapse: collapse; +} + +table td, table th { + border: 1px solid #ddd; + padding: 8px; +} + +table th { + padding-top: 12px; + padding-bottom: 12px; + text-align: left; + background-color: #4caf50; + color: white; +} + +code { + background-color: #e8e8e8; + border: 1px solid transparent; + border-radius: 5px; +} + +code[class='sourceCode python'] { + background-color: transparent; + border: 0; +} + +code[class='sourceCode bash'] { + background-color: transparent; + border: 0; +} -- 2.7.4