OProfile is a profiling system can do profiling on all parts of a running system from the kernel to shared libraries and to binaries. It can work in the background, collecting information at a low overhead, it is ideal for profiling the entire system to determine the bottle necks in a real running system.
OProfile can be run in two modes: Legacy mode and Operf mode. In legacy mode, the special OProfile kernel driver is required. Profiling is controlled by opcontrol
script and oprofiled
daemon. In operf mode, the operf program is used to control profiling instead of using opcontrol
and oprofiled
. Operf
does not require the Oprofile kernel driver, it interfaces with kernel to collect samples via the Linux Kernel Performance Events Subsystem (perf_events).
S3C2440 board does not provide the needed hardware supports to use the performance counters, which is used by Perf_events. So on S3C2440 board, OProfie falls back to use legacy mode and the timer interrupt for profiling, by using the real-time clock interrupt to collect samples. In timer mode, OProfile is not able to profile code that has interrupt disabled.
When configure buildroot, oprofile is selected and application binaries is located in /home/iot/mini2440/buildroot-2013.02/output/target/usr/bin
as below.
[root@localhost bin]# pwd
/home/iot/mini2440/buildroot-2013.02/output/target/usr/bin
[root@localhost bin]# ls op*
opannotate oparchive op-check-perfevents opcontrol openvt operf opgprof ophelp opimport opjitconv opreport oprofiled
[root@localhost bin]# ll op*
-rwxr-xr-x. 1 root root 398876 Dec 28 14:59 opannotate
-rwxr-xr-x. 1 root root 305316 Dec 28 14:59 oparchive
-rwxr-xr-x. 1 root root 4164 Dec 28 14:59 op-check-perfevents
-rwxr-xr-x. 1 root root 53899 Dec 28 14:59 opcontrol
lrwxrwxrwx. 1 root root 17 Dec 28 14:59 openvt -> ../../bin/busybox
-rwxr-xr-x. 1 root root 162700 Dec 28 14:59 operf
-rwxr-xr-x. 1 root root 336900 Dec 28 14:59 opgprof
-rwxr-xr-x. 1 root root 43424 Dec 28 14:59 ophelp
-rwxr-xr-x. 1 root root 43400 Dec 28 14:59 opimport
-rwxr-xr-x. 1 root root 29224 Dec 28 14:59 opjitconv
-rwxr-xr-x. 1 root root 505812 Dec 28 14:59 opreport
-rwxr-xr-x. 1 root root 92940 Dec 28 14:59 oprofiled
The libraries required by the applications are located in the directory /home/iot/mini2440/buildroot-2013.02/output/target/lib
and /home/iot/mini2440/buildroot-2013.02/output/target/usr/lib
.
[root@localhost lib]# ls
ld-uClibc-0.9.32.1.so libcrypt.so.0 libdl.so.0 libm-0.9.32.1.so libnsl.so.0 libresolv-0.9.32.1.so librt.so.0 libuClibc-0.9.32.1.so
ld-uClibc.so.0 libc.so.0 libgcc_s.so libm.so.0 libpthread-0.9.32.1.so libresolv.so.0 libthread_db-0.9.32.1.so libutil-0.9.32.1.so
libcrypt-0.9.32.1.so libdl-0.9.32.1.so libgcc_s.so.1 libnsl-0.9.32.1.so libpthread.so.0 librt-0.9.32.1.so libthread_db.so.1 libutil.so.0
[root@localhost lib]# pwd
/home/iot/mini2440/buildroot-2013.02/output/target/lib
[root@localhost lib]# cd ../usr/lib/
[root@localhost lib]# pwd
/home/iot/mini2440/buildroot-2013.02/output/target/usr/lib
[root@localhost lib]# ls
ldscripts libfreetype.so.6.10.0 libid3tag.so.0 libkmod.so libncurses.so.5.9 libpopt.so.0 libstdc++.so.6.0.17-gdb.py libz.so.1
libbfd-2.20.1.20100303.so libgomp.so libid3tag.so.0.3.0 libkmod.so.2 libopcodes-2.20.1.20100303.so libpopt.so.0.0.0 libsysfs.so libz.so.1.2.7
libbfd.so libgomp.so.1 libintl.so libkmod.so.2.2.2 libopcodes.so libreadline.so libsysfs.so.2 oprofile
libelf.so libgomp.so.1.0.0 libintl.so.8 libmad.so libpng14.so libreadline.so.6 libsysfs.so.2.0.1 terminfo
libelf.so.0 libhistory.so libintl.so.8.1.2 libmad.so.0 libpng14.so.14 libreadline.so.6.2 libts-1.0.so.0 ts
libelf.so.0.8.12 libhistory.so.6 libjpeg.so libmad.so.0.2.1 libpng14.so.14.12.0 libstdc++.so libts-1.0.so.0.0.0
libfreetype.so libhistory.so.6.2 libjpeg.so.8 libncurses.so libpng.so libstdc++.so.6 libts.so
libfreetype.so.6 libid3tag.so libjpeg.so.8.4.0 libncurses.so.5 libpopt.so libstdc++.so.6.0.17 libz.so
[root@localhost lib]#
Check the library dependency of the profile applications as below,
[root@localhost lib]# cd /home/iot/mini2440/buildroot-2013.02/output/target/usr/bin/
[root@localhost bin]# pwd
/home/iot/mini2440/buildroot-2013.02/output/target/usr/bin
[root@localhost bin]# arm-linux-readelf -d op* | grep library
readelf: Error: Unable to read in 0x4f20 bytes of section headers
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
0x00000001 (NEEDED) Shared library: [libpopt.so.0]
0x00000001 (NEEDED) Shared library: [libbfd-2.20.1.20100303.so]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libstdc++.so.6]
0x00000001 (NEEDED) Shared library: [libm.so.0]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libpopt.so.0]
0x00000001 (NEEDED) Shared library: [libbfd-2.20.1.20100303.so]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libstdc++.so.6]
0x00000001 (NEEDED) Shared library: [libm.so.0]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libpopt.so.0]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libstdc++.so.6]
0x00000001 (NEEDED) Shared library: [libm.so.0]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libpopt.so.0]
0x00000001 (NEEDED) Shared library: [libbfd-2.20.1.20100303.so]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libstdc++.so.6]
0x00000001 (NEEDED) Shared library: [libm.so.0]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libpopt.so.0]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libpopt.so.0]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libstdc++.so.6]
0x00000001 (NEEDED) Shared library: [libm.so.0]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libbfd-2.20.1.20100303.so]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libpopt.so.0]
0x00000001 (NEEDED) Shared library: [libbfd-2.20.1.20100303.so]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libstdc++.so.6]
0x00000001 (NEEDED) Shared library: [libm.so.0]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x00000001 (NEEDED) Shared library: [libpopt.so.0]
0x00000001 (NEEDED) Shared library: [libdl.so.0]
0x00000001 (NEEDED) Shared library: [libintl.so.8]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.0]
[root@localhost bin]#
The opcontrol script requires math function, need to configure the Busybox to support math in the shell scripts.
[root@localhost busybox-1.19.4]# pwd
/home/iot/mini2440/busybox-1.19.4
[root@localhost busybox-1.19.4]# make menuconfig
HOSTLD scripts/kconfig/mconf
HOSTCC scripts/kconfig/lxdialog/checklist.o
HOSTCC scripts/kconfig/lxdialog/inputbox.o
HOSTCC scripts/kconfig/lxdialog/lxdialog.o
HOSTCC scripts/kconfig/lxdialog/menubox.o
HOSTCC scripts/kconfig/lxdialog/msgbox.o
HOSTCC scripts/kconfig/lxdialog/textbox.o
HOSTCC scripts/kconfig/lxdialog/util.o
HOSTCC scripts/kconfig/lxdialog/yesno.o
HOSTLD scripts/kconfig/lxdialog/lxdialog
scripts/kconfig/mconf Config.in
#
# using defaults found in .config
#
*** End of configuration.
*** Execute 'make' to build the project or try 'make help'.
Under Coreutils
,
[*] tr
[*] Enable character classes (such as [:upper:]) (NEW)
[*] Enable equivalence classes (NEW)
[*] dirname
[*] expr
[*] false
[*] fold
[*] mv
[*] sleep
[*] Enable multiple arguments and s/m/h/d suffixes (NEW)
[*] Enable fractional arguments (NEW)
Under Process Utilities
,
[*] pidof
[*] Enable argument for single shot (-s) (NEW)
[*] Enable argument for omitting pids (-o) (NEW)
Under Shells
,
[*] POSIX math support
[*] Extend POSIX math support to 64 bit (NEW)
Under Editors
,
[*] awk
[*] Enable math functions (requires libm) (NEW)
[*] Allow vi and awk to execute shell commands
Recompile and install Busybox,
[root@localhost busybox-1.19.4]# make clean
CLEAN applets
CLEAN .tmp_versions _install
CLEAN busybox busybox_unstripped.map busybox_unstripped.out busybox_unstripped busybox.links .kernelrelease
[root@localhost busybox-1.19.4]# make
[root@localhost busybox-1.19.4]# make install
[root@localhost rootfilesystem]# pwd
/home/iot/mini2440/rootfilesystem
[root@localhost rootfilesystem]#
Modify the shell script create_rootfs_bash.sh
.
Add following line,
ln -s /proc/mounts etc/mtab
after,
ln -s bin/busybox init
Copy the applications, to include below lines,
cp /home/iot/mini2440/myapp/thread_demo* usr/bin
cp $TARGET_DIR/usr/bin/gdbserver usr/bin
cp $TARGET_DIR/usr/bin/op* usr/bin
cp $TARGET_DIR/usr/bin/ldd usr/bin
cp $TARGET_DIR/usr/bin/objcopy usr/bin
cp $TARGET_DIR/usr/bin/objdump usr/bin
And copy the libraries, to include below lines,
cp -P $TARGET_DIR/lib/* lib/
cp -P $TARGET_DIR/usr/lib/libpopt* usr/lib
cp -P $TARGET_DIR/usr/lib/libbfd* usr/lib
cp -P $TARGET_DIR/usr/lib/libintl* usr/lib
cp -P $TARGET_DIR/usr/lib/libstdc++* usr/lib
cp -P $TARGET_DIR/usr/lib/libz* usr/lib
cp -P $TARGET_DIR/usr/lib/libopcodes* usr/lib
The whole create root file system bash is as below,
echo "------Create rootfs --------"
rm -fr rootfs
rm initramfs.cpio
mkdir rootfs
pushd rootfs
echo "--------Create root,dev....----------"
mkdir root dev etc boot tmp usr var sys proc lib mnt home
mkdir etc/init.d etc/rc.d etc/sysconfig lib/modules
mkdir usr/sbin usr/bin usr/lib usr/modules
echo "---------Copy from busybox, rootfs-base, libs -----------"
cp -aP /home/iot/mini2440/busybox-1.19.4/_install/* .
ln -s bin/busybox init
ln -s /proc/mounts etc/mtab
cp -arP ../rootfs-base/* /home/iot/mini2440/rootfilesystem/rootfs/
cp /home/iot/mini2440/linux-3.8.7/System.map boot/
#Copy applications
cp /home/iot/mini2440/myapp/greeting usr/bin
cp /home/iot/mini2440/myapp/thread_demo* usr/bin
cp $TARGET_DIR/usr/bin/gdbserver usr/bin
cp $TARGET_DIR/usr/bin/op* usr/bin
cp $TARGET_DIR/usr/bin/ldd usr/bin
cp $TARGET_DIR/usr/bin/objcopy usr/bin
cp $TARGET_DIR/usr/bin/objdump usr/bin
cp /home/iot/mini2440/buildroot-2013.02/output/target/usr/bin/gdbserver usr/bin
cp /home/iot/mini2440/buildroot-2013.02/output/target/usr/bin/ldd usr/bin
cp -P /home/iot/mini2440/buildroot-2013.02/output/target/lib/* lib/
cp -P $TARGET_DIR/lib/* lib/
cp -P $TARGET_DIR/usr/lib/libpopt* usr/lib
cp -P $TARGET_DIR/usr/lib/libbfd* usr/lib
cp -P $TARGET_DIR/usr/lib/libintl* usr/lib
cp -P $TARGET_DIR/usr/lib/libstdc++* usr/lib
cp -P $TARGET_DIR/usr/lib/libz* usr/lib
cp -P $TARGET_DIR/usr/lib/libopcodes* usr/lib
chown -R root.root ../rootfs
echo "---------make node dev/console dev/null-----------------"
mknod -m 600 dev/console c 5 1
mknod -m 600 dev/null c 1 3
chmod 666 dev/console
chmod 666 dev/null
mknod /dev/ptmx c 5 2
mkdir mnt/etc mnt/yaffs mnt/data mnt/temp
mkdir var/lib var/lock var/run var/tmp
chmod 1777 tmp
chmod 1777 var/tmp
# Create cpio image
find . | cpio -H newc -o > ../initramfs.cpio
# Move out of working directory
popd
Run the shell script create_rootfs_bash.sh
.
[root@localhost rootfilesystem]# pwd
/home/iot/mini2440/rootfilesystem
[root@localhost rootfilesystem]# ./create_rootfs_bash.sh
------Create rootfs --------
/home/iot/mini2440/rootfilesystem/rootfs /home/iot/mini2440/rootfilesystem
--------Create root,dev....----------
---------Copy from busybox, rootfs-base, libs -----------
---------make node dev/console dev/null-----------------
mknod: ‘/dev/ptmx’: File exists
14172 blocks
/home/iot/mini2440/rootfilesystem
[root@localhost rootfilesystem]#
The result is as below,
[root@localhost rootfilesystem]# ll -h
total 9.2M
-rwxr-xr-x. 1 root root 1.9K Dec 28 15:14 create_rootfs_bash.sh
-rw-r--r--. 1 root root 7.0M May 28 11:28 initramfs.cpio
-rwx------. 1 root root 16K Dec 28 14:19 mkyaffs2image-128M
drwxr-xr-x. 16 root root 4.0K May 28 11:28 rootfs
drwxr-xr-x. 3 root root 4.0K Dec 28 14:19 rootfs-base
-rw-------. 1 root root 2.0M Dec 28 14:19 rootfs.img
drwxr-xr-x. 7 root root 4.0K Dec 28 14:19 yaffs2-4e188b0
-rw-r--r--. 1 root root 285K Dec 28 14:19 yaffs2-4e188b0.tar.gz
[root@localhost rootfilesystem]#
Use make
command,
[root@localhost linux-3.8.7]# pwd
/home/iot/mini2440/linux-3.8.7
[root@localhost linux-3.8.7]# make clean
CLEAN .
CLEAN arch/arm/kernel
CLEAN drivers/tty/vt
CLEAN drivers/video/logo
CLEAN kernel
CLEAN lib
CLEAN usr
CLEAN arch/arm/boot/compressed
CLEAN arch/arm/boot
CLEAN .tmp_versions
[root@localhost linux-3.8.7]# make
Created the new zImage file.
[root@localhost boot]# ll -h
total 17M
drwxrwxr-x. 2 root root 4.0K Apr 13 2013 bootp
drwxrwxr-x. 2 root root 4.0K May 28 11:36 compressed
drwxrwxr-x. 3 root root 12K Apr 13 2013 dts
-rwxr-xr-x. 1 root root 12M May 28 11:36 Image
-rw-rw-r--. 1 root root 1.3K Apr 13 2013 install.sh
-rw-rw-r--. 1 root root 3.1K Apr 13 2013 Makefile
-rwxr-xr-x. 1 root root 5.3M May 28 11:36 zImage
[root@localhost boot]#
[root@localhost boot]# pwd
/home/iot/mini2440/linux-3.8.7/arch/arm/boot
#check again,
[root@localhost linux-3.8.7]# ll ./arch/arm/boot/zImage
-rwxr-xr-x. 1 root root 5518192 May 28 11:36 ./arch/arm/boot/zImage
[root@localhost linux-3.8.7]# ll -h ./arch/arm/boot/zImage
-rwxr-xr-x. 1 root root 5.3M May 28 11:36 ./arch/arm/boot/zImage
[root@localhost linux-3.8.7]# pwd
/home/iot/mini2440/linux-3.8.7
[root@localhost linux-3.8.7]#
The newly generated zImage is more than 5M, but the default setting in the bootloader, it only copy 5M bytes from kernel partition to RAM, so we need to change the setting, using command part add kernel 0x00060000 0x00600000 0
, the first number in command is the starting address of kernel stored in the NAND flash. The second number in the command is the number of bytes the bootloader will copy from kernel partition to RAM, it must be greater than the size of the zImage.
The procedure is as below, use option q
to enter vivi shell.
##### FriendlyARM BIOS 2.0 for 2440 #####
[x] format NAND FLASH for Linux
[v] Download vivi
[k] Download linux kernel
[y] Download root_yaffs image
[a] Absolute User Application
[n] Download Nboot for WinCE
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin
[d] Download & Run
[z] Download zImage into RAM
[g] Boot linux from RAM
[f] Format the nand flash
[b] Boot the system
[s] Set the boot parameters
[u] Backup NAND Flash to HOST through USB(upload)
[r] Restore NAND Flash from HOST through USB
[q] Goto shell of vivi
[i] Version: 1026-2K
Enter your selection: q
Supervivi> part del kernel
deleted 'kernel' partition
Supervivi> part add kernel 0x00060000 0x00600000 0
kernel: offset = 0x00060000, size = 0x00600000, flag = 0
Supervivi> part show
Number of partitions: 4
name : offset size flag
------------------------------------------------------------
vivi : 0x00000000 0x00040000 0
param : 0x00040000 0x00020000 0
root : 0x00660000 0x3fa80000 0
kernel : 0x00060000 0x00600000 0
Supervivi> param show
Number of parameters: 9
name : hex integer
-------------------------------------------------------------
mach_type : 000007cf 1999
media_type : 00000003 3
boot_mem_base : 30000000 805306368
baudrate : 0001c200 115200
xmodem : 00000001 1
xmodem_one_nak : 00000000 0
xmodem_initial_timeout : 000493e0 300000
xmodem_timeout : 000f4240 1000000
boot_delay : 01000000 16777216
Linux command line: noinitrd init=/init console=ttySAC0,115200
Supervivi> param save
Found block size = 0x00020000
Erasing... ... done
Writing... ... done
Written 49152 bytes
Saved vivi private data
Supervivi> menu
##### FriendlyARM BIOS 2.0 for 2440 #####
[x] format NAND FLASH for Linux
[v] Download vivi
[k] Download linux kernel
[y] Download root_yaffs image
[a] Absolute User Application
[n] Download Nboot for WinCE
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin
[d] Download & Run
[z] Download zImage into RAM
[g] Boot linux from RAM
[f] Format the nand flash
[b] Boot the system
[s] Set the boot parameters
[u] Backup NAND Flash to HOST through USB(upload)
[r] Restore NAND Flash from HOST through USB
[q] Goto shell of vivi
[i] Version: 1026-2K
Enter your selection:
Download the zImage at the host side,
[root@localhost mini2440]# ./download_image.sh
csum = 0x62cc
send_file: addr = 0x33f80000, len = 0x00543370
[root@localhost mini2440]#
Download the zImage at Embedded Linux S3C2440 board side,
[x] format NAND FLASH for Linux
[v] Download vivi
[k] Download linux kernel
[y] Download root_yaffs image
[a] Absolute User Application
[n] Download Nboot for WinCE
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin
[d] Download & Run
[z] Download zImage into RAM
[g] Boot linux from RAM
[f] Format the nand flash
[b] Boot the system
[s] Set the boot parameters
[u] Backup NAND Flash to HOST through USB(upload)
[r] Restore NAND Flash from HOST through USB
[q] Goto shell of vivi
[i] Version: 1026-2K
Enter your selection: k
USB host is connected. Waiting a download.
Now, Downloading [ADDRESS:30000000h,TOTAL:5518202]
RECEIVED FILE SIZE: 5518202 (19KB/S, 280S)
Downloaded file at 0x30000000, size = 5518192 bytes
Found block size = 0x00560000
Erasing... ... done
Writing... ... done
Written 5518192 bytes
##### FriendlyARM BIOS 2.0 for 2440 #####
[x] format NAND FLASH for Linux
[v] Download vivi
[k] Download linux kernel
[y] Download root_yaffs image
[a] Absolute User Application
[n] Download Nboot for WinCE
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin
[d] Download & Run
[z] Download zImage into RAM
[g] Boot linux from RAM
[f] Format the nand flash
[b] Boot the system
[s] Set the boot parameters
[u] Backup NAND Flash to HOST through USB(upload)
[r] Restore NAND Flash from HOST through USB
[q] Goto shell of vivi
[i] Version: 1026-2K
Enter your selection:
The booting message is as below, it includes below two lines,
oprofile: no performance counters
oprofile: using timer interrupt.
##### FriendlyARM BIOS 2.0 for 2440 #####
[x] format NAND FLASH for Linux
[v] Download vivi
[k] Download linux kernel
[y] Download root_yaffs image
[a] Absolute User Application
[n] Download Nboot for WinCE
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin
[d] Download & Run
[z] Download zImage into RAM
[g] Boot linux from RAM
[f] Format the nand flash
[b] Boot the system
[s] Set the boot parameters
[u] Backup NAND Flash to HOST through USB(upload)
[r] Restore NAND Flash from HOST through USB
[q] Goto shell of vivi
[i] Version: 1026-2K
Enter your selection: b
Copy linux kernel from 0x00060000 to 0x30008000, size = 0x00600000 ... done
zImage magic = 0x016f2818
Setup linux parameters at 0x30000100
linux command line is: "noinitrd init=/init console=ttySAC0,115200"
MACH_TYPE = 1999
NOW, Booting Linux......
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 3.8.7-FriendlyARM (root@localhost.localdomain) (gcc version 4.7.2 (Buildroot 2013.02) ) #8 Tue May 28 11:36:17 SGT 2019
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: MINI2440
ATAG_INITRD is deprecated; please update your bootloader.
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: noinitrd init=/init console=ttySAC0,115200
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
__ex_table already sorted, skipping sort
Memory: 64MB = 64MB total
Memory: 52708k/52708k available, 12828k reserved, 0K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
vmalloc : 0xc4800000 - 0xff000000 ( 936 MB)
lowmem : 0xc0000000 - 0xc4000000 ( 64 MB)
modules : 0xbf000000 - 0xc0000000 ( 16 MB)
.text : 0xc0008000 - 0xc0462ee4 (4460 kB)
.init : 0xc0463000 - 0xc0b7153c (7226 kB)
.data : 0xc0b72000 - 0xc0baf028 ( 245 kB)
.bss : 0xc0baf028 - 0xc0befba0 ( 259 kB)
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS:85
irq: clearing subpending status 00000003
irq: clearing subpending status 00000002
sched_clock: 32 bits at 200 Hz, resolution 5000000ns, wraps every 4294967291ms
Console: colour dummy device 80x30
Calibrating delay loop... 201.52 BogoMIPS (lpj=503808)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0x30334630 - 0x3033466c
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
MINI2440: Option string mini2440=0tb
MINI2440: 't' ignored, touchscreen not compiled in
MINI2440: LCD [0:240x320] 1:800x480 2:1024x768 3:320x240
S3C2440: Initialising architecture
S3C2440: IRQ Support
S3C244X: Clock Support, DVS off
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Linux video capture interface: v2.00
NET: Registered protocol family 2
TCP established hash table entries: 512 (order: 0, 4096 bytes)
TCP bind hash table entries: 512 (order: -1, 2048 bytes)
TCP: Hash tables configured (established 512 bind 512)
TCP: reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
NetWinder Floating Point Emulator V0.97 (double precision)
NFS: Registering the id_resolver key type
Key type id_resolver registered
Key type id_legacy registered
jffs2: version 2.2. (NAND) �© 2001-2006 Red Hat, Inc.
msgmni has been set to 102
alg: No test for stdrng (krng)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
Console: switching to colour frame buffer device 30x20
s3c2410-lcd s3c2410-lcd: fb0: s3c2410fb frame buffer device
s3c2440-uart.0: ttySAC0 at MMIO 0x50000000 (irq = 70) is a S3C2440
console [ttySAC0] enabled
s3c2440-uart.1: ttySAC1 at MMIO 0x50004000 (irq = 73) is a S3C2440
s3c2440-uart.2: ttySAC2 at MMIO 0x50008000 (irq = 76) is a S3C2440
brd: module loaded
loop: module loaded
Loading iSCSI transport class v2.0-870.
s3c24xx-nand s3c2440-nand: Tacls=1, 9ns Twrph0=3 29ns, Twrph1=2 19ns
s3c24xx-nand s3c2440-nand: NAND soft ECC
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit), 256MiB, page size: 2048, OOB size: 64
Creating 4 MTD partitions on "nand":
0x000000000000-0x000000040000 : "u-boot"
0x000000040000-0x000000060000 : "u-boot-env"
000000060000-0x000000560000 : "kernel"
0x000000560000-0x000010000000 : "root"
dm9000 Ethernet Driver, V1.31
dm9000_probe Set bwscon and bankcon4
dm9000 dm9000: read wrong id 0x01010101
dm9000 dm9000: eth%d: Invalid ethernet MAC address. Please set using ifconfig
Now use the default MAC address: 08:90:90:90:90:90
eth0: dm9000e at c48bc300,c48be304 IRQ 51 MAC: 08:90:90:90:90:90 (chip)
usbcore: registered new interface driver cdc_ether
usbcore: registered new interface driver rndis_host
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
mousedev: PS/2 mouse device common for all mice
s3c-rtc s3c2410-rtc: rtc disabled, re-enabling
s3c-rtc s3c2410-rtc: rtc core: registered s3c as rtc0
s3c-rtc s3c2410-rtc: warning: invalid RTC value so initializing it
oprofile: no performance counters
oprofile: using timer interrupt.
TCP: cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 17
Key type dns_resolver registered
console [netcon0] enabled
netconsole: network logging started
s3c-rtc s3c2410-rtc: setting system clock to 2000-01-01 00:00:00 UTC (946684800)
Freeing init memory: 7224K
starting pid 450, tty '': '/etc/init.d/rcS'
* Mounting /proc...
* Mounting /dev...
* Mounting /sys...
* Mounting /dev/pts...
* Mounting /dev/shm...
* Starting system loggers...
* Creating devices...
* Configuring loopback interface...
* Setting hostname...
eth0 up
dm9000 dm9000 eth0: link down
starting pid 466, tty '': '/usr/sbin/telnetd -l /bin/login'
starting pid 467, tty '': '-/bin/login'
mini2440 login: dm9000 dm9000 eth0: link up, 100Mbps, full-duplex, lpa 0xC1E1
Login timed out after 60 seconds
process '-/bin/login' (pid 467) exited. Scheduling for restart.
starting pid 470, tty '': '-/bin/login'
mini2440 login: root
-sh: can't access tty; job control turned off
[root@mini2440 /root]#
Yes, check carefully, you can find below message in the booting message,
oprofile: no performance counters
oprofile: using timer interrupt.
Login as root and OProfile applications are in the directory /usr/bin
.
So we use legacy mode and clock/timer interrupt to collect samples.
[root@localhost ~]# telnet 192.168.0.11
Trying 192.168.0.11...
Connected to 192.168.0.11.
Escape character is '^]'.
mini2440 login: root
[root@mini2440 /root]# cd /usr/bin
[root@mini2440 bin]# operf
Your kernel's Performance Events Subsystem does not support your processor type.
Please use the opcontrol command instead of operf.
[root@mini2440 bin]#
Set up the OProfile, need to tell OProfile where the vmlinux
file is corresponding to the running kernel. As we don’t profile the kernel itself, use below command to inform OProfile we don’t have vmlinux
file.
[root@mini2440 bin]# opcontrol --no-vmlinux
[root@mini2440 bin]#
You can choose to create separate sample files by specifying one of the below options,
none | No profile separation(default) |
---|---|
lib | Create per-application profiles for libraries |
kernel | Create per-application profiles for the kernel and kernel modules |
thread | Create profiles for each thread and each task |
cpu | Create profile for each CPU |
All | All of the above options |
We specify separate by thread.
[root@mini2440 bin]# opcontrol --separate=thread
[root@mini2440 bin]#
We start profiling, run an application and stop the daemon. Key in several commands in one line so they are executed one after another, it will avoid affecting the results by time of hitting the keyboard.
[root@mini2440 bin]# ls op* thread*
op-check-perfevents operf opreport thread_demo_FIFO_max_min thread_demo_RR_max_max.c
opannotate opgprof oprofiled thread_demo_FIFO_max_min.c thread_demo_RR_max_min
oparchive ophelp thread_demo.c thread_demo_FIFO_min_max thread_demo_RR_max_min.c
opcontrol opimport thread_demo_FIFO_max_max thread_demo_FIFO_min_max.c thread_demo_RR_min_max
openvt opjitconv thread_demo_FIFO_max_max.c thread_demo_RR_max_max thread_demo_RR_min_max.c
Commands and the output,
[root@mini2440 bin]# opcontrol --start; ./thread_demo_RR_max_max;opcontrol --dump;opcontrol --shutdown
Using 2.6+ OProfile kernel interface.
Using log file /var/lib/oprofile/samples/oprofiled.log
Daemon started.
Profiler running.
min/max prio (1, 99)
count1 = 6680, count2 = 3321
Stopping profiling.
Killing daemon.
[root@mini2440 bin]#
Collect the results of the application.
[root@mini2440 bin]# opreport -l ./thread_demo_RR_max_max
Using /var/lib/oprofile/samples/ for samples directory.
CPU: CPU with timer interrupt, speed 301 MHz (estimated)
Profiling through timer interrupt
Processes with a thread ID of 597
Processes with a thread ID of 598
samples % samples % symbol name
282 100.000 0 0 thread_func1
0 0 140 100.000 thread_func2
[root@mini2440 bin]#
thread_func1
is only called in thread 597 and thread_func2
is only called in thread 598. So thread_func1
is not sampled in thread 598 and thread_func2
is not sampled in thread 597. main()
function is not shown because the main thread is sequentially and short and not hit by the timer interrupt.
Collect the results for the whole system.
[root@mini2440 bin]# opreport --merge tgid
Using /var/lib/oprofile/samples/ for samples directory.
CPU: CPU with timer interrupt, speed 301 MHz (estimated)
Profiling through timer interrupt
TIMER:0|
samples| %|
------------------
422 53.5533 thread_demo_RR_max_max
323 40.9898 no-vmlinux
16 2.0305 busybox
14 1.7766 libuClibc-0.9.32.1.so
11 1.3959 ld-uClibc-0.9.32.1.so
2 0.2538 oprofiled
[root@mini2440 bin]#
The opannotate
utility generates annotated source files or assembly listings, optionally mixed with the source code. If include the source file, the profiled application needs to have debug information, that is to use -g
option when compiling the application using GCC. If the binary doesn’t contain sufficient debug information, you can still use opannotate --assembly
to get annotated assembly as long as the binary has symbol information.
We already used the -g option when we compiled the thread_demo*
applications, so the applications already contains both debugging information and symbol information.
Use below command to annotate the source of our applications. -s/--source
option means to output annotated source, it requires debugging information to be available in the binaries.
[root@mini2440 bin]# opannotate -s ./thread_demo_RR_max_max
Using /var/lib/oprofile/samples/ for session-dir
/*
* Command line: opannotate -s ./thread_demo_RR_max_max
*
* Interpretation of command line:
* Output annotated source file with samples
* Output all files
*
* CPU: CPU with timer interrupt, speed 301 MHz (estimated)
* Profiling through timer interrupt
* Processes with a thread ID of 597
* Processes with a thread ID of 598
*/
opannotate (warning): unable to open for reading: /home/iot/mini2440/myapp/thread_demo_RR_max_max.c
/*
* Total samples for file : "/home/iot/mini2440/myapp/thread_demo_RR_max_max.c"
*
* 282 100.000 140 100.000
*/
/* thread_func1 total: 282 100.000 0 0 */
/* thread_func2 total: 0 0 140 100.000 */
[root@mini2440 bin]#
Above output returns opannotate (warning): unable to open for reading: /home/iot/mini2440/myapp/thread_demo_RR_max_max.c
, it is because when we cross-compile the application on the host, the source file is in the directory /home/iot/mini2440/myapp
. This path is contained in the debug information of the application. However on the target S3C2440 there is no such directoy and the source code is in /usr/bin
. We need to use -b
and -d
options to tell opannotate
where to find the source on the target.
Usage --base-dirs/-b [path]
, it is to point oprofile to a different location for source files when the debug information specifies an absolute path on your target system for the source which does not exist. The prefixed is stripped the debug source file paths, then searched int he search dirs specified by --search-dirs
, used the option `–search-dirs/-d [path].
The new command and the output is as below opannotate -s ./thread_demo_RR_max_max -b /home/iot/mini2440/myapp -d /usr/bin
, we didn’t use -a
here to include the assembly annotations.
[root@mini2440 bin]# opannotate -s ./thread_demo_RR_max_max -b /home/iot/mini2440/myapp -d /usr/bin
Using /var/lib/oprofile/samples/ for session-dir
/*
* Command line: opannotate -s ./thread_demo_RR_max_max -b /home/iot/mini2440/myapp -d /usr/bin
*
* Interpretation of command line:
* Output annotated source file with samples
* Output all files
*
* CPU: CPU with timer interrupt, speed 301 MHz (estimated)
* Profiling through timer interrupt
* Processes with a thread ID of 597
* Processes with a thread ID of 598
*/
/*
* Total samples for file : "/home/iot/mini2440/myapp/thread_demo_RR_max_max.c"
*
* 282 100.000 140 100.000
*/
:#include <stdio.h>
:#include <pthread.h>
:#include <stdlib.h>
:#include <errno.h>
:#include <assert.h>
:#include <sched.h>
:
:#define DEMO_POLICY SCHED_RR //SCHED_FIFO
:
:int count1 = 0;
:int count2 = 0;
:
:int times = 10000;
:
:void *thread_func1(void)
/* thread_func1 total: 282 100.000 0 0 */
:
: while(times > 0)
: {
: int i = 0;
:
185 65.6028 0 0 : for(i=0; i< 20000; i++)
97 34.3972 0 0 : i++;
:
: count1 ++;
:
: times --;
:
: }
:
: return (void*) NULL;
:}
:
:void *thread_func2(void)
/* thread_func2 total: 0 0 140 100.000 */
:
: while(times > 0)
: {
: int i = 0;
:
0 0 101 72.1429 : for(i=0; i< 20000; i++)
0 0 39 27.8571 : i++;
:
: count2 ++;
:
: times --;
:
: }
:
: return (void*) NULL;
:}
:
:
:int main()
:{
:
: int res;
: pthread_t thread_1;
: pthread_t thread_2;
:
: pthread_attr_t thread_1_attr;
: pthread_attr_t thread_2_attr;
:
: int min_prio;
: int max_prio;
:
: struct sched_param param1;
: struct sched_param param2;
:
: struct timespec tp;
:
: /* get max, min prop for policy FIFO/RR */
: max_prio = sched_get_priority_max(DEMO_POLICY);
: min_prio = sched_get_priority_min(DEMO_POLICY);
:
: printf("min/max prio (%d, %d)\n", min_prio, max_prio);
:
: res = pthread_attr_init(&thread_1_attr);
: assert(res == 0);
:
: res = pthread_attr_init(&thread_2_attr);
: assert(res == 0);
:
: /* Set sched policy */
: res = pthread_attr_setinheritsched(&thread_1_attr, PTHREAD_EXPLICIT_SCHED);
: assert(res == 0);
:
: res = pthread_attr_setinheritsched(&thread_2_attr, PTHREAD_EXPLICIT_SCHED);
: assert(res == 0);
:
: res = pthread_attr_setschedpolicy(&thread_1_attr, DEMO_POLICY);
: assert(res == 0);
:
: res = pthread_attr_setschedpolicy(&thread_2_attr, DEMO_POLICY);
: assert(res == 0);
:
: /* Set thread priority */
: param1.sched_priority = max_prio; // min_prio
: param2.sched_priority = max_prio; // max_prio
:
: res = pthread_attr_setschedparam(&thread_1_attr,¶m1);
: assert(res == 0);
:
: res = pthread_attr_setschedparam(&thread_2_attr,¶m2);
: assert(res == 0);
:
: /* Create threads */
: res = pthread_create(&thread_1, &thread_1_attr, (void *)thread_func1, NULL);
: assert(res == 0);
:
: res = pthread_create(&thread_2, &thread_2_attr, (void *)thread_func2, NULL);
: assert(res == 0);
:
: pthread_join(thread_1, NULL);
: pthread_join(thread_2, NULL);
:
: printf("count1 = %d, count2 = %d\n", count1, count2);
:
: exit(0);
:
:
:}
:
[root@mini2440 bin]#
Embedded Linux S3C2440 environment setup
Embedded Linux S3C2440 Environment Startup
Embedded Linux S3C2440 Build and Boot an Image
Embedded Linux S3C2440 Application Development and Debugging
Embedded Linux S3C2440 Networking
Embedded Linux S3C2440 – Kernel Module
Embedded Linux S3C2440 – Kernel Debugging
Embedded Linux S3C2440 – Multi-thread Scheduling