/* * AMD64 class Memory Controller kernel module * * Copyright (c) 2009 SoftwareBitMaker. * Copyright (c) 2009-15 Advanced Micro Devices, Inc. * * This file may be distributed under the terms of the * GNU General Public License.
*/
/* * Throughout the comments in this code, the following terms are used: * * SysAddr, DramAddr, and InputAddr * * These terms come directly from the amd64 documentation * (AMD publication #26094). They are defined as follows: * * SysAddr: * This is a physical address generated by a CPU core or a device * doing DMA. If generated by a CPU core, a SysAddr is the result of * a virtual to physical address translation by the CPU core's address * translation mechanism (MMU). * * DramAddr: * A DramAddr is derived from a SysAddr by subtracting an offset that * depends on which node the SysAddr maps to and whether the SysAddr * is within a range affected by memory hoisting. The DRAM Base * (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers * determine which node a SysAddr maps to. * * If the DRAM Hole Address Register (DHAR) is enabled and the SysAddr * is within the range of addresses specified by this register, then * a value x from the DHAR is subtracted from the SysAddr to produce a * DramAddr. Here, x represents the base address for the node that * the SysAddr maps to plus an offset due to memory hoisting. See * section 3.4.8 and the comments in amd64_get_dram_hole_info() and * sys_addr_to_dram_addr() below for more information. * * If the SysAddr is not affected by the DHAR then a value y is * subtracted from the SysAddr to produce a DramAddr. Here, y is the * base address for the node that the SysAddr maps to. See section * 3.4.4 and the comments in sys_addr_to_dram_addr() below for more * information. * * InputAddr: * A DramAddr is translated to an InputAddr before being passed to the * memory controller for the node that the DramAddr is associated * with. The memory controller then maps the InputAddr to a csrow. * If node interleaving is not in use, then the InputAddr has the same * value as the DramAddr. Otherwise, the InputAddr is produced by * discarding the bits used for node interleaving from the DramAddr. * See section 3.4.4 for more information. * * The memory controller for a given node uses its DRAM CS Base and * DRAM CS Mask registers to map an InputAddr to a csrow. See * sections 3.5.4 and 3.5.5 for more information.
*/
#define EDAC_MOD_STR "amd64_edac"
/* Extended Model from CPUID, for CPU Revision numbers */ #define K8_REV_D 1 #define K8_REV_E 2 #define K8_REV_F 4
/* Hardware limit on ChipSelect rows per MC and processors per system */ #define NUM_CHIPSELECTS 8 #define DRAM_RANGES 8 #define NUM_CONTROLLERS 12
struct amd64_umc {
u32 dimm_cfg; /* DIMM Configuration reg */
u32 umc_cfg; /* Configuration reg */
u32 sdp_ctrl; /* SDP Control reg */
u32 ecc_ctrl; /* DRAM ECC Control reg */
u32 umc_cap_hi; /* Capabilities High reg */
/* cache the dram_type */ enum mem_type dram_type;
};
struct amd64_family_flags { /* * Indicates that the system supports the new register offsets, etc. * first introduced with Family 19h Model 10h.
*/
__u64 zn_regs_v2 : 1,
__reserved : 63;
};
struct amd64_pvt { struct low_ops *ops;
/* pci_device handles which we utilize */ struct pci_dev *F1, *F2, *F3;
u16 mc_node_id; /* MC index of this MC node */
u8 fam; /* CPU family */
u8 model; /* ... model */
u8 stepping; /* ... stepping */
int ext_model; /* extended model value of this node */
/* Raw registers */
u32 dclr0; /* DRAM Configuration Low DCT0 reg */
u32 dclr1; /* DRAM Configuration Low DCT1 reg */
u32 dchr0; /* DRAM Configuration High DCT0 reg */
u32 dchr1; /* DRAM Configuration High DCT1 reg */
u32 nbcap; /* North Bridge Capabilities */
u32 nbcfg; /* F10 North Bridge Configuration */
u32 dhar; /* DRAM Hoist reg */
u32 dbam0; /* DRAM Base Address Mapping reg for DCT0 */
u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */
/* one for each DCT/UMC */ struct chip_select csels[NUM_CONTROLLERS];
/* DRAM base and limit pairs F1x[78,70,68,60,58,50,48,40] */ struct dram_range ranges[DRAM_RANGES];
u64 top_mem; /* top of memory below 4GB */
u64 top_mem2; /* top of memory above 4GB */
u32 dct_sel_lo; /* DRAM Controller Select Low */
u32 dct_sel_hi; /* DRAM Controller Select High */
u32 online_spare; /* On-Line spare Reg */
u32 gpu_umc_base; /* Base address used for channel selection on GPUs */
/* x4, x8, or x16 syndromes in use */
u8 ecc_sym_sz;
constchar *ctl_name;
u16 f1_id, f2_id; /* Maximum number of memory controllers per die/node. */
u8 max_mcs;
struct amd64_family_flags flags; /* place to store error injection parameters prior to issue */ struct error_injection injection;
/* * cache the dram_type * * NOTE: Don't use this for Family 17h and later. * Use dram_type in struct amd64_umc instead.
*/ enum mem_type dram_type;
/* * Each of the PCI Device IDs types have their own set of hardware accessor * functions and per device encoding/decoding logic.
*/ struct low_ops { void (*map_sysaddr_to_csrow)(struct mem_ctl_info *mci, u64 sys_addr, struct err_info *err); int (*dbam_to_cs)(struct amd64_pvt *pvt, u8 dct, unsignedint cs_mode, int cs_mask_nr); int (*hw_info_get)(struct amd64_pvt *pvt); bool (*ecc_enabled)(struct amd64_pvt *pvt); void (*setup_mci_misc_attrs)(struct mem_ctl_info *mci); void (*dump_misc_regs)(struct amd64_pvt *pvt); void (*get_err_info)(struct mce *m, struct err_info *err);
};
int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
u32 *val, constchar *func); int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
u32 val, constchar *func);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.