---------------------------------------------------------------------- Patch name: patch.x86-64-cpuid Author: Paul Brook Date: Sun Jan 5 2003 Detailed description: The attached patch fixes CPUID function 0x80000001 for x86-64 emulation Without it recent kernels refuse to boot, complaining about missing features. Patch was created with: cvs diff -u Apply patch to what version: cvs checked out on Sun Jan 5 2003 Instructions: To patch, go to main bochs directory. Type "patch -p0 < THIS_PATCH_FILE". ---------------------------------------------------------------------- Index: cpu/proc_ctrl.cc =================================================================== RCS file: /cvsroot/bochs/bochs/cpu/proc_ctrl.cc,v retrieving revision 1.63 diff -u -r1.63 proc_ctrl.cc --- cpu/proc_ctrl.cc 13 Nov 2002 21:00:04 -0000 1.63 +++ cpu/proc_ctrl.cc 5 Jan 2003 02:11:11 -0000 @@ -1334,36 +1334,12 @@ #endif } - - void -BX_CPU_C::CPUID(bxInstruction_c *i) +/* Get CPU feature flags. Returned by CPUID functions 1 and 80000001. */ + static inline Bit32u +get_std_cpuid_features() { -#if BX_CPU_LEVEL >= 4 - unsigned type, family, model, stepping, features; -#endif + unsigned features; - invalidate_prefetch_q(); - -#if BX_CPU_LEVEL >= 4 - switch (EAX) { - case 0: - // EAX: highest input value understood by CPUID - // EBX: vendor ID string - // EDX: vendor ID string - // ECX: vendor ID string - RAX = 1; // 486 or pentium -#if BX_SUPPORT_X86_64 - RBX = 0x68747541; // "Auth" - RDX = 0x69746e65; // "enti" - RCX = 0x444d4163; // "cAMD" -#else - RBX = 0x756e6547; // "Genu" - RDX = 0x49656e69; // "ineI" - RCX = 0x6c65746e; // "ntel" -#endif - break; - - case 1: // EAX[3:0] Stepping ID // EAX[7:4] Model: starts at 1 // EAX[11:8] Family: 4=486, 5=Pentium, 6=PPro @@ -1397,52 +1373,24 @@ // [31:30] Reserved features = 0; // start with none - type = 0; // OEM -#if BX_CPU_LEVEL == 4 - family = 4; # if BX_SUPPORT_FPU - // 486dx - model = 1; - stepping = 3; features |= 0x01; -# else - // 486sx - model = 2; - stepping = 3; # endif -#elif BX_CPU_LEVEL == 5 - family = 5; - model = 1; // Pentium (60,66) - stepping = 3; // ??? +#if (BX_CPU_LEVEL >= 5) + features |= (1<<8); // Support CMPXCHG8B instruction features |= (1<<4); // implement TSC -# if BX_SUPPORT_FPU - features |= 0x01; -# endif # if BX_SUPPORT_MMX features |= (1<<23); // support MMX # endif - -#elif BX_CPU_LEVEL == 6 - family = 6; -#if BX_SUPPORT_X86_64 - model = 2; // Hammer returns what? -#else - model = 1; // Pentium Pro #endif - stepping = 3; // ??? - features |= (1<<4); // implement TSC + +#if BX_CPU_LEVEL == 6 features |= (1<<15); // Implement CMOV instructions. # if BX_SUPPORT_APIC features |= (1<<9); // APIC on chip # endif -# if BX_SUPPORT_FPU - features |= 0x01; // support FPU -# endif -# if BX_SUPPORT_MMX - features |= (1<<23); // support MMX -# endif # if BX_SUPPORT_SSE >= 1 features |= (1<<24); // support FSAVE/FXRSTOR features |= (1<<25); // support SSE @@ -1450,9 +1398,6 @@ # if BX_SUPPORT_SSE >= 2 features |= (1<<26); // support SSE2 # endif - -#else - BX_PANIC(("CPUID: not implemented for > 6")); #endif #if BX_SUPPORT_4MEG_PAGES @@ -1467,14 +1412,75 @@ features |= (1<<6); // Support PAE. #endif -#if (BX_CPU_LEVEL >= 5) - features |= (1<<8); // Support CMPXCHG8B instruction +#if BX_SUPPORT_X86_64 + features |= (1<<5); //AMD specific MSR's +#endif + + return features; +} + + void +BX_CPU_C::CPUID(bxInstruction_c *i) +{ +#if BX_CPU_LEVEL >= 4 + unsigned type, family, model, stepping, features; #endif + invalidate_prefetch_q(); + +#if BX_CPU_LEVEL >= 4 + switch (EAX) { + case 0: + // EAX: highest input value understood by CPUID + // EBX: vendor ID string + // EDX: vendor ID string + // ECX: vendor ID string + RAX = 1; // 486 or pentium +#if BX_SUPPORT_X86_64 + RBX = 0x68747541; // "Auth" + RDX = 0x69746e65; // "enti" + RCX = 0x444d4163; // "cAMD" +#else + RBX = 0x756e6547; // "Genu" + RDX = 0x49656e69; // "ineI" + RCX = 0x6c65746e; // "ntel" +#endif + break; + + case 1: + +#if BX_CPU_LEVEL == 4 + family = 4; +# if BX_SUPPORT_FPU + // 486dx + model = 1; + stepping = 3; +# else + // 486sx + model = 2; + stepping = 3; +# endif + +#elif BX_CPU_LEVEL == 5 + family = 5; + model = 1; // Pentium (60,66) + stepping = 3; // ??? + +#elif BX_CPU_LEVEL == 6 + family = 6; +#if BX_SUPPORT_X86_64 + model = 2; // Hammer returns what? +#else + model = 1; // Pentium Pro +#endif + stepping = 3; // ??? +#else + BX_PANIC(("CPUID: not implemented for > 6")); +#endif RAX = (family <<8) | (model<<4) | stepping; RBX = RCX = 0; // reserved - RDX = features; + RDX = get_std_cpuid_features (); break; #if BX_SUPPORT_X86_64 @@ -1489,9 +1495,23 @@ case 0x80000001: // long mode supported. - // bug in manual - should be EDX not EAX - RDX = (1 << 29); - RAX = RBX = RCX = 0; + features = get_std_cpuid_features (); + RAX = features; + // Many of the bits in EDX are the same as EAX + // [10:10] Reserved + // [11:11] SYSCALL and SYSRET instructions + // [18:19] Reserved + // [20:20] No-Execute page protection + // [21:21] Reserved + // [22:22] AMD MMX Extensions + // [25:28] Reserved + // [29:29] Long Mode + // [30:30] AMD 3DNow Extensions + // [31:31] AMD 3DNow Intructions + features = features & 0x0183F3FF; + RDX = features | (1 << 29) | (1 << 11); + // RAX = RBX = RCX = 0; + RBX = RCX = 0; break; case 0x80000008: