There are many ways to reboot a PC, some methods are well documented, others are a little more obscure.
Method 1. Via the Keyboard (Embedded Controller) port.
Writing 0xfe to the keyboard (Embedded Controller) port 0x64 does the trick. This pulses the reset line to low and forces a reboot. To do so under Linux (as super user) in C do:
ioperm(0x64, 1, 1);
..make sure every filesystem is sync()'d and/or unmounted first! This can be selected in Linux with the reboot=k kernel boot parameter and reboot.
Method 2. Resetting PCI
This is more ugly and apparently works on most Intel PCI chipsets. Write 0x02 and then 0x04 to the PCI port 0xcf9, example C code as follows (again run as super user):
ioperm(0xcf9, 1, 1);
usleep(10); /* a very small delay is required, this is plenty */
Alternatively, boot Linux using the reboot=p kernel boot parameter and reboot. Note that the delay can be very small - as short as doing another port write.
Method 3. Triple faulting the CPU.
This is an Intel undocumented feature; one basically forces a triple fault and the processor just reboots. The idt is loaded with an empty descriptor pointer and an int3 (trap the debugger) instruction is executed. It's quite a brutal thing to do, but always seems to work.
Boot Linux with the reboot=t kernel boot parameter to select this mode of rebooting.
Method 4. Reboot by jumping to the BIOS (32 bit CPUs only!)
By flipping back to real mode, and jumping to 0xffff0000 using a ljmp $0xffff,$0x000 the CPU executes the BIOS reset. Who knows how the BIOS reboots, but it should work, as long as your BIOS is written correctly!
Boot Linux with the reboot=b kernel boot parameter to do this on a reboot.
Method 5. Executing a reset on the BSP or another CPU (32 bit CPUs only!)
Quite frankly, I've not figured out how this method works yet, but it can be achieved in Linux with the reboot=s kernel boot parameter and rebooting.
Method 6. Via the ACPI
Section 184.108.40.206 of the ACPI spec describes RESET_VALUE and RESET_REG which can be configured in the FADT. The OS writes the value in RESET_VALUE to the register RESET_REG to perform a reboot. I've seen this achieved by various ways, for example one BIOS has implemented this as the PCI reset method, by writing 0x06 into register 0xcf9, this works in 95% the time, but one really does need to write 0x02, delay and then write 0x04 for this to reliably work 100% of the time. So BIOS writers beware!
In Linux, this can be configured by using the reboot=a kernel boot parameter and rebooting.
Method 7. Using the EFI (Extensible Firmware Interface) reset_system runtime service.
If your Linux PC supports EFI firmware (e.g. Intel based Apple Macs), you can reboot using EFI using the reboot=e kernel boot parameter for reboots. Basically this makes the kernel call the EFI reboot service support call.
Using reboot() system call..
Rebooting from userspace with super user privileges can be achieved in Linux using the reboot() system call:
You need to include unistd.h and linux/reboot.h and then call:
Hopefully this article will solve most of your Linux rebooting issues. Have fun!
Post Script, using kexec()
I have not mentioned kexec() which allows one to execute a new kernel image, allowing one to effectively reboot very quickly without involving a hard reset and executing BIOS code... that's for another blog entry! The beauty of kexec() is it allows one to jump to a pre-loaded kernel image and reboot with this, avoiding the need to do a BIOS reboot. This gives Linux the ability to seemlessly reboot and at speed.