Confirmed users
507
edits
AlexPakhotin (talk | contribs) (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 = | ||