Mercurial > illumos > illumos-gate
changeset 10650:5195e7d7a5f4
6734814 Intel address translation Phase II
author | Vuong Nguyen <Vuong.Nguyen@Sun.COM> |
---|---|
date | Fri, 25 Sep 2009 14:44:38 -0700 |
parents | ab3ce9d83b84 |
children | 6e737c28ebe6 |
files | usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c usr/src/uts/intel/Makefile.files usr/src/uts/intel/intel_nb5000/Makefile usr/src/uts/intel/intel_nhm/Makefile usr/src/uts/intel/io/intel_nb5000/dimm_addr.c usr/src/uts/intel/io/intel_nb5000/dimm_addr.h usr/src/uts/intel/io/intel_nb5000/dimm_phys.h usr/src/uts/intel/io/intel_nb5000/intel_nb5000.c usr/src/uts/intel/io/intel_nb5000/nb5000.h usr/src/uts/intel/io/intel_nb5000/nb5000_init.c usr/src/uts/intel/io/intel_nb5000/rank.h usr/src/uts/intel/io/intel_nhm/intel_nhm.h usr/src/uts/intel/io/intel_nhm/mem_addr.c usr/src/uts/intel/io/intel_nhm/mem_addr.h usr/src/uts/intel/sys/mc_intel.h |
diffstat | 16 files changed, 509 insertions(+), 381 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/cmd/fm/eversholt/files/i386/i86pc/intel.esc Fri Sep 25 14:44:38 2009 -0700 @@ -537,17 +537,20 @@ event ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller {within(1s)}; event fault.cpu.intel.quickpath.mem_addr_parity@ - motherboard/chip/memory-controller/dram-channel/dimm; -event fault.cpu.intel.quickpath.mem_addr_parity@ motherboard/chip/memory-controller; +event fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM; +event fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM/rank; prop fault.cpu.intel.quickpath.mem_addr_parity@ motherboard/chip/memory-controller (1)-> ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller; -prop fault.cpu.intel.quickpath.mem_addr_parity@ - motherboard/chip/memory-controller/dram-channel/dimm - { payloadprop_contains("resource", asru(motherboard/chip/memory-controller/dram-channel/dimm)) } (1)-> +prop fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM + { payloadprop_contains("resource", asru(CHIPDIMM)) } (1)-> + ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller; + +prop fault.cpu.intel.quickpath.mem_addr_parity@CHIPDIMM/rank + { payloadprop_contains("resource", asru(CHIPDIMM/rank)) } (1)-> ereport.cpu.intel.quickpath.mem_addr_parity@motherboard/chip/memory-controller; event ereport.cpu.intel.quickpath.mem_bad_addr@motherboard/chip/memory-controller {within(1s)}; @@ -571,18 +574,17 @@ ereport.cpu.intel.quickpath.mem_bad_id@motherboard/chip/memory-controller; event ereport.cpu.intel.quickpath.mem_redundant@motherboard/chip/memory-controller {within(1s)}; -engine serd.cpu.intel.quickpath.mem_redundant@ - motherboard/chip/memory-controller/dram-channel/dimm, - N=2, T=72h; -event fault.cpu.intel.quickpath.mem_redundant@ - motherboard/chip/memory-controller/dram-channel/dimm, - engine=serd.cpu.intel.quickpath.mem_redundant@ - motherboard/chip/memory-controller/dram-channel/dimm; +engine serd.cpu.intel.quickpath.mem_redundant@CHIPDIMM, N=2, T=72h; +event fault.cpu.intel.quickpath.mem_redundant@CHIPDIMM, + engine=serd.cpu.intel.quickpath.mem_redundant@CHIPDIMM; + +event error.cpu.intel.quickpath.mem_redundant@CHIPDIMM/rank; -prop fault.cpu.intel.quickpath.mem_redundant@ - motherboard/chip/memory-controller/dram-channel/dimm - { payloadprop_contains("resource", - asru(motherboard/chip/memory-controller/dram-channel/dimm)) } (1)-> +prop fault.cpu.intel.quickpath.mem_redundant@CHIPDIMM (1)-> + error.cpu.intel.quickpath.mem_redundant@CHIPDIMM/rank + { is_under(CHIPDIMM, CHIPDIMM/rank) }; +prop error.cpu.intel.quickpath.mem_redundant@CHIPDIMM/rank + { CONTAINS_RANK } (1)-> ereport.cpu.intel.quickpath.mem_redundant@ motherboard/chip/memory-controller;
--- a/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c Fri Sep 25 14:44:38 2009 -0700 @@ -382,6 +382,21 @@ fm_payload_set(ereport, FM_FMRI_MEM_PHYSADDR, DATA_TYPE_UINT64, addr, NULL); (void) cmi_mc_patounum(addr, 0, 0, synd, 0, &unum); + if (unum.unum_offset != -1ULL && + (unum.unum_offset & OFFSET_ROW_BANK_COL) != 0) { + fm_payload_set(ereport, + FM_EREPORT_PAYLOAD_NAME_BANK, + DATA_TYPE_INT32, + TCODE_OFFSET_BANK(unum.unum_offset), NULL); + fm_payload_set(ereport, + FM_EREPORT_PAYLOAD_NAME_CAS, + DATA_TYPE_INT32, + TCODE_OFFSET_CAS(unum.unum_offset), NULL); + fm_payload_set(ereport, + FM_EREPORT_PAYLOAD_NAME_RAS, + DATA_TYPE_INT32, + TCODE_OFFSET_RAS(unum.unum_offset), NULL); + } } resource = gintel_ereport_create_resource_elem(nva, &unum); fm_payload_set(ereport, FM_EREPORT_PAYLOAD_NAME_RESOURCE,
--- a/usr/src/uts/intel/Makefile.files Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/Makefile.files Fri Sep 25 14:44:38 2009 -0700 @@ -303,14 +303,3 @@ mcamd_dimmcfg.o \ mcamd_subr.o \ mcamd_pcicfg.o - -# -# Intel 5000/5400/7300 MCH module -# -INTEL_NB5000_OBJS += \ - intel_nb5000.o \ - intel_nbdrv.o \ - dimm_addr.o \ - nb_pci_cfg.o \ - nb5000_init.o -
--- a/usr/src/uts/intel/intel_nb5000/Makefile Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/intel_nb5000/Makefile Fri Sep 25 14:44:38 2009 -0700 @@ -17,22 +17,25 @@ # # CDDL HEADER END # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # +# Intel 5000/5100/5400/7300 chipset memory controller hub (MCH) module +# + +# # Path to the base of the uts directory tree (usually /usr/src/uts). # UTSBASE = ../.. +UTSCLOSED = ../../../../closed/uts # # Define the module and object file sets. # MODULE = intel_nb5000 # -OBJECTS = $(INTEL_NB5000_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(INTEL_NB5000_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) SRCDIR = $(UTSBASE)/intel/io/intel_nb5000 CONF_SRCDIR = $(UTSBASE)/intel/io/intel_nb5000 @@ -43,6 +46,23 @@ include ../Makefile.intel # +# The list of object files is defined here, rather than in Makefile.files, +# because the "$(CLOSED_BUILD)" macro has not been defined at the time +# Makefile.files is processed. +# +INTEL_NB5000_OBJS += \ + intel_nb5000.o \ + intel_nbdrv.o \ + dimm_addr.o \ + nb_pci_cfg.o \ + nb5000_init.o + +$(CLOSED_BUILD)INTEL_NB5000_OBJS += memtrans.o + +OBJECTS = $(INTEL_NB5000_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(INTEL_NB5000_OBJS:%.o=$(LINTS_DIR)/%.ln) + +# # Define targets # ALL_TARGET = $(BINARY) @@ -76,3 +96,4 @@ # Include common targets. # include ../Makefile.targ +$(CLOSED_BUILD)include $(UTSCLOSED)/intel/Makefile.rules
--- a/usr/src/uts/intel/intel_nhm/Makefile Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/intel_nhm/Makefile Fri Sep 25 14:44:38 2009 -0700 @@ -22,19 +22,20 @@ # # +# Intel Nehalem memory controller module +# + +# # Path to the base of the uts directory tree (usually /usr/src/uts). # UTSBASE = ../.. +UTSCLOSED = ../../../../closed/uts # # Define the module and object file sets. # MODULE = intel_nhm # -INTEL_NHM_OBJS = nhm_init.o mem_addr.o intel_nhmdrv.o nhm_pci_cfg.o \ - dimm_topo.o intel_nhm.o -OBJECTS = $(INTEL_NHM_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(INTEL_NHM_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) CONF_SRCDIR = $(UTSBASE)/intel/io/intel_nhm @@ -44,6 +45,25 @@ include $(UTSBASE)/intel/Makefile.intel # +# The list of object files is defined here, rather than in Makefile.files, +# because the "$(CLOSED_BUILD)" macro has not been defined at the time +# Makefile.files is processed. +# +INTEL_NHM_OBJS += \ + nhm_init.o \ + mem_addr.o \ + intel_nhmdrv.o \ + nhm_pci_cfg.o \ + dimm_topo.o \ + intel_nhm.o + +$(CLOSED_BUILD)INTEL_NHM_OBJS += \ + nhm_dimm_addr.o + +OBJECTS = $(INTEL_NHM_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(INTEL_NHM_OBJS:%.o=$(LINTS_DIR)/%.ln) + +# # Define targets # ALL_TARGET = $(BINARY) $(SRC_CONFFILE) @@ -78,3 +98,4 @@ # Include common targets. # include ../Makefile.targ +$(CLOSED_BUILD)include $(UTSCLOSED)/intel/Makefile.rules
--- a/usr/src/uts/intel/io/intel_nb5000/dimm_addr.c Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/io/intel_nb5000/dimm_addr.c Fri Sep 25 14:44:38 2009 -0700 @@ -32,129 +32,13 @@ #include <sys/cmn_err.h> #include <sys/sunddi.h> #include <sys/mc_intel.h> -#include "dimm_addr.h" #include "nb_log.h" #include "rank.h" #include "dimm_phys.h" #include "nb5000.h" -struct dimm_geometry **dimm_geometry; struct rank_base *rank_base; -uint64_t -dimm_getphys(int branch, int rank, int bank, int ras, int cas) -{ - uint8_t i; - int num_ranks_per_branch; - uint64_t m; - uint64_t pa; - struct rank_base *rp; - struct rank_geometry *rgp; - - /* max number of ranks per branch */ - num_ranks_per_branch = (nb_chipset == INTEL_NB_5100) ? - NB_5100_RANKS_PER_CHANNEL : - nb_dimms_per_channel * nb_channels_per_branch; - ASSERT(rank < num_ranks_per_branch); - rp = &rank_base[(branch * num_ranks_per_branch) + rank]; - rgp = (struct rank_geometry *)rp->rank_geometry; - if (rgp == NULL) - return (-1LL); - pa = rp->base; - - for (i = 0, m = 1; bank; i++, m <<= 1) { - if ((bank & m) != 0 && rgp->bank[i] != 0xff) { - pa += 1 << rgp->bank[i]; - bank &= ~m; - } - } - for (i = 0, m = 1; cas; i++, m <<= 1) { - if ((cas & m) != 0 && rgp->col[i] != 0xff) { - pa += 1 << rgp->col[i]; - cas &= ~m; - } - } - for (i = 0, m = 1; ras; i++, m <<= 1) { - if ((ras & m) != 0 && rgp->row[i] != 0xff) { - pa += 1 << rgp->row[i]; - ras &= ~m; - } - } - if (rp->interleave > 1) { - i = 0; - if (rp->branch_interleave) { - if (branch) { - pa += 1 << rgp->interleave[i]; - } - i++; - } - if ((rp->way & 1) != 0) - pa += 1 << rgp->interleave[i]; - i++; - if ((rp->way & 2) != 0) - pa += 1 << rgp->interleave[i]; - } - if (rp->hole && pa >= rp->hole) - pa += rp->hole_size; - return (pa); -} - -uint64_t -dimm_getoffset(int branch, int rank, int bank, int ras, int cas) -{ - uint8_t i; - int num_ranks_per_branch; - uint64_t m; - uint64_t offset; - struct dimm_geometry *dgp; - struct rank_geometry *rgp; - struct rank_base *rp; - uint64_t pa; - uint64_t cal_pa; - - /* max number of ranks per branch */ - num_ranks_per_branch = (nb_chipset == INTEL_NB_5100) ? - NB_5100_RANKS_PER_CHANNEL : - nb_dimms_per_channel * nb_channels_per_branch; - ASSERT(rank < num_ranks_per_branch); - rp = &rank_base[(branch * num_ranks_per_branch) + rank]; - dgp = dimm_geometry[(branch * nb_dimms_per_channel) + - nb_rank2dimm(branch, rank)]; - if (dgp == NULL) - return (TCODE_OFFSET(rank, bank, ras, cas)); - rgp = (struct rank_geometry *)&dgp->rank_geometry[0]; - offset = 0; - pa = dimm_getphys(branch, rank, bank, ras, cas) & PAGEMASK; - - for (i = 0, m = 1; bank; i++, m <<= 1) { - if ((bank & m) != 0 && rgp->bank[i] != 0xff) { - offset += 1 << rgp->bank[i]; - bank &= ~m; - } - } - for (i = 0, m = 1; cas; i++, m <<= 1) { - if ((cas & m) != 0 && rgp->col[i] != 0xff) { - offset += 1 << rgp->col[i]; - cas &= ~m; - } - } - for (i = 0, m = 1; ras; i++, m <<= 1) { - if ((ras & m) != 0 && rgp->row[i] != 0xff) { - offset += 1 << rgp->row[i]; - ras &= ~m; - } - } - cal_pa = rp->base + (offset * rp->interleave); - if (rp->hole && cal_pa >= rp->hole) - cal_pa += rp->hole_size; - cal_pa &= PAGEMASK; - - if (pa != cal_pa) { - return (-1LL); - } - return (offset & PAGEMASK); -} - static int fmri2unum(nvlist_t *nvl, mc_unum_t *unump) { @@ -196,8 +80,6 @@ unump->unum_rank = (int)v; } - unump->unum_offset = offset; - return (1); } @@ -245,14 +127,18 @@ return (CMI_SUCCESS); unump = &unum; } - if (unump->unum_offset & OFFSET_ROW_BANK_COL) { - pa = dimm_getphys(unump->unum_mc, - TCODE_OFFSET_RANK(unump->unum_offset), - TCODE_OFFSET_BANK(unump->unum_offset), - TCODE_OFFSET_RAS(unump->unum_offset), - TCODE_OFFSET_CAS(unump->unum_offset)); - if (pa == -1LL) + if ((unump->unum_offset & OFFSET_ROW_BANK_COL)) { + if (&dimm_getphys) { + pa = dimm_getphys(unump->unum_mc, + TCODE_OFFSET_RANK(unump->unum_offset), + TCODE_OFFSET_BANK(unump->unum_offset), + TCODE_OFFSET_RAS(unump->unum_offset), + TCODE_OFFSET_CAS(unump->unum_offset)); + if (pa >= MAXPHYS_ADDR) + return (CMIERR_MC_NOADDR); + } else { return (CMIERR_MC_NOADDR); + } *pap = pa; return (CMI_SUCCESS); } @@ -277,8 +163,6 @@ { int num_ranks_per_branch; - dimm_geometry = kmem_zalloc(sizeof (void *) * - nb_number_memory_controllers * nb_dimms_per_channel, KM_SLEEP); /* max number of ranks per branch */ num_ranks_per_branch = (nb_chipset == INTEL_NB_5100) ? @@ -294,9 +178,6 @@ { int num_ranks_per_branch; - kmem_free(dimm_geometry, sizeof (void *) * - nb_number_memory_controllers * nb_dimms_per_channel); - dimm_geometry = 0; /* max number of ranks per branch */ num_ranks_per_branch = (nb_chipset == INTEL_NB_5100) ? @@ -309,48 +190,18 @@ } void -dimm_add_geometry(int branch, int dimm, int nbanks, int width, int ncolumn, - int nrow) -{ - int i; - for (i = 0; i < dimm_types; i++) { - if (dimm_data[i].row_nbits == nrow && - dimm_data[i].col_nbits == ncolumn && - dimm_data[i].width == width && - (1 << dimm_data[i].bank_nbits) == nbanks) { - dimm_geometry[(branch * nb_dimms_per_channel) + dimm] = - &dimm_data[i]; - break; - } - } -} - -void dimm_add_rank(int branch, int rank, int branch_interleave, int way, uint64_t base, uint32_t hole, uint32_t hole_size, int interleave, uint64_t limit) { - struct dimm_geometry *dimm; struct rank_base *rp; - int interleave_nbits; int num_ranks_per_branch; - dimm = dimm_geometry[(branch * nb_dimms_per_channel) + - nb_rank2dimm(branch, rank)]; - /* max number of ranks per branch */ num_ranks_per_branch = (nb_chipset == INTEL_NB_5100) ? NB_5100_RANKS_PER_CHANNEL : nb_dimms_per_channel * nb_channels_per_branch; rp = &rank_base[(branch * num_ranks_per_branch) + rank]; - if (interleave == 1) - interleave_nbits = 0; - else if (interleave == 2) - interleave_nbits = 1; - else if (interleave == 4) - interleave_nbits = 2; - else - interleave_nbits = 3; rp->branch_interleave = branch_interleave; rp->way = way; rp->base = base; @@ -358,10 +209,6 @@ rp->hole_size = hole_size; rp->interleave = interleave; rp->limit = limit; - if (dimm) - rp->rank_geometry = &dimm->rank_geometry[interleave_nbits]; - else - rp->rank_geometry = 0; } static const cmi_mc_ops_t inb_mc_ops = {
--- a/usr/src/uts/intel/io/intel_nb5000/dimm_addr.h Fri Sep 25 15:00:11 2009 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * 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. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _DIMM_ADDR_H -#define _DIMM_ADDR_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Map for memory address translation for each interleave */ - -struct rank_geometry { - uint8_t row[16]; /* Address bit associated with row bit */ - uint8_t bank[3]; /* Address bit associated with bank bit */ - uint8_t col[13]; /* Address bit associated with column bit */ - uint8_t interleave[3]; /* Address bit associated with interleave bit */ -}; - -struct dimm_geometry { - uint8_t row_nbits; /* number of row bits */ - uint8_t col_nbits; /* number of column bits */ - uint8_t bank_nbits; /* number of bank bits */ - uint8_t width; /* width */ - struct rank_geometry rank_geometry[4]; /* for interleave 1,2,4,8 */ -} dimm_data[1]; - -int dimm_types = sizeof (dimm_data) / sizeof (struct dimm_geometry); - -#ifdef __cplusplus -} -#endif - -#endif /* _DIMM_ADDR_H */
--- a/usr/src/uts/intel/io/intel_nb5000/dimm_phys.h Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/io/intel_nb5000/dimm_phys.h Fri Sep 25 14:44:38 2009 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,28 +31,18 @@ extern "C" { #endif -#define OFFSET_ROW_BANK_COL 0x8000000000000000ULL -#define OFFSET_RANK_SHIFT 52 -#define OFFSET_RAS_SHIFT 32 -#define OFFSET_BANK_SHIFT 24 -#define TCODE_OFFSET(rank, bank, ras, cas) (OFFSET_ROW_BANK_COL | \ - ((uint64_t)(rank) << OFFSET_RANK_SHIFT) | \ - ((uint64_t)(ras) << OFFSET_RAS_SHIFT) | \ - ((uint64_t)(bank) << OFFSET_BANK_SHIFT) | (cas)) - -#define TCODE_OFFSET_RANK(tcode) (((tcode) >> OFFSET_RANK_SHIFT) & RANK_MASK) -#define TCODE_OFFSET_RAS(tcode) (((tcode) >> OFFSET_RAS_SHIFT) & RAS_MASK) -#define TCODE_OFFSET_BANK(tcode) (((tcode) >> OFFSET_BANK_SHIFT) & BANK_MASK) -#define TCODE_OFFSET_CAS(tcode) ((tcode) & CAS_MASK) +#define MAXPHYS_ADDR 0xffffffff00000000ULL extern void dimm_init(void); extern void dimm_fini(void); extern void dimm_add_rank(int, int, int, int, uint64_t, uint32_t, uint32_t, int, uint64_t); -extern void dimm_add_geometry(int, int, int, int, int, int); extern uint64_t dimm_getoffset(int, int, int, int, int); -extern uint64_t dimm_getphys(int, int, int, int, int); +extern uint64_t dimm_getphys(uint16_t, uint16_t, uint64_t, uint64_t, uint64_t); + +#pragma weak dimm_getoffset +#pragma weak dimm_getphys #ifdef __cplusplus }
--- a/usr/src/uts/intel/io/intel_nb5000/intel_nb5000.c Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/io/intel_nb5000/intel_nb5000.c Fri Sep 25 14:44:38 2009 -0700 @@ -132,10 +132,30 @@ sp->bank = (nrecmema >> 12) & BANK_MASK; sp->cas = (nrecmemb >> 16) & CAS_MASK; sp->ras = nrecmemb & RAS_MASK; - sp->pa = dimm_getphys(sp->branch, sp->rank, sp->bank, sp->ras, - sp->cas); - sp->offset = dimm_getoffset(sp->branch, sp->rank, sp->bank, - sp->ras, sp->cas); + /* + * If driver was built with closed tree present then we will + * have Intel proprietary code for finding physaddr + */ + if (&dimm_getphys) { + sp->pa = dimm_getphys((uint16_t)sp->branch, + (uint16_t)sp->rank, (uint64_t)sp->bank, + (uint64_t)sp->ras, (uint64_t)sp->cas); + if (sp->pa >= MAXPHYS_ADDR) + sp->pa = -1ULL; + } else { + sp->pa = -1ULL; + } + /* + * If there is an offset decoder use it otherwise encode + * rank/bank/ras/cas + */ + if (&dimm_getoffset) { + sp->offset = dimm_getoffset(sp->branch, sp->rank, + sp->bank, sp->ras, sp->cas); + } else { + sp->offset = TCODE_OFFSET(sp->rank, sp->bank, sp->ras, + sp->cas); + } } else { if ((ferr_fat_fbd & ERR_FAT_FBD_M3) != 0) intr = "nb.fbd.otf"; /* thermal temp > Tmid M3 */ @@ -300,10 +320,26 @@ } } if (sp->ras != -1) { - sp->pa = dimm_getphys(sp->branch, sp->rank, sp->bank, sp->ras, - sp->cas); - sp->offset = dimm_getoffset(sp->branch, sp->rank, sp->bank, - sp->ras, sp->cas); + /* + * If driver was built with closed tree present then we will + * have Intel proprietary code for finding physaddr + */ + if (&dimm_getphys) { + sp->pa = dimm_getphys((uint16_t)sp->branch, + (uint16_t)sp->rank, (uint64_t)sp->bank, + (uint64_t)sp->ras, (uint64_t)sp->cas); + if (sp->pa >= MAXPHYS_ADDR) + sp->pa = -1ULL; + } else { + sp->pa = -1ULL; + } + if (&dimm_getoffset) { + sp->offset = dimm_getoffset(sp->branch, sp->rank, + sp->bank, sp->ras, sp->cas); + } else { + sp->offset = TCODE_OFFSET(sp->rank, sp->bank, sp->ras, + sp->cas); + } } return (intr); } @@ -450,10 +486,26 @@ } } if (sp->ras != -1) { - sp->pa = dimm_getphys(sp->branch, sp->rank, sp->bank, sp->ras, - sp->cas); - sp->offset = dimm_getoffset(sp->branch, sp->rank, sp->bank, - sp->ras, sp->cas); + /* + * If driver was built with closed tree present then we will + * have Intel proprietary code for finding physaddr + */ + if (&dimm_getphys) { + sp->pa = dimm_getphys((uint16_t)sp->branch, + (uint16_t)sp->rank, (uint64_t)sp->bank, + (uint64_t)sp->ras, (uint64_t)sp->cas); + if (sp->pa >= MAXPHYS_ADDR) + sp->pa = -1ULL; + } else { + sp->pa = -1ULL; + } + if (&dimm_getoffset) { + sp->offset = dimm_getoffset(sp->branch, sp->rank, + sp->bank, sp->ras, sp->cas); + } else { + sp->offset = TCODE_OFFSET(sp->rank, sp->bank, sp->ras, + sp->cas); + } } return (intr); }
--- a/usr/src/uts/intel/io/intel_nb5000/nb5000.h Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/io/intel_nb5000/nb5000.h Fri Sep 25 14:44:38 2009 -0700 @@ -937,7 +937,7 @@ nb_pci_getl(0, 16, 1, 0xc0, 0)) #define NRECFGLOG_RD(branch) (nb_chipset == INTEL_NB_5400 ? \ nb_pci_getl(0, (branch) ? 22 : 21, 1, 0x74, 0) : \ - nb_pci_getl(0, 16, 1, 0xc4, 0)) + nb_pci_getl(0, 16, 1, nb_chipset == INTEL_NB_7300 ? 0x74 : 0xc4, 0)) #define NRECFBDA_RD(branch) (nb_chipset == INTEL_NB_5400 ? \ nb_pci_getl(0, (branch) ? 22 : 21, 1, 0xc4, 0) : \ nb_pci_getl(0, 16, 1, nb_chipset == INTEL_NB_7300 ? 0xc4 : 0xc8, 0)) @@ -1370,12 +1370,16 @@ #define DMIR_RANKS(dmir, rank0, rank1, rank2, rank3) \ if (nb_chipset == INTEL_NB_5000P || nb_chipset == INTEL_NB_5000X || \ - nb_chipset == INTEL_NB_5000V || nb_chipset == INTEL_NB_5000Z || \ - nb_chipset == INTEL_NB_5100) { \ - rank0 = (dmir) & 3; \ - rank1 = ((dmir) >> 3) & 3; \ - rank2 = ((dmir) >> 6) & 3; \ - rank3 = ((dmir) >> 9) & 3; \ + nb_chipset == INTEL_NB_5000V || nb_chipset == INTEL_NB_5000Z) { \ + rank0 = (dmir) & 0x7; \ + rank1 = ((dmir) >> 3) & 0x7; \ + rank2 = ((dmir) >> 6) & 0x7; \ + rank3 = ((dmir) >> 9) & 0x7; \ + } else if (nb_chipset == INTEL_NB_5100) { \ + rank0 = (dmir) & 0x7; \ + rank1 = ((dmir) >> 4) & 0x7; \ + rank2 = ((dmir) >> 8) & 0x7; \ + rank3 = ((dmir) >> 12) & 0x7; \ } else { \ rank0 = (dmir) & 0xf; \ rank1 = ((dmir) >> 4) & 0xf; \
--- a/usr/src/uts/intel/io/intel_nb5000/nb5000_init.c Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/io/intel_nb5000/nb5000_init.c Fri Sep 25 14:44:38 2009 -0700 @@ -809,9 +809,6 @@ dimmpp[j] = nb_ddr2_dimm_init(i, j, start_rank); if (dimmpp[j]) { nb_ndimm ++; - dimm_add_geometry(i, j, dimmpp[j]->nbanks, - dimmpp[j]->width, dimmpp[j]->ncolumn, - dimmpp[j]->nrow); if (label_function) { label_function->label_function( (i * nb_dimms_per_channel) + j, @@ -875,9 +872,6 @@ dimmpp[j] = nb_fbd_dimm_init(k, j, mtr); if (dimmpp[j]) { nb_ndimm ++; - dimm_add_geometry(i, j, dimmpp[j]->nbanks, - dimmpp[j]->width, dimmpp[j]->ncolumn, - dimmpp[j]->nrow); if (label_function) { label_function->label_function( (k * nb_dimms_per_channel) + j,
--- a/usr/src/uts/intel/io/intel_nb5000/rank.h Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/io/intel_nb5000/rank.h Fri Sep 25 14:44:38 2009 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -39,7 +39,6 @@ int branch_interleave; int way; int interleave; - void *rank_geometry; }; extern struct rank_base *rank_base;
--- a/usr/src/uts/intel/io/intel_nhm/intel_nhm.h Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/io/intel_nhm/intel_nhm.h Fri Sep 25 14:44:38 2009 -0700 @@ -103,6 +103,10 @@ ((reg) & (1 << (8 + (channel))) != 0) #define MC_CONTROL_ECCEN(reg) (((reg) >> 1) & 1) #define MC_CONTROL_CLOSED_PAGE(reg) ((reg) & 1) +#define MC_CONTROL_DIVBY3(reg) ((reg >> 6) &1) + +#define NUM_CACHELINE_BITS 6 /* Cachelines are 64B */ + /* * MC_STATUS */ @@ -137,7 +141,17 @@ #define REMOVE_7(reg) (((reg) >> 25) & 1) #define REMOVE_8(reg) (((reg) >> 26) & 1) #define CH_ADDRESS_OFFSET(reg) \ - ((int64_t)(((uint64_t)(reg) & 0x00ffffff) << 40) >> 40) + (int64_t)((uint64_t)(reg) & 0x00ffffff) +#define CH_ADDRESS_SOFFSET(reg) \ + ((int64_t)(((uint64_t)(reg) & 0x00ffffff) << 40) >>40) +/* SAG offset covers SA[39:16] so granularity is 2^16 = 64KB */ +#define SAG_OFFSET_GRANULARITY 16 +/* 24-bit mask for TTMAD_CR_SAG_CH*.OFFSET */ +#define SAG_OFFSET_SIZE_MASK 0xffffffULL +/* 16-bit mask for lower bits not covered by CREG value (SA[15:0]) */ +#define SAG_OFFSET_ADDR_MASK 0xffffULL +#define CACHELINE_ADDR_MASK 0x3fULL /* 6-bit mask */ + /* * MC_RIR_LIMIT_CH */ @@ -145,11 +159,23 @@ /* * MC_RIR_WAY_CH */ -#define RIR_OFFSET(reg) ((int64_t)(((uint64_t)(reg) & 0x3ff0) << 50) >> 54) -#define RIR_RANK(reg) ((reg) & 0xf) +#define RIR_OFFSET(reg) (int64_t)((uint64_t)(reg >> 4)& 0x3ff) +#define RIR_SOFFSET(reg) ((int64_t)(((uint64_t)(reg) & 0x3ff0) << 50) \ + >> 54) +#define RIR_DIMM_RANK(reg) ((reg) & 0xf) +#define RIR_RANK(reg) ((reg) & 0x3) +#define RIR_DIMM(reg) ((reg)>>2 & 0x03) +#define RIR_OFFSET_SIZE_MASK 0x3ff #define MAX_RIR_WAY 4 +#define RIR_LIMIT_GRANULARITY 28 +#define RIR_OFFSET_ADDR_MASK 0xfffffffULL /* 28-bit mask */ +#define RIR_INTLV_PGOPEN_BIT 12 /* Rank interleaving */ +#define RIR_INTLV_PGOPEN_MASK 0xfffULL /* 12-bit mask */ +#define RIR_INTLV_PGCLS_BIT 6 /* Rank interleaving */ +#define RIR_INTLV_PGCLS_MASK 0x3fULL /* 6-bit mask */ +#define RIR_INTLV_SIZE_MASK 0x3ULL /* * MC_RAS_ENABLES */ @@ -198,9 +224,22 @@ #define SAD_DRAM_MODE(sad) (((sad) >> 1) & 3) #define SAD_DRAM_RULE_ENABLE(sad) ((sad) & 1) -#define SAD_INTERLEAVE(list, num) (((list) >> ((num) * 4)) & 0x3) -#define INTERLEAVE_NWAY 8 -#define MAX_SAD_DRAM_RULE 8 +/* + * from SAD_DRAM_RULE*.MODE + */ +#define DIRECT 0 +#define XOR 1 +#define MOD3 2 +#define SAD_INTERLEAVE(list, num) (((list) >> ((num) * 4)) & 0x3) +#define INTERLEAVE_NWAY 8 +#define MAX_SAD_DRAM_RULE 8 + +#define SAD_LIMIT_GRANULARITY 26 +#define SAD_LIMIT_ADDR_MASK 0x3ffffffULL +#define SAD_INTLV_DIRECT_BIT 6 +#define SAD_INTLV_XOR_BIT 16 +#define SAD_INTLV_SIZE_MASK 0x7ULL +#define SAD_INTLV_ADDR_MASK 0x3fULL /* * TAD_DRAM_RULE @@ -215,6 +254,57 @@ #define VRANK_SZ 0x40000000 +typedef struct sad { + uint64_t limit; + uint32_t node_list; + uint32_t node_tgt[INTERLEAVE_NWAY]; + char mode; + char enable; + char interleave; +} sad_t; + +typedef struct tad { + uint64_t limit; + uint32_t pkg_list; + uint32_t pkg_tgt[INTERLEAVE_NWAY]; + char mode; + char enable; + char interleave; +} tad_t; + +typedef struct sag_ch { + uint32_t offset; + int32_t soffset; + char divby3; + char remove6; + char remove7; + char remove8; +} sag_ch_t; + +typedef struct rir_way { + uint16_t offset; + int16_t soffset; + uint8_t rank; + uint8_t dimm; + uint8_t dimm_rank; + uint64_t rlimit; +} way_t; + +typedef struct rir { + uint64_t limit; + way_t way[MAX_RIR_WAY]; + char interleave; +} rir_t; + +typedef struct dod_type { + int NUMCol; + int NUMRow; + int NUMRank; + int NUMBank; + int DIMMPresent; + int RankOffset; +} dod_t; + /* * MC_CHANNEL_MAPPER */
--- a/usr/src/uts/intel/io/intel_nhm/mem_addr.c Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/io/intel_nhm/mem_addr.c Fri Sep 25 14:44:38 2009 -0700 @@ -28,48 +28,25 @@ #include <sys/time.h> #include <sys/fm/protocol.h> #include <sys/cpu_module_impl.h> +#include <sys/mc_intel.h> #include "intel_nhm.h" #include "nhm_log.h" - -struct sad { - uint64_t limit; - uint32_t node_list; - char mode; - char enable; - char interleave; -} sad[MAX_SAD_DRAM_RULE]; - -struct tad { - uint64_t limit; - uint32_t pkg_list; - char mode; - char enable; - char interleave; -} tad[MAX_CPU_NODES][MAX_TAD_DRAM_RULE]; - -struct sag_ch { - int32_t offset; - char divby3; - char remove6; - char remove7; - char remove8; -} sag_ch[MAX_CPU_NODES][CHANNELS_PER_MEMORY_CONTROLLER][MAX_TAD_DRAM_RULE]; - -struct rir { - uint64_t limit; - struct rir_way { - int16_t offset; - uint8_t rank; - uint64_t rlimit; - } way[MAX_RIR_WAY]; - char interleave; -} rir[MAX_CPU_NODES][CHANNELS_PER_MEMORY_CONTROLLER][MAX_TAD_DRAM_RULE]; +#include "mem_addr.h" char closed_page; char ecc_enabled; +char divby3_enabled; char lockstep[2]; char mirror_mode[2]; char spare_channel[2]; +sad_t sad[MAX_SAD_DRAM_RULE]; +tad_t tad[MAX_CPU_NODES][MAX_TAD_DRAM_RULE]; +sag_ch_t sag_ch[MAX_CPU_NODES][CHANNELS_PER_MEMORY_CONTROLLER] + [MAX_TAD_DRAM_RULE]; +rir_t rir[MAX_CPU_NODES][CHANNELS_PER_MEMORY_CONTROLLER] + [MAX_TAD_DRAM_RULE]; +dod_t dod_reg[MAX_CPU_NODES][CHANNELS_PER_MEMORY_CONTROLLER] + [MAX_DIMMS_PER_CHANNEL]; static int channel_in_interleave(int node, int channel, int rule, int *way_p, @@ -185,7 +162,7 @@ if (lockstep[node] || mirror_mode[node]) channel = 0; caddr = (((addr >> 16) + - (int64_t)sag_ch[node][channel][rule].offset) << 16) | + (int64_t)sag_ch[node][channel][rule].soffset) << 16) | (addr & 0xffc0); if (sag_ch[node][channel][rule].remove8) { caddr = ((caddr >> 1) & ~0xff) | (caddr & 0xff); @@ -205,8 +182,8 @@ } int -address_to_channel(int node, uint64_t addr, int write, uint64_t *channel_addrp, - int *interleave_p) +address_to_channel(int node, uint64_t addr, int write, + int *log_chan, uint64_t *channel_addrp, int *interleave_p) { int i; int channel = -1; @@ -233,10 +210,14 @@ default: return (-1); } + /* get logical channel number */ channel = TAD_INTERLEAVE(tad[node][i].pkg_list, way); + if (log_chan) + *log_chan = channel; + if (channel_addrp) { - *channel_addrp = channel_address(node, channel, - i, addr); + *channel_addrp = channel_address(node, + channel, i, addr); } if (interleave_p) *interleave_p = tad[node][i].interleave; @@ -257,7 +238,7 @@ case 4: channel = 2; break; - case 3: /* mirror PCH0 and PCH1 */ + case 3: /* mirror PCH0 and PCH1 */ if (!write) { if (((addr >> 24) & 1) ^ ((addr >> 12) & 1) ^ ((addr >> 6) & 1)) @@ -266,10 +247,10 @@ channel = 0; } break; - case 5: /* sparing PCH0 to PCH2 */ + case 5: /* sparing PCH0 to PCH2 */ channel = 0; break; - case 6: /* sparing PCH1 to PCH2 */ + case 6: /* sparing PCH1 to PCH2 */ channel = 1; break; } @@ -287,20 +268,19 @@ node = address_to_node(addr, &sinterleave); if (sinterleave == 1) { channels = 0; - (void) address_to_channel(node, addr, 0, 0, &channels); + (void) address_to_channel(node, addr, 0, 0, 0, &channels); } else { channels = 0; channels1 = 0; - (void) address_to_channel(0, addr, 0, 0, &channels); - (void) address_to_channel(1, addr, 0, 0, &channels1); + (void) address_to_channel(0, addr, 0, 0, 0, &channels); + (void) address_to_channel(1, addr, 0, 0, 0, &channels1); channels += channels1; } return (channels); } - int -caddr_to_dimm(int node, int channel, uint64_t caddr, int *rank_p, +channel_addr_to_dimm(int node, int channel, uint64_t caddr, int *rank_p, uint64_t *rank_addr_p) { int i; @@ -449,7 +429,7 @@ base = 0; for (i = 0; i < MAX_TAD_DRAM_RULE && found == 0; i++) { for (way = 0; way < MAX_RIR_WAY; way++) { - if (rir[node][channel][i].way[way].rank == rank) { + if (rir[node][channel][i].way[way].dimm_rank == rank) { rlimit = rir[node][channel][i].way[way].rlimit; if (rlimit && rank_addr >= rlimit) continue; @@ -457,7 +437,7 @@ caddr = (rank_addr & ~0x3f) * rir[node][channel][i].interleave - (int64_t)rir[node][channel][i]. - way[way].offset * VRANK_SZ; + way[way].soffset * VRANK_SZ; cbaddr = caddr; caddr += way << 6; caddr |= rank_addr & 0x3f; @@ -465,7 +445,7 @@ caddr = (rank_addr & ~0xfff) * rir[node][channel][i].interleave - (int64_t)rir[node][channel][i]. - way[way].offset * VRANK_SZ; + way[way].soffset * VRANK_SZ; cbaddr = caddr; caddr += way << 12; caddr |= rank_addr & 0xfff; @@ -519,9 +499,10 @@ addr = ((addr & ~0xff) << 1) | (addr & 0xff); baddr = ((baddr & ~0xff) << 1) | (baddr & 0xc0); } - addr -= (int64_t)sag_ch[node][lchannel][i].offset << 16; + addr -= (int64_t)sag_ch[node][lchannel][i].soffset << + 16; baddr -= (int64_t) - sag_ch[node][lchannel][i].offset << 16; + sag_ch[node][lchannel][i].soffset << 16; if (addr < tad[node][i].limit) { sinterleave = socket_interleave(addr, node, channel, i, &way); @@ -620,7 +601,6 @@ } return (addr); } - /*ARGSUSED*/ static cmi_errno_t nhm_patounum(void *arg, uint64_t pa, uint8_t valid_hi, uint8_t valid_lo, @@ -630,25 +610,49 @@ int channel; int dimm; int rank; + int log_chan; + uint64_t bank, row, column; uint64_t caddr, raddr; node = address_to_node(pa, 0); - if (node == -1) + if (node == -1) { + return (CMIERR_UNKNOWN); + } + channel = address_to_channel(node, pa, syndtype, &log_chan, &caddr, 0); + if (channel == -1) { return (CMIERR_UNKNOWN); - channel = address_to_channel(node, pa, syndtype, &caddr, 0); - if (channel == -1) - return (CMIERR_UNKNOWN); - dimm = caddr_to_dimm(node, channel, caddr, &rank, &raddr); - if (dimm == -1) + } + /* + * If driver was built with closed tree present then we will have Intel + * proprietary functions caddr_to_dimm and rankaddr_to_dimm for finding + * dimm/bank/row/column address otherwise we just locate dimm and + * offset. + */ + if (&caddr_to_dimm) + dimm = caddr_to_dimm(node, log_chan, caddr, &rank, &raddr); + else + dimm = channel_addr_to_dimm(node, log_chan, caddr, &rank, + &raddr); + if (dimm == -1) { return (CMIERR_UNKNOWN); + } unump->unum_board = 0; unump->unum_chip = node; unump->unum_mc = 0; unump->unum_chan = channel; unump->unum_cs = dimm; unump->unum_rank = rank; - unump->unum_offset = raddr; + + if (&rankaddr_to_dimm) { + if (rankaddr_to_dimm(raddr, node, channel, dimm, 0, &bank, &row, + &column) != DDI_SUCCESS) { + return (CMIERR_UNKNOWN); + }; + unump->unum_offset = TCODE_OFFSET(rank, bank, row, column); + } else { + unump->unum_offset = raddr; + } return (CMI_SUCCESS); } @@ -661,22 +665,26 @@ cmi_errno_t rt; int node; int channel; + int log_chan; int rank; int i; nvlist_t **hcl, *hcsp; uint_t npr; - uint64_t rank_addr; + uint64_t offset; char *hcnm, *hcid; long v; + uint64_t row, bank, col; + int dimm; + uint64_t rank_addr; if (unump == NULL) { if (nvlist_lookup_nvlist(nvl, FM_FMRI_HC_SPECIFIC, &hcsp) != 0) return (CMIERR_UNKNOWN); if (nvlist_lookup_uint64(hcsp, - "asru-" FM_FMRI_HC_SPECIFIC_OFFSET, &rank_addr) != 0 && + "asru-" FM_FMRI_HC_SPECIFIC_OFFSET, &offset) != 0 && nvlist_lookup_uint64(hcsp, FM_FMRI_HC_SPECIFIC_OFFSET, - &rank_addr) != 0) { + &offset) != 0) { if (nvlist_lookup_uint64(hcsp, "asru-" FM_FMRI_HC_SPECIFIC_PHYSADDR, &pa) == 0 || nvlist_lookup_uint64(hcsp, @@ -691,6 +699,7 @@ return (CMIERR_UNKNOWN); node = -1; channel = -1; + dimm = -1; rank = -1; for (i = 0; i < npr; i++) { if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, @@ -703,19 +712,41 @@ node = (int)v; else if (strcmp(hcnm, "dram-channel") == 0) channel = (int)v; + else if (strcmp(hcnm, "dimm") == 0) + dimm = (int)v; else if (strcmp(hcnm, "rank") == 0) rank = (int)v; } - if (node == -1 || channel == -1 || rank == -1) + if (node == -1 || channel == -1 || dimm == -1 || rank == -1) return (CMIERR_UNKNOWN); } else { node = unump->unum_chip; channel = unump->unum_chan; rank = unump->unum_rank; - rank_addr = unump->unum_offset; + dimm = unump->unum_cs; + offset = unump->unum_offset; } - pa = dimm_to_addr(node, channel, rank, rank_addr, 0, 0, 0, 0, 0, 0, 0, - 0); + + /* + * If driver was built with closed tree present then we will have Intel + * proprietary functions dimm_to_rankaddr for finding + * physical address. + */ + if (&dimm_to_rankaddr && (offset & OFFSET_ROW_BANK_COL) != 0) { + row = TCODE_OFFSET_RAS(offset); + bank = TCODE_OFFSET_BANK(offset); + col = TCODE_OFFSET_CAS(offset); + rank_addr = dimm_to_rankaddr(node, channel, dimm, row, + bank, col, &log_chan); + pa = rankaddr_to_phyaddr(node, log_chan, dimm, rank, + rank_addr); + } else if ((offset & OFFSET_ROW_BANK_COL) == 0) { + pa = dimm_to_addr(node, channel, rank, offset, 0, 0, 0, 0, 0, + 0, 0, 0); + } else { + pa = -1LL; + } + if (pa == -1) { rt = CMIERR_UNKNOWN; } else { @@ -810,7 +841,7 @@ return; for (k = 0; k <= rule; k++) { for (l = 0; l < way; l++) { - if (rir[socket][channel][k].way[l].rank == rank && + if (rir[socket][channel][k].way[l].dimm_rank == rank && rir[socket][channel][k].way[l].rlimit == 0) { rir[socket][channel][k].way[l].rlimit = rank_addr; @@ -837,6 +868,7 @@ uint8_t rank; uint64_t base; int ras_dev = 0; + uint32_t dod_value; nhm_slot = choose_cpu(&nhm_lastslot); @@ -847,6 +879,10 @@ sad[i].mode = SAD_DRAM_MODE(sad_dram_rule); sad[i].node_list = SAD_INTERLEAVE_LIST_RD(nhm_slot, i); sad[i].interleave = sad_interleave(sad[i].node_list); + for (j = 0; j < INTERLEAVE_NWAY; j++) { + sad[i].node_tgt[j] = (sad[i].node_list >> + (j * 4)) & 0x3; + } } for (i = nhm_slot; i < nhm_lastslot; i++) { @@ -871,6 +907,10 @@ tad[i][j].mode = TAD_DRAM_MODE(tad_dram_rule); tad[i][j].pkg_list = TAD_INTERLEAVE_LIST_RD(i, j); + for (k = 0; k < INTERLEAVE_NWAY; k++) { + tad[i][j].pkg_tgt[k] = ((tad[i][j].pkg_list >> + (k * 4)) & 0x3); + } if (mirror_mode[i] || lockstep[i]) { tad[i][j].interleave = 1; } else { @@ -889,6 +929,8 @@ sagch = MC_SAG_RD(i, j, k); sag_ch[i][j][k].offset = CH_ADDRESS_OFFSET(sagch); + sag_ch[i][j][k].soffset = + CH_ADDRESS_SOFFSET(sagch); sag_ch[i][j][k].divby3 = DIVBY3(sagch); sag_ch[i][j][k].remove6 = REMOVE_6(sagch); sag_ch[i][j][k].remove7 = REMOVE_7(sagch); @@ -900,32 +942,50 @@ rir_way = MC_RIR_WAY_RD(i, j, m); rir[i][j][k].way[l].offset = RIR_OFFSET(rir_way); + rir[i][j][k].way[l].soffset = + RIR_SOFFSET(rir_way); rir[i][j][k].way[l].rank = RIR_RANK(rir_way); + rir[i][j][k].way[l].dimm = + RIR_DIMM(rir_way); + rir[i][j][k].way[l].dimm_rank = + RIR_DIMM_RANK(rir_way); rir[i][j][k].way[l].rlimit = 0; m++; } - rank = rir[i][j][k].way[0].rank; - if (rank == rir[i][j][k].way[1].rank && - rank == rir[i][j][k].way[2].rank && - rank == rir[i][j][k].way[3].rank) { + rank = rir[i][j][k].way[0].dimm_rank; + if (rank == rir[i][j][k].way[1].dimm_rank && + rank == rir[i][j][k].way[2].dimm_rank && + rank == rir[i][j][k].way[3].dimm_rank) { rir[i][j][k].interleave = 1; - } else if (rank == rir[i][j][k].way[1].rank || - rank == rir[i][j][k].way[2].rank || - rank == rir[i][j][k].way[3].rank) { + } else if + (rank == rir[i][j][k].way[1].dimm_rank || + rank == rir[i][j][k].way[2].dimm_rank || + rank == rir[i][j][k].way[3].dimm_rank) { rir[i][j][k].interleave = 2; } else { rir[i][j][k].interleave = 4; } for (l = 0; l < MAX_RIR_WAY; l++) { set_rank(i, j, k, l, - rir[i][j][k].way[l].rank, - ((rir[i][j][k].way[l].offset + + rir[i][j][k].way[l].dimm_rank, + ((rir[i][j][k].way[l].soffset + base) / rir[i][j][k].interleave)); } base = rir[i][j][k].limit; } + for (k = 0; k < MAX_DIMMS_PER_CHANNEL; k++) { + dod_value = MC_DOD_RD(i, j, k); + dod_reg[i][j][k].NUMCol = NUMCOL(dod_value); + dod_reg[i][j][k].NUMRow = NUMROW(dod_value); + dod_reg[i][j][k].NUMBank = NUMBANK(dod_value); + dod_reg[i][j][k].NUMRank = NUMRANK(dod_value); + dod_reg[i][j][k].DIMMPresent = + DIMMPRESENT(dod_value); + dod_reg[i][j][k].RankOffset = + RANKOFFSET(dod_value); + } } } mc_control = MC_CONTROL_RD(nhm_slot); @@ -934,4 +994,5 @@ ecc_enabled = MC_CONTROL_ECCEN(mc_control); else if ((MC_STATUS_RD(nhm_slot) & WS_ECC_ENABLED) != 0) ecc_enabled = 1; + divby3_enabled = MC_CONTROL_DIVBY3(mc_control); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/intel/io/intel_nhm/mem_addr.h Fri Sep 25 14:44:38 2009 -0700 @@ -0,0 +1,80 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * 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. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _MEM_ADDR_H +#define _MEM_ADDR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "intel_nhm.h" + +#ifdef _KERNEL + +extern uint64_t rankaddr_to_dimm(uint64_t rankaddr, int node, + int channel, int dimm, int writing, uint64_t *bank, + uint64_t *row, uint64_t *column); +extern uint64_t dimm_to_rankaddr(int node, int channel, + int dimm, uint64_t rowaddr, uint64_t bankaddr, + uint64_t coladr, int *log_chan); +extern uint64_t rankaddr_to_phyaddr(int node, int log_chan, + int dimm, int rank, int rankaddr); +extern uint64_t caddr_to_dimm(int node, int channel, uint64_t caddr, + int *rank_p, uint64_t *rank_addr_p); + +#pragma weak caddr_to_dimm +#pragma weak rankaddr_to_dimm +#pragma weak dimm_to_rankaddr +#pragma weak rankaddr_to_phyaddr + +extern char closed_page; +extern char ecc_enabled; +extern char divby3_enabled; +extern char lockstep[2]; +extern char mirror_mode[2]; +extern char spare_channel[2]; +extern sad_t sad[MAX_SAD_DRAM_RULE]; +extern tad_t tad[MAX_CPU_NODES][MAX_TAD_DRAM_RULE]; +extern sag_ch_t sag_ch[MAX_CPU_NODES][CHANNELS_PER_MEMORY_CONTROLLER] + [MAX_TAD_DRAM_RULE]; +extern rir_t rir[MAX_CPU_NODES][CHANNELS_PER_MEMORY_CONTROLLER] + [MAX_TAD_DRAM_RULE]; +extern dod_t dod_reg[MAX_CPU_NODES][CHANNELS_PER_MEMORY_CONTROLLER] + [MAX_DIMMS_PER_CHANNEL]; + +#endif /* _KERNEL */ + +#define CAS_MASK 0xFFFFFF +#define BANK_MASK 0xFF +#define RAS_MASK 0xFFFFF +#define RANK_MASK 0x7FF + +#ifdef __cplusplus +} +#endif + +#endif /* _MEM_ADDR_H */
--- a/usr/src/uts/intel/sys/mc_intel.h Fri Sep 25 15:00:11 2009 -0400 +++ b/usr/src/uts/intel/sys/mc_intel.h Fri Sep 25 14:44:38 2009 -0700 @@ -287,6 +287,26 @@ #define MSR_MC_MISC_MEM_SYNDROME 0xffffffff00000000ULL #define MSR_MC_MISC_MEM_SYNDROME_SHIFT 32 +#define OFFSET_ROW_BANK_COL 0x8000000000000000ULL +#define OFFSET_RANK_SHIFT 52 +#define OFFSET_RAS_SHIFT 32 +#define OFFSET_BANK_SHIFT 24 +#define TCODE_OFFSET(rank, bank, ras, cas) (OFFSET_ROW_BANK_COL | \ + ((uint64_t)(rank) << OFFSET_RANK_SHIFT) | \ + ((uint64_t)(ras) << OFFSET_RAS_SHIFT) | \ + ((uint64_t)(bank) << OFFSET_BANK_SHIFT) | (cas)) + +#define MAX_CAS_MASK 0xFFFFFF +#define MAX_BANK_MASK 0xFF +#define MAX_RAS_MASK 0xFFFFF +#define MAX_RANK_MASK 0x7FF +#define TCODE_OFFSET_RANK(tcode) \ + (((tcode) >> OFFSET_RANK_SHIFT) & MAX_RANK_MASK) +#define TCODE_OFFSET_RAS(tcode) (((tcode) >> OFFSET_RAS_SHIFT) & MAX_RAS_MASK) +#define TCODE_OFFSET_BANK(tcode) \ + (((tcode) >> OFFSET_BANK_SHIFT) & MAX_BANK_MASK) +#define TCODE_OFFSET_CAS(tcode) ((tcode) & MAX_CAS_MASK) + #ifdef __cplusplus } #endif