- Add support for cpuid leaf 0xb. This allows us to determine the
topology of nehalem/corei7 based systems. - Remove the cpu_cores/cpu_logical detection from identcpu. - Describe the layout of the system in cpu_mp_announce(). Sponsored by: Nokia
This commit is contained in:
parent
113dda8a7c
commit
82fcb0f192
@ -106,9 +106,6 @@ static struct {
|
||||
{ CENTAUR_VENDOR_ID, CPU_VENDOR_CENTAUR }, /* CentaurHauls */
|
||||
};
|
||||
|
||||
int cpu_cores;
|
||||
int cpu_logical;
|
||||
|
||||
|
||||
extern int pq_l2size;
|
||||
extern int pq_l2nways;
|
||||
@ -195,7 +192,6 @@ printcpuinfo(void)
|
||||
cpu_vendor_id == CPU_VENDOR_CENTAUR) {
|
||||
printf(" Stepping = %u", cpu_id & 0xf);
|
||||
if (cpu_high > 0) {
|
||||
u_int cmp = 1, htt = 1;
|
||||
|
||||
/*
|
||||
* Here we should probably set up flags indicating
|
||||
@ -400,28 +396,6 @@ printcpuinfo(void)
|
||||
if (tsc_is_invariant)
|
||||
printf("\n TSC: P-state invariant");
|
||||
|
||||
/*
|
||||
* If this CPU supports HTT or CMP then mention the
|
||||
* number of physical/logical cores it contains.
|
||||
*/
|
||||
if (cpu_feature & CPUID_HTT)
|
||||
htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
|
||||
if (cpu_vendor_id == CPU_VENDOR_AMD &&
|
||||
(amd_feature2 & AMDID2_CMP))
|
||||
cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
|
||||
else if (cpu_vendor_id == CPU_VENDOR_INTEL &&
|
||||
(cpu_high >= 4)) {
|
||||
cpuid_count(4, 0, regs);
|
||||
if ((regs[0] & 0x1f) != 0)
|
||||
cmp = ((regs[0] >> 26) & 0x3f) + 1;
|
||||
}
|
||||
cpu_cores = cmp;
|
||||
cpu_logical = htt / cmp;
|
||||
if (cmp > 1)
|
||||
printf("\n Cores per package: %d", cmp);
|
||||
if ((htt / cmp) > 1)
|
||||
printf("\n Logical CPUs per core: %d",
|
||||
cpu_logical);
|
||||
}
|
||||
}
|
||||
/* Avoid ugly blank lines: only print newline when we have to. */
|
||||
|
@ -160,6 +160,8 @@ int apic_cpuids[MAX_APIC_ID + 1];
|
||||
static volatile u_int cpu_ipi_pending[MAXCPU];
|
||||
|
||||
static u_int boot_address;
|
||||
static int cpu_logical;
|
||||
static int cpu_cores;
|
||||
|
||||
static void assign_cpu_ids(void);
|
||||
static void set_interrupt_apic_ids(void);
|
||||
@ -181,13 +183,142 @@ mem_range_AP_init(void)
|
||||
mem_range_softc.mr_op->initAP(&mem_range_softc);
|
||||
}
|
||||
|
||||
static void
|
||||
topo_probe_0xb(void)
|
||||
{
|
||||
int logical;
|
||||
int p[4];
|
||||
int bits;
|
||||
int type;
|
||||
int cnt;
|
||||
int i;
|
||||
int x;
|
||||
|
||||
/* We only support two levels for now. */
|
||||
for (i = 0; i < 3; i++) {
|
||||
cpuid_count(0x0B, i, p);
|
||||
bits = p[0] & 0x1f;
|
||||
logical = p[1] &= 0xffff;
|
||||
type = (p[2] >> 8) & 0xff;
|
||||
if (type == 0 || logical == 0)
|
||||
break;
|
||||
for (cnt = 0, x = 0; x <= MAX_APIC_ID; x++) {
|
||||
if (!cpu_info[x].cpu_present ||
|
||||
cpu_info[x].cpu_disabled)
|
||||
continue;
|
||||
if (x >> bits == boot_cpu_id >> bits)
|
||||
cnt++;
|
||||
}
|
||||
if (type == CPUID_TYPE_SMT)
|
||||
cpu_logical = cnt;
|
||||
else if (type == CPUID_TYPE_CORE)
|
||||
cpu_cores = cnt;
|
||||
}
|
||||
if (cpu_logical == 0)
|
||||
cpu_logical = 1;
|
||||
cpu_cores /= cpu_logical;
|
||||
}
|
||||
|
||||
static void
|
||||
topo_probe_0x4(void)
|
||||
{
|
||||
u_int threads_per_cache, p[4];
|
||||
u_int htt, cmp;
|
||||
int i;
|
||||
|
||||
htt = cmp = 1;
|
||||
/*
|
||||
* If this CPU supports HTT or CMP then mention the
|
||||
* number of physical/logical cores it contains.
|
||||
*/
|
||||
if (cpu_feature & CPUID_HTT)
|
||||
htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
|
||||
if (cpu_vendor_id == CPU_VENDOR_AMD && (amd_feature2 & AMDID2_CMP))
|
||||
cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
|
||||
else if (cpu_vendor_id == CPU_VENDOR_INTEL && (cpu_high >= 4)) {
|
||||
cpuid_count(4, 0, p);
|
||||
if ((p[0] & 0x1f) != 0)
|
||||
cmp = ((p[0] >> 26) & 0x3f) + 1;
|
||||
}
|
||||
cpu_cores = cmp;
|
||||
cpu_logical = htt / cmp;
|
||||
|
||||
/* Setup the initial logical CPUs info. */
|
||||
if (cpu_feature & CPUID_HTT)
|
||||
logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
|
||||
|
||||
/*
|
||||
* Work out if hyperthreading is *really* enabled. This
|
||||
* is made really ugly by the fact that processors lie: Dual
|
||||
* core processors claim to be hyperthreaded even when they're
|
||||
* not, presumably because they want to be treated the same
|
||||
* way as HTT with respect to per-cpu software licensing.
|
||||
* At the time of writing (May 12, 2005) the only hyperthreaded
|
||||
* cpus are from Intel, and Intel's dual-core processors can be
|
||||
* identified via the "deterministic cache parameters" cpuid
|
||||
* calls.
|
||||
*/
|
||||
/*
|
||||
* First determine if this is an Intel processor which claims
|
||||
* to have hyperthreading support.
|
||||
*/
|
||||
if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_INTEL) {
|
||||
/*
|
||||
* If the "deterministic cache parameters" cpuid calls
|
||||
* are available, use them.
|
||||
*/
|
||||
if (cpu_high >= 4) {
|
||||
/* Ask the processor about the L1 cache. */
|
||||
for (i = 0; i < 1; i++) {
|
||||
cpuid_count(4, i, p);
|
||||
threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1;
|
||||
if (hyperthreading_cpus < threads_per_cache)
|
||||
hyperthreading_cpus = threads_per_cache;
|
||||
if ((p[0] & 0x1f) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the deterministic cache parameters are not
|
||||
* available, or if no caches were reported to exist,
|
||||
* just accept what the HTT flag indicated.
|
||||
*/
|
||||
if (hyperthreading_cpus == 0)
|
||||
hyperthreading_cpus = logical_cpus;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
topo_probe(void)
|
||||
{
|
||||
|
||||
logical_cpus = logical_cpus_mask = 0;
|
||||
if (cpu_high >= 0xb)
|
||||
topo_probe_0xb();
|
||||
else if (cpu_high)
|
||||
topo_probe_0x4();
|
||||
if (cpu_cores == 0)
|
||||
cpu_cores = mp_ncpus;
|
||||
if (cpu_logical == 0)
|
||||
cpu_logical = 1;
|
||||
}
|
||||
|
||||
struct cpu_group *
|
||||
cpu_topo(void)
|
||||
{
|
||||
if (cpu_cores == 0)
|
||||
cpu_cores = 1;
|
||||
if (cpu_logical == 0)
|
||||
cpu_logical = 1;
|
||||
int cg_flags;
|
||||
|
||||
/*
|
||||
* Determine whether any threading flags are
|
||||
* necessry.
|
||||
*/
|
||||
if (cpu_logical > 1 && hyperthreading_cpus)
|
||||
cg_flags = CG_FLAG_HTT;
|
||||
else if (cpu_logical > 1)
|
||||
cg_flags = CG_FLAG_SMT;
|
||||
else
|
||||
cg_flags = 0;
|
||||
if (mp_ncpus % (cpu_cores * cpu_logical) != 0) {
|
||||
printf("WARNING: Non-uniform processors.\n");
|
||||
printf("WARNING: Using suboptimal topology.\n");
|
||||
@ -202,17 +333,17 @@ cpu_topo(void)
|
||||
* Only HTT no multi-core.
|
||||
*/
|
||||
if (cpu_logical > 1 && cpu_cores == 1)
|
||||
return (smp_topo_1level(CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
|
||||
return (smp_topo_1level(CG_SHARE_L1, cpu_logical, cg_flags));
|
||||
/*
|
||||
* Only multi-core no HTT.
|
||||
*/
|
||||
if (cpu_cores > 1 && cpu_logical == 1)
|
||||
return (smp_topo_1level(CG_SHARE_NONE, cpu_cores, 0));
|
||||
return (smp_topo_1level(CG_SHARE_L2, cpu_cores, cg_flags));
|
||||
/*
|
||||
* Both HTT and multi-core.
|
||||
*/
|
||||
return (smp_topo_2level(CG_SHARE_NONE, cpu_cores,
|
||||
CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
|
||||
return (smp_topo_2level(CG_SHARE_L2, cpu_cores,
|
||||
CG_SHARE_L1, cpu_logical, cg_flags));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -318,7 +449,6 @@ void
|
||||
cpu_mp_start(void)
|
||||
{
|
||||
int i;
|
||||
u_int threads_per_cache, p[4];
|
||||
|
||||
/* Initialize the logical ID to APIC ID table. */
|
||||
for (i = 0; i < MAXCPU; i++) {
|
||||
@ -355,51 +485,8 @@ cpu_mp_start(void)
|
||||
KASSERT(boot_cpu_id == PCPU_GET(apic_id),
|
||||
("BSP's APIC ID doesn't match boot_cpu_id"));
|
||||
|
||||
/* Setup the initial logical CPUs info. */
|
||||
logical_cpus = logical_cpus_mask = 0;
|
||||
if (cpu_feature & CPUID_HTT)
|
||||
logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
|
||||
|
||||
/*
|
||||
* Work out if hyperthreading is *really* enabled. This
|
||||
* is made really ugly by the fact that processors lie: Dual
|
||||
* core processors claim to be hyperthreaded even when they're
|
||||
* not, presumably because they want to be treated the same
|
||||
* way as HTT with respect to per-cpu software licensing.
|
||||
* At the time of writing (May 12, 2005) the only hyperthreaded
|
||||
* cpus are from Intel, and Intel's dual-core processors can be
|
||||
* identified via the "deterministic cache parameters" cpuid
|
||||
* calls.
|
||||
*/
|
||||
/*
|
||||
* First determine if this is an Intel processor which claims
|
||||
* to have hyperthreading support.
|
||||
*/
|
||||
if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_INTEL) {
|
||||
/*
|
||||
* If the "deterministic cache parameters" cpuid calls
|
||||
* are available, use them.
|
||||
*/
|
||||
if (cpu_high >= 4) {
|
||||
/* Ask the processor about the L1 cache. */
|
||||
for (i = 0; i < 1; i++) {
|
||||
cpuid_count(4, i, p);
|
||||
threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1;
|
||||
if (hyperthreading_cpus < threads_per_cache)
|
||||
hyperthreading_cpus = threads_per_cache;
|
||||
if ((p[0] & 0x1f) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the deterministic cache parameters are not
|
||||
* available, or if no caches were reported to exist,
|
||||
* just accept what the HTT flag indicated.
|
||||
*/
|
||||
if (hyperthreading_cpus == 0)
|
||||
hyperthreading_cpus = logical_cpus;
|
||||
}
|
||||
/* Probe logical/physical core configuration. */
|
||||
topo_probe();
|
||||
|
||||
assign_cpu_ids();
|
||||
|
||||
@ -419,6 +506,14 @@ cpu_mp_announce(void)
|
||||
const char *hyperthread;
|
||||
int i;
|
||||
|
||||
printf("FreeBSD/SMP: %d package(s) x %d core(s)",
|
||||
mp_ncpus / (cpu_cores * cpu_logical), cpu_cores);
|
||||
if (hyperthreading_cpus > 1)
|
||||
printf(" x %d HTT threads", cpu_logical);
|
||||
else if (cpu_logical > 1)
|
||||
printf(" x %d SMT threads", cpu_logical);
|
||||
printf("\n");
|
||||
|
||||
/* List active CPUs first. */
|
||||
printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id);
|
||||
for (i = 1; i < mp_ncpus; i++) {
|
||||
|
@ -36,10 +36,6 @@ extern int boot_cpu_id;
|
||||
extern struct pcb stoppcbs[];
|
||||
extern int cpu_apic_ids[];
|
||||
|
||||
/* global data in identcpu.c */
|
||||
extern int cpu_cores;
|
||||
extern int cpu_logical;
|
||||
|
||||
/* IPI handlers */
|
||||
inthand_t
|
||||
IDTVEC(invltlb), /* TLB shootdowns - global */
|
||||
|
@ -183,6 +183,13 @@
|
||||
#define CPUID_HTT_CORES 0x00ff0000
|
||||
#define CPUID_LOCAL_APIC_ID 0xff000000
|
||||
|
||||
/*
|
||||
* CPUID instruction 0xb ebx info.
|
||||
*/
|
||||
#define CPUID_TYPE_INVAL 0
|
||||
#define CPUID_TYPE_SMT 1
|
||||
#define CPUID_TYPE_CORE 2
|
||||
|
||||
/*
|
||||
* AMD extended function 8000_0007h edx info
|
||||
*/
|
||||
|
@ -159,9 +159,6 @@ static struct {
|
||||
#endif
|
||||
};
|
||||
|
||||
int cpu_cores;
|
||||
int cpu_logical;
|
||||
|
||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
|
||||
int has_f00f_bug = 0; /* Initialized so that it can be patched. */
|
||||
#endif
|
||||
@ -690,7 +687,6 @@ printcpuinfo(void)
|
||||
if (cpu_vendor_id == CPU_VENDOR_CYRIX)
|
||||
printf(" DIR=0x%04x", cyrix_did);
|
||||
if (cpu_high > 0) {
|
||||
u_int cmp = 1, htt = 1;
|
||||
|
||||
/*
|
||||
* Here we should probably set up flags indicating
|
||||
@ -895,28 +891,6 @@ printcpuinfo(void)
|
||||
if (tsc_is_invariant)
|
||||
printf("\n TSC: P-state invariant");
|
||||
|
||||
/*
|
||||
* If this CPU supports HTT or CMP then mention the
|
||||
* number of physical/logical cores it contains.
|
||||
*/
|
||||
if (cpu_feature & CPUID_HTT)
|
||||
htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
|
||||
if (cpu_vendor_id == CPU_VENDOR_AMD &&
|
||||
(amd_feature2 & AMDID2_CMP))
|
||||
cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
|
||||
else if (cpu_vendor_id == CPU_VENDOR_INTEL &&
|
||||
(cpu_high >= 4)) {
|
||||
cpuid_count(4, 0, regs);
|
||||
if ((regs[0] & 0x1f) != 0)
|
||||
cmp = ((regs[0] >> 26) & 0x3f) + 1;
|
||||
}
|
||||
cpu_cores = cmp;
|
||||
cpu_logical = htt / cmp;
|
||||
if (cmp > 1)
|
||||
printf("\n Cores per package: %d", cmp);
|
||||
if ((htt / cmp) > 1)
|
||||
printf("\n Logical CPUs per core: %d",
|
||||
cpu_logical);
|
||||
}
|
||||
} else if (cpu_vendor_id == CPU_VENDOR_CYRIX) {
|
||||
printf(" DIR=0x%04x", cyrix_did);
|
||||
|
@ -213,6 +213,8 @@ int apic_cpuids[MAX_APIC_ID + 1];
|
||||
static volatile u_int cpu_ipi_pending[MAXCPU];
|
||||
|
||||
static u_int boot_address;
|
||||
static int cpu_logical;
|
||||
static int cpu_cores;
|
||||
|
||||
static void assign_cpu_ids(void);
|
||||
static void install_ap_tramp(void);
|
||||
@ -234,13 +236,142 @@ mem_range_AP_init(void)
|
||||
mem_range_softc.mr_op->initAP(&mem_range_softc);
|
||||
}
|
||||
|
||||
static void
|
||||
topo_probe_0xb(void)
|
||||
{
|
||||
int logical;
|
||||
int p[4];
|
||||
int bits;
|
||||
int type;
|
||||
int cnt;
|
||||
int i;
|
||||
int x;
|
||||
|
||||
/* We only support two levels for now. */
|
||||
for (i = 0; i < 3; i++) {
|
||||
cpuid_count(0x0B, i, p);
|
||||
bits = p[0] & 0x1f;
|
||||
logical = p[1] &= 0xffff;
|
||||
type = (p[2] >> 8) & 0xff;
|
||||
if (type == 0 || logical == 0)
|
||||
break;
|
||||
for (cnt = 0, x = 0; x <= MAX_APIC_ID; x++) {
|
||||
if (!cpu_info[x].cpu_present ||
|
||||
cpu_info[x].cpu_disabled)
|
||||
continue;
|
||||
if (x >> bits == boot_cpu_id >> bits)
|
||||
cnt++;
|
||||
}
|
||||
if (type == CPUID_TYPE_SMT)
|
||||
cpu_logical = cnt;
|
||||
else if (type == CPUID_TYPE_CORE)
|
||||
cpu_cores = cnt;
|
||||
}
|
||||
if (cpu_logical == 0)
|
||||
cpu_logical = 1;
|
||||
cpu_cores /= cpu_logical;
|
||||
}
|
||||
|
||||
static void
|
||||
topo_probe_0x4(void)
|
||||
{
|
||||
u_int threads_per_cache, p[4];
|
||||
u_int htt, cmp;
|
||||
int i;
|
||||
|
||||
htt = cmp = 1;
|
||||
/*
|
||||
* If this CPU supports HTT or CMP then mention the
|
||||
* number of physical/logical cores it contains.
|
||||
*/
|
||||
if (cpu_feature & CPUID_HTT)
|
||||
htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
|
||||
if (cpu_vendor_id == CPU_VENDOR_AMD && (amd_feature2 & AMDID2_CMP))
|
||||
cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
|
||||
else if (cpu_vendor_id == CPU_VENDOR_INTEL && (cpu_high >= 4)) {
|
||||
cpuid_count(4, 0, p);
|
||||
if ((p[0] & 0x1f) != 0)
|
||||
cmp = ((p[0] >> 26) & 0x3f) + 1;
|
||||
}
|
||||
cpu_cores = cmp;
|
||||
cpu_logical = htt / cmp;
|
||||
|
||||
/* Setup the initial logical CPUs info. */
|
||||
if (cpu_feature & CPUID_HTT)
|
||||
logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
|
||||
|
||||
/*
|
||||
* Work out if hyperthreading is *really* enabled. This
|
||||
* is made really ugly by the fact that processors lie: Dual
|
||||
* core processors claim to be hyperthreaded even when they're
|
||||
* not, presumably because they want to be treated the same
|
||||
* way as HTT with respect to per-cpu software licensing.
|
||||
* At the time of writing (May 12, 2005) the only hyperthreaded
|
||||
* cpus are from Intel, and Intel's dual-core processors can be
|
||||
* identified via the "deterministic cache parameters" cpuid
|
||||
* calls.
|
||||
*/
|
||||
/*
|
||||
* First determine if this is an Intel processor which claims
|
||||
* to have hyperthreading support.
|
||||
*/
|
||||
if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_INTEL) {
|
||||
/*
|
||||
* If the "deterministic cache parameters" cpuid calls
|
||||
* are available, use them.
|
||||
*/
|
||||
if (cpu_high >= 4) {
|
||||
/* Ask the processor about the L1 cache. */
|
||||
for (i = 0; i < 1; i++) {
|
||||
cpuid_count(4, i, p);
|
||||
threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1;
|
||||
if (hyperthreading_cpus < threads_per_cache)
|
||||
hyperthreading_cpus = threads_per_cache;
|
||||
if ((p[0] & 0x1f) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the deterministic cache parameters are not
|
||||
* available, or if no caches were reported to exist,
|
||||
* just accept what the HTT flag indicated.
|
||||
*/
|
||||
if (hyperthreading_cpus == 0)
|
||||
hyperthreading_cpus = logical_cpus;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
topo_probe(void)
|
||||
{
|
||||
|
||||
logical_cpus = logical_cpus_mask = 0;
|
||||
if (cpu_high >= 0xb)
|
||||
topo_probe_0xb();
|
||||
else if (cpu_high)
|
||||
topo_probe_0x4();
|
||||
if (cpu_cores == 0)
|
||||
cpu_cores = mp_ncpus;
|
||||
if (cpu_logical == 0)
|
||||
cpu_logical = 1;
|
||||
}
|
||||
|
||||
struct cpu_group *
|
||||
cpu_topo(void)
|
||||
{
|
||||
if (cpu_cores == 0)
|
||||
cpu_cores = 1;
|
||||
if (cpu_logical == 0)
|
||||
cpu_logical = 1;
|
||||
int cg_flags;
|
||||
|
||||
/*
|
||||
* Determine whether any threading flags are
|
||||
* necessry.
|
||||
*/
|
||||
if (cpu_logical > 1 && hyperthreading_cpus)
|
||||
cg_flags = CG_FLAG_HTT;
|
||||
else if (cpu_logical > 1)
|
||||
cg_flags = CG_FLAG_SMT;
|
||||
else
|
||||
cg_flags = 0;
|
||||
if (mp_ncpus % (cpu_cores * cpu_logical) != 0) {
|
||||
printf("WARNING: Non-uniform processors.\n");
|
||||
printf("WARNING: Using suboptimal topology.\n");
|
||||
@ -255,17 +386,17 @@ cpu_topo(void)
|
||||
* Only HTT no multi-core.
|
||||
*/
|
||||
if (cpu_logical > 1 && cpu_cores == 1)
|
||||
return (smp_topo_1level(CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
|
||||
return (smp_topo_1level(CG_SHARE_L1, cpu_logical, cg_flags));
|
||||
/*
|
||||
* Only multi-core no HTT.
|
||||
*/
|
||||
if (cpu_cores > 1 && cpu_logical == 1)
|
||||
return (smp_topo_1level(CG_SHARE_NONE, cpu_cores, 0));
|
||||
return (smp_topo_1level(CG_SHARE_L2, cpu_cores, cg_flags));
|
||||
/*
|
||||
* Both HTT and multi-core.
|
||||
*/
|
||||
return (smp_topo_2level(CG_SHARE_NONE, cpu_cores,
|
||||
CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
|
||||
return (smp_topo_2level(CG_SHARE_L2, cpu_cores,
|
||||
CG_SHARE_L1, cpu_logical, cg_flags));
|
||||
}
|
||||
|
||||
|
||||
@ -354,7 +485,6 @@ void
|
||||
cpu_mp_start(void)
|
||||
{
|
||||
int i;
|
||||
u_int threads_per_cache, p[4];
|
||||
|
||||
/* Initialize the logical ID to APIC ID table. */
|
||||
for (i = 0; i < MAXCPU; i++) {
|
||||
@ -399,51 +529,8 @@ cpu_mp_start(void)
|
||||
KASSERT(boot_cpu_id == PCPU_GET(apic_id),
|
||||
("BSP's APIC ID doesn't match boot_cpu_id"));
|
||||
|
||||
/* Setup the initial logical CPUs info. */
|
||||
logical_cpus = logical_cpus_mask = 0;
|
||||
if (cpu_feature & CPUID_HTT)
|
||||
logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
|
||||
|
||||
/*
|
||||
* Work out if hyperthreading is *really* enabled. This
|
||||
* is made really ugly by the fact that processors lie: Dual
|
||||
* core processors claim to be hyperthreaded even when they're
|
||||
* not, presumably because they want to be treated the same
|
||||
* way as HTT with respect to per-cpu software licensing.
|
||||
* At the time of writing (May 12, 2005) the only hyperthreaded
|
||||
* cpus are from Intel, and Intel's dual-core processors can be
|
||||
* identified via the "deterministic cache parameters" cpuid
|
||||
* calls.
|
||||
*/
|
||||
/*
|
||||
* First determine if this is an Intel processor which claims
|
||||
* to have hyperthreading support.
|
||||
*/
|
||||
if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_INTEL) {
|
||||
/*
|
||||
* If the "deterministic cache parameters" cpuid calls
|
||||
* are available, use them.
|
||||
*/
|
||||
if (cpu_high >= 4) {
|
||||
/* Ask the processor about the L1 cache. */
|
||||
for (i = 0; i < 1; i++) {
|
||||
cpuid_count(4, i, p);
|
||||
threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1;
|
||||
if (hyperthreading_cpus < threads_per_cache)
|
||||
hyperthreading_cpus = threads_per_cache;
|
||||
if ((p[0] & 0x1f) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the deterministic cache parameters are not
|
||||
* available, or if no caches were reported to exist,
|
||||
* just accept what the HTT flag indicated.
|
||||
*/
|
||||
if (hyperthreading_cpus == 0)
|
||||
hyperthreading_cpus = logical_cpus;
|
||||
}
|
||||
/* Probe logical/physical core configuration. */
|
||||
topo_probe();
|
||||
|
||||
assign_cpu_ids();
|
||||
|
||||
@ -463,6 +550,14 @@ cpu_mp_announce(void)
|
||||
const char *hyperthread;
|
||||
int i;
|
||||
|
||||
printf("FreeBSD/SMP: %d package(s) x %d core(s)",
|
||||
mp_ncpus / (cpu_cores * cpu_logical), cpu_cores);
|
||||
if (hyperthreading_cpus > 1)
|
||||
printf(" x %d HTT threads", cpu_logical);
|
||||
else if (cpu_logical > 1)
|
||||
printf(" x %d SMT threads", cpu_logical);
|
||||
printf("\n");
|
||||
|
||||
/* List active CPUs first. */
|
||||
printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id);
|
||||
for (i = 1; i < mp_ncpus; i++) {
|
||||
|
@ -45,10 +45,6 @@ extern u_long *ipi_rendezvous_counts[MAXCPU];
|
||||
extern u_long *ipi_lazypmap_counts[MAXCPU];
|
||||
#endif
|
||||
|
||||
/* global data in identcpu.c */
|
||||
extern int cpu_cores;
|
||||
extern int cpu_logical;
|
||||
|
||||
/* IPI handlers */
|
||||
inthand_t
|
||||
IDTVEC(invltlb), /* TLB shootdowns - global */
|
||||
|
@ -182,6 +182,13 @@
|
||||
#define CPUID_HTT_CORES 0x00ff0000
|
||||
#define CPUID_LOCAL_APIC_ID 0xff000000
|
||||
|
||||
/*
|
||||
* CPUID instruction 0xb ebx info.
|
||||
*/
|
||||
#define CPUID_TYPE_INVAL 0
|
||||
#define CPUID_TYPE_SMT 1
|
||||
#define CPUID_TYPE_CORE 2
|
||||
|
||||
/*
|
||||
* AMD extended function 8000_0007h edx info
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user