The ChorusOS operating system offers various services which enable an actor
to extend its address space dynamically by allocating memory regions. An actor
may also shrink its address space by freeing memory regions. The ChorusOS
operating system offers the possibility of sharing an area of memory between
two or more actors, regardless of whether these actors are user or supervisor
actors. There are three memory management models, MEM_FLAT
, MEM_PROTECTED
, and MEM_VIRTUAL
(see "Memory Management Models" for details on memory management models).
For some reference target boards, the ChorusOS operating system does not implement all memory management models. For example, the ChorusOS operating system for UltraSPARC IIi-based boards does not implement the MEM_VIRTUAL model.
Each memory management module provides semantics for subsets or variants of these concepts. These semantics and variants are introduced, but are not covered in detail, in the following sections.
The address space of a processor is split into two subsets: the supervisor address space and the user address space. A separate user address space is associated with each user actor. The address space of an actor is also called the memory context of the actor.
A memory management module supports several different user address spaces, and performs memory context switches when required in thread scheduling.
The supervisor address space is shared by every actor, but is only accessible to threads running with the supervisor privilege level. The microkernel code and data are located in the supervisor address space.
In addition, some privileged actors, that is, supervisor actors, also use the supervisor address space. No user address space is allocated to supervisor actors.
The address space is divided into non-overlapping regions. A region is a contiguous range of logical memory addresses, to which certain attributes are associated, such as access rights. Regions can be created and destroyed dynamically by threads. Within the limits of the protection rules, a region can be created remotely in an actor other than the thread's home actor.
Regions can be created with a set of access rights or protections.
The virtual pages that constitute a memory region can be protected against certain types of accesses. Protection modes are machine-dependent, but most architectures provide at least read-write and read-only. Any attempt to violate the protections triggers a page fault. The application can provide its own page fault handler.
Protections can be set independently for sub-regions inside a source region. In this case, the source region is split into several new regions. Similarly, when two contiguous regions get the same protections, they are merged into one region. The programmer is warned that abusing this module could result in consuming too many of the microkernel resources associated with regions.
The model used is determined by the settings of the VIRTUAL_ADDRESS_SPACE
and ON_DEMAND_PAGING
features. See
the MEM(5FEA)
man page for details.
MEM_FLAT
)The microkernel and all applications run in one unique, unprotected address space. This module provides simple memory allocation services.
The flat memory module, MEM_FLAT, is suited for systems that do not have a memory management unit (MMU), or when use of the memory management unit is required for reasons of efficiency only.
Virtual addresses match physical addresses directly. Applications cannot allocate more memory than is physically available.
A unique supervisor address space, matching the physical address space, is featured. Any actor can access any part of physically mapped memory, such as ROM, memory mapped I/O, or anywhere in RAM.
On a given site, memory objects can be shared by several actors. Sharing of fractions of one memory object is not available.
At region creation time, the memory object is either allocated from free physical RAM memory or shared from the memory object of another region.
The concept of sharing of memory objects is provided to control the freeing of physical memory. The memory object associated with a region is returned to the pool of free memory when the associated region is removed from its last context. This concept of sharing does not prevent an actor from accessing any part of the physically mapped memory.
The context of an actor is a collection of non-overlapping regions. The microkernel associates a linear buffer of physical memory to each region, consisting of a memory object. The memory object and the region have the same address and size.
It is not possible to wait for memory at the moment of creation of a region. The memory object must be obtainable immediately, either by sharing or by allocating free physical memory.
There is no default protection mechanism.
MEM_PROTECTED
)The protected memory module (MEM_PROTECTED) is suited to systems with memory management, address translation, and where the application programs are able to benefit from the flexibility and protection offered by separate address spaces. Unlike the full virtual memory management module (MEM_VIRTUAL), it is not directly possible to use secondary storage to emulate more memory than is physically available. This module is primarily targeted at critical and non-critical real-time applications, where memory protection is mandatory, and where low-priority access to secondary storage is kept simple.
Protected memory management supports multiple address spaces and region sharing between different address spaces. However, no external segments are defined; for example, swap and on-demand paging are not supported. Access to programs or data stored on secondary devices, such as video RAM and memory-mapped I/O, must be handled by application-specific file servers.
The microkernel associates a set of physical pages with each region. This set of physical pages is called a memory object.
At the moment of creation of the region, the memory object is either allocated from free physical memory or shared with the memory object of another region. Sharing has a semantic of physical sharing.
At the moment of creation of the region, you can initialize a region from another region. This initialization has a semantic of physical allocation and copying memory at region creation time. To keep the MEM_PROTECTED module small, no deferred on-demand paging technique is used. An actor region maps a memory object to a given virtual address, with the associated access rights.
The size of a memory object is equal to the size of the associated region(s).
It is not possible to wait for memory at region-creation time. The memory object must be obtainable immediately, either by sharing or by allocating free physical memory.
Violations of memory protection trigger memory fault exceptions that can be handled at the application level by supervisor actors.
For typical real-time applications, memory faults denote a software error that should be logged properly for offline analysis. It should also trigger an application-designed fault recovery procedure.
MEM_VIRTUAL
)The virtual memory module, MEM_VIRTUAL, is suitable for systems with page-based memory management units and where the application programs need a high-level virtual memory management system to handle memory requirements greater than the amount of physical memory available. It supports full virtual memory, including the ability to swap memory in and out on secondary devices such as video RAM and memory-mapped I/O. The main functionalities are:
Support of multiple, protected address spaces.
On systems with secondary storage (the usual case), applications can use much more virtual memory than the memory physically available. This module supports full virtual memory with swapping in and out on secondary devices. This module is designed specifically to implement distributed UNIX subsystems on top of the microkernel.
Pages are automatically swapped in and out when appropriate.
The segment is the unit of representation of information in the system.
Segments are usually located in secondary storage. The segment can be persistent (for example, files), or temporary, with a lifetime tied to that of an actor or a thread (for example, swap objects).
The microkernel itself implements special forms of segment, such as the memory objects that are allocated along with the regions.
Like actors, segments are designated by capabilities.
An actor region maps a portion of a segment to a given virtual address with the associated access rights.
The memory management provides the mapping between regions inside an actor and segments (for example, files, swap objects, and shared memory).
The segments and the regions can be created and destroyed dynamically by threads. Within the limits of the protection rules, a region can be created remotely in an actor other than the requesting actor.
Often, regions can define portions of segments that do or do not overlap. Different actors can share a segment. Segments can thus be shared across the network.
The microkernel also implements optimized region copying (copy -on-write).
Regions can be created with a set of access rights or protections.
The virtual pages constituting a memory region can be protected against certain types of access. An attempt to violate the protections triggers a page fault. The application can provide its own page fault handler.
Protections can be set independently for sub-regions inside a source region. In this case, the source region is split into several new regions. Similarly, when two contiguous regions get the same protections, they are combined into one region.
Abusing the MEM_VIRTUAL module could result in consuming too many of the microkernel resources associated with regions.
Memory management also allows explicit access to segments (namely, copying) without mapping them into an address space. Object consistency is thus guaranteed during concurrent accesses on a given site. The same cache management mechanism is used for segments representing program text and data, and files accessed by conventional read/write instructions.
The ChorusOS operating system offers the following optional memory management features:
The VIRTUAL_ADDRESS_SPACE
feature
enables separate virtual address space support using the MEM_PROTECTED
memory management model. If this feature is disabled, all the
actors and the operating system share one single, flat, address space. When
this feature is enabled, a separate virtual address space is created for each
user actor.
The ON_DEMAND_PAGING
feature enables on demand memory allocation and paging using
the MEM_VIRTUAL
model. ON_DEMAND_PAGING
is only available when the VIRTUAL_ADDRESS_SPACE
feature is enabled.
Normally when a demand is made for memory, the same amount of physical
and virtual memory is allocated by the operating system. When the ON_DEMAND_PAGING
feature is enabled, virtual memory allocation
of the user address space does not necessary mean that physical memory will
be allocated. Instead, the operating system may allocate the corresponding
amount of memory on a large swap disk partition. When this occurs, physical
memory will be used as a cache for the swap partition.
The NVRAM feature provides a raw interface to non-volatile memory devices, such as /dev/knvram and /dev/nvramX.
The NVRAM feature does not itself export an API.
The memory management API is summarized in the following table:
Function |
Description |
Flat |
Protected |
Virtual |
---|---|---|---|---|
rgnAllocate() |
Allocate a region |
+ |
+ |
+ |
rgnDup() |
Duplicate an address space |
|
+ |
+ |
rgnFree() |
Free a region |
+ |
+ |
+ |
rgnInit() |
Allocate a region initialized from a segment |
|
|
+ |
rgnInitFromActor() |
Allocate a region initialized from another region |
|
+ |
+ |
rgnMap() |
Create a region and map it to a segment |
|
|
+ |
rgnMapFromActor() |
Allocate a region mapping another region |
+ |
+ |
+ |
rgnSetInherit() |
Set inheritance options for a region |
|
|
+ |
rgnSetPaging() |
Set paging options for a region |
|
|
+ |
rgnSetProtect() |
Set protection options for a region |
+ |
+ |
+ |
rgnStat() |
Get statistics of a region |
+ |
+ |
+ |
svCopyIn() |
Byte copy from user address space |
+ |
+ |
+ |
svCopyInString() |
String copy to user address space |
+ |
+ |
+ |
svCopyOut() |
Byte to user address space |
+ |
+ |
+ |
svPagesAllocate() |
Supervisor address space page allocator |
+ |
+ |
+ |
svPagesFree() |
Free memory allocated by svPagesAllocate() |
+ |
+ |
+ |
svPhysAlloc() |
Physical memory page allocator |
+ |
+ |
+ |
svPhysFree() |
Free memory allocated by svPhysAlloc() |
+ |
+ |
+ |
svPhysMap() |
Map a physical address to the supervisor space |
+ |
+ |
+ |
svPhysUnMap() |
Destroy a mapping created by svPhysMap() |
+ |
+ |
+ |
svMemMap() |
Map a physical address to the supervisor space |
+ |
+ |
+ |
svMemUnMap() |
Destroy a mapping created by svMemUnMap() |
+ |
+ |
+ |
vmCopy() |
Copy data between address spaces |
+ |
+ |
+ |
vmFree() |
Free physical memory |
|
|
+ |
vmLock() |
Lock virtual memory in physical memory |
|
|
+ |
vmMapToPhys() |
Map a physical address to a virtual address |
|
+ |
+ |
vmPageSize() |
Get the page or block size |
+ |
+ |
+ |
vmPhysAddr() |
Get a physical address for a virtual address |
+ |
+ |
+ |
vmSetPar() |
Set the memory management parameters |
|
|
+ |
vmUnLock() |
Unlock virtual memory from physical memory |
|
|
+ |