1import{_ as n,c as a,e,o as p}from"./app-CjUkjRdW.js";const l={};function i(t,s){return p(),a("div",null,s[0]||(s[0]=[e(`<h1 id="physical-memory" tabindex="-1"><a class="header-anchor" href="#physical-memory"><span>Physical Memory</span></a></h1><p>Managing physical memory involves being able to allocate and free physical page frames. We'll create a <strong>Physical Memory Manager</strong> (PMM) that will keep track of which physical pages are free and which are in use. There are many ways to implement a PMM, the most popular being a bitmap, a free list, and a free stack. I'll keep it simple and implement a free list.</p><h2 id="free-list" tabindex="-1"><a class="header-anchor" href="#free-list"><span>Free List</span></a></h2><p>The free list will be a linked list of free memory regions. We will store the address of the list head in a global variable. Each node will be stored at the beginning of a free region, and will contain the region size in terms of frames, and a <code>next</code> pointer to the next node in the list. This way we don't have to allocate memory for the list itself ( except for the list head pointer), since we will use the free regions themselves to store the list nodes. Here's what it might look like after a few allocations and frees:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line"> 0 Physical Memory max</span> 2<span class="line"> ââââ¬âââââââââââââ¬âââââââââââââ¬âââ¬âââââââ¬âââââââââââââââââââââââââââââââ¬âââ¬ââââââââââ¬âââââââââââââââ</span> 3<span class="line">size â4 â ââââââââââââââ2 â ââââââââââââââââââââââââââââââââ3 â ââââââââââââââââ</span> 4<span class="line"> â â Free ââââââââââââââ â Free ââââââââââââââââââââââââââââââââ â Free ââââââââââââââââ</span> 5<span class="line">next âââ⤠ââââââââââââââââ⤠ââââââââââââââââââââââââââââââââââ⤠ââââââââââââââââ</span> 6<span class="line"> ââ²â¬â´âââââââââââââ´âââââââââââââ´â²â¬â´âââââââ´âââââââââââââââââââââââââââââââ´â²â¬â´ââââââââââ´âââââââââââââââ</span> 7<span class="line"> ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ</span> 8<span class="line">head ââ âââ¶ nil</span> 9<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Allocating a page frame will involve finding a free region that is large enough, splitting it if necessary, and returning the starting address of the allocated region. Freeing a region will involve finding the correct place in the list to insert the region, and merging it with adjacent regions if necessary.</p><p>Let's start by creating a new module <code>src/kernel/pmm.nim</code> and defining the following types:</p><ul><li><code>PhysAddr</code> to represent a physical address</li><li><code>PMNode</code> to represent a node in the free list</li><li><code>PMRegion</code>
9 to represent a region of memory</li></ul><p>and the following variables:</p><ul><li><code>head</code> to store the address of the list head</li><li><code>maxPhysAddr</code> to store the maximum physical address (exclusive)</li><li><code>reservedRegions</code> to store a list of reserved regions</li></ul><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/pmm.nim</span></span> 10<span class="line"></span> 11<span class="line"><span class="token keyword">const</span></span> 12<span class="line"> FrameSize <span class="token operator">=</span> <span class="token number">4096</span></span> 13<span class="line"></span> 14<span class="line"><span class="token keyword">type</span></span> 15<span class="line"> PhysAddr <span class="token operator">=</span> <span class="token keyword">distinct</span> uint64</span> 16<span class="line"></span> 17<span class="line"> PMNode <span class="token operator">=</span> <span class="token keyword">object</span></span> 18<span class="line"> nframes<span class="token operator">:</span> uint64</span> 19<span class="line"> next<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode</span> 20<span class="line"></span> 21<span class="line"> PMRegion<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span> 22<span class="line"> start<span class="token operator">*:</span> PhysAddr</span> 23<span class="line"> nframes<span class="token operator">*:</span> uint64</span> 24<span class="line"></span> 25<span class="line"><span class="token keyword">var</span></span> 26<span class="line"> head<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode</span> 27<span class="line"> maxPhysAddr<span class="token operator">:</span> PhysAddr <span class="token comment"># exclusive</span></span> 28<span class="line"> reservedRegions<span class="token operator">:</span> seq<span class="token punctuation">[</span>PMRegion<span class="token punctuation">]</span></span> 29<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We'll also define several utility procs:</p><ul><li><code>toPMNodePtr</code> to convert from <code>ptr PMNode</code> to <code>PhysAddr</code></li><li><code>toPhysAddr</code> to convert from <code>PhysAddr</code> to <code>ptr PMNode</code></li><li><code>==</code>, <code><</code>, and <code>-</code> operators for <code>PhysAddr</code></li><li><code>endAddr</code> to calculate the end address of a region given its start address and size</li><li><code>adjacent</code> to check if a node is adjacent to a physical address (and vice versa)</li><li><code>overlaps</code> to check if two regions overlap</li></ul><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/pmm.nim</span></span> 30<span class="line"></span> 31<span class="line"><span class="token keyword">proc</span> <span class="token function">toPMNodePtr<span class="token operator">*</span></span><span class="token punctuation">(</span>paddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token function">cast[ptr PMNode]</span><span class="token punctuation">(</span>paddr<span class="token punctuation">)</span></span> 32<span class="line"><span class="token keyword">proc</span> <span class="token function">toPhysAddr<span class="token operator">*</span></span><span class="token punctuation">(</span>node<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode<span class="token punctuation">)</span><span class="token operator">:</span> PhysAddr <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token function">cast[PhysAddr]</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span></span> 33<span class="line"></span> 34<span class="line"><span class="token keyword">proc</span> <span class="token function">\`==\`<span class="token operator">*</span></span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token operator">:</span> PhysAddr<span class="token punctuation">)</span><span class="token operator">:</span> bool <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span> a<span class="token operator">.</span>
34uint64 <span class="token operator">==</span> b<span class="token operator">.</span>uint64</span> 35<span class="line"><span class="token keyword">proc</span> <span class="token function">\`<\`</span><span class="token punctuation">(</span>p1<span class="token punctuation">,</span> p2<span class="token operator">:</span> PhysAddr<span class="token punctuation">)</span><span class="token operator">:</span> bool <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span> p1<span class="token operator">.</span>uint64 <span class="token operator"><</span> p2<span class="token operator">.</span>uint64</span> 36<span class="line"><span class="token keyword">proc</span> <span class="token function">\`-\`</span><span class="token punctuation">(</span>p1<span class="token punctuation">,</span> p2<span class="token operator">:</span> PhysAddr<span class="token punctuation">)</span><span class="token operator">:</span> uint64 <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span> p1<span class="token operator">.</span>uint64 <span class="token operator">-</span> p2<span class="token operator">.</span>uint64</span> 37<span class="line"></span> 38<span class="line"><span class="token keyword">proc</span> <span class="token function">endAddr</span><span class="token punctuation">(</span>paddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">,</span> nframes<span class="token operator">:</span> uint64<span class="token punctuation">)</span><span class="token operator">:</span> PhysAddr <span class="token operator">=</span></span> 39<span class="line"> result <span class="token operator">=</span> paddr <span class="token operator">+!</span> nframes <span class="token operator">*</span> FrameSize</span> 40<span class="line"></span> 41<span class="line"><span class="token keyword">proc</span> <span class="token function">adjacent</span><span class="token punctuation">(</span>node<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode<span class="token punctuation">,</span> paddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">)</span><span class="token operator">:</span> bool <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 42<span class="line"> result <span class="token operator">=</span> <span class="token punctuation">(</span></span> 43<span class="line"> <span class="token operator">not</span> node<span class="token operator">.</span>isNil <span class="token operator">and</span></span> 44<span class="line"> node<span class="token operator">.</span>toPhysAddr <span class="token operator">+!</span> node<span class="token operator">.</span>nframes <span class="token operator">*</span> FrameSize <span class="token operator">==</span> paddr</span> 45<span class="line"> <span class="token punctuation">)</span></span> 46<span class="line"></span> 47<span class="line"><span class="token keyword">proc</span> <span class="token function">adjacent</span><span class="token punctuation">(</span>paddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">,</span> nframes<span class="token operator">:</span> uint64<span class="token punctuation">,</span> node<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode<span class="token punctuation">)</span><span class="token operator">:</span> bool <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 48<span class="line"> result <span class="token operator">=</span> <span class="token punctuation">(</span></span> 49<span class="line"> <span class="token operator">not</span> node<span class="token operator">.</span>isNil <span class="token operator">and</span></span> 50<span class="line"> paddr <span class="token operator">+!</span> nframes <span class="token operator">*</span> FrameSize <span class="token operator">==</span> node<span class="token operator">.</span>toPhysAddr</span> 51<span class="line"> <span class="token punctuation">)</span></span> 52<span class="line"></span> 53<span class="line"><span class="token keyword">proc</span> <span class="token function">overlaps</span><span class="token punctuation">(</span>region1<span class="token punctuation">,</span>
53 region2<span class="token operator">:</span> PMRegion<span class="token punctuation">)</span><span class="token operator">:</span> bool <span class="token operator">=</span></span> 54<span class="line"> <span class="token keyword">var</span> r1 <span class="token operator">=</span> region1</span> 55<span class="line"> <span class="token keyword">var</span> r2 <span class="token operator">=</span> region2</span> 56<span class="line"> <span class="token keyword">if</span> r1<span class="token operator">.</span>start <span class="token operator">></span> r2<span class="token operator">.</span>start<span class="token operator">:</span></span> 57<span class="line"> r1 <span class="token operator">=</span> region2</span> 58<span class="line"> r2 <span class="token operator">=</span> region1</span> 59<span class="line"> result <span class="token operator">=</span> <span class="token punctuation">(</span></span> 60<span class="line"> r1<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr <span class="token operator"><</span> <span class="token function">endAddr</span><span class="token punctuation">(</span>r2<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> r2<span class="token operator">.</span>nframes<span class="token punctuation">)</span> <span class="token operator">and</span></span> 61<span class="line"> r2<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr <span class="token operator"><</span> <span class="token function">endAddr</span><span class="token punctuation">(</span>r1<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> r1<span class="token operator">.</span>nframes<span class="token punctuation">)</span></span> 62<span class="line"> <span class="token punctuation">)</span></span> 63<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Also, since we're going to do a lot of pointer arithmetic, let's define a <code>+!</code> operator for both <code>PhysAddr</code> and <code>ptr PMNode</code> that will allow us to add an offset to a physical address or a node pointer.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/pmm.nim</span></span> 64<span class="line"></span> 65<span class="line"><span class="token keyword">proc</span> <span class="token function">\`+!\`<span class="token operator">*</span></span><span class="token punctuation">(</span>paddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">,</span> offset<span class="token operator">:</span> uint64<span class="token punctuation">)</span><span class="token operator">:</span> PhysAddr <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 66<span class="line"> <span class="token function">PhysAddr</span><span class="token punctuation">(</span><span class="token function">cast[uint64]</span><span class="token punctuation">(</span>paddr<span class="token punctuation">)</span> <span class="token operator">+</span> offset<span class="token punctuation">)</span></span> 67<span class="line"></span> 68<span class="line"><span class="token keyword">proc</span> <span class="token function">\`+!\`<span class="token operator">*</span></span><span class="token punctuation">(</span>node<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode<span class="token punctuation">,</span> offset<span class="token operator">:</span>
68 uint64<span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span></span> 69<span class="line"> <span class="token function">cast[ptr PMNode]</span><span class="token punctuation">(</span><span class="token function">cast[uint64]</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span> <span class="token operator">+</span> offset<span class="token punctuation">)</span></span> 70<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="initialization" tabindex="-1"><a class="header-anchor" href="#initialization"><span>Initialization</span></a></h2><p>The kernel already has the memory map passed to it by the bootloader, so we'll use that to initialize the PMM.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token keyword">import</span> common<span class="token operator">/</span>bootinfo</span> 71<span class="line"><span class="token operator">...</span></span> 72<span class="line"></span> 73<span class="line"><span class="token keyword">proc</span> <span class="token function">pmInit<span class="token operator">*</span></span><span class="token punctuation">(</span>memoryMap<span class="token operator">:</span> MemoryMap<span class="token punctuation">)</span> <span class="token operator">=</span></span> 74<span class="line"> <span class="token keyword">var</span> prev<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode</span> 75<span class="line"></span> 76<span class="line"> <span class="token keyword">for</span> i <span class="token operator">in</span> <span class="token number">0</span> <span class="token operator">..<</span> memoryMap<span class="token operator">.</span>len<span class="token operator">:</span></span> 77<span class="line"> <span class="token keyword">let</span> entry <span class="token operator">=</span> memoryMap<span class="token operator">.</span>entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span> 78<span class="line"> <span class="token keyword">if</span> entry<span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">==</span> MemoryType<span class="token operator">.</span>Free<span class="token operator">:</span></span> 79<span class="line"> maxPhysAddr <span class="token operator">=</span> <span class="token function">endAddr</span><span class="token punctuation">(</span>entry<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> entry<span class="token operator">.</span>nframes<span class="token punctuation">)</span></span> 80<span class="line"> <span class="token keyword">if</span> <span class="token operator">not</span> prev<span class="token operator">.</span>isNil <span class="token operator">and</span> <span class="token function">adjacent</span><span class="token punctuation">(</span>prev<span class="token punctuation">,</span> entry<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr<span class="token punctuation">)</span><span class="token operator">:</span></span> 81<span class="line"> <span class="token comment"># merge contiguous regions</span></span> 82<span class="line"> prev<span class="token operator">.</span>nframes <span class="token operator">+=</span> entry<span class="token operator">.</span>nframes</span> 83<span class="line"> <span class="token keyword">else</span><span class="token operator">:</span></span> 84<span class="line">
84 <span class="token comment"># create a new node</span></span> 85<span class="line"> <span class="token keyword">var</span> node<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode <span class="token operator">=</span> entry<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr<span class="token operator">.</span>toPMNodePtr</span> 86<span class="line"> node<span class="token operator">.</span>nframes <span class="token operator">=</span> entry<span class="token operator">.</span>nframes</span> 87<span class="line"> node<span class="token operator">.</span>next <span class="token operator">=</span> <span class="token keyword">nil</span></span> 88<span class="line"></span> 89<span class="line"> <span class="token keyword">if</span> <span class="token operator">not</span> prev<span class="token operator">.</span>isNil<span class="token operator">:</span></span> 90<span class="line"> prev<span class="token operator">.</span>next <span class="token operator">=</span> node</span> 91<span class="line"> <span class="token keyword">else</span><span class="token operator">:</span></span> 92<span class="line"> head <span class="token operator">=</span> node</span> 93<span class="line"></span> 94<span class="line"> prev <span class="token operator">=</span> node</span> 95<span class="line"></span> 96<span class="line"> <span class="token keyword">elif</span> entry<span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">==</span> MemoryType<span class="token operator">.</span>Reserved<span class="token operator">:</span></span> 97<span class="line"> reservedRegions<span class="token operator">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token function">PMRegion</span><span class="token punctuation">(</span>start<span class="token operator">:</span> entry<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> nframes<span class="token operator">:</span> entry<span class="token operator">.</span>nframes<span class="token punctuation">)</span><span class="token punctuation">)</span></span> 98<span class="line"> </span> 99<span class="line"> <span class="token keyword">elif</span> i <span class="token operator">></span> <span class="token number">0</span><span class="token operator">:</span></span> 100<span class="line"> <span class="token comment"># check if there's a gap between the previous entry and the current entry</span></span> 101<span class="line"> <span class="token keyword">let</span> prevEntry <span class="token operator">=</span> memoryMap<span class="token operator">.</span>entries<span class="token punctuation">[</span>i <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span></span> 102<span class="line"> <span class="token keyword">let</span> gap <span class="token operator">=</span> entry<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr <span class="token operator">-</span> <span class="token function">endAddr</span><span class="token punctuation">(</span>prevEntry<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> prevEntry<span class="token operator">.</span>nframes<span class="token punctuation">)</span></span> 103<span class="line"> <span class="token keyword">if</span> gap <span class="token operator">></span> <span class="token number">0</span><span class="token operator">:</span></span> 104<span class="line"> reservedRegions<span class="token operator">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token function">PMRegion</span><span class="token punctuation">(</span></span> 105<span class="line"> start<span class="token operator">:</span> <span class="token function">endAddr</span><span class="token punctuation">(</span>prevEntry<span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> prevEntry<span class="token operator">.</span>nframes<span class="token punctuation">)</span><span class="token punctuation">,</span></span> 106<span class="line"> nframes<span class="token operator">:</span> gap <span class="token operator">div</span> FrameSize</span> 107<span class="line">
107 <span class="token punctuation">)</span><span class="token punctuation">)</span></span> 108<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The initialization procedure iterates over the memory map entries, and for each free region it either merges it with the previous region if they are contiguous, or creates a new node and adds it to the list. We also track a couple of things that will be useful for validating requests to free regions:</p><ul><li>Reserved regions, either from the memory map or from gaps between memory map entries.</li><li>The maximum physical address, which is the end address of the last free region.</li></ul><p>To try it out and see if it works, we'll need a way to iterate over the list to print the nodes. Let's add an iterator for that.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/pmm.nim</span></span> 109<span class="line"></span> 110<span class="line"><span class="token keyword">iterator</span> <span class="token function">pmFreeRegions<span class="token operator">*</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">tuple</span><span class="token punctuation">[</span>paddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">,</span> nframes<span class="token operator">:</span> uint64<span class="token punctuation">]</span> <span class="token operator">=</span></span> 111<span class="line"> <span class="token keyword">var</span> node <span class="token operator">=</span> head</span> 112<span class="line"> <span class="token keyword">while</span> <span class="token operator">not</span> node<span class="token operator">.</span>isNil<span class="token operator">:</span></span> 113<span class="line"> <span class="token function">yield</span> <span class="token punctuation">(</span>node<span class="token operator">.</span>toPhysAddr<span class="token punctuation">,</span> node<span class="token operator">.</span>nframes<span class="token punctuation">)</span></span> 114<span class="line"> node <span class="token operator">=</span> node<span class="token operator">.</span>next</span> 115<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Let's now initialize the PMM and print the free regions.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/main.nim</span></span> 116<span class="line"></span> 117<span class="line"><span class="token keyword">
117import</span> pmm</span> 118<span class="line"><span class="token operator">...</span></span> 119<span class="line"></span> 120<span class="line"><span class="token keyword">proc</span> <span class="token function">printFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span></span> 121<span class="line"> debugln <span class="token string">"kernel: Physical memory free regions "</span></span> 122<span class="line"> debug <span class="token operator">&</span><span class="token string">""" {"Start":>16}"""</span></span> 123<span class="line"> debug <span class="token operator">&</span><span class="token string">""" {"Start (KB)":>12}"""</span></span> 124<span class="line"> debug <span class="token operator">&</span><span class="token string">""" {"Size (KB)":>11}"""</span></span> 125<span class="line"> debug <span class="token operator">&</span><span class="token string">""" {"#Pages":>9}"""</span></span> 126<span class="line"> debugln <span class="token string">""</span></span> 127<span class="line"> <span class="token keyword">var</span> totalFreePages<span class="token operator">:</span> uint64 <span class="token operator">=</span> <span class="token number">0</span></span> 128<span class="line"> <span class="token function">for</span> <span class="token punctuation">(</span>start<span class="token punctuation">,</span> nframes<span class="token punctuation">)</span> <span class="token operator">in</span> <span class="token function">pmFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span></span> 129<span class="line"> debug <span class="token operator">&</span><span class="token string">" {cast[uint64](start):>#16x}"</span></span> 130<span class="line"> debug <span class="token operator">&</span><span class="token string">" {cast[uint64](start) div 1024:>#12}"</span></span> 131<span class="line"> debug <span class="token operator">&</span><span class="token string">" {nframes * 4:>#11}"</span></span> 132<span class="line"> debug <span class="token operator">&</span><span class="token string">" {nframes:>#9}"</span></span> 133<span class="line"> debugln <span class="token string">""</span></span> 134<span class="line"> totalFreePages <span class="token operator">+=</span> nframes</span> 135<span class="line"> debugln <span class="token operator">&</span><span class="token string">"kernel: Total free: {totalFreePages * 4} KiB ({totalFreePages * 4 div 1024} MiB)"</span></span> 136<span class="line"></span> 137<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMainInner</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token operator">=</span></span> 138<span class="line"> debugln <span class="token string">""</span></span> 139<span class="line"> debugln <span class="token string">"kernel: Fusion Kernel"</span></span> 140<span class="line"></span> 141<span class="line"> debug <span class="token string">"kernel: Initializing physical memory manager "</span></span> 142<span class="line"> <span class="token function">pmInit</span><span class="token punctuation">(</span>bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token punctuation">)</span></span> 143<span class="line"> debugln <span class="token string">"[success]"</span></span> 144<span class="line"></span> 145<span class="line"> <span class="token function">printFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 146<span class="line"></span> 147<span class="line"> <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 148<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If we run the kernel now, we should see something like this:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Fusion Kernel</span> 149<span class="line">kernel: Initializing physical memory manager [success]</span> 150<span class="line">kernel: Physical memory free regions </span> 151<span class="line"> Start Start (KB) Size (KB) #Pages</span> 152<span class="line"> 0x0 0 640 160</span> 153<span class="line"> 0x21a000 2152 6040 1510</span> 154<span class="line"> 0x808000 8224 12 3</span> 155<span class="line"> 0x80c000 8240 16 4</span> 156<span class="line"> 0x900000 9216 92596 23149</span> 157<span class="line"> 0x6372000 101832 17900 4475</span> 158<span class="line"> 0x77ff000 122876 7124 1781</span> 159<span class="line">kernel: Total free: 124328 KiB (121 MiB)</span> 160<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The list is much shorter than the original memory map, since we merged contiguous regions. Our PMM is now initialized and ready to be used.<
160/p><h2 id="allocating-frames" tabindex="-1"><a class="header-anchor" href="#allocating-frames"><span>Allocating Frames</span></a></h2><p>A memory manager is not very useful if we can't allocate and free memory. Let's start with adding a <code>pmAlloc</code> to allocate a contiguous region of physical memory.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/pmm.nim</span></span> 161<span class="line"></span> 162<span class="line"><span class="token keyword">import</span> std<span class="token operator">/</span>options</span> 163<span class="line"><span class="token operator">...</span></span> 164<span class="line"></span> 165<span class="line"><span class="token keyword">proc</span> <span class="token function">pmAlloc<span class="token operator">*</span></span><span class="token punctuation">(</span>nframes<span class="token operator">:</span> uint64<span class="token punctuation">)</span><span class="token operator">:</span> Option<span class="token punctuation">[</span>PhysAddr<span class="token punctuation">]</span> <span class="token operator">=</span></span> 166<span class="line"> <span class="token comment">## Allocate a contiguous region of physical memory.</span></span> 167<span class="line"> assert nframes <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">"Number of frames must be positive"</span></span> 168<span class="line"></span> 169<span class="line"> <span class="token keyword">var</span></span> 170<span class="line"> prev<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode</span> 171<span class="line"> curr <span class="token operator">=</span> head</span> 172<span class="line"></span> 173<span class="line"> <span class="token comment"># find a region with enough frames</span></span> 174<span class="line"> <span class="token keyword">while</span> <span class="token operator">not</span> curr<span class="token operator">.</span>isNil <span class="token operator">and</span> curr<span class="token operator">.</span>nframes <span class="token operator"><</span> nframes<span class="token operator">:</span></span> 175<span class="line"> prev <span class="token operator">=</span> curr</span> 176<span class="line"> curr <span class="token operator">=</span> curr<span class="token operator">.</span>next</span> 177<span class="line"> </span> 178<span class="line"> <span class="token keyword">if</span> curr<span class="token operator">.</span>isNil<span class="token operator">:</span></span> 179<span class="line"> <span class="token comment"># no region found</span></span> 180<span class="line"> <span class="token keyword">return</span> <span class="token function">none</span><span class="token punctuation">(</span>PhysAddr<span class="token punctuation">)</span></span> 181<span class="line"> </span> 182<span class="line"> <span class="token keyword">var</span> newnode<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode</span> 183<span class="line"> <span class="token keyword">if</span> curr<span class="token operator">.</span>nframes <span class="token operator">==</span> nframes<span class="token operator">:</span></span> 184<span class="line"> <span class="token comment"># exact match</span></span> 185<span class="line"> newnode <span class="token operator">=</span> curr<span class="token operator">.</span>next</span> 186<span class="line"> <span class="token keyword">else</span><span class="token operator">:</span></span> 187<span class="line"> <span class="token comment"># split the region</span></span> 188<span class="line"> newnode <span class="token operator">=</span> <span class="token function">toPMNodePtr</span><span class="token punctuation">(</span>curr<span class="token operator">.</span>toPhysAddr <span class="token operator">+!</span> nframes <span class="token operator">*</span> FrameSize<span class="token punctuation">)</span></span> 189<span class="line"> newnode<span class="token operator">.</span>nframes <span class="token operator">=</span> curr<span class="token operator">.</span>nframes <span class="token operator">-</span> nframes</span> 190<span class="line"> newnode<span class="token operator">.</span>next <span class="token operator">=</span> curr<span class="token operator">.</span>next</span> 191<span class="line"></span> 192<span class="line"> <span class="token keyword">if</span> <span class="token operator">not</span> prev<span class="token operator">.</span>isNil<span class="token operator">:</span></span> 193<span class="line"> prev<span class="token operator">.</span>next <span class="token operator">=</span> newnode</span> 194<span class="line"> <span class="token keyword">else</span><span class="token operator">:</span></span> 195<span class="line"> head <span class="token operator">=</span> newnode</span> 196<span class="line"></span> 197<span class="line"> result <span class="token operator">=</span> <span class="token function">
197some</span><span class="token punctuation">(</span>curr<span class="token operator">.</span>toPhysAddr<span class="token punctuation">)</span></span> 198<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The procedure iterates over the list until it finds a region with enough frames, and then either splits the region if it's larger than necessary, or removes it from the list if it's an exact match. If there's no region large enough, it returns <code>none</code>. Let's try it out by allocating a few pages and printing the free regions.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/main.nim</span></span> 199<span class="line"></span> 200<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMainInner</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token operator">=</span></span> 201<span class="line"> <span class="token operator">...</span></span> 202<span class="line"></span> 203<span class="line"> debugln <span class="token string">"kernel: Allocating 4 pages"</span></span> 204<span class="line"> <span class="token keyword">let</span> paddr <span class="token operator">=</span> <span class="token function">pmAlloc</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span></span> 205<span class="line"> <span class="token keyword">if</span> paddr<span class="token operator">.</span>isSome<span class="token operator">:</span></span> 206<span class="line"> debugln <span class="token operator">&</span><span class="token string">"kernel: Allocated at {paddr.get.uint64:#010x}"</span></span> 207<span class="line"> <span class="token function">printFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 208<span class="line"> <span class="token keyword">else</span><span class="token operator">:</span></span> 209<span class="line"> debugln <span class="token string">"kernel: Allocation failed"</span></span> 210<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Let's run the kernel and see what happens.</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Fusion Kernel</span> 211<span class="line">kernel: Initializing physical memory manager [success]</span> 212<span class="line">kernel: Physical memory free regions </span> 213<span class="line"> Start Start (KB) Size (KB) #Pages</span> 214<span class="line"> 0x0 0 640 160</span> 215<span class="line"> 0x21b000 2156 6036 1509</span> 216<span class="line"> 0x808000 8224 12 3</span> 217<span class="line"> 0x80c000 8240 16 4</span> 218<span class="line"> 0x900000 9216 92596 23149</span> 219<span class="line"> 0x6372000 101832 17900 4475</span> 220<span class="line"> 0x77ff000 122876 7124 1781</span> 221<span class="line">kernel: Total free: 124324 KiB (121 MiB)</span> 222<span class="line">kernel: Allocating 4 pages</span> 223<span class="line">kernel: Allocated at 0x00000000</span> 224<span class="line">kernel: Physical memory free regions </span> 225<span class="line"> Start Start (KB) Size (KB) #Pages</span> 226<span class="line"> 0x4000 16 624 156</span> 227<span class="line"> 0x21b000 2156 6036 1509</span> 228<span class="line"> 0x808000 8224 12 3</span> 229<span class="line"> 0x80c000 8240 16 4</span> 230<span class="line"> 0x900000 9216 92596 23149</span> 231<span class="line"> 0x6372000 101832 17900 4475</span> 232<span class="line"> 0x77ff000 122876 7124 1781</span> 233<span class="line">kernel: Total free: 124308 KiB (121 MiB)</span> 234<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>It looks like it worked. We can see that the first 4 pages are now allocated, and the free regions list is updated accordingly. Let's see what happens if we try to allocate more pages than available in the first free region.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"> <span class="token keyword">let</span> paddr <span class="token operator">=</span> <span class="token function">pmAlloc</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span></span> 235<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div></div></div><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Fusion Kernel</span> 236<span class="line">kernel: Initializing physical memory manager [success]</span> 237<span class="line">kernel: Physical memory free regions </span> 238<span class="line"> Start Start (KB) Size (KB) #Pages</span> 239<span class="line"> 0x0 0 640 160</span> 240<span class="line"> 0x21b000 2156 6036 1509</span> 241<span class="line"> 0x808000 8224 12 3</span> 242<span class="line"> 0x80c000 8240 16 4</span> 243<span class="line"> 0x900000 9216 92596 23149</span> 244<span class="line"> 0x6372000 101832 17900 4475</span> 245<span class="line"> 0x77ff000 122876 7124 1781</span> 246<span class="line">kernel: Total free: 124324 KiB (121 MiB)</span> 247<span class="line">kernel: Allocating 200 pages</span> 248<span class="line">kernel: Allocated at 0x0021b000</span> 249<span class="line">kernel: Physical memory free regions </span> 250<span class="line"> Start Start (KB) Size (KB) #Pages</span> 251<span class="line"> 0x0 0 640 160</span> 252<span class="line"> 0x2e3000 2956 5236 1309</span> 253<span class="line"> 0x808000 8224 12 3</span> 254<span class="line"> 0x80c000 8240 16 4</span> 255<span class="line"> 0x900000 9216 92596 23149</span> 256<span class="line"> 0x6372000 101832 17900 4475</span> 257<span class="line"> 0x77ff000 122876 7124 1781</span> 258<span class="line">kernel: Total free: 123524 KiB (120 MiB)</span> 259<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The first region is skipped because it'
259s not large enough, and the second region is used to allocate the pages, and its start address is updated and its size is reduced. Let's see what happens if we allocate exactly the number of pages in the first region (160 pages).</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"> <span class="token keyword">let</span> paddr <span class="token operator">=</span> <span class="token function">pmAlloc</span><span class="token punctuation">(</span><span class="token number">160</span><span class="token punctuation">)</span></span> 260<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div></div></div><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Fusion Kernel</span> 261<span class="line">kernel: Initializing physical memory manager [success]</span> 262<span class="line">kernel: Physical memory free regions </span> 263<span class="line"> Start Start (KB) Size (KB) #Pages</span> 264<span class="line"> 0x0 0 640 160</span> 265<span class="line"> 0x21b000 2156 6036 1509</span> 266<span class="line"> 0x808000 8224 12 3</span> 267<span class="line"> 0x80c000 8240 16 4</span> 268<span class="line"> 0x900000 9216 92596 23149</span> 269<span class="line"> 0x6372000 101832 17900 4475</span> 270<span class="line"> 0x77ff000 122876 7124 1781</span> 271<span class="line">kernel: Total free: 124324 KiB (121 MiB)</span> 272<span class="line">kernel: Allocating 160 pages</span> 273<span class="line">kernel: Allocated at 0x00000000</span> 274<span class="line">kernel: Physical memory free regions </span> 275<span class="line"> Start Start (KB) Size (KB) #Pages</span> 276<span class="line"> 0x21b000 2156 6036 1509</span> 277<span class="line"> 0x808000 8224 12 3</span> 278<span class="line"> 0x80c000 8240 16 4</span> 279<span class="line"> 0x900000 9216 92596 23149</span> 280<span class="line"> 0x6372000 101832 17900 4475</span> 281<span class="line"> 0x77ff000 122876 7124 1781</span> 282<span class="line">kernel: Total free: 123684 KiB (120 MiB)</span> 283<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The first region is now completely used, so it's removed from the list. Finally, let's see what happens if we try to allocate more pages than available in any free region.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"> <span class="token keyword">let</span> paddr <span class="token operator">=</span> <span class="token function">pmAlloc</span><span class="token punctuation">(</span><span class="token number">25000</span><span class="token punctuation">)</span></span> 284<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div></div></div><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Fusion Kernel</span> 285<span class="line">kernel: Initializing physical memory manager [success]</span> 286<span class="line">kernel: Physical memory free regions </span> 287<span class="line"> Start Start (KB) Size (KB) #Pages</span> 288<span class="line"> 0x0 0 640 160</span> 289<span class="line"> 0x21b000 2156 6036 1509</span> 290<span class="line"> 0x808000 8224 12 3</span> 291<span class="line"> 0x80c000 8240 16 4</span> 292<span class="line"> 0x900000 9216 92596 23149</span> 293<span class="line"> 0x6372000 101832 17900 4475</span> 294<span class="line"> 0x77ff000 122876 7124 1781</span> 295<span class="line">kernel: Total free: 124324 KiB (121 MiB)</span> 296<span class="line">kernel: Allocating 25000 pages</span> 297<span class="line">kernel: Allocation failed</span> 298<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The allocation fails because there are no regions large enough to satisfy the request.</p><h2 id="freeing-frames" tabindex="-1"><a class="header-anchor" href="#freeing-frames"><span>Freeing Frames</span></a></h2><p>
298Freeing a region is a lot more challenging than allocating one, because we need to:</p><ul><li>validate the request to make sure the region is: <ul><li>aligned to a page frame</li><li>within the physical memory range</li><li>not overlapping with any reserved regions</li><li>not overlapping with other free regions</li></ul></li><li>find the correct place in the free list to insert the region</li><li>if it's adjacent to other free regions, merge it with them</li><li>handle edge cases when the region is before or after all other regions</li></ul><p>Who said that writing an OS is easy? Let's go ahead and implement <code>pmFree</code>.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/pmm.nim</span></span> 299<span class="line"></span> 300<span class="line"><span class="token keyword">proc</span> <span class="token function">pmFree<span class="token operator">*</span></span><span class="token punctuation">(</span>paddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">,</span> nframes<span class="token operator">:</span> uint64<span class="token punctuation">)</span> <span class="token operator">=</span></span> 301<span class="line"> <span class="token comment">## Free a contiguous region of physical memory.</span></span> 302<span class="line"> assert paddr<span class="token operator">.</span>uint64 <span class="token operator">mod</span> FrameSize <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token operator">&</span><span class="token string">"Unaligned physical address: {paddr.uint64:#x}"</span></span> 303<span class="line"> assert nframes <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">"Number of frames must be positive"</span></span> 304<span class="line"></span> 305<span class="line"> <span class="token keyword">if</span> paddr <span class="token operator">+!</span> nframes <span class="token operator">*</span> FrameSize <span class="token operator">></span> maxPhysAddr<span class="token operator">:</span></span> 306<span class="line"> <span class="token comment"># the region is outside of the physical memory</span></span> 307<span class="line"> <span class="token keyword">raise</span> <span class="token function">newException</span><span class="token punctuation">(</span></span> 308<span class="line"> Exception<span class="token punctuation">,</span></span> 309<span class="line"> <span class="token operator">&</span><span class="token string">"Attempt to free a region outside of the physical memory.\\n"</span> <span class="token operator">&</span></span> 310<span class="line"> <span class="token operator">&</span><span class="token string">" Request: start={paddr.uint64:#x} + nframes={nframes} > max={maxPhysAddr.uint64:#x}"</span></span> 311<span class="line"> <span class="token punctuation">)</span></span> 312<span class="line"> </span> 313<span class="line"> <span class="token keyword">for</span> region <span class="token operator">in</span> reservedRegions<span class="token operator">:</span></span> 314<span class="line"> <span class="token keyword">if</span> <span class="token function">overlaps</span><span class="token punctuation">(</span>region<span class="token punctuation">,</span> <span class="token function">PMRegion</span><span class="token punctuation">(</span>start<span class="token operator">:</span> paddr<span class="token punctuation">,</span> nframes<span class="token operator">:</span> nframes<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">:</span></span> 315<span class="line"> <span class="token comment"># the region is reserved</span></span> 316<span class="line"> <span class="token keyword">raise</span> <span class="token function">newException</span><span class="token punctuation">(</span></span> 317<span class="line"> Exception<span class="token punctuation">,</span></span> 318<span class="line">
318 <span class="token operator">&</span><span class="token string">"Attempt to free a reserved region.\\n"</span> <span class="token operator">&</span></span> 319<span class="line"> <span class="token operator">&</span><span class="token string">" Request: start={paddr.uint64:#x}, nframes={nframes}\\n"</span> <span class="token operator">&</span></span> 320<span class="line"> <span class="token operator">&</span><span class="token string">" Reserved: start={region.start.uint64:#x}, nframes={region.nframes}"</span></span> 321<span class="line"> <span class="token punctuation">)</span></span> 322<span class="line"></span> 323<span class="line"> <span class="token keyword">var</span></span> 324<span class="line"> prev<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode</span> 325<span class="line"> curr <span class="token operator">=</span> head</span> 326<span class="line"></span> 327<span class="line"> <span class="token keyword">while</span> <span class="token operator">not</span> curr<span class="token operator">.</span>isNil <span class="token operator">and</span> curr<span class="token operator">.</span>toPhysAddr <span class="token operator"><</span> paddr<span class="token operator">:</span></span> 328<span class="line"> prev <span class="token operator">=</span> curr</span> 329<span class="line"> curr <span class="token operator">=</span> curr<span class="token operator">.</span>next</span> 330<span class="line"></span> 331<span class="line"> <span class="token keyword">let</span></span> 332<span class="line"> overlapsWithCurr <span class="token operator">=</span> <span class="token operator">not</span> curr<span class="token operator">.</span>isNil <span class="token operator">and</span> paddr <span class="token operator">+!</span> nframes <span class="token operator">*</span> FrameSize <span class="token operator">></span> curr<span class="token operator">.</span>toPhysAddr</span> 333<span class="line"> overlapsWithPrev <span class="token operator">=</span> <span class="token operator">not</span> prev<span class="token operator">.</span>isNil <span class="token operator">and</span> paddr <span class="token operator"><</span> prev<span class="token operator">.</span>toPhysAddr <span class="token operator">+!</span> prev<span class="token operator">.</span>nframes <span class="token operator">*</span> FrameSize</span> 334<span class="line"></span> 335<span class="line"> <span class="token keyword">if</span> overlapsWithCurr <span class="token operator">or</span> overlapsWithPrev<span class="token operator">:</span></span> 336<span class="line"> <span class="token keyword">raise</span> <span class="token function">newException</span><span class="token punctuation">(</span></span> 337<span class="line"> Exception<span class="token punctuation">,</span></span> 338<span class="line"> <span class="token operator">&</span><span class="token string">"Attempt to free a region that overlaps with another free region.\\n"</span> <span class="token operator">&</span></span> 339<span class="line"> <span class="token operator">&</span><span class="token string">" Request: start={paddr.uint64:#x}, nframes={nframes}"</span></span> 340<span class="line"> <span class="token punctuation">)</span></span> 341<span class="line"></span> 342<span class="line"> <span class="token comment"># the region to be freed is between prev and curr (either of them can be nil)</span></span> 343<span class="line"></span> 344<span class="line"> <span class="token keyword">if</span> prev<span class="token operator">.</span>isNil <span class="token operator">and</span> curr<span class="token operator">.</span>isNil<span class="token operator">:</span></span> 345<span class="line"> debugln <span class="token string">"pmFree: the list is empty"</span></span> 346<span class="line"> <span class="token comment"># the list is empty</span></span> 347<span class="line"> <span class="token keyword">var</span> newnode <span class="token operator">=</span> paddr<span class="token operator">.</span>
347toPMNodePtr</span> 348<span class="line"> newnode<span class="token operator">.</span>nframes <span class="token operator">=</span> nframes</span> 349<span class="line"> newnode<span class="token operator">.</span>next <span class="token operator">=</span> <span class="token keyword">nil</span></span> 350<span class="line"> head <span class="token operator">=</span> newnode</span> 351<span class="line"></span> 352<span class="line"> <span class="token keyword">elif</span> prev<span class="token operator">.</span>isNil <span class="token operator">and</span> <span class="token function">adjacent</span><span class="token punctuation">(</span>paddr<span class="token punctuation">,</span> nframes<span class="token punctuation">,</span> curr<span class="token punctuation">)</span><span class="token operator">:</span></span> 353<span class="line"> debugln <span class="token string">"pmFree: at the beginning, adjacent to curr"</span></span> 354<span class="line"> <span class="token comment"># at the beginning, adjacent to curr</span></span> 355<span class="line"> <span class="token keyword">var</span> newnode <span class="token operator">=</span> paddr<span class="token operator">.</span>toPMNodePtr</span> 356<span class="line"> newnode<span class="token operator">.</span>nframes <span class="token operator">=</span> nframes <span class="token operator">+</span> curr<span class="token operator">.</span>nframes</span> 357<span class="line"> newnode<span class="token operator">.</span>next <span class="token operator">=</span> curr<span class="token operator">.</span>next</span> 358<span class="line"> head <span class="token operator">=</span> newnode</span> 359<span class="line"></span> 360<span class="line"> <span class="token keyword">elif</span> curr<span class="token operator">.</span>isNil <span class="token operator">and</span> <span class="token function">adjacent</span><span class="token punctuation">(</span>prev<span class="token punctuation">,</span> paddr<span class="token punctuation">)</span><span class="token operator">:</span></span> 361<span class="line"> debugln <span class="token string">"pmFree: at the end, adjacent to prev"</span></span> 362<span class="line"> <span class="token comment"># at the end, adjacent to prev</span></span> 363<span class="line"> prev<span class="token operator">.</span>nframes <span class="token operator">+=</span> nframes</span> 364<span class="line"></span> 365<span class="line"> <span class="token keyword">elif</span> <span class="token function">adjacent</span><span class="token punctuation">(</span>prev<span class="token punctuation">,</span> paddr<span class="token punctuation">)</span> <span class="token operator">and</span> <span class="token function">adjacent</span><span class="token punctuation">(</span>paddr<span class="token punctuation">,</span> nframes<span class="token punctuation">,</span> curr<span class="token punctuation">)</span><span class="token operator">:</span></span> 366<span class="line"> debugln <span class="token string">"pmFree: exactly between prev and curr"</span></span> 367<span class="line"> <span class="token comment"># exactly between prev and curr</span></span> 368<span class="line"> prev<span class="token operator">.</span>nframes <span class="token operator">+=</span> nframes <span class="token operator">+</span> curr<span class="token operator">.</span>nframes</span> 369<span class="line"> prev<span class="token operator">.</span>next <span class="token operator">=</span> curr<span class="token operator">.</span>next</span> 370<span class="line"></span> 371<span class="line"> <span class="token keyword">else</span><span class="token operator">:</span></span> 372<span class="line"> <span class="token comment"># not adjacent to any other region</span></span> 373<span class="line"> debugln <span class="token string">"pmFree: not adjacent to any other region"</span></span> 374<span class="line"> <span class="token keyword">var</span> newnode <span class="token operator">=</span> paddr<span class="token operator">.</span>
374toPMNodePtr</span> 375<span class="line"> newnode<span class="token operator">.</span>nframes <span class="token operator">=</span> nframes</span> 376<span class="line"> newnode<span class="token operator">.</span>next <span class="token operator">=</span> curr</span> 377<span class="line"> <span class="token keyword">if</span> <span class="token operator">not</span> prev<span class="token operator">.</span>isNil<span class="token operator">:</span></span> 378<span class="line"> prev<span class="token operator">.</span>next <span class="token operator">=</span> newnode</span> 379<span class="line"> <span class="token keyword">else</span><span class="token operator">:</span></span> 380<span class="line"> head <span class="token operator">=</span> newnode</span> 381<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Let's try it out by allocating and freeing some regions.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/main.nim</span></span> 382<span class="line"></span> 383<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMainInner</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token operator">=</span></span> 384<span class="line"> <span class="token operator">...</span></span> 385<span class="line"></span> 386<span class="line"> <span class="token function">printFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 387<span class="line"></span> 388<span class="line"> debugln <span class="token string">"kernel: Allocating 8 frames"</span></span> 389<span class="line"> <span class="token keyword">let</span> paddr <span class="token operator">=</span> <span class="token function">pmAlloc</span><span class="token punctuation">(</span><span class="token number">8</span><span class="token punctuation">)</span></span> 390<span class="line"> <span class="token keyword">if</span> paddr<span class="token operator">.</span>isNone<span class="token operator">:</span></span> 391<span class="line"> debugln <span class="token string">"kernel: Allocation failed"</span></span> 392<span class="line"> <span class="token function">printFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 393<span class="line"></span> 394<span class="line"> debugln <span class="token operator">&</span><span class="token string">"kernel: Freeing 2 frames at 0x2000"</span></span> 395<span class="line"> <span class="token function">pmFree</span><span class="token punctuation">(</span><span class="token number">0x2000</span><span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span></span> 396<span class="line"> <span class="token function">printFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 397<span class="line"></span> 398<span class="line"> debugln <span class="token operator">&</span><span class="token string">"kernel: Freeing 4 frames at 0x4000"</span></span> 399<span class="line"> <span class="token function">pmFree</span><span class="token punctuation">(</span><span class="token number">0x4000</span><span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span></span> 400<span class="line"> <span class="token function">printFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 401<span class="line"></span> 402<span class="line"> debugln <span class="token operator">&</span><span class="token string">"kernel: Freeing 2 frames at 0xa0000"</span></span> 403<span class="line"> <span class="token function">pmFree</span><span class="token punctuation">(</span><span class="token number">0xa0000</span><span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span></span> 404<span class="line"> <span class="token function">printFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span> 405<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If we run the kernel now, we should see something like this:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Initializing physical memory manager [success]</span> 406<span class="line">kernel: Physical memory free regions</span> 407<span class="line"> Start Start (KB) Size (KB) #Pages</span> 408<span class="line"> 0x0 0 640 160</span> 409<span class="line"> 0x223000 2188 6004 1501</span> 410<span class="line"> 0x808000 8224 12 3</span> 411<span class="line"> 0x80c000 8240 16 4</span> 412<span class="line"> 0x900000 9216 92596 23149</span> 413<span class="line"> 0x6372000 101832 17900 4475</span> 414<span class="line"> 0x77ff000 122876 7124 1781</span> 415<span class="line">kernel: Total free: 124292 KiB (121 MiB)</span> 416<span class="line">kernel: Allocating 8 frames</span> 417<span class="line">kernel: Physical memory free regions</span> 418<span class="line"> Start Start (KB) Size (KB) #Pages</span> 419<span class="line"> 0x8000 32 608 152</span> 420<span class="line"> 0x223000 2188 6004 1501</span> 421<span class="line"> 0x808000 8224 12 3</span> 422<span class="line"> 0x80c000 8240 16 4</span> 423<span class="line"> 0x900000 9216 92596 23149</span> 424<span class="line"> 0x6372000 101832 17900 4475</span> 425<span class="line"> 0x77ff000 122876 7124 1781</span> 426<span class="line">kernel: Total free: 124260 KiB (121 MiB)</span> 427<span class="line">kernel: Freeing 2 frames at 0x2000</span> 428<span class="line">pmFree: not adjacent to any other region</span> 429<span class="line">kernel: Physical memory free regions</span> 430<span class="line"> Start Start (KB) Size (KB) #Pages</span> 431<span class="line"> 0x2000 8 8 2</span> 432<span class="line"> 0x8000 32 608 152</span> 433<span class="line"> 0x223000 2188 6004 1501</span> 434<span class="line"> 0x808000 8224 12 3</span> 435<span class="line"> 0x80c000 8240 16 4</span> 436<span class="line"> 0x900000 9216 92596 23149</span> 437<span class="line"> 0x6372000 101832 17900 4475</span> 438<span class="line"> 0x77ff000 122876 7124 1781</span> 439<span class="line">kernel: Total free: 124268 KiB (121 MiB)</span> 440<span class="line">kernel: Freeing 4 frames at 0x4000</span> 441<span class="line">pmFree: exactly between prev and curr</span> 442<span class="line">kernel: Physical memory free regions</span> 443<span class="line"> Start Start (KB) Size (KB) #Pages</span> 444<span class="line"> 0x2000 8 632 158</span> 445<span class="line"> 0x223000 2188 6004 1501</span> 446<span class="line"> 0x808000 8224 12 3</span> 447<span class="line"> 0x80c000 8240 16 4</span> 448<span class="line"> 0x900000 9216 92596 23149</span> 449<span class="line"> 0x6372000 101832 17900 4475</span> 450<span class="line"> 0x77ff000 122876 7124 1781</span> 451<span class="line">kernel: Total free: 124284 KiB (121 MiB)</span> 452<span class="line">kernel: Freeing 2 frames at 0xa0000</span> 453<span class="line"></span> 454<span class="line">
454Unhandled exception: Attempt to free a reserved region.</span> 455<span class="line"> Request: start=0xa0000, nframes=2</span> 456<span class="line"> Reserved: start=0xa0000, nframes=96 [Exception]</span> 457<span class="line"></span> 458<span class="line">Stack trace:</span> 459<span class="line">/Users/khaledhammouda/src/github.com/khaledh/fusion/src/kernel/main.nim(46) KernelMain</span> 460<span class="line">/Users/khaledhammouda/src/github.com/khaledh/fusion/src/kernel/main.nim(85) KernelMainInner</span> 461<span class="line">/Users/khaledhammouda/src/github.com/khaledh/fusion/src/kernel/pmm.nim(164) pmFree</span> 462<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>First we allocate 8 frames (starting at 0x0000), then we free 2 frames at 0x2000, and finally we free 4 frames at 0x4000. The request to free the region at 0x2000 is not adjacent to any other free region, so it's inserted in the list. The second region being freed at 0x4000 is now exactly between the first free region (ending at 0x4000) and the second free region (starting at 0x8000), so it's merged with them.</p><p>In the last free request, we try to free 2 frames at 0xa0000, which is a reserved region, so an exception is raised, which is exactly what we want. I'm not going to show all possible scenarios here, but I tested them and they all work as expected.</p><p>Phew! That was a lot of work, but we now have a working PMM. In the next chapter, we'll start looking at virtual memory.</p>`,57)]))}const r=n(l,[["render",i],["__file","11-physical-memory.html.vue"]]),c=JSON.parse(`{"path":"/osdev/11-physical-memory.html","title":"Physical Memory","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Free List","slug":"free-list","link":"#free-list","children":[]},{"level":2,"title":"Initialization","slug":"initialization","link":"#initialization","children":[]},{"level":2,"title":"Allocating Frames","slug":"allocating-frames","link":"#allocating-frames","children":[]},{"level":2,"title":"Freeing Frames","slug":"freeing-frames","link":"#freeing-frames","children":[]}],"git":{"updatedTime":1744638230000},"filePathRelative":"osdev/11-physical-memory.md","excerpt":"\\n<p>Managing physical memory involves being able to allocate and free physical page frames.\\nWe'll create a <strong>Physical Memory Manager</strong> (PMM) that will keep track of which physical\\npages are free and which are in use. There are many ways to implement a PMM, the most\\npopular being a bitmap, a free list, and a free stack. I'll keep it simple and implement a\\nfree list.</p>"}`);export{r as comp,c as data};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.