///////////////////////////////////////////////////////////////////////// // $Id$ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2014 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "param_names.h" #include "cpuid.h" #define LOG_THIS cpu-> bx_cpuid_t::bx_cpuid_t(BX_CPU_C *_cpu): cpu(_cpu) { #if BX_SUPPORT_SMP nthreads = SIM->get_param_num(BXPN_CPU_NTHREADS)->get(); ncores = SIM->get_param_num(BXPN_CPU_NCORES)->get(); nprocessors = SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get(); #else nthreads = 1; ncores = 1; nprocessors = 1; #endif for (unsigned n=0; n < BX_ISA_EXTENSIONS_ARRAY_SIZE; n++) ia_extensions_bitmask[n] = 0; } BX_CPP_INLINE static Bit32u ilog2(Bit32u x) { Bit32u count = 0; while(x>>=1) count++; return count; } // leaf 0x0000000B // void bx_cpuid_t::get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x0000000B - Extended Topology Leaf leaf->eax = 0; leaf->ebx = 0; leaf->ecx = subfunction; leaf->edx = cpu->get_apic_id(); #if BX_SUPPORT_SMP switch(subfunction) { case 0: if (nthreads > 1) { leaf->eax = ilog2(nthreads-1)+1; leaf->ebx = nthreads; leaf->ecx |= (1<<8); } else if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } else { leaf->eax = 1; leaf->ebx = 1; // number of logical CPUs at this level } break; case 1: if (nthreads > 1) { if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } else if (ncores > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; case 2: if (nthreads > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; default: break; } #endif } void bx_cpuid_t::dump_cpuid(unsigned max_std_leaf, unsigned max_ext_leaf) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=max_std_leaf; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } if (max_ext_leaf == 0) return; for (n=0x80000000; n<=(0x8000000 + max_ext_leaf); n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } }