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.