summaryrefslogtreecommitdiff
path: root/mach/externalpagermechanism.mdwn
diff options
context:
space:
mode:
Diffstat (limited to 'mach/externalpagermechanism.mdwn')
-rw-r--r--mach/externalpagermechanism.mdwn173
1 files changed, 173 insertions, 0 deletions
diff --git a/mach/externalpagermechanism.mdwn b/mach/externalpagermechanism.mdwn
new file mode 100644
index 00000000..91907131
--- /dev/null
+++ b/mach/externalpagermechanism.mdwn
@@ -0,0 +1,173 @@
+Mach provides a so-called external pager [[mechanism]]. This
+mechanism serves to separate *managing memory* from *managing
+content*. Mach does the former while user space tasks do the
+latter.
+
+# Introduction
+
+In Mach, a task's [[Mach/AddressSpace]] consists of references
+to [[Mach/MemoryObjects]]. A memory object is designated using
+a [[Mach/Port]] (a port is just a [[capability]]) and
+implemented by a normal process.
+
+To associate a memory object with a portion of a task's
+address space, vm\_map is invoked a capability designating
+the task and passing a reference to the memory object
+and the offset at which to install it. (The first time
+a task maps an object, Mach sends an initialization message
+to the server including a control capability, which it uses
+to supply pages to the kernel.) This is essentially
+the same as mapping a file into an address space on Unix
+using mmap.
+
+When a task faults, Mach checks to see if there is a memory
+object associated with the fault address. If not, the task
+is sent an exception, which is normally further propagated
+as a segmentation fault. If there is an associated memory
+object, Mach checks whether the corresponding page is in core.
+If it is, it installs the page and resumes the task. Mach
+then invokes the memory object with the memory\_object\_request
+method and the page to read. The memory manager then fetches
+or creates the content as appropriate and supplies it to
+Mach using the memory\_object\_supply method.
+
+
+# Creating and Mapping a Memory Object
+
+The following illustrates the basic idea:
+
+> ________
+> / \
+> | Mach |
+> \________/
+> /| / |\ \
+> (C) vm_map / / m_o_ready (E)\ \ (D) memory_object_init
+> / |/ (F) return \ \|
+> ________ ________
+> / \ -----> / \
+> | Client | (A) open | Server |
+> \________/ <----- \________/
+> (B) memory_object
+
+
+(A) The client sends an "open" rpc to the server.
+
+(B) The server creates a memory object (i.e., a port receive right), adds
+it to the port set that it is listening on and returns a capability (a port
+send right) to the client.
+
+(C) The client attempts to map the object into its address space using
+the vm\_map rpc. It passes a reference to the port that the server gave
+it to the vm server (typically Mach).
+
+(D) Since Mach has never seen the object before, it queues a
+memory\_object\_init on the given port along with a send right (the
+memory control port) for the manager to use to send messages to the
+kernel and also as an authentication mechanism for future
+interactions: the port is supplied so that the manager will be able to
+identify from which kernel a given memory\_object\_* IPC is from.
+
+(E) The server dequeues the message, initializes internal data
+structures to manage the mapping and then invokes the
+memory\_object\_ready method on the control object.
+
+(F) The kernel sees that the manager is ready, sets up the appropriate
+mappings in the client and then replies to the vm\_map rpc indicating
+success.
+
+There is nothing stopping others from playing "the kernel." This is
+not a security problem: clients must [[trust]] the server from whom they
+obtain memory objects and also the servers with whom they share
+the object. Multiple memory managers are a reality that should be
+dealt with gracefully: they are useful for network transparent
+mappings etc.
+
+# Resolving Page Faults
+
+> (G) Client ________
+> resumed / \
+> | Mach |
+> (A) Fault +----|------+ | \ (B) m_o_request (C) store_read
+> ____|___ \_____|__/ |\ \| ________ _________
+> / +---\-------+ \ / \ / \
+> | Client | (F) | Server |<===>| storeio |
+> \________/ m_o_supply \________/ \_________/
+> (E) return data | ^
+> | | (D) device_read
+> v |
+> ________
+> / Device \
+> | Driver |
+> \________/
+> | ^
+> | |
+> v
+> ____________
+> / Hardware \
+
+
+(A) The client does a memory access and faults. The kernel catches
+the fault and maps the address to the appropriate memory object. It
+then invokes the memory_object_request method on the associated
+capability. (In addition to the page to supply, it also supplies the
+control port so that the server can determine which kernel
+sent the message.)
+
+(B) The manager dequeues the message. On the Hurd, this is translated
+into a store_read: a function in the libstore library which is used to
+transparently manage block devices. The storeio server starts off as
+a separate process, however, if the server has the appropriate
+permission, the backing object can be contacted directly by the
+server. This layer of indirection is desirable when, for instance, a
+storeio running as root may want to only permit read only access to a
+resource, yet it cannot safely transfer its handle to the client. In
+this case, it would proxy the requests.
+
+(C) The storeio server contacts, for instance, a device driver to do
+the read. This could also be a network block device (the NBD server
+in GNU/Linux), a file, a memory object, etc.
+
+(D) The device driver allocates an anonymous page from the default
+pager and reads the data into it. Once all of the operations are
+complete, the device returns the data to the client unmapping it from
+its own address space at the same time.
+
+(E) The storeio transfers the page to the server. The page is still
+anonymous.
+
+(F) The manager does a memory_object_supply transferring the page to
+the kernel. Only now is the page not considered to be anonymous but
+managed.
+
+(G) The kernel caches the page, installs it in the client's virtual
+address space and finally, resumes the client.
+
+# Paging Data Out
+
+
+> Change manager Pager m_o_return store_write
+> \ _________ (B) __(A)__ (C) ________ (D) _______
+> S | / Default \ / \ / \ / \
+> W |<=>| Pager |<=>| Mach |==>| server |<=>| storeio |<=>
+> A | \_________/ \________/ \________/ \_______/
+> P |
+> /
+
+
+(A) The paging [[policy]] is implemented by Mach: servers just implement
+the [[mechanism]].
+
+(B) Once the kernel has selected a page that it would like to evict, it
+changes the manager from the server to the default pager. This way,
+if the server does not deallocate the page quickly enough, it cannot
+cause a denial of service: the kernel will just later double page it
+to swap (the default pager is part of the [[tcb]]).
+
+(C) Mach then invokes memory\_object\_return method on the control
+object. The server is expected to save the page free it in a timely
+fashion. The server is not required to send a response to the kernel.
+
+(D) The manager then transfers the data to the storeio which
+eventually sends it to disk. The device driver consumes the memory
+doing the equivalent of a vm_deallocate.
+