VMWare poweroff magic cli;hlt sequence

Change-Id: I9d8f96cc2e6423b89eb743e27550225d8759ee1d
This commit is contained in:
Antoine Leca 2013-03-01 18:59:18 +00:00 committed by Gerrit Code Review
parent 26f14d6b5d
commit 9f467932a6
3 changed files with 43 additions and 3 deletions

View file

@ -84,7 +84,14 @@ reset(void)
}
}
void
static __dead void
halt(void)
{
for ( ; ; )
halt_cpu();
}
static __dead void
poweroff(void)
{
const char *shutdown_str;
@ -96,8 +103,11 @@ poweroff(void)
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)

View file

@ -81,9 +81,10 @@ struct exception_frame {
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);

View file

@ -382,6 +382,35 @@ ENTRY(halt_cpu)
*/
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 */
/*===========================================================================*/