@@ -6,6 +6,7 @@ use core::convert::TryInto;
6
6
use bitfield:: bitfield;
7
7
use bitflags:: _core:: num:: flt2dec:: to_shortest_exp_str;
8
8
use crate :: apic:: get_local_apic;
9
+ use crate :: vcpu:: VCpu ;
9
10
10
11
//Used https://c9x.me/x86/html/file_module_x86_id_45.html as guid for implementing this.
11
12
const CPUID_NAME : u32 = 0 ;
@@ -28,25 +29,7 @@ const MAX_CPUID_INPUT: u32 = 0x80000004;
28
29
//
29
30
// }
30
31
31
- bitfield ! {
32
- pub struct IntelTypeFamilyModelSteppingIDEaxRes ( u32 ) ;
33
- impl Debug ;
34
- stepping_id, _: 3 , 0 ;
35
- model, _: 7 , 4 ;
36
- family_id, _: 11 , 8 ;
37
- processor_type, _: 13 , 12 ;
38
- extended_model_id, _: 19 , 16 ;
39
- extended_family_id, _: 27 , 20 ;
40
- }
41
32
42
- bitfield ! {
43
- pub struct BrandCFlushMaxIDsInitialAPIC ( u32 ) ;
44
- impl Debug ;
45
- brand_idx, _: 7 , 0 ;
46
- cflush, _: 15 , 8 ;
47
- max_processor_ids, _: 23 , 16 ;
48
- apic_id, _: 31 , 24 ;
49
- }
50
33
51
34
52
35
fn get_cpu_id_result ( vcpu : & vcpu:: VCpu , eax_in : u32 , ecx_in : u32 ) -> CpuIdResult {
@@ -59,33 +42,8 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
59
42
) ;
60
43
61
44
match eax_in {
62
- CPUID_NAME => cpuid_name ( vcpu, & mut actual) ,
63
- CPUID_MODEL_FAMILY_STEPPING => {
64
- let family_model_stepping = IntelTypeFamilyModelSteppingIDEaxRes ( actual. eax ) ;
65
- //we can change family_model_stepping, but for now just use actual.
66
- let eax = family_model_stepping. 0 ;
67
- let mut brand_cflush_max_initial = BrandCFlushMaxIDsInitialAPIC ( actual. ebx ) ;
68
- brand_cflush_max_initial. set_apic_id ( get_local_apic ( ) . id ( ) ) ; //in principle this is redundant
69
- let ebx = brand_cflush_max_initial. 0 ;
70
- let mut ecx = actual. ecx ;
71
- let mut edx = actual. edx ;
72
- // I would have made type safe bindings for this but then I saw how many fields there where...
73
-
74
- // Disable MTRR
75
- edx &= !( 1 << 12 ) ;
76
-
77
- // Disable XSAVE
78
- ecx &= !( 1 << 26 ) ;
79
-
80
- // Hide hypervisor feature
81
- ecx &= !( 1 << 31 ) ;
82
- CpuIdResult {
83
- eax,
84
- ebx,
85
- ecx,
86
- edx
87
- }
88
- }
45
+ CPUID_NAME => cpuid_name ( vcpu, actual) ,
46
+ CPUID_MODEL_FAMILY_STEPPING => cpuid_model_family_stepping ( actual)
89
47
INTEL_CORE_CACHE_TOPOLOGY => {
90
48
let core_cpus = vcpu. vm . read ( ) . config . cpus ( ) ;
91
49
@@ -103,7 +61,71 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
103
61
}
104
62
}
105
63
106
- fn cpuid_name ( vcpu : & VCpu , actual : & mut CpuIdResult ) -> CpuIdResult {
64
+ bitfield ! {
65
+ pub struct IntelTypeFamilyModelSteppingIDEaxRes ( u32 ) ;
66
+ impl Debug ;
67
+ stepping_id, _: 3 , 0 ;
68
+ model, _: 7 , 4 ;
69
+ family_id, _: 11 , 8 ;
70
+ processor_type, _: 13 , 12 ;
71
+ extended_model_id, _: 19 , 16 ;
72
+ extended_family_id, _: 27 , 20 ;
73
+ }
74
+
75
+ bitfield ! {
76
+ pub struct BrandCFlushMaxIDsInitialAPIC ( u32 ) ;
77
+ impl Debug ;
78
+ brand_idx, _: 7 , 0 ;
79
+ cflush, _: 15 , 8 ;
80
+ max_processor_ids, _: 23 , 16 ;
81
+ apic_id, _: 31 , 24 ;
82
+ }
83
+
84
+ bitfield ! {
85
+ pub struct FeatureInformationECX ( u32 ) ;
86
+ //there are a lot of features here, so only add the ones we care about for now.
87
+ xsave, _: 27 , 26 ;
88
+ hypervissor, _: 32 , 31 ;
89
+ }
90
+
91
+ bitfield ! {
92
+ pub struct FeatureInformationEDX ( u32 ) ;
93
+ //there are a lot of features here, so only add the ones we care about for now.
94
+ mtrr, _: 13 , 12 ;
95
+ }
96
+
97
+ fn cpuid_model_family_stepping ( actual : CpuIdResult ) -> CpuIdResult {
98
+ let family_model_stepping = IntelTypeFamilyModelSteppingIDEaxRes ( actual. eax ) ;
99
+ //we can change family_model_stepping, but for now just use actual.
100
+ let eax = family_model_stepping. 0 ;
101
+ let mut brand_cflush_max_initial = BrandCFlushMaxIDsInitialAPIC ( actual. ebx ) ;
102
+ brand_cflush_max_initial. set_apic_id ( todo ! ( "Waiting on virtual APICs" ) ) ;
103
+ brand_cflush_max_initial. set_max_processor_ids ( todo ! ( "Waiting on virtual APICs" ) ) ;
104
+ let ebx = brand_cflush_max_initial. 0 ;
105
+ let mut features_ecx = FeatureInformationECX ( actual. ecx ) ;
106
+ let mut features_edx = FeatureInformationEDX ( actual. edx ) ;
107
+ // I would have made type safe bindings for this but then I saw how many fields there where...
108
+
109
+ // Disable MTRR
110
+ features_edx. set_mtrr ( 0 ) ;
111
+
112
+ // Disable XSAVE
113
+ // ecx &= !(1 << 26);
114
+ features_ecx. set_xsave ( 0 ) ;
115
+
116
+ // Hide hypervisor feature
117
+ features_ecx. set_hypervisor ( 0 ) ;
118
+ let ecx = features_ecx. 0 ;
119
+ let edx = features_edx. 0 ;
120
+ CpuIdResult {
121
+ eax,
122
+ ebx,
123
+ ecx,
124
+ edx
125
+ }
126
+ }
127
+
128
+ fn cpuid_name ( vcpu : & VCpu , actual : CpuIdResult ) -> CpuIdResult {
107
129
if vcpu. vm . read ( ) . config . override_cpu_name ( ) {
108
130
let cpu_name = "MythrilCPU__" ;
109
131
let bytes = cpu_name. chars ( ) . map ( |char| char as u8 ) . collect :: < ArrayVec < [ u8 ; 12 ] > > ( ) ;
@@ -132,14 +154,11 @@ pub fn emulate_cpuid(
132
154
//todo move this into get_cpu_id_result
133
155
if guest_cpu. rax as u32 == 1 {
134
156
135
- <<<<<<< HEAD
136
157
// Hide hypervisor feature
137
158
res. ecx &= !( 1 << 31 ) ;
138
159
139
160
// Hide TSC deadline timer
140
161
res. ecx &= !( 1 << 24 ) ;
141
- =======
142
- >>>>>>> handle CPUID_MODEL_FAMILY_STEPPING
143
162
}
144
163
145
164
guest_cpu. rax = res. eax as u64 | ( guest_cpu. rax & 0xffffffff00000000 ) ;
0 commit comments