debuggers.hg

view tools/misc/xen-detect.c @ 20930:526af7ddb9bd

tools/xen-detect: fix printing xen version

check_for_xen() should return xen version rather than
boolean true if signature XenVMM is found.

Signed-off-by: Yu Zhiguo <yuzg@cn.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 03 09:42:45 2010 +0000 (2010-02-03)
parents 07f98beddc18
children
line source
1 /******************************************************************************
2 * xen_detect.c
3 *
4 * Simple GNU C / POSIX application to detect execution on Xen VMM platform.
5 *
6 * Copyright (c) 2007, XenSource Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to
10 * deal in the Software without restriction, including without limitation the
11 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 * sell copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <setjmp.h>
32 #include <signal.h>
33 #include <unistd.h>
34 #include <getopt.h>
36 static void cpuid(uint32_t idx,
37 uint32_t *eax,
38 uint32_t *ebx,
39 uint32_t *ecx,
40 uint32_t *edx,
41 int pv_context)
42 {
43 asm volatile (
44 "test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid"
45 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
46 : "0" (idx), "1" (pv_context) );
47 }
49 static int check_for_xen(int pv_context)
50 {
51 uint32_t eax, ebx, ecx, edx;
52 char signature[13];
53 uint32_t base;
55 for ( base = 0x40000000; base < 0x40010000; base += 0x100 )
56 {
57 cpuid(base, &eax, &ebx, &ecx, &edx, pv_context);
59 *(uint32_t *)(signature + 0) = ebx;
60 *(uint32_t *)(signature + 4) = ecx;
61 *(uint32_t *)(signature + 8) = edx;
62 signature[12] = '\0';
64 if ( !strcmp("XenVMMXenVMM", signature) && (eax >= (base + 2)) )
65 goto found;
66 }
68 return 0;
70 found:
71 cpuid(base + 1, &eax, &ebx, &ecx, &edx, pv_context);
72 return eax;
73 }
75 static jmp_buf sigill_jmp;
76 void sigill_handler(int sig)
77 {
78 longjmp(sigill_jmp, 1);
79 }
81 static void usage(void)
82 {
83 printf("Usage: xen_detect [options]\n");
84 printf("Options:\n");
85 printf(" -h, --help Display this information\n");
86 printf(" -q, --quiet Quiesce normal informational output\n");
87 printf(" -P, --pv Exit status 1 if not running as PV guest\n");
88 printf(" -H, --hvm Exit status 1 if not running as HVM guest.\n");
89 printf(" -N, --none Exit status 1 if running on Xen (PV or HVM)\n");
90 }
92 int main(int argc, char **argv)
93 {
94 enum { XEN_PV = 1, XEN_HVM = 2, XEN_NONE = 3 } detected = 0, expected = 0;
95 uint32_t version = 0;
96 int ch, quiet = 0;
98 const static char sopts[] = "hqPHN";
99 const static struct option lopts[] = {
100 { "help", 0, NULL, 'h' },
101 { "quiet", 0, NULL, 'q' },
102 { "pv", 0, NULL, 'P' },
103 { "hvm", 0, NULL, 'H' },
104 { "none", 0, NULL, 'N' },
105 { 0, 0, 0, 0}
106 };
108 while ( (ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1 )
109 {
110 switch ( ch )
111 {
112 case 'q':
113 quiet = 1;
114 break;
115 case 'P':
116 expected = XEN_PV;
117 break;
118 case 'H':
119 expected = XEN_HVM;
120 break;
121 case 'N':
122 expected = XEN_NONE;
123 break;
124 default:
125 usage();
126 exit(1);
127 }
128 }
130 /* Check for execution in HVM context. */
131 detected = XEN_HVM;
132 if ( (version = check_for_xen(0)) != 0 )
133 goto out;
135 /*
136 * Set up a signal handler to test the paravirtualised CPUID instruction.
137 * If executed outside Xen PV context, the extended opcode will fault, we
138 * will longjmp via the signal handler, and print "Not running on Xen".
139 */
140 detected = XEN_PV;
141 if ( !setjmp(sigill_jmp)
142 && (signal(SIGILL, sigill_handler) != SIG_ERR)
143 && ((version = check_for_xen(1)) != 0) )
144 goto out;
146 detected = XEN_NONE;
148 out:
149 if ( quiet )
150 /* nothing */;
151 else if ( detected == XEN_NONE )
152 printf("Not running on Xen.\n");
153 else
154 printf("Running in %s context on Xen v%d.%d.\n",
155 (detected == XEN_PV) ? "PV" : "HVM",
156 (uint16_t)(version >> 16), (uint16_t)version);
158 return expected && (expected != detected);
159 }