cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kexec.c (2757B)


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