Memory address space is divided into system space (shared space) or task space (user space). The system space can be accessed from any task in the same way, and the task space can be accessed only from tasks that belong to that task space [Figure 8]. Multiple tasks may in some cases belong to the same task space.
The logical address space of task space and system space depends on the CPU (and MMU) limitations and is therefore implementation-dependent, but in principle task space should be assigned to low addresses and system space to high addresses.
Since interrupt handlers and other task-independent software are not tasks, they do not have a task space of their own. Instead, while in a task-independent portion they belong to the task executing just before entering the task-independent portion. This is the same as the task space of the currently running task returned by tk_get_tid . When there is no task in RUNNING state, task space is undefined.
In a system with no MMU (or not using an MMU), essentially task space does not exist.
Memory may be resident or nonresident.
When nonresident memory is accessed, data is copied to that memory from a disk or other storage. It therefore requires complicated processing such as disk access by a device driver. Accordingly, when nonresident memory is accessed, the device driver, etc., must be in operational state. Access is not possible during dispatch disabled or interrupts disabled state, or while a task-independent portion is executing.
Similarly, in OS internal processing, it is necessary to avoid accessing nonresident memory in a critical section. One such case would be when the memory address passed in a system call parameter points to nonresident memory. Whether or not system call parameters are allowed to reference nonresident memory is an implementation-dependent matter.
Data transfer from a disk or the like due to nonresident memory access is not performed by T-Kernel. Normally T-Kernel is used along with subsystems that handle virtual memory management and other such processing.
In a system that does not use virtual memory, system call parameters or the like pointing to nonresident memory can be ignored, treating all memory as resident.
T-Kernel assumes four levels of memory protection, from 0 to 3.
Level 0 has the highest privilege and level 3 the lowest.
Access can be made only to memory at the currently running protection level or to levels with lower privilege.
Changing from one protection level to another is accomplished by invoking a system call or extended SVC, or by interrupt or CPU exception.
When a protection privilege level of the currently running task is lower than that of the memory being accessed, it is typically the MMU that detects the violation of memory access privilege and raises CPU exception.
The uses of each protection level are as follows.
|0||Kernel, subsystems, device drivers, etc.|
|1||System application tasks|
|3||User application tasks|
A non-task portion (task-independent portion, quasi-task portion, etc.) runs at protection level 0. Only a task portion can run at protection levels 1 to 3. A task portion can also run at protection level 0.
Some MMUs support only two protection levels, privileged and user level. In such a case protection levels 0 to 2 are assigned to privileged level, and protection level 3 to the user level, as if there were 4 levels. In a system with no MMU, all protection levels 0 to 3 are treated as identical.