debuggers.hg

view tools/libxl/libxl_cpuid.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents c553d3035fd5
children 6067a17114bc
line source
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as published
4 * by the Free Software Foundation; version 2.1 only. with the special
5 * exception on linking described in file LICENSE.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Lesser General Public License for more details.
11 */
13 #include <string.h>
15 #include "libxl.h"
16 #include "libxl_osdeps.h"
17 #include "libxl_internal.h"
19 void libxl_cpuid_destroy(libxl_cpuid_policy_list *p_cpuid_list)
20 {
21 int i, j;
22 libxl_cpuid_policy_list cpuid_list = *p_cpuid_list;
24 if (cpuid_list == NULL)
25 return;
26 for (i = 0; cpuid_list[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) {
27 for (j = 0; j < 4; j++)
28 if (cpuid_list[i].policy[j] != NULL)
29 free(cpuid_list[i].policy[j]);
30 }
31 return;
32 }
34 #define CPUID_REG_INV 0
35 #define CPUID_REG_EAX 1
36 #define CPUID_REG_EBX 2
37 #define CPUID_REG_ECX 3
38 #define CPUID_REG_EDX 4
40 /* mapping CPUID features to names
41 * holds a "name" for each feature, specified by the "leaf" number (and an
42 * optional "subleaf" in ECX), the "reg"ister (EAX-EDX) used and a number of
43 * bits starting with "bit" and being "length" bits long.
44 * Used for the static structure describing all features.
45 */
46 struct cpuid_flags {
47 char* name;
48 uint32_t leaf;
49 uint32_t subleaf;
50 int reg;
51 int bit;
52 int length;
53 };
55 /* go through the dynamic array finding the entry for a specified leaf.
56 * if no entry exists, allocate one and return that.
57 */
58 static libxl_cpuid_policy_list cpuid_find_match(libxl_cpuid_policy_list *list,
59 uint32_t leaf, uint32_t subleaf)
60 {
61 int i = 0;
63 if (*list != NULL) {
64 for (i = 0; (*list)[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) {
65 if ((*list)[i].input[0] == leaf && (*list)[i].input[1] == subleaf)
66 return *list + i;
67 }
68 }
69 *list = realloc(*list, sizeof((*list)[0]) * (i + 2));
70 (*list)[i].input[0] = leaf;
71 (*list)[i].input[1] = subleaf;
72 memset((*list)[i].policy, 0, 4 * sizeof(char*));
73 (*list)[i + 1].input[0] = XEN_CPUID_INPUT_UNUSED;
74 return *list + i;
75 }
77 /* parse a single key=value pair and translate it into the libxc
78 * used interface using 32-characters strings for each register.
79 * Will overwrite earlier entries and thus can be called multiple
80 * times.
81 */
82 int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str)
83 {
84 #define NA XEN_CPUID_INPUT_UNUSED
85 struct cpuid_flags cpuid_flags[] = {
86 {"maxleaf", 0x00000000, NA, CPUID_REG_EAX, 0, 32},
87 /* the following two entries are subject to tweaking later in the code */
88 {"family", 0x00000001, NA, CPUID_REG_EAX, 8, 8},
89 {"model", 0x00000001, NA, CPUID_REG_EAX, 4, 8},
90 {"stepping", 0x00000001, NA, CPUID_REG_EAX, 0, 4},
91 {"localapicid", 0x00000001, NA, CPUID_REG_EBX, 24, 8},
92 {"proccount", 0x00000001, NA, CPUID_REG_EBX, 16, 8},
93 {"clflush", 0x00000001, NA, CPUID_REG_EBX, 8, 8},
94 {"brandid", 0x00000001, NA, CPUID_REG_EBX, 0, 8},
95 {"f16c", 0x00000001, NA, CPUID_REG_ECX, 29, 1},
96 {"avx", 0x00000001, NA, CPUID_REG_ECX, 28, 1},
97 {"osxsave", 0x00000001, NA, CPUID_REG_ECX, 27, 1},
98 {"xsave", 0x00000001, NA, CPUID_REG_ECX, 26, 1},
99 {"aes", 0x00000001, NA, CPUID_REG_ECX, 25, 1},
100 {"popcnt", 0x00000001, NA, CPUID_REG_ECX, 23, 1},
101 {"movbe", 0x00000001, NA, CPUID_REG_ECX, 22, 1},
102 {"x2apic", 0x00000001, NA, CPUID_REG_ECX, 21, 1},
103 {"sse4.2", 0x00000001, NA, CPUID_REG_ECX, 20, 1},
104 {"sse4.1", 0x00000001, NA, CPUID_REG_ECX, 19, 1},
105 {"dca", 0x00000001, NA, CPUID_REG_ECX, 18, 1},
106 {"pdcm", 0x00000001, NA, CPUID_REG_ECX, 15, 1},
107 {"xtpr", 0x00000001, NA, CPUID_REG_ECX, 14, 1},
108 {"cmpxchg16", 0x00000001, NA, CPUID_REG_ECX, 13, 1},
109 {"cntxid", 0x00000001, NA, CPUID_REG_ECX, 10, 1},
110 {"ssse3", 0x00000001, NA, CPUID_REG_ECX, 9, 1},
111 {"tm2", 0x00000001, NA, CPUID_REG_ECX, 8, 1},
112 {"est", 0x00000001, NA, CPUID_REG_ECX, 7, 1},
113 {"smx", 0x00000001, NA, CPUID_REG_ECX, 6, 1},
114 {"vmx", 0x00000001, NA, CPUID_REG_ECX, 5, 1},
115 {"dscpl", 0x00000001, NA, CPUID_REG_ECX, 4, 1},
116 {"monitor", 0x00000001, NA, CPUID_REG_ECX, 3, 1},
117 {"dtes64", 0x00000001, NA, CPUID_REG_ECX, 2, 1},
118 {"sse3", 0x00000001, NA, CPUID_REG_ECX, 0, 1},
119 {"pbe", 0x00000001, NA, CPUID_REG_EDX, 31, 1},
120 {"ia64", 0x00000001, NA, CPUID_REG_EDX, 30, 1},
121 {"tm", 0x00000001, NA, CPUID_REG_EDX, 29, 1},
122 {"htt", 0x00000001, NA, CPUID_REG_EDX, 28, 1},
123 {"ss", 0x00000001, NA, CPUID_REG_EDX, 27, 1},
124 {"sse2", 0x00000001, NA, CPUID_REG_EDX, 26, 1},
125 {"sse", 0x00000001, NA, CPUID_REG_EDX, 25, 1},
126 {"fxsr", 0x00000001, NA, CPUID_REG_EDX, 24, 1},
127 {"mmx", 0x00000001, NA, CPUID_REG_EDX, 23, 1},
128 {"acpi", 0x00000001, NA, CPUID_REG_EDX, 22, 1},
129 {"ds", 0x00000001, NA, CPUID_REG_EDX, 21, 1},
130 {"clfsh", 0x00000001, NA, CPUID_REG_EDX, 19, 1},
131 {"psn", 0x00000001, NA, CPUID_REG_EDX, 18, 1},
132 {"pse36", 0x00000001, NA, CPUID_REG_EDX, 17, 1},
133 {"pat", 0x00000001, NA, CPUID_REG_EDX, 16, 1},
134 {"cmov", 0x00000001, NA, CPUID_REG_EDX, 15, 1},
135 {"mca", 0x00000001, NA, CPUID_REG_EDX, 14, 1},
136 {"pge", 0x00000001, NA, CPUID_REG_EDX, 13, 1},
137 {"mtrr", 0x00000001, NA, CPUID_REG_EDX, 12, 1},
138 {"sysenter", 0x00000001, NA, CPUID_REG_EDX, 11, 1},
139 {"apic", 0x00000001, NA, CPUID_REG_EDX, 9, 1},
140 {"cmpxchg8", 0x00000001, NA, CPUID_REG_EDX, 8, 1},
141 {"mce", 0x00000001, NA, CPUID_REG_EDX, 7, 1},
142 {"pae", 0x00000001, NA, CPUID_REG_EDX, 6, 1},
143 {"msr", 0x00000001, NA, CPUID_REG_EDX, 5, 1},
144 {"tsc", 0x00000001, NA, CPUID_REG_EDX, 4, 1},
145 {"pse", 0x00000001, NA, CPUID_REG_EDX, 3, 1},
146 {"de", 0x00000001, NA, CPUID_REG_EDX, 2, 1},
147 {"vme", 0x00000001, NA, CPUID_REG_EDX, 1, 1},
148 {"fpu", 0x00000001, NA, CPUID_REG_EDX, 0, 1},
149 {"topoext", 0x80000001, NA, CPUID_REG_ECX, 22, 1},
150 {"tbm", 0x80000001, NA, CPUID_REG_ECX, 21, 1},
151 {"nodeid", 0x80000001, NA, CPUID_REG_ECX, 19, 1},
152 {"fma4", 0x80000001, NA, CPUID_REG_ECX, 16, 1},
153 {"lwp", 0x80000001, NA, CPUID_REG_ECX, 15, 1},
154 {"wdt", 0x80000001, NA, CPUID_REG_ECX, 13, 1},
155 {"skinit", 0x80000001, NA, CPUID_REG_ECX, 12, 1},
156 {"xop", 0x80000001, NA, CPUID_REG_ECX, 11, 1},
157 {"ibs", 0x80000001, NA, CPUID_REG_ECX, 10, 1},
158 {"osvw", 0x80000001, NA, CPUID_REG_ECX, 10, 1},
159 {"3dnowprefetch",0x80000001, NA, CPUID_REG_ECX, 8, 1},
160 {"misalignsse", 0x80000001, NA, CPUID_REG_ECX, 7, 1},
161 {"sse4a", 0x80000001, NA, CPUID_REG_ECX, 6, 1},
162 {"abm", 0x80000001, NA, CPUID_REG_ECX, 5, 1},
163 {"altmovcr8", 0x80000001, NA, CPUID_REG_ECX, 4, 1},
164 {"extapic", 0x80000001, NA, CPUID_REG_ECX, 3, 1},
165 {"svm", 0x80000001, NA, CPUID_REG_ECX, 2, 1},
166 {"cmplegacy", 0x80000001, NA, CPUID_REG_ECX, 1, 1},
167 {"lahfsahf", 0x80000001, NA, CPUID_REG_ECX, 0, 1},
168 {"3dnow", 0x80000001, NA, CPUID_REG_EDX, 31, 1},
169 {"3dnowext", 0x80000001, NA, CPUID_REG_EDX, 30, 1},
170 {"lm", 0x80000001, NA, CPUID_REG_EDX, 29, 1},
171 {"rdtscp", 0x80000001, NA, CPUID_REG_EDX, 27, 1},
172 {"page1gb", 0x80000001, NA, CPUID_REG_EDX, 26, 1},
173 {"ffxsr", 0x80000001, NA, CPUID_REG_EDX, 25, 1},
174 {"mmxext", 0x80000001, NA, CPUID_REG_EDX, 22, 1},
175 {"nx", 0x80000001, NA, CPUID_REG_EDX, 20, 1},
176 {"syscall", 0x80000001, NA, CPUID_REG_EDX, 11, 1},
177 {"procpkg", 0x00000004, 0, CPUID_REG_EAX, 26, 6},
178 {"apicidsize", 0x80000008, NA, CPUID_REG_ECX, 12, 4},
179 {"nc", 0x80000008, NA, CPUID_REG_ECX, 0, 8},
181 {NULL, 0, CPUID_REG_INV, 0, 0}
182 };
183 #undef NA
184 char *sep, *val, *endptr;
185 int i;
186 struct cpuid_flags *flag;
187 struct libxl__cpuid_policy *entry;
188 unsigned long num;
189 char flags[33], *resstr;
191 sep = strchr(str, '=');
192 if (sep == NULL) {
193 return 1;
194 } else {
195 val = sep + 1;
196 }
197 for (flag = cpuid_flags; flag->name != NULL; flag++) {
198 if(!strncmp(str, flag->name, sep - str) && flag->name[sep - str] == 0)
199 break;
200 }
201 if (flag->name == NULL) {
202 return 2;
203 }
204 entry = cpuid_find_match(cpuid, flag->leaf, flag->subleaf);
205 resstr = entry->policy[flag->reg - 1];
206 if (resstr == NULL) {
207 resstr = strdup("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
208 }
209 num = strtoull(val, &endptr, 0);
210 flags[flag->length] = 0;
211 if (endptr != val) {
212 /* is this was a valid number, write the binary form into the string */
213 for (i = 0; i < flag->length; i++) {
214 flags[flag->length - 1 - i] = "01"[!!(num & (1 << i))];
215 }
216 } else {
217 switch(val[0]) {
218 case 'x': case 'k': case 's':
219 memset(flags, val[0], flag->length);
220 break;
221 default:
222 return 3;
223 }
224 }
225 /* the family and model entry is potentially split up across
226 * two fields in Fn0000_0001_EAX, so handle them here separately.
227 */
228 if (!strncmp(str, "family", sep - str)) {
229 if (num < 16) {
230 memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
231 memcpy(resstr + (32 - 8) - 20, "00000000", 8);
232 } else {
233 num -= 15;
234 memcpy(resstr + (32 - 4) - flag->bit, "1111", 4);
235 for (i = 0; i < 7; i++) {
236 flags[7 - i] = "01"[num & 1];
237 num >>= 1;
238 }
239 memcpy(resstr + (32 - 8) - 20, flags, 8);
240 }
241 } else if (!strncmp(str, "model", sep - str)) {
242 memcpy(resstr + (32 - 4) - 16, flags, 4);
243 memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
244 } else {
245 memcpy(resstr + (32 - flag->length) - flag->bit, flags,
246 flag->length);
247 }
248 entry->policy[flag->reg - 1] = resstr;
250 return 0;
251 }
253 /* parse a single list item from the legacy Python xend syntax, where
254 * the strings for each register were directly exposed to the user.
255 * Used for maintaining compatibility with older config files
256 */
257 int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list *cpuid,
258 const char* str)
259 {
260 char *endptr;
261 unsigned long value;
262 uint32_t leaf, subleaf = XEN_CPUID_INPUT_UNUSED;
263 struct libxl__cpuid_policy *entry;
265 /* parse the leaf number */
266 value = strtoul(str, &endptr, 0);
267 if (str == endptr) {
268 return 1;
269 }
270 leaf = value;
271 /* check for an optional subleaf number */
272 if (*endptr == ',') {
273 str = endptr + 1;
274 value = strtoul(str, &endptr, 0);
275 if (str == endptr) {
276 return 2;
277 }
278 subleaf = value;
279 }
280 if (*endptr != ':') {
281 return 3;
282 }
283 str = endptr + 1;
284 entry = cpuid_find_match(cpuid, leaf, subleaf);
285 for (str = endptr + 1; *str != 0;) {
286 if (str[0] != 'e' || str[2] != 'x') {
287 return 4;
288 }
289 value = str[1] - 'a';
290 endptr = strchr(str, '=');
291 if (value < 0 || value > 3 || endptr == NULL) {
292 return 4;
293 }
294 str = endptr + 1;
295 endptr = strchr(str, ',');
296 if (endptr == NULL) {
297 endptr = strchr(str, 0);
298 }
299 if (endptr - str != 32) {
300 return 5;
301 }
302 entry->policy[value] = calloc(32 + 1, 1);
303 strncpy(entry->policy[value], str, 32);
304 entry->policy[value][32] = 0;
305 if (*endptr == 0) {
306 break;
307 }
308 for (str = endptr + 1; *str == ' ' || *str == '\n'; str++);
309 }
310 return 0;
311 }
313 void libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid)
314 {
315 xc_cpuid_apply_policy(ctx->xch, domid);
316 }
318 void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
319 libxl_cpuid_policy_list cpuid)
320 {
321 int i;
322 char *cpuid_res[4];
324 for (i = 0; cpuid[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++)
325 xc_cpuid_set(ctx->xch, domid, cpuid[i].input,
326 (const char**)(cpuid[i].policy), cpuid_res);
327 }