123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- =================================
- 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.
|