Académique Documents
Professionnel Documents
Culture Documents
1983 will be a year of transition for Intel's catalog program. In order to better serve you, our customers, we are reorganizing many of our catalogs to more completely reflect product groups. In addition to the new product line handbooks listed below, an INTEL PRODUCT GUIDE (Order No. 210846) will be available free of charge in March. This GUIDE will contain a listing of Intel's complete product line along with information on quality/reliability, packaging and ordering, customer training classes and product services. Consult the Intel Literature Guide (no charge, Order No. 210620) for a complete listing of Intel literature. Literature is presently available in other forms for those handbooks that will not be published until later in the year. Write or call the Intel Literature Department, 3065 Bowers Avenue, Santa Clara, CA 95051, (800) 538-1876, or (800) 672-1833 (California only).
HANDBOOKS
Memory Components Handbook (Order No. 210830) Contains all application notes, article reprints, data sheets and other design information on RAMs, DRAMs, EPROMs, E2 PROMs, Bubble Memories. Microcontroller Handbook (Available in May) Contains all application notes, article reprints, data sheets, and other user information on the MCS-48, MCS-51 (8-bit) and the new MCS-96 (16-bit) product families. Military Handbook (Order No. 210461) Contains complete data sheets on all military products. Microprocessor and Peripherals Handbook (Order No. 210844) Contains data sheets on all microprocessors and peripherals. (Individual User Manuals are also available on the 8085, 8086, 8088, 186, 286, etc.) Development Systems Handbook (Available in April) Contains data sheets on development systems and supporting software. OEM Systems Handbook (Available in May) Contains all application notes, article reprints and data sheets for OEM boards and systems. Software Handbook (Available in May) Contains software product overview as well as data sheets for all Intel software. Quality/Reliability Standards Handbook (Available in April)
Intel Corporation makes no warranty for the use of its products and assumes no responsibility for any errors which may appear in this document nor does it make a commitment to update the information contained herein. Intel retains the right to make changes to these specifications at any time, without notice. Contact your local sales office to obtain the latest specifications before placing your order. The following are trademarks of Intel Corporation and may only be used to identify Intel Products:
2 BXp, CREDIT, i, ICE, 1 1CE, ICS, iDBP, iDIS, iLBX, i m , iMMX, Insite, INTEL, intel, Intelevision, Intellec, inteligent Identifier, intelBOS, inteligent Programming, Intellink, iOSp, iPDS, iRMS, iSBC, iSBX, iSDM, iSXM, Library Manager, MCS, Megachassis, Micromainframe, MULTIBUS, Multichannel Plug-A-Bubble, MULTIMODULE, PROMPT, Ripplemode, RMX/80, RUPI, System 2000, and UPI, and the combination of ICE, iCS, iRMX, iSBC, MCS, or UPI and a numerical suffix.
MDS is an ordering code only and is not used as a product name or trademark. MDSE is a registered trademark of Mohawk Data Sciences Corporation. ' MULTIBUS is a patented Intel bus. Additional copies of this manual or other Intel literature may be obtained from: Intel Corporation Literature Department 3065 Bowers Avenue Santa Clara, CA 95051
ii
PREFACE
This book is written for systems designers and operating system designers and programmers who plan to use the Intel iAPX 286 microprocessor in its protected, virtual-address mode. The protected-mode iAPX 286 is designed for multitasking systems: systems that serve many users or that simultaneously run several programs. This book analyzes operating system functions that are appropriate for the iAPX 286 when used in a variety of multitasking applications, including Communications, such as automated PBXs Real-time, such as instrumentation or process control Multi-user, such as time-sharing or office systems
Many of the features of the iAPX 286 are intended for use by an operating system. This book identifies and explains those features and gives examples of how they can be used in an operating system.
AUDIENCE
This book assumes that you have a knowledge of multitasking operating systems at least equivalent to that presented in introductory undergraduate textbooks on the subject. It also assumes that you have had some exposure to the architecture of the iAPX 286 through attending an introductory course or reading introductory literature such as Introduction to the iAPX 286.
RELATED PUBLICATIONS
Intel Literature
The following manuals contain additional information of use to operating-system designers and programmers:
ASM286 Assembly Language Reference Manual, 121924 Component Data Catalog, 210298 iAPX 286 Architecture Extension Kernel (K286) User's Guide, 121961 iAPX 286 Programmer's Reference Manual, 210498 iAPX 286 System Builder User's Guide, 121935 iAPX 286 Utilities User's Guide, 121934 iAPX 286/10 High Performance Microprocessor with Memory Management and Protection (Data Sheet),210253 Introduction to the iAPX 286, 210308 PL/M-286 User's Guide, 121945
iii
121960-001
PREFACE
External Literature
Many aspects of operating system construction for the iAPX 286 are the same as for other processors. The following are sources of generally applicable theories and algorithms referred to in the text of this book. Coffman, E.G., Jr., and Peter J. Denning, Operating Systems Theory (Englewood Cliffs, N.J.: Prentice-Hall,1973) Denning, Peter J., "Virtual Memory," Computing Surveys, Vol. 2, No.3 (September 1970) Knuth, Donald E., Fundamental Algorithms, Vol. 1 (Reading, Mass.: Addison-Wesley, 1973) Peterson, James L., Petri Net Theory and the Modeling of Systems (Englewood Cliffs, N.J.: PrenticeHall, 1981)
RELATED PRODUCTS
Designers interested in operating systems for the protected-mode iAPX 286 should also be aware of Intel's iAPX 286 Architecture Extension Kernel K28. K286 is an operating-system kernel designed for a wide variety of applications, including real-time, communications, business systems, and timesharing. K286 provides Short-term, priority scheduling and management of multiple tasks Interrupt management Multiprocessor support Virtual memory support Data sharing among tasks with synchronization Intertask signals and messages Extended protection
Whether you use K286 "as is," for greatest possible efficiency, or whether you add layers of software to more fully support your applications, K286 can significantly reduce your system development time. Since K286 has been designed by the architects of the iAPX 286 and implemented and tested by Intel's software engineers, using K286 can make your system more reliable. K286 implements many of the concepts discussed in this book, which can therefore give you additional understanding of why and how to use K286.
iv
121960-001
PREFACE
Identifing an operating system function (or class of functions). The functions chosen are those with which you might already be familiar, since they are similar to those used in state-of-the-art operating systems such as iRMX 86 (from Intel Corporation) or UNIX (from Bell Laboratories). Reviewing the iAPX 286 features that support that function. While this portion of each chapter may cover some material available in other Intel literature, it provides added value by discussing in one place all the iAPX 286 features that bear on a given operating system function and by identifying relationships among those features. Outlining some examples of how to use those iAPX 286 features in an implementation of the identified function. It is, of course, impossible to illustrate all the ways to design any given function, but these examples serve to illustrate a few of the ways that the designers of the iAPX 286 architecture intended for it to be applied.
2.
3.
Chapter 1 introduces the iAPX 286 architecture; identifies the role of an operating system in a protected, multitasking environment; and shows how Intel's Binder and Builder utilities aid in the construction of an operating system. You may skip Chapter 1 if you are already familiar with multitasking operating systems and with the Binder and the Builder. Both Chapter 2 and Chapter 5 contain key information about manipulating the protection features of the iAPX 286. Be sure not to omit these chapters when scanning the contents of the book. For the remaining chapters, you may turn directly to the subjects that interest you most. You will find the reading easier, however, if you observe the partial orderings outlined in table 0-1.
NOTATIONAL CONVENTIONS
UPPERCASE
italic system-id
Characters shown in uppercase must be entered in the order shown. You may enter the characters in uppercase or lowercase. Italic indicates a meta symbol that may be replaced with an item that fulfills the rules for that symbol. The actual symbol may be any of the following: Is a generic label placed on sample listings where an operating systemdependent name would actually be printed. Is a generic label placed on sample listings where the version number of the product that produced the listing would actually be printed.
Table 0-1. Prerequisites by Chapter
Target Chapter Prerequisites
Vx.y
6 7
8 9 12
4 6 4, 6 6,7 4,6,7
121960-001
Table of Contents
CHAPTER 1 INTRODUCTION TO PROTECTED MULTITASKING ON THE iAPX 286 Tasks ............................................................................................................ Structure of a Program .............................................................................. Segmented Memory .................................................................................. Multitasking ............................................................................................... Privilege Levels .............................................................................................. Levels of Segments ............................................................... ..................... Rules of Privilege ....................................................................................... Software System Structure ........................................................................... Role of the Operating System ...................................................................... Common O.S. Functions ........................................................................... O.S. Functions in a Dynamic Environment ...... .......... ........ ......................... Constructing the Initial Run-Time Environment ............................................. Building a Static System ............................................................................ Building a Dynamic System .......................................................................
Page
1-1 1-1 1-1 1-1 1-3 1-4 1-4 1-4 1-6 1-7 1-8 1-8 1-9 1-9
CHAPTER 2 USING HARDWARE PROTECTION FEATURES Addressing Mechanism ................................................................................ . Descriptors .................................................................................................... Descriptor Format ..................................................................................... . Control Flow Transfer .................................................................................. . Gate Descriptors .......... ~ ........................................................................... . Control Transfer Mechanisms ................................................................... . Privilege Rules for Gated Intersegment Transfers .................................... . Descriptor Tables .......................................................................................... Local Descriptor Table .............................................................................. . Global Descriptor Table ............................................................................ . Interrupt Descriptor Table ......................................................................... . Selectors ....................................................................................................... Format of Selector .................................................................................... . Null Selector .............................................................................................. Alias Descriptors ........................................................................................... Explicit Variation of Type .......................................................................... . Variation of Length ................................................................................... . Sharing Segments among Tasks .............................................................. . Protection and Integrity with Aliasing ........................................................ . Example of Descriptor Manipulation ............................................................ .. Slot Management ..........................................................................................
VI
2-1 2-2 2-2 2-7 2-8 2-9 2-11 2-12 2-14 2-14 2-15 2-15 2-15 2-17 2-17 2-18 2-18 2-19 2-19 2-20 2-22
121960-001
TABLE OF CONTENTS
CHAPTER 3 REAL MEMORY MANAGEMENT Memory Management Functions .......................... ......................................... Example of a Memory Manager .................................................................... Data Structures ......................................................................................... PL/M-286 Code ......................................................................................... Protection Structure ................................................. .......... .... .... ............... Advanced Memory Management .................................................................. CHAPTER 4 TASK MANAGEMENT Hardware Task-Management Features ...................................... ................... Storing Task State ........... .............................................. ........................... Switching Tasks ........................................................................................ Role of Operating System in Task Management ..... ;..................................... State Model of Task Scheduling ................................................................ Interfacing with the Hardware Scheduler ................................................... Changing Scheduling State ....................................................................... Structuring Task Information ..................................................................... Example of a Dispatcher ............................................................................... CHAPTER 5 DATA SHARING, ALIASING, AND SYNCHRONIZATION Data-Sharing Techniques .............................................................................. Sharing via the GOT .................................................................................. Sharing via Common LOT ......................................................................... Sharing via Aliases .................................................................................... Alias Management ......................................................................................... Alias Database .......... ..... .. .. ........... .. ............................... ....... .......... .. ..... .... Alias Procedures ........................................................................................ Synchronization ............................................................................................. Low-Level Mutual Exclusion ...................................................................... High-Level Mutual Exclusion ...................................................................... Message Passing .......................................................................................... Message-Passing Example ........................................................................ Variations on the Mailbox Theme .............................................................. CHAPTER 6 SIGNALS AND INTERRUPTS Interrupt Features of the iAPX 286 Architecture ........................................... Vectoring ....... ....... .... ... .... .. .. ................................................... ........ ......... .. Enabling and Disabling Interrupts .............................................................. Interrupt Descriptor Table .......................................................................... Interrupt Tasks and Interrupt Procedures ..................................................
vii
Page
5-1 5-1 5-1 5-2 5-3 5-3 5-3 5-4 5-5 5-6 5-10 5-10 5-16
TABLE OF CONTENTS
Page
Operating System Responsibilities ................................................................ Manage lOT ............................................................................................... Switch Scheduling Modes ......................................................................... Manage Interrupt Controller ........................................................................ Provide Task-Level Interrupt Procedures .................................................. Provide Software Signals ..........................................................................
CHAPTER 7 HANDLING EXCEPTION CONDITIONS Fault Mechanism ........... ..................................................................... ........... Fault Recovery .............................................................................................. Locating the Faulting Instruction .......................... ...................... .... ........... Error Code ................................................................................................. Application Interface ...................................................................................... Exception Conditions .................................................................................... Interrupt O-Divide Error .......................................................... ................. Interrupt 1-Single Step ............................................................................ Interrupt 3-Breakpoint ............................................. ................................ Interrupt 4-0verflow ................................................................................ Interrupt 5-Bound Check ........................................................................ Interrupt 6-Undefined Opcode (UO) ........................................ ................. Interrupt 7-Processor Extension Not Available (NM) ............................... Interrupt 8-Double Fault (OF) .................................................................. Interrupt 9-Processor Extension Segment Overrun ................................ Interrupt 10-lnvalidTSS (TS) ........................ ;......................................... Interrupt 11-Segment.Not Present (NP) .... ................. ...... ............. .......... Interrupt 12-Stack Exception (SS) .......................................................... Interrupt 13-General Protection Exception (GP) ...................................... Interrupt 16-Processor Extension Error (MF) ............................... :.......... Interrupt 17-Run-Time Exceptions .......................................................... Restartability Summary .................................................................................
7-1 7-1 7-1 7-2 7-2 7-2 7-3 7-3 7-3 7-3 7-4 7-4 7-4 7-5 7-5 7-5 7-6 7-6 7-7 7-8 7-8 7-8
CHAPTER 8 INPUT / OUTPUT 110 and Protection ......................................................................................... 110 Privilege Level (IOPL) .......................................................................... . Controlling 110 Addresses ........................................................................ . 110 and Memory Management ..................................................................... . Partitioning 110 Functions .............................................................................. Requirements for Parallelism and Synchronization .................................. .. Requirements for Protection ..................................................................... . Implementation Alternatives .......................................................................
viii
121960-001
TABLE OF CONTENTS
CHAPTER 9 VIRTUAL MEMORY Hardware Mechanisms .................................................................................. Accessed Bit ............................................................................................. Present Bit ......................................... ,....... ,........................ ,.. .. .. ... .. .. ... .. .... Software Mechanisms .................................................................... ,............. . Secondary Storage Management .............................................................. Level Zero Support Procedures ................................................................. Swapping Managers .................................................................................. Software Policies .................................. ,................................ ,....... ,... ......... .. Fetch ......................................................................................................... Placement .................................................. ,... ... ..... .............. .... .. .. .. .... ...... .. Replacement ............................................................................................. Thrashing ...................................................................................................... CHAPTER 10 SYSTEM INITIALIZATION Initial State .................................................................................................... Switching to Protected Mode ........................................................................ Initializing for Protected Mode ....................................................................... Interrupt Vector ......................................................................................... Stack ......................................................................................................... Global Descriptor Table ............................................................................. Starting First Task ........................................................................................ . Example of Initialization ................................................................................. Initialization Module ENTP ......................................................................... CHAPTER 11 BINDING AND LOADING Binding Model ................................................................................................ Modules ..................................................................................................... Segmentation ............................................................................................ Interfaces ................................................................................................... Naming ..................................................................................................... . Timing ........................................................................................................ Implementing According to the Model .......................................................... . Source Code ............................................................................................. Compilers ................................................................................................... Binding Utilities ......................................................................................... . Overview of Loading .................................................................................... . Converting a Program into a Task ........................................................... .. iAPX 286 Object Module Format .............................................................. . Flow of Loader .................. ,........................ ,........................................ ,.... . Load-Time Binding ....................................................................................... . Example Loader ............................................................................................
ix
Page
9-1 9-1 9-1 9-2 9-2 9-3 9-4 9-6 9-6 9-6 9-7 9-8
11-1 11-1 11-2 11-2 11-3 11-3 11-3 11-4 11-4 11-5 11-8 11-9 11-10 11-11 11-12 11-12
121960-001
TABLE OF CONTENTS
CHAPTER 12 NUMERICS PROCESSOR EXTENSION iAPX 286/20 Numerics Processing Features ................................................ ESCAPE Instructions ................................................................................. Emulation Mode Flag (EM) ........................................................................ Math Present Flag (MP) ............................................................................. Task Switched Flag (TS) ........................................................................... WAIT Instruction ........................................................................................ Summary ................................................................................................... Initialization ................................................................................................... Task State .................................................................................................... Numerics Exceptions .................................................................................... Interrupt 7-Processor Extension Not Available (NM) ... .... .... ....... ... ... ... .... Interrupt 9-Processor Extension Segment Overrun (MP) ........................ Interrupt 16-Processor Extension Error (MF) .......................................... CHAPTER 13 EXTENDED PROTECTION Extended Type .............................................................................................. Type Extension Code with Descriptor ....................................................... Type Extension Code in Segment ............................................................. Indirect Naming ......................................................................................... Parameter Validation ...................... ....... ... .... ......... .......... ........... ...... ......... .. .. Defensive Use of ARPL ............................................................................. Point-of-Entry Scrutiny .............................................................................. Usage Privilege Level ...... .......................... ................... ...... .... ..... .. .... .... ........ Send Privilege Level ........... ........................... .. ............. .... .......... ... ..... .. ........ . Constructing Shared Objects ............. .... ....... ........ .............. .... ... ........ .. ......... GLOSSARY INDEX LIST OF TABLES
Table Title
Page
12-1 12-1 12-1 12-2 12-2 12-2 12-2 12-2 12-3 12-3 12-3 12-4 12-5
13-1 13-1 13-1 13-2 13-2 13-2 13-3 13-4 13-5 13-5
Page
12-1 13-1
Prerequisites by Chapter ..................................................................... . Categories of Control Flow Transfer ................................................... . Control Transfer Mechanisms ............................................................. . Actions for Combining Segments ........................................................ . Task SWitching Operations ................................................................. . Interrupt Response Time ..................................................................... . Restart Conditions ............................................................................... . Interpretation of MP and EM Flags ...................................................... . Access Checking Instructions ............................................................. .
v
2-7 2-10 3-9 4-3 6-5
7-8
12-3 13-2
121960-001
TABLE OF CONTENTS
LIST OF FIGURES
Figure Title Page
1-6
1-7 1-8
1-9
2-1
2-2
2-3 2-4 2-5 2-6 2-7 2-8 2-9 2-10 2-11 2-12 2-13 2-14 2-15 2-16 2-17
3-1
3-2
3-3
3-4 3-5 3-6 3-7 3-8 3-9
4-1
4-2 4-3
4-4
4-5 4-6
Segregation of Segments by Tasks with Private LDTs ..................... . Global Segments in System .............................................................. . Segment Segregation by Privilege Level within a Task ..................... . A Four-Level Protection Structure ..................................................... . A Two-Level Protection Structure ..................................................... . A One-Level Unprotected Structure .................................................. . Independent Operating-System Tasks .............................................. . Building a Static System ................................................................... . Building a Dynamic System ............................................................... . Abstraction of Addressing Mechanism .............................................. . Data Segment Descriptor . ~ ................................................................ . Executable Segment Descriptor ........................................................ . System Segment Descriptor ............................................................. . Calling a Conforming Segment .......................................................... . Gate Descriptor ................................................................................. . Intralevel Control Transfers ............................................................... . Gated Interlevel Call and Return ........................................................ . Valid and Invalid Interlevel Transfers ................................................. . Format of a Selector ......................................................................... . Aliasing for Debugger ........................................................................ . Aliases for System Tables ................................................................. . Aliases with Differing Limit ................................................................ . Application of Segment Sharing ....................................................... .. Aliases for Segment Sharing ............................................................. . Descriptor Manipulation Example ...................................................... . Available Slot List ............................................................................... . Memory Fragmentation ..................................................................... . Information Hiding in Memory-Management Example ....................... . Example Memory-Management Data Structures ............................... . Using Boundary Tags ........................................................................ . Hiding Boundary Tags ....................................................................... . Example GDT Layout ........................................................................ . Splitting an Available Block of Memory ............................................. . Possibilities for Combining Segments ............................................... . Code for Memory-Management Example .......................................... . Task State Segment and Register .................................................... . Scheduling State Transition Diagram ................................................ . Expanded Scheduling State Transition Diagram ............................... . Changing Scheduling Mode .............................................................. .. Task Information Structure A ............................................................ . Task Information Structure B ............................................................ .
1-9
1-10 1-11
2-1
2-3 2-4 2-5 2-6 2-9 2-11 2-12 2-13 2-16 2-17 2-18
2-19
2-20 2-21 2-23 2-26 3-2 3-3 3-4 3-5 3-6 3-7 3-8 3-11 3-15 4-2 4-5 4-6 4-8 4-11 4-12
xi
121960-001
TABLE OF CONTENTS
Title
Figure
Page
4-7 4-8 4-9 5-1 5-2 5-3 5-4 5-5 5-6 5-7 6-1 6-2 6-3 6-4 7-1 8-1 8-2 8-3 10-1 10-2 10-3 11-1 11-2 11-3 11-4 11-5 11-6 11-7 13-1
Task Information Structure C ........................................................... .. Scheduler Queue Segment ............................................................... . Dispatcher Example .......................................................................... . Segment via Common LOT ............................................................... . Alias List ............................................................................................ . Identifying Alias List .......................................................................... . Semaphore Structure ......................................................................... Semaphore Example .......................................................................... Mailbox Structure .............................................................................. . Example of Mailbox Procedures .............................................. ,......... . Interrupt Vectoring for Tasks ........................................................... .. Interrupt Vectoring for Procedures .................................................... . Interrupt Procedure's Stack .............................................................. . Private Interrupt Procedure ............................................................... . Exception Error Code ........................................................................ . Petri Net Graph Symbols ................................................................... . Synchronization with Simple Device Driver ....................................... . Synchronization with Two-Part Device Driver .................................. .. Initialization Module ENTP ................................................................. . Dummy Segments for ENTP ............................................................. . Initial Task INIT ................................................................................. . Subsystem for Kernel Exports .......................................................... . Binder Specifications for XOS Kernel ................................................ . Builder Specifications for XOS .......................................................... . Specifying Dummy Gate Exports ...................................................... . Strategy for Load-Time Binding ........................................................ . Binding Loader .................................................................................. . BOND Module of Binding Loader ...................................................... . Caller's CPL .......... ; ........................................................................... .
4-13 4-14 4-15 5-2 5-4 5-5 5-6 5-8 5-11 5-13 6-3 6-3 6-4
6-8
7-2 8-5
8-6 8-6
10-4 10-14 10-15 11-5 11-6 11-7 11-13 11-14 11-15 11-24 13-3
xii
121960-001
TASKS
A task is the execution of a sequence of steps. A program is a logical entity that can have many representations: for example, source code file or object program file. A program becomes a task when it is actually available for execution. This is achieved by converting source (with a compiler and program loader, for example) to a representation suitable for execution and notifying the operating system that the task is ready for installation and execution. The distinction between programs and tasks is most clear in a multitasking system, where it is possible for two or more tasks to use one program simultaneously. The line editor program in a timesharing system is a common example. Even though each line editor task uses the same program, each task produces different results, since it receives different inputs.
Structure of a Program
Each program is formed from modules created by language translators and bound together into a single executable unit. The translators (for example, ASM286, PL/M-286, Pascal-286, and FORTRAN-286) and the object program utilities (for example, Intel's Builder and Binder) support the concept of logical segments. A logical segment is a contiguous block of either instructions or data. Each logical segment can contain up to 64K bytes of code or data. Logical segments are the units that may be combined when a program comprises more than one module.
Segmented Memory
The iAPX 286 structures the address space of a task into physical segments of variable length. A physical segment is a contiguous block of memory that does not (normally) overlap another physical , segment. Each physical segment may contain up to 64K bytes of either instructions or data. Each physical segment contains one or more logical segments of a task. The segments reflect how tasks are organized into code, data, and stack areas.
Multitasking
One of the most important features of the iAPX 286 is its ability to switch rapidly from executing one task to executing another task. This gives the appearance that the processor is executing more than one task at a time.
1-1
121960-001
Hardware system tables enable both the hardware and the operating system to distinguish between the physical segments of individual tasks. Figure 1-1 shows how physical segments of one task are logically separate from those of other tasks. Since references to physical segments are always relative to system descriptor tables, the actual locations of physical segments in physical memory are not significant to the tasks and therefore are not illustrated. Descriptor tables serve not only to identify the segments that belong to a task but also to isolate the address space of one task from that of another, so that one task cannot inadvertently affect the operations of another. Multitasking works through close interaction of the operating system with hardware features. When the executing task needs to wait for some event (such as the arrival of data from some I/O device), it notifies the operating system. The operating system determines which other task should execute next, and then causes the processor to store the state of the current task, retrieve the state of the next task, and begin executing the next task at the point where its processing last halted. The processor then executes that task until the task needs to wait for some event. (This is a somewhat oversimplified
TASK 0 MULTIPLAN
TASK C AEDIT'"
121960-40
1-2
121960-001
description of what can be a complex operating system function. Chapter 4 covers the subject of task switching in more detail.) Figure 1-2 illustrates how the global descriptor table defines an address space that is accessible to all tasks in the system. This global space is useful for translation tables, run-time libraries, operatingsystem code and data, and the like.
PRIVILEGE LEVELS
The iAPX 286 architecture uses the concept of privilege levels to protect critical procedures within a task from less trusted procedures in the same task. For example, with previous generations of microprocessors, applications code could access and possibly destroy tables used by the operating system. An error of this sort could cause the operating system to incorrectly service a subsequent request from another unrelated task. With the iAPX 286, such situations are prevented by hardware-enforced barriers between different levels of procedures.
GLOBAL SPACE
LOCAL SPACES
121960-58
1-3
121960-001
Applied to procedures, privilege level is a measure of the degree to which you trust a procedure not to make a mistake that might affect other procedures or data. Applied to data, privilege level is a measure of the protection you think a data structure should have from less trusted procedures. Privilege level also applies to instructions. Certain instructions (those that deal with system tables, interrupts, and I/O, for example) have such an effect on the system as a whole that only highly trusted procedures should have the right to use them.
Levels of Segments
With regard to privilege, you can view the segments of a task as being grouped into four levels. Level zero is for the most privileged procedures and the most private data; level three is for the least trusted procedures and the most public data. You (or your operating system) associate each segment of each task with one of these four levels of privilege. The privilege level of a segment applies to all the procedures or all the data in that segment. Figure 1-3 illustrates the logical segregation of segments into privilege levels. (Later chapters explain why operating-system segments are included within the task.)
PRIVILEGE LEVEL
PRIVILEGE LEVEL 1
PRIVILEGE LEVEL
2
LOT PL=O PL=O PL=O PL=1 PL=1 PL=1 PL=1 PL=2 PL=2 PL=2 PL=2 PL=2 PL=3 PL=3 PL=3 PL=3 PL=3 PL=3 PL=3
PRIVILEGE LEVEL 3
} }
>121960-41
1-4
121960-001
Rules of Privilege
The 80286 processor controls access to both data and procedures between levels of a task. These rules define access rights: Data can be accessed only from the same or a more privileged level. A procedure can be called only from the same level (or from a less privileged level, if the service is deliberately "exported" to that level. Refer to gates in Chapter 2.).
Some advantages of distributing operating-system functions are The communication between application and operating system is faster. It may be possible for all tasks to execute the same operation-system function in parallel. (You must ensure reentrancy and provide for synchronization, however.)
Figures 1-4 through 1-7 illustrate some general approaches that you may consider. The approach shown in figure 1-4 takes maximum advantage of the four privilege levels. The critical procedures and data of the operating system kernel (for example, memory allocation tables and procedures, information about tasks) are protected from all other procedures in the system. Those parts of the operating system that are less reliable, either due to inherent complexity (for example, the I/O subsystem) or due to occasional changes (for example, policies designed to increase overall throughput), are at a lower level but are still protected from application levels. Application logic has two levels so that application services (such as database management) can be protected from less trusted application code, yet application services cannot affect the integrity of the operating system. Operatingsystem procedures and application services are shared among all the tasks in the system. Figure 1-5 illustrates that you do not need to use all four privilege levels. You may prefer this two-level approach if you are converting from a traditional multitasking system that offers protection only between the two levels defined by application and operating system. The iAPX 286 can also emulate one-level systems, as illustrated in figure 1-6. This approach may be useful in the initial stages of converting from an unprotected system, but it does not take advantage of many of the protection features offered by the iAPX 286. It does isolate tasks from one another, but it does not protect the operating system from applications software. Some operating system functions are better structured as independent operating-system tasks, not as privileged procedures within a task. Certain I/O functions are suited to this treatment. Because of the complexity of I/O code, the extra protection offered by a task boundary contributes to the reliability
1-5
121960-001
GLOBAL SPACE
D~~~~:~ING
TASK B
APPLICATION
121960-43
of the system. Because many I/O functions involve waiting for responses from I/O devices, it is most convenient to treat these functions as a separate task that can run asynchronously with respect to the tasks that invoke them. Figure 1-7 illustrates a structure with independent operating-system tasks.
1-6
121960-001
GLOBAL SPACE
D D
OPERATING SYSTEM
TASK
B
APPLICATION
121960-44
executing over a period of time. Applications in which tasks frequently begin and end (for example, time-sharing systems or multi-user business systems) are called dynamic systems. Applications in which the mix of tasks does not change (for example, process control systems in which tasks service a fixed number of sensors and effectors) are called static systems.
1-7
121960-001
inter
GLOBAL SPACE
~ ~
APPLICATION DATA
121960-45
1-8
121960-001
OPERATING-SYSTEM TASKS
121960-1
1-9
121960-001
Figure 1-9 illustrates the process of constructing a dynamic system. The Builder creates a loadable module containing those operating-system functions that permanently reside in the running operating system, and it also creates a file that contains information about linking to operating-system primitives. Either a static linker (such as Intel's Binder) or a dynamically linking loader can use this information to help dynamically loaded tasks use operating-system functions.
OPERATING SYSTEM AND APPLICATION MODULES (FROM ASM286, PLlM-286, PASCAL 286, FORTRAN 286, BND286)
DEVICE DRIVER
O.S.
r=LOAOABLE~
" - CODE .,;
BOOTLOADER
.--.
121960-4
1-10
121960-001
MEMORY IMAGE
BUILDER
' -_ _- . . I
APPLICATION MODULES
121960-5
1-11
121960-001
ADDRESSING MECHANISM
The protection mechanism of the iAPX 286 is embedded in the addressing mechanism. For an introduction to the addressing mechanism, refer to figure 2-1, which shows those portions of the addressing mechanism that are not concerned with protection features. From the point of view of the applications programmer, an address is a pointer. A pointer consists of two parts: a selector and an offset. The
PHYSICAL MEMORY
~---------------------------------~
-------,
I I I I I I I I I
DESCRIPTOR TABLE
L __________________
I I
I L _________________________________ I
121960-6
2-1
121960-001
se1ector portion identifies a segment of the address space and the offset addresses an item within the segment relative to the beginning of the segment. A selector identifies a segment by reference to a descriptor table. Each entry in a descriptor table is a descriptor. A selector contains an index that identifies a particular descriptor in a particular descriptor table. The descriptor contains the physical address and access rights of the segment. Both selectors and descriptors contain additional information that relates to the protection features of the iAPX 286.
DESCRIPTORS
A reference from one segment to another is realized indirectly through a descriptor, which contains information about the referenced segment. All descriptors reside in a descriptor table. Every segment must have at least one descriptor; otherwise there is no means to address the segment. Descriptors are strictly under your control via the Builder or operating system procedures. The existence and function of descriptors is completely invisible to the applications programmer.
Descriptor Format
There are four variations in descriptor format, corresponding to the four classes of descriptor: 1. 2. 3. 4. Data segment descriptors refer only to segments that contain system or application data, including stacks (see figure 2-2). Executable segment descriptors refer only to segments that contain executable instructions (see figure 2-3). System segment descriptors refer only to segments that contain special hardware-recognized data. structures, such as descriptor tables (see figure 2-4). Gate descriptors define entry points for control transfers. A gate descriptor does not directly address a memory segment; instead it provides a. protected pointer to an exported entry point. (Refer to the section "Gate Descriptors" later in this chapter.)
The first two types of descriptor hold information that any operating system must maintain. The iAPX 286, however, requires that such information be in a fixed format so the CPU can interpret it directly. These descriptors are often created dynamically while a program executes (for example, a data-segment descriptor may be created when a task needs additional memory to store an expanding data structure). The second two types of descriptor are unique to the iAPX 286. They are constructed either once when the system is built or once when a task is created. Code to manipulate these descriptors is limited to the procedures of a dynamic operating system that create new tasks. Several of the descriptor formats have common fields. These fields are listed first in the following discussions of descriptor contents.
PRESENT BIT
This Boolean is set if the segment addressed by the descriptor is actually present in memory, reset if not present. Operating systems for dynamic applications that implement virtual memory must set and
2-2
121960-001
o
+6
,
1
0
ED W A
DPL
BASE2J.16
+4
_I
BASE 15-0
+2
LIMIT
P DPL ED W A
121960-46
reset this bit as program segments are brought into or eliminated from memory. Reference to a segment whose present bit is reset causes a fault, providing an opportunity for the operating system to load the segment from virtual store. (Chapter 9 takes up implementation of virtual memory systems.) In systems that do not implement virtual memory, this bit is always set for allocated segments.
The value of this item defines the privilege level of the segment addressed by this descriptor. You control the values in the descriptor privilege level (DPL) by the parameters you give to the builder when creating a static system or the resident portion of a dynamic system, or by the procedures your operating system uses when loading segments dynamically.
INTEL RESERVED
This portion of the descriptor is reserved by Intel and should always be initialized with zeros. Other use of this field in a valid descriptor will prevent compatability with the iAPX 386 and other additions to Intel's family of processors.
2-3
121960-001
o
I
o
+6
DPL
BASE 23_16
+4
BASE l5-0
+2
LIMIT
P DPL C R A
121960-47
SEGMENT BASE
This field contains the physical address of the beginning of the memory segment referred to by this descriptor. The 24 bits of this address give the 80286 a 16-megabyte range of real addresses. This is the only place that physical addresses are used. All other addresses are relative to the physical addresses stored in descriptors, making it possible to relocate executable and data segments without making any changes to the relocated segments or to code that refers to the segments. The only changes necessary to relocate segments are changes to the physical addresses stored in descriptor tables. You can control the actual location of segments by means of specifications to the Builder or by means of the algorithms your operating system uses to allocate memory to segments that are loaded dynamically.
SEGMENT LIMIT
Segment limits prevent accidental reading or writing beyond the space allocated to a segment. The value of this field is one less than the length of the segment (in bytes) relative to the beginning of the segment. The 16 bits of this field make it possible to have segments up to 64K bytes long. The hardware automatically checks all addressing operations to ensure that they do not exceed the segment limit of the segment to which they refer. This protects other segments from such common programming errors as runaway subscripts.
2-4
121960-001
o
+6
DPL
TYPE
BASE23'16
+4
BASE,5_0
+2
LIMIT
121960-48
Note that the segment limit field has a different meaning for "expand down" data segments. Refer to the "expansion direction" bit later in this chapter.
SEGMENT TYPE
For system segments, the type field distinguishes between kinds of system segments. System segment types are 1 and 3 Task state segment, a segment used for storing the context of a task. Chapter 4 discusses task state segments more fully. Local descriptor table. The three kinds of descriptor tables are explained later in this chapter.
The processor interprets the type field to ensure that each segment is actually used as intended; for example, an attempt to jump to a local descriptor table is obviously a mistake, and the processor detects this error while examining the target segment's descriptor during the JMP instruction.
EXPANSION DIRECTION
Data segments may contain stacks as well as other data structures. Stacks expand toward lower addresses while most other data structures expand toward greater (higher) addresses. This field indicates the growth pattern for the segment. A value of zero in this field indicates that the segment expands upward
2-5
121960-001
(from the base address toward the segment limit value that is also contained in the descriptor). A value of one indicates that the segment expands downward (from offset FFFFH toward the limit).
WRITABLE
This field applies only to data segment descriptors. A value of one permits the CPU to write into the segment; a value of zero protects the segment from attempts to write into it. Translation tables are but one example of data that deserve the extra protection afforded by storage in a read-only segment.
CONFORMING
This field applies to executable-segment descriptors only. Ordinarily (when the conforming bit is zero) a called procedure executes at the privilege level defined by the DPL in the descriptor of the segment in which the procedure resides. When the conforming bit of the called segment is set, however, the called procedure executes at the calling procedure's privilege level. This feature cannot be used to decrease (numerically) a segment's privilege level below that defined by it's DPL. Figure 2-5 shows graphically how a conforming segment works. This feature is useful when you want to make procedures (mathematical subroutines or run-time support procedures, for example) available to a number of other procedures running at different privilege levels, but when you do not want to provide increased privilege while the subroutine is executing.
121960-7
2-6
121960-001
READABLE
This field applies only to executable-segment descriptors. When reset, it prevents procedures in other. segments from reading this code segment; the contents of the segment can be executed only. It is common, however, for executable segments to contain read-only data, in which case this bit must be set.
ACCESSED
The processor sets this bit when the descriptor is accessed (that is, loaded into a segment register or used by a selector test instruction). Operating systems that implement virtual memory may, by periodically testing and resetting this bit, monitor frequency of segment usage. This bit also indicates whether a segment should be written to secondary storage before the RAM space it occupies is reused.
Intertask
different
2-7
121960-001
Control transfers within the same privilege level may be either short (within same segment) or long (to another segment). A short transfer simply specifies the offset of the instruction to which control is transferred in the same segment. A long transfer also uses a selector to identify the segment to which control is transferred. For control transfer to a different privilege level or different task, the iAPX 286 introduces gate descriptors.
Gate Descriptors
A gate descriptor is a type of descriptor used only for transferring control flow to instructions in another segment. Gates provide an indirect reference that is useful for binding and protection purposes. By requiring interlevel and intertask control transfers to reference gate descriptors, the iAPX 286 provides two additional protection features:
1.
You can hide a procedure by not providing a gate for its entry point. You can control access to a procedure via the privilege assigned to the gate. This allows hiding critical procedures from untrusted software.
2.
For call, interrupt, and trap gates, this field contains a selector for the segment descriptor of the destination executable segment. For task gates, the selector in this field points to a descriptor for a task state segment, and the RPL field is not used.
DESTINATION OFFSET
For call, interrupt, and trap gates, this field contains the offset of the entry point within the destination executable segment (not used with task gates).
WORD COUNT
For each privilege level within a task, there is a separate stack. For calls through a call gate, the processor automatically copies parameters from the stack for the calling procedure's privilege level to the stack for the destination's privilege level. In this field, you specify the number of words to copy.
GATE TYPE
For gate descriptors, the type field distinguishes among the four kinds of gates:
Call gate
2-8
121960-001
o
+6
DPL
TYPE
+4
.
DESTINATION SELECTOR X X
+2
XX -
NOT USED
121960-49
PRESENT BIT
Since a gate descriptor does not refer directly to a segment, the present bit in a gate descriptor does not necessarily indicate whether a segment is present. It can be used for other purposes, however. Refer to Chapter 11 for an example of using the present bit to facilitate late binding_
2-9
121960-001
inter
Transfer Type Intrasegment Intersegment (*)
INT instruction, external interrupt, or exception Interlevel CALL INT instruction, external interrupt, or exception RET,IRET Intertask CALL, JMP, IRET
lOT
GOT/lOT lOT
GOT/lOT GOT
GOT/LOT lOT
* Includes cases in which the target segment is incidentally the same as the calling segment.
JMP instruction may also reference a call gate. If the target executable segment is at the same privilege level, no level change occurs. For transfers of control between segments at different privilege levels (as illustrated in figure 2-8) there are three differences: Only the following instructions cali be used:
2-10
121960-001
EXECUTABLE SEGMENT
-GATE
INTRASEGMENT
INTERSEGMENT
1219608
A transfer is valid only if the following relationships among privilege level numbers both hold: MAX (CPL, RPL) < = gate DPL target DPL < = CPL Figure 2-9 illustrates both valid and invalid attempts to perform an interlevel transfer. Path E4,G5,E7 is not valid because the privilege level of gate G5 is numerically less than that of segment E4. Path E4,E8 is not valid because all interlevel transfers must pass through a gate. Path E4,G4,E6 is not valid because the privilege level of E6 is numerically greater than that of G4. Only paths El ,G2,E2; El,G 1,E3; and E2,G 1,E3 satisfy the privilege rule above.
2-11
121960-001
o-
EXECUTABLE SEGMENT
-GATE
121960-9
DESCRIPTOR TABLES
A descriptor table is simply a segment containing an array of eight-byte entries, where each entry is a descriptor. Descriptors are stored in one of three classes of descriptor table: Local descriptor table (LDT) Global descriptor table (GDT) Interrupt descriptor table (IDT) The descriptors in these tables define all the segments in the system. Each table has a variable upper limit, so the size of the table need be no larger than required for the actual number of segments used. You define the initial contents of descriptor tables through the Builder. An operating system for dynamic applications may change the contents of descriptor tables and may create and delete LDT's as tasks come and go. Correct management of descriptors is the heart of protection on the iAPX 286.
2-12
121960-001
r-"'f1 L.::..J
EXECUTABLE SEGMENT
-GATE INVALID
121960-10
2-13
121960-001
The executable segment and data segment descriptors in an LOT normally refer to segments private to a task. Call gates and task gates in an LDT provide private entry points to other procedures and programs. The processor uses a task's LOT automatically for certain addressing operations. The base address and limit of the LOT segment of the executing task are kept in the LOT register. Only two operations are available to programmatically change the contents of the LDT register: During a task switch operation, the processor loads the LOT register from the task state segment (TSS). The LLOT instruction loads the LOT register directly. The LLDT instruction can be executed only at privilege level 0 (PL 0). Initialization procedures use LLDT to give the LDT register its initial value. Note that if you change the LOT register you must also change the LOT selector in the TSS (refer to Chapter 4). An operating system may need to change the LOT register temporarily to gain access to the address space of another task when passing information between tasks.
You can use the SLOT instruction to read the contents of the LOT register. Operating-system procedures that operate on LDTs may usually be called from any task. These procedures may use the SLDT . instruction to find which LOT belongs to the current task. In PL/M-286, the built-in variable LOCAL$TABLE gives access to the LDT register. An LDT may contain up to 8,192 descriptors (the number of 8-byte descriptors that fit into a maximumsized segment of 65,536 bytes).
2-14
121960-001
Since the GOT is shared among all tasks, its entries are usually protected. The privilege-level field in each descriptor provides this function. When operating-system functions are distributed among and shared by all tasks, the executable segments and data segments of the operating system are normally kept in the GOT. Call gates then provide controlled access to privileged operating system functions. The processor uses the GOT automatically for certain addressing operations. The base address and limit of the GOT are kept in the processor's GOT register. Only the LGOT instruction (RESTORE$GLOBAL$TABLE in PL/M-286) can alter the contents of the GOT register, and the LGOT instruction can be executed only at PL 0 (i.e., by the operating system) . . The SGOT instruction (SAVE$GLOBAL$TABLE in PL/M-286) reads the contents of the GOT register. A GOT may contain up to 8,191 descriptors (the number of 8-byte descriptors that fit into a maximumsized segment of 65,536 bytes). The first entry cannot be used as a descriptor. (A null selector is identified by the fact that it refers to this first entry in the GDT.)
In a manner similar to executable segment and data segment descriptors, each gate descriptor has a descriptor privilege level. The OPL of a descriptor in the lOT determines the privilege required to execute an INT n instruction (where n is the interrupt indentifier that corresponds to the descriptor). This use of privilege levels prevents unauthorized programs from invoking interrupt handlers. The processor locates the lOT by way of the lOT register. The lOT register can be changed only by the LIOT (load lOT) instruction (RESTORE$INTERRUPT$TABLE in PL/M-286). Only PL-O procedures (i.e., the operating system) can execute an LIOT instruction. The SlOT instruction (SA VE$INTERRUPT$TABLE in PL/M-286) reads the contents of the lOT register. Refer to Chapters 6 and 7 for more detailed information on how the lOT is used.
SELECTORS
A selector references a segment indirectly by identifying the location in a descriptor table where a descriptor for that segment is stored.
Format of Selector
See figure 2-10 for the format of a selector.
2-15
121960-001
inter
15
:~E~ : : : : :
TI RPL TABLE INDICATOR REQUESTED PRIVILEGE LEVEL
IT'I
":L
121960-50
INDEX
The index field of a selector specifies a descriptor in either the GOT or the task's LOT. The index field may take on values from 0 through n-l, where n is the number of descriptors in the table. The processor compares the index with the limit of the descriptor table to ensure that the index refers to a defined descriptor.
TABLE INDICATOR
This bit item tells which descriptor table is indexed by the selector. A value of zero specifies the GOT; one specifies the LOT. (The lOT cannot be referenced via a selector; only via an interrupt identifier.)
Selector privilege is specified in the RPL field of a selector. Selector RPL may establish a less trusted privilege level than the current privilege level for the use of that selector. RPL cannot effect an increase in privilege. A task's effective privilege level is the numeric maximum of the RPL and the current privilege level. For example, if a task is executing at PL = 2, an RPL = 3 reduces the task's effective privilege to level 3 for access to that segment. On the other hand, if RPL = 1, the task's effective privilege level remains at 2. RPL is generally used by an operating system to ensure that selector parameters passed to the more privileged levels of the operating system do not give access to data at a level more privileged than the calling procedure. The RPL field is a convenient place to store the privilege level of the procedure that originated the selector. Any use of the selector can be restricted to the usage allowed its originator. The ARPL instruction (AOJUST$RPL built-in function in PL/M-286) allows the operating system to set the RPL of a selector either to CPL or to the privilege level of the originator, whichever is (numerically) larger. Refer to Chapter 13 for more information on the use of RPL.
2-16
121960-001
inter
Null Selector
A selector that has a value of zero in both the index and table indicator fields (i.e., appears to point to the first entry of the G DT) is a null selector. You .can load such a selector into the DS or ES register, but any attempt to reference memory via that register causes an exception condition.
ALIAS DESCRIPTORS
The need arises in dynamic applications for the operating system to maintain more than one descriptor for a segment; however, care must be taken to preserve system integrity and protection. As an example of the need for an alternate descriptor, consider the case of an executable segment. Ordinarily, the processor fetches instructions from an executable segment that is typed execute-only. However, if the operating system supports a debugger, the debugger needs to read the executable segment in order to display its contents. The debugger may also need to write to the executable segment in order to set breakpoints. If the debugger tries to use an execute-only segment descriptor to read from or write to the segment, the processor detects a protection exception. To properly use that segment, the debugger must use another descriptor that identifies the segment as a data segment. Figure 2-11 illustrates this situation. The use of more than one descriptor for a segment is known as aliasing. Descriptors used in this way are known as aliases, because they provide alternate names for segments.
/1
APPLICATION LOT EXECUTE ONLY CODE SEGMENT
/
o.s.
DEBUGGER LOT DATA SEGMENT
\
(
INSTRUCTIONS
/
121960-11
2-17
121960-001
Variation of Length
As illustratt~d in figure 2-13, aliases for a segment need not always have the same length. In the case shown, the processor's use of a descriptor to a TSS requires only that the segment contain 44 bytes. However, the operating system maintains another descriptor that includes additional information about the task.
GDT
IDT
e(
le(
e(
!;t
c
121960-12
2-18
121960-001
TASK PARAMETERS
4--
TASK PRIORITY SCHEDULING PARAMETERS MESSAGE QUEUE POINTERS RESOURCE POOL POINTERS
GOT
TSS ETC.
ALIAS TSS
TSS DESC.
121960-13
No other tasks have access to the display buffer. (Putting its descriptor in the GDT makes it available to all other tasks.) Other segments in each of the tasks remain protected from the other task. (With a shared LDT, all segments of each task are accessible from the other.)
2-19
121960-001
inl:el~
FLUID-LEVEL SENSORS
TEMPERATURE SENSORS
~~[I~lI~~
LT EE VM EP L LT EE VM EP L LT EE VM EP L LT EE VM EP L LT EE VM EP L VIDEO DISPLAY
n
D
E TASK B
121960-14
When you use an alias to provide an alternate type for a system segment (to write to an LDT), any procedure that has access to that alias also has unlimited power to affect the entire system. Therefore, in constructing an operating system that uses such aliases, you must restrict them to the highest privilege levels of the operating system; that is, the DPL of such aliases should always be zero.
When you design a dynamic system that uses aliases for segment sharing, you must consider what will happen when there is any change in a segment to which aliases are pointing. For example, when a segment is relocated, all descriptors pointing to the relocated segment must be updated. When a segment is deleted, all aliases to it must be nullified. Chapter 5 presents a strategy for handling these changes.
2-20
121960-001
121960-15
NULLIFY invalidates a descriptor by writing a value of 80H in the access rights byte. A value of 80H is invalid because it indicates a system segment of type zero, but no type zero is defined for system segments. POINT_AT purposely loads the access rights byte of the descriptor last, to ensure that an accidental use of the descriptor (as might occur if an external interrupt gives control to another procedure or task) does not find partially complete information in a descriptor that otherwise looks valid. These procedures do no checking of the privilege level of the calling procedure, and they freely create descriptors of any type (except gate descriptors) and any DPL. Therefore, they are suitable for use only at PL O. As long as no gates for these procedures are provided at another privilege level, they can be called only by other PL-O procedures. For an example of how you might use such procedures, refer to the example of a memory manager in Chapter 3. When writing code to manipulate descriptors, you must be careful about changing a descriptor that is currently loaded in either of the processor's data-segment registers (DS or ES). Either disable interrupts or move zero to the register before changing the descriptor, for example:
MOV DS,O
Failure to do this leaves open the possibility that an external interrupt may cause the processor to reload the segment register using the partially modified descriptor. When coding in PL/M-286, use the compiler's CODE option to view the way the generated code handles the DS and ES registers. This situation does not arise in the present example. DS points to the data segment that contains the sole
2-21
121960-001
global data item GDT~SEL. PL/M-286 uses ES for all the BASED variables used here. Referencing the descriptor table via its alias selector causes PL/M-286 to load ES with the alias descriptor, thereby ensuring that ES does not contain the descriptor to be modified.
Remember that once a descriptor has been modified, it cannot be used to access a segment until it is loaded into a segment register.
Be aware also that in a multitasking system, changes to shared segments (such as the GDT) must be synchronized. Synchronization is the. subject of Chapter 5. This example does not provide for synchroniza tion.
SLOT MANAGEMENT
The previous example assumes that the caller of POINT_AT already knows what descriptor-table slot to use. Often, slots can be reserved in advance for specific operating system and applications functions. But in general, dynamic systems require that the operating system dynamically allocate descriptor table slots.
Figure 2-17 illustrates a way of identifying available slots in a descriptor table. A value of zero in the access rights byte is invalid for any descriptor, so it can mark a free slot. A value of 80H (as used in the previous example) is also invalid and can mark a reserved but unused slot.
In larger systems, the time needed to search a descriptor table linearly for free slots may become excessive. Shorter search times may result from linking available slots together in a manner similar to that shown in figure 2-17. Contiguous free slots are treated as a block, with a count of the number of slots in the first and last slots of the block. (Note that the block size is stored in the reserved word of available descriptor slots. Since available descriptor slots contain an invalid type code, this use of the reserved word does not prevent upward compatibility.) All the free blocks are linked in a circular, twoway list that includes the list header. The list header can reside at a fixed slot location that is the same in all descriptor tables (in the case of figure 2-17 the list header is at slot number one). Algorithms normally used for managing memory space may also apply to blocks of' free descriptors. Refer to Chapter 3 for an example of such an algorithm.
It is convenient for the operating system to use adjacent descriptor slots for related purposes; for example, . by locating together all the descriptors that the operating system uses for one task, the operating system can quickly find any of those descriptors as long as it knows the location of one. Therefore, the algorithm used for slot management should combine adjacent free slots into a single block. The procedures used to manage free slots should then have a parameter that specifies the number of adjacent slots.
2-22
121960-001
PL/M-286 COMPILER
96(3-505
date
PAGE
system-ID PL/M-286 Vx.y COMPILATION OF MODULE POINT OBJECT MODULE PLACED IN :Fl:POINT.OBJ COMPILER INVOKED BY: PLM286.86 :Fl:POINT.PLM
INCLUDE
(:Fl:NUCSUB.PLM)
POINT:
DO;
DECLARE DESC_STR LITERALLY 'LIMIT WORD, LO BASE WORD, /* Format of a descriptor. */ HI-BASE BYTE, BYTE, RIGHTS SW RESRVD WORD' ; DECLARE DT SIZE GDTA SEL GDTA-WSEL INITIAL GOT LITERALLY '200', SELECTOR, /* Points to GOT alias */ WORD AT (@GDTA SEL) (8), /* Slot #1 by convention */ BASED GDTA SEL (OT SIZE) STRUCTURE (DESC_STR);
/*******************************************************/ /* Subroutine to determine either the alias for */ /* the GOT or the alias for this task's LOT, */ /* depending on the TI bit in SEL. */
4
5 6 1
FIND DT ALIAS: PROCEDURE (SEL) SELECTOR PUBLIC REENTRANT; DECLARE SEL WSEL DECLARE LOT SEL LDT-WSEL SELECTOR, WORD AT (@SEL); SELECTOR, WORD AT (@LDT_SEL);
2 2
2 2 3 3
IF (WSEL AND 0004H)=0 THEN /* It's a selector to the GOT. */ RETURN GDTA_SEL; ELSE DO; /* It's a selector to this task's LOT. */ LOT SEL=LOCAL$TABLE; /* PL/M 286 built-in; stores a selector to the GOT descriptor for this task's LOT. */ LOT WSEL=LDT WSEL+8; /* Add 1 to index field. */ /* By convention, next slot holds alias. */ RETURN LDT_SEL; END; END FIND_DT_ALIAS; $ EJECT
10
11
12
13
3 3
2
14
2-23
121960-001
PL/M-286 COMPILER
960-505
date
PAGE
/*******************************************************/ /* Create a descriptor at a given slot to a given */ /* segment, and return selector that points */ /* to that slot. */
15
16
POINT AT:
DECLARE SLOT SELECTOR, SLOTW WORD AT (@SLOT), /* Alternate type */ RIGHTS BYTE, PHYS ADDR PTR POINTER, PHYS-ADDR- BASED PHYS ADDR PTR STRUCTURE (LO-WORD WORD, -HI-WORD WORD) , LIMIT WORD; DECLARE SLOT I DTA SEL DT WORD, /* Slot index */ SELECTOR, /* To be set to either GDT alias or LDT alias. */ BASED DTA SEL (DT SIZE) STRUCTURE-(DESC_STR);
17
18 19 20 21 22 23
24
25 26
2 2 2 2 2 2 2 2 2
DTA SEL = FIND DT ALIAS(SLOT); SLOTI = SHR(SLOTW73); /* Expose index value. */ DT(SLOTI) .LO BASE PHYS ADDR.LO WORD; DT(SLOTI) .HI-BASE LOW(PHYS ADDR.HI WORD); DT (SLOTI) .LIMIT LIMIT; DT(SLOTI) .SW RESRVD 0; DT(SLOTI) .RI~HTS RIGHTS; RETURN;
NULLIFY: PROCEDURE (SLOT) PUBLIC REENTRANT; DECLARE SLOT SLOTW DECLARE SLOTI DTA_SEL DT SELECTOR, WORD AT (@SLOT); /* Alternate type */ WORD, /* Slot index */ SELECTOR, /* To be set to either GDT alias or LDT alias. */ BASED DTA SEL (DT SIZE) STRUCTURE-(DESC_STR);
28 29
2
2
30 31 32
2 2 2 2
2
33 34
DTA SEL = FIND DT ALIAS(SLOT); SLOTI = SHR(SLOTW73); /* Get index part of selector. */ DT(SLOTI) .RIGHTS 80H;/* This invalid value prevents use of the descriptor. */ RETURN;
2-24
121960-001
PL/M-286 COMPILER
960-505
date
PAGE
35
END POINT;
MODULE INFORMATION: CODE AREA SIZE CONSTANT AREA SIZE VARIABLE AREA SIZE MAXIMUM STACK SIZE 129 LINES READ o PROGRAM WARNINGS o PROGRAM ERRORS DICTIONARY SUMMARY: 96KB MEMORY AVAILABLE 5KB MEMORY USED (5%) 0KB DISK SPACE USED END OF PL/M-286 COMPILATION 00CAH 0000H 0002H 0018H 202D OD 2D 24D
2-25
121960-001
cf
SLDT FORMAT
L > .. ..............
LIMIT NEXT
BASE,.,o PREVIOUS
ACCESS RIGHTS
BYTE
FLAG DESCRIPTOR TABLE
BA~",,~
# SLOTS IN BLOCK
,
13 12 11 10
I
I
.L
, ,
c: en Z
l>
G)
,
/8,
.. \
::I:
4
....
~1\
..
:IJ C
9 8
I\)
)10
0>
r\J
I?>I
\ .............. \
.: ..... :.'
I
r
.
\
.
,.
80H
== l>
1
';-3
I:. ...............
I:.:: .,
6
5
....
'
..
I
.....
..
I
I
.l
OOH
m
"tJ
:IJ :IJ
BOH SOH
OOH
..
1
o -4 m
3
o -4
4
3
...........
\
:
~8
...
:.
\. J
" 3';
r
D
3
)1
~1
HEAD OF FREE SLOT LIST 0
~10'
1
o Z
"T1
3
I
..
.
en
6
:IJ
c:
l> -4
"I
Iii
RESERVED
AVAILABLE
~
<0 Ol
121960-51
In allocating memory statically using the Builder, you or the Builder must keep account of what memory locations are available and what locations are used. A dynamic memory allocation module must do the same, but, in addition, it needs to reuse the space vacated by tasks that have finished. Even tasks that are still executing may no longer need all of the memory they once were using, so you need to provide some means for them to return that space dynamically. The need to reclaim formerly used memory space provides considerable challenge to operating system designers.
Protection usually requires that segments not overlap. The operating system should accurately keep track of allocated memory to prevent new segments from overlapping current segments. Allocation of memory to tasks in a dynamic environment is complicated by the facts that segments have differing lengths and that the order of creation and deletion is unpredictable. Consequently, after a number of tasks have come and gone, memory becomes fragmented, as illustrated in figure 3-1. It becomes increasingly difficult to find free areas large enough to accomodate requests for space. It may happen that no single free area in all of memory is large enough to fill a request for memory even though the total of all smaller available areas is larger than the amount needed. Knuth (see "External Literature" in the Preface) discusses how various memory-management mechanisms can minimize or magnify this problem. Memory management on the iAPX 286 differs from memory management on other processors in that descriptors must be constructed to access any region of physical memory.
3-1
121960-001
o-
AVAILABLE MEMORY
ALLOCATED MEMORY
121960-17
"first fit" algorithm because it provides an opportunity to illustrate how to create descriptors dynamically to access free memory areas, not because it necessarily performs best in any specific application. Knuth discusses other algorithms, including the "buddy system." Figure 3-2 illustrates conceptually the structure of this module. Hidden inside the module are the list of available memory space, the aliases that permit modification of the GDT and LDTs, and the spacemanagement algorithms. The PUBLIC procedures ALLOCATE and FREE are the only interfaces with the world outside the module.
Data Structures
Figure 3-3 illustrates the data structures implemented in this example memory manager. One-word tags bound every memory area on the low and the high end. These boundary tags indicate whether the area is free or in use by some task. Free areas are chained into a two-way linked list that uses physical addresses to point to the next and prior segments in the list. The size of an area (in bytes) is stored with the link addresses in the low-addressed end of the area. At the high-addressed end, a physical address points to the beginning of the area. With boundary tags at both ends of every memory area, the memory manager can, when freeing a segment that is no longer needed, easily determine whether either of the adjoining areas is free. Figure 3-4 illustrates how adjacent free areas can be combined to reduce memory fragmentation. Figure 3-5 illustrates that boundary tags are invisible to procedures outside the memory management module because the tags are not within the base and limit addresses in the segment descriptor that the memory manager returns to the caller.
3-2
121960-001
ALLOCATE
GATE
0.
0
GLOBAL DATA
FRELSEG
GATE
121960-16
This memory manager does not maintain descriptors to free segments; instead, it creates descriptors dynamically when it needs to address the boundary tags and space-management linkages. This policy minimizes the number of descriptors in the GOT. Note that as a result, free areas may be larger than 64K bytes. Physical addresses are stored as double words CDWORD) to take advantage of double word arithmetic in PL/M-286. In an actual implementation, you may wish to store physical addresses in three-byte fields to save space, but you would need to implement arithmetic operations for three-byte operands. The total size of the memory-management items associated with each free area is 20 bytes; therefore, to ensure that no memory area is too small to contain the memory-management items, this algorithm chooses the size of the allocated space to be a mUltiple of the next integer greater than 20 that is also a multiple of 16. This number is identified as BLOCICMODULUS.
3-3
121960-001
inter
NULL NULL
ALLOCATED SEGMENT
CURRENT AVAILABLE
FIRST AVAILABLE
BOUNDARY TAG
--~:C5"U~S~ED[':'J
121960-18
The memory manager maintains physical-address pointers to the first segment in the available segment list and to the last. It also maintains a "current available" pointer that corresponds to Knuth's "roving pointer." This example also makes some assumptions about the placement of descriptors in the GDT. Figure 3-6 illustrates these assumptions: The memory manager frequently needs to create temporary descriptors for such purposes as reading and updating the boundary tags and link fields. For its own convenience, the memory manager reserves GDT slots for these temporary descriptors. This example identifies the slots as SLOT_A, SLOT_B, and SLOT_C. Adjacent slots in the GDT contain all the descriptors to information for one task. This way, given a selector for one task descriptor, simple addition or subtraction yields selectors for other descriptors for the same task.
3-4
121960-001
inter
BEFORE
, AFTER
"USED"
"USED"
"USED" "USED"
I I
J 1
SEGMENT TO BE FREED
I
I
I
L
"FREE"
"FREE"
121960-56
3-5
121960-001
SEGMENT
BOUNDARY TAG
121960-300
There are two ways to reserve slots in a descriptor table: 1. 2. Code absolute selector values in the program and use the Builder's RESERVE statement to prevent the Builder from allocating other descriptors to those slots. This is the method used in this example. Use EXTERNALs to dummy segments coded in an ASM286 module, and allow the Builder to assign slots for the descriptors of the dummy segments. The Builder resolves the EXTERNALs.
PL/M-286 Code
This example separates space-management functions from descriptor-management functions. The spacemanagement procedures are DELINK, FIND_FIRST_FIT, and RETURN_SPACE. The public procedures ALLOCATE and FREE_SEG call on POINT~T and NULLIFY to manipulate descriptors for allocated segments. (Refer to Chapter 2 for definitions of POINT_AT and NULLIFY.) The PL/M-286 built-ins used to manipulate system structures in this example include
(se~c~~
The external procedure GET$SEGMENT$BASE extracts the segment base address from the specified descriptor. When the procedure FIND_FIRST_FIT finds an available space that is much larger than requested, it allocates the higher-addressed portion of the space and leaves the lower-addressed portion in the freespace list. Figure 3-7 illustrates the process of splitting an available space.
3-6
121960-001
I
I I
I
I
I
I
I
1
11
n+3 n+2 n: 1
m+-2
+1
:
GOT ALIAS
NULL
121960-19
When returning an unneeded segment to the available list, the procedure RETURN_SPACE checks the boundary tags of both the lower and higher adjacent segments to see whether there is another free segment with which to combine. Four cases are possible, as illustrated in figure 3-8 at the end of this chapter. Table 3-1 summarizes the actions taken in each of the four cases. See figure 3-9 at the end of this chapter for the PL/M-286 code that implements this example of a memory manager.
Protection Structure
Where in the two-dimensional grid of protection offered by the iAPX 286 should the memorymanagement module lie? There are two approaches that offer different advantages:
1.
The module can be structured as privileged procedures that execute as part of every task that calls them. The module can execute as a separate task.
2.
3-7
121960-001
inter
BEFORE
AFTER
SIZE 2: 16 BYTES
121960-20
GLOBAL PROCEDURES
Placing the module's segment descriptors in the GDT allows all tasks in the system to share the module yet requires only one copy of the module's segments to be present in memory. This approach allows for fastest communication between the application and the memory manager. The procedures of the memory manager synchronize with the calling procedure (that is to say, the calling procedure waits until the memory-management procedure returns). However, more than one task can be executing the memory-management procedures at one time. This can be an advantage (as when there are multiple CPUs and the requests are for different regions of the memory space), but it requires synchronization of changes to space-management data structures (not shown in this example). Segments containing procedures and data structures internal to this most critical operating-system module should have the greatest protection possible. Because none of these procedures and data structures are PUBLIC, no other modules can gain knowledge of the locations of data and procedures. This by itself, however, does not constitute positive protection from accidental or intentional snooping or destruction. The segments containing these procedures and data should have privilege level 0 (PL 0) so that the processor can prevent any access from less trusted procedures.
3-8
121960-001
Action
Hi Lo Free Free
Lo START
Lo Hi Free Used
Lo START
Lo
Used
Hi Free
Lo
Used
Hi Used
This Base Null
CURR_AVLBL=
CURR_L1NK.PRIOR =
Yes No
No No
CURR_L1NK.NEXT= DELINK HI FIRST_AVLBL= CURR_AVLBL? PRIOR FREE LlNK.NEXT= CURR_AVLBL? NEXT FREE L1NK.NEXT= CURR_AVLBL?
FIRST-AVLBL No Yes
No
No
Yes
No
No
No
Yes
Yes
The PUBLIC interface procedures ALLOCATE and FREE_SEG should execute at PL 0 to access the internal data structures and procedures, which are also at PL O. ALLOCATE and FREE_SEG should have gates at PL 3, however, so that even least trusted application procedures can get the space they need for such purposes as dynamic data structures.
SEPARATE TASK
Another possible structure, not exemplified here, is to treat the memory-management module as a separate task. The iAPX 286 features for isolation of tasks provide the needed protection for the critical memory-management structures and procedures. Within the memory-management task, privilege levels can be used to isolate the various internal procedures and data structures from one another. The memory-manager task can use a message passing mechanism such as that shown in Chapter 5 to receive requests and to pass segments to the requesting task. With the memory-manager executing as a separate task, serialization of requests for space is automatic, thereby eliminating the need for synchronization when modifying space-management structures. The separate-task approach is also advantageous when there is a need to have the requesting task wait until sufficient memory becomes available to fullfil a request. While one task is waiting, the memory manager can continue to service requests from other tasks.
3-9
121960-001
3-10
121960-001
BEFORE
CASE #0
AFTER
"FREE" START
"FREE" START
(
FROM PRIOR FREE SEGMENT
I I
"FREE" "USED"
I I
SEGMENT TO BE FREED
I I
I I
"FREE"
"FREE"
121960-21
3-11
121960-001
BEFORE
CASE #1
AFTER
"USED"
"USED"
I
I
"USED" "USED"
I
I
I I
I L
I I
"FREE"
"FREE"
121960-21
3-12
121960-001
intel'
BEFORE
AFTER
"FREE" START
CASE #2
"FREE" START
"FREE" "USED"
I I
"USED" "USED"
I I
FROM PRIOR FREE SEGMENT
I
I
"FREE" "USED"
I
I
"USED"
"USED"
121960-21
3-13
121960-001
BEFORE
AFTER
"USED"
CASE #3
"USED"
I J
"USED" "USED"
I I
I I
I I
TO FORMER HEAD OF LIST
SEGMENT TO BE FREED
"USED" "USED"
.~LJ
I I
"::"
I I
"FREE" "USED"
NULL
HEAD OF LIST
"USED"
"USED"
121960-21
3-14
121960-001
PL/M-286 COMPILER
960-501
date
PAGE
system-ID PL/M-286 DEBUG Vx.y COMPILATION OF MODULE MEMORY OBJECT MODULE PLACED IN :Fl:MEMORY.OBJ COMPILER INVOKED BY: :F3:PLM286.86 :Fl:MEMORY.PLM CODE DEBUG
INCLUDE (:Fl:NUCSUB.PLM)
MEMORY:
DO; Externals. */
/*******************************************************/
/*
2 1
2
2 1
2
4
5 6
7
8 9 10
2 1 2 2
PROCEDURE (SLOT, RIGHTS, PHYS ADDR PTR, LIMIT) EXTERNAL; DECLARE SLOT SELECTOR, RIGHTS BYTE, PHYS ADDR PTR POINTER, LIMIT WORD; END POINT AT; NULLIFY: PROCEDURE (SLOT) EXTERNAL; DECLARE SLOT SELECTOR; END NULLIFY; GETSEGMENTBASE: PROCEDURE (SEL, BASE ADDR PTR) EXTERNAL; DECLARE SEL SELECTOR, BASE ADDR PTR-POINTER; END GETSEGMENTBASE; --
POINT AT:
/*******************************************************/
/*
11
Space-management definitions.
*/
DECLARE PARAGRAPH LITERALLY '16'; /* To run under SIM286, all segments must have a base address equal to zero mod PARAGRAPH. This is not required when running on iAPX 286 hardware. */ DECLARE MEM LINK LITERALLY 'PADDING (8) BYTE, START DWORD, HI TAG WORD, LO-TAG WORD, PRIOR DWORD, NEXT DWORD, SIZE DWORD'; /* Base address of link descriptor is always PARAGRAPH less than address of PRIOR field. Address of PRIOR field is always 0 mod PARAGRAPH. PRIOR, NEXT, and SIZE fields always point to a PRIOR - PARAGRAPH address. */ DECLARE TAGS SIZE LITERALLY '4'; /* The space used by both tag words */ DECLARE LINK LIMIT LITERALLY '27'; /* Limit used to construct descriptors for MEM_LINK */ DECLARE BLOCK MODULUS LITERALLY '32'; /* All memory blocks are an integral multiple of BLOCK_MODULUS in length.
12
13
14 15
*/
3-15
121960-001
PL/M-286 COMPILER
960-501
date
PAGE
16
1
1
DECLARE NULL_PHYS_ADDR LITERALLY '0'; DECLARE USED LITERALLY '1', FREE LITERALLY '0'; /* Values of boundary tags */ DECLARE OK LITERALLY '0', FAILED LITERALLY '8000H'; /* Values of exception codes */ DECLARE DWRIGHTS LITERALLY '92H' /* For manipulating space-management data structures, this module needs these rights parameters: Present, DPL=0, data segment, grow up, writable. */;
17
18
19
/*******************************************************/
/*
*/
20
DECLARE (FIRST AVLBL,LAST AVLBL,CURR AVLBL)DWORD PUBLIC; /* Physical-address pointers to chaIn of available space. These always point to PRIOR - PARAGRAPH to avoid calculating base addresses for MEM_LINKs. */ DECLARE SLOT A SELECTOR PUBLIC, WSLOT A WORD AT (@SLOT A) INITIAL (38H), /* 7 */ SLOT 8 SELECTOR PUBLIC, WSLO~ B WORD.AT (@SLOT B) INITIAL (40H), /* 8 */ SLOT_C SELECTOR PUBLIC, WSLOT C WORD AT (@SLOT C) INITIAL (48H); /* 9 */ /* "Scratch"-slots for addres~ing MEM LINKS. */ /* Be sure to reserve these slots with the Builder */
21
/*******************************************************/ Round a size parameter upwards to next greater */ /* or equal (N * BLOCK_MODULUS) ~ TAGS_SIZE for some N */
/*
22
23 24
1 2
ROUND_SIZE: PROCEDURE (A_PTR) PUBLIC REENTRANT; DECLARE A PTR POINTER, ADDR BASED A PTR DWORD; ADDR BLOCK MODULUS
~ 1)
/ BLOCK_MODULUS) + 1)
END ROUND_SIZE;
DELINK:
PROCEDURE (THIS_SEL) REENTRANT; SELECTOR, BASED THIS SEL STRUCTURE (MEM_LINK); STRUCTURE (MEM_LINK),
2 2
28
3-16
121960-001
PL/M-286 COMPILER
date
PAGE
BASED SLOT_C
STRUCTURE (MEM_LINK);
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
2 2 2 3 3 3 2 2 2 3 3 3 2 1
2
IF THIS LINK. PRIOR = NULL PHYS ADDR /* This is the beginning of the list. */ THEN FIRST AVLBL = THIS LINK.NEXT ; ELSE DO; /* Update link-from prior segment. */ CALL POINT AT(SLOT C, DWRIGHTS, -@THIS LINK.PRIOR, LINK_LIMIT); PRIOR_LINK. NEXT = THIS_LINK. NEXT; END; IF THIS LINK. NEXT = NULL PHYS ADDR /* This is the end of the list. */ THEN LAST AVLBL = THIS_LINK. PRIOR; ELSE DO; /* Update link from next segment. */ CALL POINT AT(SLOT C, DWRIGHTS, -@THIS LINK.NEXT, LINK_LIMIT); NEXT_LINK. PRIOR THIS_LINK. PRIOR; END; END DELINK;
/***************************************************** **/
FIND FIRST FIT: PROCEDURE (SIZE,BASE ADDR PTR) WORD REENTRANT; DECLARE SIZE WORD, BASE ADDR PTR POINTER, BASE-ADDR-BASED BASE ADDR_PTR DWORD; DECLARE CURR LINK BASED SLOT_A STRUCTURE (MEM_LINK), PHYS-SIZE DWORD, SIZE-DIFF DWORD, /* Boundary tag items */ BOUND ADDR DWORD, BOUND-MID BASED SLOT B STRUCTURE (MEM LINK) , BOUND=HI BASED SLOT=B STRUCTURE (MEM=LINK); DECLARE TOP LOOP LABEL; PHYS SIZE = SIZE; CALL-ROUND SIZE(@PHYS SIZE); CALL POINT-AT(SLOT A,-DWRIGHTS, @CURR_AVLBL, LINK_LIMIT); TOP LOOP: IF-SLOT A SELECTOR$OF(NIL) /* Check for end of list */ THEN DO; IF FIRST AVLBL = NULL PHYS ADDR /* The list is empty~ */ THEN RETURN FAILED; END; ELSE CALL POINT AT(SLOT A, DWRIGHTS, @FIRST AVLBL, LINK LIMIT); /* Continue from beginning of list. */ IF CURR LINK. SIZE < PHYS SIZE THEN /* This segment is-too small, so . */
44
45 46 47 48 49 50 51 52 53 54
2 2 2 2 2
2 3
3 3 2
55
3-17
121960-001
PL/M-286 COMPILER 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
2
960-501
date
PAGE
3 3 3 4 4 4 3 3
2
DO; /* Look at next free segment in the list. */ CALL POINT AT(SLOT A, DWRIGHTS, @CURR LINK.NEXT, LINK LIMIT); IF CURR AVLBL = CURR LINK. NEXT /* Have searched entire list without a hit. */ THEN DO; CALL NULLIFY(SLOT A); RETURN FAILED; END; GOTO TOP LOOP; END; /* Segment too small. */ SIZE DIFF = CURR LINK. SIZE - PHYS SIZE; /* Always a multiple of BLOCK_MODULUS */ IF SIZE DIFF = 0 THEN DO; /* This segment is a close fit. */ CURR AVLBL = CURR LINK. NEXT; CALL-DELINK (SLOT=A);
2 2
3 3 3 3 3 3 3 3 3 3 3 3
2
71
72
73 74 75 76 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 95 96 97
/* set lower boundary tag */ CURR LINK.LO TAG = USED; /* set upper-boundary tag */ CALL GET$SEGMENT$BASE (SLOT A, @BOUND_ADDR); BASE ADDR = BOUND ADDR; BOUND ADDR = BOUND ADDR + CURR LINK.SIZE + TAGS SIZE; CALL POINT AT(SLOT-B,DWRIGHTS,@BOUND ADDR,LINK LIMIT); BOUND_HI. HI_TAG =USED; - CALL NULLIFY(SLOT A); CALL NULLIFY(SLOT_B); BASE ADDR = BASE ADDR + PARAGRAPH; RETURN OK; END; /* Close fit. */ ELSE DO; /* It will fit here with room to spare. */ CALL GET$SEGMENT$BASE (SLOT A, @CURR AVLRL); /* Set boundary tag at end-of new segment. */ BOUND ADDR = CURR AVLBL + CURR LINK. SIZE + TAGS SIZE; CALL POINT AT(SLOT B,DWRIGHTS,@BOUND ADDR,LINK LIMIT); BOUND HI.HI TAG = USED; /* Calculate starting address of the new segment. */ BOUND ADDR = CURR AVLBL + SIZE DIFF; BASE ADDR = BOUND ADDR + PARAGRAPH; /* set the boundary fields between the 2 segments. */ CALL POINT AT(SLOT B,DWRIGHTS,@BOUND ADDR,LINK LIMIT); BOUND MID. START = CURR AVLBL; BOUND-MID.HI TAG = FREE; BOUND-MID.LO-TAG = USED; /* Change size of available segment, considering the 2 boundary tag words. */ CURR LINK. SIZE = SIZE DIFF - TAGS SIZE; CALL-NULLIFY(SLOT A);-CALL NULLIFY(SLOT B); RETURN OK; END; /* Room to spare. */ END FIND FIRST FIT; $EJECT -
3 3 3 3 3 3 3 3 3 3 3 3 3 3
2
3-18
121960-001
inter
PL/M-286 COMPILER
960-501
date
PAGE
RETURN_SPACE:
PROCEDURE (FREE_SEG) REENTRANT; BASED FREE SEG SELECTOR, STRUCTURE (MEM LINK);
DECLARE CURR LINK BASED SLOT A STRUCTURE (MEM_LINK), DWORD, NEIBR ADDR NEIBR-LINK BASED SLOT B STRUCTURE (MEM_LINK), DWORD, FREE BASE FREE-SIZE DWORD, DWORD, HI SIZE BYTE, NCASE HI USED LITERALLY '01H', LO-USED LITERALLY '02H'; CALL GET$SEGMENT$BASE (FREE SEG, @FREE BASE); FREE BASE = FREE BASE - PARAGRAPH; /* point to tags */ FREE SIZE = GET$SEGMENT$LIMIT (FREE SEG); FREE-SIZE = FREE SIZE + 1; CALL-ROUND SIZE (@FREE SIZE); /* Determine which case. */ NCASE = 0; /* Check higher neighbor. */ NEIBR ADDR = FREE BASE + FREE SIZE + TAGS SIZE; CALL POINT AT (SLOT B,DWRIGHTS,@NEIBR ADDR,LINK LIMIT); IF NEIBR LINK.LO TAG = USED THEN NCASE=NCASE OR-HI_USED; ELSE HI SIZE = NEIBR LINK. SIZE; /* Save */ /* Check-lower neighbor. */ NEIBR ADDR = FREE BASE; CALL POINT AT(SLOT B,DWRIGHTS,@NEIBR ADDR,LINK LIMIT); IF NEIBR LINK.HI_TAG=USED THEN NCASE~NCASE OR La_USED;
2 2 2 2 2
2
2 2 2 2
2 2 2 2 2 2 2 2 2 2
2
/* Which segment should become the new current one? */ IF (NCASE AND La USED)<>O THEN CURR AVLBL-= FREE BASE; /* low neighbor used */ ELSE CURR-AVLBL = NEIBR LINK. START; /* low free */ CALL POINT=AT (SLOT_A, DWRIGHTS,@CURR_AVLBL, LINK_LIMIT) ;
2 2
/* Calculate size of new segment. */ IF (NCASE AND LO USED) = La USED /* if low neibr used */ THEN CURR LINK.SIZE = 0; ELSE /* already contains size of low neighbor */ CURR LINK. SIZE = CURR LINK. SIZE + TAGS_SIZE; IF (NCASE AND HI USED) <> HI USED /* if high neighbor free *7 THEN CURR LINK.SIZE = CURR LINK.SIZE+HI SIZE+TAGS_SIZE; CURR_LINK.SIZE = CURR_LINK.SIZE + FREE_SIZE;
2 3 3 3
/* Set next and prior links in new segment. */ IF NCASE = 3 /* neither neighbor free */ THEN DO; /* insert at head of available list */
CURR LINK. PRIOR = NULL PHYS ADDR; CURR=LINK.NEXT FIRST=AVLBL; END;
3-19
121960-001
PL/M-286 COMPILER 131 132 133 134 135 136 137 138 139
2 2
960-5131
date
PAGE
3 3 3 3 3
4 4
140
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 166
4
3
2
2
ELSE IF (NCASE AND HI USED) <> HI USED /* if high neighbor-free */ THEN DO; /* Dispose with high neighbor's links. */ /* Make selector for high neighbor. */ NEIBR ADDR = FREE BASE + FREE SIZE + TAGS SIZE; CALL POINT AT(SLOT B,DWRIGHTS~@NEIBR ADDR~LINK LIMIT); IF NCASE =-0 /* both neighbors free */ THEN /* remove one from available list. */ CALL DELINK (SLOT B); ELSE /* Must be case 2. * / DO /* Transfer links to new current. */; CURR LINK. PRIOR = NEIBR LINK.PRIOR; CURR-LINK.NEXT = NEIBR-LINK.NEXT; END; END; /* disposing with high neighbor's links. */ IF (NCASE AND LO USED) = LO USED /* if low neighbor used. */ THEN DO; /* Fix up links in prior and next segments. */ IF CURR LINK. PRIOR = NULL PHYS ADDR THEN /* there is no prior */ FIRST AVLBL CURR AVLBL; ELSE DO; /* fix up prior */ NEIBR ADDR = CURR LINK.PRIOR; CALL POINT AT (SLOT B, DWRIGHTS, @NEIBR_ADDR, LINK-LIMIT); NEIBR_LINK.NEXT = CURR_AVLBL; END; IF CURR LINK. NEXT = NULL PHYS ADDR THEN /* there is no next */ LAST AVLBL = CURR AVLBL; ELSE DO; /* fix up-next */ NEIBR ADDR = CURR LINK. NEXT; CALL POINT AT (SLOT B, DWRIGHTS, @NEIBR_ADDR, LINK-LIMIT); NEIBR LINK. PRIOR = CURR AVLBL; END; END; /* Fixing up links. */
3 3 3 4 4
4 4 3
3 3 4 4
4 4 3 2
2 2
2
2
2
2
/* Set tag words */ CURR LINK.LO TAG = FREE; /* Set START-field in new current segment. */ NEIBR ADDR = CURR AVLBL + CURR LINK. SIZE + TAGS SIZE; CALL POINT AT(SLOT B,DWRIGHTS,@NEIBR ADDR,LINK LIMIT); NEIBR LINK~START =-CURR AVLBL; NEIBR-LINK.HI TAG = FREE; CALL NULLIFY (SLOT_A); CALL NULLIFY (SLOT_B);
END RETURN SPACE; $EJECT -
3-20
121960-001
PL/M-286 COMPILER
960-501
date
PAGE
/***************************************************** **/
167 168
ALLOCATE: PROCEDURE (SLOT, RIGHTS, SIZE, EXCEP PTR) PUBLIC REENTRANT; DECLARE SLOT SELECTOR, BYTE, RIGHTS SIZE WORD, EXCEP PTR POINTER, EXCEP-BASED EXCEP PTR WORD; DECLARE BASE_ADDR DWORD;
2 2 2 3 3 3 2 2 2
IF OK <> FIND FIRST FIT (SIZE, @BASE_ADDR) THEN DO; EXCEP = FAILED; RETURN; END; CALL POINT AT (SLOT, RIGHTS, @BASE_ADDR, SIZE-I); EXCEP = OK; END ALLOCATE;
/***************************************************** **/
178 179
1 2
FREE SEG: PROCEDURE (SLOT, EXCEP_PTR) PUBLIC REENTRANT; DECLARE SLOT SELECTOR, EXCEP PTR POINTER, EXCEP-BASED EXCEP PTR WORD; CALL RETURN SPACE (SLOT); CALL NULLIFY (SLOT); EXCEP = OK;
2 2 2 2
/***************************************************** **/
184
END MEMORY;
3-21
121960-001
Task Management
There are two ways to change the task register: By one of the task switching operations described later in this section. By the L TR instruction. L TR is used to give the task register its initial value during system initialization. Only privilege-level 0 (PL~O) procedures can execute LTR.
Because TSSs correspond one-to-one with tasks, the selector of a TSS uniquely identifies a task. The STR instruction reads the task register into a selector. Operating-system procedures can use STR to identify the calling task. The built-in variable TASK$REGISTER gives PL/M-286 programs access to the task register. The items in the TSS fall into four classes: Back link. Contains a selector to the TSS of the calling (or interrupted) task (if any). LDT selector. Contains a selector to this task's LDT.
4-1
121960-001
TASK MANAGEMENT
INTEL RESERVED
TR~----t-'"
r- __ ..!.5 ____ 0___ ,
pln01001~1
BASE 23_,.
~
0
SYSTEM SEGMENT
BASE,._o
1
I
il
I 23
I
I
PROGRAM INVISIBLE
15
~A~:'T
i }t --------________________J
LlMIT,._o
J
I I
DESCRIPTOR
L____
0 1----__ I
15
TASK LOT SELECTOR OS SELECTOR SS SELECTOR CS SELECTOR ES SELECTOR
01
o OFFSET
42 40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10
8 INITIAL STACKS FOR CPL 0,1,2 CURRENT TASK STATE
BYTE
SI BP SP BX
'-----I~
OX CX AX FLAG WORD IP (ENTRY POINT) SS FOR CPL 2 SP FOR CPL 2 SS FOR CPL 1 SP FOR CPL 1 SS FOR CPL 0 SP FOR CPL 0 BACK LINK SELECTOR TO TSS
6
4
121960-23
Processor registers and flags. Used to store the processor state of the task. Note in particular the NT flag, which indicates when the BACK LINK contains a valid selector.
Initial stacks. Contain the initial SS and SP values to be used when a CALL transfers control to any of the higher PLs (0, 1, or 2). No stack pointer is needed in the TSS for the PL-3 stack because that stack is either the current stack (pointed to by the SS:SP fields) or is locatable via the chain of stack pointers in higher-level stacks.
4-2
121960-001
TASK MANAGEMENT
The processor updates only the back link, the registers, and the flags as part of a task switching operation. The processor merely reads the initial stack fields (during interlevel CALLs) and the LDT selector (during a task switch). The operating system is responsible for initializing the stack and LDT fields. It must also update the LDT selector before changing the LDT register.
Switching Tasks
Since a multitasking system typically has more tasks than it has processors to execute those tasks, there must be some provision for causing a processor to cease executing one task and begin executing another. The 80286 has several such mechanisms, each appropriate to different situations. All use ordinary JMP, CALL, INT, or IRET instructions. The destination operand determines whether a task switch occurs. Table 4-1 summarizes the operations and operands that cause switching of tasks. In PL/M-286, an indirect CALL statement to the selector of a TSS descriptor or task gate causes generation of an intertask CALL instruction. The W AIT$FOR$INTERRUPT built-in procedure generates an IRET instruction. The operand of a CALL or JMP instruction is a pointer containing both selector and offset parts; in this case, the offset is not used, however. The selector portion may refer either to the descriptor of a TSS or to a task gate for a TSS. The result is the same in either case. The difference lies in the protection of access to the TSS. TSS descriptors, which may reside only in the GDT, normally have DPL set to zero to prevent unauthorized task switching by procedures outside the operating system. Task gates may reside in any descriptor table, giving task switching ability to procedures that have access to the gate. A task gate in an LDT gives task switching power only to that LDT's task. A task gate in the IDT gives task switching power to interrupts. This reduces operating-system involvement in interrupt handling, and thereby reduces the time needed to respond to interrupts. The operating system normally uses a JMP instruction to a TSS descriptor to cause a task switch. A CALL instruction to a task gate in an LDT is useful for implementing coroutines. The IRET instruction exits from a nested task that is invoked by a CALL as well as from one invoked by an interrupt. (You cannot use the RET instruction to exit from a CALLed task; RET does not perform a task switch.) The NT (nested task) flag controls the function of the IRET instruction. When a CALL (or interrupt) causes a task switch, the processor sets the NT flag as the new task begins and fills the back-link of the new TSS with the selector of the calling task's TSS. When the NT flag is set, the IRET instruction causes a task switch to the task whose TSS selector is stored in the back-link. The new task must be marked as busy (type code = 3); otherwise an exception occurs.
CALL, JMP, IRET CALL, JMP INT instruction, external interrupt, exception
task gate
IDT
4-3
121960-001
TASK MANAGEMENT
If the processer, while executing an IRET instruction, finds the NT flag not set, this indicates a return to an interrupted procedure in the same task. Refer to Chapter 6 for details on interrupt procedures.
For CALL and JMP instructions, success of a task switch operation depends on the type field of the TSS descriptor. If the type code is 1, denoting an available task, then the task switch proceeds. If the type code is 3, denoting a busy task, then an attempt to switch to the task causes an exception. A task is busy under either of these conditions: The task is the currently executing task. The task is on the chain of TSS back-links from the currently executing task. This prevents recursion of task invocations. A task should be restarted only by the the task that interrupts it or by the operating system after the task has been removed from the back-link chain.
If the target task is not busy, the processor takes these steps in executing a task switch:
Saves all registers in current TSS Loads TR with new TSS descriptor Loads all registers and flags from new TSS (including LDT register)
If switch is due to CALL (or interrupt), sets NT flag and sets back-link in new TSS to point to previous TSS
If switch is due to JMP or IRET, changes the old task's descriptor type code to one, indicating that the task is no longer busy
Resumes new task where it left off (i.e., CS:IP from new TSS)
Note that you cannot pass parameters by an intertask CALL. It is possible to share data between tasks, however. Chapter 5 takes up this subject.
2.
Strategy 1 is not viable in a highly protected system. Errors do happen. An erroneous program might easily skip a task entirely. A programming error that causes a tight loop in one task would prevent all other tasks from being serviced. Strategy 2 can be adequate by itself for certain real-time systems with a static mix of tasks. Task switching by interrupt is usable in dynamic systems, too, but rarely do all tasks in a dynamic system deal exclusively with interrupts. Therefore, in dynamic systems, in highly protected systems, and in systems with tasks that do not provide real-time processing, the operating system may need to assist the processor with task switching.
4-4
121960-001
inter
TASK MANAGEMENT
A WAITING task may be waiting for any of several events: Completion of a request to the OS for I/O A signal from another task Data from another task The end of a time-delay period
The READY state is really a special case of the WAITING state. A READY task is waiting for one specific event: the availability of a processor to execute it. A task becomes READY when first created. A WAITING task becomes READY upon occurrence of the event (or events) for which it is waiting. A RUNNING task becomes READY when preempted.
,.
INITIATE
121960-22
4-5
121960-001
TASK MANAGEMENT
Usually, termination of a task is possible regardless of its scheduling state; therefore, this diagram does not illustrate the transition to "terminated" state.
When IF is set, all hardware-scheduled tasks whose interrupts are not masked out have higher priority than all software-scheduled tasks. When IF is reset, all hardware-scheduled tasks have lower priority than the currently executing task. Only the operating system (CPL < = IOPL) has the right to execute
HARDWARE SCHEDULED
INITIATE
SOFTWARE SCHEDULED
121960-27
4-6
121960-001
TASK MANAGEMENT
eLI and STI instructions due to the significant effect that priority setting has on correct, overall system operation. The ability for an interrupt handler to be an independent task not only I~rotects the handler from the rest of the system but also permits greater flexibility in the kinds of fUll", '1S an interrupt handler can perform. An interrupt handler that is a task can use operating system fUll~lions that might change its scheduling state. For example, if an interrupt handler requests the operating system to read a disk record, the operating system may change the interrupt handler task's scheduling state from RUNNING to WAITING while the I/O operation takes place. (Other tasks may then execute in the meantime.) If the interrupt handler were a procedure instead of a task, it would be difficult to identify it separately from the task that it interrupted. The operating system must keep track of whether a task is attached to an interrupt (i.e., has a task gate in the IDT). Occurrence of an interrupt can at any time dispatch the task attached to the interrupt. This happens without intervention by the operating system; therefore, when a task calls on operating system services, the operating system cannot assume that the calling task is the same as the latest software-scheduled task. An operating system can easily determine whether the current task is hardware or software scheduled if it associates with each task a Boolean that indicates whether the task was software-scheduled. The operating system must ensure that only one task at a time is so marked. The operating system can use the STR instruction to identify the current task. If the current task is not marked as software-scheduled, then the interrupt mechanism must have dispatched it. By knowing whether a task is attached to an interrupt, the operating system can Avoid executing a task that is awaiting an interrupt. A software-scheduled task cannot respond to an interrupt. An exception occurs when an interrupt attempts to invoke a busy task. Avoid preempting an executing interrupt task. That task should finish before software schedules another task. Decide what action to take when an interrupt-dispatched task calls on operating-system scheduling services. Such action might be to mask off the interrupt or to place a gate for a counting task in the IDT to mark lost interrupts.
When the operating system changes a task from hardware scheduling to software scheduling, it must update the chain of tasks that threads through TSSs. Every hardware scheduled task has a link in its TSS to the TSS of the interrupted task. If the system's interrupt structure permits nesting of interrupts, then the chain of interrupted tasks may be arbitrarily long. To change a task to software-scheduled mode, the operating system must take these actions (as figure 4-4 illustrates): Reset the nested-task flag (NT) of the current task. Nullify the back-link field in the current TSS (as insurance in case it is ever used). Dispatch the prior task on the back-link chain.
4-7
121960-001
TASK MANAGEMENT
TASK X TSS FLAGS NT=1 BACK LINK TSS FLAGS NT=1 TSS FLAGS NT=1 TSS FLAGS NT=1
L,/
BACK LINK
L,/
BACK LINK
L/
B E
'\
.r
~I R
-----------------------------------------------------SOFTWARE-SCHEDULED TASKS
TSS FLAGS NT=O BACK LINK CURRENT SOFTWARESCHEDULED TASK TS!> FLAGS NT=O TSS FLAGS NT=O
HARDWARE-SCHEDULED TASKS
BACK LINK
.r-
BACK LINK
L,/
BACK LINK
A F
HARDWARE-SCHEDULED TASKS
\
~
-:r-
BACK LINK
BACK LINK
.r-
BACK LINK
121960-57
4-8
121960-001
TASK MANAGEMENT
example, when an application calls the operating system to request receipt of a message from another task, the operating system determines whether a message is waiting for delivery. If no message is waiting, then the operating system must switch the task from RUNNING state to WAITING state. Later when another task calls the operating system to send a message to the waiting task, the operating system must change the task from WAITING state to READY state. In cases such as these, the operating system plays a bookkeeping role, simply keeping track of which tasks are waiting and associating events with the correct waiting tasks. The operating system plays a much more significant role, however, when it determines which of the ready tasks to dispatch (the transition from READY state to RUNNING state) or when to preempt the task that is executing (the transition from RUNNING state to READY state). These decisions affect the overall performance of the system, both throughput and response to external events.
Because of the difficulty of establishing an effective policy for dispatching and preemption decisions, it is desirable to clearly separate mechanisms from policies. The only control an operating system can exercise over tasks is deciding which task to execute and how long to let it run before changing to another task. The scheduling mechanisms must exert such control in a manner that the policies can adjust. For example, to control how long a task executes, the scheduler implements a mechanism for preempting the task after a certain time period has elapsed. The mechanism consists of an interval timer (such as Intel's 8254 Programmable Interval Timer) that interrupts the executing task periodically so that the operating system can determine whether the task has yet exceeded the time-slice allocated to it. The length of the time-slice is a variable that the policy layer can control. The policy layer sets the length of the time-slice to reflect the importance of the task. The separation of policy and mechanism applies as well to deciding which task to execute next. For example, the scheduling mechanism associates a priority number with each task. When changing tasks it always chooses the task with highest priority. The priority, however, is a variable, and the policy layer determines its value. For the policy layer to make reasonable decisions about scheduling, the mechanism layer may need to collect statistics about the run-time behavior of tasks, for example:
Elapsed time in the system Total of actual time serviced by processor Running average of actual length of time-slice
(Note that interrupt-scheduled tasks subtract from the time allocated to software-scheduled tasks.) The privilege levels of the iAPX 286 architecture can support the separation between mechanisms and policies. The mechanisms belong to the kernel of the operating system, and as such they should be well tested, highly reliable, and not subject to frequent change; in other words, they are good candidates for PL O. Policies, on the other hand, are subject to frequent change and, as a result, are less reliable. Running scheduling policies at PL 1 ensures that errors cannot corrupt kernel procedures.
4-9
121960-001
TASK MANAGEMENT
SCHEDULING POLICIES
The actual implementation of scheduling policies depends on the needs of the application and the behavior of the tasks in the system. Consider a simple policy that Gives all tasks equal priority Allocates the processor once to each task in turn Allocates the same maximum time-slot to each task
Even this seemingly "fair" policy actually favors certain tasks over others. A task that frequently relinquishes the processor voluntarily (because, for example, it frequently has to wait for I/O) rarely uses the full time-slot. A "processor-bound" task (for example, a computational task that uses many instructions to accomplish its purpose but rarely does I/O), on the other hand, almost always uses the full time-slot, forcing the operating system to preempt it. Over a period of many time-slots, processorbound tasks will receive much more attention from the processor than I/O-bound tasks. Whether this situation is desirable depends on the roles of the tasks in the application. Attempting to discriminate against processor-bound tasks by introducing a priority mechanism can result in different problems. Suppose all I/O-bound tasks have higher priority than all processor-bound tasks. At the end of a time-slice or when a task voluntarily gives up the processor, the scheduler switches to one of the higher-priority tasks if one is ready; if none is ready, it switches to one of the lowerpriority tasks. The problem occurs when there is a such a number of I/O-bound tasks that at least one of them is always ready. In this case, the lower-priority, processor-bound tasks never execute. Many more scheduling policies than those outlined here are possible. The examples given merely illustrate how important it is that the characteristics of the tasks in the system be known and that the policies match those characteristics. Refer to Coffman and Denning (see "External Literature" in the Preface) for a survey of these and other policies.
The data-segment alias to the task's LDT The data-segment alias to the task's TSS Scheduling state Scheduling parameters (for example, time-slice, priority) Scheduling statistics (for example, total processor time used, average time-slice used, expected running time) Links for queues of waiting and ready tasks
4-10
121960-001
TASK MANAGEMENT
This additional state information is referred to here as the task database (TDB). There are two common modes of access to the task database: 1. 2. From within the current task to information about the current task. Most operating system services use this mode of access, including the scheduler's time-slice interrupt procedure. From within the current task to information about other tasks. The scheduler uses this mode of access to find the next task to execute.
ACCESS MODE 1
Access mode 1 can be efficiently implemented via the GOT. All descriptors for the key segments relating to one task reside in adjacent GOT slots. If the operating system can focate one of these descriptors (as by using the STR instruction to obtain a selector to the current TSS), then it can locate any of the others by a simple addition or subtraction. Figure 4-5 suggests one possible way of organizing the TOB. In this example the TOB is stored in a data structure called the task information block (TIB). In large systems you may need to minimize the number of GOT slots used for task information, so as not to unduly limit either the number of tasks or the number of other descriptors that GOT can hold.
TIB
GOT
I
I I I I
I
I I I
~ '\. -:'\
~
I I I I I I I
\
--
--
LOT
I
I I I
I
TSS
LOT SELECTOR
121960-24
4-11
121960-001
TASK MANAGEMENT
The example in figure 4-5 illustrates the general case in which all the pertinent information is in separate segments. This case uses five GOT slots. You can free one GOT slot by including the TSS within the TIB. The TIB descriptor can serve as the data-segment alias for the TSS. Figure 4-6 illustrates such a configura tion. Speed of access to the TOB is critical in some applications. Figure 4-7 shows another configuration of task information that helps improve access speed. Here the task's stack segment for PL 0 contains both the TSS and the TIB. The advantage of this approach is that the TIB and the TSS can be addressed relative to the base address that the processor loads into SS when transferring control to a PL-O operatingsystem procedure. This eliminates the need for loading the OS or ES register to access the current task's TSS or TIB and also frees a segment register for other use. In such a case, the SP portion of the TSS initial stack values for PL 0 is set to an offset beyond the TIB. In many. applications it is still desirable for the GOT to hold a descriptor for the TIB so as to facilitate access to TIBs for tasks other than the current one.
ACCESS MODE 2
When the scheduler is dispatching a different task, it needs quick access to the queues of waiting and ready tasks. If the links that implement these queues thread through the many segments that contain TIBs, the time needed to search and update the queues is extended by the time needed to load a
LOT
GOT
*'
,
TIB
"
'--.
121960-25
4-12
121960-001
TASK MANAGEMENT
LOT
D
PRIVILEGE-LEVEL ZERO STACK SEGMENT LOT LOT TSS TIB ALIAS STACK TIB TSS LOT SELECTOR
121960-26
segment register for each segment visited. This suggests that these queues all reside together in a separate scheduler queue segment. A pointer in each queue element can refer back to the corresponding task. Figure 4-8 illustrates such a structure.
EXAMPLE OF A DISPATCHER
The process of changing a READY task to RUNNING stateis known as "dispatching." Figure 4-9 shows a simple dispatching procedure. This procedure executes at PL 0 in the task that calls it. No call gate is provided, so only other operating system procedures can call DISPATCHER; for example, a procedure that switches the calling task to WAITING state, or a timer interrupt procedure that determines when to preempt the task that it interrupts. The DISPATCHER procedure is coded in ASM286 instead of PL/M-286 because it is more convenient to code an indirect, intertask JMP instruction in ASM286. DISPATCHER makes two assumptions about the rest of the operating system that justify the use of an intertask JMP instead of an intertask CALL: A task can call operating system procedures that change it from RUNNING state, so a task does not need to execute an IRET for that purpose. The operating system procedure that calls DISPATCHER may set the TSS back link so as to intercept an IRET if the task executes one. (When the operating system dispatches a task, it does not make sense for an IRET to return to the previously executing task. That task may, for example, be waiting for an event and not be ready to execute.)
4-13
121960-001
inter
TASK MANAGEMENT
GOT
121960-52
4-14
121960-001
TASK MANAGEMENT
960-503
04/22/83
PAGE
SERIES-III iAPX286 MACRO ASSEMBLER V1." ASSEMBLY OF MODULE DISPATCHER OBJECT MODULE PLACED IN :F5:DISP.OBJ ASSEMBLER INVOKED BY: ASM286.86 :F5:DISP.ASM LOC OBJ LINE
1 +1
2
3 4
5 6 7 8
STACK
NAME DISPATCHER EXTRN DEQUEUE READY: FAR PUBLIC DISPATCHER STACKSEG 4 DWORD PTR [BP-4] \>/ORD PTR [BP-2] WORD PTR [BP-4] SEGMENT ER PUBLIC
9 10 11 12 13 14 15 16 17 18 19 20 21
NEAR 4,0 DEQUEUE_READY AX,O D_EXIT WE'LL FORM POINTER ON STACK RETURNS S ELECTOR IN AX TO TSS SAME TASK? JUST RETURN
CLI
CALL CMP JE
22
FORM POINTER 23 MOV TSS SEL, AX TSS-OFFSET, 0 NO'r USED ANYWAY MOV 24 TSS-PTR TASK SWITCH JMP 25 26 001A 27 D EXIT: STI WHEN THIS TASK EVENTUALLY REGAINS CONTROL, 001A FB 28 IT RESUMES EXECUTING HERE, SINCE THE OFFSET 001B C9 29 LEAVE OF THIS INSTRUCTION WAS THE LATEST VALUE IN 001C C3 30 RET THE IP REGISTER FOR THIS TASK 31 32 33 DISPATCHER ENDP 34 35 NUCLEUS CODE ENDS WARNING #160, LINE #35, SEGMENT CONTAINS PRIVILEGED INSTRUCTIONS 36 END 000F 8946FE 0012 C746FC0000 0017 FF6EFC ASSEMBLY COMPLETE, 1 WARNING, NO ERRORS
4-15
121960-001
OA T A-SHARING TECHNIQUES
The architecture of the iAPX 286 allows segments to be shared among tasks through several mechanisms. Each mechanism has different advantages and disadvantages, and requires different degrees of support from the operating system. Note that while the primary subject of this chapter is data sharing, these segment-sharing techniques apply as well to code segments.
It is not always desirable to use GDT descriptors for sharing segments that only a few tasks use. A segment that has a descriptor in the GDT is accessible by all tasks, and exposing it to access from unrelated tasks may compromise the system's protection goals. Deletion of GDT descriptors may have unknown effects, because it is diffucult to control usage of GDT descriptors. GDT space may be needed for other purposes.
5-1
121960-001
121960-301
5-2
121960-001
A from using the selector to reference its own LDT, but if it does so, the selector will likely refer to the wrong descriptor. One way to avoid this potential problem is by reserving the same slot position in the LDTs of all sharing tasks.
ALIAS MANAGEMENT
In any system that uses aliases for segment sharing, the operating system must ensure that all the aliases for a given segment remain consistent in spite of changes to the segment. The operating system may relocate a segment, transfer it to or from secondary store, or delete the segment. If allowed to use a descriptor that had not been updated to reflect any of these changes, a task would fail and might cause other tasks to fail. Therefore, an operating system must implement a means to find and update all aliases for a segment when it changes anyone of the aliases.
Alias Database
Figure 5-2 shows an example method for locating aliases. This method maintains a header block for each segment that has aliases. Pointers to all the aliases for that segment are linked to the header. As long as the entire list does not span more than one segment, the link fields (FIRST, LAST, NEXT, PRIOR, and HEADER) need only contain offsets. The doubly linked list shown here aids dynamic creation and deletion of alias pointers; for static systems, a singly linked list would suffice. In addition to the FIRST and LAST links, the list header contains that segment information that might change but that must remain consistent in all the aliases of a segment. Operating-system operations on segments demand that the segment base address and the present bit be consistent. Furthermore, any interrogation of the accessed bit for a segment demands that the accessed bits in all the aliases be ORed together. This example assumes that the operating system does not permit creation of aliases with differing limit or expansion direction. When a task that has a selector for an alias descriptor calls on operating system functions that make changes to segment attributes, those changes must be broadcast to all other aliases for the segment. Therefore, the operating system must have a means, given any descriptor, to find the alias list that includes that descriptor. Figure 5-3 illustrates one technique for doing this. Each descriptor table has a parallel table of pointers to alias list headers. The index in a selector that locates a descriptor in the descriptor table also locates a pointer in the parallel table. A descriptor that has no alias has a null entry in the corresponding position in the parallel table. For applications in which aliases are few, you can employ a hashing algorithm to reduce the number of entries in the parallel table.
Alias Procedures
Implementation of procedures for alias management for the 80286 is a straightforward application of list processing algorithms and therefore is not illustrated here. At a minimum, the operating system should provide a CREATE_ALIAS procedure and a DELETE_ALIAS procedure. The operating system must enforce a correspondence between the existence of descriptors for a segment and the existence of the segment itself. A segment must always have a descriptor, and an active descriptor must always point to a valid segment. A convenient way to enforce these rules is to permit only the DELETE-ALIAS procedure to call the segment FREE procedure. DELETE-ALIAS should cause deletion of a segment only when the last descriptor for the segment has been deleted. Creating an alias is only the first step toward segment sharing. The CREATE_ALIAS procedure can only create an alias for a segment that is accessible to the task that calls CREATE_ALIAS. The next
5-3
121960001
inter
-------
})
121960-29
step toward segment sharing is to pass the alias to another task. This subject is taken up in a later section of this chapter, "Message Passing."
SYNCHRONIZA TION
Consider the example of a memory manager given in Chapter 3. While a memory management procedure manipulates the links that manage free space, there are instants when the data in the links is temporarily inconsistent (for example, the next-pointer in one segment has been set, but the previouspointer in the next segment has not yet been updated). If the processor interrupts the task in which the memory-management procedure is running to run another task (or even another procedure in the same task) and if the new task (or procedure) calls the memory manager, then the the memory manager is likely to behave incorrectly. For the protection of the system, the operating system must prevent such forms of incorrect function in its own logic and must provide synchronization operations that enable application logic to avoid such failures as well.
5-4
121960-001
DESCRIPTOR TABLE
POINTER TABLE
ALIAS LISTS
~-----------------------------~
HEADER
0--------0
t------Il~
POINTER DESCRIPTOR TABLE POINTER TABLE
i
I I
INDEX FROM SELECTOR
r-----------------------------,
HEADER
0 0---------0
10
i
I I
L ____________________________ _
t------Il~
POINTER
r-----------------------------,
HEADER
0 0---------0
121960-31
10
L ____________________________ _ I
5-5
121960-001
Do nofnest critical sections; there is only one interrupt flag. Do not switch tasks; doing so may enable interrupts. Disabling interrupts as a means to provide mutual exclusion is not a generally applicable technique. The rules above are too restrictive for many situations, and the CLI and STlinstructions for disabling and enabling interrupts are restricted to procedures whose CPL does not numerically exceed IOPL. An operating system can, however, use this technique for its own short-term, high-speed exclusion requirements and as the basis for more general synchronization operations.
Figure 5-4 illustrates an example data structure for implementing a general purpose form of control over critical sections: binary semaphores. The semaphore structure consists of a counter and a queue. Every shared resource subject to the effects of contention needs one semaphore structure to provide mutual exclusion for the tasks using the resource. The value of the counter is one minus the number of tasks waiting at the semaphore. A value of one indicates that the semaphore is available; a value of zero indicates the the semaphore has been acquired
r---------------------------,
HEAD OF QUEUE SEMAPHORE TO TASK ENTRIES IN GOT QUEUE ELEMENTS
COUNTER
QUEUE POINTER
121960-28
5-6
121960-001
but no other tasks are waiting for the semaphore; a negative value indicates that some tasks are queued, waiting for the semaphore to be released. The queue is circular so that the pointer to the head of the queue also identifies the tail of the queue. Semaphore structures may be stored individually in separate segments or may be stored together in one or more segments. In the latter case the operating system must provide a means for identifying individual semaphores within a segment. Storing the semaphore counter in a segment by itself yields two important advantages: The processor can individually protect each semaphore. The selector of the descriptor for the semaphore segment serves as a convenient identifier for the semaphore.
Semaphore structures are sensitive data that must be .cloistered behind the level 0 protection wall. Semaphores may reside either in the GDT or in the LDTs of the tasks that use them. The same considerations apply as for shared data segments.
SEMAPHORE-MANAGEMENT PROCEDURES
The minimum set of operating-system procedures needed to use semaphores includes WAIT_SEMAPHORE to acquire a semaphore if it is not already acquired SIGNAL_SEMAPHORE to signal departure from a critical section
Dynamic systems may also need to define semaphores dynamically with procedures such as CREATE_SEMAPHORE for setting up a new semaphore structure DELETE_SEMAPHORE to eliminate a semaphore structure that is no longer needed
The operating system's responsibilities in managing binary semaphores include Ensuring that no more than one task holds a semaphore When a task requests a semaphore that has not been signalled, placing the task in a waiting queue, and dispatching another task When a task signals a semaphore, awakening the next task in the waiting queue for that semaphore . and placing it in the ready queue Preventing or being prepared to handle any deadlock that may result from using semaphores
Figure 5-5 shows simple examples of how to use a low-level synchronization technique to implement WAIT_SEMAPHORE and SIGNAL_SEMAPHORE procedures. These procedures must run at PL 0 to access the semaphore structures. With segment descriptors in the GDT and with call gates at PL 3, any procedure in the system can call these synchronization primitives.
5-7
121960-001
PL/M-286 COMPILER
960-S04
date
PAGE
system-ID PL/M-286 Vx.y COMPILATION OF MODULE SEMAPH OBJECT MODULE PLACED IN :Fl:SEMAPH.OBJ COMPILER INVOKED BY: PLM286.86 :Fl:SEMAPH.PLM DEBUG
SEMAPH: /*
DO; Externals */
/*******************************************************/
2 3
4 S 6
7 8 9 1
2
DISPATCHER: PROCEDURE EXTERNAL; END DISPATCHER; ENQUEUE WAIT: PROCEDURE(QUEUE 10) EXTERNAL; DECLARE QUEUE ID SELECTOR; END ENQUEUE_WAIT; DEQUEUE WAIT: PROCEDURE(QUEUE ID,EXCEP P) EXTERNAL; DECLARE QUEUE 10 SELECTOR, EXCEP P POINTER; END DEQUEUE_WAIT; -
1 2 2 1 2
2
/*******************************************************/
/* 10
1
*/
DECLARE SEMAPHORMAT LITERALLY 'FILLER (2) WORD, COUNTER WORD'; DECLARE OK /* LITERALLY '0'; Test a semaphore; wait if not set PROCEDURE (SEMAPH 10, EXCEP P) PUBLIC-REENTRANT; */
11
/*******************************************************/
12
1
WAIT SEMAPHORE:
13
14
DECLARE SEMAPH 10 SELECTOR, SEMAPH-BASED SEMAPH_ID STRUCTURE(SEMAPHORMAT); DECLARE EXCEP P EXCEP-BASED EXCEP P POINTER, WORD;
is 16 17 18 19 20 21 22 23
2 2 2
2
3 3 3 3
2
DISABLE; SEMAPH.COUNTER=SEMAPH.COUNTER-l; IF ZERO /* Test the zero flag. */ THEN /* Semaphore was set. */ DO; ENABLE; EXCEP=OK; RETURN; END; /* Semaphore is not set; this task must wait. */ CALL ENQUEUE_WAIT (SEMAPH ID);
5-8
121960-001
PL/M-286 COMPILER
24
96(3-5(34
date
PAGE
25 26
2 2 2
/*
Set a Semaphore
*/
27 28 29 3(3 31 32 33 34 35 36 37 38 39 4(3 41
42
1
2
SIGNAL_SEMAPHORE:
DECLARE SEMAPH ID SELECTOR, SEMAPH-BASED SEMAPH_ID STRUCTURE(SEMAPHORMAT); DECLARE EXCEP P EXCEP-BASED EXCEP P POINTER, WORD;
2 2 2
2
3 3 3 3
2 2 2 2
DISABLE; SEMAPH.COUNTER=SEMAPH.COUNTER+1; IF NOT (ZERO OR SIGN) /* Test flags. */ THEN /* No one is waiting at this semaphore. */ DO; ENABLE; EXCEP=OK; RETURN; END;
/* Someone is waiting at this semaphore. */ CALL DEQUEUE WAIT (SEMAPH ID, @EXCEP); ENABLE; CALL DISPATCHER; EXCEP=OK;
END SIGNAL_SEMAPHORE;
/**********~***********.********************************/
43
END SEMAPH;
MODULE INFORMATION: CODE AREA SIZE . CONSTANT AREA SIZE VARIABLE AREA SIZE MAXIMUM STACK SIZE 1(37 LINES READ (3 PROGRAM WARNINGS (3 PROGRAM ERRORS DICTIONARY SUMMARY: 91KB MEMORY AVAILABLE 4KB MEMORY USED (4%) 0KB DISK SPACE USED END OF PL/M-286 COMPILATION (3084H 0(3(3(3H (3 (3 (3 (3H (3(31(3H 132D (3D (3D 16D
5-9
121960-001
You may wish to implement other forms of synchronization; for example: Conditional variation of WAIT_SEMAPHORE that does not force a task to wait when the semaphore has not been signalled. Timed waiting, so that a task can be awakened if the semaphore is not signalled within a reasonable time. (This helps guard against deadlocks.) An extension of the semaphore concept known as a region. A region is similar to a semaphore except that only the task that acquires a region can release (signal) it, and a task that holds a region cannot be suspended.
MESSAGE PASSING
Message passing is a general purpose means for transferring data from the address space of one task to the address space of another, cooperating task. There are two aspects to the technique: Transferring data from a segment in one task's address space into a segment in the receiving task's space Transferring a segment from one task's space into another's
The first case is suitable for passing relatively small amounts of data, such as parameters, information describing events, etc. The second case has two primary applications: For transferring large "consumable resources" such as I/O buffers For transferring aliases that implement the previously described method of "sharing via aliases"
When an alias is passed as part of a message, the operating system installs the alias in a descriptortable slot determined by the receiving task.
Message-Passing Example
Figure 5-6 shows an example data structure for implementing a simple form of message passing. This structure defines a mailbox, a queue of tasks waiting for messages from the mailbox, and a queue of undelivered messages. The system may contain one mailbox for every communication channel between tasks. For simplicity, this example assumes that the format of messages for all mailboxes is the same, consisting of a fixed-length data item and two descriptors.
Only the sending and receiving tasks need access to a mailbox; therefore, the appropriate tables for descriptors for mailbox segments are the LDTs of each of the tasks that share a mailbox. All tasks can share a global mailbox, however, if its descriptor is in the GDT. The DPL for all mailbox segments should be zero to prevent procedures outside the operating system from interfering with message passing. Mailboxes -require at least two procedures: SEND_MESSAGE and RECEIVE_MESSAGE. Figure 5-7 shows examples of these procedures. Both procedures must run at PL 0 to access level-O mailbox
5-10
121960-001
I 1 I I
r---------------------------,
QUEUE ELEMENTS
'II
I I I I I I
HEAD OF QUEUE
~~~----~
*--f-....
MAILBOX
I I I I I I I L__________________________ _ I
~---------------------------,
NEXT
DATA
DESCRIPTORS
L__________________________ _
121960-33
5-11
121960-001
segments. If there are call gates in the GOT at PL 3, then these procedures are accessible to all other procedures in the system. SEND_MESSAGE fills a message with the specified data and descriptors, removes the descriptors from the descriptor table, and links the message at the tail of the message queue. If a task is waiting at the mailbox, SEND_MESSAGE causes it to be linked into the ready queue so that it will find the message the next time it is scheduled to run.
If RECEIVE_MESSAGE finds no messages waiting at the mailbox, then it links,the task into a waiting queue. The task queue threads through the task database. The task will continue executing when another task sends a message to the mailbox. If (or when) a message is waiting, RECEIVE_MESSAGE writes the data portion of the message at a specified location in the receiving task's space and installs the descriptor portion in specified slots in one of the receiving task's descriptor tables (GOT or LOT).
These examples do not include management of space and queues for messages because conventional GET_MSG_SPACE, ENQUEUE_MESSAGE, algorithms apply. External procedures DEQUEUE_MESSAGE, and FREE_MSG_SPACE provide these functions. Special handling is required to accommodate the fact that a descriptor in a message is temporarily not in any descriptor table. There are two cases to consider: The descriptor is the sole descriptor for the segment. In this case, no changes can be made to the segment because it is temporarily inaccessible. You should take care that no failure in the communication process causes the descriptor to become lost. A memory area without a descriptor cannot be freed. The descriptor is an alias (i.e., one of several descriptors for the same segment). Since the segment is (presumably) accessible via the other aliases, it is possible for some task to request some operation on the segment during the time the descriptor in the message is absent from any descriptor table. Normally, the operating system updates all aliases when it makes any major changes to a segment (for example, relocation or swapping to secondary store). This is not possible (given the aliasing scheme previously presented in this chapter) when the alias is not in a descriptor table. To solve the problem, this example assumes there are two procedures: a. DISABLE_ALIAS_PTR that marks the alias list element to indicate to the alias manager that the alias is in a mailbox b. FDCALIAS_PTR that, when the message is delivered, updates the alias pointer with the new location of the alias and with any segment information that may have changed while the alias was absent from the alias list. Dynamic systems may need to create and delete mailboxes dynamically. The only difficulty in creating a mailbox is ensuring that no task uses it while it is being constructed. (The next section considers this problem.) To delete a mailbox the operating system must awaken any tasks that are waiting for messages, delete any descriptors (aliases) that reside in undelivered messages, and delete the undelivered messages themselves. The operating system may, as part of the process of task creation, give each task at least one mailbox. If the mailbox feature is the only means of passing aliases among tasks, a task cannot receive an alias for a mailbox unless it already has a mailbox. Some operating system designs may require every task to have a mailbox for such purposes as receiving memory segments from the memory-allocation module.
5-12
121960-001
PL/M-286 COMPILER
960-508
date
PAGE
system-I 0 PL/M-286 Vx.y COMPILATION OF MODULE MAILBOX OBJECT MODULE PLACED IN :Fl:MBOX.OBJ COMPILER INVOKED BY: PLM286.86 :Fl:MBOX.PLM DEBUG
INCLUDE
(:Fl:NUCSUB.PLM)
MAILBOX:
DO;
/*******************************************************/ /* Definitions */
2
1
DECLARE FAILED OK
/*******************************************************/ /* Externals */
3 4 5
1 2 2
1 2 2
NULLIFY: PROCEDURE (SLOT) EXTERNAL; DECLARE SLOT SELECTOR; END NULLIFY; STORE DESCR: PROCEDURE(SLOT,PTR) EXTERNAL; DECLARE SLOT SELECTOR, PTR POINTER; END STORE_DESCR; LOAD DESCR: PROCEDURE(PTR,SLOT) DECLARE PTR POINTER, SLOT SELECTOR; END LOAD_DESCR; DISPATCHER: PROCEDURE EXTERNAL; END 01 S PATCHER; ENQUEUE WAIT: PROCEDURE(QUEUE 10) EXTERNAL; DECLARE QUEUE 10 SELECTOR; END ENQUEUE_WAIT; DEQUEUE WAIT: PROCEDURE(QUEUE 10, EXCEP P) EXTERNAL; DECLARE QUEUE 10 SELECTOR, EXCEP P POINTER; END DEQUEUE_WAIT; DISABLE ALIAS PTR: PROCEDURE (SLOT) EXTERNAL; DECLARE SLOT-SELECTOR; END DISABLE_ALIAS_PTR; FIX ALIAS PTR: PROCEDURE(ALIAS LIST 10) EXTERNAL; DECLARE ALIAS LIST 10 POINTER; END FIX_ALIAS_PTR; GET MSG SPACE: PROCEDURE(BOX ID,MSG P P,EXCEP P)EXTERNAL; DECLARE BOX 10 SELECTOR, (MSG_P_P~ EXCEP_P)-POINTER; END GET_MSG_SPACE; EXTERNAL;
6 7 8
9
10
11
1 2 2
1 2
12 13 14 15 16 17 18 19 20 21 22
23
24
1 2 2
1
2
2
1 2 2
1
25 26 27 28
2 2 1
2
5-13
121960-001
inter
960-508
date
PAGE
FREE MSG SPACE: PROCEDURE(BOX ID,MSG_PTR) EXTERNAL; DECLARE-BOX ID SELECTOR, MSG-PTR POINTER; END FREE_MSG=SPACE; ENQUEUE MESSAGE: PROCEDURE (BOX ID, MSG_PTR) EXTERNAL; DECLARE BOX ID SELECTOR, MSG-PTR POINTER; END ENQUEUE MESSAGE;
DEQUEUE_MESSAGE: BROCEDURE (BOX ID, MSG_P_ P, EXCEP P) EXTERNAL; DECLARE BOX ID SELECTOR, (MSG_P_ P, EXCEP_P) POINTER; END DEQUEUE MESSAGE; -
/*******************************************************/
/*
38 39 1 1 Mailbox Data Structures LITERALLY '46' ; LITERALLY BYTE, WORD, WORD' ;
*/
/*******************************************************/
/*
40 41
1
*/
SEND MESSAGE: PROCEDURE(BOX ID, MDATA PTR, SLOT1, SLOT2, EXCEP_P) - PUBLIC REENTRANT; DECLARE BOX ID SELECTOR, MDATA PTR POINTER, (SLOT!, SLOT2) SELECTOR; DECLARE EXCEP P EXCEP- BASED EXCEP P POINTER, WORD;
42 43
2 2
DECLARE MSG PTR POINTER, MESSAGE BASED MSG PTR STRUCTURE (MESSAGE_FORt1AT) T CALL GET MSG SPACE (BOX ID, @MSG PTR, @EXC.EP); IF EXCEP~FAILED THEN /* the box-is full of messages */ DO; CALL DISPATCHER; RETURN; END; /* The next statement will cause an exception if the segment containing the data is not present. Therefore interrupts are enabled. */ CALL MOVB (MDATA PTR,@MESSAGE.MDATA,MDATA SIZE); IF SLOT1=SELECTOR$OF(NIL) THEN MESSAGE.DESCR1(2)=0; /* Mark as null */ ELSE DO; CALL STORE DESCR(SLOT1,@MESSAGE.DESCR1); CALL DISABLE_ALIAS_PTR(SLOT1);
44 45 46 47 48 49
2
2
2 3 3 3
50 ,51 52 53 54 55
2
2 2
3 3
5-14
121960-001
PL/M-286 COMPILER 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
71
960-508
date
PAGE
3 3 2 2 2 3 3 3 3 2 2 2 2 2 2 2
CALL NULLIFY(SLOT1); END; IF SLOT2=SELECTOR$OF(NIL) THEN MESSAGE.DESCR2(2)=0; /* Mark as null */ ELSE DO; CALL STORE DESCR(SLOT2,@MESSAGE.DESCR2); CALL DISABLE ALIAS PTR(SLOT2); CALL NULLIFY(SLOT2); END; DISABLE; CALL ENQUEUE MESSAGE(BOX ID, MSG PTR); CALL DEQUEUE-WAIT (BOX ID~@EXCEP); ENABLE; CALL DISPATCHER; RETURN; END SEND_MESSAGE;
RECEIVE_MESSAGE: PROCEDURE (BOX ID, MDATA PTR, SLOTl, SLOT2, EXCEP=P) PUBLIC-REENTRANT; DECLARE BOX ID MDATA PTR (SLOT!, SLOT2) SELECTOR, POINTER, SELECTOR; POINTER, WORD;
73
74 75
2
2
DECLARE MSG_PTR POINTER, MESSAGE BASED MSG PTR STRUCTURE (MESSAGE_FORMAT); CHECK MAIL: DISABLE; CALL DEQUEUE MESSAGE (BOX ID, @MSG PTR, @EXCEP); IF EXCEP=FAILED THEN /* No mail today */ DO; CALL ENQUEUE_WAIT (BOX_ID); ENABLE; CALL DISPATCHER; GOTO CHECK_MAIL; END; ENABLE;
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
92
2 2 2 3 3 3 3 3 2
2 2 3 3 3
2
93 94
/* Next statement may cause exception. */ CALL MOVB(@MESSAGE.MDATA, MDATA PTR, MDATA SIZE); IF MESSAGE.DESCRl(2)<>0 /* Test-for null descriptor */ THEN DO; CALL LOAD DESCR(@MESSAGE.DESCRl, SLOTl); CALL FIX_ALIAS_PTR(@MESSAGE.DESCR1); END; IF MESSAGE.DESCR2(2)<>0 /* Test for null descriptor */ THEN DO; CALL LOAD_DESCR(@MESSAGE.DESCR2, SLOT2);
5-15
121960-001
PL/M-286 COMPILER 95 96
97 3 3 2 2
2
960-508
da"te
PAGE
98
99
CALL FIX ALIAS_PTR(@MESSAGE.DESCR2); END; CALL FREE MSG SPACE(BOX ID,@MESSAGE); EXCEP=OK;END RECEIVE_MESSAGE;
/**********************************~~*******************/
100
END MAILBOX;
MODULE INFORMATION: CODE AREA SIZE CONSTANT AREA SIZE VARIABLE AREA SIZE MAXIMUM STACK SIZE 193 LINES READ o PROGRAM WARNINGS o PROGRAM ERRORS DICTIONARY SUMMARY: 91KB MEMORY AVAILABLE 6KB MEMORY USED (6%) 0KB DISK SPACE USED END OF PL/M-286 COMPILATION 016EH 0000H "0000H 0020H 3660 00 00 320
5-16
121960-001
Systems that implement "pipes" as a form of intertask communication can call mailbox procedures from the device drivers for the pipes.
It is possible to use mailboxes as the sole means of interface between applications and operating system. For example, the operating system has one mailbox through which it receives service requests from all applications; each task has a mailbox through which it receives responses from the operating system. To get more memory, a task would send a memory request message to the operating system; the operating system would return a message containing an alias for the allocated memory segment and install the alias in the task's LDT. The advantage is simplicity. Only two global gates are needed: one for SEND_MESSAGE and one for RECEIVE_MESSAGE. A task can wait for only one purpose: for a message from a mailbox. The disadvantage is inefficiency. Any implementation of mailboxes is bound to be less efficient than the interlevel CALL instruction normally used to communicate with an operating system.
All of these forms of message-passing can use the primitive synchronization and descriptor-manipulation techniques illustrated in this section.B
5-17
121960-001
The 80286 implements some of these generalizations of interrupts onto the multitasking environment, but the operating system has responsibility for others. Not all are relevant to every application of the 80286.
Vectoring
The processor associates each event with an identifying number in the range 0-255. The processor recognizes three classes of events: External. Events occurring outside the 80286 processor's environment are communicated to the processor via the INTR or NMI (non-maskable interrupt) pins. The NMI is interrupt 2. Other external interrupts share the INTR pin via one or more 8259A Programmable Interrupt Controllers, which can map each interrupt to a unique interrupt 10 in the range 32-255. Processor. When.the processor detects a condition that it cannot handle, it communicates this fact by causing an interrupt with an 10 in the range 0-16 (except for interrupt 2, which is the NMI). Software. Programs can generate signal events by executing the instructions INT n and INTO. With INT n, the value of n can be any interrupt indentifier in the range 0-255. This gives software the ability to simulate hardware interrupts as well as the ability to cause interrupts that are not directly associated with hardware events. (Note that many software systems use the software interrupt to call on operating-system services. With the iAPX 286, an interlevel CALL through a CALL gate serves this purpose.)
6-1
121960-001
When an interrupt occurs, the processor uses the interrupt identifier as an index into the interrupt descriptor table (IDT).
If the descriptor indexed by the interrupt identifier is a task gate, which points to a task state segment, then the processor causes a task switch. Figure 6-1 illustrates the links that identify the interrupt task. Chapter 4 discusses the .mechanisms associated with task switching and considers the impact that hardware task switching has on the operating system's task scheduler. If the descriptor indexed by the interrupt identifier is either an interrupt gate or a trap gate (which point to executable segments), then no task switch occurs. Instead the processor behaves similarly to the way it would if the current task had called the indicated procedure via a call gate. Figure 6-2 illustrates the links that identify the interrupt procedure. The iAPX 286 protection mechanism requires either that the target segment have a privilege level numerically less than or equal to CPL or that the target segment be conforming. If one of these conditions is true, then the indicated procedure begins executing in the current task. The major mechanical difference between invoking a procedure by an interrupt and invoking by a CALL is that, with an interrupt, the processor pushes the flag word onto the stack of the invoked procedure before the return address (as illustrated in figure 6-3) and clears the single-step flag (TF).
6-2
121960-001
inter
lOT
GOT TSS
INTERRUPT 10
TASK GATE
TSS DESCRIPTOR
n
121960-304
lOT
EXECUTABLE SEGMENT
OFFSET
INTERRUPT 10
--.
~
----..
ENTRY POINT
LOT OR GOT
SEGMENT DESCRIPTOR
BASE
121960-302
Note that if an interrupt occurs while a privilege-level 0 (PL-O) procedure is executing, an attempt to transfer to a less privileged level violates protection rules. (The same protection rules apply as for a CALL to a less privileged segment.) In general it is impossible to predict when an interrupt occurs; therefore, it is equally impossible to avoid a protection violation when a less privileged procedure has an interrupt gate or trap gate in the IDT.
6-3
121960-001
STACK
!
SP
~
RPL
......-
1---------1
LOW
121960-36
What is the difference between an interrupt via an interrupt gate and an interrupt via a trap gate? In the case of an interrupt gate, the processor automatically disables interrupts before transferring control to the interrupt procedure; therefore, an interrupt gate is normally used with external interrupts. In the case of a trap gate, the processor does not disable interrupts; therefore, trap gates are normally used with processor-detected exception conditions, which are also known as "traps." The IRET instruction returns control from an interrupt regardless of whether a task gate, interrupt gate, or trap gate is used to enter the interrupt handler. In all cases, executing IRET restores IF to its value before the interrupt. In the case of an interrupt procedure, the processor restores flags from the stack; in the case of an interrupt task, from the interrupted task's TSS. The difference in speed between handling an event by a task gate versus by an interrupt or trap gate is not great, as table 6-1 illustrates.
6-4
121960-001
Hardware interrupt processing Save registers PUSHA PUSH DS PUSH ES Initialize registers MaV AX,SEG item-1 MaV DS,AX MaV AX,SEG item-2 MaV ES,AX
Total Clocks
167
78
17
3 3
2 17 2 17
167
139
system. The common goal in all these extensions is to structure the software so that, when an event occurs, the hardware can handle interrupt administration chores automatically within the efficiency and protection requirements of the application.
ManagelDT
Many applications require the ability to change the association between an event and the procedure or task associated with it. Even relatively static systems require this ability if interrupt procedures and interrupt tasks are not loaded until after system initialization. Only PL-O procedures can effect runtime changes to the IDT because the data-segment alias for the IDT should have PL O. The techniques for changing the IDT are similar to those already illustrated in Chapter 2 for the GOT and LOTs.
6-5
121960-001
hardware~scheduled
Note, however, that an interrupt task that is in software-scheduled mode cannot service interrupts. If it is possible for further interrupts of the same type to occur during the time the interrupt task is software-scheduled, then switching to software-scheduled mode is not such a good idea. An alternative . strategy is to allocate interrupt-servicing duties among two or more tasks: one hardware-scheduled and the others software-scheduled. The hardware-scheduled task responds to the interrupt and invokes one of the software-scheduled tasks through a mechanism such as message-passing as discussed in Chapter 5. If there are any delays in servicing that interrupt, it is one of the software-scheduled tasks that waits, not the hardware-scheduled task.
For the operating system to maintain run-time control over the 8259A PIC, it may provide a procedure such as the following that applications programs CALL instead of executing the IRET instruction.
PROC FAR
IRET j Switch to task on back-link Execution resumes here upon interrupt
6-6
121960-001
Send RET
interrupt Return
ENDP
mask to
to
PIC procedure
application
The operating system executes the IRET instruction within WAIT_FaR_INTERRUPT. WAIT_FOILINTERRUPT would need to run as a privileged procedure within the calling task. With this approach, the operating system has control just before the task begins to wait for an interrupt as well as when the task begins to execute after the interrupt occurs. The operating system then has the opportunity to send interrupt masks, end-of-interrupt commands, and specific priority rotation commands, as appropriate for the application.
The software system designer has a choice of mechanisms that make it possible for different tasks to have different interrupt procedures for a given interrupt type
1.
2.
You must deploy alternative 1 carefully. If a trap or interrupt gate in the IDT contains a selector for an LDT slot, then there must be a system-wide convention that every LDT wiIl have an appropriate descriptor in that slot. When the interrupt occurs, the processor uses the LDT of the current task to locate the interrupt procedure. Alternative 2 demands less from convention, but more from the operating system and the processor. With this approach, each task has (in the task database) a table that is its own private analog of the IDT. The operating system supplies a GDT interrupt procedure that merely indexes the current task's handler table to find a pointer to the appropriate handler procedure. If the task does not supply an interrupt procedure for a specific interrupt, the operating system can invoke a default procedure.
CONFORMING INTERRUPT PROCEDURES
For certain interrupt procedures (for example, a divide-error exception handler that substitutes a fixed value for the quotient), the appropriate privilege level at which to run the interrupt procedure is the same as that of the interrupted procedure. In these cases, the interrupt procedure can be placed in a conforming segment. For interrupt procedures in conforming segments, the processor automatically sets CPL to the DPL of the segment containing the interrupted procedure. Note, however, that this
6-7
121960-001
inter
technique does not apply to procedures called by an interrupt distribution procedure (because the distribution procedure always runs at PL 0).
"OUTWARD CALL"
An application may contain some interrupt procedures that should run at a fixed privilege level that is grea ter than zero. The processor, on the other hand, prevents calls from PL n to PL m if n<m. For privilege-checking purposes the processor treats interrupts to procedures as calls. It is a privilege violation if the interrupt procedure resides in a segment that has a DPL numerically greater than that of the interrupted procedure. Since interrupts may occur at arbitrary times, it is possible for CPL to be less than the DPL of the interrupt procedure, which would be an exception. A similar problem results when an interrupt distribution procedure (which runs at PL 0) attempts to call a less privileged procedure identified in the task's interrupt handler table. The problem results even if the interrupt distributor attempts to simulate a conforming interrupt procedure by using the interrupted procedure's CPL as the RPL value in the selector of the interrupt handler. The operating system can employ the shadow task strategy to overcome this contradiction. Figure 6-4 outlines the shadow task strategy for invoking a lesser-privileged procedure from PL O. Only a PL-O
lOT
INTERRUPT 10
MAIN TASK
121960-53
6-8
121960-001
inter
procedure such as the interrupt distribution procedure described previously can implement this mechanism. Instead of calling the handler procedure (which could be a privilege violation), the operating system's interrupt procedure Creates a shadow task containing the handler procedure Sets the CS and IP fields of the shadow task's TSS to the entry point of the handler procedure Calls the shadow task An IRET instruction in the interrupt handler procedure returns control to the interrupt distributor procedure in the main task. Creating a shadow task involves simply allocating space for the new TSS and initializing it. Setting the LDT field of the new TSS to the same value as in the main task's TSS lets the shadow task have access to all the same segments as the main task, including the segment containing the handler procedure. The operating system may create the shadow task either at the time the main task is created or dynamically, at the time the interrupt occurs.
A software signalling mechanism is also a convenient way for the operating system to signal tasks. This method is particularly suited to Reporting exception conditions detected by the operating system Giving a task the chance to put its affairs in order before the operating system terminates it.
6-9
121960-001
FAULT MECHANISM
The processor reports an exception condition by causing one of a predefined set of interrupts; one interrupt vector is associated with each exception condition that the processor recognizes. As with any interrupt, either a procedure or a task can field a fault. Faults resemble other interrupts, but they differ in two significant ways: You cannot disable a fault. For certain faults, the processor pushes an error code onto the stack of the fault handler (whether procedure or task) to help with recovery.
FAULT RECOVERY
When a fault occurs, the fault handler has three possible ways of dealing with the exception: Ignore it and continue execution of the task. Fix the problem and retry the faulting instruction. Kill the faulting task.
Ignoring an exception is not generally advisable. Killing a task is sometimes unavoidable, but, for critical tasks, the handler should make every effort to recover from the exception. In many cases, the iAPX 286 helps the exception handler identify the faulting instruction and the conditions that caused the fault.
7-1
121960-001
Error Code
With exceptions that may relate to a specific segment, the processor pushes an error code onto the stack of the exception handler (whether procedure or task). Figure 7-1 illustrates the error code. The format of the error code resembles that of a selector. However, instead of an RPL field, the error code . contains two one-bit items: The processor sets the EX (external) bit when the fault does not directly result from an action of the task. Occurrence of this condition generally indicates a "system" problem as opposed to an "application software" problem. The processor sets the I (IDT) bit if the index portion of the error code refers to a gate descriptor in the IDT. When the I bit is set, the handler can ignore the TI bit. If the I bit is reset, then the TI bit identifies either the GDT or an LDT, just as in a selector.
The index field identifies the descriptor associated with the exception (if any). In some cases the error code on the stack is null, in which case all bits in the word are zero. For some faults, the handler can gain additional information about the fault by determining whether the error code is null.
APPLICATION INTERFACE
Since some of the actions appropriate for exception conditions depend on the requirements of individual application programs, the operating system may need to provide an application interface to the exception handling system. Chapter 6 discusses mechanisms for doing so.
EXCEPTION CONDITIONS
The action appropriate to each type of exception depends both on the type of exception and the needs of the application. This section provides details for each type of exception. Some of the exception conditions are identified by a two-character mnemonic that some other Intel literature uses.
I EX
= =
12196035
7-2
121960-001
Interrupt 3-Breakpoint
The INT 3 instruction causes this exception. The INT 3 instruction is one byte long, which makes it easy to insert a breakpoint anywhere in an executable segment. The operating system or a debugging subsystem can use a data-segment alias for an executable segment to place an INT 3 instruction anyplace where it is convenient to arrest normal execution so that some sort of special processing can be performed. Debuggers typically use breakpoints as a way of displaying registers, variables, etc., at crucial points in a task. The saved IP value points to the next instruction. If a debugger has replaced a planted breakpoint with a valid opcode, it must subtract one from the saved IP value before returning.
Interrupt 4-0verflow
This exception occurs when the processor encounters an INTO instruction and the OF (overflow) flag is set. Since signed arithmetic and unsigned arithmetic both use the same arithmetic instructions, the processor can not tell which is intended and therefore does not cause an overflow exception. Instead it merely sets OF when the results, if interpreted as signed numbers, would be out of range. When doing arithmetic on signed operands, careful programmers and compilers either test OF directly or use the INTO instruction.
7-3
121960-001
An exception handler usually terminates the faulting task; however, in some applications it is feasible to place a "maximum value" in the receiving operand and permit the task to continue. The return pointer indicates the next instruction.
The offending opcode is invalid, so the handler should not restart the instruction. You can use this exception to implement extensions of the iAPX 286 instruction set. The exception handler would interpret the instruction and advance the return pointer beyond the extended instruction before returning.
~vailable
(NM)
The processor encounters an ESC (escape) instruction, and the EM (emulate) bit of the machine status word (MSW) is set.The processor encounters a WAIT instruction, and both the MP (math present) and TS (task switched) bits of theMSW are set.
Refer to Chapter 12 for details concerning the 80287 Numerics Processor Extension.
7-4
121960-001
The processor pushes a null error code onto the stack. If this or any other action while invoking the double-fault handler causes an additional fault, the processor shuts down. To avoid the catastophe of a shut-down, the double-fault handler must be a separate task (so that pushing the error code does not cause a stack fault) and must always be present (so that invoking it does not cause a "not present" fault). Recovery is sometimes possible by eliminating the cause of the second exception and re-executing the faulting instruction so that the original fault can be handled appropriately. The greatest difficulty lies in identifying the cause of the second exception. Often, however, a double-fault condition indicates a serious error, and the faulting task should be terminated.
The value of the limit field of the descriptor to the TSS is too small (discovered during a task switch). The LDT indicated in the TSS is invalid or not present (task switch). Note that a null LDT selector does not cause an exception during a task switch. One of the segment register fields (SS, CS, DS, or ES) in the TSS is invalid (task switch). One of the privileged-stack selectors is invalid (interlevel CALL). The back-link selector is invalid (intertask IRET).
2. 3. 4. 5.
This exception does not occur when a segment-register field or the back link is marked "not present" but is otherwise valid. A "not present" exception occurs in this case. If, during an interlevel CALL, a privileged-stack selector in the TSS points to a descriptor marked "not present," then a stack exception occurs. The handler for this exception must be a separate task, invoked via a task gate in the IDT. The processor pushes an error code onto the stack of the handler. The error code either identifies the faulty TSS (case 1) or contains the faulty selector from the TSS (cases 2-5). The instruction causing the fault can be restarted. An IRET at the end of the exception handler causes the faulting instruction to execute again. .
7-5
121960-001
A few of the conditions that can cause this exception are recoverable. If the system incorporates virtual memory, the solution for a not present LDT may be to bring it in from virtual store. In the case of an invalid back-link, you can make the assumption that the NT flag was set by mistake, give control to the scheduler, and hope ....
An operating system typically uses the "not present" exception to implement a virtual memory system. Refer to Chapter 9 for more information on virtual memory. The processor pushes an error code onto the stack of the exception handler. The error code contains the selector of the descriptor that is marked "not present." A "not present" indication in a gate descriptor usually has special significance for the operating system. For gates in the IDT, the present bit may serve as a sign that the interrupt task is in software scheduled mode and temporarily unable to service an interrupt. If an interrupt arrives in this case, there may be an error either in the device that generates the interrupt or in the handling of the Interrupt Mask Register of the 8259A PIC. (Refer to Chapter 6 for more information on interrupt handling). For gates in the GDT or LDTs, the present bit may serve to signal an unresolved linkage. (Refer to Chapter 11 for information on binding.) The instruction that causes a "not present" fault is restartable (except in the case of a task switch). Execution of an IRET by the exception handler causes the processor to execute the faulting instruction again. When the processor detects the "not present" exception while loading CS, DS, or ES during a task switch, the exception occurs in the new task, and the return pointer points to the first instruction of the new task. .
7-6
121960-001
The processor pushes an error code on the stack of the exception handler. If the exception is due to a not-present stack segment or to overflow of the new stack during an interlevel CALL, the error code contains a selector to the segment in question (the exception handler can test the present bit in the descriptor to determine which exception has occurred); otherwise the error code is null. The instruction that causes a stack fault is usually restartable. Execution of an IRET by the exception handler causes the processor to execute the faulting instruction again. The one case that is not restartable is a PUSHA or POPA intruction that attempts to wrap around the 64K boundaries of a stack segment. This condition is identified by one of the values FFFEH, FFFFH, OOOOH, or OOOIH inthe saved SP. When the processor detects a stack fault while loading SS during a task switch, the exception occurs in the new task, and the return pointer has the value that the IP field of the new TSS held at the time the task switch began. When stack overflow causes the exception, the stack fault handler can increase the size of the stack segment (up to a maximum of 64K) and permit the faulting task to continue. When the exception is due to a stack segment not being present, recovery action resembles that of the "not present" fault handler.
The processor pushes an error code onto the exception handler's stack. If loading a descriptor caused the exception, the error code contains a selector to the descriptor; otherwise the error code is null. The return pointer points to the beginning of the faulting instruction. Recovery may be possible, but . because programming errors cause most of the conditions leading to a general protection exception, recovery may not be worth the trouble required to identify the cause. A string instruction (any variant of INS, OUTS, MOVS, STOS, SCAS, or CMPS) with a repeat prefix (REP, REPE, or REPNE) is not restartable if it causes a segment limit violation. Check whether SI or DI is near the segment limit.
7-7
121960-001
inter
SBB).
An instruction that both tests and modifies the carry flag is not restartable (ADC, RCL, RCR; or
0 1
.3 4
5
6
7
8
9 10 11 12
13 16
Divide error Single step Breakpoint Overflow Bound check Undefined opcode Processor extension not available Double fault Processor extension segment overrun Invalid TSS Segment not present Stack exception General protection Processor extension error
Yes No
7-8
121960-001
Input / Output
This discussion of I/O classifies physical I/O operations thus: Direct I/O, in which the 80286 processor itself communicates directly with the peripheral device. Direct I/O breaks down further into a. Memory-mapped, in which I/O is triggered by processor instructions that reference certain memory locations. b. I/O-mapped, in which special I/O instructions cause the processor to do I/O. Indirect I/O, in which an external processor (such as the Intel 8089 I/O Processor) performs the I/O.
8-1
121960-001
inter
OUT OUTS STI CLI LOCK
INPUT /OUTPUT
output output string set interrupt flag (enable interrupts) clear interrupt flag (disable interrupts) lock bus
When interpreting any of these restricted instructions, the processor compares CPL to 10PL. If CPL exceeds 10PL, the processor causes a general protection exception and does not carry out the instruction. Only a privilege-level 0 (PL-O) procedure (i.e., the operating system) can change 10PL. There is no instruction that explicitly affects IOPL; however, any of the operations that load the flag word can, in some cases, change 10PL. The only mechanisms for changing the flag word are A task switch The POPF (pop flags) instruction IRET
When CPL is greater than zero, the POPF instruction does not change 10PL, even though it changes other flags in the flag word. The processor issues no error indication when this occurs. A task switch loads the flags from the Task State Segment (TSS). As long as the operating system does not make data-segment aliases for the TSS available to less privileged levels, only the operating system can change 10PL in theTSS. For maximum protection, the procedures of an I/O subsystem that run in the calling task should run at a protection level numerically greater than the operating-system kernel but less than applications procedures. 10PL can then include the I/O subsystem but exclude applications procedures. Used this way, 10PL forces less privileged application procedures to call on I/O subsystem procedures for I/O functions, thereby giving the operating system control over many I/O operations .. Tasks that deal primarily with I/O (device drivers, for example) may have an 10PL value as great as three. If that is the case, all procedures in the task have access to I/O operations, yet all four privilege levels are available to protect the procedures of the task from one another.
Memory-mapped I/O is subject to the segment-level protection mechanism of the iAPX 286. A task can execute a memory-mapped I/O operation only if it has access to a descriptor for a data segment that contains one of the memory addresses reserved for I/O. Giving a task descriptors for only the I/O memory addresses that it has the right to use yields a double benefit: The task cannot access I/O devices assigned to other tasks. Within the task, I/O is restricted to those procedures whose privilege level is numerically less than or equal to the DPL of the I/O memory address segments.
8-2
121960-001
INPUT/OUTPUT
You can still take advantage of I/O memory address protection even though the I/O devices on the bus respond to I/O commands. A hardware address mapper can convert the processor's memory cycles for the I/O memory space into I/O cycles on the bus. The address mapper will not initiate a bus I/O cycle unless the memory operation passes the processor's protection checking.
With indirect I/O, the external controller accesses I/O buffers independently of the 80286. This presents a three-fold problem to the operating system: Memory access by the controller is not subject to the automatic protection checking of the 80286. The controller (probably) uses "flat" addresses (i.e., addresses that are not relative to a base address). The addressing range of the controller may not coincide completely with that of the 80286.
The flow of control for indirect I/O requests must pass through operating-system procedures at PL 0 so that the operating system can Check memory addresses and privilege levels against information stored in the task's descriptors Transform base-relative addresses to a flat format recognizable by the controller
8-3
121960-001
INPUT IOUTPUT
Figure 8-1 explains the symbols used in a Petri net graph. Figures 8-2 and 8-3 use Petri net graphs to illustrate two approaches to synchronization between parts ofan I/O subsystem. A horizontal line represents an event of interest that occurs only under certain conditions. Circles preceding an event represent the conditions under which the event can occur. Circles after an event represent the conditions that result from occurrence of the event. A dot inside a circle is called a token. A token represents a condition that is in effect. An event occurs if and only if there are tokens for all its input conditions. When an event occurs, tokens flow into all its output conditions. Figure 8-2 assumes the simple device driver mentioned previously and points out how such a driver can service only one task at a time. Figure 8-3 shows how a two-part driver can deal with more than one I/O request at a time (assuming that the I/O device can do so as well). I/O requests from applications procedures drive part A, while interrupts drive part B. Not shown by the Petri net graphs is the fact that the two parts of the driver must share information about outstanding I/O requests. Both figures show simplified device drivers to highlight the interactions among parts of the I/O subsystem; for example, a real device driver may issue multiple physical I/O commands in response to one I/O request and may retry I/O operations in case of certain error indications from the device.
8-4
121960-001
inter
INPUT /OUTPUT
Only the operating system and the I/O subsystem should use queues of buffers and I/O requests. An application procedure must not use a buffer that an I/O device is simultaneously using.
Implementation Alternatives
If descriptors for data global to the I/O subsystem (such as device allocation tables) reside in the GDT with DPL equal to the I/O privilege level, then I/O procedures can access them regardless of what
o o
FALSE CONDITION
CONDITIONAL EVENTS
t t fa ~
8-5
OCCURRENCES OF EVENTS
121960-39
121960-001
INPUT IOUTPUT
APPLICA nON
DEVICE DRIVER
REQUEST
110
CONTINUE PROCESSING DO OTHER PROCESSING RECEIVE RESPONSE HARDWARE 1/0 DEVICE
121960-37
APPLICATION
REQUEST 1/0 CONTINUE PROCESSING DO OTHER PROCESSING RECEIVE RESPONSE HARDWARE 1/0 DEVICE
GET COMMAND
DO 1/0 APPLICATION REQUEST 1/0 CONTINUE PROCESSING DO OTHER PROCESSING RECEIVE RESPONSE CAUSE INTERRUPT
121960-38
121960-001
INPUT IOUTPUT
task the I/O procedures run in. The I/O interface procedures (READ, WRITE, etc.) must have DPL equal to that of the global I/O data and therefore must have call gates at the privilege level of application procedures (PL 3). If these call gates reside in the LOTs of application tasks, then I/O interface procedures can be shared by (but limited to) those tasks that need them. The call gates can also reside in the GOT, where all tasks can access them. In either case the interface procedures run in the calling task. The possibilities for running device drivers in parallel with the calling task suggests that they be separate tasks. Such a separation also serves to protect applications and device drivers from one another, a definite advantage because inherent complexity and frequency of change tend to place device drivers among the least reliable of operating system functions. The I/O interface procedures have the responsibility for managing the details of communication between the calling task and the device drivers. You can implement a sophisticated device driver such as that illustrated in figure 8-3 as two cooperating tasks: one scheduled by interrupts via a task gate in the lOT, and the other scheduled by I/O requests via an operating-system mailbox facility.
It is possible to implement device drivers as interrupt procedures that run within applications tasks. Such a structure is advantageous in these cases:
Efficiency of I/O is an overriding goal. Interrupts may arrive when a driver is busy.
The lack of protection inherent in such a structure becomes apparent, however, when you consider that the driver procedure that fields an I/O-complete interrupt may run as part of a task completely unrelated to the task that originally requested the I/O operation, and must run at PL O. Viewing the possible implementations of buffers from the perspective of the iAPX 286 architecture, the most pertinent consideration is whether a segment contains just one buffer or several buffers. An approach that uses one segment per buffer has several advantages: The protection mechanism of the iAPX 286 (working as it does on segment descriptors) focuses on each buffer individually. The selector of a buffer segment serves as a convenient buffer identifier, fitting easily into the aliasing and mailbox schemes outlined in Chapter 5.
You can avoid the potential GOT congestion that may result from having one segment (and therefore at least one segment descriptor) per buffer by storing buffer descriptors in LOTs. When tasks share buffers (as between an application task and one or more device-driver tasks), you have a choice between Leaving the buffer at all times within the address spaces of all the sharing tasks Transferring the buffer from the address space of one task into that of another
The mailbox scheme outlined in Chapter 5 easily accomplishes the latter approach. This scheme has the advantage that the application task cannot use the buffer at the same time as I/O is in progress. The "usage privilege level" (UPL), if set to 10PL, provides additional protection by limiting mailbox access to I/O procedures. The application's requirements for I/O efficiency may, however, preclude use of mailboxes for this purpose.
8-7
121960-001
Virtual Memory
HARDWARE MECHANISMS
The 80286 provides the essential hardware mechanisms without which virtual memory systems would not be possible. The segment is the basic unit of the virtual-memory scheme, just as it is the basic unit of the real-memory scheme. In each segment descriptor, the iAPX 286 architecture provides an accessed bit and a present bit to aid the operating system in simulating the virtual memory space with available RAM.
Accessed Bit
Every descriptor for an executable segment or data segment has an accessed flag in the least significant bit position of the access rights byte. Each time a task loads segment register with a segment descriptor, the processor automatically sets the accessed bit in that descriptor. The processor does not automatically reset the accessed bit; software must explicitly write a zero into the accessed bit. The accessed bit has a dual function in virtual memory management: By testing and then resetting the accessed bit at regular intervals, the virtual-memory manager can measure how frequently the segment is being accessed. For writable data segments, the accessed bit (when set) indicates that the segment may have been changed.
Present Bit
Every segment descriptor has a present flag in the high-order bit position of the access-rights byte. The processor automatically tests this bit as it loads segment registers. If the present bit is reset, the processor causes a trap. Which trap depends on the circumstances: Trap 11 (Segment not Present) occurs when loading the CS, DS, or ES register with a not-present segment descriptor, when switching to a not-present TSS, when loading the Task Register by means of the LTR instruction with a not-present TSS descriptor, or when loading the LDT register with a not-present LDT descriptor. Trap 11 also occurs when loading CS with a gate descriptor that is marked "not present." This condition does not necessarily mean that a segment is not present, however. The operating system
9-1
121960-001
VIRTUAL MEMORY
may attach other meaning to the present bit of gate descriptors. Refer to the section on load-time binding in Chapter 11 for an example of an alternate use for the present bit in gate descriptors. Trap 12 (Stack Exception) occurs when loading the SS register with a not-present descriptor. The exception handler can distinguish this condition from other stack exceptions by examining the access rights byte of the descriptor selected by the error code. Trap 10 (Invalid TSS) occurs when switching to a TSS that points to a not-present LDT. The exception handler can distinguish this from other "invalid TSS" conditions by examining the access rights byte of the descriptor selected by the error code. Trap 8 (Double Fault) occurs if the processor, while trying to invoke an exception handler due to a previous exception, finds that the code segment containing its entry point is not present. The difficulty of distinguishing between this and other double fault conditions implies that trap 8 is to be treated as an error condition, not a normal use of the present bit.
Some operating systems may implement both approaches. A system that allocates swap space only at load-time cannot swap out certain segments; namely, segments that a bootloader creates initially and segments that the operating system creates dynamically. In many systems, this is not a problem. Often
9-2
121960-001
VIRTUAL MEMORY
those segments that are bootloaded are just the segments that should not be swapped out. Other operating systems may allocate many segments dynamically: stacks, mailboxes, variable-length arrays, etc. These systems may need both approaches. In designing a dynamic swap-space allocation scheme, you should consider at what time it is best to allocate swap space. The procedure that first allocates RAM space for a segment (a loader, for example) often creates a writable data segment descriptor. Later, when the,procedure has initialized the segment (for example, by writing descriptors into a segment that is to be used as an LOT), it modifies the type code in the descriptor to reflect the intended use of the segment (in this example, it would change the type to LOT). By delaying the allocation of swap space until first swap out, the operating system never allocates swap space for segments that it never swaps out (there is no need to allocate swap space for an LOT, for example, if the operating system does not support swapping of LOTs). Once the operating system allocates swap space for a segment, it must store the swap-space address in a location that is easily accessible when it is time to swap the segment out. Two possible mechanisms for storing the swap-space address are In a boundary tag of the segment, if boundary tags are used. (Refer to Chapter 3 for an example of a space-management scheme that uses boundary tags.) In a table parallel to the descriptor table. To determine whether to call the swap-space allocation procedure when it is time to swap a segment out, the operating system can test whether the swap-space address field contains a null value. When a segment is not present, the operating system can use the 24-bit base-address field in the segment descriptor to store the address of the swap space in which the segment is stored. As long as the present bit of a descriptor is reset, the processor does not use the base-address field. Storing the swap-space address in the descriptor also makes the swap-space address readily accessible to the "not-present" trap handler because the error code presented to the trap handler contains a selector to the descriptor for the not-present segment.
The following checklist identifies some of those segments that should remain permanently in RAM (in your application, there may be others): The GOT. (It is the key to all addressing operations.) LOTs that refer to present segments. (The processor cannot access an LOT segment without fetching its descriptor from the LOT.)
9-3
121960-001
VIRTUAL MEMORY
TSSs that point to present LDTs. (You cannot switch to a task and use its LDT without referring to its TSS.) TSSs whose NT (nested task) flag is set. Certain operating-system kernel segments that are frequently referenced (for example, the segment or segments containing the scheduler's queues). (System performance may degrade excessively.) Segments belonging to the swapping managers.
Note that, while the iAPX 286 does offer mechanisms that support swapping of TSSs and LDTs, doing so is likely to cause not-present faults in PL-O procedures and to cause unacceptable delays in invoking interrupt tasks that are not present. For either of these reasons, the designers of an operating system may elect not to swap out TSSs and LDTs.
Swapping Managers
Swapping managers may need to distinguish between two classes of segments: Segments of a task superstructure (the TSS, the task database (TDB), and possibly the level-zero stack segment) Segments not part of a task superstructure
Swapping of the task superstructure requires that swapping managers be aware that the kernel may treat the TSS as a "subsegment" of the TDB, which may itself reside within the level-zero stack (as outlined in Chapter 4). The swapping managers should treat these segments as a unit. Considering the complexities associated with swapping the segments of the task superstructure, it is perfectly reasonable for an operating system to simplify its virtual-memory subsystem by leaving those segments in RAM for the duration of the task.
OUT-SWAPPER
The out-swapper works best as a separate task; when the out-swapper must wait for the swappingdevice I/O driver to write a segment, other tasks can continue to run, including the task whose segment is being swapped out. The out-swapper's responsibility is to Mark all the descriptors for the segment "not present." The out-swap per must ensure that the present bits in all descriptors for a segment always appear consistent. It must use a semaphore or region to prevent other access to the aliases while it is changing present bits. Copy the swap-space address into all the descriptors for the segment (or possibly, depending on alias implementation, into a "master descriptor" that is linked to other descriptors). Create a temporary data-segment descriptor to give the swapper the right to read the segment. The operating system must not move or delete this segment until the out-swapper is finished with it. Write the segment to the swap-space allocated for it (but only if the segment is writable and its accessed bit is set).
9-4
121960-001
VIRTUAL MEMORY
Return the RAM space used by the segment. Delete the temporary data-segment descriptor.
IN-SWAPPER
In theory, the fetch policy module, invokes the in-swapper. In practice, when the fetch policy is "on demand," the in-swapper is the "not-present" fault handler, which may also be called by the stack segment fault handler (for not present stack segments) and by the "invalid TSS" fault handler (for not present LDTs). The not-present fault handler can run as a procedure in the task that caused the fault. There is one case, however, that such a procedure cannot handle well. A dispatcher procedure running in task A causes a not-present fault when switching to task B whose TSS is not present. If the notpresent handler procedure continues running in task A, then task A must wait until task B's TSS can be swapped in. Whether this is a problem depends on the role of task A in the application. The notpresent handler procedure can avoid this situation by suspending task B and sending a message to yet another task that is dedicated to swapping in TSSs. The steps that an in-swapper procedure takes are to Get the swap-space address and segment size (limit) from the descriptor indicated by the error code. Allocate a writable data segment in RAM large enough to receive the segment. Copy the segment from swap space to the newly allocated RAM space. Update all regular descriptors for the segment with the new base address, setting the present bit and resetting the accessed bit. (The base address comes from the temporary writable data-segment descriptor.) Delete the temporary writable data-segment descriptor.
An in-swapper task for not present TSSs gets a message from its input mailbox that identifies the descriptor for the TSS and identifies the task to which the TSS belongs. The in-swapper task performs the same steps as an in-swapper procedure, but it must also inform the scheduler when the task is ready to run. You can avoid the additional complexities of not-present TSSs by not swapping TSSs out.
COORDINATION OF IN- AND OUT-SWAPPER
A number of interactions between the in-swapper and out-swapper present pitfalls that the operating system must avoid: A task may attempt to use a segment that is being swapped out. If the in-swapper does not handle this possibility, it may swap in- old, erroneous data from the swap-space. Task A may request swapping in of a shared segment that is being swapped in for task B. If the inswapper blithely reads in the segment again for task A, it may overwrite changes made by task B. A task may delete a segment that is being swapped out. If the swap-space release procedure does not allow for this case, the segment's swap space may be released and reallocated while the outswapper is writing to it.
The in-swapper, out-swapper, and swap-space release procedures can control these interactions by maintaining a shared table of all segments that are in transition. They must use a semaphore or region to coordinate access to the shared table. The swap-space address can serve as the segment identifier in the table.
9-5
121960-001
inter
SOFTWARE POLICIES
VIRTUAL MEMORY
A virtual memory system gives each task the opportunity to affect other tasks in the system. Tasks compete with one another for real memory resources. One task may attempt to use memory in such a way as to unduly impede the progress of other tasks. The operating system must enforce policies which ensure that every task makes appropriate progress. Virtual memory management policies are not unique to the iAPX 286; the computer-science literature contains many discussions of policies that apply to various classes of applications. There is, however, a distinction between segmented architectures and paged architectures. The iAPX 286 has a segmented architecture. Literature that deals with paged architectures may not apply to the iAPX 286. Refer to the paper by Denning (see "External Literature" in the Preface) for a broad survey of the science of virtual-memory management. The remainder of this chapter is an introduction to memory-management policy. The policies you need to consider are of three types: fetch policy, placement policy, and replacement policy.
Fetch
The fetch policy determines which segment to bring from swap space into RAM and determines when to bring it in. The simplest fetch policy is to bring in a segment on demand, that is, at the time it is referenced. Under this policy, the operating system brings in a segment from swap space only when the processor causes a not-present exception as the result of a reference to the segment. All other fetch policies are in some way anticipatory. A simple example of an anticipatory fetch policy on the iAPX 286 is to always bring in the LDT of a task when bringing in its TSS. Some time-sharing systems implement an anticipatory policy that brings in all the segments of a task at once. This policy may be suitable for tasks that consist only of one code segment, one or two data segments, and stack segment (as, for example, simple BASIC programs submitted by students in a university environinent). The swapping managers can use the segment register fields in the TSS (CS, DS, ES, SS) to identify the task's working set. Attempting to implement such a full-task swap policy for more complex tasks that use many segments may result in frequently fetching segments that are not referenced in anyone time slice. The additional complexity of implementing an anticipatory fetch policy is justifiable only if the anticipatory policy performs better than the demand policy. Given the efficiency of the iAPX 286 exception mechanism and given that in a multitasking environment there is usually some other task to service while one task waits for the in-swapper to fetch a segment, an anticipatory policy typically does not provide significantly greater throughput. An anticipatory policy may give better performance, however, when judged by performance standards other than throughput (for example, interrupt latency for specific tasks).
Placement
Determining where in RAM to place an incoming segment is the subject of Chapter 3. In a virtualmemory system, however, the constant reallocation of real memory to segments of varying length places special demands on the operating system's memory management module. When choosing a spacemanagement algorithm for a system that includes virtual memory, you may wish to give extra consideration to the trade-off between speed and memory fragmentation.
9-6
121960-001
VIRTUAL MEMORY
Replacement
The operating system may need to replace one or more other segments that already reside in real memory to make space for a segment that is the object of a "segment-not-present" fault. The replacement policy determines which segments to eliminate and when to eliminate them. The choice of which segments to evict from RAM -is crucial to the performance of the system. The goal is to evict only segments that will not soon be referenced. The difficulty is knowing which segments will not soon be referenced. Many different policies are discussed in the liteniture. They' fall into three general classes:
Naive policies that determine which segment to evict without any knowledge of segment access patterns Historical policies that use information about prior access patterns to determine the probability that a segment will soon be referenced Optimal policies that use analyses of actual program control flow to determine the probability that a segment will soon be referenced
HISTORICAL POLICIES
The iAPX 286 architecture supports gathering of historical information about actual segment access patterns via the accessed bit in executable and data segment descriptors. An operating-system module that periodically tests and resets the accessed bits of descriptors can develop a "profile" of segment usage. The information gathered this way can be used both by the replacement policy module for runtime decision making and by the operating system designers for improving replacement policy. A "profiler" works best if it takes samples at regular intervals. To find all descriptors, it must step thru LOTs. A profiler does not need to examine all descriptors in the system each time it is invoked; it needs only to examine those of tasks that have run since the last time it was invoked. The same timer interrupt procedure used by the scheduler can invoke the profiler at appropriate times. A profiler may run either as a separate task or as a shared procedure in the current task. A profiler that runs as a procedure in the current task can easily locate the LOT with an SLOT instruction. The LSL (load segment limit) instruction helps the profiler find the size of an LOT. The LAR (load access rights) instruction enables the profiler to test the accessed bit. A profiler that runs as a separate task may require the support of a PL-O procedure that locates LOTs and tests accessed bits in other tasks. A profiler must give special consideration to aliases. If the accessed bit in any of the aliases of a segment is set, the segment has been accessed. Here again, a PL-O segment may be needed to step through the kernel's alias lists.
OPTIMAL POLICIES
Many of the optimal policies discussed in the literature are of theoretical interest only. They are used as a standard against which to measure the performance of more practical policies. The segment-register fields of the TSS provide support for a trivial, but possibly useful, optimal policy. The replacement policy can assume that, next time any given task runs, all the segments identified by the CS, OS, SS, and ES fields of the TSS will be referenced. The processor loads all these registers during a task switch and causes a fault at that time for each not-present segment. Since the task cannot run if anyone of these segments is not present, the replacement policy may as well replace all of them
9-7
121960-001
VIRTUAL MEMORY
at once. It then becomes possible to allocate swap space for these segments in such a way as to minimize seek time. Such a policy works well with the full-task fetch policy outlined previously.
THRASHING
If not carefully controlled, the I/O traffic in support of virtual memory may degrade system performance beyond acceptable limits. The, worst case of performance degradation is called thrashing. This happens when RAM is committed to simulating an excessively large virtual-memory, space and the behavior of the tasks in that space is such that no task can run without causing a not-present fault.
You can avoid thrashing by measuring or estimating the minimum amount of RAM a task needs in which to operate without causing frequent not-present faults. If the task loader knows this figure, it can refuse to load a task when not enough RAM is available. You can measure a task's RAM requirements' with a profiler such as that described previously.
9-8
121960-001
System Initialization
10
INITIAL STATE
When you power up an 80286 system or perform a RESET, the state of the processor is as follows: The MSW (machine status word) is zero; i.e., the 80286 starts running in the real-address mode. CS:IP be set to FOOO:FFFO, and the CS limit is OFFFFH. The four high-order address lines A 23 -20 are automatically asserted for all subsequent references to CS until your initialization code changes CS. SS, DS, ES are set to zero, and the corresponding limit registers are set to OFFFFH. The flag word is zero. This means that the 80286 starts running with the maskable interrupts disabled.
The initial state of the address lines and CS:IP causes the processor to begin executing instructions at physical address OFFFFFOH. Presumably, this addresses a JMP instruction in an initialization procedure located in ROM or in RAM that has been loaded by another processor. The initialization procedure may occupy any portion of the last 65,536 bytes of the 16-megabyte address space. The JMP instruction at physical address OFFFFFOH transfers control to the actual beginning of the initialization procedure. The first instruction that modifies the CS register causes the processor to cease asserting the high-order four address lines; therefore, the initialization procedure must avoid using any instructions that modify the CS register, except for the final JMP instruction. The initial state of the DS, ES, and SS registers gives the initialization procedure access to the first 65,536 bytes of the address space. The initialization procedure may change these registers, however, to gain access to any location in the first megabyte of the address space. (With regard to segmentation and addressing, the 80286 in real-address mode behaves just as an 8086.) Access to other portions of memory is possible only after switching into protected mode.
10-1
121960-001
SYSTEM INITIALIZATION
Interrupt Vector
The initial state of the 80286 leaves interrupts disabled; however, to ensure a predictable action in case an exception or non-maskable interrupt (NMI) occurs, it is a good idea to initialize the lOT register. Since it is unlikely that the NMI interrupt handler or any exception handler has been initialized, the most appropriate value to load into the lOT register is zeros, thereby guaranteeing a shutdown should an interrupt happen. (The 80286 signals shutdown externally as an indication of a severe problem.) Later, when interrupt service routines are ready, you can change the lOT register to point to an actual lOT that contains gate descriptors for the interrupt routines. Interrupts may be enabled at that time.
Stack
Before you perform any stack operations, whether in real-address mode or in protected, virtual-address mode, you must load the SS register with a descriptor to a stack segment in RAM. If the SS register is loaded in real-address mode, it continues to point to the same segment after the switch into protected, virtual-address mode.
10-2
121960-001
SYSTEM INITIALIZATION
Starting the first task is simply a matter of executing a long JMP via the descriptor of a TSS or via a task gate to that descriptor. This task can perform any remaining initialization work while enjoying the full protection and virtual-address features of the iAPX 286, the state assumed by the development tools.
EXAMPLE OF INITIALIZATION
The following figures present a detailed example of one way to initialize a protected, virtual-address mode system. This example includes assembly language modules that work in conjunction with Builder specifications. Figure 10-1 shows the primary initialization module ENTP (ENTer Protected mode). This module puts the 80286 into protected, virtual-address mode and invokes the first task constructed by BL0286. You use a module such as ENTP by binding it with other modules (presumably those constituting the operating system and the initial task) that you intend to place in EPROM. The module SEGS shown in figure 10-2 supplies dummy segment descriptions for ENTP. The program INIT shown in figure 10-3 serves as the initial task. It merely displays a message when initialization is. complete.
The initializations immediately following RESET_STARTUP are redundant. They simulate the hardware RESET initializations in case of a software reset or in case of a branch to RESET_STARTUP during debugging. INITIAL_GOT is a temparary GOT containing descriptors for the lOT and the main GOT in EPROM (the one constructed by BL0286). Since the symbols for these descriptors, GOT....:OESC and IOT_OESC, are PUBLIC, the Builder can insert the actual base and limit values into the table. The code in segment ENTP_CODE is self-relocatable. In an EPROM-based system, you would specify to the Builder the actual address of the segment ENTP_CODE, making sure that the entry point resides at physical address FFFFFOH. ENTP assumes a specific format for the GOT constructed by BL0286. The first two descriptors are the data-segment aliases for the GOT and the lOT. The remaining descriptors are grouped according to the template defined by TASICENTRY. Three adjacent descriptors identify the key segments of each task. ENTP adapts at run time to the actual number of such groups in the GOT. The task that ENTP initiates is identified by a fixed position in the GOT.
10-3
121960-001
Enter Protected
Mod~
360-516
date
P~G=
systeN-IO iAPX286 ~ACqO ASSEMBLER Vx.y ASSEMBLY CF MODULE ENT? OBJeCT MUDULE PLACED IN :Fl:ENTP.C3J ASSEMBLER INVOKED BY: ASH286.86 :cl:E~TP.A86 LOC 09J LINE
1 +1
2
l
en -< en
Z
r
3
4
5 6 7
8 9
10
11 12
S~itch the 90286 from real address mode into protected mode. Th& initial EPR~M GOT, lOT, TSS, and LOT (if any) constructed by 9L0286 are copied from EPRO~ into RA~. The RAM areas are defined by data segments allocated as fixed entri2s i~ tha GOT. The CPU registers for the GOT, lOT, TSS, and LDT ar~ ;et to point at the RAM ba;ed segments. The base fields in the RAM GOT are also updated to point at the RA~ based segments.
o
I
.....
13 14 15 16
17
18 19 20
Z1
Interrupts are disabled during this moda s~itching code. The EPROM bas~d GDT, lOT, TSS, and LOT are ch.cked to assure they are valid before copying them to RAM. If any of the RAM-based alias segments are smaller than the EPROM seg~ents they are to hold, halt or shutdown occurs. In general any exception or NMI causes shutdown to occur until the first task is invoked. If the RAM segment is larger than the EPROM segment, the RAM segment is expanded with zeroes. If the initial TS5 specifies an LOT, the LOT is also copied into LOT_ALIAS with zero fill if needed. The EPROM or QA~ based GOT, lOT, TSS, and LOT segments may be located anywhere in physical memory. $EJECT Define layout of a descriptor. DESC
-t m 3:
l>
=t
22
23
o Z
-t
N >
24 25 26 27 +1 28 29 30 31 32
33
LIMIT
BASE_LOW BASE_HIGH ACCESS RES OESC
34
35
36
37
STRUC OW OW 08 DB OW ENDS
o o o o o
Offset of last byte in se~ment Lo~ 16 bits of 14-bit address High 8 bits of 24-bit address Access rights byte Reserved word
38 39 40
Define the fixed GOT selector values for the descriptors that define the EPROM based tables.
date
PAGE
l
en -< en
3:
is is is is is
d~t8 segment space for data segment space for data segment sp~ce for TSS for starting task data segl1lent space for
0001
Define particular values of descriptor access rights byte. OT_ACCESS OS_ACCESS TSS_ACCESS OPL ACCESSED TI TSS_SIZE LOT_OFFSET TIRPL_MASK SEJECT EeU EeU EQU EeU EQU EQU EQU EQU EQU 82H 92H 8114 60H 1
4
I 01
44 42 "SIZE OESC-l
Access byte value for an LOT Access byte value for data segl1lent: expand up, level 0, .riteable Access byte value for an idle TSS Privilege lev,tI field of access rights Define accessed bit Position of TI bit Siz8 of a TSS Position of LOT in TSS Tl and RPL field mask
-t m
Z =t N
r
l>
Pass control from the power UP address to the mode switch code. The sagment cont~ini"9 this code must be at physical 8ddr~ss FFFElOH to ~lace the JMP instruction at physic~l addrass =FFFFOH. The base address is chosen according to the size of this segment. ENTP COJE
CS_~FFSET
o Z
-t
SEG"'ENT Eeu
O~G
E~
JMP
Low 16 bits of st~rting address Start at address FFFFFOH Do not change CSt
Dafina the template ~or a temporary GOT used to locate the 1nitial GOT and stack. This data is copied to location O. This space is 81so used for a temporary stack ~nd finally sarv~s as the TSS written into when ~ntering the initial TSS. QQG INITIU_GDT LABEL Place remaining code below power_up address
0000
~
m
0 <0
82
,'33 34 35
WORD
NULL_DESC
DESt
<>
iAPX286 lOC 0002 0004 0005 0006 0008 OOOA OOOC 0000 OOOE 0010 0012 0014 0015 0016 0018 OOlA ODIC 0010 ODIE
~
MACR~
ASSE~BLER
~nter
Protect~d
Mod~
360-516
date
PAG~
OSJ 0000 00 00 0000 0000 0000 00 00 0000 0000 0000 00 00 0000 0000 0000 00 00 0000
LINE
S:JU~CE
l
en -< en
~
86
Gn _OESC
DESC
<>.
Descriptor for
EPRO~
GOT
97
lOT _O:::SC
OESC
<>
88
T::MP_OESC
OESC
<>
Temporary descriptor
-t m
89 90
m
0020. 0022 0024 0025 0026 3fOO 0000 00 92 0000
92 93 94
Define a descriptor which points the GOT at location Q. This descriptor is also loaded into SS to d~fine th~ initial protected mod3 stack se~m~nt.
TEMP _ST ACK
> rN
Z =t
nESC
<=ND_GOT-INITIAl_GOT-l,O,O,DS_ACC~SS,O>
o Z
95 +1 96
97 98 99
-t
>
SEJECT
Define the TSS descriptor used to allow the task switch to the first task to overwrite this region of memory. The TSS overl~ys the initial GOT and stack at location o.
SAVE_TSS
100 101
DESt
<ENO_GOT-INITIAL_GDT-1,0,O,TSS_ACCESS,0>
0>
<0
0030 (B
Define the initial stack space and filler for the end of the TS5. OW 8 OUP (0)
date
PAGE
l
en -< en
m
~
LABEL LABEL OW
Define tenplate for the task definition list. TASK_ENTRY TSS_SEl TSS_ALI AS LOT _ALI AS TASK_ENTRY TASK_LI ST STRUC OW OW OW ENOS
? ?
0000 0002 0004 0044 0046 0048 004A 004C 004C 004D 004E 0050 0052 0054 0056 2000 1800 2800 0000 FA FC 33FF 8EOF 8ECl 8EOl 8C4000
Define layout of task description Selector for TSS Data seg~ent alias for TSS Data segment alias for LOT if any <START_TASK,START_TSS_ALIAS,START_LOT_ALIAS> Terl1linate list No interrupts allo.edl Use autoincre~ent ~ode Point ES:OI at physical address OOOOOOH
TASK_ENTRY OW
-i
o
I
.....
-....I
RESET_STUTUP:
CLI
CLO XOR MOV MOV MOV MOV SEJECT
:;
N
r
Z =i
128
129
OI,DI DS,DI ES,OI SS,OJ ; Set stack at end of reserved are. SP,ENO_GOT-INITIAL_GDT
o Z
l> -i
130 +1
131 132
133
134 135 136 137 138 139
For~ an adjustment f~ctor from the real CS base of ~FOOOCH to the segment base address assumed by A5M286. Any data reference mad a into CS must add an indexing term CSP) to compensate for the differ~nc. between the offset generated by ASM286 and th~ offset required from the b~se of FFOOOOH.
START
STA~T1:
PQOC
140
141 142
CALL
PQP SU9
STAHl
The value of IP at run time is not the same as used by ASM1S51 Get true offset of START1 Subtract 4S~296 offset of START1 leaving adjustment factor in SP Set up null lOT to force shutdown on any protection ~rror or interrupt
o 6
en
~
<0
143
144
145
146
LIDT
Ent~r
Protectld SOUtlC;:
~ode
960-516
date
P4G':
L.INE
147 148 149 150 151 152 153 154 155 156 151 158 159 160 161 162 163 164 165 166 161 168 169 170 171 112 +1 173 174 175 176 177 178 179 laO 181 182 183 184 185 186
197
t~mporary
GOT into RAM. Setup point~r to GOT Set length Put into reserv~d RAM
SI,INITIAL_GDT[SPJ
CX,(END_GOT-I~ITIAl_GDT)/2
R;:P
AX AX,PE AX
$+Z
Get current MSW Sat P!: bit Enter protected mode! Clear queue of ipstructions decodad while in Real Address Mode C?L is now 0, CS still points at FFf!:10 in physical memory Put initial GOT into RA"l area Setup SS with v?lid protected mode selector to the RIlM GOT and stack Sit the current lOT to null Any references to it causes an exception causing shutdown Set initial TSS into the low tlAM The task switch n~eds a valid TSS
en -< en
~
-t m
o
(X)
lGDT
Mav
N
:I>
}> r-
Z =i
-t
o Z
Copy the :PROM based GOT into the RAM data segment alias. First the descriptor for the RAM data segment must ~e copied into the temporary GOT. MOV CMP
J9
OOBE 2E8B4608 0092 302FOO 0095 723C 0097 009A 0090 OOAO
~ CD m
Get size of GOT Be sure the last entry exp~cted by this code is inside the ~OT Jump if GDT i5nt big enough Form selector to ~PROM GOT Get selector of GOT alias Copy into EPROM Get selector of lOT alias Indicate EPRO~ leT Set up addreSSing into EPROM GOT
B80800 BE0800 E80600 BE1000 00~3 B81000 00A6 E8COOO 00A9 B80800 OOAt 8EOS
Enter Protected Mode 960-515 LINE 191 192 193 194 195 196 197 198 199 200 201 202 203 204
205
date
PAGe:
SOURCE
cl
en -< en
m 3:
-f
MJV LGDT
eX.GOT_ALIA5
(~X ]
Get GOT ali3s data se~ment selector Set GOT to ~AM ~OT S5 and TR remain in low RAM
Copy all tasks TSS and LOT segments into RAM LEA
COPY_TASK_l~OP:
Define list of tasks to set up Copy them into RA~ Go to next entry See if there is another entry
With TSS, GOT, and LOT set, start up the initial taskl MOV MOV M:JV LIOT JMP
BA~_GOT:
to
0003 0003 F4
0004 0004 F4 0005 0005 0008 OOOA OOOE OOEO 00E3 00E6 00E9 SEOBOO 8EOE 2E8B1702 8EC6 OF03C6 2E8B37 OF0206 75E9
Ol
to
210 211 212 213 214 215 216 217 218 +1 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
Point OS at GOT Get rOT alias data segment selector Set rOT for errors and interrupts Start the first taskl The 10m RAM area is over.ritten .ith the current CPU context Halt here if GOT isn-t big enough
:;
r-
Z =i
o
Z
> -f
Copy the TSS and LOT for the task pointed at by CS:BX. If the task has an LOT it mill be copied down. too. BX and BP are transparent. BAO_TSS: HLT COPY_TASKS Halt here if TSS is invalid PROC SI,GOT_ALIAS OS,SI SI,CS:CBXJ.TSS_ALIAS ES,SI AX,SI
SI,CS:C~XJ.TSS_SEL
Get addressability to GOT Get selector for TSS alias Point ES at alias data segment Get length of TSS alias Get TSS selector Get alias access rights Jump if invalid reference
iAPX286 MACRO ASSEMBLER lOC OOEB OOEO OOFO 00F3 08J 8A06 80E69F 80FE81 150F
Enter Protected Mode 960-516 LINE 231 238 239 240 241 242 243 244 245 246 241 248 249 250 251 252 253 254 S:JUReE HOV AND eMP JNZ lSl eMP JB Ol,O" OH,NOT OPl OH,TSS_ACeESS
BAO~TSS
date
PACE
Il:
I "
Save TSS descriptor access byte I~nore privilege Su if TSS Jump if not Cet length of EPROM based TSS Verify it is of proper size Jump if it is not big enough
Setup for moving the EPROM based TSS to RAM. OS points at GOT. MOV MOV CAll rSIJ.ACeESS,OS_AeCESS OS,SI COPY_WITH_FIll Make TSS into data segment Point OS at EPROM T~S Copy OS~seoment to =S with zero fill CX has copy count, AX-CX fill count
en -< en
3:
Set the COT TSS limit and base address to the RAM values. MOV MOV MOV M::IV AX,GOT_ALIAS OS, AX ES,AX OI,CS:r5Xl.TSS_SEl sr,CS:raXl.TSS_AlIAS
;
255
-t m
!..
0
.....
0106 0109 0108 0100 0110 0114 0115 0116 0111 0119 011A
'?
~
0
0>
CD
256 257 258 259 260 261 262 263 264 265 266 261 +1 268 269 270 271 272 273 214 215 276 277 278 279 280 281 282
Restore
G~T
addressing
MDV
MOVSW M:JVSW lOOSW MOV STQSW MOVSW SEJECT
AH,Ol
Get TSS selector Get RAM alias selactor Copy limit Copy low 16 bits of address Get high a bits of address Mark as TSS descriptor Fill in high address and access bytes Copy reserved ~ord
> r -t 5 Z
N
See if a valid lOT is specified for the startup task. If so t~en copy the EPROM version into the RAM alias. MOV MOV AND DS,CS:CBXl.TSS_AlIAS Address TSS to get LOT SI,DS:WORO PTR lOT_OFFSET Ignore TI and RPL SI,NOT TIRPl MASK NO LOT Skip this if no LOT used SI OX,SI BAD LOT OL,DIi CH,NOT OPL Save LOT selector Test descriptor Jump if invalid selector Save LOT descriptor access byte Ignore privitlege
JZ
PUSH lAR JNZ MOV AND
Enter Protected Mode 960-516 LINE 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 29S 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 +1 320 321 322 323 324 325 326 327 SOURCE eMP JNE MOV MOV LSL CAll MOV DH,OT_ACC:SS eAO_LDT ES:CSIJ.ACC:SS,DS_ACCeSS; OS,SI AX,51 T:ST_OT_LtMIT CX,AX
date
PAGE
~i
--
0134 80FE82 0137 7532 0139 013E 0140 0143 0146 26C6440592 8EOE OF03C6 E82600 88CS
Be sure it is an LOT descriptor Jump if invalid Mark LOT as data segment Point 05 at EPROM LOT Gat LOT limit Verify it is valid Save for later
Examine the LOT alias segment and, if good, copy to RAM. MOV MOV LSL CALL CALL SI,CS:CBXJ.LOT_ALIAS ES,SI AX,St T!:ST_OT_LIMtT COPY_WITH_FILL Get LOT alias selector Point ES at alias segment Get length of alias seg~ent Verify it is valid COpy LOT into RAM alias segment
en -< en
~
Set the LOT limit and base address to the RAM copy of the LOT. MLlV POP MOV MOV MOV MOV5W MOVSW LOOSW MOV STOSW HOVSW NO_LOT: R:T IIAO_LOT: HLT COPY_TASKS SEHCT ENDP
~t
-t
.....
0
!..
0157 0158 DISC 015F 0161 0163 0164 0165 0166 016S 0169 016A 016A 0168 0168
Restore LOT alias selector Restore LOT selector Restore G~T addressin9 Move the RAM LOT limit Mova the low 16 bits across Get the high 9 bits Mark as LOT descriptor Set high address and access rights Copy reserved ~ord All done Halt here if LOT is invalid
> rN
Z =i
AH,OL
> 0
Z
-t
Test the descriptor table size in AX to verify that even number of descriptors in length. TEST _OT _LIMIT PUSH AND PROe AX AL,1
is an
016C
~
<0 0>
::!
ASSE~BLER
Enter Protected Mode 960-516 LINE SOURCE C'1P POP JNE RET SAC_oT_L1MIT: HLT TEST_OT _LIMIT ENOl' AL,7 AX BAo_OT_LIMIT Must be all ones Restore length
All OK
date
PAGE
l
en < en
m 3:
-I
0176.
!..
I\)
0176 0178 017A 017F 0185 0188 018A 0180 0190 0192 0195 0196 0197 019A 019S 01ge 0190 019E 019F
8COO 8Eeo 26C6470592 26C747060000 OF03C3 88CS E80FFF BF0800 8EOF BF1800 57 AD ESDZFF AS AS AS AS 07 SEDS
~
<0
0>
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 +1 370 371 372 373
Die!
Copy the EPROM oT at selector ex in the te~porary GOT to the alias data segment at selector S1. Any improper descriptors or limits cause shutdownl CoPY_EpROM_OT M!lV PRec AX,SS ES,AX ES:CBXJ.ACCESS,QS_ACCESS; ES:CBXJ.RES,O AX,SX CX,AX TEST_OT_LIMIT oI,GoT_OESC-INIT1AL_GOT oS,DI oI,TEMP_oESC-IN1TIAL_GoT; 01 'TEST_oT_LIMIT Point ES:OI at temporary descriptor Mark descriptor as a data segment Clear reserved word Get li~it of EPROM DT Save for later Verify it is a proper li~it Address EPROM GOT in OS Get selector for temporary descriptor Save offset for later use as selector Get alias segment size Verify it is an even multiple of descriptors in length Put length into temporary Copy remaining entries into temporary ES now points at the GOT alias area OS now points at EPROM DT as data Copy segment to alias with zero fill CX is copy count, AX-CX is fill count Fall into CapY_WITH_FIll
Mav Mav
M;JV
LSl MOV CALL MOV MOV M:JV PUSH lOOSW CALL SToSW MaVSW MOVSW M:lVSW POP MOV
:;
N
r-
o Z
l> -I
ES DS,9X
COPY_EPROM_DT SEJECT
END?
Copy the segment at OS to the segment at ES for length CX. Fill the end with AX-eX zeroes. Use word operations for speed but allow odd byte operations.
Ent~r
date
PAGE
10
cl
en -< en
-t
~
LINE
OlAl OlAl OlA3 OlA5 01A7 OIAA OlAC DIAD OlAE OlAF 33F6 HFF 2BCI 83CIOI 0109 F3 AS 91 7307
374 375 376 317 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
PROC SI,SI 01,01 AX,CX CX,l CX,l AX,CX EVEN_COPY CX,CX EXIT _COpy Start at
be~inning
of segments
Form fill count Convert limit to count Allow full 64K move COpy DT into alias area Get fill count and zero AX Jump if even byte count on cdpy Copy odd byte Exit if no fill Even out the segment offset Adjust remaining fill count count on fill Clear unused words at end
For~ ~ord
01B1 A4 0lB2 OBC9 0184 7409 01B6 01B7 01B8 0188 01BA 01B8 OIBC
AA
(J.)
.!..
49 01E9 F3 AB 7301
'ex
CX,l
l> r-
***
EXIT COpy 395 JNC 396 STOSS OIBE AA 397 EXIT COpy: 01BF 398 RET 399 01BF C3 400 END? COPY_WIT~_FILL 401 402 403 ENTP_CODE ENOS WARNING .160, LINE .403, SEGMENT CONTAINS PRIVILEGED INSTRUCTIONS 404 END ASSEMBLY COMPLETE, WARNING, NO EIlRJRS
o Z
-t
en
<0
LAPX286 MACR3
syst9~-ID
ASSE~BLE~
DEFIN~
SEGM~NTS
N~EJEQ
=O~
I~IT
CJCE
~=F
date
PAG ::
iAPX236 MAC~O ASS ~3L=R VX.y ASSEMeLY CF McaULE S::GMENT 3BJECT MODULE ?LACEO IN :F1: EGS.03J ASSEMBLE~ INVOKED ~Y: :~1:A M286.86 :c1:SEGS.A86 LOC OBJ LINE 1 +1 2
3 4 5 6
7
SJU~CE
t
(J)
STI TlE( DEFINE SEGMENTS NEEJEJ FeR INIT caOE) NAME INIT _ STACKO INIT_STACKO LOT S EG SEGMENT_D::F SEG"IENT Rio! Ow ENDS SEGMENT RW 8 DUP CD CW ENDS SEGMENT RW 8 CUP OW ENDS SEG"IENT iHI 8 OUP DW ENOS S "GMErH RW 8 OUP (1) DW ENCS END Ne
ERRC:~S
0000 1171
Clefine stack 50 mode 5~itc~ code C3n run in protected node Define ali3s segments whose true size ~ust be set by the BLDZ8S com:11and file
(?)
8
9
0000 (8
1111
)
10
11
(J)
-<
-t
m
3:
~
12 0000 (8 1171
13 14
15 16 11
TSS_SEG IOT_SEG
:; r N
l>
0
(1)
-t
0000 (B 1171
)
18
19
IJT_SEG GDT_SEG
20 21 0000 (3 1171
)
2.2 23 24 25
GOT _S::G
ASSEMBLY COMPLETE.
~
(0
r-;a I'IARNINGS.
0>
INITIAL TASK
date
PAG=
iAPX286 MACRO ASSEMBLER vx.y ASSEMBLY OF MODULE INIT MOO OBJECT MODULE PLACED IN :Fl:INIT.OBJ ASSEMBLER INVOKED BY: :Fl:ASM286.86 :Fl:INIT.AB6 OBJ LINE 1 +1 2 3
4
LOC
5
6
0000 1111
7 B 9 10
11
ow
SEG~ENT
RW PUBLIC
fJ)
E"lCS
SEG~ENT
12
13
ASSUME DB
fJ) ~
-<
-"
.!....
01
14 15
::
Z =i 5> r N
l>
~
~
U)
***
16 001B 17 INIT_START: 001B SEOOOO 18 MOV SI,OFFSET MESSAGE OOlE FC 19 CLO 001F 20 MESS_LOOP: OOlF 2EAC 21 LOOS CS:BYTE PTR (SI) 0021 OACO 22 OR AL,AL 0023 7408 23 JZ INIT_EXJT 24 25 PUSH AX 0025 50 0026 9AOOOO---E 26 CALL CO 27 J~P MESS_LOOP 002S EBF2 28 INIT_=XIT: 0020 29 HLT 0020 F4 30 31 INIT_CCDE ENOS WARNING .160, LINE .31, SEGMENT CONTAINS PRIVILEGED INSTRUCTIONS 32 END INIT_START,OS:INIT_OATA,SS:INIT_STACK WARNING. NO
ERR~RS
o z
Ol
ASSEMBLY COMPLETE,
11
BINDING MODEL
To ensure that the binding process works correctly, it is a good idea to start with a model of the system structure you wish to achieve. A binding model includes these factors: Modules-dividing programming into compilation units Segmentation-distributing instructions and data of modules among physical segments Interfaces-specifying the connections among modules Naming-choosing names for modules, segments, and interfaces, avoiding ambiguity but promoting flexibility Timing-determining when to bind various types of symbolic references
As an example of a binding model, assume that the example modules presented in prior chapters constitute a complete operating system, called XOS, and apply each of these factors to XOS.
Modules
The criteria used to separate functions into modules may include Comprehensibility. Each module collects together functions that support a single operating system concept of limited scope (for example, aliases, synchronization). Information hiding. Each module implements a data structure (for example, the alias lists in the ALIAS module) that you can manipulate only by calling the procedures defined in the module for that purpose. Other modules cannot access the data structure. Independent development. You can choose modules so that each can be developed by a different programmer. Points of cooperation and communication among programmers include only the specified interfaces among modules. Minimizing the number and complexity of interfaces reduces project administration costs. Structured testing. Testing of the whole system is simpler when you choose modules so that each can be tested by itself, before testing its interactions with other modules. Flexibility. When you can anticipate changes to the system, you can limit the effects of the changes on other modules by isolating the areas of expected change in a module.
Only the first of these criteria is significant to XOS, but all may be applicable to your operating system design.
11-1
121960~001
Modules are relevant to binding in that they (indirectly) define the units that can be distributed among physical segments. A module is a single compilation unit. Intel's translators divide each compilation unit into logical segments. Each logical segment is a named object that can be assigned to a physical segment. You can use the development tool Binder to combine more that one logical segment into a physical segment.
Segmentation
Protection requirements partially dictate how to distribute modules among physical segments: Data and procedures of different privilege levels must reside in different physical segments. Data and procedures of one task must reside in different segments from those of other tasks unless sharing is explicitly intended. Instructions must reside in different physical segments from writable data items. Data structures for which you wish to provide individual protection (for example, the semaphores and mailboxes discussed in Chapter 5) must each be in a separate segment.
Operating system procedures that have the same privilege level and are shared via the GDT can be combined in just one segment (assuming that the total size does not exceed 64K bytes). In fact, doing so has two advantages: all intermodule calls can be implemented as short CALL instructions, avoiding the additional processing associated with changing the contents of the CS register,and more GDT slots are available for other purposes. Of the procedures in XOS, the level-zero procedures presented in Chapters 3 thru 5 can be combined in one segment, while the level-one I/O interface procedures can go in another segment. Each device-driver task has its own code, data, and stack segments.
Interfaces
Possible mechanisms for implementing the interfaces among modules are Intrasegment (short) references. References to data or procedures in the same segment are most efficiently implemented when you can use the current contents of a segment register. Intersegment (long) references. References to data or procedures in a segment not currently indicated by one of the segment registers must cause a segment selector to be loaded into a segment register. Intersegment references permit sharing of functions among many modules and permit access to functions at another privilege level. Sharing by value. Procedures and data can be shared by including a copy of the data or procedures in the same unit (segment or task, as appropriate) as each procedure that uses them. While this approach can yield more efficient execution in some cases, it has limited applicability. It is usually best to share dynamically changing data by name, so that all the procedures that use it can obtain the most up-to-date version. Sharing large or widely used data or procedures by name uses main memory more efficiently. Sharing by name. The "name" referred to here is the descriptor of the shared data or procedure. Chapter 5 discusses methods of sharing by name (namely GDT, common LDT, and aliases).
In XOS, all tasks share the segments of the kernel and I/O-interface segments via the GDT. Applications procedures use long calls to access the primitives in these segments. Calls within the kernel level or within the I/O level to private procedures at the same level are short calls.
11-2
121960-001
Naming
The names by which you reference the components of a system influence the way the system can be bound. Classes of names over which you have some degree of control arc Modules. Builder uses the name of a module to represent all publics or all segments within the module. Debuggers use module names to qualify identifiers of variables and procedures. Logical segments. The choice of logical segment names determines the possibilities for segment combination. Binder combines logical segments that have the same name as well as compatible combine-types. Physical segments. The names of physical segments give you the ability to assign segment attributes individually using the Builder. Publics. Public identifiers must be unique among the modules that are bound together. Gates. Gate names identify the entry points to procedures. You can use gate names to give entry points different public names than those used in the source language.
Timing
With respect to time, you can rate bindings on a scale running from early to late. An example of early binding is a compiler's assignment of segment-relative locations to procedures and data. The latest binding is that accomplished by the processor as it adds a segment-relative location to the 24-bit base address of the segment. Between these extremes are other opportunities for binding: Post-compile-time. Through Intel's utilities Builder and Binder, you can combine segments, resolve intersegment references, allocate descriptor table slots, and allocate memory. Load-time. The loader can incorporate various levels of binding. a. If the object module contains fix-up information (as in a linkable module), the loader can bind all references as it loads the segments of a task. b. The call gates of the iAPX 286 architecture make it possible for the loader to efficiently resolve references to predefined classes of procedures (to operating system primitives, for example) at the time a program is being loaded. This chapter presents an example of this form of load-time binding in a later section. Run-time. Call gates also permit binding to an executable segment at the time it is first referenced. By resetting the present bit in a call gate to an unloaded segment, you ensure that a trap will occur when the gate is used. The "not present" trap handler can then load the required segment, allocate a descriptor for it, and fix up the call gate.
11-3
121960-001
The model behind the example operating system, XOS, includes these components: Each module contains functionally related data structures and procedures. One segment contains level-zero (kernel) procedures, another segment contains level-zero data, another segment level-one (I/O) procedures, and another level-one data. Operating system tasks (such as device drivers) have their own distinct segments. The GDT contains descriptors of kernel and I/O segments, making them sharable by all tasks. Gates for operating-system primitives, however, reside in the LDTs of the tasks that use them. The segment names created by PL/M-286 set the standard for segment naming in general. (Refer to the chapter entitled "Linking to Modules Written in Other Languages" in the PL/M-286 User's Guide for definition of PL/M-286 segment names). Load-time binding to XOS primitives is an option. (This is one reason for placing gates for operatingsystem primitives in LDTs.)
Source Code
Since some of the logical segments declared in assembly language may be combined after assembly by the Builder, the assembler needs to know whether the object of an external reference will be in one of those segments whose descriptors it 'assumes to be loaded in segment registers. If the reference is to another segment, the assembler must emit instructions that change the contents of a segment register. The programmer supplies this information via additional assembly language syntax. A variety of forms are available for this purpose, such as
SEGMENT ASSUME N EAR and FAR variants of PRO C and LAB E L segment overrides (for example E S : TAB L E_ I T EM)
(Refer to the ASM286 Assembly Language Reference Manual for details on the use of these items.) The module DISP containing the dispatcher is the only kernel module of XOS written in assembly language (refer to Chapter 4). The logical code segment has the name NUCLEUS_CODE and combine type ER so that it will combine with PL/M-286 segments of the same name. This module has no logical data segment. The procedure DISPATCHER is a NEAR procedure because only other kernel procedures in the same physical segment call it.
Compilers
With PL/M-286, decisions regarding segmentation are not imbedded in source code but rather are implemented by the compiler according to compiler control statements that you supply. (Refer to the SMALL, COMPACT, LARGE, and extended segmentation controls in the PL/M-286 User's Guide.) With these control statements, you have nearly as much control over system structure as with assembly language, but changes in system structure do not require changes to source code. It is just as important, however, that use of these controls conform to a consistent model of system structure. Figure 11-1 shows the segmentation controls used for compiling the kernel modules of XOS. These controls define a subsystem named NUCLEUS that contains all the PL-O modules of XOS. The PL/M-286 compiler prefixes the names of the code and data segments with the subsystem name. The list of exports includes all the primitives. For each of the procedures named in the exports list, the
11-4
121960-001
$ COMPACT (NUCLEUS HAS SLOT $ GATE $ DISPATCHER $ SEMAPH $ INTRUPT $ DESCRIPTOR $ DISQUE $ $ EXPORTS RESERVE SLOTS $ ALLOCATE $ CREATE ALIAS $ WAIT SEMAPHORE $ SEND-MESSAGE $ CREATE LDT $ LOAD LOT $ GET GATE POINTER $ ATTACH TO INTERRUPT $
POINT MEMORY ALIAS MAILBOX TASK GATE MESSAGE RELINQUISH_SLOTS FREE SEG CHANGE AR SIGNAL-SEMAPHORE RECEIVE MESSAGE CREATE TASK LOAD_LOT_GATE
WAIT_FOR_INTERRUPT
compiler generates a long RET instruction at the end of the procedure or at RETURN statements. This enables procedures in other segments to call the the kernel procedures. The keyword COMPACT tells the compiler to generate short RET instructions for procedures not named in the export list.
Binding Utilities
Intel's iAPX 286 Binder (BND286) and System Builder (BLD286) provide a variety of binding services, including Combining logical segments that have the same name and combine type Resolving references among modules Constructing templates for GDT, LDT, and TSSs Allocating memory for bootloadable portions of the system Assigning access rights to segments
11-5
121960-001
Constructing gates Formatting object files for the convenience of boot loaders and dynamic loaders Creating export modules that contain gates for operating-system interfaces
Figure 11-2 shows the Binder specifications that combine the level-zero modules of XOS. The input modules contain only three unique segment names (the PL/M-286 names: NUCLEUS_CODE, NUCLEUS_DATA, and STACK); therefore, the output module contains just three segments: one for instructions, one for static data items, and one for the level-zero stack. The name of the output module is NUCLEUS; it is written to the file NUC.LNK. Similar specifications combine the level-one modules. Figure 11-3 shows the specifications to build a bootloadable file for the example operating system. The SEGMENT statement assigns privilege levels to to each of the segments; segments not mentioned in this clause receive privilege level 3 (PL 3) by default. The TABLE statement defines the descriptor tables. The RESERVE clause allocates space for the working descriptors used by such modules as the memory-management module described in Chapter 3. The ENTRY clause identifies the remaining segment descriptors that belong in each table. Builder allocates slots for each of these descriptors. The TASK statement provides information for contructing TSSs. The identifier assigned to each task is the identifier of the descriptor of its TSS. The OBJECT clause identifies the module containing the information Builder can use to fill the segment-register and initial stack fields of the TSS. The GATE statement creates gates for each of the public procedures that are XOS primitives, assigns a privilege level to each gate, and gives each a name different from the procedure name. The EXPORT statement creates a linkable module KERNEL in file XOS.EXP that application modules can use for binding to the gates for XOS primitives.
RUN :F2:BND286 & :Fl:POINT.OBJ, :Fl:SLOT.OBJ, & :Fl:MEMORY.OBJ, :Fl:DISP.OBJ, & :Fl:ALIAS.OBJ, :Fl:SEMAPH.OBJ, & :Fl:MBOX.OBJ, :Fl:INTRPT.OBJ, & :Fl:DESCR.OBJ, :Fl:DISQUE.OBJ, & :Fl:TASK.OBJ :Fl:MESSAG.OBJ, & PLM286.LIB & NAME (NUCLEUS) OBJECT (:Fl:NUC.LNK) NOLOAD DEBUG
11-6
121960-001
inler
system-ID
:F1:NUC.LNK, :F1:URTASK.OBJ, :F1:CONSOL.OBJ, :Fl:LOADER.LNK, :F2:LARGE.LB2, :F1:STACKS.OBJ OUTPUT FILE: :F1:XOS CONTROLS SPECIFIED: TITLE(Examp1e O.S.) BOOT LOAD BUILDFILE(:F1:XOS.BLD) OBJECT (:F1: XOS) BUILD FILE:
1 2 3 4 5
6
INPUT FILES:
:F1:XOS.BLD
7 8 9 10
11 12
13
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
SEGMENT NUCLEUS CODE NUCLEUS-DATA NUCLEUS:-STACK URTASK CODE URTASK-DATA URTASK:-STACK LQ PLM286 LIB CODE LARGE V1P0.STACK0 LARGE-VIP0.STACKl LARGE-V1P0.STACK2 CONSOLE DRIVER CODE CONSOLE-DRIVER-DATA CONSOLE-DRIVER:-STACK CONSOLE-STACK0 LOADER_STACK0
(DPL=O) , (DPL=0) , (DPL=0, LIMIT=+20), (DPL=0) , (DPL=0) , (DPL=0, LIMIT=+20H), (DPL=0, CONFORMING), (DPL=0) , (DPL=l) , (DPL=2), (DPL=1) , (DPL=1) , (DPL=1, LIMIT=+20), (DPL=0, LIMIT=+20), (DPL=0, LIMIT=+20); DPL=1) DPL=1) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) DPL=3) , , , , , , , , , , , , , , , , ,
GATE XQ ATTACH TO INTERRUPT (ENTRY~ATTACH TO INTERRUPT, XQ-WAIT FOR INTERRUPT (ENTRY=WAIT FOR INTERRUPT, XQ-RESERVE SLOTS (ENTRY=RESERVE SLOTS, XQ-RELINQUISH SLOTS (ENTRY=RELINQUISH_SLOTS, XQ-ALLOCATE (ENTRY=ALLOCATE, XQ-FREE SEG (ENTRY=FREE SEG, XQ-CREATE ALIAS (ENTRY=CREATE_ALIAS, XQ-CHANGE-AR (ENTRY=CHANGE AR, XQ-WAIT SEMAPHORE (ENTRY=WAIT SEMAPHORE, XQ-SIGNAL SEMAPHORE (ENTRY=SIGNAL SEMAPHORE, XQ-SEND MESSAGE (ENTRY=SEND MESSAGE, XQ-RECEIVE MESSAGE (ENTRY=RECEIVE MESSAGE, XQ-CREATE LDT (ENTRY=CREATE_LDT, XQ-CREATE-TASK (ENTRY=CREATE TASK, XQ-LOAD LDT (ENTRY=LOAD LDT, XQ-LOAD-LDT GATE (ENTRY=LOAD-LDT GATE, XQ-GET GATE-POINTER (ENTRY=GET GATE-POINTER, TI~E SLICE 1INTERRUPT, DPL=0, ENTRY=TI~INT); TABLE GDT (RESERVE=(4 . 9), ENTRY=( NUCLEUS CODE, NUCLEUS-DATA, NUCLEUS:-STACK, LQ PLM286 LIB CODE, LARGE_V1P0.STACK,
11-7
121960-001
47 48
49
50 51 52 53 54 55 56 57 58 59
60
)
)
URTASK LOT (ENTRY=(URTASK, CONSOLE LOT (ENTRY=(CONSOLE DRIVER, CONSOLE STACK0, LOADER TASK LOT (ENTRY=(LOADER, LOADER STACK0, lOT (ENTRY=(15:TIME_SLICE; TASK ADAM (INITIAL, OBJECT LOT CONSOLE DEVICE (OBJECT LOT STACKS LOADER TASK (OBJECT LOT STACKS URTASK, URTASK LOT) , CONSOLE DRIVER, CONSOLE-LOT, (CONSOLE STACK0) ) , LOADER, LOADER TASK LOT, (LOADER_STACK0;
61
62
63 64 65 66 67 68
69
70 71 72 73 74 75 76 77 78 79
EXPORT #:F1:XOS.LB2 (KERNEL XQ RESERVE SLOTS, XQ-RELINQUISH SLOTS, XQ-ALLOCATE, XQ-FREE SEG, XQ-CREATE ALIAS, XQ-CHANGE-AR, XQ_WAIT SEMAPHORE, xQ_SIGNAL SEMAPHORE, XQ-SEND MESSAGE, XQ=RECEIVE_MESSAGE; END
These specifications do not illustrate all the features of Builder; refer to the iAPX 286 System Builder User's Guide for a complete description of Builder syntax.
OVERVIEW OF LOADING
The loader in a dynamic system is not only responsible for copying a program into main memory, but is also a step in the binding process. A loader installs the actual TSS and LDT for a task, thereby making it possible for the processor to interpret the task's memory references.
If all symbolic references are already resolved, a loader's work is simple. The iAPX 286 object module format (OMF) organizes segment information to facilitate rapid loading with little decision-making by the loader program.
11-8
121960-001
Either the following structures must be present or some mechanism must be in place to make them present when necessary: Stack segments for each privilege level at which the task runs. (A stack-fault handler could automatically allocate a stack the first time it is used.) Executable and data segments. (A virtual memory system could make these present when referenced.)
Most programs also need an LDT to contain descriptors for segments private to the task. An LOT is not required, however, if all descriptors used by the task reside in the GOT. The initial values in the CS:IP fields of the TSS should point to the entry point of the first procedure of the new task.
STYLES OF LOADERS
There are several ways to structure a loader. The following are just a few examples: 1. As a separate and permanent task. With such a structure the loader constructs data segments in the format of the new task's TSS and LDT. To create the new task, it passes descriptors for these segments to privilege-level 0 (PL-O) procedures that convert them to system segments and start the new task. As procedures that run within an existing task. This approach suits the UNIX EXECUTE function, where the FORK function creates the task in which the loader runs as a duplicate of the task that called the FORK function. The loader deletes the descriptors it finds in the task's LOT (thereby deleting the associated segments unless aliases exist in other tasks) and creates new descriptors for the segments it loads. As procedures in a skeletal task created by the operating-system kernel. The loader has only to allocate an LOT and install descriptors for the segments it loads.
2.
3.
For approaches 2 and 3, the procedures of the loader may have segment descriptors and gates in the GOT so as not to encumber the LOTs.
KERNEL SUPPORT
A loader normally runs at PLs 2 or 3 because it uses of both kernel-level procedures (for example, ALLOCATE to create a segment for the new task) and PL-l procedures (for example, the I/O procedures to read object modules from disk). However, task creation involves some functions that only
11-9
121960-001
intel"
PL-O procedures can execute. For these functions the operating system must provide some additional support. These functions include Changing the access rights byte of a descriptor. The loader can create a writable data segment (using a level-O procedure such as the ALLOCATE procedure described in Chapter 3) into which to read a segment from the object file of the program being loaded. But, if that segment is to have some other type in the new task (the segment might be an executable segment, for example), the access rights byte must be changed. Filling the new task's LOT with the base addresses of its segments. When the loader allocates a segment for the new task, the ALLOCATE procedure places the physical base address of the segment in a descriptor table (presumably the loader's LOT, but possibly the GOT). Only PL-O procedures should have access to physical addresses in descriptor tables. Allocating the stack segment for PL O. Insufficient space in this segment can cause failure of PL-O procedures. Also, if the kernel requires the TSS to be located in the PL-O stack segment (as suggested in Chapter 4), then the kernel should handle the complexities of setting up such a structure. Initializing the task database (TOB) for the new task. Only PL-O procedures have access to this data structure. (Refer to Chapter 4 for a discussion of the task database.) Entering the new task in the scheduling queues and setting the back-link and nested task flag in the new TSS. These operations are crucial to proper functioning of the scheduler and therefore should be done at PL O.
Refer to the iAPX 286 System Builder User's Guide for detailed definitions of the iAPX 286 Object Module Format. Loaders that adhere to Intel's OMFs for loadable modules can load object modules created by Intel's program development tools. There are two basic variations of the iAPX 286 OMF for loadable modules: That created by the Binder supports straightforward, single-task modules. That created by the Builder supports more complex variations, including multitask modules with shared segments (possibly including shared LOTs), reserved LOT locations, GOT descriptors to be installed as the task is loaded, etc.
Builder not only produces modules intended for use by dynamic loaders but also produces bootloadable modules designed for use by bootstrap or initializing loaders. Bootloadable modules use absolute addresses. A boot loader must be able to write to absolute physical locations.
11-10
121960-001
The OMF of each object module consists of a header followed by a sequence of sections of various kinds. The sections relevant to this discussion are those in loadable modules, including OESCRP: contains all the descriptors for the module. A loader can use this section as a template for the LOT. LOOTXT: contains the data and instructions to be loaded. A loader fills allocated memory segments from the records of LOOTXT. OESNAM: provides symbolic names for segments. A loader can use these symbolic names to provide a load-time interface for making changes to segment parameters (for example, decreasing segment limit of an expand-down stack segment to provide more stack space).
Flow of Loader
A loader must take different action depending on whether the loadable modules are created by the Binder or by the Builder. The main difference in loading the two types of OMF is the source of information for descriptor tables. In the case of Binder OMFs, the OESCRP section is in the format of an LOT. In the case of Builder-created OMFs, information for the GOT, lOT, and LOTs comes from various LOOTXT records. A Boolean in the header of a load able module distinguishes between Buildercreated and Binder-created modules.
FLOW FOR BINDER-CREATED MODULE
1. 2. 3. 4. 5. 6. 7. 8.
Allocate space for LOT segment. The size of the segment is eight times the value of the descriptor count field of the module header. Put LOT descriptor in GOT. Read the OESCR section into the LOT segment. Allocate space for all segments specified in the LOT, updating the base-address fields. Allocate space for the TSS. (Step 3 does not allocate the TSS because the OESCR section does not contain a TSS descriptor.) Put TSS descriptor in GOT. Read first LOOTXT section into TSS segment. (The first LOOTXT record is always a TSS.) Put LOT selector into TSS.
If the LOOTXT section is exhausted, the task is completely loaded. Jump to the TSS.
Read next LOOTXT record into proper segment. Go to step 7.
1. 2. 3. 4. 5.
Allocate temporary space to hold all entries from the OESCRP section. Read the OESCRP section into this space. Allocate physical segments for all OESCRP entries (except for gates). Read beginning of LOOTXT record. Examine descriptor name of LOOTXT record. The selector name is either a special identifier for the GOT or lOT, or it is an index into the OESCRP entries. The type field of a OESCRP entry distinguishes LOT segments from other types. a. If the LOOTXT record defines entries of the GOT, then, for each entry in the record, obtain the descriptor from OESCRP and install it in the GOT. b. If the LOOTXT record defines entries of the lOT, then, for each entry in the record, obtain the descriptor from OESCRP and install it in the lOT.
11-11
121960-001
inter
c. If the LODTXT record defines an LOT, then, for each entry in the record, obtain the descriptor from DESCRP and install it in the LDT. d. If the LODTXT record does not apply to a descriptor table, read the LODTXT record directly into the selected segment. . 6. 7. 8.
If more LODTXT records remain, go to step 4.
Free the space used for DESCRP entries. The task or tasks are loaded. Jump to the TSS identified in the module header.
LOAD-TIME BINDING
As with any system, it is possible on the iAPX 286 to delay many binding operations until load time by incorporating binding functions into the loader. The call gates of the iAPX 286 architecture, however, provide an especially convenient and efficient way to delay one specific binding operation: namely, binding of calls to operating-system primitives. Load-time binding to operating-system primitives is an advantage when The operating system is under development, and GDT locations of operating-system segment descriptors are subject to change Programs may execute under different operating systems that have different GOT layouts
Data structures for implementing load-time binding are An export module of specially marked, dummy gates for operating system primitives. Figure 11-4 shows how you can create such a module through Builder specifications. The NOT PRESENT specification marks the gates by resetting the present bit. Gates used for this purpose must reside in the LDT so that Binder (which works only with LDT descriptors) can use them. You need to update this export file only when you change the number or names of operating-system gates. A table of actual gates for the operating-system primitives. This table must contain, for each primitive, the gate name, a GDT selector for the segment in which the primitive resides, and the entry point (offset) within the segment. It is most convenient to take such information from a Builder export file that exports the gates for operating-system primitives. The example specifications shown in figure 11-3 create such an export file.
Figure 11-5 shows the data flow for load-time binding. By using the gate name from the DESNAM section, the loader associates a marked gate in the LOT with its gate name. Given the gate name, it looks up the actual binding information.
EXAMPLE LOADER
Figure 11-6 shows an example of a loader that reads the iAPX 286 OMF, resolves references to operating-system primitives, and calls kernel procedures to create a new task. In the interest of simplicity, this example recognizes only the single-task OMF produced by the Binder, and all error checking is omitted. This loader calls the kernel procedures CREATE_LDT, LOAD_LDT, LOAD_LDT_GATE, CREATE_TASK, RESERVE_SLOTS, and CHANGE_AR, which are not shown. CREATE_LDT allocates an LDT segment for a new task and installs its descriptors in two of the four GDT slots specified by TASICSEL. LOAD_LDT transfers a descriptor from the LDT of the loader to the LDT of the new task. LOAD_LDT_GATE places a gate in the LDT of the new task. CREATE_TASK
11-12
121960-001
inter
system-ID
INPUT FILES: :F1:NUC.LNK OUTPUT FILE: (none) CONTROLS SPECIFIED: TITLE(Gates for Load-Time Binding) NOBOOTLOAD NOOBJECT BUILDFILE(:F1:XOSGAT.BLD) PRINT(:F1:XOSGAT.MP2) BUILD FILE:
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
24
GATE XQ - RESERVE SLOTS XQ RELINQUISH SLOTS XQ ALLOCATE XQ FREE SEG XQ-CREATE ALIAS XQ=CHANGE-AR XQ WAIT SEMAPHORE XQ SIGNAL SEMAPHORE XQ SEND MESSAGE XQ RECEIVE - MESSAGE -
(ENTRY=RES ERVE SLOTS, (ENTRY=RELINQUISH_SLOTS, (ENTRY=ALLOCATE, (ENTRY=FREE SEG, (ENTRY=CREATE ALIAS, (ENTRY=CHANGE_AR, (ENTRY=WAIT SEMAPHORE, (ENTRY=S IGNAL SEMAPHORE, (ENTRY=SEND MESSAGE, (ENTRY=RECEIVE MESSAGE,
DPL=3, DPL=3, DPL=3, DPL=3, DPL=3, DPL=3, DPL=3, DPL=3, DPL=3, DPL=3,
NOT NOT NOT NOT NOT NOT NOT NOT NOT NOT
PRESENT) PRESENT) PRES ENT) PRESENT) PRESENT) PRESENT) PRESENT) PRESENT) PRES ENT) PRESENT)
, , , , , , , , , ;
TABLE GDT (ENTRY=(NUCLEUS_CODE, NUCLEUS_DATA, NUCLEUS.STACK)), DUMMY (ENTRY= ( XQ RESERVE SLOTS, XQ-RELINQUISH SLOTS, XQ-ALLOCATE, XQ-FREE SEG, XQ-CREATE ALIAS, XQ-CHANGE-AR, XQ-WAIT SEMAPHORE, XQ-SIGNAL SEMAPHORE, XQ_SEND MESSAGE, XQ=RECEIVE_MESSAGE)); EXPORT #:Fl:XOSGAT.LB2 (KERNEL XQ RESERVE SLOTS, XQ-RELINQUISH SLOTS, XQ-ALLOCATE, XQ-FREE SEG, XQ_CREATE ALIAS, XQ-CHANGE-AR, XQ-WAIT SEMAPHORE, XQ-SIGNAL SEMAPHORE, XQ-SEND MESSAGE, XQ-RECEIVE_MESSAGE)); END
25 26 27 28 29 30 31 32
33
34 35 36
37
38 39 40 41
42
43 44 45
11-13
121960-001
BINDING LOADER
121960-55
finishes creation of the new task by creating a TSS from a template in the loader and placing the new task in the scheduler's queues. RESERVE_SLOTS uses techniques such as those illustrated in Chapter 2 to allocate descriptor table slots. CHANGE_AR is used to place the correct type code into the writable data-segment descriptor used by the loader to fill a segment. The module BOND (shown in figure 11-7) shows the handling of the table of actual gates for operating-system primitives. The procedure GET_LOAD_FILE is not defined here. It simply fetches the file specification for a load able module from, for example, the console or the command line interpreter.
11-14
121960-001
PL/M-286 COMPILER
960-515
date
PAGE
system-ID PL/M-286 Vx.y COMPILATION OF MODULE LOADER OBJECT MODULE PLACED IN :Fl:LOADER.OBJ COMPILER INVOKED BY: PLM286.86 :Fl:LOADER.PLM DEBUG
$ $ $ $ $
1
PAGEWIDTH(71) TITLE('960-515') INCLUDE (:Fl:NUCSUB.PLM) NOLIST INCLUDE (:Fl:UDISUB.PLM) NOLIST $ COMPACT DO; Language Extensions LITERALLY LITERALLY LITERALLY LITERALLY LITERALLY LITERALLY LITERALLY 'BYTE' , '0' , '0FFH' , 'WORD' , 'TOKEN' , 'WORD' , 'WHILE TRUE';
LOADER:
/***************************************************** **/
/*
2 1 DECLARE BOOLEAN FALSE TRUE TOKEN CONNECTION OFFSET FOREVER
*/
/***************************************************** **/
/*
3
Ex ternal s
*/
1 2 2 1 2 2 1 2 2 1 2
2
4 5 6 7 8 9 10
11
RESERVE SLOTS: PROCEDURE(TABLE,COUNT,SLOT_PTR,EXCEP_PT~) EXTERNAL; DECLARE TABLE WORD, COUNT WORD, (SLOT_PTR,EXCEP_PTR) POINTER; END RESERVE_SLOTS; CHANGE AR: PROCEDURE (SLOT,RIGHTS,EXCEP PTR) EXTERNAL; DECLARE SLOT SELECTOR, RIGHTS BYTE, EXCEP PTR POINTER; END CHANGE_AR; ALLOCATE: PROCEDURE (SLOT,RIGHTS,SIZE,EXCEP_PTR) EXTERNAL; DECLARE SLOT SELECTOR, RIGHTS BYTE, SIZE WORD, EXCEP PTR POINTER; END ALLOCATE; FREE SEG: PROCEDURE (SLOT, EXCEP PTR) EXTERNAL; DECLARE SLOT SELECTOR, EXCEP_PTR POINTER; END FREE_SEG; CREATE LOT: PROCEDURE(TASK SEL,SIZE,EXCEP PTR) EXTERNAL; DECLARE TASK SEL SELECTOR~ SIZE WORD, EXCEP PTR POINTER; END CREATE_LOT; LOAD LOT: PROCEDURE (TASK SEL, NEW SLOT, OLD SLOT, EXCEP PTR) EXTERNAL; DECLARE (TASK SEL, NEW SLOT, OLD_SLOT) SELECTOR, EXCEP_PTR POINTER; -
12 13 14 15 16 17 18 19
1 2 2 1 2
11-15
121960-001
PL/M-286 COMPILER 20 21 22 23 2 1 2 2
960-515
date
PAGE
LOAD LOT GATE: PROCEDURE (TASK SEL, NEW SLOT, RIGHTS, TARGET~ COUNT, EXCEP PTR) EXTERNAL; DECLARE (TASK SEL, NEW SLOT) SELECTOR, RIGHTS BYTE, (TARGET, EXCEP PTR) POINTER, COUNT BYTE; END LOAD_LDT_GATE; CREATE TASK: PROCEDURE (TASK SEL, TEMPLATE, PRIORITY, EXCEP PTR) EXTERNAL; DECLARE TASK SEL SELECTOR, (TEMPLATE, EXCEP_PTR) POINTER, PRIORITY BYTE; END CREATE_TASK; GET LOAD FILE: PROCEDURE (FILE SPEC PTR) EXTERNAL; DECLARE-FILE SPEC PTR POINTERT END GET_LOAD=FILET BUILD BOND TABLE: PROCEDURE (FILESPEC_PTR, EXCEP_PTR) EXTERNAL; DECLARE (FILESPEC PTR, EXCEP PTR) .POINTERi END BUILD_BONO_TABLE; FIND BOND: PROCEDURE (SNAME PTR, ENTRY PTR, SEL_PTR, EXCEP PTR) EXTERNAL; DECLARE (SNAME_PTR, ENTRY_PTR, SEL_PTR, EXCEP_PTR) POINTER; END FIND_BONDi INITIALIZE SYSTEM: PROCEDURE EXTERNAL; END INITIALIZE_SYSTEM; REPORT: PROCEDURE (EXCEP PTR) DECLARE EXCEP PTR POINTER; END REPORT; . EXTERNAL;
24
25 26
1
2 2
27
28 29 30 31 32 33
34
1
2 2 1
2 2
1
2
35 36 37 38 39
2
1
2
1
40 41 42
43
2 2
1 2
2
DQ$ATTACH: PROCEDURE (PATH$P, EXCEP$P) CONNECTION EXTERNAL; DECLARE (PATH$P, EXCEP$P) POINTER; END DQ$ATTACH; PROCEDURE (CONN, EXCEP$P) EXTERNALi DQ$DETACH: DECLARE CONN 'CONNECTION, EXCEP$P POINTER; END DQ$DETACH; DQ$OPEN: PROCEDURE (CONN, ACCESS, NUM$BUF, EXCEP$P) EXTERNAL; DECLARE CONN CONNECTION, (ACCESS, NUM$BUF) BYTE, EXCEP$P POINTER; END DQ$OPEN; DQ$SEEK: PROCEDURE (CONN, MODE, LOCATION, EXCEP$P) EXTERNAL; DECLARE CONN CONNECTION, MODE BYTE, LOCATION DWORD, EXCEP$P POINTER; END DQ$SEEK;
44
45
1
2
46 47 48
49
50 51 52
2 1 2
2
1
2 2
Figur~
11-16
121960-001
PL/M-286 COMPILER 53 54 55 56 57 58
1 2 2
960-515
date
PAGE
PROCEDURE DQ$READ: (CONN, BUF$P, COUNT, EXCEP$P) WORD EXTERNAL; DECLARE CONN CONNECTION, COUNT WORD, (BUF$P, EXCEP$P) POINTER; END DQ$READ; DQ$CLOSE: PROCEDURE (CONN, EXCEP$P) EXTERNAL; DECLARE CONN CONNECTION, EXCEP$P POINTER; END DQ$CLOSE;
1 2 2
/*******************************************************/ /* Da ta */
59
1
DECLARE IN GDT LITERALLY '0', IN-LDT LITERALLY '1', DATA W LITERALLY 'lll10010B', /* Access rights: present~ DPL=3, expand-up, writable, data segment */ DATA WD LITERALLY '111101108', /* Access rights: present, DPL=3, expand-down, writable, data segment */ READ LITERALLY '1', DEFAULT PRIORITY LITERALLY '4', ALLOCATED LITERALLY '80H', OK LITERALLY '0', EXCEPTION LITERALLY 'EXCEP<)OK';
60
/* Disk file to load */ DECLARE PATH NAME (47) BYTE, LOAD-FILE CONNECTION, WORD, ACTUAL EXCEP WORD, SELECTOR, /* First of GDT slots TASK_SLOT for new task */ SELECTOR, /* Data or code segment of new task */ BOND FILESPEC (*) BYTE INITIAL (11 , ' : F 1 : XOS LB 2 ' ) ;
DECLARE FILE_HEADER DECLARE MODULE HEADER TOTAL-SPACE DESCR=COUNT BUILT DATE TIME CREATOR TSS SEL DESCRP LOC LODTXT-LOC IGNORE-l DESNAM-LOC IGNORE-2 IGNORE-3 IGNORE-4 LAST LOC RESERVEDl BYTE; STRUCTURE DWORD, WORD, BYTE, BYTE, BYTE, BYTE, WORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD,
61 62
1 1
(8 ) (8 ) (41 )
/* /* /* /* /* /* /* /*
0 */
1 */
2 3 4 5 6 7
*/ */ */ */ */ */
11-17
121960-001
PL/M-286 COMPILER
960-515 RESERVED2
date DWORD);
PAGE
63
/* Table of segment names from DESNAM section of OMF */ DECLARE DESNAM SEL SELECTOR, DESNAM-WIDTH LITERALLY '41', DESNAM-BASED DESNAM SEL (2) STRUCTURE ( NAME (DESNAM WIDTH) BYTE ), WORD; /* Index */ DIX /* RAM copy of DESCRP section of OMF */ DECLARE DESCRP SEL SELECTOR, SEGDT BASED DESCRP SEL (2) STRUCTURE LIMIT WORD,LO BASE WORD, HI-BASE BYTE, /* Data/code segment descr */ RIGHTS BYTE, RESERVED WORD ), GATET BASED DESCRP SEL (2) STRUCTURE ( ENTRY POINT OFFSET, SEL SELECTOR, WORD COUNT BYTE, /* Gate descriptor */ RIGHTS BYTE, ) , RESERVED WORD LIX WORD; /* Index * / /* Template for Task State Segment for new task */ DECLARE TSS STRUCTURE ( BACKL SELECTOR, SP0 OFFSET, SS0 SELECTOR, SPl OFFSET, SSl SELECTOR, SP2 OFFSET, SS2 SELECTOR, IP OFFSET, FLAG WORD, (AX, CX, DX, BX, SP, BP, SI, DI, ES, CS, SS, DS, LDT_LINK) SELECTOR ); /*******************************************************/ /* Subroutines */
64
65
66 67 68
1
2 2
SECTION_SIZE: PROCEDURE (TOCIX) DWORD; DECLARE TOCIX WORD;/* Index into Table of Contents */ DECLARE TOC(8) DWORD AT (@MODULE_HEADER.DESCRP_LOC), IX WORD; /* Find the size of an OMF section */ DO IX=TOCIX+l TO 7; IF TOC(IX)<>0 /* Skip by null sections */ THEN RETURN TOC(IX)-TOC(TOCIX); END; END SECTION_SIZE; /*******************************************************/ BUILD_DESNAM_TABLE: PROCEDURE (DESNAM_SIZE); DECLARE DESNAM SIZE DWORD;
69 70 71 72
73
3 3 3
2
74
75
1 2
11-18
121960-001
PL/M-286 COMPILER
9613-515
date
PAGE
76
DECLARE DESNAM USED DWORD, DESNAM-HEADER STRUCTURE (DESCR IN WORD, NAME_LENGTH BYTE); DESNAM USED=!J; /* Allocate a segment for the table */ CALL ALLOCATE (DESNAM SEL, DATA W, DESNAM WIDTH * (MODULE HEADER.DESCR COUNT + 1), @EXCE -P);IF EXCEPTION THEN CALL REPORT (@EXCEP); /* Initialize the table */ DO DIX=!J TO MODULE HEADER.DESCR COUNT; CALL MOVB(@(' '),@DESNAM(DIX).NAME(!J),l); CALL MOVB(@DESNAM(DIX) .NAME(!J), @DESNAM(DIX) .NAME(l) ,DESNAM_WIDTH-l); END; /* Read each descriptor name */ DO WHILE DESNAM USED < DESNAM SIZE; /* Read fixed-portion of DESNAMrecord */ ACTUAL=DQ$READ (LOAD FILE, @DESNAM HEADER, 3, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); DE"SNAM USED=DESNAM USED+ACTUAL; DIX=DESNAM HEADER.OESCR IN-I; DESNAM(DIX).NAME(0)=DESNAM HEADER. NAME LENGTH; /* Read rest of name into-table entry-*/ ACTUAL=DQ$READ(LOAD FILE,@DESNAM(DIX) .NAME(l) , - DESNAM(DIX) .NAME(!J), @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); DESNAM USED=DESNAM USED+ACTUAL; END /* DO LOOP */; -
77
78 79 81 82 83 84 85 86 87 89 90 91
9.2
2 2 2 2 3 3 3 2 3 3 3 3 3 3 3 3 3 2 1 2 2
93 95 96 97 98 99 11313
DECLARE LODTXT HEADER STRUCTURE LOAD OFFSET WORD, WORD, DESCR IN LENGTH WORD COUNT WORD, LODTXT USED DWORD;
1131
DECLARE NEW LOT SEL SELECTOR, NEW LOT SEL W WORD AT (@NEW LOT SEL), SEG=RIGHTS BYTE; DECLARE TSS_IN LITERALLY '!JFFFDH'; LODTXT USED=!J; /* Step thru all LODTXT records */ DO WHILE LODTXT_USED<LODTXT_SIZE;
2 2 2
11-19
121960-001
PL/M-286 COMPILER
960-515
date
PAGE
105 106 108 109 110 III 112 114 115 116 117 118 119 120 121 122 124 125 127 128 129 131 132 133 135 136 137 138 139 140 141 143 144
3 3 3 3 3 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 2 1 2 2 2 3
1* Read in the LODTXT header *1 ACTUAL=DQ$READ(LOAD FILE,@LODTXT HEADER,6,@EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); LODTXT USED=LODTXT USED+ACTUAL; IF LODTXT_HEADER.DESCR_IN=TSS_IN
THEN DO; 1* Load the Task State Segment *1 ACTUAL=DQ$READ(LOAD FILE,@TSS,LODTXT HEADER. LENGTH, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); LODTXT USED=LODTXT USED+ACTUAL; END 1* loading Task-State Segment *1; ELSE DO; 1* Load a data or code segment *1 LIX=LODTXT HEADER.DESCR IN-I; IF (SEGDT(LIX) .RIGHTSAND 06H) = 06H 1* expand-down data segment? *1 THEN SEG RIGHTS=DATA WD; ELSE SEG-RIGHTS=DATA-W; 1* Allocate a segment *1 CALL ALLOCATE (DCS SEL, SEG RIGHTS, SEGDT(LIX) .LIMI~+l, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); 1* Read LODTXT record into segment *1 ACTUAL=DQ$READ(LOAD FILE, BUILD$PTR(DCS SEL,LODTXT HEADER. LOAD OFFSET), LODTXT HEADER.LENGTH, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); LODTXT USED=LODTXT USED+ACTUAL; 1* Put actual access rights in descriptor *1 CALL CHANGE AR (DCS SEL, SEGDT(LIX) .RIGHTS, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); 1* Construct selector for slot in new LOT *1 1* DPL = 3; TI = 1 *1 NEW LOT SEL W = (SHL(LIX,3) OR 07H); I*-Transfer descriptor to new LOT *1 CALL LOAD LOT (TASK SLOT,NEW LOT SEL,DCS SEL,@EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP);1* Mark descriptor as allocated *1 SEGDT(LIX) .RIGHTS=ALLOCATED; END 1* loading a data or code segment *1; END 1* stepping thru all LODTXT records *1; END LOAD_SEGMENTS;
1*******************************************************1
LOAD_DESCRP: PROCEDURE;
1* Allocate a segment for the DESCRP section *1 CALL ALLOCATE (DESCRP SEL, DATA W, 8*MODULE HEADER.OESCR COUNT, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); 1* Step thru all descriptors *1 DO LIX = 0 TO MODULE HEADER.DESCR COUNT-I; 1* Read LOT entry *1 ACTUAL=DQ$READ (LOAD FILE, @SEGDT(LIX), - 8, @EXCEP);
11-20
121960-001
inter
PL/M-286 COMPILER 145 147
3 3
960-515
date
PAGE
3 3 4
4 4 4 3
2
IF EXCEPTION THEN CALL REPORT (@EXCEP); /* Is it marked with Present bit = 0 ? */ IF (SEGDT(LIX) .RIGHTS AND 80H)=0 THEN /* Is it a call gate? */ IF (SEGDT(LIX) .RIGHTS AND 0FH)=4 /* Type field */ THEN DO; /* Insert pointer from BOND table */ CALL FIND BOND (@DESNAM(LIX) .NAME, @GATET(~IX) .ENTRY POINT, @GATET(LIX) .SEL, @EXCEP); IF EXCEP=OK THEN /* set present bit. */ GATET(LIX) .RIGHTS=GATET(LIX) .RIGHTS OR 80H; END /* inserting pointer */; END /* stepping through all descriptors */; END LOAD_DESCRP; /*******************************************************/ /* Transfer remaining descriptors to new LOT */
156
TRANSFER REMAINDERS: PROCEDURE; /* Handles descriptors for which there was no LODTXT record (e.g. stacks and gates). DECLARE NEW LOT SEL SELECTOR, NEW-LDT-SEL W WORD AT (@NEW LOT SEL), SEG-RIGHTS BYTE; --
*/
157
/* Step thru DESCRP entries, skipping LOT alias */ DO LIX = 2 TO MODULE_HEADER.DESCR_COUNT-l; IF (SEGDT (LIX) .RIGHTS AND 0FH) = 4 THEN /* call-gate */ DO; /* Construct selector for slot in new LOT */ NEW LOT SEL W = (SHL(LIX,3) OR 07H); /*-Transfer descriptor to new LOT */ CALL LOAD LOT GATE (TASK SLOT, NEW LOT SEL, GATET(LIX) .RIGHTS,-BUILD$PTR(GATET(LIX) .SEL, GATET(LIX) .ENTRY POINT), GATET(LIX) .WORD COUNT, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); END /* call gate */; ELSE IF (SEGDT(LIX) .RIGHTS AND 10H) <> 0 THEN /* unallocated data or code segment */ DO; IF (SEGDT(LIX) .RIGHTS AND 06H) = 06H /* expand-down data segment? */ THEN SEG RIGHTS=DATA WDi ELSE SEG-RIGHTS=DATA-W; /* Allocate a segment */ CALL ALLOCATE (DCS SEL, SEG RIGHTS, SEGDT (LI X) LIMIT+l, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP)i /* Put actual access rights in descriptor */ CALL CHANGE AR (DCS SEL, SEGDT(LIX) .RIGHTS, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); /* Construct selector for slot in new LOT */
3 3
4 4
163 165 166 167 168 169 170 171 172 .174 175
4 4 3 3 4 4 4 4 4 4 4
11-21
121960-001
PL/M-286 COMPILER
9613-515
date
PAGE
4
4
4 4
/* DPL = 3; TI = 1 */ NEW LDT SEL W = (SHL(LIX,3) OR 1J7H); /*-Transfer descriptor to new LDT */ CALL LOAD LDT(TASK SLOT,NEW LDT SEL,DCS SEL,@EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP);END /* unallocated data or code segment */; END /* stepping thru DESCRP entries */; END TRANSFER_REMAINDERS;
/***************************************************** **/
3
2
/* 184 185 186 188 189 191 192 194 195 197 198. 199 21313 2132 2133 205 2136 2138 2139 211 212 214 215 216 218 219 221 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
Main Line
*/
CALL INITIALIZE_SYSTEM; CALL BUILD BOND TABLE (@BOND FILESPEC,@EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); CALL RESERVE SLOTS (IN LDT, 1, @DCS SEL, @EXCEP); IF EXCEPTION-THEN CALL-REPORT (@EXCEP); CALL RESERVE SLOTS (IN LDT, 1, @DESCRP SEL, @EXCEP); IF EXCEPTION-THEN CALL-REPORT (@EXCEP); CALL RESERVE SLOTS (IN LDT, 1, @DESNAM SEL, @EXCEP); IF EXCEPTION-THEN CALL-REPORT (@EXCEP); DO FOREVER; GET NAME: CALL GET LOAD FILE (@PATH NAME); /* May wait */ LOAD FILE=DQ$ATTACH (@PATH NAME, @EXCEP); IF EXCEPTION THEN GOTO GET-NAME; CALL DQ$OPEN (LOAD FILE, READ, 1, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); /* Read file header. */ ACTUAL=DQ$READ (LOAD FILE, @FILE HEADER, 1, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); /* Read load able-module header */ ACTUAL=DQ$READ (LOAD FILE, @MODULE HEADER, SIZE(MODULE HEADER)~ @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); /* Process DESNAM section of OMF */ CALL DQ$SEEK (LOAD FILE,2,MODULE HEADER.DESNAM LOC, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); CALL BUILD_DESNAM_TABLE (SECTION_SIZE(3)); /* Tell OS to allocate an LDT */ CALL RESERVE SLOTS (IN GDT, 4, @TASK SLOT, @EXCEP); IF EXCEPTION-THEN CALL-REPORT (@EXCEP); CALL CREATE LDT (TASK SLOT, MODULE HEADER.DESCR COUNT, @EXCEP) ; IF EXCEPTION THEN CALL REPORT (@EXCEP); /* Process DESCRP section */ CALL DQ$SEEK (LOAD FILE,2,MODULE HEADER.DESCRP LOC, @EXCEP); -
11-22
121960-001
PL/M-286 COMPILER 222 224 225 226 228 229 230 231 233 234 236 237 239 240 242 243 245 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
960-515
date
PAGE
/* Process LODTXT section */ CALL DQ$SEEK (LOAD FILE,2,MODULE_HEADER.LODTXT_LOC, @EXCEP) ; IF EXCEPTION THEN CALL REPORT (@EXCEP); CALL LOAD_SEGMENTS(SECTION_SIZE(l));
CALL TRANSFER_REMAINDERS;
/* Tell OS to create the new task */ CALL CREATE TASK(TASK SLOT, @TSS, DEFAULT_PRIORITY, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP);
(LOAD FILE, @EXCEP); CALL DQ$CLOSE IF EXCEPTION THEN CALL REPORT (@EXCEP); CALL DQ$DETACH (LOAD FILE, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); CALL FREE SEG (DESCRP SEL, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); CALL FREE SEG (DESNAM SEL, @EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); END /* FOREVER */;
/***************************************************** **/
246
END LOADER;
MODULE INFORMATION: CODE AREA SIZE CONSTANT AREA SIZE VARIABLE AREA SIZE MAXIMUM STACK SIZE 508 LINES READ o PROGRAM WARNINGS o PROGRAM ERRORS DICTIONARY SUMMARY: 96KB MEMORY AVAILABLE 11KB MEMORY USED (11%) 0KB DISK SPACE USED END OF PL/M-286 COMPILATION 08B2H 0001H 00FFH 0018H 2226D 10 255D 240
11-23
121960-001
PL/M-286 COMPILER
960-521
date
PAGE
system-ID PL/M-286 Vx.y COMPILATION OF MODULE BOND OBJECT MODULE PLACED IN :F1:BOND.OBJ COMPILER INVOKED BY: PLM286.86 :F1:BOND.PLM DEBUG
$ $ $ $ $ $
1
PAGEWIDTH(71) TITLE('960-521') INCLUDE (:F1:NUCSUB.PLM) NOLIST INCLUDE (:F1:UDISUB.PLM) NOLIST COMPACT DO; Language Extensions LITERALLY LITERALLY LITERALLY LITERALLY LITERALLY LITERALLY 'BYTE' , '0' , '0FFH' , 'WORD' , 'TOKEN', 'WORD' ;
BOND:
/***************************************************** **/
/*
2 1 DECLARE BOOLEAN FALSE TRUE TOKEN CONNECTION OFFSET
*/
/*******************************************************/
/*
3
1 2 2
Externals
*/
4
5 6
RESERVE SLOTS: PROCEDURE (TABLE,COUNT,SLOT_PTR, EXCEP_PTR) EXTERNAL; DECLARE TABLE WORD, COUNT WORD, (SLOT_PTR, EXCEP_PTR) POINTER; END RESERVE_SLOTS; GET GATE POINTER: PROCEDURE (GATE SEL, SEG_SEL_PTR, SEG OFFSET PTR, EXCEP PTR) EXTERNAL; /* Returns selector and offset from a gate descriptor */ DECLARE GATE SEL SELECTOR, (SEG SEL: PTR, SEG OFFSET PTR, EXCEP PTR) POINTER; END GET_GATE_POINTER; ALLOCATE :.PROCEDURE (SLOT, RIGHTS, SIZE, EXCEP PTR) EXTERNAL; DECLARE SLOT SELECTOR, RIGHTS BYTE, SIZE WORD, EXCEP PTR POINTER; END ALLOCATE; REPORT: PROCEDURE (EXCEP PTR) EXTERNAL; DECLARE EXCEP PTR POINTER; END REPORT; DQ$ATTACH: PROCEDURE (PATH$P, EXCEP$P) CONNECTION EXTERNAL; DECLARE (PATH$P, EXCEP$P) POINTER; END DQ$ATTACH; DQ$DETACH: PROCEDURE (CONN, EXCEP$P) EXTERNAL;
7
8 9
2
2
1
2
10
11
12 13 14 15 16 17 18
1
2
1
2
2 1
11-24
121960-001
PL/M-286 COMPILER
96CJ-521
date
PAGE
19
20
21
2 2 1 2 2 1
2
DECLARE CONN CONNECTION, EXCEP$P POINTER; END DQ$DETACH; DQ$OPEN: PROCEDURE (CONN, ACCESS, NUM$BUF, EXCEP$P) EXTERNAL; DECLARE CONN CONNECTION, (ACCESS, NUM$BUF) BYTE, EXCEP$P POINTER; END DQ$OPEN; DQ$SEEK: PROCEDURE (CONN, MODE, LOCATION, EXCEP$P) EXTERNAL; DECLARE CONN CONNECTION, MODE BYTE, LOCATION DWORD, EXCEP$P POINTER; END DQ$SEEK; DQ$READ: PROCEDURE (CONN, BUF$P, COUNT, EXCEP$P) WORD EXTERNAL; DECLARE CONN CONNECTION, COUNT WORD, (BUF$P, EXCEP$P) POINTER; END DQ$READ; DQ$CLOSE: PROCEDURE (CONN, EXCEP$P) EXTERNAL; DECLARE CONN CONNECTION, EXCEP$P POINTER; END DQ$CLOSE;
22 23
24
25 26
27 28
2 1 2
2 1 2 2
29
30 31 32
/*******************************************************/ /* Data */
33
1
DECLARE IN_LOT LITERALLY '1', DATA W LITERALLY 'lll10010B', /* Access rights: present~ DPL=3, expand-up, writable, data segment */ READ LITERALLY '1', EQUALS LITERALLY '0FFFFH', OK LITERALLY '0', EXCEPTION LITERALLY 'EXCEP<>OK'; DECLARE BOND FILE ACTUAL SEL WSEL DECLARE FILE HEADER CONNECTION, WORD, SELECTOR, /* for type conversion */ WORD AT (@SEL); BYTE; STRUCTURE DWORD, WORD, WORD, WORD, WORD, BYTE, BYTE, BYTE, BYTE, BYTE, DWORD, DWORD, DWORD,
34
35
1 1
36
DECLARE MODULE HEADER TOTAL-LENGTH SEGMENT COUNT GATE COUNT PUB COUNT EXT-COUNT LINKED DATE TIME MODULE NAME CREATOR IGNOREl PUBDEF LOC PUBDEF-LENGTH
(8 ) (8 )
(41 ) (41 )
(6)
11-25
121960-001
PL/M-286 COMPILER
960-521 IGNORE2
(8 )
date DWORD) i
PAGE
37
/* Table of actual locations of O.S. primitives */ DECLARE BOND SEL SELECTOR, BOND-BASED BOND SEL (2) STRUCTURE GATE NAME(41) BYTE, ENTRY POINT OFFSET, GDT SEL SELECTOR ), BIX WORDi /* Index */
DECLARE PUBDEF STRUCTURE (ENTRY POINT GDT IN IGNORE WORD COUNT LENGTH WORD, WORD, WORD, BYTE, BYTE)i
38
/*******************************************************/ /* Subroutines */
/* Create table of actual GDT selectors and
entry points for O.S. primitives. */ 39 40 41 42 43 45 46 48 49 51 52 54 55 57 58 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 BUILD BOND TABLE: PROCEDURE (BOND NAME PTR, EXCEP PTR) PUBLICi DECLARE (BOND NAME PTR, EXCEP PTR) POINTERi DECLARE EXCEP-BASED EXCEP_PTR-WORDi
/* Initialize file */ BOND FILE=DQ$ATTACH (BOND NAME PTR,@EXCEP)i IF EXCEPTION THEN RETURN i CALL DQ$OPEN (BOND FILE, READ, 1, @EXCEP)i IF EXCEPTION THEN CALL REPORT (@EXCEP)i /* Read file header */ ACTUAL=DQ$READ (BOND FILE,@FILE HEADER,l,@EXCEP)i IF EXCEPTION THEN CALL REPORT (@EXCEP)i /* Read module header */ ACTUAL=DQ$READ (BOND FILE,@MODULE HEADER, SIZE(MODULE HEADER), @EXCEP)i IF EXCEPTION THEN CALL REPORT (@EXCEP)i /* Get space for table */ CALL RESERVE SLOTS (IN LDT,l,@BOND SEL,@EXCEP)i IF EXCEPTION-THEN CALL-REPORT (@EXCEP)i CALL ~LLOCATE (BOND SEL, DATA W, (MODULE HEADER. PUB COUNT+l)*SIZE(BOND(0 ,@EXCEP)i IF EXCEPTION THEN CALL REPORT (@EXCEP)i /* Read the PUBDEF section */ /* (Locations are relative to beginning of module,
60 61 63 64
2 2 2
not beginning of file. Assume module at 1.) */ CALL DQ$SEEK (BOND FILE,2,MODULE HEADER.PUBDEF LOC+l, . @EXCEP)i IF EXCEPTION THEN CALL REPORT (@EXCEP)i /* Loop thru the PUBDEF entries */ DO BIX = 0 TO MODULE HEADER. PUB COUNT-li /*Read fixed part-of PUBDEF record */ ACTUAL=DQ$READ(BOND_FILE,@PUBDEF, 8, @EXCEP)i
11-26
121960-001
PL/M-286 COMPILER 65 3 3
3
960-521
date
PAGE
67
68 69
71 72 73 75
3 3 3 3
3
2
IF EXCEPTION THEN CALL REPORT (@EXCEP); /* Convert index into GDT selector */ WSEL=SHL(PUBDEF.GDT IN,3); /* Extract gate selector and offset from GDT */ CALL GET GATE POINTER (SEL, @BOND(BIX) .GDT SEL, @BOND(BIX) .ENTRY POINT, @EXCEP)i IF EXCEPTION THEN CALL-REPORT (@EXCEP); /* Read variable-length name */ BOND(BIX) .GATE NAME(0)=PUBDEF.LENGTH; ACTUAL=DQ$READ(BOND FILE,@BOND(BIX) .GATE NAME(l), PUBDEF.LENGTH,@EXCEP); IF EXCEPTION THEN CALL REPORT (@EXCEP); END /* looping thru PUBDEF entries */;
76
/***************************************************** **/
77
*/
DECLARE (SNAME PTR, PO INTER; DECLARE SNAME ENTRY_POINT GDT SEL EXCEP
ENTRY_PTR, SEL_PTR, EXCEP_PTR) BASED BASED BASED BASED SNAME PTR ENTRY-PTR SEL PTR EXCEP_PTR (41) BYTE, WORD, SELECTOR, WORD;
80 81 82 83 84 85 86 87 88 89 90 91 92
2 3
3 3 4 4 4 4 4 3
2
2
2
DO BIX = 0 TO MODULE HEADER. PUB COUNT-l; IF SNAME(0)=BOND(BIX) .GATE NAME(0) /* Same length? */ THEN /* Compare characters */ IF EQUALS=CMPB(@SNAME(l) ,@BOND(BIX) .GATE_NAME(l), SNAME (0) ) THEN DO; ENTRY POINT=BOND(BIX) .ENTRY POINT; GDT SEL=BOND(BIX) .GDT SEL; EXCEP=OK; RETURN; END; END; EXCEP=NOT OK; RETURN; END FIND_BOND;
/***************************************************** **/
93
END BOND;
MODULE INFORMATION:
11-27
121960-001
PL!M-286 COMPILER
date
PAGE
CODE AREA SIZE CONSTANT AREA SIZE VARIABLE AREA SIZE MAXIMUM STACK SIZE 245 LINES READ o PROGRAM WARNINGS o PROGRAM ERRORS DICTIONARY SUMMARY:
96KB MEMORY AVAILABLE 8KB MEMORY USED (8%) 0KB DISK SPACE USED END OF PL!M-286 COMPILATION
11-28
121960-001
12
ESCAPE Instructions
The 80287 NPX extends the instruction set of the iAPX 286 by over fifty opcodes. The CPU identifies the extended instruction set by the bit pattern 11011 B in the high-order five bits of the first byte of the instruction. Instructions thus marked are called ESCAPE or ESC instructions. The CPU performs some functions upon encountering an ESC instruction, before sending the instruction to the NPX. Those functions that are of interest to the operating system include Testing the emulation mode (EM) flag to determine whether NPX functions are being emulated by software. Testing the TS flag to determine whether there has been a context change since the last ESC instruction. For some ESC instructions, testing the ERROR pin to determine whether an error condition exists at the NPX as a result of a previous ESC instruction.
The ASM286 Assembly Language Reference Manual provides more information on each 80287 instruction.
12-1
121960-001
WAIT Instruction
The WAIT instruction is not an ESC instruction, but WAIT causes the CPU to perform some of the same tests that it performs upon encountering an ESC instruction: The CPU waits until the NPX no longer asserts the BUSY pin. You can therefore use WAIT to synchronize the CPU with the NPX. The CPU tests the ERROR pin (if EM is not set). You can therefore use WAIT to cause trap 16 if an error is pending from a previous ESC instruction. (The CPU makes this test only after BUSY goes inactive.) Note that, if no 80287 is present, the ERROR pin should be tied inactive to prevent WAIT from causing spurious traps.
Summary
Table 12-1 summarizes functions of the ESC and WAIT instructions that depend on setting of the MP and EM flags.
INITIALIZATION
During its initialization phase the operating system must Set flags in the MSW to reflect the numerics processing environment Reset the 80287 (if present) Switch the 80287 into protected mode
You can use a configuration parameter to communicate the numerics processing environment to the operating system. The FNINIT instruction (lNIT$REAL$MATH$UNIT in PL/M-286) resets the 80287, and the FSETPM instruction places the 80287 into protected mode.
12-2
121960-001
Set Reset N Y Y
Reset Set
Instruction
MP Flag
TRAP 7? WAIT TEST BUSY? TEST ERROR? (TRAP 16) TRAP 7? ESCAPE TEST BUSY? TEST ERROR? (TRAP 16)
if TS=1
Y Y
Y N N
if TS=1
Y Y
TASK STATE
When a task uses the 80287 NPX, the operating system has two additional concerns in keeping track of the task's state: The task database must be expanded to include 47 words of state information for the 80287. The operating system must change 80287 state when a different task attempts to use the 80287.
The state of the 80287 consists of 47 words. Saving and restoring the 80287 state is therefore a relatively expensive operation that should not be performed any more frequently than necessary. Typically, only a few of the active tasks in a system use the NPX; therefore, it would be wasteful to save and update the state information with every task switch. It is preferable for the operating system to record which task is using the 80287 and to swap state information only when some other task attempts to use the 80287. The 80286 supports sharing of the 80287 by providing the TS flag. The processor automatically sets the TS every time a task switch occurs. The first use of an ESC or WAIT instruction when the TS is set causes trap 7. This enables the operating system to keep track of the task to which the NPX is assigned at any given time and to change 80287 state when necessary.
NUMERICS EXCEPTIONS
Three interrupt vector positions are reserved for exceptions that relate to numerics processing. Interrupts for these vectors are not maskable.
12-3
121960-001
The CPU encounters either the WAIT instruction or an ESC instruction when both MP and TS are set. In this case, the exception handler should update the state of the NPX if necessary.
'EMULATION
The return link points to the first byte of the ESC instruction (or to the prefix byte, if any). As the emulator decodes the ESC instruction, it should step the return pointer so that, at the end of the emulation routine, the return from the exception handler causes execution to resume at the first instruction following the ESC instruction.
UPDATING STATE
To make sure that the state of the NPX corresponds to the current task, the operating system should implement the concept of "ownership" of the NPX. Ownership can be indicated by a Boolean in the task database (TDB). The operating system must ensure that only one task at a time is marked as the owner of the NPX. The exception handler should follow these steps: 1. 2. 3. 4. 5. Use the CLTS instruction to reset TS. Return if the current task owns the NPX. Use the FSA VE ESC, instruction (PL/M-286 SA VE$REAL$STATUS) to store NPX context in the former owner's task database. Record the current task as the owner of the NPX. Use the FRSTOR ESC instruction (PL/M-286 RESTORE$REAL$ST ATUS) to load the NPX context from the new owner's TDB.
Since task switches may occur during execution of the exception handler, steps 3, 4, and 5 are a critical region and must be protected by a mechanism such as a semaphore. The exception handler must run at' PL 0, both because it alters the critical task database at PL 0 and because it uses the privileged instruction CLTS. The exception handler must be an interrupt procedure, not an interrupt task. If it were an interrupt task, the task switch that occurs upon returning from the exception handler would set TS, thereby causing the exception again. The return link points to the first byte of the interrupted instruction. Return from the exception handler causes restart of that instruction, but this time TS is reset and the instruction can proceed.
12-4
121960-001
The offending ESC instruction cannot be restarted. The task containing the ESC instruction (which may not be the current task) must eventually be cancelled. The exception handler must execute an FINIT instruction before executing a WAIT or other ESC instruction; otherwise, the WAIT or ESC instruction will never finish. FINIT does not affect the CS:IP value and data address saved in the 80287. Note that the 80286 CPU detects some addressing violations before sending the ESC instruction to the 80287 NPX. In these cases, the CPU causes trap 13 (pushing an error code of zero), and it is generally possible to restart the ESC instruction. Refer to Chapter 7 for more information regarding trap 13.
1.
INVALID OPERATION OVERFLOW ZERO DIVISOR UNDERFLOW DENORMALIZED OPERAND PRECISION (INEXACT RESULT)
2.
3.
4.
5.
6.
The steps to be taken to remove the error condition depend on the application. Once the exception handler corrects the error condition causing the exception, the floating point instruction that caused the exception can be restarted, if appropriate. This cannot be accomplished by IRET, however, because the trap occurs at the ESC or WAIT instruction following the offending ESC instruction. The handler must obtain from the 80287 the address of the offending instruction in the task that initiated it, make a copy of it, execute the copy in the context of the offending task, and then return via IRET to the current CPU instruction stream. The ESC instructions that do not cause automatic checking of the ERROR pin are FNCLEX, FNINIT, FSA VE, FSETPM, FSTCW, FSTENV, and FSTSW . You can use the WAIT instruction to test the ERROR pin before these instructions, if necessary.
12-5
121960-001
Extended Protection
13
EXTENDED TYPE
It is both convenient and dangerous to use a selector as the name of an operating-system object. The danger arises from the fact that the selector by itself carries no information regarding the type of object it identifies. A program can, for example, mistakenly pass the selector of a semaphore to an operatingsystem procedure that operates on mailboxes, producing catastrophic results. The solution is to associate a type extension code for the object with the segment in which it resides or with a descriptor to that segment. Operating-system procedures can then check the type of objects identified by selector parameters. (The term type extension code is used here to avoid confusion with the processor-recognized type code in a descriptor.) There are three general methods of associating type with operating-system objects: 1. 2. 3. Place the type extension code in the segment in which the object resides. Associate the type code with a descriptor for the segment. Use indirect names and associate the type code with the name of the object.
Only segments likely to contain named operating-system objects need to have type extension codes; namely, privilege-level 0 (PL 0), expand up, writable, data segments.
13-1
121960-001
inter
Indirect Naming
EXTENDED PROTECTION
The most general approach to naming avoids giving to less privileged procedures any direct links to the named objects. Instead, names are indexes (or perhaps pointers) into a name table, which is administered by the operating system at a highly privileged level. Each entry in the name table holds the type extension code of the object, the selector of the segment in which the object resides, and any other information needed to ensure appropriate use of the object. This approach not only offers the greatest potential for protection, but also makes it possible to change the naming scheme without affecting procedures that use the names and provides a consistent way of naming both those objects that reside in dedicated segments and those that are packed into a segment with other objects.
PARAMETER VALIDATION
There is one type of privilege violation that the iAPX 286 cannot automatically check for. Consider, for example, procedure A at PL 3 that passes a pointer parameter via the stack to procedure B at PL 1. Procedure A could (accidently or purposely) pass a pointer that refers to a data structure at PL 2. Doing so would violate the intent of the protection features of the iAPX 286 because procedure A does not have sufficient privilege to operate on the data structure. However, the processor does not detect the violation because procedure B, which actually addresses the data structure, does have sufficient privilege to do so. The iAPX 286 provides the RPL field in the selector as well as the instructions shown in table 13-1 to help software guard against such protection violations. In addition to type checking as mentioned previously, an operating system can provide two levels of parameter valid:].tion: 1. 2. Defensive use of ARPL instruction Point-of-entry scrutiny
seLb
Table 13-1. Access Checking Instructions
ASM286 Mnemonic
Description
Adjust requested privilege level Verify segment for reading Verify segment for writing Load access rights Load segment limit
13-2
121960-001
EXTENDED PROTECTION
ARPL adjusts the RPL field of seLa to the greater of its current value and the value of the RPL field in seLb. The CPL of the calling procedure is stored in the RPL field of the return pointer on the stack, as figure 13-1 illustrates. Assuming the parameter is also on the stack, statements of the form
Point-of-Entry Scrutiny
While use of ARPL alone is sufficient to detect such invalid parameters, it has one drawback: it does not help to isolate the source of the invalid parameter. An exception will eventually occur when some higher-level procedure uses the parameter, but this may not happen until several instructions after the procedure was called, and may not happen until after the called procedure passes the parameter to yet
STACK
HIGH
1
SP - - - - - .
RETURN CS
RETURN IP
LOW
121960-32
13-3
121960-001
EXTENDED PROTECTION
another procedure. To detect parameter errors at the earliest opportunity, the operating system should examine pointer parameters with the VERR, VERW, LAR, and LSL instructions. The strategy for scrutinizing a pointer parameter includes Using ARPL as described previously to ensure that the RPL field of the pointer parameter contains the calling procedure's privilege level. Using VERR or VERW to ensure that the indicated segment is accessible at the calling procedure's privilege level. VERR also determines whether the indicated segment is readable; an execute-only segment, for example, is not readable. VERW also determines whether the segment is writable; only a writable data segment passes this test. Using LAR and LSL to make sure that the offset portion of the pointer parameter actually points to a location within the boundaries of the segment. LAR makes the access-rights byte of the indicated descriptor available, so you can determine whether the segment is an expand-down data segment. LSL makes the segment-limit field of the descriptor available. If the segment is an expand-down data segment, the offset portion of the pointer parameter must be greater than or equal to the segment limit; otherwise the offset must be strictly less than the limit.
Refer to the appropriate language reference manual for details concerning the use of these instructions. This strategy for parameter validation is somewhat more costly than using the ARPL instruction alone, as described in the previous section. Therefore, you may wish to limit use of this 'strategy to those operating system procedures that can be called by less privileged, applications procedures.
These examples illustrate the need for additional protection over the use of operating-system objects, such as semaphores and mailboxes. By associating a usage privilege level (UPL) with objects, the operating system can provide protection analogous to that provided by hardware for access to segments. By means of a privilege-level parameter to the creation procedure, the task that creates an object defines the maximum (numerical) privilege level that can use the object. The UPL can be stored either in the data structures that define the object or (if indirect naming is used) with the name of the object. In the procedures that operate on the object, the operating system can check whether the calling procedure's privilege level exceeds the UPL of.the object. The calling procedure's privilege level is readily available on the stack, as figure 13-1 illustrates.
13-4
121960-001
EXTENDED PROTECTION
13-5
121960-001
Glossary
GLOSSARY
8254 Programmable Interval Timer: an Intel counter/timer device that provides three independent 16-bit counters and six counter modes. For operating-system applications the 8254 can provide timed interrupts for use by the software scheduler. 8259A Programmable Interrupt Controller: an Intel device that handles up to eight vectored priority interrupts for the CPU. The chip is designed to minimize software and real-time overhead in handling multi-level priority interrupts. It has several software selectable. modes, permitting optimization for a variety of system requirements. 80286: the CPU chip of the iAPX 286 architecture. 80287: the numerics processor extension chip of the iAPX 286/20 chip set. access rights: the attributes of a segment, defined by a descriptor, that control how a segment can be used by instructions in other segments. accessed bit: a Boolean in the access rights byte of a descriptor that the processor sets when it loads the descriptor into a segment register. address mapper: a hardware device that selectively translates the CPU's addressing signals into signals of another form. alias: one of several descriptors for a segment. Each alias may define a different type, access rights, or (in some cases) limit for the segment. alias list: a data structure that enables the operating system to find all the aliases for a given segment. asynchronous: characterized by unpredictable order in the occurrence of events; not synchronous. back link: the selector field in a TSS that identifies the task to be invoked when the current task executes an IRET instruction. The processor reads the back link only if the NT flag is set. The processor sets the back link to point to the TSS of the former task when a CALL instruction or interrupt causes a task switch. base address: the 24-bit address in physical memory at which a segment starts. busy task: either the currently executing task or a task on a back-link chain from the currently executing task. A busy task has a type code of three in the descriptor for its TSS. Binder: see iAPX 286 Binder. binding: the process of translating a symbolic reference to a form that the processor can interpret directly. bootloader: see bootstrap loader. bootstrap loader: a small, usually ROM-resident, program whose function is to load a larger, fullyfeatured loader.
Glossary-1
121960-001
inter
GLOSSARY
bootloadable module: a module containing absolute object code in a simple format that expedites loading by a bootstrap loader. boundary tag: a field at the low or high end of a block of memory used by the memory allocation algorithm to distinguish between allocated and unallocated blocks. breakpoint: a position in a program marked in such a way that intervention can occur when execution of the program reaches that position. buddy system: a memory-management algorithm that partitions memory into pairs of memory blocks of equal size. When both blocks of a pair are not used, they are combined into a larger block that also has a partner or "buddy" of the larger size. buffer: an area of RAM used for transferring data to or from an external device. built-in: in PL/M-286, a predefined identifier. Builder: see iAPX 286 System Builder. BUSY: an input pin to the 80286 used by a processor extension such as the 80287 to indicate when the processor extension is unable to accept a new instruction. call gate: a gate used to transfer control to a procedure in a segment of the same task at an equal or (numerically) lesser privilege level. carry flag (CF): one of the six arithmetic flags typically used for unsigned integer comparisons and extended precision arithmetic~ CF is set by a carry into, or a borrow from, the high-order bit of a result operand. . code segment: see executable segment. combine type: one of the characteristics that the Binder associates with segments. The Binder combines segments only if they have compatible combine types. compaction: relocating allocated memory segments into consecutive locations in order to bring together all unallocated memory blocks. compiler control statement: source statements that specify options to the compiler. Control statements begin with a dollar sign ($) in the left margin. conforming segment: an executable segment that executes at the CPL of any segment that calls it. A conforming segment is identified by a bit in the access rights byte of its descriptor. control flow transfer: any change.in the normal sequential progress of a program. JMP, CALL, RET, IRET, and INT instructions, as well as exceptions and external interrupts, can cause a change .in control flow. coroutine: a type of subroutine that cooperates with other coroutines in quasi-parallel execution. A set of related coroutines transfer control from one to another. Each coroutine maintains local variables across invocations and maintains an independent instruction counter that determines where to begin execution upon next invocation. critical section: a procedure or portion of a procedure that operates on shared data in such a way that it may act incorrectly if another procedure operates on the same data within the same time interval.
Glossary-2
121960-001
GLOSSARY
CS (code segment) register: the segment register that provides addressability for access to instructions. current privilege level (CPL): the privilege level that the processor is using to execute the currentlyaccessible executable segment. CPL may be equal to OPL of the executable segment, or CPL may be numerically greater that OPL if the segment is conforming. data segment: a segment that contains data (other than immediate data) for an executable segment. A data segment is identified by a specific type code in the descriptor of the segment. descriptor: an eight-byte item that defines the use of memory in an iAPX 286 protected-mode system. descriptor table: one of the processor-recognized tables that contain the descriptors for the system. These tables are the GOT, the lOT, and LOTs. descriptor privilege level (DPL): the privilege level defined in the descriptor of a segment. device driver: the task or procedures that use knowledge of the physical characteristics of an I/O device to carry out higher-level I/O requests. direct I/O: I/O operations in which the CPU participates. dispatching: determining which task the processor should work on, and switching the processor to that task; also known as "scheduling." double fault: a fault that occurs while the processor is attempting to handle a prior fault. DS (data segment) register: one of three segment registers that provide addressability to data segments. dynamic system: an application in which tasks begin and end relatively frequently. EM (emulation mode) bit: a Boolean in the MSW that indicates to the processor whether ESC instruction processing is being emulated by software. emulation: software interpretation of instructions for a processing device (such as the 80287 Numerics Processor Extension) that is not present in the system. entry point: an executable-segment offset that identifies the starting point for execution, as when the segment is invoked via a gate. error code: a word automatically pushed on the stack as a result of certain exceptions. The error code helps identify the segment involved in the exception. ERROR: an input pin of the 80286 used by a processor extension (such as the 80287) to signal error conditions. ES (extra segment) register: one of three segment registers that provide addressability to data segments. ESC or ESCAPE instruction: an instruction (usually for a processor extension) identified by the fivebit prefix 110118: EX (external) bit: a Boolean in the error code which, when set, indicates that the exception is due to factors outside the control of the task in which the exception occurs.
Glossary-3
121960-001
GLOSSARY
exception: a processor-detected condition that requires software intervention. The iAPX 286 communicates exceptions to software by means of the interrupt mechanism. executable segment: a segment that contains processor instructions. An executable segment is identified by a specific type code in its descriptor. execute-only segment: a special case of an executable segment that the processor can access for the purpose of fetching instructions but cannot access for the purposes of reading data. An execute-only segment is identified by a Boolean in the access-rights byte of its descriptor. expand-down segment: a data segment that contains a data structure (such as a stack) that grows toward lower memory locations. An expand-down segment is identified by a Boolean in the accessrights byte of its descriptor. Offset addresses in an expand-down segment extend from the value contained in the limit field of the descriptor thru OFFFFH. exportation: a process by which a system-software interface is made available to applications and other system programs. Gates and segments providing .access to system services (such as operating-system primitives) are placed, via the Builder's export definition, into a linkable module. This module is used when building loadable tasks that depend on the exported services.
EXPORTS list: a clause of PL/M-286's extended segmentation control syntax that specifies the public
identifiers that may be referenced from outside a subsystem. external reference: a reference to an identifier that is defined as PUBLIC in another module. fault: an interrupt that results from an exception. fetch policy: the algorithm that determines which segment to bring into RAM from secondary storage and when to bring it in. first fit algorithm: a dynamic storage allocation algorithm that satisfies a request for space with the first unallocated block of storage whose size is greater than or equal to the requested size. flag: one of several Booleans maintained by the CPU, including the arithmetic flags (CF, PF, AF, ZF, SF, OF), the control flags (TF, IF, DF), and the nested task flag (NT). flag word: a 16-bit register of the 80286 that contains the arithmetic flags, the control flags, the nested task flag, and the IOPL. The processor saves the flag word in the TSS with each task switch and loads the flag word from the TSS of the next task, thereby enabling each task to use the flags without interference from other tasks. fragmentation: a condition resulting from some dynamic storage-allocation algorithms, in which unallocated storage is dispersed in many small areas. gate: a gate descriptor. gate descriptor: a descriptor that defines a protected entry point to an executable segment or task.
GDT register: a register of the 80286 that contains the base address and limit of the ODT.
global descriptor table (GDT): the descriptor table that contains descriptors that can be used by every task in the system. There is only one ODT per processor.
Glossary-4
121960-001
GLOSSARY
handler table: a table of selectors to call gates that identify the procedures for servicing asynchronous events such as interrupts or software signals. A handler table is used by an operating system's interrupt distributor and signalling primitives. I bit: a Boolean in the error code which, when set, indicates that index portion of the error code points to an entry in the lOT. iAPX 286 Binder: an iAPX 286 program development utility used to link modules, combine segments, and create a single-task, loadable output module. iAPX 286 System Builder: the configuration utility for iAPX 286 protected-mode systems. IDT register: an 80286 register that stores the base address and limit of the lOT. index: the field of a selector that identifies a slot in a descriptor table. indirect I/O: a style of I/O interface in which I/O operations are executed by an independent processor, not by the CPU. interrupt: I) the electrical or logical signal that an event has occurred; 2) the mechanism by which a computer system responds quickly to events that occur at unpredictable times. interrupt controller: a device (such as Intel's 8259A Programmable Interrupt Controller) that assists the CPU in responding to mUltiple external interrupt signals by performing such functions as detection, priority resolution, and identification. interrupt descriptor table (IDT): a descriptor table that contains gates to the handler procedures or handler tasks for interrupts and traps. The lOT may contain only interrupt gates, trap gates, and task gates. interrupt distributor: an operating-system interrupt procedure that transfers control to a task-defined procedure for servicing the interrupt. interrupt-enable flag (IF): a control flag of the 80286 that determines whether the processor responds to external interrupt signals presented at the processor's INTR pin. interrupt gate: a gate that identifies the entry point of a procedure for handling an interrupt. When an interrupt transfers control through an interrupt gate, the processor resets the interrupt-enable flag. Interrupt gates are valid only in the lOT. interrupt handler: a procedure or task that is invoked by an interrupt. interrupt latency: the time from the occurrence of an interrupt signal to the execution of the first instruction of an interrupt handler. interrupt procedure: an interrupt handler that is identified by an interrupt gate or trap gate. An interrupt procedure runs in the interrupted task. interrupt task: an interrupt handler that is identified by a task gate and runs as a task separate from the interrupted task. interrupt vectoring: the mapping from an interrupt source to the interrupt handler. In the iAPX 286 architecture, the 8259A and the lOT are components of the interrupt vectoring process.
Glossary-5
121960-001
GLOSSARY
intersegment reference: a reference to a location in a segment other than the segment containing the reference. intrasegment reference: a reference to a location in the same segment as the segment containing the reference. interlevel reference: an intersegment reference to a segment that has a different privilege level than that of the segment containing the reference. intertask transfer: a transfer of control flow to a task other that the current task. I/O-mapped I/O: a style of I/O interface in which I/O devices respond to addresses in an address space that is distinct from the memory address space. Special I/O instructions (IN, INS, OUT, OUTS) trigger I/O operations. The 80286 uses the M/IO pin to distinguish memory addresses from I/O addresses. I/O privilege level (IOPL): a two-bit item in the flag register of the 80286 that controls the current task's right to execute the I/O-related instructions IN, INS, OUT, OUTS, eLI, STI, LOCK. A procedure may not execute any of these instructions if CPL> 10PL. I/O subsystem: the portion of an operating system that deals with filing and I/O. IP (instruction pointer): an 80286 register that contains the offset of the instruction to be executed within the current code segment. kernel: that portion of an operating system that implements the most primitive of its functions. LDT register: an 80286 register that stores the selector, base address, and limit of the current LDT. limit: the field of a descriptor that defines the offset of the last byte of the segment. linkable module: an object module created by iAPX 286 translators, by the Binder, or by the Builder that can serve as input to either the Builder or the Binder. A linkable module requires further processing before it can be executed. linking: the process of combining segments from one or more input modules and resolving references between modules. The Binder provides linking services for iAPX 286 program development. loadable module: an executable object module (usually created by the Builder or the Binder) that has a format suitable for processing by a loader running under control of an operating system. loader: the task or procedures of an operating system that places an object module in RAM and prepares it for execution by the operating system and the processor. load-time: at the time a task is loaded. local descriptor table (LDT): the descriptor table that contains descriptors that are (generally) private to a given task. Each task may have an LDT. A task can use only descriptors that are in its LDT or in the GDT. The LDT protects tasks from one another. logical segment: the representation of a segment used by translators and program development utilities prior to the time when the segment is actually placed in physical memory.
Glossary-6
121960-001
inter
GLOSSARY
machine status word (MSW): an 80286 register that includes the TS, EM, MP, and PE Booleans. These items are global to the system and are not a part of the task state. mailbox: a software mechanism for sending messages between tasks. The mechanism consists of two queues: one a queue of undelivered messages, the other a queue of tasks waiting for messages. Messages are delivered in FIFO order. memory management: the set of operating system functions that deal with the allocation of RAM to tasks. memory-mapped I/O: a style of I/O interface in which I/O devices respond to specific addresses in the memory address space. I/O operations are triggered by standard instructions that read from, and write to, memory locations. message: a unit of intertask communication. module: a compilation unit or a combination of compilation units. MP (math present) flag: a Boolean in the MSW that indicates whether a processor extension (such as the 80287 Numerics Processor Extension) is present. mutual exclusion: preventing two critical sections from executing concurrently. multiprocessing: using more than one CPU to execute a multitasking system. multitasking: the capability to support more than one task either simultaneously (by using more than one CPU) or virtually simultaneously (by multiplexing one CPU among several tasks). nested task (NT) flag: a Boolean in the flag word that indicates the existence of a back link field in the TSS to a previous TSS. non-maskable interrupt (NMI): an external interrupt presented to the NMI pin of the 80286 that the processor does not ignore, even when IF is reset. not-present segment: a segment whose descriptor has the present bit reset. In a virtual-memory system, this condition normally indicates that the segment has been evicted from RAM to make space for other segments. nucleus: see kernel. nullify: assign a null value to. numerics processor extension (NPX): the 80287 processor which cooperates with the 80286 CPU to extend its processing power in mathematical applications. object module format (OMF): a standard for the structure of object code files. OF (overflow) flag: an arithmetic flag that indicates when a signed operation produces a positive number that is too large or a negative number that is too small to fit in the destination operand. offset: the address of a location within a segment, expressed as a quantity to be added to the base address of the segment.
Glossary-7
121960-001
GLOSSARY
outward call: the attempt to call a procedure in another segment whose DPL is numerically greater than CPL. parallel table: a table whose entries have a one-to-one correspondence with the entries of a descriptor table, used to associate additional information with each descriptor. parallelism: concurrent execution of two or more tasks or devices. parameter validation: checking the attributes of parameters passed between procedures at different privilege levels to prevent protection violations or to detect exception conditions. PE bit: a Boolean in the MSW that indicates whether the 80286 is running in real-address mode or in protected, virtual-address mode. Petri net graph: a notation for visualizing Petri nets. Petri nets are a mathematical tool for modeling systems, first proposed by Dr. Carl Adam Petri in 1962. physical address: a 24-bit address, such as that used as a base address, capable of encompassing the entire address space of the 80286. physical segment: a segment as viewed by the processor, to be distinguished from "logical segment." PIC: programmable interrupt controller. See interrupt controller. pipes: a mechanism for intertask communication used in the UNIX operating system. Each task views a communication channel as a file and uses READ and WRITE operations to receive and send messages. placement policy: the algorithm for determining where in RAM to locate a segment. pointer: an item that specifies a memory location. A full or long pointer includes a selector, which indirectly chooses a segment base address, and an offset value, which points to a specific address within that segment. An offset by itself is called a short pointer. preemption: a dispatching process in which the operating system switches to another task 'even though the current task has not requested any function that would cause it to wait. The operating system may preempt one task in order to give other tasks a share of CPU attention. '', prefix: one of several instruction codes that modify the function or the environment of the following instruction. iAPX 286 prefixes include the LOCK prefix, repeat prefixes, segment-override prefixes, and the ESCAPE prefix. present bit: a Boolean in a segment descriptor that indicates whether the segment is actuallly present in RAM. In a virtual-memory system, the segment may have been evicted from RAM to create space for another segment. primitive: one of the operating-system operations made accessible to applications by some explicit mechanism. In the iAPX 286 architecture, primitives are typically procedures with call gates in the GOT or LOTs. privilege: the right to access certain portions of memory or to execute certain processor instructions. privilege level (PL): a measure of privilege. In the iAPX 286 architecture, privilege is measured by integers in the range 0-3, where 0 is the most privileged and 3 the least.
Glossary-8
121960-001
GLOSSARY
privileged instruction: an instruction that can be executed only by a procedure running at privilege level o. Privileged instructions include CL TS, HL T, LGDT, LIDT, LLDT, LMSW, and LTR. processor extension: an optional, special-purpose processor (such as the 80287) that runs in parallel with the 80286 and extends its processing power. profiler: a procedure or task that collects data about segment usage. protected, virtual-address mode: the mode of operation of the 80286 that provides virtual-memory addressing and memory protection. protection: a mechanism that limits or prevents access to areas of memory or to public: a symbol available for intermodule reference. readable segment: an executable segment that can be read. It is necessary to read from an executable segment if that segment contains constants. A readable segment is identified by a Boolean in the access rights byte of its descriptor. read-only segment: a data segment that cannot be written to. A read-only segment is identified by a Boolean in the access rights byte of its descriptor. real-address mode: the mode of operation of the 80286 that provides greatest compatability with the 8086, without protection and virtual memory addressing. real memory: the physical memory, as distinguished from virtual memory. real-time system: a system that responds to external events in a relatively short time, as contrasted with a batch system. region: a mechanism for providing mutual exclusion among critical sections. A region is similar to a semaphore that has the additional properties that I) only the task that acquires a region can release it, and 2) a task cannot be suspended while holding aregion. relocation: changing the physical location of a segment. replacement policy: the algorithm that determines when to remove segments from RAM and which segments to remove when space is (or is likely to be) needed for another segment. resolving reference: see binding. requested privilege level (RPL): the privilege-level field of a selector. A procedure may request a numerically greater privilege level for use of a segment by placing the desired privilege level in the RPL field of the selector that identifies that segment. run-time: the time a task executes. scheduler queue segment: a segment that contains one or more of the task queues used by a scheduler. Keeping a queue in one segment may reduce the time for searching the queue. scheduling: see dispatching. scheduling mode: one of two styles of scheduling a task: hardware- (interrupt-) scheduled mode or software-scheduled mode.
instru~tions.
Glossary-9
121960-001
GLOSSARY
scheduling state: one of several conditions that affect the way a task is treated by the scheduler. A task may be ready to execute, executing, waiting for some event, etc. secondary storage: a slower, less expensive storage medium than RAM (for example, disk). segment: a variable-length area of contiguous memory addresses not exceeding 64K bytes. segment register: one of four 80286 registers that hold addressing information for the segments that are currently addressable by a task. The segment registers are CS (code segment), DS (data segment), ES (extra segment), and SS (stack segment). selector: an item that identifies a descriptor by the location of the descriptor in a descriptor table. semaphore: a synchronization mechanism that communicates the occurrence of an event between two (or more) tasks via a shared memory loca,tion. send privilege level(SPL): a software-implemented measure of the right to send or delete a segment. shadow task: a duplicate task used to enable the operating system to perform an outward call. signal: a mechanism for permitting one task to communicate the occurence of an event to another task that is not waiting for the event to occur. single step: a mode of execution that permits intervention between each instruction; used primarily as a debugging aid. slot: an entry in a descriptor table. SS (stack segment) register: the segment register that provides addressability to the current stack segment. stack segment: a segment used by the processor to hold return addresses, dynamic data, temporary data, and parameters. For greatest protection, each privilege level of a task may have its own stack. Stack segments usually expand downward. static system: an application in which the mix of tasks does not change over time. subsystem: in PL/M-286, a collection of tightly-coupled, logically-related modules that obey the same model of segmentation. swap space: the secondary storage area used to contain segments that have been removed from RAM. swapping: in a virtual-memory system, the process of moving segments between RAM and secondary storage. swapping manager: a procedure or task responsible for swapping. synchronization: imposition of an order on the occurrence of certain events. system segment: a segment containing a descriptor table or task state. table indicator (TI): a Boolean in a selector that identifies the descriptor table to which the selector refers.
Glossary-10
121960-001
GLOSSARY
task: a single thread of execution that has an associated processor state. task database: the collection of information about a task that the operating system needs to store. task information block: a segment or part or a segment used by the operating system to contain all or part of a task database. task gate: a gate that identifies a TSS. A control transfer through a task gate causes a task switch. task register: an 80286 register that points to the TSS of the currently active task. task state segment (TSS): a segment used by the processor to store the contents of the task-variable registers, the stack-segment selectorsand pointers for the three most privileged levels, the selector for the task's local descriptor table, and a back link that may point to another task in a chain of nested task invocations. TF (single step flag): a Boolean in the flag word that, when set, indicates that the processor should cause a trap after each instruction. Typically, TF is used to facilitate debugging. thrashing: in a virtual memory system, a condition in which excessive swapping seriously degrades performance of all tasks. time-sharing system: a multi-user, multitasking system in which processors are multiplexed among users. time slice: the time interval for which the CPU is allocated to a task. translator: an assembler or compiler. trap: an interrupt due to an exception condition. trap gate: a gate that identifies the procedure to handle a trap. An interrupt through a trap gate differs from an interrupt through an interrupt gate in that, with a trap gate, interrupts are not disabled upon entry into the procedure. Trap gates are valid only in the IDT. Trojan horse: a type of protection violation in which a procedure passes a selector that it has no right to use to a more privileged procedure that does have the right to use it. trusted instruction: one of a set of I/O-related instructions that cannot be executed unless CPL is less than or equal to IOPL. The trusted instructions are CLI, STI, IN, INS, OUT, OUTS, and LOCK. type code: a value in a descriptor that specifies the intended use of a segment. The processor interprets the type code to ensure that segments are used only as intended. type extension code: a software extension to the type code concept that includes usages recognized by the operating system. UDI (Universal Development Interface): an Intel standard for interfaces to operating-system services. usage privilege level (UPL): a software-defined measure of the right to use an operating-system object. vectoring: see interrupt vectoring.
Glossary-11
121960-001
GLOSSARY
virtual address: an address that consists of a selector and an offset value. The selector chooses a descriptor for a segment; the offset provides an index into the selected segment. virtual address space: The set of all possible virtual addresses that a task can access, as defined by the GDT and the task's LDT. The maximum possible virtual address space for one task is one gigabyte. virtual memory: a style of memory management that permits the virtual address space to exceed the physical address space of RAM. With the help of processor features, the operating system simulates the virtual address space by using secondary storage to hold the overflow from RAM. word count: a field of a gate descriptor that specifies the number of words of parameters to be copied from the calling procedure's stack to the stack of the called procedure. writable segment: a data segment that can be written to. A writable segment is identified by a ~oolean in its descriptor. XOS (Example Operating System): an imaginary operating system, portions of which are used in this book as examples.
Glossary-12
121960-001
INDEX
8089 I/O processor, 8-1 8254 Programmable Interval Timer (PIT), 4-5, 4-9,4-13 8259A Programmable Interrupt Controller (PIC), 4-6, 6-1, 6-6, 7-6 80287 Numerics Processor Extension (NPX), 1-7, 7-4, 7-5, 7-8, Chapter 12 access rights (field of descriptor), 2-21, 2-22, 9-2,11-5,11-10,13-1,13-2,13-4 accessed bit, 2-7, 5-3, 9-1, 9-4, 9-5, 9-7, 10-2 ADC,7-8 addressing mechanism, 2-1 ADJUST$RPL, 2-16, 13-2 alias, 2-17 thru 2-22, 3-2, 4-10, 4-12, Chapter 5, 6-5, 8-2, 9-3, 9-7, 10-3, 11-2, 11-9, 13-5 ARPL, 2-16, 13-2 thru 13-4 ASM286, 3-6, 4-13, 11-4, 13-2 ASSUME, 11-4 asynchronous execution, 1-6 back link (of TSS), 4-1 thru 4-4, 4-7,4-13,7-5, 7-6, 10-2, 11-10 base address, 2-4, 2-15, 4-1, 5-3, 9-3, 9-5, 10-3, 11-3, 11-10, 11-11 binding, 1-8, 2-8, 2-9, Chapter 11 Binder, see iAPX 286 Binder bootloadable, see module, bootloadable BOUND, 7-4 bound check exception, 7-4 boundary tags, 3-2, 3-5, 3-6, 9-3 breakpoint, 2-17, 7-3 buffer, 2-18, 3-1, 3-10, 5-10, 8-1, 8-3, 8-5, 8-7, 9-2,9-4 Builder, see iAPX 286 System Builder BUSY / pin, 12-2, 12-3 busy task, 4-3, 4-4, 7-7 CALL, 2-7,2-9,.2-10,4-2 thru 4-4, 4-13, 4-17, 6-1, 6-2, 6-4, 6-6, 7-5 thru 7-7, 11-3 carry flag (CF), 7-8 CLI, 4-6, 4-7, 5-6, 6-2, 8-2 CLTS, 12-2, 12-4 CMPS, 7-7 combine type, 11-4 COMPACT, 11-4,,11-5 compaction, 3-10 compiler control statements, 11-4 conforming segment, 2-5, 6-2, 6-7, 6-8 critica1 section, 5-5 thru 5-7, 12-4 CS register, 4-4,6-9, 7-5 thru 7-7, 9-1, 9-6, 9-7, 10-1, 11-3, 11-9, 12-5 current privilege level (CPL), 2-11, 2-16, 4-6, 5-6, 6-2, 6-7, 6-8, 8-2, 10-1, 10-2, 13-3 deadlock, 5-7, 5-10 debugger, 2-17, 7-3, 11-3, 11-10 deletion of segment, 2-20, 5-2, 5-3, 8-3, 9-5, 13-1 of descriptor, 13-5 DESCRP section, 11-11, 11-12 descriptor, 2-2, 2-12, 11-6, 11-9 data segment, 2-2, 2-3, 2-6, 2-14, 2-15, 2-18, 7-7, 9-3 thru 9-5, 9-7 dynamic creation, 3-1, 3-2 executable segment, 2-2, 2-4, 2-6, 2-7, 2-14, 2-15,2-17,6-7,7-7,9-7 gate, 2-2, 2-7 thru 2-11, 2-15, 6-2, 7-6, 9-1, 9-2, 10-2, 11-3, 11-9 system segment, 2-2, 2-5 descriptor privilege level (DPL), 2-3, 2-6, 2-9, 2-11,2-15,2-20,2-21,4-3,5-7,6-7, 6-8, 8-2~ 8-5, 8-7 descriptor table, 2-2, 2-12, 2-15 see also global descriptor table, local -descriptor table, interrupt descriptor table DESNAM section, 11-11 device drivers, 5-17, 8-1, 8-2, 8-4, 8-7, 9-2, 9-4, 11-2,11-4 DI register, 7-7 DISABLE, 6-2, 6-4, 7-1 dispatching, 4-9, 4-13, 5-7, 9-5, 11-4 divide error exception, 6-7, 7-3 double fault, 7-5, 9-2, 9-4 DPL, see descriptor privilege level DS register, 2-17, 2-18, 2-21, 4-12,7-5 thru 7-7, 9-1,9-6,9-7, 10-1 dynamic system, 1-7 thru 1-10,2-2,2-3, 2-12, 2-18 thru 2-20, 2-22, 3-1, 4-4, 5-7, 6-5, 11-8 effective privilege level, 2-16 EM (emulation mode) flag, 7-4, 7-8, 12-1 thru 12-3 emulation, 7-8, 12-1, 12-4 ENABLE, 6-2 ENTER,7-6 ENTRY, 11-6 EPROM,10-3 ERROR/ pin, 7-8, 12-1 thru 12-3, 12-5 error code, 7-1, 7-2, 7-5 thru 7-7, 7-9, 9-2, 9-3, 12-5
Index-1
121960-001
INDEX
ES register, 2-17,2-18,2-21,2-22,4-12,7-5 thru 7-7, 9-1, 9-6, 9-7,10-1 ESCAPE instructions, 7-4, 12-1 thru 12-5 EX (external) bit, 7-2 examples, 2-20 thru 2-26,3-1 thru 3-9, 3-15 thru 3-21,4-15,5-8,5-9,5-13 thru 5-16, 10-3 thru 10-15, 11-6 thru 11-8, 11-12 thru 11-28 exception, 1-7,2-8,2-10,2-17,4-3,4-7,5-5,6-2, 6-4,6-9, Chapter 7, 9-1,11-3,13-3,13-5 handler, 6-7, Chapter 7, 9-2, 9-4, 11-3, 12-4, 12-5 recovery, Chapter 7, 12-3 thru 12-5 EXECUTE, 11-9 execute-only segment, 7-7, 13-4 expand-down segment, 2-5,11-11, 13-4 expansion direction, 2-5, 5-3 EXPORT, 11-6 export module, 11-6, 11-12, 11-13 exports list, 11-4, 11-5 extended segmentation controls, 11-4 EXTERNAL, 3-6
global descriptor table (GOT), 1-3,2-12, 2-14 thru 2-19, 2-22, 3-3, 3-4, 3-7, 3-8, 4-1, 4-3, 4-10 thru 4-12,5-1,5-7,5-10,6-7,7-2,8-7, 10-2,10-3,11-2,11-4,11-5,11-9 thru 11-12, 13-5 handler table, 6-7 hashing algorithm, 5-3 I bit (of error code), 7-2 iAPX 286 Binder, 1-10, 11-3, 11-5, 11-6, 11-10, 11-11 iAPX 286 System Builder, 1-8 thru 1-11, 2-2, 2-4, 2-12, 2-18, 3-1, 3-6; 8-2, 10-3, 11-3 thru 11-6, 11-8, 11-10, 11-11 iAPX 386, 2-3 identifier, 5-7, 5-10, 8-7 see also interrupt identifier lOT, see interrupt descriptor table lOT register, 2-15, 6-2 IF (interrupt-enable) flag, 4-6, 5-"6, 6-2, 6-4 index field (of selector), 2-16, 2-17, 5-3, 7-2 INIT$REAL$MATH$UNIT,12-2 initialization of 80287, 12-2 see also system initialization input/output (1/0),1-4 thru 1-7,2-18,4-5,4-7, 4-10, 5-10, Chapter 8, 9-2, 9-4, 9-8, 11-2, 11-4, 11-9 indirect, 8-3 memory-mapped, 8-2 IN,8-1 INS, 7-7, 8-1 INT, 2-7, 2-10, 2-15,4-3,6-1,6-2,7-3 INTA cycles, 2-15 INTO, 6-1, 6-2, 7-3 INTR pin, 6-1, 6-2, 6-6 interrupt, 1-4, 1-7, 2-10, 2-15, 2-21, 4-3, 5-4 thru 5-6, Chapter 6,7-1,7-6,7-7,8-4,10-1, 10-2 distribution, 6-7 thru 6-9 flag, see IF identifier, 2-15, 6-1, 6-2 handler, 2-15, 2-18, 4-6 latency, see interrupt response time mask, 4-7, 12-4 procedure, 4-4,4-7,4-11,4-13,6-2,6-4 thru 6-7,7-1,12-4 response time, 4-3,5-5,6-5, 12-4 scheduled task, see scheduling software, 6-1 task, 4-4, 4-7, 6-2, 6-4 thru 6-6, 7-1, 7-6, 9-4, 12-4, 13-5 interrupt descriptor table (lOT), 2-12, 2-15, 2-16,2-18,4-3,4-5,4-7,6-2,6-4,6-5,6-7, 7-2, 7-5, 10-2, 10-3, 11-11
Index-2
FAR, 11-4 fault, see exception FINIT,12-5 "first fit" algorithm, 3-1, 3-2 flag word, 4-2 thru 4-4, 6-2, 6-4, 8-1, 8-2, 10-1 FNINIT, 12-2, 12-5 FORK,I1-9 fragmentation, 3-1, 3-2, 9-6 FRSTOR, 12-4 FSA VE, 12-4, 12-5 FSETPM, 12-2, 12-5
gate, 2-8, 2-11, 11-6 call, 2-8, 2-10, 2-12, 2-14, 2-15, 2-21, 3-9, 4-13, 5-7, 5-12, .6-1, 6-2, 8-7, 11-3, 11-12, 11-14 interrupt, 2-8, 2-15, 6-2, 6-4, 6-7 name, 11-6 task, 2-8, 2-14, 2-15, 4-3, 4-7, 6-2, 6-4, 7-5, 10-3 trap, 2-8, 2-15, 6-2, 6-4, 6-7 see also descriptor, gate GATE,11-6 GOT, see global descriptor table GOT register, 2-15, 10-2 general protection exception, 7-7, 8-2 GET$ACCESS$RIGHTS, 13-2 GET$SEGMENT$LIMIT,3-6, 13-2
121960-001
inter
INDEX
"invalid TSS" exception, 7-5 thru 7-7, 9-2, 9-5 IOPL % privilege level), 4-6,5-6, 8-1, 8-2, 8-5 IP register, 4-4, 6-9, 7-1, 7-3,7-5,7-7,10-1, 11-9, 12-4, 12-5 IRET, 2-7, 2-10, 4-3, 4-4, 4-13, 6-4, 6-6, 6-7, 6-9, 7-3, 7-5, 7-7, 8-2, 12-5 JMP, 2-5, 2-7, 2-9, 2-10, 4-3, 4-4, 4-13, 7-7, 10-1, 10-3 LABEL, 11-4 LAR, 9-7, 13-2, 13-4 LARGE,II-4 LDT, see local descriptor table LOT register, 2-14, 4-3, 7-6, 9-1 LDT selector (ofTSS), 4-1, 4-3, 6-9, 7-5, 10-2, 11-11 LEAVE,7-6 LGDT,2-15 LIDT, 2-15,6-2 limit field (of descriptor), 2-4, 2-5, 2-12, 2-15, 2-16,4-1, 5-3, 7-5 thru 7-7, 9-5, 10-1, 10-3, 11-11,12-4,13-2,13-4 linkage, 1-10, 7-6 LLDT, 2-14, 7-6 LMSW, 10-1, 12-1 loading, see program loading local descriptor table (LDT), 2-5, 2-12, 2-14, 2-16,2-18 thru 2-20, 3-1,4-10, 5-1 thru 5-3, 5-10,5-17,6-7,7-2,8-7,9-3,9-4,9-7,10-2, 10-3, 11-2, 11-4, 11-5, 11-8 thru 11-12 not present, 9-1, 9-2 LOCAL$TABLE, 2-14 LOCK,8-2 LODTXT section, 11-11, 11-12 logical segment, 1-1, 11-2 thru 11-5 LSL, 9-7, 13-2, 13-4 LTR, 4-1, 9-1 MACHINE$STATUS, 12-1 mailbox, 5-10 thru 5-12, 5-16, 5-17, 8-7, 9-3, 9-5, 11-2, 13-1, 13-4, 13-5 mechanisms, see policies and mechanisms memory management real, 1-8, 1-9,2-22, Chapter 3, 5-4, 5-12, 5-17, 8-3, 8-5, 11-6 virtual, 1-8,2-2,2-3, 2-7, 7-6, Chapter 9, 11-9 message, 2-19, 3-9, 4-9, 5-4, 5-10, 5-12, 5-16 module, 11-1 thru 11-6 bootloadable, 11-6, 11-10 linkable, 11-6, 11-10 loadable, 1-10, 11-10, 11-11, 11-14 object, 1-8, 1-9, 11-9, 11-10
MOV,7-6 MOVS,7-7 MP (math present) flag, 7-4, 12-1 thru 12-4 MSW (machine status word), 7-4, 7-8, 10-1, 12-1, 12-2 multiprocessor systems, 3-10 mutual exclusion, 5-5, 5-6 naming, 11-1 thru 11-6, 11-11, 11-12, 13-1, 13-2, 13-4, 13-5 NEAR,11-4 NMI (non-maskable interrupt), 6-1, 6-2, 10-2 NOT PRESENT statement, 11-12 "not present" exception, 7-5 thru 7-7,9-1, 9-3 thru 9-8, 11-3 see also present bit NT (nested task) flag, 4-2 thru 4-4, 4-7, 7-6, 9-4, 11-10 Numerics Processor Extension (NPX), see 80287 OBJECT, 11-6 object module format (OMF), 11-8, 11-10, 11-11 OF (overflow) flag, 7-3 OUT,8-2 OUTS, 7-7, 8-2 outward call, 6-8 overflow exception, 7-3 paged architecture, 9-6 parallel table, 5-3, 13-1 parallelism, 1-4, 8-4, 8-7 PE (protection enable) flag, 10-1 Petri net graph, 8-4, 8-5 physical address, 1-8, 1-9, 2-4, 3-2 thru 3-4, 11-10 , physical segment, 1-1, 1-2, 2-12, 2-15, 11-1 thru 11-3 PIC, see 8259A Programmable Interrupt Controller pipes, 5-17 PL/M-286, 2-14 thru 2-16,2-21, 2-22, 3-3, 3-6, 4-1,4-3,4-13,6-2, 11-4, 11-6, 12-2, 12-4, 13-2 pointer parameters, see selector parameters policies and mechanisms scheduling, 4-9, 4-10 virtual memory management, 9-1, 9-6 POP, 7-6 POPA,7-7 POPF,8-2 preemption, 4-5,4-7,4-9,4-10,4-13 prefix, 7-1
.lndex-3
121960-001
INDEX
present bit, 2-2, 2-3, 2-9, 5-3, 7-5, 7-6, 9-1 thru 9-5, 11-12 primitives, 11-3, 11-4, 11-6, 11-12, 11-14, 13-4 priority, 2-19, 4-6, 4-7, 4-9, 4-10, 6-6, 6-7 privilege level, 1-3, 1-4, 1-8, 2-6, 2-7 thru 2-11, 2-15,2-18,2-20,2-21,3-8,3-9,4-1,4-2,4-9, 4-12,4-13,5-2,5-7,5-10,5-12,6-2,6-3,6-5, 6-8,8-2, 8-3, 8-7, 9-3, 9-7, 11-2, 11-6, 11-9, 11-10, 12-2, 12-4, 13 .. 1, 13-2, 13-4, 13-5 PROC, 11-4 "processor extension error" exception, 7-8, 12-5 "processor extension not available" exception, 7-4, 12-3, 12-4 "processor extension segment overrun" exception, 7-5, 12-4, 12-5 profiling, 9-7, 9-8 program loading, 1-8, 1-10, 2-3, 2-4, 3-1, 6-5, Chapter 11 bootstrap, 1-9, 11-10 protected, virtual-address mode, 10-1, 10-2, 12-2 protection, 1-3 thru 1-5, 1-9, Chapter 2, 3-1, 3-7, 4-3, 4-4, 4-6, 5-1, 5-4, 5-7, 5-10, 6-2, 6-3, 6-5,6-6,7-3, 8-1 thru 8-4, 8-7, Chapter 13 violation, 6-4, 6-9, 7-7 PUBLIC, 3-2, 3-6, 3-8, 3-9, 10-3, 11-3, 11-6 PUSH,7-6 PUSHA,7-7 RCL, RCR, 7-8 readable segment, 2-7 read-only segment, 7-7 real address mode, 10-1, 10-2 real memory management, see memory management, real recovery, see exceptions region, 5-10, 9-4, 9-5 REP, REPE, REPNE, 7-7 requested privilege level (RPL), 2-11, 2-16, 7-2, 13-2 thru 13-4 RESERVE,3-6, 11-6 reserved word (of descriptor), 2-3, 2-22 RESET, 10-1, 10-3 RESTORE$GLOBAL$TABLE,2-15 RESTORE$INTERRUPT$TABLE, 2-15 RESTORE$REAL$STATUS, 12-4 return pointer, 6-2, Chapter 7, 12-4, 13-3 return link, see return pointer return address, see return pointer relocation (of segment), 2-4, 2-20, 5-2, 5-3, 5-12, 8-3 RET, 2-7, 2-9, 2-10, 4-3, 11-5 RETURN, 11-5 ROM, 10-1 RPL, see requested privilege level
SAVE$GLOBAL$TABLE,2-15 SAVE$INTERRUPT$TABLE,2-15 SA VE$REAL$STATUS, 12-4 SBB,7-8 SCAS,7-7 scheduling, 2-19, 4-11, 5-12, 9-5 hardware, see scheduling, interrupt interrupt, 4-6, 4-7, 4-9, 6-1, 6-5, 6-6, 8-7 queues, 4-12, 4-13, 9-4, 11-10, 11-14 software, 4-7, 4-9, 6-1, 6-5, 6-6, 7-6 state, 4-5 thru 4-7, 4-10 SEGMENT, 11-4, 11-6 segment, see logical segment, physical segment segment limit, see limit field segmented architecture, 9-6 SEGMENT$READABLE, SEGMENT$WRITABLE,13-2 selector, 2-1,2-2,2-8,2-9,2-15,2-16,3-6,4-1, 4-3,5-7,7-6,7-7,11-12,13-1 parameters, 2-16, 13-1 thru 13-4 null, 2-15, 2-17, 7-7 SELECTOR$OF, 3-6 semaphore, 5-6, 5-7, 5-10, 5-16, 9-4, 9-5, 11-2, 12-4, 13-1, 13-4, 13-5 send privilege level (SPL), 13-5 SGDT,2-15 shadow task, 6-8, 6-9 sharing (of segments), 2-14, 2-15, 2-19, 2-20, 2-22,4-4, Chapter 5, 8-7, 9-5,11-2,11-4, 13-1, 13-4, 13-5 shutdown, 7-5, 10-2 SI register, 7-7 SIDT, 2-15, 6-2 signal, 4-5, 5-7, 5-10, Chapter 6 single-step flag (TF), 6-2, 7-3 SLDT, 2-14, 9-7 slot, 2-20, 2-22, 2-26, 5- 10, 11-6, 11-14, 13-5 SMALL, 11-4 SMSW,12-1 SP register, 4-2, 4-12, 7-6 SPL, see send privilege level SS register, 4-2, 4-12, 7-5 thru 7-7, 9-2, 9-6, 10-1 stack, 2-5, 2-8, 3-1, 4-12, 6-2, 6-4, 7-1, 7-2, 7-6, 7-7,9-3,9-4,9-7, 10-2, 11-6, 11-9 thru 11-11,13-4 initial, 4-2, 4-3, 11-6 overflow, 7-5,7-7 exception, 7-5 thru 7-7, 9~2 static system, 1-7, 1-9, 1-10,2-3,2-19,3-1,4-4, 6-4,11-9 STI, 4-6, 4-7, 5-6, 6-2, 8-2 STOS,7-7 STR, 4-1, 4-7, 4-11
Index-4
121960-001
INDEX
subsystem, 11-4 swapping, 5-12, 8-3, 9-2 thru 9-4, 9-8 synchronization, 2-22, 3-8, 3-9, Chapter 5, 8-4, 8-6, 12-2, 13-4, 13-5 system initialization, 6-5, 6-6, Chapter 10 TABLE,II-6 table indicator (TI), 2-16, 2-17, 7-2 task, 1-1 creation, 2-2, 2-18, 3-1, 5-12, 6-9, 11-9 database (TDB), 4-11,5-12,9-4, 11-9, 11-10, 12-3, 12-4 management, Chapter 4 state, 4-1, 10-2, 12-3 switching, 2-14, 4-1, 4-3, 4-4, 4-9, 5-6, 6-2, 7-5 thru 7-7, 8-2, 9-4, 9-5, 10-2, 11-9, 12-2 thru 12-4 TASK,II-6 task register (TR), 4-1, 4-2, 4-4, 9-1, 10-2 task state segment (TSS), 2-5, 2-14, 2-18, 3-1, 4-1 thru 4-4, 4-10 thru 4-13,5-1,6-2,6-4, 6-9,7-1,7-5,7-7,8-2,9-1,9-4 thru 9-7, 10-2, 10-3, 10-5, 11-6, 11-8 thru 11-12, 11-14 T ASK$REG ISTER, 4-1 TDB, see task database termination (of task), 6-9, 7-1, 7-5, 12-5 TF, see single-step flag
thrashing, 9-8 TI, see table indicator time slice, 4-5, 4-9 thru 4-11 timer, see 8254 Programmable Interval Timer TS (task switched) flag, 7-4, 12-1 thru 12-4 TSS, see task state segment type field of descriptor, 2-5, 2-17, 2-18, 2-20, 2-21, 4-3, 4-4, 6-2, 9-3, 11-10, 11-14, 13-1 extended, 13-1, 13-2, 13-5 UDI (Universal Development Interface), 8-1 "undefined opcode" exception, 7-4 . UNIX, 11-9 usage privilege level (UPL), 8-7, 13-4, 13-5 vectoring, 6-1, 6-3, 7-1 VERR, VER W, 13-2, 13-4 virtual memory, see memory management, virtual WAIT, 7-4, 7-8,12-1 thru 12-5 W AIT$FOR$INTERRUPT, 4-3 word count, 2-8 writable data segment, 2-6, 9-5, 11-10, 11-14, 13-1, 13-4 XOS, 11-1, 11-2, 11-4, 11-6
Index-5
121960-001
inter
ALAIIAMA
Intel Corp, 303 Williams Avenue. S.W. SUIte 1422 HuntsvIlle 35801 Tel: (205) 533-9353 ARIZONA Intel Corp 11225 N. 28th Drive SUIte 2140 Phoenl, 85029 Tel: (802) 869-4980 CALIFORNIA Intel Corp 1010 Hurley Way SUIte 300 Sacramento 95825 Tol: (916) 9294078 Intel Corp 7870 Opportunity Road SUIte 135 San DIego 92111 Tol: (714) 268-3583 Intel Corp.' 2000 East 4th Street SUIte 100 Santa Ana 92705 Tel (819) 8359&42 TWX: 910-595-1114 Intel Corp.' 1350 Shorebird Way Mt. VIew 94043 Tel: (415) 968-8086 TWX: 910-339-9279 910-338-0255 Intel Corp.' 5530 Corbin Avenue SUIte 120 Tarzana 91356 Tel: (213) 708-0333 TWX: 910-495-2045 COLORADO Intel Corp. 4445 Northpark Drive SUIte 100 Colorado Springs 80907 Tel: (303) 594-6622 Intel Corp.' 850 S. Cherry Street Suite 720 Denver 80222 Tel: (3031321-8086 TWX: 910-931-2289 CONNECTICUT Intel Corp.
36 Padanaram Aoad
NEW JERSEY Intel Corp.' Rantan Plaza III Rantan Center EdIson 08837 Tel: (20112253000 TWX. 710-480-6238 NEW MEXICO Intel Corp 1120JuanTaboN.E Albuqu.rque 87112 Tel: (50S) 292-8086 NEW YORK Intel Corp.' 300 VanderbIlt Motor Parkway Hauppauge 11768 Tel: (5161231-3300 TWX: 510-227-6236 Intel Corp. 80 WashIngton Street Poughkeepsie 12801 Tel: (9141 473-2303 TWX: 510-248-0060 Intel Corp.' 211 White Spruce Boulevard Rochester 14623 Tel: (7161424.1050 TWX: 510-253-7391 T-Squared &443 RIdings Road Syracuse 13206 Tel: (3151483-8592 TWX: 710-541-0554 T-Squared 7353 Pittsford Victor Road Victor 145&4 Tel: (716) 924-9101 TWX: 510-254-8542 NORTH CAROLINA Intel Corp. 2306 W. M.adow.... ew Road Suite 206 Greensboro 27407 Tol: (919) 294-1541 OHIO Int.1 Corp.' 6500 Poe Av.nue Dayton 45414 Tel:(513) 890-5350 TWX: 810-450-2528 Inlel Corp.' Chagrin-Brainard Bldg., No. 300 28001 Chagrin Boulevard Clev.land 44122 Tol: (21B) 464-6915 TWX: 810-427-9298 OKLAHOMA Intel Corp. 4157 S. Harvard Avenue Suite 123 Tulsa 74135 Tel: (918) 749-8688 OREGON Intel Corp. 10700 SW. Beaverton HIllsdale Highway Suite 22 Beaverton 97005 Tel: (5031 &41-8086 TWX: 910-467-8741
PENNSYLVANIA Intel Corp.' 510 Pennsylvania Avenue Fort WaShIngton 19034 Tel: (2151 &41-1000 TWX: 510-661-2077 Intel Corp.' 201 Ponn Cent.r Boulevard SUIte 301W PIttsburgh 15235 Tel: (412) 823-4970
a E.D. ElectrOniCS
300 N. York Road Halboro 19040 Tel: (215) 674-9600 TEXAS Intel Corp.' 12300 Ford Road SUIte 380 Dallas 75234 Tel: (214) 241-8087 TWX: 910-860-5617
Intel Corp.-
193051. Andrews Drive N.E. Cedar Rapids 52402 Tel: (319) 393-5510 KANSAS Intel Corp. &400 W. IIOth Street Suite 170 Overland Park 66210 Tel: (9131 &42-8080 LOUISIANA Industrial Digital Systems Corp. 2332 Severn Avenue Suite 202 Metal,,", LA 70001 Tel: (504) 831-8492 MARYLAND Intel Corp.' 7257 Parkway Drive Hanover 21076 Tel: (301) 796-7500 TWX: 710-862-1944 Intel Corp. 7833 Walker Drive Greenbelt 20770 Tel: (301) 4311200 MASSACHUSETTS Intel Corp.' 27 Indust"al Avenue Ch.lmslord 01824 Tel: (617) 256-1800 TWX: 710-343-8333 EMC Corp. 385 Elliot Str.et Newton 02164 Tel: (617) 244-4740 TWX: 922531 MICHIGAN Intel Corp.' 26500 Northwest.rn Hwy Suite 401 Southf,eld 48075 Tel: (3131353-0920 TWX: 810-244-4915 MINNESOTA Int.1 Corp. 3500 W. 60th Street SUIte 380 Bloomington 55431 T.I: (6121835-6722 TWX: 910-576-2867 MISSOURI Int.1 Corp. 4203 Earth CIty E,pressway Suite 131 Earth CIty 63045 Tel: (3141291-1990
7322 S.w. Fr.eway SUIte 1490 Houston 77074 Tel: (713) 988-8086 TWX: 910-881-2490 Indust"al DIgItal Systems Corp 5925 SovereIgn Suite 101 Houston 77036 Tel: (713) 988-9421 Intel Corp 313 E. Anderson Lane SUIte 314 Austin 78752 Tel: (512) 454-3628 UTAH Int.1 Corp. 268 West 400 South Salt Lake CIty 64101 Tel: (80t) 533-8086 VIRGINIA Intel Corp. 1803 Santa Rosa Road Suite 109 RIchmond 23288 Tel: (804) 282-5668 WASHINGTON Intel Corp. 110 IIOth Avenue N.E. SUIte 510 Bellevue 98004 Tel: (206) 453-8086 TWX: 910-443-3002 WISCONSIN Intel Corp. 450 N. Suonyslope Road Suite 130 Brook fIeld 53005 Tel: (414) 764-9060
Danbury 0681 0 Tel: (203) 792-8366 TWX: 710-456-1199 EMC Corp. 393 Center Street Wallingford 0&492 Tel: (203) 265-6991 FLORIDA Intel Corp. 1500 N. W. 62nd Street Suite 104 Ft. Lauderdale 33309 Tel: (305) 771-0600 TWX: 510-956-9407 Intel Corp. 500 N. M8I11and Suite 205 Maitland 32751 Tel: (305) 628-2393 TWX: 810-853-9219
inter
ALABAMA t Arrow ElectronIcs. Inc 3611 Memo"al Parkway So. Huntsville 35405 Tel: (205) 8822730 tHamliton/Avnet E~tronlcs 4812 CommercIal Drive NoW Huntsville 35805 Tel: (205) 8377210 TWX: 8107262162 tPloneer/Huntsville 1207 Putnam Drive NoW. Huntsville 35805 Tel: (205) 8379300 TWX: 8107262197 ARIZONA tHamilton/Avnet Electronics 505 S. MadISon Drive Tempe 85281 Tel: (602) 2315140 TWX: 9109500077 tWyle D,strobution Group 8155 N. 24th Street Phoenix 85021 Tel: (602) 2492232 TWX: 9109514282 CALIFORNIA tArrow Electronics. Inc. 521 Weddell Drive Sunnyvale 94086 Tel: (408) 7456600 TWX: 9103399371 tArrow Electronics. Inc. 19748 Dearborn Street Chatsworth 91311 Tel: (213) 7017500 TWX: 9104932086 tHamilton/Avnet Electronics 350 McCormIck Avenue Costa Mesa 92626 Tel: (714) 7546051 TWX: 9105951928 tHamilton/Avnet Electronics 19515 So. Vermont Avenue Torrance 90502 Tel: (213) 6153909 TWX: 9103496263 tHamilton/Avnet Electronics 1175 Bordeau. Drive Sunnyvale 94086 Tel: (408) 7433300 TWX: 9103399332 tHamiiton/Avnet Electronics 4545 Viewridge Avenue San Diego 92123 Tel: (714) 641-4109 TWX: 9105952638 tHamilton/Avnet Electronics 10912 W. Washington Boulevard Culver City 90230 Tel: (213) 5582458 TWX: 9103406364 tHamilton/Avnet ElectronIcs 21050 Erwin Street Woodland Hills 91367 Tel: (213) 8830000 TWX: 9104942207 tHamllton Electro Sales 3170 Pullman Street Costa Mesa 92626 Tel: (714) 6414109 TWX: 9105952638 tHamiton/Avnet Electronics 4103 Northgate Boulevard Sacramento 95834 Tel: (916) 9203150 Kierulff Electronics. Inc. 3969 E. Bayshore Road Palo Alto 94303 Tel: (415) 9686292 TWX: 9103796430 Kierulff Electronics. Inc. 14101 Franklin Avenue Tustin 92680 Tel: (714) 7315711 TWX: 9105952599 Kierulff Electronics, Inc. 2585 Commerce Way Los Angeles 90040 Tel: (213) 7250325 TWX: 9105803666 tWyle Distribution Group 124 Maryland Street EI Segundo 90245 Tel: (213) 3228100 TWX: 9103487140 or 7111 tWyle Distribution Group 9525 Chesapeake Drove San Diego 92123 Tel: (714) 5659171 TWX: 9103351590 tWyle Distribution Group 3000 Bowers Avenue Santa Clara 95051 Tel: (408) 7272500 TWX: 9103380451 or 0451/0 tWyle DistributIon Group 17872 Cowan Avenue Irvine 92714 Tel: (7t4) 6411600 TWX: 9105951572
u.s. DISTRIBUTORS
COLORADO tWyle D,strobut,on Group 451 E. 124th Avenue Thornton 80241 Tel: (303) 4579953 TWX: 9109360770 tHamilton/Avnet Electronic. 8765 E. Orchard Road Suite 708 Englewood 80111 Tel: (303) 7401017 TWX: 9109350787 CONNECTICUT tArrow Electonics. Inc. 12 Beaumont Road Wallingford 06492 Tel: (203) 2657741 TWX: 71()'2201684 tHamiiton/Avnet Electronics Commerce Industrial Park Commerce Drive Danbury 06810 Tel: (203) 7972800 TWX: 710-<156-9974 t Harvey Electronics 112 Main Street Norwalk 06851 Tel: (203) 8531515 TWX: 7104683373 FLORIDA t Arrow Electronics. Inc. 1001 NoW. 62nd Street Suite 108 FI. Lauderdale 33309 Tel: (305) 7767790 TWX: 5109559456 tArrow Electronics. Inc. 50 Woodlake Drive W. Bldg. B Palm Bay 32905 Tel: (305) 7251480 TWX: 5109596337 tHamiiton/Avnet Electronics 6801 NoW. 15th Way FI. Lauderdale 33309 Tel: (305) 9712900 TWX: 5109563097 tHamliton/Avnet Electronics 3197 TeCh. Drive North 51. Petersburg 33702 Tel: (813) 5763930 TWX: 8108630374 tPioneer/Orlando 6220 S. Orange Blossom Trail Suite 412 Orlando 32809 Tel: (305) 8593600 TWX: 8108500177 tPioneer/FI. Lauderdale 1500 62nd Street N.W. Suite 506 FI. Lauderdale 33309 Tel: (305) 771-7520 TWX: 5109559653 GEORGIA tArrow Electronics. Inc. 2979 PaCific Drive Norcross 30071 Tel: (404) 4498252 TWX: 8107660439 tHamilton/Avnet Electronics 5825 D. Peachtree Corners Norcross 30092 Tel: (404) 4477500 TWX: 8107660432 tPioneer/Georgia 5835B Peachtree Corners E Norcross 30092 Tel: (404) 4481711 TWX: 8107664515 ILLINOIS tArrow Electronics. Inc. 2000 E. Alonquin Street Schaumberg 60195 Tel: (312) 3973440 TWX: 9102913544 tHamiiton/Avnet Electronics 1130 Thorndale Avenue Bensenville 60108 Tel: (312) 8607780 TWX: 9102270060 tPioneer/Chicago 1551 Carmen Drive Elk Grove Village 60007 Tel: (312) 4379680 TWX: 9102621182 INDtANA t Arrow Elec1ronocs. Inc 2718 Rand Road IndIanapolIS 48241 (317) 243-9353 TWX: 8103413119 tHami~on/Avnet Elec1ronocs 485 Orodle DrIve Carrnet 46032 Tel: (317) 8449333 TWX: 81 ().28().3966 tPioneer/lndiana 8408 CasHeplaca Drive Indianapolis 48250 Tel: (317) 8497300 TWX: 81()'26().1794 KANSAS
tHami~on/Avnet Electronics 9219 Qulvera Road Overland Pari< 66215 Tel: (913) 6688900 TWX: 91()'743ooo5
NEW HAMPSHIRE tArrow Elec1ronOCI. Inc 1 PerImeter Road Manchelter 03103 Tel: (603) 668-69&8 TWX: 71()'22().1684 NEWJERIEY t Arrow Elec1ronocs. Inc. Plea..nt Valley Avenue Moor"town 08057 Tel: (215) 928-1800 TWX: 71()'897.()829 tArrow Electronics. Inc. 285 Midland Avenue Saddle Brook 07662 Tel: (201) 7975800 TWX: 71()'998-2206 tArrow Electronics. Inc 2 Industrial Road Fairfield 07006 Tel: (201) 575-5300 TWX: 71 ()'998-2206 tHami~on/Avnet Elec1ronic. 1 Keystone Avenue Bldg. 36 Cherry HIli 08003 Tel: (609) 4240100 TWX: 71 ()'94()'0262 tHarvey Electronics 45 Route 46 Pinebrook 07058 Tel: (201) 5753510 TWX: 71 (). 7344382 tMTI Systems Sales 383 Route 46 W Fairfield 07006 Tel: (201) 2275552 NEW MEXICO t Alliance Electronics Inc. 11030 Cochiti S.E. Albuquerque 87123 Tel: (505) 2923360 TWX: 9109891151 tHamiiton/Avnet Electronics 2524 Baylor Drive S.E. Albuquerque 87106 Tel: (505) 7651500 TWX: 9109890614 NEW YORK tArrow ElectroniCS. Inc. 900 Broad Hollow Road Farmingdale 11735 Tel: (516) 6946800 TWX: 5102246126 tArrow ElectroniCS. Inc. 3000 South Winton Road Rochester 14623 Tel: (715) 2750300 TWX: 510253-<1766 tArrow Electronics. Inc. 7705 M altage Drive Liverpool 13086 Tel: (315) 6521000 TWX: 7105450230 tArrow ElectroniCS. Inc. 20 Oser Avenue Hauppauge 117e8 Tel: (516) 231-1000 TWX: 5102276623 tHamllton/Avnet Electronics 333 Metro Park Rochester 14623 Tel: (716) 4759130 TWX: 5102535470 tHamiiton/Avnet Electronics 16 Corporate Circle E. Syracuse 13057 Tel: (315) 4372641 TWX: 7105411560 tHamilton/Avnet Electronics 5 Hub Drive Melville. Long Island 11747 Tel: (516) 4546000 TWX: 5102246166 t Harvey Electronics P.O. Bo. 1208 Binghamton 13902 Tel: (607) 7488211 TWX: 5102520893
MARYLAND tHamiiton/Avnet Electronics 6822 Oak Hall Lane Columbia 21045 Tel: (301) 9953500 TWX: 71()'8621861 t Mesa Technology Corporation 16021 Industrial Drive Gaithersburg 20877 Tel: (301) 9484350 TWX: 7108289702 tPioneer 911lO Gaither Road Gaithersburg 20877 Tel: (301) 9480710 TWX: 7108280545 MASSACHUSETTS tHamilton/Avnet Electronics 50 Tower Office Park Woburn 01801 Tel: (617) 9359700 TWX: 7103930382 tArrow Electronics. Inc. 1 Arrow Drive Woburn 01801 Tel: (617) 9338130 TWX: 7103936770 tHarvey/Boston 44 Hartwell Avenue Le.ington 02173 Tel: (617) 8631200 TWX: 7103266617 MICHIGAN t Arrow Electronics. Inc. 3810 Vr.rsily Drive Ann Arbor 48104 Tel: (313) 9718220 TWX: 8102236020 tPloneer/Michigan 13485 Stamford Livonia 48150 Tel: (313) 5251800 TWX: 8102423271 tHamiiton/Avnet Electronics 32487 Schoolcraft Road Livonia 48150 Tel: (313) 522-<1700 TWX: 8102428775 tHamilton/Avnet Electronics 2215 29th Street S.E. Space AS Grand Rapids. 49508 Tel: (616) 2438805 TWX: 8102736921 MINNESOTA tArrow Electronics. Inc. 5230 W. 73rd Street Edina 55435 Tel: (612) 83().1800 TV/X: 9105763125 tHamilton/Avnet ElectroniCS 10300 Bren Road East Minnetonka 55343 Tel: (612) 9320600 TWX: (910) 5762720 Pioneer/Twin Cities 10203 Bren Road East Minnetonka 55343 Tel: (612) 9355444 TWX: 9105762738 MISSOURI tArrow Electronics, Inc. 2380 Schuetz 51. Louis 63141 Tel: (314) 5676688 TWX: 9107646600 tHamilton/Avnet Electronics 13743 Shoreline Court Earth Cily 63045 Tel: (314) 3441200 TWX: 9107620684
inter
NEW YORK (C~nt.) tHarvey ElectroniCS 60 Crossways Park West Woodbury. Long Island' 1797 Tel: (5'6) 92'8700 TWX: 5'022'2'84 tHarvey/Rochester 840 Fairport Park Fairport '4450 Tel: (7t6) 38'7070 TWX: 5'0253700' t MTI Systems Sales 38 Harbor Park Drive Port Washington" 050 Tel: (5'6)62'6200 TWX: 5 t 02230846 NORTH CAROLINA OREGON
u.s. DISTRIBUTORS
UTAH tHamllton/Avnet Electronics t 585 West 2100 South Salt Lake City 841'9 Tel: (801) 9722800 TWX: 9'09254018 tArrow Electronics. Inc. 4980 Amelia Earhart Drive Salt Lake City 84112 Tel: (801) 5391135 WASHINGTON t Almac Electronics Corporation '4360 S.E. Eastgate Way Bellevue 98007 Tel: (206) 643-9992 TWX: 9tO444-2067
t Almac Electronics Corporation 8022 S.W. Nimbus. Bldg. 7 Beaverton 97005 Tel: (503) 6419070 TWX: 9104678743
tHamliton/Avnet Electronics
6024 S.w. Jean Road Bldg. C. SUite 10 Lake Oswego 97034 Tel: (503) 6357848 TWX: 9'04558179 PENNSYLVANIA t Arrow Electronics, Inc. 650 Seco Road Monroeville 15'46 Tel: (4'2) 8567000 tPloneer/P,ttsburgh 259 Kappa Drive Pittsburgh 15238 Tel: (4'2) 7822300 TWX: 7107953122 tPioneer/Delaware Valley 261 G,bralter Road Horsham'9044 Tel: (215) 6744000 TWX: 5106656778 TEXAS
t Arrow Electronics. Inc. 938 Burke Street W,nstonSalem 27'0' Tel: (9'9) 72587" TWX: 5'093'3'69 t Arrow Electronics. Inc. 3"7 Poplarwood Court SUite '23 Ralelgn 27265 Tel: (9'9)8763'32 TWX: 5'0928"856 tHamllton/Avnet Electronics 2803 Industrial Drive Raleigh 27609 Tel: (9'9) 8298030 TWX: 5'0928'836 tPloneeriCarollna '03 Industrial Avenue Greensboro 27406 Tel: (9'9)273444' TWX: 5'0925"'4
OHIO
t Arrow ElectroniCS.
, 3715 Gama Road Dallas 75234 Tel: (214) 3867500 TWX: 9108605377
Inc
tArrow Electronics, Inc. 430 W. Rausson Avenue Oakcreek 53154 Tel: (414) 764-6600 TWX: 910-2621193
tHamilton/Avnet Electronics 2975 Moorland Road New Berlin 53151 Tel: (4'4) 784-4510 TWX: 910-2621182
tArrow Electronics. Inc. 7620 McEwen Road Centerville 45459 Tel: (5'3) 4355563 TWX: 8'0459'6" t Arrow E.lectronlcs. Inc 6238 Cochran Road SOlon 44t39 Tel: (2'6) 2483990 TWX: 8'04279409 tHamllton/Avnet ElectrOnic. 954 Senate Drive Dayton 45459 Tel: (5'3) 43306'0 TWX: 8104502531
tHamllton/Avnet Electronics 4588 Emery Industrial Parkway Heights 44128 Tel: (216) 8313500 TWX: 8104279452
Warrensvill~
t Arrow ElectroniCS. Inc 10125 MetropOlitan Austin 78758 Tel: (512) 8354100 TWX: 9108741348
tHamilton/Avnet Electronics 2401 Rutland Auslln 78757 Tel: (512) 8378911 TWX: 9108741319 tHamilton/Avnet Electronics 2111 W. Walnut HIli Lane Irving 75062 Tel: (214) 6594'00 TWX: 910860-5929
tHamilton/Avnet Electronics 8750 West Park Houston 77063 Tel: (7'3)780-177' TWX: 910-881-5523
tPioneer/Austin 9901 Burnet Road Austin 78758 Tel: (512) 635-4000 TWX: 9'0-874-1323 tPioneer/Dallas 13710 Omega Road Dallas 75234 Tel: (2'4) 386-7300 TWX: 91 0-8505563 tPloneer/Houston 5853 Point West Drive Houston 77036 Tel: (7t3) 988-5555 TWX: 910-5762738 tMicrocomputer System Technical Demonstrator Cent.rs
tPloneer/Dayton 4433 Interpoint Boulevard Dayton 45424 Tel: (513)2369900 TWX: 810459,1622 t Pioneer/Cleveland 4800 E. 131st Street Cleveland 44105 Tel: (2'6) 5873600 TWX: 8104222211 OKLAHOMA fArrow ElectroniCS, Inc. 4719 S. Memorial Drive Tulsa 74145 Tel: (918) 6657700
intJ
BELGIUM Intel Corporation S.A Parc Seny
Rue du Moulin a Paplef 51
BOlte 1 B-1160 Brussels Tel: (02) 661 07 11 TELEX: 24814 DENMARK Inlel Denmark A/S Lyngbyvel 32F 2nd Floor OK-21oo Copenhagen Easl Tel: (01) 182000 TELEX: 19567 FINLAND Inlel Finland OY Hameentle 103 SF - 00550 Helsinki 55 Tel: 0/716 955 TELEX: 123 332 FRANCE Intel Corporation, S.A.R.L: 5 Place de la Balance SIlic 223 94528 RunglS Cedex Tel: (01) 687 22 21 TELEX: 270475 Intel Corporation, S.A.R.L. Immeuble BBC 4 Qual des Etrolts 69005 Lyon Tel: (7) 842 40 89 TELEX: 305153
EUROPEAN DISTRIBUTORS/REPRESENTATIVES
AUSTRIA Bacher Elektronlsche Geraete GmbH Rotemuehlgasse 26
A 1120 Vienna
Tel: (222) 83 63 96 TELEX: 11532 BASAT A BELGIUM Inelco Belgium SA Ave. des CrOix de Guerre 94 B1120 Brussels Tel: (02) 216 01 60 TELEX: 25441 DENMARK MultlKomponent A/S Fabriksparken 31 OK-2600 Gloskrup Tel: (02) 45 66 45 TX: 33355 Scandinavian Semiconductor Supply A/S Nannasgade 18 OK-2200 Copenhagen Tel: (01) 83 50 90 TELEX: 19037 FINLAND Oy Flntronlc AB Melkonkatu 24 A SF-00210 Helsinki 21 Tel: (0) 692 60 22 TELEX: 124 224 Ftron SF FRANCE Jermyn SA rue Jules Ferry 35 93170 Bagnolet Tel: (1) 859 04 04 TELEX: 213610 F Metrologle
WEST GERMANY Electronic 2000 Vertrlebs A.G. Neumarkter Strasse 75 0-8000 Munich 80 Tel: (89) 43 40 61 TELEX: 522561 EIEC 0 Jermyn GmbH PosUach 1180 Schulstrosse 48 0-6277 Bad Camberg Tel: (06434) 231 TELEX: 484426 JERM D Celdls Enetechnlk Systems GmbH Schlilerstruse 14 0-2085 Qulckborn-Hamburg Tel: (4106) 6121 TELEX: 213590 ENA D Proelectron Vertrlebs GmbH Max Planck Strasse 1-3 6072 Drelelch bel Frankfurt Tel: (6103) 33564 TELEX: 417983 IRELAND Micro Marketing Glenageary Office Park Glenageary Co. Dublin Tel: (1) 85 62 88 TELEX: 31584 ISRAEL Eastronlcs Ltd. 11 Ronnls Street P.O. Box 39300 Tel Aviv 61390 Tel: (3) 4751 51 TELEX: 33638 ITALY Eledra 35 S.P.A. VIaie Elvella, 18 I 20154 Milano Tel: (2) 34 97 51 TELEX: 332332 Intesi Milonlior; Pal. E/5 20090 Assogo Milano Tel: (02) 82470 TELEX: 311351
NETHERLANDS Koning & Hartman Koperwerf 30 P.O. Box 43220 2544 EN's Gravenhage Tel: 31 (70) 210.101 TELEX: 31528 NORWAY Nordlsk Elektronlc (Norge) A/S Postofflce Box 122 Smedsvlngen 4 1364 Hvalslad Tel: (2) 786 210 TELEX: 16963 PORTUGAL Oitram Componentes E Electronlca LOA Av. Miguel Bombarda, 133 PI 000 LIsboa Tel: (19) 545 313 TELEX: 14182 Brleks-P SPAIN Interface SA Ronda San Pedro 22, 3 Barcelona 10 Tel: (3) 301 7851 TWX: 51508 ITISESA Miguel Angel 23-3 Madrid 10 Tel: (1) 419 5400 TELEX: 27707 SWEDEN AB Gosta Backstrom Box 12009 Aistroemergatan 22 5-10221 Stockholm 12 Tel: (8) 541 080 TELEX: 10135 Nordlsk Electronlk AB Box 27301 Sandhamnsgatan 71 5-10254 Stockholm Tel: (8) 635 040 TELEX: 10547
SWITZERLAND :ndustrade AG Gemsenstrasse 2 Postcheck 80 - 21190 CH-8021 Zurich Tel: (01) 363 23 20 TELEX: 56788 INOEL CH UNITED KINGDOM Bytech Ltd. Unit 57 London Road Earley, Reading Berkshire Tel: (0734) 61031 TELEX: 848215 Comway MIcrosystems Ltd. Market Street UK-Bracknell, Berkshire Tel: 44 (344) 55333 TELEX: 847201 DECADE Ltd. 100 School Road Tilehurst Reading, Berkshire Tel: (0734) 413127 TELEX: 837953 Jermyn Industries Vestry Estate Sevenoaks, Kent Tel: (0732) 450144 TELEX: 95142 M.E.O.L. East Lane Road North Wembley Middlesex HA9 7PP Tel: (01) 904 93 07 TELEX: 28817 Rapid Recall, Ltd Rapid House/Denmark St High Wycombe Berks, England HPll 2ER Tel: (0494) 26 271 TELEX: 837931 YUGOSLAVIA H. R. Microelectronics Enterprises P.O. Box 5604 San Jose, California 95150 T01: 408/978-8000 TELEX: 278-559
inter
AUSTRALIA Intel Semiconductor Ply. Ltd. Spectrum BUilding 200 Pacific Highway LeyelO Crow. Nest, NSW, 2089 Australia Tel: 011-61-2-436-2744 TELEX: 790-20097 HONG KONG Intel Semiconductor Corp. 99-105 De. Voeux Rd., Central 18F, Unit B Hong Kong Tel: 011-852-5-499-432 TELEX: 63869
INTERNATIONAL DISTRIBUTORS/REPRESENTATIVES
CHILE ARGENTINA VLC S.R.L. Sarmiento 1630 PISO (1042) Buenos Aires Tel: 35-1202/9242 TELEX: PuDlic Booth 9900 or 9901 Mailing Address Soimex International Corporation 15 Park Row, Room "1730 New York, New York 10038 (212) 406-3052 Attn: Gaston Briones AUSTRALIA Total Electronics 9 Harker Street Burwood Victoria 3125 Tel: 61 3288-4044 TELEX: .1..1. 31261 Mailing Address Priyate Bag 250 Burwood, Victor,. 3125 Australia Total Electronics "1 Johnstone Lane Lane Coye, N.S.w. 2066 TELEX: 26297 BRAZIL Icetron S.A 05110 Ay. Mutinga 3650-6 Andar PlntuDa Sao Paulo Tel: 261-0211 TELEX: 1122274/1COTBR DIN AV. VIC MCKENNA 204 Casilla 6055 Santiago Tel: 227 564 TELEX: 352003 COLOMIIIA International Computer Machines Carrera 7 No. 72-34 Apdo. Aereo 19403 Bogota 1 Tel: 211-7282 TELEX: 457161CM CO. HONG KONG Schmidt & Co. Ltd. Wing on Centre, 28th Floor 111 Connaught Road Central Tel: 5-455-644 TELEX: 74766 SCHMC HX INDIA Mlcronlc Devices 104/109C, Nirmal Industrial Estate Sion(E) BomDay 400022 Tel: 486-170 TELEX: 011-71447 MDEV IN JAPAN Asahi Electronics Co. Ltd. KMM Bldg. Room 407 2-14-1 Asano, Kokura Kita-Ku, Kitakyushu City 802 Tel: (093) 511-6471 TELEX: AECKY 7126-16 Hamllton-Aynet Electronics Japan Ltd. YU and YOU Bldg. 1-4 Horidome-Cho Nihonbashi Chuo-Ku, Tokyo 103 Tel: (03) 662-9911 TELEX: 2523774 Ryoyo Electric Corp. Konwa Bldg. 1-12-22, Tsukiji Chuo-Ku, Tokyo 104 Tel: (03) 543-7711 Tokyo Electron Ltd. Shin JukU, Nomura Bldg. 26-2 Nishi-Shin Juku-Ichome Shin Juku-Ku, Tokyo 160 Tel. (03) 343-4411 TELEX: 232-2220 LABTEL J KOREA Karam Digital Room 909 Woonam Bldg. 7, 1-KA Bongre-Dong Chung-Ku Seoul 100 Tel: 2-753-8123 TELEX: K25299 KODIGIT NEW ZEALAND McLean Information Technology Ltd. 459 KyDer Pass Road, Newmarket, P.O. Box 9464, Newmarket Auckland 1 , New Zealand Tel: 501-801, 501-219, 587-037 TELEX: NZ21570 THERMAL SINGAPORE General Engineers Corporation Ply. Ltd. Block 3, Units 1003-1008, 10th Floor P.S.A. Multi-Storey Complex TELOK BLANGAH/Pasir Panjang Road Singapore 05 t 1 Tel: 271-3t67 TELEX: RS23987 GENERCO SOUTH AFRICA Electronic Building Elements, Ply. Ltd. P.O. Box 4609 Hazelwood, Pretoria 0001 Tel: 011-27-12-46-9221 or 9227 TELEX: 3-Ot81 SA TAIWAN Taiwan Automation Corp" 3d Floor "75, Section 4 Nanking East Road Taipei Tel: 771-0940 TELEX: 11942 TAIAUTO YUGOSLAVIA H. R. Microelectronics Enterprises P.O. Box 5604 San Jose, California 95150 Tel: (408) 978-8000 TELEX: 278-559
inter
CALIFORNIA Inlel Corp 1350 Shorebird Way MI. View 94043 Tel: (415) 968-8086 TWX: 910-339-9279 910-338-0255 Intel Corp. 2000 E. 41h Sireel Suile 110 Sanla Ana 92705 Tel: (714) 835-2670 TWX: 910-595-2475 Inlel Corp. 7670 Opportunily Road San Diego 92111 Tel: (714) 268-3563 Inlel Corp 5530 N. Corbin Avenue Suile 120 Tarzana 91356 Tel: (213) 708-0333 COLORADO Inlel Corp. 650 Soulh Cherry Suite 720 Denver 80222 Tel: (303) 321-8086 TWX: 910-931-2289 CONNECTICUT Intel Corp. 36 Padanaram Road Danbury 06810 Tel: (203) 792-8366 FLORIDA Intel Corp. 1500 NW. 62nd Street Suite 104 FI. Lauderdale 33309 Tel: (305) 771-0600 TWX: 510-956-9407 Intel Corp. 500 N. Maitland Avenue Suite 205 Maitland 32751 Tel: (305) 628-2393 TWX: 810-853-9219 Inlel Corp. 5151 Adanson Street Orlando 32804 Tel: (305) 628-2393 GEORGIA Intel Corp. 3300 Holcomb Bridge Road SUite 225 Norcross 30092 Tel: (404) 449-0541 ILLINOIS Intel Corp. 2550 Golf Road Suite 815 Rolling Meadows 60008 Tel: (312) 981-7230 TWX: 910-253-1825 KANSAS Inlel Corp. 9393 W. 110th Street Suite 265 Overland Park 66210 Tel: (913) 642-8080 MARYLAND Intel Corp. 7257 Parkway Drive Hanover 21076 Tel: (301) 796-7500 TWX: 710-862-1944