Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f65ac45e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
  x86, mce: do not compile mcelog message on AMD
  EDAC, AMD: decode FR MCEs
  EDAC, AMD: decode load store MCEs
  EDAC, AMD: decode bus unit MCEs
  EDAC, AMD: decode instruction cache MCEs
  EDAC, AMD: decode data cache MCEs
  EDAC, AMD: carve out decoding of MCi_STATUS ErrorCode
  EDAC, AMD: carve out MCi_STATUS decoding
  x86, mce: pass mce info to EDAC for decoding
  amd64_edac: cleanup amd64_decode_bus_error
  amd64_edac: remove memory and GART TLB error decoders
  amd64_edac: cleanup/complete NB MCE decoding
  amd64_edac: cleanup amd64_process_error_info
  EDAC: beef up ErrorCodeExt error signatures
  EDAC: move MCE error descriptions to EDAC core
parents 4142e0d1 22223c9b
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -183,6 +183,11 @@ void mce_log(struct mce *mce)
	set_bit(0, &mce_need_notify);
}

void __weak decode_mce(struct mce *m)
{
	return;
}

static void print_mce(struct mce *m)
{
	printk(KERN_EMERG
@@ -205,6 +210,8 @@ static void print_mce(struct mce *m)
	printk(KERN_EMERG "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
			m->cpuvendor, m->cpuid, m->time, m->socketid,
			m->apicid);

	decode_mce(m);
}

static void print_mce_head(void)
@@ -215,7 +222,10 @@ static void print_mce_head(void)
static void print_mce_tail(void)
{
	printk(KERN_EMERG "This is not a software problem!\n"
	       "Run through mcelog --ascii to decode and contact your hardware vendor\n");
#if (!defined(CONFIG_EDAC) || !defined(CONFIG_CPU_SUP_AMD))
	       "Run through mcelog --ascii to decode and contact your hardware vendor\n"
#endif
	       );
}

#define PANIC_TIMEOUT 5 /* 5 seconds */
+5 −1
Original line number Diff line number Diff line
@@ -17,6 +17,10 @@ ifdef CONFIG_PCI
edac_core-objs	+= edac_pci.o edac_pci_sysfs.o
endif

ifdef CONFIG_CPU_SUP_AMD
edac_core-objs  += edac_mce_amd.o
endif

obj-$(CONFIG_EDAC_AMD76X)		+= amd76x_edac.o
obj-$(CONFIG_EDAC_CPC925)		+= cpc925_edac.o
obj-$(CONFIG_EDAC_I5000)		+= i5000_edac.o
@@ -32,7 +36,7 @@ obj-$(CONFIG_EDAC_X38) += x38_edac.o
obj-$(CONFIG_EDAC_I82860)		+= i82860_edac.o
obj-$(CONFIG_EDAC_R82600)		+= r82600_edac.o

amd64_edac_mod-y :=  amd64_edac_err_types.o amd64_edac.o
amd64_edac_mod-y := amd64_edac.o
amd64_edac_mod-$(CONFIG_EDAC_DEBUG) += amd64_edac_dbg.o
amd64_edac_mod-$(CONFIG_EDAC_AMD64_ERROR_INJECTION) += amd64_edac_inj.o

+107 −221
Original line number Diff line number Diff line
@@ -18,6 +18,63 @@ struct amd64_pvt;
static struct mem_ctl_info *mci_lookup[MAX_NUMNODES];
static struct amd64_pvt *pvt_lookup[MAX_NUMNODES];

/*
 * See F2x80 for K8 and F2x[1,0]80 for Fam10 and later. The table below is only
 * for DDR2 DRAM mapping.
 */
u32 revf_quad_ddr2_shift[] = {
	0,	/* 0000b NULL DIMM (128mb) */
	28,	/* 0001b 256mb */
	29,	/* 0010b 512mb */
	29,	/* 0011b 512mb */
	29,	/* 0100b 512mb */
	30,	/* 0101b 1gb */
	30,	/* 0110b 1gb */
	31,	/* 0111b 2gb */
	31,	/* 1000b 2gb */
	32,	/* 1001b 4gb */
	32,	/* 1010b 4gb */
	33,	/* 1011b 8gb */
	0,	/* 1100b future */
	0,	/* 1101b future */
	0,	/* 1110b future */
	0	/* 1111b future */
};

/*
 * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing
 * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching-
 * or higher value'.
 *
 *FIXME: Produce a better mapping/linearisation.
 */

struct scrubrate scrubrates[] = {
	{ 0x01, 1600000000UL},
	{ 0x02, 800000000UL},
	{ 0x03, 400000000UL},
	{ 0x04, 200000000UL},
	{ 0x05, 100000000UL},
	{ 0x06, 50000000UL},
	{ 0x07, 25000000UL},
	{ 0x08, 12284069UL},
	{ 0x09, 6274509UL},
	{ 0x0A, 3121951UL},
	{ 0x0B, 1560975UL},
	{ 0x0C, 781440UL},
	{ 0x0D, 390720UL},
	{ 0x0E, 195300UL},
	{ 0x0F, 97650UL},
	{ 0x10, 48854UL},
	{ 0x11, 24427UL},
	{ 0x12, 12213UL},
	{ 0x13, 6101UL},
	{ 0x14, 3051UL},
	{ 0x15, 1523UL},
	{ 0x16, 761UL},
	{ 0x00, 0UL},        /* scrubbing off */
};

/*
 * Memory scrubber control interface. For K8, memory scrubbing is handled by
 * hardware and can involve L2 cache, dcache as well as the main memory. With
@@ -693,7 +750,7 @@ static void find_csrow_limits(struct mem_ctl_info *mci, int csrow,
 * specific.
 */
static u64 extract_error_address(struct mem_ctl_info *mci,
				 struct amd64_error_info_regs *info)
				 struct err_regs *info)
{
	struct amd64_pvt *pvt = mci->pvt_info;

@@ -1049,7 +1106,7 @@ static int k8_early_channel_count(struct amd64_pvt *pvt)

/* extract the ERROR ADDRESS for the K8 CPUs */
static u64 k8_get_error_address(struct mem_ctl_info *mci,
				struct amd64_error_info_regs *info)
				struct err_regs *info)
{
	return (((u64) (info->nbeah & 0xff)) << 32) +
			(info->nbeal & ~0x03);
@@ -1092,7 +1149,7 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
}

static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
					struct amd64_error_info_regs *info,
					struct err_regs *info,
					u64 SystemAddress)
{
	struct mem_ctl_info *src_mci;
@@ -1101,8 +1158,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
	u32 page, offset;

	/* Extract the syndrome parts and form a 16-bit syndrome */
	syndrome = EXTRACT_HIGH_SYNDROME(info->nbsl) << 8;
	syndrome |= EXTRACT_LOW_SYNDROME(info->nbsh);
	syndrome  = HIGH_SYNDROME(info->nbsl) << 8;
	syndrome |= LOW_SYNDROME(info->nbsh);

	/* CHIPKILL enabled */
	if (info->nbcfg & K8_NBCFG_CHIPKILL) {
@@ -1311,7 +1368,7 @@ static void amd64_teardown(struct amd64_pvt *pvt)
}

static u64 f10_get_error_address(struct mem_ctl_info *mci,
			struct amd64_error_info_regs *info)
			struct err_regs *info)
{
	return (((u64) (info->nbeah & 0xffff)) << 32) +
			(info->nbeal & ~0x01);
@@ -1688,7 +1745,7 @@ static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
 * The @sys_addr is usually an error address received from the hardware.
 */
static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
				     struct amd64_error_info_regs *info,
				     struct err_regs *info,
				     u64 sys_addr)
{
	struct amd64_pvt *pvt = mci->pvt_info;
@@ -1701,8 +1758,8 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
	if (csrow >= 0) {
		error_address_to_page_and_offset(sys_addr, &page, &offset);

		syndrome = EXTRACT_HIGH_SYNDROME(info->nbsl) << 8;
		syndrome |= EXTRACT_LOW_SYNDROME(info->nbsh);
		syndrome  = HIGH_SYNDROME(info->nbsl) << 8;
		syndrome |= LOW_SYNDROME(info->nbsh);

		/*
		 * Is CHIPKILL on? If so, then we can attempt to use the
@@ -2045,7 +2102,7 @@ static int get_channel_from_ecc_syndrome(unsigned short syndrome)
 *	- 0: if no valid error is indicated
 */
static int amd64_get_error_info_regs(struct mem_ctl_info *mci,
				     struct amd64_error_info_regs *regs)
				     struct err_regs *regs)
{
	struct amd64_pvt *pvt;
	struct pci_dev *misc_f3_ctl;
@@ -2094,10 +2151,10 @@ static int amd64_get_error_info_regs(struct mem_ctl_info *mci,
 *	- 0: if no error is found
 */
static int amd64_get_error_info(struct mem_ctl_info *mci,
				struct amd64_error_info_regs *info)
				struct err_regs *info)
{
	struct amd64_pvt *pvt;
	struct amd64_error_info_regs regs;
	struct err_regs regs;

	pvt = mci->pvt_info;

@@ -2152,48 +2209,12 @@ static int amd64_get_error_info(struct mem_ctl_info *mci,
	return 1;
}

static inline void amd64_decode_gart_tlb_error(struct mem_ctl_info *mci,
					 struct amd64_error_info_regs *info)
{
	u32 err_code;
	u32 ec_tt;		/* error code transaction type (2b) */
	u32 ec_ll;		/* error code cache level (2b) */

	err_code = EXTRACT_ERROR_CODE(info->nbsl);
	ec_ll = EXTRACT_LL_CODE(err_code);
	ec_tt = EXTRACT_TT_CODE(err_code);

	amd64_mc_printk(mci, KERN_ERR,
		     "GART TLB event: transaction type(%s), "
		     "cache level(%s)\n", tt_msgs[ec_tt], ll_msgs[ec_ll]);
}

static inline void amd64_decode_mem_cache_error(struct mem_ctl_info *mci,
				      struct amd64_error_info_regs *info)
{
	u32 err_code;
	u32 ec_rrrr;		/* error code memory transaction (4b) */
	u32 ec_tt;		/* error code transaction type (2b) */
	u32 ec_ll;		/* error code cache level (2b) */

	err_code = EXTRACT_ERROR_CODE(info->nbsl);
	ec_ll = EXTRACT_LL_CODE(err_code);
	ec_tt = EXTRACT_TT_CODE(err_code);
	ec_rrrr = EXTRACT_RRRR_CODE(err_code);

	amd64_mc_printk(mci, KERN_ERR,
		     "cache hierarchy error: memory transaction type(%s), "
		     "transaction type(%s), cache level(%s)\n",
		     rrrr_msgs[ec_rrrr], tt_msgs[ec_tt], ll_msgs[ec_ll]);
}


/*
 * Handle any Correctable Errors (CEs) that have occurred. Check for valid ERROR
 * ADDRESS and process.
 */
static void amd64_handle_ce(struct mem_ctl_info *mci,
			    struct amd64_error_info_regs *info)
			    struct err_regs *info)
{
	struct amd64_pvt *pvt = mci->pvt_info;
	u64 SystemAddress;
@@ -2216,7 +2237,7 @@ static void amd64_handle_ce(struct mem_ctl_info *mci,

/* Handle any Un-correctable Errors (UEs) */
static void amd64_handle_ue(struct mem_ctl_info *mci,
			    struct amd64_error_info_regs *info)
			    struct err_regs *info)
{
	int csrow;
	u64 SystemAddress;
@@ -2261,59 +2282,24 @@ static void amd64_handle_ue(struct mem_ctl_info *mci,
	}
}

static void amd64_decode_bus_error(struct mem_ctl_info *mci,
				   struct amd64_error_info_regs *info)
static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
					    struct err_regs *info)
{
	u32 err_code, ext_ec;
	u32 ec_pp;		/* error code participating processor (2p) */
	u32 ec_to;		/* error code timed out (1b) */
	u32 ec_rrrr;		/* error code memory transaction (4b) */
	u32 ec_ii;		/* error code memory or I/O (2b) */
	u32 ec_ll;		/* error code cache level (2b) */

	ext_ec = EXTRACT_EXT_ERROR_CODE(info->nbsl);
	err_code = EXTRACT_ERROR_CODE(info->nbsl);

	ec_ll = EXTRACT_LL_CODE(err_code);
	ec_ii = EXTRACT_II_CODE(err_code);
	ec_rrrr = EXTRACT_RRRR_CODE(err_code);
	ec_to = EXTRACT_TO_CODE(err_code);
	ec_pp = EXTRACT_PP_CODE(err_code);
	u32 ec  = ERROR_CODE(info->nbsl);
	u32 xec = EXT_ERROR_CODE(info->nbsl);
	int ecc_type = info->nbsh & (0x3 << 13);

	amd64_mc_printk(mci, KERN_ERR,
		"BUS ERROR:\n"
		"  time-out(%s) mem or i/o(%s)\n"
		"  participating processor(%s)\n"
		"  memory transaction type(%s)\n"
		"  cache level(%s) Error Found by: %s\n",
		to_msgs[ec_to],
		ii_msgs[ec_ii],
		pp_msgs[ec_pp],
		rrrr_msgs[ec_rrrr],
		ll_msgs[ec_ll],
		(info->nbsh & K8_NBSH_ERR_SCRUBER) ?
			"Scrubber" : "Normal Operation");

	/* If this was an 'observed' error, early out */
	if (ec_pp == K8_NBSL_PP_OBS)
		return;		/* We aren't the node involved */

	/* Parse out the extended error code for ECC events */
	switch (ext_ec) {
	/* F10 changed to one Extended ECC error code */
	case F10_NBSL_EXT_ERR_RES:		/* Reserved field */
	case F10_NBSL_EXT_ERR_ECC:		/* F10 ECC ext err code */
		break;
	/* Bail early out if this was an 'observed' error */
	if (PP(ec) == K8_NBSL_PP_OBS)
		return;

	default:
		amd64_mc_printk(mci, KERN_ERR, "NOT ECC: no special error "
					       "handling for this error\n");
	/* Do only ECC errors */
	if (xec && xec != F10_NBSL_EXT_ERR_ECC)
		return;
	}

	if (info->nbsh & K8_NBSH_CECC)
	if (ecc_type == 2)
		amd64_handle_ce(mci, info);
	else if (info->nbsh & K8_NBSH_UECC)
	else if (ecc_type == 1)
		amd64_handle_ue(mci, info);

	/*
@@ -2324,139 +2310,26 @@ static void amd64_decode_bus_error(struct mem_ctl_info *mci,
	 * catastrophic.
	 */
	if (info->nbsh & K8_NBSH_OVERFLOW)
		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR
					  "Error Overflow set");
		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR "Error Overflow");
}

int amd64_process_error_info(struct mem_ctl_info *mci,
			     struct amd64_error_info_regs *info,
			     int handle_errors)
void amd64_decode_bus_error(int node_id, struct err_regs *regs)
{
	struct amd64_pvt *pvt;
	struct amd64_error_info_regs *regs;
	u32 err_code, ext_ec;
	int gart_tlb_error = 0;

	pvt = mci->pvt_info;
	struct mem_ctl_info *mci = mci_lookup[node_id];

	/* If caller doesn't want us to process the error, return */
	if (!handle_errors)
		return 1;

	regs = info;

	debugf1("NorthBridge ERROR: mci(0x%p)\n", mci);
	debugf1("  MC node(%d) Error-Address(0x%.8x-%.8x)\n",
		pvt->mc_node_id, regs->nbeah, regs->nbeal);
	debugf1("  nbsh(0x%.8x) nbsl(0x%.8x)\n",
		regs->nbsh, regs->nbsl);
	debugf1("  Valid Error=%s Overflow=%s\n",
		(regs->nbsh & K8_NBSH_VALID_BIT) ? "True" : "False",
		(regs->nbsh & K8_NBSH_OVERFLOW) ? "True" : "False");
	debugf1("  Err Uncorrected=%s MCA Error Reporting=%s\n",
		(regs->nbsh & K8_NBSH_UNCORRECTED_ERR) ?
			"True" : "False",
		(regs->nbsh & K8_NBSH_ERR_ENABLE) ?
			"True" : "False");
	debugf1("  MiscErr Valid=%s ErrAddr Valid=%s PCC=%s\n",
		(regs->nbsh & K8_NBSH_MISC_ERR_VALID) ?
			"True" : "False",
		(regs->nbsh & K8_NBSH_VALID_ERROR_ADDR) ?
			"True" : "False",
		(regs->nbsh & K8_NBSH_PCC) ?
			"True" : "False");
	debugf1("  CECC=%s UECC=%s Found by Scruber=%s\n",
		(regs->nbsh & K8_NBSH_CECC) ?
			"True" : "False",
		(regs->nbsh & K8_NBSH_UECC) ?
			"True" : "False",
		(regs->nbsh & K8_NBSH_ERR_SCRUBER) ?
			"True" : "False");
	debugf1("  CORE0=%s CORE1=%s CORE2=%s CORE3=%s\n",
		(regs->nbsh & K8_NBSH_CORE0) ? "True" : "False",
		(regs->nbsh & K8_NBSH_CORE1) ? "True" : "False",
		(regs->nbsh & K8_NBSH_CORE2) ? "True" : "False",
		(regs->nbsh & K8_NBSH_CORE3) ? "True" : "False");


	err_code = EXTRACT_ERROR_CODE(regs->nbsl);

	/* Determine which error type:
	 *	1) GART errors - non-fatal, developmental events
	 *	2) MEMORY errors
	 *	3) BUS errors
	 *	4) Unknown error
	 */
	if (TEST_TLB_ERROR(err_code)) {
		/*
		 * GART errors are intended to help graphics driver developers
		 * to detect bad GART PTEs. It is recommended by AMD to disable
		 * GART table walk error reporting by default[1] (currently
		 * being disabled in mce_cpu_quirks()) and according to the
		 * comment in mce_cpu_quirks(), such GART errors can be
		 * incorrectly triggered. We may see these errors anyway and
		 * unless requested by the user, they won't be reported.
		 *
		 * [1] section 13.10.1 on BIOS and Kernel Developers Guide for
		 *     AMD NPT family 0Fh processors
		 */
		if (report_gart_errors == 0)
			return 1;

		/*
		 * Only if GART error reporting is requested should we generate
		 * any logs.
		 */
		gart_tlb_error = 1;

		debugf1("GART TLB error\n");
		amd64_decode_gart_tlb_error(mci, info);
	} else if (TEST_MEM_ERROR(err_code)) {
		debugf1("Memory/Cache error\n");
		amd64_decode_mem_cache_error(mci, info);
	} else if (TEST_BUS_ERROR(err_code)) {
		debugf1("Bus (Link/DRAM) error\n");
		amd64_decode_bus_error(mci, info);
	} else {
		/* shouldn't reach here! */
		amd64_mc_printk(mci, KERN_WARNING,
			     "%s(): unknown MCE error 0x%x\n", __func__,
			     err_code);
	}

	ext_ec = EXTRACT_EXT_ERROR_CODE(regs->nbsl);
	amd64_mc_printk(mci, KERN_ERR,
		"ExtErr=(0x%x) %s\n", ext_ec, ext_msgs[ext_ec]);

	if (((ext_ec >= F10_NBSL_EXT_ERR_CRC &&
			ext_ec <= F10_NBSL_EXT_ERR_TGT) ||
			(ext_ec == F10_NBSL_EXT_ERR_RMW)) &&
			EXTRACT_LDT_LINK(info->nbsh)) {

		amd64_mc_printk(mci, KERN_ERR,
			"Error on hypertransport link: %s\n",
			htlink_msgs[
			EXTRACT_LDT_LINK(info->nbsh)]);
	}
	__amd64_decode_bus_error(mci, regs);

	/*
	 * Check the UE bit of the NB status high register, if set generate some
	 * logs. If NOT a GART error, then process the event as a NO-INFO event.
	 * If it was a GART error, skip that process.
	 *
	 * FIXME: this should go somewhere else, if at all.
	 */
	if (regs->nbsh & K8_NBSH_UNCORRECTED_ERR) {
		amd64_mc_printk(mci, KERN_CRIT, "uncorrected error\n");
		if (!gart_tlb_error)
			edac_mc_handle_ue_no_info(mci, "UE bit is set\n");
	}

	if (regs->nbsh & K8_NBSH_PCC)
		amd64_mc_printk(mci, KERN_CRIT,
			"PCC (processor context corrupt) set\n");
	if (regs->nbsh & K8_NBSH_UC_ERR && !report_gart_errors)
		edac_mc_handle_ue_no_info(mci, "UE bit is set");

	return 1;
}
EXPORT_SYMBOL_GPL(amd64_process_error_info);

/*
 * The main polling 'check' function, called FROM the edac core to perform the
@@ -2464,10 +2337,12 @@ EXPORT_SYMBOL_GPL(amd64_process_error_info);
 */
static void amd64_check(struct mem_ctl_info *mci)
{
	struct amd64_error_info_regs info;
	struct err_regs regs;

	if (amd64_get_error_info(mci, &info))
		amd64_process_error_info(mci, &info, 1);
	if (amd64_get_error_info(mci, &regs)) {
		struct amd64_pvt *pvt = mci->pvt_info;
		amd_decode_nb_mce(pvt->mc_node_id, &regs, 1);
	}
}

/*
@@ -3163,6 +3038,13 @@ static int amd64_init_2nd_stage(struct amd64_pvt *pvt)

	mci_lookup[node_id] = mci;
	pvt_lookup[node_id] = NULL;

	/* register stuff with EDAC MCE */
	if (report_gart_errors)
		amd_report_gart_errors(true);

	amd_register_ecc_decoder(amd64_decode_bus_error);

	return 0;

err_add_mc:
@@ -3229,6 +3111,10 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev)

	mci_lookup[pvt->mc_node_id] = NULL;

	/* unregister from EDAC MCE */
	amd_report_gart_errors(false);
	amd_unregister_ecc_decoder(amd64_decode_bus_error);

	/* Free the EDAC CORE resources */
	edac_mc_free(mci);
}
+4 −67
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@
#include <linux/edac.h>
#include <asm/msr.h>
#include "edac_core.h"
#include "edac_mce_amd.h"

#define amd64_printk(level, fmt, arg...) \
	edac_printk(level, "amd64", fmt, ##arg)
@@ -303,21 +304,9 @@ enum {
#define K8_NBSL				0x48


#define EXTRACT_HIGH_SYNDROME(x)	(((x) >> 24) & 0xff)
#define EXTRACT_EXT_ERROR_CODE(x)	(((x) >> 16) & 0x1f)

/* Family F10h: Normalized Extended Error Codes */
#define F10_NBSL_EXT_ERR_RES		0x0
#define F10_NBSL_EXT_ERR_CRC		0x1
#define F10_NBSL_EXT_ERR_SYNC		0x2
#define F10_NBSL_EXT_ERR_MST		0x3
#define F10_NBSL_EXT_ERR_TGT		0x4
#define F10_NBSL_EXT_ERR_GART		0x5
#define F10_NBSL_EXT_ERR_RMW		0x6
#define F10_NBSL_EXT_ERR_WDT		0x7
#define F10_NBSL_EXT_ERR_ECC		0x8
#define F10_NBSL_EXT_ERR_DEV		0x9
#define F10_NBSL_EXT_ERR_LINK_DATA	0xA

/* Next two are overloaded values */
#define F10_NBSL_EXT_ERR_LINK_PROTO	0xB
@@ -348,17 +337,6 @@ enum {
#define K8_NBSL_EXT_ERR_CHIPKILL_ECC	0x8
#define K8_NBSL_EXT_ERR_DRAM_PARITY	0xD

#define EXTRACT_ERROR_CODE(x)		((x) & 0xffff)
#define	TEST_TLB_ERROR(x)		(((x) & 0xFFF0) == 0x0010)
#define	TEST_MEM_ERROR(x)		(((x) & 0xFF00) == 0x0100)
#define	TEST_BUS_ERROR(x)		(((x) & 0xF800) == 0x0800)
#define	EXTRACT_TT_CODE(x)		(((x) >> 2) & 0x3)
#define	EXTRACT_II_CODE(x)		(((x) >> 2) & 0x3)
#define	EXTRACT_LL_CODE(x)		(((x) >> 0) & 0x3)
#define	EXTRACT_RRRR_CODE(x)		(((x) >> 4) & 0xf)
#define	EXTRACT_TO_CODE(x)		(((x) >> 8) & 0x1)
#define	EXTRACT_PP_CODE(x)		(((x) >> 9) & 0x3)

/*
 * The following are for BUS type errors AFTER values have been normalized by
 * shifting right
@@ -368,28 +346,7 @@ enum {
#define K8_NBSL_PP_OBS			0x2
#define K8_NBSL_PP_GENERIC		0x3


#define K8_NBSH				0x4C

#define K8_NBSH_VALID_BIT		BIT(31)
#define K8_NBSH_OVERFLOW		BIT(30)
#define K8_NBSH_UNCORRECTED_ERR		BIT(29)
#define K8_NBSH_ERR_ENABLE		BIT(28)
#define K8_NBSH_MISC_ERR_VALID		BIT(27)
#define K8_NBSH_VALID_ERROR_ADDR	BIT(26)
#define K8_NBSH_PCC			BIT(25)
#define K8_NBSH_CECC			BIT(14)
#define K8_NBSH_UECC			BIT(13)
#define K8_NBSH_ERR_SCRUBER		BIT(8)
#define K8_NBSH_CORE3			BIT(3)
#define K8_NBSH_CORE2			BIT(2)
#define K8_NBSH_CORE1			BIT(1)
#define K8_NBSH_CORE0			BIT(0)

#define EXTRACT_LDT_LINK(x)		(((x) >> 4) & 0x7)
#define EXTRACT_ERR_CPU_MAP(x)		((x) & 0xF)
#define EXTRACT_LOW_SYNDROME(x)		(((x) >> 15) & 0xff)


#define K8_NBEAL			0x50
#define K8_NBEAH			0x54
@@ -455,23 +412,6 @@ enum amd64_chipset_families {
	F11_CPUS,
};

/*
 * Structure to hold:
 *
 * 1) dynamically read status and error address HW registers
 * 2) sysfs entered values
 * 3) MCE values
 *
 * Depends on entry into the modules
 */
struct amd64_error_info_regs {
	u32 nbcfg;
	u32 nbsh;
	u32 nbsl;
	u32 nbeah;
	u32 nbeal;
};

/* Error injection control structure */
struct error_injection {
	u32	section;
@@ -542,7 +482,7 @@ struct amd64_pvt {
	u32 online_spare;               /* On-Line spare Reg */

	/* temp storage for when input is received from sysfs */
	struct amd64_error_info_regs ctl_error_info;
	struct err_regs ctl_error_info;

	/* place to store error injection parameters prior to issue */
	struct error_injection injection;
@@ -601,11 +541,11 @@ struct low_ops {
	int (*early_channel_count)(struct amd64_pvt *pvt);

	u64 (*get_error_address)(struct mem_ctl_info *mci,
			struct amd64_error_info_regs *info);
			struct err_regs *info);
	void (*read_dram_base_limit)(struct amd64_pvt *pvt, int dram);
	void (*read_dram_ctl_register)(struct amd64_pvt *pvt);
	void (*map_sysaddr_to_csrow)(struct mem_ctl_info *mci,
					struct amd64_error_info_regs *info,
					struct err_regs *info,
					u64 SystemAddr);
	int (*dbam_map_to_pages)(struct amd64_pvt *pvt, int dram_map);
};
@@ -637,8 +577,5 @@ static inline struct low_ops *family_ops(int index)
#define F10_MIN_SCRUB_RATE_BITS	0x5
#define F11_MIN_SCRUB_RATE_BITS	0x6

int amd64_process_error_info(struct mem_ctl_info *mci,
			     struct amd64_error_info_regs *info,
			     int handle_errors);
int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
			     u64 *hole_offset, u64 *hole_size);
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data,

		/* Process the Mapping request */
		/* TODO: Add race prevention */
		amd64_process_error_info(mci, &pvt->ctl_error_info, 1);
		amd_decode_nb_mce(pvt->mc_node_id, &pvt->ctl_error_info, 1);

		return count;
	}
Loading