From 8eece1c00cda2275d6184f6c96844f9b2e8c3181 Mon Sep 17 00:00:00 2001 From: Tomas Hruby Date: Thu, 23 Sep 2010 14:42:19 +0000 Subject: [PATCH] CPU type detection - sometimes the system needs to know precisely on what type of cpu is running. The cpu type id detected during arch specific initialization and kept in the machine structure for later use. - as a side-effect the information is exported to userland --- include/minix/type.h | 8 +++++++ kernel/arch/i386/arch_system.c | 35 ++++++++++++++++++++++++++++ kernel/arch/i386/include/archconst.h | 4 ++++ 3 files changed, 47 insertions(+) diff --git a/include/minix/type.h b/include/minix/type.h index 7e8c9ff16..5cf9bcef9 100644 --- a/include/minix/type.h +++ b/include/minix/type.h @@ -120,6 +120,13 @@ struct loadinfo { clock_t last_clock; }; +struct cpu_type { + u8_t vendor; + u8_t family; + u8_t model; + u8_t stepping; +}; + struct machine { int pc_at; int ps_mca; @@ -131,6 +138,7 @@ struct machine { int vdu_vga; int apic_enabled; /* does the kernel use APIC or not? */ phys_bytes acpi_rsdp; /* where is the acpi RSDP */ + struct cpu_type cpu_type; }; struct io_range diff --git a/kernel/arch/i386/arch_system.c b/kernel/arch/i386/arch_system.c index fbc9b14e7..14cf4e661 100644 --- a/kernel/arch/i386/arch_system.c +++ b/kernel/arch/i386/arch_system.c @@ -304,8 +304,43 @@ PUBLIC void restore_fpu(struct proc *pr) } } +PRIVATE void cpu_identify(void) +{ + u32_t eax, ebx, ecx, edx; + + eax = 0; + _cpuid(&eax, &ebx, &ecx, &edx); + + if (ebx == INTEL_CPUID_GEN_EBX && ecx == INTEL_CPUID_GEN_ECX && + edx == INTEL_CPUID_GEN_EDX) { + machine.cpu_type.vendor = CPU_VENDOR_INTEL; + printf("Genuine Intel found\n"); + } else if (ebx == AMD_CPUID_GEN_EBX && ecx == AMD_CPUID_GEN_ECX && + edx == AMD_CPUID_GEN_EDX) { + machine.cpu_type.vendor = CPU_VENDOR_AMD; + printf("Authentic AMD found\n"); + } else + machine.cpu_type.vendor = CPU_VENDOR_UNKNOWN; + + if (eax == 0) + return; + + eax = 1; + _cpuid(&eax, &ebx, &ecx, &edx); + + machine.cpu_type.family = (eax >> 8) & 0xf; + if (machine.cpu_type.family == 0xf) + machine.cpu_type.family += (eax >> 20) & 0xff; + machine.cpu_type.model = (eax >> 4) & 0xf; + if (machine.cpu_type.model == 0xf || machine.cpu_type.model == 0x6) + machine.cpu_type.model += ((eax >> 16) & 0xf) << 4 ; + machine.cpu_type.stepping = eax & 0xf; +} + PUBLIC void arch_init(void) { + cpu_identify(); + #ifdef CONFIG_APIC /* * this is setting kernel segments to cover most of the phys memory. The diff --git a/kernel/arch/i386/include/archconst.h b/kernel/arch/i386/include/archconst.h index d66f19275..2019e9c68 100644 --- a/kernel/arch/i386/include/archconst.h +++ b/kernel/arch/i386/include/archconst.h @@ -153,6 +153,10 @@ #define AMD_CPUID_GEN_EDX 0x69746e65 /* ASCII value of "enti" */ #define AMD_CPUID_GEN_ECX 0x444d4163 /* ASCII value of "cAMD" */ +#define CPU_VENDOR_INTEL 0 +#define CPU_VENDOR_AMD 2 +#define CPU_VENDOR_UNKNOWN 0xff + /* fpu context should be saved in 16-byte aligned memory */ #define FPUALIGN 16 -- 2.44.0