Go to the first, previous, next, last section, table of contents.


Virtual Memory Interface

Memory Allocation

Function: kern_return_t vm_allocate (mach_port_t target_task, vm_address_t *address, vm_size_t size, boolean_t anywhere)
The function vm_allocate allocates a region of virtual memory, placing it in the specified task's address space.

The starting address is address. If the anywhere option is false, an attempt is made to allocate virtual memory starting at this virtual address. If this address is not at the beginning of a virtual page, it will be rounded down to one. If there is not enough space at this address, no memory will be allocated. If the anywhere option is true, the input value of this address will be ignored, and the space will be allocated wherever it is available. In either case, the address at which memory was actually allocated will be returned in address.

size is the number of bytes to allocate (rounded by the system in a machine dependent way to an integral number of virtual pages).

If anywhere is true, the kernel should find and allocate any region of the specified size, and return the address of the resulting region in address address, rounded to a virtual page boundary if there is sufficient space.

The physical memory is not actually allocated until the new virtual memory is referenced. By default, the kernel rounds all addresses down to the nearest page boundary and all memory sizes up to the nearest page size. The global variable vm_page_size contains the page size. mach_task_self returns the value of the current task port which should be used as the target_task argument in order to allocate memory in the caller's address space. For languages other than C, these values can be obtained by the calls vm_statistics and mach_task_self. Initially, the pages of allocated memory will be protected to allow all forms of access, and will be inherited in child tasks as a copy. Subsequent calls to vm_protect and vm_inherit may be used to change these properties. The allocated region is always zero-filled.

The function returns KERN_SUCCESS if the memory was successfully allocated, KERN_INVALID_ADDRESS if an illegal address was specified and KERN_NO_SPACE if there was not enough space left to satisfy the request.

Memory Deallocation

Function: kern_return_t vm_deallocate (mach_port_t target_task, vm_address_t address, vm_size_t size)
vm_deallocate relinquishes access to a region of a task's address space, causing further access to that memory to fail. This address range will be available for reallocation. address is the starting address, which will be rounded down to a page boundary. size is the number of bytes to deallocate, which will be rounded up to give a page boundary. Note, that because of the rounding to virtual page boundaries, more than size bytes may be deallocated. Use vm_page_size or vm_statistics to find out the current virtual page size.

This call may be used to deallocte memory that was passed to a task in a message (via out of line data). In that case, the rounding should cause no trouble, since the region of memory was allocated as a set of pages.

The vm_deallocate call affects only the task specified by the target_task. Other tasks which may have access to this memory may continue to reference it.

The function returns KERN_SUCCESS if the memory was successfully deallocated and KERN_INVALID_ADDRESS if an illegal or non-allocated address was specified.

Data Transfer

Function: kern_return_t vm_read (mach_port_t target_task, vm_address_t address, vm_size_t size, vm_offset_t *data, mach_msg_type_number_t *data_count)
The function vm_read allows one task's virtual memory to be read by another task. The target_task is the task whose memory is to be read. address is the first address to be read and must be on a page boundary. size is the number of bytes of data to be read and must be an integral number of pages. data is the array of data copied from the given task, and data_count is the size of the data array in bytes (will be an integral number of pages).

Note that the data array is returned in a newly allocated region; the task reading the data should vm_deallocate this region when it is done with the data.

The function returns KERN_SUCCESS if the memory was successfully read, KERN_INVALID_ADDRESS if an illegal or non-allocated address was specified or there was not size bytes of data following the address, KERN_INVALID_ARGUMENT if the address does not start on a page boundary or the size is not an integral number of pages, KERN_PROTECTION_FAILURE if the address region in the target task is protected against reading and KERN_NO_SPACE if there was not enough room in the callers virtual memory to allocate space for the data to be returned.

Function: kern_return_t vm_write (mach_port_t target_task, vm_address_t address, vm_offset_t data, mach_msg_type_number_t data_count)
The function vm_write allows a task to write to the vrtual memory of target_task. address is the starting address in task to be affected. data is an array of bytes to be written, and data_count the size of the data array.

The current implementation requires that address, data and data_count all be page-aligned. Otherwise, KERN_INVALID_ARGUMENT is returned.

The function returns KERN_SUCCESS if the memory was successfully written, KERN_INVALID_ADDRESS if an illegal or non-allocated address was specified or there was not data_count bytes of allocated memory starting at address and KERN_PROTECTION_FAILURE if the address region in the target task is protected against writing.

Function: kern_return_t vm_copy (mach_port_t target_task, vm_address_t source_address, vm_size_t count, vm_offset_t dest_address)
The function vm_copy causes the source memory range to be copied to the destination address. The source and destination memory ranges may overlap. The destination address range must already be allocated and writable; the source range must be readable.

vm_copy is equivalent to vm_read followed by vm_write.

The current implementation requires that address, data and data_count all be page-aligned. Otherwise, KERN_INVALID_ARGUMENT is returned.

The function returns KERN_SUCCESS if the memory was successfully written, KERN_INVALID_ADDRESS if an illegal or non-allocated address was specified or there was insufficient memory allocated at one of the addresses and KERN_PROTECTION_FAILURE if the destination region was not writable or the source region was not readable.

Memory Attributes

Function: kern_return_t vm_region (mach_port_t target_task, vm_address_t *address, vm_size_t *size, vm_prot_t *protection, vm_prot_t *max_protection, vm_inherit_t *inheritance, boolean_t *shared, mach_port_t *object_name, vm_offset_t *offset)
The function vm_region returns a description of the specified region of target_task's virtual address space. vm_region begins at address and looks forward through memory until it comes to an allocated region. If address is within a region, then that region is used. Various bits of information about the region are returned. If address was not within a region, then address is set to the start of the first region which follows the incoming value. In this way an entire address space can be scanned.

The size returned is the size of the located region in bytes. protection is the current protection of the region, max_protection is the maximum allowable protection for this region. inheritance is the inheritance attribute for this region. shared tells if the region is shared or not. The port object_name identifies the memory object associated with this region, and offset is the offset into the pager object that this region begins at.

The function returns KERN_SUCCESS if the memory region was successfully located and the information returned and KERN_NO_SPACE if there is no region at or above address in the specified task.

Function: kern_return_t vm_protect (mach_port_t target_task, vm_address_t address, vm_size_t size, boolean_t set_maximum, vm_prot_t new_protection)
The function vm_protect sets the virtual memory access privileges for a range of allocated addresses in target_task's virtual address space. The protection argument describes a combination of read, write, and execute accesses that should be permitted.

address is the starting address, which will be rounded down to a page boundary. size is the size in bytes of the region for which protection is to change, and will be rounded up to give a page boundary. If set_maximum is set, make the protection change apply to the maximum protection associated with this address range; otherwise, the current protection on this range is changed. If the maximum protection is reduced below the current protection, both will be changed to reflect the new maximum. new_protection is the new protection value for this region; a set of: VM_PROT_READ, VM_PROT_WRITE, VM_PROT_EXECUTE.

The enforcement of virtual memory protection is machine-dependent. Nominally read access requires VM_PROT_READ permission, write access requires VM_PROT_WRITE permission, and execute access requires VM_PROT_EXECUTE permission. However, some combinations of access rights may not be supported. In particular, the kernel interface allows write access to require VM_PROT_READ and VM_PROT_WRITE permission and execute access to require VM_PROT_READ permission.

The function returns KERN_SUCCESS if the memory was successfully protected, KERN_INVALID_ADDRESS if an illegal or non-allocated address was specified and KERN_PROTECTION_FAILURE if an attempt was made to increase the current or maximum protection beyond the existing maximum protection value.

Function: kern_return_t vm_inherit (mach_port_t target_task, vm_address_t address, vm_size_t size, vm_inherit_t new_inheritance)
The function vm_inherit specifies how a region of target_task's address space is to be passed to child tasks at the time of task creation. Inheritance is an attribute of virtual pages, so address to start from will be rounded down to a page boundary and size, the size in bytes of the region for wihch inheritance is to change, will be rounded up to give a page boundary. How this memory is to be inherited in child tasks is specified by new_inheritance. Inheritance is specified by using one of these following three values:

VM_INHERIT_SHARE
Child tasks will share this memory with this task.
VM_INHERIT_COPY
Child tasks will receive a copy of this region.
VM_INHERIT_NONE
This region will be absent from child tasks.

Setting vm_inherit to VM_INHERIT_SHARE and forking a child task is the only way two Mach tasks can share physical memory. Remember that all the theads of a given task share all the same memory.

The function returns KERN_SUCCESS if the memory inheritance was successfully set and KERN_INVALID_ADDRESS if an illegal or non-allocated address was specified.

Function: kern_return_t vm_wire (mach_port_t host_priv, mach_port_t target_task, vm_address_t address, vm_size_t size, vm_prot_t access)
The function vm_wire allows privileged applications to control memory pageability. host_priv is the privileged host port for the host on which target_task resides. address is the starting address, which will be rounded down to a page boundary. size is the size in bytes of the region for which protection is to change, and will be rounded up to give a page boundary. access specifies the types of accesses that must not cause page faults.

The semantics of a successful vm_wire operation are that memory in the specified range will not cause page faults for any accesses included in access. Data memory can be made non-pageable (wired) with a access argument of VM_PROT_READ | VM_PROT_WRITE. A special case is that VM_PROT_NONE makes the memory pageable.

The function returns KERN_SUCCESS if the call succeeded, KERN_INVALID_HOST if host_priv was not the privileged host port, KERN_INVALID_TASK if task was not a valid task, KERN_INVALID_VALUE if access specified an invalid access mode, KERN_FAILURE if some memory in the specified range is not present or has an inappropriate protection value, and KERN_INVALID_ARGUMENT if unwiring (access is VM_PROT_NONE) and the memory is not already wired.

The vm_wire call is actually an RPC to host_priv, normally a send right for a privileged host port, but potentially any send right. In addition to the normal diagnostic return codes from the call's server (normally the kernel), the call may return mach_msg return codes.

Function: kern_return_t vm_machine_attribute (mach_port_t task, vm_address_t address, vm_size_t size, vm_prot_t access, vm_machine_attribute_t attribute, vm_machine_attribute_val_t value)
The function vm_machine_attribute specifies machine-specific attributes for a VM mapping, such as cachability, migrability, replicability. This is used on machines that allow the user control over the cache (this is the case for MIPS architectures) or placement of memory pages as in NUMA architectures (Non-Uniform Memory Access time) such as the IBM ACE multiprocessor.

Machine-specific attributes can be consider additions to the machine-independent ones such as protection and inheritance, but they are not guaranteed to be supported by any given machine. Moreover, implementations of Mach on new architectures might find the need for new attribute types and or values besides the ones defined in the initial implementation.

The types currently defined are

MATTR_CACHE
Controls caching of memory pages
MATTR_MIGRATE
Controls migrability of memory pages
MATTR_REPLICATE
Controls replication of memory pages

Corresponding values, and meaning of a specific call to vm_machine_attribute

MATTR_VAL_ON
Enables the attribute. Being enabled is the default value for any applicable attribute.
MATTR_VAL_OFF
Disables the attribute, making memory non-cached, or non-migratable, or non-replicatable.
MATTR_VAL_GET
Returns the current value of the attribute for the memory segment. If the attribute does not apply uniformly to the given range the value returned applies to the initial portion of the segment only.
MATTR_VAL_CACHE_FLUSH
Flush the memory pages from the Cache. The size value in this case might be meaningful even if not a multiple of the page size, depending on the implementation.
MATTR_VAL_ICACHE_FLUSH
Same as above, applied to the Instruction Cache alone.
MATTR_VAL_DCACHE_FLUSH
Same as above, applied to the Data Cache alone.

The function returns KERN_SUCCESS if call succeeded, and KERN_INVALID_ARGUMENT if task is not a task, or address and size do not define a valid address range in task, or attribute is not a valid attribute type, or it is not implemented, or value is not a permissible value for attribute.

Mapping Memory Objects

Function: kern_return_t vm_map (mach_port_t target_task, vm_address_t *address, vm_size_t size, vm_address_t mask, boolean_t anywhere, mach_port_t memory_object, vm_offset_t offset, boolean_t copy, vm_prot_t cur_protection, vm_prot_t max_protection, vm_inherit_t inheritance)
The function vm_map maps a region of virtual memory at the specified address, for which data is to be supplied by the given memory object, starting at the given offset within that object. In addition to the arguments used in vm_allocate, the vm_map call allows the specification of an address alignment parameter, and of the initial protection and inheritance values.

If the memory object in question is not currently in use, the kernel will perform a memory_object_init call at this time. If the copy parameter is asserted, the specified region of the memory object will be copied to this address space; changes made to this object by other tasks will not be visible in this mapping, and changes made in this mapping will not be visible to others (or returned to the memory object).

The vm_map call returns once the mapping is established. Completion of the call does not require any action on the part of the memory manager.

Warning: Only memory objects that are provided by bona fide memory managers should be used in the vm_map call. A memory manager must implement the memory object interface described elsewhere in this manual. If other ports are used, a thread that accesses the mapped virtual memory may become permanently hung or may receive a memory exception.

target_task is the task to be affected. The starting address is address. If the anywhere option is used, this address is ignored. The address actually allocated will be returned in address. size is the number of bytes to allocate (rounded by the system in a machine dependent way). The alignment restriction is specified by mask. Bits asserted in this mask must not be asserted in the address returned. If anywhere is set, the kernel should find and allocate any region of the specified size, and return the address of the resulting region in address.

memory_object is the port that represents the memory object: used by user tasks in vm_map; used by the make requests for data or other management actions. If this port is MEMORY_OBJECT_NULL, then zero-filled memory is allocated instead. Within a memory object, offset specifes an offset in bytes. This must be page aligned. If copy is set, the range of the memory object should be copied to the target task, rather than mapped read-write.

The function returns KERN_SUCCESS if the object is mapped, KERN_NO_SPACE if no unused region of the task's virtual address space that meets the address, size, and alignment criteria could be found, and KERN_INVALID_ARGUMENT if an illegal argument was provided.

Memory Statistics

Data type: vm_statistics_data_t
This structure is returned in vm_stats by the vm_statistics function and provides virtual memory statistics for the system. It has the following members:

long pagesize
The page size in bytes.
long free_count
The number of free pages.
long active_count
The umber of active pages.
long inactive_count
The number of inactive pages.
long wire_count
The number of pages wired down.
long zero_fill_count
The number of zero filled pages.
long reactivations
The number of reactivated pages.
long pageins
The number of pageins.
long pageouts
The number of pageouts.
long faults
The number of faults.
long cow_faults
The number of copy-on-writes.
long lookups
The number of object cache lookups.
long hits
The number of object cache hits.

Function: kern_return_t vm_statistics (mach_port_t target_task, vm_statistics_data_t *vm_stats)
The function vm_statistics returns the statistics about the kernel's use of virtual memory since the kernel was booted. pagesize can also be found as a global variable vm_page_size which is set at task initialization and remains constant for the life of the task.


Go to the first, previous, next, last section, table of contents.