Hi,
xen-detect may hang on some cases.
I hit this issue on one of my box. And I found that
it hang when executing "ud2a". Seems it not trap
and sig the user.
OS: RHEL 5.4 2.6.18-164.15.1.el5
glibc-2.5-42.el5_4.3.x86_64
/var/log/message
kernel: xen-detect general protection rip:400665 rsp:7fff3a922888 error:0
On platform it work correctly, the message is
kernel: xen-detect trap invalid opcode rip:40068d rsp:7fffa8acadc8 error:0
Any idea of this, why it behaves different?
source codes:
------------------------
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#include <getopt.h>
static void cpuid(uint32_t idx,
uint32_t *eax,
uint32_t *ebx,
uint32_t *ecx,
uint32_t *edx,
int pv_context)
{
asm volatile (
"test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1:
cpuid"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx),
"=d" (*edx)
: "0" (idx), "1" (pv_context) );
}
static int check_for_xen(int pv_context)
{
uint32_t eax, ebx, ecx, edx;
char signature[13];
uint32_t base;
for ( base = 0x40000000; base < 0x40010000; base += 0x100 )
{
cpuid(base, &eax, &ebx, &ecx, &edx, pv_context);
*(uint32_t *)(signature + 0) = ebx;
*(uint32_t *)(signature + 4) = ecx;
*(uint32_t *)(signature + 8) = edx;
signature[12] = ''\0'';
if ( !strcmp("XenVMMXenVMM", signature) && (eax >=
(base + 2)) )
goto found;
}
return 0;
found:
cpuid(base + 1, &eax, &ebx, &ecx, &edx, pv_context);
return 1;
}
static jmp_buf sigill_jmp;
void sigill_handler(int sig)
{
longjmp(sigill_jmp, 1);
}
static void usage(void)
{
printf("Usage: xen_detect [options]\n");
printf("Options:\n");
printf(" -h, --help Display this information\n");
printf(" -q, --quiet Quiesce normal informational output\n");
printf(" -P, --pv Exit status 1 if not running as PV
guest\n");
printf(" -H, --hvm Exit status 1 if not running as HVM
guest.\n");
printf(" -N, --none Exit status 1 if running on Xen (PV or
HVM)\n");
}
int main(int argc, char **argv)
{
enum { XEN_PV = 1, XEN_HVM = 2, XEN_NONE = 3 } detected = 0, expected 0;
uint32_t version = 0;
int ch, quiet = 0;
const static char sopts[] = "hqPHN";
const static struct option lopts[] = {
{ "help", 0, NULL, ''h'' },
{ "quiet", 0, NULL, ''q'' },
{ "pv", 0, NULL, ''P'' },
{ "hvm", 0, NULL, ''H'' },
{ "none", 0, NULL, ''N'' },
{ 0, 0, 0, 0}
};
while ( (ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1 )
{
switch ( ch )
{
case ''q'':
quiet = 1;
break;
case ''P'':
expected = XEN_PV;
break;
case ''H'':
expected = XEN_HVM;
break;
case ''N'':
expected = XEN_NONE;
break;
default:
usage();
exit(1);
}
}
/* Check for execution in HVM context. */
detected = XEN_HVM;
if ( (version = check_for_xen(0)) != 0 )
goto out;
/*
* Set up a signal handler to test the paravirtualised CPUID
instruction.
* If executed outside Xen PV context, the extended opcode will fault,
we
* will longjmp via the signal handler, and print "Not running on
Xen".
*/
detected = XEN_PV;
if ( !setjmp(sigill_jmp)
&& (signal(SIGILL, sigill_handler) != SIG_ERR)
&& ((version = check_for_xen(1)) != 0) )
goto out;
detected = XEN_NONE;
out:
if ( quiet )
/* nothing */;
else if ( detected == XEN_NONE )
printf("Not running on Xen.\n");
else
printf("Running in %s context on Xen v%d.%d.\n",
(detected == XEN_PV) ? "PV" : "HVM",
(uint16_t)(version >> 16), (uint16_t)version);
return expected && (expected != detected);
}
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
lists.xensource.com/xen-devel