-
Notifications
You must be signed in to change notification settings - Fork 5
Migration Experience
During my experimentation with Linux kernel for Android emulator I did several different things/steps before I come to a point that I can use the code:
-
I use the 2.6.29 code from Android git repo as the base. Once I get the code I copy over the Android code to the mainline 2.6.29 kernel code and boots the emulator using the newly compiled kernel
-
Once step 1 was successfull I migrate each version incrementally as per the version number - for example I migrate 2.6.29 and the move on to 2.6.31 and if successfull I move up to 2.6.35 and so on until I can complete the 2.6.x version
-
The compiler I'm using is the one that comes with the Android source code which lives inside the prebuilt/ directory. The version is gcc 4.4.3
-
When I'm stuck with something I use GDB to debug the code, the only thing to enable is the CONFIG_DEBUG_INFO flag in the .config file as this will generate the debugging info inside the vmlinux file which can be used in GDB like so:
arm-eabi-gcc-adb vmlinux -
There are few changes that needs to be done for 3.x inside the board-goldfish.c the following declaration changes has been put in
MACHINE_START(GOLDFISH, "Goldfish") //.phys_io = IO_START, //.io_pg_offst = ((IO_BASE) >> 18) & 0xfffc, .atag_offset = 0x100, .map_io = goldfish_map_io, .init_irq = goldfish_init_irq, .init_machine = goldfish_init, .timer = &goldfish_timer, MACHINE_ENDas can be seen in the above code snippets the .phys_io and .io_pg_offset is no more supported in 3.x so that need to be removed/remarked
-
There was a major issue with 3.4 which I've outlined in the section "Problem with 3.4". While going through the process of finding this problem I learned quite a lot from this exercise
- I learnt about what is the function of __init
- Even though I can't see the console I can still print out the contents of memory by using GDB. All I need to know is the variable that stored this information where in Linux case it is inside the __log_buf variable and I can use the command x/200s __log_buf to view the content of the memory location
- Registration in Linux is simple yet confusing, it is based on linked list.
- Linux has got a "virtual" bus called "platform" which can be used as parent for other "virtual" device to connect to
- Most of the code are located inside kernel/ or drivers/base/ folder
- With QEMU it is not possible to 'watch' variable as it requires hardware breakpoint which is not supported. This can be done only in real hardware not emulated
-
System.map file is useful to know the memory address location of the function/variable that is in the kernel
-
The main entry point in kernel is kernel_init and the main entry file is init/main.c
-
When doing cross compiling I need to use gcc for cross compiling which means that extra parameters must be use:
arm-eabi-gcc ARCH=arm CROSS_COMPILE=<location_of_the_toolchain> -j<no_of_threads_for_compiling_building> -
Qemu prints out a lot of information that can be utilized in debugging by using the -show-kernel option
-
To enable debugging we need to give the following parameter to the emulator. This will stops Qemu from starting the kernel and will open port 1234 to accept incoming connection from GDB.
emulator -qemu -S -s -
From GDB to connect to Qemu for debugging we use the command - target remote :1234
-
To set value for a field inside a struct variable inside GDB we use the command
set variable p.dev=200 (where p is the variable that is a struct and dev is the field inside the struct) -
After kernel boots up it will try to switch to userspace by running the init.c (located in the ramdisk.img of Android). The code that do this is in init/main.c of the kernel and the function that do this is init_post
-
The ramdisk.img of Android is a standard Linux ramdisk image file that the kernel understand on how to extract the information out.
- The are significant changes from 2.6.38 onwards in the codebase
- Do search on google for keywoards
- I still can't find a way on how to debug code in the userspace once kernel boots up, this is useful if we can load userspace code in GDB after debugging the kernel code.
- Qemu is very powerful as it can emulate several different hardware that can run Linux. Very handy if want to learn Linux and it's internal without having to worry about having the hardware.
The problem that I find most of the time was that the console does not print anything on the screen. I found this when migrating 3.4, it was hard for me to look at the log messages as that was the only thing I was relying on, but because I can’t see the messages on the screen I resort to using GDB. By using GDB I was able to dump memory of __log_buf which contains the log messages that have been passed to printk function.
Looking at the log messages I was able to see the message ‘_pdev_bus: failed to claim resource 0’ , this message was printed by platform.c. After debugging through the code I found that in resource.c in the __request_resource loop the if comparison failed because the ioport_resource structure the .end member was not populated with the IO_SPACE_LIMIT value, it was 0.
The reason why the IO_SPACE_LIMIT was not populated was because there were some changes in the kernel in how this value will be used in populating the ioport_resource and that is by turning on the flag CONFIG_NEED_MACH_IO. To do this I have to change the Kconfig file inside arch/arm/, I found this out by reading the code in arch/arm/include/asm/io.h where there was a line
#ifdef CONFIG_NEED_MACH_IO_H
#include <mach/io.h>
#else
#define __io(a) __typesafe_io((a) & IO_SPACE_LIMIT)
#endif
the mach/io.h that is referred inside that code is referring to the arch/arm/mach-goldfish/include/mach directory where in the io.h of that directory it contains the IO_SPACE_LIMIT value.
After changing the Kconfig and compiling it I can see that the pdev_bus was successfully registered which allows the other drivers to be registered correctly to that as the pdev_bus is the parent that will be used to attach all the different goldfish driver.
This is a very crude and 'hacky' way to make 3.4 works, there must be some other cleaner way to fix this
- It will be cool if we can add peripherals into the emulator by creating drivers for it, or we can simulate the hardware in Qemu