summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/cpuid_drv.c11
-rw-r--r--usr/src/uts/common/os/chip.c4
-rw-r--r--usr/src/uts/common/os/cpu.c5
-rw-r--r--usr/src/uts/common/sys/chip.h10
-rw-r--r--usr/src/uts/i86pc/os/cpuid.c306
-rw-r--r--usr/src/uts/i86pc/os/lgrpplat.c15
-rw-r--r--usr/src/uts/i86pc/os/mp_machdep.c23
-rw-r--r--usr/src/uts/intel/ia32/ml/i86_subr.s49
-rw-r--r--usr/src/uts/intel/sys/x86_archext.h22
-rw-r--r--usr/src/uts/sun4u/os/cmp.c11
-rw-r--r--usr/src/uts/sun4v/os/cmp.c6
11 files changed, 318 insertions, 144 deletions
diff --git a/usr/src/uts/common/io/cpuid_drv.c b/usr/src/uts/common/io/cpuid_drv.c
index 0be0fc03f5..f1a03c83b1 100644
--- a/usr/src/uts/common/io/cpuid_drv.c
+++ b/usr/src/uts/common/io/cpuid_drv.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -110,7 +110,7 @@ cpuid_open(dev_t *dev, int flag, int otyp, cred_t *cr)
static int
cpuid_read(dev_t dev, uio_t *uio, cred_t *cr)
{
- uint32_t crs[4];
+ struct cpuid_regs crs;
int error = 0;
if ((x86_feature & X86_CPUID) == 0)
@@ -127,10 +127,11 @@ cpuid_read(dev_t dev, uio_t *uio, cred_t *cr)
break;
}
- crs[0] = cpuid_insn(NULL,
- (uint32_t)uoff, &crs[1], &crs[2], &crs[3]);
+ crs.cp_eax = (uint32_t)uoff;
+ crs.cp_ebx = crs.cp_ecx = crs.cp_edx = 0;
+ (void) cpuid_insn(NULL, &crs);
- if ((error = uiomove(crs, sizeof (crs), UIO_READ, uio)) != 0)
+ if ((error = uiomove(&crs, sizeof (crs), UIO_READ, uio)) != 0)
break;
uio->uio_loffset = uoff + 1;
}
diff --git a/usr/src/uts/common/os/chip.c b/usr/src/uts/common/os/chip.c
index c564933a72..b6fcbe89d2 100644
--- a/usr/src/uts/common/os/chip.c
+++ b/usr/src/uts/common/os/chip.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -219,7 +219,7 @@ chip_cpu_init(cpu_t *cp)
* leveraged to implement core level load balancing.
*/
#ifdef sun4v
- cid = chip_plat_get_pipeid(cp);
+ cid = chip_plat_get_coreid(cp);
#else
cid = chip_plat_get_chipid(cp);
#endif /* sun4v */
diff --git a/usr/src/uts/common/os/cpu.c b/usr/src/uts/common/os/cpu.c
index 1adfe6b28c..e9f4453f81 100644
--- a/usr/src/uts/common/os/cpu.c
+++ b/usr/src/uts/common/os/cpu.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -2072,6 +2072,7 @@ static struct {
kstat_named_t ci_cpu_fru;
#endif
kstat_named_t ci_brandstr;
+ kstat_named_t ci_core_id;
} cpu_info_template = {
{ "state", KSTAT_DATA_CHAR },
{ "state_begin", KSTAT_DATA_LONG },
@@ -2085,6 +2086,7 @@ static struct {
{ "cpu_fru", KSTAT_DATA_STRING },
#endif
{ "brand", KSTAT_DATA_STRING },
+ { "core_id", KSTAT_DATA_LONG },
};
static kmutex_t cpu_info_template_lock;
@@ -2136,6 +2138,7 @@ cpu_info_kstat_update(kstat_t *ksp, int rw)
kstat_named_setstr(&cpu_info_template.ci_cpu_fru, cpu_fru_fmri(cp));
#endif
kstat_named_setstr(&cpu_info_template.ci_brandstr, cp->cpu_brandstr);
+ cpu_info_template.ci_core_id.value.l = chip_plat_get_coreid(cp);
return (0);
}
diff --git a/usr/src/uts/common/sys/chip.h b/usr/src/uts/common/sys/chip.h
index 226efb74cd..e33b521783 100644
--- a/usr/src/uts/common/sys/chip.h
+++ b/usr/src/uts/common/sys/chip.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -52,6 +52,7 @@ typedef enum chip_type {
CHIP_SMT, /* SMT, single core */
CHIP_CMP_SPLIT_CACHE, /* CMP with split caches */
CHIP_CMP_SHARED_CACHE, /* CMP with shared caches */
+ CHIP_CMT, /* CMT w/ multiple cores and threads */
CHIP_NUM_TYPES
} chip_type_t;
@@ -182,12 +183,9 @@ void chip_kstat_create(chip_t *);
* Platform chip operations
*/
chipid_t chip_plat_get_chipid(cpu_t *);
-#ifdef sun4v
-id_t chip_plat_get_pipeid(cpu_t *);
-#endif /* sun4v */
-
-void chip_plat_define_chip(cpu_t *, chip_def_t *);
+id_t chip_plat_get_coreid(cpu_t *);
int chip_plat_get_clogid(cpu_t *);
+void chip_plat_define_chip(cpu_t *, chip_def_t *);
#endif /* !_KERNEL && !_KMEMUSER */
diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c
index b89334180a..a16c5a6298 100644
--- a/usr/src/uts/i86pc/os/cpuid.c
+++ b/usr/src/uts/i86pc/os/cpuid.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -117,13 +117,6 @@ uint_t enable486;
*/
const char CyrixInstead[] = "CyrixInstead";
-struct cpuidr {
- uint32_t cp_eax;
- uint32_t cp_ebx;
- uint32_t cp_ecx;
- uint32_t cp_edx;
-};
-
/*
* These constants determine how many of the elements of the
* cpuid we cache in the cpuid_info data structure; the
@@ -148,11 +141,10 @@ struct cpuid_info {
chipid_t cpi_chipid; /* fn 1: %ebx: chip # on ht cpus */
uint_t cpi_brandid; /* fn 1: %ebx: brand ID */
int cpi_clogid; /* fn 1: %ebx: thread # */
- uint_t cpi_ncpu_per_chip;
-
+ uint_t cpi_ncpu_per_chip; /* fn 1: %ebx: logical cpu count */
uint8_t cpi_cacheinfo[16]; /* fn 2: intel-style cache desc */
uint_t cpi_ncache; /* fn 2: number of elements */
- struct cpuidr cpi_std[NMAX_CPI_STD]; /* 0 .. 5 */
+ struct cpuid_regs cpi_std[NMAX_CPI_STD]; /* 0 .. 5 */
/*
* extended function information
*/
@@ -160,7 +152,10 @@ struct cpuid_info {
char cpi_brandstr[49]; /* fn 0x8000000[234] */
uint8_t cpi_pabits; /* fn 0x80000006: %eax */
uint8_t cpi_vabits; /* fn 0x80000006: %eax */
- struct cpuidr cpi_extd[NMAX_CPI_EXTD]; /* 0x80000000 .. 0x80000008 */
+ struct cpuid_regs cpi_extd[NMAX_CPI_EXTD]; /* 0x8000000[0-8] */
+ id_t cpi_coreid;
+ uint_t cpi_ncore_per_chip; /* AMD: fn 0x80000008: %ecx[7-0] */
+ /* Intel: fn 4: %eax[31-26] */
/*
* supported feature information
*/
@@ -217,7 +212,7 @@ cpuid_pass1(cpu_t *cpu)
uint32_t mask_ecx, mask_edx;
uint_t feature = X86_CPUID;
struct cpuid_info *cpi;
- struct cpuidr *cp;
+ struct cpuid_regs *cp;
int xcpuid;
/*
@@ -232,8 +227,8 @@ cpuid_pass1(cpu_t *cpu)
kmem_zalloc(sizeof (*cpi), KM_SLEEP);
cp = &cpi->cpi_std[0];
- cp->cp_eax = __cpuid_insn(0, &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
- cpi->cpi_maxeax = cp->cp_eax;
+ cp->cp_eax = 0;
+ cpi->cpi_maxeax = __cpuid_insn(cp);
{
uint32_t *iptr = (uint32_t *)cpi->cpi_vendorstr;
*iptr++ = cp->cp_ebx;
@@ -283,7 +278,8 @@ cpuid_pass1(cpu_t *cpu)
goto pass1_done;
cp = &cpi->cpi_std[1];
- cp->cp_eax = __cpuid_insn(1, &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
+ cp->cp_eax = 1;
+ (void) __cpuid_insn(cp);
/*
* Extract identifying constants for easy access.
@@ -352,28 +348,32 @@ cpuid_pass1(cpu_t *cpu)
* These CPUs have an incomplete implementation
* of MCA/MCE which we mask away.
*/
- mask_edx =
- CPUID_INTC_EDX_DE |
- CPUID_INTC_EDX_PSE |
- CPUID_INTC_EDX_TSC |
- CPUID_INTC_EDX_MSR |
- CPUID_INTC_EDX_CX8 |
- CPUID_INTC_EDX_PGE;
+ mask_edx &= ~(CPUID_INTC_EDX_MCE | CPUID_INTC_EDX_MCA);
+
+ /*
+ * Model 0 uses the wrong (APIC) bit
+ * to indicate PGE. Fix it here.
+ */
if (cpi->cpi_model == 0) {
- /*
- * Model 0 uses the wrong (APIC) bit
- * to indicate PGE. Fix it here.
- */
if (cp->cp_edx & 0x200) {
cp->cp_edx &= ~0x200;
cp->cp_edx |= CPUID_INTC_EDX_PGE;
}
- } else if (cpi->cpi_model >= 6)
- mask_edx |= CPUID_INTC_EDX_MMX;
- } else if (cpi->cpi_family >= 0xf) {
- /* SSE3 and CX16, at least, are valid; enable all */
- mask_ecx = 0xffffffff;
+ }
+
+ /*
+ * Early models had problems w/ MMX; disable.
+ */
+ if (cpi->cpi_model < 6)
+ mask_edx &= ~CPUID_INTC_EDX_MMX;
}
+
+ /*
+ * For newer families, SSE3 and CX16, at least, are valid;
+ * enable all
+ */
+ if (cpi->cpi_family >= 0xf)
+ mask_ecx = 0xffffffff;
break;
case X86_VENDOR_TM:
/*
@@ -520,12 +520,14 @@ cpuid_pass1(cpu_t *cpu)
* (AMD chose to set the HTT bit on their CMP processors,
* even though they're not actually hyperthreaded. Thus it
* takes a bit more work to figure out what's really going
- * on ... see the handling of the HTvalid bit below)
+ * on ... see the handling of the CMP_LEGACY bit below)
*/
if (cp->cp_edx & CPUID_INTC_EDX_HTT) {
cpi->cpi_ncpu_per_chip = CPI_CPU_COUNT(cpi);
if (cpi->cpi_ncpu_per_chip > 1)
feature |= X86_HTT;
+ } else {
+ cpi->cpi_ncpu_per_chip = 1;
}
/*
@@ -561,8 +563,8 @@ cpuid_pass1(cpu_t *cpu)
if (xcpuid) {
cp = &cpi->cpi_extd[0];
- cpi->cpi_xmaxeax = cp->cp_eax = __cpuid_insn(0x80000000,
- &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
+ cp->cp_eax = 0x80000000;
+ cpi->cpi_xmaxeax = __cpuid_insn(cp);
}
if (cpi->cpi_xmaxeax & 0x80000000) {
@@ -576,8 +578,8 @@ cpuid_pass1(cpu_t *cpu)
if (cpi->cpi_xmaxeax < 0x80000001)
break;
cp = &cpi->cpi_extd[1];
- cp->cp_eax = __cpuid_insn(0x80000001,
- &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
+ cp->cp_eax = 0x80000001;
+ (void) __cpuid_insn(cp);
if (cpi->cpi_vendor == X86_VENDOR_AMD &&
cpi->cpi_family == 5 &&
cpi->cpi_model == 6 &&
@@ -599,14 +601,16 @@ cpuid_pass1(cpu_t *cpu)
feature |= X86_NX;
/*
- * Unless both the HTT bit is set, and the
- * HTvalid bit is set, then we're not actually
- * HyperThreaded at all..
+ * If both the HTT and CMP_LEGACY bits are set,
+ * then we're not actually HyperThreaded. Read
+ * "AMD CPUID Specification" for more details.
*/
if (cpi->cpi_vendor == X86_VENDOR_AMD &&
- (feature & X86_HTT) == X86_HTT &&
- (cp->cp_ecx & CPUID_AMD_ECX_HTvalid) == 0)
+ (feature & X86_HTT) &&
+ (cp->cp_ecx & CPUID_AMD_ECX_CMP_LEGACY)) {
feature &= ~X86_HTT;
+ feature |= X86_CMP;
+ }
#if defined(_LP64)
/*
* It's really tricky to support syscall/sysret in
@@ -630,48 +634,147 @@ cpuid_pass1(cpu_t *cpu)
break;
}
+ /*
+ * Get CPUID data about processor cores and hyperthreads.
+ */
switch (cpi->cpi_vendor) {
case X86_VENDOR_Intel:
+ if (cpi->cpi_maxeax >= 4) {
+ cp = &cpi->cpi_std[4];
+ cp->cp_eax = 4;
+ cp->cp_ecx = 0;
+ (void) __cpuid_insn(cp);
+ }
+ /*FALLTHROUGH*/
case X86_VENDOR_AMD:
if (cpi->cpi_xmaxeax < 0x80000008)
break;
cp = &cpi->cpi_extd[8];
- cp->cp_eax = __cpuid_insn(0x80000008,
- &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
+ cp->cp_eax = 0x80000008;
+ (void) __cpuid_insn(cp);
/*
* Virtual and physical address limits from
* cpuid override previously guessed values.
*/
cpi->cpi_pabits = BITX(cp->cp_eax, 7, 0);
cpi->cpi_vabits = BITX(cp->cp_eax, 15, 8);
+ break;
+ default:
+ break;
+ }
- /*
- * This -might- be a CMP processor?
- */
- if (cpi->cpi_vendor == X86_VENDOR_AMD) {
- cpi->cpi_ncpu_per_chip =
- 1 + BITX(cp->cp_ecx, 7, 0);
- if (cpi->cpi_ncpu_per_chip > 1)
- feature |= X86_CMP;
+ switch (cpi->cpi_vendor) {
+ case X86_VENDOR_Intel:
+ if (cpi->cpi_maxeax < 4) {
+ cpi->cpi_ncore_per_chip = 1;
+ break;
+ } else {
+ cpi->cpi_ncore_per_chip =
+ BITX((cpi)->cpi_std[4].cp_eax, 31, 26) + 1;
+ }
+ break;
+ case X86_VENDOR_AMD:
+ if (cpi->cpi_xmaxeax < 0x80000008) {
+ cpi->cpi_ncore_per_chip = 1;
+ break;
+ } else {
+ cpi->cpi_ncore_per_chip =
+ BITX((cpi)->cpi_extd[8].cp_ecx, 7, 0) + 1;
}
break;
default:
+ cpi->cpi_ncore_per_chip = 1;
break;
}
+
}
+ /*
+ * If more than one core, then this processor is CMP.
+ */
+ if (cpi->cpi_ncore_per_chip > 1)
+ feature |= X86_CMP;
+ /*
+ * If the number of cores is the same as the number
+ * of CPUs, then we cannot have HyperThreading.
+ */
+ if (cpi->cpi_ncpu_per_chip == cpi->cpi_ncore_per_chip)
+ feature &= ~X86_HTT;
+
if ((feature & (X86_HTT | X86_CMP)) == 0) {
+ /*
+ * Single-core single-threaded processors.
+ */
cpi->cpi_chipid = -1;
cpi->cpi_clogid = 0;
+ cpi->cpi_coreid = cpu->cpu_id;
} else if (cpi->cpi_ncpu_per_chip > 1) {
- uint_t i, cid_shift, apic_id;
-
- for (i = 1, cid_shift = 0;
- i < cpi->cpi_ncpu_per_chip; i <<= 1)
- cid_shift++;
- apic_id = CPI_APIC_ID(cpi);
- cpi->cpi_chipid = apic_id >> cid_shift;
- cpi->cpi_clogid = apic_id & ((1 << cid_shift) - 1);
+ uint_t i;
+ uint_t chipid_shift = 0;
+ uint_t coreid_shift = 0;
+ uint_t apic_id = CPI_APIC_ID(cpi);
+
+ for (i = 1; i < cpi->cpi_ncpu_per_chip; i <<= 1)
+ chipid_shift++;
+ cpi->cpi_chipid = apic_id >> chipid_shift;
+ cpi->cpi_clogid = apic_id & ((1 << chipid_shift) - 1);
+
+ if (cpi->cpi_vendor == X86_VENDOR_Intel) {
+ if (feature & X86_CMP) {
+ /*
+ * Multi-core (and possibly multi-threaded)
+ * processors.
+ */
+ uint_t ncpu_per_core;
+ if (cpi->cpi_ncore_per_chip == 1)
+ ncpu_per_core = cpi->cpi_ncpu_per_chip;
+ else if (cpi->cpi_ncore_per_chip > 1)
+ ncpu_per_core = cpi->cpi_ncpu_per_chip /
+ cpi->cpi_ncore_per_chip;
+ /*
+ * 8bit APIC IDs on dual core Pentiums
+ * look like this:
+ *
+ * +-----------------------+------+------+
+ * | Physical Package ID | MC | HT |
+ * +-----------------------+------+------+
+ * <------- chipid -------->
+ * <------- coreid --------------->
+ * <--- clogid -->
+ *
+ * Where the number of bits necessary to
+ * represent MC and HT fields together equals
+ * to the minimum number of bits necessary to
+ * store the value of cpi->cpi_ncpu_per_chip.
+ * Of those bits, the MC part uses the number
+ * of bits necessary to store the value of
+ * cpi->cpi_ncore_per_chip.
+ */
+ for (i = 1; i < ncpu_per_core; i <<= 1)
+ coreid_shift++;
+ cpi->cpi_coreid =
+ apic_id & ((1 << coreid_shift) - 1);
+ } else if (feature & X86_HTT) {
+ /*
+ * Single-core multi-threaded processors.
+ */
+ cpi->cpi_coreid = cpi->cpi_chipid;
+ }
+ } else if (cpi->cpi_vendor == X86_VENDOR_AMD) {
+ /*
+ * AMD currently only has dual-core processors with
+ * single-threaded cores. If they ever release
+ * multi-threaded processors, then this code
+ * will have to be updated.
+ */
+ cpi->cpi_coreid = cpu->cpu_id;
+ } else {
+ /*
+ * All other processors are currently
+ * assumed to have single cores.
+ */
+ cpi->cpi_coreid = cpi->cpi_chipid;
+ }
}
pass1_done:
@@ -693,7 +796,7 @@ cpuid_pass2(cpu_t *cpu)
{
uint_t n, nmax;
int i;
- struct cpuidr *cp;
+ struct cpuid_regs *cp;
uint8_t *dp;
uint32_t *iptr;
struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
@@ -709,8 +812,8 @@ cpuid_pass2(cpu_t *cpu)
* (We already handled n == 0 and n == 1 in pass 1)
*/
for (n = 2, cp = &cpi->cpi_std[2]; n < nmax; n++, cp++) {
- cp->cp_eax = __cpuid_insn(n,
- &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
+ cp->cp_eax = n;
+ (void) __cpuid_insn(cp);
switch (n) {
case 2:
/*
@@ -781,8 +884,8 @@ cpuid_pass2(cpu_t *cpu)
*/
iptr = (void *)cpi->cpi_brandstr;
for (n = 2, cp = &cpi->cpi_extd[2]; n < nmax; cp++, n++) {
- cp->cp_eax = __cpuid_insn(n + 0x80000000,
- &cp->cp_ebx, &cp->cp_ecx, &cp->cp_edx);
+ cp->cp_eax = 0x80000000 + n;
+ (void) __cpuid_insn(cp);
switch (n) {
case 2:
case 3:
@@ -895,7 +998,7 @@ intel_cpubrand(const struct cpuid_info *cpi)
case 6:
switch (cpi->cpi_model) {
uint_t celeron, xeon;
- const struct cpuidr *cp;
+ const struct cpuid_regs *cp;
case 0:
case 1:
case 2:
@@ -1371,14 +1474,15 @@ cpuid_pass4(cpu_t *cpu)
#endif
}
- if (cpuid_is_ht(cpu))
+ if (x86_feature & X86_HTT)
hwcap_flags |= AV_386_PAUSE;
if (cpi->cpi_xmaxeax < 0x80000001)
goto pass4_done;
switch (cpi->cpi_vendor) {
- uint32_t junk, *edx;
+ struct cpuid_regs cp;
+ uint32_t *edx;
case X86_VENDOR_Intel: /* sigh */
case X86_VENDOR_AMD:
@@ -1416,8 +1520,9 @@ cpuid_pass4(cpu_t *cpu)
break;
case X86_VENDOR_TM:
- edx = &cpi->cpi_support[TM_EDX_FEATURES];
- (void) __cpuid_insn(0x80860001, &junk, &junk, edx);
+ cp.cp_eax = 0x80860001;
+ (void) __cpuid_insn(&cp);
+ cpi->cpi_support[TM_EDX_FEATURES] = cp.cp_edx;
break;
default:
@@ -1436,11 +1541,10 @@ pass4_done:
* about the hardware, independently of kernel support.
*/
uint32_t
-cpuid_insn(cpu_t *cpu,
- uint32_t eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+cpuid_insn(cpu_t *cpu, struct cpuid_regs *cp)
{
struct cpuid_info *cpi;
- struct cpuidr *cp;
+ struct cpuid_regs *xcp;
if (cpu == NULL)
cpu = CPU;
@@ -1452,21 +1556,23 @@ cpuid_insn(cpu_t *cpu,
* CPUID data is cached in two separate places: cpi_std for standard
* CPUID functions, and cpi_extd for extended CPUID functions.
*/
- if (eax <= cpi->cpi_maxeax && eax < NMAX_CPI_STD)
- cp = &cpi->cpi_std[eax];
- else if (eax >= 0x80000000 && eax <= cpi->cpi_xmaxeax &&
- eax < 0x80000000 + NMAX_CPI_EXTD)
- cp = &cpi->cpi_extd[eax - 0x80000000];
+ if (cp->cp_eax <= cpi->cpi_maxeax && cp->cp_eax < NMAX_CPI_STD)
+ xcp = &cpi->cpi_std[cp->cp_eax];
+ else if (cp->cp_eax >= 0x80000000 && cp->cp_eax <= cpi->cpi_xmaxeax &&
+ cp->cp_eax < 0x80000000 + NMAX_CPI_EXTD)
+ xcp = &cpi->cpi_extd[cp->cp_eax - 0x80000000];
else
/*
* The caller is asking for data from an input parameter which
* the kernel has not cached. In this case we go fetch from
* the hardware and return the data directly to the user.
*/
- return (__cpuid_insn(eax, ebx, ecx, edx));
- *ebx = cp->cp_ebx;
- *ecx = cp->cp_ecx;
- *edx = cp->cp_edx;
+ return (__cpuid_insn(cp));
+
+ cp->cp_eax = xcp->cp_eax;
+ cp->cp_ebx = xcp->cp_ebx;
+ cp->cp_ecx = xcp->cp_ecx;
+ cp->cp_edx = xcp->cp_edx;
return (cp->cp_eax);
}
@@ -1486,7 +1592,7 @@ cpuid_getbrandstr(cpu_t *cpu, char *s, size_t n)
}
int
-cpuid_is_ht(cpu_t *cpu)
+cpuid_is_cmt(cpu_t *cpu)
{
if (cpu == NULL)
cpu = CPU;
@@ -1528,7 +1634,7 @@ cpuid_getidstr(cpu_t *cpu, char *s, size_t n)
ASSERT(cpuid_checkpass(cpu, 1));
- if (cpuid_is_ht(cpu))
+ if (cpuid_is_cmt(cpu))
return (snprintf(s, n, fmt_ht, cpi->cpi_chipid,
cpi->cpi_vendorstr, cpi->cpi_family, cpi->cpi_model,
cpi->cpi_step, cpu->cpu_type_info.pi_clock));
@@ -1573,6 +1679,13 @@ cpuid_get_ncpu_per_chip(cpu_t *cpu)
}
uint_t
+cpuid_get_ncore_per_chip(cpu_t *cpu)
+{
+ ASSERT(cpuid_checkpass(cpu, 1));
+ return (cpu->cpu_m.mcpu_cpi->cpi_ncore_per_chip);
+}
+
+uint_t
cpuid_getstep(cpu_t *cpu)
{
ASSERT(cpuid_checkpass(cpu, 1));
@@ -1584,11 +1697,18 @@ chip_plat_get_chipid(cpu_t *cpu)
{
ASSERT(cpuid_checkpass(cpu, 1));
- if (cpuid_is_ht(cpu))
+ if (cpuid_is_cmt(cpu))
return (cpu->cpu_m.mcpu_cpi->cpi_chipid);
return (cpu->cpu_id);
}
+id_t
+chip_plat_get_coreid(cpu_t *cpu)
+{
+ ASSERT(cpuid_checkpass(cpu, 1));
+ return (cpu->cpu_m.mcpu_cpi->cpi_coreid);
+}
+
int
chip_plat_get_clogid(cpu_t *cpu)
{
@@ -1636,7 +1756,7 @@ cpuid_get_dtlb_nent(cpu_t *cpu, size_t pagesize)
* Check the L2 TLB info
*/
if (cpi->cpi_xmaxeax >= 0x80000006) {
- struct cpuidr *cp = &cpi->cpi_extd[6];
+ struct cpuid_regs *cp = &cpi->cpi_extd[6];
switch (pagesize) {
@@ -1671,7 +1791,7 @@ cpuid_get_dtlb_nent(cpu_t *cpu, size_t pagesize)
* No L2 TLB support for this size, try L1.
*/
if (cpi->cpi_xmaxeax >= 0x80000005) {
- struct cpuidr *cp = &cpi->cpi_extd[5];
+ struct cpuid_regs *cp = &cpi->cpi_extd[5];
switch (pagesize) {
case 4 * 1024:
@@ -1700,7 +1820,7 @@ int
cpuid_opteron_erratum(cpu_t *cpu, uint_t erratum)
{
struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi;
- uint_t eax, edx, junk;
+ uint_t eax;
if (cpi->cpi_vendor != X86_VENDOR_AMD)
return (0);
@@ -1860,8 +1980,10 @@ cpuid_opteron_erratum(cpu_t *cpu, uint_t erratum)
* if this is a K8 family processor
*/
if (CPI_FAMILY(cpi) == 0xf) {
- (void) __cpuid_insn(0x80000007, &junk, &junk, &edx);
- return (!(edx & 0x100));
+ struct cpuid_regs regs;
+ regs.cp_eax = 0x80000007;
+ (void) __cpuid_insn(&regs);
+ return (!(regs.cp_edx & 0x100));
}
return (0);
default:
@@ -2165,7 +2287,7 @@ add_amd_l2_cache(dev_info_t *devi, const char *label,
static void
amd_cache_info(struct cpuid_info *cpi, dev_info_t *devi)
{
- struct cpuidr *cp;
+ struct cpuid_regs *cp;
if (cpi->cpi_xmaxeax < 0x80000005)
return;
@@ -2616,7 +2738,7 @@ intel_l2cinfo(void *arg, const struct cachetab *ct)
static void
amd_l2cacheinfo(struct cpuid_info *cpi, struct l2info *l2i)
{
- struct cpuidr *cp;
+ struct cpuid_regs *cp;
uint_t size, assoc;
int *ip;
diff --git a/usr/src/uts/i86pc/os/lgrpplat.c b/usr/src/uts/i86pc/os/lgrpplat.c
index b7f8f6b5c3..d05f74de03 100644
--- a/usr/src/uts/i86pc/os/lgrpplat.c
+++ b/usr/src/uts/i86pc/os/lgrpplat.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -62,7 +62,7 @@
#define LGRP_PLAT_PROBE_NROUNDS 64 /* default laps for probing */
#define LGRP_PLAT_PROBE_NSAMPLES 1 /* default samples to take */
-
+#define LGRP_PLAT_PROBE_NREADS 256 /* number of vendor ID reads */
/*
* Multiprocessor Opteron machines have Non Uniform Memory Access (NUMA).
@@ -293,6 +293,11 @@ int lgrp_plat_probe_nrounds = LGRP_PLAT_PROBE_NROUNDS;
int lgrp_plat_probe_nsamples = LGRP_PLAT_PROBE_NSAMPLES;
/*
+ * Number of times to read vendor ID from Northbridge for each probe.
+ */
+int lgrp_plat_probe_nreads = LGRP_PLAT_PROBE_NREADS;
+
+/*
* How to probe to determine lgroup topology
*/
lgrp_plat_probe_op_t lgrp_plat_probe_op = LGRP_PLAT_PROBE_VENDOR;
@@ -1063,6 +1068,7 @@ lgrp_plat_probe_time(int to)
hrtime_t max;
hrtime_t min;
hrtime_t start;
+ int cnt;
extern int use_sse_pagecopy;
/*
@@ -1142,9 +1148,10 @@ lgrp_plat_probe_time(int to)
outl(PCI_CONFADD, PCI_CADDR1(0, dev, opt_probe_func,
OPT_PCS_OFF_VENDOR));
start = gethrtime();
- dev_vendor = inl(PCI_CONFDATA);
+ for (cnt = 0; cnt < lgrp_plat_probe_nreads; cnt++)
+ dev_vendor = inl(PCI_CONFDATA);
end = gethrtime();
- elapsed = end - start;
+ elapsed = (end - start) / lgrp_plat_probe_nreads;
splx(ipl);
kpreempt_enable();
break;
diff --git a/usr/src/uts/i86pc/os/mp_machdep.c b/usr/src/uts/i86pc/os/mp_machdep.c
index 2a95e4083d..c6b8a301f5 100644
--- a/usr/src/uts/i86pc/os/mp_machdep.c
+++ b/usr/src/uts/i86pc/os/mp_machdep.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -169,13 +169,28 @@ int simulator_run = 0; /* patch to non-zero if running under simics */
void
chip_plat_define_chip(cpu_t *cp, chip_def_t *cd)
{
- if (x86_feature & (X86_HTT|X86_CMP))
+ if ((x86_feature & (X86_HTT|X86_CMP)) == X86_HTT) {
/*
- * Hyperthreading is SMT
+ * Single-core Pentiums with Hyper-Threading enabled.
*/
cd->chipd_type = CHIP_SMT;
- else
+ } else if ((x86_feature & (X86_HTT|X86_CMP)) == X86_CMP) {
+ /*
+ * Multi-core Opterons or Multi-core Pentiums with
+ * Hyper-Threading disabled.
+ */
+ cd->chipd_type = CHIP_CMP_SPLIT_CACHE;
+ } else if ((x86_feature & (X86_HTT|X86_CMP)) == (X86_HTT|X86_CMP)) {
+ /*
+ * Multi-core Pentiums with Hyper-Threading enabled.
+ */
+ cd->chipd_type = CHIP_CMT;
+ } else {
+ /*
+ * Single-core/single-threaded chips.
+ */
cd->chipd_type = CHIP_DEFAULT;
+ }
cd->chipd_rechoose_adj = 0;
}
diff --git a/usr/src/uts/intel/ia32/ml/i86_subr.s b/usr/src/uts/intel/ia32/ml/i86_subr.s
index e523413bb8..4c75164e50 100644
--- a/usr/src/uts/intel/ia32/ml/i86_subr.s
+++ b/usr/src/uts/intel/ia32/ml/i86_subr.s
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -610,7 +610,7 @@ setcr8(ulong_t val)
/*ARGSUSED*/
uint32_t
-__cpuid_insn(uint32_t eax, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
+__cpuid_insn(struct cpuid_regs *regs)
{ return (0); }
#else /* __lint */
@@ -618,15 +618,21 @@ __cpuid_insn(uint32_t eax, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
#if defined(__amd64)
ENTRY(__cpuid_insn)
- movq %rbx, %r11
- movq %rdx, %r8 /* r8 = ecxp */
- movq %rcx, %r9 /* r9 = edxp */
- movl %edi, %eax
+ movq %rbx, %r8
+ movq %rcx, %r9
+ movq %rdx, %r11
+ movl (%rdi), %eax /* %eax = regs->cp_eax */
+ movl 0x4(%rdi), %ebx /* %ebx = regs->cp_ebx */
+ movl 0x8(%rdi), %ecx /* %ecx = regs->cp_ecx */
+ movl 0xc(%rdi), %edx /* %edx = regs->cp_edx */
cpuid
- movl %ebx, (%rsi)
- movl %ecx, (%r8)
- movl %edx, (%r9)
- movq %r11, %rbx
+ movl %eax, (%rdi) /* regs->cp_eax = %eax */
+ movl %ebx, 0x4(%rdi) /* regs->cp_ebx = %ebx */
+ movl %ecx, 0x8(%rdi) /* regs->cp_ecx = %ecx */
+ movl %edx, 0xc(%rdi) /* regs->cp_edx = %edx */
+ movq %r8, %rbx
+ movq %r9, %rcx
+ movq %r11, %rdx
ret
SET_SIZE(__cpuid_insn)
@@ -634,18 +640,21 @@ __cpuid_insn(uint32_t eax, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
ENTRY(__cpuid_insn)
pushl %ebp
- movl %esp, %ebp
+ movl 0x8(%esp), %ebp /* %ebp = regs */
pushl %ebx
- movl 8(%ebp), %eax
+ pushl %ecx
+ pushl %edx
+ movl (%ebp), %eax /* %eax = regs->cp_eax */
+ movl 0x4(%ebp), %ebx /* %ebx = regs->cp_ebx */
+ movl 0x8(%ebp), %ecx /* %ecx = regs->cp_ecx */
+ movl 0xc(%ebp), %edx /* %edx = regs->cp_edx */
cpuid
- pushl %eax
- movl 0x0c(%ebp), %eax
- movl %ebx, (%eax)
- movl 0x10(%ebp), %eax
- movl %ecx, (%eax)
- movl 0x14(%ebp), %eax
- movl %edx, (%eax)
- popl %eax
+ movl %eax, (%ebp) /* regs->cp_eax = %eax */
+ movl %ebx, 0x4(%ebp) /* regs->cp_ebx = %ebx */
+ movl %ecx, 0x8(%ebp) /* regs->cp_ecx = %ecx */
+ movl %edx, 0xc(%ebp) /* regs->cp_edx = %edx */
+ popl %edx
+ popl %ecx
popl %ebx
popl %ebp
ret
diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h
index bab2c3c77f..4b93663dbd 100644
--- a/usr/src/uts/intel/sys/x86_archext.h
+++ b/usr/src/uts/intel/sys/x86_archext.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -154,7 +154,7 @@ extern "C" {
"\20cmov\17mca\16pge\15mtrr\14syscall\12apic\11cx8" \
"\10mce\7pae\6msr\5tsc\4pse\3de\2vme\1fpu"
-#define CPUID_AMD_ECX_HTvalid 0x00000001 /* AMD: HTT bit valid */
+#define CPUID_AMD_ECX_CMP_LEGACY 0x00000010 /* AMD: multi-core chip */
#define FMT_CPUID_AMD_ECX \
"\20" \
@@ -457,6 +457,16 @@ extern const char CyrixInstead[];
#if defined(_KERNEL)
+/*
+ * This structure is used to pass arguments and get return values back
+ * from the CPUID instruction in __cpuid_insn() routine.
+ */
+struct cpuid_regs {
+ uint32_t cp_eax;
+ uint32_t cp_ebx;
+ uint32_t cp_ecx;
+ uint32_t cp_edx;
+};
extern uint64_t rdmsr(uint_t);
extern void wrmsr(uint_t, const uint64_t);
@@ -473,9 +483,8 @@ extern void cpu_fast_syscall_disable(void *);
struct cpu;
extern int cpuid_checkpass(struct cpu *, int);
-extern uint32_t cpuid_insn(struct cpu *,
- uint32_t, uint32_t *, uint32_t *, uint32_t *);
-extern uint32_t __cpuid_insn(uint32_t, uint32_t *, uint32_t *, uint32_t *);
+extern uint32_t cpuid_insn(struct cpu *, struct cpuid_regs *);
+extern uint32_t __cpuid_insn(struct cpuid_regs *);
extern int cpuid_getbrandstr(struct cpu *, char *, size_t);
extern int cpuid_getidstr(struct cpu *, char *, size_t);
extern const char *cpuid_getvendorstr(struct cpu *);
@@ -484,7 +493,8 @@ extern uint_t cpuid_getfamily(struct cpu *);
extern uint_t cpuid_getmodel(struct cpu *);
extern uint_t cpuid_getstep(struct cpu *);
extern uint_t cpuid_get_ncpu_per_chip(struct cpu *);
-extern int cpuid_is_ht(struct cpu *);
+extern uint_t cpuid_get_ncore_per_chip(struct cpu *);
+extern int cpuid_is_cmt(struct cpu *);
extern int cpuid_syscall32_insn(struct cpu *);
extern int getl2cacheinfo(struct cpu *, int *, int *, int *);
diff --git a/usr/src/uts/sun4u/os/cmp.c b/usr/src/uts/sun4u/os/cmp.c
index b917c8378e..792ccddc6f 100644
--- a/usr/src/uts/sun4u/os/cmp.c
+++ b/usr/src/uts/sun4u/os/cmp.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -146,6 +146,15 @@ chip_plat_get_chipid(cpu_t *cp)
return (cmp_cpu_to_chip(cp->cpu_id));
}
+/*
+ * We don't have any multi-threaded cores on sun4u yet.
+ */
+id_t
+chip_plat_get_coreid(cpu_t *cp)
+{
+ return (cp->cpu_id);
+}
+
void
chip_plat_define_chip(cpu_t *cp, chip_def_t *cd)
{
diff --git a/usr/src/uts/sun4v/os/cmp.c b/usr/src/uts/sun4v/os/cmp.c
index 236af92900..fc0aa2e46c 100644
--- a/usr/src/uts/sun4v/os/cmp.c
+++ b/usr/src/uts/sun4v/os/cmp.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -104,7 +104,7 @@ chip_plat_get_chipid(cpu_t *cp)
void
chip_plat_define_chip(cpu_t *cp, chip_def_t *cd)
{
- cd->chipd_type = CHIP_CMP_SHARED_CACHE;
+ cd->chipd_type = CHIP_CMT;
/*
* Define any needed adjustment of rechoose_interval
@@ -121,7 +121,7 @@ chip_plat_define_chip(cpu_t *cp, chip_def_t *cd)
*/
id_t
-chip_plat_get_pipeid(cpu_t *cp)
+chip_plat_get_coreid(cpu_t *cp)
{
return (cp->cpu_m.cpu_ipipe);
}