Print this page
7713 fabric-xlate fmd(1m) module isn't 64-bit safe
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fm/modules/common/fabric-xlate/fx_subr.c
+++ new/usr/src/cmd/fm/modules/common/fabric-xlate/fx_subr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright 2016 Jason King
24 25 */
26 +
25 27 #include <strings.h>
26 28 #include <fm/topo_hc.h>
27 29 #include <sys/fm/util.h>
28 30 #include <libxml/xpath.h>
29 31 #include <libxml/parser.h>
30 32 #include <libxml/xpathInternals.h>
31 33 #include <libxml/tree.h>
34 +#include <sys/debug.h>
32 35
33 36 #include "fabric-xlate.h"
34 37
35 38 #define HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name)
36 39 #define GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name))
37 40 #define FREE_PROP(prop) xmlFree((xmlChar *)prop)
38 41
39 42 extern xmlXPathContextPtr fab_xpathCtx;
40 43
41 44 /* ARGSUSED */
42 45 int
43 46 fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt,
44 47 boolean_t isRC)
45 48 {
46 49 uint64_t *now;
47 50 uint64_t ena;
48 51 uint_t nelem;
49 52 nvlist_t *detector, *new_detector;
50 53 char rcpath[255];
51 54 int err = 0;
52 55
53 56 /* Grab the tod, ena and detector(FMRI) */
54 57 err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
55 58 err |= nvlist_lookup_uint64(nvl, "ena", &ena);
56 59 err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector);
57 60 if (err)
58 61 return (err);
59 62
60 63 /* Make a copy of the detector */
61 64 err = nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME);
62 65 if (err)
63 66 return (err);
64 67
65 68 /* Copy the tod and ena to erpt */
66 69 (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
67 70 (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
68 71
69 72 /*
70 73 * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used
71 74 * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl
72 75 * comments for more information.
73 76 */
74 77 if (isRC && fab_get_rcpath(hdl, nvl, rcpath)) {
75 78 /* Create the correct PCIe RC new_detector aka FMRI */
76 79 (void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH,
77 80 DATA_TYPE_STRING);
78 81 (void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH,
79 82 rcpath);
80 83 }
81 84
82 85 /* Copy the FMRI to erpt */
83 86 (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector);
84 87
85 88 nvlist_free(new_detector);
86 89 return (err);
87 90 }
88 91
89 92 void
90 93 fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class,
91 94 boolean_t isPrimary)
92 95 {
93 96 nvlist_t *nvl = data->nvl;
94 97 nvlist_t *erpt;
95 98 char *fmri = NULL;
96 99 uint32_t tgt_trans;
97 100 uint64_t tgt_addr;
98 101 uint16_t tgt_bdf;
99 102
100 103 if (isPrimary) {
101 104 tgt_trans = data->pcie_ue_tgt_trans;
102 105 tgt_addr = data->pcie_ue_tgt_addr;
103 106 tgt_bdf = data->pcie_ue_tgt_bdf;
104 107 } else {
105 108 tgt_trans = data->pcie_sue_tgt_trans;
106 109 tgt_addr = data->pcie_sue_tgt_addr;
107 110 tgt_bdf = data->pcie_sue_tgt_bdf;
108 111 }
109 112
110 113 fmd_hdl_debug(hdl, "Sending Target Ereport: "
111 114 "type 0x%x addr 0x%llx fltbdf 0x%x\n",
112 115 tgt_trans, tgt_addr, tgt_bdf);
113 116
114 117 if (!tgt_trans)
115 118 return;
116 119
117 120 if ((tgt_trans == PF_ADDR_PIO) && tgt_addr)
118 121 fmri = fab_find_addr(hdl, nvl, tgt_addr);
119 122 else if ((tgt_trans == PF_ADDR_CFG || (tgt_trans == PF_ADDR_DMA)) &&
120 123 tgt_bdf)
121 124 fmri = fab_find_bdf(hdl, nvl, tgt_bdf);
122 125
123 126 if (fmri) {
124 127 uint64_t *now;
125 128 uint64_t ena;
126 129 uint_t nelem;
127 130 nvlist_t *detector;
128 131 int err = 0;
129 132
130 133 /* Allocate space for new erpt */
131 134 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
132 135 goto done;
133 136
134 137 /* Generate the target ereport class */
135 138 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
136 139 PCI_ERROR_SUBCLASS, class);
137 140 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
138 141
139 142 /* Grab the tod, ena and detector(FMRI) */
140 143 err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
141 144 err |= nvlist_lookup_uint64(nvl, "ena", &ena);
142 145
143 146 /* Copy the tod and ena to erpt */
144 147 (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
145 148 (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
146 149
147 150 /* Create the correct FMRI */
148 151 if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) {
149 152 nvlist_free(erpt);
150 153 goto done;
151 154 }
152 155 (void) nvlist_add_uint8(detector, FM_VERSION,
153 156 FM_DEV_SCHEME_VERSION);
154 157 (void) nvlist_add_string(detector, FM_FMRI_SCHEME,
155 158 FM_FMRI_SCHEME_DEV);
156 159 (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri);
157 160 (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector);
158 161 nvlist_free(detector);
159 162
160 163 /* Add the address payload */
161 164 (void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr);
162 165
163 166 fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n",
164 167 fab_buf, tgt_addr);
165 168 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
166 169 if (fmd_xprt_error(hdl, fab_fmd_xprt))
167 170 goto done;
168 171 fmd_hdl_strfree(hdl, fmri);
169 172 } else {
170 173 fmd_hdl_debug(hdl,
171 174 "Cannot find Target FMRI addr:0x%llx bdf 0x%x\n",
172 175 tgt_addr, tgt_bdf);
173 176 }
174 177
175 178 return;
176 179 done:
↓ open down ↓ |
135 lines elided |
↑ open up ↑ |
177 180 if (fmri)
178 181 xmlFree(fmri);
179 182 fmd_hdl_debug(hdl, "Failed to send Target PCI ereport\n");
180 183 }
181 184
182 185 void
183 186 fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl)
184 187 {
185 188 fab_erpt_tbl_t *erpt_tbl, *entry;
186 189 nvlist_t *erpt;
190 + uintptr_t addr;
187 191 uint32_t reg;
188 192
189 193 erpt_tbl = tbl->erpt_tbl;
194 + addr = (uintptr_t)data + tbl->reg_offset;
195 +
190 196 if (tbl->reg_size == 16) {
191 - reg = (uint32_t)*((uint16_t *)
192 - ((uint32_t)data + tbl->reg_offset));
197 + reg = (uint32_t)*((uint16_t *)addr);
193 198 } else {
194 - reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset));
199 + ASSERT3U(tbl->reg_size, ==, 32);
200 + reg = *((uint32_t *)addr);
195 201 }
196 202
197 203 for (entry = erpt_tbl; entry->err_class; entry++) {
198 204 if (!(reg & entry->reg_bit))
199 205 continue;
200 206
201 207 if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
202 208 goto done;
203 209 if (tbl->fab_prep(hdl, data, erpt, entry) != 0) {
204 210 fmd_hdl_debug(hdl, "Prepping ereport failed: "
205 211 "class = %s\n", entry->err_class);
206 212 nvlist_free(erpt);
207 213 continue;
208 214 }
209 215
210 216 if (data->pcie_rp_send_all) {
211 217 fab_send_erpt_all_rps(hdl, erpt);
212 218 nvlist_free(erpt);
213 219 return;
214 220 }
215 221
216 222 fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg);
217 223 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
218 224 if (fmd_xprt_error(hdl, fab_fmd_xprt)) {
219 225 fmd_hdl_debug(hdl, "Failed to send PCI ereport\n");
220 226 return;
221 227 }
222 228 }
223 229
224 230 return;
225 231 done:
226 232 fmd_hdl_debug(hdl, "Failed to send PCI ereport\n");
227 233 }
228 234
229 235 char *
230 236 fab_xpath_query(fmd_hdl_t *hdl, const char *query)
231 237 {
232 238 xmlXPathObjectPtr xpathObj;
233 239 xmlNodeSetPtr nodes;
234 240 char *temp, *res;
235 241
236 242 fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
237 243
238 244 xpathObj = xmlXPathEvalExpression((const xmlChar *)query,
239 245 fab_xpathCtx);
240 246
241 247 if (xpathObj == NULL)
242 248 return (NULL);
243 249
244 250 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj,
245 251 xpathObj->type);
246 252 nodes = xpathObj->nodesetval;
247 253
248 254 if (nodes) {
249 255 temp = (char *)xmlNodeGetContent(nodes->nodeTab[0]);
250 256 fmd_hdl_debug(hdl, "query result: %s\n", temp);
251 257 res = fmd_hdl_strdup(hdl, temp, FMD_SLEEP);
252 258 xmlFree(temp);
253 259 xmlXPathFreeObject(xpathObj);
254 260 return (res);
255 261 }
256 262 xmlXPathFreeObject(xpathObj);
257 263 return (NULL);
258 264 }
259 265
260 266 #define FAB_HC2DEV_QUERY_SIZE_MIN 160
261 267 #define FAB_HC2DEV_QUERY_SIZE(sz) \
262 268 ((sz + FAB_HC2DEV_QUERY_SIZE_MIN) * sizeof (char))
263 269
264 270 /*
265 271 * hc_path is in form of "/motherboard=0/hostbridge=0/pciexrc=0"
266 272 */
267 273 boolean_t
268 274 fab_hc2dev(fmd_hdl_t *hdl, const char *hc_path, char **dev_path)
269 275 {
270 276 char *query;
271 277 uint_t len = FAB_HC2DEV_QUERY_SIZE_MIN + strlen(hc_path);
272 278
273 279 query = fmd_hdl_alloc(hdl, len, FMD_SLEEP);
274 280 (void) snprintf(query, len, "//propval[@name='resource' and contains("
275 281 "substring(@value, string-length(@value) - %d + 1), '%s')]"
276 282 "/parent::*/following-sibling::*/propval[@name='dev']/@value",
277 283 strlen(hc_path) + 1, hc_path);
278 284
279 285 *dev_path = fab_xpath_query(hdl, query);
280 286
281 287 fmd_hdl_free(hdl, query, len);
282 288
283 289 return (*dev_path != NULL);
284 290 }
285 291
286 292 static boolean_t
287 293 fab_hc_path(fmd_hdl_t *hdl, nvlist_t *detector, char **hcpath, size_t *lenp)
288 294 {
289 295 char c, *name, *id, *buf;
290 296 uint_t i, size;
291 297 nvlist_t **hcl;
292 298 size_t len = 0, buf_size = 0;
293 299
294 300 if (nvlist_lookup_nvlist_array(detector, FM_FMRI_HC_LIST, &hcl,
295 301 &size) != 0)
296 302 return (B_FALSE);
297 303
298 304 for (i = 0; i < size; i++) {
299 305 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0)
300 306 return (B_FALSE);
301 307 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &id) != 0)
302 308 return (B_FALSE);
303 309 buf_size += snprintf(&c, 1, "/%s=%s", name, id);
304 310 }
305 311
306 312 buf_size++;
307 313 buf = fmd_hdl_alloc(hdl, buf_size, FMD_SLEEP);
308 314
309 315 for (i = 0; i < size; i++) {
310 316 (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name);
311 317 (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &id);
312 318 len += snprintf(buf + len, buf_size - len, "/%s=%s", name, id);
313 319 }
314 320
315 321 *hcpath = buf;
316 322 *lenp = buf_size;
317 323
318 324 return (B_TRUE);
319 325 }
320 326
321 327 boolean_t
322 328 fab_hc2dev_nvl(fmd_hdl_t *hdl, nvlist_t *detector, char **dev_path)
323 329 {
324 330 char *hcl;
325 331 size_t len;
326 332
327 333 if (! fab_hc_path(hdl, detector, &hcl, &len))
328 334 return (B_FALSE);
329 335
330 336 (void) fab_hc2dev(hdl, hcl, dev_path);
331 337
332 338 fmd_hdl_free(hdl, hcl, len);
333 339
334 340 return (*dev_path != NULL);
335 341 }
336 342
337 343 boolean_t
338 344 fab_get_hcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char **hcpath, size_t *len)
339 345 {
340 346 nvlist_t *detector;
341 347 char *scheme;
342 348
343 349 if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0 ||
344 350 nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0 ||
345 351 ! STRCMP(scheme, FM_FMRI_SCHEME_HC))
346 352 return (B_FALSE);
347 353
348 354 return (fab_hc_path(hdl, detector, hcpath, len));
349 355 }
350 356
351 357 char *
352 358 fab_find_rppath_by_df(fmd_hdl_t *hdl, nvlist_t *nvl, uint8_t df)
353 359 {
354 360 char query[500];
355 361 char str[10];
356 362 char *hcpath;
357 363 size_t len;
358 364
359 365 (void) snprintf(str, sizeof (str), "%0hhx", df);
360 366
361 367 /*
362 368 * get the string form of the hc detector, eg
363 369 * /chassis=0/motherboard=0/hostbridge=0
364 370 */
365 371 if (!fab_get_hcpath(hdl, nvl, &hcpath, &len))
366 372 return (NULL);
367 373
368 374 /*
369 375 * Explanation of the XSL XPATH Query
370 376 * Line 1: Look at all nodes with the node name "propval"
371 377 * Line 2: See if the "BDF" of the node matches DF
372 378 * Line 3-4: See if the the node is pciexrc
373 379 * Line 5-6: See if the "ASRU" contains root complex
374 380 * Line 7-8: Go up one level and get prop value of io/dev
375 381 */
376 382 (void) snprintf(query, sizeof (query), "//propval["
377 383 "@name='BDF' and contains(substring(@value, "
378 384 "string-length(@value) - 1), '%s')]"
379 385 "/parent::*/parent::*/propgroup[@name='pci']/propval"
380 386 "[@name='extended-capabilities' and @value='%s']"
381 387 "/parent::*/parent::*/propgroup[@name='protocol']"
382 388 "/propval[@name='resource' and contains(@value, '%s')]"
383 389 "/parent::*/parent::*/propgroup[@name='io']"
384 390 "/propval[@name='dev']/@value", str, PCIEX_ROOT, hcpath);
385 391
386 392 fmd_hdl_free(hdl, hcpath, len);
387 393
388 394 return (fab_xpath_query(hdl, query));
389 395 }
390 396
391 397 char *
392 398 fab_find_rppath_by_devbdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf)
393 399 {
394 400 xmlXPathObjectPtr xpathObj;
395 401 xmlNodeSetPtr nodes;
396 402 xmlNodePtr devNode;
397 403 char *retval, *temp;
398 404 char query[500];
399 405 int i, size, bus, dev, fn;
400 406 char *hcpath;
401 407 size_t len;
402 408
403 409 if (bdf != (uint16_t)-1) {
404 410 bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT;
405 411 dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT;
406 412 fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT;
407 413 }
408 414
409 415 /*
410 416 * get the string form of the hc detector, eg
411 417 * /chassis=0/motherboard=0/hostbridge=0
412 418 */
413 419 if (!fab_get_hcpath(hdl, nvl, &hcpath, &len))
414 420 goto fail;
415 421
416 422 /*
417 423 * Explanation of the XSL XPATH Query
418 424 * Line 1: Look at all nodes with the node name "propval"
419 425 * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
420 426 * Line 4-5: See if the "value" of the node ends with correct PCI BDF
421 427 * Line 6: Go up one level to the parent of the current node
422 428 * Line 7: See if child node contains "ASRU" with the same PCIe Root
423 429 * Line 8: Go up see all the ancestors
424 430 */
425 431 (void) snprintf(query, sizeof (query), "//propval["
426 432 "contains(substring(@value, string-length(@value) - 34), "
427 433 "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
428 434 "contains(substring(@value, string-length(@value) - 28), "
429 435 "'pcibus=%d/pcidev=%d/pcifn=%d')"
430 436 "]/parent::"
431 437 "*/propval[@name='resource' and contains(@value, '%s')]"
432 438 "/ancestor::*",
433 439 bus, dev, fn, bus, dev, fn, hcpath);
434 440
435 441 fmd_hdl_free(hdl, hcpath, len);
436 442
437 443 fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
438 444
439 445 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
440 446
441 447 if (xpathObj == NULL)
442 448 goto fail;
443 449
444 450 nodes = xpathObj->nodesetval;
445 451 size = (nodes) ? nodes->nodeNr : 0;
446 452
447 453 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d size %d\n",
448 454 xpathObj, xpathObj->type, size);
449 455
450 456 for (i = 0; i < size; i++) {
451 457 devNode = nodes->nodeTab[i];
452 458 if (STRCMP(devNode->name, "range") &&
453 459 HAS_PROP(devNode, "name")) {
454 460 char *tprop = GET_PROP(devNode, "name");
455 461
456 462 /* find "range name='pciexrc'" in ancestors */
457 463 if (STRCMP(tprop, PCIEX_ROOT)) {
458 464 /* go down to the pciexrc instance node */
459 465 FREE_PROP(tprop);
460 466 devNode = nodes->nodeTab[i+1];
461 467 goto found;
462 468 }
463 469 FREE_PROP(tprop);
464 470 }
465 471 }
466 472 goto fail;
467 473
468 474 found:
469 475 /* Traverse down the xml tree to find the right propgroup */
470 476 for (devNode = devNode->children; devNode; devNode = devNode->next) {
471 477 if (STRCMP(devNode->name, "propgroup")) {
472 478 char *tprop = GET_PROP(devNode, "name");
473 479
474 480 if (STRCMP(tprop, "io")) {
475 481 FREE_PROP(tprop);
476 482 goto propgroup;
477 483 }
478 484 FREE_PROP(tprop);
479 485 }
480 486 }
481 487 goto fail;
482 488
483 489 propgroup:
484 490 /* Retrive the "dev" propval and return */
485 491 for (devNode = devNode->children; devNode; devNode = devNode->next) {
486 492 if (STRCMP(devNode->name, "propval")) {
487 493 char *tprop = GET_PROP(devNode, "name");
488 494
489 495 if (STRCMP(tprop, "dev")) {
490 496 temp = GET_PROP(devNode, "value");
491 497 retval = fmd_hdl_strdup(hdl, temp, FMD_SLEEP);
492 498 fmd_hdl_debug(hdl, "RP Path: %s\n", retval);
493 499 xmlFree(temp);
494 500 xmlXPathFreeObject(xpathObj);
495 501 }
496 502 FREE_PROP(tprop);
497 503
498 504 return (retval);
499 505 }
500 506 }
501 507 fail:
502 508 if (xpathObj != NULL)
503 509 xmlXPathFreeObject(xpathObj);
504 510 return (NULL);
505 511 }
506 512
507 513 char *
508 514 fab_find_rppath_by_devpath(fmd_hdl_t *hdl, const char *devpath)
509 515 {
510 516 char query[500];
511 517
512 518 /*
513 519 * Explanation of the XSL XPATH Query
514 520 * Line 1: Look at all nodes with the node name "propval"
515 521 * Line 2: See if the node is pciexrc
516 522 * Line 3: Go up to the io pgroup
517 523 * Line 4: See if the "dev" prop is parent of devpath
518 524 * Line 5: Get the 'dev' prop
519 525 */
520 526 (void) snprintf(query, sizeof (query), "//propval"
521 527 "[@name='extended-capabilities' and @value='%s']"
522 528 "/parent::*/parent::*/propgroup[@name='io']"
523 529 "/propval[@name='dev' and starts-with('%s', concat(@value, '/'))]"
524 530 "/@value", PCIEX_ROOT, devpath);
525 531
526 532 return (fab_xpath_query(hdl, query));
527 533 }
528 534
529 535 /* ARGSUSED */
530 536 boolean_t
531 537 fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath)
532 538 {
533 539 nvlist_t *detector;
534 540 char *path, *scheme;
535 541
536 542 if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0)
537 543 goto fail;
538 544 if (nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0)
539 545 goto fail;
540 546
541 547 if (STRCMP(scheme, FM_FMRI_SCHEME_DEV)) {
542 548 if (nvlist_lookup_string(detector, FM_FMRI_DEV_PATH,
543 549 &path) != 0)
544 550 goto fail;
545 551 (void) strncpy(rcpath, path, FM_MAX_CLASS);
546 552 } else if (STRCMP(scheme, FM_FMRI_SCHEME_HC)) {
547 553 /*
548 554 * This should only occur for ereports that come from the RC
549 555 * itself. In this case convert HC scheme to dev path.
550 556 */
551 557 if (fab_hc2dev_nvl(hdl, detector, &path)) {
552 558 (void) strncpy(rcpath, path, FM_MAX_CLASS);
553 559 fmd_hdl_strfree(hdl, path);
554 560 } else {
555 561 goto fail;
556 562 }
557 563 } else {
558 564 return (B_FALSE);
559 565 }
560 566
561 567 /*
562 568 * Extract the RC path by taking the first device in the dev path
563 569 *
564 570 * /pci@0,0/pci8086,3605@2/pci8086,3500@0/pci8086,3514@1/pci8086,105e@0
565 571 * - to -
566 572 * /pci@0,0
567 573 */
568 574 path = strchr(rcpath + 1, '/');
569 575 if (path)
570 576 path[0] = '\0';
571 577
572 578 return (B_TRUE);
573 579 fail:
574 580 return (B_FALSE);
575 581 }
576 582
577 583 char *
578 584 fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf)
579 585 {
580 586 char *retval;
581 587 char query[500];
582 588 int bus, dev, fn;
583 589 char rcpath[255];
584 590
585 591 if (bdf != (uint16_t)-1) {
586 592 bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT;
587 593 dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT;
588 594 fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT;
589 595 }
590 596
591 597 if (!fab_get_rcpath(hdl, nvl, rcpath))
592 598 goto fail;
593 599
594 600 /*
595 601 * Explanation of the XSL XPATH Query
596 602 * Line 1: Look at all nodes with the node name "propval"
597 603 * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
598 604 * Line 4-5: See if the "value" of the node ends with correct PCI BDF
599 605 * Line 6: Go up one level to the parent of the current node
600 606 * Line 7: See if child node contains "ASRU" with the same PCIe Root
601 607 * Line 8: Traverse up the parent and the other siblings and look for
602 608 * the io "propgroup" and get the value of the dev "propval"
603 609 */
604 610 (void) snprintf(query, sizeof (query), "//propval["
605 611 "contains(substring(@value, string-length(@value) - 34), "
606 612 "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
607 613 "contains(substring(@value, string-length(@value) - 28), "
608 614 "'pcibus=%d/pcidev=%d/pcifn=%d')"
609 615 "]/parent::"
610 616 "*/propval[@name='ASRU' and contains(@value, '%s')]"
611 617 "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/"
612 618 "@value", bus, dev, fn, bus, dev, fn, rcpath);
613 619
614 620 retval = fab_xpath_query(hdl, query);
615 621 if (retval) {
616 622 fmd_hdl_debug(hdl, "BDF Dev Path: %s\n", retval);
617 623 return (retval);
618 624 }
619 625 fail:
620 626 return (NULL);
621 627 }
622 628
623 629 char *
624 630 fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr)
625 631 {
626 632 xmlXPathObjectPtr xpathObj;
627 633 xmlNodeSetPtr nodes;
628 634 xmlNodePtr devNode;
629 635 char *retval, *temp;
630 636 char query[500];
631 637 int size, i, j;
632 638 uint32_t prop[50];
633 639 char *token;
634 640 pci_regspec_t *assign_p;
635 641 uint64_t low, hi;
636 642 char rcpath[255];
637 643
638 644 if (!fab_get_rcpath(hdl, nvl, rcpath))
639 645 goto fail;
640 646
641 647 (void) snprintf(query, sizeof (query), "//propval["
642 648 "@name='ASRU' and contains(@value, '%s')]/"
643 649 "parent::*/following-sibling::*[@name='pci']/"
644 650 "propval[@name='assigned-addresses']", rcpath);
645 651
646 652 fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
647 653
648 654 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
649 655
650 656 if (xpathObj == NULL)
651 657 goto fail;
652 658
653 659 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type);
654 660
655 661 nodes = xpathObj->nodesetval;
656 662 size = (nodes) ? nodes->nodeNr : 0;
657 663
658 664 /* Decode the list of assigned addresses xml nodes for each device */
659 665 for (i = 0; i < size; i++) {
660 666 char *tprop;
661 667
662 668 devNode = nodes->nodeTab[i];
663 669 if (!HAS_PROP(devNode, "value"))
664 670 continue;
665 671
666 672 /* Convert "string" assigned-addresses to pci_regspec_t */
667 673 j = 0;
668 674 tprop = GET_PROP(devNode, "value");
669 675 for (token = strtok(tprop, " "); token;
670 676 token = strtok(NULL, " ")) {
671 677 prop[j++] = strtoul(token, (char **)NULL, 16);
672 678 }
673 679 prop[j] = (uint32_t)-1;
674 680 FREE_PROP(tprop);
675 681
676 682 /* Check if address belongs to this device */
677 683 for (assign_p = (pci_regspec_t *)prop;
678 684 assign_p->pci_phys_hi != (uint_t)-1; assign_p++) {
679 685 low = assign_p->pci_phys_low;
680 686 hi = low + assign_p->pci_size_low;
681 687 if ((addr < hi) && (addr >= low)) {
682 688 fmd_hdl_debug(hdl, "Found Address\n");
683 689 goto found;
684 690 }
685 691 }
686 692 }
687 693 goto fail;
688 694
689 695 found:
690 696 /* Traverse up the xml tree and back down to find the right propgroup */
691 697 for (devNode = devNode->parent->parent->children;
692 698 devNode; devNode = devNode->next) {
693 699 char *tprop;
694 700
695 701 tprop = GET_PROP(devNode, "name");
696 702 if (STRCMP(devNode->name, "propgroup") &&
697 703 STRCMP(tprop, "io")) {
698 704 FREE_PROP(tprop);
699 705 goto propgroup;
700 706 }
701 707 FREE_PROP(tprop);
702 708 }
703 709 goto fail;
704 710
705 711 propgroup:
706 712 /* Retrive the "dev" propval and return */
707 713 for (devNode = devNode->children; devNode; devNode = devNode->next) {
708 714 char *tprop;
709 715
710 716 tprop = GET_PROP(devNode, "name");
711 717 if (STRCMP(devNode->name, "propval") &&
712 718 STRCMP(tprop, "dev")) {
713 719 FREE_PROP(tprop);
714 720 temp = GET_PROP(devNode, "value");
715 721 retval = fmd_hdl_strdup(hdl, temp, FMD_SLEEP);
716 722 fmd_hdl_debug(hdl, "Addr Dev Path: %s\n", retval);
717 723 xmlFree(temp);
718 724 xmlXPathFreeObject(xpathObj);
719 725 return (retval);
720 726 }
721 727 FREE_PROP(tprop);
722 728 }
723 729 fail:
724 730 if (xpathObj != NULL)
725 731 xmlXPathFreeObject(xpathObj);
726 732 return (NULL);
727 733 }
728 734
729 735 void
730 736 fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl)
731 737 {
732 738 nvpair_t *nvp;
733 739
734 740 for (nvp = nvlist_next_nvpair(nvl, NULL);
735 741 nvp != NULL;
736 742 nvp = nvlist_next_nvpair(nvl, nvp)) {
737 743
738 744 data_type_t type = nvpair_type(nvp);
739 745 const char *name = nvpair_name(nvp);
740 746
741 747 boolean_t b;
742 748 uint8_t i8;
743 749 uint16_t i16;
744 750 uint32_t i32;
745 751 uint64_t i64;
746 752 char *str;
747 753 nvlist_t *cnv;
748 754
749 755 nvlist_t **nvlarr;
750 756 uint_t arrsize;
751 757 int arri;
752 758
753 759
754 760 if (STRCMP(name, FM_CLASS))
755 761 continue; /* already printed by caller */
756 762
757 763 fmd_hdl_debug(hdl, " %s=", name);
758 764
759 765 switch (type) {
760 766 case DATA_TYPE_BOOLEAN:
761 767 fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1");
762 768 break;
763 769
764 770 case DATA_TYPE_BOOLEAN_VALUE:
765 771 (void) nvpair_value_boolean_value(nvp, &b);
766 772 fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d",
767 773 b ? "1" : "0");
768 774 break;
769 775
770 776 case DATA_TYPE_BYTE:
771 777 (void) nvpair_value_byte(nvp, &i8);
772 778 fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8);
773 779 break;
774 780
775 781 case DATA_TYPE_INT8:
776 782 (void) nvpair_value_int8(nvp, (void *)&i8);
777 783 fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8);
778 784 break;
779 785
780 786 case DATA_TYPE_UINT8:
781 787 (void) nvpair_value_uint8(nvp, &i8);
782 788 fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8);
783 789 break;
784 790
785 791 case DATA_TYPE_INT16:
786 792 (void) nvpair_value_int16(nvp, (void *)&i16);
787 793 fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16);
788 794 break;
789 795
790 796 case DATA_TYPE_UINT16:
791 797 (void) nvpair_value_uint16(nvp, &i16);
792 798 fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16);
793 799 break;
794 800
795 801 case DATA_TYPE_INT32:
796 802 (void) nvpair_value_int32(nvp, (void *)&i32);
797 803 fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32);
798 804 break;
799 805
800 806 case DATA_TYPE_UINT32:
801 807 (void) nvpair_value_uint32(nvp, &i32);
802 808 fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32);
803 809 break;
804 810
805 811 case DATA_TYPE_INT64:
806 812 (void) nvpair_value_int64(nvp, (void *)&i64);
807 813 fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx",
808 814 (u_longlong_t)i64);
809 815 break;
810 816
811 817 case DATA_TYPE_UINT64:
812 818 (void) nvpair_value_uint64(nvp, &i64);
813 819 fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx",
814 820 (u_longlong_t)i64);
815 821 break;
816 822
817 823 case DATA_TYPE_HRTIME:
818 824 (void) nvpair_value_hrtime(nvp, (void *)&i64);
819 825 fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx",
820 826 (u_longlong_t)i64);
821 827 break;
822 828
823 829 case DATA_TYPE_STRING:
824 830 (void) nvpair_value_string(nvp, &str);
825 831 fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"",
826 832 str ? str : "<NULL>");
827 833 break;
828 834
829 835 case DATA_TYPE_NVLIST:
830 836 fmd_hdl_debug(hdl, "[");
831 837 (void) nvpair_value_nvlist(nvp, &cnv);
832 838 fab_pr(hdl, NULL, cnv);
833 839 fmd_hdl_debug(hdl, " ]");
834 840 break;
835 841
836 842 case DATA_TYPE_BOOLEAN_ARRAY:
837 843 case DATA_TYPE_BYTE_ARRAY:
838 844 case DATA_TYPE_INT8_ARRAY:
839 845 case DATA_TYPE_UINT8_ARRAY:
840 846 case DATA_TYPE_INT16_ARRAY:
841 847 case DATA_TYPE_UINT16_ARRAY:
842 848 case DATA_TYPE_INT32_ARRAY:
843 849 case DATA_TYPE_UINT32_ARRAY:
844 850 case DATA_TYPE_INT64_ARRAY:
845 851 case DATA_TYPE_UINT64_ARRAY:
846 852 case DATA_TYPE_STRING_ARRAY:
847 853 fmd_hdl_debug(hdl, "[...]");
848 854 break;
849 855 case DATA_TYPE_NVLIST_ARRAY:
850 856 arrsize = 0;
851 857 (void) nvpair_value_nvlist_array(nvp, &nvlarr,
852 858 &arrsize);
853 859
854 860 for (arri = 0; arri < arrsize; arri++) {
855 861 fab_pr(hdl, ep, nvlarr[arri]);
856 862 }
857 863
858 864 break;
859 865 case DATA_TYPE_UNKNOWN:
860 866 fmd_hdl_debug(hdl, "<unknown>");
861 867 break;
862 868 }
863 869 }
864 870 }
865 871
866 872 char *
867 873 fab_get_rpdev(fmd_hdl_t *hdl)
868 874 {
869 875 char *retval;
870 876 char query[500];
871 877
872 878 (void) snprintf(query, sizeof (query), "//propval["
873 879 "@name='extended-capabilities' and contains(@value, '%s')]"
874 880 "/parent::*/parent::*/propgroup[@name='io']"
875 881 "/propval[@name='dev']/@value", PCIEX_ROOT);
876 882
877 883 retval = fab_xpath_query(hdl, query);
878 884 if (retval) {
879 885 fmd_hdl_debug(hdl, "Root port path is %s\n", retval);
880 886 return (retval);
881 887 }
882 888
883 889 return (NULL);
884 890 }
885 891
886 892 void
887 893 fab_send_erpt_all_rps(fmd_hdl_t *hdl, nvlist_t *erpt)
888 894 {
889 895 xmlXPathObjectPtr xpathObj;
890 896 xmlNodeSetPtr nodes;
891 897 char *rppath, *hbpath;
892 898 char query[600];
893 899 nvlist_t *detector, *nvl;
894 900 uint_t i, size;
895 901 size_t len;
896 902
897 903 /* get hostbridge's path */
898 904 if (!fab_get_hcpath(hdl, erpt, &hbpath, &len)) {
899 905 fmd_hdl_debug(hdl,
900 906 "fab_send_erpt_on_all_rps: fab_get_hcpath() failed.\n");
901 907 return;
902 908 }
903 909
904 910 (void) snprintf(query, sizeof (query), "//propval["
905 911 "@name='extended-capabilities' and contains(@value, '%s')]"
906 912 "/parent::*/parent::*/propgroup[@name='protocol']"
907 913 "/propval[@name='resource' and contains(@value, '%s/')"
908 914 "]/parent::*/parent::*/propgroup[@name='io']"
909 915 "/propval[@name='dev']/@value", PCIEX_ROOT, hbpath);
910 916
911 917 fmd_hdl_free(hdl, hbpath, len);
912 918
913 919 fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
914 920
915 921 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
916 922
917 923 if (xpathObj == NULL)
918 924 return;
919 925
920 926 nodes = xpathObj->nodesetval;
921 927 size = (nodes) ? nodes->nodeNr : 0;
922 928
923 929 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d size %d\n",
924 930 xpathObj, xpathObj->type, size);
925 931
926 932 for (i = 0; i < size; i++) {
927 933 rppath = (char *)xmlNodeGetContent(nodes->nodeTab[i]);
928 934 fmd_hdl_debug(hdl, "query result: %s\n", rppath);
929 935
930 936 nvl = detector = NULL;
931 937 if (nvlist_dup(erpt, &nvl, NV_UNIQUE_NAME) != 0 ||
932 938 nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) {
933 939 xmlFree(rppath);
934 940 nvlist_free(nvl);
935 941 continue;
936 942 }
937 943
938 944 /*
939 945 * set the detector in the original ereport to the root port
940 946 */
941 947 (void) nvlist_add_string(detector, FM_VERSION,
942 948 FM_DEV_SCHEME_VERSION);
943 949 (void) nvlist_add_string(detector, FM_FMRI_SCHEME,
944 950 FM_FMRI_SCHEME_DEV);
945 951 (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH,
946 952 rppath);
947 953 (void) nvlist_remove_all(nvl, FM_EREPORT_DETECTOR);
948 954 (void) nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR,
949 955 detector);
950 956 nvlist_free(detector);
951 957 xmlFree(rppath);
952 958
953 959 fmd_hdl_debug(hdl, "Sending ereport: %s\n", fab_buf);
954 960 fmd_xprt_post(hdl, fab_fmd_xprt, nvl, 0);
955 961 if (fmd_xprt_error(hdl, fab_fmd_xprt))
956 962 fmd_hdl_debug(hdl,
957 963 "Failed to send PCI ereport\n");
958 964 }
959 965
960 966 xmlXPathFreeObject(xpathObj);
961 967 }
↓ open down ↓ |
757 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX