PageSourceSearch

https://0xc0ffee.netlify.app/assets/13-higher-half-kernel.html-BSFc-GAk.js

js 0xc0ffee.netlify.app collected 2026-10-03 10:23:34 UTC 75,784 bytes, 351 lines download raw bytes

1import{_ as s,c as a,e,o as p}from"./app-CjUkjRdW.js";const t={};function l(o,n){return p(),a("div",null,n[0]||(n[0]=[e(`<h1 id="higher-half-kernel" tabindex="-1"><a class="header-anchor" href="#higher-half-kernel"><span>Higher Half Kernel</span></a></h1><p>The kernel is currently linked at address <code>0x100000</code>, not at the higher half of the address space. The UEFI environment does have paging enabled, but we need to build our own page tables, and map the kernel at the higher half of the address space. This needs to be done in the bootloader, before we jump to the kernel (since we&#39;ll change the kernel to be linked at the higher half). Once we&#39;re in the kernel, we can set up different page tables that fit our needs.</p><h2 id="linking-the-kernel" tabindex="-1"><a class="header-anchor" href="#linking-the-kernel"><span>Linking the kernel</span></a></h2><p>To link the kernel at the higher half of the address space, we need to change the base address of the kernel in the linker script. However, instead of linking the kernel at exactly <code>0xFFFF800000000000</code>, we&#39;ll link it at 1 MiB above that address, i.e. <code>0xFFFF800000100000</code>. This will make virtual addresses and physical addresses line up nicely, and we can compare them visually by just looking at the least significant bytes of the address, which makes debugging page table mappings easier.</p><div class="language-ld line-numbers-mode" data-highlighter="prismjs" data-ext="ld" data-title="ld"><pre><code><span class="line"><span class="token comment">/* src/kernel/kernel.ld */</span></span>
2<span class="line"></span>
3<span class="line">SECTIONS</span>
4<span class="line"><span class="token punctuation">{</span></span>
5<span class="line highlighted">  <span class="token location-counter important">.</span> <span class="token operator">=</span> <span class="token number">0xFFFF800000100000</span><span class="token punctuation">;</span></span>
6<span class="line">  <span class="token section keyword">.text</span>   <span class="token operator">:</span> <span class="token punctuation">{</span></span>
7<span class="line">    <span class="token operator">*</span>main<span class="token operator">*</span>.o<span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text.KernelMain<span class="token punctuation">)</span></span>
8<span class="line">    <span class="token operator">*</span>main<span class="token operator">*</span>.o<span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text.<span class="token operator">*</span><span class="token punctuation">)</span></span>
9<span class="line">    <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>text<span class="token operator">*</span><span class="token punctuation">)</span></span>
10<span class="line">  <span class="token punctuation">}</span></span>
11<span class="line">  <span class="token section keyword">.rodata</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>rodata<span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
12<span class="line">  <span class="token section keyword">.data</span>   <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>data<span class="token punctuation">)</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token location-counter important">.</span><span class="token operator">*</span>bss<span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
13<span class="line">  <span class="token section keyword">.shstrtab</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token section keyword">.shstrtab</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
14<span class="line"></span>
15<span class="line">  <span class="token operator">/</span>DISCARD<span class="token operator">/</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token operator">*</span><span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span> <span class="token punctuation">}</span></span>
16<span class="line"><span class="token punctuation">}</span></span>
17<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></div><p>If we try to compile and link the kernel, we&#39;ll get a bunch of relocation errors:</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash">just kernel</span></span></span>
18<span class="line"><span class="token output">ld.lld: error: .../fusion/build/@mmain.nim.c.o:(function KernelMainInner__main_u7: .text.KernelMainInner__main_u7+0x232): relocation R_X86_64_32S out of range: -140737488267184 is not in [-2147483648, 2147483647]; references section &#39;.rodata&#39;</span>
19<span class="line">&gt;&gt;&gt; referenced by @mmain.nim.c</span>
20<span class="line">...</span>
21<span class="line"></span></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></div><p>The problem here is that the compiler has something called a &quot;code model&quot;
21, which determines how it generates code. The default code model is <code>small</code>, which means that the compiler assumes that the code and data are linked in the lower 2 GiB of the address space. What we need here is the <code>large</code> code model, which assumes that the code and data are linked anywhere in the address space. We can specify the code model using the <code>-mcmodel</code> flag, so let&#39;s add it to the kernel&#39;s <code>nim.cfg</code> file.</p><div class="language-properties line-numbers-mode" data-highlighter="prismjs" data-ext="properties" data-title="properties"><pre><code><span class="line"><span class="token comment"># src/kernel/nim.cfg</span></span>
22<span class="line">...</span>
23<span class="line"><span class="token key attr-name">--passc</span><span class="token punctuation">:</span><span class="token value attr-value">&quot;-mcmodel=large&quot;</span></span>
24<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></div><p>Now the kernel should compile and link successfully. Let&#39;s take a quick look at the linker map.</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token command"><span class="token shell-symbol important">$</span> <span class="token bash language-bash"><span class="token function">head</span> <span class="token parameter variable">-n</span> <span class="token number">10</span> build/kernel.map</span></span></span>
25<span class="line"><span class="token output">             VMA              LMA     Size Align Out     In      Symbol</span>
26<span class="line">               0                0 ffff800000100000     1 . = 0xFFFF800000100000</span>
27<span class="line">ffff800000100000 ffff800000100000    2048c    16 .text</span>
28<span class="line">ffff800000100000 ffff800000100000      1ee    16         .../fusion/build/@mmain.nim.c.o:(.ltext.KernelMain)</span>
29<span class="line">ffff800000100000 ffff800000100000      1ee     1                 KernelMain</span>
30<span class="line">ffff8000001001f0 ffff8000001001f0     261f    16         .../fusion/build/@mmain.nim.c.o:(.ltext.KernelMainInner__main_u13)</span>
31<span class="line">ffff8000001001f0 ffff8000001001f0     261f     1                 KernelMainInner__main_u13</span>
32<span class="line">ffff800000102810 ffff800000102810       9b    16         .../fusion/build/@mmain.nim.c.o:(.ltext.nimFrame)</span>
33<span class="line">ffff800000102810 ffff800000102810       9b     1                 nimFrame</span>
34<span class="line">ffff8000001028b0 ffff8000001028b0       25    16         .../fusion/build/@mmain.nim.c.o:(.ltext.nimErrorFlag)</span>
35<span class="line"></span></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></div><p>Looks good. Before we start setting up paging, let&#39;s add a few utility procs to prepare the <code>BootInfo</code> structure with the physical memory map and the virtual memory map.</p><h2 id="preparing-bootinfo" tabindex="-1"><a class="header-anchor" href="#preparing-bootinfo"><span>Preparing BootInfo</span></a></h2><p>We need to pass a few things to the kernel, including:</p><ul><li>The physical memory map</li><li>The virtual memory map</li><li>The virtual address where physical memory is mapped</li></ul><p>We already have a <code>convertUefiMemoryMap</code> proc that converts the UEFI memory map to our own format. Let&#39;s add a proc to create a virtual memory map as well, which will contain the virtual address space regions that we&#39;ll map.</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/boot/bootx64.nim</span></span>
36<span class="line"><span class="token operator">...</span></span>
37<span class="line"></span>
38<span class="line"><span class="token keyword">const</span></span>
39<span class="line">  KernelPhysicalBase <span class="token operator">=</span> <span class="token number">0x10_0000&#39;u64</span></span>
40<span class="line">  KernelVirtualBase <span class="token operator">=</span> <span class="token number">0xFFFF_8000_0000_0000&#39;u64</span> <span class="token operator">+</span> KernelPhysicalBase</span>
41<span class="line"></span>
42<span class="line">  KernelStackVirtualBase <span class="token operator">=</span> <span class="token number">0xFFFF_8001_0000_0000&#39;u64</span> <span class="token comment"># KernelVirtualBase + 4 GiB</span></span>
43<span class="line">
43  KernelStackSize <span class="token operator">=</span> <span class="token number">16</span> <span class="token operator">*</span> <span class="token number">1024&#39;u64</span></span>
44<span class="line">  KernelStackPages <span class="token operator">=</span> KernelStackSize <span class="token operator">div</span> PageSize</span>
45<span class="line"></span>
46<span class="line">  BootInfoVirtualBase <span class="token operator">=</span> KernelStackVirtualBase <span class="token operator">+</span> KernelStackSize <span class="token comment"># after kernel stack</span></span>
47<span class="line"></span>
48<span class="line">  PhysicalMemoryVirtualBase <span class="token operator">=</span> <span class="token number">0xFFFF_8002_0000_0000&#39;u64</span> <span class="token comment"># KernelVirtualBase + 8 GiB</span></span>
49<span class="line"></span>
50<span class="line"><span class="token operator">...</span></span>
51<span class="line"></span>
52<span class="line"><span class="token keyword">proc</span> <span class="token function">createVirtualMemoryMap</span><span class="token punctuation">(</span></span>
53<span class="line">  kernelImagePages<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
54<span class="line">  physMemoryPages<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
55<span class="line"><span class="token punctuation">)</span><span class="token operator">:</span> seq<span class="token punctuation">[</span>MemoryMapEntry<span class="token punctuation">]</span> <span class="token operator">=</span></span>
56<span class="line"></span>
57<span class="line">  result<span class="token operator">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token function">MemoryMapEntry</span><span class="token punctuation">(</span></span>
58<span class="line">    <span class="token keyword">type</span><span class="token operator">:</span> KernelCode<span class="token punctuation">,</span></span>
59<span class="line">    start<span class="token operator">:</span> KernelVirtualBase<span class="token punctuation">,</span></span>
60<span class="line">    nframes<span class="token operator">:</span> kernelImagePages</span>
61<span class="line">  <span class="token punctuation">)</span><span class="token punctuation">)</span></span>
62<span class="line">  result<span class="token operator">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token function">MemoryMapEntry</span><span class="token punctuation">(</span></span>
63<span class="line">    <span class="token keyword">type</span><span class="token operator">:</span> KernelStack<span class="token punctuation">,</span></span>
64<span class="line">    start<span class="token operator">:</span> KernelStackVirtualBase<span class="token punctuation">,</span></span>
65<span class="line">    nframes<span class="token operator">:</span> KernelStackPages</span>
66<span class="line">  <span class="token punctuation">)</span><span class="token punctuation">)</span></span>
67<span class="line">  result<span class="token operator">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token function">MemoryMapEntry</span><span class="token punctuation">(</span></span>
68<span class="line">    <span class="token keyword">type</span><span class="token operator">:</span> KernelData<span class="token punctuation">,</span></span>
69<span class="line">    start<span class="token operator">:</span> BootInfoVirtualBase<span class="token punctuation">,</span></span>
70<span class="line">    nframes<span class="token operator">:</span> <span class="token number">1</span></span>
71<span class="line">  <span class="token punctuation">)</span><span class="token punctuation">)</span></span>
72<span class="line">  result<span class="token operator">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token function">MemoryMapEntry</span><span class="token punctuation">(</span></span>
73<span class="line">    <span class="token keyword">type</span><span class="token operator">:</span> KernelData<span class="token punctuation">,</span></span>
74<span class="line">    start<span class="token operator">:</span> PhysicalMemoryVirtualBase<span class="token punctuation">,</span></span>
75<span class="line">    nframes<span class="token operator">:</span> physMemoryPages</span>
76<span class="line">  <span class="token punctuation">)</span><span class="token punctuation">)</span></span>
77<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></div><p>Now, let&#39;s add a proc to prepare the <code>BootInfo</code> structure itself.</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/boot/bootx64.nim</span></span>
78<span class="line"><span class="token operator">...</span></span>
79<span class="line"></span>
80<span class="line"><span class="token keyword">proc</span> <span class="token function">createBootInfo</span><span class="token punctuation">(</span></span>
81<span class="line">  bootInfoBase<span class="token operator">:</span>
81 uint64<span class="token punctuation">,</span></span>
82<span class="line">  kernelImagePages<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
83<span class="line">  physMemoryPages<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
84<span class="line">  physMemoryMap<span class="token operator">:</span> seq<span class="token punctuation">[</span>MemoryMapEntry<span class="token punctuation">]</span><span class="token punctuation">,</span></span>
85<span class="line">  virtMemoryMap<span class="token operator">:</span> seq<span class="token punctuation">[</span>MemoryMapEntry<span class="token punctuation">]</span><span class="token punctuation">,</span></span>
86<span class="line"><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo <span class="token operator">=</span></span>
87<span class="line">  <span class="token keyword">var</span> bootInfo <span class="token operator">=</span> <span class="token function">cast[ptr BootInfo]</span><span class="token punctuation">(</span>bootInfoBase<span class="token punctuation">)</span></span>
88<span class="line">  bootInfo<span class="token operator">.</span>physicalMemoryVirtualBase <span class="token operator">=</span> PhysicalMemoryVirtualBase</span>
89<span class="line"></span>
90<span class="line">  <span class="token comment"># copy physical memory map entries to boot info</span></span>
91<span class="line">  bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token operator">.</span>len <span class="token operator">=</span> physMemoryMap<span class="token operator">.</span>len<span class="token operator">.</span>uint</span>
92<span class="line">  bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token operator">.</span>entries <span class="token operator">=</span></span>
93<span class="line">    <span class="token keyword">cast</span><span class="token punctuation">[</span><span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>MemoryMapEntry<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">(</span>bootInfoBase <span class="token operator">+</span> <span class="token function">sizeof</span><span class="token punctuation">(</span>BootInfo<span class="token punctuation">)</span><span class="token operator">.</span>uint64<span class="token punctuation">)</span></span>
94<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">..&lt;</span> physMemoryMap<span class="token operator">.</span>len<span class="token operator">:</span></span>
95<span class="line">    bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token operator">.</span>entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> physMemoryMap<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
96<span class="line">  <span class="token keyword">let</span> physMemoryMapSize <span class="token operator">=</span> physMemoryMap<span class="token operator">.</span>len<span class="token operator">.</span>uint64 <span class="token operator">*</span> <span class="token function">sizeof</span><span class="token punctuation">(</span>MemoryMapEntry<span class="token punctuation">)</span><span class="token operator">.</span>uint64</span>
97<span class="line"></span>
98<span class="line">  <span class="token comment"># copy virtual memory map entries to boot info</span></span>
99<span class="line">  bootInfo<span class="token operator">.</span>virtualMemoryMap<span class="token operator">.</span>len <span class="token operator">=</span> virtMemoryMap<span class="token operator">.</span>len<span class="token operator">.</span>uint</span>
100<span class="line">  bootInfo<span class="token operator">.</span>virtualMemoryMap<span class="token operator">.</span>entries <span class="token operator">=</span></span>
101<span class="line">    <span class="token keyword">cast</span><span class="token punctuation">[</span><span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>MemoryMapEntry<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">(</span>bootInfoBase <span class="token operator">+</span> <span class="token function">sizeof</span><span class="token punctuation">(</span>BootInfo<span class="token punctuation">)</span><span class="token operator">.</span>
101uint64 <span class="token operator">+</span> physMemoryMapSize<span class="token punctuation">)</span></span>
102<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">..&lt;</span> virtMemoryMap<span class="token operator">.</span>len<span class="token operator">:</span></span>
103<span class="line">    bootInfo<span class="token operator">.</span>virtualMemoryMap<span class="token operator">.</span>entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> virtMemoryMap<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
104<span class="line">  </span>
105<span class="line">  result <span class="token operator">=</span> bootInfo</span>
106<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></div><p>Finally, we&#39;ll call these procs from <code>EfiMainInner</code>. We&#39;ll also get the <code>maxPhysAddr</code> (which is the highest usable physical address) and use it to calculate the number of physical memory 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 comment"># src/boot/bootx64.nim</span></span>
107<span class="line"><span class="token operator">...</span></span>
108<span class="line"></span>
109<span class="line"><span class="token keyword">proc</span> <span class="token function">EfiMainInner</span><span class="token punctuation">(</span>imgHandle<span class="token operator">:</span> EfiHandle<span class="token punctuation">,</span> sysTable<span class="token operator">:</span> <span class="token keyword">ptr</span> EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span>
110<span class="line">  <span class="token operator">...</span></span>
111<span class="line"></span>
112<span class="line">  <span class="token comment"># ======= NO MORE UEFI BOOT SERVICES =======</span></span>
113<span class="line"></span>
114<span class="line">  <span class="token keyword">let</span> physMemoryMap <span class="token operator">=</span> <span class="token function">convertUefiMemoryMap</span><span class="token punctuation">(</span>memoryMap<span class="token punctuation">,</span> memoryMapSize<span class="token punctuation">,</span> memoryMapDescriptorSize<span class="token punctuation">)</span></span>
115<span class="line"></span>
116<span class="line">  <span class="token comment"># get max free physical memory address</span></span>
117<span class="line">  <span class="token keyword">var</span> maxPhysAddr<span class="token operator">:</span> PhysAddr</span>
118<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">..&lt;</span> physMemoryMap<span class="token operator">.</span>len<span class="token operator">:</span></span>
119<span class="line">    <span class="token keyword">if</span> physMemoryMap<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">==</span> Free<span class="token operator">:</span></span>
120<span class="line">      maxPhysAddr <span class="token operator">=</span> physMemoryMap<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr <span class="token operator">+!</span> physMemoryMap<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>nframes <span class="token operator">*</span> PageSize</span>
121<span class="line"></span>
122<span class="line">  <span class="token keyword">let</span> physMemoryPages<span class="token operator">:</span>
122 uint64 <span class="token operator">=</span> maxPhysAddr<span class="token operator">.</span>uint64 <span class="token operator">div</span> PageSize</span>
123<span class="line"></span>
124<span class="line">  <span class="token keyword">let</span> virtMemoryMap <span class="token operator">=</span> <span class="token function">createVirtualMemoryMap</span><span class="token punctuation">(</span>kernelImagePages<span class="token punctuation">,</span> physMemoryPages<span class="token punctuation">)</span></span>
125<span class="line"></span>
126<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;boot: Preparing BootInfo&quot;</span></span>
127<span class="line">  <span class="token keyword">let</span> bootInfo <span class="token operator">=</span> <span class="token function">createBootInfo</span><span class="token punctuation">(</span></span>
128<span class="line">    bootInfoBase<span class="token punctuation">,</span></span>
129<span class="line">    kernelImagePages<span class="token punctuation">,</span></span>
130<span class="line">    physMemoryPages<span class="token punctuation">,</span></span>
131<span class="line">    physMemoryMap<span class="token punctuation">,</span></span>
132<span class="line">    virtMemoryMap<span class="token punctuation">,</span></span>
133<span class="line">  <span class="token punctuation">)</span></span>
134<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></div><h2 id="bootloader-paging-setup" tabindex="-1"><a class="header-anchor" href="#bootloader-paging-setup"><span>Bootloader paging setup</span></a></h2><p>We know we need to map the kernel to the higher half. But since we&#39;re going to be changing the paging structures in the bootloader, we&#39;ll need to identity-map the bootloader image itself. The reason is that the bootloader code is currently running from the bootloader image, which is mapped to the lower half of the address space. If we change the page tables, the bootloader code will no longer be accessible, and we&#39;ll get a page fault. Here&#39;s a list of things we need to map:</p><ul><li>The bootloader image (identity-mapped)</li><li>The boot info structure</li><li>The kernel image</li><li>The kernel stack</li><li>All physical memory</li></ul><p>We&#39;ll create a new page table structure and map all of the above regions (including physical memory), and install it before jumping to the kernel. Let&#39;s create a new proc to do the mapping.</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/boot/bootx64.nim</span></span>
135<span class="line"><span class="token operator">...</span></span>
136<span class="line"><span class="token keyword">import</span> kernel<span class="token operator">/</span>pmm</span>
137<span class="line"><span class="token keyword">import</span> kernel<span class="token operator">/</span>vmm</span>
138<span class="line"><span class="token operator">...</span></span>
139<span class="line"></span>
140<span class="line"><span class="token keyword">type</span></span>
141<span class="line">  AlignedPage <span class="token operator">=</span> <span class="token keyword">object</span></span>
142<span class="line">    data <span class="token punctuation">{.</span><span class="token function">align</span><span class="token punctuation">(</span>PageSize<span class="token punctuation">)</span><span class="token punctuation">.}</span><span class="token operator">:</span> array<span class="token punctuation">[</span>PageSize<span class="token punctuation">,</span> uint8<span class="token punctuation">]</span></span>
143<span class="line"></span>
144<span class="line"><span class="token keyword">proc</span> <span class="token function">createPageTable</span><span class="token punctuation">(</span></span>
145<span class="line">  bootloaderBase<span class="token operator">:</span>
145 uint64<span class="token punctuation">,</span></span>
146<span class="line">  bootloaderPages<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
147<span class="line">  kernelImageBase<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
148<span class="line">  kernelImagePages<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
149<span class="line">  kernelStackBase<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
150<span class="line">  kernelStackPages<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
151<span class="line">  bootInfoBase<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
152<span class="line">  bootInfoPages<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
153<span class="line">  physMemoryPages<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
154<span class="line"><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">ptr</span> PML4Table <span class="token operator">=</span></span>
155<span class="line"></span>
156<span class="line">  <span class="token keyword">proc</span> <span class="token function">bootAlloc</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>
157<span class="line">    result <span class="token operator">=</span> <span class="token function">some</span><span class="token punctuation">(</span><span class="token function">cast[PhysAddr]</span><span class="token punctuation">(</span>new AlignedPage<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
158<span class="line"></span>
159<span class="line">  <span class="token comment"># initialize vmm using identity-mapped physical memory</span></span>
160<span class="line">  <span class="token function">vmInit</span><span class="token punctuation">(</span>physMemoryVirtualBase <span class="token operator">=</span> <span class="token number">0&#39;u64</span><span class="token punctuation">,</span> physAlloc <span class="token operator">=</span> bootAlloc<span class="token punctuation">)</span></span>
161<span class="line"></span>
162<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;boot: Creating new page tables&quot;</span></span>
163<span class="line">  <span class="token keyword">var</span> pml4 <span class="token operator">=</span> <span class="token function">cast[ptr PML4Table]</span><span class="token punctuation">(</span><span class="token function">bootAlloc</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">.</span>get<span class="token punctuation">)</span></span>
164<span class="line"></span>
165<span class="line">  <span class="token comment"># identity-map bootloader image</span></span>
166<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;boot:   {&quot;Identity-mapping bootloader\\:&quot;:&lt;30} base={bootloaderBase:#010x}, pages={bootloaderPages}&quot;&quot;&quot;</span></span>
167<span class="line">  <span class="token function">identityMapRegion</span><span class="token punctuation">(</span>pml4<span class="token punctuation">,</span> bootloaderBase<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> bootloaderPages<span class="token operator">.</span>uint64<span class="token punctuation">,</span> paReadWrite<span class="token punctuation">,</span> pmSupervisor<span class="token punctuation">)</span></span>
168<span class="line"></span>
169<span class="line">  <span class="token comment"># identity-map boot info</span></span>
170<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;boot:   {&quot;Identity-mapping BootInfo\\:&quot;:&lt;30} base={bootInfoBase:#010x}, pages={bootInfoPages}&quot;&quot;&quot;</span></span>
171<span class="line">  <span class="token function">identityMapRegion</span><span class="token punctuation">(</span>pml4<span class="token punctuation">,</span> bootInfoBase<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> bootInfoPages<span class="token punctuation">,</span> paReadWrite<span class="token punctuation">,</span> pmSupervisor<span class="token punctuation">)</span></span>
172<span class="line"></span>
173<span class="line">  <span class="token comment"># map kernel to higher half</span></span>
174<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;boot:   {&quot;Mapping kernel to higher half\\:&quot;:&lt;30} base={KernelVirtualBase:#010x}, pages={kernelImagePages}&quot;&quot;&quot;</span></span>
175<span class="line">  <span class="token function">mapRegion</span><span class="token punctuation">(</span>pml4<span class="token punctuation">,</span> KernelVirtualBase<span class="token operator">.</span>VirtAddr<span class="token punctuation">,</span> kernelImageBase<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> kernelImagePages<span class="token punctuation">,</span> paReadWrite<span class="token punctuation">,</span> pmSupervisor<span class="token punctuation">)</span></span>
176<span class="line"></span>
177<span class="line">  <span class="token comment"># map kernel stack</span></span>
178<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;boot:   {&quot;Mapping kernel stack\\:&quot;:&lt;30} base={KernelStackVirtualBase:#010x}, pages={kernelStackPages}&quot;&quot;&quot;</span></span>
179<span class="line">  <span class="token function">mapRegion</span><span class="token punctuation">(</span>pml4<span class="token punctuation">,</span> KernelStackVirtualBase<span class="token operator">.</span>VirtAddr<span class="token punctuation">,</span> kernelStackBase<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span> kernelStackPages<span class="token punctuation">,</span> paReadWrite<span class="token punctuation">,</span> pmSupervisor<span class="token punctuation">)</span></span>
180<span class="line"></span>
181<span class="line">  <span class="token comment"># map all physical memory; assume 128 MiB of physical memory</span></span>
182<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;boot:   {&quot;Mapping physical memory\\:&quot;:&lt;30} base={PhysicalMemoryVirtualBase:#010x}, pages={physMemoryPages}&quot;&quot;&quot;</span></span>
183<span class="line">  <span class="token function">mapRegion</span><span class="token punctuation">(</span>pml4<span class="token punctuation">,</span> PhysicalMemoryVirtualBase<span class="token operator">.</span>VirtAddr<span class="token punctuation">,</span> <span class="token number">0.</span>PhysAddr<span class="token punctuation">,</span> physMemoryPages<span class="token punctuation">,</span> paReadWrite<span class="token punctuation">,</span> pmSupervisor<span class="token punctuation">)</span></span>
184<span class="line"></span>
185<span class="line">  result <span class="token operator">=</span> pml4</span>
186<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></div><p>Notice the <code>AlignedPage</code> type and the inner proc <code>bootAlloc</code>. This is a temporary proc that we&#39;ll use to allow the VMM to allocate physical memory for the page tables (the pages must be aligned to 4 KiB, hence the <code>AlignedPage</code> type). It works because the UEFI environment is identity-mapped, so allocating using the <code>new</code> operator will return an address of a page that we can use for the page tables. In the kernel, we&#39;ll rely on the physical memory manager to allocate physical memory for the page tables.</p><p>Now, let&#39;s put everything together in <code>EfiMainInner</code>. Notice that we added an assembly instruction to load the new page tables into the <code>cr3</code> register. This is the register that holds the physical address of the PML4 table.</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/boot/bootx64.nim</span></span>
187<span class="line"><span class="token operator">...</span></span>
188<span class="line"></span>
189<span class="line"><span class="token keyword">proc</span> <span class="token function">EfiMainInner</span><span class="token punctuation">(</span>imgHandle<span class="token operator">:</span> EfiHandle<span class="token punctuation">,</span> sysTable<span class="token operator">:</span> <span class="token keyword">ptr</span>
189 EFiSystemTable<span class="token punctuation">)</span><span class="token operator">:</span> EfiStatus <span class="token operator">=</span></span>
190<span class="line">  <span class="token operator">...</span></span>
191<span class="line"></span>
192<span class="line">  <span class="token keyword">let</span> physMemoryMap <span class="token operator">=</span> <span class="token function">convertUefiMemoryMap</span><span class="token punctuation">(</span>memoryMap<span class="token punctuation">,</span> memoryMapSize<span class="token punctuation">,</span> memoryMapDescriptorSize<span class="token punctuation">)</span></span>
193<span class="line"></span>
194<span class="line">  <span class="token comment"># get max free physical memory address</span></span>
195<span class="line">  <span class="token keyword">var</span> maxPhysAddr<span class="token operator">:</span> PhysAddr</span>
196<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">..&lt;</span> physMemoryMap<span class="token operator">.</span>len<span class="token operator">:</span></span>
197<span class="line">    <span class="token keyword">if</span> physMemoryMap<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span><span class="token keyword">type</span> <span class="token operator">==</span> Free<span class="token operator">:</span></span>
198<span class="line">      maxPhysAddr <span class="token operator">=</span> physMemoryMap<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>start<span class="token operator">.</span>PhysAddr <span class="token operator">+!</span> physMemoryMap<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">.</span>nframes <span class="token operator">*</span> PageSize</span>
199<span class="line"></span>
200<span class="line">  <span class="token keyword">let</span> physMemoryPages<span class="token operator">:</span> uint64 <span class="token operator">=</span> maxPhysAddr<span class="token operator">.</span>uint64 <span class="token operator">div</span> PageSize</span>
201<span class="line"></span>
202<span class="line">  <span class="token keyword">let</span> virtMemoryMap <span class="token operator">=</span> <span class="token function">createVirtualMemoryMap</span><span class="token punctuation">(</span>kernelImagePages<span class="token punctuation">,</span> physMemoryPages<span class="token punctuation">)</span></span>
203<span class="line"></span>
204<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;boot: Preparing BootInfo&quot;</span></span>
205<span class="line">  <span class="token keyword">let</span> bootInfo <span class="token operator">=</span> <span class="token function">createBootInfo</span><span class="token punctuation">(</span></span>
206<span class="line">    bootInfoBase<span class="token punctuation">,</span></span>
207<span class="line">    kernelImagePages<span class="token punctuation">,</span></span>
208<span class="line">    physMemoryPages<span class="token punctuation">,</span></span>
209<span class="line">    physMemoryMap<span class="token punctuation">,</span></span>
210<span class="line">    virtMemoryMap<span class="token punctuation">,</span></span>
211<span class="line">  <span class="token punctuation">)</span></span>
212<span class="line"></span>
213<span class="line">  <span class="token keyword">let</span> bootloaderPages <span class="token operator">=</span> <span class="token punctuation">(</span>loadedImage<span class="token operator">.</span>imageSize<span class="token operator">.</span>uint <span class="token operator">+</span> <span class="token number">0xFFF</span><span class="token punctuation">)</span> <span class="token operator">div</span> <span class="token number">0x1000</span><span class="token operator">.</span>uint</span>
214<span class="line"></span>
215<span class="line">  <span class="token keyword">let</span> pml4 <span class="token operator">=</span> <span class="token function">createPageTable</span><span class="token punctuation">(</span></span>
216<span class="line">    <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>
216loadedImage<span class="token operator">.</span>imageBase<span class="token punctuation">)</span><span class="token punctuation">,</span></span>
217<span class="line">    bootloaderPages<span class="token punctuation">,</span></span>
218<span class="line">    <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>kernelImageBase<span class="token punctuation">)</span><span class="token punctuation">,</span></span>
219<span class="line">    kernelImagePages<span class="token punctuation">,</span></span>
220<span class="line">    kernelStackBase<span class="token punctuation">,</span></span>
221<span class="line">    kernelStackPages<span class="token punctuation">,</span></span>
222<span class="line">    bootInfoBase<span class="token punctuation">,</span></span>
223<span class="line">    <span class="token number">1</span><span class="token punctuation">,</span> <span class="token comment"># bootInfoPages</span></span>
224<span class="line">    physMemoryPages<span class="token punctuation">,</span></span>
225<span class="line">  <span class="token punctuation">)</span></span>
226<span class="line"></span>
227<span class="line">  <span class="token comment"># jump to kernel</span></span>
228<span class="line">  <span class="token keyword">let</span> kernelStackTop <span class="token operator">=</span> KernelStackVirtualBase <span class="token operator">+</span> KernelStackSize</span>
229<span class="line">  <span class="token keyword">let</span> cr3 <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>pml4<span class="token punctuation">)</span></span>
230<span class="line">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;boot: Jumping to kernel at {cast[uint64](KernelVirtualBase):#010x}&quot;</span></span>
231<span class="line">  <span class="token keyword">asm</span> <span class="token string">&quot;&quot;&quot;</span>
232<span class="line">    mov rdi, %0  # bootInfo</span>
233<span class="line">    mov cr3, %2  # PML4</span>
234<span class="line">    mov rsp, %1  # kernel stack top</span>
235<span class="line">    jmp %3       # kernel entry point</span>
236<span class="line">    :</span>
237<span class="line">    : &quot;r&quot;(\`bootInfoBase\`),</span>
238<span class="line">      &quot;r&quot;(\`kernelStackTop\`),</span>
239<span class="line">      &quot;r&quot;(\`cr3\`),</span>
240<span class="line">      &quot;r&quot;(\`KernelVirtualBase\`)</span>
241<span class="line">  &quot;&quot;&quot;</span></span>
242<span class="line"></span>
243<span class="line">  <span class="token comment"># we should never get here</span></span>
244<span class="line">  <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
245<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></div><h2 id="initializing-the-pmm-and-vmm" tabindex="-1"><a class="header-anchor" href="#initializing-the-pmm-and-vmm"><span>Initializing the PMM and VMM</span></a></h2><p>Now that physical memory is not identity-mapped anymore, we need to update the PMM to know about the new virtual address of physical memory. To access a <code>PMNode</code> as a physical address, we subtract the physical memory virtual base address from the pointer. To access a physical address as a <code>PMNode</code>, we add the physical memory virtual base address to the address.</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>
246<span class="line"></span>
247<span class="line"><span class="token keyword">var</span></span>
248<span class="line">  head<span class="token operator">:</span> <span class="token keyword">ptr</span> PMNode</span>
249<span class="line">  maxPhysAddr<span class="token operator">:</span> PhysAddr <span class="token comment"># exclusive</span></span>
250<span class="line highlighted">  physicalMemoryVirtualBase<span class="token operator">:</span> uint64</span>
251<span class="line">  reservedRegions<span class="token operator">:</span> seq<span class="token punctuation">[</span>PMRegion<span class="token punctuation">]</span></span>
252<span class="line"></span>
253<span class="line highlighted"><span class="token keyword">proc</span> <span class="token function">pmInit<span class="token operator">*</span></span><span class="token punctuation">(</span>physMemoryVirtualBase<span class="token operator">:</span>
253 uint64<span class="token punctuation">,</span> memoryMap<span class="token operator">:</span> MemoryMap<span class="token punctuation">)</span> <span class="token operator">=</span></span>
254<span class="line highlighted">  physicalMemoryVirtualBase <span class="token operator">=</span> physMemoryVirtualBase</span>
255<span class="line">  <span class="token operator">...</span></span>
256<span class="line"></span>
257<span class="line"><span class="token keyword">proc</span> <span class="token function">toPhysAddr</span><span class="token punctuation">(</span>p<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>
258<span class="line highlighted">  result <span class="token operator">=</span> <span class="token function">PhysAddr</span><span class="token punctuation">(</span><span class="token function">cast[uint64]</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span> <span class="token operator">-</span> physicalMemoryVirtualBase<span class="token punctuation">)</span></span>
259<span class="line"></span>
260<span class="line"><span class="token keyword">proc</span> <span class="token function">toPMNodePtr</span><span class="token punctuation">(</span>p<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>
261<span class="line highlighted">  result <span class="token operator">=</span> <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>p<span class="token punctuation">)</span> <span class="token operator">+</span> physicalMemoryVirtualBase<span class="token punctuation">)</span></span>
262<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></div><p>The VMM already takes a parameter for the physical memory virtual base (in the bootloader we set it to <code>0</code>, since physical memory is identity-mapped there). We just need to pass it from the kernel. Let&#39;s initialize both the PMM and the VMM with this parameter.</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>
263<span class="line"></span>
264<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>
265<span class="line">  debugln <span class="token string">&quot;&quot;</span></span>
266<span class="line">  debugln <span class="token string">&quot;kernel: Fusion Kernel&quot;</span></span>
267<span class="line"></span>
268<span class="line highlighted">  debug <span class="token string">&quot;kernel: Initializing physical memory manager &quot;</span></span>
269<span class="line highlighted">  <span class="token function">pmInit</span><span class="token punctuation">(</span>bootInfo<span class="token operator">.</span>physicalMemoryVirtualBase<span class="token punctuation">,</span> bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token punctuation">)</span></span>
270<span class="line highlighted">  debugln <span class="token string">&quot;[success]&quot;</span></span>
271<span class="line highlighted"></span>
272<span class="line highlighted">  debug <span class="token string">&quot;kernel: Initializing virtual memory manager &quot;</span></span>
273<span class="line highlighted">  <span class="token function">vmInit</span><span class="token punctuation">(</span>bootInfo<span class="token operator">.</span>physicalMemoryVirtualBase<span class="token punctuation">,</span> pmm<span class="token operator">.</span>pmAlloc<span class="token punctuation">)</span></span>
274<span class="line highlighted">  debugln <span class="token string">&quot;[success]&quot;</span></span>
275<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></div><p>Let&#39;s try to compile and run the kernel. We should see the following output:</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token output">kernel: Fusion Kernel</span>
276<span class="line">kernel: Initializing physical memory manager [success]</span>
277<span class="line">kernel: Initializing virtual memory manager [success]</span>
278<span class="line"></span></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></div><p>Looks good.</p><h2 id="print-memory-maps" tabindex="-1"><a class="header-anchor" href="#print-memory-maps"><span>Print memory maps</span></a></h2><p>Let&#39;s add a couple of procs to print the physical and virtual memory maps.</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>
279<span class="line"><span class="token operator">...</span></span>
280<span class="line"></span>
281<span class="line highlighted"><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>
282<span class="line highlighted">  debug <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;   {&quot;Start&quot;:&gt;16}&quot;&quot;&quot;</span></span>
283<span class="line highlighted">  debug <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;   {&quot;Start (KB)&quot;:&gt;12}&quot;&quot;&quot;</span></span>
284<span class="line highlighted">  debug <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;   {&quot;Size (KB)&quot;:&gt;11}&quot;&quot;&quot;</span></span>
285<span class="line highlighted">  debug <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;   {&quot;#Pages&quot;:&gt;9}&quot;&quot;&quot;</span></span>
286<span class="line highlighted">  debugln <span class="token string">&quot;&quot;</span></span>
287<span class="line highlighted">  <span class="token keyword">var</span> totalFreePages<span class="token operator">:</span>
287 uint64 <span class="token operator">=</span> <span class="token number">0</span></span>
288<span class="line highlighted">  <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>
289<span class="line highlighted">    debug <span class="token operator">&amp;</span><span class="token string">&quot;   {cast[uint64](start):&gt;#16x}&quot;</span></span>
290<span class="line highlighted">    debug <span class="token operator">&amp;</span><span class="token string">&quot;   {cast[uint64](start) div 1024:&gt;#12}&quot;</span></span>
291<span class="line highlighted">    debug <span class="token operator">&amp;</span><span class="token string">&quot;   {nframes * 4:&gt;#11}&quot;</span></span>
292<span class="line highlighted">    debug <span class="token operator">&amp;</span><span class="token string">&quot;   {nframes:&gt;#9}&quot;</span></span>
293<span class="line highlighted">    debugln <span class="token string">&quot;&quot;</span></span>
294<span class="line highlighted">    totalFreePages <span class="token operator">+=</span> nframes</span>
295<span class="line highlighted">  debugln <span class="token operator">&amp;</span><span class="token string">&quot;kernel: Total free: {totalFreePages * 4} KiB ({totalFreePages * 4 div 1024} MiB)&quot;</span></span>
296<span class="line highlighted"></span>
297<span class="line highlighted"><span class="token keyword">proc</span> <span class="token function">printVMRegions</span><span class="token punctuation">(</span>memoryMap<span class="token operator">:</span> MemoryMap<span class="token punctuation">)</span> <span class="token operator">=</span></span>
298<span class="line highlighted">  debug <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;   {&quot;Start&quot;:&gt;20}&quot;&quot;&quot;</span></span>
299<span class="line highlighted">  debug <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;   {&quot;Type&quot;:12}&quot;&quot;&quot;</span></span>
300<span class="line highlighted">  debug <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;   {&quot;VM Size (KB)&quot;:&gt;12}&quot;&quot;&quot;</span></span>
301<span class="line highlighted">  debug <span class="token operator">&amp;</span><span class="token string">&quot;&quot;&quot;   {&quot;#Pages&quot;:&gt;9}&quot;&quot;&quot;</span></span>
302<span class="line highlighted">  debugln <span class="token string">&quot;&quot;</span></span>
303<span class="line highlighted">  <span class="token keyword">for</span> i <span class="token operator">in</span> <span class="token number">0</span> <span class="token operator">..&lt;</span> memoryMap<span class="token operator">.</span>len<span class="token operator">:</span></span>
304<span class="line highlighted">    <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>
305<span class="line highlighted">    debug <span class="token operator">&amp;</span><span class="token string">&quot;   {entry.start:&gt;#20x}&quot;</span></span>
306<span class="line highlighted">    debug <span class="token operator">&amp;</span><span class="token string">&quot;   {entry.type:#12}&quot;</span></span>
307<span class="line highlighted">    debug <span class="token operator">&amp;</span><span class="token string">&quot;   {entry.nframes * 4:&gt;#12}&quot;</span></span>
308<span class="line highlighted">    debug <span class="token operator">&amp;</span><span class="token string">&quot;   {entry.nframes:&gt;#9}&quot;</span></span>
309<span class="line highlighted">    debugln <span class="token string">&quot;&quot;</span></span>
310<span class="line"></span>
311<span class="line"><span class="token operator">...</span></span>
312<span class="line"></span>
313<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>
314<span class="line">  debugln <span class="token string">&quot;&quot;</span></span>
315<span class="line">  debugln <span class="token string">&quot;kernel: Fusion Kernel&quot;</span></span>
316<span class="line"></span>
317<span class="line">  debug <span class="token string">&quot;kernel: Initializing physical memory manager &quot;</span></span>
318<span class="line">  <span class="token function">pmInit</span><span class="token punctuation">(</span>bootInfo<span class="token operator">.</span>physicalMemoryVirtualBase<span class="token punctuation">,</span> bootInfo<span class="token operator">.</span>physicalMemoryMap<span class="token punctuation">)</span></span>
319<span class="line">  debugln <span class="token string">&quot;[success]&quot;</span></span>
320<span class="line"></span>
321<span class="line">  debug <span class="token string">&quot;kernel: Initializing virtual memory manager &quot;</span></span>
322<span class="line">  <span class="token function">vmInit</span><span class="token punctuation">(</span>bootInfo<span class="token operator">.</span>physicalMemoryVirtualBase<span class="token punctuation">,</span> pmm<span class="token operator">.</span>pmAlloc<span class="token punctuation">)</span></span>
323<span class="line">  debugln <span class="token string">&quot;[success]&quot;</span></span>
324<span class="line"></span>
325<span class="line highlighted">  debugln <span class="token string">&quot;kernel: Physical memory free regions &quot;</span></span>
326<span class="line highlighted">  <span class="token function">printFreeRegions</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
327<span class="line highlighted"></span>
328<span class="line highlighted">  debugln <span class="token string">&quot;kernel: Virtual memory regions &quot;</span></span>
329<span class="line highlighted">  <span class="token function">printVMRegions</span><span class="token punctuation">(</span>bootInfo<span class="token operator">.</span>virtualMemoryMap<span class="token punctuation">)</span></span>
330<span class="line">  <span class="token operator">...</span></span>
331<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></div><p>Let&#39;s compile and run the kernel. If everything goes well, we should see the following output:</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token output">kernel: Fusion Kernel</span>
332<span class="line">kernel: Initializing physical memory manager [success]</span>
333<span class="line">kernel: Initializing virtual memory manager [success]</span>
334<span class="line">kernel: Physical memory free regions</span>
335<span class="line">              Start     Start (KB)     Size (KB)      #Pages</span>
336<span class="line">                0x0              0           640         160</span>
337<span class="line">           0x222000           2184          6008        1502</span>
338<span class="line">           0x808000           8224            12           3</span>
339<span class="line">           0x80c000           8240            16           4</span>
340<span class="line">           0x900000           9216         90276       22569</span>
341<span class="line">          0x6235000         100564          1248         312</span>
342<span class="line">          0x6372000         101832         17900        4475</span>
343<span class="line">          0x77ff000         122876          7124        1781</span>
344<span class="line">kernel: Total free: 123224 KiB (120 MiB)</span>
345<span class="line">kernel: Virtual memory regions</span>
346<span class="line">                  Start   Type           VM Size (KB)      #Pages</span>
347<span class="line">     0xffff800000100000   KernelCode             1160         290</span>
348<span class="line">     0xffff800100000000   KernelStack              16           4</span>
349<span class="line">     0xffff800100004000   KernelData                4           1</span>
350<span class="line">     0xffff800200000000   KernelData           130000       32500</span>
351<span class="line"></span></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>Great! Our kernel is now running at the higher half of the address space. This is another big milestone.</p><p>There are many things we can tackle next, but one important thing we need to take care of before we add more code is handling CPU exceptions. The reason is that sooner or later our kernel will crash, and we won&#39;
351t know why. Handling CPU exceptions gives us a way to print a debug message and halt the CPU, so we can see what went wrong.</p><p>But before we can do that, we need to set up the <strong>Global Descriptor Table</strong> (GDT), which we&#39;ll look at in the next section.</p>`,45)]))}const c=s(t,[["render",l],["__file","13-higher-half-kernel.html.vue"]]),r=JSON.parse(`{"path":"/osdev/13-higher-half-kernel.html","title":"Higher Half Kernel","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Linking the kernel","slug":"linking-the-kernel","link":"#linking-the-kernel","children":[]},{"level":2,"title":"Preparing BootInfo","slug":"preparing-bootinfo","link":"#preparing-bootinfo","children":[]},{"level":2,"title":"Bootloader paging setup","slug":"bootloader-paging-setup","link":"#bootloader-paging-setup","children":[]},{"level":2,"title":"Initializing the PMM and VMM","slug":"initializing-the-pmm-and-vmm","link":"#initializing-the-pmm-and-vmm","children":[]},{"level":2,"title":"Print memory maps","slug":"print-memory-maps","link":"#print-memory-maps","children":[]}],"git":{"updatedTime":1744638230000},"filePathRelative":"osdev/13-higher-half-kernel.md","excerpt":"\\n<p>The kernel is currently linked at address <code>0x100000</code>, not at the higher half of the\\naddress space. The UEFI environment does have paging enabled, but we need to build our own\\npage tables, and map the kernel at the higher half of the address space. This needs to be\\ndone in the bootloader, before we jump to the kernel (since we'll change the kernel to be\\nlinked at the higher half). Once we're in the kernel, we can set up different page tables\\nthat fit our needs.</p>"}`);export{c as comp,r 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.