Chapter 10 Initialization
Chapter 10 Initialization
Chapter 10 Initialization
----------------------------------------------------------------------------
After a signal on the RESET pin, certain registers of the 80386 are set to
predefined values. These values are adequate to enable execution of a
bootstrap program, but additional initialization must be performed by
software before all the features of the processor can be utilized.
10.1 Processor State after Reset
10.1 Processor State After Reset
The contents of EAX depend upon the results of the power-up self test. The
self-test may be requested externally by assertion of BUSY# at the end of
RESET. The EAX register holds zero if the 80386 passed the test. A nonzero
value in EAX after self-test indicates that the particular 80386 unit is
faulty. If the self-test is not requested, the contents of EAX after RESET
is undefined.
DX holds a component identifier and revision number after RESET as Figure
10-1 illustrates. DH contains 3, which indicates an 80386 component. DL
contains a unique identifier of the revision level.
Control register zero (CR0) contains the values shown in Figure 10-2. The
ET bit of CR0 is set if an 80387 is present in the configuration (according
to the state of the ERROR# pin after RESET). If ET is reset, the
configuration either contains an 80287 or does not contain a coprocessor. A
software test is required to distinguish between these latter two
possibilities.
The remaining registers and flags are set as follows:
EFLAGS =00000002H
IP =0000FFF0H
CS selector =000H
DS selector =0000H
ES selector =0000H
SS selector =0000H
FS selector =0000H
GS selector =0000H
IDTR:
base =0
limit =03FFH
All registers not mentioned above are undefined.
These settings imply that the processor begins in real-address mode with
interrupts disabled.
See Also: Fig.10-1 Fig.10-2
10.2 Software Initialization for Real-Address Mode
10.2 Software Initialization for Real-Address Mode
In real-address mode a few structures must be initialized before a program
can take advantage of all the features available in this mode.
10.2.1 Stack
10.2.1 Stack
No instructions that use the stack can be used until the stack-segment
register (SS) has been loaded. SS must point to an area in RAM.
10.2.2 Interrupt Table
10.2.2 Interrupt Table
The initial state of the 80386 leaves interrupts disabled; however, the
processor will still attempt to access the interrupt table if an exception
or nonmaskable interrupt (NMI) occurs. Initialization software should take
one of the following actions:
* Change the limit value in the IDTR to zero. This will cause a shutdown
if an exception or nonmaskable interrupt occurs. (Refer to the 80386
Hardware Reference Manual to see how shutdown is signalled externally.)
* Put pointers to valid interrupt handlers in all positions of the
interrupt table that might be used by exceptions or interrupts.
* Change the IDTR to point to a valid interrupt table.
10.2.3 First Instructions
10.2.3 First Instructions
After RESET, address lines A{31-20} are automatically asserted for
instruction fetches. This fact, together with the initial values of CS:IP,
causes instruction execution to begin at physical address FFFFFFF0H. Near
(intrasegment) forms of control transfer instructions may be used to pass
control to other addresses in the upper 64K bytes of the address space. The
first far (intersegment) JMP or CALL instruction causes A{31-20} to drop
low, and the 80386 continues executing instructions in the lower one
megabyte of physical memory. This automatic assertion of address lines
A{31-20} allows systems designers to use a ROM at the high end of
the address space to initialize the system.
10.3 Switching to Protected Mode
10.3 Switching to Protected Mode
Setting the PE bit of the MSW in CR0 causes the 80386 to begin executing in
protected mode. The current privilege level (CPL) starts at zero. The
segment registers continue to point to the same linear addresses as in real
address mode (in real address mode, linear addresses are the same physical
addresses).
Immediately after setting the PE flag, the initialization code must flush
the processor's instruction prefetch queue by executing a JMP instruction.
The 80386 fetches and decodes instructions and addresses before they are
used; however, after a change into protected mode, the prefetched
instruction information (which pertains to real-address mode) is no longer
valid. A JMP forces the processor to discard the invalid information.
10.4 Software Initialization for Protected Mode
10.4 Software Initialization for Protected Mode
Most of the initialization needed for protected mode can be done either
before or after switching to protected mode. If done in protected mode,
however, the initialization procedures must not use protected-mode features
that are not yet initialized.
10.4.1 Interrupt Descriptor Table
10.4.1 Interrupt Descriptor Table
The IDTR may be loaded in either real-address or protected mode. However,
the format of the interrupt table for protected mode is different than that
for real-address mode. It is not possible to change to protected mode and
change interrupt table formats at the same time; therefore, it is inevitable
that, if IDTR selects an interrupt table, it will have the wrong format at
some time. An interrupt or exception that occurs at this time will have
unpredictable results. To avoid this unpredictability, interrupts should
remain disabled until interrupt handlers are in place and a valid IDT has
been created in protected mode.
10.4.2 Stack
10.4.2 Stack
The SS register may be loaded in either real-address mode or protected
mode. If loaded in real-address mode, SS continues to point to the same
linear base-address after the switch to protected mode.
10.4.3 Global Descriptor Table
10.4.3 Global Descriptor Table
Before any segment register is changed in protected mode, the GDT register
must point to a valid GDT. Initialization of the GDT and GDTR may be done in
real-address mode. The GDT (as well as LDTs) should reside in RAM, because
the processor modifies the accessed bit of descriptors.
10.4.4 Page Tables
10.4.4 Page Tables
Page tables and the PDBR in CR3 can be initialized in either real-address
mode or in protected mode; however, the paging enabled (PG) bit of CR0
cannot be set until the processor is in protected mode. PG may be set
simultaneously with PE, or later. When PG is set, the PDBR in CR3 should
already be initialized with a physical address that points to a valid page
directory. The initialization procedure should adopt one of the following
strategies to ensure consistent addressing before and after paging is
enabled:
* The page that is currently being executed should map to the same
physical addresses both before and after PG is set.
* A JMP instruction should immediately follow the setting of PG.
10.4.5 First Task
10.4.5 First Task
The initialization procedure can run awhile in protected mode without
initializing the task register; however, before the first task switch, the
following conditions must prevail:
* There must be a valid task state segment (TSS) for the new task. The
stack pointers in the TSS for privilege levels numerically less than or
equal to the initial CPL must point to valid stack segments.
* The task register must point to an area in which to save the current
task state. After the first task switch, the information dumped in this
area is not needed, and the area can be used for other purposes.
10.5 Initialization Example
10.5 Initialization Example
$TITLE ('Initial Task')
NAME INIT
init_stack SEGMENT RW
DW 20 DUP(?)
tos LABEL WORD
init_stack ENDS
init_data SEGMENT RW PUBLIC
DW 20 DUP(?)
init_data ENDS
init_code SEGMENT ER PUBLIC
ASSUME DS:init_data
nop
nop
nop
init_start:
; set up stack
mov ax, init_stack
mov ss, ax
mov esp, offset tos
mov a1,1
blink:
xor a1,1
out 0e4h,a1
mov cx,3FFFh
here:
dec cx
jnz here
jmp SHORT blink
hlt
init_code ends
END init_start, SS:init_stack, DS:init_data
$TITLE('Protected Mode Transition -- 386 initialization')
NAME RESET
;*****************************************************************
; Upon reset the 386 starts executing at address 0FFFFFFF0H. The
; upper 12 address bits remain high until a FAR call or jump is
; executed.
;
; Assume the following:
;
;
; - a short jump at address 0FFFFFFF0H (placed there by the
; system builder) causes execution to begin at START in segment
; RESET_CODE.
;
;
; - segment RESET_CODE is based at physical address 0FFFF0000H,
; i.e. at the start of the last 64K in the 4G address space.
; Note that this is the base of the CS register at reset. If
; you locate ROMcode above this address, you will need to
; figure out an adjustment factor to address things within this
; segment.
;
;*****************************************************************
$EJECT ;
; Define addresses to locate GDT and IDT in RAM.
; These addresses are also used in the BLD386 file that defines
; the GDT and IDT. If you change these addresses, make sure you
; change the base addresses specified in the build file.
GDTbase EQU 00001000H ; physical address for GDT base
IDTbase EQU 00000400H ; physical address for IDT base
PUBLIC GDT_EPROM
PUBLIC IDT_EPROM
PUBLIC START
DUMMY segment rw ; ONLY for ASM386 main module stack init
DW 0
DUMMY ends
;*****************************************************************
;
; Note: RESET CODE must be USEl6 because the 386 initally executes
; in real mode.
;
RESET_CODE segment er PUBLIC USE16
ASSUME DS:nothing, ES:nothing
;
; 386 Descriptor template
DESC STRUC
lim_0_15 DW 0 ; limit bits (0..15)
bas_0_15 DW 0 ; base bits (0..15)
bas_16_23 DB 0 ; base bits (16..23)
access DB 0 ; access byte
gran DB 0 ; granularity byte
bas_24_31 DB 0 ; base bits (24..31)
DESC ENDS
; The following is the layout of the real GDT created by BLD386.
; It is located in EPROM and will be copied to RAM.
;
; GDT[O] ... NULL
; GDT[1] ... Alias for RAM GDT
; GDT[2] ... Alias for RAM IDT
; GDT[2] ... initial task TSS
; GDT[3] ... initial task TSS alias
; GDT[4] ... initial task LDT
; GDT[5] ... initial task LDT alias
;
; define entries in GDT and IDT.
GDT_ENTRIES EQU 8
IDT_ENTRIES EQU 32
; define some constants to index into the real GDT
GDT_ALIAS EQU 1*SIZE DESC
IDT_ALIAS EQU 2*SIZE DESC
INIT_TSS EQU 3*SIZE DESC
INIT_TSS_A EQU 4*SIZE DESC
INIT_LDT EQU 5*SIZE DESC
INIT_LDT_A EQU 6*SIZE DESC
;
; location of alias in INIT_LDT
INIT_LDT_ALIAS EQU 1*SIZE DESC
;
; access rights byte for DATA and TSS descriptors
DS_ACCESS EQU 010010010B
TSS_ACCESS EQU 010001001B
;
; This temporary GDT will be used to set up the real GDT in RAM.
Temp_GDT LABEL BYTE ; tag for begin of scratch GDT
NULL_DES DESC <> ; NULL descriptor
; 32-Gigabyte data segment based at 0
FLAT_DES DESC <0FFFFH,0,0,92h,0CFh,0>
GDT_eprom DP ? ; Builder places GDT address and limit
; in this 6 byte area.
IDT_eprom DP ? ; Builder places IDT address and limit
; in this 6 byte area.
;
; Prepare operand for loadings GDTR and LDTR.
TGDT_pword LABEL PWORD ; for temp GDT
DW end_Temp_GDT_Temp_GDT -1
DD 0
GDT_pword LABEL PWORD ; for GDT in RAM
DW GDT_ENTRIES * SIZE DESC -1
DD GDTbase
IDT_pword LABEL PWORD ; for IDT in RAM
DW IDT_ENTRIES * SIZE DESC -1
DD IDTbase
end_Temp_GDT LABEL BYTE
;
; Define equates for addressing convenience.
GDT_DES_FLAT EQU DS:GDT_ALIAS +GDTbase
IDT_DES_FLAT EQU DS:IDT_ALIAS +GDTbase
INIT_TSS_A_OFFSET EQU DS:INIT_TSS_A
INIT_TSS_OFFSET EQU DS:INIT_TSS
INIT_LDT_A_OFFSET EQU DS:INIT_LDT_A
INIT_LDT_OFFSET EQU DS:INIT_LDT
; define pointer for first task switch
ENTRY POINTER LABEL DWORD
DW 0, INIT_TSS
;******************************************************************
;
; Jump from reset vector to here.
START:
CLI ;disable interrupts
CLD ;clear direction flag
LIDT NULL_des ;force shutdown on errors
;
; move scratch GDT to RAM at physical 0
XOR DI,DI
MOV ES,DI ;point ES:DI to physical location 0
MOV SI,OFFSET Temp_GDT
MOV CX,end_Temp_GDT-Temp_GDT ;set byte count
INC CX
;
; move table
REP MOVS BYTE PTR ES:[DI],BYTE PTR CS:[SI]
LGDT tGDT_pword ;load GDTR for Temp. GDT
;(located at 0)
; switch to protected mode
MOV EAX,CR0 ;get current CRO
MOV EAX,1 ;set PE bit
MOV CRO,EAX ;begin protected mode
;
; clear prefetch queue
JMP SHORT flush
flush:
; set DS,ES,SS to address flat linear space (0 ... 4GB)
MOV BX,FLAT_DES-Temp_GDT
MOV US,BX
MOV ES,BX
MOV SS,BX
;
; initialize stack pointer to some (arbitrary) RAM location
MOV ESP, OFFSET end_Temp_GDT
;
; copy eprom GDT to RAM
MOV ESI,DWORD PTR GDT_eprom +2 ; get base of eprom GDT
; (put here by builder).
MOV EDI,GDTbase ; point ES:EDI to GDT base in RAM.
MOV CX,WORD PTR gdt_eprom +0 ; limit of eprom GDT
INC CX
SHR CX,1 ; easier to move words
CLD
REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]
;
; copy eprom IDT to RAM
;
MOV ESI,DWORD PTR IDT_eprom +2 ; get base of eprom IDT
; (put here by builder)
MOV EDI,IDTbase ; point ES:EDI to IDT base in RAM.
MOV CX,WORD PTR idt_eprom +0 ; limit of eprom IDT
INC CX
SHR CX,1
CLD
REP MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]
; switch to RAM GDT and IDT
;
LIDT IDT_pword
LGDT GDT_pword
;
MOV BX,GDT_ALIAS ; point DS to GDT alias
MOV DS,BX
;
; copy eprom TSS to RAM
;
MOV BX,INIT_TSS_A ; INIT TSS A descriptor base
; has RAM location of INIT TSS.
MOV ES,BX ; ES points to TSS in RAM
MOV BX,INIT_TSS ; get inital task selector
LAR DX,BX ; save access byte
MOV [BX].access,DS_ACCESS ; set access as data segment
MOV FS,BX ; FS points to eprom TSS
XOR si,si ; FS:si points to eprom TSS
XOR di,di ; ES:di points to RAM TSS
MOV CX,[BX].lim_0_15 ; get count to move
INC CX
;
; move INIT_TSS to RAM.
REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si]
MOV [BX].access,DH ; restore access byte
;
; change base of INIT TSS descriptor to point to RAM.
MOV AX,INIT_TSS_A_OFFSET.bas_0_15
MOV INIT_TSS_OFFSET.bas_0_15,AX
MOV AL,INIT_TSS_A_OFFSET.bas_16_23
MOV INIT_TSS_OFFSET.bas_16_23,AL
MOV AL,INIT_TSS_A_OFFSET.bas_24_31
MOV INIT_TSS_OFFSET.bas_24_31,AL
;
; change INIT TSS A to form a save area for TSS on first task
; switch. Use RAM at location 0.
MOV BX,INIT_TSS_A
MOV WORD PTR [BX].bas_0_15,0
MOV [BX].bas_16_23,0
MOV [BX].bas_24_31,0
MOV [BX].access,TSS_ACCESS
MOV [BX].gran,O
LTR BX ; defines save area for TSS
;
; copy eprom LDT to RAM
MOV BX,INIT_LDT_A ; INIT_LDT_A descriptor has
; base address in RAM for INIT_LDT.
MOV ES,BX ; ES points LDT location in RAM.
MOV AH,[BX].bas_24_31
MOV AL,[BX].bas_16_23
SHL EAX,16
MOV AX,[BX].bas_0_15 ; save INIT_LDT base (ram) in EAX
MOV BX,INIT_LDT ; get inital LDT selector
LAR DX,BX ; save access rights
MOV [BX].access,DS_ACCESS ; set access as data segment
MOV FS,BX ; FS points to eprom LDT
XOR si,si ; FS:SI points to eprom LDT
XOR di,di ; ES:DI points to RAM LDT
MOV CX,[BX].lim_0_15 ; get count to move
INC CX
;
; move initial LDT to RAM
REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si]
MOV [BX].access,DH ; restore access rights in
; INIT_LDT descriptor
;
; change base of alias (of INIT_LDT) to point to location in RAM.
MOV ES:[INIT_LDT_ALIAS].bas_0_15,AX
SHR EAX,16
MOV ES:[INIT_LDT_ALIAS].bas_16_23,AL
MOV ES:[INIT_LDT_ALIAS].bas_24_31,AH
;
; now set the base value in INIT_LDT descriptor
MOV AX,INIT_LDT_A_OFFSET.bas_0_15
MOV INIT_LDT_OFFSET.bas_0_15,AX
MOV AL,INIT_LDT_A_OFFSET.bas_16_23
MOV INIT_LDT_OFFSET.bas_16_23,AL
MOV AL,INIT_LDT_A_OFFSET.bas_24_31
MOV INIT_LDT_OFFSET.bas_24_31,AL
;
; Now GDT, IDT, initial TSS and initial LDT are all set up.
;
; Start the first task!
'
JMP ENTRY_POINTER
RESET_CODE ends
END START, SS:DUMMY,DS:DUMMY
10.6 TLB Testing
10.6 TLB Testing
The 80386 provides a mechanism for testing the Translation Lookaside Buffer
(TLB), the cache used for translating linear addresses to physical
addresses. Although failure of the TLB hardware is extremely unlikely, users
may wish to include TLB confidence tests among other power-up confidence
tests for the 80386.
---------------------------------------------------------------------------
NOTE
This TLB testing mechanism is unique to the 80386 and may not be
continued in the same way in future processors. Sortware that uses
this mechanism may be incompatible with future processors.
---------------------------------------------------------------------------
When testing the TLB it is recommended that paging be turned off (PG=0 in
CR0) to avoid interference with the test data being written to the TLB.
10.6.1 Structure of the TLB
10.6.1 Structure of the TLB
The TLB is a four-way set-associative memory. Figure 10-3 illustrates the
structure of the TLB. There are four sets of eight entries each. Each entry
consists of a tag and data. Tags are 24-bits wide. They contain the
high-order 20 bits of the linear address, the valid bit, and three attribute
bits. The data portion of each entry contains the high-order 20 bits of the
physical address.
See Also: Fig.10-3
10.6.2 Test Registers
10.6.2 Test Registers
Two test registers, shown in Figure 10-4, are provided for the purpose of
testing. TR6 is the test command register, and TR7 is the test data
register. These registers are accessed by variants of the MOV
instruction. A test register may be either the source operand or destination
operand. The MOV instructions are defined in both real-address mode and
protected mode. The test registers are privileged resources; in protected
mode, the MOV instructions that access them can only be executed at
privilege level 0. An attempt to read or write the test registers when
executing at any other privilege level causes a general
protection exception.
The test command register (TR6) contains a command and an address tag to
use in performing the command:
C This is the command bit. There are two TLB testing commands:
write entries into the TLB, and perform TLB lookups. To cause an
immediate write into the TLB entry, move a doubleword into TR6
that contains a 0 in this bit. To cause an immediate TLB lookup,
move a doubleword into TR6 that contains a 1 in this bit.
Linear On a TLB write, a TLB entry is allocated to this linear address;
Address the rest of that TLB entry is set per the value of TR7 and the
value just written into TR6. On a TLB lookup, the TLB is
interrogated per this value; if one and only one TLB entry
matches, the rest of the fields of TR6 and TR7 are set from the
matching TLB entry.
V The valid bit for this TLB entry. The TLB uses the valid bit to
identify entries that contain valid data. Entries of the TLB
that have not been assigned values have zero in the valid bit.
All valid bits can be cleared by writing to CR3.
D, D# The dirty bit (and its complement) for/from the TLB entry.
U, U# The U/S bit (and its complement) for/from the TLB entry.
W, W# The R/W bit (and its complement) for/from the TLB entry.
The meaning of these pairs of bits is given by Table 10-1,
where X represents D, U, or W.
The test data register (TR7) holds data read from or data to be written to
the TLB.
Physical This is the data field of the TLB. On a write to the TLB, the
Address TLB entry allocated to the linear address in TR6 is set to this
value. On a TLB lookup, if HT is set, the data field (physical
address) from the TLB is read out to this field. If HT is not
set, this field is undefined.
HT For a TLB lookup, the HT bit indicates whether the lookup was a
hit (HT = 1) or a miss (HT = 0). For a TLB write, HT must be set
to 1.
REP For a TLB write, selects which of four associative blocks of the
TLB is to be written. For a TLB read, if HT is set, REP reports
in which of the four associative blocks the tag was found; if HT
is not set, REP is undefined.
See Also: Tab.10-1 Fig.10-3 Fig.10-4
10.6.3 Test Operations
10.6.3 Test Operations
To write a TLB entry:
1. Move a doubleword to TR7 that contains the desired physical address,
HT, and REP values. HT must contain 1. REP must point to the
associative block in which to place the entry.
2. Move a doubleword to TR6 that contains the appropriate linear
address, and values for V, D, U, and W. Be sure C=0 for "write"
command.
Be careful not to write duplicate tags; the results of doing so are
undefined.
To look up (read) a TLB entry:
1. Move a doubleword to TR6 that contains the appropriate linear address
and attributes. Be sure C=1 for "lookup" command.
2. Store TR7. If the HT bit in TR7 indicates a hit, then the other
values reveal the TLB contents. If HT indicates a miss, then the other
values in TR7 are indeterminate.
For the purposes of testing, the V bit functions as another bit of
addresss. The V bit for a lookup request should usually be set, so that
uninitialized tags do not match. Lookups with V=0 are unpredictable if any
tags are uninitialized.