11414Scindi /* 21414Scindi * CDDL HEADER START 31414Scindi * 41414Scindi * The contents of this file are subject to the terms of the 51538Sgavinm * Common Development and Distribution License (the "License"). 61538Sgavinm * You may not use this file except in compliance with the License. 71414Scindi * 81414Scindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91414Scindi * or http://www.opensolaris.org/os/licensing. 101414Scindi * See the License for the specific language governing permissions 111414Scindi * and limitations under the License. 121414Scindi * 131414Scindi * When distributing Covered Code, include this CDDL HEADER in each 141414Scindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151414Scindi * If applicable, add the following below this CDDL HEADER, with the 161414Scindi * fields enclosed by brackets "[]" replaced with your own identifying 171414Scindi * information: Portions Copyright [yyyy] [name of copyright owner] 181414Scindi * 191414Scindi * CDDL HEADER END 201414Scindi */ 211414Scindi 221414Scindi /* 23*10947SSrihari.Venkatesan@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 241414Scindi * Use is subject to license terms. 251414Scindi */ 261414Scindi 271414Scindi #ifndef _AO_H 281414Scindi #define _AO_H 291414Scindi 301414Scindi #include <sys/types.h> 311414Scindi #include <sys/mc.h> 321414Scindi #include <sys/mca_amd.h> 333164Sgavinm #include <sys/mc_amd.h> 345254Sgavinm #include <sys/cpu_module_ms_impl.h> 351414Scindi #include <sys/nvpair.h> 361414Scindi #include <sys/cyclic.h> 371414Scindi #include <sys/errorq.h> 381414Scindi #include <sys/kobj.h> 391414Scindi #include <sys/fm/util.h> 401414Scindi 411414Scindi #ifdef __cplusplus 421414Scindi extern "C" { 431414Scindi #endif 441414Scindi 455254Sgavinm #define AO_MAX_CHIPS 8 465254Sgavinm 471414Scindi #define AO_MCA_MAX_ERRORS 10 481414Scindi 495254Sgavinm typedef struct ao_ms_data ao_ms_data_t; 501414Scindi 511414Scindi /* 521414Scindi * Rather than using torturous conditionals, we match errors using a table of 531414Scindi * ao_error_disp_t's. The members in the ao_error_disp_t are matched against 541414Scindi * the value of MCi_STATUS, with a successful match indicating that the given 551414Scindi * error occurred. 561414Scindi * 571414Scindi * While aed_stat_code will match most of the status code bits, a few of the 581414Scindi * status code fields are either/or, and are treated separately so as to 591414Scindi * minimize the number of ao_error_disp_t structures that must be created. 601414Scindi * For example, the dc.tag_par error can have r4 values drd or dwr. Rather 611414Scindi * than creating two ao_error_disp_t's, we use the separate aed_stat_r4_bits 621414Scindi * field to indicate both AO_MCA_R4_BIT_DRD and AO_MCA_R4_BIT_DWD. As the 631414Scindi * matching r4 values are drawn from aed_stat_r4_bits, we don't use the r4 641414Scindi * bits in aed_stat_code for matching. Similar reasoning lies behind the 651414Scindi * creation of the pp and ii fields. 661414Scindi */ 671538Sgavinm #define AO_AED_PANIC_NEVER 0x00 681538Sgavinm #define AO_AED_PANIC_IFMCE 0x01 691538Sgavinm #define AO_AED_PANIC_ALWAYS 0x80 701414Scindi 715254Sgavinm /* 725254Sgavinm * The AO_AED_F_* flags tell us how to interpret aspects of the error 735254Sgavinm * telemetry, such as which bits of the captured address are valid for 745254Sgavinm * this error. 755254Sgavinm */ 765254Sgavinm /* MCi_ADDR ... */ 775254Sgavinm #define AO_AED_F_LINEAR 0x01 /* is a linear address */ 785254Sgavinm #define AO_AED_F_PHYSICAL 0x02 /* is a physical address */ 795254Sgavinm #define AO_AED_F_PAGEALIGNED 0x04 /* aligns to page size */ 805254Sgavinm #define AO_AED_F_L2SETWAY 0x08 /* 3:0 = way, 15/14/13/12:6 = set */ 813164Sgavinm 823164Sgavinm #define AO_AED_FLAGS_ADDRTYPE (AO_AED_F_LINEAR | AO_AED_F_PHYSICAL | \ 833164Sgavinm AO_AED_F_PAGEALIGNED | AO_AED_F_L2SETWAY) 841414Scindi 855254Sgavinm /* 865254Sgavinm * The AO_AED_ET_* flags group individual error dispositions into 875254Sgavinm * error types. This is used to nominate additional telemetry beyond the 885254Sgavinm * architectural bank registers to capture for this error type. 895254Sgavinm */ 905254Sgavinm #define AO_AED_ET_MEMECC 0x0001 /* Main memory ECC error */ 915254Sgavinm 921414Scindi typedef struct ao_error_disp { 931414Scindi const char *aed_class; /* ereport class for use if match */ 941414Scindi uint64_t aed_ereport_members; /* ereport contents flags if match */ 951414Scindi uint64_t aed_stat_mask; /* status msr bits for match */ 961414Scindi uint64_t aed_stat_mask_res; /* status mask result for match */ 971414Scindi uint16_t aed_stat_code; /* status code for match */ 981414Scindi uint8_t aed_stat_extcode; /* extended status code for match */ 991414Scindi uint8_t aed_stat_pp_bits:4; /* AO_MCA_PP_BIT_* for pp matching */ 1001414Scindi uint8_t aed_stat_ii_bits:4; /* AO_MCA_II_BIT_* for ii matching */ 1011414Scindi uint16_t aed_stat_r4_bits; /* AO_MCA_R4_BIT_* for r4 matching */ 1023164Sgavinm uint8_t aed_addrvalid_hi; /* most significant valid addr bit */ 1033164Sgavinm uint8_t aed_addrvalid_lo; /* least significant valid addr bit */ 1041414Scindi uint8_t aed_panic_when; /* extra conditions for panic */ 1055254Sgavinm uint16_t aed_flags; /* AO_AED_F_* */ 1065254Sgavinm uint16_t aed_errtype; /* AO_AED_ET_* */ 1071414Scindi } ao_error_disp_t; 1081414Scindi 1091414Scindi /* 1105254Sgavinm * We store non-architectutal config as inherited from the BIOS to assist 1115254Sgavinm * in troubleshooting. 1121414Scindi */ 1135254Sgavinm struct ao_bios_cfg { 1145254Sgavinm uint64_t *bcfg_bank_mask; 1155254Sgavinm }; 1161414Scindi 1171414Scindi /* 1181414Scindi * The master data structure used to hold MCA-related state. 1191414Scindi */ 1205254Sgavinm typedef struct ao_ms_mca { 1215254Sgavinm struct ao_bios_cfg ao_mca_bios_cfg; 1221414Scindi kmutex_t ao_mca_poll_lock; /* keep pollers from colliding */ 1231414Scindi uint_t ao_mca_flags; /* AO_MCA_F_* */ 1245254Sgavinm } ao_ms_mca_t; 1251414Scindi 1261414Scindi /* 1275254Sgavinm * Per-chip shared state 1282869Sgavinm */ 1292869Sgavinm struct ao_chipshared { 1305254Sgavinm uint32_t aos_chiprev; 1312869Sgavinm volatile ulong_t aos_cfgonce; /* Config performed once per chip */ 1325254Sgavinm hrtime_t aos_nb_poll_timestamp; 1335254Sgavinm cmi_hdl_t aos_nb_poll_owner; 1345254Sgavinm uint64_t aos_bcfg_nb_misc; /* BIOS value of MC4_MISC MSR */ 1352869Sgavinm uint32_t aos_bcfg_nb_cfg; /* BIOS value of NB MCA Config */ 1362869Sgavinm uint32_t aos_bcfg_nb_sparectl; /* BIOS value of Online Spare Control */ 1373766Sgavinm uint32_t aos_bcfg_dcfg_lo; /* BIOS value of DRAM Config Low */ 1383766Sgavinm uint32_t aos_bcfg_dcfg_hi; /* BIOS value of DRAM Config High */ 1395254Sgavinm uint32_t aos_bcfg_scrubctl; /* BIOS value of scrub control */ 1402869Sgavinm }; 1412869Sgavinm 1425254Sgavinm /* Bit numbers for once-per-chip operations policed by cms_once */ 1432869Sgavinm enum ao_cfgonce_bitnum { 1443766Sgavinm AO_CFGONCE_NBMCA, 1455254Sgavinm AO_CFGONCE_NBCFG, 1463766Sgavinm AO_CFGONCE_DRAMCFG 1472869Sgavinm }; 1482869Sgavinm 1492869Sgavinm /* 1505254Sgavinm * Per-CPU model-specific state 1511414Scindi */ 1525254Sgavinm struct ao_ms_data { 1535254Sgavinm cmi_hdl_t ao_ms_hdl; 1545254Sgavinm ao_ms_mca_t ao_ms_mca; 1555254Sgavinm struct ao_chipshared *ao_ms_shared; 1565254Sgavinm uint64_t ao_ms_hwcr_val; 1571414Scindi }; 1581414Scindi 1591414Scindi #ifdef _KERNEL 1601414Scindi 1611414Scindi struct regs; 1621414Scindi 1635254Sgavinm /* 1645254Sgavinm * Our cms_ops operations and function prototypes for all non-NULL members. 1655254Sgavinm */ 1665254Sgavinm extern const cms_ops_t _cms_ops; 1671414Scindi 1685254Sgavinm extern int ao_ms_init(cmi_hdl_t, void **); 1695254Sgavinm extern void ao_ms_post_startup(cmi_hdl_t); 1705254Sgavinm extern void ao_ms_post_mpstartup(cmi_hdl_t); 1715254Sgavinm extern uint64_t ao_ms_mcgctl_val(cmi_hdl_t, int, uint64_t); 1725254Sgavinm extern boolean_t ao_ms_bankctl_skipinit(cmi_hdl_t, int); 1735254Sgavinm extern uint64_t ao_ms_bankctl_val(cmi_hdl_t, int, uint64_t); 1745254Sgavinm extern void ao_ms_mca_init(cmi_hdl_t, int); 1755254Sgavinm extern uint64_t ao_ms_poll_ownermask(cmi_hdl_t, hrtime_t); 1765254Sgavinm extern uint32_t ao_ms_error_action(cmi_hdl_t, int, int, uint64_t, 1775254Sgavinm uint64_t, uint64_t, void *); 1785254Sgavinm extern cms_cookie_t ao_ms_disp_match(cmi_hdl_t, int, uint64_t, uint64_t, 1795254Sgavinm uint64_t, void *); 1805254Sgavinm extern void ao_ms_ereport_class(cmi_hdl_t, cms_cookie_t, const char **, 1815254Sgavinm const char **); 1825254Sgavinm extern boolean_t ao_ms_ereport_includestack(cmi_hdl_t, cms_cookie_t); 1835254Sgavinm extern void ao_ms_ereport_add_logout(cmi_hdl_t, nvlist_t *, 1845254Sgavinm nv_alloc_t *, int, uint64_t, uint64_t, uint64_t, void *, void *); 1855254Sgavinm extern cms_errno_t ao_ms_msrinject(cmi_hdl_t, uint_t, uint64_t); 1861414Scindi 1875254Sgavinm /* 1885254Sgavinm * Local functions 1895254Sgavinm */ 190*10947SSrihari.Venkatesan@Sun.COM extern void ao_procnode_scrubber_enable(cmi_hdl_t, ao_ms_data_t *); 1911414Scindi extern void ao_pcicfg_write(uint_t, uint_t, uint_t, uint32_t); 1921414Scindi extern uint32_t ao_pcicfg_read(uint_t, uint_t, uint_t); 1935254Sgavinm extern void ao_bankstatus_prewrite(cmi_hdl_t, ao_ms_data_t *); 1945254Sgavinm extern void ao_bankstatus_postwrite(cmi_hdl_t, ao_ms_data_t *); 1952869Sgavinm 1961414Scindi #endif /* _KERNEL */ 1971414Scindi 1981414Scindi #ifdef __cplusplus 1991414Scindi } 2001414Scindi #endif 2011414Scindi 2021414Scindi #endif /* _AO_H */ 203