From dcdc4f4b435491550377a93954df5e1f8c5a384e Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Mon, 5 Feb 2007 01:46:28 +0000 Subject: [PATCH] pulled over some stuff from newos: at boot, per cpu, detect the cpu, pull down all the relevant cpuid bits and save them into the per-cpu structure. Changed most of the code scattered here and there that reads the cpuid to use a new api, x86_check_feature, which looks at the saved bits. Also changed the system_info stuff to read from these bits. While i was at it, refreshed all the bits to be current. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20072 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/cpu.h | 1 + headers/private/kernel/arch/ppc/arch_cpu.h | 5 + headers/private/kernel/arch/x86/arch_cpu.h | 92 ++++++- .../kernel/arch/x86/arch_system_info.h | 1 - headers/private/kernel/cpu.h | 5 + src/add-ons/kernel/cpu/x86/generic_x86.cpp | 11 +- src/add-ons/kernel/cpu/x86/via.cpp | 3 +- src/system/kernel/arch/x86/arch_cpu.c | 231 +++++++++++++++++- src/system/kernel/arch/x86/arch_system_info.c | 65 ++--- .../kernel/arch/x86/arch_vm_translation_map.c | 4 +- src/system/kernel/cpu.c | 5 + src/system/kernel/main.c | 2 + 12 files changed, 373 insertions(+), 52 deletions(-) diff --git a/headers/private/kernel/arch/cpu.h b/headers/private/kernel/arch/cpu.h index ecab79391a..53386f072f 100644 --- a/headers/private/kernel/arch/cpu.h +++ b/headers/private/kernel/arch/cpu.h @@ -21,6 +21,7 @@ extern "C" { status_t arch_cpu_preboot_init(kernel_args *args); status_t arch_cpu_init(kernel_args *args); +status_t arch_cpu_init_percpu(kernel_args *args, int curr_cpu); status_t arch_cpu_init_post_vm(kernel_args *args); status_t arch_cpu_init_post_modules(kernel_args *args); status_t arch_cpu_shutdown(bool reboot); diff --git a/headers/private/kernel/arch/ppc/arch_cpu.h b/headers/private/kernel/arch/ppc/arch_cpu.h index 6ed695da24..755beb3539 100644 --- a/headers/private/kernel/arch/ppc/arch_cpu.h +++ b/headers/private/kernel/arch/ppc/arch_cpu.h @@ -101,6 +101,11 @@ enum machine_state { struct block_address_translation; +typedef struct arch_cpu_info { + int null; +} arch_cpu_info; + + #ifdef __cplusplus extern "C" { #endif diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index bda8b3bee4..db15611f4a 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -21,12 +21,55 @@ #define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 #define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 -// cpuid eax 1 features -#define IA32_FEATURE_MSR (1UL << 5) -#define IA32_FEATURE_MTRR (1UL << 12) -#define IA32_FEATURE_GLOBAL_PAGES (1UL << 13) -#define IA32_FEATURE_SSE (1UL << 25) -#define IA32_FEATURE_FXSR (1UL << 24) +// x86 features from cpuid eax 1, edx register +#define IA32_FEATURE_FPU 0x00000001 // x87 fpu +#define IA32_FEATURE_VME 0x00000002 // virtual 8086 +#define IA32_FEATURE_DE 0x00000004 // debugging extensions +#define IA32_FEATURE_PSE 0x00000008 // page size extensions +#define IA32_FEATURE_TSC 0x00000010 // rdtsc instruction +#define IA32_FEATURE_MSR 0x00000020 // rdmsr/wrmsr instruction +#define IA32_FEATURE_PAE 0x00000040 // extended 3 level page table addressing +#define IA32_FEATURE_MCE 0x00000080 // machine check exception +#define IA32_FEATURE_CX8 0x00000100 // cmpxchg8b instruction +#define IA32_FEATURE_APIC 0x00000200 // local apic on chip +#define IA32_FEATURE_SEP 0x00000800 // SYSENTER/SYSEXIT +#define IA32_FEATURE_MTRR 0x00001000 // MTRR +#define IA32_FEATURE_PGE 0x00002000 // paging global bit +#define IA32_FEATURE_MCA 0x00004000 // machine check architecture +#define IA32_FEATURE_CMOV 0x00008000 // cmov instruction +#define IA32_FEATURE_PAT 0x00010000 // page attribute table +#define IA32_FEATURE_PSE36 0x00020000 // page size extensions with 4MB pages +#define IA32_FEATURE_PSN 0x00040000 // processor serial number +#define IA32_FEATURE_CLFSH 0x00080000 // cflush instruction +#define IA32_FEATURE_DS 0x00200000 // debug store +#define IA32_FEATURE_ACPI 0x00400000 // thermal monitor and clock ctrl +#define IA32_FEATURE_MMX 0x00800000 // mmx instructions +#define IA32_FEATURE_FXSR 0x01000000 // FXSAVE/FXRSTOR instruction +#define IA32_FEATURE_SSE 0x02000000 // SSE +#define IA32_FEATURE_SSE2 0x04000000 // SSE2 +#define IA32_FEATURE_SS 0x08000000 // self snoop +#define IA32_FEATURE_HTT 0x10000000 // hyperthreading +#define IA32_FEATURE_TM 0x20000000 // thermal monitor +#define IA32_FEATURE_PBE 0x80000000 // pending break enable + +// x86 features from cpuid eax 1, ecx register +#define IA32_FEATURE_EXT_SSE3 0x00000001 // SSE3 +#define IA32_FEATURE_EXT_MONITOR 0x00000008 // MONITOR/MWAIT +#define IA32_FEATURE_EXT_DSCPL 0x00000010 // CPL qualified debug store +#define IA32_FEATURE_EXT_EST 0x00000080 // speedstep +#define IA32_FEATURE_EXT_TM2 0x00000100 // thermal monitor 2 +#define IA32_FEATURE_EXT_CNXTID 0x00000400 // L1 context ID + +// x86 features from cpuid eax 0x80000001, edx register (AMD) +// only care about the ones that are unique to this register +#define IA32_FEATURE_AMD_EXT_SYSCALL (1<<11) // SYSCALL/SYSRET +#define IA32_FEATURE_AMD_EXT_NX (1<<20) // no execute bit +#define IA32_FEATURE_AMD_EXT_MMXEXT (1<<22) // mmx extensions +#define IA32_FEATURE_AMD_EXT_FFXSR (1<<25) // fast FXSAVE/FXRSTOR +#define IA32_FEATURE_AMD_EXT_RDTSCP (1<<27) // rdtscp instruction +#define IA32_FEATURE_AMD_EXT_LONG (1<<29) // long mode +#define IA32_FEATURE_AMD_EXT_3DNOWEXT (1<<30) // 3DNow! extensions +#define IA32_FEATURE_AMD_EXT_3DNOW (1<<31) // 3DNow! // cr4 flags #define IA32_CR4_GLOBAL_PAGES (1UL << 7) @@ -90,6 +133,41 @@ struct iframe { uint32 user_ss; }; +// features +enum x86_feature_type { + FEATURE_COMMON = 0, // cpuid eax=1, ecx register + FEATURE_EXT, // cpuid eax=1, edx register + FEATURE_EXT_AMD, // cpuid eax=0x80000001, edx register (AMD) + + FEATURE_NUM +}; + +enum x86_vendors { + VENDOR_INTEL = 0, + VENDOR_AMD, + VENDOR_CYRIX, + VENDOR_UMC, + VENDOR_NEXGEN, + VENDOR_CENTAUR, + VENDOR_RISE, + VENDOR_TRANSMETA, + VENDOR_NSC, + + VENDOR_NUM, + VENDOR_UNKNOWN, +}; + +typedef struct arch_cpu_info { + enum x86_vendors vendor; + enum x86_feature_type feature[FEATURE_NUM]; + char model_name[49]; + const char *vendor_name; + int type; + int family; + int stepping; + int model; + char feature_string[256]; +} arch_cpu_info; #ifdef __cplusplus extern "C" { @@ -124,8 +202,10 @@ void x86_set_task_gate(int32 n, int32 segment); uint32 x86_count_mtrrs(void); void x86_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type); status_t x86_get_mtrr(uint32 index, uint64 *_base, uint64 *_length, uint8 *_type); +bool x86_check_feature(uint32 feature, enum x86_feature_type type); struct tss *x86_get_main_tss(void); + #define read_cr3(value) \ __asm__("movl %%cr3,%0" : "=r" (value)) diff --git a/headers/private/kernel/arch/x86/arch_system_info.h b/headers/private/kernel/arch/x86/arch_system_info.h index 3575fe869c..e243607364 100644 --- a/headers/private/kernel/arch/x86/arch_system_info.h +++ b/headers/private/kernel/arch/x86/arch_system_info.h @@ -8,7 +8,6 @@ #include - #ifdef __cplusplus extern "C" { #endif diff --git a/headers/private/kernel/cpu.h b/headers/private/kernel/cpu.h index 4393872542..4554cc6151 100644 --- a/headers/private/kernel/cpu.h +++ b/headers/private/kernel/cpu.h @@ -12,6 +12,7 @@ #include #include #include +#include /* CPU local data structure */ @@ -29,6 +30,9 @@ typedef struct cpu_ent { bigtime_t last_user_time; bool disabled; + + // arch-specific stuff + arch_cpu_info arch; } cpu_ent __attribute__((aligned(64))); @@ -41,6 +45,7 @@ extern "C" { status_t cpu_preboot_init(struct kernel_args *args); status_t cpu_init(struct kernel_args *args); +status_t cpu_init_percpu(kernel_args *ka, int curr_cpu); status_t cpu_init_post_vm(struct kernel_args *args); status_t cpu_init_post_modules(struct kernel_args *args); bigtime_t cpu_get_active_time(int32 cpu); diff --git a/src/add-ons/kernel/cpu/x86/generic_x86.cpp b/src/add-ons/kernel/cpu/x86/generic_x86.cpp index 05373d674c..10d667d24a 100644 --- a/src/add-ons/kernel/cpu/x86/generic_x86.cpp +++ b/src/add-ons/kernel/cpu/x86/generic_x86.cpp @@ -14,6 +14,7 @@ #include #include +#include //#define TRACE_MTRR @@ -46,10 +47,8 @@ uint64 gPhysicalMask = 0; uint32 generic_count_mtrrs(void) { - cpuid_info cpuInfo; - if (get_current_cpuid(&cpuInfo, 1) != B_OK - || (cpuInfo.eax_1.features & IA32_FEATURE_MTRR) == 0 - || (cpuInfo.eax_1.features & IA32_FEATURE_MSR) == 0) + if (!x86_check_feature(IA32_FEATURE_MTRR, FEATURE_COMMON) + || !x86_check_feature(IA32_FEATURE_MSR, FEATURE_COMMON)) return 0; mtrr_capabilities capabilities(x86_read_msr(IA32_MSR_MTRR_CAPABILITIES)); @@ -139,9 +138,9 @@ generic_mtrr_compute_physical_mask(void) uint32 bits = 36; cpuid_info cpuInfo; - if (get_cpuid(&cpuInfo, 0x80000000, 0) == B_OK + if (get_current_cpuid(&cpuInfo, 0x80000000) == B_OK && cpuInfo.eax_0.max_eax & 0xff >= 8) { - get_cpuid(&cpuInfo, 0x80000008, 0); + get_current_cpuid(&cpuInfo, 0x80000008); bits = cpuInfo.regs.eax & 0xff; // Obviously, the bits are not always reported correctly diff --git a/src/add-ons/kernel/cpu/x86/via.cpp b/src/add-ons/kernel/cpu/x86/via.cpp index a4f5b6adc5..d1afbd23f4 100644 --- a/src/add-ons/kernel/cpu/x86/via.cpp +++ b/src/add-ons/kernel/cpu/x86/via.cpp @@ -17,8 +17,7 @@ static uint32 via_count_mtrrs(void) { cpuid_info cpuInfo; - if (get_cpuid(&cpuInfo, 1, 0) != B_OK - || (cpuInfo.eax_1.features & IA32_FEATURE_MTRR) == 0) + if (!x86_check_feature(IA32_FEATURE_MTRR, FEATURE_COMMON)) return 0; // IA32_MSR_MTRR_CAPABILITIES doesn't exist on VIA CPUs diff --git a/src/system/kernel/arch/x86/arch_cpu.c b/src/system/kernel/arch/x86/arch_cpu.c index 1903d02291..1e61ea4942 100644 --- a/src/system/kernel/arch/x86/arch_cpu.c +++ b/src/system/kernel/arch/x86/arch_cpu.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -24,6 +25,24 @@ #include +/* cpu vendor info */ +struct cpu_vendor_info { + const char *vendor; + const char *ident_string[2]; +}; + +static const struct cpu_vendor_info vendor_info[VENDOR_NUM] = { + { "Intel", { "GenuineIntel" } }, + { "AMD", { "AuthenticAMD" } }, + { "Cyrix", { "CyrixInstead" } }, + { "UMC", { "UMC UMC UMC" } }, + { "NexGen", { "NexGenDriven" } }, + { "Centaur", { "CentaurHauls" } }, + { "Rise", { "RiseRiseRise" } }, + { "Transmeta", { "GenuineTMx86", "TransmetaCPU" } }, + { "NSC", { "Geode by NSC" } }, +}; + #define CR0_CACHE_DISABLE (1UL << 30) #define CR0_NOT_WRITE_THROUGH (1UL << 29) #define CR0_FPU_EMULATION (1UL << 2) @@ -173,10 +192,8 @@ x86_get_mtrr(uint32 index, uint64 *_base, uint64 *_length, uint8 *_type) static void init_sse(void) { - cpuid_info info; - if (get_current_cpuid(&info, 1) != B_OK - || (info.eax_1.features & IA32_FEATURE_SSE) == 0 - || (info.eax_1.features & IA32_FEATURE_FXSR) == 0) { + if (!x86_check_feature(IA32_FEATURE_SSE, FEATURE_COMMON) + || !x86_check_feature(IA32_FEATURE_FXSR, FEATURE_COMMON)) { // we don't have proper SSE support return; } @@ -228,10 +245,206 @@ init_double_fault(int cpuNum) // set_tss_descriptor(&gGDT[DOUBLE_FAULT_TSS_SEGMENT + cpuNum], (addr_t)sDoubleFaultTSS[cpuNum], sizeof(struct tss)); } +static void make_feature_string(cpu_ent *cpu, char *str, size_t strlen) +{ + str[0] = 0; + + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_FPU) + strlcat(str, "fpu ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_VME) + strlcat(str, "vme ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_DE) + strlcat(str, "de ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_PSE) + strlcat(str, "pse ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_TSC) + strlcat(str, "tsc ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_MSR) + strlcat(str, "msr ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_PAE) + strlcat(str, "pae ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_MCE) + strlcat(str, "mce ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_CX8) + strlcat(str, "cx8 ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_APIC) + strlcat(str, "apic ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_SEP) + strlcat(str, "sep ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_MTRR) + strlcat(str, "mtrr ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_PGE) + strlcat(str, "pge ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_MCA) + strlcat(str, "mca ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_CMOV) + strlcat(str, "cmov ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_PAT) + strlcat(str, "pat ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_PSE36) + strlcat(str, "pse36 ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_PSN) + strlcat(str, "psn ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_CLFSH) + strlcat(str, "clfsh ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_DS) + strlcat(str, "ds ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_ACPI) + strlcat(str, "acpi ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_MMX) + strlcat(str, "mmx ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_FXSR) + strlcat(str, "fxsr ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_SSE) + strlcat(str, "sse ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_SSE2) + strlcat(str, "sse2 ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_SS) + strlcat(str, "ss ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_HTT) + strlcat(str, "htt ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_TM) + strlcat(str, "tm ", strlen); + if(cpu->arch.feature[FEATURE_COMMON] & IA32_FEATURE_PBE) + strlcat(str, "pbe ", strlen); + if(cpu->arch.feature[FEATURE_EXT] & IA32_FEATURE_EXT_SSE3) + strlcat(str, "sse3 ", strlen); + if(cpu->arch.feature[FEATURE_EXT] & IA32_FEATURE_EXT_MONITOR) + strlcat(str, "monitor ", strlen); + if(cpu->arch.feature[FEATURE_EXT] & IA32_FEATURE_EXT_DSCPL) + strlcat(str, "dscpl ", strlen); + if(cpu->arch.feature[FEATURE_EXT] & IA32_FEATURE_EXT_EST) + strlcat(str, "est ", strlen); + if(cpu->arch.feature[FEATURE_EXT] & IA32_FEATURE_EXT_TM2) + strlcat(str, "tm2 ", strlen); + if(cpu->arch.feature[FEATURE_EXT] & IA32_FEATURE_EXT_CNXTID) + strlcat(str, "cnxtid ", strlen); + if(cpu->arch.feature[FEATURE_EXT_AMD] & IA32_FEATURE_AMD_EXT_SYSCALL) + strlcat(str, "syscall ", strlen); + if(cpu->arch.feature[FEATURE_EXT_AMD] & IA32_FEATURE_AMD_EXT_NX) + strlcat(str, "nx ", strlen); + if(cpu->arch.feature[FEATURE_EXT_AMD] & IA32_FEATURE_AMD_EXT_MMXEXT) + strlcat(str, "mmxext ", strlen); + if(cpu->arch.feature[FEATURE_EXT_AMD] & IA32_FEATURE_AMD_EXT_FFXSR) + strlcat(str, "ffxsr ", strlen); + if(cpu->arch.feature[FEATURE_EXT_AMD] & IA32_FEATURE_AMD_EXT_LONG) + strlcat(str, "long ", strlen); + if(cpu->arch.feature[FEATURE_EXT_AMD] & IA32_FEATURE_AMD_EXT_3DNOWEXT) + strlcat(str, "3dnowext ", strlen); + if(cpu->arch.feature[FEATURE_EXT_AMD] & IA32_FEATURE_AMD_EXT_3DNOW) + strlcat(str, "3dnow ", strlen); +} + +static int detect_cpu(kernel_args *ka, int curr_cpu) +{ + cpuid_info cpuid; + unsigned int data[4]; + char vendor_str[17]; + int i; + cpu_ent *cpu = get_cpu_struct(); + + // clear out the cpu info data + cpu->arch.vendor = VENDOR_UNKNOWN; + cpu->arch.vendor_name = "UNKNOWN VENDOR"; + cpu->arch.feature[FEATURE_COMMON] = 0; + cpu->arch.feature[FEATURE_EXT] = 0; + cpu->arch.feature[FEATURE_EXT_AMD] = 0; + cpu->arch.model_name[0] = 0; + + // print some fun data + get_current_cpuid(&cpuid, 0); + + // build the vendor string + memset(vendor_str, 0, sizeof(vendor_str)); + memcpy(vendor_str, cpuid.eax_0.vendor_id, sizeof(cpuid.eax_0.vendor_id)); + + // get the family, model, stepping + get_current_cpuid(&cpuid, 1); + cpu->arch.type = cpuid.eax_1.type; + cpu->arch.family = cpuid.eax_1.family; + cpu->arch.model = cpuid.eax_1.model; + cpu->arch.stepping = cpuid.eax_1.stepping; + dprintf("CPU %d: type %d family %d model %d stepping %d, string '%s'\n", + curr_cpu, cpu->arch.type, cpu->arch.family, cpu->arch.model, cpu->arch.stepping, vendor_str); + + // figure out what vendor we have here + + for(i=0; iarch.vendor = i; + cpu->arch.vendor_name = vendor_info[i].vendor; + break; + } + if(!strcmp(vendor_str, vendor_info[i].ident_string[1])) { + cpu->arch.vendor = i; + cpu->arch.vendor_name = vendor_info[i].vendor; + break; + } + } + + // see if we can get the model name + get_current_cpuid(&cpuid, 0x80000000); + if(cpuid.eax_0.max_eax >= 0x80000004) { + // build the model string (need to swap ecx/edx data before copying) + unsigned int temp; + memset(cpu->arch.model_name, 0, sizeof(cpu->arch.model_name)); + get_current_cpuid(&cpuid, 0x80000002); + temp = cpuid.regs.edx; cpuid.regs.edx = cpuid.regs.ecx; cpuid.regs.ecx = temp; + memcpy(cpu->arch.model_name, cpuid.as_chars, sizeof(cpuid.as_chars)); + get_current_cpuid(&cpuid, 0x80000003); + temp = cpuid.regs.edx; cpuid.regs.edx = cpuid.regs.ecx; cpuid.regs.ecx = temp; + memcpy(cpu->arch.model_name + 16, cpuid.as_chars, sizeof(cpuid.as_chars)); + get_current_cpuid(&cpuid, 0x80000004); + temp = cpuid.regs.edx; cpuid.regs.edx = cpuid.regs.ecx; cpuid.regs.ecx = temp; + memcpy(cpu->arch.model_name + 32, cpuid.as_chars, sizeof(cpuid.as_chars)); + + // some cpus return a right-justified string + for(i = 0; cpu->arch.model_name[i] == ' '; i++) + ; + if(i > 0) { + memmove(cpu->arch.model_name, + &cpu->arch.model_name[i], + strlen(&cpu->arch.model_name[i]) + 1); + } + + dprintf("CPU %d: vendor '%s' model name '%s'\n", + curr_cpu, cpu->arch.vendor_name, cpu->arch.model_name); + } else { + strcpy(cpu->arch.model_name, "unknown"); + } + + // load feature bits + get_current_cpuid(&cpuid, 1); + cpu->arch.feature[FEATURE_COMMON] = cpuid.eax_1.features; // edx + cpu->arch.feature[FEATURE_EXT] = cpuid.eax_1.extended_features; // ecx + if(cpu->arch.vendor == VENDOR_AMD) { + get_current_cpuid(&cpuid, 0x80000001); + cpu->arch.feature[FEATURE_EXT_AMD] = cpuid.regs.edx; // edx + } + + make_feature_string(cpu, cpu->arch.feature_string, sizeof(cpu->arch.feature_string)); + dprintf("CPU %d: features: %s\n", curr_cpu, cpu->arch.feature_string); + + return 0; +} + +bool x86_check_feature(uint32 feature, enum x86_feature_type type) +{ + cpu_ent *cpu = get_cpu_struct(); + +#if 0 + int i; + dprintf("x86_check_feature: feature 0x%x, type %d\n", feature, type); + for (i = 0; i < FEATURE_NUM; i++) { + dprintf("features %d: 0x%x\n", i, cpu->arch.feature[i]); + } +#endif + + return (cpu->arch.feature[type] & feature) ? TRUE : FALSE; +} // #pragma mark - - status_t arch_cpu_preboot_init(kernel_args *args) { @@ -244,6 +457,14 @@ arch_cpu_preboot_init(kernel_args *args) } +status_t +arch_cpu_init_percpu(kernel_args *args, int curr_cpu) +{ + detect_cpu(args, curr_cpu); + + return 0; +} + status_t arch_cpu_init(kernel_args *args) { diff --git a/src/system/kernel/arch/x86/arch_system_info.c b/src/system/kernel/arch/x86/arch_system_info.c index ae3135eb06..935e9b6197 100644 --- a/src/system/kernel/arch/x86/arch_system_info.c +++ b/src/system/kernel/arch/x86/arch_system_info.c @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -77,49 +78,55 @@ arch_system_info_init(struct kernel_args *args) { // This is what you get if the CPU vendor is not recognized // or the CPU does not support cpuid with eax == 1. - uint32 base = B_CPU_x86; + uint32 base; uint32 model = 0; - - cpuid_info cpuInfo; - if (get_current_cpuid(&cpuInfo, 0) == B_OK) { - // set CPU type and revision - - if (!strncmp(cpuInfo.eax_0.vendor_id, "GenuineIntel", 12)) + cpu_ent *cpu = get_cpu_struct(); + + switch (cpu->arch.vendor) { + case VENDOR_INTEL: base = B_CPU_INTEL_x86; - else if (!strncmp(cpuInfo.eax_0.vendor_id, "AuthenticAMD", 12)) + break; + case VENDOR_AMD: base = B_CPU_AMD_x86; - else if (!strncmp(cpuInfo.eax_0.vendor_id, "CyrixInstead", 12)) + break; + case VENDOR_CYRIX: base = B_CPU_CYRIX_x86; - else if (!strncmp(cpuInfo.eax_0.vendor_id, "RiseRiseRise", 12)) - base = B_CPU_RISE_x86; - else if (!strncmp(cpuInfo.eax_0.vendor_id, "CentaurHauls", 12)) + break; + case VENDOR_UMC: + base = B_CPU_INTEL_x86; // XXX + break; + case VENDOR_NEXGEN: + base = B_CPU_INTEL_x86; // XXX + break; + case VENDOR_CENTAUR: base = B_CPU_VIA_IDT_x86; - else if (!strncmp(cpuInfo.eax_0.vendor_id, "NexGenDriven", 12)) - // ToDo: add NexGen CPU types - base = B_CPU_x86; - else if (!strncmp(cpuInfo.eax_0.vendor_id, "GenuineTMx86", 12)) + break; + case VENDOR_RISE: + base = B_CPU_RISE_x86; + break; + case VENDOR_TRANSMETA: base = B_CPU_TRANSMETA_x86; - else if (!strncmp(cpuInfo.eax_0.vendor_id, "Geode by NSC", 12)) + break; + case VENDOR_NSC: base = B_CPU_NATIONAL_x86; - - if (cpuInfo.eax_0.max_eax >= 1) { - get_current_cpuid(&cpuInfo, 1); - if (base != B_CPU_x86) - model = (cpuInfo.eax_1.family << 4) + cpuInfo.eax_1.model; - - sCpuRevision = (cpuInfo.eax_1.type << 12) - | (cpuInfo.eax_1.family << 8) - | (cpuInfo.eax_1.model << 4) - | cpuInfo.eax_1.stepping; - } + break; + default: + base = B_CPU_x86; } + if (base != B_CPU_x86) + model = (cpu->arch.family << 4) + cpu->arch.model; + + sCpuRevision = (cpu->arch.type << 12) + | (cpu->arch.family << 8) + | (cpu->arch.model << 4) + | cpu->arch.stepping; + sCpuType = base + model; sCpuClockSpeed = args->arch_args.cpu_clock_speed; return B_OK; } - // #pragma mark - diff --git a/src/system/kernel/arch/x86/arch_vm_translation_map.c b/src/system/kernel/arch/x86/arch_vm_translation_map.c index ab104f3de9..20910646b6 100644 --- a/src/system/kernel/arch/x86/arch_vm_translation_map.c +++ b/src/system/kernel/arch/x86/arch_vm_translation_map.c @@ -823,7 +823,6 @@ arch_vm_translation_map_init_kernel_map_post_sem(vm_translation_map *map) status_t arch_vm_translation_map_init(kernel_args *args) { - cpuid_info info; status_t error; TRACE(("vm_translation_map_init: entry\n")); @@ -875,8 +874,7 @@ arch_vm_translation_map_init(kernel_args *args) } // enable global page feature if available - get_current_cpuid(&info, 1); - if (info.eax_1.features & IA32_FEATURE_GLOBAL_PAGES) { + if (x86_check_feature(IA32_FEATURE_PGE, FEATURE_COMMON)) { // this prevents kernel pages from being flushed from TLB on context-switch x86_write_cr4(x86_read_cr4() | IA32_CR4_GLOBAL_PAGES); } diff --git a/src/system/kernel/cpu.c b/src/system/kernel/cpu.c index 66de2d625b..06f9aee1d0 100644 --- a/src/system/kernel/cpu.c +++ b/src/system/kernel/cpu.c @@ -36,6 +36,11 @@ cpu_init(kernel_args *args) return arch_cpu_init(args); } +status_t +cpu_init_percpu(kernel_args *args, int curr_cpu) +{ + return arch_cpu_init_percpu(args, curr_cpu); +} status_t cpu_init_post_vm(kernel_args *args) diff --git a/src/system/kernel/main.c b/src/system/kernel/main.c index 077ed4416c..756c516316 100644 --- a/src/system/kernel/main.c +++ b/src/system/kernel/main.c @@ -95,6 +95,7 @@ _start(kernel_args *bootKernelArgs, int currentCPU) // init modules TRACE(("init CPU\n")); cpu_init(&sKernelArgs); + cpu_init_percpu(&sKernelArgs, currentCPU); TRACE(("init interrupts\n")); int_init(&sKernelArgs); @@ -165,6 +166,7 @@ _start(kernel_args *bootKernelArgs, int currentCPU) resume_thread(thread); } else { // this is run for each non boot processor after they've been set loose + cpu_init_percpu(&sKernelArgs, currentCPU); smp_per_cpu_init(&sKernelArgs, currentCPU); thread_per_cpu_init(currentCPU);