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 *
get_hw_error(uint8_t type)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 *
get_illegal_req(uint8_t type,uint8_t TR)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
devtab_illegal_entry(amd_iommu_t * iommu,uint32_t * event)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
io_page_fault(amd_iommu_t * iommu,uint32_t * event)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
devtab_hw_error(amd_iommu_t * iommu,uint32_t * event)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
pgtable_hw_error(amd_iommu_t * iommu,uint32_t * event)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
cmdbuf_illegal_cmd(amd_iommu_t * iommu,uint32_t * event)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
cmdbuf_hw_error(amd_iommu_t * iommu,uint32_t * event)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
iotlb_inval_to(amd_iommu_t * iommu,uint32_t * event)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
device_illegal_req(amd_iommu_t * iommu,uint32_t * event)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
amd_iommu_process_one_event(amd_iommu_t * iommu)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
amd_iommu_read_log(amd_iommu_t * iommu,amd_iommu_log_op_t op)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