kernel_restart()
linux 6.6
sys_reboot函数调用栈:
作用: 重启。这在中断上下文中调用是不安全的
参数:
- cmd:指向缓冲区的指针,其中包含命令行参数,可以为NULL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void kernel_restart(char *cmd) { kernel_restart_prepare(cmd); do_kernel_restart_prepare(); migrate_to_reboot_cpu(); syscore_shutdown(); if (!cmd) pr_emerg("Restarting system\n"); else pr_emerg("Restarting system with command '%s'\n", cmd); kmsg_dump(KMSG_DUMP_SHUTDOWN); machine_restart(cmd); }
EXPORT_SYMBOL_GPL(kernel_restart);
|
kernel_restart_prepare()
linux 6.6
作用: 处理一些重启前的准备工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void kernel_restart_prepare(char *cmd) { blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); system_state = SYSTEM_RESTART; usermodehelper_disable(); device_shutdown(); }
|
do_kernel_restart_prepare()
linux 6.6
1 2 3 4 5 6
| static void do_kernel_restart_prepare(void) { blocking_notifier_call_chain(&restart_prep_handler_list, 0, NULL); }
|
migrate_to_reboot_cpu()
linux 6.6
作用:
将当前任务迁移到一个特定的CPU上运行,通常是为了解决重启或迁移操作时的CPU选择问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void migrate_to_reboot_cpu(void) { int cpu = reboot_cpu; cpu_hotplug_disable(); if (!cpu_online(cpu)) cpu = cpumask_first(cpu_online_mask); current->flags |= PF_NO_SETAFFINITY; set_cpus_allowed_ptr(current, cpumask_of(cpu)); }
|
syscore_shutdown()
作用: 执行所有注册的系统核心关机回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void syscore_shutdown(void) { struct syscore_ops *ops; mutex_lock(&syscore_ops_lock); list_for_each_entry_reverse(ops, &syscore_ops_list, node) if (ops->shutdown) { if (initcall_debug) pr_info("PM: Calling %pS\n", ops->shutdown); ops->shutdown(); } mutex_lock(&syscore_ops_lock); }
|
machine_restart()
作用: 执行实际的重启操作
1 2 3
| void machine_restart(char *cmd) { machine_ops.restart(cmd); }
|
native_machine_restart()
作用: 执行系统的重启操作
1 2 3 4 5 6 7 8 9 10 11
| void native_machine_restart(char *__unused) { pr_notice("machine restart\n"); if (!reboot_force) machine_shutdown(); __machine_emergency_restart(0); }
|
machine_shutdown()
作用: 执行具体的关机操作
1 2 3 4
| void machine_shutdown(void) { machine_ops.shutdown(); }
|
native_machine_shutdown()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| void native_machine_shutdown(void) { #ifdef CONFIG_X86_IO_APIC clear_IO_APIC(); #endif
#ifdef CONFIG_SMP local_irq_disable(); stop_other_cpus(); #endif lapic_shutdown(); restore_boot_irq_mode(); #ifdef CONFIG_HPET_TIMER hpet_disable(); #endif #ifdef CONFIG_X86_64 x86_platform.iommu_shutdown(); #endif }
|
__machine_emergency_restart()
1 2 3 4 5 6
| static reboot_emergency; static void __machine_emergency_restart(int emergency) { reboot_emergency = emergency; machine_ops.emergency_restart(); }
|
native_machine_emergency_restart()
linux 6.6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| static void native_machine_emergency_restart(void) { int i; int attempt = 0; int orig_reboot_type = reboot_type; unsigned short mode; if (reboot_emergency) emergency_reboot_disable_virtualization(); tboot_shutdown(TB_SHUTDOWN_REBOOT); mode = reboot_mode == REBOOT_WARM ? 0X1234 : 0; *((unsigned short *)__va(0x472)) = mode; if (efi_capsule_pending(NULL)) { pr_info("EFI capsule is pending, forcing EFI reboot. \n"); reboot_type = BOOT_EFI; } for (;;) { switch (reboot_type) { case BOOT_ACPI: acpi_reboot(); reboot_type = BOOT_KBD; break; case BOOT_KBD: mach_reboot_fixups(); for (i = 0; i < 10; i++) { kb_wait(); udelay(50); outb(0xfe, 0x64); udelay(50); } if (attempt == 0 && orig_reboot_type == BOOT_ACPI) { attempt = 1; reboot_type = BOOT_ACPI; } else { reboot_type = BOOT_EFT; } break; case BOOT_EFI: efi_reboot(reboot_mode, NULL); reboot_type = BOOT_BIOS; break; case BOOT_BIOS: machine_real_restart(MBR_BIOS); reboot_type = BOOT_CF9_SAFE; break; case BOOT_CF9_FORCE: port_cf9_safe = true; fallthrough; case BOOT_CF9_SAFE: if (port_cf9_safe) { u8 reboot_code = reboot_mode == REBOOT_WARM ? 0X06 : 0x0E; u8 cf9 = inb(0xcf9) & ~reboot_code; outb(cf9|2, 0xcf9); udelay(50); outb(cf9|reboot_code, 0xcf9); udelay(50); } reboot_type = BOOT_TRIPLE; break; case BOOT_TRIPLE: idt_invalidate(); __asm__ __volatile__("int3"); reboot_type = BOOT_KBD; break; } } }
|
后续有时间再继续整理重启的各种模式