int machine_kexec_prepare(struct kimage *image) { #ifdef CONFIG_KEXEC_HARDBOOT struct kexec_segment *current_segment; __be32 header; int i, err; /* No segment at default ATAGs address. try to locate * a dtb using magic */ for (i = 0; i < image->nr_segments; i++) { current_segment = &image->segment[i]; err = memblock_is_region_memory(current_segment->mem, current_segment->memsz); if (!err) return - EINVAL; if(current_segment->mem == image->start) mem_text_write_kernel_word(&kexec_kernel_len, current_segment->memsz); err = get_user(header, (__be32*)current_segment->buf); if (err) return err; if (be32_to_cpu(header) == OF_DT_HEADER) { mem_text_write_kernel_word(&kexec_boot_atags, current_segment->mem); mem_text_write_kernel_word(&kexec_boot_atags_len, current_segment->memsz); } } #endif return 0; }
inline void arm_write_hook ( void *target, char *code ) { unsigned long *target_arm = (unsigned long *)target; unsigned long *code_arm = (unsigned long *)code; mem_text_write_kernel_word(target_arm, *code_arm); mem_text_write_kernel_word(target_arm + 1, *(code_arm + 1)); mem_text_write_kernel_word(target_arm + 2, *(code_arm + 2)); }
inline void arm_write_hook ( void *target, char *code ) { unsigned long *target_arm = (unsigned long *)target; unsigned long *code_arm = (unsigned long *)code; // We should have something more generalized here, but we'll // get away with it since the ARM hook is always 12 bytes mem_text_write_kernel_word(target_arm, *code_arm); mem_text_write_kernel_word(target_arm + 1, *(code_arm + 1)); mem_text_write_kernel_word(target_arm + 2, *(code_arm + 2)); }
void machine_kexec(struct kimage *image) { unsigned long page_list; unsigned long reboot_code_buffer_phys; void *reboot_code_buffer; arch_kexec(); page_list = image->head & PAGE_MASK; /* we need both effective and real address here */ reboot_code_buffer_phys = page_to_pfn(image->control_code_page) << PAGE_SHIFT; reboot_code_buffer = page_address(image->control_code_page); /* Prepare parameters for reboot_code_buffer*/ #ifdef CONFIG_KEXEC_HARDBOOT mem_text_write_kernel_word(&kexec_start_address, image->start); mem_text_write_kernel_word(&kexec_indirection_page, page_list); mem_text_write_kernel_word(&kexec_mach_type, machine_arch_type); if (!kexec_boot_atags) mem_text_write_kernel_word(&kexec_boot_atags, image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET); mem_text_write_kernel_word(&kexec_hardboot, image->hardboot); #else kexec_start_address = image->start; kexec_indirection_page = page_list; kexec_mach_type = machine_arch_type; kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; #endif /* copy our kernel relocation code to the control code page */ memcpy(reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size); flush_icache_range((unsigned long) reboot_code_buffer, (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); printk(KERN_INFO "Bye!\n"); if (kexec_reinit) kexec_reinit(); #ifdef CONFIG_KEXEC_HARDBOOT /* Run any final machine-specific shutdown code. */ if (image->hardboot && kexec_hardboot_hook) kexec_hardboot_hook(); #endif soft_restart(reboot_code_buffer_phys); }
void machine_kexec(struct kimage *image) { unsigned long page_list; unsigned long reboot_code_buffer_phys; void *reboot_code_buffer; arch_kexec(); page_list = image->head & PAGE_MASK; /* we need both effective and real address here */ reboot_code_buffer_phys = page_to_pfn(image->control_code_page) << PAGE_SHIFT; reboot_code_buffer = page_address(image->control_code_page); /* Prepare parameters for reboot_code_buffer*/ mem_text_write_kernel_word(&kexec_start_address, image->start); mem_text_write_kernel_word(&kexec_indirection_page, page_list); mem_text_write_kernel_word(&kexec_mach_type, machine_arch_type); mem_text_write_kernel_word(&kexec_boot_atags, image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET); #ifdef CONFIG_KEXEC_HARDBOOT mem_text_write_kernel_word(&kexec_hardboot, image->hardboot); #endif /* copy our kernel relocation code to the control code page */ memcpy(reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size); flush_icache_range((unsigned long) reboot_code_buffer, (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); printk(KERN_INFO "Bye!\n"); if (kexec_reinit) kexec_reinit(); local_irq_disable(); local_fiq_disable(); setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/ #ifdef CONFIG_KEXEC_HARDBOOT if (image->hardboot && kexec_hardboot_hook) /* Run any final machine-specific shutdown code. */ kexec_hardboot_hook(); #endif flush_cache_all(); outer_flush_all(); outer_disable(); cpu_proc_fin(); outer_inv_all(); flush_cache_all(); __virt_to_phys(cpu_reset)(reboot_code_buffer_phys); }
inline void arm_write_hook ( void *target, char *code ) { #ifdef ARM64 u32 *target_arm = (u32 *)target; u32 *code_arm = (u32 *)code; #else unsigned long *target_arm = (unsigned long *)target; unsigned long *code_arm = (unsigned long *)code; #endif mem_text_write_kernel_word(target_arm, *code_arm); mem_text_write_kernel_word(target_arm + 1, *(code_arm + 1)); mem_text_write_kernel_word(target_arm + 2, *(code_arm + 2)); }
void machine_kexec(struct kimage *image) { unsigned long page_list; unsigned long reboot_code_buffer_phys; unsigned long reboot_entry = (unsigned long)relocate_new_kernel; unsigned long reboot_entry_phys; void *reboot_code_buffer; if (num_online_cpus() > 1) { pr_err("kexec: error: multiple CPUs still online\n"); return; } page_list = image->head & PAGE_MASK; /* we need both effective and real address here */ reboot_code_buffer_phys = page_to_pfn(image->control_code_page) << PAGE_SHIFT; reboot_code_buffer = page_address(image->control_code_page); /* Prepare parameters for reboot_code_buffer*/ mem_text_write_kernel_word(&kexec_start_address, image->start); mem_text_write_kernel_word(&kexec_indirection_page, page_list); mem_text_write_kernel_word(&kexec_mach_type, machine_arch_type); if (!kexec_boot_atags) mem_text_write_kernel_word(&kexec_boot_atags, image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET); #ifdef CONFIG_KEXEC_HARDBOOT mem_text_write_kernel_word(&kexec_hardboot, image->hardboot); #endif /* copy our kernel relocation code to the control code page */ reboot_entry = fncpy(reboot_code_buffer, reboot_entry, relocate_new_kernel_size); reboot_entry_phys = (unsigned long)reboot_entry + (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer); printk(KERN_INFO "Bye!\n"); if (kexec_reinit) kexec_reinit(); #ifdef CONFIG_KEXEC_HARDBOOT /* Run any final machine-specific shutdown code. */ if (image->hardboot && kexec_hardboot_hook) kexec_hardboot_hook(); #endif soft_restart(reboot_code_buffer_phys); }