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