@@ -55,13 +55,32 @@ typedef union cpuid_feature_t {
5555 uint32_t value ;
5656} cpuid_feature_t ;
5757
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+
5865static cpuid_cache_t cache = {0 };
5966
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+ };
6584
6685void cpuid_query_leaf (cpuid_args_t * args , uint32_t leaf )
6786{
@@ -134,42 +153,41 @@ bool cpuid_host_has_feature_uncached(uint32_t feature_key)
134153
135154void cpuid_init_supported_features (void )
136155{
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 ;
138158
139159 // 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
158180 }
159181 }
160182
161183 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 );
169185
170186 // 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 =
173191 FEATURE (SSE3 ) |
174192 FEATURE (SSSE3 ) |
175193 FEATURE (SSE41 ) |
@@ -179,7 +197,7 @@ void cpuid_init_supported_features(void)
179197 FEATURE (AESNI ) |
180198 FEATURE (PCLMULQDQ ) |
181199 FEATURE (POPCNT ),
182- .feature_1_edx =
200+ .edx =
183201 FEATURE (PAT ) |
184202 FEATURE (FPU ) |
185203 FEATURE (VME ) |
@@ -202,23 +220,19 @@ void cpuid_init_supported_features(void)
202220 FEATURE (SSE2 ) |
203221 FEATURE (SS ) |
204222 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 =
208228 FEATURE (NX ) |
209229 FEATURE (SYSCALL ) |
210230 FEATURE (RDTSCP ) |
211231 FEATURE (EM64T )
212232 };
213233
214234 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 );
222236}
223237
224238void cpuid_guest_init (hax_cpuid_t * cpuid )
@@ -237,130 +251,170 @@ void cpuid_set_features_mask(hax_cpuid_t *cpuid, uint64_t features_mask)
237251 cpuid -> features_mask = features_mask ;
238252}
239253
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 )
245255{
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 ;
250267}
251268
252269void cpuid_set_guest_features (hax_cpuid_t * cpuid , hax_cpuid * cpuid_info )
253270{
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 ]);
260271 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 );
261279
262280 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 );
267282
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 );
270286 }
271287
272288 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 );
277290}
278291
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 )
281295{
282296 int i ;
283- hax_cpuid_entry * entry , * found = NULL ;
297+ hax_cpuid_entry * entry ;
284298
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 ;
291306 }
292307
293- return found ;
308+ return NULL ;
294309}
295310
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 )
297313{
298- const uint32_t kFunction = 0x01 ;
299- hax_cpuid_entry * entry ;
314+ hax_cpuid_entry * dest , * src , * host_supported , * hax_supported ;
300315
301- entry = find_cpuid_entry (cpuid_info , kFunction , 0 );
302- if (entry == NULL )
316+ if (features == NULL || cpuid_info == NULL )
303317 return ;
304318
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 ;
309322
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 ;
312326
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 );
318331
319- // Set fixed supported features
320- cpuid_set_fixed_features ( cpuid ) ;
332+ if ( host_supported == NULL || hax_supported == NULL )
333+ return ;
321334
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 );
328360}
329361
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 )
331364{
332- const uint32_t kFunction = 0x80000001 ;
365+ const uint32_t kFixedFeatures =
366+ FEATURE (MCE ) |
367+ FEATURE (APIC ) |
368+ FEATURE (MTRR ) |
369+ FEATURE (PAT );
333370 hax_cpuid_entry * entry ;
334371
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 );
336376 if (entry == NULL )
337377 return ;
338378
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+ }
343381
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 ;
345386
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 ;
350389
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 );
354396 }
355397}
356398
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 )
358401{
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+ }
364418
365- cpuid -> feature_1_edx |= kFixedFeatures ;
419+ return -1 ;
366420}
0 commit comments