Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / greatlakes / huron / src / vpci_piu.s
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: vpci_piu.s
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
46 * Use is subject to license terms.
47 */
48
49 .ident "@(#)vpci_piu.s 1.7 07/08/15 SMI"
50
51 .file "vpci_piu.s"
52
53#include <sys/asm_linkage.h>
54#include <sys/htypes.h>
55#include <hypervisor.h>
56#include <sparcv9/asi.h>
57#include <sun4v/asi.h>
58#include <asi.h>
59#include <mmu.h>
60
61#include <guest.h>
62#include <offsets.h>
63#include <debug.h>
64#include <vcpu.h>
65#include <util.h>
66#include <abort.h>
67#include <vpiu_errs.h>
68#include <intr.h>
69#include <fpga.h>
70
71#if defined(CONFIG_PIU)
72
73#ifdef VPCI_DEBUG
74
75#define _VPCI_PRINTX(r) PRINTX(r)
76#define _VPCI_PRINT(s) PRINT(s)
77#else
78#define _VPCI_PRINTX(r)
79#define _VPCI_PRINT(s)
80#endif
81
82#define _VPCI_PRINT1(s, r1) _VPCI_PRINT(s); _VPCI_PRINTX(r1)
83#define _VPCI_PRINT2(s, r1, r2) _VPCI_PRINT1(s, r1); \
84 _VPCI_PRINT1(" ", r2)
85#define _VPCI_PRINT3(s, r1, r2, r3) _VPCI_PRINT2(s, r1, r2); \
86 _VPCI_PRINT1(" ", r3)
87#define _VPCI_PRINT4(s, r1, r2, r3, r4) _VPCI_PRINT3(s, r1, r2, r3); \
88 _VPCI_PRINT1(" ", r4)
89#define VPCI_PRINT1(s, r1) _VPCI_PRINT1(s, r1); \
90 _VPCI_PRINT("\r\n")
91#define VPCI_PRINT2(s, r1, r2) _VPCI_PRINT1(s, r1); \
92 VPCI_PRINT1(" ", r2)
93#define VPCI_PRINT3(s, r1, r2, r3) _VPCI_PRINT2(s, r1, r2); \
94 VPCI_PRINT1(" ", r3)
95#define VPCI_PRINT4(s, r1, r2, r3, r4) _VPCI_PRINT3(s, r1, r2, r3) \
96 VPCI_PRINT1(" ", r4)
97
98#define REGNO2OFFSET(no, off) sllx no, 3, off
99#define PCIDEV2PIUDEV(pci, piu) sllx pci, 4, piu
100
101#if PIU_MSIEQ_SIZE != 0x28
102#error "PIU_MSIEQ_SIZE changed, breaks the shifts below"
103#endif
104#define MSIEQNUM2MSIEQ(piucookie, num, msieq, scr1, scr2) \
105 ldx [piucookie + PIU_COOKIE_MSICOOKIE], msieq ;\
106 sllx num, 5, scr1 ;\
107 sllx num, 3, scr2 ;\
108 add scr1, scr2, scr1 ;\
109 inc PIU_MSI_COOKIE_EQ, scr1 ;\
110 add msieq, scr1, msieq
111
112#define IOTSB0_PIU_COOKIE PIU_COOKIE_IOTSB0
113#define IOTSB1_PIU_COOKIE PIU_COOKIE_IOTSB1
114#define SETUP_IOTSB_BASE(rc_cookie, pcie, t, scr1, scr2, scr3) \
115 ldx [rc_cookie + t/**/_PIU_COOKIE], scr1 ;\
116 srlx scr1, t/**/_PAGESHIFT, scr1 ;\
117 sllx scr1, IOTSB_BASE_PA_SHIFT, scr1 ;\
118 set IOTSBDESC_REG(t), scr2 ;\
119 ldx [pcie + scr2], scr3 ;\
120 or scr3, scr1, scr3 ;\
121 stx scr3, [pcie + scr2]
122
123 ! Ordered to minimize wasted space
124 BSS_GLOBAL(piu_0_equeue, (PIU_NEQS * PIU_EQSIZE), 512 KB)
125 BSS_GLOBAL(piu_iotsb0, IOTSB0_SIZE, 8 KB)
126 BSS_GLOBAL(piu_iotsb1, IOTSB1_SIZE, 8 KB)
127 BSS_GLOBAL(piu_virtual_intmap, 0x10, 0x10)
128
129 DATA_GLOBAL(piu_ncu_init_table)
130 .xword PIU_BAR(CFGIO(0)), PIU_PCIE_A_IOCON_OFFSET_BASE
131 .xword PIU_BAR(MEM32(0)), PIU_PCIE_A_MEM32_OFFSET_BASE
132 .xword PIU_BAR(MEM64(0)), PIU_PCIE_A_MEM64_OFFSET_BASE
133 .xword PIU_SIZE(MEM32_SIZE), PIU_PCIE_A_MEM32_OFFSET_MASK
134 .xword PIU_BAR_V(MEM32(0)), PIU_PCIE_A_MEM32_OFFSET_BASE
135
136 .xword PIU_SIZE(CFGIO_SIZE), PIU_PCIE_A_IOCON_OFFSET_MASK
137 .xword PIU_BAR_V(CFGIO(0)), PIU_PCIE_A_IOCON_OFFSET_BASE
138
139 .xword PIU_SIZE(MEM64_SIZE), PIU_PCIE_A_MEM64_OFFSET_MASK
140 .xword PIU_BAR_V(MEM64(0)), PIU_PCIE_A_MEM64_OFFSET_BASE
141 .xword -1,-1 /* End of Table */
142 SET_SIZE(piu_ncu_init_table)
143
144 DATA_GLOBAL(piu_leaf_init_table)
145 .xword 0xffffffffffffffff, PIU_DLC_IMU_ICS_IMU_ERROR_LOG_EN_REG
146 .xword 0xffffffffffffffff, PIU_DLC_IMU_ICS_IMU_INT_EN_REG
147 .xword 0xffffffffffffffff, PIU_DLC_IMU_ICS_IMU_LOGGED_ERROR_STATUS_REG_RW1C_ALIAS
148 .xword 0x0000000000000010, PIU_DLC_ILU_CIB_ILU_LOG_EN
149 .xword 0x0000001000000010, PIU_DLC_ILU_CIB_ILU_INT_EN
150 .xword 0x00000000da130001, PIU_PLC_TLU_CTB_TLR_TLU_CTL
151 /* DW for N2 set fast link mode, reset assert */
152 .xword 0x00000000001b0808, PIU_PLC_TLU_CTB_TLR_CSR_A_LINK_CTL_ADDR
153 .xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_OE_LOG
154 .xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_OE_ERR_RW1C_ALIAS
155 .xword 0xffffffffffffffff, PCI_E_PEU_OTHER_INT_ENB_ADDR
156 .xword 0x0000000000000040, PIU_PLC_TLU_CTB_TLR_DEV_CTL
157 .xword 0x0000000000000040, PIU_PLC_TLU_CTB_TLR_LNK_CTL
158 .xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_UE_LOG
159 .xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_UE_INT_EN
160 .xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_CE_LOG
161 .xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_CE_INT_EN
162 .xword 0xffffffffffffffff, PIU_DLC_IMU_ICS_DMC_INTERRUPT_MASK_REG
163 .xword 0x0000000000000000, PIU_DLC_CRU_DMC_DBG_SEL_A_REG
164 .xword 0x0000000000000000, PIU_DLC_CRU_DMC_DBG_SEL_B_REG
165 .xword 0xffffffffffffffff, PIU_DLC_ILU_CIB_PEC_INT_EN
166 .xword 0xffffffffffffffff, PIU_DLC_MMU_INV
167 .xword 0x0000000000000000, PIU_DLC_MMU_TSB
168#ifndef DEBUG_LEGION
169 .xword 0x0000000000000000, PIU_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_ADDR ! XXX is this right?
170#endif
171
172 .xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(0)
173 .xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(1)
174 .xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(2)
175 .xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(3)
176 .xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(4)
177 .xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(5)
178 .xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(6)
179 .xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(7)
180 .xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(8)
181 .xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(9)
182 .xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(10)
183 .xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(11)
184 .xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(12)
185 .xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(13)
186 .xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(14)
187 .xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(15)
188
189 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(0) /* 0 */
190 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(1) /* 1 */
191 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(2) /* 2 */
192 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(3) /* 3 */
193 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(4) /* 4 */
194 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(5) /* 5 */
195 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(6) /* 6 */
196 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(7) /* 7 */
197 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(8) /* 8 */
198 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(9) /* 9 */
199 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(10) /* 10 */
200 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(11) /* 11 */
201 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(12) /* 12 */
202 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(13) /* 13 */
203 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(14) /* 14 */
204 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(15) /* 15 */
205 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(16) /* 16 */
206 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(17) /* 17 */
207 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(18) /* 18 */
208 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(19) /* 19 */
209 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(20) /* 20 */
210 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(21) /* 21 */
211 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(22) /* 22 */
212 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(23) /* 23 */
213 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(24) /* 24 */
214 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(25) /* 25 */
215 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(26) /* 26 */
216 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(27) /* 27 */
217 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(28) /* 28 */
218 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(29) /* 29 */
219 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(30) /* 30 */
220 .xword IOTSBDESC(UNUSED), IOTSBDESC_REG(31) /* 31 */
221
222 .xword IOTSBDESC(IOTSB0), IOTSBDESC_REG(IOTSB0)
223 .xword IOTSBDESC(IOTSB1), IOTSBDESC_REG(IOTSB1)
224
225 .xword 0x0000000000000000, PIU_DLC_MMU_TSB
226 .xword 0x0000000000000000, PIU_DLC_MMU_CTL
227 .xword 0xffffffffffffffff, PIU_DLC_MMU_INT_EN
228
229 .xword 0x0000000002000000, PIU_DLC_CRU_CSR_A_DMC_PCIE_CFG_ADDR
230
231 /* MSI ranges */
232
233 .xword 0x000000007fff0000, PIU_DLC_IMU_ICS_MSI_32_ADDR_REG
234 .xword 0x00000003ffff0000, PIU_DLC_IMU_ICS_MSI_64_ADDR_REG
235 .xword -1, -1 /* End of Table */
236 SET_SIZE(piu_leaf_init_table)
237
238/*
239 * piu_init
240 *
241 * in:
242 * %i0 - global config pointer
243 * %i1 - base of guests (not used)
244 * %i2 - base of cpus (not used)
245 * %g7 - return address
246 */
247 ENTRY_NP(piu_init)
248
249 setx piu_ncu_init_table, %g5, %g3
250 setx piu_dev, %g5, %g1
251 ldx [%i0 + CONFIG_RELOC], %o0
252 sub %g3, %o0, %g3
253 sub %g1, %o0, %g1
254 ! %g1 = piup
255 ! %g3 = piu_ncu_init_table base
256 ! %g7 = return PC
257 ldx [%g1 + PIU_COOKIE_NCU], %g4
258
259 brz,pn %g4, 3f
260 nop
261
262 ! %g1 = piup
263 ! %g3 = piu_init_table base
264 ! %g4 = NCU Base PA
265 ! %g7 = return PC
2661:
267 ldx [%g3 + 8], %g5 ! Offset
268 add %g5, 1, %g6
269 brz,pn %g6, 3f
270 ldx [%g3 + 0], %g6 ! Data
271 add %g3, 16, %g3
272 ba 1b
273 stx %g6, [%g4 + %g5]
2743:
275 setx piu_leaf_init_table, %g5, %g3
276 ldx [%i0 + CONFIG_RELOC], %o0
277 sub %g3, %o0, %g3
278
279 ldx [%g1 + PIU_COOKIE_PCIE], %g4
280
281 !brz,pn %g4, 3f
282 !nop
2831:
284 ldx [%g3 + 8], %g6 ! Offset
285 add %g6, 1, %g2
286 brz,pn %g2, 2f
287 ldx [%g3 + 0], %g2 ! Data
288 add %g3, 16, %g3
289 ba 1b
290 stx %g2, [%g4 + %g6]
2912:
292 ! Setup Interrupt Mondo Data 0 register
293 set PCI_E_INT_MONDO_DATA_0_ADDR, %g6
294 stx %g0, [%g4 + %g6]
295
296 ! Setup Interrupt Mondo Data 1 register
297 set PCI_E_INT_MONDO_DATA_1_ADDR, %g6
298 set PIU_AID, %g2
299 sllx %g2, PIU_DEVINO_SHIFT, %g2
300! ldx [%g1 + PIU_COOKIE_HANDLE], %g2
301 stx %g2, [%g4 + %g6]
302
303 ! Setup interrupt mappings
304 ! mondo 62 leafs A and B
305 ! mondo 63 only leaf A
306 VCPU_STRUCT(%g4)
307 VCPU2STRAND_STRUCT(%g4, %g2)
308 ldub [%g2 + STRAND_ID], %g2
309
310 mov %g0, %g5
311 ! Add CPU number
312 sllx %g2, JPID_SHIFT, %g6
313 or %g5, %g6, %g5
314
315 ! Select a PIU Interrupt Controller
316 and %g2, (NPIUINTRCONTROLLERS - 1), %g2
317 add %g2, PIU_INTR_CNTLR_SHIFT, %g2
318 mov 1, %g6
319 sllx %g6, %g2, %g2
320 or %g5, %g2, %g5
321
322 ! Set MDO MODE bit
323 mov 1, %g6
324 sllx %g6, PIU_INTMR_MDO_MODE_SHIFT, %g6
325 or %g5, %g6, %g5
326
327 ! Set Valid bit
328 mov 1, %g6
329 sllx %g6, PIU_INTMR_V_SHIFT, %g6
330 or %g5, %g6, %g5
331
332 mov DMU_INTERNAL_INT, %g4
333 REGNO2OFFSET(%g4, %g4)
334 ldx [%g1 + PIU_COOKIE_INTMAP], %g3
335 stx %g5, [%g3 + %g4] ! leaf A, mondo 62
336 ldx [%g1 + PIU_COOKIE_INTCLR], %g2
337 stx %g0, [%g2 + %g4]
338
339 mov PEU_INTERNAL_INT, %g4
340 REGNO2OFFSET(%g4, %g4)
341 ldx [%g1 + PIU_COOKIE_INTMAP], %g3
342 stx %g5, [%g3 + %g4] ! leaf A, mondo 63
343 ldx [%g1 + PIU_COOKIE_INTCLR], %g2
344 stx %g0, [%g2 + %g4]
345
346 ! %g1 = PIU COOKIE
347 ! %g3 = PIU PCIE Base
348 set PIU_DLC_MMU_CTL, %g5
349 ! PIU Leaf A PCIE reg base
350 ldx [%g1 + PIU_COOKIE_PCIE], %g3
351 set PIU_MMU_CSR_VALUE, %g2
352 ! Leaf A MMU_CTRL reg
353 stx %g2, [%g3 + %g5]
354
355 ! %g1 = PIU COOKIE
356 ! %g3 = PIU PCIE Base
357 set PIU_DLC_MMU_TSB, %g6
358 ldx [%g1 + PIU_COOKIE_IOTSB0], %g2
359 or %g2, IOTSB0_TSB_SIZE, %g2
360 ! Leaf A MMU_TSB_CTRL reg
361#if (PIU_MMU_CSR_VALUE & PIU_MMU_CSR_SUN4V_EN == 0)
362 stx %g2, [%g3 + %g6]
363#else
364 stx %g0, [%g3 + %g6]
365#endif
366
367 ! %g1 = PIU COOKIE
368 ! %g3 = PIU PCIE Base
369 SETUP_IOTSB_BASE(%g1, %g3, IOTSB0, %g2, %g4, %g5)
370 SETUP_IOTSB_BASE(%g1, %g3, IOTSB1, %g2, %g4, %g5)
371
372 ! %g1 = PIU COOKIE
373 ! %g3 = PIU PCIE Base
374 ldx [%g1 + PIU_COOKIE_MSIEQBASE], %g2
375 setx MSI_EQ_BASE_BYPASS_ADDR, %g7, %g6
376 or %g2, %g6, %g2
377 set PIU_DLC_IMU_EQS_EQ_BASE_ADDRESS, %g6
378 ! Leaf A EQ Base Address
379 stx %g2, [%g3 + %g6]
380
3813:
382 HVRET
383 SET_SIZE(piu_init)
384
385
386/*
387 * piu_devino2vino
388 *
389 * %g1 Piu Cookie Pointer
390 * arg0 dev config pa (%o0)
391 * arg1 dev ino (%o1)
392 * --
393 * ret0 status (%o0)
394 * ret1 virtual INO (%o1)
395 */
396 ENTRY_NP(piu_devino2vino)
397 ! %g1 pointer to PIU_COOKIE
398 ldx [%g1 + PIU_COOKIE_HANDLE], %g2
399 cmp %o0, %g2
400 bne herr_inval
401 lduh [%g1 + PIU_COOKIE_INOMAX], %g3
402 cmp %o1, %g3
403 bgu,pn %xcc, herr_inval
404 lduh [%g1 + PIU_COOKIE_VINO], %g4
405 or %o1, %g4, %o1
406 HCALL_RET(EOK)
407 SET_SIZE(piu_devino2vino)
408
409/*
410 * piu_intr_getvalid
411 *
412 * %g1 PIU Cookie Pointer
413 * arg0 Virtual INO (%o0)
414 * --
415 * ret0 status (%o0)
416 * ret1 intr valid state (%o1)
417 */
418 ENTRY_NP(piu_intr_getvalid)
419 ! %g1 pointer to PIU_COOKIE
420 VPCI_PRINT1("HV: intr_getvalid ", %o0)
421 ldx [%g1 + PIU_COOKIE_INTMAP], %g2
422 and %o0, PIU_DEVINO_MASK, %g4
423 REGNO2OFFSET(%g4, %g4)
424 ldx [%g2 + %g4], %g5
425 sra %g5, 0, %g5
426 mov INTR_DISABLED, %o1
427 movrlz %g5, INTR_ENABLED, %o1
428 HCALL_RET(EOK)
429 SET_SIZE(piu_intr_getvalid)
430
431/*
432 * _piu_intr_setvalid
433 *
434 * %g1 PIU Cookie Pointer
435 * %g2 INO
436 * %g3 intr valid state
437 * --
438 *
439 * ret0 PIU Cookie (%g1)
440 * ret1 INO (%g2)
441 */
442 ENTRY_NP(_piu_intr_setvalid)
443 ! %g1 = pointer to PIU_COOKIE
444 ldx [%g1 + PIU_COOKIE_INTMAP], %g6
445 and %g2, PIU_DEVINO_MASK, %g4
446 REGNO2OFFSET(%g4, %g4)
447 add %g4, %g6, %g4
448 ldx [%g4], %g5
449 mov 1, %g6
450 sllx %g6, PIU_INTMR_V_SHIFT, %g6
451 andn %g5, %g6, %g5
452 sllx %g3, PIU_INTMR_V_SHIFT, %g6
453 or %g5, %g6, %g5
454 stx %g5, [%g4]
455
456 HVRET
457 SET_SIZE(_piu_intr_setvalid)
458
459/*
460 * piu_intr_setvalid
461 *
462 * %g1 PIU Cookie Pointer
463 * arg0 Virtual INO (%o0)
464 * arg1 intr valid state (%o1) 1: Valid 0: Invalid
465 * --
466 * ret0 status (%o0)
467 */
468 ENTRY_NP(piu_intr_setvalid)
469 VPCI_PRINT2("HV: intr_setvalid ", %o0, %o1)
470 ! %g1 = pointer to PIU_COOKIE
471 mov %o0, %g2
472 mov %o1, %g3
473 HVCALL(_piu_intr_setvalid)
474
475 HCALL_RET(EOK)
476 SET_SIZE(piu_intr_setvalid)
477
478/*
479 * piu_intr_getstate
480 *
481 * %g1 PIU Cookie Pointer
482 * arg0 Virtual INO (%o0)
483 * --
484 * ret0 status (%o0)
485 * ret1 (%o1) 1: Pending / 0: Idle
486 */
487 ENTRY_NP(piu_intr_getstate)
488 VPCI_PRINT1("HV: intr_getstate ", %o0)
489 ! %g1 pointer to PIU_COOKIE
490 ldx [%g1 + PIU_COOKIE_INTCLR], %g2
491 and %o0, PIU_DEVINO_MASK, %g4
492 REGNO2OFFSET(%g4, %g4)
493 ldx [%g2 + %g4], %g3
494 sub %g3, PIU_INTR_RECEIVED, %g4
495 movrz %g4, INTR_DELIVERED, %o1
496 movrnz %g4, INTR_RECEIVED, %o1
497 movrz %g3, INTR_IDLE, %o1
498 HCALL_RET(EOK)
499 SET_SIZE(piu_intr_getstate)
500
501/*
502 * piu_intr_setstate
503 *
504 * %g1 PIU Cookie Pointer
505 * arg0 Virtual INO (%o0)
506 * arg1 (%o1) 1: Pending / 0: Idle XXX
507 * --
508 * ret0 status (%o0)
509 */
510 ENTRY_NP(piu_intr_setstate)
511 VPCI_PRINT2("HV: intr_setstate ", %o0, %o1)
512 ! %g1 pointer to PIU_COOKIE
513 cmp %o1, INTR_DELIVERED
514 bgu,pn %xcc, herr_inval
515 mov %o0, %g2
516 mov %o1, %g3
517 HVCALL(_piu_intr_setstate)
518
519 HCALL_RET(EOK)
520 SET_SIZE(piu_intr_setstate)
521
522/*
523 * %g1 = PIU Cookie
524 * %g2 = device ino
525 * %g3 = Pending/Idle
526 * --
527 * %g1 = PIU Cookie
528 * %g2 = device ino
529 */
530 ENTRY_NP(_piu_intr_setstate)
531 ldx [%g1 + PIU_COOKIE_INTCLR], %g5
532 and %g2, PIU_DEVINO_MASK, %g4
533 REGNO2OFFSET(%g4, %g4)
534 movrz %g3, PIU_INTR_IDLE, %g3
535 movrnz %g3, PIU_INTR_RECEIVED, %g3
536 stx %g3, [%g5 + %g4]
537
538 HVRET
539 SET_SIZE(_piu_intr_setstate)
540
541/*
542 * piu_intr_gettarget
543 *
544 * %g1 PIU Cookie Pointer
545 * arg0 Virtual INO (%o0)
546 * --
547 * ret0 status (%o0)
548 * ret1 cpuid (%o1)
549 */
550 ENTRY_NP(piu_intr_gettarget)
551 VPCI_PRINT1("HV: intr_gettarget ", %o0)
552 ! %g1 pointer to PIU_COOKIE
553
554 mov %o0, %g2
555 HVCALL(_piu_intr_gettarget)
556
557 ! get the virtual cpuid
558 PID2VCPUP(%g3, %g4, %g5, %g6)
559 ldub [%g4 + CPU_VID], %o1
560
561 HCALL_RET(EOK)
562 SET_SIZE(piu_intr_gettarget)
563
564/*
565 * %g1 = PIU cookie
566 * %g2 = device ino
567 * --
568 * %g1 = PIU cookie
569 * %g2 = device ino
570 * %g3 = phys cpuid
571 */
572 ENTRY_NP(_piu_intr_gettarget)
573 ldx [%g1 + PIU_COOKIE_INTMAP], %g3
574 and %g2, PIU_DEVINO_MASK, %g4
575 REGNO2OFFSET(%g4, %g4)
576 ldx [%g3 + %g4], %g3
577 srlx %g3, JPID_SHIFT, %g3
578 and %g3, JPID_MASK, %g4
579 STRAND_STRUCT(%g3)
580 STRAND2CONFIG_STRUCT(%g3, %g3)
581 ldx [%g3 + CONFIG_STRANDS], %g3
582 set STRAND_SIZE, %g5
583 mulx %g4, %g5, %g5
584 add %g3, %g5, %g3
585 ldub [%g3 + STRAND_ID], %g3
586
587 HVRET
588 SET_SIZE(_piu_intr_gettarget)
589
590/*
591 * piu_intr_settarget
592 *
593 * %g1 PIU Cookie Pointer
594 * arg0 Virtual INO (%o0)
595 * arg1 cpuid (%o1)
596 * --
597 * ret0 status (%o0)
598 */
599 ENTRY_NP(piu_intr_settarget)
600 VPCI_PRINT2("HV: intr_settarget ", %o0, %o1)
601 ! %g1 pointer to PIU_COOKIE
602 GUEST_STRUCT(%g3)
603 VCPUID2CPUP(%g3, %o1, %g4, herr_nocpu, %g5)
604
605 IS_CPU_IN_ERROR(%g4, %g5)
606 be,pn %xcc, herr_cpuerror
607 nop
608
609 VCPU2STRAND_STRUCT(%g4, %g3)
610 ldub [%g3 + STRAND_ID], %g3
611 and %o0, PIU_DEVINO_MASK, %g2
612
613 HVCALL(_piu_intr_settarget)
614
615 HCALL_RET(EOK)
616 SET_SIZE(piu_intr_settarget)
617
618/*
619 * %g1 = PIU cookie
620 * %g2 = device ino
621 * %g3 = Physical CPU number
622 * --
623 * %g1 = PIU cookie
624 * %g2 = device ino
625 */
626
627 ENTRY_NP(_piu_intr_settarget)
628 ldx [%g1 + PIU_COOKIE_INTMAP], %g4
629 REGNO2OFFSET(%g2, %g6)
630 add %g4, %g6, %g4
631 ldx [%g4], %g5
632
633 ! %g2 INO offset
634 ! %g3 Physical CPU number
635 ! %g4 INTMAP base
636 ! %g5 INTMAP reg value
637
638 ! Add CPU number
639 mov JPID_MASK, %g6
640 sllx %g6, JPID_SHIFT, %g6
641 andn %g5, %g6, %g5
642 sllx %g3, JPID_SHIFT, %g6
643 or %g5, %g6, %g5
644
645 ! Clear Interrupt Controller bits
646 andn %g5, (PIU_INTR_CNTLR_MASK << PIU_INTR_CNTLR_SHIFT), %g5
647
648 ! Select a PIU Interrupt Controller
649 and %g3, (NPIUINTRCONTROLLERS - 1), %g3
650 add %g3, PIU_INTR_CNTLR_SHIFT, %g3
651 mov 1, %g6
652 sllx %g6, %g3, %g3
653 or %g5, %g3, %g5
654
655 ! Set MDO MODE bit
656 mov 1, %g6
657 sllx %g6, PIU_INTMR_MDO_MODE_SHIFT, %g6
658 or %g5, %g6, %g5
659
660 stx %g5, [%g4]
661 HVRET
662 SET_SIZE(_piu_intr_settarget)
663
664/*
665 * piu_iommu_map
666 *
667 * %g1 PIU Cookie Pointer
668 * arg0 dev config pa (%o0)
669 * arg1 tsbid (%o1)
670 * arg2 #ttes (%o2)
671 * arg3 tte attributes (%o3)
672 * arg4 io_page_list_p (%o4)
673 * --
674 * ret0 status (%o0)
675 * ret1 #ttes mapped (%o1)
676 */
677 ENTRY_NP(_piu_iommu_map)
678 VPCI_PRINT2("HV: iommu_map ", %o1, %o2)
679 !! %g1 pointer to PIU_COOKIE
680 ! Check io_page_list_p alignment
681 ! and make sure it is 8 byte aligned
682 btst SZ_LONG - 1, %o4
683 bnz,pn %xcc, herr_badalign
684 ldx [%g1 + PIU_COOKIE_IOTSB0], %g5
685 sethi %hi(IOTSB0_INDEX_MASK), %g3
686 or %g3, %lo(IOTSB0_INDEX_MASK), %g3
687 cmp %o1, %g3
688 bgu,pn %xcc, herr_inval
689 brlez,pn %o2, herr_inval
690 cmp %o2, IOMMU_MAP_MAX
691 movgu %xcc, IOMMU_MAP_MAX, %o2
692
693 ! Check to ensure the end of the mapping is still within
694 ! range.
695
696 !! %o2 #ttes
697 !! %o1 tte index
698 !! %g3 IOTSB_INDEX_MAX
699
700 add %o1, %o2, %g2
701 inc %g3 ! make sure last mapping succeeds.
702 cmp %g2, %g3
703 bgu,pn %xcc, herr_inval
704 nop
705
706 GUEST_STRUCT(%g2)
707
708 sllx %o2, IOTTE_SHIFT, %g6
709 RA2PA_RANGE_CONV_UNK_SIZE(%g2, %o4, %g6, herr_noraddr, %g7, %g3)
710 mov %g3, %g6
711 !! %g6 PA
712
713 ldx [%g1 + PIU_COOKIE_MMUFLUSH], %g1
714 mov 1, %g7
715 sllx %g7, PIU_IOTTE_V_SHIFT, %g7
716 or %g7, %o3, %o3
717
718 set IOTSB0_PAGESIZE, %g4
719
720 !! %g1 = PIU MMU Flush Reg
721 !! %g2 = Guest Struct
722 !! %g4 = IOTSB pagesize
723 !! %g5 = IOTSB base
724 !! %g6 = PA of pagelist
725 !! %o1 = TTE index
726 !! %o2 = #ttes to map
727 !! %o3 = TTE Attributes + Valid Bit
728
729 sllx %o1, IOTTE_SHIFT, %o1
730 add %g5, %o1, %g5
731 mov 0, %o1
732
733 !! %g1 = PIU NCU Reg Block Base
734 !! %g2 = Guest
735 !! %g4 = IOTSB pagesize
736 !! %g5 = IOTSB base
737 !! %g6 = PA of pagelist
738 !! %o1 = TTE index
739 !! %o2 = #ttes to map
740 !! %o3 = TTE Attributes + Valid Bit
741
742.piu_iommu_map_loop:
743 ldx [%g6], %g3
744 srlx %g3, IOTSB0_PAGESHIFT, %o0
745 sllx %o0, IOTSB0_PAGESHIFT, %o0
746
747 cmp %g3, %o0
748 bne,pn %xcc, .piu_badalign
749 nop
750
751 RA2PA_RANGE_CONV(%g2, %o0, %g4, .piu_noraddr, %g7, %g3)
752 mov %g3, %o0
753 !! RA -> PA (%o0)
754
755 or %o0, %o3, %o0
756 stx %o0, [%g5]
757 and %g5, (1 << 6) - 1, %o0
758
759 stx %g5, [%g1] ! IOMMU flush
760
761 add %g5, IOTTE_SIZE, %g5 ! *IOTSB++
762 add %g6, IOTTE_SIZE, %g6 ! *PAGELIST++
763 sub %o2, 1, %o2
764 brgz,pt %o2, .piu_iommu_map_loop
765 add %o1, 1, %o1
766
767 mov 0, %o2
768 HCALL_RET(EOK)
769
770.piu_noraddr:
771 brz,pn %o1, herr_noraddr
772 mov 0, %o2
773 HCALL_RET(EOK)
774
775.piu_badalign:
776 brz,pn %o1, herr_badalign
777 mov 0, %o2
778 HCALL_RET(EOK)
779 SET_SIZE(_piu_iommu_map)
780/*
781 * piu_iommu_map
782 *
783 * %g1 Piu Cookie Pointer
784 * arg0 dev config pa (%o0)
785 * arg1 tsbid (%o1)
786 * arg2 #ttes (%o2)
787 * arg3 tte attributes (%o3)
788 * arg4 io_page_list_p (%o4)
789 * --
790 * ret0 status (%o0)
791 * ret1 #ttes mapped (%o1)
792 */
793 ENTRY_NP(piu_iommu_map)
794 VPCI_PRINT4("HV: iommu_map ", %o1, %o2, %o3, %o4)
795 ! %g1 pointer to PIU_COOKIE
796 and %o3, HVIO_TTE_ATTR_MASK, %g7
797 cmp %o3, %g7
798 bne,pn %xcc, herr_inval
799 nop
800 ba,a _piu_iommu_map
801 SET_SIZE(piu_iommu_map)
802
803/*
804 * piu_iommu_map_v2
805 *
806 * %g1 = PIU Cookie Pointer
807 * arg0 dev config pa (%o0)
808 * arg1 tsbid (%o1)
809 * arg2 #ttes (%o2)
810 * arg3 tte attributes (%o3)
811 * arg4 io_page_list_p (%o4)
812 * --
813 * ret0 status (%o0)
814 * ret1 #ttes mapped (%o1)
815 */
816 ENTRY_NP(piu_iommu_map_v2)
817 VPCI_PRINT4("HV: iommu_map_v2 ", %o1, %o2, %o3, %o4)
818 ! %g1 pointer to PIU_COOKIE
819 andn %o3, HVIO_TTE_L, %o3
820 set HVIO_TTE_ATTR_MASK_V2, %g6
821 and %o3, %g6, %g7
822 cmp %o3, %g7
823 bne,pn %xcc, herr_inval
824 set HVIO_TTE_BDF, %g6
825 btst %o3, %g6
826 bnz,pt %xcc, 1f
827 and %o3, (HVIO_TTE_R | HVIO_TTE_W), %g5
828 ! No BDF given, check for PP bits
829 btst HVIO_TTE_PP, %o3
830 bnz,pn %xcc, herr_inval
831 nop
832 ba 2f
833 nop
8341:
835 srlx %o3, HVIO_TTE_BDF_SHIFT, %g6
836 sllx %g6, PIU_TTE_BDF_SHIFT, %g6
837 or %g6, PIU_TTE_DEV_KEY, %g6
838 or %g5, %g6, %g5
839
840 ! %g5 = IOTTE
841 and %o3, HVIO_TTE_PP, %g6
842
843 cmp %g6, HVIO_TTE_PP_ALL
844 be,a,pt %xcc, 2f
845 or %g5, PIU_TTE_FNM_ALL, %g5
846
847 cmp %g6, HVIO_TTE_PP_2MSBS
848 be,a,pt %xcc, 2f
849 or %g5, PIU_TTE_FNM_2MSBS, %g5
850
851 cmp %g6, HVIO_TTE_PP_MSB
852 be,a,pt %xcc, 2f
853 or %g5, PIU_TTE_FNM_MSB, %g5
854
855 cmp %g6, HVIO_TTE_PP_NONE
856 be,a,pt %xcc, 2f
857 or %g5, PIU_TTE_FNM_NONE, %g5
858
859 ! %g5 = IOTTE
8602: ba _piu_iommu_map
861 mov %g5, %o3
862 SET_SIZE(piu_iommu_map_v2)
863
864/*
865 * _piu_iommu_getmap
866 *
867 * %g1 = Piu Cookie Pointer
868 * arg0 dev config pa (%o0)
869 * arg1 tsbid (%o1)
870 * --
871 * ret0 status (%o0)
872 * ret1 attributes (%o1)
873 * ret2 ra (%o2)
874 */
875 ENTRY_NP(_piu_iommu_getmap)
876 ! %g1 pointer to PIU_COOKIE
877 ldx [%g1 + PIU_COOKIE_IOTSB0], %g5
878 sethi %hi(IOTSB0_INDEX_MASK), %g3
879 or %g3, %lo(IOTSB0_INDEX_MASK), %g3
880 cmp %o1, %g3
881 bgu,pn %xcc, herr_inval
882 sllx %o1, IOTTE_SHIFT, %g2
883 ldx [%g5 + %g2], %g5
884 mov 1, %g4
885 sllx %g4, PIU_IOTTE_V_SHIFT, %g4
886 btst %g4, %g5
887 bz,pt %xcc, herr_nomap
888 GUEST_STRUCT(%g2)
889
890 ! %g1 = PIU Cookie Pointer
891 ! %g2 = Guest pointer
892 ! %g5 = IOTTE
893 sllx %g5, (64-JBUS_PA_SHIFT), %g3
894 srlx %g3, (64-JBUS_PA_SHIFT + IOTSB0_PAGESHIFT), %g3
895 sllx %g3, IOTSB0_PAGESHIFT, %g3
896 PA2RA_CONV(%g2, %g3, %o2, %g7, %g4) ! PA -> RA (%o2)
897
898 btst PIU_TTE_DEV_KEY, %g5 ! Device key valid?
899 bz 1f
900 and %g5, HVIO_TTE_ATTR_MASK, %o1
901
902 srlx %g5, PIU_TTE_BDF_SHIFT, %g6
903 sllx %g6, HVIO_TTE_BDF_SHIFT, %g6
904 set HVIO_TTE_BDF, %g3
905 and %g6, %g3, %g3
906 or %o1, %g3, %o1
907
908 and %g5, PIU_TTE_FNM_MASK, %g6
909 cmp %g6, PIU_TTE_FNM_ALL ! All bits of func number used
910 be,a,pt %xcc, 1f
911 or %o1, HVIO_TTE_PP_ALL, %o1
912 cmp %g6, PIU_TTE_FNM_2MSBS ! 2 MSBs of func number used
913 be,a,pt %xcc, 1f
914 or %o1, HVIO_TTE_PP_2MSBS, %o1
915 cmp %g6, PIU_TTE_FNM_MSB ! MSB of func number used
916 be,a,pt %xcc, 1f
917 or %o1, HVIO_TTE_PP_MSB, %o1
918 cmp %g6, PIU_TTE_FNM_NONE ! No phanthom func numbers
919 be,a,pt %xcc, 1f
920 or %o1, HVIO_TTE_PP_NONE, %o1
9211:
922 and %g5, (1 << PIU_IOTTE_V_SHIFT), %g5
923 movrz %g5, 0, %o1 ! Clear the attributes if V=0
924#ifdef DEBUG
925 brz %o1, 1f
926 nop
927 VPCI_PRINT2("HV:iommu_getmap ", %g2, %o1)
9281:
929#endif
930 HCALL_RET(EOK)
931 SET_SIZE(_piu_iommu_getmap)
932
933/*
934 * piu_iommu_getmap
935 *
936 * %g1 = Piu Cookie Pointer
937 * arg0 dev config pa (%o0)
938 * arg1 tsbid (%o1)
939 * --
940 * ret0 status (%o0)
941 * ret1 attributes (%o1)
942 * ret2 ra (%o2)
943 */
944 ENTRY_NP(piu_iommu_getmap)
945 HVCALL(_piu_iommu_getmap)
946 and %o1, HVIO_TTE_ATTR_MASK, %o1
947 HCALL_RET(EOK)
948 SET_SIZE(piu_iommu_getmap)
949
950/*
951 * piu_iommu_getmap_v2
952 *
953 * %g1 PIU Cookie Pointer
954 * arg0 dev config pa (%o0)
955 * arg1 tsbid (%o1)
956 * --
957 * ret0 status (%o0)
958 * ret1 attributes (%o1)
959 * ret2 ra (%o2)
960 */
961 ENTRY_NP(piu_iommu_getmap_v2)
962 HVCALL(_piu_iommu_getmap)
963 HCALL_RET(EOK)
964 SET_SIZE(piu_iommu_getmap_v2)
965
966/*
967 *
968 *
969 * %g1 Piu Cookie Pointer
970 * arg0 dev config pa (%o0)
971 * arg1 tsbid (%o1)
972 * arg2 #ttes (%o2)
973 * --
974 * ret0 status (%o0)
975 * ret1 #ttes demapped (%o1)
976 */
977 ENTRY_NP(piu_iommu_unmap)
978 VPCI_PRINT2("HV: iommu_unmap ", %o1, %o2)
979 ! %g1 pointer to PIU_COOKIE
980 ldx [%g1 + PIU_COOKIE_IOTSB0], %g5
981 sethi %hi(IOTSB0_INDEX_MASK), %g3
982 or %g3, %lo(IOTSB0_INDEX_MASK), %g3
983 cmp %o1, %g3
984 bgu,pn %xcc, herr_inval
985 brlez,pn %o2, herr_inval
986 cmp %o2, IOMMU_MAP_MAX
987 movgu %xcc, IOMMU_MAP_MAX, %o2
988 brz,pn %o2, herr_inval
989 add %o1, %o2, %g2
990 inc %g3 ! make sure last mapping succeeds.
991 cmp %g2, %g3
992 bgu,pn %xcc, herr_inval
993 sllx %o1, IOTTE_SHIFT, %g2
994 add %g5, %g2, %g2
995 mov 0, %o1
996
997 ! %g1 = PIU Cookie Pointer
998 ! %g2 = IOTSB offset
999 ! %o1 = #ttes unmapped so far
1000 ! %o2 = #ttes to unmap
1001 ldx [%g1 + PIU_COOKIE_MMUFLUSH], %g1
10020:
1003 ldx [%g2], %g5
1004 ! Clear Valid bit
1005 mov 1, %g4
1006 sllx %g4, PIU_IOTTE_V_SHIFT, %g4
1007 andn %g5, %g4, %g4
1008 ! Clear Attributes
1009 srlx %g4, IOTSB0_PAGESHIFT, %g4
1010 sllx %g4, IOTSB0_PAGESHIFT, %g4
1011 stx %g4, [%g2]
1012 ! IOMMU Flush
1013 stx %g2, [%g1] ! IOMMU Flush
1014 add %g2, IOTTE_SIZE, %g2
1015 sub %o2, 1, %o2
1016 brgz,pt %o2, 0b
1017 add %o1, 1, %o1
1018
1019 ! Flush PIU TSB here XXXX
1020 HCALL_RET(EOK)
1021 SET_SIZE(piu_iommu_unmap)
1022
1023/*
1024 * piu_iommu_getbypass
1025 *
1026 * arg0 dev config pa
1027 * arg1 ra
1028 * arg2 io attributes
1029 * --
1030 * ret0 status (%o0)
1031 * ret1 bypass addr (%o1)
1032 */
1033 ENTRY_NP(piu_iommu_getbypass)
1034 ! %g1 pointer to PIU_COOKIE
1035
1036 /*
1037 * ldoms hypervisor does not handle this
1038 * function correctly yet, so all we can do
1039 * is to return ENOSUPP right here and now
1040 */
1041 HCALL_RET(ENOTSUPPORTED)
1042
1043 andncc %o2, HVIO_IO_ATTR_MASK, %g0
1044 bnz,pn %xcc, herr_inval
1045 .empty
1046 GUEST_STRUCT(%g2)
1047
1048 RA2PA_RANGE_CONV(%g2, %o1, 1, herr_noraddr, %g4, %g3)
1049 ! %g3 pa of bypass ra
1050
1051 setx PIU_IOMMU_BYPASS_BASE, %g5, %g4
1052 or %g3, %g4, %o1
1053 HCALL_RET(EOK)
1054 SET_SIZE(piu_iommu_getbypass)
1055
1056/*
1057 * piu_config_get
1058 *
1059 * arg0 dev config pa (%o0)
1060 * arg1 PCI device (%o1)
1061 * arg2 offset (%o2)
1062 * arg3 size (%o3)
1063 * --
1064 * ret0 status (%o0)
1065 * ret1 error_flag (%o1)
1066 * ret2 value (%o2)
1067 */
1068
1069 ! %g1 pointer to PIU_COOKIE
1070 ENTRY_NP(piu_config_get)
1071
1072 ! If leaf is blacklisted fail access
1073 lduw [%g1 + PIU_COOKIE_BLACKLIST], %g3
1074 brnz,a,pn %g3, .skip_config_get
1075 mov 1, %o1
1076
1077 ldx [%g1 + PIU_COOKIE_CFG], %g3
1078 mov 1, %g5
1079 STRAND_STRUCT(%g4)
1080 set STRAND_IO_PROT, %g6
1081
1082 ! strand.io_prot = 1
1083 stx %g5, [%g4 + %g6]
1084
1085 ! %g1 = PIU cookie
1086 ! %g3 = CFG base address
1087 ! %g4 = CPU struct
1088
1089 DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1090
1091 PCIDEV2PIUDEV(%o1, %g2)
1092 or %g2, %o2, %g2
1093 sub %g0, 1, %o2
1094
1095 cmp %o3, SZ_WORD
1096 beq,a,pn %xcc,1f
1097 lduwa [%g3 + %g2]ASI_P_LE, %o2
1098 cmp %o3, SZ_HWORD
1099 beq,a,pn %xcc,1f
1100 lduha [%g3 + %g2]ASI_P_LE, %o2
1101 ldub [%g3 + %g2], %o2
11021:
1103 set STRAND_IO_PROT, %g6
1104 ! strand.io_prot = 0
1105 stx %g0, [%g4 + %g6]
1106 set STRAND_IO_ERROR, %g6
1107 ! strand.io_error
1108 ldx [%g4 + %g6], %o1
1109 ! strand.io_error = 0
1110 stx %g0, [%g4 + %g6]
1111
1112 ! %g1 = PIU cookie
1113
1114 ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1115
1116#if DEBUG
1117 brnz %o1, 1f
1118 nop
1119 VPCI_PRINT2("HV:config_get ", %g2, %o2)
11201:
1121#endif
1122.skip_config_get:
1123 HCALL_RET(EOK)
1124 SET_SIZE(piu_config_get)
1125
1126/*
1127 * piu_config_put
1128 *
1129 * arg0 dev config pa (%o0)
1130 * arg1 PCI device (%o1)
1131 * arg2 offset (%o2)
1132 * arg3 size (%o3)
1133 * arg4 data (%o4)
1134 * --
1135 * ret0 status (%o0)
1136 */
1137 ! %g1 pointer to PIU_COOKIE
1138 ENTRY_NP(piu_config_put)
1139
1140 ! If leaf is blacklisted fail access
1141 lduw [%g1 + PIU_COOKIE_BLACKLIST], %g3
1142 brnz,a,pn %g3, .skip_config_put
1143 mov 1, %o1
1144
1145 ldx [%g1 + PIU_COOKIE_CFG], %g3
1146 mov 1, %g5
1147 STRAND_STRUCT(%g4)
1148 set STRAND_IO_PROT, %g6
1149
1150 ! strand.io_prot = 1
1151 stx %g5, [%g4 + %g6]
1152
1153 ! %g1 = PIU cookie
1154 ! %g3 = CFG base address
1155 ! %g4 = CPU struct
1156
1157 DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1158
1159 PCIDEV2PIUDEV(%o1, %g2)
1160 or %g2, %o2, %g2
1161 cmp %o3, SZ_WORD
1162 beq,a,pn %xcc,1f
1163 stwa %o4, [%g3 + %g2]ASI_P_LE
1164 cmp %o3, SZ_HWORD
1165 beq,a,pn %xcc,1f
1166 stha %o4, [%g3 + %g2]ASI_P_LE
1167 stb %o4, [%g3 + %g2]
1168
11691:
1170 andn %g2, PCI_CFG_OFFSET_MASK, %g6
1171 ldub [%g3 + %g6], %g0
1172 set STRAND_IO_PROT, %g6
1173 ! strand.io_prot = 0
1174 stx %g0, [%g4 + %g6]
1175 set STRAND_IO_ERROR, %g6
1176 ! strand.io_error
1177 ldx [%g4 + %g6], %o1
1178 ! strand.io_error = 0
1179 stx %g0, [%g4 + %g6]
1180
1181 ! %g1 = PIU cookie
1182
1183 ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1184
1185#if DEBUG
1186 brnz %o1, 1f
1187 nop
1188 VPCI_PRINT2("HV:config_put ", %g2, %o4)
11891:
1190#endif
1191.skip_config_put:
1192 HCALL_RET(EOK)
1193 SET_SIZE(piu_config_put)
1194
1195
1196/*
1197 * piu_dma_sync
1198 *
1199 * %g1 = PIU Cookie Pointer
1200 * arg0 devhandle (%o0)
1201 * arg1 r_addr (%o1)
1202 * arg2 size (%o2)
1203 * arg3 direction (%o3) (1: for device 2: for cpu)
1204 * --
1205 * ret0 status (%o0)
1206 * ret1 #bytes synced (%o1)
1207 */
1208 ENTRY_NP(piu_dma_sync)
1209 GUEST_STRUCT(%g2)
1210 RA2PA_RANGE_CONV_UNK_SIZE(%g2, %o1, %o2, herr_noraddr, %g4, %g3)
1211 mov %o2, %o1
1212 HCALL_RET(EOK);
1213 SET_SIZE(piu_dma_sync)
1214
1215/*
1216 * piu_io_peek
1217 *
1218 * %g1 = PIU Cookie Pointer
1219 * arg0 devhandle (%o0)
1220 * arg1 r_addr (%o1)
1221 * arg2 size (%o2)
1222 * --
1223 * ret0 status (%o0)
1224 * ret1 error? (%o1)
1225 * ret2 data (%o2)
1226 */
1227 ENTRY_NP(piu_io_peek)
1228 GUEST_STRUCT(%g2)
1229 ! %g2 = Guestp
1230 ! %o1 = ra
1231 ! %o2 = size
1232 ! %g4, %g5 = scratch
1233 RANGE_CHECK_IO(%g2, %o1, %o2, .piu_io_peek_found, herr_noraddr,
1234 %g4, %g6)
1235.piu_io_peek_found:
1236 mov 1, %g5
1237 STRAND_STRUCT(%g4)
1238 set STRAND_IO_PROT, %g6
1239 ! strand.io_prot = 1
1240 stx %g5, [%g4 + %g6]
1241
1242 ! %g1 = PIU cookie
1243 ! %g4 = strand struct
1244
1245 DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1246
1247 cmp %o2, SZ_LONG
1248 beq,a,pn %xcc,1f
1249 ldxa [%o1]ASI_P_LE, %o2
1250 cmp %o2, SZ_WORD
1251 beq,a,pn %xcc,1f
1252 lduwa [%o1]ASI_P_LE, %o2
1253 cmp %o2, SZ_HWORD
1254 beq,a,pn %xcc,1f
1255 lduha [%o1]ASI_P_LE, %o2
1256 ldub [%o1], %o2
1257
12581: set STRAND_IO_PROT, %g6
1259 ! strand.io_prot = 0
1260 stx %g0, [%g4 + %g6]
1261 set STRAND_IO_ERROR, %g6
1262 ! strand.io_error
1263 ldx [%g4 + %g6], %o1
1264 ! strand.io_error = 0
1265 stx %g0, [%g4 + %g6]
1266
1267 ! %g1 = PIU cookie
1268
1269 ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1270
1271 HCALL_RET(EOK)
1272 SET_SIZE(piu_io_peek)
1273
1274/*
1275 * piu_io_poke
1276 *
1277 * %g1 = PIU Cookie Pointer
1278 * arg0 devhandle (%o0)
1279 * arg1 r_addr (%o1)
1280 * arg2 size (%o2)
1281 * arg3 data (%o3)
1282 * arg4 PCI device (%o4)
1283 * --
1284 * ret0 status (%o0)
1285 * ret1 error? (%o1)
1286 */
1287 ENTRY_NP(piu_io_poke)
1288 ldx [%g1 + PIU_COOKIE_CFG], %g3
1289 GUEST_STRUCT(%g2)
1290 ! %g2 = Guestp
1291 ! %o1 = ra
1292 ! %o2 = size
1293 ! %g4, %g5 = scratch
1294 RANGE_CHECK_IO(%g2, %o1, %o2, .piu_io_poke_found, herr_noraddr,
1295 %g4, %g6)
1296.piu_io_poke_found:
1297 PCIDEV2PIUDEV(%o4, %g2)
1298 mov 1, %g5
1299 STRAND_STRUCT(%g4)
1300 set STRAND_IO_PROT, %g6
1301
1302 ! strand.io_prot = 1
1303 stx %g5, [%g4 + %g6]
1304
1305 ! %g1 = PIU cookie
1306 ! %g2 = PCI device BDF
1307 ! %g3 = CFG base address
1308 ! %g4 = strand struct
1309
1310 DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1311
1312 cmp %o2, SZ_LONG
1313 beq,a,pn %xcc,1f
1314 stxa %o3, [%o1]ASI_P_LE
1315 cmp %o2, SZ_WORD
1316 beq,a,pn %xcc,1f
1317 stwa %o3, [%o1]ASI_P_LE
1318 cmp %o2, SZ_HWORD
1319 beq,a,pn %xcc,1f
1320 stha %o3, [%o1]ASI_P_LE
1321 stb %o3, [%o1]
13221:
1323 ! Read from PCI config space
1324 ldub [%g3 + %g2], %g0
1325
1326 set STRAND_IO_PROT, %g6
1327 ! strand.io_prot = 0
1328 stx %g0, [%g4 + %g6]
1329 set STRAND_IO_ERROR, %g6
1330 ! strand.io_error
1331 ldx [%g4 + %g6], %o1
1332 ! strand.io_error = 0
1333 stx %g0, [%g4 + %g6]
1334
1335 ! %g1 = PIU cookie
1336
1337 ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
1338
1339 HCALL_RET(EOK)
1340 SET_SIZE(piu_io_poke)
1341
1342/*
1343 * piu_mondo_receive
1344 *
1345 * %g1 = PIU Cookie
1346 * %g2 = Mondo DATA0
1347 * %g3 = Mondo DATA1
1348 */
1349 ENTRY_NP(piu_mondo_receive)
1350 ba insert_device_mondo_r
1351 rd %pc, %g7
1352 retry
1353 SET_SIZE(piu_mondo_receive)
1354
1355/*
1356 * piu_msiq_conf
1357 *
1358 * %g1 = PIU Cookie Pointer
1359 * arg0 dev config pa (%o0)
1360 * arg1 MSI EQ id (%o1)
1361 * arg2 EQ base RA (%o2)
1362 * arg3 #entries (%o3)
1363 * --
1364 * ret0 status (%o0)
1365 */
1366 ENTRY_NP(piu_msiq_conf)
1367 cmp %o1, PIU_NEQS
1368 bgeu,pn %xcc, herr_inval
1369 sethi %hi(PIU_EQSIZE-1), %g2
1370 or %g2, %lo(PIU_EQSIZE-1), %g2
1371 and %o2, %g2, %g2
1372 brnz %g2, herr_badalign
1373 cmp %o3, PIU_NEQRECORDS
1374 bne herr_inval
1375
1376 /*
1377 * Verify RA range/alignment
1378 */
1379 set PIU_EQREC_SIZE, %g2
1380 mulx %g2, %o3, %g4
1381 GUEST_STRUCT(%g2)
1382 RA2PA_RANGE_CONV(%g2, %o2, %g0, herr_noraddr, %g7, %g6)
1383 andcc %o2, 3, %g0
1384 bnz %xcc, herr_badalign
1385 .empty
1386 ! %g6 PA
1387
1388 MSIEQNUM2MSIEQ(%g1, %o1, %g4, %g3, %g2)
1389 ldx [%g1 + PIU_COOKIE_EQSTATE], %g2
1390 REGNO2OFFSET(%o1, %g5)
1391 ldx [%g2 + %g5], %g3
1392 and %g3, 3, %g3
1393 sub %g3, 1, %g3
1394 brnz %g3, herr_inval
1395 ldx [%g1 + PIU_COOKIE_EQHEAD], %g2
1396 ldx [%g1 + PIU_COOKIE_EQTAIL], %g3
1397
1398 stx %g0, [%g2 + %g5]
1399 stx %g0, [%g3 + %g5]
1400 stx %g6, [%g4 + PIU_MSIEQ_GUEST]
1401
1402 HCALL_RET(EOK)
1403 SET_SIZE(piu_msiq_conf)
1404
1405/*
1406 * piu_msiq_info
1407 *
1408 * %g1 = PIU Cookie Pointer
1409 * arg0 dev config pa (%o0)
1410 * arg1 MSI EQ id (%o1)
1411 * --
1412 * ret0 status (%o0)
1413 * ret1 ra (%o1)
1414 * ret2 #entries (%o2)
1415 */
1416 ENTRY_NP(piu_msiq_info)
1417 cmp %o1, PIU_NEQS
1418 bgeu,pn %xcc, herr_inval
1419 .empty
1420 MSIEQNUM2MSIEQ(%g1, %o1, %g4, %g3, %g5)
1421 ldx [%g4 + PIU_MSIEQ_GUEST], %g5
1422 set PIU_NEQRECORDS, %o2
1423 movrz %g5, %g0, %o2
1424 brz,pn %g5, 1f
1425 GUEST_STRUCT(%g2)
1426 PA2RA_CONV(%g2, %g5, %o1, %g6, %g4) ! PA -> RA (%o1)
14271: HCALL_RET(EOK)
1428 SET_SIZE(piu_msiq_info)
1429
1430/*
1431 * piu_msiq_getvalid
1432 *
1433 * %g1 = PIU Cookie Pointer
1434 * arg0 dev config pa (%o0)
1435 * arg1 MSI EQ id (%o1)
1436 * --
1437 * ret0 status (%o0)
1438 * ret1 EQ valid (%o1) (0: Invalid 1: Valid)
1439 */
1440 ENTRY_NP(piu_msiq_getvalid)
1441 VPCI_PRINT1("HV:msiq_getvalid ", %o1)
1442 cmp %o1, PIU_NEQS
1443 bgeu,pn %xcc, herr_inval
1444 ldx [%g1 + PIU_COOKIE_EQSTATE], %g2
1445 REGNO2OFFSET(%o1, %g7)
1446 ldx [%g2 + %g7], %g4
1447 and %g4, 3, %g4
1448 sub %g4, 1, %o1
1449 HCALL_RET(EOK)
1450 SET_SIZE(piu_msiq_getvalid)
1451
1452/*
1453 * piu_msiq_setvalid
1454 *
1455 * %g1 = PIU Cookie Pointer
1456 * arg0 dev config pa (%o0)
1457 * arg1 MSI EQ id (%o1)
1458 * arg2 EQ valid (%o2) (0: Invalid 1: Valid)
1459 * --
1460 * ret0 status
1461 */
1462 ENTRY_NP(piu_msiq_setvalid)
1463 VPCI_PRINT2("HV:msiq_setvalid ", %o1, %o2)
1464 cmp %o1, PIU_NEQS
1465 bgeu,pn %xcc, herr_inval
1466 .empty
1467 MSIEQNUM2MSIEQ(%g1, %o1, %g3, %g2, %g4)
1468
1469 ldx [%g3 + PIU_MSIEQ_GUEST], %g2 ! Guest Q base
1470 brnz %g2, 1f
1471 movrz %o2, PIU_COOKIE_EQCTLCLR, %g3
1472 brnz %o2, herr_inval
14731: movrnz %o2, PIU_COOKIE_EQCTLSET, %g3
1474 ldx [%g1 + %g3], %g3
1475 setx (1<<44), %g5, %g4
1476 REGNO2OFFSET(%o1, %g7)
1477 stx %g4, [%g3 + %g7]
1478 HCALL_RET(EOK)
1479 SET_SIZE(piu_msiq_setvalid)
1480
1481/*
1482 * piu_msiq_getstate
1483 *
1484 * %g1 = PIU Cookie Pointer
1485 * arg0 dev config pa (%o0)
1486 * arg1 MSI EQ id (%o1)
1487 * --
1488 * ret0 status (%o0)
1489 * ret1 EQ state (%o1) (0: Idle 1: Error)
1490 */
1491 ENTRY_NP(piu_msiq_getstate)
1492 VPCI_PRINT1("HV:msiq_getstate ", %o1)
1493 cmp %o1, PIU_NEQS
1494 bgeu,pn %xcc, herr_inval
1495 REGNO2OFFSET(%o1, %g4)
1496 ldx [%g1 + PIU_COOKIE_EQSTATE], %g2
1497 ldx [%g2 + %g4], %g3
1498 and %g3, 4, %o1
1499 movrnz %o1, HVIO_MSIQSTATE_ERROR, %o1
1500 HCALL_RET(EOK)
1501 SET_SIZE(piu_msiq_getstate)
1502
1503/*
1504 * piu_msiq_setstate
1505 *
1506 * %g1 = PIU Cookie Pointer
1507 * arg0 dev config pa (%o0)
1508 * arg1 MSI EQ id (%o1)
1509 * arg2 EQ state (%o2) (0: Idle 1: Error)
1510 * --
1511 * ret0 status (%o0)
1512 */
1513 ENTRY_NP(piu_msiq_setstate)
1514 VPCI_PRINT2("HV:msiq_setstate ", %o1, %o2)
1515 REGNO2OFFSET(%o1, %g4)
1516 cmp %o1, PIU_NEQS
1517 bgeu,pn %xcc, herr_inval
1518 .empty
1519 /*
1520 * To change state from error to idle, we set bits 57 and 47 in the
1521 * Event Queue Control Clear Register (CCR)
1522 *
1523 * To change state from idle to error, we set bits 44 and 57 in the
1524 * Event Queue Control Set Register (CSR)
1525 */
1526 mov PIU_COOKIE_EQCTLCLR, %g6 ! EQ CCR
1527 movrnz %o2, PIU_COOKIE_EQCTLSET, %g6 ! EQ CSR
1528 ldx [%g1 + %g6], %g2
1529 setx (1 << PIU_EQCCR_COVERR)|(1 << PIU_EQCCR_E2I_SHIFT), %g5, %g3 ! set idle
1530 setx (1 << PIU_EQCSR_ENOVERR)|(1 << PIU_EQCSR_EN_SHIFT), %g5, %g6 ! set error
1531 movrnz %o2, %g6, %g3
1532 stx %g3, [%g2 + %g4]
1533 HCALL_RET(EOK)
1534 SET_SIZE(piu_msiq_setstate)
1535
1536/*
1537 * piu_msiq_gethead
1538 *
1539 * %g1 = PIU Cookie Pointer
1540 * arg0 dev config pa (%o0)
1541 * arg1 MSI EQ id (%o1)
1542 * --
1543 * ret0 status
1544 * ret1 head index
1545 */
1546 ENTRY_NP(piu_msiq_gethead)
1547 VPCI_PRINT1("HV:msiq_gethead ", %o1)
1548 cmp %o1, PIU_NEQS
1549 bgeu,pn %xcc, herr_inval
1550 REGNO2OFFSET(%o1, %g4)
1551 ldx [%g1 + PIU_COOKIE_EQHEAD], %g2
1552 ldx [%g2 + %g4], %o1
1553 sllx %o1, PIU_EQREC_SHIFT, %o1
1554 HCALL_RET(EOK)
1555 SET_SIZE(piu_msiq_gethead)
1556
1557/*
1558 * piu_msiq_sethead
1559 *
1560 * %g1 = PIU Cookie Pointer
1561 * arg0 dev config pa (%o0)
1562 * arg1 MSI EQ id (%o1)
1563 * arg2 head offset (%o2)
1564 * --
1565 * ret0 status (%o0)
1566 */
1567 ENTRY_NP(piu_msiq_sethead)
1568 VPCI_PRINT2("HV:msiq_sethead ", %o1, %o2)
1569 cmp %o1, PIU_NEQS
1570 bgeu,pn %xcc, herr_inval
1571 set PIU_EQSIZE, %g2
1572 cmp %o2, %g2
1573 bgeu,pn %xcc, herr_inval
1574 REGNO2OFFSET(%o1, %g6)
1575 ldx [%g1 + PIU_COOKIE_EQHEAD], %g2
1576 ldx [%g2 + %g6], %g3
1577 mov %o2, %g6
1578 sllx %g3, PIU_EQREC_SHIFT, %g3
1579 !! %g1 = PIU COOKIE
1580 !! %g2 = EQ HEAD reg
1581 !! %g3 = Prev Head offset
1582 !! %g6 = New Head offset
1583 MSIEQNUM2MSIEQ(%g1, %o1, %g4, %g5, %g7)
1584 !! %g1 = PIU COOKIE
1585 !! %g2 = EQ HEAD reg
1586 !! %g3 = Prev Head offset
1587 !! %g4 = struct *piu_msieq
1588 !! %g6 = New Head offset
1589 ldx [%g4 + PIU_MSIEQ_BASE], %g5 /* HW Q base */
1590 add %g5, %g3, %g7
15911:
1592 stx %g0, [%g7 + 0x00]
1593 stx %g0, [%g7 + 0x08]
1594 stx %g0, [%g7 + 0x10]
1595 stx %g0, [%g7 + 0x18]
1596 stx %g0, [%g7 + 0x20]
1597 stx %g0, [%g7 + 0x28]
1598 stx %g0, [%g7 + 0x30]
1599 stx %g0, [%g7 + 0x38]
1600 add %g3, 0x40, %g3
1601 ldx [%g4 + PIU_MSIEQ_EQMASK], %g7
1602 and %g3, %g7, %g3
1603 cmp %g6, %g3
1604 bne 1b
1605 add %g5, %g3, %g7
1606 REGNO2OFFSET(%o1, %g6)
1607 srlx %o2, PIU_EQREC_SHIFT, %g3
1608 stx %g3, [%g2 + %g6]
1609 HCALL_RET(EOK)
1610 SET_SIZE(piu_msiq_sethead)
1611
1612/*
1613 * piu_msiq_gettail
1614 *
1615 * %g1 = PIU Cookie Pointer
1616 * arg0 dev config pa (%o0)
1617 * arg1 MSI EQ id (%o1)
1618 * --
1619 * ret0 status (%o0)
1620 * ret1 tail index (%o1)
1621 */
1622 ENTRY_NP(piu_msiq_gettail)
1623 VPCI_PRINT1("HV:msiq_gettail ", %o1)
1624 cmp %o1, PIU_NEQS
1625 bgeu,pn %xcc, herr_inval
1626 REGNO2OFFSET(%o1, %g4)
1627 ldx [%g1 + PIU_COOKIE_EQTAIL], %g2
1628 ldx [%g2 + %g4], %o1
1629 sllx %o1, PIU_EQREC_SHIFT, %o1
1630 HCALL_RET(EOK)
1631 SET_SIZE(piu_msiq_gettail)
1632
1633/*
1634 * piu_msi_getvalid
1635 *
1636 * %g1 = PIU Cookie Pointer
1637 * arg0 dev config pa (%o0)
1638 * arg1 MSI number (%o1)
1639 * --
1640 * ret0 status (%o0)
1641 * ret1 MSI status (%o1) (0: Invalid 1: Valid)
1642 */
1643 ENTRY_NP(piu_msi_getvalid)
1644 VPCI_PRINT1("HV:msiq_getvalid ", %o1)
1645 cmp %o1, PIU_MSI_MASK
1646 bgu,pn %xcc, herr_inval
1647 REGNO2OFFSET(%o1, %g4)
1648 ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
1649 ldx [%g2 + %g4], %g5
1650 mov HVIO_MSI_INVALID, %o1
1651 movrlz %g5, HVIO_MSI_VALID, %o1
1652 HCALL_RET(EOK)
1653 SET_SIZE(piu_msi_getvalid)
1654
1655/*
1656 * piu_msi_setvalid
1657 *
1658 * %g1 = PIU Cookie Pointer
1659 * arg0 dev config pa (%o0)
1660 * arg1 MSI number (%o1)
1661 * arg2 MSI status (%o2) (0: Invalid 1: Valid)
1662 * --
1663 * ret0 status (%o0)
1664 */
1665 ENTRY_NP(piu_msi_setvalid)
1666 VPCI_PRINT2("HV:msiq_setvalid ", %o1, %o2)
1667 cmp %o1, PIU_MSI_MASK
1668 bgu,pn %xcc, herr_inval
1669 REGNO2OFFSET(%o1, %g4)
1670 ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
1671 ldx [%g2 + %g4], %g5
1672 sllx %g5, 1, %g5
1673 srlx %g5, 1, %g5
1674 sllx %o2, PIU_MSIMR_V_SHIFT, %g3
1675 or %g5, %g3, %g5
1676 stx %g5, [%g2 + %g4]
1677 HCALL_RET(EOK)
1678 SET_SIZE(piu_msi_setvalid)
1679
1680/*
1681 * piu_msi_getstate
1682 *
1683 * %g1 = PIU Cookie Pointer
1684 * arg0 dev config pa (%o0)
1685 * arg1 MSI number (%o1)
1686 * --
1687 * ret0 status (%o0)
1688 * ret1 MSI state (%o1) (0: Idle 1: Delivered)
1689 */
1690 ENTRY_NP(piu_msi_getstate)
1691 VPCI_PRINT1("HV:msi_getstate ", %o1)
1692 cmp %o1, PIU_MSI_MASK
1693 bgu,pn %xcc, herr_inval
1694 REGNO2OFFSET(%o1, %g4)
1695 ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
1696 ldx [%g2 + %g4], %g5
1697 brlz,pn %g5, 0f
1698 mov HVIO_MSI_INVALID, %o1
1699 HCALL_RET(EOK)
1700
17010: srlx %g5, PIU_MSIMR_EQWR_N_SHIFT, %o1
1702 and %o1, HVIO_MSI_VALID, %o1
1703 HCALL_RET(EOK)
1704 SET_SIZE(piu_msi_getstate)
1705
1706/*
1707 * piu_msi_setstate
1708 *
1709 * %g1 = PIU Cookie Pointer
1710 * arg0 dev config pa (%o0)
1711 * arg1 MSI number (%o1)
1712 * arg2 MSI state (%o2) (0: Idle)
1713 * --
1714 * ret0 status (%o0)
1715 */
1716 ENTRY_NP(piu_msi_setstate)
1717 VPCI_PRINT2("HV:msi_setstate ", %o1, %o2)
1718 cmp %o1, PIU_MSI_MASK
1719 bgu,pn %xcc, herr_inval
1720 REGNO2OFFSET(%o1, %g4)
1721 brnz,pn %o2, herr_inval
1722 mov 1, %g5
1723 sllx %g5, PIU_MSIMR_EQWR_N_SHIFT, %g5
1724 ldx [%g1 + PIU_COOKIE_MSICLR], %g2
1725 stx %g5, [%g2 + %g4]
1726 HCALL_RET(EOK)
1727 SET_SIZE(piu_msi_setstate)
1728
1729/*
1730 * piu_msi_getmsiq
1731 *
1732 * %g1 = PIU Cookie Pointer
1733 * arg0 dev config pa (%o0)
1734 * arg1 MSI number (%o1)
1735 * --
1736 * ret0 status (%o0)
1737 * ret1 MSI EQ id (%o1)
1738 */
1739 ENTRY_NP(piu_msi_getmsiq)
1740 VPCI_PRINT1("HV:msi_getmsiq ", %o1)
1741 cmp %o1, PIU_MSI_MASK
1742 bgu,pn %xcc, herr_inval
1743 REGNO2OFFSET(%o1, %g7)
1744 ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
1745 ldx [%g2 + %g7], %o1
1746 and %o1, PIU_MSIEQNUM_MASK, %o1
1747 HCALL_RET(EOK)
1748 SET_SIZE(piu_msi_getmsiq)
1749
1750/*
1751 * piu_msi_setmsiq
1752 *
1753 * %g1 = PIU Cookie Pointer
1754 * arg0 dev config pa (%o0)
1755 * arg1 MSI number (%o1)
1756 * arg2 MSI EQ id (%o2)
1757 * arg3 MSI type (%o3) (MSI32=0 MSI64=1)
1758 * --
1759 * ret0 status (%o0)
1760 */
1761 ENTRY_NP(piu_msi_setmsiq)
1762 VPCI_PRINT2("HV:msi_setmsiq ", %o1, %o2)
1763 cmp %o1, PIU_MSI_MASK
1764 bgu,pn %xcc, herr_inval
1765 cmp %o2, PIU_NEQS
1766 bgeu,pn %xcc, herr_inval
1767 ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
1768 REGNO2OFFSET(%o1, %g7)
1769 ldx [%g2 + %g7], %g5
1770 andn %g5, PIU_MSIEQNUM_MASK, %g5
1771 or %g5, %o2, %g5
1772 stx %g5, [%g2 + %g7]
1773 HCALL_RET(EOK)
1774 SET_SIZE(piu_msi_setmsiq)
1775
1776/*
1777 * piu_msi_msg_getmsiq
1778 *
1779 * %g1 = PIU Cookie Pointer
1780 * arg0 dev config pa (%o0)
1781 * arg1 MSI msg type (%o1)
1782 * --
1783 * ret0 status (%o0)
1784 * ret1 MSI EQ id (%o1)
1785 */
1786 ENTRY_NP(piu_msi_msg_getmsiq)
1787 VPCI_PRINT1("HV:msi_msg_getmsiq ", %o1)
1788 ldx [%g1 + PIU_COOKIE_MSGMAP], %g2
1789 cmp %o1, PCIE_CORR_MSG
1790 be,a,pn %xcc, 1f
1791 mov PIU_CORR_OFF, %g3
1792 cmp %o1, PCIE_NONFATAL_MSG
1793 be,a,pn %xcc, 1f
1794 mov PIU_NONFATAL_OFF, %g3
1795 cmp %o1, PCIE_FATAL_MSG
1796 be,a,pn %xcc, 1f
1797 mov PIU_FATAL_OFF, %g3
1798 cmp %o1, PCIE_PME_MSG
1799 be,a,pn %xcc, 1f
1800 mov PIU_PME_OFF, %g3
1801 cmp %o1, PCIE_PME_ACK_MSG
1802 be,a,pn %xcc, 1f
1803 mov PIU_PME_ACK_OFF, %g3
1804 ba herr_inval
1805 nop
18061: ldx [%g2 + %g3], %o1
1807 and %o1, PIU_MSIEQNUM_MASK, %o1
1808 HCALL_RET(EOK)
1809 SET_SIZE(piu_msi_msg_getmsiq)
1810
1811/*
1812 * piu_msi_msg_setmsiq
1813 *
1814 * %g1 = PIU Cookie Pointer
1815 * arg0 dev config pa (%o0)
1816 * arg1 MSI msg type (%o1)
1817 * arg2 MSI EQ id (%o2)
1818 * --
1819 * ret0 status (%o0)
1820 */
1821 ENTRY_NP(piu_msi_msg_setmsiq)
1822 VPCI_PRINT2("HV:msi_msg_setmsiq ", %o1, %o2)
1823 cmp %o2, PIU_NEQS
1824 bgeu,pn %xcc, herr_inval
1825 ldx [%g1 + PIU_COOKIE_MSGMAP], %g2
1826 cmp %o1, PCIE_CORR_MSG
1827 be,a,pn %xcc, 1f
1828 mov PIU_CORR_OFF, %g3
1829 cmp %o1, PCIE_NONFATAL_MSG
1830 be,a,pn %xcc, 1f
1831 mov PIU_NONFATAL_OFF, %g3
1832 cmp %o1, PCIE_FATAL_MSG
1833 be,a,pn %xcc, 1f
1834 mov PIU_FATAL_OFF, %g3
1835 cmp %o1, PCIE_PME_MSG
1836 be,a,pn %xcc, 1f
1837 mov PIU_PME_OFF, %g3
1838 cmp %o1, PCIE_PME_ACK_MSG
1839 be,a,pn %xcc, 1f
1840 mov PIU_PME_ACK_OFF, %g3
1841 ba herr_inval
1842 nop
18431: ldx [%g2 + %g3], %g4
1844 andn %g4, PIU_MSIEQNUM_MASK, %g4
1845 or %g4, %o2, %g4
1846 stx %g4, [%g2 + %g3]
1847 HCALL_RET(EOK)
1848 SET_SIZE(piu_msi_msg_setmsiq)
1849
1850/*
1851 * piu_msi_msg_getvalid
1852 *
1853 * %g1 = PIU Cookie Pointer
1854 * arg0 dev config pa (%o0)
1855 * arg1 MSI msg type (%o1)
1856 * --
1857 * ret0 status (%o0)
1858 * ret1 MSI msg valid state (%o1)
1859 */
1860 ENTRY_NP(piu_msi_msg_getvalid)
1861 VPCI_PRINT1("HV:msi_msg_getvalid ", %o1)
1862 ldx [%g1 + PIU_COOKIE_MSGMAP], %g2
1863 cmp %o1, PCIE_CORR_MSG
1864 be,a,pn %xcc, 1f
1865 ldx [%g2 + PIU_CORR_OFF], %g3
1866 cmp %o1, PCIE_NONFATAL_MSG
1867 be,a,pn %xcc, 1f
1868 ldx [%g2 + PIU_NONFATAL_OFF], %g3
1869 cmp %o1, PCIE_FATAL_MSG
1870 be,a,pn %xcc, 1f
1871 ldx [%g2 + PIU_FATAL_OFF], %g3
1872 cmp %o1, PCIE_PME_MSG
1873 be,a,pn %xcc, 1f
1874 ldx [%g2 + PIU_PME_OFF], %g3
1875 cmp %o1, PCIE_PME_ACK_MSG
1876 be,a,pn %xcc, 1f
1877 ldx [%g2 + PIU_PME_ACK_OFF], %g3
1878 ba,pt %xcc, herr_inval
1879 nop
18801: movrlz %g3, HVIO_PCIE_MSG_VALID, %o1
1881 movrgez %g3, HVIO_PCIE_MSG_INVALID, %o1
1882 HCALL_RET(EOK)
1883 SET_SIZE(piu_msi_msg_getvalid)
1884
1885/*
1886 * piu_msi_msg_setvalid
1887 *
1888 * %g1 = PIU Cookie Pointer
1889 * arg0 dev config pa (%o0)
1890 * arg1 MSI msg type (%o1)
1891 * arg2 MSI msg valid state (%o2)
1892 * --
1893 * ret0 status (%o0)
1894 */
1895 ENTRY_NP(piu_msi_msg_setvalid)
1896 VPCI_PRINT2("HV:msi_msg_setvalid ", %o1, %o2)
1897 cmp %o2, 1
1898 bgu,pn %xcc, herr_inval
1899 ldx [%g1 + PIU_COOKIE_MSGMAP], %g2
1900 cmp %o1, PCIE_CORR_MSG
1901 be,a,pn %xcc, 1f
1902 mov PIU_CORR_OFF, %g3
1903 cmp %o1, PCIE_NONFATAL_MSG
1904 be,a,pn %xcc, 1f
1905 mov PIU_NONFATAL_OFF, %g3
1906 cmp %o1, PCIE_FATAL_MSG
1907 be,a,pn %xcc, 1f
1908 mov PIU_FATAL_OFF, %g3
1909 cmp %o1, PCIE_PME_MSG
1910 be,a,pn %xcc, 1f
1911 mov PIU_PME_OFF, %g3
1912 cmp %o1, PCIE_PME_ACK_MSG
1913 be,a,pn %xcc, 1f
1914 mov PIU_PME_ACK_OFF, %g3
1915 ba herr_inval
1916 nop
19171:
1918 sllx %o2, PIU_MSGMR_V_SHIFT, %g5
1919 ldx [%g2 + %g3], %g4
1920 sllx %g4, 1, %g4
1921 srlx %g4, 1, %g4
1922 or %g4, %g5, %g4
1923 stx %g4, [%g2 + %g3]
1924 HCALL_RET(EOK)
1925 SET_SIZE(piu_msi_msg_setvalid)
1926
1927/*
1928 * piu_msi_mondo_receive
1929 *
1930 * %g1 = PIU Cookie
1931 * %g2 = Mondo DATA0
1932 * %g3 = Mondo DATA1
1933 */
1934 ENTRY_NP(piu_msi_mondo_receive)
1935 STRAND_PUSH(%g1, %g6, %g7)
1936 STRAND_PUSH(%g2, %g6, %g7)
1937 STRAND_PUSH(%g3, %g6, %g7)
1938 ba insert_device_mondo_r
1939 rd %pc, %g7
1940 STRAND_POP(%g3, %g6)
1941 STRAND_POP(%g2, %g6)
1942 STRAND_POP(%g1, %g6)
1943
1944 and %g2, PIU_DEVINO_MASK, %g2
1945 sub %g2, PIU_EQ2INO(0), %g2
1946 MSIEQNUM2MSIEQ(%g1, %g2, %g3, %g4, %g5)
1947 ! %g1 = PIU Cookie
1948 ! %g2 = MSI EQ Number
1949 ! %g3 = struct *piu_msieq
1950 REGNO2OFFSET(%g2, %g2)
1951 ldx [%g1 + PIU_COOKIE_EQTAIL], %g5
1952 ldx [%g5 + %g2], %g7
1953 ldx [%g1 + PIU_COOKIE_EQHEAD], %g5
1954 ldx [%g5 + %g2], %g6
1955
1956 ! %g1 = PIU COOKIE
1957 ! %g2 = MSI EQ OFFSET
1958 ! %g3 = struct piu_msieq *
1959 ! %g6 = Head
1960 ! %g7 = New Tail
1961 cmp %g6, %g7
1962 be 9f
1963 sllx %g6, PIU_EQREC_SHIFT, %g6 /* New tail offset */
1964 sllx %g7, PIU_EQREC_SHIFT, %g7 /* Old Tail offset */
1965
1966 ldx [%g3 + PIU_MSIEQ_GUEST], %g2 /* Guest Q base */
1967 brz,pn %g2, 9f
1968 ldx [%g3 + PIU_MSIEQ_BASE], %g5 /* HW Q base */
1969
1970 ! %g2 = Guest Q base
1971 ! %g3 = struct piu_msieq *
1972 ! %g5 = HW Q base
1973 ! %g6 = Old Tail
1974 ! %g7 = New Tail
1975 ! %g1 = scratch
1976 ! %g4 = scratch
1977
19781:
1979 ! Word 0 is TTTT EQW0[63:61]
1980 ldx [%g5 + %g6], %g1 ! Read Word 0 From HW
1981 stx %g1, [%g3 + PIU_MSIEQ_WORD0]
1982
1983 srlx %g1, PIU_EQREC_TYPE_SHIFT+5, %g4
1984 stx %g4, [%g2 + %g6] ! Store Word 0
1985 add %g6, 8, %g6
1986
1987 ldx [%g5 + %g6], %g4 ! Read Word 1 from HW
1988 stx %g4, [%g3 + PIU_MSIEQ_WORD1]
1989
1990 stx %g0, [%g2 + %g6] ! Store Word 1 = 0
1991 add %g6, 8, %g6
1992
1993 stx %g0, [%g2 + %g6] ! Store Word 2 = 0
1994 add %g6, 8, %g6
1995
1996 stx %g0, [%g2 + %g6] ! Store Word 3 = 0
1997 add %g6, 8, %g6
1998
1999 ! Word 4 is RRRR.RRRR EQW0[31:16]
2000 sllx %g1, 64-(MSIEQ_RID_SHIFT+MSIEQ_RID_SIZE_BITS), %g4
2001 srlx %g4, 64-MSIEQ_RID_SHIFT, %g4
2002
2003 stx %g4, [%g2 + %g6] ! Store Word 4
2004 add %g6, 8, %g6
2005
2006 ! Word 5 is MSI address EQW1[63:0]
2007 ldx [%g3 + PIU_MSIEQ_WORD1], %g4
2008 stx %g4, [%g2 + %g6] ! Store Word 5
2009 add %g6, 8, %g6
2010
2011 ! Word 6 is MSI Data EQW0[15:0]
2012 sllx %g1, 1, %g4
2013 brgz,pt %g4, 2f
2014 sllx %g1, 64-MSIEQ_DATA_SIZE_BITS, %g4
2015 ! MSI
2016 srlx %g4, 64-MSIEQ_DATA_SIZE_BITS, %g4
2017 stx %g4, [%g2 + %g6] ! Store Word 6
2018 ba 3f
2019 add %g6, 8, %g6
2020
20212: ! MSG
2022 ! %g1 = HW Word 0
2023
2024 ! Extract GGGG.GGGG EQW0[31:16] -> W6[47:32]
2025 srlx %g1, MSIEQ_TID_SHIFT, %g4
2026 sllx %g4, 64-MSIEQ_TID_SIZE_BITS, %g4
2027 srlx %g4, 64-(MSIEQ_TID_SIZE_BITS+VPCI_MSIEQ_TID_SHIFT), %g4
2028
2029 ldx [%g3 + PIU_MSIEQ_WORD0], %g1
2030
2031 ! Extract CCC field EQW0[58:56] -> W6[18:16]
2032 sllx %g1, 64-(MSIEQ_MSG_RT_CODE_SHIFT+MSIEQ_MSG_RT_CODE_SIZE_BITS), %g1
2033 srlx %g1, 64-MSIEQ_MSG_RT_CODE_SIZE_BITS, %g1
2034 sllx %g1, VPCI_MSIEQ_MSG_RT_CODE_SHIFT, %g1
2035 or %g1, %g4, %g4
2036
2037 ldx [%g3 + PIU_MSIEQ_WORD0], %g1
2038
2039 ! Extract MMMM.MMMM field EQW0[7:0] -> W6[7:0]
2040 sllx %g1, 64-MSIEQ_MSG_CODE_SIZE_BITS, %g1
2041 srlx %g1, 64-MSIEQ_MSG_CODE_SIZE_BITS, %g1
2042 or %g1, %g4, %g4
2043 stx %g4, [%g2 + %g6] ! Store Word 6
2044 add %g6, 8, %g6
20453:
2046 stx %g0, [%g2 + %g6] ! Store Word 7
2047 add %g6, 8, %g6
2048
2049 ldx [%g3 + PIU_MSIEQ_EQMASK], %g4
2050 and %g6, %g4, %g6
2051 cmp %g6, %g7
2052 bne 1b
2053 nop
20549:
2055 retry
2056 SET_SIZE(piu_msi_mondo_receive)
2057
2058
2059
2060/*
2061 * Each register entry is 0x20 bytes
2062 */
2063#define PIU_PERF_READ_ADR (0 * SIZEOF_UI64)
2064#define PIU_PERF_READ_MASK (1 * SIZEOF_UI64)
2065#define PIU_PERF_WRITE_ADR (2 * SIZEOF_UI64)
2066#define PIU_PERF_WRITE_MASK (3 * SIZEOF_UI64)
2067#define PIU_PERF_TBL_ENTRY_SIZE (4 * SIZEOF_UI64)
2068#define PIU_PERF_TBL_ENTRY_SHIFT 5 /* log2(TBL_ENTRY_SIZE) */
2069#define PIU_PERF_TBL_NENTRIES ((piu_perf_regs_table_end - \
2070 piu_perf_regs_table) / PIU_PERF_TBL_ENTRY_SIZE)
2071#define PIU_REGID2OFFSET(id, offset) \
2072 sllx id, PIU_PERF_TBL_ENTRY_SHIFT, offset
2073
2074 .align 8
2075 .section ".text"
2076piu_perf_regs_table:
2077 ! Registers 0 - 2
2078 .xword PIU_DLC_IMU_ICS_IMU_PERF_CNTRL, 0x000000000000ffff
2079 .xword PIU_DLC_IMU_ICS_IMU_PERF_CNTRL, 0x000000000000ffff
2080 .xword PIU_DLC_IMU_ICS_IMU_PERF_CNT0, 0xffffffffffffffff
2081 .xword PIU_DLC_IMU_ICS_IMU_PERF_CNT0, 0xffffffffffffffff
2082 .xword PIU_DLC_IMU_ICS_IMU_PERF_CNT1, 0xffffffffffffffff
2083 .xword PIU_DLC_IMU_ICS_IMU_PERF_CNT1, 0xffffffffffffffff
2084 ! Registers 3 - 5
2085 .xword PIU_DLC_MMU_PRFC, 0x000000000000ffff
2086 .xword PIU_DLC_MMU_PRFC, 0x000000000000ffff
2087 .xword PIU_DLC_MMU_PRF0, 0xffffffffffffffff
2088 .xword PIU_DLC_MMU_PRF0, 0xffffffffffffffff
2089 .xword PIU_DLC_MMU_PRF1, 0xffffffffffffffff
2090 .xword PIU_DLC_MMU_PRF1, 0xffffffffffffffff
2091 ! Registers 6 - 9
2092 .xword PIU_PLC_TLU_CTB_TLR_TLU_PRFC, 0x000000000003ffff
2093 .xword PIU_PLC_TLU_CTB_TLR_TLU_PRFC, 0x000000000003ffff
2094 .xword PIU_PLC_TLU_CTB_TLR_TLU_PRF0, 0xffffffffffffffff
2095 .xword PIU_PLC_TLU_CTB_TLR_TLU_PRF0, 0xffffffffffffffff
2096 .xword PIU_PLC_TLU_CTB_TLR_TLU_PRF1, 0xffffffffffffffff
2097 .xword PIU_PLC_TLU_CTB_TLR_TLU_PRF1, 0xffffffffffffffff
2098 .xword PIU_PLC_TLU_CTB_TLR_TLU_PRF2, 0x00000000ffffffff
2099 .xword PIU_PLC_TLU_CTB_TLR_TLU_PRF2, 0x00000000ffffffff
2100 ! Registers 10 - 11
2101 .xword PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_BIT_ERR_CNT_1_ADDR, 0xc0000000ffff003f
2102 .xword PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_BIT_ERR_CNT_1_ADDR, 0xc000000000000000
2103 .xword PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_BIT_ERR_CNT_2_ADDR, 0x3f3f3f3f3f3f3f3f
2104 .xword PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_BIT_ERR_CNT_2_ADDR, 0x0000000000000000
2105piu_perf_regs_table_end:
2106
2107/*
2108 * piu_get_perf_reg
2109 *
2110 * %g1 = PIU Cookie Pointer
2111 * arg0 dev config pa (%o0)
2112 * arg1 perf reg ID (%o1)
2113 * --
2114 * ret0 status (%o0)
2115 * ret1 value (%o1)
2116 */
2117 ENTRY_NP(piu_get_perf_reg)
2118 cmp %o1, PIU_PERF_TBL_NENTRIES
2119 bgeu,pn %xcc, herr_inval
2120 mov 1, %g3
2121 sllx %g3, %o1, %g3
2122 ldx [%g1 + PIU_COOKIE_PERFREGS], %g2
2123 and %g2, %g3, %g3
2124 brz,pn %g3, herr_inval
2125 ldx [%g1 + PIU_COOKIE_PCIE], %g2
2126
2127 ! %g1 = PIU cookie pointer
2128 ! %g2 = PIU base PA
2129 LABEL_ADDRESS(piu_perf_regs_table, %g4)
2130
2131 ! %g1 = PIU cookie pointer
2132 ! %g2 = PIU base PA
2133 ! %g4 = Performance regs table
2134 PIU_REGID2OFFSET(%o1, %g3)
2135 add %g3, %g4, %g4
2136 ldx [%g4 + PIU_PERF_READ_ADR], %g3
2137 ldx [%g4 + PIU_PERF_READ_MASK], %g4
2138
2139 ! %g1 = PIU cookie pointer
2140 ! %g2 = PIU base PA
2141 ! %g3 = Perf reg offset
2142 ! %g4 = Perf reg mask
2143 ldx [%g2 + %g3], %o1
2144 and %o1, %g4, %o1
2145 HCALL_RET(EOK)
2146 SET_SIZE(piu_get_perf_reg)
2147
2148/*
2149 * piu_set_perf_reg
2150 *
2151 * %g1 = PIU Cookie Pointer
2152 * arg0 dev config pa (%o0)
2153 * arg1 perf reg ID (%o1)
2154 * arg2 value (%o2)
2155 * --
2156 * ret0 status (%o0)
2157 */
2158 ENTRY_NP(piu_set_perf_reg)
2159 cmp %o1, PIU_PERF_TBL_NENTRIES
2160 bgeu,pn %xcc, herr_inval
2161 mov 1, %g3
2162 sllx %g3, %o1, %g3
2163 ldx [%g1 + PIU_COOKIE_PERFREGS], %g2
2164 and %g2, %g3, %g3
2165 brz,pn %g3, herr_inval
2166 ldx [%g1 + PIU_COOKIE_PCIE], %g2
2167
2168 ! %g1 = PIU cookie pointer
2169 ! %g2 = PIU base PA
2170 LABEL_ADDRESS(piu_perf_regs_table, %g4)
2171
2172 ! %g1 = PIU cookie pointer
2173 ! %g2 = PIU base PA
2174 ! %g4 = Performance regs table
2175 PIU_REGID2OFFSET(%o1, %g3)
2176 add %g3, %g4, %g4
2177 ldx [%g4 + PIU_PERF_WRITE_ADR], %g3
2178 ldx [%g4 + PIU_PERF_WRITE_MASK], %g4
2179
2180 ! %g1 = PIU cookie pointer
2181 ! %g2 = PIU base PA
2182 ! %g3 = Perf reg offset
2183 ! %g4 = Perf reg mask
2184 and %o2, %g4, %g5
2185 stx %g5, [%g2 + %g3]
2186 HCALL_RET(EOK)
2187 SET_SIZE(piu_set_perf_reg)
2188
2189
2190#ifdef DEBUG
2191! When DEBUG is defined hcall.s versions
2192! of these are labels are too far away
2193herr_nocpu: HCALL_RET(ENOCPU)
2194herr_nomap: HCALL_RET(ENOMAP)
2195herr_inval: HCALL_RET(EINVAL)
2196herr_badalign: HCALL_RET(EBADALIGN)
2197#endif
2198
2199
2200#define PIU_INVALIDATE_INTX(piup, intx_off, scr1, scr2) \
2201 ldx [piup + PIU_COOKIE_PCIE], scr1 ;\
2202 set intx_off, scr2 ;\
2203 add scr1, scr2, scr1 ;\
2204 set 1, scr2 ;\
2205 stx scr2, [scr1]
2206
2207/*
2208 * PIU_MSIQ_UNCONFIGURE
2209 *
2210 * piu - (preserved) PIU Cookie Pointer
2211 * msieq_id - (preserved) MSI EQ id
2212 *
2213 */
2214#define PIU_MSIQ_UNCONFIGURE(piu, msieq_id, scr1, scr2, scr3, scr4) \
2215 .pushlocals ;\
2216 cmp msieq_id, PIU_NEQS ;\
2217 bgeu,pn %xcc, 0f ;\
2218 MSIEQNUM2MSIEQ(piu, msieq_id, scr3, scr2, scr1) ;\
2219 REGNO2OFFSET(msieq_id, scr4) ;\
2220 ldx [piu + PIU_COOKIE_EQHEAD], scr1 ;\
2221 ldx [piu + PIU_COOKIE_EQTAIL], scr2 ;\
2222 stx %g0, [scr1 + scr4] ;\
2223 stx %g0, [scr2 + scr4] ;\
2224 stx %g0, [scr3 + PIU_MSIEQ_GUEST] ;\
22250: ;\
2226 .poplocals
2227
2228
2229/*
2230 * PIU_MSIQ_INVALIDATE
2231 *
2232 * piu - (preserved) PIU Cookie Pointer
2233 * msieq_id - (preserved) MSI EQ id
2234 *
2235 */
2236#define PIU_MSIQ_INVALIDATE(piu, msieq_id, scr1, scr2, scr3, scr4) \
2237 .pushlocals ;\
2238 cmp msieq_id, PIU_NEQS ;\
2239 bgeu,pn %xcc, 0f ;\
2240 nop ;\
2241 ldx [piu + PIU_COOKIE_EQCTLCLR], scr1 ;\
2242 /* setx (1<<44), scr3, scr2 */ ;\
2243 /* 44=disable, 47=e2i 57=coverr */ ;\
2244 setx (1<<44)|(1<<47)|(1<<57), scr3, scr2 ;\
2245 REGNO2OFFSET(msieq_id, scr4) ;\
2246 stx scr2, [scr1 + scr4] ;\
22470: ;\
2248 .poplocals
2249
2250
2251/*
2252 * PIU_MSI_INVALIDATE - Invalidate the MSI mappings and then clear
2253 * the MSI status (mark as "idle")
2254 *
2255 * piu - (preserved) PIU Cookie Pointer
2256 * msi_num - (preserved) MSI number (%o1)
2257 *
2258 */
2259#define PIU_MSI_INVALIDATE(piu, msi_num, scr1, scr2, scr3) \
2260 .pushlocals ;\
2261 cmp msi_num, PIU_MSI_MASK ;\
2262 bgu,pn %xcc, 0f ;\
2263 REGNO2OFFSET(msi_num, scr2) ;\
2264 ldx [piu + PIU_COOKIE_MSIMAP], scr1 ;\
2265 ldx [scr1 + scr2], scr3 ;\
2266 /* clear both bits 62 and 63 in the map reg */ ;\
2267 /* valid and ok to write (pending MSI) bit */ ;\
2268 sllx scr3, 2, scr3 ;\
2269 srlx scr3, 2, scr3 ;\
2270 stx scr3, [scr1 + scr2] ;\
2271 mov 1, scr3 /* now mark status as "idle" */ ;\
2272 sllx scr3, PIU_MSIMR_EQWR_N_SHIFT, scr3 ;\
2273 ldx [piu + PIU_COOKIE_MSICLR], scr1 ;\
2274 stx scr3, [scr1 + scr2] ;\
22750: ;\
2276 .poplocals
2277
2278
2279/*
2280 * PIU_MSI_MSG_INVALIDATE
2281 *
2282 * piu - (preserved) PIU Cookie Pointer
2283 * msg_offset - (preserved) message offset such as PIU_CORR_OFF,
2284 * PIU_NONFATAL_OFF, etc. (reg or contant)
2285 *
2286 */
2287#define PIU_MSI_MSG_INVALIDATE(piu, msg_offset, scr1, scr2) \
2288 ldx [piu+ PIU_COOKIE_MSGMAP], scr1 ;\
2289 ldx [scr1 + msg_offset], scr2 ;\
2290 sllx scr2, 1, scr2 ;\
2291 srlx scr2, 1, scr2 ;\
2292 stx scr2, [scr1 + msg_offset]
2293
2294 ! %g1 PIU cookie
2295 ! %g7 return address
2296 ENTRY(piu_leaf_soft_reset)
2297
2298 !
2299 ! if piu is blacklisted just skip this
2300 !
2301 lduw [%g1 + PIU_COOKIE_BLACKLIST], %g4
2302 brnz,pn %g4, skip_piu_leaf_soft_reset
2303 nop
2304 !
2305 ! Disable Link errors
2306 !
2307 DISABLE_PCIE_LUP_LDN_ERRORS(%g1, %g4, %g5, %g6)
2308 membar #Sync
2309
2310 !
2311 ! Put STRAND in protected mode
2312 !
2313 STRAND_STRUCT(%g4)
2314 mov 1, %g5
2315 set STRAND_IO_PROT, %g6
2316 stx %g5, [%g4 + %g6]
2317 membar #Sync
2318
2319 ! clear the IOTSB
2320 mov %g1, %g6
2321 mov %g7, %g5
2322 ldx [%g1 + PIU_COOKIE_IOTSB0], %g1
2323 set IOTSB0_SIZE, %g2
2324 HVCALL(bzero)
2325 mov %g6, %g1
2326 mov %g5, %g7
2327
2328
2329 ! %g1 piu struct
2330
2331 !
2332 ! Do secondary reset and initialize upstream port)
2333 !
2334 mov PIU_RESET_MAX_ATTEMPTS, %g3
23350:
2336 STRAND_PUSH(%g3, %g4, %g5)
2337 mov %g0, %g2 ! %g2 bus
2338 RESET_PIU_LEAF(%g1, %g2, %g3, %g4, %g5, %g6)
2339 membar #Sync
2340 STRAND_POP(%g3, %g4)
2341
2342 !
2343 ! Verify that the PIU link came up in x8 mode
2344 ! Give the Link Status a chance to update first
2345 !
2346 CPU_MSEC_DELAY(300, %g2, %g4, %g5)
2347
2348 set PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_ADDR, %g4
2349 ldx [%g1 + PIU_COOKIE_PCIE], %g2
2350 ldx [%g2 + %g4], %g2
2351#ifdef DEBUG
2352 mov %g7, %g5
2353 PRINT("PIU Link Status Register after leaf reset 0x")
2354 PRINTX(%g2)
2355 PRINT("\r\n")
2356 mov %g5, %g7
2357#endif
2358 srlx %g2, PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_WIDTH_SHIFT, %g2
2359 and %g2, PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_WIDTH_MASK, %g2
2360 cmp %g2, PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_WIDTH_x8
2361 be,pt %xcc, 1f ! link width x8, continue
2362 dec %g3
2363 brgz,pt %g3, 0b ! < PIU_RESET_MAX_ATTEMPTS ?
2364 nop
2365
2366 !
2367 ! we have exhausted the PIU link training retry limit, blacklist
2368 ! the device and move on
2369 !
2370 mov 1, %g4
2371 ba,pn %xcc, piu_leaf_soft_reset_exit
2372 stw %g4, [%g1 + PIU_COOKIE_BLACKLIST]
23731:
2374
2375 !
2376 ! Invalidate any pending legacy (level) interrupts
2377 ! that were previously signalled from switches we just reset
2378 !
2379
2380 PIU_INVALIDATE_INTX(%g1, PCI_E_INT_A_CLEAR_ADDR, %g2, %g4)
2381 PIU_INVALIDATE_INTX(%g1, PCI_E_INT_B_CLEAR_ADDR, %g2, %g4)
2382 PIU_INVALIDATE_INTX(%g1, PCI_E_INT_C_CLEAR_ADDR, %g2, %g4)
2383 PIU_INVALIDATE_INTX(%g1, PCI_E_INT_D_CLEAR_ADDR, %g2, %g4)
2384
2385 !
2386 ! invalidate all MSIs
2387 !
2388 set PIU_MAX_MSIS - 1, %g2
23891: PIU_MSI_INVALIDATE(%g1, %g2, %g6, %g4, %g5)
2390 brgz,pt %g2, 1b
2391 dec %g2
2392 membar #Sync
2393
2394 !
2395 ! invalidate all MSI Messages
2396 !
2397 PIU_MSI_MSG_INVALIDATE(%g1, PIU_CORR_OFF, %g5, %g4)
2398 PIU_MSI_MSG_INVALIDATE(%g1, PIU_NONFATAL_OFF, %g5, %g4)
2399 PIU_MSI_MSG_INVALIDATE(%g1, PIU_FATAL_OFF, %g5, %g4)
2400 PIU_MSI_MSG_INVALIDATE(%g1, PIU_PME_OFF, %g5, %g4)
2401 PIU_MSI_MSG_INVALIDATE(%g1, PIU_PME_ACK_OFF, %g5, %g4)
2402
2403 !
2404 ! invalidate all interrupts
2405 !
2406 ! invalidate inos 63 and 62, special case ones not set with
2407 ! _piu_intr_setvalid
2408 ldx [%g1 + PIU_COOKIE_VIRTUAL_INTMAP], %g2
2409 add %g2, DMU_ERR_MONDO_OFFSET, %g2
2410 stb %g0, [%g2]
2411 ldx [%g1 + PIU_COOKIE_VIRTUAL_INTMAP], %g2
2412 add %g2, PEU_ERR_MONDO_OFFSET, %g2
2413 stb %g0, [%g2]
2414
2415 STRAND_PUSH(%g7, %g4, %g5) ! _piu_intr_setvalid clobbers all regs
2416 ! Don't invalidate inos 62 & 63 in this loop, 62 and 63 done above
2417 set NPIUDEVINO - 3, %g2
2418 clr %g3
24191: HVCALL(_piu_intr_setvalid) ! clobbers %g4-%g6
2420 cmp %g2, 20
2421 bgu,pt %xcc, 1b
2422 dec %g2
2423 membar #Sync
2424 STRAND_POP(%g7, %g4) ! restore clobbered value
2425
2426 !
2427 ! invalidate and unconfigure all MSI EQs
2428 !
2429 set PIU_NEQS - 1, %g2
24301: PIU_MSIQ_INVALIDATE(%g1, %g2, %g3, %g4, %g5, %g6)
2431 PIU_MSIQ_UNCONFIGURE(%g1, %g2, %g3, %g4, %g5, %g6)
2432 brgz,pt %g2, 1b
2433 dec %g2
2434 membar #Sync
2435
2436 !
2437 ! clear any pending error interrupts
2438 ! all these registers are RW1C
2439 !
2440 mov -1, %g3
2441 ldx [%g1 + PIU_COOKIE_PCIE], %g2
2442 set PIU_DLC_IMU_ICS_IMU_LOGGED_ERROR_STATUS_REG_RW1C_ALIAS, %g4
2443 stx %g3, [%g2 + %g4]
2444 set PIU_PLC_TLU_CTB_TLR_OE_ERR_RW1C_ALIAS, %g4
2445 stx %g3, [%g2 + %g4]
2446 set PCI_E_MMU_ERR_STAT_CL_ADDR, %g4
2447 stx %g3, [%g2 + %g4]
2448 set PCI_E_PEU_UE_STAT_CL_ADDR, %g4
2449 stx %g3, [%g2 + %g4]
2450 set PCI_E_ILU_ERR_STAT_CL_ADDR, %g4
2451 stx %g3, [%g2 + %g4]
2452 set PCI_E_PEU_CXPL_STAT_CL_ADDR, %g4
2453 stx %g3, [%g2 + %g4]
2454
2455 !
2456 ! re-enable errors
2457 !
2458 ENABLE_PCIE_LUP_LDN_ERRORS(%g1, %g2, %g4, %g5)
2459 membar #Sync
2460
2461piu_leaf_soft_reset_exit:
2462 !
2463 ! Bring STRAND out of protected mode
2464 !
2465 STRAND_STRUCT(%g4)
2466 set STRAND_IO_PROT, %g2
2467 stx %g0, [%g4 + %g2]
2468 set STRAND_IO_ERROR, %g2
2469 stx %g0, [%g4 + %g2]
2470
2471skip_piu_leaf_soft_reset:
2472
2473 HVRET
2474
2475 SET_SIZE(piu_leaf_soft_reset)
2476
2477 /*
2478 * Wrapper around piu_leaf_soft_reset() so that it can be called from C
2479 * SPARC ABI requries only that g2,g3,g4 are preserved across
2480 * function calls.
2481 * %o0 = PIU cookie
2482 * %o1 = root complex bus number (0)
2483 *
2484 * void c_piu_leaf_soft_reset(struct pcie_cookie *, uint64 root)
2485 */
2486
2487 ENTRY(c_piu_leaf_soft_reset)
2488
2489 STRAND_PUSH(%g2, %g6, %g7)
2490 STRAND_PUSH(%g3, %g6, %g7)
2491 STRAND_PUSH(%g4, %g6, %g7)
2492
2493 mov %o0, %g1 ! %g1 PIU cookie
2494 HVCALL(piu_leaf_soft_reset)
2495
2496 STRAND_POP(%g4, %g6)
2497 STRAND_POP(%g3, %g6)
2498 STRAND_POP(%g2, %g6)
2499
2500 retl
2501 nop
2502 SET_SIZE(c_piu_leaf_soft_reset)
2503
2504 /*
2505 * FIXME: The following link up/down functions are not ready
2506 * for use yet, awaiting more information
2507 */
2508
2509 /*
2510 * This macro brings a given PIU leaf's link up
2511 *
2512 * Inputs:
2513 *
2514 * piu - (preserved) pointer to PIU_COOKIE
2515 *
2516 * Bring up a piu link. Returns false on failure.
2517 */
2518 ENTRY(piu_link_up)
2519
2520 PIU_LINK_UP(%o0, %o1, %o2, %o3)
2521
2522 retl
2523 mov 1, %o0
2524 SET_SIZE(piu_link_up)
2525
2526 /*
2527 * This function brings a given piu leaf's link down
2528 * Inputs:
2529 *
2530 * piu - (preserved) pointer to PIU_COOKIE
2531 * Returns:
2532 * false (0) on failure.
2533 */
2534 ENTRY(piu_link_down)
2535
2536 /* get the base addr of RC control regs */
2537 ldx [ %o0 + PIU_COOKIE_PCIE ], %o1
2538 /* And now the actual reset code... */
2539 /* Remain in detect quiesce */
2540 ! PEU control register
2541 set PIU_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_ADDR, %o2
2542 ldx [ %o1 + %o2 ], %o3
2543 bset (1 << 8), %o3
2544 stx %o3, [ %o1 + %o2]
2545
2546 ! Disable link - set bit 4 of PEU Link Control register
2547 set PIU_PLC_TLU_CTB_TLR_LNK_CTL, %o2
2548 ldx [ %o1 + %o2], %o3
2549 bset (1 << 4), %o3
2550 stx %o3, [ %o1 + %o2]
2551
2552 ! Wait for link to go down
2553 setx PIU_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_ADDR, %o4, %o2
25541:
2555 ldx [ %o1 + %o2 ], %o3
2556 andcc %o3, 0x7, %o3 ! status bits [2:0]
2557 cmp %o3, 0x1 ! data link inactive
2558 bne,pt %xcc, 1b
2559 nop
2560
2561
2562 retl
2563 mov 1, %o0
2564 SET_SIZE(piu_link_down)
2565
2566 /*
2567 * Check and see if a PIU link is up. Returns true on
2568 * success, false on failure.
2569 */
2570 ENTRY(is_piu_port_link_up)
2571 ldx [ %o0 + PIU_COOKIE_PCIE ], %o1
2572 ! PEU status register
2573 setx PIU_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_ADDR, %o3, %o2
2574 ldx [ %o1 + %o2 ], %o3
2575 and %o3, 0x7, %o3 ! status bits [2:0]
2576 cmp %o3, 0x4 ! data link active
2577 mov %g0, %o0
2578 move %xcc, 1, %o0
2579 retl
2580 nop
2581 SET_SIZE(is_piu_port_link_up)
2582
2583
2584/*
2585 * arg0 (%g1) = PIU Cookie
2586 * arg2 (%g2) = Offset
2587 * arg3 (%g3) = size (1, 2, 4)
2588 * --------------------
2589 * ret0 = status (1 fail, 0 pass)
2590 * ret1 = data
2591 */
2592
2593 ENTRY_NP(hv_config_get)
2594
2595 !! %g1 = piu cookie (pointer)
2596 !! %g2 = offset
2597 !! %g3 = size (1 byte, 2 bytes, 4 bytes)
2598
2599 mov 1, %g5
2600 STRAND_STRUCT(%g4)
2601 set STRAND_IO_PROT, %g6
2602
2603 !! %g4 = Strand struct
2604
2605 ! strand.io_prot = 1
2606 stx %g5, [%g4 + %g6]
2607
2608 DISABLE_PCIE_RWUC_ERRORS(%g1, %g4, %g5, %g6)
2609
2610
2611 ldx [%g1 + PIU_COOKIE_CFG], %g4
2612 cmp %g3, 1
2613 beq,a,pn %xcc,1f
2614 ldub [%g4 + %g2], %g3
2615 cmp %g3, 2
2616 beq,a,pn %xcc,1f
2617 lduha [%g4 + %g2]ASI_P_LE, %g3
2618 lduwa [%g4 + %g2]ASI_P_LE, %g3
26191:
2620 STRAND_STRUCT(%g4)
2621 set STRAND_IO_PROT, %g6
2622 ! strand.io_prot = 0
2623 stx %g0, [%g4 + %g6]
2624 set STRAND_IO_ERROR, %g6
2625 ! strand.io_error
2626 ldx [%g4 + %g6], %g5
2627 ! strand.io_error = 0
2628 stx %g0, [%g4 + %g6]
2629
2630 ENABLE_PCIE_RWUC_ERRORS(%g1, %g4, %g2, %g6)
2631
2632 HVRET
2633
2634 SET_SIZE(hv_config_get)
2635
2636/*
2637 * bool_t pci_config_get(uint64_t piup, uint64_t offset, int size,
2638 * uint64_t *data)
2639 */
2640 ENTRY(pci_config_get)
2641
2642 STRAND_PUSH(%g2, %g6, %g7)
2643 STRAND_PUSH(%g3, %g6, %g7)
2644 STRAND_PUSH(%g4, %g6, %g7)
2645
2646 mov %o0, %g1
2647 mov %o1, %g2
2648 mov %o2, %g3
2649
2650 ! %g1 - piupp
2651 ! %g2 - Address
2652 ! %g3 - size ( 1, 2, 4)
2653
2654 HVCALL(hv_config_get)
2655
2656 stx %g3, [%o3]
2657 movrnz %g5, 0, %o0
2658 movrz %g5, 1, %o0
2659
2660 STRAND_POP(%g4, %g6)
2661 STRAND_POP(%g3, %g6)
2662 STRAND_POP(%g2, %g6)
2663
2664 retl
2665 nop
2666 SET_SIZE(pci_config_get)
2667
2668/*
2669 * piu_intr_redistribution
2670 *
2671 * %g1 - this cpu id
2672 * %g2 - tgt cpu id
2673 *
2674 * Need to invalidate all of the virtual intrs that are
2675 * mapped to the cpu passed in %g1
2676 *
2677 * Need to retarget the 3 HW intrs hv controls that are
2678 * mapped to the cpu passed in %g1 to cpu in %g2
2679 */
2680 ENTRY(piu_intr_redistribution)
2681 CPU_PUSH(%g7, %g3, %g4, %g5)
2682
2683 mov %g1, %g3 ! save cpuid
2684 GUEST_STRUCT(%g4)
2685 mov PIU_AID, %g1
2686 DEVINST2INDEX(%g4, %g1, %g1, %g5, .piu_intr_redis_fail)
2687 DEVINST2COOKIE(%g4, %g1, %g1, %g5, .piu_intr_redis_fail)
2688
2689 ! %g1 - piu cookie
2690 ! %g3 - this cpu
2691 HVCALL(_piu_intr_redistribution)
2692
2693.piu_intr_redis_fail:
2694 mov %g3, %g1 ! restore cpuid
2695 CPU_POP(%g7, %g3, %g4, %g5)
2696 HVRET
2697 SET_SIZE(piu_intr_redistribution)
2698
2699/*
2700 * _piu_intr_redistribution
2701 *
2702 * %g1 - piu cookie
2703 * %g3 - this cpu
2704 */
2705 ENTRY(_piu_intr_redistribution)
2706 CPU_PUSH(%g7, %g4, %g5, %g6)
2707
2708 ! %g1 - piu cookie ptr
2709 lduh [%g1 + PIU_COOKIE_INOMAX], %g2 ! loop counter
2710 dec %g2 ! INOMAX - 1
2711
2712._piu_intr_redis_loop:
2713 cmp %g2, DMU_INTERNAL_INT
2714 be %xcc, .piu_intr_redis_continue ! DMU errors handle separate
2715 nop
2716
2717 cmp %g2, PEU_INTERNAL_INT
2718 be %xcc, .piu_intr_redis_continue ! PEU errors handle separate
2719 nop
2720
2721 ldx [%g1 + PIU_COOKIE_INTMAP], %g5
2722 REGNO2OFFSET(%g2, %g4)
2723 ldx [%g5 + %g4], %g4
2724
2725 ! Extract cpuid
2726 srlx %g4, JPID_SHIFT, %g7
2727 and %g7, JPID_MASK, %g7
2728
2729 ! %g7 - cpuid
2730 ! compare with this cpu, if match, set to idle
2731 cmp %g3, %g7
2732 bne,pt %xcc, .piu_intr_redis_continue
2733 nop
2734
2735 ! save cpuid since call clobbers it
2736 CPU_PUSH(%g3, %g4, %g5, %g6)
2737 CPU_PUSH(%g2, %g4, %g5, %g6)
2738 mov INTR_DISABLED, %g3 ! Invalid
2739
2740 ! %g1 = PIU Cookie
2741 ! %g2 = device ino
2742 ! %g3 = Idle
2743 HVCALL(_piu_intr_setvalid)
2744
2745 CPU_POP(%g2, %g4, %g5, %g6)
2746 CPU_POP(%g3, %g4, %g5, %g6)
2747
2748.piu_intr_redis_continue:
2749 deccc %g2
2750 bgeu,pt %xcc, ._piu_intr_redis_loop
2751 nop
2752
2753.piu_redis_done:
2754
2755 CPU_POP(%g7, %g4, %g5, %g6)
2756 HVRET
2757 SET_SIZE(_piu_intr_redistribution)
2758
2759#endif /* CONFIG_PIU */