1bd185b41SIngo Weinhold /* 2bd185b41SIngo Weinhold * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3bd185b41SIngo Weinhold * Distributed under the terms of the MIT License. 4bd185b41SIngo Weinhold */ 5bd185b41SIngo Weinhold 6bd185b41SIngo Weinhold 7bd185b41SIngo Weinhold #include <arch/system_info.h> 8bd185b41SIngo Weinhold 9bd185b41SIngo Weinhold #include <string.h> 10bd185b41SIngo Weinhold 11bd185b41SIngo Weinhold #include <KernelExport.h> 12bd185b41SIngo Weinhold #include <OS.h> 13bd185b41SIngo Weinhold 14bd185b41SIngo Weinhold #include <boot/kernel_args.h> 15bd185b41SIngo Weinhold #include <cpu.h> 16bd185b41SIngo Weinhold #include <kernel.h> 17bd185b41SIngo Weinhold #include <smp.h> 18bd185b41SIngo Weinhold 19bd185b41SIngo Weinhold 20bd185b41SIngo Weinhold uint32 sCpuType; 21bd185b41SIngo Weinhold int32 sCpuRevision; 22bd185b41SIngo Weinhold int64 sCpuClockSpeed; 23bd185b41SIngo Weinhold 24bd185b41SIngo Weinhold 25bd185b41SIngo Weinhold static bool 26bd185b41SIngo Weinhold get_cpuid_for(cpuid_info *info, uint32 currentCPU, uint32 eaxRegister, 27bd185b41SIngo Weinhold uint32 forCPU) 28bd185b41SIngo Weinhold { 29bd185b41SIngo Weinhold if (currentCPU != forCPU) 30bd185b41SIngo Weinhold return false; 31bd185b41SIngo Weinhold 32*4110b730SPawel Dziepak get_current_cpuid(info, eaxRegister, 0); 33bd185b41SIngo Weinhold return true; 34bd185b41SIngo Weinhold } 35bd185b41SIngo Weinhold 36bd185b41SIngo Weinhold 37bd185b41SIngo Weinhold status_t 38bd185b41SIngo Weinhold get_cpuid(cpuid_info *info, uint32 eaxRegister, uint32 forCPU) 39bd185b41SIngo Weinhold { 40bd185b41SIngo Weinhold uint32 numCPUs = (uint32)smp_get_num_cpus(); 41bd185b41SIngo Weinhold cpu_status state; 42bd185b41SIngo Weinhold 43bd185b41SIngo Weinhold if (forCPU >= numCPUs) 44bd185b41SIngo Weinhold return B_BAD_VALUE; 45bd185b41SIngo Weinhold 46bd185b41SIngo Weinhold // prevent us from being rescheduled 47bd185b41SIngo Weinhold state = disable_interrupts(); 48bd185b41SIngo Weinhold 49bd185b41SIngo Weinhold // ToDo: as long as we only run on pentium-class systems, we can assume 50bd185b41SIngo Weinhold // that the CPU supports cpuid. 51bd185b41SIngo Weinhold 52bd185b41SIngo Weinhold if (!get_cpuid_for(info, smp_get_current_cpu(), eaxRegister, forCPU)) { 5311d3892dSAlex Smith smp_send_broadcast_ici(SMP_MSG_CALL_FUNCTION, (addr_t)info, 54bd185b41SIngo Weinhold eaxRegister, forCPU, (void *)get_cpuid_for, SMP_MSG_FLAG_SYNC); 55bd185b41SIngo Weinhold } 56bd185b41SIngo Weinhold 57bd185b41SIngo Weinhold restore_interrupts(state); 58bd185b41SIngo Weinhold return B_OK; 59bd185b41SIngo Weinhold } 60bd185b41SIngo Weinhold 61bd185b41SIngo Weinhold 62bd185b41SIngo Weinhold status_t 63bd185b41SIngo Weinhold arch_get_system_info(system_info *info, size_t size) 64bd185b41SIngo Weinhold { 65bd185b41SIngo Weinhold info->cpu_type = (cpu_types)sCpuType; 66bd185b41SIngo Weinhold info->cpu_revision = sCpuRevision; 67bd185b41SIngo Weinhold 68bd185b41SIngo Weinhold // - various cpu_info 69bd185b41SIngo Weinhold info->cpu_clock_speed = sCpuClockSpeed; 70bd185b41SIngo Weinhold // - bus_clock_speed 719a5503d0SAlex Smith #ifdef __x86_64__ 729a5503d0SAlex Smith info->platform_type = B_64_BIT_PC_PLATFORM; 739a5503d0SAlex Smith #else 74bd185b41SIngo Weinhold info->platform_type = B_AT_CLONE_PLATFORM; 759a5503d0SAlex Smith #endif 76bd185b41SIngo Weinhold 77bd185b41SIngo Weinhold // ToDo: clock speeds could be retrieved via SMBIOS/DMI 78bd185b41SIngo Weinhold return B_OK; 79bd185b41SIngo Weinhold } 80bd185b41SIngo Weinhold 81bd185b41SIngo Weinhold 82bd185b41SIngo Weinhold status_t 83bd185b41SIngo Weinhold arch_system_info_init(struct kernel_args *args) 84bd185b41SIngo Weinhold { 85bd185b41SIngo Weinhold // This is what you get if the CPU vendor is not recognized 86bd185b41SIngo Weinhold // or the CPU does not support cpuid with eax == 1. 87bd185b41SIngo Weinhold uint32 base; 88bd185b41SIngo Weinhold uint32 model = 0; 89bd185b41SIngo Weinhold cpu_ent *cpu = get_cpu_struct(); 90bd185b41SIngo Weinhold 91bd185b41SIngo Weinhold switch (cpu->arch.vendor) { 92bd185b41SIngo Weinhold case VENDOR_INTEL: 93bd185b41SIngo Weinhold base = B_CPU_INTEL_x86; 94bd185b41SIngo Weinhold break; 95bd185b41SIngo Weinhold case VENDOR_AMD: 96bd185b41SIngo Weinhold base = B_CPU_AMD_x86; 97bd185b41SIngo Weinhold break; 98bd185b41SIngo Weinhold case VENDOR_CYRIX: 99bd185b41SIngo Weinhold base = B_CPU_CYRIX_x86; 100bd185b41SIngo Weinhold break; 101bd185b41SIngo Weinhold case VENDOR_UMC: 102bd185b41SIngo Weinhold base = B_CPU_INTEL_x86; // XXX 103bd185b41SIngo Weinhold break; 104bd185b41SIngo Weinhold case VENDOR_NEXGEN: 105bd185b41SIngo Weinhold base = B_CPU_INTEL_x86; // XXX 106bd185b41SIngo Weinhold break; 107bd185b41SIngo Weinhold case VENDOR_CENTAUR: 108bd185b41SIngo Weinhold base = B_CPU_VIA_IDT_x86; 109bd185b41SIngo Weinhold break; 110bd185b41SIngo Weinhold case VENDOR_RISE: 111bd185b41SIngo Weinhold base = B_CPU_RISE_x86; 112bd185b41SIngo Weinhold break; 113bd185b41SIngo Weinhold case VENDOR_TRANSMETA: 114bd185b41SIngo Weinhold base = B_CPU_TRANSMETA_x86; 115bd185b41SIngo Weinhold break; 116bd185b41SIngo Weinhold case VENDOR_NSC: 117bd185b41SIngo Weinhold base = B_CPU_NATIONAL_x86; 118bd185b41SIngo Weinhold break; 119bd185b41SIngo Weinhold default: 120bd185b41SIngo Weinhold base = B_CPU_x86; 121bd185b41SIngo Weinhold } 122bd185b41SIngo Weinhold 123bd185b41SIngo Weinhold if (base != B_CPU_x86) { 124548b1a49SAlexander von Gluck IV if (base == B_CPU_INTEL_x86 125548b1a49SAlexander von Gluck IV || (base == B_CPU_AMD_x86 && cpu->arch.family == 0xF)) { 126bd185b41SIngo Weinhold model = (cpu->arch.extended_family << 20) 127bd185b41SIngo Weinhold + (cpu->arch.extended_model << 16) 128bd185b41SIngo Weinhold + (cpu->arch.family << 4) + cpu->arch.model; 129bd185b41SIngo Weinhold } else { 130548b1a49SAlexander von Gluck IV model = (cpu->arch.family << 4) 131548b1a49SAlexander von Gluck IV + cpu->arch.model; 132548b1a49SAlexander von Gluck IV // Isn't much useful extended family and model information 133548b1a49SAlexander von Gluck IV // yet on other processors. 134bd185b41SIngo Weinhold } 135bd185b41SIngo Weinhold } 136bd185b41SIngo Weinhold 137bd185b41SIngo Weinhold sCpuRevision = (cpu->arch.extended_family << 18) 138bd185b41SIngo Weinhold | (cpu->arch.extended_model << 14) | (cpu->arch.type << 12) 139bd185b41SIngo Weinhold | (cpu->arch.family << 8) | (cpu->arch.model << 4) | cpu->arch.stepping; 140bd185b41SIngo Weinhold 141bd185b41SIngo Weinhold sCpuType = base + model; 142bd185b41SIngo Weinhold sCpuClockSpeed = args->arch_args.cpu_clock_speed; 143bd185b41SIngo Weinhold return B_OK; 144bd185b41SIngo Weinhold } 145bd185b41SIngo Weinhold 146bd185b41SIngo Weinhold 147bd185b41SIngo Weinhold // #pragma mark - 148bd185b41SIngo Weinhold 149bd185b41SIngo Weinhold 150bd185b41SIngo Weinhold status_t 151bd185b41SIngo Weinhold _user_get_cpuid(cpuid_info *userInfo, uint32 eaxRegister, uint32 cpuNum) 152bd185b41SIngo Weinhold { 153bd185b41SIngo Weinhold cpuid_info info; 154bd185b41SIngo Weinhold status_t status; 155bd185b41SIngo Weinhold 156bd185b41SIngo Weinhold if (!IS_USER_ADDRESS(userInfo)) 157bd185b41SIngo Weinhold return B_BAD_ADDRESS; 158bd185b41SIngo Weinhold 159bd185b41SIngo Weinhold status = get_cpuid(&info, eaxRegister, cpuNum); 160bd185b41SIngo Weinhold 161bd185b41SIngo Weinhold if (status == B_OK 162bd185b41SIngo Weinhold && user_memcpy(userInfo, &info, sizeof(cpuid_info)) < B_OK) 163bd185b41SIngo Weinhold return B_BAD_ADDRESS; 164bd185b41SIngo Weinhold 165bd185b41SIngo Weinhold return status; 166bd185b41SIngo Weinhold } 167