booting linux on physical cpu 0x0
How to kick your computer’s Linux kernel on boot up to a new (or already existing) kernel.
You probably know by now that Linux is the OS that every other operating system is based on. In fact, you probably even know that Linux is a kernel itself, or at least the kernel you get from the kernel. In fact, you probably even know that there are hundreds of kernels, all of which are based on Linux, so if you’re wondering, you can probably start there.
But before we do, we need to take a look at boot. You might be wondering what the heck is boot. Boot is a process that gets started by the operating system on your computer to get your computer up and running. The kernel on your computer is the base for the OS on your computer. The kernel is the base for all the OSes you use and everything else that follows.
Boot is a process, which gets started by the OS on the computer to get your computer up and running, then continues on. It’s a matter of getting the OS installed on your computer and getting it up and running after the OS is installed. This process is called boot. It’s a process that gets your computer running when you boot on your computer, and then it gets started again at boot.
In most cases, linux is installed on your computer. Its a distribution of Linux that is installed onto your computer’s hard drive, and everything is a part of the OS. The kernel is the base for all the OSes you use and everything else that follows.
The kernel is the part of your computer that runs the OS, the system tools, and the drivers that go along with it. As the OS is built, a kernel is built that runs the OS and everything follows. With a new hard drive, it takes a lot of time to build the kernel, and you need to know what you are doing in order to do it so it can be done in a way that you understand.
It’s not all that hard to boot a new kernel on a new hard drive, if you just know what you are doing, but it is to be careful with the rest of the instructions. There are several reasons for these, but the most important one is that it will fail if your hard drive fails.
The reason why the linux loader is very important and difficult to get right is because the kernel starts off running in read-only mode. This means that there are no writes to the memory. To fix this, you need a way to make the new hard drive writeable. This can be done easily by a bootloader, but this is not what the linux loader is for. It is for the kernel itself, which is why it is called a bootloader.
The linux loader is just the kernel that runs when you boot the linux distro. The linux kernel is a program that runs and runs and runs. It is the kernel that takes the system and adds the functionality of another program into it. The linux kernel uses a bunch of system calls to do some very cool stuff.
And of course the linux kernel provides loads of other functionality too, but let’s focus on the kernel part for now. It is the part that takes the system and adds the functionality of another program into it. We can think of the linux kernel as the part of the computer that is the most important, so it is our goal to make it the most important part of the system.
Problems in linux kernel porting, stuck in paging_init function
Above logs are from a working sabresd board. My source are taken from nxp’s android O source. I am porting android on our custom board, that is similar to sabresd and based on imx6q . My ported kernel is stuck. Here are the logs,
Uncompressing Linux. done, booting the kernel. [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 4.9.17 (mrigendra.chaubey@CPU-384U) (gcc version 4.9.x 20150123 (prerelease) (GCC) ) #23 SMP PREEMPT Sat Jul 7 23:29:19 IST 2018 [ 0.000000] CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c53c7d [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache [ 0.000000] OF: fdt:Machine model: Freescale i.MX6 MYSABRE Board [ 0.000000] bootconsole [earlycon0] enabled [ 0.000000] cma: early_cma(448M) [ 0.000000] cma: dma_contiguous_reserve(limit ffffffff) [ 0.000000] cma: dma_contiguous_reserve: reserving 448 MiB for global area [ 0.000000] cma: cma_declare_contiguous(size 0x1c000000, base 0x00000000, limit 0x50000000 alignment 0x00000000) [ 0.000000] cma: Reserved 448 MiB at 0x2a000000 [ 0.000000] Memory policy: Data cache writealloc [ 0.000000] ##DEBUGmmu.c: build_mem_type_table done [ 0.000000] ##DEBUGmmu.c: build_mem_type_table done [ 0.000000] ##DEBUGmmu.c: prepare_page_table done [ 0.000000] ##DEBUGmmu.c: map_lowmem done [ 0.000000] ##DEBUGmmu.c: memblock_set_current_limit done [ 0.000000] ##DEBUGdna-mapping.c: dma_contiguous_remap1 [ 0.000000] ##DEBUGdna-mapping.c: dma_contiguous_remap2 [ 0.000000] ##DEBUGsmb_tlb.c: flush_tlb_kernel_range1 [ 0.000000] ##DEBUGsmb_tlb.c: start: da000000 end: f6000000
Both boards are configured for vmsplit_3g. My setup_arch call is not completed due to some issue that I am not able to find, this is the call flow
start_kernel > setup_arch > paging_init > dma_contiguous_remap > flush_kernel_tlb_range > local_flush_tlb_range
local_flush_tlb_kernel_range(start, end);
the start and end I printed just above local_flush_tlb_kernel_range(start, end) call in function flush_tlb_kernel_range. In my case and in nxp sabre case this is local_flush_tlb_kernel_range becomes
struct cpu_tlb_fns < void (*flush_user_range)(unsigned long, unsigned long, struct vm_area_struct *); void (*flush_kern_range)(unsigned long, unsigned long); unsigned long tlb_flags; >; /* * Select the calling method */ #ifdef MULTI_TLB #define __cpu_flush_user_tlb_range cpu_tlb.flush_user_range #define __cpu_flush_kern_tlb_range cpu_tlb.flush_kern_range #else xx #define __cpu_flush_user_tlb_range __glue(_TLB,_flush_user_tlb_range) #define __cpu_flush_kern_tlb_range __glue(_TLB,_flush_kern_tlb_range) extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *); extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
- I have this idea that setup_arch have nothing to do with my board specific functions and its a generic call to all arm architectures.
- I tried to put sabresd dtb in uboot, so that if something related to memory is done inside it, atleast that much initialisation will happen, same result as this.
- Tried to put pr_info until I could not find defenition of the function flush_kern_range. In nxp sabre this function is called again and again.
Can anyone help me with some of the points.
U-Bboot won’t autoboot but manual boot works fine
I’ve built an image for a Freescale iMX6 EVK board (ARM based), using Buildroot. It booted fine off an SD card, and I wanted to experiment with customized boot commands in U-Boot. I want to make the boot sequence as lean and fast as possible, so I streamlined some of the checks and tests done by U-Boot (e.g. removed the check for a boot script and network boot). Here’s my bootcmd U-Boot env variable (formatted for easy reading):
bootcmd= echo Booting from SD. ; mmc dev $; if mmc rescan; then setenv mmcroot /dev/mmcblk1p2 rootwait ro; setenv bootargs console=$,$ root=$; fatload mmc $:$ $ $; setenv fdt_file imx6ull-14x14-evk.dtb; fatload mmc $:$ $ $; bootz $ - $; else echo Boot FAILED: Couldnt find kernel or dtb; fi
Hit any key to stop autoboot: 0 Booting from SD. switch to partitions #0, OK mmc1 is current device reading zImage 4652504 bytes read in 369 ms (12 MiB/s) reading imx6ull-14x14-evk.dtb 33755 bytes read in 30 ms (1.1 MiB/s) Kernel image @ 0x80800000 [ 0x000000 - 0x46fdd8 ] ## Flattened Device Tree blob at 83000000 Booting using the fdt blob at 0x83000000 Using Device Tree in place at 83000000, end 8300b3da Starting kernel .
It then hangs at the «Starting kernel . » stage. HOWEVER, if I interrupt U-Boot by pressing enter, then (from the U-Boot prompt) run either of these commands:
It shows the exact same messages as above, but then the kernel starts OK. I’ve compared the outputs in both cases and they are identical up to «Starting kernel». I also added a line to bootcmd to print out the env variables ( printenv ), and confirmed that the variables are also identical in both cases. Here are the final bootargs (printed with echo $ ) — these too are the same in both cases:
console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait ro
I thought the boot command just executed bootcmd, and that the autoboot process did the same thing if not interrupted. So why does it work if I interrupt it and run boot manually? ==== EDIT ==== Following comments from sawdust, I did some more experiments to clarify the problem. 1/ Added ‘earlyprintk’ to kernel build (Kernel hacking options). This caused the following to be printed on a SUCCESSFUL boot:
Starting kernel . Uncompressing Linux. done, booting the kernel. Booting Linux on physical CPU 0x0
On a FAILED boot, it still stops at «Starting kernel . » (no additional information from earlyprintk). 2/ Further hacking of bootcmd to clarify the problem. Here’s the default «bootcmd» env variable, created by a fresh build (Nb: Normally this is all on one line, i.e. «bootcmd=. «; formatted here for clarity):
run findfdt; mmc dev $; mmc dev $; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else run netboot; fi
run findfdt; mmc dev $; mmc dev $; mmc rescan; if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi;
All I did was remove the outer ‘if’ structure (if mmc rescan; then. ). It still calls «mmc rescan», which succeeds. Note this is saved by putting the above on one line (‘xxxx’), and using:
setenv bootcmd 'xxxxx' saveenv
This causes the board to hang at «Starting kernel . «, but if I interrupt the auto boot, enter the u-boot prompt then use «boot», it boots fine. I can change back to the original bootcmd and it works correctly (autoboot is OK) so I think the method for changing the variable is OK. I saw one weird thing at one point when I changed it over to my version:
Starting kernel . resetting . [Board Rebooted itself!] U-Boot 2016.03 (Nov 16 2017 - 07:08:36 +1300) [Auto-boot] Starting kernel . [Hang.]
From then on, it was back to hanging unless I interrupt the boot and enter «boot» command. Bug in u-boot? u-boot environment variables somehow being corrupted? Nb: This is not a major issue right now, but I think we could save some ms by getting rid of the pointless search for a boot script that I know isn’t there, and in the future we might have reason to customize the boot for some other reason and I’d like to know that it it could be done predictably!