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*12437SAdrian.Frost@Sun.COM * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 241414Scindi */ 251414Scindi 261414Scindi #ifndef _AO_H 271414Scindi #define _AO_H 281414Scindi 291414Scindi #include <sys/types.h> 301414Scindi #include <sys/mc.h> 311414Scindi #include <sys/mca_amd.h> 323164Sgavinm #include <sys/mc_amd.h> 335254Sgavinm #include <sys/cpu_module_ms_impl.h> 341414Scindi #include <sys/nvpair.h> 351414Scindi #include <sys/cyclic.h> 361414Scindi #include <sys/errorq.h> 371414Scindi #include <sys/kobj.h> 381414Scindi #include <sys/fm/util.h> 391414Scindi 401414Scindi #ifdef __cplusplus 411414Scindi extern "C" { 421414Scindi #endif 431414Scindi 445254Sgavinm #define AO_MAX_CHIPS 8 455254Sgavinm 461414Scindi #define AO_MCA_MAX_ERRORS 10 471414Scindi 485254Sgavinm typedef struct ao_ms_data ao_ms_data_t; 491414Scindi 501414Scindi /* 511414Scindi * Rather than using torturous conditionals, we match errors using a table of 521414Scindi * ao_error_disp_t's. The members in the ao_error_disp_t are matched against 531414Scindi * the value of MCi_STATUS, with a successful match indicating that the given 541414Scindi * error occurred. 551414Scindi * 561414Scindi * While aed_stat_code will match most of the status code bits, a few of the 571414Scindi * status code fields are either/or, and are treated separately so as to 581414Scindi * minimize the number of ao_error_disp_t structures that must be created. 591414Scindi * For example, the dc.tag_par error can have r4 values drd or dwr. Rather 601414Scindi * than creating two ao_error_disp_t's, we use the separate aed_stat_r4_bits 611414Scindi * field to indicate both AO_MCA_R4_BIT_DRD and AO_MCA_R4_BIT_DWD. As the 621414Scindi * matching r4 values are drawn from aed_stat_r4_bits, we don't use the r4 631414Scindi * bits in aed_stat_code for matching. Similar reasoning lies behind the 641414Scindi * creation of the pp and ii fields. 651414Scindi */ 661538Sgavinm #define AO_AED_PANIC_NEVER 0x00 671538Sgavinm #define AO_AED_PANIC_IFMCE 0x01 681538Sgavinm #define AO_AED_PANIC_ALWAYS 0x80 691414Scindi 705254Sgavinm /* 715254Sgavinm * The AO_AED_F_* flags tell us how to interpret aspects of the error 725254Sgavinm * telemetry, such as which bits of the captured address are valid for 735254Sgavinm * this error. 745254Sgavinm */ 755254Sgavinm /* MCi_ADDR ... */ 765254Sgavinm #define AO_AED_F_LINEAR 0x01 /* is a linear address */ 775254Sgavinm #define AO_AED_F_PHYSICAL 0x02 /* is a physical address */ 785254Sgavinm #define AO_AED_F_PAGEALIGNED 0x04 /* aligns to page size */ 795254Sgavinm #define AO_AED_F_L2SETWAY 0x08 /* 3:0 = way, 15/14/13/12:6 = set */ 803164Sgavinm 813164Sgavinm #define AO_AED_FLAGS_ADDRTYPE (AO_AED_F_LINEAR | AO_AED_F_PHYSICAL | \ 823164Sgavinm AO_AED_F_PAGEALIGNED | AO_AED_F_L2SETWAY) 831414Scindi 845254Sgavinm /* 855254Sgavinm * The AO_AED_ET_* flags group individual error dispositions into 865254Sgavinm * error types. This is used to nominate additional telemetry beyond the 875254Sgavinm * architectural bank registers to capture for this error type. 885254Sgavinm */ 895254Sgavinm #define AO_AED_ET_MEMECC 0x0001 /* Main memory ECC error */ 905254Sgavinm 911414Scindi typedef struct ao_error_disp { 921414Scindi const char *aed_class; /* ereport class for use if match */ 931414Scindi uint64_t aed_ereport_members; /* ereport contents flags if match */ 941414Scindi uint64_t aed_stat_mask; /* status msr bits for match */ 951414Scindi uint64_t aed_stat_mask_res; /* status mask result for match */ 961414Scindi uint16_t aed_stat_code; /* status code for match */ 971414Scindi uint8_t aed_stat_extcode; /* extended status code for match */ 981414Scindi uint8_t aed_stat_pp_bits:4; /* AO_MCA_PP_BIT_* for pp matching */ 991414Scindi uint8_t aed_stat_ii_bits:4; /* AO_MCA_II_BIT_* for ii matching */ 1001414Scindi uint16_t aed_stat_r4_bits; /* AO_MCA_R4_BIT_* for r4 matching */ 1013164Sgavinm uint8_t aed_addrvalid_hi; /* most significant valid addr bit */ 1023164Sgavinm uint8_t aed_addrvalid_lo; /* least significant valid addr bit */ 1031414Scindi uint8_t aed_panic_when; /* extra conditions for panic */ 1045254Sgavinm uint16_t aed_flags; /* AO_AED_F_* */ 1055254Sgavinm uint16_t aed_errtype; /* AO_AED_ET_* */ 1061414Scindi } ao_error_disp_t; 1071414Scindi 1081414Scindi /* 1095254Sgavinm * We store non-architectutal config as inherited from the BIOS to assist 1105254Sgavinm * in troubleshooting. 1111414Scindi */ 1125254Sgavinm struct ao_bios_cfg { 1135254Sgavinm uint64_t *bcfg_bank_mask; 1145254Sgavinm }; 1151414Scindi 1161414Scindi /* 1171414Scindi * The master data structure used to hold MCA-related state. 1181414Scindi */ 1195254Sgavinm typedef struct ao_ms_mca { 1205254Sgavinm struct ao_bios_cfg ao_mca_bios_cfg; 1211414Scindi kmutex_t ao_mca_poll_lock; /* keep pollers from colliding */ 1221414Scindi uint_t ao_mca_flags; /* AO_MCA_F_* */ 1235254Sgavinm } ao_ms_mca_t; 1241414Scindi 1251414Scindi /* 1265254Sgavinm * Per-chip shared state 1272869Sgavinm */ 1282869Sgavinm struct ao_chipshared { 1295254Sgavinm uint32_t aos_chiprev; 1302869Sgavinm volatile ulong_t aos_cfgonce; /* Config performed once per chip */ 1315254Sgavinm hrtime_t aos_nb_poll_timestamp; 1325254Sgavinm cmi_hdl_t aos_nb_poll_owner; 1335254Sgavinm uint64_t aos_bcfg_nb_misc; /* BIOS value of MC4_MISC MSR */ 1342869Sgavinm uint32_t aos_bcfg_nb_cfg; /* BIOS value of NB MCA Config */ 1352869Sgavinm uint32_t aos_bcfg_nb_sparectl; /* BIOS value of Online Spare Control */ 1363766Sgavinm uint32_t aos_bcfg_dcfg_lo; /* BIOS value of DRAM Config Low */ 1373766Sgavinm uint32_t aos_bcfg_dcfg_hi; /* BIOS value of DRAM Config High */ 1385254Sgavinm uint32_t aos_bcfg_scrubctl; /* BIOS value of scrub control */ 1392869Sgavinm }; 1402869Sgavinm 1415254Sgavinm /* Bit numbers for once-per-chip operations policed by cms_once */ 1422869Sgavinm enum ao_cfgonce_bitnum { 1433766Sgavinm AO_CFGONCE_NBMCA, 1445254Sgavinm AO_CFGONCE_NBCFG, 1453766Sgavinm AO_CFGONCE_DRAMCFG 1462869Sgavinm }; 1472869Sgavinm 1482869Sgavinm /* 1495254Sgavinm * Per-CPU model-specific state 1501414Scindi */ 1515254Sgavinm struct ao_ms_data { 1525254Sgavinm cmi_hdl_t ao_ms_hdl; 1535254Sgavinm ao_ms_mca_t ao_ms_mca; 1545254Sgavinm struct ao_chipshared *ao_ms_shared; 1555254Sgavinm uint64_t ao_ms_hwcr_val; 1561414Scindi }; 1571414Scindi 1581414Scindi #ifdef _KERNEL 1591414Scindi 1601414Scindi struct regs; 1611414Scindi 1625254Sgavinm /* 1635254Sgavinm * Our cms_ops operations and function prototypes for all non-NULL members. 1645254Sgavinm */ 1655254Sgavinm extern const cms_ops_t _cms_ops; 1661414Scindi 1675254Sgavinm extern int ao_ms_init(cmi_hdl_t, void **); 1685254Sgavinm extern void ao_ms_post_startup(cmi_hdl_t); 1695254Sgavinm extern void ao_ms_post_mpstartup(cmi_hdl_t); 1705254Sgavinm extern uint64_t ao_ms_mcgctl_val(cmi_hdl_t, int, uint64_t); 1715254Sgavinm extern boolean_t ao_ms_bankctl_skipinit(cmi_hdl_t, int); 1725254Sgavinm extern uint64_t ao_ms_bankctl_val(cmi_hdl_t, int, uint64_t); 1735254Sgavinm extern void ao_ms_mca_init(cmi_hdl_t, int); 1745254Sgavinm extern uint64_t ao_ms_poll_ownermask(cmi_hdl_t, hrtime_t); 1755254Sgavinm extern uint32_t ao_ms_error_action(cmi_hdl_t, int, int, uint64_t, 1765254Sgavinm uint64_t, uint64_t, void *); 177*12437SAdrian.Frost@Sun.COM extern cms_cookie_t ao_ms_disp_match(cmi_hdl_t, int, int, uint64_t, uint64_t, 1785254Sgavinm uint64_t, void *); 1795254Sgavinm extern void ao_ms_ereport_class(cmi_hdl_t, cms_cookie_t, const char **, 1805254Sgavinm const char **); 1815254Sgavinm extern boolean_t ao_ms_ereport_includestack(cmi_hdl_t, cms_cookie_t); 1825254Sgavinm extern void ao_ms_ereport_add_logout(cmi_hdl_t, nvlist_t *, 1835254Sgavinm nv_alloc_t *, int, uint64_t, uint64_t, uint64_t, void *, void *); 1845254Sgavinm extern cms_errno_t ao_ms_msrinject(cmi_hdl_t, uint_t, uint64_t); 1851414Scindi 1865254Sgavinm /* 1875254Sgavinm * Local functions 1885254Sgavinm */ 18910947SSrihari.Venkatesan@Sun.COM extern void ao_procnode_scrubber_enable(cmi_hdl_t, ao_ms_data_t *); 1901414Scindi extern void ao_pcicfg_write(uint_t, uint_t, uint_t, uint32_t); 1911414Scindi extern uint32_t ao_pcicfg_read(uint_t, uint_t, uint_t); 1925254Sgavinm extern void ao_bankstatus_prewrite(cmi_hdl_t, ao_ms_data_t *); 1935254Sgavinm extern void ao_bankstatus_postwrite(cmi_hdl_t, ao_ms_data_t *); 1942869Sgavinm 1951414Scindi #endif /* _KERNEL */ 1961414Scindi 1971414Scindi #ifdef __cplusplus 1981414Scindi } 1991414Scindi #endif 2001414Scindi 2011414Scindi #endif /* _AO_H */ 202