17aec1d6eScindi /* 27aec1d6eScindi * CDDL HEADER START 37aec1d6eScindi * 47aec1d6eScindi * The contents of this file are subject to the terms of the 5a307a255Sgavinm * Common Development and Distribution License (the "License"). 6a307a255Sgavinm * You may not use this file except in compliance with the License. 77aec1d6eScindi * 87aec1d6eScindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97aec1d6eScindi * or http://www.opensolaris.org/os/licensing. 107aec1d6eScindi * See the License for the specific language governing permissions 117aec1d6eScindi * and limitations under the License. 127aec1d6eScindi * 137aec1d6eScindi * When distributing Covered Code, include this CDDL HEADER in each 147aec1d6eScindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157aec1d6eScindi * If applicable, add the following below this CDDL HEADER, with the 167aec1d6eScindi * fields enclosed by brackets "[]" replaced with your own identifying 177aec1d6eScindi * information: Portions Copyright [yyyy] [name of copyright owner] 187aec1d6eScindi * 197aec1d6eScindi * CDDL HEADER END 207aec1d6eScindi */ 217aec1d6eScindi 227aec1d6eScindi /* 23*c84b7bbeSAdrian Frost * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 247aec1d6eScindi */ 257aec1d6eScindi 267aec1d6eScindi #ifndef _AO_H 277aec1d6eScindi #define _AO_H 287aec1d6eScindi 297aec1d6eScindi #include <sys/types.h> 307aec1d6eScindi #include <sys/mc.h> 317aec1d6eScindi #include <sys/mca_amd.h> 324156fc34Sgavinm #include <sys/mc_amd.h> 3320c794b3Sgavinm #include <sys/cpu_module_ms_impl.h> 347aec1d6eScindi #include <sys/nvpair.h> 357aec1d6eScindi #include <sys/cyclic.h> 367aec1d6eScindi #include <sys/errorq.h> 377aec1d6eScindi #include <sys/kobj.h> 387aec1d6eScindi #include <sys/fm/util.h> 397aec1d6eScindi 407aec1d6eScindi #ifdef __cplusplus 417aec1d6eScindi extern "C" { 427aec1d6eScindi #endif 437aec1d6eScindi 4420c794b3Sgavinm #define AO_MAX_CHIPS 8 4520c794b3Sgavinm 467aec1d6eScindi #define AO_MCA_MAX_ERRORS 10 477aec1d6eScindi 4820c794b3Sgavinm typedef struct ao_ms_data ao_ms_data_t; 497aec1d6eScindi 507aec1d6eScindi /* 517aec1d6eScindi * Rather than using torturous conditionals, we match errors using a table of 527aec1d6eScindi * ao_error_disp_t's. The members in the ao_error_disp_t are matched against 537aec1d6eScindi * the value of MCi_STATUS, with a successful match indicating that the given 547aec1d6eScindi * error occurred. 557aec1d6eScindi * 567aec1d6eScindi * While aed_stat_code will match most of the status code bits, a few of the 577aec1d6eScindi * status code fields are either/or, and are treated separately so as to 587aec1d6eScindi * minimize the number of ao_error_disp_t structures that must be created. 597aec1d6eScindi * For example, the dc.tag_par error can have r4 values drd or dwr. Rather 607aec1d6eScindi * than creating two ao_error_disp_t's, we use the separate aed_stat_r4_bits 617aec1d6eScindi * field to indicate both AO_MCA_R4_BIT_DRD and AO_MCA_R4_BIT_DWD. As the 627aec1d6eScindi * matching r4 values are drawn from aed_stat_r4_bits, we don't use the r4 637aec1d6eScindi * bits in aed_stat_code for matching. Similar reasoning lies behind the 647aec1d6eScindi * creation of the pp and ii fields. 657aec1d6eScindi */ 66a307a255Sgavinm #define AO_AED_PANIC_NEVER 0x00 67a307a255Sgavinm #define AO_AED_PANIC_IFMCE 0x01 68a307a255Sgavinm #define AO_AED_PANIC_ALWAYS 0x80 697aec1d6eScindi 7020c794b3Sgavinm /* 7120c794b3Sgavinm * The AO_AED_F_* flags tell us how to interpret aspects of the error 7220c794b3Sgavinm * telemetry, such as which bits of the captured address are valid for 7320c794b3Sgavinm * this error. 7420c794b3Sgavinm */ 7520c794b3Sgavinm /* MCi_ADDR ... */ 7620c794b3Sgavinm #define AO_AED_F_LINEAR 0x01 /* is a linear address */ 7720c794b3Sgavinm #define AO_AED_F_PHYSICAL 0x02 /* is a physical address */ 7820c794b3Sgavinm #define AO_AED_F_PAGEALIGNED 0x04 /* aligns to page size */ 7920c794b3Sgavinm #define AO_AED_F_L2SETWAY 0x08 /* 3:0 = way, 15/14/13/12:6 = set */ 804156fc34Sgavinm 814156fc34Sgavinm #define AO_AED_FLAGS_ADDRTYPE (AO_AED_F_LINEAR | AO_AED_F_PHYSICAL | \ 824156fc34Sgavinm AO_AED_F_PAGEALIGNED | AO_AED_F_L2SETWAY) 837aec1d6eScindi 8420c794b3Sgavinm /* 8520c794b3Sgavinm * The AO_AED_ET_* flags group individual error dispositions into 8620c794b3Sgavinm * error types. This is used to nominate additional telemetry beyond the 8720c794b3Sgavinm * architectural bank registers to capture for this error type. 8820c794b3Sgavinm */ 8920c794b3Sgavinm #define AO_AED_ET_MEMECC 0x0001 /* Main memory ECC error */ 9020c794b3Sgavinm 917aec1d6eScindi typedef struct ao_error_disp { 927aec1d6eScindi const char *aed_class; /* ereport class for use if match */ 937aec1d6eScindi uint64_t aed_ereport_members; /* ereport contents flags if match */ 947aec1d6eScindi uint64_t aed_stat_mask; /* status msr bits for match */ 957aec1d6eScindi uint64_t aed_stat_mask_res; /* status mask result for match */ 967aec1d6eScindi uint16_t aed_stat_code; /* status code for match */ 977aec1d6eScindi uint8_t aed_stat_extcode; /* extended status code for match */ 987aec1d6eScindi uint8_t aed_stat_pp_bits:4; /* AO_MCA_PP_BIT_* for pp matching */ 997aec1d6eScindi uint8_t aed_stat_ii_bits:4; /* AO_MCA_II_BIT_* for ii matching */ 1007aec1d6eScindi uint16_t aed_stat_r4_bits; /* AO_MCA_R4_BIT_* for r4 matching */ 1014156fc34Sgavinm uint8_t aed_addrvalid_hi; /* most significant valid addr bit */ 1024156fc34Sgavinm uint8_t aed_addrvalid_lo; /* least significant valid addr bit */ 1037aec1d6eScindi uint8_t aed_panic_when; /* extra conditions for panic */ 10420c794b3Sgavinm uint16_t aed_flags; /* AO_AED_F_* */ 10520c794b3Sgavinm uint16_t aed_errtype; /* AO_AED_ET_* */ 1067aec1d6eScindi } ao_error_disp_t; 1077aec1d6eScindi 1087aec1d6eScindi /* 10920c794b3Sgavinm * We store non-architectutal config as inherited from the BIOS to assist 11020c794b3Sgavinm * in troubleshooting. 1117aec1d6eScindi */ 11220c794b3Sgavinm struct ao_bios_cfg { 11320c794b3Sgavinm uint64_t *bcfg_bank_mask; 11420c794b3Sgavinm }; 1157aec1d6eScindi 1167aec1d6eScindi /* 1177aec1d6eScindi * The master data structure used to hold MCA-related state. 1187aec1d6eScindi */ 11920c794b3Sgavinm typedef struct ao_ms_mca { 12020c794b3Sgavinm struct ao_bios_cfg ao_mca_bios_cfg; 1217aec1d6eScindi kmutex_t ao_mca_poll_lock; /* keep pollers from colliding */ 1227aec1d6eScindi uint_t ao_mca_flags; /* AO_MCA_F_* */ 12320c794b3Sgavinm } ao_ms_mca_t; 1247aec1d6eScindi 1257aec1d6eScindi /* 12620c794b3Sgavinm * Per-chip shared state 1278a40a695Sgavinm */ 1288a40a695Sgavinm struct ao_chipshared { 12920c794b3Sgavinm uint32_t aos_chiprev; 1308a40a695Sgavinm volatile ulong_t aos_cfgonce; /* Config performed once per chip */ 13120c794b3Sgavinm hrtime_t aos_nb_poll_timestamp; 13220c794b3Sgavinm cmi_hdl_t aos_nb_poll_owner; 13320c794b3Sgavinm uint64_t aos_bcfg_nb_misc; /* BIOS value of MC4_MISC MSR */ 1348a40a695Sgavinm uint32_t aos_bcfg_nb_cfg; /* BIOS value of NB MCA Config */ 1358a40a695Sgavinm uint32_t aos_bcfg_nb_sparectl; /* BIOS value of Online Spare Control */ 136bb86c342Sgavinm uint32_t aos_bcfg_dcfg_lo; /* BIOS value of DRAM Config Low */ 137bb86c342Sgavinm uint32_t aos_bcfg_dcfg_hi; /* BIOS value of DRAM Config High */ 13820c794b3Sgavinm uint32_t aos_bcfg_scrubctl; /* BIOS value of scrub control */ 1398a40a695Sgavinm }; 1408a40a695Sgavinm 14120c794b3Sgavinm /* Bit numbers for once-per-chip operations policed by cms_once */ 1428a40a695Sgavinm enum ao_cfgonce_bitnum { 143bb86c342Sgavinm AO_CFGONCE_NBMCA, 14420c794b3Sgavinm AO_CFGONCE_NBCFG, 145bb86c342Sgavinm AO_CFGONCE_DRAMCFG 1468a40a695Sgavinm }; 1478a40a695Sgavinm 1488a40a695Sgavinm /* 14920c794b3Sgavinm * Per-CPU model-specific state 1507aec1d6eScindi */ 15120c794b3Sgavinm struct ao_ms_data { 15220c794b3Sgavinm cmi_hdl_t ao_ms_hdl; 15320c794b3Sgavinm ao_ms_mca_t ao_ms_mca; 15420c794b3Sgavinm struct ao_chipshared *ao_ms_shared; 15520c794b3Sgavinm uint64_t ao_ms_hwcr_val; 1567aec1d6eScindi }; 1577aec1d6eScindi 1587aec1d6eScindi #ifdef _KERNEL 1597aec1d6eScindi 1607aec1d6eScindi struct regs; 1617aec1d6eScindi 16220c794b3Sgavinm /* 16320c794b3Sgavinm * Our cms_ops operations and function prototypes for all non-NULL members. 16420c794b3Sgavinm */ 16520c794b3Sgavinm extern const cms_ops_t _cms_ops; 1667aec1d6eScindi 16720c794b3Sgavinm extern int ao_ms_init(cmi_hdl_t, void **); 16820c794b3Sgavinm extern void ao_ms_post_startup(cmi_hdl_t); 16920c794b3Sgavinm extern void ao_ms_post_mpstartup(cmi_hdl_t); 17020c794b3Sgavinm extern uint64_t ao_ms_mcgctl_val(cmi_hdl_t, int, uint64_t); 17120c794b3Sgavinm extern boolean_t ao_ms_bankctl_skipinit(cmi_hdl_t, int); 17220c794b3Sgavinm extern uint64_t ao_ms_bankctl_val(cmi_hdl_t, int, uint64_t); 17320c794b3Sgavinm extern void ao_ms_mca_init(cmi_hdl_t, int); 17420c794b3Sgavinm extern uint64_t ao_ms_poll_ownermask(cmi_hdl_t, hrtime_t); 17520c794b3Sgavinm extern uint32_t ao_ms_error_action(cmi_hdl_t, int, int, uint64_t, 17620c794b3Sgavinm uint64_t, uint64_t, void *); 177*c84b7bbeSAdrian Frost extern cms_cookie_t ao_ms_disp_match(cmi_hdl_t, int, int, uint64_t, uint64_t, 17820c794b3Sgavinm uint64_t, void *); 17920c794b3Sgavinm extern void ao_ms_ereport_class(cmi_hdl_t, cms_cookie_t, const char **, 18020c794b3Sgavinm const char **); 18120c794b3Sgavinm extern boolean_t ao_ms_ereport_includestack(cmi_hdl_t, cms_cookie_t); 18220c794b3Sgavinm extern void ao_ms_ereport_add_logout(cmi_hdl_t, nvlist_t *, 18320c794b3Sgavinm nv_alloc_t *, int, uint64_t, uint64_t, uint64_t, void *, void *); 18420c794b3Sgavinm extern cms_errno_t ao_ms_msrinject(cmi_hdl_t, uint_t, uint64_t); 1857aec1d6eScindi 18620c794b3Sgavinm /* 18720c794b3Sgavinm * Local functions 18820c794b3Sgavinm */ 1898031591dSSrihari Venkatesan extern void ao_procnode_scrubber_enable(cmi_hdl_t, ao_ms_data_t *); 1907aec1d6eScindi extern void ao_pcicfg_write(uint_t, uint_t, uint_t, uint32_t); 1917aec1d6eScindi extern uint32_t ao_pcicfg_read(uint_t, uint_t, uint_t); 19220c794b3Sgavinm extern void ao_bankstatus_prewrite(cmi_hdl_t, ao_ms_data_t *); 19320c794b3Sgavinm extern void ao_bankstatus_postwrite(cmi_hdl_t, ao_ms_data_t *); 1948a40a695Sgavinm 1957aec1d6eScindi #endif /* _KERNEL */ 1967aec1d6eScindi 1977aec1d6eScindi #ifdef __cplusplus 1987aec1d6eScindi } 1997aec1d6eScindi #endif 2007aec1d6eScindi 2017aec1d6eScindi #endif /* _AO_H */ 202