Bit64s BX_CPU_C::param_restore(bx_param_c *param, Bit64s val) { #else UNUSED(devptr); #endif // !BX_USE_CPU_SMF const char *pname, *segname; bx_segment_reg_t *segment = NULL; pname = param->get_name(); if (!strcmp(pname, "cpu_version")) { if (val != get_cpu_version_information()) { BX_PANIC(("save/restore: CPU version mismatch")); } } else if (!strcmp(pname, "cpuid_std")) { if (val != get_std_cpuid_features()) { BX_PANIC(("save/restore: CPUID mismatch")); } } else if (!strcmp(pname, "cpuid_ext")) { if (val != get_extended_cpuid_features()) { BX_PANIC(("save/restore: CPUID mismatch")); } } else if (!strcmp(pname, "EFLAGS")) { BX_CPU_THIS_PTR setEFlags((Bit32u)val); #if BX_SUPPORT_X86_64 } else if (!strcmp(pname, "EFER")) { BX_CPU_THIS_PTR efer.sce = (val >> 0) & 1; BX_CPU_THIS_PTR efer.lme = (val >> 8) & 1; BX_CPU_THIS_PTR efer.lma = (val >> 10) & 1; BX_CPU_THIS_PTR efer.nxe = (val >> 11) & 1; BX_CPU_THIS_PTR efer.ffxsr = (val >> 14) & 1; #endif } else if (!strcmp(pname, "ar_byte") || !strcmp(pname, "selector")) {
/* Get CPU feature flags. Returned by CPUID function 80000001 in EDX register */ Bit32u bx_generic_cpuid_t::get_std2_cpuid_features(void) const { // Many of the bits in EDX are the same as EAX [*] for AMD // [*] [0:0] FPU on chip // [*] [1:1] VME: Virtual-8086 Mode enhancements // [*] [2:2] DE: Debug Extensions (I/O breakpoints) // [*] [3:3] PSE: Page Size Extensions // [*] [4:4] TSC: Time Stamp Counter // [*] [5:5] MSR: RDMSR and WRMSR support // [*] [6:6] PAE: Physical Address Extensions // [*] [7:7] MCE: Machine Check Exception // [*] [8:8] CXS: CMPXCHG8B instruction // [*] [9:9] APIC: APIC on Chip // [10:10] Reserved // [11:11] SYSCALL/SYSRET support // [*] [12:12] MTRR: Memory Type Range Reg // [*] [13:13] PGE/PTE Global Bit // [*] [14:14] MCA: Machine Check Architecture // [*] [15:15] CMOV: Cond Mov/Cmp Instructions // [*] [16:16] PAT: Page Attribute Table // [*] [17:17] PSE-36: Physical Address Extensions // [18:19] Reserved // [20:20] No-Execute page protection // [21:21] Reserved // [22:22] AMD MMX Extensions // [*] [23:23] MMX Technology // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] Fast FXSAVE/FXRSTOR mode support // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions Bit32u features = BX_CPU_VENDOR_INTEL ? 0 : get_std_cpuid_features(); features &= 0x0183F3FF; #if BX_SUPPORT_3DNOW // only AMD is interesting in AMD MMX extensions features |= BX_CPUID_STD2_AMD_MMX_EXT | BX_CPUID_STD2_3DNOW_EXT | BX_CPUID_STD2_3DNOW; #endif #if BX_SUPPORT_X86_64 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) { features |= BX_CPUID_STD2_LONG_MODE; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_RDTSCP)) features |= BX_CPUID_STD2_RDTSCP; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_NX)) features |= BX_CPUID_STD2_NX; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_FFXSR)) features |= BX_CPUID_STD2_FFXSR; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_1G_PAGES)) features |= BX_CPUID_STD2_1G_PAGES; if (cpu->long64_mode()) features |= BX_CPUID_STD2_SYSCALL_SYSRET; } #endif return features; }
Bit64s BX_CPU_C::param_save(bx_param_c *param, Bit64s val) { #else UNUSED(devptr); #endif // !BX_USE_CPU_SMF const char *pname, *segname; bx_segment_reg_t *segment = NULL; pname = param->get_name(); if (!strcmp(pname, "cpu_version")) { val = get_cpu_version_information(); } else if (!strcmp(pname, "cpuid_std")) { val = get_std_cpuid_features(); } else if (!strcmp(pname, "cpuid_ext")) { val = get_extended_cpuid_features(); } else if (!strcmp(pname, "EFLAGS")) { val = BX_CPU_THIS_PTR read_eflags(); #if BX_SUPPORT_X86_64 } else if (!strcmp(pname, "EFER")) { val = BX_CPU_THIS_PTR get_EFER(); #endif } else if (!strcmp(pname, "ar_byte") || !strcmp(pname, "selector")) { segname = param->get_parent()->get_name(); if (!strcmp(segname, "CS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS]; } else if (!strcmp(segname, "DS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; } else if (!strcmp(segname, "SS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS]; } else if (!strcmp(segname, "ES")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES]; } else if (!strcmp(segname, "FS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS]; } else if (!strcmp(segname, "GS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS]; } else if (!strcmp(segname, "LDTR")) { segment = &BX_CPU_THIS_PTR ldtr; } else if (!strcmp(segname, "TR")) { segment = &BX_CPU_THIS_PTR tr; } if (segment != NULL) { if (!strcmp(pname, "ar_byte")) { val = ar_byte(&(segment->cache)); } else if (!strcmp(pname, "selector")) { val = segment->selector.value; } } } else { BX_PANIC(("Unknown param %s in param_save handler !", pname)); } return val; }
// leaf 0x00000001 // void bx_generic_cpuid_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = get_cpu_version_information(); // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID leaf->ebx = 0; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CLFLUSH)) { leaf->ebx |= (CACHE_LINE_SIZE / 8) << 8; } #if BX_SUPPORT_SMP unsigned n_logical_processors = ncores*nthreads; #else unsigned n_logical_processors = 1; #endif leaf->ebx |= (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags #if BX_CPU_LEVEL >= 6 leaf->ecx = get_extended_cpuid_features(); #else leaf->ecx = 0; #endif // EDX: Standard Feature Flags leaf->edx = get_std_cpuid_features(); }
void BX_CPU_C::set_cpuid_defaults(void) { cpuid_function_t *cpuid; int i; for (i=0;i<MAX_STD_CPUID_FUNCTION;i++) { BX_CPU_THIS_PTR cpuid_std_function[i].eax = 0; BX_CPU_THIS_PTR cpuid_std_function[i].ebx = 0; BX_CPU_THIS_PTR cpuid_std_function[i].ecx = 0; BX_CPU_THIS_PTR cpuid_std_function[i].edx = 0; } for (i=0;i<MAX_EXT_CPUID_FUNCTION;i++) { BX_CPU_THIS_PTR cpuid_ext_function[i].eax = 0; BX_CPU_THIS_PTR cpuid_ext_function[i].ebx = 0; BX_CPU_THIS_PTR cpuid_ext_function[i].ecx = 0; BX_CPU_THIS_PTR cpuid_ext_function[i].edx = 0; } // ------------------------------------------------------ // CPUID function 0x00000000 cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[0]); // EAX: highest input value understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string #if BX_CPU_LEVEL <= 5 // 486 and Pentium processors cpuid->eax = 1; #else // for Pentium Pro, Pentium II, Pentium 4 processors cpuid->eax = 2; if (BX_SUPPORT_MONITOR_MWAIT) cpuid->eax = 0x5; if (BX_SUPPORT_XSAVE) cpuid->eax = 0xD; #endif #if BX_CPU_VENDOR_INTEL cpuid->ebx = 0x756e6547; // "Genu" cpuid->edx = 0x49656e69; // "ineI" cpuid->ecx = 0x6c65746e; // "ntel" #else cpuid->ebx = 0x68747541; // "Auth" cpuid->edx = 0x69746e65; // "enti" cpuid->ecx = 0x444d4163; // "cAMD" #endif // ------------------------------------------------------ // CPUID function 0x00000001 cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[1]); // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [31:14] Reserved cpuid->eax = get_cpu_version_information(); // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID cpuid->ebx = 0; #if BX_SUPPORT_APIC cpuid->ebx |= (BX_CPU_THIS_PTR local_apic.get_id() << 24); #endif #if BX_SUPPORT_CLFLUSH cpuid->ebx |= (CACHE_LINE_SIZE / 8) << 8; #endif #if BX_SUPPORT_SMP unsigned n_logical_processors = SIM->get_param_num(BXPN_CPU_NCORES)->get()*SIM->get_param_num(BXPN_CPU_NTHREADS)->get(); if (n_logical_processors > 1) cpuid->ebx |= (n_logical_processors << 16); #endif // ECX: Extended Feature Flags // [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // [2:2] reserved // [3:3] MONITOR/MWAIT support // [4:4] DS-CPL: CPL qualified debug store // [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // [7:7] EST: Enhanced Intel SpeedStep Technology // [8:8] TM2: Thermal Monitor 2 // [9:9] SSE3E: SSE3E Instructions (Intel Core Duo 2 new instructions) // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // [13:13] CMPXCHG16B: CMPXCHG16B instruction support // [14:14] xTPR update control // [17:15] reserved // [18:18] DCA - Direct Cache Access // [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:22] X2APIC // [22:22] Reserved // [23:23] POPCNT instruction // [24:24] reserved // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [31:29] reserved cpuid->ecx = get_extended_cpuid_features(); // EDX: Feature Flags // [0:0] FPU on chip // [1:1] VME: Virtual-8086 Mode enhancements // [2:2] DE: Debug Extensions (I/O breakpoints) // [3:3] PSE: Page Size Extensions // [4:4] TSC: Time Stamp Counter // [5:5] MSR: RDMSR and WRMSR support // [6:6] PAE: Physical Address Extensions // [7:7] MCE: Machine Check Exception // [8:8] CXS: CMPXCHG8B instruction // [9:9] APIC: APIC on Chip // [10:10] Reserved // [11:11] SYSENTER/SYSEXIT support // [12:12] MTRR: Memory Type Range Reg // [13:13] PGE/PTE Global Bit // [14:14] MCA: Machine Check Architecture // [15:15] CMOV: Cond Mov/Cmp Instructions // [16:16] PAT: Page Attribute Table // [17:17] PSE-36: Physical Address Extensions // [18:18] Processor Serial Number // [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // [23:23] MMX Technology // [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] SSE: SSE Extensions // [26:26] SSE2: SSE2 Extensions // [27:27] Reserved // [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable cpuid->edx = get_std_cpuid_features(); #if BX_CPU_LEVEL >= 6 // ------------------------------------------------------ // CPUID function 0x00000002 - Cache and TLB Descriptors cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[2]); #if BX_CPU_VENDOR_INTEL cpuid->eax = 0x00410601; // for Pentium Pro compatibility cpuid->ebx = 0; cpuid->ecx = 0; cpuid->edx = 0; #else cpuid->eax = 0; // ignore for AMD cpuid->ebx = 0; cpuid->ecx = 0; cpuid->edx = 0; #endif // ------------------------------------------------------ // CPUID function 0x00000003 - Processor Serial Number cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[3]); cpuid->eax = 0; cpuid->ebx = 0; cpuid->ecx = 0; cpuid->edx = 0; // ------------------------------------------------------ // CPUID function 0x00000004 - Deterministic Cache Parameters cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[4]); cpuid->eax = 0; cpuid->ebx = 0; cpuid->ecx = 0; cpuid->edx = 0; #if BX_SUPPORT_MONITOR_MWAIT // ------------------------------------------------------ // CPUID function 0x00000005 cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[5]); // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - Reserved cpuid->eax = CACHE_LINE_SIZE; cpuid->ebx = CACHE_LINE_SIZE; cpuid->ecx = 3; cpuid->edx = 0; #endif #if BX_SUPPORT_XSAVE // ------------------------------------------------------ // CPUID function 0x0000000D cpuid = &(BX_CPU_THIS_PTR cpuid_std_function[0xD]); // EAX - XCR0 lower 32 bits // EBX - Maximum size (in bytes) required by enabled features // ECX - Maximum size (in bytes) required by CPU supported features // EDX - XCR0 upper 32 bits cpuid->eax = BX_CPU_THIS_PTR xcr0.getRegister(); cpuid->ebx = 512+64; cpuid->ecx = 512+64; cpuid->edx = 0; #endif #if BX_SUPPORT_SSE >= 2 // report Pentium 4 extended functions // ------------------------------------------------------ // CPUID function 0x80000000 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[0]); // EAX: highest input value understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string cpuid->eax = BX_SUPPORT_X86_64 ? 0x80000008 : 0x80000004; #if BX_CPU_VENDOR_INTEL cpuid->ebx = 0; cpuid->edx = 0; // Reserved for Intel cpuid->ecx = 0; #else cpuid->ebx = 0x68747541; // "Auth" cpuid->edx = 0x69746e65; // "enti" cpuid->ecx = 0x444d4163; // "cAMD" #endif // ------------------------------------------------------ // CPUID function 0x80000001 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[1]); // EAX: CPU Version Information cpuid->eax = BX_CPU_VENDOR_INTEL ? 0 : get_cpu_version_information(); // EBX: Brand ID cpuid->ebx = 0; // ECX: // [0:0] LAHF/SAHF available in 64-bit mode // [1:1] AMD CmpLegacy // [2:2] AMD Secure Virtual Machine Technology // [3:3] Extended APIC Space // [4:4] Alternative CR8 (treat lock mov cr0 as mov cr8) // [5:5] LZCNT support // [6:6] SSE4A support // [7:7] Misaligned SSE support // [8:8] 3DNow! prefetch support // [9:9] OS visible workarounds // [10:10] Reserved // [11:11] SSE5A // [12:31] Reserved #if BX_SUPPORT_X86_64 cpuid->ecx = 1 | (1<<8); #endif #if BX_SUPPORT_MISALIGNED_SSE cpuid->ecx |= (1<<7); #endif // EDX: // Many of the bits in EDX are the same as EAX [*] for AMD // [*] [0:0] FPU on chip // [*] [1:1] VME: Virtual-8086 Mode enhancements // [*] [2:2] DE: Debug Extensions (I/O breakpoints) // [*] [3:3] PSE: Page Size Extensions // [*] [4:4] TSC: Time Stamp Counter // [*] [5:5] MSR: RDMSR and WRMSR support // [*] [6:6] PAE: Physical Address Extensions // [*] [7:7] MCE: Machine Check Exception // [*] [8:8] CXS: CMPXCHG8B instruction // [*] [9:9] APIC: APIC on Chip // [10:10] Reserved // [11:11] SYSCALL/SYSRET support // [*] [12:12] MTRR: Memory Type Range Reg // [*] [13:13] PGE/PTE Global Bit // [*] [14:14] MCA: Machine Check Architecture // [*] [15:15] CMOV: Cond Mov/Cmp Instructions // [*] [16:16] PAT: Page Attribute Table // [*] [17:17] PSE-36: Physical Address Extensions // [18:19] Reserved // [20:20] No-Execute page protection // [21:21] Reserved // [22:22] AMD MMX Extensions // [*] [23:23] MMX Technology // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] Fast FXSAVE/FXRSTOR mode support // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions unsigned features = BX_CPU_VENDOR_INTEL ? 0 : get_std_cpuid_features(); features &= 0x0183F3FF; #if BX_SUPPORT_3DNOW features |= (1 << 22) | (1 << 30) | (1 << 31); // only AMD is interesting in AMD MMX extensions #endif #if BX_SUPPORT_X86_64 features |= (1 << 29) | (1 << 27) | (1 << 25) | (1 << 20) | (1 << 11); #endif cpuid->edx = features; #if BX_CPU_VENDOR_INTEL // Processor Brand String, use the value that is returned // by the first processor in the Pentium 4 family // (according to Intel manual) // ------------------------------------------------------ // CPUID function 0x80000002 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[2]); cpuid->eax = 0x20202020; // " " cpuid->ebx = 0x20202020; // " " cpuid->ecx = 0x20202020; // " " cpuid->edx = 0x6E492020; // " In" // CPUID function 0x80000003 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[3]); cpuid->eax = 0x286C6574; // "tel(" cpuid->ebx = 0x50202952; // "R) P" cpuid->ecx = 0x69746E65; // "enti" cpuid->edx = 0x52286D75; // "um(R" // CPUID function 0x80000004 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[4]); cpuid->eax = 0x20342029; // ") 4 " cpuid->ebx = 0x20555043; // "CPU " cpuid->ecx = 0x20202020; // " " cpuid->edx = 0x00202020; // " " #else // Processor Brand String, use the value given // in AMD manuals. // ------------------------------------------------------ // CPUID function 0x80000002 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[2]); cpuid->eax = 0x20444D41; // "AMD " cpuid->ebx = 0x6C687441; // "Athl" cpuid->ecx = 0x74286E6F; // "on(t" cpuid->edx = 0x7020296D; // "m) p" // ------------------------------------------------------ // CPUID function 0x80000003 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[3]); cpuid->eax = 0x65636F72; // "roce" cpuid->ebx = 0x726F7373; // "ssor" cpuid->ecx = 0x00000000; cpuid->edx = 0x00000000; // ------------------------------------------------------ // CPUID function 0x80000004 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[4]); cpuid->eax = 0x00000000; cpuid->ebx = 0x00000000; cpuid->ecx = 0x00000000; cpuid->edx = 0x00000000; #endif #if BX_SUPPORT_X86_64 // ------------------------------------------------------ // CPUID function 0x80000005 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[5]); /* cache info (L1 cache) */ cpuid->eax = 0x01ff01ff; cpuid->ebx = 0x01ff01ff; cpuid->ecx = 0x40020140; cpuid->edx = 0x40020140; // ------------------------------------------------------ // CPUID function 0x80000006 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[6]); /* cache info (L2 cache) */ cpuid->eax = 0; cpuid->ebx = 0x42004200; cpuid->ecx = 0x02008140; cpuid->edx = 0; // ------------------------------------------------------ // CPUID function 0x00000007 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[7]); cpuid->eax = 0; cpuid->ebx = 0; cpuid->ecx = 0; cpuid->edx = 0; // ------------------------------------------------------ // CPUID function 0x80000008 cpuid = &(BX_CPU_THIS_PTR cpuid_ext_function[8]); // virtual & phys address size in low 2 bytes. cpuid->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); cpuid->ebx = 0; cpuid->ecx = 0; // Reserved, undefined cpuid->edx = 0; #endif // BX_SUPPORT_X86_64 #endif // BX_SUPPORT_SSE >= 2 #endif // BX_CPU_LEVEL >= 6 }