mirror of
https://git.rtems.org/rtems-docs/
synced 2025-05-31 02:21:26 +08:00
293 lines
12 KiB
ReStructuredText
293 lines
12 KiB
ReStructuredText
.. comment SPDX-License-Identifier: CC-BY-SA-4.0
|
|
|
|
.. COMMENT: COPYRIGHT (c) 1988-2002.
|
|
.. COMMENT: On-Line Applications Research Corporation (OAR).
|
|
.. COMMENT: All rights reserved.
|
|
.. COMMENT: Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
|
|
.. COMMENT: Micro-Research Finland Oy
|
|
|
|
Intel/AMD x86 Specific Information
|
|
**********************************
|
|
|
|
This chapter discusses the Intel x86 architecture dependencies in this port of
|
|
RTEMS. This family has multiple implementations from multiple vendors and
|
|
suffers more from having evolved rather than being designed for growth.
|
|
|
|
For information on the i386 processor, refer to the following documents:
|
|
|
|
- *386 Programmer's Reference Manual, Intel, Order No. 230985-002*.
|
|
|
|
- *386 Microprocessor Hardware Reference Manual, Intel,
|
|
Order No. 231732-003*.
|
|
|
|
- *80386 System Software Writer's Guide, Intel, Order No. 231499-001*.
|
|
|
|
- *80387 Programmer's Reference Manual, Intel, Order No. 231917-001*.
|
|
|
|
CPU Model Dependent Features
|
|
============================
|
|
|
|
This section presents the set of features which vary across i386
|
|
implementations and are of importance to RTEMS. The set of CPU model feature
|
|
macros are defined in the :file:`cpukit/score/cpu/i386/i386.h` based upon the
|
|
particular CPU model specified on the compilation command line.
|
|
|
|
bswap Instruction
|
|
-----------------
|
|
|
|
The macro ``I386_HAS_BSWAP`` is set to 1 to indicate that this CPU model has
|
|
the ``bswap`` instruction which endian swaps a thirty-two bit quantity. This
|
|
instruction appears to be present in all CPU models i486's and above.
|
|
|
|
Calling Conventions
|
|
===================
|
|
|
|
Processor Background
|
|
--------------------
|
|
|
|
The i386 architecture supports a simple yet effective call and return
|
|
mechanism. A subroutine is invoked via the call (``call``) instruction. This
|
|
instruction pushes the return address on the stack. The return from subroutine
|
|
(``ret``) instruction pops the return address off the current stack and
|
|
transfers control to that instruction. It is is important to note that the
|
|
i386 call and return mechanism does not automatically save or restore any
|
|
registers. It is the responsibility of the high-level language compiler to
|
|
define the register preservation and usage convention.
|
|
|
|
Calling Mechanism
|
|
-----------------
|
|
|
|
All RTEMS directives are invoked using a call instruction and return to the
|
|
user application via the ret instruction.
|
|
|
|
Register Usage
|
|
--------------
|
|
|
|
As discussed above, the call instruction does not automatically save any
|
|
registers. RTEMS uses the registers EAX, ECX, and EDX as scratch registers.
|
|
These registers are not preserved by RTEMS directives therefore, the contents
|
|
of these registers should not be assumed upon return from any RTEMS directive.
|
|
|
|
Parameter Passing
|
|
-----------------
|
|
|
|
RTEMS assumes that arguments are placed on the current stack before the
|
|
directive is invoked via the call instruction. The first argument is assumed
|
|
to be closest to the return address on the stack. This means that the first
|
|
argument of the C calling sequence is pushed last. The following pseudo-code
|
|
illustrates the typical sequence used to call a RTEMS directive with three (3)
|
|
arguments:
|
|
|
|
.. code-block:: c
|
|
|
|
push third argument
|
|
push second argument
|
|
push first argument
|
|
invoke directive
|
|
remove arguments from the stack
|
|
|
|
The arguments to RTEMS are typically pushed onto the stack using a push
|
|
instruction. These arguments must be removed from the stack after control is
|
|
returned to the caller. This removal is typically accomplished by adding the
|
|
size of the argument list in bytes to the stack pointer.
|
|
|
|
Memory Model
|
|
============
|
|
|
|
Flat Memory Model
|
|
-----------------
|
|
|
|
RTEMS supports the i386 protected mode, flat memory model with paging disabled.
|
|
In this mode, the i386 automatically converts every address from a logical to a
|
|
physical address each time it is used. The i386 uses information provided in
|
|
the segment registers and the Global Descriptor Table to convert these
|
|
addresses. RTEMS assumes the existence of the following segments:
|
|
|
|
- a single code segment at protection level (0) which contains all application
|
|
and executive code.
|
|
|
|
- a single data segment at protection level zero (0) which contains all
|
|
application and executive data.
|
|
|
|
The i386 segment registers and associated selectors must be initialized when
|
|
the initialize_executive directive is invoked. RTEMS treats the segment
|
|
registers as system registers and does not modify or context switch them.
|
|
|
|
This i386 memory model supports a flat 32-bit address space with addresses
|
|
ranging from 0x00000000 to 0xFFFFFFFF (4 gigabytes). Each address is
|
|
represented by a 32-bit value and is byte addressable. The address may be used
|
|
to reference a single byte, half-word (2-bytes), or word (4 bytes).
|
|
|
|
Interrupt Processing
|
|
====================
|
|
|
|
Although RTEMS hides many of the processor dependent details of interrupt
|
|
processing, it is important to understand how the RTEMS interrupt manager is
|
|
mapped onto the processor's unique architecture. Discussed in this chapter are
|
|
the the processor's response and control mechanisms as they pertain to RTEMS.
|
|
|
|
Vectoring of Interrupt Handler
|
|
------------------------------
|
|
|
|
Although the i386 supports multiple privilege levels, RTEMS and all user
|
|
software executes at privilege level 0. This decision was made by the RTEMS
|
|
designers to enhance compatibility with processors which do not provide
|
|
sophisticated protection facilities like those of the i386. This decision
|
|
greatly simplifies the discussion of i386 processing, as one need only consider
|
|
interrupts without privilege transitions.
|
|
|
|
Upon receipt of an interrupt the i386 automatically performs the following
|
|
actions:
|
|
|
|
- pushes the EFLAGS register
|
|
|
|
- pushes the far address of the interrupted instruction
|
|
|
|
- vectors to the interrupt service routine (ISR).
|
|
|
|
A nested interrupt is processed similarly by the i386.
|
|
|
|
Interrupt Stack Frame
|
|
---------------------
|
|
|
|
The structure of the Interrupt Stack Frame for the i386 which is placed on the
|
|
interrupt stack by the processor in response to an interrupt is as follows:
|
|
|
|
+----------------------+-------+
|
|
| Old EFLAGS Register | ESP+8 |
|
|
+----------+-----------+-------+
|
|
| UNUSED | Old CS | ESP+4 |
|
|
+----------+-----------+-------+
|
|
| Old EIP | ESP |
|
|
+----------------------+-------+
|
|
|
|
|
|
Interrupt Levels
|
|
----------------
|
|
|
|
Although RTEMS supports 256 interrupt levels, the i386 only supports two -
|
|
enabled and disabled. Interrupts are enabled when the interrupt-enable flag
|
|
(IF) in the extended flags (EFLAGS) is set. Conversely, interrupt processing
|
|
is inhibited when the IF is cleared. During a non-maskable interrupt, all
|
|
other interrupts, including other non-maskable ones, are inhibited.
|
|
|
|
RTEMS interrupt levels 0 and 1 such that level zero
|
|
(0) indicates that interrupts are fully enabled and level one that interrupts
|
|
are disabled. All other RTEMS interrupt levels are undefined and their
|
|
behavior is unpredictable.
|
|
|
|
Interrupt Stack
|
|
---------------
|
|
|
|
The i386 family does not support a dedicated hardware interrupt stack. On this
|
|
processor, RTEMS allocates and manages a dedicated interrupt stack. As part of
|
|
vectoring a non-nested interrupt service routine, RTEMS switches from the stack
|
|
of the interrupted task to a dedicated interrupt stack. When a non-nested
|
|
interrupt returns, RTEMS switches back to the stack of the interrupted stack.
|
|
The current stack pointer is not altered by RTEMS on nested interrupt.
|
|
|
|
Default Fatal Error Processing
|
|
==============================
|
|
|
|
The default fatal error handler for this architecture disables processor
|
|
interrupts, places the error code in EAX, and executes a HLT instruction to
|
|
halt the processor.
|
|
|
|
Symmetric Multiprocessing
|
|
=========================
|
|
|
|
SMP is not supported.
|
|
|
|
Thread-Local Storage
|
|
====================
|
|
|
|
Thread-local storage is supported.
|
|
|
|
Board Support Packages
|
|
======================
|
|
|
|
System Reset
|
|
------------
|
|
|
|
An RTEMS based application is initiated when the i386 processor is reset. When
|
|
the i386 is reset,
|
|
|
|
- The EAX register is set to indicate the results of the processor's power-up
|
|
self test. If the self-test was not executed, the contents of this register
|
|
are undefined. Otherwise, a non-zero value indicates the processor is faulty
|
|
and a zero value indicates a successful self-test.
|
|
|
|
- The DX register holds a component identifier and revision level. DH contains
|
|
3 to indicate an i386 component and DL contains a unique revision level
|
|
indicator.
|
|
|
|
- Control register zero (CR0) is set such that the processor is in real mode
|
|
with paging disabled. Other portions of CR0 are used to indicate the
|
|
presence of a numeric coprocessor.
|
|
|
|
- All bits in the extended flags register (EFLAG) which are not permanently set
|
|
are cleared. This inhibits all maskable interrupts.
|
|
|
|
- The Interrupt Descriptor Register (IDTR) is set to point at address zero.
|
|
|
|
- All segment registers are set to zero.
|
|
|
|
- The instruction pointer is set to 0x0000FFF0. The first instruction executed
|
|
after a reset is actually at 0xFFFFFFF0 because the i386 asserts the upper
|
|
twelve address until the first intersegment (FAR) JMP or CALL instruction.
|
|
When a JMP or CALL is executed, the upper twelve address lines are lowered
|
|
and the processor begins executing in the first megabyte of memory.
|
|
|
|
Typically, an intersegment JMP to the application's initialization code is
|
|
placed at address 0xFFFFFFF0.
|
|
|
|
Processor Initialization
|
|
------------------------
|
|
|
|
This initialization code is responsible for initializing all data structures
|
|
required by the i386 in protected mode and for actually entering protected
|
|
mode. The i386 must be placed in protected mode and the segment registers and
|
|
associated selectors must be initialized before the initialize_executive
|
|
directive is invoked.
|
|
|
|
The initialization code is responsible for initializing the Global Descriptor
|
|
Table such that the i386 is in the thirty-two bit flat memory model with paging
|
|
disabled. In this mode, the i386 automatically converts every address from a
|
|
logical to a physical address each time it is used. For more information on
|
|
the memory model used by RTEMS, please refer to the Memory Model chapter in
|
|
this document.
|
|
|
|
Since the processor is in real mode upon reset, the processor must be switched
|
|
to protected mode before RTEMS can execute. Before switching to protected
|
|
mode, at least one descriptor table and two descriptors must be created.
|
|
Descriptors are needed for a code segment and a data segment. ( This will give
|
|
you the flat memory model.) The stack can be placed in a normal read/write
|
|
data segment, so no descriptor for the stack is needed. Before the GDT can be
|
|
used, the base address and limit must be loaded into the GDTR register using an
|
|
LGDT instruction.
|
|
|
|
If the hardware allows an NMI to be generated, you need to create the IDT and a
|
|
gate for the NMI interrupt handler. Before the IDT can be used, the base
|
|
address and limit for the idt must be loaded into the IDTR register using an
|
|
LIDT instruction.
|
|
|
|
Protected mode is entered by setting thye PE bit in the CR0 register. Either a
|
|
LMSW or MOV CR0 instruction may be used to set this bit. Because the processor
|
|
overlaps the interpretation of several instructions, it is necessary to discard
|
|
the instructions from the read-ahead cache. A JMP instruction immediately after
|
|
the LMSW changes the flow and empties the processor if intructions which have
|
|
been pre-fetched and/or decoded. At this point, the processor is in protected
|
|
mode and begins to perform protected mode application initialization.
|
|
|
|
If the application requires that the IDTR be some value besides zero, then it
|
|
should set it to the required value at this point. All tasks share the same
|
|
i386 IDTR value. Because interrupts are enabled automatically by RTEMS as part
|
|
of the initialize_executive directive, the IDTR MUST be set properly before
|
|
this directive is invoked to insure correct interrupt vectoring. If processor
|
|
caching is to be utilized, then it should be enabled during the reset
|
|
application initialization code. The reset code which is executed before the
|
|
call to initialize_executive has the following requirements:
|
|
|
|
For more information regarding the i386 data structures and their contents,
|
|
refer to Intel's 386 Programmer's Reference Manual.
|