<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>blog.pr4tt.com</title>
    <description>Simon Pratt's blog</description>
    <link>http://blog.pr4tt.com/</link>
    <atom:link href="http://blog.pr4tt.com/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>goasm - a Go assembly generator</title>
        <description>&lt;p&gt;Recently, I’ve been learning &lt;a href=&quot;https://golang.org/&quot;&gt;Go&lt;/a&gt;.  One thing I’ve learned is that &lt;a href=&quot;https://golang.org/doc/asm&quot;&gt;the Go compiler generates its own assembly language&lt;/a&gt;.  There’s &lt;a href=&quot;https://www.youtube.com/watch?v=KINIAgRpkDA&quot;&gt;a great talk by Rob Pike about it&lt;/a&gt;.  While I was learning, I began to wish there was a tool similar to &lt;a href=&quot;https://godbolt.org/&quot;&gt;the Compiler Explorer (more commonly referred to as Godbolt)&lt;/a&gt;, but for Go assembly.  So I built &lt;a href=&quot;https://goasm.herokuapp.com&quot;&gt;goasm, a Go assembly generator&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;details&quot;&gt;Details&lt;/h1&gt;

&lt;p&gt;The design is straightforward.  It prints the Go code to a temporary file, and then compiles it (sending the output object file to /dev/null).  One lesson I learned was that if you send an XMLHTTPRequest using JavaScript, and your form data is encoded as a FormData object, this is received by the back-end as multi-part form data.  This threw me off at first, because simply submitting the form doesn’t do this.&lt;/p&gt;

&lt;p&gt;I deployed the app on &lt;a href=&quot;https://www.heroku.com&quot;&gt;Heroku&lt;/a&gt;, since they &lt;a href=&quot;https://www.heroku.com/go&quot;&gt;support Go apps&lt;/a&gt;.  Normally, Go is only available on your Heroku dyno while building your app, but I used &lt;a href=&quot;https://github.com/jpillora/heroku-buildpack-go&quot;&gt;jpillora’s custom heroku Go buildpack&lt;/a&gt;, because it keeps Go in the run environment.  Jpillora built this in order to build the pretty neat &lt;a href=&quot;https://gox.jpillora.com&quot;&gt;cloud-gox&lt;/a&gt; tool.&lt;/p&gt;

&lt;h1 id=&quot;future&quot;&gt;Future&lt;/h1&gt;

&lt;p&gt;I would like to implement setting arbitrary GOOS and GOARCH variables.  It would be very easy, except that &lt;a href=&quot;https://github.com/golang/go/issues/12868&quot;&gt;Go doesn’t yet support specifying an environment variable for a single command&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Right now, the output is taken raw from the output of the Go compiler.  I’d like to parse the output for just the assembly code, and make it look much more like Godbolt.&lt;/p&gt;
</description>
        <pubDate>Thu, 02 Feb 2017 00:00:00 +0000</pubDate>
        <link>http://blog.pr4tt.com/2017/02/02/goasm/</link>
        <guid isPermaLink="true">http://blog.pr4tt.com/2017/02/02/goasm/</guid>
      </item>
    
      <item>
        <title>lc2.js - an LC-2 Simulator in JS</title>
        <description>&lt;p&gt;The book &lt;a href=&quot;https://www.amazon.ca/Introduction-Computing-Systems-Gates-Beyond/dp/0072376902/&quot;&gt;“Introduction to Computing Systems: from Bits &amp;amp; Gates to C &amp;amp; Beyond” by Patt &amp;amp; Patel&lt;/a&gt; introduces in some detail a computer called LC-2.  This computer never physically existed, but the publisher’s website includes &lt;a href=&quot;http://www.mhhe.com/engcs/compsci/patt/lc2unix.mhtml&quot;&gt;Windows and Unix versions of a simulator for the computer&lt;/a&gt;.  I couldn’t get the Unix version to run on my system, and I didn’t want to dual-boot just for that, so I decided to write a JavaScript simulator.  And so I built &lt;a href=&quot;http://blog.pr4tt.com/lc2.js&quot;&gt;lc2.js&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;about-the-lc-2&quot;&gt;About the LC-2&lt;/h1&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.cs.utexas.edu/users/fussell/courses/cs310h/simulator/lc2.pdf&quot;&gt;LC-2&lt;/a&gt; is a 16-bit CPU with 8 general-purpose registers (r0 to r7), 2 special purpose registers: PC, which stores the memory address of the next instruction to be loaded; and IR, which stores the most recently loaded instruction.  Additionally, the LC-2’s memory management unit (MMU) has 2 additional registers: MAR, which stores an address in memory; and MDR, which stores the data at that address in memory.  These registers are used to read and write to memory.&lt;/p&gt;

&lt;h1 id=&quot;technology&quot;&gt;Technology&lt;/h1&gt;

&lt;p&gt;The simulated MMU in lc2.js uses typed arrays of unsigned 16-bit integers to model the memory.  In order to minimize wasted memory, each page (9 bit index, 20 512 memory addresses) are only initialized when they are first read/written.  For any reasonably program, lc2.js will only initialize 3 pages of memory.  The first and last pages contain OS code, and user code exists in the page starting with address 0x3000 by convention.  This means that lc2.js normally only uses 3kb of browser memory, rather than the full 131 kb (2&lt;sup&gt;16&lt;/sup&gt; = 65536 memory locations, each of which is 2 bytes).&lt;/p&gt;

&lt;p&gt;I wrote lc2.js in a test-driven way.  I began by specifying a series of &lt;a href=&quot;http://blog.pr4tt.com/lc2.js/tests/index.html&quot;&gt;unit tests in QUnit&lt;/a&gt;, and then worked backwards from there to make the tests pass with minimal code changes.  It worked well enough, but there was at least one instance where I wrote a wrong test, and only caught it when I was trying to run a real program.&lt;/p&gt;

&lt;h1 id=&quot;project-future&quot;&gt;Project Future&lt;/h1&gt;

&lt;p&gt;The book that defines LC-2 has a gap.  In one chapter, we are using LC-2 assembly, and in the next we are using C.  I would like to use lc2.js to bridge that gap.  I think it would be interesting to build a &lt;a href=&quot;https://en.wikipedia.org/wiki/Forth_(programming_language)&quot;&gt;Forth&lt;/a&gt; on top of lc2.js, and use that to bootstrap a simple &lt;a href=&quot;https://en.wikipedia.org/wiki/Lisp_(programming_language)&quot;&gt;Lisp&lt;/a&gt; dialect.&lt;/p&gt;
</description>
        <pubDate>Mon, 23 Jan 2017 00:00:00 +0000</pubDate>
        <link>http://blog.pr4tt.com/2017/01/23/lc2.js/</link>
        <guid isPermaLink="true">http://blog.pr4tt.com/2017/01/23/lc2.js/</guid>
      </item>
    
      <item>
        <title>Virtual Memory Differences</title>
        <description>&lt;p&gt;Previously, we’ve been looking at &lt;a href=&quot;/2016/02/01/posix-memory-management/&quot;&gt;how POSIX specifies memory management&lt;/a&gt;, &lt;a href=&quot;/2016/02/07/radixVM/&quot;&gt;an academic design for virtual memory&lt;/a&gt; and BSD virtual memory in particular:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/2016/02/02/BSD-virtual-memory/&quot;&gt;BSD Virtual Memory&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2016/02/23/OpenBSD-Virtual-Memory/&quot;&gt;OpenBSD Virtual Memory&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, let’s look at the differences between the virtual memory systems of NetBSD, OpenBSD, Linux, and OpenIndiana.&lt;/p&gt;

&lt;h1 id=&quot;history&quot;&gt;History&lt;/h1&gt;

&lt;p&gt;First, let’s give just a tiny summary of where each of these OSes come from.  We covered the history of BSD in the article on &lt;a href=&quot;/2016/02/02/BSD-virtual-memory/&quot;&gt;BSD Virtual Memory&lt;/a&gt;, so I’ll skip those.  If we go back to &lt;a href=&quot;https://en.wikipedia.org/wiki/History_of_Unix&quot;&gt;the Wiki entry on the History of Unix&lt;/a&gt;, we can see that SunOS derived originally from BSD 3.0 to 4.1, then evolved alongside BSD until about the same time as BSD4.4.  At which point, Sun built a new OS called Solaris based on Unix System V.  Finally, OpenSolaris split from Solaris 10.  From &lt;a href=&quot;https://en.wikipedia.org/wiki/OpenIndiana&quot;&gt;the Wiki entry on OpenIndiana&lt;/a&gt;, it seems to have come into existence when Sun was being acquired by Oracle.&lt;/p&gt;

&lt;p&gt;As for Linux, the kernel was created in 1991 during the period immediately before 386BSD was first released.  At this time, people were becoming aware that the 386 was powerful enough to support some flavor of Unix, but nothing had yet been written.  It dovetailed perfectly with the GNU effort begun in 1983 to make a wholly free flavor of Unix.&lt;/p&gt;

&lt;h1 id=&quot;differences&quot;&gt;Differences&lt;/h1&gt;

&lt;p&gt;With the history out of the way, let’s get into the differences.  They are the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How the kernel deals with being out of memory&lt;/li&gt;
  &lt;li&gt;Copy-on-write mechanisms&lt;/li&gt;
  &lt;li&gt;How the kernel accesses user memory&lt;/li&gt;
  &lt;li&gt;Dead queue (OpenBSD versus NetBSD)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;how-the-kernel-deals-with-being-out-of-memory&quot;&gt;How the kernel deals with being out of memory&lt;/h2&gt;

&lt;p&gt;When OpenBSD’s kernel runs out of memory, it simply panics.  I think the same is true of OpenIndiana.&lt;/p&gt;

&lt;p&gt;Linux infamously has an Out-Of-Memory (OOM) killer.  This is a heuristic that runs when the kernel runs out of memory, and decides on a process to kill in order to free up memory.&lt;/p&gt;

&lt;h2 id=&quot;copy-on-write-mechanisms&quot;&gt;Copy-on-write mechanisms&lt;/h2&gt;

&lt;p&gt;In UVM, copy-on-write simply creates a read-only reference to a backing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_object&lt;/code&gt;.  When written to, UVM creates an anonymous map, and copies the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_object&lt;/code&gt;’s data into the anonymous map.  (See page 51 of &lt;a href=&quot;http://chuck.cranor.org/p/diss.pdf&quot;&gt;Cranor’s dissertation&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;This simplifies the original VM system, which used chains of copy/shadow objects which could get arbitrarily long.&lt;/p&gt;

&lt;h2 id=&quot;how-the-kernel-accesses-user-memory&quot;&gt;How the kernel accesses user memory&lt;/h2&gt;

&lt;p&gt;On Linux, the kernel maps all of physical memory into the kernel’s address space.  This makes it possible to copy data from a user process into the kernel’s memory without the overhead of first mapping the process’ physical memory into the kernel’s address space.  There’s &lt;a href=&quot;http://www.ibm.com/developerworks/library/l-kernel-memory-access/&quot;&gt;a great article by IBM on how this works in linux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To figure out how this works on NetBSD, I found &lt;a href=&quot;http://www.onlamp.com/pub/a/onlamp/2001/06/21/linux_bsd.html?page=3&quot;&gt;an interesting article on linux compatibility on NetBSD&lt;/a&gt;, which led me to the code for &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html&quot;&gt;the POSIX &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; system call&lt;/a&gt; in &lt;a href=&quot;http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/kern/sys_generic.c?rev=1.130&amp;amp;content-type=text/x-cvsweb-markup&amp;amp;only_with_tag=MAIN&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/kern/sys_generic.c&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * Read system call.
 */&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* ARGSUSED */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;sys_read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lwp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys_read_args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;register_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;retval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* {
		syscallarg(int)		fd;
		syscallarg(void *)	buf;
		syscallarg(size_t)	nbyte;
	} */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;file_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCARG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd_getfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EBADF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_flag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FREAD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;fd_putfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EBADF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* dofileread() will unuse the descriptor for us */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dofileread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCARG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCARG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbyte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
	    &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FOF_UPDATE_OFFSET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;retval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So that just calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dofileread()&lt;/code&gt; in the same file (&lt;a href=&quot;http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/kern/sys_generic.c?rev=1.130&amp;amp;content-type=text/x-cvsweb-markup&amp;amp;only_with_tag=MAIN&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/kern/sys_generic.c&lt;/code&gt;&lt;/a&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;dofileread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbyte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;off_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;register_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;retval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iovec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aiov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uio&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cnt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;lwp_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curlwp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;aiov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iov_base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;aiov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iov_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbyte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uio_iov&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aiov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uio_iovcnt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uio_resid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbyte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uio_rw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UIO_READ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uio_vmspace&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l_proc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_vmspace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * Reads return ssize_t because -1 is returned on error.  Therefore
	 * we must restrict the length to SSIZE_MAX to avoid garbage return
	 * values.
	 */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uio_resid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SSIZE_MAX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EINVAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;cnt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uio_resid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_ops&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fo_read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f_cred&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uio_resid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cnt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERESTART&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
		    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EINTR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EWOULDBLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;cnt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;auio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uio_resid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;ktrgenio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UIO_READ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cnt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;retval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cnt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;nl&quot;&gt;out:&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;fd_putfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Actually, I think that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SCARGS()&lt;/code&gt; macro uses something like linux’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copy_from_user()&lt;/code&gt; function, whose equivalent is &lt;a href=&quot;http://netbsd.gw.com/cgi-bin/man-cgi?copyin+9+NetBSD-current&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copyin()&lt;/code&gt; in NetBSD&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.usenix.org/legacy/event/usenix2000/freenix/full_papers/silvers/silvers_html/&quot;&gt;Chuck Silvers’ UBC paper&lt;/a&gt; states the intention to implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copyin()&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copyout()&lt;/code&gt; using UVM page loans, but this doesn’t seem to be implemented.&lt;/p&gt;

&lt;p&gt;It turns out, the implementation for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copyin()&lt;/code&gt; is hardware-dependent since it is related to how pmap actually stores the memory.  The x86-64 implementation is in &lt;a href=&quot;http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/arch/amd64/amd64/copy.S?rev=1.20&amp;amp;content-type=text/x-cvsweb-markup&amp;amp;only_with_tag=MAIN&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/arch/amd64/amd64/copy.S&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-asm&quot; data-lang=&quot;asm&quot;&gt;ENTRY(copyin)
	DEFERRED_SWITCH_CHECK

	xchgq	%rdi,%rsi
	movq	%rdx,%rax

	addq	%rsi,%rdx		/* check source address not wrapped */
	jc	_C_LABEL(copy_efault)
	movq	$VM_MAXUSER_ADDRESS,%r8
	cmpq	%r8,%rdx
	ja	_C_LABEL(copy_efault)	/* j if end in kernel space */

.Lcopyin_start:
3:	/* bcopy(%rsi, %rdi, %rax); */
	movq	%rax,%rcx
	shrq	$3,%rcx
	rep
	movsq
	movb	%al,%cl
	andb	$7,%cl
	rep
	movsb
.Lcopyin_end:
	xorl	%eax,%eax
	ret
	DEFERRED_SWITCH_CALL&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As unsatisfying as it is, I’m not really sure what this does.  It seems to copy byte-by-byte from user space to kernel space.  Does this mean that all of physical memory exists in the kernel’s virtual address space, since assembly instructions act on virtual addresses?&lt;/p&gt;

&lt;p&gt;I’ll go through line by line and add comments where necessary to try and explain what the assembly does.  The most helpful documentation I could find for gas or AT&amp;amp;T syntax x86-64 code was &lt;a href=&quot;http://docs.oracle.com/cd/E26502_01/html/E28388/ennby.html#scrolltoc&quot;&gt;Oracle’s x86 assembly language reference manual&lt;/a&gt;, which documents the solaris assembler, which is very similar to gas.  Another useful resource was &lt;a href=&quot;https://en.wikibooks.org/wiki/X86_Assembly/Shift_and_Rotate&quot;&gt;the x86 assembly wikibook on shift and rotate&lt;/a&gt; and &lt;a href=&quot;http://x86.renejeschke.de/html/file_module_x86_id_203.html&quot;&gt;the x86 instruction set reference on MOVS&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-asm&quot; data-lang=&quot;asm&quot;&gt;ENTRY(copyin)
	DEFERRED_SWITCH_CHECK

	/* the 'q' suffix after an instruction indicates that the instruction
	 * works on a &quot;quadword&quot; or 64- bits
	 */

	xchgq	%rdi,%rsi		/* Exchange rdi, rsi */
	movq	%rdx,%rax		/* Move rdx into rax */

	addq	%rsi,%rdx		/* add rsi to rdx */
	jc	_C_LABEL(copy_efault)	/* jump if carry bit set after prev. */
					/* instruction */
	movq	$VM_MAXUSER_ADDRESS,%r8	/* move the max user address into r8 */
	cmpq	%r8,%rdx			/* compare r8 and rdx */
	ja	_C_LABEL(copy_efault)	/* jump if r8 is above rdx */

.Lcopyin_start:
3:	/* bcopy(%rsi, %rdi, %rax); */
	movq	%rax,%rcx	/* move rax to rcx */
	shrq	$3,%rcx		/* shift rcx right by 3 bits */
	rep			/* repeat the following until rcx is 0 ... */
	movsq			/* move quadword from rsi to rdi */
	movb	%al,%cl		/* move byte from al to cl */
	andb	$7,%cl		/* logical AND bytes 7 and cl */
	rep			/* repeat the following until rcx is 0 ... */
	movsb			/* move byte from rsi to rdi */
.Lcopyin_end:
	xorl	%eax,%eax	/* logical XOR long (32 bit) eax with itself */
				/* effectively, zero out eax */
	ret
	DEFERRED_SWITCH_CALL&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It certainly copies bytes around, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rep movsq&lt;/code&gt;, but it’s still not clear how the kernel indexes into user space without mapping all of physical memory into its address space.&lt;/p&gt;

&lt;h2 id=&quot;dead-queue-openbsd-versus-netbsd&quot;&gt;Dead queue (OpenBSD versus NetBSD)&lt;/h2&gt;

&lt;p&gt;I’ve mostly been studying UVM since I began to study virtual memory.  When I began, I assumed that OpenBSD was mostly still running a VM system that was based on Cranor’s UVM.  However, it seems that OpenBSD’s VM system was substantially rewritten in 2011 by Ariane van der Steldt.&lt;/p&gt;

&lt;p&gt;Ariane posted &lt;a href=&quot;http://openbsd-archive.7691.n7.nabble.com/vmmap-replacement-please-test-td169729.html&quot;&gt;a diff in OpenBSD’s tech mailing list&lt;/a&gt; detailing a vmmap rewrite, and also made &lt;a href=&quot;http://www.openbsd.org/papers/tdose_memalloc/presentation.html&quot;&gt;a presentation about it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the changes Ariane made was to add a “dead entry queue,” and as far as I can tell there is no official documentation about what a dead entry is.  We can see that &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_map.h.diff?r1=text&amp;amp;tr1=1.44&amp;amp;r2=text&amp;amp;tr2=1.45&quot;&gt;the dead entry queue was added in revision 1.45&lt;/a&gt; in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_map.h?rev=1.45&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;2011 by ariane&lt;/a&gt;.  This was part of Ariane’s VM rewrite, so it isn’t clear what the dead entry queue in particular was meant to do.&lt;/p&gt;

&lt;p&gt;Since OpenBSD seems to differ significantly from Cranor’s design, I’m going to switch to studying NetBSD instead.&lt;/p&gt;
</description>
        <pubDate>Wed, 24 Feb 2016 00:00:00 +0000</pubDate>
        <link>http://blog.pr4tt.com/2016/02/24/VM-Differences/</link>
        <guid isPermaLink="true">http://blog.pr4tt.com/2016/02/24/VM-Differences/</guid>
      </item>
    
      <item>
        <title>OpenBSD Virtual Memory</title>
        <description>&lt;p&gt;Today, we answer the following questions about OpenBSD’s virtual memory system:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How are contiguous regions of memory managed?&lt;/li&gt;
  &lt;li&gt;How is memory freed?
    &lt;ul&gt;
      &lt;li&gt;What happens when the kernel runs out of memory?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Is there any special code for Non-Uniform Memory Access (NUMA) architectures?&lt;/li&gt;
  &lt;li&gt;How is physical memory managed?
    &lt;ul&gt;
      &lt;li&gt;Does it assume more virtual than physical memory?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;What are its data structures which store information about memory?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Along the way, I’ll show the relevant parts of the OpenBSD source and link to their location in their web CVS, which should serve both as a map and let anyone interested easily find out more.  But first, we’ll look at UVM’s design at a high-level.&lt;/p&gt;

&lt;h1 id=&quot;uvm-design-overview&quot;&gt;UVM Design Overview&lt;/h1&gt;

&lt;p&gt;As we learned in &lt;a href=&quot;/2016/02/02/BSD-virtual-memory/&quot;&gt;the article on BSD’s virtual memory system&lt;/a&gt;, Charles Cranor wrote &lt;a href=&quot;http://chuck.cranor.org/p/diss.pdf&quot;&gt;his PhD dissertation&lt;/a&gt; on his massive rewrite of NetBSD’s VM system, which he called UVM.  This rewrite was meant to address the following issues in 4.4BSD’s VM, which was based on Mach’s VM:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;shadow/copy object chaining&lt;/li&gt;
  &lt;li&gt;one page at a time I/O operations&lt;/li&gt;
  &lt;li&gt;poor integration with the kernel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a process is &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork&lt;/code&gt;&lt;/a&gt;ed, its existing address space is copied to the new process.  Since actually copying the entire address space would be a tremendous overhead on every call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork&lt;/code&gt;, and since a common pattern in unix is to immediately fork and kill the original process to start a process in the background, POSIX systems typically don’t actually copy the address space.  In 4.4BSD, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork&lt;/code&gt; creates a “copy” object between the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_entry&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vnode&lt;/code&gt;.  This allows the kernel to fault on any writes to this memory, and only then copy the data to the writing process’ address space.  This mechanism is called copy-on-write.   (See section 5.5, page 146 of The Design and Implementation of the 4.4BSD Operating System.)&lt;/p&gt;

&lt;p&gt;Similarly, when a process has a private mapping from memory to a file, this means that changes made by that process are not reflected in the file but are visible to that process.  To support this, 4.4BSD creates a “shadow” object between the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_entry&lt;/code&gt; and the file object, which stores the private changes made by the process to the file.  (See section 5.5, page 142 of The Design and Implementation of the 4.4BSD Operating System.)&lt;/p&gt;

&lt;p&gt;These shadow/copy object chains can get quite long, which slows memory search times and can contain inaccessible redundant copies of the same page of data.  If left unchecked, this can fill swap space with redundant data and cause the system to deadlock, these are called swap memory leak deadlocks.  4.4BSD addresses this problem with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;collapse&lt;/code&gt; operation which can bypass or discards any redundant pages that are still accessible, but this process can’t do anything to redundant pages that have become inaccessible.&lt;/p&gt;

&lt;p&gt;UVM simplifies the copy-on-write mechanisms by replacing shadow/copy objects with a 2-level scheme based on page reference counters.  UVM also uses these reference counters to eliminate swap memory leaks.&lt;/p&gt;

&lt;p&gt;Second on the list of issues meant to be addressed by UVM is the fact that I/O operations in the BSD VM are performed one page at a time, which slows paging response time.  UVM addresses this by allowing such operations on multi-page clusters.&lt;/p&gt;

&lt;p&gt;Finally, Cranor claims that BSD’s VM is poorly integrated with the kernel, and gives the example that unreferenced memory-mapped file objects are cached both at the I/O system (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vnode&lt;/code&gt;) layer, and redundantly at the VM layer as well.&lt;/p&gt;

&lt;h2 id=&quot;locking&quot;&gt;Locking&lt;/h2&gt;

&lt;p&gt;Section 3.3.2 of &lt;a href=&quot;http://chuck.cranor.org/p/diss.pdf&quot;&gt;Cranor’s dissertation&lt;/a&gt; describes data structure locking, noting that OS data structures can be protected either by one big lock or by many small “fine-grained” locks.  It goes on to say that when Mach’s VM system was ported to BSD, they ignored its fine-grained locking support.  One of UVM’s goals is to restore this fine-grained locking support.&lt;/p&gt;

&lt;h1 id=&quot;contiguous-memory-management&quot;&gt;Contiguous Memory Management&lt;/h1&gt;

&lt;p&gt;What data structure is used to represent a contiguous region of memory?  Well, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_object&lt;/code&gt; struct is used to provide a reference to a backing store (such as physical memory), and can hold references to a contiguous sequence of pages.  But there’s no mechanism to allocate contiguous regions of physical memory aside from the direct-memory-access (DMA) interface meant for driver developers.&lt;/p&gt;

&lt;h1 id=&quot;freeing-memory&quot;&gt;Freeing Memory&lt;/h1&gt;

&lt;p&gt;What actually happens when we call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;munmap()&lt;/code&gt;?  Well, rather than go through &lt;em&gt;yet another&lt;/em&gt; trail of indirection citing the code at every step, I’ll simply look through the code and enumerate the calls here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sys_munmap()&lt;/code&gt; system call in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_mmap.c?rev=1.122&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_mmap.c&lt;/code&gt;&lt;/a&gt; calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_unmap_remove(map, addr, addr + size, &amp;amp;dead_entries, FALSE, TRUE)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_unmap_remove(struct vm_map *map, vaddr_t start, vaddr_t end,
 struct uvm_map_deadq *dead, boolean_t remove_holes,
 boolean_t markfree)&lt;/code&gt; in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_map.c?rev=1.205&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_map.c&lt;/code&gt;&lt;/a&gt; calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_mapent_mkfree(map, entry, &amp;amp;prev_hint, dead, markfree)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_mapent_mkfree(struct vm_map *map, struct vm_map_entry *entry,
 struct vm_map_entry **prev_ptr, struct uvm_map_deadq *dead,
 boolean_t markfree)&lt;/code&gt; in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_map.c?rev=1.205&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;the same file&lt;/a&gt;, which mostly just seems to put the entry into a queue of dead entries.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;what-happens-when-the-kernel-runs-out-of-memory&quot;&gt;What happens when the kernel runs out of memory?&lt;/h2&gt;

&lt;p&gt;When a user process runs out of memory, a call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt; simply returns the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENOMEM&lt;/code&gt; error, as we can see in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_mmap.c?rev=1.122&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_mmap.c&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * sys_mmap: mmap system call.
 *
 * =&amp;gt; file offset and address may not be page aligned
 *    - if MAP_FIXED, offset and address must have remainder mod PAGE_SIZE
 *    - if address isn't page aligned the mapping starts at trunc_page(addr)
 *      and the return value is adjusted up by the page offset.
 */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;sys_mmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;register_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;retval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* check for file mappings (i.e. not anonymous) and verify file. */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_ANON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* MAP_ANON case */&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_ANON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
		    &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_PRIVATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROT_WRITE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
			    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_rlimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RLIMIT_DATA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rlim_cur&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptoa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_vmspace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_dused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENOMEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;But when the kernel runs out of memory, we see a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;panic&lt;/code&gt; as in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_map.c?rev=1.205&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_map.c&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * uvm_mapent_alloc: allocate a map entry
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;uvm_mapent_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;pool_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PR_WAITOK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_TRYLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;pool_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PR_NOWAIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VM_MAP_INTRSAFE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;mtx_enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_kmapent_mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kentry_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;km_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_dirty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			    &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd_nowait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;uvm_mapent_alloc: cannot allocate map &quot;&lt;/span&gt;
				    &lt;span class=&quot;s&quot;&gt;&quot;entry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;numa&quot;&gt;NUMA&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Non-uniform_memory_access&quot;&gt;Non-Uniform Memory Access (NUMA)&lt;/a&gt; is when each processor has some section of fast memory which is considered “local,” and the rest is much slower and considered “remote.”  Section 5.2.16 of &lt;a href=&quot;http://www.acpi.info/spec.htm&quot;&gt;the ACPI specification&lt;/a&gt; defines the System Resource Affinity Table (SRAT) which associates processors and memory to proximity domains, essentially what memory is local to which processor.  Section 5.2.17 of the same spec defines the System Locality Distance Information Table (SLIT) which provides information about the memory latency for each proximity domain.&lt;/p&gt;

&lt;p&gt;I learned on &lt;a href=&quot;http://www.feyrer.de/NetBSD/bx/blosxom.cgi/index.front?-tags=numa&quot;&gt;hubertf’s blog&lt;/a&gt; that Christoph Egger wrote &lt;a href=&quot;http://mail-index.netbsd.org/tech-kern/2009/11/23/msg006518.html&quot;&gt;an ACPI SLIT parser&lt;/a&gt; and &lt;a href=&quot;http://mail-index.netbsd.org/tech-kern/2009/11/23/msg006517.html&quot;&gt;an ACPI SRAT parser&lt;/a&gt; for NetBSD.  Indeed, &lt;a href=&quot;http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/acpi/?only_with_tag=MAIN&quot;&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/dev/acpi&lt;/code&gt; directory in NetBSD’s CVS&lt;/a&gt; contains &lt;a href=&quot;http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/acpi/acpi_slit.h?rev=1.3&amp;amp;content-type=text/x-cvsweb-markup&amp;amp;only_with_tag=MAIN&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acpi_slit.h&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/acpi/acpi_slit.c?rev=1.3&amp;amp;content-type=text/x-cvsweb-markup&amp;amp;only_with_tag=MAIN&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acpi_slit.c&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/acpi/acpi_srat.h?rev=1.3&amp;amp;content-type=text/x-cvsweb-markup&amp;amp;only_with_tag=MAIN&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acpi_srat.h&lt;/code&gt;&lt;/a&gt;, and &lt;a href=&quot;http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/acpi/acpi_srat.c?rev=1.3&amp;amp;content-type=text/x-cvsweb-markup&amp;amp;only_with_tag=MAIN&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acpi_srat.c&lt;/code&gt;&lt;/a&gt;.  No similar files exist in OpenBSD, which suggests that they haven’t been ported.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://openbsd-archive.7691.n7.nabble.com/numa-implementation-td165563.html&quot;&gt;There seems to have been some work done on adding NUMA support as well as the concept of memory and CPU affinity to OpenBSD&lt;/a&gt;, but nothing since 2009.  &lt;a href=&quot;http://www.google.com/#q=numa%20site:http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/&quot;&gt;A search within OpenBSD’s web CVS reveals no mention of numa&lt;/a&gt;, which suggests that Ariane’s patch was never accepted.&lt;/p&gt;

&lt;h2 id=&quot;what-about-other-bsds&quot;&gt;What about other BSDs?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.dragonflybsd.org/presentations/dragonflybsd.asiabsdcon04.pdf&quot;&gt;The paper describing DragonFly BSD’s design goals as a fork of FreeBSD states that it is designed with a NUMA-centric view&lt;/a&gt;, by explicitly partitioning the workload among multiple processors.  &lt;a href=&quot;https://www.dragonflybsd.org/mailarchive/kernel/2010-03/msg00119.html&quot;&gt;There was also a Google Summer of Code project in 2010 to make DragonFly BSD NUMA-aware&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;physical-memory-management&quot;&gt;Physical Memory Management&lt;/h1&gt;

&lt;p&gt;The BSD VM system is split into two layers: machine dependent and independent.  UVM’s machine-dependent layer is essentially the same as BSD’s, which is called the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pmap&lt;/code&gt; layer.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pmap&lt;/code&gt; handles adding to, removing from, or querying for virtual or physical mappings within the processor’s memory management unit (MMU).&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pmap&lt;/code&gt; layer is a deliberately thin abstraction over the MMU, in order that the VM code built on top can reuse as much code as possible across every supported platform.  This also lets us hide shortcomings of the MMU, such as painfully small page sizes on the VAX, by dealing with such things at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pmap&lt;/code&gt; layer.  Unfortunately, it has a symmetric shortcoming of its own, in that it abstracts away the nicer features of any MMU in order to provide a simple interface supported by all architectures.  Also, this means that memory information is stored both in the page tables manipulated by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pmap&lt;/code&gt; layer, and in the higher-level UVM structures.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pmap&lt;/code&gt; structure is in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/arch/i386/include/pmap.h?rev=1.79&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/arch/i386/include/pmap.h&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * The pmap structure
 *
 * Note that the pm_obj contains the reference count,
 * page list, and number of PTPs within the pmap.
 */&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pmap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_pdidx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* PDIEs for PAE mode */&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_apte_mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;paddr_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_pdirpa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* PA of PD (read-only after create) */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_pdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* VA of PD (lck by object lock) */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;pm_pdirsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* PD size (4k vs 16k on PAE) */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* object (lck by object lock) */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;LIST_ENTRY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* list (lck by pm_list lock) */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pm_ptphint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* pointer to a PTP in our pmap */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pmap_statistics&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_stats&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/* pmap stats (lck by object lock) */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_hiexec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* highest executable mapping */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;			&lt;span class=&quot;cm&quot;&gt;/* see below */&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;segment_descriptor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_codeseg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* cs descriptor for process */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;descriptor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pm_ldt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* user-set LDT */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_ldt_len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;			&lt;span class=&quot;cm&quot;&gt;/* number of LDT entries */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pm_ldt_sel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;			&lt;span class=&quot;cm&quot;&gt;/* LDT selector */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;do-they-assume-more-virtual-than-physical-addresses&quot;&gt;Do they assume more virtual than physical addresses?&lt;/h2&gt;

&lt;p&gt;Although this used to be a reasonable assumption on x86, the x86-64 specification has a bigger physical address space (52 bits) than virtual address space (48 bits).&lt;/p&gt;

&lt;p&gt;On Linux, the kernel allocates every page of physical memory into the kernel’s virtual address space.  This makes the fundamental assumption that there will always be more virtual than physical memory.&lt;/p&gt;

&lt;p&gt;I can’t find any definitive proof, but I will show how UVM initializes memory.  First, let’s see how the kernel is initialized in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/kern/init_main.c?rev=1.248&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/kern/init_main.c&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * System startup; initialize the world, create process 0, mount root
 * filesystem, and fork to create init and pagedaemon.  Most of the
 * hard work is done in the lower-level initialization routines including
 * startup(), which does memory initialization and autoconfiguration.
 */&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* XXX return int, so gcc -Werror won't complain */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;framep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;process&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdevinit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pdev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;quad_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdevinit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pdevinit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;disk_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * Initialize the current process pointer (curproc) before
	 * any possible traps/probes to simplify trap processing.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;curproc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proc0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_cpu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;curcpu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * Initialize timeouts.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;timeout_startup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * Attempt to find console and initialize
	 * in case of early panic or other messages.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;config_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* init autoconfiguration data structures */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;consinit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copyright&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;KERNEL_LOCK_INIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;SCHED_LOCK_INIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;uvm_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And we can find the code for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_init&lt;/code&gt; in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_init.c?rev=1.39&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_init.c&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * uvm_init: init the VM system.   called from kern/init_main.c.
 */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;uvm_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kvm_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kvm_end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* step 0: ensure that the hardware set the page size */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvmexp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pagesize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;uvm_init: page size not set&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* step 1: set up stats. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;averunnable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fscale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FSCALE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 2: init the page sub-system.  this includes allocating the
	 * vm_page structures, and setting up all the page queues (and
	 * locks).  available memory will be put in the &quot;free&quot; queue.
	 * kvm_start and kvm_end will be set to the area of kernel virtual
	 * memory which is available for general use.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvm_page_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvm_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvm_end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 3: init the map sub-system.  allocates the static pool of
	 * vm_map_entry structures that are used for &quot;special&quot; kernel maps
	 * (e.g. kernel_map, kmem_map, etc...).
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvm_map_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 4: setup the kernel's virtual memory data structures.  this
	 * includes setting up the kernel_map/kernel_object and the kmem_map/
	 * kmem_object.
	 */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;uvm_km_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_min_kernel_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kvm_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kvm_end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 4.5: init (tune) the fault recovery code.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvmfault_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 5: init the pmap module.   the pmap module is free to allocate
	 * memory for its private use (e.g. pvlists).
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pmap_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 6: init the kernel memory allocator.   after this call the
	 * kernel memory allocator (malloc) can be used.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;kmeminit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 6.5: init the dma allocator, which is backed by pools.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;dma_alloc_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 7: init all pagers and the pager_map.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvm_pager_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 8: init anonymous memory system
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;amap_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * step 9: init uvm_km_page allocator memory.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvm_km_page_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * the VM system is now up!  now that malloc is up we can
	 * enable paging of kernel objects.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uao_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VM_KERNEL_SPACE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UAO_FLAG_KERNSWAP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * reserve some unmapped space for malloc/pool use after free usage
	 */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef DEADBEEF0
&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;kvm_start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trunc_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DEADBEEF0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kernel_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvm_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_UNKNOWN_OFFSET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_MAPFLAG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROT_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;n&quot;&gt;PROT_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_INHERIT_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MADV_RANDOM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_FIXED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;uvm_init: cannot reserve dead beef @0x%x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DEADBEEF0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
#ifdef DEADBEEF1
&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;kvm_start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trunc_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DEADBEEF1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kernel_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kvm_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_UNKNOWN_OFFSET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_MAPFLAG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROT_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;n&quot;&gt;PROT_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_INHERIT_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MADV_RANDOM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_FIXED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;uvm_init: cannot reserve dead beef @0x%x&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DEADBEEF1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/*
	 * init anonymous memory systems
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvm_anon_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#ifndef SMALL_KERNEL
&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/*
	 * Switch kernel and kmem_map over to a best-fit allocator,
	 * instead of walking the tree.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvm_map_set_uaddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kernel_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kernel_map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uaddr_any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
	    &lt;span class=&quot;n&quot;&gt;uaddr_bestfit_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_map_min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kernel_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
	    &lt;span class=&quot;n&quot;&gt;vm_map_max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kernel_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvm_map_set_uaddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kmem_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kmem_map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uaddr_any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
	    &lt;span class=&quot;n&quot;&gt;uaddr_bestfit_create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_map_min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kmem_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
	    &lt;span class=&quot;n&quot;&gt;vm_map_max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kmem_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif &lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* !SMALL_KERNEL */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As far as I can tell, none of these &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_init()&lt;/code&gt; functions does anything like map all of physical memory into the kernel’s virtual address space.&lt;/p&gt;

&lt;h1 id=&quot;data-structures&quot;&gt;Data Structures&lt;/h1&gt;

&lt;p&gt;For the upper level, we have the following from Cranor’s Usenix paper about UVM:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.pr4tt.com/wiki/lib/exe/fetch.php?media=uvm.gif&quot; style=&quot;width:100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We’ll just go through and look at each of the struct definitions for now.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmspace&lt;/code&gt; struct is defined in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_extern.h?rev=1.137&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_extern.h&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * Shareable process virtual address space.
 * May eventually be merged with vm_map.
 * Several fields are temporary (text, data stuff).
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmspace&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* VM address map */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;vm_refcnt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* number of references */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;caddr_t&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;vm_shm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* SYS5 shared memory private data XXX */&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* we copy from vm_startcopy to the end of the structure on fork */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define vm_startcopy vm_rssize
&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;segsz_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_rssize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 	&lt;span class=&quot;cm&quot;&gt;/* current resident set size in pages */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;segsz_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_swrss&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* resident set size before last swap */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;segsz_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_tsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* text size (pages) XXX */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;segsz_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_dsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* data size (pages) XXX */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;segsz_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_dused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* data segment length (pages) XXX */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;segsz_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_ssize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* stack size (pages) */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;caddr_t&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;vm_taddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* user virtual address of text XXX */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;caddr_t&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;vm_daddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* user virtual address of data XXX */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;caddr_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_maxsaddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* user VA at max stack growth */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;caddr_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_minsaddr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* user VA at top of stack */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map&lt;/code&gt; struct is defined in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_map.h?rev=1.55&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_map.h&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 *	A Map is a rbtree of map entries, kept sorted by address.
 *	In addition, free space entries are also kept in a rbtree,
 *	indexed by free size.
 *
 *
 *
 *	LOCKING PROTOCOL NOTES:
 *	-----------------------
 *
 *	VM map locking is a little complicated.  There are both shared
 *	and exclusive locks on maps.  However, it is sometimes required
 *	to downgrade an exclusive lock to a shared lock, and upgrade to
 *	an exclusive lock again (to perform error recovery).  However,
 *	another thread *must not* queue itself to receive an exclusive
 *	lock while before we upgrade back to exclusive, otherwise the
 *	error recovery becomes extremely difficult, if not impossible.
 *
 *	In order to prevent this scenario, we introduce the notion of
 *	a `busy' map.  A `busy' map is read-locked, but other threads
 *	attempting to write-lock wait for this flag to clear before
 *	entering the lock manager.  A map may only be marked busy
 *	when the map is write-locked (and then the map must be downgraded
 *	to read-locked), and may only be marked unbusy by the thread
 *	which marked it busy (holding *either* a read-lock or a
 *	write-lock, the latter being gained by an upgrade).
 *
 *	Access to the map `flags' member is controlled by the `flags_lock'
 *	simple lock.  Note that some flags are static (set once at map
 *	creation time, and never changed), and thus require no locking
 *	to check those flags.  All flags which are r/w must be set or
 *	cleared while the `flags_lock' is asserted.  Additional locking
 *	requirements are:
 *
 *		VM_MAP_PAGEABLE		r/o static flag; no locking required
 *
 *		VM_MAP_INTRSAFE		r/o static flag; no locking required
 *
 *		VM_MAP_WIREFUTURE	r/w; may only be set or cleared when
 *					map is write-locked.  may be tested
 *					without asserting `flags_lock'.
 *
 *		VM_MAP_BUSY		r/w; may only be set when map is
 *					write-locked, may only be cleared by
 *					thread which set it, map read-locked
 *					or write-locked.  must be tested
 *					while `flags_lock' is asserted.
 *
 *		VM_MAP_WANTLOCK		r/w; may only be set when the map
 *					is busy, and thread is attempting
 *					to write-lock.  must be tested
 *					while `flags_lock' is asserted.
 *
 *		VM_MAP_GUARDPAGES	r/o; must be specified at map
 *					initialization time.
 *					If set, guards will appear between
 *					automatic allocations.
 *					No locking required.
 *
 *		VM_MAP_ISVMSPACE	r/o; set by uvmspace_alloc.
 *					Signifies that this map is a vmspace.
 *					(The implementation treats all maps
 *					without this bit as kernel maps.)
 *					No locking required.
 *
 *
 * All automatic allocations (uvm_map without MAP_FIXED) will allocate
 * from vm_map.free.
 * If that allocation fails:
 * - vmspace maps will spill over into vm_map.bfree,
 * - all other maps will call uvm_map_kmem_grow() to increase the arena.
 * 
 * vmspace maps have their data, brk() and stack arenas automatically
 * updated when uvm_map() is invoked without MAP_FIXED.
 * The spill over arena (vm_map.bfree) will contain the space in the brk()
 * and stack ranges.
 * Kernel maps never have a bfree arena and this tree will always be empty.
 *
 *
 * read_locks and write_locks are used in lock debugging code.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pmap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;pmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* Physical map */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rwlock&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* Lock for map data */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_map_addr&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* Entry tree, by addr */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* virtual size */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;ref_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Reference count */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* flags */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;flags_lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* flags lock */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Version number */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;min_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* First address in map. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;max_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Last address in map. */&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * Allocation overflow regions.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;b_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Start for brk() alloc. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;b_end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* End for brk() alloc. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;s_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Start for stack alloc. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;s_end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* End for stack alloc. */&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * Special address selectors.
	 *
	 * The uaddr_exe mapping is used if:
	 * - protX is selected
	 * - the pointer is not NULL
	 *
	 * If uaddr_exe is not used, the other mappings are checked in
	 * order of appearance.
	 * If a hint is given, the selection will only be used if the hint
	 * falls in the range described by the mapping.
	 *
	 * The states are pointers because:
	 * - they may not all be in use
	 * - the struct size for different schemes is variable
	 *
	 * The uaddr_brk_stack selector will select addresses that are in
	 * the brk/stack area of the map.
	 */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_addr_state&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uaddr_exe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Executable selector. */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_addr_state&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uaddr_any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* More selectors. */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_addr_state&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uaddr_brk_stack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Brk/stack selector. */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The reference to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_map_addr&lt;/code&gt; is actually a reference to a red-black tree defined earlier:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;n&quot;&gt;RB_HEAD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_map_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RB_HEAD&lt;/code&gt; call is a standard part of NetBSD/OpenBSD, and we can look at &lt;a href=&quot;http://netbsd.gw.com/cgi-bin/man-cgi?RB_HEAD+3+NetBSD-6.0&quot;&gt;the relevant man page&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;RED-BLACK TREES
     A red-black tree is a binary search tree with the node color as an extra
     attribute.  It fulfills a set of conditions:
           1.   every search path from the root to a leaf consists of the same
                number of black nodes,
           2.   each red node (except for the root) has a black parent,
           3.   each leaf node is black.

     Every operation on a red-black tree is bounded as O(lg n).  The maximum
     height of a red-black tree is 2lg (n+1).

     A red-black tree is headed by a structure defined by the RB_HEAD() macro.
     A RB_HEAD structure is declared as follows:

           RB_HEAD(HEADNAME, TYPE) head;

     where HEADNAME is the name of the structure to be defined, and struct
     TYPE is the type of the elements to be inserted into the tree.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So the type of elements stored in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_map_addr&lt;/code&gt; red-black tree is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_entry&lt;/code&gt; which is defined earlier in the same file as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * Address map entries consist of start and end addresses,
 * a VM object (or sharing map) and offset into that object,
 * and user-exported inheritance and protection information.
 * Also included is control information for virtual copy operations.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;RB_ENTRY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;addr_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* address tree */&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daddrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;RB_ENTRY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;rbtree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* Link freespace tree. */&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;TAILQ_ENTRY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tailq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* Link freespace queue. */&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;TAILQ_ENTRY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deadq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* dead entry queue */&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dfree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#define uvm_map_entry_start_copy start
&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* start address */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* end address */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* bytes in guard */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;fspace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* free space */&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_object&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* object I point to */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* offset into object */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_aref&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;aref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* anonymous overlay */&lt;/span&gt;

	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;etype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* entry type */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;vm_prot_t&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;protection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* protection code */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vm_prot_t&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;max_protection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* maximum protection */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vm_inherit_t&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;inheritance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* inheritance */&lt;/span&gt;

	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;wired_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* can be paged if == 0 */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;advice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* madvise advice */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define uvm_map_entry_stop_copy flags
&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;u_int8_t&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* flags */&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#define UVM_MAP_STATIC		0x01		&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* static map entry */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#define UVM_MAP_KMEM		0x02		&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* from kmem entry pool */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;fspace_augment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* max(fspace) in subtree */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Notice also that a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_entry&lt;/code&gt; has makes a couple of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TAILQ_ENTRY&lt;/code&gt; calls, which create &lt;a href=&quot;http://nixdoc.net/man-pages/openbsd/man3/TAILQ_HEAD.3.html&quot;&gt;another standard data structure&lt;/a&gt;, this time a tail queue:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;...
     TAILQ_ENTRY(TYPE);

     TAILQ_HEAD(HEADNAME, TYPE);
...
DESCRIPTION    [Toc]    [Back]

     These macros define and operate on five types of data structures: singlylinked
  lists, simple queues, lists, tail queues, and circular queues.
     All five structures support the following functionality:

           1.   Insertion of a new entry at the head of the list.
           2.   Insertion of a new entry after any element in the
list.
           3.   Removal of an entry from the head of the list.
           4.   Forward traversal through the list.
...
     Tail queues add the following functionality:

           1.   Entries can be added at the end of a list.
           2.   They may be traversed backwards, at a cost.

     However:

           1.   All list insertions and removals must specify the
head of the
                list.
           2.   Each head entry requires two pointers rather than
one.
           3.   Code size is about 15% greater and operations run
about 20%
                slower than singly-linked lists.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Exactly what the “dead” entry queue does, I’m not sure.  If we look at &lt;a href=&quot;http://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/uvm/uvm_map.h&quot;&gt;the same struct in NetBSD&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * Address map entries consist of start and end addresses,
 * a VM object (or sharing map) and offset into that object,
 * and user-exported inheritance and protection information.
 * Also included is control information for virtual copy operations.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rb_node&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;rb_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* tree information */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;gap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* free space after */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;maxgap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* space in subtree */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* previous entry */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* next entry */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* start address */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* end address */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* uvm object */&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* belongs to another map */&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;				&lt;span class=&quot;cm&quot;&gt;/* object I point to */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* offset into object */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;etype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* entry type */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vm_prot_t&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;protection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* protection code */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vm_prot_t&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;max_protection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* maximum protection */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vm_inherit_t&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;inheritance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* inheritance */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;wired_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* can be paged if == 0 */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_aref&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;aref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* anonymous overlay */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;advice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* madvise advice */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;map_attrib&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* uvm-external map attributes */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#define uvm_map_entry_stop_copy flags
&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;u_int8_t&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* flags */&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#define	UVM_MAP_KERNEL		0x01		&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* kernel map entry */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#define	UVM_MAP_STATIC		0x04		&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* special static entries */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#define	UVM_MAP_NOMERGE		0x08		&lt;/span&gt;&lt;span class=&quot;cm&quot;&gt;/* this entry is not mergable */&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can see that it doesn’t have a dead entry queue at all.  :/&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_object&lt;/code&gt; union is defined earlier in the same file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * Objects which live in maps may be either VM objects, or another map
 * (called a &quot;sharing map&quot;) which denotes read-write sharing with other maps.
 *
 * XXXCDC: private pager data goes here now
 */&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_object&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* UVM OBJECT */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt;		&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* belongs to another map */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_object&lt;/code&gt; struct is defined in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_object.h?rev=1.21&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_object.h&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * uvm_object: all that is left of mach objects.
 */&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_pagerops&lt;/span&gt;		&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgops&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* pager ops */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;RB_HEAD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_objtree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;	 &lt;span class=&quot;n&quot;&gt;memt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* pages in object */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;				 &lt;span class=&quot;n&quot;&gt;uo_npages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* # of pages in memt */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;				 &lt;span class=&quot;n&quot;&gt;uo_refs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* reference count */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;From the definition of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_object&lt;/code&gt; we can see that it also contains a red-black tree of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_page&lt;/code&gt; objects, which are defined in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_page.h?rev=1.60&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_page.h&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 *	Management of resident (logical) pages.
 *
 *	A small structure is kept for each resident
 *	page, indexed by page number.  Each structure
 *	contains a list used for manipulating pages, and
 *	a tree structure for in object/offset lookups
 *
 *	In addition, the structure contains the object
 *	and offset to which this page belongs (for pageout),
 *	and sundry status bits.
 *
 *	Fields in this structure are possibly locked by the lock on the page
 *	queues (P).
 */&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;TAILQ_HEAD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pglist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;TAILQ_ENTRY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;pageq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* queue info for FIFO
						 * queue or free list (P) */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;RB_ENTRY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;objt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* object tree */&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_anon&lt;/span&gt;		&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uanon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* anon (P) */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uobject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* object (P) */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* offset into object (P) */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;u_int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;pg_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* object flags [P] */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;u_int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;pg_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* version count */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;u_int&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;wire_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* wired down map refs [P] */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;paddr_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;phys_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* physical address of page */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;psize_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;fpgsz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* free page range size */&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page_md&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;mdpage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* pmap-specific data */&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#if defined(UVM_PAGE_TRKOWN)
&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* debugging fields to track page ownership */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pid_t&lt;/span&gt;			&lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* proc that set PG_BUSY */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;			&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;owner_tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* why it was set busy */&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The lowest level in the above diagram shows a “pager” object, which corresponds to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_pagerops&lt;/code&gt; struct, which is defined in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_pager.h?rev=1.29&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_pager.h&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_pagerops&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
						&lt;span class=&quot;cm&quot;&gt;/* init pager */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;			&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgo_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
						&lt;span class=&quot;cm&quot;&gt;/* add reference to obj */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;			&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgo_reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
						&lt;span class=&quot;cm&quot;&gt;/* drop reference to obj */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;			&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgo_detach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
						&lt;span class=&quot;cm&quot;&gt;/* special nonstd fault fn */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgo_fault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_faultinfo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				 &lt;span class=&quot;n&quot;&gt;vm_page_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_fault_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				 &lt;span class=&quot;n&quot;&gt;vm_prot_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
						&lt;span class=&quot;cm&quot;&gt;/* flush pages out of obj */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;boolean_t&lt;/span&gt;		&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgo_flush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				 &lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
						&lt;span class=&quot;cm&quot;&gt;/* get/read page */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgo_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				 &lt;span class=&quot;n&quot;&gt;vm_page_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_prot_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
						&lt;span class=&quot;cm&quot;&gt;/* put/write page */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;			&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgo_put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				 &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boolean_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
						&lt;span class=&quot;cm&quot;&gt;/* return range of cluster */&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;			&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgo_cluster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				 &lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
						&lt;span class=&quot;cm&quot;&gt;/* make &quot;put&quot; cluster */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgo_mk_pcluster&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				 &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				 &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voff_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As we can see, this effectively implements a kind of multiple dispatch in which the underlying “pager” implements these functions and stores pointers to them in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_pagerops&lt;/code&gt; struct.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;TODO&lt;/p&gt;

&lt;h1 id=&quot;aside-x86-mmu&quot;&gt;Aside: x86 MMU&lt;a name=&quot;x86-mmu&quot;&gt; &lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;The x86 implementation of pmap, located in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/arch/i386/i386/pmap.c?rev=1.186&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/arch/i386/i386/pmap.c&lt;/code&gt;&lt;/a&gt; contains some nice documentation for the x86 MMU:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * this file contains the code for the &quot;pmap module.&quot;   the module's
 * job is to manage the hardware's virtual to physical address mappings.
 * note that there are two levels of mapping in the VM system:
 *
 *  [1] the upper layer of the VM system uses vm_map's and vm_map_entry's
 *      to map ranges of virtual address space to objects/files.  for
 *      example, the vm_map may say: &quot;map VA 0x1000 to 0x22000 read-only
 *      to the file /bin/ls starting at offset zero.&quot;   note that
 *      the upper layer mapping is not concerned with how individual
 *      vm_pages are mapped.
 *
 *  [2] the lower layer of the VM system (the pmap) maintains the mappings
 *      from virtual addresses.   it is concerned with which vm_page is
 *      mapped where.   for example, when you run /bin/ls and start
 *      at page 0x1000 the fault routine may lookup the correct page
 *      of the /bin/ls file and then ask the pmap layer to establish
 *      a mapping for it.
 *
 * note that information in the lower layer of the VM system can be
 * thrown away since it can easily be reconstructed from the info
 * in the upper layer.
 *
 * data structures we use include:
 *
 *  - struct pmap: describes the address space of one thread
 *  - struct pv_entry: describes one &amp;lt;PMAP,VA&amp;gt; mapping of a PA
 *  - struct pv_head: there is one pv_head per managed page of
 *	physical memory.   the pv_head points to a list of pv_entry
 *	structures which describe all the &amp;lt;PMAP,VA&amp;gt; pairs that this
 *      page is mapped in.    this is critical for page based operations
 *      such as pmap_page_protect() [change protection on _all_ mappings
 *      of a page]
 */&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/*
 * i386 MMU hardware structure:
 *
 * the i386 MMU is a two-level MMU which maps 4GB of virtual memory.
 * the pagesize is 4K (4096 [0x1000] bytes), although newer pentium
 * processors can support a 4MB pagesize as well.
 *
 * the first level table (segment table?) is called a &quot;page directory&quot;
 * and it contains 1024 page directory entries (PDEs).   each PDE is
 * 4 bytes (an int), so a PD fits in a single 4K page.   this page is
 * the page directory page (PDP).  each PDE in a PDP maps 4MB of space
 * (1024 * 4MB = 4GB).   a PDE contains the physical address of the
 * second level table: the page table.   or, if 4MB pages are being used,
 * then the PDE contains the PA of the 4MB page being mapped.
 *
 * a page table consists of 1024 page table entries (PTEs).  each PTE is
 * 4 bytes (an int), so a page table also fits in a single 4K page.  a
 * 4K page being used as a page table is called a page table page (PTP).
 * each PTE in a PTP maps one 4K page (1024 * 4K = 4MB).   a PTE contains
 * the physical address of the page it maps and some flag bits (described
 * below).
 *
 * the processor has a special register, &quot;cr3&quot;, which points to the
 * the PDP which is currently controlling the mappings of the virtual
 * address space.
 *
 * the following picture shows the translation process for a 4K page:
 *
 * %cr3 register [PA of PDP]
 *      |
 *      |
 *      |   bits &amp;lt;31-22&amp;gt; of VA         bits &amp;lt;21-12&amp;gt; of VA   bits &amp;lt;11-0&amp;gt;
 *      |   index the PDP (0 - 1023)   index the PTP        are the page offset
 *      |         |                           |                  |
 *      |         v                           |                  |
 *      +---&amp;gt;+----------+                     |                  |
 *           | PD Page  |   PA of             v                  |
 *           |          |---PTP--------&amp;gt;+------------+           |
 *           | 1024 PDE |               | page table |--PTE--+   |
 *           | entries  |               | (aka PTP)  |       |   |
 *           +----------+               | 1024 PTE   |       |   |
 *                                      | entries    |       |   |
 *                                      +------------+       |   |
 *                                                           |   |
 *                                                bits &amp;lt;31-12&amp;gt;   bits &amp;lt;11-0&amp;gt;
 *                                                p h y s i c a l  a d d r
 *
 * the i386 caches PTEs in a TLB.   it is important to flush out old
 * TLB mappings when making a change to a mapping.   writing to the
 * %cr3 will flush the entire TLB.    newer processors also have an
 * instruction that will invalidate the mapping of a single page (which
 * is useful if you are changing a single mapping because it preserves
 * all the cached TLB entries).
 *
 * as shows, bits 31-12 of the PTE contain PA of the page being mapped.
 * the rest of the PTE is defined as follows:
 *   bit#	name	use
 *   11		n/a	available for OS use, hardware ignores it
 *   10		n/a	available for OS use, hardware ignores it
 *   9		n/a	available for OS use, hardware ignores it
 *   8		G	global bit (see discussion below)
 *   7		PS	page size [for PDEs] (0=4k, 1=4M &amp;lt;if supported&amp;gt;)
 *   6		D	dirty (modified) page
 *   5		A	accessed (referenced) page
 *   4		PCD	cache disable
 *   3		PWT	prevent write through (cache)
 *   2		U/S	user/supervisor bit (0=supervisor only, 1=both u&amp;amp;s)
 *   1		R/W	read/write bit (0=read only, 1=read-write)
 *   0		P	present (valid)
 *
 * notes:
 *  - on the i386 the R/W bit is ignored if processor is in supervisor
 *    state (bug!)
 *  - PS is only supported on newer processors
 *  - PTEs with the G bit are global in the sense that they are not
 *    flushed from the TLB when %cr3 is written (to flush, use the
 *    &quot;flush single page&quot; instruction).   this is only supported on
 *    newer processors.    this bit can be used to keep the kernel's
 *    TLB entries around while context switching.   since the kernel
 *    is mapped into all processes at the same place it does not make
 *    sense to flush these entries when switching from one process'
 *    pmap to another.
 */&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/*
 * A pmap describes a process' 4GB virtual address space.  This
 * virtual address space can be broken up into 1024 4MB regions which
 * are described by PDEs in the PDP.  The PDEs are defined as follows:
 *
 * Ranges are inclusive -&amp;gt; exclusive, just like vm_map_entry start/end.
 * The following assumes that KERNBASE is 0xd0000000.
 *
 * PDE#s	VA range		Usage
 * 0-&amp;gt;831	0x0 -&amp;gt; 0xcfc00000	user address space, note that the
 *					max user address is 0xcfbfe000
 *					the final two pages in the last 4MB
 *					used to be reserved for the UAREA
 *					but now are no longer used.
 * 831		0xcfc00000-&amp;gt;		recursive mapping of PDP (used for
 *			0xd0000000	linear mapping of PTPs).
 * 832-&amp;gt;1023	0xd0000000-&amp;gt;		kernel address space (constant
 *			0xffc00000	across all pmaps/processes).
 * 1023		0xffc00000-&amp;gt;		&quot;alternate&quot; recursive PDP mapping
 *			&amp;lt;end&amp;gt;		(for other pmaps).
 *
 *
 * Note: A recursive PDP mapping provides a way to map all the PTEs for
 * a 4GB address space into a linear chunk of virtual memory.  In other
 * words, the PTE for page 0 is the first int mapped into the 4MB recursive
 * area.  The PTE for page 1 is the second int.  The very last int in the
 * 4MB range is the PTE that maps VA 0xffffe000 (the last page in a 4GB
 * address).
 *
 * All pmaps' PDs must have the same values in slots 832-&amp;gt;1023 so that
 * the kernel is always mapped in every process.  These values are loaded
 * into the PD at pmap creation time.
 *
 * At any one time only one pmap can be active on a processor.  This is
 * the pmap whose PDP is pointed to by processor register %cr3.  This pmap
 * will have all its PTEs mapped into memory at the recursive mapping
 * point (slot #831 as show above).  When the pmap code wants to find the
 * PTE for a virtual address, all it has to do is the following:
 *
 * Address of PTE = (831 * 4MB) + (VA / PAGE_SIZE) * sizeof(pt_entry_t)
 *                = 0xcfc00000 + (VA / 4096) * 4
 *
 * What happens if the pmap layer is asked to perform an operation
 * on a pmap that is not the one which is currently active?  In that
 * case we take the PA of the PDP of the non-active pmap and put it in
 * slot 1023 of the active pmap.  This causes the non-active pmap's
 * PTEs to get mapped in the final 4MB of the 4GB address space
 * (e.g. starting at 0xffc00000).
 *
 * The following figure shows the effects of the recursive PDP mapping:
 *
 *   PDP (%cr3)
 *   +----+
 *   |   0| -&amp;gt; PTP#0 that maps VA 0x0 -&amp;gt; 0x400000
 *   |    |
 *   |    |
 *   | 831| -&amp;gt; points back to PDP (%cr3) mapping VA 0xcfc00000 -&amp;gt; 0xd0000000
 *   | 832| -&amp;gt; first kernel PTP (maps 0xd0000000 -&amp;gt; 0xe0400000)
 *   |    |
 *   |1023| -&amp;gt; points to alternate pmap's PDP (maps 0xffc00000 -&amp;gt; end)
 *   +----+
 *
 * Note that the PDE#831 VA (0xcfc00000) is defined as &quot;PTE_BASE&quot;.
 * Note that the PDE#1023 VA (0xffc00000) is defined as &quot;APTE_BASE&quot;.
 *
 * Starting at VA 0xcfc00000 the current active PDP (%cr3) acts as a
 * PTP:
 *
 * PTP#831 == PDP(%cr3) =&amp;gt; maps VA 0xcfc00000 -&amp;gt; 0xd0000000
 *   +----+
 *   |   0| -&amp;gt; maps the contents of PTP#0 at VA 0xcfc00000-&amp;gt;0xcfc01000
 *   |    |
 *   |    |
 *   | 831| -&amp;gt; maps the contents of PTP#831 (the PDP) at VA 0xcff3f000
 *   | 832| -&amp;gt; maps the contents of first kernel PTP
 *   |    |
 *   |1023|
 *   +----+
 *
 * Note that mapping of the PDP at PTP#831's VA (0xcff3f000) is
 * defined as &quot;PDP_BASE&quot;.... within that mapping there are two
 * defines:
 *   &quot;PDP_PDE&quot; (0xcff3fcfc) is the VA of the PDE in the PDP
 *      which points back to itself.
 *   &quot;APDP_PDE&quot; (0xcff3fffc) is the VA of the PDE in the PDP which
 *      establishes the recursive mapping of the alternate pmap.
 *      To set the alternate PDP, one just has to put the correct
 *	PA info in *APDP_PDE.
 *
 * Note that in the APTE_BASE space, the APDP appears at VA
 * &quot;APDP_BASE&quot; (0xfffff000).
 */&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;attribution&quot;&gt;Attribution&lt;/h1&gt;

&lt;p&gt;The diagram for UVM’s data structures comes from &lt;a href=&quot;http://usenix.org/legacy/publications/library/proceedings/usenix99/full_papers/cranor/cranor_html/index.html&quot;&gt;Charles Craynor’s paper at Usenix in 1999&lt;/a&gt;, of which there is also &lt;a href=&quot;https://www.usenix.org/event/usenix99/full_papers/cranor/cranor.pdf&quot;&gt;a PDF version&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 23 Feb 2016 00:00:00 +0000</pubDate>
        <link>http://blog.pr4tt.com/2016/02/23/OpenBSD-Virtual-Memory/</link>
        <guid isPermaLink="true">http://blog.pr4tt.com/2016/02/23/OpenBSD-Virtual-Memory/</guid>
      </item>
    
      <item>
        <title>RadixVM</title>
        <description>&lt;p&gt;So far this blog has &lt;a href=&quot;/2016/02/01/posix-memory-management/&quot;&gt;investigated the virtual memory interface in POSIX&lt;/a&gt;, and dived into &lt;a href=&quot;/2016/02/02/BSD-virtual-memory/&quot;&gt;some of the details of how it’s implemented in BSD&lt;/a&gt;.  Today, we’ll look at the state of the art in academic virtual memory design, in particular a design called &lt;a href=&quot;https://people.csail.mit.edu/nickolai/papers/clements-radixvm-2014-08-05.pdf&quot;&gt;RadixVM by Austin T. Clements, M. Frans Kaashoek, Nickolai Zeldovich at MIT’s CSAIL&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;background&quot;&gt;Background&lt;/h1&gt;

&lt;p&gt;Recall that virtual memory allows us to pretend that each process has exclusive access to a huge amount of (virtual) memory.  Each fixed-size page of this virtual address space is usually stored either resident in an equal-sized frame of physical memory, or swapped out to disk.  A process’ operations on these virtual addresses are passed through a translation lookaside buffer (TLB) that caches the actual physical memory locations for each virtual page.  In the case where an entry for a page is not found in the TLB, a page table is consulted.  If the page is not presently loaded in physical memory (referred to as a page fault), it is loaded before continuing.  Finally, the TLB is updated with the address and the process continues operating in the virtual address space.&lt;/p&gt;

&lt;p&gt;These days, memory allocation such as a call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; is often handled by mapping an anonymous region in memory using an underlying call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt;.  &lt;a href=&quot;http://www.canonware.com/jemalloc/&quot;&gt;One of the most well-known &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; implementations, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jemalloc&lt;/code&gt;&lt;/a&gt;, explicitly states in its documentation that &lt;a href=&quot;http://www.canonware.com/download/jemalloc/jemalloc-latest/doc/jemalloc.html&quot;&gt;it prefers to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt; over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt;&lt;/a&gt;.  When such regions are unmapped, it’s important to immediately flush their entries in the TLB otherwise a dangling pointer referring to that allocation may end up modifying a region of memory which was already reallocated.  This process is called a TLB shootdown.  When multiple threads of the same process are spread across multiple cores, and one thread unmaps the region, any core running threads from this process needs to have its TLB flushed.  This is called remote TLB shootdown.&lt;/p&gt;

&lt;h1 id=&quot;problem&quot;&gt;Problem&lt;/h1&gt;

&lt;p&gt;Unfortunately, most operating systems serialize calls to mmap and munmap (single lock per shared address space).  mmap and munmap should be perfectly parallelizable since they should be operating on different parts of the address space.&lt;/p&gt;

&lt;p&gt;Operating systems typically use balanced trees to keep track of mapped memory regions within a process’ address space.  Linux uses red/black trees, FreeBSD uses splay trees, Solairs and Windows use AVL trees.  Since these data structures require rebalancing on insert and delete (to maintain O(log n) height), they use a single lock to serialize changes to the entire data structure.&lt;/p&gt;

&lt;h1 id=&quot;radixvm&quot;&gt;RadixVM&lt;/h1&gt;

&lt;p&gt;RadixVM attempts to solve this problem.  RadixVM has 3 novel parts: its radix-tree-based data structure for tracking mapped memory, its method of avoiding remote TLB shootdowns, and its memory-efficient distributed reference counting scheme.&lt;/p&gt;

&lt;h2 id=&quot;refcache-reference-counting&quot;&gt;Refcache: Reference Counting&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Reference_counting&quot;&gt;Reference counting&lt;/a&gt; is a common form of memory management in which memory is automatically freed when the number of references to a memory region drops to zero.&lt;/p&gt;

&lt;p&gt;The RadixVM paper introduces a memory-efficient distributed reference counting scheme, called Refcache.  Roughly speaking, refcache counts references to a memory location across possibly many cores.  Refcache divides time into fixed-length epochs (the canonical implementation uses an epoch of length 10ms), and only frees unreferenced memory after its reference count has dropped to zero and remains at zero for an entire epoch.&lt;/p&gt;

&lt;h2 id=&quot;data-structure&quot;&gt;Data Structure&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/6/63/An_example_of_how_to_find_a_string_in_a_Patricia_trie.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Radix_tree&quot;&gt;Radix tree&lt;/a&gt; is a type of data structure better known as a prefix tree, or a trie.  This data structure is a tree for storing strings of characters from a set called the alphabet.  A string is represented as a leaf in the tree by its root to leaf path, each edge of which is labeled with a sequence of characters.  At each node along this path, the concatenation of the edges of the root to node path form a prefix shared by all children of this node.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/X86_Paging_4K.svg/512px-X86_Paging_4K.svg.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the context of operating systems, we normally use a variant of a radix tree which is built on bit strings has fixed depth.  That is, each outgoing edge from a level has the same number of bits.  This is very commonly used to represent a hierarchical page table, indexed by a 32 or 64-bit word, whose first few bits are the index into the highest level page table, the next few bits are the index into the next-highest level page table, etc.&lt;/p&gt;

&lt;p&gt;RadixVM uses a data structure based on a radix tree, very similar to a typical page table, in which each level is indexed by 9 (or fewer) bits.  Unlike a typical page table, RadixVM’s data structure stores a separate copy of the mapping metadata in the radix tree for each page in the mapped range.&lt;/p&gt;

&lt;h2 id=&quot;avoiding-remote-tlb-shootdowns&quot;&gt;Avoiding Remote TLB Shootdowns&lt;/h2&gt;

&lt;p&gt;Each core has its own TLB, and the x86 architecture doesn’t inform the kernel about its contents.  Therefore, most operating systems perform the simplest possible kind of TLB shootdown when memory is unmapped, which is to shootdown the TLB on every core.  To avoid remote TLB shootdowns, RadixVM uses a scheme that tracks which cores have what mappings, and only performs remote TLB shootdowns when necessary.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;The authors learned in a previous paper about &lt;a href=&quot;https://people.csail.mit.edu/nickolai/papers/clements-bonsai.pdf&quot;&gt;a lock-free VM implementation called BonsaiVM&lt;/a&gt;, that big operating systems like Linux have a high level of coupling between the VM system and other parts of the operating system.  This means that implementing a novel VM design can be a monumental task.  So instead, the authors chose to implement radixvm on xv6.  &lt;a href=&quot;https://pdos.csail.mit.edu/6.828/2014/xv6.html&quot;&gt;xv6&lt;/a&gt; is a recently rewritten variant of Unix v6 ported to modern hardware for academic use at MIT.&lt;/p&gt;

&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;

&lt;p&gt;The authors were able to compare the behavior of Metis, a single-server multithreaded MapReduce library running on RadixVM, Bonsai, and regular linux.  The Metis workload stresses concurrent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt;s and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pagefault&lt;/code&gt;s, but not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;munmap&lt;/code&gt;s.  In their experiments, RadixVM and Bonsai (only with 8MB block sizes) scale very well.  Linux/64kb seems to peak at 10 cores before dropping off.  Linux/8MB and Bonsai/64kb drop off after 20 cores.&lt;/p&gt;

&lt;p&gt;Since most large, complex applications have been built around the traditional limitations of mmap and munmap, they don’t allow for good measurements of improvements to mmap/munmap.  Thus, the authors were forced to rely on microbenchmarks to measure performance in other workloads.  According to these microbenchmarks on the workloads they tested, only RadixVM really scales.&lt;/p&gt;

&lt;h2 id=&quot;do-we-really-need-all-3-parts&quot;&gt;Do we really need all 3 parts?&lt;/h2&gt;

&lt;p&gt;One final interesting thing to note about RadixVM is that the authors consider very strongly whether all 3 parts of their design are necessary.  Of course, they determine that yes, all parts of their design are necessary.  But it is still good that they spent the time to explain why.&lt;/p&gt;

&lt;h1 id=&quot;attribution&quot;&gt;Attribution&lt;/h1&gt;

&lt;p&gt;Patricia trie diagram by Saffles (Microsoft Visio) &lt;a href=&quot;http://creativecommons.org/licenses/by-sa/3.0&quot;&gt;CC BY-SA 3.0&lt;/a&gt;, via Wikimedia Commons.&lt;/p&gt;

&lt;p&gt;Page table diagram by RokerHRO (eigene Arbeit / own work using Xfig.) &lt;a href=&quot;http://creativecommons.org/licenses/by-sa/3.0&quot;&gt;CC BY-SA 3.0&lt;/a&gt;, via Wikimedia Commons.&lt;/p&gt;
</description>
        <pubDate>Sun, 07 Feb 2016 00:00:00 +0000</pubDate>
        <link>http://blog.pr4tt.com/2016/02/07/radixVM/</link>
        <guid isPermaLink="true">http://blog.pr4tt.com/2016/02/07/radixVM/</guid>
      </item>
    
      <item>
        <title>BSD Virtual Memory</title>
        <description>&lt;p&gt;After &lt;a href=&quot;/2016/02/01/posix-memory-management/&quot;&gt;the article on POSIX memory management&lt;/a&gt;, we have a good grasp of the high-level memory allocation functions specified in &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/9699919799/&quot;&gt;POSIX.1&lt;/a&gt;.  We learned how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; is a C library function which can be implemented using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt;.  Now it’s time to dive into the details about how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt; is implemented.&lt;/p&gt;

&lt;p&gt;Under the hood, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt; touches a fundamental concept in operating systems.  Specifically, it must interface with the kernel’s implementation of virtual memory.  Virtual memory is the way in which we give each process the illusion that it is the only running process and it has full access to the system’s memory.&lt;/p&gt;

&lt;p&gt;There are 3 main ways to virtualize memory: segmentation, paging, and swapping.  Segmentation builds on the concept we touched on in &lt;a href=&quot;/2016/02/01/posix-memory-management/&quot;&gt;the previous article&lt;/a&gt;, that each process is split into several “segments,” such as heap, stack and text.  These segments can be placed independently in physical memory and with hardware support their virtual addresses could be translated to physical ones.  However, keeping these segments contiguous in memory can be a lot of overhead.  For that reason, paging divides virtual memory into fixed-size pages, which are placed independently in fixed-size frames in physical memory.  Finally, swapping moves allocated but inactive parts of memory to disk to free up space for active processes.&lt;/p&gt;

&lt;p&gt;POSIX.1 doesn’t specify implementation details, so we have to pick a particular operating system to investigate.  For no particularly good reason, we’re going with BSD, and we’ll be looking at NetBSD and FreeBSD in particular.  We’ll be looking at those two BSDs in particular for historical reasons, so it’s worth taking a brief aside to go over that history.&lt;/p&gt;

&lt;h1 id=&quot;bsd-history&quot;&gt;BSD History&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Unix&quot;&gt;UNIX was started at Bell Labs in 1969.&lt;/a&gt;  In 1974, the University of California at Berkeley received a copy of UNIX which they ran on a &lt;a href=&quot;https://en.wikipedia.org/wiki/PDP-11&quot;&gt;PDP-11&lt;/a&gt;.  In 1975, they installed UNIX v6.  By 1977, they had written enough software in which other Universities were interested that they started bundling it together as &lt;a href=&quot;https://en.wikipedia.org/wiki/Berkeley_Software_Distribution&quot;&gt;1BSD&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In 1978, a &lt;a href=&quot;https://en.wikipedia.org/wiki/VAX-11&quot;&gt;VAX computer&lt;/a&gt; was installed at Berkeley, and though the original UNIX for the PDP-11 supported paging and swapping, the UNIX version ported to this machine, UNIX/32V, was released without paging.  So 2BSD included a largely rewritten kernel for the VAX which included support for paging.&lt;/p&gt;

&lt;p&gt;In 1985, a group at Carnegie Mellon University began work on &lt;a href=&quot;https://en.wikipedia.org/wiki/Mach_%28kernel%29&quot;&gt;a research kernel called Mach&lt;/a&gt; that would replace the BSD kernel.  Importantly, Mach was designed to be platform-independent (as opposed to all previous versions of BSD or UNIX).  This decision likely led to the good kernel design that inspired the design of several future BSD variants.&lt;/p&gt;

&lt;p&gt;In 1988, the decision was finally made to move BSD away from VAX and cleanly separate its machine-dependent and machine-independent code.  4.3BSD-Tahoe was the interrim BSD release for the Power 6/32 platform which put this into practice, though the port for that platform was very quickly abandoned.&lt;/p&gt;

&lt;p&gt;Also in 1988, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Single_UNIX_Specification&quot;&gt;Single UNIX Specification&lt;/a&gt; officially became the first version of &lt;a href=&quot;https://en.wikipedia.org/wiki/POSIX&quot;&gt;POSIX, IEEE 1003.1-1988&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By 1989, much of BSD relied on proprietary UNIX code which relied on having an AT&amp;amp;T software license, which was becoming increasingly expensive.  Thus began an effort to rewrite all the proprietary dependencies which became BSD Net/1.&lt;/p&gt;

&lt;p&gt;In 1990, 4.3BSD-Reno, another interrim version, was released which pushed towards POSIX compliance.  By 1991, most of the AT&amp;amp;T code had been replaced, and Net/2 was released.  Net/2 used the VM system from Mach 2.5.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://porting-unix-to-the-386.jolix.com/&quot;&gt;In 1992, 4.3BSD-Reno and Net/2 were used as the basis of a port to the Intel 386 processor, which was called 386BSD.  Notably, this finally replaced all the proprietary code that was still left in Net/2.&lt;/a&gt;  Also in 1992, &lt;a href=&quot;https://en.wikipedia.org/wiki/BSD/OS&quot;&gt;BSD/386&lt;/a&gt;, a commercial port to the 386, was also released, but even before its release AT&amp;amp;T filed a lawsuit against them for breach of their copyright.&lt;/p&gt;

&lt;p&gt;In 1993, 386BSD was forked into &lt;a href=&quot;https://en.wikipedia.org/wiki/FreeBSD&quot;&gt;FreeBSD&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/NetBSD&quot;&gt;NetBSD&lt;/a&gt;.  By 1994, 386BSD was abandoned.  Also, the AT&amp;amp;T lawsuit was resolved, and 4.4BSD-Lite was released, containing no AT&amp;amp;T source code.  This release incorporated many of Mach’s design decisions and were largely adopted by both FreeBSD and NetBSD over the following years.  In 1996, NetBSD was forked into &lt;a href=&quot;https://en.wikipedia.org/wiki/OpenBSD&quot;&gt;OpenBSD&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In 1998, &lt;a href=&quot;http://chuck.cranor.org/p/diss.pdf&quot;&gt;Charles Cranor wrote a dissertation&lt;/a&gt; on the design of &lt;a href=&quot;http://www.netbsd.org/docs/kernel/uvm.html&quot;&gt;UVM&lt;/a&gt;, a virtual memory system which was to replace Mach’s in NetBSD.  Much of this was also ported to OpenBSD.&lt;/p&gt;

&lt;p&gt;In 2004, version 4.8 of FreeBSD was forked into &lt;a href=&quot;https://en.wikipedia.org/wiki/DragonFly_BSD&quot;&gt;DragonFly BSD&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;virtual-memory-systems&quot;&gt;Virtual Memory Systems&lt;/h1&gt;

&lt;p&gt;So finally, we can talk about virtual memory systems.  We can summarize the above by saying that there are 2 main BSD variants today: FreeBSD and NetBSD.  Each of which has its own sub-variant: DragonFly BSD and OpenBSD, respectively.  FreeBSD and DragonFly BSD have virtual memory systems based on Mach (or 4.4BSD-Lite if you prefer), and NetBSD and OpenBSD have virtual memory systems based on UVM.&lt;/p&gt;

&lt;h2 id=&quot;freebsd-mach&quot;&gt;FreeBSD (Mach)&lt;/h2&gt;

&lt;h3 id=&quot;data-structures&quot;&gt;Data Structures&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://www.pr4tt.com/wiki/lib/exe/fetch.php?media=freebsd_virtual_memory.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The FreeBSD kernel stores address space information about each process in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmspace&lt;/code&gt; structure, which encapsulates both machine-dependent and machine-independent information.  We describe here only the machine-independent data structures.  Each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmspace&lt;/code&gt; structure contains a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map&lt;/code&gt; structure, which points to an ordered linked-list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_entry&lt;/code&gt; structure objects.&lt;/p&gt;

&lt;p&gt;Each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_entry&lt;/code&gt; describes a contiguous region of virtual memory and contains a pointer to a next entry, and to a chain of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt; structures.  Each contiguous region of virtual memory pointed to by a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_entry&lt;/code&gt; has the same attributes (such as protection), so these are also stored in this structure.  Between a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_entry&lt;/code&gt; and its chain of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt;s, there are zero or more “shadow” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt;s which track changes to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt;, each of which stores a pointer to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_page&lt;/code&gt; containing the changes and another pointer to the unmodified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt; structure contains a pointer to another linked list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_page&lt;/code&gt; structures which represent the physical memory cache of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt;.  The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_page&lt;/code&gt; also keeps a radix tree of these &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_page&lt;/code&gt; structures (keyed by its logical offset from the start of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt;).  This radix tree makes searching for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_page&lt;/code&gt; structures much quicker.&lt;/p&gt;

&lt;h3 id=&quot;dragonfly-bsd-changes&quot;&gt;DragonFly BSD Changes&lt;/h3&gt;

&lt;p&gt;A notable difference between DragonFly BSD and FreeBSD is that the former also stores the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map_entry&lt;/code&gt; structures in a tree.&lt;/p&gt;

&lt;h2 id=&quot;netbsd-and-openbsd-uvm&quot;&gt;NetBSD and OpenBSD (UVM)&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;http://www.pr4tt.com/wiki/lib/exe/fetch.php?media=uvm.gif&quot; style=&quot;width: 100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;UVM was based on 4.4BSD which itself was based on Mach, and so it initially bares some resemblance to the virtual memory system in FreeBSD.  However, UVM was designed to support memory sharing using three mechanisms: page loanout, page transfer, and map entry passing.&lt;/p&gt;

&lt;p&gt;Page loanout is when a process loans its memory to another process.  This is useful particularly in networking, in which data can be sent to the kernel’s network stack simply by loaning the appropriate pages.  This avoids the need for costly copy operations.&lt;/p&gt;

&lt;p&gt;Page transfer is similar to loanout, except the pages remain in the possession of the receiving process.&lt;/p&gt;

&lt;p&gt;Map entry passing, rather than transfering the pages of virtual memory, copies the higher-level map objects in order to export a large range of memory to another process.  This saves nothing when copying a single page, but scales very well since a map object can point to very many pages in memory, and only the map structure itself need be copied.&lt;/p&gt;

&lt;h3 id=&quot;data-structures-1&quot;&gt;Data Structures&lt;/h3&gt;

&lt;p&gt;UVM is designed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmspace&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_map&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_page&lt;/code&gt; objects which function similarly to those in FreeBSD.  We will describe the differences.&lt;/p&gt;

&lt;p&gt;In addition to what was described above, each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt; has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_pager&lt;/code&gt; object which describes how the backing store can be accessed.  Essentially, this is a pointer to a list of functions which fetch and store pages between the memory pointed to by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_page&lt;/code&gt; object and whatever backing store (such as a disk) underlies the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vm_object&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;implementation&quot;&gt;Implementation&lt;/h3&gt;

&lt;p&gt;It’s interesting to look at the implementation to see all the gory details.  We can find the definition of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt; system call for OpenBSD in &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_mmap.c?rev=1.122&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;their CVS repo in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_mmap.c&lt;/code&gt;&lt;/a&gt;.  In fact, there are too many gory details here, so I will show a version here with lots of extra stuff cut out.  We only really care about the case where extra anonymous memory is allocated.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * sys_mmap: mmap system call.
 *
 * =&amp;gt; file offset and address may not be page aligned
 *    - if MAP_FIXED, offset and address must have remainder mod PAGE_SIZE
 *    - if address isn't page aligned the mapping starts at trunc_page(addr)
 *      and the return value is adjusted up by the page offset.
 */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;sys_mmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;register_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;retval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* first, extract syscall args from the uap. */&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* validate the flags */&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pledge_protexec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* align file position and save offset.  adjust size. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;ALIGN_ADDR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pageoff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* now check (MAP_FIXED) or get (!MAP_FIXED) the &quot;addr&quot; */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_FIXED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;

	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* check for file mappings (i.e. not anonymous) and verify file. */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_ANON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;		&lt;span class=&quot;cm&quot;&gt;/* MAP_ANON case */&lt;/span&gt;
		&lt;span class=&quot;cm&quot;&gt;/*
		 * XXX What do we do about (MAP_SHARED|MAP_PRIVATE) == 0?
		 */&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EINVAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;is_anon:&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* label for SunOS style /dev/zero */&lt;/span&gt;

		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_ANON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
		    &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_PRIVATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROT_WRITE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
			    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_rlimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RLIMIT_DATA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rlim_cur&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptoa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_vmspace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_dused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENOMEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;maxprot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROT_MASK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_mmapanon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_vmspace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxprot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		    &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_rlimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RLIMIT_MEMLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rlim_cur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;cm&quot;&gt;/* remember to add offset */&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;retval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;register_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pageoff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_mmapanon&lt;/code&gt; is defined in the same file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * uvm_mmapanon: internal version of mmap for anons
 *
 * - used by sys_mmap
 */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;uvm_mmapanon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_map_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_prot_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vm_prot_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxprot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locklimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;advice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MADV_NORMAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvmflag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;align&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* userland page size */&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * for non-fixed mappings, round off the suggested address.
	 * for fixed mappings, check alignment and zap old mappings.
	 */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_FIXED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;round_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* round */&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAGE_MASK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EINVAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

		&lt;span class=&quot;n&quot;&gt;uvmflag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_FIXED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__MAP_NOREPLACE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;uvmflag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_UNMAP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_FIXED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__LDPGSZ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;align&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__LDPGSZ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_SHARED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;cm&quot;&gt;/* XXX: defer amap create */&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;uvmflag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_COPYONW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
		&lt;span class=&quot;cm&quot;&gt;/* shared: create amap now */&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;uvmflag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_OVERLAY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* set up mapping flags */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvmflag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_MAPFLAG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxprot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_SHARED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_INHERIT_SHARE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_INHERIT_COPY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;n&quot;&gt;advice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvmflag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_mapanon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvmflag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_mmaplock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locklimit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The function prototype for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_mapanon&lt;/code&gt; is in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_extern.h&lt;/code&gt; but &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_map.c?rev=1.205&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;its definition is in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_map.c&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * uvm_mapanon: establish a valid mapping in map for an anon
 *
 * =&amp;gt; *addr and sz must be a multiple of PAGE_SIZE.
 * =&amp;gt; *addr is ignored, except if flags contains UVM_FLAG_FIXED.
 * =&amp;gt; map must be unlocked.
 *
 * =&amp;gt; align: align vaddr, must be a power-of-2.
 *    Align is only a hint and will be ignored if the alignment fails.
 */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;uvm_mapanon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * Before grabbing the lock, allocate a map entry for later
	 * use to ensure we don't wait for memory while holding the
	 * vm_map_lock.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_mapent_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ENOMEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * Create new entry.
	 * first and last may be invalidated after this call.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_map_mkentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENOMEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;KDASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;protection&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_protection&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxprot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inheritance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inherit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wired_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;advice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;advice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_NOFAULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etype&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_ET_NOFAULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_COPYONW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etype&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_ET_COPYONWRITE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_OVERLAY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etype&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_ET_NEEDSCOPY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_OVERLAY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;KERNEL_LOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ar_pageoff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ar_amap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amap_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		    &lt;span class=&quot;n&quot;&gt;ptoa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_AMAPPAD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_AMAP_CHUNK&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
		    &lt;span class=&quot;n&quot;&gt;M_WAITOK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;KERNEL_UNLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* Update map and process statistics. */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vmspace&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm_dused&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvmspace_dused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;unlock:&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vm_map_unlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/*
	 * Remove dead entries.
	 *
	 * Dead entries may be the result of merging.
	 * uvm_map_mkentry may also create dead entries, when it attempts to
	 * destroy free-space entries.
	 */&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;uvm_unmap_detach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;out:&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;uvm_mapent_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So that largely defers to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_map_mkentry&lt;/code&gt;, which is again defined in the same file.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * Create and insert new entry.
 *
 * Returned entry contains new addresses and is inserted properly in the tree.
 * first and last are (probably) no longer valid.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;uvm_map_mkentry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vsize_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_map_deadq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;

	&lt;span class=&quot;cm&quot;&gt;/* Initialize new entry. */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_mapent_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Again, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uvm_mapent_alloc&lt;/code&gt; is in the same file.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cm&quot;&gt;/*
 * uvm_mapent_alloc: allocate a map entry
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;uvm_mapent_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;pool_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PR_WAITOK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_FLAG_TRYLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;pool_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PR_NOWAIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VM_MAP_INTRSAFE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;mtx_enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_kmapent_mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kentry_free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;km_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_dirty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			    &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd_nowait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;uvm_mapent_alloc: cannot allocate map &quot;&lt;/span&gt;
				    &lt;span class=&quot;s&quot;&gt;&quot;entry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
			    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
			    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;RB_LEFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daddrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;RB_LEFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daddrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ratecheck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_kmapent_last_warn_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			    &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_kmapent_warn_rate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;uvm_mapent_alloc: out of static &quot;&lt;/span&gt;
				    &lt;span class=&quot;s&quot;&gt;&quot;map entries&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;uvm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kentry_free&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RB_LEFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daddrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;uvmexp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kmapent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;mtx_leave&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_kmapent_mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_MAP_STATIC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kernel_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;splassert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IPL_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_map_entry_kmem_pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_MAP_KMEM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;splassert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IPL_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_map_entry_pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pool_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;RB_LEFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daddrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
		    &lt;span class=&quot;n&quot;&gt;RB_RIGHT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daddrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
		    &lt;span class=&quot;n&quot;&gt;RB_PARENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daddrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr_entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVMMAP_DEADBEEF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;out:&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finally, we’re starting to get to the good stuff.  This calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;km_alloc&lt;/code&gt;, which is &lt;a href=&quot;http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/uvm/uvm_km.c?rev=1.126.6.1&amp;amp;content-type=text/x-cvsweb-markup&quot;&gt;defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/sys/uvm/uvm_km.c&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;km_alloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kmem_va_mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kmem_pa_mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kmem_dyn_mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pglist&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pgl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapflags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vm_prot_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;paddr_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pla_align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pla_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pla_maxseg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;vaddr_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;va&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sva&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;KASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;round_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;TAILQ_INIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_nomem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_pageable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc_va&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;pla_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd_waitok&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_PLA_WAITOK&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_PLA_NOWAIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pla_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_PLA_TRYCONTIG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_zero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;pla_flags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_PLA_ZERO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;pla_align&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef __HAVE_PMAP_DIRECT
&lt;/span&gt;	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pla_align&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;pla_align&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;pla_maxseg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_maxseg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pla_maxseg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;pla_maxseg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_pglistalloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_constraint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ucr_low&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_constraint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ucr_high&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pla_align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_boundary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	    &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pla_maxseg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pla_flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;	
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#ifdef __HAVE_PMAP_DIRECT
&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/*
	 * Only use direct mappings for single page or single segment
	 * allocations.
	 */&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_singlepage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_maxseg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;TAILQ_FOREACH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pageq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;va&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pmap_map_direct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TAILQ_FIRST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;sva&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;va&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sva&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;alloc_va:&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROT_READ&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROT_WRITE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_pageable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;KASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;KASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_singlepage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;KASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_singlepage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;KASSERT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#ifdef __HAVE_PMAP_DIRECT
&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;panic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;km_alloc: DIRECT single page&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#else
&lt;/span&gt;		&lt;span class=&quot;n&quot;&gt;mtx_enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd_waitok&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;mtx_leave&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;uvm_pglistfree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
				&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;msleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			    &lt;span class=&quot;s&quot;&gt;&quot;getpage&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;va&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lowat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
		    &lt;span class=&quot;n&quot;&gt;curproc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;km_proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd_slowdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd_slowdown&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;wakeup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;km_proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;mtx_leave&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_km_pages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#endif
&lt;/span&gt;	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uvm_object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uobj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd_trylock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;mapflags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_KMF_TRYLOCK&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;uobj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;try_map:&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;va&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vm_map_min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uvm_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;va&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd_prefer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		    &lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UVM_MAPFLAG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_INHERIT_NONE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		    &lt;span class=&quot;n&quot;&gt;MADV_RANDOM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapflags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kv_wait&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kd_waitok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;n&quot;&gt;tsleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PVM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;km_allocva&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
				&lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;try_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;uvm_pglistfree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;sva&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;va&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;TAILQ_FOREACH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pgl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pageq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kp_pageable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;pmap_enter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pmap_kernel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;va&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VM_PAGE_TO_PHYS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
			    &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PMAP_WIRED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;pmap_kenter_pa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;va&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VM_PAGE_TO_PHYS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;va&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;pmap_update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pmap_kernel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sva&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Whew.  That’s a lot to unravel, so I’ll leave it here for now.&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;p&gt;For the section on FreeBSD, I referred to &lt;a href=&quot;http://www.amazon.com/Design-Implementation-FreeBSD-Operating-Edition/dp/0321968972&quot;&gt;“The Design and Implementation of FreeBSD.”&lt;/a&gt;  For the section on NetBSD and OpenBSD, I referred to Charles Cranor’s dissertation &lt;a href=&quot;http://chuck.cranor.org/p/diss.pdf&quot;&gt;“Design and Implementation of the UVM Virtual Memory System.”&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;attribution&quot;&gt;Attribution&lt;/h1&gt;

&lt;p&gt;The diagram for UVM’s data structures comes from &lt;a href=&quot;http://usenix.org/legacy/publications/library/proceedings/usenix99/full_papers/cranor/cranor_html/index.html&quot;&gt;Charles Craynor’s paper at Usenix in 1999&lt;/a&gt;, of which there is also &lt;a href=&quot;https://www.usenix.org/event/usenix99/full_papers/cranor/cranor.pdf&quot;&gt;a PDF version&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 02 Feb 2016 00:00:00 +0000</pubDate>
        <link>http://blog.pr4tt.com/2016/02/02/BSD-virtual-memory/</link>
        <guid isPermaLink="true">http://blog.pr4tt.com/2016/02/02/BSD-virtual-memory/</guid>
      </item>
    
      <item>
        <title>POSIX Memory Management</title>
        <description>&lt;p&gt;As an application programmer using a unix-flavored operating system, one’s view of memory management is usually limited to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; and its various alternative forms.  However, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; is part of the C standard library and while it is specified as part of &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/9699919799/&quot;&gt;POSIX.1&lt;/a&gt;, the specification defers to the ISO C standard.  In fact, since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; is part of the C standard library it is not a part of the kernel and can’t allocate memory directly.  For that, we need to use kernel functions.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/7908799/&quot;&gt;POSIX.1-1998&lt;/a&gt; specifies both &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/7908799/xsh/brk.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/007908799/xsh/mmap.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt;&lt;/a&gt; for allocating memory.  But &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt; was &lt;a href=&quot;http://stackoverflow.com/questions/6988487/what-does-brk-system-call-do&quot;&gt;allegedly removed in POSIX.1-2001&lt;/a&gt;, and certainly we can see it no longer exists in &lt;a href=&quot;http://pubs.opengroup.org/cgi/kman2.cgi?value=sbrk&quot;&gt;the version of POSIX.1-2004 still available online&lt;/a&gt;.  To understand what they do and why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt; was probably removed, we need to understand how a program’s code and data are laid out in memory.&lt;/p&gt;

&lt;h1 id=&quot;memory-layout&quot;&gt;Memory Layout&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Typical_computer_data_memory_arrangement.png/161px-Typical_computer_data_memory_arrangement.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Modern operating systems implement virtual memory, which gives each application the illusion that each has access to all (or most) of the machine’s physical memory.  In reality, the kernel maps virtual memory locations to physical ones and, with help from the CPU, translates virtual to physical addresses on the fly.  Since we ostensibly have the entire address space in which to arrange our code and data, this gives us a lot of flexibility.&lt;/p&gt;

&lt;p&gt;The diagram on the right shows a pretty typical way to arrange the code and data for a program.  Starting at the bottom (which has the lowest memory address), we have the text region.  This is where a prorgam’s code would be stored.  Above that is the &lt;a href=&quot;https://en.wikipedia.org/wiki/.bss&quot;&gt;BSS (Block Started by Symbol) region&lt;/a&gt; and above that is the initialized data region, which are where static variables (uninitialized and initialized, respectively) are stored.  Above that, we have the heap, free memory, and the stack.&lt;/p&gt;

&lt;p&gt;Any standard C course will explain the difference between the stack and the heap.  The stack contains variables like function arguments and variables defined locally within a function.  These variables are automatically pushed onto the stack when a function is called, and are popped off the stack when the function returns a value.  In order to keep a variable around for longer than the life of a function call, we need to allocate on the heap.&lt;/p&gt;

&lt;p&gt;Keep in mind that this memory layout is only the typical case.  An OS that implements the POSIX.1 specification may not lay out memory in the same way.&lt;/p&gt;

&lt;h1 id=&quot;sbrk&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt;&lt;/h1&gt;

&lt;p&gt;The &lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/7908799/xsh/brk.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brk&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt; kernel functions&lt;/a&gt; move the boundary between the heap and free memory, effectively increasing the size of the heap and allocating more memory for a program.  In particular, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brk&lt;/code&gt; takes a memory address and sets that as the new “break” (the byte past the last heap-allocated memory), whereas &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt; more usefully takes a number of bytes and increases the size of the heap by that many bytes.  We can effectively decrease the size of the heap by giving &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt; a negative value.&lt;/p&gt;

&lt;p&gt;We could get away with only using this function if we treated the heap as another stack.  In other words, if we always deallocated in the reverse order as we allocated memory, then we could easily just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, it’s much more useful as an application programmer to be able to allocate and deallocate from the heap in any order.  For this reason, when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; is implemented using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt;, it usually allocates more space than it needs and uses something like a linked-list to keep track of unused memory locations.&lt;/p&gt;

&lt;p&gt;A naive implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; might assume that no programmer would both use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; and call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt; directly, so the specification warns that the behavior of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt; is unspecified if an application also uses any other functions (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Notice that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt; makes this strong assumption that the heap is a contiguous area of memory with a single boundary which can grow or shrink to allocate more or less memory to a process.  This, and that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt; doesn’t play well with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt;, are probably why it was removed from the POSIX.1 standard.  That said, most unix-flavored OSes typically still implement it.  Thankfully, we have a nice alternative: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ASIDE: For more on implementing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt;, there’s &lt;a href=&quot;https://stackoverflow.com/questions/13159564/explain-this-implementation-of-malloc-from-the-kr-book/13159565#13159565&quot;&gt;a great code review cleaning up the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; implementation from K&amp;amp;R&lt;/a&gt; which uses a function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;morecore&lt;/code&gt; which seems to be analagous to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbrk&lt;/code&gt;.  There’s also &lt;a href=&quot;http://jamesgolick.com/2013/5/15/memory-allocators-101.html&quot;&gt;a high-level view of how malloc works&lt;/a&gt;, as well as &lt;a href=&quot;http://danluu.com/malloc-tutorial/&quot;&gt;a tutorial on implementing a simple version of malloc&lt;/a&gt; based on &lt;a href=&quot;http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf&quot;&gt;a tutorial on implmeneting a complex version of malloc&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;mmap&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt;&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;http://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt; is specified in the latest version of the POSIX.1 specification.&lt;/a&gt; Its brief description is “The mmap() function shall establish a mapping between an address space of a process and a memory object.” Immediately, we can see that this doesn’t make any assumptions about how a program is laid out in memory.  Although at first glance, it may seem that this function is more about mapping something like I/O into the address space of a process.&lt;/p&gt;

&lt;p&gt;The function prototype for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt; is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The specification also goes on to state that if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addr&lt;/code&gt; is 0, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FLAG_FIXED&lt;/code&gt; is not set, then the implementation is free to find unused memory into which to map.  Also, most operating systems have an additional flag &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAP_ANON&lt;/code&gt; which effectively just allocates the desired memory in the same way that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; would, without making any assumptions about memory layout.  To illustrate this, we can implement a very rudimentary version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;malloc&lt;/code&gt; using only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mmap&lt;/code&gt; (and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;munmap&lt;/code&gt; to implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free&lt;/code&gt;).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;sys/mman.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mymalloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;// addr&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// len&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;PROT_READ&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROT_WRITE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// prot&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;MAP_ANON&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAP_PRIVATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// flags&lt;/span&gt;
                    &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;// filedes&lt;/span&gt;
                    &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;// off&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;myfree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;munmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// addr&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;// len&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Allocating first integer...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heap_integer_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mymalloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Allocating char...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heap_char_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mymalloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Allocating second integer...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heap_integer_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mymalloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Writing to char...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_char_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'o'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Writing to first integer...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_integer_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1111&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Writing to second integer...&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_integer_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2222&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Reading from allocated integers...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;First allocated integer:  %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_integer_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Heap allocated char:      %c&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_char_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Second allocated integer: %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_integer_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Deallocating second integer...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;myfree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_integer_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Deallocating char...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;myfree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_char_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;puts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Deallocating first integer...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;myfree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_integer_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can &lt;a href=&quot;http://codepad.org/NTnpRMCz&quot;&gt;run this code online at codepad&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;attribution&quot;&gt;Attribution&lt;/h1&gt;

&lt;p&gt;The memory arrangement diagram is by Majenko (Own work) &lt;a href=&quot;http://creativecommons.org/licenses/by-sa/4.0&quot;&gt;CC BY-SA 4.0&lt;/a&gt;, via Wikimedia Commons.  It appears on &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_segment&quot;&gt;the Wikipedia page for the data segment&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Mon, 01 Feb 2016 00:00:00 +0000</pubDate>
        <link>http://blog.pr4tt.com/2016/02/01/posix-memory-management/</link>
        <guid isPermaLink="true">http://blog.pr4tt.com/2016/02/01/posix-memory-management/</guid>
      </item>
    
      <item>
        <title>Possession, Ownership, and Copyright</title>
        <description>&lt;p&gt;Possession is the natural state of actually physically having some item. An item can only either be in your possession or not. Maybe there’s some ambiguity if several people are holding the same item, but we can say that everyone holds the item possesses it. The idea of possession comes naturally from being able to carry and use things.&lt;/p&gt;

&lt;p&gt;From the state of possession comes the natural rights to take and leave. If an item exists, taking it is the action of moving from a state of not possessing that item to the opposite. Similarly, leaving an item is the opposite action.&lt;/p&gt;

&lt;p&gt;With that understood, let’s consider the concept of ownership. If an item is not owned by anyone else (or if the owner permits), I can claim ownership of that item. Ownership supersedes the right of others to take that item without my granting them license to do so.&lt;/p&gt;

&lt;p&gt;Items that are owned are said to be property. Such property can be privately owned by a single individual, collectively owned by several individuals, or publicly owned by some public entity like a government.&lt;/p&gt;

&lt;p&gt;Ownership is an old concept. &lt;a href=&quot;http://plato.stanford.edu/entries/property/&quot;&gt;Plato argued that collective ownership was necessary to promote common pursuit of the common interest, while Aristotle said “when everyone has a distinct interest, men will not complain of one another, and they will make more progress, because every one will be attending to his own business.”&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Interestingly, Aristotle defined freedom as the extent to which one owns one’s self. In other words, your ability to control yourself determines your level of freedom. If you have absolute self control, you are absolutely free. Otherwise you are to some extent a natural slave to your desires.&lt;/p&gt;

&lt;p&gt;Hume argued that there is no natural “mine” or “thine”, and that ownership must be understood as the creation of a sovereign state or the artificial product of a convention “enter’d into by all the members of the society to bestow stability on the possession of…external goods, and leave every one in the peaceable enjoyment of what he may acquire by his fortune and industry.”&lt;/p&gt;

&lt;p&gt;Locke argued that ownership arises naturally since we naturally own ourselves and from this follows ownership of other items by our own labour, but this seems to confuse the concepts of possession and ownership. We naturally possess ourselves, but do we naturally own ourselves? As defined above, ownership is a protection from the rights of others to take items that are not in our possession. How can we cease to possess ourselves that ownership might prevent others from exercising their right to take? The idea is nonsensical.&lt;/p&gt;

&lt;p&gt;While not arising naturally, ownership of any kind is useful. It would be impractical to require that in order to assure your continued ability to possess an item, you must keep others from possessing it at all times. A collective agreement that you own an item means you can spend your time productively instead.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://plato.stanford.edu/entries/intellectual-property/&quot;&gt;Intellectual property dates back at least to the Ancient Greeks&lt;/a&gt;, but it is clear that it isn’t the same as regular property since as with self-ownership, it isn’t obvious that we can ever cease to possess an idea. If I tell someone an idea of mine, we both possess the idea. There is no scarcity of ideas.&lt;/p&gt;

&lt;p&gt;The protection of intellectual property by ancient societies was not codified in law, but by franchises or royal favours. Bugbee makes the distinction that these cases were works that were in the public domain being removed from the publi by some authority, as opposed to a creator depriving the public of something that did not previously exist.&lt;/p&gt;

&lt;p&gt;One of the first codified protections was by the Republic of Florence in 1421, wherein &lt;a href=&quot;http://en.wikipedia.org/wiki/History_of_patent_law#Italy&quot;&gt;an architect was granted certain rights to an his invention of a barge with hoisting gear for carrying marble&lt;/a&gt;. This precedent was useful at least in that it incentivized creation of new works. This became known as the Florentine patent statute. Specifically, the statute protected the architects right to build the barge, not the idea itself.&lt;/p&gt;

&lt;p&gt;Literary works were unprotected until the Gutenberg printing press was invented in 1450, and even then few copyrights were granted.&lt;/p&gt;

&lt;p&gt;The English Statute of Monopolies (1624) and the Statute of Anne (1710) extended this idea by ending the practice of patenting unoriginal ideas and works which were already in the public domain. The Statute of Anne is considered to be the first codification of copyrights, in which authors were granted the control of the copying of their work for a fixed period with the explicit intent to incentivize writing. The statute specifically mentions the common practice of copying and reprinting works by printers.&lt;/p&gt;

&lt;p&gt;The Statute of Anne shifted the protection from the ability to create an object based on an original idea to the protection of the idea itself. The protection was from physical books being created from the same intellectual material, but the underlying notion was that the creators deserved to be rewarded for their creation. International copyright law has since been expanded by the Berne convention and the TRIPS agreement, but the same notion applies.&lt;/p&gt;

&lt;p&gt;One fundamental question that must be asked is to what extent do creators have the right to be rewarded? Unquestionably, the creation of novel ideas benefits us all, but each protection we give creators is a right that we are taking from users.&lt;/p&gt;

&lt;p&gt;For example, the recently passed Canadian Copyright Modernization Act &lt;a href=&quot;http://www.parl.gc.ca/HousePublications/Publication.aspx?Language=E&amp;amp;Mode=1&amp;amp;DocId=5697419&amp;amp;File=4&quot;&gt;Bill C-11&lt;/a&gt; extends many user rights to copyrighted work, but all of these rights are trumped by a digital lock on the work. &lt;a href=&quot;http://www.mondaq.com/canada/x/186120/Copyright/Canadas+Copyright+Modernization+Act+Receives+Royal+Assent&quot;&gt;Additionally, it is now illegal to break digital locks for any purpose, and it is illegal to distribute tools which might break digital locks.&lt;/a&gt; Is it really within the purview of protecting creators’ rights to be rewarded to remove the right to distribute creations not in any way related to the creator’s work?&lt;/p&gt;

&lt;p&gt;In answering the question of rewarding creators, we must also answer the question: how much does copying of a work hurt a creator? Cory Doctrow argues that excessive copyright hurts creators. &lt;a href=&quot;https://www.eff.org/deeplinks/2009/04/doctorows-law&quot;&gt;One of Doctrow’s main points is that digital locks send the message that if you buy a work then it may be taken away at any time, but if you steal it you can keep it forever.&lt;/a&gt; In this sense, Doctrow is saying that digital locks prevent ownership of a copy of the work.&lt;/p&gt;

&lt;p&gt;Doctrow’s eponymous law states “anytime someone puts a lock on something you own, against your wishes, and doesn’t give you the key, they’re not doing it for your benefit.”&lt;/p&gt;
</description>
        <pubDate>Sun, 12 May 2013 00:00:00 +0000</pubDate>
        <link>http://blog.pr4tt.com/2013/05/12/possession-ownership-and-copyright/</link>
        <guid isPermaLink="true">http://blog.pr4tt.com/2013/05/12/possession-ownership-and-copyright/</guid>
      </item>
    
      <item>
        <title>Readability</title>
        <description>&lt;p&gt;If you’re reading this in a maximized browser on a wide-screen monitor, you may wonder why the margins are so big. The answer isn’t that this page is optimized for small displays. In fact, I asked the same question of LaTeX margins and I found &lt;a href=&quot;http://tex.stackexchange.com/questions/71172/why-are-default-latex-margins-so-big&quot;&gt;an excellent answer on the LaTeX stackexchange&lt;/a&gt; that points out that the problem isn’t large margins, but large paper with respect to optimal line length.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.webtypography.net/&quot;&gt;The Elements of Typographic Style Applied to the Web&lt;/a&gt; states that &lt;a href=&quot;http://www.webtypography.net/Rhythm_and_Proportion/Horizontal_Motion/2.1.2/&quot;&gt;line lengths are optimally between 45 and 75 characters including spaces&lt;/a&gt;. &lt;a href=&quot;http://en.wikipedia.org/wiki/Emil_Ruder&quot;&gt;Emil Ruder&lt;/a&gt; suggests 50-60 characters in his book, &lt;a href=&quot;http://www.goodreads.com/book/show/67269.Typographie_&quot;&gt;Typographie&lt;/a&gt;. Emil goes on to say that &lt;a href=&quot;http://baymard.com/blog/line-length-readability&quot;&gt;readers are energized when their eyes move from the end of one line to the beginning of the next&lt;/a&gt;, as long as it doesn’t happen too frequently, and that this energy diminishes over the length of the line.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://webstyleguide.com/&quot;&gt;The Web Style Guide&lt;/a&gt; claims that &lt;a href=&quot;http://webstyleguide.com/wsg3/7-page-design/6-page-width-line-length.html&quot;&gt;research that reading slows as line lengths exceed the maximum width of about 12 words&lt;/a&gt;. With a space between each word and assuming 4 letters per word on average, this converts to about 12*4+11=59 characters per line.&lt;/p&gt;

&lt;p&gt;You can use &lt;a href=&quot;http://www.gbsheli.com/2009/04/wc-word-count-and-char-count.html&quot;&gt;this bookmarklet&lt;/a&gt; to check the number of characters on a line in your browser. As of this writing, line lengths on this blog tend to be around 71 characters.&lt;/p&gt;

&lt;p&gt;I would also like to take this opportunity to recommend &lt;a href=&quot;http://www.readability.com/&quot;&gt;Readability&lt;/a&gt; which converts any web page to a more readable version, and whose novel theme inspired the design of this blog.&lt;/p&gt;
</description>
        <pubDate>Sun, 07 Apr 2013 00:00:00 +0000</pubDate>
        <link>http://blog.pr4tt.com/2013/04/07/readability/</link>
        <guid isPermaLink="true">http://blog.pr4tt.com/2013/04/07/readability/</guid>
      </item>
    
  </channel>
</rss>
