Kernel-2.6.32-573.12.1.el6_kernel-ABI

        =================================
        INTERNAL KERNEL ABI FOR FR-V ARCH
        =================================

The internal FRV kernel ABI is not quite the same as the userspace ABI. A
number of the registers are used for special purposed, and the ABI is not
consistent between modules vs core, and MMU vs no-MMU.

This partly stems from the fact that FRV CPUs do not have a separate
supervisor stack pointer, and most of them do not have any scratch
registers, thus requiring at least one general purpose register to be
clobbered in such an event. Also, within the kernel core, it is possible to
simply jump or call directly between functions using a relative offset.
This cannot be extended to modules for the displacement is likely to be too
far. Thus in modules the address of a function to call must be calculated
in a register and then used, requiring two extra instructions.

This document has the following sections:

() System call register ABI
(
) CPU operating modes
() Internal kernel-mode register ABI
(
) Internal debug-mode register ABI
(*) Virtual interrupt handling

========================
SYSTEM CALL REGISTER ABI
========================

When a system call is made, the following registers are effective:

REGISTERS    CALL            RETURN
===============    =======================    =======================
GR7        System call number    Preserved
GR8        Syscall arg #1        Return value
GR9-GR13    Syscall arg #2-6    Preserved

===================
CPU OPERATING MODES
===================

The FR-V CPU has three basic operating modes. In order of increasing
capability:

(1) User mode.

  Basic userspace running mode.

(2) Kernel mode.

  Normal kernel mode. There are many additional control registers
  available that may be accessed in this mode, in addition to all the
  stuff available to user mode. This has two submodes:

  (a) Exceptions enabled (PSR.T == 1).

  Exceptions will invoke the appropriate normal kernel mode
  handler. On entry to the handler, the PSR.T bit will be cleared.

  (b) Exceptions disabled (PSR.T == 0).

  No exceptions or interrupts may happen. Any mandatory exceptions
  will cause the CPU to halt unless the CPU is told to jump into
  debug mode instead.

(3) Debug mode.

  No exceptions may happen in this mode. Memory protection and
  management exceptions will be flagged for later consideration, but
  the exception handler won't be invoked. Debugging traps such as
  hardware breakpoints and watchpoints will be ignored. This mode is
  entered only by debugging events obtained from the other two modes.

  All kernel mode registers may be accessed, plus a few extra debugging
  specific registers.

=================================
INTERNAL KERNEL-MODE REGISTER ABI
=================================

There are a number of permanent register assignments that are set up by
entry.S in the exception prologue. Note that there is a complete set of
exception prologues for each of user->kernel transition and kernel->kernel
transition. There are also user->debug and kernel->debug mode transition
prologues.

REGISTER    FLAVOUR    USE
===============    =======    ==============================================
GR1            Supervisor stack pointer
GR15            Current thread info pointer
GR16            GP-Rel base register for small data
GR28            Current exception frame pointer (__frame)
GR29            Current task pointer (current)
GR30            Destroyed by kernel mode entry
GR31        NOMMU    Destroyed by debug mode entry
GR31        MMU    Destroyed by TLB miss kernel mode entry
CCR.ICC2        Virtual interrupt disablement tracking
CCCR.CC3        Cleared by exception prologue 
            (atomic op emulation)
SCR0        MMU    See mmu-layout.txt.
SCR1        MMU    See mmu-layout.txt.
SCR2        MMU    Save for EAR0 (destroyed by icache insns 
                       in debug mode)
SCR3        MMU    Save for GR31 during debug exceptions
DAMR/IAMR    NOMMU    Fixed memory protection layout.
DAMR/IAMR    MMU    See mmu-layout.txt.

Certain registers are also used or modified across function calls:

REGISTER    CALL                RETURN
===============    ===============================    ======================
GR0        Fixed Zero            -
GR2        Function call frame pointer
GR3        Special                Preserved
GR3-GR7        -                Clobbered
GR8        Function call arg #1        Return value 
                        (or clobbered)
GR9        Function call arg #2        Return value MSW 
                        (or clobbered)
GR10-GR13    Function call arg #3-#6        Clobbered
GR14        -                Clobbered
GR15-GR16    Special                Preserved
GR17-GR27    -                Preserved
GR28-GR31    Special                Only accessed 
                        explicitly
LR        Return address after CALL    Clobbered
CCR/CCCR    -                Mostly Clobbered

================================
INTERNAL DEBUG-MODE REGISTER ABI
================================

This is the same as the kernel-mode register ABI for functions calls. The
difference is that in debug-mode there’s a different stack and a different
exception frame. Almost all the global registers from kernel-mode
(including the stack pointer) may be changed.

REGISTER    FLAVOUR    USE
===============    =======    ==============================================
GR1            Debug stack pointer
GR16            GP-Rel base register for small data
GR31            Current debug exception frame pointer 
            (__debug_frame)
SCR3        MMU    Saved value of GR31

Note that debug mode is able to interfere with the kernel’s emulated atomic
ops, so it must be exceedingly careful not to do any that would interact
with the main kernel in this regard. Hence the debug mode code (gdbstub) is
almost completely self-contained. The only external code used is the
sprintf family of functions.

Furthermore, break.S is so complicated because single-step mode does not
switch off on entry to an exception. That means unless manually disabled,
single-stepping will blithely go on stepping into things like interrupts.
See gdbstub.txt for more information.

==========================
VIRTUAL INTERRUPT HANDLING
==========================

Because accesses to the PSR is so slow, and to disable interrupts we have
to access it twice (once to read and once to write), we don’t actually
disable interrupts at all if we don’t have to. What we do instead is use
the ICC2 condition code flags to note virtual disablement, such that if we
then do take an interrupt, we note the flag, really disable interrupts, set
another flag and resume execution at the point the interrupt happened.
Setting condition flags as a side effect of an arithmetic or logical
instruction is really fast. This use of the ICC2 only occurs within the
kernel - it does not affect userspace.

The flags we use are:

(*) CCR.ICC2.Z [Zero flag]

 Set to virtually disable interrupts, clear when interrupts are
 virtually enabled. Can be modified by logical instructions without
 affecting the Carry flag.

(*) CCR.ICC2.C [Carry flag]

 Clear to indicate hardware interrupts are really disabled, set otherwise.

What happens is this:

(1) Normal kernel-mode operation.

ICC2.Z is 0, ICC2.C is 1.

(2) An interrupt occurs. The exception prologue examines ICC2.Z and
determines that nothing needs doing. This is done simply with an
unlikely BEQ instruction.

(3) The interrupts are disabled (local_irq_disable)

ICC2.Z is set to 1.

(4) If interrupts were then re-enabled (local_irq_enable):

ICC2.Z would be set to 0.

 A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would
 be used to trap if interrupts were now virtually enabled, but
 physically disabled - which they're not, so the trap isn't taken. The
 kernel would then be back to state (1).

(5) An interrupt occurs. The exception prologue examines ICC2.Z and
determines that the interrupt shouldn’t actually have happened. It
jumps aside, and there disabled interrupts by setting PSR.PIL to 14
and then it clears ICC2.C.

(6) If interrupts were then saved and disabled again (local_irq_save):

ICC2.Z would be shifted into the save variable and masked off 
(giving a 1).

ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be
unaffected (ie: 0).

(7) If interrupts were then restored from state (6) (local_irq_restore):

ICC2.Z would be set to indicate the result of XOR'ing the saved
value (ie: 1) with 1, which gives a result of 0 - thus leaving
ICC2.Z set.

ICC2.C would remain unaffected (ie: 0).

 A TIHI #2 instruction would be used to again assay the current state,
 but this would do nothing as Z==1.

(8) If interrupts were then enabled (local_irq_enable):

ICC2.Z would be cleared. ICC2.C would be left unaffected. Both
flags would now be 0.

 A TIHI #2 instruction again issued to assay the current state would
 then trap as both Z==0 [interrupts virtually enabled] and C==0
 [interrupts really disabled] would then be true.

(9) The trap #2 handler would simply enable hardware interrupts
(set PSR.PIL to 0), set ICC2.C to 1 and return.

(10) Immediately upon returning, the pending interrupt would be taken.

(11) The interrupt handler would take the path of actually processing the
interrupt (ICC2.Z is clear, BEQ fails as per step (2)).

(12) The interrupt handler would then set ICC2.C to 1 since hardware
interrupts are definitely enabled - or else the kernel wouldn’t be here.

(13) On return from the interrupt handler, things would be back to state (1).

This trap (#2) is only available in kernel mode. In user mode it will
result in SIGILL.