Error Detection And Correction (EDAC) Devices¶
Main Concepts used at the EDAC subsystem¶
There are several things to be aware of that aren’t at all obvious, likesockets, *socket sets,banks,rows,chip-select rows,channels,etc...
These are some of the many terms that are thrown about that don’t alwaysmean what people think they mean (Inconceivable!). In the interest ofcreating a common ground for discussion, terms and their definitionswill be established.
Memory devices
The individual DRAM chips on a memory stick. These devices commonlyoutput 4 and 8 bits each (x4, x8). Grouping several of these in parallelprovides the number of bits that the memory controller expects:typically 72 bits, in order to provide 64 bits + 8 bits of ECC data.
Memory Stick
A printed circuit board that aggregates multiple memory devices inparallel. In general, this is the Field Replaceable Unit (FRU) whichgets replaced, in the case of excessive errors. Most often it is alsocalled DIMM (Dual Inline Memory Module).
Memory Socket
A physical connector on the motherboard that accepts a single memorystick. Also called as “slot” on several datasheets.
Channel
A memory controller channel, responsible to communicate with a group ofDIMMs. Each channel has its own independent control (command) and databus, and can be used independently or grouped with other channels.
Branch
It is typically the highest hierarchy on a Fully-Buffered DIMM memorycontroller. Typically, it contains two channels. Two channels at thesame branch can be used in single mode or in lockstep mode. Whenlockstep is enabled, the cacheline is doubled, but it generally bringssome performance penalty. Also, it is generally not possible to point tojust one memory stick when an error occurs, as the error correction codeis calculated using two DIMMs instead of one. Due to that, it is capableof correcting more errors than on single mode.
Single-channel
The data accessed by the memory controller is contained into one dimmonly. E. g. if the data is 64 bits-wide, the data flows to the CPU usingone 64 bits parallel access. Typically used with SDR, DDR, DDR2 and DDR3memories. FB-DIMM and RAMBUS use a different concept for channel, sothis concept doesn’t apply there.
Double-channel
The data size accessed by the memory controller is interlaced into twodimms, accessed at the same time. E. g. if the DIMM is 64 bits-wide (72bits with ECC), the data flows to the CPU using a 128 bits parallelaccess.
Chip-select row
This is the name of the DRAM signal used to select the DRAM ranks to beaccessed. Common chip-select rows for single channel are 64 bits, fordual channel 128 bits. It may not be visible by the memory controller,as some DIMM types have a memory buffer that can hide direct access toit from the Memory Controller.
Single-Ranked stick
A Single-ranked stick has 1 chip-select row of memory. Motherboardscommonly drive two chip-select pins to a memory stick. A single-rankedstick, will occupy only one of those rows. The other will be unused.
Double-Ranked stick
A double-ranked stick has two chip-select rows which access differentsets of memory devices. The two rows cannot be accessed concurrently.
Double-sided stick
DEPRECATED TERM, seeDouble-Ranked stick.
A double-sided stick has two chip-select rows which access different setsof memory devices. The two rows cannot be accessed concurrently.“Double-sided” is irrespective of the memory devices being mounted onboth sides of the memory stick.
Socket set
All of the memory sticks that are required for a single memory access orall of the memory sticks spanned by a chip-select row. A single socketset has two chip-select rows and if double-sided sticks are used thesewill occupy those chip-select rows.
Bank
This term is avoided because it is unclear when needing to distinguishbetween chip-select rows and socket sets.
High Bandwidth Memory (HBM)
HBM is a new memory type with low power consumption and ultra-widecommunication lanes. It uses vertically stacked memory chips (DRAM dies)interconnected by microscopic wires called “through-silicon vias,” orTSVs.
Several stacks of HBM chips connect to the CPU or GPU through an ultra-fastinterconnect called the “interposer”. Therefore, HBM’s characteristicsare nearly indistinguishable from on-chip integrated RAM.
Memory Controllers¶
Most of the EDAC core is focused on doing Memory Controller error detection.Theedac_mc_alloc(). It uses internally the structmem_ctl_infoto describe the memory controllers, with is an opaque struct for the EDACdrivers. Only the EDAC core is allowed to touch it.
- enumdev_type¶
describe the type of memory DRAM chips used at the stick
Constants
DEV_UNKNOWNCan’t be determined, or MC doesn’t support detect it
DEV_X11 bit for data
DEV_X22 bits for data
DEV_X44 bits for data
DEV_X88 bits for data
DEV_X1616 bits for data
DEV_X3232 bits for data
DEV_X6464 bits for data
Description
Typical values are x4 and x8.
- enumhw_event_mc_err_type¶
type of the detected error
Constants
HW_EVENT_ERR_CORRECTEDCorrected Error - Indicates that an ECCcorrected error was detected
HW_EVENT_ERR_UNCORRECTEDUncorrected Error - Indicates an error thatcan’t be corrected by ECC, but it is notfatal (maybe it is on an unused memory area,or the memory controller could recover fromit for example, by re-trying the operation).
HW_EVENT_ERR_DEFERREDDeferred Error - Indicates an uncorrectableerror whose handling is not urgent. This couldbe due to hardware data poisoning where thesystem can continue operation until the poisoneddata is consumed. Preemptive measures may alsobe taken, e.g. offlining pages, etc.
HW_EVENT_ERR_FATALFatal Error - Uncorrected error that could notbe recovered.
HW_EVENT_ERR_INFOInformational - The CPER spec defines a forthtype of error: informational logs.
- enummem_type¶
memory types. For a more detailed reference, please seehttp://en.wikipedia.org/wiki/DRAM
Constants
MEM_EMPTYEmpty csrow
MEM_RESERVEDReserved csrow type
MEM_UNKNOWNUnknown csrow type
MEM_FPMFPM - Fast Page Mode, used on systems up to 1995.
MEM_EDOEDO - Extended data out, used on systems up to 1998.
MEM_BEDOBEDO - Burst Extended data out, an EDO variant.
MEM_SDRSDR - Single data rate SDRAMhttp://en.wikipedia.org/wiki/Synchronous_dynamic_random-access_memoryThey use 3 pins for chip select: Pins 0 and 2 arefor rank 0; pins 1 and 3 are for rank 1, if the memoryis dual-rank.
MEM_RDRRegistered SDR SDRAM
MEM_DDRDouble data rate SDRAMhttp://en.wikipedia.org/wiki/DDR_SDRAM
MEM_RDDRRegistered Double data rate SDRAMThis is a variant of the DDR memories.A registered memory has a buffer inside it, hidingpart of the memory details to the memory controller.
MEM_RMBSRambus DRAM, used on a few Pentium III/IV controllers.
MEM_DDR2DDR2 RAM, as described at JEDEC JESD79-2F.Those memories are labeled as “PC2-” instead of “PC” todifferentiate from DDR.
MEM_FB_DDR2Fully-Buffered DDR2, as described at JEDEC Std No. 205and JESD206.Those memories are accessed per DIMM slot, and not bya chip select signal.
MEM_RDDR2Registered DDR2 RAMThis is a variant of the DDR2 memories.
MEM_XDRRambus XDRIt is an evolution of the original RAMBUS memories,created to compete with DDR2. Weren’t used on anyx86 arch, but cell_edac PPC memory controller uses it.
MEM_DDR3DDR3 RAM
MEM_RDDR3Registered DDR3 RAMThis is a variant of the DDR3 memories.
MEM_LRDDR3Load-Reduced DDR3 memory.
MEM_LPDDR3Low-Power DDR3 memory.
MEM_DDR4Unbuffered DDR4 RAM
MEM_RDDR4Registered DDR4 RAMThis is a variant of the DDR4 memories.
MEM_LRDDR4Load-Reduced DDR4 memory.
MEM_LPDDR4Low-Power DDR4 memory.
MEM_DDR5Unbuffered DDR5 RAM
MEM_RDDR5Registered DDR5 RAM
MEM_LRDDR5Load-Reduced DDR5 memory.
MEM_NVDIMMNon-volatile RAM
MEM_WIO2Wide I/O 2.
MEM_HBM2High bandwidth Memory Gen 2.
MEM_HBM3High bandwidth Memory Gen 3.
- enumedac_type¶
Error Detection and Correction capabilities and mode
Constants
EDAC_UNKNOWNUnknown if ECC is available
EDAC_NONEDoesn’t support ECC
EDAC_RESERVEDReserved ECC type
EDAC_PARITYDetects parity errors
EDAC_ECError Checking - no correction
EDAC_SECDEDSingle bit error correction, Double detection
EDAC_S2ECD2EDChipkill x2 devices - do these exist?
EDAC_S4ECD4EDChipkill x4 devices
EDAC_S8ECD8EDChipkill x8 devices
EDAC_S16ECD16EDChipkill x16 devices
- enumscrub_type¶
scrubbing capabilities
Constants
SCRUB_UNKNOWNUnknown if scrubber is available
SCRUB_NONENo scrubber
SCRUB_SW_PROGSW progressive (sequential) scrubbing
SCRUB_SW_SRCSoftware scrub only errors
SCRUB_SW_PROG_SRCProgressive software scrub from an error
SCRUB_SW_TUNABLESoftware scrub frequency is tunable
SCRUB_HW_PROGHW progressive (sequential) scrubbing
SCRUB_HW_SRCHardware scrub only errors
SCRUB_HW_PROG_SRCProgressive hardware scrub from an error
SCRUB_HW_TUNABLEHardware scrub frequency is tunable
- enumedac_mc_layer_type¶
memory controller hierarchy layer
Constants
EDAC_MC_LAYER_BRANCHmemory layer is named “branch”
EDAC_MC_LAYER_CHANNELmemory layer is named “channel”
EDAC_MC_LAYER_SLOTmemory layer is named “slot”
EDAC_MC_LAYER_CHIP_SELECTmemory layer is named “chip select”
EDAC_MC_LAYER_ALL_MEMmemory layout is unknown. All memory is mappedas a single memory area. This is used whenretrieving errors from a firmware driven driver.
Description
Thisenumis used by the drivers to tell edac_mc_sysfs what name shouldbe used when describing a memory stick location.
- structedac_mc_layer¶
describes the memory controller hierarchy
Definition:
struct edac_mc_layer { enum edac_mc_layer_type type; unsigned size; bool is_virt_csrow;};Members
typelayer type
sizenumber of components per layer. For example,if the channel layer has two channels, size = 2
is_virt_csrowThis layer is part of the “csrow” when old APIcompatibility mode is enabled. Otherwise, it isa channel
- structrank_info¶
contains the information for one DIMM rank
Definition:
struct rank_info { int chan_idx; struct csrow_info *csrow; struct dimm_info *dimm; u32 ce_count;};Members
chan_idxchannel number where the rank is (typically, 0 or 1)
csrowA pointer to the chip select row structure (the parentstructure). The location of the rank is given bythe (csrow->csrow_idx, chan_idx) vector.
dimmA pointer to the DIMM structure, where the DIMM labelinformation is stored.
ce_countnumber of correctable errors for this rank
Description
- FIXME: Currently, the EDAC core model will assume one DIMM per rank.
This is a bad assumption, but it makes this patch easier. Laterpatches in this series will fix this issue.
- structedac_raw_error_desc¶
Raw error report structure
Definition:
struct edac_raw_error_desc { char location[LOCATION_SIZE]; char label[(EDAC_MC_LABEL_LEN + 1 + sizeof(OTHER_LABEL)) * EDAC_MAX_LABELS]; long grain; u16 error_count; enum hw_event_mc_err_type type; int top_layer; int mid_layer; int low_layer; unsigned long page_frame_number; unsigned long offset_in_page; unsigned long syndrome; const char *msg; const char *other_detail;};Members
locationlocation of the error
labellabel of the affected DIMM(s)
grainminimum granularity for an error report, in bytes
error_countnumber of errors of the same type
typeseverity of the error (CE/UE/Fatal)
top_layertop layer of the error (layer[0])
mid_layermiddle layer of the error (layer[1])
low_layerlow layer of the error (layer[2])
page_frame_numberpage where the error happened
offset_in_pagepage offset
syndromesyndrome of the error (or 0 if unknown or ifthe syndrome is not applicable)
msgerror message
other_detailother driver-specific detail about the error
- structdimm_info*edac_get_dimm(structmem_ctl_info*mci,intlayer0,intlayer1,intlayer2)¶
Get DIMM info from a memory controller given by [layer0,layer1,layer2] position
Parameters
structmem_ctl_info*mciMC descriptor
structmem_ctl_infointlayer0layer0 position
intlayer1layer1 position. Unused if n_layers < 2
intlayer2layer2 position. Unused if n_layers < 3
Description
For 1 layer, this function returns “dimms[layer0]”;
For 2 layers, this function is similar to allocating a two-dimensionalarray and returning “dimms[layer0][layer1]”;
For 3 layers, this function is similar to allocating a tri-dimensionalarray and returning “dimms[layer0][layer1][layer2]”;
- structedac_scrub_ops¶
scrub device operations (all elements optional)
Definition:
struct edac_scrub_ops { int (*read_addr)(struct device *dev, void *drv_data, u64 *base); int (*read_size)(struct device *dev, void *drv_data, u64 *size); int (*write_addr)(struct device *dev, void *drv_data, u64 base); int (*write_size)(struct device *dev, void *drv_data, u64 size); int (*get_enabled_bg)(struct device *dev, void *drv_data, bool *enable); int (*set_enabled_bg)(struct device *dev, void *drv_data, bool enable); int (*get_min_cycle)(struct device *dev, void *drv_data, u32 *min); int (*get_max_cycle)(struct device *dev, void *drv_data, u32 *max); int (*get_cycle_duration)(struct device *dev, void *drv_data, u32 *cycle); int (*set_cycle_duration)(struct device *dev, void *drv_data, u32 cycle);};Members
read_addrread base address of scrubbing range.
read_sizeread offset of scrubbing range.
write_addrset base address of the scrubbing range.
write_sizeset offset of the scrubbing range.
get_enabled_bgcheck if currently performing background scrub.
set_enabled_bgstart or stop a bg-scrub.
get_min_cycleget minimum supported scrub cycle duration in seconds.
get_max_cycleget maximum supported scrub cycle duration in seconds.
get_cycle_durationget current scrub cycle duration in seconds.
set_cycle_durationset current scrub cycle duration in seconds.
- structedac_ecs_ops¶
ECS device operations (all elements optional)
Definition:
struct edac_ecs_ops { int (*get_log_entry_type)(struct device *dev, void *drv_data, int fru_id, u32 *val); int (*set_log_entry_type)(struct device *dev, void *drv_data, int fru_id, u32 val); int (*get_mode)(struct device *dev, void *drv_data, int fru_id, u32 *val); int (*set_mode)(struct device *dev, void *drv_data, int fru_id, u32 val); int (*reset)(struct device *dev, void *drv_data, int fru_id, u32 val); int (*get_threshold)(struct device *dev, void *drv_data, int fru_id, u32 *threshold); int (*set_threshold)(struct device *dev, void *drv_data, int fru_id, u32 threshold);};Members
get_log_entry_typeread the log entry type value.
set_log_entry_typeset the log entry type value.
get_moderead the mode value.
set_modeset the mode value.
resetreset the ECS counter.
get_thresholdread the threshold count per gigabits of memory cells.
set_thresholdset the threshold count per gigabits of memory cells.
- structedac_mem_repair_ops¶
memory repair operations (all elements are optional except do_repair, set_hpa/set_dpa)
Definition:
struct edac_mem_repair_ops { int (*get_repair_type)(struct device *dev, void *drv_data, const char **type); int (*get_persist_mode)(struct device *dev, void *drv_data, bool *persist); int (*set_persist_mode)(struct device *dev, void *drv_data, bool persist); int (*get_repair_safe_when_in_use)(struct device *dev, void *drv_data, bool *safe); int (*get_hpa)(struct device *dev, void *drv_data, u64 *hpa); int (*set_hpa)(struct device *dev, void *drv_data, u64 hpa); int (*get_min_hpa)(struct device *dev, void *drv_data, u64 *hpa); int (*get_max_hpa)(struct device *dev, void *drv_data, u64 *hpa); int (*get_dpa)(struct device *dev, void *drv_data, u64 *dpa); int (*set_dpa)(struct device *dev, void *drv_data, u64 dpa); int (*get_min_dpa)(struct device *dev, void *drv_data, u64 *dpa); int (*get_max_dpa)(struct device *dev, void *drv_data, u64 *dpa); int (*get_nibble_mask)(struct device *dev, void *drv_data, u32 *val); int (*set_nibble_mask)(struct device *dev, void *drv_data, u32 val); int (*get_bank_group)(struct device *dev, void *drv_data, u32 *val); int (*set_bank_group)(struct device *dev, void *drv_data, u32 val); int (*get_bank)(struct device *dev, void *drv_data, u32 *val); int (*set_bank)(struct device *dev, void *drv_data, u32 val); int (*get_rank)(struct device *dev, void *drv_data, u32 *val); int (*set_rank)(struct device *dev, void *drv_data, u32 val); int (*get_row)(struct device *dev, void *drv_data, u32 *val); int (*set_row)(struct device *dev, void *drv_data, u32 val); int (*get_column)(struct device *dev, void *drv_data, u32 *val); int (*set_column)(struct device *dev, void *drv_data, u32 val); int (*get_channel)(struct device *dev, void *drv_data, u32 *val); int (*set_channel)(struct device *dev, void *drv_data, u32 val); int (*get_sub_channel)(struct device *dev, void *drv_data, u32 *val); int (*set_sub_channel)(struct device *dev, void *drv_data, u32 val); int (*do_repair)(struct device *dev, void *drv_data, u32 val);};Members
get_repair_typeget the memory repair type, listed in
enumedac_mem_repair_function.get_persist_modeget the current persist mode.false - Soft repair type (temporary repair).true - Hard memory repair type (permanent repair).
set_persist_modeset the persist mode of the memory repair instance.
get_repair_safe_when_in_useget whether memory media is accessible anddata is retained during repair operation.
get_hpaget current host physical address (HPA) of memory to repair.
set_hpaset host physical address (HPA) of memory to repair.
get_min_hpaget the minimum supported host physical address (HPA).
get_max_hpaget the maximum supported host physical address (HPA).
get_dpaget current device physical address (DPA) of memory to repair.
set_dpaset device physical address (DPA) of memory to repair.In some states of system configuration (e.g. before address decodershave been configured), memory devices (e.g. CXL) may not have an activemapping in the host physical address map. As such, the memoryto repair must be identified by a device specific physical addressingscheme using a device physical address(DPA). The DPA and other controlattributes to use for the repair operations will be presented in relatederror records.
get_min_dpaget the minimum supported device physical address (DPA).
get_max_dpaget the maximum supported device physical address (DPA).
get_nibble_maskget current nibble mask of memory to repair.
set_nibble_maskset nibble mask of memory to repair.
get_bank_groupget current bank group of memory to repair.
set_bank_groupset bank group of memory to repair.
get_bankget current bank of memory to repair.
set_bankset bank of memory to repair.
get_rankget current rank of memory to repair.
set_rankset rank of memory to repair.
get_rowget current row of memory to repair.
set_rowset row of memory to repair.
get_columnget current column of memory to repair.
set_columnset column of memory to repair.
get_channelget current channel of memory to repair.
set_channelset channel of memory to repair.
get_sub_channelget current subchannel of memory to repair.
set_sub_channelset subchannel of memory to repair.
do_repairIssue memory repair operation for the HPA/DPA andother control attributes set for the memory to repair.
Description
All elements are optional except do_repair and at least one of set_hpa/set_dpa.
- structmem_ctl_info*edac_mc_alloc(unsignedintmc_num,unsignedintn_layers,structedac_mc_layer*layers,unsignedintsz_pvt)¶
Allocate and partially fill a struct
mem_ctl_info.
Parameters
unsignedintmc_numMemory controller number
unsignedintn_layersNumber of MC hierarchy layers
structedac_mc_layer*layersDescribes each layer as seen by the Memory Controller
unsignedintsz_pvtsize of private storage needed
Description
Everything is kmalloc’ed as one big chunk - more efficient.Only can be used if all structures have the same lifetime - otherwiseyou have to allocate and initialize your own structures.
Useedac_mc_free() to free mc structures allocated by this function.
Note
drivers handle multi-rank memories in different ways: in somedrivers, one multi-rank memory stick is mapped as one entry, while, inothers, a single multi-rank memory stick would be mapped into severalentries. Currently, this function will allocate multiplestructdimm_infoon such scenarios, as grouping the multiple ranks require drivers change.
Return
On success, return a pointer tostructmem_ctl_info pointer;NULL otherwise
- constchar*edac_get_owner(void)¶
Return the owner’s mod_name of EDAC MC
Parameters
voidno arguments
Return
Pointer to mod_name string when EDAC MC is owned. NULL otherwise.
- voidedac_mc_free(structmem_ctl_info*mci)¶
Frees a previously allocatedmci structure
Parameters
structmem_ctl_info*mcipointer to a
structmem_ctl_infostructure
- booledac_has_mcs(void)¶
Check if any MCs have been allocated.
Parameters
voidno arguments
Return
True if MC instances have been registered successfully.False otherwise.
- structmem_ctl_info*edac_mc_find(intidx)¶
Search for a mem_ctl_info structure whose index isidx.
Parameters
intidxindex to be seek
Description
If found, return a pointer to the structure.Else return NULL.
- structmem_ctl_info*find_mci_by_dev(structdevice*dev)¶
Scan list of controllers looking for the one that manages thedev device.
Parameters
structdevice*devpointer to a
structdevicerelated with the MCI
Return
on success, returns a pointer to structmem_ctl_info;NULL otherwise.
- structmem_ctl_info*edac_mc_del_mc(structdevice*dev)¶
Remove sysfs entries for mci structure associated withdev and remove mci structure from global list.
Parameters
structdevice*devPointer to struct
devicerepresenting mci structure to remove.
Return
pointer to removed mci structure, orNULL if device not found.
- intedac_mc_find_csrow_by_page(structmem_ctl_info*mci,unsignedlongpage)¶
Ancillary routine to identify what csrow contains a memory page.
Parameters
structmem_ctl_info*mcipointer to a
structmem_ctl_infostructureunsignedlongpagememory page to find
Return
on success, returns the csrow. -1 if not found.
- voidedac_raw_mc_handle_error(structedac_raw_error_desc*e)¶
Reports a memory event to userspace without doing anything to discover the error location.
Parameters
structedac_raw_error_desc*eerror description
Description
This raw function is used internally byedac_mc_handle_error(). It shouldonly be called directly when the hardware error come directly from BIOS,like in the case of APEI GHES driver.
- voidedac_mc_handle_error(constenumhw_event_mc_err_typetype,structmem_ctl_info*mci,constu16error_count,constunsignedlongpage_frame_number,constunsignedlongoffset_in_page,constunsignedlongsyndrome,constinttop_layer,constintmid_layer,constintlow_layer,constchar*msg,constchar*other_detail)¶
Reports a memory event to userspace.
Parameters
constenumhw_event_mc_err_typetypeseverity of the error (CE/UE/Fatal)
structmem_ctl_info*mcia
structmem_ctl_infopointerconstu16error_countNumber of errors of the same type
constunsignedlongpage_frame_numbermem page where the error occurred
constunsignedlongoffset_in_pageoffset of the error inside the page
constunsignedlongsyndromeECC syndrome
constinttop_layerMemory layer[0] position
constintmid_layerMemory layer[1] position
constintlow_layerMemory layer[2] position
constchar*msgMessage meaningful to the end users thatexplains the event
constchar*other_detailTechnical details about the event thatmay help hardware manufacturers andEDAC developers to analyse the event
PCI Controllers¶
The EDAC subsystem provides a mechanism to handle PCI controllers by callingtheedac_pci_alloc_ctl_info(). It will use the structedac_pci_ctl_info to describe the PCI controllers.
- structedac_pci_ctl_info*edac_pci_alloc_ctl_info(unsignedintsz_pvt,constchar*edac_pci_name)¶
The
alloc()function for the ‘edac_pci’ control info structure.
Parameters
unsignedintsz_pvtsize of the private info at struct
edac_pci_ctl_infoconstchar*edac_pci_namename of the PCI device
Description
The chip driver will allocate one of these for eachedac_pci it is going to control/register with the EDAC CORE.
Return
a pointer to structedac_pci_ctl_info on success;NULL otherwise.
- voidedac_pci_free_ctl_info(structedac_pci_ctl_info*pci)¶
Last action on the pci control structure.
Parameters
structedac_pci_ctl_info*pcipointer to struct
edac_pci_ctl_info
Description
Calls the remove sysfs information, which will unregisterthis control struct’s kobj. When that kobj’s ref countgoes to zero, its release function will be call and thenkfree() the memory.
- intedac_pci_alloc_index(void)¶
Allocate a unique PCI index number
Parameters
voidno arguments
Return
allocated index number
- intedac_pci_add_device(structedac_pci_ctl_info*pci,intedac_idx)¶
Insert the ‘edac_dev’ structure into the edac_pci global list and create sysfs entries associated with edac_pci structure.
Parameters
structedac_pci_ctl_info*pcipointer to the edac_device structure to be added to the list
intedac_idxA unique numeric identifier to be assigned to the‘edac_pci’ structure.
Return
0 on Success, or an error code on failure
Parameters
structdevice*devPointer to ‘
structdevice’ representing edac_pci structureto remove
Description
Remove sysfs entries for specified edac_pci structure andthen remove edac_pci structure from global list
Return
Pointer to removed edac_pci structure,orNULL if device not found
Parameters
structdevice*devpointer to struct
device;constchar*mod_namename of the PCI device
Description
A generic constructor for a PCI parity polling deviceSome systems have more than one domain of PCI busses.For systems with one domain, then this API willprovide for a generic poller.
This routine calls theedac_pci_alloc_ctl_info() forthe generic device, with default values
Return
Pointer to structedac_pci_ctl_info on success,NULL onfailure.
- voidedac_pci_release_generic_ctl(structedac_pci_ctl_info*pci)¶
Parameters
structedac_pci_ctl_info*pcipointer to struct
edac_pci_ctl_info
Description
The release function of a generic EDAC PCI polling device
- intedac_pci_create_sysfs(structedac_pci_ctl_info*pci)¶
Parameters
structedac_pci_ctl_info*pcipointer to struct
edac_pci_ctl_info
Description
Create the controls/attributes for the specified EDAC PCI device
- voidedac_pci_remove_sysfs(structedac_pci_ctl_info*pci)¶
Parameters
structedac_pci_ctl_info*pcipointer to struct
edac_pci_ctl_info
Description
remove the controls and attributes for this EDAC PCI device
EDAC Blocks¶
The EDAC subsystem also provides a generic mechanism to report errors onother parts of the hardware viaedac_device_alloc_ctl_info() function.
The structuresedac_dev_sysfs_block_attribute,edac_device_block,edac_device_instance andedac_device_ctl_info provide a generic or abstract ‘edac_device’representation at sysfs.
This set of structures and the code that implements the APIs for the same, provide for registering EDAC type devices which are NOT standard memory orPCI, like:
CPU caches (L1 and L2)
DMA engines
Core CPU switches
Fabric switch units
PCIe interface controllers
other EDAC/ECC type devices that can be monitored forerrors, etc.
It allows for a 2 level set of hierarchy.
For example, a cache could be composed of L1, L2 and L3 levels of cache.Each CPU core would have its own L1 cache, while sharing L2 and maybe L3caches. On such case, those can be represented via the following sysfsnodes:
/sys/devices/system/edac/..pci/ <existing pci directory (if available)>mc/ <existing memory device directory>cpu/cpu0/.. <L1 and L2 block directory> /L1-cache/ce_count /ue_count /L2-cache/ce_count /ue_countcpu/cpu1/.. <L1 and L2 block directory> /L1-cache/ce_count /ue_count /L2-cache/ce_count /ue_count...the L1 and L2 directories would be "edac_device_block's"
- intedac_device_add_device(structedac_device_ctl_info*edac_dev)¶
Insert the ‘edac_dev’ structure into the edac_device global list and create sysfs entries associated with edac_device structure.
Parameters
structedac_device_ctl_info*edac_devpointer to edac_device structure to be added to the list‘edac_device’ structure.
Return
0 on Success, or an error code on failure
- structedac_device_ctl_info*edac_device_del_device(structdevice*dev)¶
Remove sysfs entries for specified edac_device structure and then remove edac_device structure from global list
Parameters
structdevice*devPointer to struct
devicerepresenting the edac devicestructure to remove.
Return
Pointer to removed edac_device structure,orNULL if device not found.
- voidedac_device_handle_ce_count(structedac_device_ctl_info*edac_dev,unsignedintcount,intinst_nr,intblock_nr,constchar*msg)¶
Log correctable errors.
Parameters
structedac_device_ctl_info*edac_devpointer to struct
edac_device_ctl_infounsignedintcountNumber of errors to log.
intinst_nrnumber of the instance where the CE error happened
intblock_nrnumber of the block where the CE error happened
constchar*msgmessage to be printed
- voidedac_device_handle_ue_count(structedac_device_ctl_info*edac_dev,unsignedintcount,intinst_nr,intblock_nr,constchar*msg)¶
Log uncorrectable errors.
Parameters
structedac_device_ctl_info*edac_devpointer to struct
edac_device_ctl_infounsignedintcountNumber of errors to log.
intinst_nrnumber of the instance where the CE error happened
intblock_nrnumber of the block where the CE error happened
constchar*msgmessage to be printed
- voidedac_device_handle_ce(structedac_device_ctl_info*edac_dev,intinst_nr,intblock_nr,constchar*msg)¶
Log a single correctable error
Parameters
structedac_device_ctl_info*edac_devpointer to struct
edac_device_ctl_infointinst_nrnumber of the instance where the CE error happened
intblock_nrnumber of the block where the CE error happened
constchar*msgmessage to be printed
- voidedac_device_handle_ue(structedac_device_ctl_info*edac_dev,intinst_nr,intblock_nr,constchar*msg)¶
Log a single uncorrectable error
Parameters
structedac_device_ctl_info*edac_devpointer to struct
edac_device_ctl_infointinst_nrnumber of the instance where the UE error happened
intblock_nrnumber of the block where the UE error happened
constchar*msgmessage to be printed
- intedac_device_alloc_index(void)¶
Allocate a unique device index number
Parameters
voidno arguments
Return
allocated index number
Heterogeneous system support¶
An AMD heterogeneous system is built by connecting the data fabrics ofboth CPUs and GPUs via custom xGMI links. Thus, the data fabric on theGPU nodes can be accessed the same way as the data fabric on CPU nodes.
The MI200 accelerators are data center GPUs. They have 2 data fabrics,and each GPU data fabric contains four Unified Memory Controllers (UMC).Each UMC contains eight channels. Each UMC channel controls one 128-bitHBM2e (2GB) channel (equivalent to 8 X 2GB ranks). This creates a totalof 4096-bits of DRAM data bus.
While the UMC is interfacing a 16GB (8high X 2GB DRAM) HBM stack, each UMCchannel is interfacing 2GB of DRAM (represented as rank).
Memory controllers on AMD GPU nodes can be represented in EDAC thusly:
GPU DF / GPU Node -> EDAC MCGPU UMC -> EDAC CSROWGPU UMC channel -> EDAC CHANNEL
For example: a heterogeneous system with 1 AMD CPU is connected to4 MI200 (Aldebaran) GPUs using xGMI.
Some more heterogeneous hardware details:
The CPU UMC (Unified Memory Controller) is mostly the same as the GPU UMC.They have chip selects (csrows) and channels. However, the layouts are differentfor performance, physical layout, or other reasons.
CPU UMCs use 1 channel, In this case UMC = EDAC channel. This follows themarketing speak. CPU has X memory channels, etc.
CPU UMCs use up to 4 chip selects, So UMC chip select = EDAC CSROW.
GPU UMCs use 1 chip select, So UMC = EDAC CSROW.
GPU UMCs use 8 channels, So UMC channel = EDAC channel.
The EDAC subsystem provides a mechanism to handle AMD heterogeneoussystems by calling system specific ops for both CPUs and GPUs.
AMD GPU nodes are enumerated in sequential order based on the PCIhierarchy, and the first GPU node is assumed to have a Node ID valuefollowing those of the CPU nodes after latter are fully populated:
$ ls /sys/devices/system/edac/mc/ mc0 - CPU MC node 0 mc1 | mc2 |- GPU card[0] => node 0(mc1), node 1(mc2) mc3 | mc4 |- GPU card[1] => node 0(mc3), node 1(mc4) mc5 | mc6 |- GPU card[2] => node 0(mc5), node 1(mc6) mc7 | mc8 |- GPU card[3] => node 0(mc7), node 1(mc8)
For example, a heterogeneous system with one AMD CPU is connected tofour MI200 (Aldebaran) GPUs using xGMI. This topology can be representedvia the following sysfs entries:
/sys/devices/system/edac/mc/..CPU # CPU node├── mc 0GPU Nodes are enumerated sequentially after CPU nodes have been populatedGPU card 1 # Each MI200 GPU has 2 nodes/mcs├── mc 1 # GPU node 0 == mc1, Each MC node has 4 UMCs/CSROWs│ ├── csrow 0 # UMC 0│ │ ├── channel 0 # Each UMC has 8 channels│ │ ├── channel 1 # size of each channel is 2 GB, so each UMC has 16 GB│ │ ├── channel 2│ │ ├── channel 3│ │ ├── channel 4│ │ ├── channel 5│ │ ├── channel 6│ │ ├── channel 7│ ├── csrow 1 # UMC 1│ │ ├── channel 0│ │ ├── ..│ │ ├── channel 7│ ├── .. ..│ ├── csrow 3 # UMC 3│ │ ├── channel 0│ │ ├── ..│ │ ├── channel 7│ ├── rank 0│ ├── .. ..│ ├── rank 31 # total 32 ranks/dimms from 4 UMCs├├── mc 2 # GPU node 1 == mc2│ ├── .. # each GPU has total 64 GBGPU card 2├── mc 3│ ├── ..├── mc 4│ ├── ..GPU card 3├── mc 5│ ├── ..├── mc 6│ ├── ..GPU card 4├── mc 7│ ├── ..├── mc 8│ ├── ..