B.4   Architecture Considerations

This section describes the following characteristics of the SPARC and SPARClite architectures that you should keep in mind as you write a VxWorks application:

Reserved Registers

Following the SPARC specification (Appendix D, Software Considerations, in The SPARC Architecture Manual, Version 8 from Sun Microsystems), registers g5, g6, and g7 are reserved for VxWorks kernel use. Avoid using these registers in your applications.

Processor Mode

VxWorks for SPARC and SPARClite always runs in Supervisor mode.

Vector Table Initialization

After the VxWorks for SPARC or SPARClite has completed initialization, traps are enabled and the PIL (Processor Interrupt Level) is set to zero. All 15 interrupt levels are active with the coprocessor enables set according to hardware availability and application use.

The TBR (Trap Base Register) points to the active vector table at address 0x1000 in local memory.

Make sure that vectors are not reserved for the processor or the kernel before acquiring them for an application.

Double-word Integers: long long

The double-word integer long long is not supported, except as an artifact of your particular architecture and compiler. For more information about handling unsupported features, please see the Customer Support User's Guide.

Interrupt Handling

For VxWorks for SPARC and SPARClite, an interrupt stack allows all interrupt processing to be performed on a separate stack. The interrupt stack is implemented in software because the SPARC family does not support such a stack in hardware.

SPARC Interrupts

The SPARC microprocessor allows 15 levels of interrupts. The level is encoded by external hardware on the four interrupt signal lines. The integer unit (CPU) decodes this level and passes control directly to the entry in the vector table at an offset of 0x100 plus the interrupt level times 16 bytes. This corresponds to vectors 16 through 31 (addresses 0x100 to 0x1F0). Each 16-byte entry in the vector table contains up to four instructions. Typically, control passes to an interrupt service routine (ISR) with a call or branch instruction.

The SPARC uses auto-vectored interrupts. The chip does not perform any type of interrupt acknowledge (IACK) cycle. The address in the Trap Base Register (TBR) concatenated with the interrupt level vector displacement allows the SPARC to begin interrupt processing.

The alternative is vectored interrupts. The CPU responds to the interrupt with an IACK cycle so that an interrupt controller chip or individual device can return a value that clears and identifies the source of the interrupt. This is extremely useful for multiple sources of interrupts on a single-interrupt level.

The ability to perform an interrupt acknowledge cycle is a function of the microprocessor (not the software or board-level hardware). However, a target board can synthesize an IACK cycle by accessing an area created in its address space. This is often necessary to clear the interrupt pending bit in an interrupting device. An IACK cycle also differs from a normal read cycle in that the value returned is an interrupt vector. This vector is used to select an offset in the vector table that has the device's ISR connected to that table entry.

VxWorks allows an application to connect ISRs to vectors with the routine intConnect( ). A stub is built dynamically that calls an interrupt entry routine, calls the ISR, and then calls an exit routine. The SPARC, like other RISC processors, delegates to software the task of building an exception stack frame (ESF) to save volatile information. The kernel builds up two types of exception stack frames: one for interrupts and one for all other exceptions. The code execution sequence following an interrupt is as follows:

  1. Vector table

  1. Exception stack frame building

  1. Overflow exception handling

  1. Interrupt entry code

  1. ISR

  1. Interrupt exit code

  1. Rescheduling, if the interrupt added work for the kernel (such as a semGive( ))

Vectored Interrupts

The SPARC kernel was designed to handle vectored interrupts as an option. Because this implementation varies with every target board, the kernel must work with the board support package (BSP). The implementation of vectored interrupts on a processor that does not support them must be done in software.

A table in the BSP allows an IACK for each of the 15 interrupt levels. A NULL (0) entry corresponds to no interrupt acknowledge. If an IACK is required, the table entry corresponds to a routine that performs the necessary operations. Because the SPARC vector table contains 256 entries, a byte-sized vector can select any exception handler.

Note that the microprocessor, the board, and the kernel reserve certain vector table entries. The kernel appends this vector to the TBR and continues execution with the selected ISR. All checking for the IACK condition and performing of the operation is done by the kernel and is transparent. The interrupt connection mechanism is the same, and checking for and clearing the pending interrupt is done before the ISR attached by intConnect( ) is called.

The following shows the structure used on the SPARCengine 1E (also known as a Sun 1E) SPARC board in installDir/target/config/sun1e/sysLib.c. It illustrates the use of vectored interrupts for VME, but does not require an IACK cycle for local (on-board) interrupts:

extern sysVmeAck();    /* IACK Leaf Functions, code in sysALib */
int (*sysIntAckTable [16])() = { NULL, /* Reserved for Kernel */ NULL, /* Interrupt Level 1 - Software 1 */ sysVmeAck, /* Interrupt Level 2 - VME 1 */ sysVmeAck, /* Interrupt Level 3 - VME 2 */ NULL, /* Interrupt Level 4 - SCSI */ sysVmeAck, /* Interrupt Level 5 - VME 3 */ NULL, /* Interrupt Level 6 - Ethernet */ NULL, /* Interrupt Level 7 - P2 Bus */ sysVmeAck, /* Interrupt Level 8 - VME 4 */ sysVmeAck, /* Interrupt Level 9 - VME 5 */ NULL, /* Interrupt Level 10 - Timer 0 */ sysVmeAck, /* Interrupt Level 11 - VME 6 */ NULL, /* Interrupt Level 12 - Serial Ports */ NULL, /* Interrupt Level 13 - Mailbox */ NULL, /* Interrupt Level 14 - Timer 1 */ NULL /* Interrupt Level 15 - NMI */ };

The performance penalty for this added feature is negligible. When vectored interrupts are used, this penalty increases, because an operation is being handled in software that the SPARC microprocessor was not designed to do. There are some restrictions on these vector routines because they are called in a critical section of code. Again, the Sun 1E SPARC board is used as an example. Note that you must use special "leaf" procedures.

The corresponding code for the function table is in installDir/target/config/sun1e/sysALib.s:

/* IACK Function Call Template 
/* Input:     %l5 - return address 
/* Volatile:  %l4, %l6 (DO NOT USE OTHER REGISTERS !!!) 
/* Return:    %l5 - vector table index */
.global _sysVmeAck
_sysVmeAck: 
    sethi    %hi(SUN_VME_ACK),%l6 /* VMEbus IACK - 0xFFD18001          */ 
    or       %l6,%lo(SUN_VME_ACK),%l6 
    rd       %tbr,%l4             /* Extract interrupt level           */ 
    and      %l4,0x00F0,%l4 
    add      %l4,0x0010,%l4       /* Sun 1E to VME level conversion    */ 
    srl      %l4,5,%l4            /* Add 1, divide by 2 (no remainder) */ 
    sll      %l4,1,%l4            /* Multiply VME level by 2           */ 
    ldub     [%l6 + %l4],%l4      /* VMEbus IACK and get vector        */ 
    jmpl     %l5,%g0              /* Return address - leaf routine     */ 
    mov      %l4,%l5              /* Interrupt vector to %l5           */
VMEbus Interrupt Handling

SPARC uses fifteen interrupt levels instead of the seven used by VMEbus. The mapping of the seven VMEbus interrupts to the fifteen SPARC levels is board dependent. VMEbus interrupts must be acknowledged.

Floating-Point Support

Floating-Point Contexts

A task can be spawned with floating-point support by setting the VX_FP_TASK option. This causes switch hooks to initialize, save, and restore a floating-point context. This option increases the task's context switch time and memory consumption, so only spawn tasks with VX_FP_TASK if they must perform floating-point operations.

The floating-point data registers are initialized to NaN (Not-a-Number), which is 0xFFFFFFFF. You can change the FSR's (Floating-point Status Register) value using the global variable fppFsrDefault.

Floating-Point Exceptions

The following are SPARC floating-point exceptions (most are deferred):

  • FPU Disabled (or not present)
  • Unfinished Operation
  • Unimplemented Operation
  • Sequence Error
  • Invalid Operation
  • Overflow
  • Underflow
  • Divide-by-Zero
  • Inexact
  • Exception Options
  • The application can configure the types of floating-point exceptions that VxWorks handles. The ideal solution is to not generate any floating-point exceptions in the application tasks. However, a more realistic scheme is to mask all exceptions globally (all tasks) in the TEM (Trap Enable Mask) field of the FSR (Floating-point Status Register). Alternatively, this can be done locally (on a per task basis) as tasks are spawned and the FSR is initialized. In addition to global and local masks, individual exceptions (invalid operation, overflow, underflow, divide-by-zero, inexact) can be masked in the TEM. The masked exception continues to accrue (for example, become more inexact, continue to overflow, and so on). The default for VxWorks is to mask only the inexact exception.

  • Exception Handlers
  • All floating-point exceptions (if enabled) result in the suspension of the offending task and a message sent through the exception handling task, excTask( ). The floating-point unit is flushed so that other tasks can still use the hardware and continue their numeric processing.

  • Deferred Exceptions
  • Floating-point exceptions on the SPARC floating-point units are deferred. When they occur in the FPU, they do not immediately interrupt the CPU (integer unit). Instead they remain pended until they are pushed out of the queue by additional floating-point operations or an FSR access.

    If one of the last floating-point operations causes an unmasked exception before a context switch, saving the task's context flushes out the exception while in the kernel. The exception handler checks for this special case and works its way back to the kernel so that it can continue the context switch. When the task that caused the exception is switched back in, it continues in the exception handler and suspends itself. The relationship between a deferred exception and a context switch cannot be controlled due to its asynchronous nature.

  • Floating-Point Exception Simulation
  • SPARCmon is a product from Sun Microsystems that you can attach to the floating-point exception vectors to handle all exception cases for the SPARC. Any floating-point exceptions must be simulated by software and the queue flushed of all pending operations. This simulation fixes the error that caused the exception whenever possible, or takes some default action (for example, suspends the task).

    Stack Pointer Usage

    Because the stack pointer can advance without stack memory actually being written or read, it is possible for the stack high water marker to appear below the current stack pointer. In other words, current stack usage can be greater than the high stack usage. This is an artifact of the SPARC architecture's rolling register windows.

    The stack pointer is used very little. The local and output registers in each register window perform the bulk of stack operations. The stack is used for long argument lists, or if a window overflow exception pushes registers onto the stack.

    SPARClite Overview

    All information pertaining to the SPARC applies to the SPARClite, with the addition of the architectural enhancements described in the following subsections.

    Instruction and Data Cache Locking

    The SPARClite allows the global and local locking of the instruction and data caches. The ability to lock instructions and/or data in the caches allows for higher performance and more deterministic systems. The locking must be done in such a way that overall system performance is improved, not degraded. For a better real-time system, call cacheMb930LockAuto( ) to enable instruction and data cache locking. After the caches are locked, they cannot be unlocked or disabled.

    To enhance performance, some of the VxWorks kernel data items are locked in the data cache. This uses approximately 128 bytes. The remainder of the data cache is available to the developer. Additional data can be locked in the cache using the BSP.

    USS Floating-Point Emulation Library

    The SPARClite does not have a floating-point coprocessor; thus, the USS floating-point emulation library is used. Using the -msparclite compile flag allows this library to be accessed by your code for floating-point calculations.

    Memory Layout

    The memory layout of both the SPARC and SPARClite processors is shown in Figure B-1. The memory layout of the microSPARC processor is in Figure B-2. These figures contain the following labels:


    SM Anchor

    Anchor for the shared memory network (if there is shared memory on the board).

    Boot Line

    ASCII string of boot parameters.

    Exception Message

    ASCII string of the fatal exception message.

    Interrupt Vector Table

    Table of exception/interrupt vectors.

    Initial Stack

    Initial stack for usrInit( ), until usrRoot( ) gets allocated stack.

    System Image

    Entry point for VxWorks.

    WDB Memory Pool

    Size depends on the macro WDB_POOL_SIZE which defaults to one-sixteenth of the system memory pool. This space is used by the target server to support host-based tools. Modify WDB_POOL_SIZE under INCLUDE_WDB.

    Interrupt Stack

    Size is defined by ISR_STACK_SIZE under INCLUDE_KERNEL. Location depends on system image size.

    System Memory Pool

    Size depends on size of system image and interrupt stack. The end of the free memory pool for this board is returned by sysMemTop( ).


    All addresses shown are relative to the start of memory for a particular target board. The start of memory (corresponding to 0x0 in the memory-layout diagram) is defined as LOCAL_MEM_LOCAL_ADRS under INCLUDE_MEMORY_CONFIG for each target.