[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
mips64orion _CPU_ISR_Set_level
- Date: Wed, 19 May 1999 17:15:07 -0700 (PDT)
- From: eb at starium.com (Eric Blossom)
- Subject: mips64orion _CPU_ISR_Set_level
joel at oarcorp.com writes:
>
> What do you think will be required to get the mips port into a similar
> organization.
>
> > I am still somewhat confused about _CPU_ISR_Set_level and how important is it
> > to support interrupt levels for the mips architecture. I see some architectures
> > support multiple levels if the CPU allows an easy way to do so, otherwise it
> > just enables and disables interrupts. I could certainly go either way, but I'm
> > just not sure what the "best" way to go is, knowing that there is no one best way.
>
> _CPU_ISR_Set_level does what it has to as best it can for a port. :)
>
> The i386 just recognizes on and off as well. THe set level implementation
> for the i386 is this:
>
> #define _CPU_ISR_Set_level( _new_level ) \
> { \
> if ( _new_level ) asm volatile ( "cli" ); \
> else asm volatile ( "sti" ); \
> }
>
Hi,
I have a mostly complete MIPS TX39 port of rtems that I am not
actively using nor working on. The interrupt handling is complete,
however.
The following is from exec/score/cpu/mipstx39/cpu.c
I believe that it works for any mips 3000 variant. The 4000's
have a somewhat different status register format, but this is close.
If somebody wants the whole tree, I'll gladly send it to you.
It was built on 4.0 Beta IIRC.
Eric Blossom
----------------------------------------------------------------
/*PAGE
*
* _CPU_ISR_Set_level
*/
/*
*
* map task level to status register imask bits like this
*
* task level sr imask bits
* 0 11111111 // all interrupts enabled
* 1 11111110 // sw0 disabled
* 2 11111100 // sw1, sw0 disabled
* 3 11111000 // int0, sw1, sw0 disabled
* 4 11110000 // int1, int0, sw1, sw0 disabled
* 5 11100000 // int2, int1, int0, sw1, sw0 disabled
* 6 11000000 // int3, int2, int1, int0, sw1, sw0 disabled
* 7 10000000 // int4, int3, int2, int1, int0, sw1, sw0 disabled
* 8 00000000 // all interrupts disabled
*/
unsigned32
_CPU_ISR_Compute_sr_imask (unsigned32 new_level)
{
unsigned32 mask;
if (new_level > 8)
new_level = 8;
mask = (0xff >> new_level) << new_level;
return (mask << 8) | SR_IEc;
}
void _CPU_ISR_Set_level( unsigned32 new_level )
{
unsigned32 sr;
sr = mfc0_status ();
sr &= ~SR_INTMASK;
sr |= _CPU_ISR_Compute_sr_imask (new_level);
mtc0_status (sr);
}
/*
*
* _CPU_ISR_Get_level
*
* This routine returns the current interrupt level.
*/
unsigned32 _CPU_ISR_Get_level( void )
{
unsigned32 mask;
unsigned32 i;
mask = mfc0_status () >> 8;
for (i = 0; i < 8; i++){
if (mask & 0x1)
return i;
mask >>= 1;
}
return i;
}
/* -*-C-*-
*******************************************************************************
*
* File: tx39_cp0.h
* RCS: $Id: $
* Description: tx39 Coprocessor 0 defs
* Author: Eric Blossom
* Created: Sat Sep 26 22:38:32 1998
* Modified: Fri Dec 4 16:33:28 1998 (eric) eb at baton.starium.com
* Language: C
* Package: N/A
* Status: Experimental (Do Not Distribute)
*
*******************************************************************************
*/
#ifndef _TX39_CP0_H_
#define _TX39_CP0_H_
/*
* Coprocessor 0 registers
*/
#define C0_CONFIG $3 /* processor config */
#define C0_CACHE $7 /* cache locking */
#define C0_BADVADDR $8 /* last virtual addr triggering error */
#define C0_SR $12 /* status register */
#define C0_CAUSE $13 /* cause register */
#define C0_EPC $14 /* exception error addr */
#define C0_PRID $15 /* processor revision ID */
#define C0_DEBUG $16 /* debug exception control */
#define C0_DEPC $17 /* PC for debug exception */
/*
* Not all TX39 family members have TLB's
*/
#define C0_INDEX $0 /* TLB Index register */
#define C0_RANDOM $1 /* TLB Random register */
#define C0_TLBLO $2 /* TLB EntryLo register */
#define C0_TLBHI $10 /* TLB EntryHi register */
/*
* C callable access routines for all CP0 registers.
* These macros generate inline assembly code for functions of the form
*
* int mfc0_<foo> (void);
* void mtc0_<foo> (int v);
*
* Where <foo> is
* config, cache, badvaddr, status, cause, epc, prid, debug, depc
*/
#define MFC0(reg,dst) asm("mfc0 %0," #reg "; nop" : "=r" (dst))
#define MTC0(reg,src) asm("nop; mtc0 %0," #reg "; nop" :: "r" (src))
#define DEF_MFX(name, regno) \
inline static int mfc0_ ## name (void){int r; MFC0 (regno, r); return r;}
#define DEF_MTX(name, regno) \
inline static void mtc0_ ## name (int v){MTC0 (regno, v);}
#define DEF_MXX(name, regno) DEF_MFX(name, regno) DEF_MTX(name, regno)
#ifndef ASM
DEF_MXX (config, $3)
DEF_MXX (cache, $7)
DEF_MXX (badvaddr, $8)
DEF_MXX (status, $12)
DEF_MXX (cause, $13)
DEF_MXX (epc, $14)
DEF_MXX (prid, $15)
DEF_MXX (debug, $16)
DEF_MXX (depc, $17)
DEF_MXX (index, $0)
DEF_MXX (random, $1)
DEF_MXX (tlblo, $2)
DEF_MXX (tlbhi, $10)
#endif /* !ASM */
/*
* status register bits
*/
#define SR_IEc 0x00000001 /* Intr Enabled current 1 = enabled */
#define SR_KUc 0x00000002 /* Kernel/User current 1 = User */
#define SR_IEp 0x00000004 /* Intr Enabled prev */
#define SR_KUp 0x00000008 /* Kernel/User prev */
#define SR_IEo 0x00000010 /* Intr Enabled old */
#define SR_KUo 0x00000020 /* Kernel/User old */
#define SR_INTMASK 0x0000ff00 /* interupt enable mask */
#define SR_NMI 0x00100000 /* Non-maskable int (write 1 to clear) */
#define SR_TS 0x00200000 /* TLB shutdown */
#define SR_BEV 0x00400000 /* Bootstrap exception vector */
#define SR_RE 0x02000000 /* Reverse Endian in user mode */
#define SR_CU0 0x10000000 /* mark CP0 usable */
#define SR_CU1 0x20000000 /* mark CP1 usable */
#define SR_CU2 0x40000000 /* mark CP2 usable */
#define SR_CU3 0x80000000 /* mark CP3 usable */
/*
* config register bits
*/
#define CP0CFG_DRSIZE_MASK 0x00000003 /* data burst refill size (see DCBR) */
#define CP0CFG_DRSIZE_4 0x00000000 /* 4 words */
#define CP0CFG_DRSIZE_8 0x00000001 /* 8 words */
#define CP0CFG_DRSIZE_16 0x00000002 /* 16 words */
#define CP0CFG_DRSIZE_32 0x00000003 /* 32 words */
#define CP0CFG_IRSIZE_MASK 0x0000000c /* inst burst refill size */
#define CP0CFG_IRSIZE_4 0x00000000 /* 4 words */
#define CP0CFG_IRSIZE_8 0x00000004 /* 8 words */
#define CP0CFG_IRSIZE_16 0x00000008 /* 16 words */
#define CP0CFG_IRSIZE_32 0x0000000c /* 32 words */
#define CP0CFG_DCE 0x00000010 /* Data Cache Enable */
#define CP0CFG_ICE 0x00000020 /* Instruction Cache Enable */
#define CP0CFG_DCBR 0x00000040 /* Data Cache Burst Refill */
#define CP0CFG_LOCK 0x00000080 /* lock config register */
#define CP0CFG_HALT 0x00000100 /* enter Halt mode */
#define CP0CFG_DOZE 0x00000200 /* enter Doze mode */
#define CP0CFG_RF_MASK 0x00000c00 /* reduced frequency */
#define CP0CFG_WBON 0x00001000 /* write back mode on (3920 core) */
#define CP0CFG_CWFON 0x00002000 /* critical word first mode (3920 core) */
#define CP0CFG_DCS_SHIFT 16
#define CP0CFG_DCS_MASK 0x7
#define CP0CFG_ICS_SHIFT 19
#define CP0CFG_ICS_MASK 0x7
#endif /* _TX39_CP0_H_ */
// small excerpt from cpu.h
/* ISR handler macros */
/*
* Disable all interrupts for an RTEMS critical section. The previous
* state is returned in _isr_cookie.
*/
#define _CPU_ISR_Disable( _isr_cookie ) \
do { \
int _t1_ = 0; \
_isr_cookie = 0; \
asm volatile (" \n\
.set noreorder \n\
mfc0 %0, $12 \n\
not %1, %2 \n\
and %1, %1, %0 \n\
mtc0 %1, $12 \n\
and %0, %2 \n\
.set reorder \n\
" \
: "=&r" (_isr_cookie), "=&r" (_t1_) \
: "r" (/*SR_INTMASK*/ 0x0000ff00) \
); \
} while (0)
/*
* Enable interrupts to the previous state (returned by _CPU_ISR_Disable).
* This indicates the end of an RTEMS critical section. The parameter
* _isr_cookie is not modified.
*/
#define _CPU_ISR_Enable( _isr_cookie ) \
do { \
int _t1_ = 0; \
asm volatile (" \n\
.set noreorder \n\
mfc0 %0, $12 \n\
nop \n\
or %0, %1 \n\
mtc0 %0, $12 \n\
.set reorder \n\
" \
: "=&r" (_t1_) \
: "r" (_isr_cookie) \
); \
} while (0)
/*
* This temporarily restores the interrupt to _level before immediately
* disabling them again. This is used to divide long RTEMS critical
* sections into two or more parts. The parameter _level is not
* modified.
*/
#define _CPU_ISR_Flash( _isr_cookie ) \
do { \
int _discard_; \
_CPU_ISR_Enable (_isr_cookie); \
_CPU_ISR_Disable (_discard_); \
} while (0)
/*
* Map interrupt level in task mode onto the hardware that the CPU
* actually provides. Currently, interrupt levels which do not
* map onto the CPU in a generic fashion are undefined. Someday,
* it would be nice if these were "mapped" by the application
* via a callout. For example, m68k has 8 levels 0 - 7, levels
* 8 - 255 would be available for bsp/application specific meaning.
* This could be used to manage a programmable interrupt controller
* via the rtems_task_mode directive.
*
* The get routine usually must be implemented as a subroutine.
*/
unsigned32 _CPU_ISR_Compute_sr_imask (unsigned32 new_level);
void _CPU_ISR_Set_level( unsigned32 new_level );
unsigned32 _CPU_ISR_Get_level( void );