-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add trap code for metag. At the lowest level Meta traps (and return from interrupt instruction - RTI) simply swap the PC and PCX registers and optionally toggle the interrupt status bit (ISTAT). Low level TBX code in tbipcx.S handles the core context save, determine the TBX signal number based on the core trigger that fired (using the TXSTATI status register), and call TBX signal handlers (mostly in traps.c) via a vector table. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Al Viro <viro@zeniv.linux.org.uk>
- Loading branch information
James Hogan
committed
Mar 2, 2013
1 parent
a2c5d4e
commit ac919f0
Showing
5 changed files
with
1,167 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* Copyright (C) 2012 Imagination Technologies Ltd. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
*/ | ||
|
||
#ifndef _ASM_METAG_SWITCH_H | ||
#define _ASM_METAG_SWITCH_H | ||
|
||
/* metag SWITCH codes */ | ||
#define __METAG_SW_PERM_BREAK 0x400002 /* compiled in breakpoint */ | ||
#define __METAG_SW_SYS_LEGACY 0x440000 /* legacy system calls */ | ||
#define __METAG_SW_SYS 0x440001 /* system calls */ | ||
|
||
/* metag SWITCH instruction encoding */ | ||
#define __METAG_SW_ENCODING(TYPE) (0xaf000000 | (__METAG_SW_##TYPE)) | ||
|
||
#endif /* _ASM_METAG_SWITCH_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright (C) 2005,2008 Imagination Technologies | ||
* | ||
* This file is subject to the terms and conditions of the GNU General Public | ||
* License. See the file COPYING in the main directory of this archive | ||
* for more details. | ||
*/ | ||
|
||
#ifndef _METAG_TBIVECTORS_H | ||
#define _METAG_TBIVECTORS_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
#include <asm/tbx.h> | ||
|
||
typedef TBIRES (*kick_irq_func_t)(TBIRES, int, int, int, PTBI, int *); | ||
|
||
extern TBIRES kick_handler(TBIRES, int, int, int, PTBI); | ||
struct kick_irq_handler { | ||
struct list_head list; | ||
kick_irq_func_t func; | ||
}; | ||
|
||
extern void kick_register_func(struct kick_irq_handler *); | ||
extern void kick_unregister_func(struct kick_irq_handler *); | ||
|
||
extern void head_end(TBIRES, unsigned long); | ||
extern void restart_critical_section(TBIRES State); | ||
extern TBIRES tail_end_sys(TBIRES, int, int *); | ||
static inline TBIRES tail_end(TBIRES state) | ||
{ | ||
return tail_end_sys(state, -1, NULL); | ||
} | ||
|
||
DECLARE_PER_CPU(PTBI, pTBI); | ||
extern PTBI pTBI_get(unsigned int); | ||
|
||
extern int ret_from_fork(TBIRES arg); | ||
|
||
extern int do_page_fault(struct pt_regs *regs, unsigned long address, | ||
unsigned int write_access, unsigned int trapno); | ||
|
||
extern TBIRES __TBIUnExpXXX(TBIRES State, int SigNum, int Triggers, int Inst, | ||
PTBI pTBI); | ||
|
||
#endif | ||
|
||
#endif /* _METAG_TBIVECTORS_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* Copyright (C) 2009 Imagination Technologies | ||
* | ||
* This file is subject to the terms and conditions of the GNU General Public | ||
* License. See the file COPYING in the main directory of this archive | ||
* for more details. | ||
* | ||
* The Meta KICK interrupt mechanism is generally a useful feature, so | ||
* we provide an interface for registering multiple interrupt | ||
* handlers. All the registered interrupt handlers are "chained". When | ||
* a KICK interrupt is received the first function in the list is | ||
* called. If that interrupt handler cannot handle the KICK the next | ||
* one is called, then the next until someone handles it (or we run | ||
* out of functions). As soon as one function handles the interrupt no | ||
* other handlers are called. | ||
* | ||
* The only downside of chaining interrupt handlers is that each | ||
* handler must be able to detect whether the KICK was intended for it | ||
* or not. For example, when the IPI handler runs and it sees that | ||
* there are no IPI messages it must not signal that the KICK was | ||
* handled, thereby giving the other handlers a chance to run. | ||
* | ||
* The reason that we provide our own interface for calling KICK | ||
* handlers instead of using the generic kernel infrastructure is that | ||
* the KICK handlers require access to a CPU's pTBI structure. So we | ||
* pass it as an argument. | ||
*/ | ||
#include <linux/kernel.h> | ||
#include <linux/mm.h> | ||
#include <linux/types.h> | ||
|
||
#include <asm/traps.h> | ||
|
||
/* | ||
* All accesses/manipulations of kick_handlers_list should be | ||
* performed while holding kick_handlers_lock. | ||
*/ | ||
static DEFINE_SPINLOCK(kick_handlers_lock); | ||
static LIST_HEAD(kick_handlers_list); | ||
|
||
void kick_register_func(struct kick_irq_handler *kh) | ||
{ | ||
unsigned long flags; | ||
|
||
spin_lock_irqsave(&kick_handlers_lock, flags); | ||
|
||
list_add_tail(&kh->list, &kick_handlers_list); | ||
|
||
spin_unlock_irqrestore(&kick_handlers_lock, flags); | ||
} | ||
|
||
void kick_unregister_func(struct kick_irq_handler *kh) | ||
{ | ||
unsigned long flags; | ||
|
||
spin_lock_irqsave(&kick_handlers_lock, flags); | ||
|
||
list_del(&kh->list); | ||
|
||
spin_unlock_irqrestore(&kick_handlers_lock, flags); | ||
} | ||
|
||
TBIRES | ||
kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI) | ||
{ | ||
struct kick_irq_handler *kh; | ||
struct list_head *lh; | ||
int handled = 0; | ||
TBIRES ret; | ||
|
||
head_end(State, ~INTS_OFF_MASK); | ||
|
||
/* If we interrupted user code handle any critical sections. */ | ||
if (State.Sig.SaveMask & TBICTX_PRIV_BIT) | ||
restart_critical_section(State); | ||
|
||
trace_hardirqs_off(); | ||
|
||
/* | ||
* There is no need to disable interrupts here because we | ||
* can't nest KICK interrupts in a KICK interrupt handler. | ||
*/ | ||
spin_lock(&kick_handlers_lock); | ||
|
||
list_for_each(lh, &kick_handlers_list) { | ||
kh = list_entry(lh, struct kick_irq_handler, list); | ||
|
||
ret = kh->func(State, SigNum, Triggers, Inst, pTBI, &handled); | ||
if (handled) | ||
break; | ||
} | ||
|
||
spin_unlock(&kick_handlers_lock); | ||
|
||
WARN_ON(!handled); | ||
|
||
return tail_end(ret); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* Pass a breakpoint through to Codescape */ | ||
|
||
#include <asm/tbx.h> | ||
|
||
.text | ||
.global ___TBIUnExpXXX | ||
.type ___TBIUnExpXXX,function | ||
___TBIUnExpXXX: | ||
TSTT D0Ar2,#TBICTX_CRIT_BIT ! Result of nestable int call? | ||
BZ $LTBINormCase ! UnExpXXX at background level | ||
MOV D0Re0,TXMASKI ! Read TXMASKI | ||
XOR TXMASKI,D1Re0,D1Re0 ! Turn off BGNDHALT handling! | ||
OR D0Ar2,D0Ar2,D0Re0 ! Preserve bits cleared | ||
$LTBINormCase: | ||
MSETL [A0StP],D0Ar6,D0Ar4,D0Ar2 ! Save args on stack | ||
SETL [A0StP++],D0Ar2,D1Ar1 ! Init area for returned values | ||
SWITCH #0xC20208 ! Total stack frame size 8 Dwords | ||
! write back size 2 Dwords | ||
GETL D0Re0,D1Re0,[--A0StP] ! Get result | ||
SUB A0StP,A0StP,#(8*3) ! Recover stack frame | ||
MOV PC,D1RtP | ||
.size ___TBIUnExpXXX,.-___TBIUnExpXXX |
Oops, something went wrong.