1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * sun4v DR Utility functions 31 */ 32 33 #include <sys/types.h> 34 #include <sys/cmn_err.h> 35 #include <sys/sunddi.h> 36 #include <sys/note.h> 37 #include <sys/sysevent.h> 38 #include <sys/sysevent/dr.h> 39 #include <sys/sysevent/eventdefs.h> 40 #include <sys/ldoms.h> 41 42 #include <sys/dr_util.h> 43 44 boolean_t 45 dr_is_disabled(dr_type_t type) 46 { 47 /* 48 * The type argument is currently unused. However, it 49 * keeps the interface flexible enough to allows for 50 * only disabling certain types of DR. 51 */ 52 _NOTE(ARGUNUSED(type)) 53 54 /* 55 * DR requires that the kernel is using its own CIF 56 * handler. If that is not the case, either because 57 * domaining has been explicitly disabled, or because 58 * the firmware does not support it, the system must 59 * remain static and DR must be disabled. 60 */ 61 if (!domaining_enabled()) { 62 cmn_err(CE_NOTE, "!Kernel CIF handler is not enabled, DR " 63 "is not available\n"); 64 return (B_TRUE); 65 } 66 67 return (B_FALSE); 68 } 69 70 /* 71 * Generate a DR sysevent based on the type of resource and 72 * sysevent hint specified. The hint indicates whether the 73 * resource was added or removed. 74 */ 75 void 76 dr_generate_event(dr_type_t type, int se_hint) 77 { 78 int rv; 79 sysevent_id_t eid; 80 sysevent_t *ev = NULL; 81 sysevent_attr_list_t *evnt_attr_list = NULL; 82 sysevent_value_t evnt_val; 83 static char pubname[] = SUNW_KERN_PUB"dr"; 84 85 DR_DBG_ALL("generate_event: type=%s, hint=%s\n", DR_TYPE2STR(type), 86 SE_HINT2STR(se_hint)); 87 88 /* 89 * Add the attachment point attribute 90 */ 91 ev = sysevent_alloc(EC_DR, ESC_DR_AP_STATE_CHANGE, pubname, KM_SLEEP); 92 evnt_val.value_type = SE_DATA_TYPE_STRING; 93 evnt_val.value.sv_string = DR_TYPE2STR(type); 94 95 rv = sysevent_add_attr(&evnt_attr_list, DR_AP_ID, &evnt_val, KM_SLEEP); 96 if (rv != 0) { 97 DR_DBG_ALL("generate_event: failed to add attr '%s' for " 98 "'%s' event\n", DR_AP_ID, EC_DR); 99 goto done; 100 } 101 102 /* 103 * Add the DR hint attribute 104 */ 105 evnt_val.value_type = SE_DATA_TYPE_STRING; 106 evnt_val.value.sv_string = SE_HINT2STR(se_hint); 107 108 rv = sysevent_add_attr(&evnt_attr_list, DR_HINT, &evnt_val, KM_SLEEP); 109 if (rv != 0) { 110 DR_DBG_ALL("generate_event: failed to add attr '%s' for " 111 "'%s' event\n", DR_HINT, EC_DR); 112 sysevent_free_attr(evnt_attr_list); 113 goto done; 114 } 115 116 /* 117 * Attach the attribute list to the event 118 */ 119 rv = sysevent_attach_attributes(ev, evnt_attr_list); 120 if (rv != 0) { 121 DR_DBG_ALL("generate_event: failed to add attr list for " 122 "'%s' event\n", EC_DR); 123 sysevent_free_attr(evnt_attr_list); 124 goto done; 125 } 126 127 /* 128 * Log the event 129 */ 130 rv = log_sysevent(ev, KM_NOSLEEP, &eid); 131 if (rv != 0) { 132 DR_DBG_ALL("generate_event: failed to log event (%d)\n", rv); 133 } 134 135 done: 136 if (ev != NULL) 137 sysevent_free(ev); 138 } 139 140 /* 141 * Debugging Features 142 */ 143 #ifdef DEBUG 144 145 uint_t dr_debug = 0x0; 146 147 #define BYTESPERLINE 8 148 #define LINEWIDTH ((BYTESPERLINE * 3) + (BYTESPERLINE + 2) + 1) 149 #define ASCIIOFFSET ((BYTESPERLINE * 3) + 2) 150 #define ISPRINT(c) ((c >= ' ') && (c <= '~')) 151 152 /* 153 * Output a buffer formatted with a set number of bytes on 154 * each line. Append each line with the ASCII equivalent of 155 * each byte if it falls within the printable ASCII range, 156 * and '.' otherwise. 157 */ 158 void 159 dr_dbg_dump_msg(void *buf, size_t len) 160 { 161 int i, j; 162 char *msg = buf; 163 char *curr; 164 char *aoff; 165 char line[LINEWIDTH]; 166 167 /* abort if not debugging transport */ 168 if (!(dr_debug & DR_DBG_FLAG_TRANS)) { 169 return; 170 } 171 172 /* walk the buffer one line at a time */ 173 for (i = 0; i < len; i += BYTESPERLINE) { 174 175 bzero(line, LINEWIDTH); 176 177 curr = line; 178 aoff = line + ASCIIOFFSET; 179 180 /* 181 * Walk the bytes in the current line, storing 182 * the hex value for the byte as well as the 183 * ASCII representation in a temporary buffer. 184 * All ASCII values are placed at the end of 185 * the line. 186 */ 187 for (j = 0; (j < BYTESPERLINE) && ((i + j) < len); j++) { 188 (void) sprintf(curr, " %02x", msg[i + j]); 189 *aoff = (ISPRINT(msg[i + j])) ? msg[i + j] : '.'; 190 curr += 3; 191 aoff++; 192 } 193 194 /* 195 * Fill in to the start of the ASCII translation 196 * with spaces. This will only be necessary if 197 * this is the last line and there are not enough 198 * bytes to fill the whole line. 199 */ 200 while (curr != (line + ASCIIOFFSET)) 201 *curr++ = ' '; 202 203 DR_DBG_TRANS("%s\n", line); 204 } 205 } 206 #endif /* DEBUG */ 207