changeset 3766:0e6dc235b6f9 onnv_60

6504327 make with no target in i86pc fails 6521185 Solaris trusts BIOS too much wrt AMD erratum 172 6528027 fallback to cpu.generic if number of mca banks not as expected
author gavinm
date Mon, 05 Mar 2007 18:48:06 -0800
parents e36fc8d4b665
children 9d24e84a65d8
files usr/src/uts/i86pc/Makefile.workarounds usr/src/uts/i86pc/cpu/amd_opteron/ao.h usr/src/uts/i86pc/cpu/amd_opteron/ao_cpu.c usr/src/uts/i86pc/cpu/amd_opteron/ao_main.c usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c usr/src/uts/i86pc/cpu/scripts/Makefile usr/src/uts/i86pc/io/mc/mcamd.h usr/src/uts/intel/sys/mc_amd.h usr/src/uts/intel/sys/mca_amd.h
diffstat 9 files changed, 207 insertions(+), 189 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/i86pc/Makefile.workarounds	Mon Mar 05 15:58:42 2007 -0800
+++ b/usr/src/uts/i86pc/Makefile.workarounds	Mon Mar 05 18:48:06 2007 -0800
@@ -107,3 +107,7 @@
 #
 WORKAROUND_DEFS += -DOPTERON_WORKAROUND_6323525
 
+#
+# Some Registered DIMMs incompatible with address parity feature
+#
+WORKAROUND_DEFS += -DOPTERON_ERRATUM_172
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao.h	Mon Mar 05 15:58:42 2007 -0800
+++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao.h	Mon Mar 05 18:48:06 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -213,14 +213,16 @@
 	uint64_t aos_bcfg_nb_misc;	/* BIOS value of MC4_MISC */
 	uint32_t aos_bcfg_nb_cfg;	/* BIOS value of NB MCA Config */
 	uint32_t aos_bcfg_nb_sparectl;	/* BIOS value of Online Spare Control */
+	uint32_t aos_bcfg_dcfg_lo;	/* BIOS value of DRAM Config Low */
+	uint32_t aos_bcfg_dcfg_hi;	/* BIOS value of DRAM Config High */
 };
 
 /* Bit numbers for aos_cfgonce */
 enum ao_cfgonce_bitnum {
-	AO_CFGONCE_NBMCA
+	AO_CFGONCE_NBMCA,
+	AO_CFGONCE_DRAMCFG
 };
 
-
 /*
  * Per-CPU state
  */
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao_cpu.c	Mon Mar 05 15:58:42 2007 -0800
+++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao_cpu.c	Mon Mar 05 18:48:06 2007 -0800
@@ -123,7 +123,7 @@
 	 * If ao_scrub_policy is DEFAULT, return immediately.  Otherwise we
 	 * disable scrubbing activity while we fiddle with the configuration.
 	 */
-	scrubctl = ao_pcicfg_read(chipid, AMD_NB_FUNC, AMD_NB_REG_SCRUBCTL);
+	scrubctl = ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBCTL);
 	cas32(&ao_scrub_bios, 0, scrubctl);
 
 	if (ao_scrub_policy == AO_SCRUB_BIOSDEFAULT)
@@ -133,15 +133,15 @@
 	scrubctl &= ~AMD_NB_SCRUBCTL_L2_MASK;
 	scrubctl &= ~AMD_NB_SCRUBCTL_DC_MASK;
 
-	ao_pcicfg_write(chipid, AMD_NB_FUNC, AMD_NB_REG_SCRUBCTL, scrubctl);
+	ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBCTL, scrubctl);
 
 	/*
 	 * Read the DRAM Scrub Address Low and High registers, clear their
 	 * address fields, enable sequential-redirect mode, and update the
 	 * address fields using the specified DRAM Base Address.
 	 */
-	lo = ao_pcicfg_read(chipid, AMD_NB_FUNC, AMD_NB_REG_SCRUBADDR_LO);
-	hi = ao_pcicfg_read(chipid, AMD_NB_FUNC, AMD_NB_REG_SCRUBADDR_HI);
+	lo = ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBADDR_LO);
+	hi = ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBADDR_HI);
 
 	lo &= ~AMD_NB_SCRUBADDR_LO_MASK;
 	hi &= ~AMD_NB_SCRUBADDR_HI_MASK;
@@ -152,8 +152,8 @@
 	ao_scrub_lo = lo;
 	ao_scrub_hi = hi;
 
-	ao_pcicfg_write(chipid, AMD_NB_FUNC, AMD_NB_REG_SCRUBADDR_LO, lo);
-	ao_pcicfg_write(chipid, AMD_NB_FUNC, AMD_NB_REG_SCRUBADDR_HI, hi);
+	ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBADDR_LO, lo);
+	ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBADDR_HI, hi);
 
 	if (ao_scrub_rate_dcache > AMD_NB_SCRUBCTL_RATE_MAX) {
 		cmn_err(CE_WARN, "ao_scrub_rate_dcache is too large; "
@@ -235,7 +235,7 @@
 	    ao_scrub_rate_l2cache, ao_scrub_rate_dram);
 
 	ao_scrub_system = scrubctl;
-	ao_pcicfg_write(chipid, AMD_NB_FUNC, AMD_NB_REG_SCRUBCTL, scrubctl);
+	ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SCRUBCTL, scrubctl);
 
 	return (rv);
 }
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao_main.c	Mon Mar 05 15:58:42 2007 -0800
+++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao_main.c	Mon Mar 05 18:48:06 2007 -0800
@@ -71,6 +71,19 @@
 	if (!(cap & MCG_CAP_CTL_P))
 		return (ENOTSUP);
 
+	/*
+	 * Arrange to fallback to generic.cpu if the bank count is not
+	 * as expected.  We're not silent about this - if we have X86_MCA
+	 * and MCG_CAP_CTL_P then we appear not to be virtualized.
+	 */
+	if ((cap & MCG_CAP_COUNT_MASK) != AMD_MCA_BANK_COUNT) {
+		cmn_err(CE_WARN, "CPU %d has %llu MCA banks; expected %u: "
+		    "disabling AMD-specific MCA support on this CPU",
+		    cp->cpu_id, (u_longlong_t)cap & MCG_CAP_COUNT_MASK,
+		    AMD_MCA_BANK_COUNT);
+		return (ENOTSUP);
+	}
+
 	ao = *datap = kmem_zalloc(sizeof (ao_data_t), KM_SLEEP);
 	ao->ao_cpu = cp;
 
--- a/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c	Mon Mar 05 15:58:42 2007 -0800
+++ b/usr/src/uts/i86pc/cpu/amd_opteron/ao_mca.c	Mon Mar 05 18:48:06 2007 -0800
@@ -408,7 +408,7 @@
 }
 
 /*
- * NorthBridge (NB) Configuration.
+ * NorthBridge (NB) MCA Configuration.
  *
  * We add and remove bits from the BIOS-configured value, rather than
  * writing an absolute value.  The variables ao_nb_cfg_{add,remove}_cmn and
@@ -483,7 +483,7 @@
 	 * modify the settings accordingly, and store the new value back.
 	 */
 	ao->ao_shared->aos_bcfg_nb_cfg = val =
-	    ao_pcicfg_read(chipid, AMD_NB_FUNC, AMD_NB_REG_CFG);
+	    ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG);
 
 	switch (ao_nb_watchdog_policy) {
 	case AO_NB_WDOG_LEAVEALONE:
@@ -528,7 +528,28 @@
 		nbcp++;
 	}
 
-	ao_pcicfg_write(chipid, AMD_NB_FUNC, AMD_NB_REG_CFG, val);
+	ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_NBCFG, val);
+}
+
+static void
+ao_dram_cfg(ao_data_t *ao, uint32_t rev)
+{
+	uint_t chipid = pg_plat_hw_instance_id(CPU, PGHW_CHIP);
+	union mcreg_dramcfg_lo dcfglo;
+
+	ao->ao_shared->aos_bcfg_dcfg_lo = MCREG_VAL32(&dcfglo) =
+	    ao_pcicfg_read(chipid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGLO);
+	ao->ao_shared->aos_bcfg_dcfg_hi =
+	    ao_pcicfg_read(chipid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGHI);
+
+#ifdef OPTERON_ERRATUM_172
+	if (X86_CHIPREV_MATCH(rev, AO_REVS_FG) &&
+	    MCREG_FIELD_revFG(&dcfglo, ParEn)) {
+		MCREG_FIELD_revFG(&dcfglo, ParEn) = 0;
+		ao_pcicfg_write(chipid, MC_FUNC_DRAMCTL, MC_DC_REG_DRAMCFGLO,
+		    MCREG_VAL32(&dcfglo));
+	}
+#endif
 }
 
 /*
@@ -552,7 +573,7 @@
 	int chan, cs;
 
 	ao->ao_shared->aos_bcfg_nb_sparectl = MCREG_VAL32(&sparectl) =
-	    ao_pcicfg_read(chipid, AMD_NB_FUNC, AMD_NB_REG_SPARECTL);
+	    ao_pcicfg_read(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL);
 
 	if (ao_nb_cfg_sparectl_noseize)
 		return;	/* stash BIOS value, but no changes */
@@ -568,7 +589,7 @@
 	MCREG_FIELD_revFG(&sparectl, EccErrCntWrEn) = 1;
 
 	/* First write, preparing for writes to EccErrCnt */
-	ao_pcicfg_write(chipid, AMD_NB_FUNC, AMD_NB_REG_SPARECTL,
+	ao_pcicfg_write(chipid, MC_FUNC_MISCCTL, MC_CTL_REG_SPARECTL,
 	    MCREG_VAL32(&sparectl));
 
 	/*
@@ -580,8 +601,8 @@
 
 		for (cs = 0; cs < MC_CHIP_NCS; cs++) {
 			MCREG_FIELD_revFG(&sparectl, EccErrCntDramCs) = cs;
-			ao_pcicfg_write(chipid, AMD_NB_FUNC,
-			    AMD_NB_REG_SPARECTL, MCREG_VAL32(&sparectl));
+			ao_pcicfg_write(chipid, MC_FUNC_MISCCTL,
+			    MC_CTL_REG_SPARECTL, MCREG_VAL32(&sparectl));
 		}
 	}
 }
@@ -1052,25 +1073,21 @@
 {
 	ao_data_t *ao = data;
 	ao_mca_t *mca = &ao->ao_mca;
-	uint64_t cap;
+	uint64_t cap = rdmsr(IA32_MSR_MCG_CAP);
 	uint32_t rev;
-	int donb;
+	int donb, dodcfg;
 	int i;
 
-	ASSERT(x86_feature & X86_MCA);
-	cap = rdmsr(IA32_MSR_MCG_CAP);
-	ASSERT(cap & MCG_CAP_CTL_P);
-
 	/*
-	 * If the hardware's bank count is different than what we expect, then
-	 * we're running on some Opteron variant that we don't understand yet.
+	 * cmi_mca_init is only called during cpu startup if features include
+	 * X86_MCA (defined as both MCA and MCE support indicated by CPUID).
+	 * Furthermore, our ao_init function returns ENOTSUP if features
+	 * lacked X86_MCA, IA32_MSR_MCG_CAP lacks MCG_CAP_CTL_P, or the
+	 * cpu has an unexpected number of detector banks.
 	 */
-	if ((cap & MCG_CAP_COUNT_MASK) != AMD_MCA_BANK_COUNT) {
-		cmn_err(CE_WARN, "CPU %d has %llu MCA banks; expected %u: "
-		    "disabling MCA on this CPU", ao->ao_cpu->cpu_id,
-		    (u_longlong_t)cap & MCG_CAP_COUNT_MASK, AMD_MCA_BANK_COUNT);
-		return;
-	}
+	ASSERT(x86_feature & X86_MCA);
+	ASSERT(cap & MCG_CAP_CTL_P);
+	ASSERT((cap & MCG_CAP_COUNT_MASK) == AMD_MCA_BANK_COUNT);
 
 	/*
 	 * Configure the logout areas.  We preset every logout area's acl_ao
@@ -1086,10 +1103,11 @@
 	rev = ao->ao_shared->aos_chiprev = cpuid_getchiprev(ao->ao_cpu);
 
 	/*
-	 * Must this core perform NB MCA configuration?  This must be done
-	 * by just one core.
+	 * Must this core perform NB MCA or DRAM configuration?  This must be
+	 * done by just one core.
 	 */
 	donb = ao_chip_once(ao, AO_CFGONCE_NBMCA);
+	dodcfg = ao_chip_once(ao, AO_CFGONCE_DRAMCFG);
 
 	/*
 	 * Initialize poller data, but don't start polling yet.
@@ -1107,10 +1125,12 @@
 	ao_bank_cfg(ao, rev, donb);
 
 	/*
-	 * Modify the MCA NB Configuration Register.
+	 * Modify the MCA NB Configuration and Dram Configuration Registers.
 	 */
 	if (donb)
 		ao_nb_cfg(ao, rev);
+	if (dodcfg)
+		ao_dram_cfg(ao, rev);
 
 	/*
 	 * Setup the Online Spare Control Register
--- a/usr/src/uts/i86pc/cpu/scripts/Makefile	Mon Mar 05 15:58:42 2007 -0800
+++ b/usr/src/uts/i86pc/cpu/scripts/Makefile	Mon Mar 05 18:48:06 2007 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -36,7 +36,7 @@
 
 .KEEP_STATE:
 
-all install setup: $(PERLFILES)
+def all install setup: $(PERLFILES)
 
 clean clobber:
 	$(RM) $(PERLFILES)
--- a/usr/src/uts/i86pc/io/mc/mcamd.h	Mon Mar 05 15:58:42 2007 -0800
+++ b/usr/src/uts/i86pc/io/mc/mcamd.h	Mon Mar 05 18:48:06 2007 -0800
@@ -29,6 +29,12 @@
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+/*
+ * Header file for the mc-amd AMD memory-controller driver.  This should be
+ * included from that driver source alone - any more-widely useful definitions
+ * belong in mc_amd.h.
+ */
+
 #include <sys/types.h>
 #include <sys/ddi.h>
 #include <sys/sunddi.h>
@@ -41,77 +47,32 @@
 extern "C" {
 #endif
 
-/*
- * PCI configuration space functions for the memory controller.  Note that
- * the function numbers here also serve as the mc_func indices in the mc_t.
- * We will not attach to function 3 "Miscellaneous Control" pci1022,1103
- * since the agpgart driver already attaches to that function; instead we
- * retrieve what function 3 parameters we require via direct PCI Mechanism 1
- * accesses.
- */
-enum mc_funcnum {
-	MC_FUNC_HTCONFIG = 0,
-#define	MC_FUNC_HTCONFIG_BINDNM	"pci1022,1100"
-	MC_FUNC_ADDRMAP	= 1,
-#define	MC_FUNC_ADDRMAP_BINDNM	"pci1022,1101"
-	MC_FUNC_DRAMCTL = 2,
-#define	MC_FUNC_DRAMCTL_BINDNM	"pci1022,1102"
-	MC_FUNC_MISCCTL = 3
-};
-
-/*
- * The memory controller driver attaches to several device nodes, but publishes
- * a single minor node.  We need to ensure that the minor node can be
- * consistently mapped back to a single (and the same) device node, so we need
- * to pick one to be used.  We'll use the misc control device node, as it'll
- * be the last to be attached (since we do not attach function 3)
- */
-#define	MC_FUNC_DEVIMAP		MC_FUNC_DRAMCTL
-
-#define	MC_FUNC_NUM		4	/* include MISCCTL, even if no attach */
-
-/*
- * The following define the offsets at which various MC registers are
- * accessed in PCI config space.  For defines describing the register
- * structure see mc_amd.h.
- */
+#if	MC_CHIP_DIMMPERCS > MC_UNUM_NDIMM
+#error	"MC_CHIP_DIMMPERCS exceeds MC_UNUM_NDIMM"
+#endif
 
 /*
- * Function 0 (HT Config) offsets
+ * The memory controller configuration registers are accessed via PCI bus 0,
+ * device 0x18 + nodeid, functions 0 to 3.  The function numbers are
+ * MC_FUNC_*, defined in mc_amd.h.
+ *
+ * We do not attach to function 3 "Miscellaneous Control" pci1022,1103
+ * since the agpgart driver already attaches to that function; instead we
+ * retrieve what function 3 parameters we require via direct PCI Mechanism 1
+ * accesses
+ *
+ * The memory controller driver attaches to these device nodes, but publishes
+ * a single minor node.  We need to ensure that the minor node can be
+ * consistently mapped back to a single (and the same) device node, so we
+ * need to pick one to be used.  We'll use the dram address map device node,
+ * as it'll be the last to be attached.
  */
-#define	MC_HT_REG_RTBL_NODE_0	0x40
-#define	MC_HT_REG_RTBL_INCR	4
-#define	MC_HT_REG_NODEID	0x60
-#define	MC_HT_REG_UNITID	0x64
-
-/*
- * Function 1 (address mask) offsets for DRAM base, DRAM limit, DRAM hole
- * registers.
- */
-#define	MC_AM_REG_DRAMBASE_0	0x40	/* Offset for DRAM Base 0 */
-#define	MC_AM_REG_DRAMLIM_0	0x44	/* Offset for DRAM Limit 0 */
-#define	MC_AM_REG_DRAM_INCR	8	/* incr between base/limit pairs */
-#define	MC_AM_REG_HOLEADDR	0xf0	/* DRAM Hole Address Register */
+#define	MC_FUNC_DEVIMAP		MC_FUNC_DRAMCTL
+#define	MC_FUNC_NUM		(MC_FUNC_MISCCTL + 1)
 
-/*
- * Function 2 (dram controller) offsets for chip-select base, chip-select mask,
- * DRAM bank address mapping, DRAM configuration registers.
- */
-#define	MC_DC_REG_CS_INCR	4	/* incr for CS base and mask */
-#define	MC_DC_REG_CSBASE_0	0x40	/* 0x40 - 0x5c */
-#define	MC_DC_REG_CSMASK_0	0x60	/* 0x60 - 0x7c */
-#define	MC_DC_REG_BANKADDRMAP	0x80
-#define	MC_DC_REG_DRAMCFGLO	0x90
-#define	MC_DC_REG_DRAMCFGHI	0x94
-#define	MC_DC_REG_DRAMMISC	0xa0
-
-/*
- * Function 3 (misc control) offset for NB MCA config, scrubber control
- * and online spare control.
- */
-#define	MC_CTL_REG_NBCFG	0x44	/* MCA NB configuration register */
-#define	MC_CTL_REG_SCRUBCTL	0x58	/* Scrub control register */
-#define	MC_CTL_REG_SPARECTL	0xb0	/* On-line spare control register */
+#define	MC_FUNC_HTCONFIG_BINDNM	"pci1022,1100"
+#define	MC_FUNC_ADDRMAP_BINDNM	"pci1022,1101"
+#define	MC_FUNC_DRAMCTL_BINDNM	"pci1022,1102"
 
 typedef struct mc_func {
 	uint_t mcf_instance;
--- a/usr/src/uts/intel/sys/mc_amd.h	Mon Mar 05 15:58:42 2007 -0800
+++ b/usr/src/uts/intel/sys/mc_amd.h	Mon Mar 05 18:48:06 2007 -0800
@@ -18,7 +18,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -35,6 +35,12 @@
 #endif
 
 /*
+ * Definitions, register offsets, register structure etc pertaining to
+ * the memory controller on AMD64 systems.  These are used by both the
+ * AMD cpu module and the mc-amd driver.
+ */
+
+/*
  * The mc-amd driver exports an nvlist to userland, where the primary
  * consumer is the "chip" topology enumerator for this platform type which
  * builds a full topology subtree from this information.  Others can use
@@ -116,15 +122,105 @@
 #define	MC_CHIP_DIMMPERCS	2	/* max number of dimms per cs */
 #define	MC_CHIP_DIMMPAIR(csnum)	(csnum / MC_CHIP_DIMMPERCS)
 
-#if	MC_CHIP_DIMMPERCS > MC_UNUM_NDIMM
-#error	"MC_CHIP_DIMMPERCS exceeds MC_UNUM_NDIMM"
-#endif
+/*
+ * Memory controller registers are read via PCI config space accesses on
+ * bus 0, device 24 + NodeId, and function as follows:
+ *
+ * Function 0: HyperTransport Technology Configuration
+ * Function 1: Address Map
+ * Function 2: DRAM Controller & HyperTransport Technology Trace Mode
+ * Function 3: Miscellaneous Control
+ */
+enum mc_funcnum {
+	MC_FUNC_HTCONFIG = 0,
+	MC_FUNC_ADDRMAP	= 1,
+	MC_FUNC_DRAMCTL = 2,
+	MC_FUNC_MISCCTL = 3
+};
+
+/*
+ * For a given (bus, device, function) a particular offset selects the
+ * desired register.  All registers are 32-bits wide.
+ *
+ * Different family 0xf processor revisions vary slightly in the content
+ * of these configuration registers.  The biggest change is with rev F
+ * where DDR2 support has been introduced along with some hardware-controlled
+ * correctable memory error thresholding.  Fortunately most of the config info
+ * required by the mc-amd driver is similar across revisions.
+ *
+ * We will try to insulate most of the driver code from config register
+ * details by reading all memory-controller PCI config registers that we
+ * will need at driver attach time for each of functions 0 through 3, and
+ * storing them in a "cooked" form as memory controller properties.
+ * These are to be accessed directly where we have an mc_t to hand, otherwise
+ * through mcamd_get_numprop.  As such we expect most/all use of the
+ * structures and macros defined below to be in those attach codepaths.
+ */
+
+/*
+ * Function 0 (HT Config) offsets
+ */
+#define	MC_HT_REG_RTBL_NODE_0	0x40
+#define	MC_HT_REG_RTBL_INCR	4
+#define	MC_HT_REG_NODEID	0x60
+#define	MC_HT_REG_UNITID	0x64
 
 /*
- * MC_REV_* are used a a convenient shorter form of the X86_CHIPREV
- * counterparts; these must map directly as we fill mcp_rev from
- * a cpuid_getchiprev call.
+ * Function 1 (address map) offsets for DRAM base, DRAM limit, DRAM hole
+ * registers.
+ */
+#define	MC_AM_REG_DRAMBASE_0	0x40	/* Offset for DRAM Base 0 */
+#define	MC_AM_REG_DRAMLIM_0	0x44	/* Offset for DRAM Limit 0 */
+#define	MC_AM_REG_DRAM_INCR	8	/* incr between base/limit pairs */
+#define	MC_AM_REG_HOLEADDR	0xf0	/* DRAM Hole Address Register */
+
+/*
+ * Function 2 (dram controller) offsets for chip-select base, chip-select mask,
+ * DRAM bank address mapping, DRAM configuration registers.
+ */
+#define	MC_DC_REG_CS_INCR	4	/* incr for CS base and mask */
+#define	MC_DC_REG_CSBASE_0	0x40	/* 0x40 - 0x5c */
+#define	MC_DC_REG_CSMASK_0	0x60	/* 0x60 - 0x7c */
+#define	MC_DC_REG_BANKADDRMAP	0x80	/* DRAM Bank Address Mapping */
+#define	MC_DC_REG_DRAMCFGLO	0x90	/* DRAM Configuration Low */
+#define	MC_DC_REG_DRAMCFGHI	0x94	/* DRAM Configuration High */
+#define	MC_DC_REG_DRAMMISC	0xa0	/* DRAM Miscellaneous */
+
+/*
+ * Function 3 (misc control) offset for NB MCA config, scrubber control
+ * and online spare control.
  */
+#define	MC_CTL_REG_NBCFG	0x44	/* MCA NB configuration register */
+#define	MC_CTL_REG_SCRUBCTL	0x58	/* Scrub control register */
+#define	MC_CTL_REG_SCRUBADDR_LO	0x5c	/* DRAM Scrub Address Low */
+#define	MC_CTL_REG_SCRUBADDR_HI	0x60	/* DRAM Scrub Address High */
+#define	MC_CTL_REG_SPARECTL	0xb0	/* On-line spare control register */
+
+/*
+ * Registers will be represented as unions, with one fixed-width unsigned
+ * integer member providing access to the raw register value and one or more
+ * structs breaking the register out into bitfields (more than one struct if
+ * the register definitions varies across processor revisions).
+ *
+ * The "raw" union member will always be '_val32'.  Use MCREG_VAL32 to
+ * access this member.
+ *
+ * The bitfield structs are all named _fmt_xxx where xxx identifies the
+ * processor revision to which it applies.  At this point the only xxx
+ * values in use are:
+ *			'cmn' - applies to all revisions
+ *			'preF' - applies to revisions E and earlier
+ *			'revFG' - applies to revisions F and G
+ * Variants such as 'preD', 'revDE', 'postCG' etc should be introduced
+ * as requirements arise.  The MC_REV_* and MC_REV_MATCH etc macros
+ * will also need to grow to match.  Use MCREG_FIELD_* to access the
+ * individual bitfields of a register, perhaps using MC_REV_* and MC_REV_MATCH
+ * to decide which revision suffix to provide.  Where a bitfield appears
+ * in different revisions but has the same use it should be named identically
+ * (even if the BKDG varies a little) so that the MC_REG_FIELD_* macros
+ * can lookup that member based on revision only.
+ */
+
 #define	MC_REV_UNKNOWN	X86_CHIPREV_UNKNOWN
 #define	MC_REV_B	X86_CHIPREV_AMD_F_REV_B
 #define	MC_REV_C	(X86_CHIPREV_AMD_F_REV_C0 | X86_CHIPREV_AMD_F_REV_CG)
@@ -151,69 +247,6 @@
  */
 #define	MC_REV_ATLEAST(rev, minrev)	X86_CHIPREV_ATLEAST(rev, minrev)
 
-/*
- * Chip socket types
- */
-#define	MC_SKT_UNKNOWN	0x0
-#define	MC_SKT_754	0x1
-#define	MC_SKT_939	0x2
-#define	MC_SKT_940	0x3
-#define	MC_SKT_S1g1	0x4
-#define	MC_SKT_AM2	0x5
-#define	MC_SKT_F1207	0x6
-
-/*
- * Memory controller registers are read via PCI config space accesses on
- * bus 0, device 24 + NodeId, and function as follows:
- *
- * Function 0: HyperTransport Technology Configuration
- * Function 1: Address Map
- * Function 2: DRAM Controller & HyperTransport Technology Trace Mode
- * Function 3: Miscellaneous Control
- *
- * For a given (bus, device, function) a particular offset selects the
- * desired register.  All registers are 32-bits wide.
- *
- * Different family 0xf processor revisions vary slightly in the content
- * of these configuration registers.  The biggest change is with rev F
- * where DDR2 support has been introduced along with some hardware-controlled
- * correctable memory error thresholding.  Fortunately most of the config info
- * required by the mc-amd driver is similar across revisions.
- *
- * We will try to insulate most of the driver code from config register
- * details by reading all memory-controller PCI config registers that we
- * will need at driver attach time for each of functions 0 through 3, and
- * storing them in a "cooked" form as memory controller properties.
- * These are to be accessed directly where we have an mc_t to hand, otherwise
- * through mcamd_get_numprop.  As such we expect most/all use of the
- * structures and macros defined below to be in those attach codepaths.
- */
-
-/*
- * Registers will be represented as unions, with one fixed-width unsigned
- * integer member providing access to the raw register value and one or more
- * structs breaking the register out into bitfields (more than one struct if
- * the register definitions varies across processor revisions).
- *
- * The "raw" union member will always be '_val32'.  Use MCREG_VAL32 to
- * access this member.
- *
- * The bitfield structs are all named _fmt_xxx where xxx identifies the
- * processor revision to which it applies.  At this point the only xxx
- * values in use are:
- *			'cmn' - applies to all revisions
- *			'preF' - applies to revisions E and earlier
- *			'revFG' - applies to revisions F and G
- * Variants such as 'preD', 'revDE', 'postCG' etc should be introduced
- * as requirements arise.  The MC_REV_* and MC_REV_MATCH etc macros
- * will also need to grow to match.  Use MCREG_FIELD_* to access the
- * individual bitfields of a register, perhaps using MC_REV_* and MC_REV_MATCH
- * to decide which revision suffix to provide.  Where a bitfield appears
- * in different revisions but has the same use it should be named identically
- * (even if the BKDG varies a little) so that the MC_REG_FIELD_* macros
- * can lookup that member based on revision only.
- */
-
 #define	_MCREG_FIELD(up, revsuffix, field) ((up)->_fmt_##revsuffix.field)
 
 #define	MCREG_VAL32(up) ((up)->_val32)
--- a/usr/src/uts/intel/sys/mca_amd.h	Mon Mar 05 15:58:42 2007 -0800
+++ b/usr/src/uts/intel/sys/mca_amd.h	Mon Mar 05 18:48:06 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -321,21 +321,6 @@
 	(((uint64_t)(synd) << AMD_BANK_STAT_SYND_SHIFT) & \
 	AMD_BANK_STAT_SYND_MASK)
 
-/* northbridge (NB) status registers */
-
-#define	AMD_NB_FUNC			3
-#define	AMD_NB_REG_CFG			0x44
-#define	AMD_NB_REG_STLO			0x48	/* alias: NB_STATUS[0:31] */
-#define	AMD_NB_REG_STHI			0x4c	/* alias: NB_STATUS[32:63] */
-#define	AMD_NB_REG_ADDRLO		0x50	/* alias: NB_ADDR[0:31] */
-#define	AMD_NB_REG_ADDRHI		0x54	/* alias: NB_ADDR[32:63] */
-
-#define	AMD_NB_REG_SCRUBCTL		0x58
-#define	AMD_NB_REG_SCRUBADDR_LO		0x5c
-#define	AMD_NB_REG_SCRUBADDR_HI		0x60
-
-#define	AMD_NB_REG_SPARECTL		0xb0
-
 #define	AMD_NB_STAT_DRAMCHANNEL		0x0000020000000000ULL
 #define	AMD_NB_STAT_LDTLINK_MASK	0x0000007000000000ULL
 #define	AMD_NB_STAT_LDTLINK_SHIFT	4