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);
outb(0xfe, 0x64);
..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);
outb(0x02, 0xcf9);
usleep(10); /* a very small delay is required, this is plenty */
outb(0x04, 0xcf9);
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 4.7.3.6 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:
reboot(LINUX_REBOOT_CMD_RESTART);
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.
Award yourself the CDM for the complete show off as I didnot understand one ****** sentence,
ReplyDeleteCadburys Dairy Milk.
But thanks for the laugh,
Ron.
Hi Anonymous reader. Thanks for your posting. I was not intending to show off, but to write something technically informative. I will take your advice and award myself a bar of chocolate :-)
ReplyDeleteDear Colin,
ReplyDeleteVery nice writeup. Exactly what I've been looking for while debugging reboot issues with old Linux kernels and coreboot. This should go to the kernel's Documentation folder.
Stefan
@Stefan, thanks for your comment; I'm glad it's helped you with coreboot.
ReplyDeleteI am running Ubuntu 11.04 on a 2011 Mac Mini "natively". I've seen some advice concerning reboot parameters and pci tweaks and I was wondering if you had any comment.
ReplyDelete> 21. Add the following to /etc/rc.d/rc.local (or equivalent, if using a strange or orange version of Linux):
setpci -s 0:1f.0 0xa4.b=0
This will force your Mac to auto-reboot in the event of a power failure. Do not ask why the arguments are as they are. [1]
> Oh, one more kernel parameter to avoid crashing at system stop/reboot is "reboot=p", also add to grub default as described above. [2]
Thanks,
Bryan
[1] http://www.ilikejam.org/blog/unix/linux-mac-mini.html
[2] http://ubuntuforums.org/showthread.php?p=11084566
@Bryan,
ReplyDeletesetpci -s 0:1f.0 0xa4.b=0 is an interesting rune. I found that device 00:1f.0 refers to:
00:1f.0 ISA bridge: Intel Corporation 82801GBM (ICH7-M) LPC Interface Bridge (rev 02)
so I downloaded the ICH7 PDF from Intel: http://www.intel.com/content/www/us/en/io/i-o-controller-hub-7-datasheet.html and byte 0xa4 can be found in section 10.8.1.3 and refers to GEN_PMCON_3—General PM Configuration 3 Register. So the setpci command is clearing this, I suspect we are just interested in clearing bit zero:
"AFTERG3_EN — R/W. This bit determines what state to go to when power is re-applied after a power failure (G3 state). This bit is in the RTC well and is not cleared by any type of reset except writes to CF9h or RTCRST#.
0 = System will return to S0 state (boot) after power is re-applied.
1 = System will return to the S5 state (except if it was in S4, in which case it will return to S4). In the S5 state, the only enabled wake event is the Power Button or any enabled wake event that was preserved through the power failure."
As for "reboot=p", well that triggers writing 2 and then 6 to 0xcf9 register to initiate a PCI reset. I suspect this works around the flaky default reboot behavior on this platform.
Hi Colin,
ReplyDeleteThanks for the writeup. I'm working on a piece of security-sensitive code that runs before the kernel. I am learning and there is still a lot I don't know. It is my understanding that a hard reset is better from a security perspective than a soft reset. What is the difference between a hard reset and soft reset?
In the code I'm studying, three different methods are used to reboot the system. Two of them you mention above:
1) Writing 0xfe to 0x64
2) Writing 0x06 to 0x6f9
3) Writing 0x0a and then 0x0e to 0xcf9
The last one is supposed to do a power-cycle on all TXT-capable chipsets.
Do you know if your methods 1, 2, and 6 or the ones I mentioned work reliably on AMD?
thanks,
Safayet