Protected mode has a number of features designed to enhance an operating system's control over application software, in order to increase security and system stability.
Privilege levels In protected mode, there are four privilege levels or
rings, numbered from 0 to 3, with ring 0 being the most privileged and 3 being the least. The use of rings allows for system software to restrict tasks from accessing data,
call gates or executing privileged instructions. In most environments, the operating system and some
device drivers run in ring 0 and applications run in ring 3. For the most part, the binary compatibility with real-mode code, the ability to access up to 16 MB of physical memory, and 1 GB of
virtual memory, were the most apparent changes to application programmers. This was not without its limitations. If an application utilized or relied on any of the techniques below, it would not run: • Segment arithmetic • Privileged instructions • Direct hardware access •
Writing to a code segment • Executing data • Overlapping segments • Use of BIOS functions, due to the BIOS interrupts being reserved by Intel In reality, almost all
DOS application programs violated these rules. Due to these limitations,
virtual 8086 mode was introduced with the 386. Despite such potential setbacks,
Windows 3.0 and its successors can take advantage of the binary compatibility with real mode to run many Windows 2.x (
Windows 2.0 and
Windows 2.1x) applications in protected mode, which ran in real mode in Windows 2.x.
Virtual 8086 mode With the release of the 386, protected mode offers what the Intel manuals call
virtual 8086 mode. Virtual 8086 mode is designed to allow code previously written for the 8086 to run unmodified and concurrently with other tasks, without compromising security or system stability. Virtual 8086 mode, however, is not completely backward compatible with all programs. Programs that require segment manipulation, privileged instructions, direct hardware access, or use
self-modifying code will generate an
exception that must be served by the operating system. In addition, applications running in virtual 8086 mode generate a
trap with the use of instructions that involve
input/output (I/O), which can negatively impact performance. Due to these limitations, some programs originally designed to run on the 8086 cannot be run in virtual 8086 mode. As a result, system software is forced to either compromise system security or backward compatibility when dealing with
legacy software. An example of such a compromise can be seen with the release of
Windows NT, which dropped backward compatibility for "ill-behaved" DOS applications.
Segment addressing Real mode In real mode each logical address points directly into a physical memory location, every logical address consists of two
16-bit parts: The segment part of the logical address contains the base address of a segment with a granularity of 16 bytes, i.e. a segment may start at physical address 0, 16, 32, ..., 220 − 16. The offset part of the logical address contains an offset inside the segment, i.e. the physical address can be calculated as physical_address = segment_part × 16 + offset, if the address
line A20 is enabled, or (segment_part × 16 + offset) mod 220, if A20 is off. Every segment has a size of 216 bytes.
Protected mode In protected mode, the is replaced by a 16-bit
selector, in which the 13 upper bits (bit 3 to bit 15) contain the index of an
entry inside a
descriptor table. The next bit (bit 2) specifies whether the operation is used with the GDT or the LDT. The lowest two bits (bit 1 and bit 0) of the selector are combined to define the privilege of the request, where the values of 0 and 3 represent the highest and the lowest privilege, respectively. This means that the byte offset of descriptors in the descriptor table is the same as the 16-bit selector, provided the lower three bits are zeroed. The descriptor table entry defines the real
linear address of the segment, a limit value for the segment size, and some attribute bits (flags).
286 The segment address inside the descriptor table entry has a length of 24 bits so every byte of the physical memory can be defined as bound of the segment. The limit value inside the descriptor table entry has a length of 16 bits so segment length can be between 1 byte and 216 byte. The calculated linear address equals the physical memory address.
386 The segment address inside the descriptor table entry is expanded to 32 bits so every byte of the physical memory can be defined as bound of the segment. The limit value inside the descriptor table entry is expanded to 20 bits and completed with a granularity flag (G-bit, for short): • If G-bit is zero limit has a granularity of 1 byte, i.e. segment size may be 1, 2, ..., 220 bytes. • If G-bit is one limit has a granularity of 212 bytes, i.e. segment size may be 1 × 212, 2 × 212, ..., 220 × 212 bytes. If paging is off, the calculated linear address equals the physical memory address. If paging is on, the calculated linear address is used as input of paging. The 386 processor also uses 32 bit values for the address offset. For maintaining compatibility with 286 protected mode a new default flag (D-bit, for short) was added. If the D-bit of a code segment is off (0) all commands inside this segment will be interpreted as 16-bit commands by default; if it is on (1), they will be interpreted as 32-bit commands.
Structure of segment descriptor entry Where: •
A is the
Accessed bit; •
R is the
Readable bit; •
C (Bit 42) depends on
X: • if
X = 1 then
C is the
Conforming bit, and determines which privilege levels can far-jump to this segment (without changing privilege level): • if
C = 0 then only code with the same privilege level as
DPL may jump here; • if
C = 1 then code with the same or a lower privilege level relative to
DPL may jump here. • if
X = 0 then
C is the
direction bit: • if
C = 0 then the segment grows
up; • if
C = 1 then the segment grows
down. •
X is the
Executable bit: •
DPL is the
Descriptor Privilege Level; •
P is the
Present bit; •
D is the
Default operand size; •
G is the
Granularity bit; • Bit 52 of the 80386 descriptor is not used by the hardware.
Paging In addition to adding virtual 8086 mode, the 386 also added paging to protected mode. Through paging, system software can restrict and control a task's access to pages, which are sections of memory. In many operating systems, paging is used to create an independent virtual address space for each task, preventing one task from manipulating the memory of another. Paging also allows for pages to be moved out of
primary storage and onto a slower and larger
secondary storage, such as a
hard disk drive. This allows for more memory to be used than physically available in primary storage.
Multitasking Through the use of the rings, privileged
call gates, and the
Task State Segment (TSS), introduced with the 286,
preemptive multitasking was made possible on the x86 architecture. The TSS allows general-purpose registers, segment selector fields, and stacks to all be modified without affecting those of another task. The TSS also allows a task's privilege level, and I/O port permissions to be independent of another task's. In many operating systems, the full features of the TSS are not used. This is commonly due to portability concerns or due to the performance issues created with hardware task switches. == Operating systems ==