}
}
-void
+static __dead void
+halt(void)
+{
+ for ( ; ; )
+ halt_cpu();
+}
+
+static __dead void
poweroff(void)
{
const char *shutdown_str;
shutdown_str = "Shutdown";
while (*shutdown_str) outb(0x8900, *(shutdown_str++));
+ /* VMware magic power off; likely to halt CPU */
+ poweroff_vmware_clihlt();
+
/* fallback option: hang */
- for (; ; ) halt_cpu();
+ halt();
}
__dead void arch_shutdown(int how)
void exception(struct exception_frame * frame);
-/* klib386.s */
+/* klib.S */
__dead void monitor(void);
__dead void reset(void);
+__dead void poweroff_vmware_clihlt(void);
__dead void x86_triplefault(void);
reg_t read_cr0(void);
reg_t read_cr2(void);
*/
ret
+/*===========================================================================*/
+/* poweroff_vmware_clihlt */
+/*===========================================================================*/
+/*
+ * PUBLIC void poweroff_vmware_clihlt(void);
+ * VMware detects this peculiar sequence and forces the virtual machine off
+ * when the parameter gui.exitOnCLIHLT is set to TRUE.
+ * Otherwise this sequence just hangs the CPU, requiring a power down action.
+ */
+ENTRY(poweroff_vmware_clihlt)
+#ifndef NO_VMWARE_DETECTION
+ mov $1, %eax
+ cpuid
+ test $[1<<31], %ecx /* "virtualized" */
+ jz 1f /* always 0 on real hardware */
+ mov $0x40000000, %eax /* select hypervisor-use leaf */
+ cpuid
+ cmp $0x61774D56, %ebx /* ASCII "VMwa" */
+ jne 1f
+ cmp $0x4D566572, %ecx /* ASCII "reVM" */
+ jne 1f
+ cmp $0x65726177, %edx /* ASCII "ware" */
+ jne 1f
+ /* we are virtualized by some VMware product! */
+#endif
+ cli
+ hlt
+1: ret
+
/*===========================================================================*/
/* read_flags */
/*===========================================================================*/