Mobile/Fennec/Android/Profiling: Difference between revisions

no edit summary
(Created page with "= Custom kernel for Nexus One = == Background information == ''oprofile'' is disabled in Nexus One kernel, so the kernel needs to be rebuilt to include it. These links have ins...")
 
No edit summary
Line 1: Line 1:
= Adding ''oprofile'' to CyanogenMod 7 =
CyanogenMod 7 is used here, but these steps will probably work similarly for other ROMs.
tl;dr:
* CyanogenMod comes with the oprofile binaries opcontrol and oprofiled
* However the CyanogenMod kernel doesn't include the oprofile module, so we need to recompile the kernel with oprofile
* However oprofile module is kind of broken, so we need to patch it
* opcontrol is broken too; we need to fix it
* oprofile profiles happily there after
== Recompile kernel with oprofile ==
Root and flash a standard CyanogenMod 7 ROM. Make sure the ROM runs.
Check the kernel version:
> adb shell uname -r
2.6.32.28-cyanogenmod-g4f4ee2e
Note the kernel branch (2.6.32) and revision (4f4ee2e) used to compile the kernel. Also find the right kernel repo for your phone at https://github.com/CyanogenMod (for HTC G2 it's 'htc-kernel-msm7x30').
Checkout the kernel source with the same revision:
git clone -b KERNEL_VER git://github.com/CyanogenMod/KERNEL_REPO.git ~/android-kernel
cd ~/android-kernel
git checkout KERNEL_REV
In this example, replace KERNEL_VER with 'android-msm-2.6.32', KERNEL_REPO with 'htc-kernel-msm7x30', and KERNEL_REV with '4f4ee2e'
Get a copy of the kernel config:
adb pull /proc/config.gz
gunzip -c config.gz > .config
Make sure .config contains these lines:
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE_ARMV7=y
Currently oprofile on ARM only supports OMAP3 processors. If your processor is anything else (the HTC G2 has a Qualcomm MSM7230), you need to patch oprofile. For MSM7x30, apply this patch:
diff --git a/arch/arm/oprofile/op_model_v7.c b/arch/arm/oprofile/op_model_v7.c
index f20295f..b0fbc65 100644
--- a/arch/arm/oprofile/op_model_v7.c
+++ b/arch/arm/oprofile/op_model_v7.c
@@ -371,6 +371,9 @@ static int irqs[] = {
  #ifdef CONFIG_ARCH_OMAP3
        INT_34XX_BENCH_MPU_EMUL,
  #endif
+#if defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_QSD8X50)
+        INT_ARM11_PM,
+#endif
  };
 
  static void armv7_pmnc_stop(void)
Set the toolchain and compile: (the original kernel is built with 4.4.3 but NDK has 4.4.0; not sure if this matters...)
export CCOMPILER=/PATH/TO/NDK/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-
make ARCH=arm CROSS_COMPILE=$CCOMPILER -j4
After the smoke settles, the kernel should be at arch/arm/boot/zImage
== Flash kernel to phone ==
Extract a copy of of boot.img from the CyanogenMod zip used to flash the phone:
unzip update-cm-7.0.3-vision-signed.zip boot.img
Use the split_bootimg.pl [http://android-dls.com/files/linux/split_bootimg.zip] script to extract boot.img; note the output
> split_bootimg.pl boot.img
Page size: 2048 (0x00000800)
Kernel size: 2275692 (0x0022b96c)
Ramdisk size: 144106 (0x000232ea)
Second size: 0 (0x00000000)
Board name:
Command line: no_console_suspend=1 console=null
Writing boot.img-kernel ... complete.
Writing boot.img-ramdisk.gz ... complete.
Now we need to make a new boot.img using the mkbootimg [http://forum.xda-developers.com/attachment.php?attachmentid=475249&d=1293574570] tool included in the Android source repo.
mkbootimg --kernel ~/android-kernel/arch/arm/boot/zImage --ramdisk boot.img-ramdisk.gz --cmdline "CMDLINE" --board "BOARD" --base BASE -o new-boot.img
Replace CMDLINE and BOARD with values in the output from split_bootimg.pl. I found the value for BASE from a hex dump of boot.img:
> xxd -s 12 -l 4 -g 1 boot.img
000000c: 00 80 00 04                                      ....
00 80 00 04 is little-endian for 0x04008000 so BASE is 0x04000000. So in this example the command is:
mkbootimg --kernel ~/android-kernel/arch/arm/boot/zImage --ramdisk boot.img-ramdisk.gz --cmdline "no_console_suspend=1 console=null" --base 0x04000000 -o new-boot.img
As a sanity check, if for --kernel you specify 'boot.img-kernel', new-boot.img should be identical to boot.img
Now you can put the kernel on the phone. Boot into bootloader and use fastboot:
adb reboot bootloader
fastboot boot new-boot.img
This kernel update will be temporary. You can also do "fastboot flash boot new-boot.img" to make it permanent. If fastboot outputs error ("not allowed", etc), you might need a new bootloader that supports fastboot. On the HTC G2, I found a 0.76.2 ENG bootloader and flashed it with dd in adb shell.
If Wifi breaks, you have to replace the wlan kernel module. For the HTC Vision, the module is located at drivers/net/wireless/bcm4329/bcm4329.ko. Of course, since you replaced the module, you have to replace the kernel with ''fastboot flash'' rather than ''fastboot boot''
adb shell mount -o remount,rw /system
adb push bcm4329.ko /system/lib/modules/
adb shell mount -o remount,ro /system
== Patch and build opcontrol ==
There's a prebuilt opcontrol here [http://people.mozilla.com/~alexp/android/oprofile/opcontrol-oprofiled.zip], otherwise:
Because opcontrol is a part of CyanogenMod, we need to recompile the whole thing. (Or not, but I don't know any alternative way) Follow step here: http://wiki.cyanogenmod.com/wiki/Building_from_source. You might need to use a branch/revision that corresponds to your CyanogenMod version.
Before you start building, you want to edit external/oprofile/opcontrol/opcontrol.cpp and find calls to mkdir and add a 0 in front of the permissions.
== Set up oprofile ==
adb shell mount -o remount,rw /system
adb push opcontrol /system/xbin
adb shell chmod +x /system/xbin/opcontrol
echo "#! /system/xbin/bash
touch /data/local/tmp/vmlinux
opcontrol --setup
opcontrol --vmlinux=/data/local/tmp/vmlinux \
--kernel-range=0x`adb shell cat /proc/kallsyms | grep ' _text' | head -c 8`,\
0x`adb shell cat /proc/kallsyms | grep ' _etext' | head -c 8` \
--event=CPU_CYCLES:125000" > opsetup
adb push opsetup /system/xbin
adb shell chmod +x /system/xbin/opsetup
echo "#! /bin/bash
rm -f -R oprofile
mkdir oprofile
adb pull /data/oprofile oprofile/" > oppull
chmod +x oppull
adb shell mount -o remount,ro /system
The sample rate is (CPU freuqency in MHz) / (CPU_CYCLES count) / 64. For the HTC G2, it's 800MHz / 100000 / 64 = 125 samples per second.
= Using ''oprofile'' on CyanogenMod 7 =
adb shell opsetup > /dev/null 2>&1 & # start up oprofile
adb shell opcontrol --start          # start profiling
adb shell opcontrol --status        # check status
adb shell opcontrol --stop          # stop profiling
adb shell opcontrol --shutdown      # shut down oprofile
./oppull                            # pull profile data from phone
Note that if you do start and stop, then start and stop again, the second set of data will be merged with the first set of data. I think you should be able use ''adb shell opcontrol --reset'' to start all over, but it didn't seem to work for me. Alternatively, you can always do a shut down and start up sequence to start over.
opreport is used to analyze the profile. The native x86 version seems to deal with the ARM data fine.
sudo apt-get install oprofile
You will see a lot of names in the form "/path/to/file.so (deleted)", and opreport can't find symbols because of the " (deleted)" part, so we create some symlinks:
rm -f -R oplibs
mkdir oplibs
for f in /PATH/TO/OBJDIR/dist/lib/*
do ln -s $f "oplibs/${f##*/} (deleted)"
done
Then you can see the report after the profile is pulled. e.g.:
opreport --session-dir=oprofile -l -t 1 -p ~+/oplibs 2>/dev/null
= Custom kernel for Nexus One =
= Custom kernel for Nexus One =


Confirmed users
507

edits