xref: /onnv-gate/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_log.c (revision 10566:b09132fd6cd8)
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