@@ -6,6 +6,7 @@ use core::convert::TryInto;
66use bitfield:: bitfield;
77use bitflags:: _core:: num:: flt2dec:: to_shortest_exp_str;
88use crate :: apic:: get_local_apic;
9+ use crate :: vcpu:: VCpu ;
910
1011//Used https://c9x.me/x86/html/file_module_x86_id_45.html as guid for implementing this.
1112const CPUID_NAME : u32 = 0 ;
@@ -28,25 +29,7 @@ const MAX_CPUID_INPUT: u32 = 0x80000004;
2829//
2930// }
3031
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- }
4132
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- }
5033
5134
5235fn 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
5942 ) ;
6043
6144 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)
8947 INTEL_CORE_CACHE_TOPOLOGY => {
9048 let core_cpus = vcpu. vm . read ( ) . config . cpus ( ) ;
9149
@@ -103,7 +61,71 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
10361 }
10462}
10563
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 {
107129 if vcpu. vm . read ( ) . config . override_cpu_name ( ) {
108130 let cpu_name = "MythrilCPU__" ;
109131 let bytes = cpu_name. chars ( ) . map ( |char| char as u8 ) . collect :: < ArrayVec < [ u8 ; 12 ] > > ( ) ;
@@ -129,10 +151,6 @@ pub fn emulate_cpuid(
129151 let ecx = guest_cpu. rcx as u32 ;
130152 let mut res = get_cpu_id_result ( vcpu, eax, ecx) ;
131153
132- //todo move this into get_cpu_id_result
133- if guest_cpu. rax as u32 == 1 {
134-
135- }
136154
137155 guest_cpu. rax = res. eax as u64 | ( guest_cpu. rax & 0xffffffff00000000 ) ;
138156 guest_cpu. rbx = res. ebx as u64 | ( guest_cpu. rbx & 0xffffffff00000000 ) ;
0 commit comments