@@ -55,13 +55,32 @@ typedef union cpuid_feature_t {
55
55
uint32_t value ;
56
56
} cpuid_feature_t ;
57
57
58
+ typedef void (* set_feature_t )(hax_cpuid_entry * , hax_cpuid * , uint32_t );
59
+
60
+ typedef struct cpuid_set_t {
61
+ uint32_t function ;
62
+ set_feature_t set_feature ;
63
+ } cpuid_set_t ;
64
+
58
65
static cpuid_cache_t cache = {0 };
59
66
60
- static hax_cpuid_entry * find_cpuid_entry (hax_cpuid * cpuid_info ,
61
- uint32_t function , uint32_t index );
62
- static void cpuid_set_0000_0001 (hax_cpuid_t * cpuid , hax_cpuid * cpuid_info );
63
- static void cpuid_set_8000_0001 (hax_cpuid_t * cpuid , hax_cpuid * cpuid_info );
64
- static void cpuid_set_fixed_features (hax_cpuid_t * cpuid );
67
+ static hax_cpuid_entry * find_cpuid_entry (hax_cpuid_entry * features ,
68
+ uint32_t size , uint32_t function ,
69
+ uint32_t index );
70
+ static void set_feature (hax_cpuid_entry * features , hax_cpuid * cpuid_info ,
71
+ uint32_t function );
72
+ static void set_feature_0000_0001 (hax_cpuid_entry * features ,
73
+ hax_cpuid * cpuid_info , uint32_t function );
74
+ static void cpuid_set_fixed_features (hax_cpuid_entry * features ,
75
+ uint32_t function );
76
+ static void dump_features (hax_cpuid_entry * features , uint32_t size );
77
+ static uint32_t get_feature_key_leaf (uint32_t function , uint32_t reg ,
78
+ uint32_t bit );
79
+
80
+ static const cpuid_set_t kCpuidSet [CPUID_FEATURE_SET_SIZE ] = {
81
+ {0x00000001 , set_feature_0000_0001 },
82
+ {0x80000001 , set_feature }
83
+ };
65
84
66
85
void cpuid_query_leaf (cpuid_args_t * args , uint32_t leaf )
67
86
{
@@ -134,42 +153,41 @@ bool cpuid_host_has_feature_uncached(uint32_t feature_key)
134
153
135
154
void cpuid_init_supported_features (void )
136
155
{
137
- uint32_t bit , flag , function , x86_feature ;
156
+ uint32_t i , bit , flag , function , x86_feature ;
157
+ hax_cpuid_entry * host_supported , * hax_supported ;
138
158
139
159
// Initialize host supported features
140
- for (bit = 0 ; bit < sizeof (uint32_t ) * 8 ; ++ bit ) {
141
- flag = 1 << bit ;
142
-
143
- function = 0x01 ;
144
- x86_feature = FEATURE_KEY_LEAF (0 , function , CPUID_REG_ECX , bit );
145
- if (cpuid_host_has_feature (x86_feature )) {
146
- cache .host_supported .feature_1_ecx |= flag ;
147
- }
148
-
149
- x86_feature = FEATURE_KEY_LEAF (1 , function , CPUID_REG_EDX , bit );
150
- if (cpuid_host_has_feature (x86_feature )) {
151
- cache .host_supported .feature_1_edx |= flag ;
152
- }
153
-
154
- function = 0x80000001 ;
155
- x86_feature = FEATURE_KEY_LEAF (5 , function , CPUID_REG_EDX , bit );
156
- if (cpuid_host_has_feature (x86_feature )) {
157
- cache .host_supported .feature_8000_0001_edx |= flag ;
160
+ host_supported = cache .host_supported .features ;
161
+
162
+ for (i = 0 ; i < CPUID_FEATURE_SET_SIZE ; ++ i ) {
163
+ function = kCpuidSet [i ].function ;
164
+ host_supported [i ].function = function ;
165
+
166
+ for (bit = 0 ; bit < sizeof (uint32_t ) * 8 ; ++ bit ) {
167
+ flag = 1 << bit ;
168
+
169
+ #define SET_FEATURE_FLAG (r , n ) \
170
+ x86_feature = get_feature_key_leaf(function, (n), bit); \
171
+ if (cpuid_host_has_feature(x86_feature)) { \
172
+ host_supported[i].r |= flag; \
173
+ }
174
+
175
+ SET_FEATURE_FLAG (eax , CPUID_REG_EAX );
176
+ SET_FEATURE_FLAG (ebx , CPUID_REG_EBX );
177
+ SET_FEATURE_FLAG (ecx , CPUID_REG_ECX );
178
+ SET_FEATURE_FLAG (edx , CPUID_REG_EDX );
179
+ #undef SET_FEATURE_FLAG
158
180
}
159
181
}
160
182
161
183
hax_log (HAX_LOGI , "%s: host supported features:\n" , __func__ );
162
- hax_log (HAX_LOGI , "feature_1_ecx: %08lx, feature_1_edx: %08lx\n" ,
163
- cache .host_supported .feature_1_ecx ,
164
- cache .host_supported .feature_1_edx );
165
- hax_log (HAX_LOGI , "feature_8000_0001_ecx: %08lx, "
166
- "feature_8000_0001_edx: %08lx\n" ,
167
- cache .host_supported .feature_8000_0001_ecx ,
168
- cache .host_supported .feature_8000_0001_edx );
184
+ dump_features (host_supported , CPUID_FEATURE_SET_SIZE );
169
185
170
186
// Initialize HAXM supported features
171
- cache .hax_supported = (hax_cpuid_t ){
172
- .feature_1_ecx =
187
+ hax_supported = cache .hax_supported .features ;
188
+ hax_supported [0 ] = (hax_cpuid_entry ){
189
+ .function = 0x01 ,
190
+ .ecx =
173
191
FEATURE (SSE3 ) |
174
192
FEATURE (SSSE3 ) |
175
193
FEATURE (SSE41 ) |
@@ -179,7 +197,7 @@ void cpuid_init_supported_features(void)
179
197
FEATURE (AESNI ) |
180
198
FEATURE (PCLMULQDQ ) |
181
199
FEATURE (POPCNT ),
182
- .feature_1_edx =
200
+ .edx =
183
201
FEATURE (PAT ) |
184
202
FEATURE (FPU ) |
185
203
FEATURE (VME ) |
@@ -202,23 +220,19 @@ void cpuid_init_supported_features(void)
202
220
FEATURE (SSE2 ) |
203
221
FEATURE (SS ) |
204
222
FEATURE (PSE ) |
205
- FEATURE (HTT ),
206
- .feature_8000_0001_ecx = 0 ,
207
- .feature_8000_0001_edx =
223
+ FEATURE (HTT )
224
+ };
225
+ hax_supported [1 ] = (hax_cpuid_entry ){
226
+ .function = 0x80000001 ,
227
+ .edx =
208
228
FEATURE (NX ) |
209
229
FEATURE (SYSCALL ) |
210
230
FEATURE (RDTSCP ) |
211
231
FEATURE (EM64T )
212
232
};
213
233
214
234
hax_log (HAX_LOGI , "%s: HAXM supported features:\n" , __func__ );
215
- hax_log (HAX_LOGI , "feature_1_ecx: %08lx, feature_1_edx: %08lx\n" ,
216
- cache .hax_supported .feature_1_ecx ,
217
- cache .hax_supported .feature_1_edx );
218
- hax_log (HAX_LOGI , "feature_8000_0001_ecx: %08lx, "
219
- "feature_8000_0001_edx: %08lx\n" ,
220
- cache .hax_supported .feature_8000_0001_ecx ,
221
- cache .hax_supported .feature_8000_0001_edx );
235
+ dump_features (hax_supported , CPUID_FEATURE_SET_SIZE );
222
236
}
223
237
224
238
void cpuid_guest_init (hax_cpuid_t * cpuid )
@@ -237,130 +251,170 @@ void cpuid_set_features_mask(hax_cpuid_t *cpuid, uint64_t features_mask)
237
251
cpuid -> features_mask = features_mask ;
238
252
}
239
253
240
- void cpuid_get_guest_features (hax_cpuid_t * cpuid ,
241
- uint32_t * cpuid_1_features_ecx ,
242
- uint32_t * cpuid_1_features_edx ,
243
- uint32_t * cpuid_8000_0001_features_ecx ,
244
- uint32_t * cpuid_8000_0001_features_edx )
254
+ void cpuid_get_guest_features (hax_cpuid_t * cpuid , hax_cpuid_entry * features )
245
255
{
246
- * cpuid_1_features_ecx = cpuid -> feature_1_ecx ;
247
- * cpuid_1_features_edx = cpuid -> feature_1_edx ;
248
- * cpuid_8000_0001_features_ecx = cpuid -> feature_8000_0001_ecx ;
249
- * cpuid_8000_0001_features_edx = cpuid -> feature_8000_0001_edx ;
256
+ hax_cpuid_entry * entry ;
257
+
258
+ if (cpuid == NULL || features == NULL )
259
+ return ;
260
+
261
+ entry = find_cpuid_entry (cpuid -> features , CPUID_FEATURE_SET_SIZE ,
262
+ features -> function , 0 );
263
+ if (entry == NULL )
264
+ return ;
265
+
266
+ * features = * entry ;
250
267
}
251
268
252
269
void cpuid_set_guest_features (hax_cpuid_t * cpuid , hax_cpuid * cpuid_info )
253
270
{
254
- static void (* cpuid_set_guest_feature [])(hax_cpuid_t * , hax_cpuid * ) = {
255
- cpuid_set_0000_0001 ,
256
- cpuid_set_8000_0001
257
- };
258
- static size_t count = sizeof (cpuid_set_guest_feature ) /
259
- sizeof (cpuid_set_guest_feature [0 ]);
260
271
int i ;
272
+ const cpuid_set_t * kItem ;
273
+
274
+ if (cpuid == NULL || cpuid_info == NULL )
275
+ return ;
276
+
277
+ hax_log (HAX_LOGI , "%s: user setting:\n" , __func__ );
278
+ dump_features (cpuid_info -> entries , cpuid_info -> total );
261
279
262
280
hax_log (HAX_LOGI , "%s: before:\n" , __func__ );
263
- hax_log (HAX_LOGI , "feature_1_ecx: %08lx, feature_1_edx: %08lx\n" ,
264
- cpuid -> feature_1_ecx , cpuid -> feature_1_edx );
265
- hax_log (HAX_LOGI , "feature_8000_0001_ecx: %08lx, feature_8000_0001_edx: %08lx"
266
- "\n" , cpuid -> feature_8000_0001_ecx , cpuid -> feature_8000_0001_edx );
281
+ dump_features (cpuid -> features , CPUID_FEATURE_SET_SIZE );
267
282
268
- for (i = 0 ; i < count ; ++ i ) {
269
- cpuid_set_guest_feature [i ](cpuid , cpuid_info );
283
+ for (i = 0 ; i < CPUID_FEATURE_SET_SIZE ; ++ i ) {
284
+ kItem = & kCpuidSet [i ];
285
+ kItem -> set_feature (cpuid -> features , cpuid_info , kItem -> function );
270
286
}
271
287
272
288
hax_log (HAX_LOGI , "%s: after:\n" , __func__ );
273
- hax_log (HAX_LOGI , "feature_1_ecx: %08lx, feature_1_edx: %08lx\n" ,
274
- cpuid -> feature_1_ecx , cpuid -> feature_1_edx );
275
- hax_log (HAX_LOGI , "feature_8000_0001_ecx: %08lx, feature_8000_0001_edx: %08lx"
276
- "\n" , cpuid -> feature_8000_0001_ecx , cpuid -> feature_8000_0001_edx );
289
+ dump_features (cpuid -> features , CPUID_FEATURE_SET_SIZE );
277
290
}
278
291
279
- static hax_cpuid_entry * find_cpuid_entry (hax_cpuid * cpuid_info ,
280
- uint32_t function , uint32_t index )
292
+ static hax_cpuid_entry * find_cpuid_entry (hax_cpuid_entry * features ,
293
+ uint32_t size , uint32_t function ,
294
+ uint32_t index )
281
295
{
282
296
int i ;
283
- hax_cpuid_entry * entry , * found = NULL ;
297
+ hax_cpuid_entry * entry ;
284
298
285
- for (i = 0 ; i < cpuid_info -> total ; ++ i ) {
286
- entry = & cpuid_info -> entries [i ];
287
- if (entry -> function == function && entry -> index == index ) {
288
- found = entry ;
289
- break ;
290
- }
299
+ if (features == NULL )
300
+ return NULL ;
301
+
302
+ for (i = 0 ; i < size ; ++ i ) {
303
+ entry = & features [i ];
304
+ if (entry -> function == function && entry -> index == index )
305
+ return entry ;
291
306
}
292
307
293
- return found ;
308
+ return NULL ;
294
309
}
295
310
296
- static void cpuid_set_0000_0001 (hax_cpuid_t * cpuid , hax_cpuid * cpuid_info )
311
+ static void set_feature (hax_cpuid_entry * features , hax_cpuid * cpuid_info ,
312
+ uint32_t function )
297
313
{
298
- const uint32_t kFunction = 0x01 ;
299
- hax_cpuid_entry * entry ;
314
+ hax_cpuid_entry * dest , * src , * host_supported , * hax_supported ;
300
315
301
- entry = find_cpuid_entry (cpuid_info , kFunction , 0 );
302
- if (entry == NULL )
316
+ if (features == NULL || cpuid_info == NULL )
303
317
return ;
304
318
305
- hax_log (HAX_LOGI , "%s: function: %08lx, index: %lu, flags: %08lx\n" ,
306
- __func__ , entry -> function , entry -> index , entry -> flags );
307
- hax_log (HAX_LOGI , "%s: eax: %08lx, ebx: %08lx, ecx: %08lx, edx: %08lx\n" ,
308
- __func__ , entry -> eax , entry -> ebx , entry -> ecx , entry -> edx );
319
+ dest = find_cpuid_entry (features , CPUID_FEATURE_SET_SIZE , function , 0 );
320
+ if (dest == NULL )
321
+ return ;
309
322
310
- cpuid -> feature_1_ecx = entry -> ecx ;
311
- cpuid -> feature_1_edx = entry -> edx ;
323
+ src = find_cpuid_entry (cpuid_info -> entries , cpuid_info -> total , function , 0 );
324
+ if (src == NULL )
325
+ return ;
312
326
313
- // Filter the unsupported features
314
- cpuid -> feature_1_ecx &= cache .host_supported .feature_1_ecx &
315
- cache .hax_supported .feature_1_ecx ;
316
- cpuid -> feature_1_edx &= cache .host_supported .feature_1_edx &
317
- cache .hax_supported .feature_1_edx ;
327
+ host_supported = find_cpuid_entry (cache .host_supported .features ,
328
+ CPUID_FEATURE_SET_SIZE , function , 0 );
329
+ hax_supported = find_cpuid_entry (cache .hax_supported .features ,
330
+ CPUID_FEATURE_SET_SIZE , function , 0 );
318
331
319
- // Set fixed supported features
320
- cpuid_set_fixed_features ( cpuid ) ;
332
+ if ( host_supported == NULL || hax_supported == NULL )
333
+ return ;
321
334
322
- if (entry -> ecx != cpuid -> feature_1_ecx ||
323
- entry -> edx != cpuid -> feature_1_edx ) {
324
- hax_log (HAX_LOGW , "%s: filtered or unchanged flags: ecx: %08lx, "
325
- "edx: %08lx\n" , __func__ , entry -> ecx ^ cpuid -> feature_1_ecx ,
326
- entry -> edx ^ cpuid -> feature_1_edx );
327
- }
335
+ * dest = * src ;
336
+ dest -> eax &= host_supported -> eax & hax_supported -> eax ;
337
+ dest -> ebx &= host_supported -> ebx & hax_supported -> ebx ;
338
+ dest -> ecx &= host_supported -> ecx & hax_supported -> ecx ;
339
+ dest -> edx &= host_supported -> edx & hax_supported -> edx ;
340
+
341
+ if (src -> eax == dest -> eax && src -> ebx == dest -> ebx &&
342
+ src -> ecx == dest -> ecx && src -> edx == dest -> edx )
343
+ return ;
344
+
345
+ hax_log (HAX_LOGW , "%s: filtered or unchanged flags:\n" , __func__ );
346
+ hax_log (HAX_LOGW , "function: %08lx, eax: %08lx, ebx: %08lx, ecx: %08lx, "
347
+ "edx: %08lx\n" , function , src -> eax ^ dest -> eax ,
348
+ src -> ebx ^ dest -> ebx , src -> ecx ^ dest -> ecx , src -> edx ^ dest -> edx );
349
+ }
350
+
351
+ static void set_feature_0000_0001 (hax_cpuid_entry * features ,
352
+ hax_cpuid * cpuid_info , uint32_t function )
353
+ {
354
+ if (features == NULL || cpuid_info == NULL )
355
+ return ;
356
+
357
+ set_feature (features , cpuid_info , function );
358
+ // Set fixed supported features
359
+ cpuid_set_fixed_features (features , function );
328
360
}
329
361
330
- static void cpuid_set_8000_0001 (hax_cpuid_t * cpuid , hax_cpuid * cpuid_info )
362
+ static void cpuid_set_fixed_features (hax_cpuid_entry * features ,
363
+ uint32_t function )
331
364
{
332
- const uint32_t kFunction = 0x80000001 ;
365
+ const uint32_t kFixedFeatures =
366
+ FEATURE (MCE ) |
367
+ FEATURE (APIC ) |
368
+ FEATURE (MTRR ) |
369
+ FEATURE (PAT );
333
370
hax_cpuid_entry * entry ;
334
371
335
- entry = find_cpuid_entry (cpuid_info , kFunction , 0 );
372
+ if (features == NULL )
373
+ return ;
374
+
375
+ entry = find_cpuid_entry (features , CPUID_FEATURE_SET_SIZE , function , 0 );
336
376
if (entry == NULL )
337
377
return ;
338
378
339
- hax_log (HAX_LOGI , "%s: function: %08lx, index: %lu, flags: %08lx\n" ,
340
- __func__ , entry -> function , entry -> index , entry -> flags );
341
- hax_log (HAX_LOGI , "%s: eax: %08lx, ebx: %08lx, ecx: %08lx, edx: %08lx\n" ,
342
- __func__ , entry -> eax , entry -> ebx , entry -> ecx , entry -> edx );
379
+ entry -> edx |= kFixedFeatures ;
380
+ }
343
381
344
- cpuid -> feature_8000_0001_edx = entry -> edx ;
382
+ static void dump_features (hax_cpuid_entry * features , uint32_t size )
383
+ {
384
+ int i ;
385
+ hax_cpuid_entry * entry ;
345
386
346
- // Filter the unsupported features
347
- cpuid -> feature_8000_0001_edx &=
348
- cache .host_supported .feature_8000_0001_edx &
349
- cache .hax_supported .feature_8000_0001_edx ;
387
+ if (features == NULL )
388
+ return ;
350
389
351
- if (entry -> edx != cpuid -> feature_8000_0001_edx ) {
352
- hax_log (HAX_LOGW , "%s: filtered or unchanged flags: edx: %08lx\n" ,
353
- __func__ , entry -> edx ^ cpuid -> feature_8000_0001_edx );
390
+ for (i = 0 ; i < size ; ++ i ) {
391
+ entry = & features [i ];
392
+ hax_log (HAX_LOGI , "function: %08lx, index: %lu, flags: %08lx\n" ,
393
+ entry -> function , entry -> index , entry -> flags );
394
+ hax_log (HAX_LOGI , "eax: %08lx, ebx: %08lx, ecx: %08lx, edx: %08lx\n" ,
395
+ entry -> eax , entry -> ebx , entry -> ecx , entry -> edx );
354
396
}
355
397
}
356
398
357
- static void cpuid_set_fixed_features (hax_cpuid_t * cpuid )
399
+ static uint32_t get_feature_key_leaf (uint32_t function , uint32_t reg ,
400
+ uint32_t bit )
358
401
{
359
- const uint32_t kFixedFeatures =
360
- FEATURE (MCE ) |
361
- FEATURE (APIC ) |
362
- FEATURE (MTRR ) |
363
- FEATURE (PAT );
402
+ if (function == 0x01 ) {
403
+ if (reg == CPUID_REG_ECX )
404
+ return FEATURE_KEY_LEAF (0 , function , reg , bit );
405
+
406
+ if (reg == CPUID_REG_EDX )
407
+ return FEATURE_KEY_LEAF (1 , function , reg , bit );
408
+
409
+ return -1 ;
410
+ }
411
+
412
+ if (function == 0x80000001 ) {
413
+ if (reg == CPUID_REG_EDX )
414
+ return FEATURE_KEY_LEAF (5 , function , reg , bit );
415
+
416
+ return -1 ;
417
+ }
364
418
365
- cpuid -> feature_1_edx |= kFixedFeatures ;
419
+ return -1 ;
366
420
}
0 commit comments