Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / greatlakes / huron / src / vpci_piu.s
/*
* ========== Copyright Header Begin ==========================================
*
* Hypervisor Software File: vpci_piu.s
*
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* - Do no alter or remove copyright notices
*
* - Redistribution and use of this software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* - Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or
* intended for use in the design, construction, operation or maintenance of
* any nuclear facility.
*
* ========== Copyright Header End ============================================
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
.ident "@(#)vpci_piu.s 1.7 07/08/15 SMI"
.file "vpci_piu.s"
#include <sys/asm_linkage.h>
#include <sys/htypes.h>
#include <hypervisor.h>
#include <sparcv9/asi.h>
#include <sun4v/asi.h>
#include <asi.h>
#include <mmu.h>
#include <guest.h>
#include <offsets.h>
#include <debug.h>
#include <vcpu.h>
#include <util.h>
#include <abort.h>
#include <vpiu_errs.h>
#include <intr.h>
#include <fpga.h>
#if defined(CONFIG_PIU)
#ifdef VPCI_DEBUG
#define _VPCI_PRINTX(r) PRINTX(r)
#define _VPCI_PRINT(s) PRINT(s)
#else
#define _VPCI_PRINTX(r)
#define _VPCI_PRINT(s)
#endif
#define _VPCI_PRINT1(s, r1) _VPCI_PRINT(s); _VPCI_PRINTX(r1)
#define _VPCI_PRINT2(s, r1, r2) _VPCI_PRINT1(s, r1); \
_VPCI_PRINT1(" ", r2)
#define _VPCI_PRINT3(s, r1, r2, r3) _VPCI_PRINT2(s, r1, r2); \
_VPCI_PRINT1(" ", r3)
#define _VPCI_PRINT4(s, r1, r2, r3, r4) _VPCI_PRINT3(s, r1, r2, r3); \
_VPCI_PRINT1(" ", r4)
#define VPCI_PRINT1(s, r1) _VPCI_PRINT1(s, r1); \
_VPCI_PRINT("\r\n")
#define VPCI_PRINT2(s, r1, r2) _VPCI_PRINT1(s, r1); \
VPCI_PRINT1(" ", r2)
#define VPCI_PRINT3(s, r1, r2, r3) _VPCI_PRINT2(s, r1, r2); \
VPCI_PRINT1(" ", r3)
#define VPCI_PRINT4(s, r1, r2, r3, r4) _VPCI_PRINT3(s, r1, r2, r3) \
VPCI_PRINT1(" ", r4)
#define REGNO2OFFSET(no, off) sllx no, 3, off
#define PCIDEV2PIUDEV(pci, piu) sllx pci, 4, piu
#if PIU_MSIEQ_SIZE != 0x28
#error "PIU_MSIEQ_SIZE changed, breaks the shifts below"
#endif
#define MSIEQNUM2MSIEQ(piucookie, num, msieq, scr1, scr2) \
ldx [piucookie + PIU_COOKIE_MSICOOKIE], msieq ;\
sllx num, 5, scr1 ;\
sllx num, 3, scr2 ;\
add scr1, scr2, scr1 ;\
inc PIU_MSI_COOKIE_EQ, scr1 ;\
add msieq, scr1, msieq
#define IOTSB0_PIU_COOKIE PIU_COOKIE_IOTSB0
#define IOTSB1_PIU_COOKIE PIU_COOKIE_IOTSB1
#define SETUP_IOTSB_BASE(rc_cookie, pcie, t, scr1, scr2, scr3) \
ldx [rc_cookie + t/**/_PIU_COOKIE], scr1 ;\
srlx scr1, t/**/_PAGESHIFT, scr1 ;\
sllx scr1, IOTSB_BASE_PA_SHIFT, scr1 ;\
set IOTSBDESC_REG(t), scr2 ;\
ldx [pcie + scr2], scr3 ;\
or scr3, scr1, scr3 ;\
stx scr3, [pcie + scr2]
! Ordered to minimize wasted space
BSS_GLOBAL(piu_0_equeue, (PIU_NEQS * PIU_EQSIZE), 512 KB)
BSS_GLOBAL(piu_iotsb0, IOTSB0_SIZE, 8 KB)
BSS_GLOBAL(piu_iotsb1, IOTSB1_SIZE, 8 KB)
BSS_GLOBAL(piu_virtual_intmap, 0x10, 0x10)
DATA_GLOBAL(piu_ncu_init_table)
.xword PIU_BAR(CFGIO(0)), PIU_PCIE_A_IOCON_OFFSET_BASE
.xword PIU_BAR(MEM32(0)), PIU_PCIE_A_MEM32_OFFSET_BASE
.xword PIU_BAR(MEM64(0)), PIU_PCIE_A_MEM64_OFFSET_BASE
.xword PIU_SIZE(MEM32_SIZE), PIU_PCIE_A_MEM32_OFFSET_MASK
.xword PIU_BAR_V(MEM32(0)), PIU_PCIE_A_MEM32_OFFSET_BASE
.xword PIU_SIZE(CFGIO_SIZE), PIU_PCIE_A_IOCON_OFFSET_MASK
.xword PIU_BAR_V(CFGIO(0)), PIU_PCIE_A_IOCON_OFFSET_BASE
.xword PIU_SIZE(MEM64_SIZE), PIU_PCIE_A_MEM64_OFFSET_MASK
.xword PIU_BAR_V(MEM64(0)), PIU_PCIE_A_MEM64_OFFSET_BASE
.xword -1,-1 /* End of Table */
SET_SIZE(piu_ncu_init_table)
DATA_GLOBAL(piu_leaf_init_table)
.xword 0xffffffffffffffff, PIU_DLC_IMU_ICS_IMU_ERROR_LOG_EN_REG
.xword 0xffffffffffffffff, PIU_DLC_IMU_ICS_IMU_INT_EN_REG
.xword 0xffffffffffffffff, PIU_DLC_IMU_ICS_IMU_LOGGED_ERROR_STATUS_REG_RW1C_ALIAS
.xword 0x0000000000000010, PIU_DLC_ILU_CIB_ILU_LOG_EN
.xword 0x0000001000000010, PIU_DLC_ILU_CIB_ILU_INT_EN
.xword 0x00000000da130001, PIU_PLC_TLU_CTB_TLR_TLU_CTL
/* DW for N2 set fast link mode, reset assert */
.xword 0x00000000001b0808, PIU_PLC_TLU_CTB_TLR_CSR_A_LINK_CTL_ADDR
.xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_OE_LOG
.xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_OE_ERR_RW1C_ALIAS
.xword 0xffffffffffffffff, PCI_E_PEU_OTHER_INT_ENB_ADDR
.xword 0x0000000000000040, PIU_PLC_TLU_CTB_TLR_DEV_CTL
.xword 0x0000000000000040, PIU_PLC_TLU_CTB_TLR_LNK_CTL
.xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_UE_LOG
.xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_UE_INT_EN
.xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_CE_LOG
.xword 0xffffffffffffffff, PIU_PLC_TLU_CTB_TLR_CE_INT_EN
.xword 0xffffffffffffffff, PIU_DLC_IMU_ICS_DMC_INTERRUPT_MASK_REG
.xword 0x0000000000000000, PIU_DLC_CRU_DMC_DBG_SEL_A_REG
.xword 0x0000000000000000, PIU_DLC_CRU_DMC_DBG_SEL_B_REG
.xword 0xffffffffffffffff, PIU_DLC_ILU_CIB_PEC_INT_EN
.xword 0xffffffffffffffff, PIU_DLC_MMU_INV
.xword 0x0000000000000000, PIU_DLC_MMU_TSB
#ifndef DEBUG_LEGION
.xword 0x0000000000000000, PIU_PLC_TLU_CTB_TLR_CSR_A_DEV_CTL_ADDR ! XXX is this right?
#endif
.xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(0)
.xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(1)
.xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(2)
.xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(3)
.xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(4)
.xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(5)
.xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(6)
.xword DEV2IOTSB(IOTSB0), DEV2IOTSB_REG(7)
.xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(8)
.xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(9)
.xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(10)
.xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(11)
.xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(12)
.xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(13)
.xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(14)
.xword DEV2IOTSB(IOTSB1), DEV2IOTSB_REG(15)
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(0) /* 0 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(1) /* 1 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(2) /* 2 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(3) /* 3 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(4) /* 4 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(5) /* 5 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(6) /* 6 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(7) /* 7 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(8) /* 8 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(9) /* 9 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(10) /* 10 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(11) /* 11 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(12) /* 12 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(13) /* 13 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(14) /* 14 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(15) /* 15 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(16) /* 16 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(17) /* 17 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(18) /* 18 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(19) /* 19 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(20) /* 20 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(21) /* 21 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(22) /* 22 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(23) /* 23 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(24) /* 24 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(25) /* 25 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(26) /* 26 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(27) /* 27 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(28) /* 28 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(29) /* 29 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(30) /* 30 */
.xword IOTSBDESC(UNUSED), IOTSBDESC_REG(31) /* 31 */
.xword IOTSBDESC(IOTSB0), IOTSBDESC_REG(IOTSB0)
.xword IOTSBDESC(IOTSB1), IOTSBDESC_REG(IOTSB1)
.xword 0x0000000000000000, PIU_DLC_MMU_TSB
.xword 0x0000000000000000, PIU_DLC_MMU_CTL
.xword 0xffffffffffffffff, PIU_DLC_MMU_INT_EN
.xword 0x0000000002000000, PIU_DLC_CRU_CSR_A_DMC_PCIE_CFG_ADDR
/* MSI ranges */
.xword 0x000000007fff0000, PIU_DLC_IMU_ICS_MSI_32_ADDR_REG
.xword 0x00000003ffff0000, PIU_DLC_IMU_ICS_MSI_64_ADDR_REG
.xword -1, -1 /* End of Table */
SET_SIZE(piu_leaf_init_table)
/*
* piu_init
*
* in:
* %i0 - global config pointer
* %i1 - base of guests (not used)
* %i2 - base of cpus (not used)
* %g7 - return address
*/
ENTRY_NP(piu_init)
setx piu_ncu_init_table, %g5, %g3
setx piu_dev, %g5, %g1
ldx [%i0 + CONFIG_RELOC], %o0
sub %g3, %o0, %g3
sub %g1, %o0, %g1
! %g1 = piup
! %g3 = piu_ncu_init_table base
! %g7 = return PC
ldx [%g1 + PIU_COOKIE_NCU], %g4
brz,pn %g4, 3f
nop
! %g1 = piup
! %g3 = piu_init_table base
! %g4 = NCU Base PA
! %g7 = return PC
1:
ldx [%g3 + 8], %g5 ! Offset
add %g5, 1, %g6
brz,pn %g6, 3f
ldx [%g3 + 0], %g6 ! Data
add %g3, 16, %g3
ba 1b
stx %g6, [%g4 + %g5]
3:
setx piu_leaf_init_table, %g5, %g3
ldx [%i0 + CONFIG_RELOC], %o0
sub %g3, %o0, %g3
ldx [%g1 + PIU_COOKIE_PCIE], %g4
!brz,pn %g4, 3f
!nop
1:
ldx [%g3 + 8], %g6 ! Offset
add %g6, 1, %g2
brz,pn %g2, 2f
ldx [%g3 + 0], %g2 ! Data
add %g3, 16, %g3
ba 1b
stx %g2, [%g4 + %g6]
2:
! Setup Interrupt Mondo Data 0 register
set PCI_E_INT_MONDO_DATA_0_ADDR, %g6
stx %g0, [%g4 + %g6]
! Setup Interrupt Mondo Data 1 register
set PCI_E_INT_MONDO_DATA_1_ADDR, %g6
set PIU_AID, %g2
sllx %g2, PIU_DEVINO_SHIFT, %g2
! ldx [%g1 + PIU_COOKIE_HANDLE], %g2
stx %g2, [%g4 + %g6]
! Setup interrupt mappings
! mondo 62 leafs A and B
! mondo 63 only leaf A
VCPU_STRUCT(%g4)
VCPU2STRAND_STRUCT(%g4, %g2)
ldub [%g2 + STRAND_ID], %g2
mov %g0, %g5
! Add CPU number
sllx %g2, JPID_SHIFT, %g6
or %g5, %g6, %g5
! Select a PIU Interrupt Controller
and %g2, (NPIUINTRCONTROLLERS - 1), %g2
add %g2, PIU_INTR_CNTLR_SHIFT, %g2
mov 1, %g6
sllx %g6, %g2, %g2
or %g5, %g2, %g5
! Set MDO MODE bit
mov 1, %g6
sllx %g6, PIU_INTMR_MDO_MODE_SHIFT, %g6
or %g5, %g6, %g5
! Set Valid bit
mov 1, %g6
sllx %g6, PIU_INTMR_V_SHIFT, %g6
or %g5, %g6, %g5
mov DMU_INTERNAL_INT, %g4
REGNO2OFFSET(%g4, %g4)
ldx [%g1 + PIU_COOKIE_INTMAP], %g3
stx %g5, [%g3 + %g4] ! leaf A, mondo 62
ldx [%g1 + PIU_COOKIE_INTCLR], %g2
stx %g0, [%g2 + %g4]
mov PEU_INTERNAL_INT, %g4
REGNO2OFFSET(%g4, %g4)
ldx [%g1 + PIU_COOKIE_INTMAP], %g3
stx %g5, [%g3 + %g4] ! leaf A, mondo 63
ldx [%g1 + PIU_COOKIE_INTCLR], %g2
stx %g0, [%g2 + %g4]
! %g1 = PIU COOKIE
! %g3 = PIU PCIE Base
set PIU_DLC_MMU_CTL, %g5
! PIU Leaf A PCIE reg base
ldx [%g1 + PIU_COOKIE_PCIE], %g3
set PIU_MMU_CSR_VALUE, %g2
! Leaf A MMU_CTRL reg
stx %g2, [%g3 + %g5]
! %g1 = PIU COOKIE
! %g3 = PIU PCIE Base
set PIU_DLC_MMU_TSB, %g6
ldx [%g1 + PIU_COOKIE_IOTSB0], %g2
or %g2, IOTSB0_TSB_SIZE, %g2
! Leaf A MMU_TSB_CTRL reg
#if (PIU_MMU_CSR_VALUE & PIU_MMU_CSR_SUN4V_EN == 0)
stx %g2, [%g3 + %g6]
#else
stx %g0, [%g3 + %g6]
#endif
! %g1 = PIU COOKIE
! %g3 = PIU PCIE Base
SETUP_IOTSB_BASE(%g1, %g3, IOTSB0, %g2, %g4, %g5)
SETUP_IOTSB_BASE(%g1, %g3, IOTSB1, %g2, %g4, %g5)
! %g1 = PIU COOKIE
! %g3 = PIU PCIE Base
ldx [%g1 + PIU_COOKIE_MSIEQBASE], %g2
setx MSI_EQ_BASE_BYPASS_ADDR, %g7, %g6
or %g2, %g6, %g2
set PIU_DLC_IMU_EQS_EQ_BASE_ADDRESS, %g6
! Leaf A EQ Base Address
stx %g2, [%g3 + %g6]
3:
HVRET
SET_SIZE(piu_init)
/*
* piu_devino2vino
*
* %g1 Piu Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 dev ino (%o1)
* --
* ret0 status (%o0)
* ret1 virtual INO (%o1)
*/
ENTRY_NP(piu_devino2vino)
! %g1 pointer to PIU_COOKIE
ldx [%g1 + PIU_COOKIE_HANDLE], %g2
cmp %o0, %g2
bne herr_inval
lduh [%g1 + PIU_COOKIE_INOMAX], %g3
cmp %o1, %g3
bgu,pn %xcc, herr_inval
lduh [%g1 + PIU_COOKIE_VINO], %g4
or %o1, %g4, %o1
HCALL_RET(EOK)
SET_SIZE(piu_devino2vino)
/*
* piu_intr_getvalid
*
* %g1 PIU Cookie Pointer
* arg0 Virtual INO (%o0)
* --
* ret0 status (%o0)
* ret1 intr valid state (%o1)
*/
ENTRY_NP(piu_intr_getvalid)
! %g1 pointer to PIU_COOKIE
VPCI_PRINT1("HV: intr_getvalid ", %o0)
ldx [%g1 + PIU_COOKIE_INTMAP], %g2
and %o0, PIU_DEVINO_MASK, %g4
REGNO2OFFSET(%g4, %g4)
ldx [%g2 + %g4], %g5
sra %g5, 0, %g5
mov INTR_DISABLED, %o1
movrlz %g5, INTR_ENABLED, %o1
HCALL_RET(EOK)
SET_SIZE(piu_intr_getvalid)
/*
* _piu_intr_setvalid
*
* %g1 PIU Cookie Pointer
* %g2 INO
* %g3 intr valid state
* --
*
* ret0 PIU Cookie (%g1)
* ret1 INO (%g2)
*/
ENTRY_NP(_piu_intr_setvalid)
! %g1 = pointer to PIU_COOKIE
ldx [%g1 + PIU_COOKIE_INTMAP], %g6
and %g2, PIU_DEVINO_MASK, %g4
REGNO2OFFSET(%g4, %g4)
add %g4, %g6, %g4
ldx [%g4], %g5
mov 1, %g6
sllx %g6, PIU_INTMR_V_SHIFT, %g6
andn %g5, %g6, %g5
sllx %g3, PIU_INTMR_V_SHIFT, %g6
or %g5, %g6, %g5
stx %g5, [%g4]
HVRET
SET_SIZE(_piu_intr_setvalid)
/*
* piu_intr_setvalid
*
* %g1 PIU Cookie Pointer
* arg0 Virtual INO (%o0)
* arg1 intr valid state (%o1) 1: Valid 0: Invalid
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_intr_setvalid)
VPCI_PRINT2("HV: intr_setvalid ", %o0, %o1)
! %g1 = pointer to PIU_COOKIE
mov %o0, %g2
mov %o1, %g3
HVCALL(_piu_intr_setvalid)
HCALL_RET(EOK)
SET_SIZE(piu_intr_setvalid)
/*
* piu_intr_getstate
*
* %g1 PIU Cookie Pointer
* arg0 Virtual INO (%o0)
* --
* ret0 status (%o0)
* ret1 (%o1) 1: Pending / 0: Idle
*/
ENTRY_NP(piu_intr_getstate)
VPCI_PRINT1("HV: intr_getstate ", %o0)
! %g1 pointer to PIU_COOKIE
ldx [%g1 + PIU_COOKIE_INTCLR], %g2
and %o0, PIU_DEVINO_MASK, %g4
REGNO2OFFSET(%g4, %g4)
ldx [%g2 + %g4], %g3
sub %g3, PIU_INTR_RECEIVED, %g4
movrz %g4, INTR_DELIVERED, %o1
movrnz %g4, INTR_RECEIVED, %o1
movrz %g3, INTR_IDLE, %o1
HCALL_RET(EOK)
SET_SIZE(piu_intr_getstate)
/*
* piu_intr_setstate
*
* %g1 PIU Cookie Pointer
* arg0 Virtual INO (%o0)
* arg1 (%o1) 1: Pending / 0: Idle XXX
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_intr_setstate)
VPCI_PRINT2("HV: intr_setstate ", %o0, %o1)
! %g1 pointer to PIU_COOKIE
cmp %o1, INTR_DELIVERED
bgu,pn %xcc, herr_inval
mov %o0, %g2
mov %o1, %g3
HVCALL(_piu_intr_setstate)
HCALL_RET(EOK)
SET_SIZE(piu_intr_setstate)
/*
* %g1 = PIU Cookie
* %g2 = device ino
* %g3 = Pending/Idle
* --
* %g1 = PIU Cookie
* %g2 = device ino
*/
ENTRY_NP(_piu_intr_setstate)
ldx [%g1 + PIU_COOKIE_INTCLR], %g5
and %g2, PIU_DEVINO_MASK, %g4
REGNO2OFFSET(%g4, %g4)
movrz %g3, PIU_INTR_IDLE, %g3
movrnz %g3, PIU_INTR_RECEIVED, %g3
stx %g3, [%g5 + %g4]
HVRET
SET_SIZE(_piu_intr_setstate)
/*
* piu_intr_gettarget
*
* %g1 PIU Cookie Pointer
* arg0 Virtual INO (%o0)
* --
* ret0 status (%o0)
* ret1 cpuid (%o1)
*/
ENTRY_NP(piu_intr_gettarget)
VPCI_PRINT1("HV: intr_gettarget ", %o0)
! %g1 pointer to PIU_COOKIE
mov %o0, %g2
HVCALL(_piu_intr_gettarget)
! get the virtual cpuid
PID2VCPUP(%g3, %g4, %g5, %g6)
ldub [%g4 + CPU_VID], %o1
HCALL_RET(EOK)
SET_SIZE(piu_intr_gettarget)
/*
* %g1 = PIU cookie
* %g2 = device ino
* --
* %g1 = PIU cookie
* %g2 = device ino
* %g3 = phys cpuid
*/
ENTRY_NP(_piu_intr_gettarget)
ldx [%g1 + PIU_COOKIE_INTMAP], %g3
and %g2, PIU_DEVINO_MASK, %g4
REGNO2OFFSET(%g4, %g4)
ldx [%g3 + %g4], %g3
srlx %g3, JPID_SHIFT, %g3
and %g3, JPID_MASK, %g4
STRAND_STRUCT(%g3)
STRAND2CONFIG_STRUCT(%g3, %g3)
ldx [%g3 + CONFIG_STRANDS], %g3
set STRAND_SIZE, %g5
mulx %g4, %g5, %g5
add %g3, %g5, %g3
ldub [%g3 + STRAND_ID], %g3
HVRET
SET_SIZE(_piu_intr_gettarget)
/*
* piu_intr_settarget
*
* %g1 PIU Cookie Pointer
* arg0 Virtual INO (%o0)
* arg1 cpuid (%o1)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_intr_settarget)
VPCI_PRINT2("HV: intr_settarget ", %o0, %o1)
! %g1 pointer to PIU_COOKIE
GUEST_STRUCT(%g3)
VCPUID2CPUP(%g3, %o1, %g4, herr_nocpu, %g5)
IS_CPU_IN_ERROR(%g4, %g5)
be,pn %xcc, herr_cpuerror
nop
VCPU2STRAND_STRUCT(%g4, %g3)
ldub [%g3 + STRAND_ID], %g3
and %o0, PIU_DEVINO_MASK, %g2
HVCALL(_piu_intr_settarget)
HCALL_RET(EOK)
SET_SIZE(piu_intr_settarget)
/*
* %g1 = PIU cookie
* %g2 = device ino
* %g3 = Physical CPU number
* --
* %g1 = PIU cookie
* %g2 = device ino
*/
ENTRY_NP(_piu_intr_settarget)
ldx [%g1 + PIU_COOKIE_INTMAP], %g4
REGNO2OFFSET(%g2, %g6)
add %g4, %g6, %g4
ldx [%g4], %g5
! %g2 INO offset
! %g3 Physical CPU number
! %g4 INTMAP base
! %g5 INTMAP reg value
! Add CPU number
mov JPID_MASK, %g6
sllx %g6, JPID_SHIFT, %g6
andn %g5, %g6, %g5
sllx %g3, JPID_SHIFT, %g6
or %g5, %g6, %g5
! Clear Interrupt Controller bits
andn %g5, (PIU_INTR_CNTLR_MASK << PIU_INTR_CNTLR_SHIFT), %g5
! Select a PIU Interrupt Controller
and %g3, (NPIUINTRCONTROLLERS - 1), %g3
add %g3, PIU_INTR_CNTLR_SHIFT, %g3
mov 1, %g6
sllx %g6, %g3, %g3
or %g5, %g3, %g5
! Set MDO MODE bit
mov 1, %g6
sllx %g6, PIU_INTMR_MDO_MODE_SHIFT, %g6
or %g5, %g6, %g5
stx %g5, [%g4]
HVRET
SET_SIZE(_piu_intr_settarget)
/*
* piu_iommu_map
*
* %g1 PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 tsbid (%o1)
* arg2 #ttes (%o2)
* arg3 tte attributes (%o3)
* arg4 io_page_list_p (%o4)
* --
* ret0 status (%o0)
* ret1 #ttes mapped (%o1)
*/
ENTRY_NP(_piu_iommu_map)
VPCI_PRINT2("HV: iommu_map ", %o1, %o2)
!! %g1 pointer to PIU_COOKIE
! Check io_page_list_p alignment
! and make sure it is 8 byte aligned
btst SZ_LONG - 1, %o4
bnz,pn %xcc, herr_badalign
ldx [%g1 + PIU_COOKIE_IOTSB0], %g5
sethi %hi(IOTSB0_INDEX_MASK), %g3
or %g3, %lo(IOTSB0_INDEX_MASK), %g3
cmp %o1, %g3
bgu,pn %xcc, herr_inval
brlez,pn %o2, herr_inval
cmp %o2, IOMMU_MAP_MAX
movgu %xcc, IOMMU_MAP_MAX, %o2
! Check to ensure the end of the mapping is still within
! range.
!! %o2 #ttes
!! %o1 tte index
!! %g3 IOTSB_INDEX_MAX
add %o1, %o2, %g2
inc %g3 ! make sure last mapping succeeds.
cmp %g2, %g3
bgu,pn %xcc, herr_inval
nop
GUEST_STRUCT(%g2)
sllx %o2, IOTTE_SHIFT, %g6
RA2PA_RANGE_CONV_UNK_SIZE(%g2, %o4, %g6, herr_noraddr, %g7, %g3)
mov %g3, %g6
!! %g6 PA
ldx [%g1 + PIU_COOKIE_MMUFLUSH], %g1
mov 1, %g7
sllx %g7, PIU_IOTTE_V_SHIFT, %g7
or %g7, %o3, %o3
set IOTSB0_PAGESIZE, %g4
!! %g1 = PIU MMU Flush Reg
!! %g2 = Guest Struct
!! %g4 = IOTSB pagesize
!! %g5 = IOTSB base
!! %g6 = PA of pagelist
!! %o1 = TTE index
!! %o2 = #ttes to map
!! %o3 = TTE Attributes + Valid Bit
sllx %o1, IOTTE_SHIFT, %o1
add %g5, %o1, %g5
mov 0, %o1
!! %g1 = PIU NCU Reg Block Base
!! %g2 = Guest
!! %g4 = IOTSB pagesize
!! %g5 = IOTSB base
!! %g6 = PA of pagelist
!! %o1 = TTE index
!! %o2 = #ttes to map
!! %o3 = TTE Attributes + Valid Bit
.piu_iommu_map_loop:
ldx [%g6], %g3
srlx %g3, IOTSB0_PAGESHIFT, %o0
sllx %o0, IOTSB0_PAGESHIFT, %o0
cmp %g3, %o0
bne,pn %xcc, .piu_badalign
nop
RA2PA_RANGE_CONV(%g2, %o0, %g4, .piu_noraddr, %g7, %g3)
mov %g3, %o0
!! RA -> PA (%o0)
or %o0, %o3, %o0
stx %o0, [%g5]
and %g5, (1 << 6) - 1, %o0
stx %g5, [%g1] ! IOMMU flush
add %g5, IOTTE_SIZE, %g5 ! *IOTSB++
add %g6, IOTTE_SIZE, %g6 ! *PAGELIST++
sub %o2, 1, %o2
brgz,pt %o2, .piu_iommu_map_loop
add %o1, 1, %o1
mov 0, %o2
HCALL_RET(EOK)
.piu_noraddr:
brz,pn %o1, herr_noraddr
mov 0, %o2
HCALL_RET(EOK)
.piu_badalign:
brz,pn %o1, herr_badalign
mov 0, %o2
HCALL_RET(EOK)
SET_SIZE(_piu_iommu_map)
/*
* piu_iommu_map
*
* %g1 Piu Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 tsbid (%o1)
* arg2 #ttes (%o2)
* arg3 tte attributes (%o3)
* arg4 io_page_list_p (%o4)
* --
* ret0 status (%o0)
* ret1 #ttes mapped (%o1)
*/
ENTRY_NP(piu_iommu_map)
VPCI_PRINT4("HV: iommu_map ", %o1, %o2, %o3, %o4)
! %g1 pointer to PIU_COOKIE
and %o3, HVIO_TTE_ATTR_MASK, %g7
cmp %o3, %g7
bne,pn %xcc, herr_inval
nop
ba,a _piu_iommu_map
SET_SIZE(piu_iommu_map)
/*
* piu_iommu_map_v2
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 tsbid (%o1)
* arg2 #ttes (%o2)
* arg3 tte attributes (%o3)
* arg4 io_page_list_p (%o4)
* --
* ret0 status (%o0)
* ret1 #ttes mapped (%o1)
*/
ENTRY_NP(piu_iommu_map_v2)
VPCI_PRINT4("HV: iommu_map_v2 ", %o1, %o2, %o3, %o4)
! %g1 pointer to PIU_COOKIE
andn %o3, HVIO_TTE_L, %o3
set HVIO_TTE_ATTR_MASK_V2, %g6
and %o3, %g6, %g7
cmp %o3, %g7
bne,pn %xcc, herr_inval
set HVIO_TTE_BDF, %g6
btst %o3, %g6
bnz,pt %xcc, 1f
and %o3, (HVIO_TTE_R | HVIO_TTE_W), %g5
! No BDF given, check for PP bits
btst HVIO_TTE_PP, %o3
bnz,pn %xcc, herr_inval
nop
ba 2f
nop
1:
srlx %o3, HVIO_TTE_BDF_SHIFT, %g6
sllx %g6, PIU_TTE_BDF_SHIFT, %g6
or %g6, PIU_TTE_DEV_KEY, %g6
or %g5, %g6, %g5
! %g5 = IOTTE
and %o3, HVIO_TTE_PP, %g6
cmp %g6, HVIO_TTE_PP_ALL
be,a,pt %xcc, 2f
or %g5, PIU_TTE_FNM_ALL, %g5
cmp %g6, HVIO_TTE_PP_2MSBS
be,a,pt %xcc, 2f
or %g5, PIU_TTE_FNM_2MSBS, %g5
cmp %g6, HVIO_TTE_PP_MSB
be,a,pt %xcc, 2f
or %g5, PIU_TTE_FNM_MSB, %g5
cmp %g6, HVIO_TTE_PP_NONE
be,a,pt %xcc, 2f
or %g5, PIU_TTE_FNM_NONE, %g5
! %g5 = IOTTE
2: ba _piu_iommu_map
mov %g5, %o3
SET_SIZE(piu_iommu_map_v2)
/*
* _piu_iommu_getmap
*
* %g1 = Piu Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 tsbid (%o1)
* --
* ret0 status (%o0)
* ret1 attributes (%o1)
* ret2 ra (%o2)
*/
ENTRY_NP(_piu_iommu_getmap)
! %g1 pointer to PIU_COOKIE
ldx [%g1 + PIU_COOKIE_IOTSB0], %g5
sethi %hi(IOTSB0_INDEX_MASK), %g3
or %g3, %lo(IOTSB0_INDEX_MASK), %g3
cmp %o1, %g3
bgu,pn %xcc, herr_inval
sllx %o1, IOTTE_SHIFT, %g2
ldx [%g5 + %g2], %g5
mov 1, %g4
sllx %g4, PIU_IOTTE_V_SHIFT, %g4
btst %g4, %g5
bz,pt %xcc, herr_nomap
GUEST_STRUCT(%g2)
! %g1 = PIU Cookie Pointer
! %g2 = Guest pointer
! %g5 = IOTTE
sllx %g5, (64-JBUS_PA_SHIFT), %g3
srlx %g3, (64-JBUS_PA_SHIFT + IOTSB0_PAGESHIFT), %g3
sllx %g3, IOTSB0_PAGESHIFT, %g3
PA2RA_CONV(%g2, %g3, %o2, %g7, %g4) ! PA -> RA (%o2)
btst PIU_TTE_DEV_KEY, %g5 ! Device key valid?
bz 1f
and %g5, HVIO_TTE_ATTR_MASK, %o1
srlx %g5, PIU_TTE_BDF_SHIFT, %g6
sllx %g6, HVIO_TTE_BDF_SHIFT, %g6
set HVIO_TTE_BDF, %g3
and %g6, %g3, %g3
or %o1, %g3, %o1
and %g5, PIU_TTE_FNM_MASK, %g6
cmp %g6, PIU_TTE_FNM_ALL ! All bits of func number used
be,a,pt %xcc, 1f
or %o1, HVIO_TTE_PP_ALL, %o1
cmp %g6, PIU_TTE_FNM_2MSBS ! 2 MSBs of func number used
be,a,pt %xcc, 1f
or %o1, HVIO_TTE_PP_2MSBS, %o1
cmp %g6, PIU_TTE_FNM_MSB ! MSB of func number used
be,a,pt %xcc, 1f
or %o1, HVIO_TTE_PP_MSB, %o1
cmp %g6, PIU_TTE_FNM_NONE ! No phanthom func numbers
be,a,pt %xcc, 1f
or %o1, HVIO_TTE_PP_NONE, %o1
1:
and %g5, (1 << PIU_IOTTE_V_SHIFT), %g5
movrz %g5, 0, %o1 ! Clear the attributes if V=0
#ifdef DEBUG
brz %o1, 1f
nop
VPCI_PRINT2("HV:iommu_getmap ", %g2, %o1)
1:
#endif
HCALL_RET(EOK)
SET_SIZE(_piu_iommu_getmap)
/*
* piu_iommu_getmap
*
* %g1 = Piu Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 tsbid (%o1)
* --
* ret0 status (%o0)
* ret1 attributes (%o1)
* ret2 ra (%o2)
*/
ENTRY_NP(piu_iommu_getmap)
HVCALL(_piu_iommu_getmap)
and %o1, HVIO_TTE_ATTR_MASK, %o1
HCALL_RET(EOK)
SET_SIZE(piu_iommu_getmap)
/*
* piu_iommu_getmap_v2
*
* %g1 PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 tsbid (%o1)
* --
* ret0 status (%o0)
* ret1 attributes (%o1)
* ret2 ra (%o2)
*/
ENTRY_NP(piu_iommu_getmap_v2)
HVCALL(_piu_iommu_getmap)
HCALL_RET(EOK)
SET_SIZE(piu_iommu_getmap_v2)
/*
*
*
* %g1 Piu Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 tsbid (%o1)
* arg2 #ttes (%o2)
* --
* ret0 status (%o0)
* ret1 #ttes demapped (%o1)
*/
ENTRY_NP(piu_iommu_unmap)
VPCI_PRINT2("HV: iommu_unmap ", %o1, %o2)
! %g1 pointer to PIU_COOKIE
ldx [%g1 + PIU_COOKIE_IOTSB0], %g5
sethi %hi(IOTSB0_INDEX_MASK), %g3
or %g3, %lo(IOTSB0_INDEX_MASK), %g3
cmp %o1, %g3
bgu,pn %xcc, herr_inval
brlez,pn %o2, herr_inval
cmp %o2, IOMMU_MAP_MAX
movgu %xcc, IOMMU_MAP_MAX, %o2
brz,pn %o2, herr_inval
add %o1, %o2, %g2
inc %g3 ! make sure last mapping succeeds.
cmp %g2, %g3
bgu,pn %xcc, herr_inval
sllx %o1, IOTTE_SHIFT, %g2
add %g5, %g2, %g2
mov 0, %o1
! %g1 = PIU Cookie Pointer
! %g2 = IOTSB offset
! %o1 = #ttes unmapped so far
! %o2 = #ttes to unmap
ldx [%g1 + PIU_COOKIE_MMUFLUSH], %g1
0:
ldx [%g2], %g5
! Clear Valid bit
mov 1, %g4
sllx %g4, PIU_IOTTE_V_SHIFT, %g4
andn %g5, %g4, %g4
! Clear Attributes
srlx %g4, IOTSB0_PAGESHIFT, %g4
sllx %g4, IOTSB0_PAGESHIFT, %g4
stx %g4, [%g2]
! IOMMU Flush
stx %g2, [%g1] ! IOMMU Flush
add %g2, IOTTE_SIZE, %g2
sub %o2, 1, %o2
brgz,pt %o2, 0b
add %o1, 1, %o1
! Flush PIU TSB here XXXX
HCALL_RET(EOK)
SET_SIZE(piu_iommu_unmap)
/*
* piu_iommu_getbypass
*
* arg0 dev config pa
* arg1 ra
* arg2 io attributes
* --
* ret0 status (%o0)
* ret1 bypass addr (%o1)
*/
ENTRY_NP(piu_iommu_getbypass)
! %g1 pointer to PIU_COOKIE
/*
* ldoms hypervisor does not handle this
* function correctly yet, so all we can do
* is to return ENOSUPP right here and now
*/
HCALL_RET(ENOTSUPPORTED)
andncc %o2, HVIO_IO_ATTR_MASK, %g0
bnz,pn %xcc, herr_inval
.empty
GUEST_STRUCT(%g2)
RA2PA_RANGE_CONV(%g2, %o1, 1, herr_noraddr, %g4, %g3)
! %g3 pa of bypass ra
setx PIU_IOMMU_BYPASS_BASE, %g5, %g4
or %g3, %g4, %o1
HCALL_RET(EOK)
SET_SIZE(piu_iommu_getbypass)
/*
* piu_config_get
*
* arg0 dev config pa (%o0)
* arg1 PCI device (%o1)
* arg2 offset (%o2)
* arg3 size (%o3)
* --
* ret0 status (%o0)
* ret1 error_flag (%o1)
* ret2 value (%o2)
*/
! %g1 pointer to PIU_COOKIE
ENTRY_NP(piu_config_get)
! If leaf is blacklisted fail access
lduw [%g1 + PIU_COOKIE_BLACKLIST], %g3
brnz,a,pn %g3, .skip_config_get
mov 1, %o1
ldx [%g1 + PIU_COOKIE_CFG], %g3
mov 1, %g5
STRAND_STRUCT(%g4)
set STRAND_IO_PROT, %g6
! strand.io_prot = 1
stx %g5, [%g4 + %g6]
! %g1 = PIU cookie
! %g3 = CFG base address
! %g4 = CPU struct
DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
PCIDEV2PIUDEV(%o1, %g2)
or %g2, %o2, %g2
sub %g0, 1, %o2
cmp %o3, SZ_WORD
beq,a,pn %xcc,1f
lduwa [%g3 + %g2]ASI_P_LE, %o2
cmp %o3, SZ_HWORD
beq,a,pn %xcc,1f
lduha [%g3 + %g2]ASI_P_LE, %o2
ldub [%g3 + %g2], %o2
1:
set STRAND_IO_PROT, %g6
! strand.io_prot = 0
stx %g0, [%g4 + %g6]
set STRAND_IO_ERROR, %g6
! strand.io_error
ldx [%g4 + %g6], %o1
! strand.io_error = 0
stx %g0, [%g4 + %g6]
! %g1 = PIU cookie
ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
#if DEBUG
brnz %o1, 1f
nop
VPCI_PRINT2("HV:config_get ", %g2, %o2)
1:
#endif
.skip_config_get:
HCALL_RET(EOK)
SET_SIZE(piu_config_get)
/*
* piu_config_put
*
* arg0 dev config pa (%o0)
* arg1 PCI device (%o1)
* arg2 offset (%o2)
* arg3 size (%o3)
* arg4 data (%o4)
* --
* ret0 status (%o0)
*/
! %g1 pointer to PIU_COOKIE
ENTRY_NP(piu_config_put)
! If leaf is blacklisted fail access
lduw [%g1 + PIU_COOKIE_BLACKLIST], %g3
brnz,a,pn %g3, .skip_config_put
mov 1, %o1
ldx [%g1 + PIU_COOKIE_CFG], %g3
mov 1, %g5
STRAND_STRUCT(%g4)
set STRAND_IO_PROT, %g6
! strand.io_prot = 1
stx %g5, [%g4 + %g6]
! %g1 = PIU cookie
! %g3 = CFG base address
! %g4 = CPU struct
DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
PCIDEV2PIUDEV(%o1, %g2)
or %g2, %o2, %g2
cmp %o3, SZ_WORD
beq,a,pn %xcc,1f
stwa %o4, [%g3 + %g2]ASI_P_LE
cmp %o3, SZ_HWORD
beq,a,pn %xcc,1f
stha %o4, [%g3 + %g2]ASI_P_LE
stb %o4, [%g3 + %g2]
1:
andn %g2, PCI_CFG_OFFSET_MASK, %g6
ldub [%g3 + %g6], %g0
set STRAND_IO_PROT, %g6
! strand.io_prot = 0
stx %g0, [%g4 + %g6]
set STRAND_IO_ERROR, %g6
! strand.io_error
ldx [%g4 + %g6], %o1
! strand.io_error = 0
stx %g0, [%g4 + %g6]
! %g1 = PIU cookie
ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
#if DEBUG
brnz %o1, 1f
nop
VPCI_PRINT2("HV:config_put ", %g2, %o4)
1:
#endif
.skip_config_put:
HCALL_RET(EOK)
SET_SIZE(piu_config_put)
/*
* piu_dma_sync
*
* %g1 = PIU Cookie Pointer
* arg0 devhandle (%o0)
* arg1 r_addr (%o1)
* arg2 size (%o2)
* arg3 direction (%o3) (1: for device 2: for cpu)
* --
* ret0 status (%o0)
* ret1 #bytes synced (%o1)
*/
ENTRY_NP(piu_dma_sync)
GUEST_STRUCT(%g2)
RA2PA_RANGE_CONV_UNK_SIZE(%g2, %o1, %o2, herr_noraddr, %g4, %g3)
mov %o2, %o1
HCALL_RET(EOK);
SET_SIZE(piu_dma_sync)
/*
* piu_io_peek
*
* %g1 = PIU Cookie Pointer
* arg0 devhandle (%o0)
* arg1 r_addr (%o1)
* arg2 size (%o2)
* --
* ret0 status (%o0)
* ret1 error? (%o1)
* ret2 data (%o2)
*/
ENTRY_NP(piu_io_peek)
GUEST_STRUCT(%g2)
! %g2 = Guestp
! %o1 = ra
! %o2 = size
! %g4, %g5 = scratch
RANGE_CHECK_IO(%g2, %o1, %o2, .piu_io_peek_found, herr_noraddr,
%g4, %g6)
.piu_io_peek_found:
mov 1, %g5
STRAND_STRUCT(%g4)
set STRAND_IO_PROT, %g6
! strand.io_prot = 1
stx %g5, [%g4 + %g6]
! %g1 = PIU cookie
! %g4 = strand struct
DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
cmp %o2, SZ_LONG
beq,a,pn %xcc,1f
ldxa [%o1]ASI_P_LE, %o2
cmp %o2, SZ_WORD
beq,a,pn %xcc,1f
lduwa [%o1]ASI_P_LE, %o2
cmp %o2, SZ_HWORD
beq,a,pn %xcc,1f
lduha [%o1]ASI_P_LE, %o2
ldub [%o1], %o2
1: set STRAND_IO_PROT, %g6
! strand.io_prot = 0
stx %g0, [%g4 + %g6]
set STRAND_IO_ERROR, %g6
! strand.io_error
ldx [%g4 + %g6], %o1
! strand.io_error = 0
stx %g0, [%g4 + %g6]
! %g1 = PIU cookie
ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
HCALL_RET(EOK)
SET_SIZE(piu_io_peek)
/*
* piu_io_poke
*
* %g1 = PIU Cookie Pointer
* arg0 devhandle (%o0)
* arg1 r_addr (%o1)
* arg2 size (%o2)
* arg3 data (%o3)
* arg4 PCI device (%o4)
* --
* ret0 status (%o0)
* ret1 error? (%o1)
*/
ENTRY_NP(piu_io_poke)
ldx [%g1 + PIU_COOKIE_CFG], %g3
GUEST_STRUCT(%g2)
! %g2 = Guestp
! %o1 = ra
! %o2 = size
! %g4, %g5 = scratch
RANGE_CHECK_IO(%g2, %o1, %o2, .piu_io_poke_found, herr_noraddr,
%g4, %g6)
.piu_io_poke_found:
PCIDEV2PIUDEV(%o4, %g2)
mov 1, %g5
STRAND_STRUCT(%g4)
set STRAND_IO_PROT, %g6
! strand.io_prot = 1
stx %g5, [%g4 + %g6]
! %g1 = PIU cookie
! %g2 = PCI device BDF
! %g3 = CFG base address
! %g4 = strand struct
DISABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
cmp %o2, SZ_LONG
beq,a,pn %xcc,1f
stxa %o3, [%o1]ASI_P_LE
cmp %o2, SZ_WORD
beq,a,pn %xcc,1f
stwa %o3, [%o1]ASI_P_LE
cmp %o2, SZ_HWORD
beq,a,pn %xcc,1f
stha %o3, [%o1]ASI_P_LE
stb %o3, [%o1]
1:
! Read from PCI config space
ldub [%g3 + %g2], %g0
set STRAND_IO_PROT, %g6
! strand.io_prot = 0
stx %g0, [%g4 + %g6]
set STRAND_IO_ERROR, %g6
! strand.io_error
ldx [%g4 + %g6], %o1
! strand.io_error = 0
stx %g0, [%g4 + %g6]
! %g1 = PIU cookie
ENABLE_PCIE_RWUC_ERRORS(%g1, %g5, %g6, %g7)
HCALL_RET(EOK)
SET_SIZE(piu_io_poke)
/*
* piu_mondo_receive
*
* %g1 = PIU Cookie
* %g2 = Mondo DATA0
* %g3 = Mondo DATA1
*/
ENTRY_NP(piu_mondo_receive)
ba insert_device_mondo_r
rd %pc, %g7
retry
SET_SIZE(piu_mondo_receive)
/*
* piu_msiq_conf
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI EQ id (%o1)
* arg2 EQ base RA (%o2)
* arg3 #entries (%o3)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_msiq_conf)
cmp %o1, PIU_NEQS
bgeu,pn %xcc, herr_inval
sethi %hi(PIU_EQSIZE-1), %g2
or %g2, %lo(PIU_EQSIZE-1), %g2
and %o2, %g2, %g2
brnz %g2, herr_badalign
cmp %o3, PIU_NEQRECORDS
bne herr_inval
/*
* Verify RA range/alignment
*/
set PIU_EQREC_SIZE, %g2
mulx %g2, %o3, %g4
GUEST_STRUCT(%g2)
RA2PA_RANGE_CONV(%g2, %o2, %g0, herr_noraddr, %g7, %g6)
andcc %o2, 3, %g0
bnz %xcc, herr_badalign
.empty
! %g6 PA
MSIEQNUM2MSIEQ(%g1, %o1, %g4, %g3, %g2)
ldx [%g1 + PIU_COOKIE_EQSTATE], %g2
REGNO2OFFSET(%o1, %g5)
ldx [%g2 + %g5], %g3
and %g3, 3, %g3
sub %g3, 1, %g3
brnz %g3, herr_inval
ldx [%g1 + PIU_COOKIE_EQHEAD], %g2
ldx [%g1 + PIU_COOKIE_EQTAIL], %g3
stx %g0, [%g2 + %g5]
stx %g0, [%g3 + %g5]
stx %g6, [%g4 + PIU_MSIEQ_GUEST]
HCALL_RET(EOK)
SET_SIZE(piu_msiq_conf)
/*
* piu_msiq_info
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI EQ id (%o1)
* --
* ret0 status (%o0)
* ret1 ra (%o1)
* ret2 #entries (%o2)
*/
ENTRY_NP(piu_msiq_info)
cmp %o1, PIU_NEQS
bgeu,pn %xcc, herr_inval
.empty
MSIEQNUM2MSIEQ(%g1, %o1, %g4, %g3, %g5)
ldx [%g4 + PIU_MSIEQ_GUEST], %g5
set PIU_NEQRECORDS, %o2
movrz %g5, %g0, %o2
brz,pn %g5, 1f
GUEST_STRUCT(%g2)
PA2RA_CONV(%g2, %g5, %o1, %g6, %g4) ! PA -> RA (%o1)
1: HCALL_RET(EOK)
SET_SIZE(piu_msiq_info)
/*
* piu_msiq_getvalid
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI EQ id (%o1)
* --
* ret0 status (%o0)
* ret1 EQ valid (%o1) (0: Invalid 1: Valid)
*/
ENTRY_NP(piu_msiq_getvalid)
VPCI_PRINT1("HV:msiq_getvalid ", %o1)
cmp %o1, PIU_NEQS
bgeu,pn %xcc, herr_inval
ldx [%g1 + PIU_COOKIE_EQSTATE], %g2
REGNO2OFFSET(%o1, %g7)
ldx [%g2 + %g7], %g4
and %g4, 3, %g4
sub %g4, 1, %o1
HCALL_RET(EOK)
SET_SIZE(piu_msiq_getvalid)
/*
* piu_msiq_setvalid
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI EQ id (%o1)
* arg2 EQ valid (%o2) (0: Invalid 1: Valid)
* --
* ret0 status
*/
ENTRY_NP(piu_msiq_setvalid)
VPCI_PRINT2("HV:msiq_setvalid ", %o1, %o2)
cmp %o1, PIU_NEQS
bgeu,pn %xcc, herr_inval
.empty
MSIEQNUM2MSIEQ(%g1, %o1, %g3, %g2, %g4)
ldx [%g3 + PIU_MSIEQ_GUEST], %g2 ! Guest Q base
brnz %g2, 1f
movrz %o2, PIU_COOKIE_EQCTLCLR, %g3
brnz %o2, herr_inval
1: movrnz %o2, PIU_COOKIE_EQCTLSET, %g3
ldx [%g1 + %g3], %g3
setx (1<<44), %g5, %g4
REGNO2OFFSET(%o1, %g7)
stx %g4, [%g3 + %g7]
HCALL_RET(EOK)
SET_SIZE(piu_msiq_setvalid)
/*
* piu_msiq_getstate
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI EQ id (%o1)
* --
* ret0 status (%o0)
* ret1 EQ state (%o1) (0: Idle 1: Error)
*/
ENTRY_NP(piu_msiq_getstate)
VPCI_PRINT1("HV:msiq_getstate ", %o1)
cmp %o1, PIU_NEQS
bgeu,pn %xcc, herr_inval
REGNO2OFFSET(%o1, %g4)
ldx [%g1 + PIU_COOKIE_EQSTATE], %g2
ldx [%g2 + %g4], %g3
and %g3, 4, %o1
movrnz %o1, HVIO_MSIQSTATE_ERROR, %o1
HCALL_RET(EOK)
SET_SIZE(piu_msiq_getstate)
/*
* piu_msiq_setstate
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI EQ id (%o1)
* arg2 EQ state (%o2) (0: Idle 1: Error)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_msiq_setstate)
VPCI_PRINT2("HV:msiq_setstate ", %o1, %o2)
REGNO2OFFSET(%o1, %g4)
cmp %o1, PIU_NEQS
bgeu,pn %xcc, herr_inval
.empty
/*
* To change state from error to idle, we set bits 57 and 47 in the
* Event Queue Control Clear Register (CCR)
*
* To change state from idle to error, we set bits 44 and 57 in the
* Event Queue Control Set Register (CSR)
*/
mov PIU_COOKIE_EQCTLCLR, %g6 ! EQ CCR
movrnz %o2, PIU_COOKIE_EQCTLSET, %g6 ! EQ CSR
ldx [%g1 + %g6], %g2
setx (1 << PIU_EQCCR_COVERR)|(1 << PIU_EQCCR_E2I_SHIFT), %g5, %g3 ! set idle
setx (1 << PIU_EQCSR_ENOVERR)|(1 << PIU_EQCSR_EN_SHIFT), %g5, %g6 ! set error
movrnz %o2, %g6, %g3
stx %g3, [%g2 + %g4]
HCALL_RET(EOK)
SET_SIZE(piu_msiq_setstate)
/*
* piu_msiq_gethead
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI EQ id (%o1)
* --
* ret0 status
* ret1 head index
*/
ENTRY_NP(piu_msiq_gethead)
VPCI_PRINT1("HV:msiq_gethead ", %o1)
cmp %o1, PIU_NEQS
bgeu,pn %xcc, herr_inval
REGNO2OFFSET(%o1, %g4)
ldx [%g1 + PIU_COOKIE_EQHEAD], %g2
ldx [%g2 + %g4], %o1
sllx %o1, PIU_EQREC_SHIFT, %o1
HCALL_RET(EOK)
SET_SIZE(piu_msiq_gethead)
/*
* piu_msiq_sethead
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI EQ id (%o1)
* arg2 head offset (%o2)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_msiq_sethead)
VPCI_PRINT2("HV:msiq_sethead ", %o1, %o2)
cmp %o1, PIU_NEQS
bgeu,pn %xcc, herr_inval
set PIU_EQSIZE, %g2
cmp %o2, %g2
bgeu,pn %xcc, herr_inval
REGNO2OFFSET(%o1, %g6)
ldx [%g1 + PIU_COOKIE_EQHEAD], %g2
ldx [%g2 + %g6], %g3
mov %o2, %g6
sllx %g3, PIU_EQREC_SHIFT, %g3
!! %g1 = PIU COOKIE
!! %g2 = EQ HEAD reg
!! %g3 = Prev Head offset
!! %g6 = New Head offset
MSIEQNUM2MSIEQ(%g1, %o1, %g4, %g5, %g7)
!! %g1 = PIU COOKIE
!! %g2 = EQ HEAD reg
!! %g3 = Prev Head offset
!! %g4 = struct *piu_msieq
!! %g6 = New Head offset
ldx [%g4 + PIU_MSIEQ_BASE], %g5 /* HW Q base */
add %g5, %g3, %g7
1:
stx %g0, [%g7 + 0x00]
stx %g0, [%g7 + 0x08]
stx %g0, [%g7 + 0x10]
stx %g0, [%g7 + 0x18]
stx %g0, [%g7 + 0x20]
stx %g0, [%g7 + 0x28]
stx %g0, [%g7 + 0x30]
stx %g0, [%g7 + 0x38]
add %g3, 0x40, %g3
ldx [%g4 + PIU_MSIEQ_EQMASK], %g7
and %g3, %g7, %g3
cmp %g6, %g3
bne 1b
add %g5, %g3, %g7
REGNO2OFFSET(%o1, %g6)
srlx %o2, PIU_EQREC_SHIFT, %g3
stx %g3, [%g2 + %g6]
HCALL_RET(EOK)
SET_SIZE(piu_msiq_sethead)
/*
* piu_msiq_gettail
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI EQ id (%o1)
* --
* ret0 status (%o0)
* ret1 tail index (%o1)
*/
ENTRY_NP(piu_msiq_gettail)
VPCI_PRINT1("HV:msiq_gettail ", %o1)
cmp %o1, PIU_NEQS
bgeu,pn %xcc, herr_inval
REGNO2OFFSET(%o1, %g4)
ldx [%g1 + PIU_COOKIE_EQTAIL], %g2
ldx [%g2 + %g4], %o1
sllx %o1, PIU_EQREC_SHIFT, %o1
HCALL_RET(EOK)
SET_SIZE(piu_msiq_gettail)
/*
* piu_msi_getvalid
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI number (%o1)
* --
* ret0 status (%o0)
* ret1 MSI status (%o1) (0: Invalid 1: Valid)
*/
ENTRY_NP(piu_msi_getvalid)
VPCI_PRINT1("HV:msiq_getvalid ", %o1)
cmp %o1, PIU_MSI_MASK
bgu,pn %xcc, herr_inval
REGNO2OFFSET(%o1, %g4)
ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
ldx [%g2 + %g4], %g5
mov HVIO_MSI_INVALID, %o1
movrlz %g5, HVIO_MSI_VALID, %o1
HCALL_RET(EOK)
SET_SIZE(piu_msi_getvalid)
/*
* piu_msi_setvalid
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI number (%o1)
* arg2 MSI status (%o2) (0: Invalid 1: Valid)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_msi_setvalid)
VPCI_PRINT2("HV:msiq_setvalid ", %o1, %o2)
cmp %o1, PIU_MSI_MASK
bgu,pn %xcc, herr_inval
REGNO2OFFSET(%o1, %g4)
ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
ldx [%g2 + %g4], %g5
sllx %g5, 1, %g5
srlx %g5, 1, %g5
sllx %o2, PIU_MSIMR_V_SHIFT, %g3
or %g5, %g3, %g5
stx %g5, [%g2 + %g4]
HCALL_RET(EOK)
SET_SIZE(piu_msi_setvalid)
/*
* piu_msi_getstate
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI number (%o1)
* --
* ret0 status (%o0)
* ret1 MSI state (%o1) (0: Idle 1: Delivered)
*/
ENTRY_NP(piu_msi_getstate)
VPCI_PRINT1("HV:msi_getstate ", %o1)
cmp %o1, PIU_MSI_MASK
bgu,pn %xcc, herr_inval
REGNO2OFFSET(%o1, %g4)
ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
ldx [%g2 + %g4], %g5
brlz,pn %g5, 0f
mov HVIO_MSI_INVALID, %o1
HCALL_RET(EOK)
0: srlx %g5, PIU_MSIMR_EQWR_N_SHIFT, %o1
and %o1, HVIO_MSI_VALID, %o1
HCALL_RET(EOK)
SET_SIZE(piu_msi_getstate)
/*
* piu_msi_setstate
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI number (%o1)
* arg2 MSI state (%o2) (0: Idle)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_msi_setstate)
VPCI_PRINT2("HV:msi_setstate ", %o1, %o2)
cmp %o1, PIU_MSI_MASK
bgu,pn %xcc, herr_inval
REGNO2OFFSET(%o1, %g4)
brnz,pn %o2, herr_inval
mov 1, %g5
sllx %g5, PIU_MSIMR_EQWR_N_SHIFT, %g5
ldx [%g1 + PIU_COOKIE_MSICLR], %g2
stx %g5, [%g2 + %g4]
HCALL_RET(EOK)
SET_SIZE(piu_msi_setstate)
/*
* piu_msi_getmsiq
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI number (%o1)
* --
* ret0 status (%o0)
* ret1 MSI EQ id (%o1)
*/
ENTRY_NP(piu_msi_getmsiq)
VPCI_PRINT1("HV:msi_getmsiq ", %o1)
cmp %o1, PIU_MSI_MASK
bgu,pn %xcc, herr_inval
REGNO2OFFSET(%o1, %g7)
ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
ldx [%g2 + %g7], %o1
and %o1, PIU_MSIEQNUM_MASK, %o1
HCALL_RET(EOK)
SET_SIZE(piu_msi_getmsiq)
/*
* piu_msi_setmsiq
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI number (%o1)
* arg2 MSI EQ id (%o2)
* arg3 MSI type (%o3) (MSI32=0 MSI64=1)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_msi_setmsiq)
VPCI_PRINT2("HV:msi_setmsiq ", %o1, %o2)
cmp %o1, PIU_MSI_MASK
bgu,pn %xcc, herr_inval
cmp %o2, PIU_NEQS
bgeu,pn %xcc, herr_inval
ldx [%g1 + PIU_COOKIE_MSIMAP], %g2
REGNO2OFFSET(%o1, %g7)
ldx [%g2 + %g7], %g5
andn %g5, PIU_MSIEQNUM_MASK, %g5
or %g5, %o2, %g5
stx %g5, [%g2 + %g7]
HCALL_RET(EOK)
SET_SIZE(piu_msi_setmsiq)
/*
* piu_msi_msg_getmsiq
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI msg type (%o1)
* --
* ret0 status (%o0)
* ret1 MSI EQ id (%o1)
*/
ENTRY_NP(piu_msi_msg_getmsiq)
VPCI_PRINT1("HV:msi_msg_getmsiq ", %o1)
ldx [%g1 + PIU_COOKIE_MSGMAP], %g2
cmp %o1, PCIE_CORR_MSG
be,a,pn %xcc, 1f
mov PIU_CORR_OFF, %g3
cmp %o1, PCIE_NONFATAL_MSG
be,a,pn %xcc, 1f
mov PIU_NONFATAL_OFF, %g3
cmp %o1, PCIE_FATAL_MSG
be,a,pn %xcc, 1f
mov PIU_FATAL_OFF, %g3
cmp %o1, PCIE_PME_MSG
be,a,pn %xcc, 1f
mov PIU_PME_OFF, %g3
cmp %o1, PCIE_PME_ACK_MSG
be,a,pn %xcc, 1f
mov PIU_PME_ACK_OFF, %g3
ba herr_inval
nop
1: ldx [%g2 + %g3], %o1
and %o1, PIU_MSIEQNUM_MASK, %o1
HCALL_RET(EOK)
SET_SIZE(piu_msi_msg_getmsiq)
/*
* piu_msi_msg_setmsiq
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI msg type (%o1)
* arg2 MSI EQ id (%o2)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_msi_msg_setmsiq)
VPCI_PRINT2("HV:msi_msg_setmsiq ", %o1, %o2)
cmp %o2, PIU_NEQS
bgeu,pn %xcc, herr_inval
ldx [%g1 + PIU_COOKIE_MSGMAP], %g2
cmp %o1, PCIE_CORR_MSG
be,a,pn %xcc, 1f
mov PIU_CORR_OFF, %g3
cmp %o1, PCIE_NONFATAL_MSG
be,a,pn %xcc, 1f
mov PIU_NONFATAL_OFF, %g3
cmp %o1, PCIE_FATAL_MSG
be,a,pn %xcc, 1f
mov PIU_FATAL_OFF, %g3
cmp %o1, PCIE_PME_MSG
be,a,pn %xcc, 1f
mov PIU_PME_OFF, %g3
cmp %o1, PCIE_PME_ACK_MSG
be,a,pn %xcc, 1f
mov PIU_PME_ACK_OFF, %g3
ba herr_inval
nop
1: ldx [%g2 + %g3], %g4
andn %g4, PIU_MSIEQNUM_MASK, %g4
or %g4, %o2, %g4
stx %g4, [%g2 + %g3]
HCALL_RET(EOK)
SET_SIZE(piu_msi_msg_setmsiq)
/*
* piu_msi_msg_getvalid
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI msg type (%o1)
* --
* ret0 status (%o0)
* ret1 MSI msg valid state (%o1)
*/
ENTRY_NP(piu_msi_msg_getvalid)
VPCI_PRINT1("HV:msi_msg_getvalid ", %o1)
ldx [%g1 + PIU_COOKIE_MSGMAP], %g2
cmp %o1, PCIE_CORR_MSG
be,a,pn %xcc, 1f
ldx [%g2 + PIU_CORR_OFF], %g3
cmp %o1, PCIE_NONFATAL_MSG
be,a,pn %xcc, 1f
ldx [%g2 + PIU_NONFATAL_OFF], %g3
cmp %o1, PCIE_FATAL_MSG
be,a,pn %xcc, 1f
ldx [%g2 + PIU_FATAL_OFF], %g3
cmp %o1, PCIE_PME_MSG
be,a,pn %xcc, 1f
ldx [%g2 + PIU_PME_OFF], %g3
cmp %o1, PCIE_PME_ACK_MSG
be,a,pn %xcc, 1f
ldx [%g2 + PIU_PME_ACK_OFF], %g3
ba,pt %xcc, herr_inval
nop
1: movrlz %g3, HVIO_PCIE_MSG_VALID, %o1
movrgez %g3, HVIO_PCIE_MSG_INVALID, %o1
HCALL_RET(EOK)
SET_SIZE(piu_msi_msg_getvalid)
/*
* piu_msi_msg_setvalid
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 MSI msg type (%o1)
* arg2 MSI msg valid state (%o2)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_msi_msg_setvalid)
VPCI_PRINT2("HV:msi_msg_setvalid ", %o1, %o2)
cmp %o2, 1
bgu,pn %xcc, herr_inval
ldx [%g1 + PIU_COOKIE_MSGMAP], %g2
cmp %o1, PCIE_CORR_MSG
be,a,pn %xcc, 1f
mov PIU_CORR_OFF, %g3
cmp %o1, PCIE_NONFATAL_MSG
be,a,pn %xcc, 1f
mov PIU_NONFATAL_OFF, %g3
cmp %o1, PCIE_FATAL_MSG
be,a,pn %xcc, 1f
mov PIU_FATAL_OFF, %g3
cmp %o1, PCIE_PME_MSG
be,a,pn %xcc, 1f
mov PIU_PME_OFF, %g3
cmp %o1, PCIE_PME_ACK_MSG
be,a,pn %xcc, 1f
mov PIU_PME_ACK_OFF, %g3
ba herr_inval
nop
1:
sllx %o2, PIU_MSGMR_V_SHIFT, %g5
ldx [%g2 + %g3], %g4
sllx %g4, 1, %g4
srlx %g4, 1, %g4
or %g4, %g5, %g4
stx %g4, [%g2 + %g3]
HCALL_RET(EOK)
SET_SIZE(piu_msi_msg_setvalid)
/*
* piu_msi_mondo_receive
*
* %g1 = PIU Cookie
* %g2 = Mondo DATA0
* %g3 = Mondo DATA1
*/
ENTRY_NP(piu_msi_mondo_receive)
STRAND_PUSH(%g1, %g6, %g7)
STRAND_PUSH(%g2, %g6, %g7)
STRAND_PUSH(%g3, %g6, %g7)
ba insert_device_mondo_r
rd %pc, %g7
STRAND_POP(%g3, %g6)
STRAND_POP(%g2, %g6)
STRAND_POP(%g1, %g6)
and %g2, PIU_DEVINO_MASK, %g2
sub %g2, PIU_EQ2INO(0), %g2
MSIEQNUM2MSIEQ(%g1, %g2, %g3, %g4, %g5)
! %g1 = PIU Cookie
! %g2 = MSI EQ Number
! %g3 = struct *piu_msieq
REGNO2OFFSET(%g2, %g2)
ldx [%g1 + PIU_COOKIE_EQTAIL], %g5
ldx [%g5 + %g2], %g7
ldx [%g1 + PIU_COOKIE_EQHEAD], %g5
ldx [%g5 + %g2], %g6
! %g1 = PIU COOKIE
! %g2 = MSI EQ OFFSET
! %g3 = struct piu_msieq *
! %g6 = Head
! %g7 = New Tail
cmp %g6, %g7
be 9f
sllx %g6, PIU_EQREC_SHIFT, %g6 /* New tail offset */
sllx %g7, PIU_EQREC_SHIFT, %g7 /* Old Tail offset */
ldx [%g3 + PIU_MSIEQ_GUEST], %g2 /* Guest Q base */
brz,pn %g2, 9f
ldx [%g3 + PIU_MSIEQ_BASE], %g5 /* HW Q base */
! %g2 = Guest Q base
! %g3 = struct piu_msieq *
! %g5 = HW Q base
! %g6 = Old Tail
! %g7 = New Tail
! %g1 = scratch
! %g4 = scratch
1:
! Word 0 is TTTT EQW0[63:61]
ldx [%g5 + %g6], %g1 ! Read Word 0 From HW
stx %g1, [%g3 + PIU_MSIEQ_WORD0]
srlx %g1, PIU_EQREC_TYPE_SHIFT+5, %g4
stx %g4, [%g2 + %g6] ! Store Word 0
add %g6, 8, %g6
ldx [%g5 + %g6], %g4 ! Read Word 1 from HW
stx %g4, [%g3 + PIU_MSIEQ_WORD1]
stx %g0, [%g2 + %g6] ! Store Word 1 = 0
add %g6, 8, %g6
stx %g0, [%g2 + %g6] ! Store Word 2 = 0
add %g6, 8, %g6
stx %g0, [%g2 + %g6] ! Store Word 3 = 0
add %g6, 8, %g6
! Word 4 is RRRR.RRRR EQW0[31:16]
sllx %g1, 64-(MSIEQ_RID_SHIFT+MSIEQ_RID_SIZE_BITS), %g4
srlx %g4, 64-MSIEQ_RID_SHIFT, %g4
stx %g4, [%g2 + %g6] ! Store Word 4
add %g6, 8, %g6
! Word 5 is MSI address EQW1[63:0]
ldx [%g3 + PIU_MSIEQ_WORD1], %g4
stx %g4, [%g2 + %g6] ! Store Word 5
add %g6, 8, %g6
! Word 6 is MSI Data EQW0[15:0]
sllx %g1, 1, %g4
brgz,pt %g4, 2f
sllx %g1, 64-MSIEQ_DATA_SIZE_BITS, %g4
! MSI
srlx %g4, 64-MSIEQ_DATA_SIZE_BITS, %g4
stx %g4, [%g2 + %g6] ! Store Word 6
ba 3f
add %g6, 8, %g6
2: ! MSG
! %g1 = HW Word 0
! Extract GGGG.GGGG EQW0[31:16] -> W6[47:32]
srlx %g1, MSIEQ_TID_SHIFT, %g4
sllx %g4, 64-MSIEQ_TID_SIZE_BITS, %g4
srlx %g4, 64-(MSIEQ_TID_SIZE_BITS+VPCI_MSIEQ_TID_SHIFT), %g4
ldx [%g3 + PIU_MSIEQ_WORD0], %g1
! Extract CCC field EQW0[58:56] -> W6[18:16]
sllx %g1, 64-(MSIEQ_MSG_RT_CODE_SHIFT+MSIEQ_MSG_RT_CODE_SIZE_BITS), %g1
srlx %g1, 64-MSIEQ_MSG_RT_CODE_SIZE_BITS, %g1
sllx %g1, VPCI_MSIEQ_MSG_RT_CODE_SHIFT, %g1
or %g1, %g4, %g4
ldx [%g3 + PIU_MSIEQ_WORD0], %g1
! Extract MMMM.MMMM field EQW0[7:0] -> W6[7:0]
sllx %g1, 64-MSIEQ_MSG_CODE_SIZE_BITS, %g1
srlx %g1, 64-MSIEQ_MSG_CODE_SIZE_BITS, %g1
or %g1, %g4, %g4
stx %g4, [%g2 + %g6] ! Store Word 6
add %g6, 8, %g6
3:
stx %g0, [%g2 + %g6] ! Store Word 7
add %g6, 8, %g6
ldx [%g3 + PIU_MSIEQ_EQMASK], %g4
and %g6, %g4, %g6
cmp %g6, %g7
bne 1b
nop
9:
retry
SET_SIZE(piu_msi_mondo_receive)
/*
* Each register entry is 0x20 bytes
*/
#define PIU_PERF_READ_ADR (0 * SIZEOF_UI64)
#define PIU_PERF_READ_MASK (1 * SIZEOF_UI64)
#define PIU_PERF_WRITE_ADR (2 * SIZEOF_UI64)
#define PIU_PERF_WRITE_MASK (3 * SIZEOF_UI64)
#define PIU_PERF_TBL_ENTRY_SIZE (4 * SIZEOF_UI64)
#define PIU_PERF_TBL_ENTRY_SHIFT 5 /* log2(TBL_ENTRY_SIZE) */
#define PIU_PERF_TBL_NENTRIES ((piu_perf_regs_table_end - \
piu_perf_regs_table) / PIU_PERF_TBL_ENTRY_SIZE)
#define PIU_REGID2OFFSET(id, offset) \
sllx id, PIU_PERF_TBL_ENTRY_SHIFT, offset
.align 8
.section ".text"
piu_perf_regs_table:
! Registers 0 - 2
.xword PIU_DLC_IMU_ICS_IMU_PERF_CNTRL, 0x000000000000ffff
.xword PIU_DLC_IMU_ICS_IMU_PERF_CNTRL, 0x000000000000ffff
.xword PIU_DLC_IMU_ICS_IMU_PERF_CNT0, 0xffffffffffffffff
.xword PIU_DLC_IMU_ICS_IMU_PERF_CNT0, 0xffffffffffffffff
.xword PIU_DLC_IMU_ICS_IMU_PERF_CNT1, 0xffffffffffffffff
.xword PIU_DLC_IMU_ICS_IMU_PERF_CNT1, 0xffffffffffffffff
! Registers 3 - 5
.xword PIU_DLC_MMU_PRFC, 0x000000000000ffff
.xword PIU_DLC_MMU_PRFC, 0x000000000000ffff
.xword PIU_DLC_MMU_PRF0, 0xffffffffffffffff
.xword PIU_DLC_MMU_PRF0, 0xffffffffffffffff
.xword PIU_DLC_MMU_PRF1, 0xffffffffffffffff
.xword PIU_DLC_MMU_PRF1, 0xffffffffffffffff
! Registers 6 - 9
.xword PIU_PLC_TLU_CTB_TLR_TLU_PRFC, 0x000000000003ffff
.xword PIU_PLC_TLU_CTB_TLR_TLU_PRFC, 0x000000000003ffff
.xword PIU_PLC_TLU_CTB_TLR_TLU_PRF0, 0xffffffffffffffff
.xword PIU_PLC_TLU_CTB_TLR_TLU_PRF0, 0xffffffffffffffff
.xword PIU_PLC_TLU_CTB_TLR_TLU_PRF1, 0xffffffffffffffff
.xword PIU_PLC_TLU_CTB_TLR_TLU_PRF1, 0xffffffffffffffff
.xword PIU_PLC_TLU_CTB_TLR_TLU_PRF2, 0x00000000ffffffff
.xword PIU_PLC_TLU_CTB_TLR_TLU_PRF2, 0x00000000ffffffff
! Registers 10 - 11
.xword PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_BIT_ERR_CNT_1_ADDR, 0xc0000000ffff003f
.xword PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_BIT_ERR_CNT_1_ADDR, 0xc000000000000000
.xword PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_BIT_ERR_CNT_2_ADDR, 0x3f3f3f3f3f3f3f3f
.xword PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_BIT_ERR_CNT_2_ADDR, 0x0000000000000000
piu_perf_regs_table_end:
/*
* piu_get_perf_reg
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 perf reg ID (%o1)
* --
* ret0 status (%o0)
* ret1 value (%o1)
*/
ENTRY_NP(piu_get_perf_reg)
cmp %o1, PIU_PERF_TBL_NENTRIES
bgeu,pn %xcc, herr_inval
mov 1, %g3
sllx %g3, %o1, %g3
ldx [%g1 + PIU_COOKIE_PERFREGS], %g2
and %g2, %g3, %g3
brz,pn %g3, herr_inval
ldx [%g1 + PIU_COOKIE_PCIE], %g2
! %g1 = PIU cookie pointer
! %g2 = PIU base PA
LABEL_ADDRESS(piu_perf_regs_table, %g4)
! %g1 = PIU cookie pointer
! %g2 = PIU base PA
! %g4 = Performance regs table
PIU_REGID2OFFSET(%o1, %g3)
add %g3, %g4, %g4
ldx [%g4 + PIU_PERF_READ_ADR], %g3
ldx [%g4 + PIU_PERF_READ_MASK], %g4
! %g1 = PIU cookie pointer
! %g2 = PIU base PA
! %g3 = Perf reg offset
! %g4 = Perf reg mask
ldx [%g2 + %g3], %o1
and %o1, %g4, %o1
HCALL_RET(EOK)
SET_SIZE(piu_get_perf_reg)
/*
* piu_set_perf_reg
*
* %g1 = PIU Cookie Pointer
* arg0 dev config pa (%o0)
* arg1 perf reg ID (%o1)
* arg2 value (%o2)
* --
* ret0 status (%o0)
*/
ENTRY_NP(piu_set_perf_reg)
cmp %o1, PIU_PERF_TBL_NENTRIES
bgeu,pn %xcc, herr_inval
mov 1, %g3
sllx %g3, %o1, %g3
ldx [%g1 + PIU_COOKIE_PERFREGS], %g2
and %g2, %g3, %g3
brz,pn %g3, herr_inval
ldx [%g1 + PIU_COOKIE_PCIE], %g2
! %g1 = PIU cookie pointer
! %g2 = PIU base PA
LABEL_ADDRESS(piu_perf_regs_table, %g4)
! %g1 = PIU cookie pointer
! %g2 = PIU base PA
! %g4 = Performance regs table
PIU_REGID2OFFSET(%o1, %g3)
add %g3, %g4, %g4
ldx [%g4 + PIU_PERF_WRITE_ADR], %g3
ldx [%g4 + PIU_PERF_WRITE_MASK], %g4
! %g1 = PIU cookie pointer
! %g2 = PIU base PA
! %g3 = Perf reg offset
! %g4 = Perf reg mask
and %o2, %g4, %g5
stx %g5, [%g2 + %g3]
HCALL_RET(EOK)
SET_SIZE(piu_set_perf_reg)
#ifdef DEBUG
! When DEBUG is defined hcall.s versions
! of these are labels are too far away
herr_nocpu: HCALL_RET(ENOCPU)
herr_nomap: HCALL_RET(ENOMAP)
herr_inval: HCALL_RET(EINVAL)
herr_badalign: HCALL_RET(EBADALIGN)
#endif
#define PIU_INVALIDATE_INTX(piup, intx_off, scr1, scr2) \
ldx [piup + PIU_COOKIE_PCIE], scr1 ;\
set intx_off, scr2 ;\
add scr1, scr2, scr1 ;\
set 1, scr2 ;\
stx scr2, [scr1]
/*
* PIU_MSIQ_UNCONFIGURE
*
* piu - (preserved) PIU Cookie Pointer
* msieq_id - (preserved) MSI EQ id
*
*/
#define PIU_MSIQ_UNCONFIGURE(piu, msieq_id, scr1, scr2, scr3, scr4) \
.pushlocals ;\
cmp msieq_id, PIU_NEQS ;\
bgeu,pn %xcc, 0f ;\
MSIEQNUM2MSIEQ(piu, msieq_id, scr3, scr2, scr1) ;\
REGNO2OFFSET(msieq_id, scr4) ;\
ldx [piu + PIU_COOKIE_EQHEAD], scr1 ;\
ldx [piu + PIU_COOKIE_EQTAIL], scr2 ;\
stx %g0, [scr1 + scr4] ;\
stx %g0, [scr2 + scr4] ;\
stx %g0, [scr3 + PIU_MSIEQ_GUEST] ;\
0: ;\
.poplocals
/*
* PIU_MSIQ_INVALIDATE
*
* piu - (preserved) PIU Cookie Pointer
* msieq_id - (preserved) MSI EQ id
*
*/
#define PIU_MSIQ_INVALIDATE(piu, msieq_id, scr1, scr2, scr3, scr4) \
.pushlocals ;\
cmp msieq_id, PIU_NEQS ;\
bgeu,pn %xcc, 0f ;\
nop ;\
ldx [piu + PIU_COOKIE_EQCTLCLR], scr1 ;\
/* setx (1<<44), scr3, scr2 */ ;\
/* 44=disable, 47=e2i 57=coverr */ ;\
setx (1<<44)|(1<<47)|(1<<57), scr3, scr2 ;\
REGNO2OFFSET(msieq_id, scr4) ;\
stx scr2, [scr1 + scr4] ;\
0: ;\
.poplocals
/*
* PIU_MSI_INVALIDATE - Invalidate the MSI mappings and then clear
* the MSI status (mark as "idle")
*
* piu - (preserved) PIU Cookie Pointer
* msi_num - (preserved) MSI number (%o1)
*
*/
#define PIU_MSI_INVALIDATE(piu, msi_num, scr1, scr2, scr3) \
.pushlocals ;\
cmp msi_num, PIU_MSI_MASK ;\
bgu,pn %xcc, 0f ;\
REGNO2OFFSET(msi_num, scr2) ;\
ldx [piu + PIU_COOKIE_MSIMAP], scr1 ;\
ldx [scr1 + scr2], scr3 ;\
/* clear both bits 62 and 63 in the map reg */ ;\
/* valid and ok to write (pending MSI) bit */ ;\
sllx scr3, 2, scr3 ;\
srlx scr3, 2, scr3 ;\
stx scr3, [scr1 + scr2] ;\
mov 1, scr3 /* now mark status as "idle" */ ;\
sllx scr3, PIU_MSIMR_EQWR_N_SHIFT, scr3 ;\
ldx [piu + PIU_COOKIE_MSICLR], scr1 ;\
stx scr3, [scr1 + scr2] ;\
0: ;\
.poplocals
/*
* PIU_MSI_MSG_INVALIDATE
*
* piu - (preserved) PIU Cookie Pointer
* msg_offset - (preserved) message offset such as PIU_CORR_OFF,
* PIU_NONFATAL_OFF, etc. (reg or contant)
*
*/
#define PIU_MSI_MSG_INVALIDATE(piu, msg_offset, scr1, scr2) \
ldx [piu+ PIU_COOKIE_MSGMAP], scr1 ;\
ldx [scr1 + msg_offset], scr2 ;\
sllx scr2, 1, scr2 ;\
srlx scr2, 1, scr2 ;\
stx scr2, [scr1 + msg_offset]
! %g1 PIU cookie
! %g7 return address
ENTRY(piu_leaf_soft_reset)
!
! if piu is blacklisted just skip this
!
lduw [%g1 + PIU_COOKIE_BLACKLIST], %g4
brnz,pn %g4, skip_piu_leaf_soft_reset
nop
!
! Disable Link errors
!
DISABLE_PCIE_LUP_LDN_ERRORS(%g1, %g4, %g5, %g6)
membar #Sync
!
! Put STRAND in protected mode
!
STRAND_STRUCT(%g4)
mov 1, %g5
set STRAND_IO_PROT, %g6
stx %g5, [%g4 + %g6]
membar #Sync
! clear the IOTSB
mov %g1, %g6
mov %g7, %g5
ldx [%g1 + PIU_COOKIE_IOTSB0], %g1
set IOTSB0_SIZE, %g2
HVCALL(bzero)
mov %g6, %g1
mov %g5, %g7
! %g1 piu struct
!
! Do secondary reset and initialize upstream port)
!
mov PIU_RESET_MAX_ATTEMPTS, %g3
0:
STRAND_PUSH(%g3, %g4, %g5)
mov %g0, %g2 ! %g2 bus
RESET_PIU_LEAF(%g1, %g2, %g3, %g4, %g5, %g6)
membar #Sync
STRAND_POP(%g3, %g4)
!
! Verify that the PIU link came up in x8 mode
! Give the Link Status a chance to update first
!
CPU_MSEC_DELAY(300, %g2, %g4, %g5)
set PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_ADDR, %g4
ldx [%g1 + PIU_COOKIE_PCIE], %g2
ldx [%g2 + %g4], %g2
#ifdef DEBUG
mov %g7, %g5
PRINT("PIU Link Status Register after leaf reset 0x")
PRINTX(%g2)
PRINT("\r\n")
mov %g5, %g7
#endif
srlx %g2, PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_WIDTH_SHIFT, %g2
and %g2, PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_WIDTH_MASK, %g2
cmp %g2, PIU_PLC_TLU_CTB_TLR_CSR_A_LNK_STS_WIDTH_x8
be,pt %xcc, 1f ! link width x8, continue
dec %g3
brgz,pt %g3, 0b ! < PIU_RESET_MAX_ATTEMPTS ?
nop
!
! we have exhausted the PIU link training retry limit, blacklist
! the device and move on
!
mov 1, %g4
ba,pn %xcc, piu_leaf_soft_reset_exit
stw %g4, [%g1 + PIU_COOKIE_BLACKLIST]
1:
!
! Invalidate any pending legacy (level) interrupts
! that were previously signalled from switches we just reset
!
PIU_INVALIDATE_INTX(%g1, PCI_E_INT_A_CLEAR_ADDR, %g2, %g4)
PIU_INVALIDATE_INTX(%g1, PCI_E_INT_B_CLEAR_ADDR, %g2, %g4)
PIU_INVALIDATE_INTX(%g1, PCI_E_INT_C_CLEAR_ADDR, %g2, %g4)
PIU_INVALIDATE_INTX(%g1, PCI_E_INT_D_CLEAR_ADDR, %g2, %g4)
!
! invalidate all MSIs
!
set PIU_MAX_MSIS - 1, %g2
1: PIU_MSI_INVALIDATE(%g1, %g2, %g6, %g4, %g5)
brgz,pt %g2, 1b
dec %g2
membar #Sync
!
! invalidate all MSI Messages
!
PIU_MSI_MSG_INVALIDATE(%g1, PIU_CORR_OFF, %g5, %g4)
PIU_MSI_MSG_INVALIDATE(%g1, PIU_NONFATAL_OFF, %g5, %g4)
PIU_MSI_MSG_INVALIDATE(%g1, PIU_FATAL_OFF, %g5, %g4)
PIU_MSI_MSG_INVALIDATE(%g1, PIU_PME_OFF, %g5, %g4)
PIU_MSI_MSG_INVALIDATE(%g1, PIU_PME_ACK_OFF, %g5, %g4)
!
! invalidate all interrupts
!
! invalidate inos 63 and 62, special case ones not set with
! _piu_intr_setvalid
ldx [%g1 + PIU_COOKIE_VIRTUAL_INTMAP], %g2
add %g2, DMU_ERR_MONDO_OFFSET, %g2
stb %g0, [%g2]
ldx [%g1 + PIU_COOKIE_VIRTUAL_INTMAP], %g2
add %g2, PEU_ERR_MONDO_OFFSET, %g2
stb %g0, [%g2]
STRAND_PUSH(%g7, %g4, %g5) ! _piu_intr_setvalid clobbers all regs
! Don't invalidate inos 62 & 63 in this loop, 62 and 63 done above
set NPIUDEVINO - 3, %g2
clr %g3
1: HVCALL(_piu_intr_setvalid) ! clobbers %g4-%g6
cmp %g2, 20
bgu,pt %xcc, 1b
dec %g2
membar #Sync
STRAND_POP(%g7, %g4) ! restore clobbered value
!
! invalidate and unconfigure all MSI EQs
!
set PIU_NEQS - 1, %g2
1: PIU_MSIQ_INVALIDATE(%g1, %g2, %g3, %g4, %g5, %g6)
PIU_MSIQ_UNCONFIGURE(%g1, %g2, %g3, %g4, %g5, %g6)
brgz,pt %g2, 1b
dec %g2
membar #Sync
!
! clear any pending error interrupts
! all these registers are RW1C
!
mov -1, %g3
ldx [%g1 + PIU_COOKIE_PCIE], %g2
set PIU_DLC_IMU_ICS_IMU_LOGGED_ERROR_STATUS_REG_RW1C_ALIAS, %g4
stx %g3, [%g2 + %g4]
set PIU_PLC_TLU_CTB_TLR_OE_ERR_RW1C_ALIAS, %g4
stx %g3, [%g2 + %g4]
set PCI_E_MMU_ERR_STAT_CL_ADDR, %g4
stx %g3, [%g2 + %g4]
set PCI_E_PEU_UE_STAT_CL_ADDR, %g4
stx %g3, [%g2 + %g4]
set PCI_E_ILU_ERR_STAT_CL_ADDR, %g4
stx %g3, [%g2 + %g4]
set PCI_E_PEU_CXPL_STAT_CL_ADDR, %g4
stx %g3, [%g2 + %g4]
!
! re-enable errors
!
ENABLE_PCIE_LUP_LDN_ERRORS(%g1, %g2, %g4, %g5)
membar #Sync
piu_leaf_soft_reset_exit:
!
! Bring STRAND out of protected mode
!
STRAND_STRUCT(%g4)
set STRAND_IO_PROT, %g2
stx %g0, [%g4 + %g2]
set STRAND_IO_ERROR, %g2
stx %g0, [%g4 + %g2]
skip_piu_leaf_soft_reset:
HVRET
SET_SIZE(piu_leaf_soft_reset)
/*
* Wrapper around piu_leaf_soft_reset() so that it can be called from C
* SPARC ABI requries only that g2,g3,g4 are preserved across
* function calls.
* %o0 = PIU cookie
* %o1 = root complex bus number (0)
*
* void c_piu_leaf_soft_reset(struct pcie_cookie *, uint64 root)
*/
ENTRY(c_piu_leaf_soft_reset)
STRAND_PUSH(%g2, %g6, %g7)
STRAND_PUSH(%g3, %g6, %g7)
STRAND_PUSH(%g4, %g6, %g7)
mov %o0, %g1 ! %g1 PIU cookie
HVCALL(piu_leaf_soft_reset)
STRAND_POP(%g4, %g6)
STRAND_POP(%g3, %g6)
STRAND_POP(%g2, %g6)
retl
nop
SET_SIZE(c_piu_leaf_soft_reset)
/*
* FIXME: The following link up/down functions are not ready
* for use yet, awaiting more information
*/
/*
* This macro brings a given PIU leaf's link up
*
* Inputs:
*
* piu - (preserved) pointer to PIU_COOKIE
*
* Bring up a piu link. Returns false on failure.
*/
ENTRY(piu_link_up)
PIU_LINK_UP(%o0, %o1, %o2, %o3)
retl
mov 1, %o0
SET_SIZE(piu_link_up)
/*
* This function brings a given piu leaf's link down
* Inputs:
*
* piu - (preserved) pointer to PIU_COOKIE
* Returns:
* false (0) on failure.
*/
ENTRY(piu_link_down)
/* get the base addr of RC control regs */
ldx [ %o0 + PIU_COOKIE_PCIE ], %o1
/* And now the actual reset code... */
/* Remain in detect quiesce */
! PEU control register
set PIU_PLC_TLU_CTB_TLR_CSR_A_TLU_CTL_ADDR, %o2
ldx [ %o1 + %o2 ], %o3
bset (1 << 8), %o3
stx %o3, [ %o1 + %o2]
! Disable link - set bit 4 of PEU Link Control register
set PIU_PLC_TLU_CTB_TLR_LNK_CTL, %o2
ldx [ %o1 + %o2], %o3
bset (1 << 4), %o3
stx %o3, [ %o1 + %o2]
! Wait for link to go down
setx PIU_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_ADDR, %o4, %o2
1:
ldx [ %o1 + %o2 ], %o3
andcc %o3, 0x7, %o3 ! status bits [2:0]
cmp %o3, 0x1 ! data link inactive
bne,pt %xcc, 1b
nop
retl
mov 1, %o0
SET_SIZE(piu_link_down)
/*
* Check and see if a PIU link is up. Returns true on
* success, false on failure.
*/
ENTRY(is_piu_port_link_up)
ldx [ %o0 + PIU_COOKIE_PCIE ], %o1
! PEU status register
setx PIU_PLC_TLU_CTB_TLR_CSR_A_TLU_STS_ADDR, %o3, %o2
ldx [ %o1 + %o2 ], %o3
and %o3, 0x7, %o3 ! status bits [2:0]
cmp %o3, 0x4 ! data link active
mov %g0, %o0
move %xcc, 1, %o0
retl
nop
SET_SIZE(is_piu_port_link_up)
/*
* arg0 (%g1) = PIU Cookie
* arg2 (%g2) = Offset
* arg3 (%g3) = size (1, 2, 4)
* --------------------
* ret0 = status (1 fail, 0 pass)
* ret1 = data
*/
ENTRY_NP(hv_config_get)
!! %g1 = piu cookie (pointer)
!! %g2 = offset
!! %g3 = size (1 byte, 2 bytes, 4 bytes)
mov 1, %g5
STRAND_STRUCT(%g4)
set STRAND_IO_PROT, %g6
!! %g4 = Strand struct
! strand.io_prot = 1
stx %g5, [%g4 + %g6]
DISABLE_PCIE_RWUC_ERRORS(%g1, %g4, %g5, %g6)
ldx [%g1 + PIU_COOKIE_CFG], %g4
cmp %g3, 1
beq,a,pn %xcc,1f
ldub [%g4 + %g2], %g3
cmp %g3, 2
beq,a,pn %xcc,1f
lduha [%g4 + %g2]ASI_P_LE, %g3
lduwa [%g4 + %g2]ASI_P_LE, %g3
1:
STRAND_STRUCT(%g4)
set STRAND_IO_PROT, %g6
! strand.io_prot = 0
stx %g0, [%g4 + %g6]
set STRAND_IO_ERROR, %g6
! strand.io_error
ldx [%g4 + %g6], %g5
! strand.io_error = 0
stx %g0, [%g4 + %g6]
ENABLE_PCIE_RWUC_ERRORS(%g1, %g4, %g2, %g6)
HVRET
SET_SIZE(hv_config_get)
/*
* bool_t pci_config_get(uint64_t piup, uint64_t offset, int size,
* uint64_t *data)
*/
ENTRY(pci_config_get)
STRAND_PUSH(%g2, %g6, %g7)
STRAND_PUSH(%g3, %g6, %g7)
STRAND_PUSH(%g4, %g6, %g7)
mov %o0, %g1
mov %o1, %g2
mov %o2, %g3
! %g1 - piupp
! %g2 - Address
! %g3 - size ( 1, 2, 4)
HVCALL(hv_config_get)
stx %g3, [%o3]
movrnz %g5, 0, %o0
movrz %g5, 1, %o0
STRAND_POP(%g4, %g6)
STRAND_POP(%g3, %g6)
STRAND_POP(%g2, %g6)
retl
nop
SET_SIZE(pci_config_get)
/*
* piu_intr_redistribution
*
* %g1 - this cpu id
* %g2 - tgt cpu id
*
* Need to invalidate all of the virtual intrs that are
* mapped to the cpu passed in %g1
*
* Need to retarget the 3 HW intrs hv controls that are
* mapped to the cpu passed in %g1 to cpu in %g2
*/
ENTRY(piu_intr_redistribution)
CPU_PUSH(%g7, %g3, %g4, %g5)
mov %g1, %g3 ! save cpuid
GUEST_STRUCT(%g4)
mov PIU_AID, %g1
DEVINST2INDEX(%g4, %g1, %g1, %g5, .piu_intr_redis_fail)
DEVINST2COOKIE(%g4, %g1, %g1, %g5, .piu_intr_redis_fail)
! %g1 - piu cookie
! %g3 - this cpu
HVCALL(_piu_intr_redistribution)
.piu_intr_redis_fail:
mov %g3, %g1 ! restore cpuid
CPU_POP(%g7, %g3, %g4, %g5)
HVRET
SET_SIZE(piu_intr_redistribution)
/*
* _piu_intr_redistribution
*
* %g1 - piu cookie
* %g3 - this cpu
*/
ENTRY(_piu_intr_redistribution)
CPU_PUSH(%g7, %g4, %g5, %g6)
! %g1 - piu cookie ptr
lduh [%g1 + PIU_COOKIE_INOMAX], %g2 ! loop counter
dec %g2 ! INOMAX - 1
._piu_intr_redis_loop:
cmp %g2, DMU_INTERNAL_INT
be %xcc, .piu_intr_redis_continue ! DMU errors handle separate
nop
cmp %g2, PEU_INTERNAL_INT
be %xcc, .piu_intr_redis_continue ! PEU errors handle separate
nop
ldx [%g1 + PIU_COOKIE_INTMAP], %g5
REGNO2OFFSET(%g2, %g4)
ldx [%g5 + %g4], %g4
! Extract cpuid
srlx %g4, JPID_SHIFT, %g7
and %g7, JPID_MASK, %g7
! %g7 - cpuid
! compare with this cpu, if match, set to idle
cmp %g3, %g7
bne,pt %xcc, .piu_intr_redis_continue
nop
! save cpuid since call clobbers it
CPU_PUSH(%g3, %g4, %g5, %g6)
CPU_PUSH(%g2, %g4, %g5, %g6)
mov INTR_DISABLED, %g3 ! Invalid
! %g1 = PIU Cookie
! %g2 = device ino
! %g3 = Idle
HVCALL(_piu_intr_setvalid)
CPU_POP(%g2, %g4, %g5, %g6)
CPU_POP(%g3, %g4, %g5, %g6)
.piu_intr_redis_continue:
deccc %g2
bgeu,pt %xcc, ._piu_intr_redis_loop
nop
.piu_redis_done:
CPU_POP(%g7, %g4, %g5, %g6)
HVRET
SET_SIZE(_piu_intr_redistribution)
#endif /* CONFIG_PIU */