Regarding starting point of Linux kernel - linux

I understand that main is not a starting point in Linux kernel, as kernel developers are experienced enough to customize the starting point.
Consider the following:
qemu-system-arm -M versatilepb -m 128M -kernel arch/arm/boot/uImage -initrd rootfs.img -append "root=/dev/ram rdinit=/sbin/init" -dtb "versatile-pb.dtb"
Above, I supplied the kernel image, device tree, rootfs.img as the input to the mainline kernel, so now which file in kernel is executed first. If it is an initialization file, someone would be triggering that initialization code within the kernel image. If yes, which file does that? Please advice.
Note: looking for a clear answer, i.e. exact file in arm architecture.

Entry point of Linux kernel, just like any other ELF binary, is _start. For ARM, it is defined in arch/arm/boot/bootp/init.S

Related

Difficulties on emulating AT91SAM9260 embedded Linux on qemu-system-arm virt machine

I've built a kernel and root file system for the AT91SAM9260 with the following buildroot menu selections on "Filesystem Settings":
And the kernel build settings including the at91_dt_defconfig option.
buildroot's output folders contained the following images:
rootfs.cpio rootfs.ext2 rootfs.tar zImage
I've tried to boot using qemu with the following commands:
qemu-system-arm -machine virt -kernel zImage -initrd rootfs.cpio -hda rootfs.ext2 -append "console=ttyS0,115200 root=/dev/sda" -serial stdio
Which resulted in a blank qemu screen.
What am I doing wrong? Is it a qemu operation or buildroot configuration problem?
The problem is that a kernel will only boot on a piece of Arm hardware if it is compiled for that hardware. Otherwise it will generally fail, usually by crashing before it is able to output anything useful. This is because (unlike x86 systems), every embedded Arm board and SoC is different to every other one, with different devices, devices and RAM at different addresses, and so on. The QEMU "virt" board is not an AT91SAM9260, and will not run a kernel that is built for that SoC.
You can either:
build a kernel that is intended to run on the 'virt' board, and run it
write device models and an SoC model for QEMU for the SoC you're interested in (beware that this is a large amount of work; it's about as much effort as porting the Linux kernel and writing device drivers for the hardware would be; it also requires either having or learning quite a lot about QEMU's internals)

Qemu booting raw kernel image (not ELF)

is there a way to convince qemu (qemu-system-mipsel v4.1.0, if it matters) to load a binary (non-elf) image built for (ancient) u-boot?
I tried both my uImage and vmlinux.bin, but I always get "The image is not ELF"
Full command-line is:
qemu-system-mipsel -M malta -kernel output/images/vmlinux.bin -serial stdio -drive file=output/images/rootfs.ext2,format=raw -append "rootwait root=/dev/hda" -net nic,model=pcnet -net user
Error is:
qemu-system-mipsel: could not load kernel 'output/images/vmlinux.bin': The image is not ELF
... which is absolutely true! That image (its uImage counter-part, actually) works fine on a real target (very similar to Malta, but that's beyond point; a failing kernel would be a completely different problem) using (in u-boot) something like:
usb reset; fatload usb 0 85000000 uImage; fatload usb 0 86000000 initram.cpio.xz; setenv bootargs rd_start=0x86000000 rd_size=15000000 USE=usb; bootm 85000000
As said: my problem is qemu doesn't even try to load the image, not that it fails at run-time.
What is the right spell to use?
You may have to use the -bios flag to provide the U-boot image and then set up the environment yourself to do the hand-off to the kernel. From my understanding, QEMU requires ELF-formatted images to be provided to the -kernel flag, presumably (heavy emphasis on this word) because the data contained in the ELF headers is necessary to configure the environment in lieu of a true bootloader (since you're effectively bypassing that boot stage and jumping straight to kernel execution). -bios does not have these requirements, as you're probably not going to see a first-stage binary using ELF headers.
If you know the entry point to the kernel image, which it seems like you do based off of that uboot command, you could use the -bios flag in conjunction with the -device loader,addr=[entry point],cpu-num=0. However, if there's any MMU, TLB, or other arch-specific addressing going on in your hardware, you might run into problems with that.
Take all of this with a dose of a skepticism, as I'm only working off of knowledge I've acquired by doing something similar to you. There may be a better way of doing it.
You have to build U-Boot for QEMU MIPS and pass it as kernel to qemu-system-mips.
You can use QEMU tftp parameter to make the directory holding the uImage available to U-Boot.
Use U-Boot's tftp command to load the kernel image and the bootm command to start the kernel.

QEMU Showing Black Screen Only

I compiled my custom kernel with different configs and images like u,zImages. But when I try to run qemu with my image, qemu showing only black screen.
Also I looked at this post but it didn't help me.
EDIT
I just tried to compile kernel with these commands.
make ARCH=arm distclean
make ARCH=arm integrator_defconfig
make ARCH=arm menuconfig
NOTE: I used default menuconfig.
make ARCH=arm CROSS_COMPILE=arm-none-eabi- zImage
qemu-system-arm -M integratorcp -kernel arch/arm/boot/zImage
And last i tried this command;
qemu-system-arm -M integratorcp -kernel arch/arm/boot/zImage -append 'console=ttyAMA0 earlyprintk=ttyAMA0' -serial stdio
NOTE: when i try to use -dtb, qemu giving to me "Unable to copy device tree in memory." error.
"QEMU does nothing with a black screen" almost always means "QEMU is running fine, but the guest code crashed or stopped early in the boot process without sending any output". Almost certainly either your kernel is misconfigured, or your QEMU command line is wrong. You don't give enough information to say which. You need to tell us at least:
what the kernel is you're running and what machine you've configured it for
what the QEMU command line you're using is
Given your updated question with a command line, some suggestions:
tell your guest to use the serial port (use the QEMU option -append 'console=ttyAMA0' to set the guest kernel command line)
either check the serial output view in the GUI, or send it to stdout with -nographic or -serial stdio
enable any earlyprintk or earlycon options in the guest config that you can and on the guest command line, so if the guest fails early you have more chance to catch it
pass the device tree for the kernel with -dtb integratorcp.dtb (use the one from your kernel tree; you'll probably have to tell the kernel makefiles to build it for you)
PS: integratorcp is an absolutely ancient development board -- why do you want to use it?

How to debug Linux kernel modules with QEMU?

I am working on academic project that modifies some Kernel Networking code as well as include a new Kernel module.
I am using QEMU to load modified kernel and test.
However, i find that a complete OS is required in some .img to debug.
Is it possible without it ?
Or, which is the distro that can be used with Kernel 2.6 for system. The distro need not have any features, except ability to run programs, including networking support.
The easiest way in my opinion is to use buildroot
http://buildroot.uclibc.org/
clone it, configure it to use your custom kernel (default userspace is fine for a start, you might want to change it later).
it will build your kernel and root filesystem. the entire process takes about half an hour, twenty minutes of which is compiling the monster
my run line looks something:
qemu-system-i386
-hda rootfs.ext2
-kernel bzImage
-m 512M
-append "root=/dev/sda console=ttyS0"
-localtime
-serial stdio
and some more options regarding a tap device
Minimal fully automated QEMU + GDB + Buildroot example
QEMU + GDB on non-module Linux kernel is covered in detail at: How to debug the Linux kernel with GDB and QEMU? and building the kernel modules inside QEMU at: How to add Linux driver as a Buildroot package Get those working first.
Next, I have also fully automated GDB module debugging at: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/1c29163c3919d4168d5d34852d804fd3eeb3ba67#kernel-module-debugging
These are the main steps you have to take:
Compile the kernel module with debug symbols:
ccflags-y += -g -DDEBUG
as mentioned at: kernel module no debugging symbols found
Stop GDB with Ctrl + C and run:
lx-symbols path/to/parent/of/modules/
This amazing command, which is defined in a GDB Python script inside the Linux kernel source tree, automatically loads symbols for loaded modules present under the given directory recursively whenever GDB stops.
The best way to make that command available is to use:
gdb -ex add-auto-load-safe-path /full/path/to/linux/kernel
as explained at: GDB: lx-symbols undefined command
insmod the kernel module.
This must be done before setting breakpoints, because we don't know where the kernel will insert the module in memory beforehand.
lx-symbols automatically takes care of finding the module location (in host filesystem and guest memory!) for us.
Break GDB again with Ctrl + C, set breakpoints, and enjoy.
If were feeling hardcore, you could also drop lx-symbols entirely, and find the module location after insmod with:
cat /proc/modules
and then add the .ko manually with:
add-symbol-file path/to/mymodule.ko 0xfffffffa00000000

Compiling a kernel - no bzImage/vmlinuz produced

I'm trying to compile a kernel (altered version of 2.6.32.9, found here https://github.com/rabeeh/linux-2.6.32.9). I am doing the compilation on a emulated ARM system (qemu) (yes, I should probably cross-compile, but that's a different topic) running Ubuntu Core (https://wiki.ubuntu.com/Core) and the kernel (vmlinuz) from Ubuntu 11.04 (downloaded from http://ports.ubuntu.com/ubuntu-ports/dists/natty/main/installer-armel/current/images/versatile/netboot/vmlinuz).
After running make bzImage, I look in the arch/arm/boot folder, and find only a file called zImage. I tried using this zImage instead of the vmlinuz I downloaded from ubuntu.com in qemu, but that doesn't work, just shows a black screen. I guess zImage is not the same as bzImage, which is what I think vmlinuz (judging from different articles on the internet) is.
So, a few questions:
Why doesn't make bzImage produce a bzImage/vmlinuz?
Can I convert a vmlinux to a vmlinuz using for example mkimage (there are lots of guides on the opposite...)?
Thanks
The bzImage filename and make target was originally x86-specific (big zImage). Many of the bootloaders on architectures that are not equal to baremetal-x86 (SPARC, PPC, IA64, etc. and also Xen on *) directly take vmlinux (or one of its compressed forms, for example vmlinux.gz, aka zImage). I guess some maintainers just added bzImage as a make target name because they wanted to have the x86 madness on their arch as well.
I get the result you describe by asking qemu to emulate a different cpu than arm926ej-s. But booting versatilepb with the default cpu works. I've cross-compiled my kernel, and I compiled all the drivers into it (so I don't use initrd).
Just download 100MB arm-eabi toolchain from http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/ (it's free but they want your email, like the x86 Intel compiler). It has an installer, just say "next" until it's done, like on Windows. Then add the bin directory to your path:
export PATH=~/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin/:$PATH
Then go back to your kernel source dir and do
make ARCH=arm CROSS_COMPILE=arm-none-eabi- menuconfig
make ARCH=arm CROSS_COMPILE=arm-none-eabi- zImage modules
You can do
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- INSTALL_MOD_PATH=path_to_arm_root modules_install
if you can reach your ARM filesystem from the host. If you're using NFS root it's trivial, but if you're using a disk image you need to either:
use a raw disk image and kpartx (depends on your host kernel having dm-multipath) or
qemu-nbd which supports qcow (and depends on host kernel having network block device support)
To boot in qemu with disk you need the right drivers (SYM53C8XX SCSI). The versatile defconfig doesn't select those.

Resources