Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/arm/kernel/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  machine_kexec.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * machine_kexec.c - handle transition of Linux booting another kernel
 */


#include <linux/mm.h>
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/memblock.h>
#include <linux/of_fdt.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
#include <asm/kexec-internal.h>
#include <asm/fncpy.h>
#include <asm/mach-types.h>
#include <asm/smp_plat.h>
#include <asm/system_misc.h>
#include <asm/set_memory.h>

extern void relocate_new_kernel(void);
extern const unsigned int relocate_new_kernel_size;

static atomic_t waiting_for_crash_ipi;

/*
 * Provide a dummy crash_notes definition while crash dump arrives to arm.
 * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
 */


int machine_kexec_prepare(struct kimage *image)
{
 struct kexec_segment *current_segment;
 __be32 header;
 int i, err;

 image->arch.kernel_r2 = image->start - KEXEC_ARM_ZIMAGE_OFFSET
         + KEXEC_ARM_ATAGS_OFFSET;

 /*
 * Validate that if the current HW supports SMP, then the SW supports
 * and implements CPU hotplug for the current HW. If not, we won't be
 * able to kexec reliably, so fail the prepare operation.
 */

 if (num_possible_cpus() > 1 && platform_can_secondary_boot() &&
     !platform_can_cpu_hotplug())
  return -EINVAL;

 /*
 * 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];

  if (!memblock_is_region_memory(idmap_to_phys(current_segment->mem),
            current_segment->memsz))
   return -EINVAL;

  err = get_user(header, (__be32*)current_segment->buf);
  if (err)
   return err;

  if (header == cpu_to_be32(OF_DT_HEADER))
   image->arch.kernel_r2 = current_segment->mem;
 }
 return 0;
}

void machine_kexec_cleanup(struct kimage *image)
{
}

static void machine_crash_nonpanic_core(void *unused)
{
 struct pt_regs regs;

 local_fiq_disable();

 crash_setup_regs(®s, get_irq_regs());
 printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
        smp_processor_id());
 crash_save_cpu(®s, smp_processor_id());
 flush_cache_all();

 set_cpu_online(smp_processor_id(), false);
 atomic_dec(&waiting_for_crash_ipi);

 while (1) {
  cpu_relax();
  wfe();
 }
}

static DEFINE_PER_CPU(call_single_data_t, cpu_stop_csd) =
 CSD_INIT(machine_crash_nonpanic_core, NULL);

void crash_smp_send_stop(void)
{
 static int cpus_stopped;
 unsigned long msecs;
 call_single_data_t *csd;
 int cpu, this_cpu = raw_smp_processor_id();

 if (cpus_stopped)
  return;

 atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
 for_each_online_cpu(cpu) {
  if (cpu == this_cpu)
   continue;

  csd = &per_cpu(cpu_stop_csd, cpu);
  smp_call_function_single_async(cpu, csd);
 }

 msecs = 1000; /* Wait at most a second for the other cpus to stop */
 while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
  mdelay(1);
  msecs--;
 }
 if (atomic_read(&waiting_for_crash_ipi) > 0)
  pr_warn("Non-crashing CPUs did not react to IPI\n");

 cpus_stopped = 1;
}

void machine_crash_shutdown(struct pt_regs *regs)
{
 local_irq_disable();
 crash_smp_send_stop();

 crash_save_cpu(regs, smp_processor_id());
 machine_kexec_mask_interrupts();

 pr_info("Loading crashdump kernel...\n");
}

void machine_kexec(struct kimage *image)
{
 unsigned long page_list, reboot_entry_phys;
 struct kexec_relocate_data *data;
 void (*reboot_entry)(void);
 void *reboot_code_buffer;

 /*
 * This can only happen if machine_shutdown() failed to disable some
 * CPU, and that can only happen if the checks in
 * machine_kexec_prepare() were not correct. If this fails, we can't
 * reliably kexec anyway, so BUG_ON is appropriate.
 */

 BUG_ON(num_online_cpus() > 1);

 page_list = image->head & PAGE_MASK;

 reboot_code_buffer = page_address(image->control_code_page);

 /* copy our kernel relocation code to the control code page */
 reboot_entry = fncpy(reboot_code_buffer,
        &relocate_new_kernel,
        relocate_new_kernel_size);

 data = reboot_code_buffer + relocate_new_kernel_size;
 data->kexec_start_address = image->start;
 data->kexec_indirection_page = page_list;
 data->kexec_mach_type = machine_arch_type;
 data->kexec_r2 = image->arch.kernel_r2;

 /* get the identity mapping physical address for the reboot code */
 reboot_entry_phys = virt_to_idmap(reboot_entry);

 pr_info("Bye!\n");

 soft_restart(reboot_entry_phys);
}

Messung V0.5
C=96 H=64 G=81

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.