|
1 | 1 | use crate::error::Result;
|
2 | 2 | use crate::{vcpu, vmexit};
|
| 3 | +use raw_cpuid::CpuIdResult; |
| 4 | +use arrayvec::ArrayVec; |
| 5 | +use core::convert::TryInto; |
| 6 | +use bitfield::bitfield; |
3 | 7 |
|
4 | 8 | //Used https://c9x.me/x86/html/file_module_x86_id_45.html as guid for implementing this.
|
5 | 9 | const CPUID_NAME: u32 = 0;
|
6 | 10 | const CPUID_MODEL_FAMILY_STEPPING: u32 = 1;
|
7 | 11 | const CPUID_CACHE_TLB_INFO: u32 = 2;
|
8 |
| -const INTEL_CORE_CACHE_TOPOLOGY : u32 = 4; |
| 12 | +const INTEL_CORE_CACHE_TOPOLOGY: u32 = 4; |
9 | 13 | const CPUID_BRAND_STRING_1: u32 = 0x80000002;
|
10 | 14 | const CPUID_BRAND_STRING_2: u32 = 0x80000003;
|
11 | 15 | const CPUID_BRAND_STRING_3: u32 = 0x80000004;
|
| 16 | +const MAX_CPUID_INPUT: u32 = 0x80000004; |
12 | 17 | //todo //CPUID leaves above 2 and below 80000000H are visible only when
|
13 | 18 | // // IA32_MISC_ENABLE[bit 22] has its default value of 0.
|
14 | 19 |
|
15 | 20 |
|
| 21 | +// |
| 22 | +// bitfield! { |
| 23 | +// pub struct IntelCoreCacheTopologyEaxRes(u32) |
| 24 | +// impl Debug; |
| 25 | +// impl Copy; |
| 26 | +// |
| 27 | +// } |
16 | 28 |
|
17 |
| -pub fn emulate_cpuid( |
18 |
| - vcpu: &mut vcpu::VCpu, |
19 |
| - guest_cpu: &mut vmexit::GuestCpuState, |
20 |
| -) -> Result<()> { |
21 |
| - let eax = guest_cpu.rax as u32; |
| 29 | +bitfield! { |
| 30 | + pub struct IntelTypeFamilyModelSteppingIDEaxRes(u32); |
| 31 | + impl Debug; |
| 32 | + stepping_id, _: 3,0; |
| 33 | + model,_:7,4; |
| 34 | + family_id,_:11,8; |
| 35 | + processor_type,_:13,12; |
| 36 | + extended_model_id,_:19,16; |
| 37 | + extended_family_id,_:27,20; |
| 38 | +} |
| 39 | + |
| 40 | +fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax: u32, ecx: u32) -> Option<CpuIdResult> { |
| 41 | + const NAME_CREATION_ERROR_MESSAGE: &'static str = "Somehow bytes was not actually a 12 element array"; |
22 | 42 |
|
23 | 43 | match eax {
|
24 | 44 | CPUID_NAME => {
|
25 |
| - if vcpu.vm.read().config.override_cpu_name(){ |
26 |
| - todo!() |
| 45 | + if vcpu.vm.read().config.override_cpu_name() { |
| 46 | + let cpu_name = "MythrilCPU__"; |
| 47 | + let bytes = cpu_name.chars().map(|char| char as u8).collect::<ArrayVec<[u8; 12]>>(); |
| 48 | + let first_bytes: [u8; 4] = bytes[0..4].try_into().expect(NAME_CREATION_ERROR_MESSAGE); |
| 49 | + let second_bytes: [u8; 4] = bytes[4..8].try_into().expect(NAME_CREATION_ERROR_MESSAGE); |
| 50 | + let third_bytes: [u8; 4] = bytes[8..12].try_into().expect(NAME_CREATION_ERROR_MESSAGE); |
| 51 | + return Some(CpuIdResult { |
| 52 | + eax: MAX_CPUID_INPUT, |
| 53 | + ebx: u32::from_le_bytes(first_bytes), |
| 54 | + ecx: u32::from_le_bytes(second_bytes), |
| 55 | + edx: u32::from_le_bytes(third_bytes), |
| 56 | + }); |
27 | 57 | }
|
28 |
| - }, |
29 |
| - CPUID_MODEL_FAMILY_STEPPING => todo!(), |
| 58 | + } |
| 59 | + CPUID_MODEL_FAMILY_STEPPING => { |
| 60 | + |
| 61 | + } |
30 | 62 | INTEL_CORE_CACHE_TOPOLOGY => {
|
31 |
| - _vcpu.vm.read().config.cpus() |
| 63 | + let core_cpus = vcpu.vm.read().config.cpus(); |
| 64 | + |
| 65 | + todo!() |
| 66 | + } |
| 67 | + CPUID_BRAND_STRING_1..=CPUID_BRAND_STRING_2 => { |
| 68 | + if vcpu.vm.read().config.override_cpu_name() { todo!("CPU Brand string not implemented yet") } |
| 69 | + return None; |
32 | 70 | }
|
33 |
| - CPUID_BRAND_STRING_1 => todo!(), |
34 |
| - CPUID_BRAND_STRING_2 => todo!(), |
35 | 71 | _ => {
|
36 |
| - // dbg!(eax); |
37 |
| - // todo!("If you are reading this then a invalid arg was passed to cpuid. In principle we should prob fault here or something, but this probably indicates a bug.") |
| 72 | + //TODO for code review. Idk how I feel about silently fallingback on real cpuid here. |
| 73 | + // I would perhaps prefer to put a todo!() and explicitly implement stuff. |
| 74 | + return None; |
38 | 75 | }
|
39 |
| - } |
| 76 | + }; |
| 77 | + panic!() |
| 78 | +} |
| 79 | + |
| 80 | +pub fn emulate_cpuid( |
| 81 | + vcpu: &mut vcpu::VCpu, |
| 82 | + guest_cpu: &mut vmexit::GuestCpuState, |
| 83 | +) -> Result<()> { |
| 84 | + let eax = guest_cpu.rax as u32; |
| 85 | + |
40 | 86 |
|
41 | 87 | //FIXME: for now just use the actual cpuid
|
42 | 88 | let mut res = raw_cpuid::native_cpuid::cpuid_count(
|
|
0 commit comments