Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <linux/kernel.h>
  4#include <linux/console.h>
  5#include <linux/kexec.h>
  6#include <linux/delay.h>
  7#include <linux/reboot.h>
  8
  9#include <asm/cacheflush.h>
 10#include <asm/sections.h>
 11
 12extern void relocate_new_kernel(unsigned long head,
 13				unsigned long start,
 14				unsigned long phys);
 15
 16extern const unsigned int relocate_new_kernel_size;
 17extern unsigned int kexec_initrd_start_offset;
 18extern unsigned int kexec_initrd_end_offset;
 19extern unsigned int kexec_cmdline_offset;
 20extern unsigned int kexec_free_mem_offset;
 21
 22static void kexec_show_segment_info(const struct kimage *kimage,
 23				    unsigned long n)
 24{
 25	pr_debug("    segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\n",
 26			n,
 27			kimage->segment[n].mem,
 28			kimage->segment[n].mem + kimage->segment[n].memsz,
 29			(unsigned long)kimage->segment[n].memsz,
 30			(unsigned long)kimage->segment[n].memsz /  PAGE_SIZE);
 31}
 32
 33static void kexec_image_info(const struct kimage *kimage)
 34{
 35	unsigned long i;
 36
 37	pr_debug("kexec kimage info:\n");
 38	pr_debug("  type:        %d\n", kimage->type);
 39	pr_debug("  start:       %lx\n", kimage->start);
 40	pr_debug("  head:        %lx\n", kimage->head);
 41	pr_debug("  nr_segments: %lu\n", kimage->nr_segments);
 42
 43	for (i = 0; i < kimage->nr_segments; i++)
 44		kexec_show_segment_info(kimage, i);
 45
 46#ifdef CONFIG_KEXEC_FILE
 47	if (kimage->file_mode) {
 48		pr_debug("cmdline: %.*s\n", (int)kimage->cmdline_buf_len,
 49			 kimage->cmdline_buf);
 50	}
 51#endif
 52}
 53
 54void machine_kexec_cleanup(struct kimage *kimage)
 55{
 56}
 57
 58void machine_crash_shutdown(struct pt_regs *regs)
 59{
 60}
 61
 62void machine_shutdown(void)
 63{
 64	smp_send_stop();
 65	while (num_online_cpus() > 1) {
 66		cpu_relax();
 67		mdelay(1);
 68	}
 69}
 70
 71void machine_kexec(struct kimage *image)
 72{
 73#ifdef CONFIG_64BIT
 74	Elf64_Fdesc desc;
 75#endif
 76	void (*reloc)(unsigned long head,
 77		      unsigned long start,
 78		      unsigned long phys);
 79
 80	unsigned long phys = page_to_phys(image->control_code_page);
 81	void *virt = (void *)__fix_to_virt(FIX_TEXT_KEXEC);
 82	struct kimage_arch *arch = &image->arch;
 83
 84	set_fixmap(FIX_TEXT_KEXEC, phys);
 85
 86	flush_cache_all();
 87
 88#ifdef CONFIG_64BIT
 89	reloc = (void *)&desc;
 90	desc.addr = (long long)virt;
 91#else
 92	reloc = (void *)virt;
 93#endif
 94
 95	memcpy(virt, dereference_function_descriptor(relocate_new_kernel),
 96		relocate_new_kernel_size);
 97
 98	*(unsigned long *)(virt + kexec_cmdline_offset) = arch->cmdline;
 99	*(unsigned long *)(virt + kexec_initrd_start_offset) = arch->initrd_start;
100	*(unsigned long *)(virt + kexec_initrd_end_offset) = arch->initrd_end;
101	*(unsigned long *)(virt + kexec_free_mem_offset) = PAGE0->mem_free;
102
103	flush_cache_all();
104	flush_tlb_all();
105	local_irq_disable();
106
107	reloc(image->head & PAGE_MASK, image->start, phys);
108}
109
110int machine_kexec_prepare(struct kimage *image)
111{
112	kexec_image_info(image);
113	return 0;
114}