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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/sunddi.h> 28 #include <sys/amd_iommu.h> 29 #include "amd_iommu_impl.h" 30 #include "amd_iommu_log.h" 31 32 33 static const char * 34 get_hw_error(uint8_t type) 35 { 36 const char *hwerr; 37 38 switch (type) { 39 case 0: 40 hwerr = "Reserved"; 41 break; 42 case 1: 43 hwerr = "Master Abort"; 44 break; 45 case 2: 46 hwerr = "Target Abort"; 47 break; 48 case 3: 49 hwerr = "Data Error"; 50 break; 51 default: 52 hwerr = "Unknown"; 53 break; 54 } 55 56 return (hwerr); 57 } 58 59 const char * 60 get_illegal_req(uint8_t type, uint8_t TR) 61 { 62 const char *illreq; 63 64 switch (type) { 65 case 0: 66 illreq = (TR == 1) ? "Translation I=0/V=0/V=1&&TV=0" : 67 "Read or Non-posted Write in INTR Range"; 68 break; 69 case 1: 70 illreq = (TR == 1) ? "Translation INTR/Port-IO/SysMgt; OR" 71 "Translation when SysMgt=11b/Port-IO when IOCTL=10b " 72 "while V=1 && TV=0" : 73 "Pre-translated transaction from device with I=0 or V=0"; 74 break; 75 case 2: 76 illreq = (TR == 1) ? "Reserved": 77 "Port-IO transaction for device with IoCtl = 00b"; 78 break; 79 case 3: 80 illreq = (TR == 1) ? "Reserved": 81 "Posted write to SysMgt with device SysMgt=00b " 82 "OR SysMgt=10b && message not INTx " 83 "OR Posted write to addr transaltion range with " 84 "HtAtsResv=1"; 85 break; 86 case 4: 87 illreq = (TR == 1) ? "Reserved": 88 "Read request or non-posted write in SysMgt with " 89 "device SysMgt=10b or 0xb" 90 "OR Read request or non-posted write in " 91 "addr translation range with HtAtsResv=1"; 92 break; 93 case 5: 94 illreq = (TR == 1) ? "Reserved": 95 "Posted write to Interrupt/EOI Range " 96 "for device that has IntCtl=00b"; 97 break; 98 case 6: 99 illreq = (TR == 1) ? "Reserved": 100 "Posted write to reserved Interrupt Address Range"; 101 break; 102 case 7: 103 illreq = (TR == 1) ? "Reserved": 104 "transaction to SysMgt when SysMgt=11b OR " 105 "transaction to Port-IO when IoCtl=10b while " 106 "while V=1 TV=0"; 107 break; 108 default: 109 illreq = "Unknown error"; 110 break; 111 } 112 return (illreq); 113 } 114 115 static void 116 devtab_illegal_entry(amd_iommu_t *iommu, uint32_t *event) 117 { 118 uint16_t deviceid; 119 uint8_t TR; 120 uint8_t RZ; 121 uint8_t RW; 122 uint8_t I; 123 uint32_t vaddr_lo; 124 uint32_t vaddr_hi; 125 const char *driver = ddi_driver_name(iommu->aiomt_dip); 126 int instance = ddi_get_instance(iommu->aiomt_dip); 127 const char *f = "devtab_illegal_entry"; 128 129 ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) == 130 AMD_IOMMU_EVENT_DEVTAB_ILLEGAL_ENTRY); 131 132 deviceid = AMD_IOMMU_REG_GET32(&event[0], 133 AMD_IOMMU_EVENT_DEVTAB_ILL_DEVICEID); 134 135 TR = AMD_IOMMU_REG_GET32(&event[1], 136 AMD_IOMMU_EVENT_DEVTAB_ILL_TR); 137 138 RZ = AMD_IOMMU_REG_GET32(&event[1], 139 AMD_IOMMU_EVENT_DEVTAB_ILL_RZ); 140 141 RW = AMD_IOMMU_REG_GET32(&event[1], 142 AMD_IOMMU_EVENT_DEVTAB_ILL_RW); 143 144 I = AMD_IOMMU_REG_GET32(&event[1], 145 AMD_IOMMU_EVENT_DEVTAB_ILL_INTR); 146 147 vaddr_lo = AMD_IOMMU_REG_GET32(&event[2], 148 AMD_IOMMU_EVENT_DEVTAB_ILL_VADDR_LO); 149 150 vaddr_hi = event[3]; 151 152 cmn_err(CE_WARN, "%s: %s%d: idx = %d. Illegal device table entry " 153 "deviceid=%u, %s request, %s %s transaction, %s request, " 154 "virtual address = %p", 155 f, driver, instance, iommu->aiomt_idx, 156 deviceid, 157 TR == 1 ? "Translation" : "Transaction", 158 RZ == 1 ? "Non-zero reserved bit" : "Illegal Level encoding", 159 RW == 1 ? "Write" : "Read", 160 I == 1 ? "Interrupt" : "Memory", 161 (void *)(uintptr_t)(((uint64_t)vaddr_hi) << 32 | vaddr_lo)); 162 } 163 164 static void 165 io_page_fault(amd_iommu_t *iommu, uint32_t *event) 166 { 167 uint16_t deviceid; 168 uint16_t domainid; 169 uint8_t TR; 170 uint8_t RZ; 171 uint8_t RW; 172 uint8_t PE; 173 uint8_t PR; 174 uint8_t I; 175 uint32_t vaddr_lo; 176 uint32_t vaddr_hi; 177 const char *driver = ddi_driver_name(iommu->aiomt_dip); 178 int instance = ddi_get_instance(iommu->aiomt_dip); 179 const char *f = "io_page_fault"; 180 181 ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) == 182 AMD_IOMMU_EVENT_IO_PAGE_FAULT); 183 184 deviceid = AMD_IOMMU_REG_GET32(&event[0], 185 AMD_IOMMU_EVENT_IO_PGFAULT_DEVICEID); 186 187 TR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_TR); 188 189 RZ = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_RZ); 190 191 PE = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_PE); 192 193 RW = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_RW); 194 195 PR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_PR); 196 197 I = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_INTR); 198 199 domainid = AMD_IOMMU_REG_GET32(&event[1], 200 AMD_IOMMU_EVENT_IO_PGFAULT_DOMAINID); 201 202 vaddr_lo = event[2]; 203 204 vaddr_hi = event[3]; 205 206 cmn_err(CE_WARN, "%s: %s%d: idx = %d. IO Page Fault. " 207 "deviceid=%u, %s request, %s, %s permissions, %s transaction, " 208 "%s, %s request, domainid=%u, virtual address = %p", 209 f, driver, instance, iommu->aiomt_idx, 210 deviceid, 211 TR == 1 ? "Translation" : "Transaction", 212 RZ == 1 ? "Non-zero reserved bit" : "Illegal Level encoding", 213 PE == 1 ? "did not have" : "had", 214 RW == 1 ? "Write" : "Read", 215 PR == 1 ? "Page present or Interrupt Remapped" : 216 "Page not present or Interrupt Blocked", 217 I == 1 ? "Interrupt" : "Memory", 218 domainid, 219 (void *)(uintptr_t)(((uint64_t)vaddr_hi) << 32 | vaddr_lo)); 220 } 221 222 static void 223 devtab_hw_error(amd_iommu_t *iommu, uint32_t *event) 224 { 225 uint16_t deviceid; 226 uint8_t type; 227 uint8_t TR; 228 uint8_t RW; 229 uint8_t I; 230 uint32_t physaddr_lo; 231 uint32_t physaddr_hi; 232 const char *hwerr; 233 const char *driver = ddi_driver_name(iommu->aiomt_dip); 234 int instance = ddi_get_instance(iommu->aiomt_dip); 235 const char *f = "devtab_hw_error"; 236 237 ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) == 238 AMD_IOMMU_EVENT_DEVTAB_HW_ERROR); 239 240 deviceid = AMD_IOMMU_REG_GET32(&event[0], 241 AMD_IOMMU_EVENT_DEVTAB_HWERR_DEVICEID); 242 243 type = AMD_IOMMU_REG_GET32(&event[1], 244 AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE); 245 246 hwerr = get_hw_error(type); 247 248 TR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_DEVTAB_HWERR_TR); 249 250 RW = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_DEVTAB_HWERR_RW); 251 252 I = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_DEVTAB_HWERR_INTR); 253 254 physaddr_lo = AMD_IOMMU_REG_GET32(&event[2], 255 AMD_IOMMU_EVENT_DEVTAB_HWERR_PHYSADDR_LO); 256 257 physaddr_hi = event[3]; 258 259 cmn_err(CE_WARN, "%s: %s%d: idx = %d. Device Table HW Error. " 260 "deviceid=%u, HW error type: %s, %s request, %s transaction, " 261 "%s request, physical address = %p", 262 f, driver, instance, iommu->aiomt_idx, 263 deviceid, hwerr, 264 TR == 1 ? "Translation" : "Transaction", 265 RW == 1 ? "Write" : "Read", 266 I == 1 ? "Interrupt" : "Memory", 267 (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo)); 268 } 269 270 271 static void 272 pgtable_hw_error(amd_iommu_t *iommu, uint32_t *event) 273 { 274 uint16_t deviceid; 275 uint16_t domainid; 276 uint8_t type; 277 uint8_t TR; 278 uint8_t RW; 279 uint8_t I; 280 uint32_t physaddr_lo; 281 uint32_t physaddr_hi; 282 const char *hwerr; 283 const char *driver = ddi_driver_name(iommu->aiomt_dip); 284 int instance = ddi_get_instance(iommu->aiomt_dip); 285 const char *f = "pgtable_hw_error"; 286 287 ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) == 288 AMD_IOMMU_EVENT_PGTABLE_HW_ERROR); 289 290 deviceid = AMD_IOMMU_REG_GET32(&event[0], 291 AMD_IOMMU_EVENT_PGTABLE_HWERR_DEVICEID); 292 293 type = AMD_IOMMU_REG_GET32(&event[1], 294 AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE); 295 296 hwerr = get_hw_error(type); 297 298 TR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_PGTABLE_HWERR_TR); 299 300 RW = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_PGTABLE_HWERR_RW); 301 302 I = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_PGTABLE_HWERR_INTR); 303 304 domainid = AMD_IOMMU_REG_GET32(&event[1], 305 AMD_IOMMU_EVENT_PGTABLE_HWERR_DOMAINID); 306 307 physaddr_lo = AMD_IOMMU_REG_GET32(&event[2], 308 AMD_IOMMU_EVENT_PGTABLE_HWERR_PHYSADDR_LO); 309 310 physaddr_hi = event[3]; 311 312 cmn_err(CE_WARN, "%s: %s%d: idx = %d. Page Table HW Error. " 313 "deviceid=%u, HW error type: %s, %s request, %s transaction, " 314 "%s request, domainid=%u, physical address = %p", 315 f, driver, instance, iommu->aiomt_idx, 316 deviceid, hwerr, 317 TR == 1 ? "Translation" : "Transaction", 318 RW == 1 ? "Write" : "Read", 319 I == 1 ? "Interrupt" : "Memory", 320 domainid, 321 (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo)); 322 } 323 324 static void 325 cmdbuf_illegal_cmd(amd_iommu_t *iommu, uint32_t *event) 326 { 327 uint32_t physaddr_lo; 328 uint32_t physaddr_hi; 329 const char *driver = ddi_driver_name(iommu->aiomt_dip); 330 int instance = ddi_get_instance(iommu->aiomt_dip); 331 const char *f = "cmdbuf_illegal_cmd"; 332 333 ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) == 334 AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD); 335 336 physaddr_lo = AMD_IOMMU_REG_GET32(&event[2], 337 AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD_PHYS_LO); 338 339 physaddr_hi = event[3]; 340 341 cmn_err(CE_WARN, "%s: %s%d: idx = %d. Illegal IOMMU command. " 342 "command physical address = %p", 343 f, driver, instance, iommu->aiomt_idx, 344 (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo)); 345 } 346 347 static void 348 cmdbuf_hw_error(amd_iommu_t *iommu, uint32_t *event) 349 { 350 uint32_t physaddr_lo; 351 uint32_t physaddr_hi; 352 uint8_t type; 353 const char *hwerr; 354 const char *driver = ddi_driver_name(iommu->aiomt_dip); 355 int instance = ddi_get_instance(iommu->aiomt_dip); 356 const char *f = "cmdbuf_hw_error"; 357 358 ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) == 359 AMD_IOMMU_EVENT_CMDBUF_HW_ERROR); 360 361 type = AMD_IOMMU_REG_GET32(&event[1], 362 AMD_IOMMU_EVENT_CMDBUF_HWERR_TYPE); 363 364 hwerr = get_hw_error(type); 365 366 physaddr_lo = AMD_IOMMU_REG_GET32(&event[2], 367 AMD_IOMMU_EVENT_CMDBUF_HWERR_PHYS_LO); 368 369 physaddr_hi = event[3]; 370 371 cmn_err(CE_WARN, "%s: %s%d: idx = %d. Command Buffer HW error. " 372 "HW error type = %s, command buffer physical address = %p", 373 f, driver, instance, iommu->aiomt_idx, 374 hwerr, 375 (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo)); 376 } 377 378 static void 379 iotlb_inval_to(amd_iommu_t *iommu, uint32_t *event) 380 { 381 uint16_t deviceid; 382 uint32_t physaddr_lo; 383 uint32_t physaddr_hi; 384 uint8_t type; 385 const char *hwerr; 386 const char *driver = ddi_driver_name(iommu->aiomt_dip); 387 int instance = ddi_get_instance(iommu->aiomt_dip); 388 const char *f = "iotlb_inval_to"; 389 390 ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) == 391 AMD_IOMMU_EVENT_IOTLB_INVAL_TO); 392 393 deviceid = AMD_IOMMU_REG_GET32(&event[0], 394 AMD_IOMMU_EVENT_IOTLB_INVAL_TO_DEVICEID); 395 396 /* 397 * XXX bug in spec. Is the type field available +04 26:25 or is 398 * it reserved 399 */ 400 type = AMD_IOMMU_REG_GET32(&event[1], 401 AMD_IOMMU_EVENT_IOTLB_INVAL_TO_TYPE); 402 hwerr = get_hw_error(type); 403 404 physaddr_lo = AMD_IOMMU_REG_GET32(&event[2], 405 AMD_IOMMU_EVENT_IOTLB_INVAL_TO_PHYS_LO); 406 407 physaddr_hi = event[3]; 408 409 cmn_err(CE_WARN, "%s: %s%d: idx = %d. deviceid = %u " 410 "IOTLB invalidation Timeout. " 411 "HW error type = %s, invalidation command physical address = %p", 412 f, driver, instance, iommu->aiomt_idx, deviceid, 413 hwerr, 414 (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo)); 415 } 416 417 static void 418 device_illegal_req(amd_iommu_t *iommu, uint32_t *event) 419 { 420 uint16_t deviceid; 421 uint8_t TR; 422 uint32_t addr_lo; 423 uint32_t addr_hi; 424 uint8_t type; 425 const char *reqerr; 426 const char *driver = ddi_driver_name(iommu->aiomt_dip); 427 int instance = ddi_get_instance(iommu->aiomt_dip); 428 const char *f = "device_illegal_req"; 429 430 ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) == 431 AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ); 432 433 deviceid = AMD_IOMMU_REG_GET32(&event[0], 434 AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_DEVICEID); 435 436 TR = AMD_IOMMU_REG_GET32(&event[1], 437 AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TR); 438 439 type = AMD_IOMMU_REG_GET32(&event[1], 440 AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TYPE); 441 442 reqerr = get_illegal_req(type, TR); 443 444 445 addr_lo = event[2]; 446 addr_hi = event[3]; 447 448 cmn_err(CE_WARN, "%s: %s%d: idx = %d. deviceid = %d " 449 "Illegal Device Request. " 450 "Illegal Request type = %s, %s request, address accessed = %p", 451 f, driver, instance, iommu->aiomt_idx, deviceid, 452 reqerr, 453 TR == 1 ? "Translation" : "Transaction", 454 (void *)(uintptr_t)(((uint64_t)addr_hi) << 32 | addr_lo)); 455 } 456 457 static void 458 amd_iommu_process_one_event(amd_iommu_t *iommu) 459 { 460 uint32_t event[4]; 461 amd_iommu_event_t event_type; 462 int i; 463 const char *driver = ddi_driver_name(iommu->aiomt_dip); 464 int instance = ddi_get_instance(iommu->aiomt_dip); 465 const char *f = "amd_iommu_process_one_event"; 466 467 ASSERT(MUTEX_HELD(&iommu->aiomt_eventlock)); 468 469 SYNC_FORKERN(iommu->aiomt_dmahdl); 470 for (i = 0; i < 4; i++) { 471 event[i] = iommu->aiomt_event_head[i]; 472 } 473 474 event_type = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE); 475 476 switch (event_type) { 477 case AMD_IOMMU_EVENT_DEVTAB_ILLEGAL_ENTRY: 478 devtab_illegal_entry(iommu, event); 479 break; 480 case AMD_IOMMU_EVENT_IO_PAGE_FAULT: 481 io_page_fault(iommu, event); 482 break; 483 case AMD_IOMMU_EVENT_DEVTAB_HW_ERROR: 484 devtab_hw_error(iommu, event); 485 break; 486 case AMD_IOMMU_EVENT_PGTABLE_HW_ERROR: 487 pgtable_hw_error(iommu, event); 488 break; 489 case AMD_IOMMU_EVENT_CMDBUF_HW_ERROR: 490 cmdbuf_hw_error(iommu, event); 491 break; 492 case AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD: 493 cmdbuf_illegal_cmd(iommu, event); 494 break; 495 case AMD_IOMMU_EVENT_IOTLB_INVAL_TO: 496 iotlb_inval_to(iommu, event); 497 break; 498 case AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ: 499 device_illegal_req(iommu, event); 500 break; 501 default: 502 cmn_err(CE_WARN, "%s: %s%d: idx = %d. Unknown event: %u", 503 f, driver, instance, iommu->aiomt_idx, event_type); 504 break; 505 } 506 } 507 508 int 509 amd_iommu_read_log(amd_iommu_t *iommu, amd_iommu_log_op_t op) 510 { 511 caddr_t evtail; 512 uint64_t evtail_off; 513 uint64_t evhead_off; 514 515 ASSERT(op != AMD_IOMMU_LOG_INVALID_OP); 516 517 mutex_enter(&iommu->aiomt_eventlock); 518 519 ASSERT(iommu->aiomt_event_head != NULL); 520 521 /* XXX verify */ 522 evtail_off = AMD_IOMMU_REG_GET64( 523 REGADDR64(iommu->aiomt_reg_eventlog_tail_va), 524 AMD_IOMMU_EVENTTAILPTR); 525 526 evtail_off = EV2OFF(evtail_off); 527 528 ASSERT(evtail_off < iommu->aiomt_eventlog_sz); 529 530 evtail = iommu->aiomt_eventlog + evtail_off; 531 532 if (op == AMD_IOMMU_LOG_DISCARD) { 533 /*LINTED*/ 534 iommu->aiomt_event_head = (uint32_t *)evtail; 535 AMD_IOMMU_REG_SET64(REGADDR64( 536 iommu->aiomt_reg_eventlog_head_va), 537 AMD_IOMMU_EVENTHEADPTR, OFF2EV(evtail_off)); 538 cmn_err(CE_NOTE, "Discarded IOMMU event log"); 539 mutex_exit(&iommu->aiomt_eventlock); 540 return (DDI_SUCCESS); 541 } 542 543 /*LINTED*/ 544 while (1) { 545 if ((caddr_t)iommu->aiomt_event_head == evtail) 546 break; 547 548 cmn_err(CE_WARN, "evtail_off = %p, head = %p, tail = %p", 549 (void *)(uintptr_t)evtail_off, 550 (void *)iommu->aiomt_event_head, 551 (void *)evtail); 552 553 amd_iommu_process_one_event(iommu); 554 555 /* 556 * Update the head pointer in soft state 557 * and the head pointer register 558 */ 559 iommu->aiomt_event_head += 4; 560 if ((caddr_t)iommu->aiomt_event_head >= 561 iommu->aiomt_eventlog + iommu->aiomt_eventlog_sz) { 562 /* wraparound */ 563 iommu->aiomt_event_head = 564 /*LINTED*/ 565 (uint32_t *)iommu->aiomt_eventlog; 566 evhead_off = 0; 567 } else { 568 evhead_off = (caddr_t)iommu->aiomt_event_head 569 /*LINTED*/ 570 - iommu->aiomt_eventlog; 571 } 572 573 ASSERT(evhead_off < iommu->aiomt_eventlog_sz); 574 575 AMD_IOMMU_REG_SET64(REGADDR64( 576 iommu->aiomt_reg_eventlog_head_va), 577 AMD_IOMMU_EVENTHEADPTR, OFF2EV(evhead_off)); 578 } 579 mutex_exit(&iommu->aiomt_eventlock); 580 581 return (DDI_SUCCESS); 582 } 583