11ae08745Sheppo /* 21ae08745Sheppo * CDDL HEADER START 31ae08745Sheppo * 41ae08745Sheppo * The contents of this file are subject to the terms of the 51ae08745Sheppo * Common Development and Distribution License (the "License"). 61ae08745Sheppo * You may not use this file except in compliance with the License. 71ae08745Sheppo * 81ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 101ae08745Sheppo * See the License for the specific language governing permissions 111ae08745Sheppo * and limitations under the License. 121ae08745Sheppo * 131ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 141ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 161ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 171ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 181ae08745Sheppo * 191ae08745Sheppo * CDDL HEADER END 201ae08745Sheppo */ 211ae08745Sheppo 221ae08745Sheppo /* 23*79afa7fbSSean McEnroe * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 241ae08745Sheppo * Use is subject to license terms. 251ae08745Sheppo */ 261ae08745Sheppo 271ae08745Sheppo /* 281ae08745Sheppo * sun4v DR Utility functions 291ae08745Sheppo */ 301ae08745Sheppo 311ae08745Sheppo #include <sys/types.h> 321ae08745Sheppo #include <sys/cmn_err.h> 331ae08745Sheppo #include <sys/sunddi.h> 341ae08745Sheppo #include <sys/note.h> 351ae08745Sheppo #include <sys/sysevent.h> 361ae08745Sheppo #include <sys/sysevent/dr.h> 371ae08745Sheppo #include <sys/sysevent/eventdefs.h> 381ae08745Sheppo #include <sys/ldoms.h> 39*79afa7fbSSean McEnroe #include <sys/memlist.h> 401ae08745Sheppo #include <sys/dr_util.h> 411ae08745Sheppo 429853d9e8SJason Beloro extern int ppvm_enable; 439853d9e8SJason Beloro 441ae08745Sheppo boolean_t 451ae08745Sheppo dr_is_disabled(dr_type_t type) 461ae08745Sheppo { 471ae08745Sheppo /* 481ae08745Sheppo * The type argument is currently unused. However, it 491ae08745Sheppo * keeps the interface flexible enough to allows for 501ae08745Sheppo * only disabling certain types of DR. 511ae08745Sheppo */ 521ae08745Sheppo _NOTE(ARGUNUSED(type)) 531ae08745Sheppo 541ae08745Sheppo /* 551ae08745Sheppo * DR requires that the kernel is using its own CIF 561ae08745Sheppo * handler. If that is not the case, either because 571ae08745Sheppo * domaining has been explicitly disabled, or because 581ae08745Sheppo * the firmware does not support it, the system must 591ae08745Sheppo * remain static and DR must be disabled. 601ae08745Sheppo */ 6122e19ac1Sjm22469 if (!domaining_enabled()) { 621ae08745Sheppo cmn_err(CE_NOTE, "!Kernel CIF handler is not enabled, DR " 631ae08745Sheppo "is not available\n"); 641ae08745Sheppo return (B_TRUE); 651ae08745Sheppo } 661ae08745Sheppo 679853d9e8SJason Beloro if (type == DR_TYPE_MEM && ppvm_enable == 0) { 689853d9e8SJason Beloro cmn_err(CE_NOTE, "!Memory DR is disabled\n"); 699853d9e8SJason Beloro return (B_TRUE); 709853d9e8SJason Beloro } 719853d9e8SJason Beloro 721ae08745Sheppo return (B_FALSE); 731ae08745Sheppo } 741ae08745Sheppo 751ae08745Sheppo /* 761ae08745Sheppo * Generate a DR sysevent based on the type of resource and 771ae08745Sheppo * sysevent hint specified. The hint indicates whether the 781ae08745Sheppo * resource was added or removed. 791ae08745Sheppo */ 801ae08745Sheppo void 811ae08745Sheppo dr_generate_event(dr_type_t type, int se_hint) 821ae08745Sheppo { 831ae08745Sheppo int rv; 841ae08745Sheppo sysevent_id_t eid; 851ae08745Sheppo sysevent_t *ev = NULL; 861ae08745Sheppo sysevent_attr_list_t *evnt_attr_list = NULL; 871ae08745Sheppo sysevent_value_t evnt_val; 881ae08745Sheppo static char pubname[] = SUNW_KERN_PUB"dr"; 891ae08745Sheppo 901ae08745Sheppo DR_DBG_ALL("generate_event: type=%s, hint=%s\n", DR_TYPE2STR(type), 911ae08745Sheppo SE_HINT2STR(se_hint)); 921ae08745Sheppo 931ae08745Sheppo /* 941ae08745Sheppo * Add the attachment point attribute 951ae08745Sheppo */ 961ae08745Sheppo ev = sysevent_alloc(EC_DR, ESC_DR_AP_STATE_CHANGE, pubname, KM_SLEEP); 971ae08745Sheppo evnt_val.value_type = SE_DATA_TYPE_STRING; 981ae08745Sheppo evnt_val.value.sv_string = DR_TYPE2STR(type); 991ae08745Sheppo 1001ae08745Sheppo rv = sysevent_add_attr(&evnt_attr_list, DR_AP_ID, &evnt_val, KM_SLEEP); 1011ae08745Sheppo if (rv != 0) { 1021ae08745Sheppo DR_DBG_ALL("generate_event: failed to add attr '%s' for " 1031ae08745Sheppo "'%s' event\n", DR_AP_ID, EC_DR); 1041ae08745Sheppo goto done; 1051ae08745Sheppo } 1061ae08745Sheppo 1071ae08745Sheppo /* 1081ae08745Sheppo * Add the DR hint attribute 1091ae08745Sheppo */ 1101ae08745Sheppo evnt_val.value_type = SE_DATA_TYPE_STRING; 1111ae08745Sheppo evnt_val.value.sv_string = SE_HINT2STR(se_hint); 1121ae08745Sheppo 1131ae08745Sheppo rv = sysevent_add_attr(&evnt_attr_list, DR_HINT, &evnt_val, KM_SLEEP); 1141ae08745Sheppo if (rv != 0) { 1151ae08745Sheppo DR_DBG_ALL("generate_event: failed to add attr '%s' for " 1161ae08745Sheppo "'%s' event\n", DR_HINT, EC_DR); 1171ae08745Sheppo sysevent_free_attr(evnt_attr_list); 1181ae08745Sheppo goto done; 1191ae08745Sheppo } 1201ae08745Sheppo 1211ae08745Sheppo /* 1221ae08745Sheppo * Attach the attribute list to the event 1231ae08745Sheppo */ 1241ae08745Sheppo rv = sysevent_attach_attributes(ev, evnt_attr_list); 1251ae08745Sheppo if (rv != 0) { 1261ae08745Sheppo DR_DBG_ALL("generate_event: failed to add attr list for " 1271ae08745Sheppo "'%s' event\n", EC_DR); 1281ae08745Sheppo sysevent_free_attr(evnt_attr_list); 1291ae08745Sheppo goto done; 1301ae08745Sheppo } 1311ae08745Sheppo 1321ae08745Sheppo /* 1331ae08745Sheppo * Log the event 1341ae08745Sheppo */ 1351ae08745Sheppo rv = log_sysevent(ev, KM_NOSLEEP, &eid); 1361ae08745Sheppo if (rv != 0) { 1371ae08745Sheppo DR_DBG_ALL("generate_event: failed to log event (%d)\n", rv); 1381ae08745Sheppo } 1391ae08745Sheppo 1401ae08745Sheppo done: 1411ae08745Sheppo if (ev != NULL) 1421ae08745Sheppo sysevent_free(ev); 1431ae08745Sheppo } 1441ae08745Sheppo 145*79afa7fbSSean McEnroe struct memlist * 146*79afa7fbSSean McEnroe dr_memlist_dup(struct memlist *mlist) 147*79afa7fbSSean McEnroe { 148*79afa7fbSSean McEnroe struct memlist *hl = NULL, *tl, **mlp; 149*79afa7fbSSean McEnroe 150*79afa7fbSSean McEnroe if (mlist == NULL) 151*79afa7fbSSean McEnroe return (NULL); 152*79afa7fbSSean McEnroe 153*79afa7fbSSean McEnroe mlp = &hl; 154*79afa7fbSSean McEnroe tl = *mlp; 155*79afa7fbSSean McEnroe for (; mlist; mlist = mlist->ml_next) { 156*79afa7fbSSean McEnroe *mlp = (struct memlist *)kmem_zalloc(sizeof (struct memlist),\ 157*79afa7fbSSean McEnroe KM_SLEEP); 158*79afa7fbSSean McEnroe (*mlp)->ml_address = mlist->ml_address; 159*79afa7fbSSean McEnroe (*mlp)->ml_size = mlist->ml_size; 160*79afa7fbSSean McEnroe (*mlp)->ml_prev = tl; 161*79afa7fbSSean McEnroe tl = *mlp; 162*79afa7fbSSean McEnroe mlp = &((*mlp)->ml_next); 163*79afa7fbSSean McEnroe } 164*79afa7fbSSean McEnroe *mlp = NULL; 165*79afa7fbSSean McEnroe 166*79afa7fbSSean McEnroe return (hl); 167*79afa7fbSSean McEnroe } 168*79afa7fbSSean McEnroe 169*79afa7fbSSean McEnroe /* 170*79afa7fbSSean McEnroe * Free a memlist and its elements 171*79afa7fbSSean McEnroe */ 172*79afa7fbSSean McEnroe void 173*79afa7fbSSean McEnroe dr_memlist_delete(struct memlist *mlist) 174*79afa7fbSSean McEnroe { 175*79afa7fbSSean McEnroe register struct memlist *ml; 176*79afa7fbSSean McEnroe 177*79afa7fbSSean McEnroe for (ml = mlist; ml; ml = mlist) { 178*79afa7fbSSean McEnroe mlist = ml->ml_next; 179*79afa7fbSSean McEnroe kmem_free((void *)ml, sizeof (struct memlist)); 180*79afa7fbSSean McEnroe } 181*79afa7fbSSean McEnroe } 182*79afa7fbSSean McEnroe 1831ae08745Sheppo /* 1841ae08745Sheppo * Debugging Features 1851ae08745Sheppo */ 1861ae08745Sheppo #ifdef DEBUG 1871ae08745Sheppo 1881ae08745Sheppo uint_t dr_debug = 0x0; 1891ae08745Sheppo 1901ae08745Sheppo #define BYTESPERLINE 8 1911ae08745Sheppo #define LINEWIDTH ((BYTESPERLINE * 3) + (BYTESPERLINE + 2) + 1) 1921ae08745Sheppo #define ASCIIOFFSET ((BYTESPERLINE * 3) + 2) 1931ae08745Sheppo #define ISPRINT(c) ((c >= ' ') && (c <= '~')) 1941ae08745Sheppo 1951ae08745Sheppo /* 1961ae08745Sheppo * Output a buffer formatted with a set number of bytes on 1971ae08745Sheppo * each line. Append each line with the ASCII equivalent of 1981ae08745Sheppo * each byte if it falls within the printable ASCII range, 1991ae08745Sheppo * and '.' otherwise. 2001ae08745Sheppo */ 2011ae08745Sheppo void 2021ae08745Sheppo dr_dbg_dump_msg(void *buf, size_t len) 2031ae08745Sheppo { 2041ae08745Sheppo int i, j; 2051ae08745Sheppo char *msg = buf; 2061ae08745Sheppo char *curr; 2071ae08745Sheppo char *aoff; 2081ae08745Sheppo char line[LINEWIDTH]; 2091ae08745Sheppo 2101ae08745Sheppo /* abort if not debugging transport */ 2111ae08745Sheppo if (!(dr_debug & DR_DBG_FLAG_TRANS)) { 2121ae08745Sheppo return; 2131ae08745Sheppo } 2141ae08745Sheppo 2151ae08745Sheppo /* walk the buffer one line at a time */ 2161ae08745Sheppo for (i = 0; i < len; i += BYTESPERLINE) { 2171ae08745Sheppo 2181ae08745Sheppo bzero(line, LINEWIDTH); 2191ae08745Sheppo 2201ae08745Sheppo curr = line; 2211ae08745Sheppo aoff = line + ASCIIOFFSET; 2221ae08745Sheppo 2231ae08745Sheppo /* 2241ae08745Sheppo * Walk the bytes in the current line, storing 2251ae08745Sheppo * the hex value for the byte as well as the 2261ae08745Sheppo * ASCII representation in a temporary buffer. 2271ae08745Sheppo * All ASCII values are placed at the end of 2281ae08745Sheppo * the line. 2291ae08745Sheppo */ 2301ae08745Sheppo for (j = 0; (j < BYTESPERLINE) && ((i + j) < len); j++) { 2311ae08745Sheppo (void) sprintf(curr, " %02x", msg[i + j]); 2321ae08745Sheppo *aoff = (ISPRINT(msg[i + j])) ? msg[i + j] : '.'; 2331ae08745Sheppo curr += 3; 2341ae08745Sheppo aoff++; 2351ae08745Sheppo } 2361ae08745Sheppo 2371ae08745Sheppo /* 2381ae08745Sheppo * Fill in to the start of the ASCII translation 2391ae08745Sheppo * with spaces. This will only be necessary if 2401ae08745Sheppo * this is the last line and there are not enough 2411ae08745Sheppo * bytes to fill the whole line. 2421ae08745Sheppo */ 2431ae08745Sheppo while (curr != (line + ASCIIOFFSET)) 2441ae08745Sheppo *curr++ = ' '; 2451ae08745Sheppo 2461ae08745Sheppo DR_DBG_TRANS("%s\n", line); 2471ae08745Sheppo } 2481ae08745Sheppo } 2491ae08745Sheppo #endif /* DEBUG */ 250