mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-19 09:04:57 +00:00
027f891f76
Add source files from the Thread Binary Interface (TBI) library which provides useful low level operations and traps/context management. Among other things it handles interrupt/exception/syscall entry (in tbipcx.S). Signed-off-by: James Hogan <james.hogan@imgtec.com>
136 lines
4.4 KiB
ArmAsm
136 lines
4.4 KiB
ArmAsm
/*
|
|
* 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
|
|
*/
|