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