Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / metag / tbx / tbicore.S
diff --git a/kernel/arch/metag/tbx/tbicore.S b/kernel/arch/metag/tbx/tbicore.S
new file mode 100644 (file)
index 0000000..a0838eb
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * tbicore.S
+ *
+ * Copyright (C) 2001, 2002, 2007, 2012 Imagination Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * Core functions needed to support use of the thread binary interface for META
+ * processors
+ */
+
+       .file   "tbicore.S"
+/* Get data structures and defines from the TBI C header */
+#include <asm/metag_mem.h>
+#include <asm/metag_regs.h>
+#include <asm/tbx.h>
+
+       .data
+       .balign 8
+       .global ___pTBISegs
+       .type   ___pTBISegs,object
+___pTBISegs:
+       .quad   0               /* Segment list pointer with it's */
+       .size   ___pTBISegs,.-___pTBISegs
+                                       /* own id or spin-lock location */
+/*
+ * Return ___pTBISegs value specific to privilege level - not very complicated
+ * at the moment
+ *
+ * Register Usage: D0Re0 is the result, D1Re0 is used as a scratch
+ */
+       .text
+       .balign 4
+       .global ___TBISegList
+       .type   ___TBISegList,function
+___TBISegList:
+       MOVT    A1LbP,#HI(___pTBISegs)
+       ADD     A1LbP,A1LbP,#LO(___pTBISegs)
+       GETL    D0Re0,D1Re0,[A1LbP]
+       MOV     PC,D1RtP
+       .size   ___TBISegList,.-___TBISegList
+
+/*
+ * Search the segment list for a match given Id, pStart can be NULL
+ *
+ * Register Usage: D1Ar1 is pSeg, D0Ar2 is Id, D0Re0 is the result
+ *                 D0Ar4, D1Ar3 are used as a scratch
+ *                 NB: The PSTAT bit if Id in D0Ar2 may be toggled
+ */
+       .text
+       .balign 4
+       .global ___TBIFindSeg
+       .type   ___TBIFindSeg,function
+___TBIFindSeg:
+       MOVT    A1LbP,#HI(___pTBISegs)
+       ADD     A1LbP,A1LbP,#LO(___pTBISegs)
+       GETL    D1Ar3,D0Ar4,[A1LbP]     /* Read segment list head */
+       MOV     D0Re0,TXSTATUS          /* What priv level are we at? */
+       CMP     D1Ar1,#0                /* Is pStart provided? */
+/* Disable privilege adaption for now */
+       ANDT    D0Re0,D0Re0,#0  /*HI(TXSTATUS_PSTAT_BIT)  ; Is PSTAT set? Zero if not */
+       LSL     D0Re0,D0Re0,#(TBID_PSTAT_S-TXSTATUS_PSTAT_S)
+       XOR     D0Ar2,D0Ar2,D0Re0       /* Toggle Id PSTAT if privileged */
+       MOVNZ   D1Ar3,D1Ar1             /* Use pStart if provided */
+$LFindSegLoop:                 
+       ADDS    D0Re0,D1Ar3,#0          /* End of list? Load result into D0Re0 */
+       MOVZ    PC,D1RtP                /* If result is NULL we leave */
+       GETL    D1Ar3,D0Ar4,[D1Ar3]     /* Read pLink and Id */
+       CMP     D0Ar4,D0Ar2             /* Does it match? */
+       BNZ     $LFindSegLoop           /* Loop if there is no match */
+       TST     D0Re0,D0Re0             /* Clear zero flag - we found it! */
+       MOV     PC,D1RtP                /* Return */
+       .size   ___TBIFindSeg,.-___TBIFindSeg
+
+/* Useful offsets to encode the lower bits of the lock/unlock addresses */
+#define UON  (LINSYSEVENT_WR_ATOMIC_LOCK   & 0xFFF8)
+#define UOFF (LINSYSEVENT_WR_ATOMIC_UNLOCK & 0xFFF8)
+
+/*
+ * Perform a whole spin-lock sequence as used by the TBISignal routine
+ *
+ * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result
+ *                 (All other usage due to ___TBIPoll - D0Ar6, D1Re0)
+ */
+       .text
+       .balign 4
+       .global ___TBISpin
+       .type   ___TBISpin,function
+___TBISpin:
+       SETL    [A0StP++],D0FrT,D1RtP   /* Save our return address */
+       ORS     D0Re0,D0Re0,#1          /* Clear zero flag */
+       MOV     D1RtP,PC                /* Setup return address to form loop */
+$LSpinLoop:
+       BNZ     ___TBIPoll              /* Keep repeating if fail to set */
+       GETL    D0FrT,D1RtP,[--A0StP]   /* Restore return address */
+       MOV     PC,D1RtP                /* Return */
+       .size   ___TBISpin,.-___TBISpin
+
+/*
+ * Perform an attempt to gain access to a spin-lock and set some bits
+ * 
+ * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result
+ *                 !!On return Zero flag is SET if we are sucessfull!!
+ *                 A0.3 is used to hold base address of system event region
+ *                 D1Re0 use to hold TXMASKI while interrupts are off
+ */
+       .text
+       .balign 4
+       .global ___TBIPoll
+       .type   ___TBIPoll,function
+___TBIPoll:
+       MOV     D1Re0,#0                /* Prepare to disable ints */
+       MOVT    A0.3,#HI(LINSYSEVENT_WR_ATOMIC_LOCK)
+       SWAP    D1Re0,TXMASKI           /* Really stop ints */
+       LOCK2                           /* Gain all locks */
+       SET     [A0.3+#UON],D1RtP       /* Stop shared memory access too */
+       DCACHE  [D1Ar1],A0.3            /* Flush Cache line */
+       GETD    D0Re0,[D1Ar1]           /* Get new state from memory or hit */
+       DCACHE  [D1Ar1],A0.3            /* Flush Cache line */
+       GETD    D0Re0,[D1Ar1]           /* Get current state */
+       TST     D0Re0,D0Ar2             /* Are we clear to send? */
+       ORZ     D0Re0,D0Re0,D0Ar2       /* Yes: So set bits and */
+       SETDZ   [D1Ar1],D0Re0           /*      transmit new state */
+       SET     [A0.3+#UOFF],D1RtP      /* Allow shared memory access */
+       LOCK0                           /* Release all locks */
+       MOV     TXMASKI,D1Re0           /* Allow ints */
+$LPollEnd:
+       XORNZ   D0Re0,D0Re0,D0Re0       /* No: Generate zero result */
+       MOV     PC,D1RtP                /* Return (NZ indicates failure) */
+       .size   ___TBIPoll,.-___TBIPoll
+
+/*
+ * End of tbicore.S
+ */