一、命令行

1. kexec -l $kpwd --append="$arg"

其中$kpwd =目标内核的路径

  $arg =传给内核的参数,与/proc/cmdline一致时表示重启现有内核

2. kexec -e  

 

二、执行过程

1. kexec-tools执行过程

kexec 的main函数解析参数,kexec -l 解析为调用my_load函数。

my_load函数根据路径参数读取内核文件到kernel_buf中,然后执行通用函数file_type[i].load,mips下对应elf_mips_load。

elf_mips_load函数主要内容是解析elf格式的kernel文件,并将所有信息存放在info中,主要是对elf文件的ELF header, Program header table进行解析:

1) build_elf_exec_info(buf, len, &ehdr, 0) 根据header到解析elf文件到ehdr中;

2) elf_exec_load(&ehdr, info) 解析各段内容到info中,具体实现为调用add_segment()函数,与此同时给出了kernel的入口地址。

3) cmdline_buf中存放的是传给内核的参数,也需要用add_buffer添加进info内。

4) 删除源码中的device tree部分。

将kernel文件解析到info中之后,回到my_load函数进行一些检验等操作,然后调用kexec_load(info.entry,info.nr_segments, info.segment,info.kexec_flags),进行系统调用:syscall(__NR_kexec_load, entry, nr_segments, segments, flags)

 

2. kexec_load系统调用执行过程

内核在syscall_table.S,syscalls.h等内注册了kexec_load系统调用,宏展开后最终调用kernel/kexec.c文件的SYSCALL_DEFINE4(kexec_load...)函数。该函数主要功能就是把新的内核文件装入内存中。

kimage_alloc_init初始化内存分配,主要初始化入口信息,并使用copy_from_user函数把传入的内核数据拷贝到image内,然后分配一张控制页(control_code_page)。

接下来调用machine_kexec_prepare,这个函数回调之前注册过的loongson_kexec_prepare函数,该函数是对传入参数的类似bootloader的处理。

最主要的函数是kimage_load_segment,该函数把内核段打散成页,先调用alloc_pages分配一张内核页(在mips64中分配空间为0x8000 0000 0000 0000到

0xC000 0000 0000 0000共0x4000 0000 0000 0000大小的空间内),再调用kimage_add_page将该页加入到image->entry指向的内存区域,然后进行内核数据拷贝,循环直到所有页都分配完毕。

 

3. reboot执行过程

当执行kexec -e 时,进行reboot系统调用,并由kernel_kexec接管。该函数先进行重启之前例行操作,如kernel_restart_prepare, migrate_to_reboot_cpu,machine_shutdown等,最后是调用machine_kexec(kexec_image)进行kexec模式重启。

之前准备好的kernel被打散到内核内存中,这个函数将完成kernel的重定位,并且从image->start即entry开始执行。要做到这一点,该函数首先把entry的地址赋值给kexec_start_address,把存在image->head的地址赋给kexec_indirection_page,然后将一段内核重定位的汇编代码使用memcpy拷贝至control_code_page内,最后执行该函数即转入汇编执行。汇编代码以kexec_indirection_page为索引,负责将之前分配到内存的所有页面拷贝至目的内存中,最后一条跳转指令跳至kexec_start_address处执行。

posted on 2017-10-10 09:03  Ruu  阅读(1008)  评论(0编辑  收藏  举报