summaryrefslogtreecommitdiff
path: root/usr/src/common/mc
diff options
context:
space:
mode:
authorgavinm <none@none>2006-11-24 01:54:59 -0800
committergavinm <none@none>2006-11-24 01:54:59 -0800
commit4156fc34b973159b0334e05ae5ec19344487bdc0 (patch)
treecb5476c983800a14bd9e655ecdfff41933b4546c /usr/src/common/mc
parentaa3da23c1e735ce968058c7dfd8b0480e31d4e3d (diff)
downloadillumos-joyent-4156fc34b973159b0334e05ae5ec19344487bdc0.tar.gz
6474853 Solaris should be cognizant of the platform while attempting to turn off smi mc polling
6489753 mc_amd.h not quite ready for revision G 6491720 DC/IC/BU system infill only capture physical <39:6> 6495485 i86pc/cpu/scripts do not get clobbered
Diffstat (limited to 'usr/src/common/mc')
-rw-r--r--usr/src/common/mc/mc-amd/mcamd_api.h2
-rw-r--r--usr/src/common/mc/mc-amd/mcamd_err.c10
-rw-r--r--usr/src/common/mc/mc-amd/mcamd_err.h8
-rw-r--r--usr/src/common/mc/mc-amd/mcamd_patounum.c56
4 files changed, 46 insertions, 30 deletions
diff --git a/usr/src/common/mc/mc-amd/mcamd_api.h b/usr/src/common/mc/mc-amd/mcamd_api.h
index 977b9dfe94..4053199ebd 100644
--- a/usr/src/common/mc/mc-amd/mcamd_api.h
+++ b/usr/src/common/mc/mc-amd/mcamd_api.h
@@ -197,7 +197,7 @@ union mcamd_dimm_offset_un {
extern const char *mcamd_get_propname(mcamd_propcode_t);
extern int mcamd_patounum(struct mcamd_hdl *, mcamd_node_t *, uint64_t,
- uint32_t, int, mc_unum_t *);
+ uint8_t, uint8_t, uint32_t, int, mc_unum_t *);
extern int mcamd_unumtopa(struct mcamd_hdl *, mcamd_node_t *, mc_unum_t *,
uint64_t *);
extern int mc_pa_to_offset(struct mcamd_hdl *, mcamd_node_t *, mcamd_node_t *,
diff --git a/usr/src/common/mc/mc-amd/mcamd_err.c b/usr/src/common/mc/mc-amd/mcamd_err.c
index d0e1666423..689e556cd4 100644
--- a/usr/src/common/mc/mc-amd/mcamd_err.c
+++ b/usr/src/common/mc/mc-amd/mcamd_err.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -31,8 +30,9 @@
static const char *const _mcamd_errlist[] = {
"Invalid syndrome", /* EMCAMD_SYNDINVALID */
"Invalid configuration tree", /* EMCAMD_TREEINVALID */
- "Address not found" /* EMCAMD_NOADDR */
- "Operation not supported" /* EMCAMD_NOTSUP */
+ "Address not found", /* EMCAMD_NOADDR */
+ "Operation not supported", /* EMCAMD_NOTSUP */
+ "Too few valid address bits", /* EMCAMD_INSUFF_RES */
};
static const int _mcamd_nerr = sizeof (_mcamd_errlist) /
diff --git a/usr/src/common/mc/mc-amd/mcamd_err.h b/usr/src/common/mc/mc-amd/mcamd_err.h
index f9a762e211..f9dc53f32d 100644
--- a/usr/src/common/mc/mc-amd/mcamd_err.h
+++ b/usr/src/common/mc/mc-amd/mcamd_err.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -38,7 +37,8 @@ enum {
EMCAMD_SYNDINVALID = EMCAMD_BASE, /* invalid syndrome */
EMCAMD_TREEINVALID, /* invalid configuration tree */
EMCAMD_NOADDR, /* address not found */
- EMCAMD_NOTSUP /* operation not supported */
+ EMCAMD_NOTSUP, /* operation not supported */
+ EMCAMD_INSUFF_RES /* insufficient resolution */
};
extern const char *mcamd_errmsg(struct mcamd_hdl *);
diff --git a/usr/src/common/mc/mc-amd/mcamd_patounum.c b/usr/src/common/mc/mc-amd/mcamd_patounum.c
index b58a751d60..594af7e7cc 100644
--- a/usr/src/common/mc/mc-amd/mcamd_patounum.c
+++ b/usr/src/common/mc/mc-amd/mcamd_patounum.c
@@ -36,6 +36,8 @@
#include <mcamd_api.h>
#include <mcamd_err.h>
+#define MC_SYSADDR_MSB 39
+#define MC_SYSADDR_LSB 3
#define CSDIMM1 0x1
#define CSDIMM2 0x2
@@ -342,7 +344,7 @@ unum_fill(struct mcamd_hdl *hdl, mcamd_node_t *cs, int which,
*/
static int
mc_whichdimm(struct mcamd_hdl *hdl, mcamd_node_t *cs, uint64_t pa,
- uint32_t synd, int syndtype)
+ uint8_t valid_lo, uint32_t synd, int syndtype)
{
int lobit, hibit, data, check;
uint64_t dimm1, dimm2;
@@ -379,14 +381,22 @@ mc_whichdimm(struct mcamd_hdl *hdl, mcamd_node_t *cs, uint64_t pa,
/*
* 64/8 ECC is checked separately for the upper and lower
* halves, so even an uncorrectable error is contained within
- * one of the two halves. The error address is accurate to
- * 8 bytes, so bit 4 distinguises upper from lower.
+ * one of the two halves. If we have sufficient address resolution
+ * then we can determine which DIMM.
*/
if (syndtype == AMD_SYNDTYPE_ECC) {
- mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_whichdimm: 64/8 ECC "
- "and PA 0x%llx is in %s half\n", pa,
- pa & 8 ? "lower" : "upper");
- return (pa & 8 ? CSDIMM2 : CSDIMM1);
+ if (valid_lo <= MC_SYSADDR_LSB) {
+ mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_whichdimm: 64/8 "
+ "ECC in 128-bit mode, PA 0x%llx is in %s half\n",
+ pa, pa & 0x8 ? "upper" : "lower");
+ return (pa & 0x8 ? CSDIMM2 : CSDIMM1);
+ } else {
+ mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_whichdimm: "
+ "64/8 ECC in 128-bit mode, PA 0x%llx with least "
+ "significant valid bit %d cannot be resolved to "
+ "a single DIMM\n", pa, valid_lo);
+ return (mcamd_set_errno(hdl, EMCAMD_INSUFF_RES));
+ }
}
/*
@@ -430,7 +440,8 @@ mc_whichdimm(struct mcamd_hdl *hdl, mcamd_node_t *cs, uint64_t pa,
*/
static int
mc_bkdg_patounum(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
- uint32_t synd, int syndtype, mc_unum_t *unump)
+ uint8_t valid_lo, uint32_t synd, int syndtype,
+ mc_unum_t *unump)
{
int which;
uint64_t mcnum, rev;
@@ -565,8 +576,8 @@ mc_bkdg_patounum(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
if ((sparecs = cs_sparedto(hdl, cs, mc)) != NULL)
cs = sparecs;
- if ((which = mc_whichdimm(hdl, cs, pa, synd,
- syndtype)) < 0)
+ if ((which = mc_whichdimm(hdl, cs, pa, valid_lo,
+ synd, syndtype)) < 0)
return (-1); /* errno is set for us */
/*
@@ -597,7 +608,7 @@ mc_bkdg_patounum(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
/*ARGSUSED*/
static int
mc_patounum(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
- uint32_t synd, int syndtype, mc_unum_t *unump)
+ uint8_t valid_lo, uint32_t synd, int syndtype, mc_unum_t *unump)
{
uint64_t iaddr;
mcamd_node_t *cs, *sparecs;
@@ -612,7 +623,8 @@ mc_patounum(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
* difficult to review against the BKDG approach.
*/
mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "BKDG brute-force method begins\n");
- bkdgres = mc_bkdg_patounum(hdl, mc, pa, synd, syndtype, &bkdg_unum);
+ bkdgres = mc_bkdg_patounum(hdl, mc, pa, valid_lo, synd,
+ syndtype, &bkdg_unum);
mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "BKDG brute-force method ends\n");
#endif
@@ -639,7 +651,8 @@ mc_patounum(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
cs = sparecs;
}
- if ((which = mc_whichdimm(hdl, cs, pa, synd, syndtype)) < 0)
+ if ((which = mc_whichdimm(hdl, cs, pa, valid_lo, synd,
+ syndtype)) < 0)
return (-1); /* errno is set for us */
if (unum_fill(hdl, cs, which, iaddr, unump, 1) < 0)
@@ -676,24 +689,27 @@ mc_patounum(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
int
mcamd_patounum(struct mcamd_hdl *hdl, mcamd_node_t *root, uint64_t pa,
- uint32_t synd, int syndtype, mc_unum_t *unump)
+ uint8_t valid_hi, uint8_t valid_lo, uint32_t synd, int syndtype,
+ mc_unum_t *unump)
{
mcamd_node_t *mc;
mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_patounum: pa=0x%llx, "
"synd=0x%x, syndtype=%d\n", pa, synd, syndtype);
- /*
- * Consider allowing syndrome 0 to act as a generic multibit
- * syndrome. For example icache inf_sys_ecc1 captures an address
- * but no syndrome - we can still resolve this to a dimm or dimms.
- */
+ if (valid_hi < MC_SYSADDR_MSB) {
+ mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_patounum: require "
+ "pa<%d> to be valid\n", MC_SYSADDR_MSB);
+ return (mcamd_set_errno(hdl, EMCAMD_INSUFF_RES));
+ }
+
if (!mcamd_synd_validate(hdl, synd, syndtype))
return (mcamd_set_errno(hdl, EMCAMD_SYNDINVALID));
for (mc = mcamd_mc_next(hdl, root, NULL); mc != NULL;
mc = mcamd_mc_next(hdl, root, mc)) {
- if (mc_patounum(hdl, mc, pa, synd, syndtype, unump) == 0)
+ if (mc_patounum(hdl, mc, pa, valid_lo, synd,
+ syndtype, unump) == 0)
return (0);
if (mcamd_errno(hdl) != EMCAMD_NOADDR)