| mpc85xx kexec howto |
| ------------------- |
| |
| Matthew McClintock <msm@freescale.com> |
| Last Updated: 2010-07-20 |
| |
| There is some terminology that will be useful which will be described here. |
| |
| boot kernel - the first one that you start, from u-boot for instance |
| kexec kernel - the kernel that you reboot into when running "kexec -e" |
| kdump kernel - the kernel that you reboot into after the boot kernel crash |
| relocatable kernel - kernel that can boot from a 256MB alignment of physical |
| memory (for mpc85xx systems at least) |
| |
| Each of the above types of kernels have specific requirements, they can |
| all be different kernels or all the same kernel depending on your |
| particular requirements. |
| |
| 1) Build kernel for kexec (i.e. running kexec -e to reboot) |
| |
| This case is the simplest. You need to enable CONFIG_KEXEC for kexec for the |
| "boot kernel", the kexec kernel can be a any kernel that already boots on your |
| platform. However, if you want to be able run kexec again after rebooting once |
| you will need to have CONFIG_KEXEC enabled for the kexec kernel as well. |
| |
| 2) Build for kdump (i.e. for rebooting when your main kernel crashes) |
| |
| In this situation, you need to be aware that the kdump kernel will boot from |
| a different physical address than your boot kernel (or even the kexec kernel). |
| There are two approaches to this. First, you can build a relocatable kernel |
| which will boot from a different physical address with no changes. This method |
| is ideal as it would even allow your boot kernel and kdump kernel to be the |
| same one. Optionally, you can build a kernel with custom physical address and |
| kernel base address according to where you will load the kdump kernel*, but |
| it's much easier to just use a relocatable kernel and let things work |
| themselves out at run time. |
| |
| You will need to enable CONFIG_CRASH_DUMP on the boot kernel. You can chose to |
| enable CONFIG_RELOCATABLE for the kdump kernel, and you will still want to |
| verify that CONFIG_KERNEL_START and CONFIG_PHYSICAL_START have sane defaults. |
| Most likely, you can leave these as 0xC0000000 and 0x0000000 respectively. |
| Finally, on the kdump kernel you will want to make sure CONFIG_PROC_VMCORE is |
| enabled as well so the core dump is exported via /proc/vmcore. You can just |
| enable all these options on the boot and kdump and use the same kernel for both |
| which is the simplest option. |
| |
| Summary of 1 & 2: |
| |
| Just enable kexec, crash support, and relocatable kernel and you should be good |
| to go for all of the above scenarios using the same kernel. |
| |
| 3) Obtaining a device tree |
| |
| You best bet for getting a working device tree is to pull the one the current |
| kernel is using. The easiest way to do this is use the device tree compiler |
| to create one from the proc file system |
| |
| $ dtc -I fs -O dtb /proc/device-tree/ > flat-device-tree |
| |
| Kexec should be able to take this flat device tree, and modifiy it/update it |
| as needed for your particular scenario. It will update memreserve regions, add |
| initrd/ramdisks, fixup the command line, etc. |
| |
| NOTE: If no device tree is given, kexec will do the above on it's own to |
| obtain a useable device tree. You can specify the device tree to use |
| with the --dtb=<flat_device_tree_blob> kexec argument. |
| |
| 4) Kexec'ing a new kernel |
| |
| If you have followed the procedure above you need to do the following to reboot |
| into a new kexec kernel. |
| |
| $ kexec -l {uImage,vmlinux} |
| $ kexec -e |
| |
| These options will boot the new kernel, you should see some message as shown |
| below. NOTE: The old command line is used, so if you are booting from an NFS |
| mount it should work fine, however it you are using an initrd/ramdisk there are |
| caveats to consider (see #6 below). |
| |
| sd 2:0:0:0: [sda] Synchronizing SCSI cache |
| Starting new kernel |
| Bye! |
| Reserving 256MB of memory at 512MB for crashkernel (System RAM: 4096MB) |
| Using MPC8572 DS machine description |
| [snip] |
| |
| 5) Setting for a kdump kernel |
| |
| For the boot kernel, you need to reserve a region of memory for the kdump kernel |
| to use when the system crashes. This region is removed for use from the boot |
| kernel and when the system crashes the kdump kernel will operate out of this |
| region exclusively. For mpc85xx, we need to pick a region aligned at 256MB if we |
| are using a relocatable kernel, other than that the size allocated needs to leave |
| enough memory for your kdump environment to function properly as well as store |
| the kdump kernel and any other items added (this would most likely be a ramdisk). |
| Some valid options are: |
| |
| crashkernel={128M,256M,512M}@{256M,512M} and others |
| |
| For the example below we choose 256MB (0x10000000) of memory located at offset |
| 512MB (0x20000000). The command line option would look like this. |
| |
| crashkernel=256M@512M |
| |
| You can see the values the kernel parsed by running looking |
| at your proc entries. In this case, the physical address is a 64bit value. |
| |
| $ hexdump -C /proc/device-tree/chosen/linux,crashkernel-base |
| 00000000 00 00 00 00 20 00 00 00 |.... ...| |
| 00000008 |
| $ hexdump -C /proc/device-tree/chosen/linux,crashkernel-size |
| 00000000 00 00 00 00 10 00 00 00 |........| |
| 00000008 |
| |
| Kdump kernels are only run when the current kernel crashes, there you can not |
| just restart your system. However, you can still trigger a crash for testing |
| purposes by enabling CONFIG_MAGIC_SYSRQ and executing the following. |
| |
| $ echo c > /proc/sysrq-trigger |
| |
| However, before this we need to setup our kdump kernel as shown below. |
| |
| $ kexec -p {uImage.reloc, vmlinux} |
| |
| The kernel we pass in is a relocatable kernel, in the case of vmlinux no changes |
| are required since there is no wrapper specifically assigning it to a certain |
| address. However, kexec will attempt to honor the addresses given to mkimage |
| when you created your uImage, therefore you need to create a uImage with the |
| appropriate load and entry address |
| |
| $ mkimage -A ppc -O linux -T kernel -C gzip -a 0x20000000 -e 0x20000000 |
| -n Linux-2.6.35-rc3 |
| Image Name: Linux-2.6.35-rc3-00246-gd666cd8- |
| Created: Wed Jul 14 17:34:19 2010 |
| Image Type: PowerPC Linux Kernel Image (gzip compressed) |
| Data Size: 3261979 Bytes = 3185.53 kB = 3.11 MB |
| Load Address: 0x20000000 |
| Entry Point: 0x20000000 |
| |
| You do not sctrictly need to use a RELOCATABLE kernel, you can build a kernel |
| that can execute from this load address and entry point and it would your |
| kdump kernel would still function properly. |
| |
| The above load address aligns with the crashkernel argument we passed |
| in via the command line. It is important to make sure these addresses match |
| each other when using uImage. It's less important for vmlinux since kexec will |
| attempt to load it at the first available region which should match correctly. |
| |
| 6) Misc. options to kexec |
| |
| There are a few options you can pass into kexec to modify it's behaviour. First, |
| if you want to reuse your current initrd/ramdisk you can use the following. |
| You will also need to add "retain_initrd" to the boot kernel command line for |
| this option to work. So now your command line would look something like this. |
| |
| crashkernel=256M@512M retain_initrd |
| |
| NOTE: If you are setting up a kdump kernel, you will need to make sure your |
| original initrd/ramdisk resides in the memory range reserved for the kdump |
| kernel, otherwise the kdump kernel won't be able to access it. For example |
| it needs to live within the 512MB-768M range in this case. A warning will |
| be displayed if this is not the case. |
| |
| $ kexec -p uImage.reloc --reuseinitrd |
| |
| It's even easier to specify a new ramdisk and you don't need to modify your |
| boot kernel command line. You also might need to update your command line to |
| boot with your new ramdisk, you can do it via the --command-line option as well |
| as add any other changes you want to the command line as well. |
| |
| $ kexec -p uImage.reloc --ramdisk=rootfs.ext2.gz |
| --command-line="root=/dev/ram rw console=ttyS0,115200" |
| |
| or the following if you wanted kexec and add "retain_initrd" to the command |
| line and boot with a ramdisk |
| |
| $ kexec -l uImage --ramdisk=rootfs.ext2.gz |
| --command-line="`cat /proc/cmdline` retain_initrd" |
| $ kexec -e |
| |
| 7) After a crash |
| |
| If you have a kdump kernel loaded and your system crashes you can now debug |
| the crash. |
| |
| $ gdb vmlinux /proc/vmcore |
| |
| You might need to copy these files elsewhere or setup your ramdisk to do these |
| things automatically. |