Restricting IO Accesses

The Problem

This section is a copy of the section entitled “IO Port Anarchy” on page 32 from the chapter entitled “Multitasking Problems” on page 31. It is repeated here to eliminate the need to turn back to that section. It states the nature of the IO-related problem that must be dealt with in VM86 (as well as other) programs.

Assume that the currently executing task needs to initiate a disk access.

  1. To do this, it must program the disk controller's IO registers with the information defining the disk command type (e.g., disk read), the cylinder number, the head (or surface) number, the start sector number and the number of sectors to be transferred. This is accomplished by executing a series of OUT instructions that cause the processor to perform a series of IO write transactions on its FSB to transfer the command and associated parameters to the disk controller.

  2. Now assume that the task has programmed some, but not all of the disk controller's registers and the task's timeslice expires. The processor is interrupted, causing a switch back to the OS scheduler.

  3. The scheduler suspends the current task and starts or resumes another task.

  4. The new task, having no knowledge of the suspended task, may decide that it also wants to issue a command to the disk controller. Assume that it does so and that the operation completes without error.

  5. Eventually, the OS suspends this task and reawakens the other task. This task doesn't know that it was put to sleep and resumes execution at the point of suspension.

  6. It completes the series of IO writes to transfer the remainder of the request parameters to the disk controller. It has no idea that the initial parameters that it sent to the disk controller (before it was suspended) were overwritten by the other task while it was asleep.

  7. The end result will be that the task's disk operation will not occur correctly.

Generally speaking, the system's IO devices should be treated as a pool of shared resources to be managed by a central entity (the OS). Having one entity perform all communications with IO devices ensures that there will be no contention for IO devices between multiple tasks.

To accomplish this, the OS cannot permit tasks to talk directly to IO ports. In other words, any attempt to execute an IN or OUT instruction (or INS or OUTS) should cause the processor to trap (i.e., jump) to the OS. The OS then communicates with the IO device for the task.

The OS and/or processor could be configured to permit a task to access certain IO ports directly, but restrict access to other ports.

The sections that follow describe the methods used to monitor task IO accesses in both IO and memory-mapped IO space.

IO-Mapped IO

IO Permission in Protected Mode

When the processor is in Protected Mode but is not in VM86 mode (i.e., EFlags[VM] = 0) and it attempts to execute an IOPL-sensitive instruction (see “Definition of IO Privilege Level (IOPL)” on page 176), the privilege check is performed in the following manner:

  • If the CPL is numerically ≤ the IOPL (i.e., the program's privilege level is the same as or exceeds the IOPL; see Figure 15-5 on page 343), no exception is generated and the IO instruction is executed.

  • If the CPL is numerically > the IOPL (i.e., the program's privilege level is not as good as the IOPL) and the instruction is one of the IO instructions (IN, OUT, INS, or OUTS), the processor checks the current task's IO Permission Bit Map (in its TSS; see Figure 15-4 on page 342) to determine if the current application is permitted to access the addressed IO port(s). If the bit map indicates that the task is permitted to access the indicated IO port(s), no exception is generated and the IO instruction is executed. Otherwise, a GP exception is generated.

    Figure 15-4. Solving the IO Problem (when VM86 = 1, IOPL is don't care))

The IO Permission Bit Map was described in the section entitled “IO Permission Bit Map Offset Field” on page 178.

IO Permission in VM86 Mode

When the processor is in Protected Mode and is operating in VM86 mode (i.e., EFlags[VM] = 1) and attempts to execute an IO instruction (IN, INS, OUT, or OUTS), the permission check is performed as follows:

  • The IOPL is not checked at all.

  • The processor checks the current task's IO permission bit map (see Figure 15-4 on page 342) to determine if the current application is permitted to access the addressed IO port(s). If the bit map indicates that the task is permitted to access the indicated IO port(s), no exception is generated and the IO instruction is executed. Otherwise, a GP exception is generated.

The IO Permission Bit Map was described in the section entitled “IO Permission Bit Map Offset Field” on page 178.

Memory-Mapped IO

The system may implement memory-mapped IO ports that are used to communicate with IO devices. Just as with IO-mapped IO ports, the OS should provide a mechanism that permits the current task to communicate directly with some memory-mapped IO ports while denying direct access to others. This can be implemented using the Paging mechanism.

Segregate Ports into Two Groups of Memory Pages

The system designer can group the memory-mapped IO ports that tasks are permitted to access directly into one (or more) 4KB pages of physical memory space. Those memory-mapped IO ports that only the OS should be able to access, on the other hand, should be grouped into one (or more) other 4KB pages of linear memory space.

Set Up Task's Page Tables to Permit or Deny Access

In each task's Page Tables, memory-mapped IO accesses that are to be permitted should be mapped to the physical page(s) actually occupied by the memory-mapped IO ports. Conversely, memory-mapped IO accesses that are to be denied should be mapped to a page(s) that is marked not present (P = 0).

When the task attempts a memory access to a port that it is permitted to access, the Paging Unit translates the linear memory address into the physical memory address of the port and performs the access.

When the task attempts a memory access to a restricted port, the Paging Unit selects a Page Table entry with P = 0 and a Page Fault exception is generated. The Page Fault exception handler then passes control to the task's VMM. The VMM can then examine the IO instruction attempted and the 32-bit linear address targeted and decide what to do (e.g., terminate the task, perform the access itself, etc.).

Handling Display Frame Buffer Updates

As discussed earlier, each DOS program “owns” a 1MB block of linear memory space that it thinks is the first megabyte of physical memory space. Many DOS programs update the video frame buffer in memory directly (rather than making a BIOS or DOS function call) by performing memory writes to the display frame buffer area (memory addresses 000A0000h through 000BFFFFh). The OS sets up the Page Tables for each VM86 task to direct all accesses within its linear address range 000A0000h through 000BFFFFh to a separate physical memory buffer (a “virtual” video frame buffer) for each task.

Whenever a DOS task is resumed, the VMM can then copy the DOS program's “virtual” frame buffer into the physical frame buffer residing in physical memory in the range from 000A0000h through 000BFFFFh. At some point (due to timeslice exhaustion or some other interrupt), the OS suspends the VM86 task and transfers control to another task. If the next task is another VM86 task, the OS first copies the task's virtual frame buffer into the real frame buffer and then resumes the task. This ensures that the screen looks just as it did at the point when the task was suspended earlier.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.12.240