User's Manual

PROTECTION
Each reference into the segment defined
by
a segment register
is
checked by the hardware to verify
that it
is
within the defined limits of the segment and
is
of the proper type. For example, a code
segment or read-only data segment cannot be written. All these checks are made before the memory
cycle
is
started; any violation
will
prevent that cycle from starting and cause an exception
to
occur.
Since the checks are performed concurrently with address formation, there
is
no
performance penalty.
By
controlling the access rights and privilege attributes of segments, the system designer can assure a
program
will
not change its code or overwrite data belonging
to
another task. Such assurances are vital
to maintaining system integrity
in
the face of error-prone programs.
7.2.1 Separation of Address Spaces
\
As described
in
Chapter
6,
each task can address up
to
a gigabyte (214-2 segments of
up
to
65,536
bytes each) of virtual memory defined
by
the task's LDT (Local Descriptor Table) and the system
GDT.
Up
to
one-half gigabyte (2
13
segments of up
to
65,536 bytes each) of the task's address space
is
defined by the LDT and represents the task's private address space. The remaining virtual address
space
is
defined by the G DT and
is
common
to
all tasks
in
the system.
Each descriptor table
is
itself a special kind of segment recognized
by
the 80286 architecture. These
tables are defined by descriptors in the GDT (Global Descriptor Table). The
CPU has a set of base
and limit registers that point to the GDT and the LDT of the currently running task. The local descrip-
tor table register
is
loaded by a task switch operation.
An active task can only load selectors that reference segments defined
by
descriptors
in
either the
GDT or its private LDT. Since a task cannot reference descriptors in other LDTs, and
no
descriptors
in its LDT refer
to
data or code belonging
to
other tasks, it cannot gain access
to
another tasks' private
code and data (see figure
7-3).
Since the GDT contains information that
is
accessible
by
all users (e.g., library routines, common data,
Operating System services, etc.), the
80286 uses privilege levels and special descriptor types to control
access (see section
7.2.2). Privilege levels protect more trusted data and code (in GDT and LDT) from
less trusted access (WITHIN a task), while the private virtual address spaces defined
by
unique LDTs
provide protection BETWEEN tasks (see figure
7-4).
7.2.2
LOT
and GOT Access Checks
All descriptor tables have a limit used by the protection hardware
to
ensure address space separation
of tasks. Each task's LDT can
be
a different size as defined
by
its descriptor
in
the GDT. The GDT
may also contain less than
8191
descriptors as defined
by
the GDT limit value. The descriptor table
limit identifies the last valid byte of the last descriptor
in
that table. Since each descriptor
is
eight
bytes long, the limit value
is
N X 8
-1
for N descriptors.
Any attempt by a program
to
load a segment register, local descriptor table register (LDTR), or task
register (TR) with a selector that refers
to
a descriptor outside the corresponding limit causes an excep-
tion with an error code identifying the invalid selector used (see figure
7-5).
Not
all descriptor entries
in
the GDT or LDT need contain a valid descriptor. There can
be
holes, or
"empty" descriptors, in the LDT and GDT. "Empty" descriptors allow dynamic allocation and deletion
of segments or other system objects without changing the size of the GDT or LDT. Any descriptor
with an access byte equal
to
zero
is
considered empty. Any attempt
to
load a segment register with a
selector that refers to an empty descriptor
will
cause an exception with an error code identifying the
invalid selection.
7-5