Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / metag / tbx / tbicore.S
1 /*
2  * tbicore.S
3  *
4  * Copyright (C) 2001, 2002, 2007, 2012 Imagination Technologies.
5  *
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation.
9  *
10  * Core functions needed to support use of the thread binary interface for META
11  * processors
12  */
13
14         .file   "tbicore.S"
15 /* Get data structures and defines from the TBI C header */
16 #include <asm/metag_mem.h>
17 #include <asm/metag_regs.h>
18 #include <asm/tbx.h>
19
20         .data
21         .balign 8
22         .global ___pTBISegs
23         .type   ___pTBISegs,object
24 ___pTBISegs:
25         .quad   0               /* Segment list pointer with it's */
26         .size   ___pTBISegs,.-___pTBISegs
27                                         /* own id or spin-lock location */
28 /*
29  * Return ___pTBISegs value specific to privilege level - not very complicated
30  * at the moment
31  *
32  * Register Usage: D0Re0 is the result, D1Re0 is used as a scratch
33  */
34         .text
35         .balign 4
36         .global ___TBISegList
37         .type   ___TBISegList,function
38 ___TBISegList:
39         MOVT    A1LbP,#HI(___pTBISegs)
40         ADD     A1LbP,A1LbP,#LO(___pTBISegs)
41         GETL    D0Re0,D1Re0,[A1LbP]
42         MOV     PC,D1RtP
43         .size   ___TBISegList,.-___TBISegList
44
45 /*
46  * Search the segment list for a match given Id, pStart can be NULL
47  *
48  * Register Usage: D1Ar1 is pSeg, D0Ar2 is Id, D0Re0 is the result
49  *                 D0Ar4, D1Ar3 are used as a scratch
50  *                 NB: The PSTAT bit if Id in D0Ar2 may be toggled
51  */
52         .text
53         .balign 4
54         .global ___TBIFindSeg
55         .type   ___TBIFindSeg,function
56 ___TBIFindSeg:
57         MOVT    A1LbP,#HI(___pTBISegs)
58         ADD     A1LbP,A1LbP,#LO(___pTBISegs)
59         GETL    D1Ar3,D0Ar4,[A1LbP]     /* Read segment list head */
60         MOV     D0Re0,TXSTATUS          /* What priv level are we at? */
61         CMP     D1Ar1,#0                /* Is pStart provided? */
62 /* Disable privilege adaption for now */
63         ANDT    D0Re0,D0Re0,#0  /*HI(TXSTATUS_PSTAT_BIT)  ; Is PSTAT set? Zero if not */
64         LSL     D0Re0,D0Re0,#(TBID_PSTAT_S-TXSTATUS_PSTAT_S)
65         XOR     D0Ar2,D0Ar2,D0Re0       /* Toggle Id PSTAT if privileged */
66         MOVNZ   D1Ar3,D1Ar1             /* Use pStart if provided */
67 $LFindSegLoop:                  
68         ADDS    D0Re0,D1Ar3,#0          /* End of list? Load result into D0Re0 */
69         MOVZ    PC,D1RtP                /* If result is NULL we leave */
70         GETL    D1Ar3,D0Ar4,[D1Ar3]     /* Read pLink and Id */
71         CMP     D0Ar4,D0Ar2             /* Does it match? */
72         BNZ     $LFindSegLoop           /* Loop if there is no match */
73         TST     D0Re0,D0Re0             /* Clear zero flag - we found it! */
74         MOV     PC,D1RtP                /* Return */
75         .size   ___TBIFindSeg,.-___TBIFindSeg
76
77 /* Useful offsets to encode the lower bits of the lock/unlock addresses */
78 #define UON  (LINSYSEVENT_WR_ATOMIC_LOCK   & 0xFFF8)
79 #define UOFF (LINSYSEVENT_WR_ATOMIC_UNLOCK & 0xFFF8)
80
81 /*
82  * Perform a whole spin-lock sequence as used by the TBISignal routine
83  *
84  * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result
85  *                 (All other usage due to ___TBIPoll - D0Ar6, D1Re0)
86  */
87         .text
88         .balign 4
89         .global ___TBISpin
90         .type   ___TBISpin,function
91 ___TBISpin:
92         SETL    [A0StP++],D0FrT,D1RtP   /* Save our return address */
93         ORS     D0Re0,D0Re0,#1          /* Clear zero flag */
94         MOV     D1RtP,PC                /* Setup return address to form loop */
95 $LSpinLoop:
96         BNZ     ___TBIPoll              /* Keep repeating if fail to set */
97         GETL    D0FrT,D1RtP,[--A0StP]   /* Restore return address */
98         MOV     PC,D1RtP                /* Return */
99         .size   ___TBISpin,.-___TBISpin
100
101 /*
102  * Perform an attempt to gain access to a spin-lock and set some bits
103  * 
104  * Register Usage: D1Ar1 is pLock, D0Ar2 is Mask, D0Re0 is the result
105  *                 !!On return Zero flag is SET if we are sucessfull!!
106  *                 A0.3 is used to hold base address of system event region
107  *                 D1Re0 use to hold TXMASKI while interrupts are off
108  */
109         .text
110         .balign 4
111         .global ___TBIPoll
112         .type   ___TBIPoll,function
113 ___TBIPoll:
114         MOV     D1Re0,#0                /* Prepare to disable ints */
115         MOVT    A0.3,#HI(LINSYSEVENT_WR_ATOMIC_LOCK)
116         SWAP    D1Re0,TXMASKI           /* Really stop ints */
117         LOCK2                           /* Gain all locks */
118         SET     [A0.3+#UON],D1RtP       /* Stop shared memory access too */
119         DCACHE  [D1Ar1],A0.3            /* Flush Cache line */
120         GETD    D0Re0,[D1Ar1]           /* Get new state from memory or hit */
121         DCACHE  [D1Ar1],A0.3            /* Flush Cache line */
122         GETD    D0Re0,[D1Ar1]           /* Get current state */
123         TST     D0Re0,D0Ar2             /* Are we clear to send? */
124         ORZ     D0Re0,D0Re0,D0Ar2       /* Yes: So set bits and */
125         SETDZ   [D1Ar1],D0Re0           /*      transmit new state */
126         SET     [A0.3+#UOFF],D1RtP      /* Allow shared memory access */
127         LOCK0                           /* Release all locks */
128         MOV     TXMASKI,D1Re0           /* Allow ints */
129 $LPollEnd:
130         XORNZ   D0Re0,D0Re0,D0Re0       /* No: Generate zero result */
131         MOV     PC,D1RtP                /* Return (NZ indicates failure) */
132         .size   ___TBIPoll,.-___TBIPoll
133
134 /*
135  * End of tbicore.S
136  */