Unit - 3
Protection and multitasking
1. The purpose of the protection features of the 80386 is to help detect and identify bugs. The 80386 supports sophisticated applications that may consist of hundreds or thousands of program modules.
2. In such applications, the question is how bugs can be found and eliminated as quickly as possible and how their damage can be tightly confined. To help debug applications faster and make them more robust in production, the 80386 contains mechanisms to verify memory accesses and instruction execution for conformance to protection criteria.
3. These mechanisms may be used or ignored, according to system design objectives.
Key takeaways
- In such applications, the question is how bugs can be found and eliminated as quickly as possible and how their damage can be tightly confined
- These mechanisms may be used or ignored, according to system design objectives.
1. Protection in the 80386 has five aspects:
(i) Type checking
(ii) Limit checking
(iii) Restriction of addressable domain
(iv) Restriction of procedure entry points
(v) Restriction of instruction set
2. The protection hardware of the 80386 is an integral part of the memory management hardware.
3. Protection applies both to segment translation and to page translation.
4. Each reference to memory is checked by the hardware to verify that it satisfies the protection criteria. All these checks are made before the memory cycle is started; any violation prevents that cycle from starting and results in an exception. Since the checks are performed concurrently with address formation, there is no performance penalty.
5. Invalid attempts to access memory result in an exception.
6. The concept of "privilege" is central to several aspects of protection Applied to procedures, privilege is the degree to which the procedure can be trusted not to make a mistake that might affect other procedures or data.
7. Applied to data, privilege is the degree of protection that a data structure should have from less trusted procedures.
8. The concept of privilege applies both to segment protection and to page protection.
Key takeaways
- Protection applies both to segment translation and to page translation.
- Applied to data, privilege is the degree of protection that a data structure should have from less trusted procedures.
- Invalid attempts to access memory result in an exception.
All five aspects of protection apply to segment translation:
1. Type checking
2. Limit checking
3. Restriction of addressable domain
4. Restriction of procedure entry points
5. Restriction of instruction set
The segment is the unit of protection, and segment descriptors store protection parameters. Protection checks are performed automatically by the CPU when the selector of a segment descriptor is loaded into a segment register and with every segment access. Segment registers hold the protection parameters of the currently addressable segments.
3.3.1 Descriptors Store Protection Parameters
1. The protection parameters are placed in the descriptor by systems software at the time a descriptor is created. In general, applications programmers do not need to be concerned about protection parameters.
2. When a program loads a selector into a segment register, the processor loads not only the base address of the segment but also protection information.
3. Each segment register has bits in the invisible portion for storing base, limit, type, and privilege level; therefore, subsequent protection checks on the same segment do not consume additional clock cycles.
3.3.2 Restricting Access to Data
1. To address operands in memory, an 80386 program must load the selector of a data segment into a data-segment register (DS, ES, FS, GS, SS).
2. The processor automatically evaluates access to a data segment by comparing privilege levels.
3. The evaluation is performed at the time a selector for the descriptor of the target segment is loaded into the data-segment register. As three different privilege levels enter into this type of privilege check:
- The CPL (current privilege level).
- The RPL (requestor's privilege level) of the selector used to specify the target segment.
- The DPL of the descriptor of the target segment.
4. Instructions may load a data-segment register (and subsequently use the target segment) only if the DPL of the target segment is numerically greater than or equal to the maximum of the CPL and the selector's RPL. In other words, a procedure can only access data that is at the same or less privileged level.
5. The addressable domain of a task varies as CPL changes. When CPL is zero, data segments at all privilege levels are accessible; when CPL is one, only data segments at privilege levels one through three are accessible; when CPL is three, only data segments at privilege level three are accessible.
6. This property of the 80386 can be used, for example, to prevent applications procedures from reading or changing tables of the operating system.
3.3.3 Restricting Control Transfers
1. With the 80386, control transfers are accomplished by the instructions JMP, CALL, RET, INT, and IRET, as well as by the exception and interrupt mechanisms . Exceptions and interrupts are special cases . This chapter discusses only JMP, CALL, and RET instructions.
2. The "near" forms of JMP, CALL, and RET transfer within the current code segment, and therefore are subject only to limit checking.
3.The processor ensures that the destination of the JMP, CALL, or RET instruction does not exceed the limit of the current executable segment.
4. This limit is cached in the CS register; therefore, protection checks for near transfers require no extra clock cycles.
5. The operands of the "far" forms of JMP and CALL refer to other segments; therefore, the processor performs privilege checking. There are two ways a JMP or CALL can refer to another segment:
- The operand selects the descriptor of another executable segment.
- The operand selects a call gate descriptor. This gated form of transfer is discussed in a later section on call gates.
6. As two different privilege levels enter into a privilege check for a control transfer that does not use a call gate:
- The CPL (current privilege level).
- The DPL of the descriptor of the target segment.
7. Normally the CPL is equal to the DPL of the segment that the processor is currently executing. CPL may, however, be greater than DPL if the conforming bit is set in the descriptor of the current executable segment.
8. The processor keeps a record of the CPL cached in the CS register; this value can be different from the DPL in the descriptor of the code segment.
9. The processor permits a JMP or CALL directly to another segment only if one of the following privilege rules is satisfied:
9.1 DPL of the target is equal to CPL.
The conforming bit of the target code-segment descriptor is set, and the DPL of the target is less than or equal to CPL.
10. An executable segment whose descriptor has the conforming bit set is called a conforming segment. The conforming-segment mechanism permits sharing of procedures that may be called from various privilege levels but should execute at the privilege level of the calling procedure.
11. Examples of such procedures include math libraries and some exception handlers. When control is transferred to a conforming segment, the CPL does not change. This is the only case when CPL may be unequal to the DPL of the current executable segment.
12. Most code segments are not conforming. The basic rules of privilege above mean that, for nonconforming segments, control can be transferred without a gate only to executable segments at the same level of privilege.
13. There is a need, however, to transfer control to (numerically) smaller privilege levels; this need is met by the CALL instruction when used with call-gate descriptors, which are explained in the next section. The JMP instruction may never transfer
3.3.4 Gate Descriptors Guard Procedure Entry Points
1. To provide protection for control transfers among executable segments at different privilege levels, the 80386 uses gate descriptors. There are four kinds of gate descriptors:
(i) Call gates
(ii) Trap gates
(iii) Interrupt gates
(iv) Task gates
2. This chapter is concerned only with call gates. Task gates are used for task switching, it explains how trap gates and interrupt gates are used by exceptions and interrupts. illustrates the format of a call gate. A call gate descriptor may reside in the GDT or in an LDT, but not in the IDT. A call gate has two primary functions:
- To define an entry point of a procedure.
- To specify the privilege level of the entry point.
3. Call gate descriptors are used by call and jump instructions in the same manner as code segment descriptors.
4. When the hardware recognizes that the destination selector refers to a gate descriptor, the operation of the instruction is expanded as determined by the contents of the call gate.
5. The selector and offset fields of a gate form a pointer to the entry point of a procedure.
6. A call gate guarantees that all transitions to another segment go to a valid entry point, rather than possibly into the middle of a procedure (or worse, into the middle of an instruction).
7. The far pointer operand of the control transfer instruction does not point to the segment and offset of the target instruction; rather, the selector part of the pointer selects a gate, and the offset is not used. It illustrates this style of addressing.
8. Four different privilege levels are used to check the validity of a control transfer via a call gate:
- The CPL (current privilege level).
- The RPL (requestor's privilege level) of the selector used to specify the call gate.
- The DPL of the gate descriptor.
- The DPL of the descriptor of the target executable segment.
9. The DPL field of the gate descriptor determines what privilege levels can use the gate. One code segment can have several procedures that are intended for use by different privilege levels.
10. For example, an operating system may have some services that are intended to be used by applications, whereas others may be intended only for use by other systems software.
11. Gates can be used for control transfers to numerically smaller privilege levels or to the same privilege level (though they are not necessary for transfers to the same level).
12. Only CALL instructions can use gates to transfer to smaller privilege levels. A gate may be used by a JMP instruction only to transfer to an executable segment with the same privilege level or to a conforming segment.
3.3.5 Some Instructions are reserved for Operating System
1. Instructions that have the power to affect the protection mechanism or to influence general system performance can only be executed by trusted procedures. The 80386 has two classes of such instructions:
2. Privileged instructions -- those used for system control.
3. Sensitive instructions -- those used for I/O and I/O related activities.
Interlevel Return Checks SF = Stack Fault GP = General Protection Exception NP = Segment-Not-Present Exception
Type of Check Exception Error Code
ESP is within current SS segment SF 0 ESP + 7 is within current SS segment SF 0 RPL of return CS is greater than CPL GP Return CS Return CS selector is not null GP Return CS Return CS segment is within descriptor table limit GP Return CS Return CS descriptor is a code segment GP Return CS Return CS segment is present NP Return CS DPL of return nonconforming code segment = RPL of return CS, or DPL of return conforming code segment <= RPL of return CS GP Return CS ESP + N + 15 is within SS segment N Immediate Operand of RET N Instruction SF Return SS SS selector at ESP + N + 12 is not null GP Return SS SS selector at ESP + N + 12 is within descriptor table limit GP Return SS SS descriptor is writable data segment GP Return SS SS segment is present SF Return SS Saved SS segment DPL = RPL of saved CS GP Return SS Saved SS selector RPL = Saved SS segment DPL GP Return SS |
3.3.6 Instructions for Pointer Validation
1. Pointer validation is an important part of locating programming errors. Pointer validation is necessary for maintaining isolation between the privilege levels. Pointer validation consists of the following steps:
(i) Check if the supplier of the pointer is entitled to access the segment.
(ii) Check if the segment type is appropriate to its intended use.
(iii) Check if the pointer violates the segment limit.
2. Although the 80386 processor automatically performs checks 2 and 3 during instruction execution, software must assist in performing the first check. The unprivileged instruction ARPL is provided for this purpose.
3. Software can also explicitly perform steps 2 and 3 to check for potential violations (rather than waiting for an exception). The unprivileged instructions LAR, LSL, VERR, and VERW are provided for this purpose.
4. LAR (Load Access Rights) is used to verify that a pointer refers to a segment of the proper privilege level and type. LAR has one operand selector for a descriptor whose access rights are to be examined.
5. The descriptor must be visible at the privilege level which is the maximum of the CPL and the selector's RPL. If the descriptor is visible, LAR obtains a masked form of the second double word of the descriptor, masks this value with 00FxFF00H, stores the result into the specified 32-bit destination register, and sets the zero flag.
6. (The x indicates that the corresponding four bits of the stored value are undefined.) Once loaded, the access-rights bits can be tested. All valid descriptor types can be tested by the LAR instruction.
7. If the RPL or CPL is greater than DPL, or if the selector is outside the table limit, no access-rights value is returned, and the zero flag is cleared. Conforming code segments may be accessed from any privilege level.
8. LSL (Load Segment Limit) allows software to test the limit of a descriptor. If the descriptor denoted by the given selector (in memory or a register) is visible at the CPL, LSL loads the specified 32-bit register with a 32-bit, byte granular, unscrambled limit that is calculated from fragmented limit fields and the G-bit of that descriptor.
9. This can only be done for segments (data, code, task state, and local descriptor tables); gate descriptors are inaccessible. (lists in detail which types are valid and which are not.) Interpreting the limit is a function of the segment type.
10. For example, downward expandable data segments treat the limit differently than code segments do. For both LAR and LSL, the zero flag (ZF) is set if the loading was performed; otherwise, the ZF is cleared.
Valid Descriptor Types for LSL
Type Descriptor Type Valid?
Code
0 (invalid) NO
1 Available 286 TSS YES
2 LDT YES
3 Busy 286 TSS YES
4 286 Call Gate NO
5 Task Gate NO
6 286 Trap Gate NO
7 286 Interrupt Gate NO
8 (invalid) NO
9 Available 386 TSS YES
A (invalid) NO
B Busy 386 TSS YES
C 386 Call Gate NO
D (invalid) NO
E 386 Trap Gate NO
F 386 Interrupt Gate NO
Key takeaways
- LAR (Load Access Rights) is used to verify that a pointer refers to a segment of the proper privilege level and type. LAR has one operand selector for a descriptor whose access rights are to be examined.
- The descriptor must be visible at the privilege level which is the maximum of the CPL and the selector's RPL
- If the descriptor is visible, LAR obtains a masked form of the second double word of the descriptor, masks this value with 00FxFF00H, stores the result into the specified 32-bit destination register, and sets the zero flag.
- When the hardware recognizes that the destination selector refers to a gate descriptor, the operation of the instruction is expanded as determined by the contents of the call gate.
- Instructions that have the power to affect the protection mechanism or to influence general system performance can only be executed by trusted procedures.
- The processor keeps a record of the CPL cached in the CS register; this value can be different from the DPL in the descriptor of the code segment.
- . Protection checks are performed automatically by the CPU when the selector of a segment descriptor is loaded into a segment register and with every segment access.
- When a program loads a selector into a segment register, the processor loads not only the base address of the segment but also protection information.
- The "near" forms of JMP, CALL, and RET transfer within the current code segment, and therefore are subject only to limit checking.
Two kinds of protection are related to pages:
1. Restriction of addressable domain.
2. Type checking.
1. Restricting Addressable Domain
1. The concept of privilege for pages is implemented by assigning each page to one of two levels:
2. Supervisor level (U/S=0) -- for the operating system and other systems software and related data.
3. User level (U/S=1) -- for applications procedures and data.
4. The current level (U or S) is related to CPL. If CPL is 0, 1, or 2, the processor is executing at supervisor level. If CPL is 3, the processor is executing at user level.
5. When the processor is executing at supervisor level, all pages are addressable, but, when the processor is executing at user level, only pages that belong to the user level are addressable.
2. Type Checking
1. At the level of page addressing, two types are defined:
Read-only access (R/W=0)
Read/write access (R/W=1)
2. When the processor is executing at supervisor level, all pages are both readable and writable.
3. When the processor is executing at user level, only pages that belong to user level and are marked for read/write access are writable; pages that belong to supervisor level are neither readable nor writable from user level.
Key takeaways
- Supervisor level (U/S=0) -- for the operating system and other systems software and related data.
- When the processor is executing at supervisor level, all pages are both readable and writable.
All the information the processor needs in order to manage a task is stored in a special type of segment, a task state segment (TSS).
The fields of a TSS belong to two classes:
1. A dynamic set that the processor updates with each switch from the task. This set includes the fields that store:
(i) The general registers (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI).
(ii) The segment registers (ES, CS, SS, DS, FS, GS).
(iii) The flags register (EFLAGS).
(iv) The instruction pointer (EIP).
(v) The selector of the TSS of the previously executing task (updated only when a return is expected).
2. A static set that the processor reads but does not change. This set includes the fields that store:
- The selector of the task's LDT.
- The register (PDBR) that contains the base address of the task's page directory (read only when paging is enabled).
- Pointers to the stacks for privilege levels 0-2.
- The T-bit (debug trap bit) which causes the processor to raise a debug exception when a task switch occurs .
- The I/O map base
3. Task state segments may reside anywhere in the linear space. The only case that requires caution is when the TSS spans a page boundary and the higher-addressed page is not present.
4. In this case, the processor raises an exception if it encounters the not-present page while reading the TSS during a task switch. Such an exception can be avoided by either of two strategies:
- By allocating the TSS so that it does not cross a page boundary.
- By ensuring that both pages are either both present or both not-present at the time of a task switch. If both pages are not-present, then the page-fault handler must make both pages present before restarting the instruction that caused the task switch.
Key takeaways
- All the information the processor needs in order to manage a task is stored in a special type of segment, a task state segment (TSS).
- By allocating the TSS so that it does not cross a page boundary.
- If both pages are not-present, then the page-fault handler must make both pages present before restarting the instruction that caused the task switch.
1. The task state segment, like all other segments, is defined by a descriptor.
2. The B-bit in the type field indicates whether the task is busy. A type code of 9 indicates a non-busy task; a type code of 11 indicates a busy task. Tasks are not re-entrant. The B-bit allows the processor to detect an attempt to switch to a task that is already busy.
3. The BASE, LIMIT, and DPL fields and the G-bit and P-bit have functions similar to their counterparts in data-segment descriptors. The LIMIT field, however, must have a value equal to or greater than 103.
4. An attempt to switch to a task whose TSS descriptor has a limit less that 103 causes an exception. A larger limit is permissible, and a larger limit is required if an I/O permission map is present.
5. A larger limit may also be convenient for systems software if additional data is stored in the same segment as the TSS.
6. A procedure that has access to a TSS descriptor can cause a task switch. In most systems the DPL fields of TSS descriptors should be set to zero, so that only trusted software has the right to perform task switching.
7. Having access to a TSS-descriptor does not give a procedure the right to read or modify a TSS. Reading and modification can be accomplished only with another descriptor that redefines the TSS as a data segment. An attempt to load a TSS descriptor into any of the segment registers (CS, SS, DS, ES, FS, GS) causes an exception.
8. TSS descriptors may reside only in the GDT. An attempt to identify a TSS with a selector that has TI=1 (indicating the current LDT) results in an exception.
Key takeaways
- Having access to a TSS-descriptor does not give a procedure the right to read or modify a TSS. Reading and modification can be accomplished only with another descriptor that redefines the TSS as a data segment.
- An attempt to switch to a task whose TSS descriptor has a limit less that 103 causes an exception. A larger limit is permissible, and a larger limit is required if an I/O permission map is present.
1. The task register (TR) identifies the currently executing task by pointing to the TSS.
2. The task register has both a "visible" portion (i.e., can be read and changed by instructions) and an "invisible" portion (maintained by the processor to correspond to the visible portion; cannot be read by any instruction).
3. The selector in the visible portion selects a TSS descriptor in the GDT. The processor uses the invisible portion to cache the base and limit values from the TSS descriptor.
4. Holding the base and limit in a register makes execution of the task more efficient, because the processor does not need to repeatedly fetch these values from memory when it references the TSS of the current task.
5. The instructions LTR and STR are used to modify and read the visible portion of the task register. Both instructions take one operand, a 16-bit selector located in memory or in a general register.
6. LTR (Load task register) loads the visible portion of the task register with the selector operand, which must select a TSS descriptor in the GDT. LTR also loads the invisible portion with information from the TSS descriptor selected by the operand.
7. LTR is a privileged instruction; it may be executed only when CPL is zero. LTR is generally used during system initialization to give an initial value to the task register; thereafter, the contents of TR are changed by task switch operations.
8. STR (Store task register) stores the visible portion of the task register in a general register or memory word. STR is not privileged.
Key takeaways
- The task register has both a "visible" portion (i.e., can be read and changed by instructions) and an "invisible" portion (maintained by the processor to correspond to the visible portion; cannot be read by any instruction).
- The instructions LTR and STR are used to modify and read the visible portion of the task register. Both instructions take one operand, a 16-bit selector located in memory or in a general register.
1. A task gate descriptor provides an indirect, protected reference to a TSS.
The SELECTOR field of a task gate must refer to a TSS descriptor. The value of the RPL in this selector is not used by the processor.
2. The DPL field of a task gate controls the right to use the descriptor to cause a task switch.
3. A procedure may not select a task gate descriptor unless the maximum of the selector's RPL and the CPL of the procedure is numerically less than or equal to the DPL of the descriptor.
4. This constraint prevents untrusted procedures from causing a task switch. (Note that when a task gate is used, the DPL of the target TSS descriptor is not used for privilege checking.)
5. A procedure that has access to a task gate has the power to cause a task switch, just as a procedure that has access to a TSS descriptor. The 80386 has task gates in addition to TSS descriptors to satisfy three needs:
i) The need for a task to have a single busy bit. Because the busy-bit is stored in the TSS descriptor, each task should have only one such descriptor. There may, however, be several task gates that select the single TSS descriptor.
ii) The need to provide selective access to tasks. Task gates fulfill this need, because they can reside in LDTs and can have a DPL that is different from the TSS descriptor's DPL. A procedure that does not have sufficient privilege to use the TSS descriptor in the GDT (which usually has a DPL of 0) can still switch to another task if it has access to a task gate for that task in its LDT. With task gates, systems software can limit the right to cause task switches to specific tasks.
iii) The need for an interrupt or exception to cause a task switch. Task gates may also reside in the IDT, making it possible for interrupts and exceptions to cause task switching. When interrupt or exception vectors to an IDT entry that contains a task gate, the 80386 switches to the indicated task. Thus, all tasks in the system can benefit from the protection afforded by isolation from interrupt tasks.
Key takeaways
- The SELECTOR field of a task gate must refer to a TSS descriptor. The value of the RPL in this selector is not used by the processor.
- Task gates fulfill this need, because they can reside in LDTs and can have a DPL that is different from the TSS descriptor's DPL.
1. The 80386 switches execution to another task in any of four cases:
(i) The current task executes a JMP or CALL that refers to a TSS descriptor.
(ii) The current task executes a JMP or CALL that refers to a task gate.
(iii) An interrupt or exception vectors to a task gate in the IDT.
(iv) The current task executes an IRET when the NT flag is set.
2. JMP, CALL, IRET, interrupts, and exceptions are all ordinary mechanisms of the 80386 that can be used in circumstances that do not require a task switch. Either the type of descriptor referenced or the NT (nested task) bit in the flag word distinguishes between the standard mechanism and the variant that causes a task switch.
3. To cause a task switch, a JMP or CALL instruction can refer either to a TSS descriptor or to a task gate. The effect is the same in either case: the 80386 switches to the indicated task.
4. An exception or interrupt causes a task switch when it vectors to a task gate in the IDT. If it vectors to an interrupt or trap gate in the IDT, a task switch does not occur.
5. Whether invoked as a task or as a procedure of the interrupted task, an interrupt handler always returns control to the interrupted procedure in the interrupted task. If the NT flag is set, however, the handler is an interrupt task, and the IRET switches back to the interrupted task.
6. A task switching operation involves these steps:
i) Checking that the current task is allowed to switch to the designated task. Data-access privilege rules apply in the case of JMP or CALL instructions. The DPL of the TSS descriptor or task gate must be numerically greater (e.g., lower privilege level) than or equal to the maximum of CPL and the RPL of the gate selector. Exceptions, interrupts, and IRET are permitted to switch tasks regardless of the DPL of the target task gate or TSS descriptor.
ii) Checking that the TSS descriptor of the new task is marked present and has a valid limit. Any errors up to this point occur in the context of the outgoing task. Errors are restartable and can be handled in a way that is transparent to applications procedures.
iii) Saving the state of the current task. The processor finds the base address of the current TSS cached in the task register. It copies the registers into the current TSS (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, ES, CS, SS, DS, FS, GS, and the flag register). The EIP field of the TSS points to the instruction after the one that caused the task switch.
iv) Loading the task register with the selector of the incoming task's TSS descriptor, marking the incoming task's TSS descriptor as busy, and setting the TS (task switched) bit of the MSW. The selector is either the operand of a control transfer instruction or is taken from a task gate.
v) Loading the incoming task's state from its TSS and resuming execution. The registers loaded are the LDT register; the flag register; the general registers EIP, EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI; the segment registers ES, CS, SS, DS, FS, and GS; and PDBR. Any errors detected in this step occur in the context of the incoming task. To an exception handler, it appears that the first instruction of the new task has not yet executed.
7. Note that the state of the outgoing task is always saved when a task switch occurs. If execution of that task is resumed, it starts after the instruction that caused the task switch. The registers are restored to the values they held when the task stopped executing.
8. Every task switch sets the TS (task switched) bit in the MSW (machine status word). The TS flag is useful to systems software when a coprocessor (such as a numeric coprocessor) is present. The TS bit signals that the context of the coprocessor may not correspond to the current 80386 task.
9. Exception handlers that field task-switch exceptions in the incoming task should be cautious about taking any action that might load the selector that caused the exception. Such an action will probably cause another exception, unless the exception handler first examines the selector and fixes any potential problem.
10. The privilege level at which execution resumes in the incoming task is neither restricted nor affected by the privilege level at which the outgoing task was executing. Because the tasks are isolated by their separate address spaces and TSSs and because privilege rules can be used to prevent improper access to a TSS, no privilege rules are needed to constrain the relation between the CPLs of the tasks. The new task begins executing at the privilege level indicated by the RPL of the CS selector value that is loaded from the TSS.
Key takeaways
- JMP, CALL, IRET, interrupts, and exceptions are all ordinary mechanisms of the 80386 that can be used in circumstances that do not require a task switch.
- Because the tasks are isolated by their separate address spaces and TSSs and because privilege rules can be used to prevent improper access to a TSS, no privilege rules are needed to constrain the relation between the CPLs of the tasks.
- An exception or interrupt causes a task switch when it vectors to a task gate in the IDT.
1. The back-link field of the TSS and the NT (nested task) bit of the flag word together allow the 80386 to automatically return to a task that Called another task or was interrupted by another task.
2. When a CALL instruction, an interrupt instruction, an external interrupt, or an exception causes a switch to a new task, the 80386 automatically fills the back-link of the new TSS with the selector of the outgoing task's TSS and, at the same time, sets the NT bit in the new task's flag register.
3. The NT flag indicates whether the back-link field is valid. The new task releases control by executing an IRET instruction. When interpreting an IRET, the 80386 examines the NT flag. If NT is set, the 80386 switches back to the task selected by the back-link field.
3.10.1 Busy Bit Prevents Loops
1. The B-bit (busy bit) of the TSS descriptor ensures the integrity of the back-link. A chain of back-links may grow to any length as interrupt tasks interrupt other interrupt tasks or as called tasks call other tasks.
2. The busy bit ensures that the CPU can detect any attempt to create a loop. A loop would indicate an attempt to reenter a task that is already busy; however, the TSS is not a reentrable resource.
3. The processor uses the busy bit as follows:
i) When switching to a task, the processor automatically sets the busy bit of the new task.
ii) When switching from a task, the processor automatically clears the busy bit of the old task if that task is not to be placed on the back-link chain (i.e., the instruction causing the task switch is JMP or IRET). If the task is placed on the back-link chain, its busy bit remains set.
iii) When switching to a task, the processor signals an exception if the busy bit of the new task is already set.
iv) By these actions, the processor prevents a task from switching to itself or to any task that is on a back-link chain, thereby preventing invalid reentry into a task.
3.10.2 Modifying Task Linkages
1. Any modification of the linkage order of tasks should be accomplished only by software that can be trusted to correctly update the back-link and the busy-bit. Such changes may be needed to resume an interrupted task before the task that interrupted it.
2. Trusted software that removes a task from the back-link chain must follow one of the following policies:
i) First change the back-link field in the TSS of the interrupting task, then clear the busy-bit in the TSS descriptor of the task removed from the list.
ii) Ensure that no interrupts occur between updating the back-link chain and the busy bit.
Key takeaways
- When a CALL instruction, an interrupt instruction, an external interrupt, or an exception causes a switch to a new task, the 80386 automatically fills the back-link of the new TSS with the selector of the outgoing task's TSS and, at the same time, sets the NT bit in the new task's flag register.
- When switching to a task, the processor signals an exception if the busy bit of the new task is already set.
- Any modification of the linkage order of tasks should be accomplished only by software that can be trusted to correctly update the back-link and the busy-bit.
1. The LDT selector and PDBR fields of the TSS give software systems designers flexibility in utilization of segment and page mapping features of the 80386.
2. By appropriate choice of the segment and page mappings for each task, tasks may share address spaces, may have address spaces that are largely distinct from one another, or may have any degree of sharing between these two extremes.
3. The ability for tasks to have distinct address spaces is an important aspect of 80386 protection.
4. A module in one task cannot interfere with a module in another task if the modules do not have access to the same address spaces. The flexible memory management features of the 80386 allow systems designers to assign areas of shared address space to those modules of different tasks that are designed to cooperate with each other.
3.11.1 Task Linear-to-Physical Space Mapping
1. The choices for arranging the linear-to-physical mappings of tasks fall into two general classes:
(i) One linear-to-physical mapping shared among all tasks.
When paging is not enabled, this is the only possibility. Without page tables, all linear addresses map to the same physical addresses.
When paging is enabled, this style of linear-to-physical mapping results from using one page directory for all tasks. The linear space utilized may exceed the physical space available if the operating system also implements page-level virtual memory.
(ii) Several partially overlapping linear-to-physical mappings.
This style is implemented by using a different page directory for each task. Because the PDBR (page directory base register) is loaded from the TSS with each task switch, each task may have a different page directory.
2. In theory, the linear address spaces of different tasks may map to completely distinct physical addresses. If the entries of different page directories point to different page tables and the page tables point to different pages of physical memory, then the tasks do not share any physical addresses.
3. In practice, some portion of the linear address spaces of all tasks must map to the same physical addresses. The task state segments must lie in a common space so that the mapping of TSS addresses does not change while the processor is reading and updating the TSSs during a task switch.
4. The linear space mapped by the GDT should also be mapped to a common physical space; otherwise, the purpose of the GDT is defeated.
3.11.2 Task Logical Address Space
1. By itself, a common linear-to-physical space mapping does not enable sharing of data among tasks. To share data, tasks must also have a common logical-to-linear space mapping; i.e., they must also have access to descriptors that point into a shared linear address space.
2. There are three ways to create common logical-to-physical address-space mappings:
2.1 Via the GDT. All tasks have access to the descriptors in the GDT. If those descriptors point into a linear-address space that is mapped to a common physical-address space for all tasks, then the tasks can share data and instructions.
2.2 By sharing LDTs. Two or more tasks can use the same LDT if the LDT selectors in their TSSs select the same LDT segment. Those LDT-resident descriptors that point into a linear space that is mapped to a common physical space permit the tasks to share physical memory. This method of sharing is more selective than sharing by the GDT; the sharing can be limited to specific tasks. Other tasks in the system may have different LDTs that do not give them access to the shared areas.
2.3 By descriptor aliases in LDTs. It is possible for certain descriptors of different LDTs to point to the same linear address space. If that linear address space is mapped to the same physical space by the page mapping of the tasks involved, these descriptors permit the tasks to share the common space. Such descriptors are commonly called "aliases". This method of sharing is even more selective than the prior two; other descriptors in the LDTs may point to distinct linear addresses or to linear addresses that are not shared.
Key takeaways
- By appropriate choice of the segment and page mappings for each task, tasks may share address spaces, may have address spaces that are largely distinct from one another, or may have any degree of sharing between these two extremes.
- In theory, the linear address spaces of different tasks may map to completely distinct physical addresses
- By sharing LDTs. Two or more tasks can use the same LDT if the LDT selectors in their TSSs select the same LDT segment.
References
1. A.Ray, K.Bhurchandi, ”Advanced Microprocessors and peripherals: Arch, Programming &
Interfacing”, Tata McGraw Hill,2004 ISBN 0-07-463841-6
2. Intel 80386 Programmer's Reference Manual 1986, Intel Corporation, Order no.: 231630-011,
December 1995.
3. James Turley, “Advanced 80386 Programming Techniques”, McGraw-Hill, ISBN: 10:
0078813425, 13: 978-0078813429.