arch/loongarch/kernel/machine_kexec.c

Source file repositories/reference/linux-study-clean/arch/loongarch/kernel/machine_kexec.c

File Facts

System
Linux kernel
Corpus path
arch/loongarch/kernel/machine_kexec.c
Extension
.c
Size
7418 bytes
Lines
296
Domain
Architecture Layer
Bucket
arch/loongarch
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
				if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
					kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
				break;
			}
		}

		if (!kimage->arch.cmdline_ptr) {
			pr_err("Command line not included in the provided image\n");
			return -EINVAL;
		}
	}

	/* kexec/kdump need a safe page to save reboot_code_buffer */
	kimage->control_code_page = virt_to_page((void *)KEXEC_CONTROL_CODE);

	reboot_code_buffer = (unsigned long)page_address(kimage->control_code_page);
	memcpy((void *)reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size);

#ifdef CONFIG_SMP
	/* All secondary cpus now may jump to kexec_smp_wait cycle */
	relocated_kexec_smp_wait = reboot_code_buffer + (void *)(kexec_smp_wait - relocate_new_kernel);
#endif

	return 0;
}

void machine_kexec_cleanup(struct kimage *kimage)
{
}

void kexec_reboot(void)
{
	do_kexec_t do_kexec = NULL;

	/*
	 * We know we were online, and there will be no incoming IPIs at
	 * this point. Mark online again before rebooting so that the crash
	 * analysis tool will see us correctly.
	 */
	set_cpu_online(smp_processor_id(), true);

	/* Ensure remote CPUs observe that we're online before rebooting. */
	smp_mb__after_atomic();

	/*
	 * Make sure we get correct instructions written by the
	 * machine_kexec_prepare() CPU.
	 */
	__asm__ __volatile__ ("\tibar 0\n"::);

#ifdef CONFIG_SMP
	/* All secondary cpus go to kexec_smp_wait */
	if (smp_processor_id() > 0) {
		relocated_kexec_smp_wait(NULL);
		BUG();
	}
#endif

	do_kexec = (void *)reboot_code_buffer;
	do_kexec(efi_boot, cmdline_ptr, systable_ptr, start_addr, first_ind_entry);

	BUG();
}


#ifdef CONFIG_SMP
static void kexec_shutdown_secondary(void *regs)
{
	int cpu = smp_processor_id();

	if (!cpu_online(cpu))
		return;

	/* We won't be sent IPIs any more. */
	set_cpu_online(cpu, false);

	local_irq_disable();
	while (!atomic_read(&kexec_ready_to_reboot))
		cpu_relax();

	kexec_reboot();
}

static void crash_shutdown_secondary(void *passed_regs)
{
	int cpu = smp_processor_id();
	struct pt_regs *regs = passed_regs;

	/*

Annotation

Implementation Notes