PageSourceSearch

https://0xc0ffee.netlify.app/assets/19-tasks.html-Do41fZil.js

js 0xc0ffee.netlify.app collected 2026-10-03 10:23:44 UTC 59,023 bytes, 275 lines download raw bytes

1import{_ as n,c as a,e,o as p}from"./app-CjUkjRdW.js";const t={};function l(i,s){return p(),a("div",null,s[0]||(s[0]=[e(`<h1 id="tasks" tabindex="-1"><a class="header-anchor" href="#tasks"><span>Tasks</span></a></h1><p>We&#39;re starting to accumulate a number of things about the user program that the kernel needs to track: the user page table, the user stack, the kernel switch stack, and the user <code>rsp</code> when executing <code>syscall</code>. These are all currently tracked in global variables. Once we start having more than one user task, it will be hard to keep track of all these things.</p><h2 id="task-definition" tabindex="-1"><a class="header-anchor" href="#task-definition"><span>Task definition</span></a></h2><p>Let&#39;s define a <code>Task</code> type to encapsulate all this information. This will prepare us for having multiple tasks. Let&#39;s create a new module <code>tasks.nim</code> for this.</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/tasks.nim</span></span>
2<span class="line"></span>
3<span class="line"><span class="token keyword">import</span> common<span class="token operator">/</span>pagetables</span>
4<span class="line"><span class="token keyword">import</span> vmm</span>
5<span class="line"></span>
6<span class="line"><span class="token keyword">type</span></span>
7<span class="line">  TaskStack<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
8<span class="line">    data<span class="token operator">*:</span> <span class="token keyword">ptr</span> uint8</span>
9<span class="line">    size<span class="token operator">*:</span> uint64</span>
10<span class="line">    bottom<span class="token operator">*:</span> uint64</span>
11<span class="line"></span>
12<span class="line">  Task<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">ref</span> <span class="token keyword">object</span></span>
13<span class="line">    id<span class="token operator">*:</span> uint64</span>
14<span class="line">    pml4<span class="token operator">*:</span> <span class="token keyword">ptr</span> PML4Table</span>
15<span class="line">    ustack<span class="token operator">*:</span> TaskStack</span>
16<span class="line">    kstack<span class="token operator">*:</span> TaskStack</span>
17<span class="line">    rsp<span class="token operator">*:</span> uint64</span>
18<span class="line"></span>
19<span class="line"><span class="token keyword">var</span></span>
20<span class="line">  nextId<span class="token operator">*:</span> uint64 <span class="token operator">=</span> <span class="token number">0</span></span>
21<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>Each task has a unique <code>id</code>, a pointer to its page table, and two stacks: one for user mode and one for kernel mode. The <code>rsp</code> field is where the user stack pointer is stored when the task is executing in kernel mode (e.g. when executing a system call). We also define a <code>TaskStack</code> type to encapsulate the stack address, size, and the bottom of the stack (i.e. the address just beyond the end of the stack). The <code>nextId</code> variable will be used to assign unique IDs to each task.</p><p>Before we can start creating tasks, we need a way to allocate virtual memory within an address space. Let&#39;
21s add a few things to the virtual memory manager to support this.</p><h2 id="address-space-abstraction" tabindex="-1"><a class="header-anchor" href="#address-space-abstraction"><span>Address space abstraction</span></a></h2><p>For a particular address space, we need to track which regions are currently allocated, and a way to allocate more regions. We&#39;ll use this to allocate the user stack and kernel stack. To make it easy to refer to a particular address space, and track which regions are currently allocated in it, we&#39;ll define a <code>VMAddressSpace</code> type.</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/vmm.nim</span></span>
22<span class="line"></span>
23<span class="line"><span class="token keyword">type</span></span>
24<span class="line">  VMRegion<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
25<span class="line">    start<span class="token operator">:</span> VirtAddr</span>
26<span class="line">    npages<span class="token operator">:</span> uint64</span>
27<span class="line"></span>
28<span class="line">  VMAddressSpace<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
29<span class="line">    minAddress<span class="token operator">*:</span> VirtAddr</span>
30<span class="line">    maxAddress<span class="token operator">*:</span> VirtAddr</span>
31<span class="line">    regions<span class="token operator">*:</span> seq<span class="token punctuation">[</span>VMRegion<span class="token punctuation">]</span></span>
32<span class="line">    pml4<span class="token operator">*:</span> <span class="token keyword">ptr</span> PML4Table</span>
33<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>Notice that I also defined a <code>VMRegion</code> type to represent a contiguous region of virtual memory. Notice also that I defined two fields <code>minAddress</code> and <code>maxAddress</code> in <code>VMAddressSpace</code> to track the minimum and maximum addresses in the address space. This will make it easy to confine the address space to the lower half (for user space) or upper half (for kernel space) of the virtual address space.</p><p>Let&#39;s make a slight modification to the <code>Task</code> type to use the new <code>VMAddressSpace</code> type instead of a pointer to a <code>PML4Table</code>.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line">  Task<span class="token operator">*</span> <span class="token operator">=</span> <span class="token keyword">ref</span> <span class="token keyword">object</span></span>
34<span class="line">    id<span class="token operator">*:</span> uint64</span>
35<span class="line highlighted">    space<span class="token operator">*:</span> VMAddressSpace</span>
36<span class="line">    ustack<span class="token operator">*:</span> TaskStack</span>
37<span class="line">    kstack<span class="token operator">*:</span> TaskStack</span>
38<span class="line">    rsp<span class="token operator">*:</span> uint64</span>
39<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></div><p>Let&#39;s now add a proc to allocate virtual memory in an address space.</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/vmm.nim</span></span>
40<span class="line"><span class="token keyword">
40import</span> std<span class="token operator">/</span>algorithm</span>
41<span class="line"><span class="token operator">...</span></span>
42<span class="line"></span>
43<span class="line"><span class="token keyword">proc</span> <span class="token function">vmalloc<span class="token operator">*</span></span><span class="token punctuation">(</span></span>
44<span class="line">  space<span class="token operator">:</span> <span class="token keyword">var</span> VMAddressSpace<span class="token punctuation">,</span></span>
45<span class="line">  pageCount<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
46<span class="line">  pageAccess<span class="token operator">:</span> PageAccess<span class="token punctuation">,</span></span>
47<span class="line">  pageMode<span class="token operator">:</span> PageMode<span class="token punctuation">,</span></span>
48<span class="line"><span class="token punctuation">)</span><span class="token operator">:</span> Option<span class="token punctuation">[</span>VirtAddr<span class="token punctuation">]</span> <span class="token operator">=</span></span>
49<span class="line">  <span class="token comment"># find a free region</span></span>
50<span class="line">  <span class="token keyword">var</span> virtAddr<span class="token operator">:</span> VirtAddr <span class="token operator">=</span> space<span class="token operator">.</span>minAddress</span>
51<span class="line">  <span class="token keyword">for</span> region <span class="token operator">in</span> space<span class="token operator">.</span>regions<span class="token operator">:</span></span>
52<span class="line">    <span class="token keyword">if</span> virtAddr <span class="token operator">+!</span> pageCount <span class="token operator">*</span> PageSize <span class="token operator">&lt;=</span> region<span class="token operator">.</span>start<span class="token operator">:</span></span>
53<span class="line">      <span class="token keyword">break</span></span>
54<span class="line">    virtAddr <span class="token operator">=</span> region<span class="token operator">.</span>start <span class="token operator">+!</span> region<span class="token operator">.</span>npages <span class="token operator">*</span> PageSize</span>
55<span class="line"></span>
56<span class="line">  <span class="token comment"># allocate physical memory and map it</span></span>
57<span class="line">  <span class="token keyword">let</span> physAddr <span class="token operator">=</span> <span class="token function">pmalloc</span><span class="token punctuation">(</span>pageCount<span class="token punctuation">)</span><span class="token operator">.</span>get <span class="token comment"># TODO: handle allocation failure</span></span>
58<span class="line">  <span class="token function">mapRegion</span><span class="token punctuation">(</span>space<span class="token operator">.</span>pml4<span class="token punctuation">,</span> virtAddr<span class="token punctuation">,</span> physAddr<span class="token punctuation">,</span>
58 pageCount<span class="token punctuation">,</span> pageAccess<span class="token punctuation">,</span> pageMode<span class="token punctuation">)</span></span>
59<span class="line"></span>
60<span class="line">  <span class="token comment"># add the region to the address space</span></span>
61<span class="line">  space<span class="token operator">.</span>regions<span class="token operator">.</span>add <span class="token function">VMRegion</span><span class="token punctuation">(</span>start<span class="token operator">:</span> virtAddr<span class="token punctuation">,</span> npages<span class="token operator">:</span> pageCount<span class="token punctuation">)</span></span>
62<span class="line"></span>
63<span class="line">  <span class="token comment"># sort the regions by start address</span></span>
64<span class="line">  space<span class="token operator">.</span>regions <span class="token operator">=</span> space<span class="token operator">.</span>regions<span class="token operator">.</span><span class="token function">sortedByIt</span><span class="token punctuation">(</span>it<span class="token operator">.</span>start<span class="token punctuation">)</span></span>
65<span class="line"></span>
66<span class="line">  result <span class="token operator">=</span> some virtAddr</span>
67<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><p>The <code>vmalloc</code> proc finds a free region in the address space, allocates physical memory, and maps it into the address space. It returns the virtual address of the allocated region. We then sort the regions by start address, so that we can easily find a free region in the future. (Ideally, the standard library should provide a sorted container that we can use here, but for now, we&#39;ll just sort the regions manually after adding a new one.)</p><p>We also need a way to add existing VM regions to an address space. We&#39;ll need this to add the existing kernel VM regions (code/data and stack) to its address space.</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/vmm.nim</span></span>
68<span class="line"></span>
69<span class="line"><span class="token keyword">proc</span> <span class="token function">vmAddRegion<span class="token operator">*</span></span><span class="token punctuation">(</span>space<span class="token operator">:</span> <span class="token keyword">var</span> VMAddressSpace<span class="token punctuation">,</span> start<span class="token operator">:</span> VirtAddr<span class="token punctuation">,</span> npages<span class="token operator">:</span> uint64<span class="token punctuation">)</span> <span class="token operator">=</span></span>
70<span class="line">  space<span class="token operator">.</span>regions<span class="token operator">.</span>add <span class="token function">VMRegion</span><span class="token punctuation">(</span>start<span class="token operator">:</span> start<span class="token punctuation">,</span> npages<span class="token operator">:</span> npages<span class="token punctuation">)</span></span>
71<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></div><h2 id="kernel-address-space" tabindex="-1"><a class="header-anchor" href="#kernel-address-space"><span>Kernel address space</span></a></h2><p>The kernel itself needs its own address space. Let&#39;s create a global variable <code>kspace</code> to track it.</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/vmm.nim</span></span>
72<span class="line"><span class="token operator">...</span></span>
73<span class="line"></span>
74<span class="line"><span class="token keyword">const</span></span>
75<span class="line">  KernelSpaceMinAddress<span class="token operator">*</span> <span class="token operator">=</span> <span class="token number">
750xffff800000000000&#39;u64</span><span class="token operator">.</span>VirtAddr</span>
76<span class="line">  KernelSpaceMaxAddress<span class="token operator">*</span> <span class="token operator">=</span> <span class="token number">0xffffffffffffffff&#39;u64</span><span class="token operator">.</span>VirtAddr</span>
77<span class="line">  UserSpaceMinAddress<span class="token operator">*</span> <span class="token operator">=</span> <span class="token number">0x0000000000000000&#39;u64</span><span class="token operator">.</span>VirtAddr</span>
78<span class="line">  UserSpaceMaxAddress<span class="token operator">*</span> <span class="token operator">=</span> <span class="token number">0x00007fffffffffff&#39;u64</span><span class="token operator">.</span>VirtAddr</span>
79<span class="line"></span>
80<span class="line"><span class="token keyword">var</span></span>
81<span class="line">  kspace<span class="token operator">*:</span> VMAddressSpace</span>
82<span class="line"></span>
83<span class="line"><span class="token keyword">proc</span> <span class="token function">vmInit<span class="token operator">*</span></span><span class="token punctuation">(</span>physMemoryVirtualBase<span class="token operator">:</span> uint64<span class="token punctuation">,</span> physAlloc<span class="token operator">:</span> PhysAlloc<span class="token punctuation">)</span> <span class="token operator">=</span></span>
84<span class="line">  physicalMemoryVirtualBase <span class="token operator">=</span> physMemoryVirtualBase</span>
85<span class="line">  pmalloc <span class="token operator">=</span> physAlloc</span>
86<span class="line">  kspace <span class="token operator">=</span> <span class="token function">VMAddressSpace</span><span class="token punctuation">(</span></span>
87<span class="line">    minAddress<span class="token operator">:</span> KernelSpaceMinAddress<span class="token punctuation">,</span></span>
88<span class="line">    maxAddress<span class="token operator">:</span> KernelSpaceMaxAddress<span class="token punctuation">,</span></span>
89<span class="line">    regions<span class="token operator">:</span> <span class="token operator">@</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span></span>
90<span class="line">    pml4<span class="token operator">:</span> <span class="token function">getActivePML4</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span></span>
91<span class="line">  <span class="token punctuation">)</span></span>
92<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></div><p>Let&#39;s also add the existing kernel VM regions to it (code/data and stack).</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>
93<span class="line"><span class="token operator">...</span></span>
94<span class="line"></span>
95<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMain</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 punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
96<span class="line">  <span class="token operator">...</span></span>
97<span class="line"></span>
98<span class="line">  debug <span class="token string">&quot;kernel: Initializing virtual memory manager &quot;</span></span>
99<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>
100<span class="line">  <span class="token function">vmAddRegion</span><span class="token punctuation">(</span>kspace<span class="token punctuation">,</span> bootInfo<span class="token operator">.</span>kernelImageVirtualBase<span class="token operator">.</span>VirtAddr<span class="token punctuation">,</span> bootInfo<span class="token operator">.</span>kernelImagePages<span class="token punctuation">)</span></span>
101<span class="line">  <span class="token function">vmAddRegion</span><span class="token punctuation">(</span>kspace<span class="token punctuation">,</span> bootInfo<span class="token operator">.</span>kernelStackVirtualBase<span class="token operator">.</span>VirtAddr<span class="token punctuation">,</span> bootInfo<span class="token operator">.</span>kernelStackPages<span class="token punctuation">)</span></span>
102<span class="line">  debugln <span class="token string">&quot;[success]&quot;</span></span>
103<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></div><h2 id="creating-a-task" tabindex="-1"><a class="header-anchor" href="#creating-a-task"><span>Creating a task</span></a></h2><p>Creating a task involves the following steps:</p><ol><li>Creating a VM address space and allocating a page table</li><li>Mapping the task image (code and data) into the task page table</li><li>Mapping the kernel space into the task page table</li><li>Allocating and mapping a user stack (in user space)</li><li>Allocating and mapping a kernel stack (in kernel space)</li><li>Creating an interrupt stack frame on the kernel stack (for switching to user mode)</li><li>Setting the <code>rsp</code> field to point to the interrupt stack frame</li></ol><p>This seems like a lot of steps, but it&#39;
103s not too bad. Let&#39;s add a <code>createTask</code> proc to the <code>tasks</code> module to do all this. We&#39;ll also add a <code>createStack</code> helper proc to allocate a stack in a particular address space.</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/tasks.nim</span></span>
104<span class="line"></span>
105<span class="line"><span class="token keyword">proc</span> <span class="token function">createStack<span class="token operator">*</span></span><span class="token punctuation">(</span>space<span class="token operator">:</span> <span class="token keyword">var</span> VMAddressSpace<span class="token punctuation">,</span> npages<span class="token operator">:</span> uint64<span class="token punctuation">,</span> mode<span class="token operator">:</span> PageMode<span class="token punctuation">)</span><span class="token operator">:</span> TaskStack <span class="token operator">=</span></span>
106<span class="line">  <span class="token keyword">let</span> stackPtr <span class="token operator">=</span> <span class="token function">vmalloc</span><span class="token punctuation">(</span>space<span class="token punctuation">,</span> npages<span class="token punctuation">,</span> paReadWrite<span class="token punctuation">,</span> mode<span class="token punctuation">)</span></span>
107<span class="line">  <span class="token keyword">if</span> stackPtr<span class="token operator">.</span>isNone<span class="token operator">:</span></span>
108<span class="line">    <span class="token keyword">raise</span> <span class="token function">newException</span><span class="token punctuation">(</span>Exception<span class="token punctuation">,</span> <span class="token string">&quot;tasks: Failed to allocate stack&quot;</span><span class="token punctuation">)</span></span>
109<span class="line">  result<span class="token operator">.</span>data <span class="token operator">=</span> <span class="token keyword">cast</span><span class="token punctuation">[</span><span class="token keyword">ptr</span> UncheckedArray<span class="token punctuation">[</span>uint64<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">(</span>stackPtr<span class="token operator">.</span>get<span class="token punctuation">)</span></span>
110<span class="line">  result<span class="token operator">.</span>size <span class="token operator">=</span> npages <span class="token operator">*</span> PageSize</span>
111<span class="line">  result<span class="token operator">.</span>bottom <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>result<span class="token operator">.</span>data<span class="token punctuation">)</span> <span class="token operator">+</span> result<span class="token operator">.</span>size</span>
112<span class="line"></span>
113<span class="line"><span class="token keyword">proc</span> <span class="token function">createTask<span class="token operator">*</span></span><span class="token punctuation">(</span></span>
114<span class="line">  imageVirtAddr<span class="token operator">:</span> VirtAddr<span class="token punctuation">,</span></span>
115<span class="line">  imagePhysAddr<span class="token operator">:</span> PhysAddr<span class="token punctuation">,</span></span>
116<span class="line">  imagePageCount<span class="token operator">:</span> uint64<span class="token punctuation">,</span></span>
117<span class="line">  entryPoint<span class="token operator">:</span> VirtAddr</span>
118<span class="line"><span class="token punctuation">)</span><span class="token operator">:</span> Task <span class="token operator">=</span></span>
119<span class="line">  <span class="token function">new</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span></span>
120<span class="line"></span>
121<span class="line">  <span class="token keyword">let</span> taskId <span class="token operator">=</span> nextId</span>
122<span class="line">  inc nextId</span>
123<span class="line"></span>
124<span class="line">  <span class="token keyword">var</span> uspace <span class="token operator">=</span> <span class="token function">VMAddressSpace</span><span class="token punctuation">(</span></span>
125<span class="line">    minAddress<span class="token operator">:</span> UserSpaceMinAddress<span class="token punctuation">,</span></span>
126<span class="line">    maxAddress<span class="token operator">:</span> UserSpaceMaxAddress<span class="token punctuation">,</span></span>
127<span class="line">    pml4<span class="token operator">:</span> <span class="token function">cast[ptr PML4Table]</span><span class="token punctuation">(</span>
127new PML4Table<span class="token punctuation">)</span></span>
128<span class="line">  <span class="token punctuation">)</span></span>
129<span class="line"></span>
130<span class="line">  <span class="token comment"># map task image</span></span>
131<span class="line">  <span class="token function">mapRegion</span><span class="token punctuation">(</span></span>
132<span class="line">    pml4 <span class="token operator">=</span> uspace<span class="token operator">.</span>pml4<span class="token punctuation">,</span></span>
133<span class="line">    virtAddr <span class="token operator">=</span> imageVirtAddr<span class="token punctuation">,</span></span>
134<span class="line">    physAddr <span class="token operator">=</span> imagePhysAddr<span class="token punctuation">,</span></span>
135<span class="line">    pageCount <span class="token operator">=</span> imagePageCount<span class="token punctuation">,</span></span>
136<span class="line">    pageAccess <span class="token operator">=</span> paReadWrite<span class="token punctuation">,</span></span>
137<span class="line">    pageMode <span class="token operator">=</span> pmUser<span class="token punctuation">,</span></span>
138<span class="line">  <span class="token punctuation">)</span></span>
139<span class="line"></span>
140<span class="line">  <span class="token comment"># map kernel space</span></span>
141<span class="line">  <span class="token keyword">var</span> kpml4 <span class="token operator">=</span> <span class="token function">getActivePML4</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
142<span class="line">  <span class="token keyword">for</span> i <span class="token operator">in</span> <span class="token number">256</span> <span class="token operator">..&lt;</span> <span class="token number">512</span><span class="token operator">:</span></span>
143<span class="line">    uspace<span class="token operator">.</span>pml4<span class="token operator">.</span>entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> kpml4<span class="token operator">.</span>entries<span class="token punctuation">[</span>i<span class="token punctuation">]</span></span>
144<span class="line"></span>
145<span class="line">  <span class="token comment"># create user and kernel stacks</span></span>
146<span class="line">  <span class="token keyword">let</span> ustack <span class="token operator">=</span> <span class="token function">createStack</span><span class="token punctuation">(</span>uspace<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> pmUser<span class="token punctuation">)</span></span>
147<span class="line">  <span class="token keyword">let</span> kstack <span class="token operator">=</span> <span class="token function">createStack</span><span class="token punctuation">(</span>kspace<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> pmSupervisor<span class="token punctuation">)</span></span>
148<span class="line"></span>
149<span class="line">  <span class="token comment"># create interrupt stack frame on the kernel stack</span></span>
150<span class="line">  <span class="token keyword">var</span> index <span class="token operator">=</span> kstack<span class="token operator">.</span>size <span class="token operator">div</span> <span class="token number">8</span></span>
151<span class="line">  kstack<span class="token operator">.</span>data<span class="token punctuation">[</span>index <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>DataSegmentSelector<span class="token punctuation">)</span> <span class="token comment"># SS</span></span>
152<span class="line">  kstack<span class="token operator">.</span>data<span class="token punctuation">[</span>index <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>ustack<span class="token operator">.</span>bottom<span class="token punctuation">)</span> <span class="token comment"># RSP</span></span>
153<span class="line">  kstack<span class="token operator">.</span>data<span class="token punctuation">[</span>index <span class="token operator">-</span> <span class="token number">3</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span><span class="token number">0x202</span><span class="token punctuation">)</span> <span class="token comment"># RFLAGS</span></span>
154<span class="line">  kstack<span class="token operator">.</span>data<span class="token punctuation">[</span>index <span class="token operator">-</span> <span class="token number">4</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>UserCodeSegmentSelector<span class="token punctuation">)</span> <span class="token comment"># CS</span></span>
155<span class="line">  kstack<span class="token operator">.</span>data<span class="token punctuation">[</span>index <span class="token operator">-</span> <span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>entryPoint<span class="token punctuation">)</span> <span class="token comment"># RIP</span></span>
156<span class="line"></span>
157<span class="line">  result<span class="token operator">.</span>id <span class="token operator">=</span> taskId</span>
158<span class="line">  result<span class="token operator">.</span>space <span class="token operator">=</span> uspace</span>
159<span class="line">  result<span class="token operator">.</span>ustack <span class="token operator">=</span> ustack</span>
160<span class="line">  result<span class="token operator">.</span>kstack <span class="token operator">=</span> kstack</span>
161<span class="line">  result<span class="token operator">.</span>rsp <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>kstack<span class="token operator">.</span>data<span class="token punctuation">[</span>index <span class="token operator">-</span> <span class="token number">5</span><span class="token punctuation">]</span><span class="token operator">.</span><span class="token keyword">addr</span><span class="token punctuation">)</span></span>
162<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><p>Most of this code is not new; we just put it together in one place. The only new thing is calling <code>vmalloc</code> to allocate the user stack and kernel stack (which in turn allocates the backing physical memory). We no longer need to create global arrays to statically allocate the stacks.<
162/p><h2 id="switching-to-a-task" tabindex="-1"><a class="header-anchor" href="#switching-to-a-task"><span>Switching to a task</span></a></h2><p>The part responsible for switching to a task was at the end of the <code>KernelMainInner</code> proc. Let&#39;s move it to the <code>tasks</code> module.</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/tasks.nim</span></span>
163<span class="line"></span>
164<span class="line"><span class="token keyword">proc</span> <span class="token function">switchTo<span class="token operator">*</span></span><span class="token punctuation">(</span>task<span class="token operator">:</span> <span class="token keyword">var</span> Task<span class="token punctuation">)</span> <span class="token punctuation">{.</span>noreturn<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
165<span class="line">  tss<span class="token operator">.</span>rsp0 <span class="token operator">=</span> task<span class="token operator">.</span>kstack<span class="token operator">.</span>bottom</span>
166<span class="line">  <span class="token keyword">let</span> rsp <span class="token operator">=</span> task<span class="token operator">.</span>rsp</span>
167<span class="line">  <span class="token function">setActivePML4</span><span class="token punctuation">(</span>task<span class="token operator">.</span>space<span class="token operator">.</span>pml4<span class="token punctuation">)</span></span>
168<span class="line">  <span class="token keyword">asm</span> <span class="token string">&quot;&quot;&quot;</span>
169<span class="line">    mov rbp, 0</span>
170<span class="line">    mov rsp, %0</span>
171<span class="line">    iretq</span>
172<span class="line">    :</span>
173<span class="line">    : &quot;r&quot;(\`rsp\`)</span>
174<span class="line">  &quot;&quot;&quot;</span></span>
175<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>We update <code>tss.rsp0</code> to point to the kernel stack (so it can be used when the task switches to kernel mode), set the active page table to the task&#39;s page table, set the <code>rsp</code> register to the task&#39;s <code>rsp</code> field (which should point to the interrupt stack frame), and then execute <code>iretq</code> to switch to the task.</p><h2 id="trying-it-out" tabindex="-1"><a class="header-anchor" href="#trying-it-out"><span>Trying it out</span></a></h2><p>We can now replace a big chunk of the code we had in <code>KernelMainInner</code> with a call to <code>createTask</code> and <code>switchTo</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/main.nim</span></span>
176<span class="line"><span class="token operator">...</span></span>
177<span class="line"></span>
178<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMain</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 punctuation">{.</span>exportc<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
179<span class="line">  <span class="token operator">...</span></span>
180<span class="line"></span>
181<span class="line">  debugln <span class="token string">&quot;kernel: Creating user task&quot;</span></span>
182<span class="line">  <span class="token keyword">var</span> task <span class="token operator">=</span> <span class="token function">createTask</span><span class="token punctuation">(</span></span>
183<span class="line">
183    imageVirtAddr <span class="token operator">=</span> UserImageVirtualBase<span class="token operator">.</span>VirtAddr<span class="token punctuation">,</span></span>
184<span class="line">    imagePhysAddr <span class="token operator">=</span> bootInfo<span class="token operator">.</span>userImagePhysicalBase<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span></span>
185<span class="line">    imagePageCount <span class="token operator">=</span> bootInfo<span class="token operator">.</span>userImagePages<span class="token punctuation">,</span></span>
186<span class="line">    entryPoint <span class="token operator">=</span> UserImageVirtualBase<span class="token operator">.</span>VirtAddr</span>
187<span class="line">  <span class="token punctuation">)</span></span>
188<span class="line"></span>
189<span class="line">  debug <span class="token string">&quot;kernel: Initializing Syscalls &quot;</span></span>
190<span class="line">  <span class="token function">syscallInit</span><span class="token punctuation">(</span>task<span class="token operator">.</span>kstack<span class="token operator">.</span>bottom<span class="token punctuation">)</span></span>
191<span class="line">  debugln <span class="token string">&quot;[success]&quot;</span></span>
192<span class="line"></span>
193<span class="line">  debugln <span class="token string">&quot;kernel: Switching to user mode&quot;</span></span>
194<span class="line">  <span class="token function">switchTo</span><span class="token punctuation">(</span>task<span class="token punctuation">)</span></span>
195<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>Let&#39;s try it out.</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Initializing GDT [success]</span>
196<span class="line">kernel: Initializing IDT [success]</span>
197<span class="line">kernel: Creating user task</span>
198<span class="line">kernel: Initializing Syscalls [success]</span>
199<span class="line">kernel: Switching to user mode</span>
200<span class="line">syscall: num=2</span>
201<span class="line">syscall: print</span>
202<span class="line">user: Hello from user mode!</span>
203<span class="line">syscall: num=1</span>
204<span class="line">syscall: exit: code=0</span>
205<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></div><p>Great! It&#39;s nice to be able to encapsulate all the task information in a <code>Task</code> object, and to be able to create a task and switch to it with just a few lines of code.</p><p>There&#39;s one thing that I still don&#39;t like, which is that we initialize the system calls with the kernel stack of the task. The system call entry point should be able to switch to the current task&#39;s kernel stack on its own, without relying on a global variable for the kernel stack. Once we start having multiple tasks, we need to be able to switch to the kernel stack of the current task.</p><h2 id="tracking-the-current-task" tabindex="-1"><a class="header-anchor" href="#tracking-the-current-task"><span>Tracking the current task</span></a></h2><p>We can solve this problem by tracking the current task in a global variable. Let&#39;s add a <code>currentTask</code> variable to the <code>tasks</code> module, and set it in the <code>switchTo</code> proc. One thing we&#39;ll do differently here is that we&#39;ll add the <code>exportc</code> pragma to this variable, so that we can access it from inline assembly later.</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/tasks.nim</span></span>
206<span class="line"></span>
207<span class="line"><span class="token keyword">var</span></span>
208<span class="line">  currentTask<span class="token operator">*</span> <span class="token punctuation">{.</span>exportc<span class="token punctuation">.}</span><span class="token operator">:</span> Task</span>
209<span class="line"></span>
210<span class="line"><span class="token keyword">proc</span> <span class="token function">switchTo<span class="token operator">*</span></span><span class="token punctuation">(</span>task<span class="token operator">:</span> <span class="token keyword">var</span> Task<span class="token punctuation">)</span> <span class="token punctuation">{.</span>noreturn<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
211<span class="line">  currentTask <span class="token operator">=</span> task</span>
212<span class="line">  <span class="token operator">...</span></span>
213<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>Now, we can change the system call entry point to switch to the current task&#39;s kernel stack.</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/syscalls.nim</span></span>
214<span class="line"></span>
215<span class="line"><span class="token keyword">
215import</span> tasks</span>
216<span class="line"><span class="token operator">...</span></span>
217<span class="line"></span>
218<span class="line"><span class="token keyword">var</span></span>
219<span class="line">  syscallTable<span class="token operator">:</span> array<span class="token punctuation">[</span><span class="token number">256</span><span class="token punctuation">,</span> SyscallHandler<span class="token punctuation">]</span></span>
220<span class="line">  tss <span class="token punctuation">{.</span>importc<span class="token punctuation">.}</span><span class="token operator">:</span> TaskStateSegment</span>
221<span class="line highlighted">  currentTask <span class="token punctuation">{.</span>importc<span class="token punctuation">.}</span><span class="token operator">:</span> Task</span>
222<span class="line"></span>
223<span class="line"><span class="token keyword">proc</span> <span class="token function">syscallEntry</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{.</span>asmNoStackFrame<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
224<span class="line">  <span class="token keyword">asm</span> <span class="token string">&quot;&quot;&quot;</span>
225<span class="line">    # switch to kernel stack</span>
226<span class="line">    mov %0, rsp</span>
227<span class="line">    mov rsp, %1</span>
228<span class="line"></span>
229<span class="line">    ...</span>
230<span class="line"></span>
231<span class="line">    # switch to user stack</span>
232<span class="line">    mov rsp, %0</span>
233<span class="line"></span>
234<span class="line">    sysretq</span>
235<span class="line highlighted">    : &quot;+r&quot;(\`currentTask\`-&gt;rsp)</span>
236<span class="line highlighted">    : &quot;m&quot;(\`currentTask\`-&gt;kstack.bottom)</span>
237<span class="line">    : &quot;rcx&quot;, &quot;r11&quot;, &quot;rdi&quot;, &quot;rsi&quot;, &quot;rdx&quot;, &quot;rcx&quot;, &quot;r8&quot;, &quot;r9&quot;, &quot;rax&quot;</span>
238<span class="line">  &quot;&quot;&quot;</span></span>
239<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></div><p>We can now remove the argument to <code>syscallInit</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/syscalls.nim</span></span>
240<span class="line"><span class="token operator">...</span></span>
241<span class="line"></span>
242<span class="line"><span class="token keyword">proc</span> <span class="token function">syscallInit<span class="token operator">*</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span></span>
243<span class="line">  <span class="token operator">...</span></span>
244<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></div><p>And make the corresponding change in <code>KernelMainInner</code>. Also, since we don&#39;t need the kernel stack to initialize system calls anymore, we can move the call to <code>syscallInit</code> before creating the task.</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>
245<span class="line"></span>
246<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>
247<span class="line">  <span class="token operator">...</span></span>
248<span class="line"></span>
249<span class="line">  debug <span class="token string">&quot;kernel: Initializing Syscalls &quot;</span></span>
250<span class="line">  <span class="token function">syscallInit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
251<span class="line">  debugln <span class="token string">&quot;[success]&quot;</span></span>
252<span class="line"></span>
253<span class="line">  debugln <span class="token string">&quot;kernel: Creating user task&quot;</span></span>
254<span class="line">  <span class="token keyword">var</span> task <span class="token operator">=</span> <span class="token function">createTask</span><span class="token punctuation">(</span></span>
255<span class="line">
255    imageVirtAddr <span class="token operator">=</span> UserImageVirtualBase<span class="token operator">.</span>VirtAddr<span class="token punctuation">,</span></span>
256<span class="line">    imagePhysAddr <span class="token operator">=</span> bootInfo<span class="token operator">.</span>userImagePhysicalBase<span class="token operator">.</span>PhysAddr<span class="token punctuation">,</span></span>
257<span class="line">    imagePageCount <span class="token operator">=</span> bootInfo<span class="token operator">.</span>userImagePages<span class="token punctuation">,</span></span>
258<span class="line">    entryPoint <span class="token operator">=</span> UserImageVirtualBase<span class="token operator">.</span>VirtAddr</span>
259<span class="line">  <span class="token punctuation">)</span></span>
260<span class="line"></span>
261<span class="line">  debugln <span class="token string">&quot;kernel: Switching to user mode&quot;</span></span>
262<span class="line">  <span class="token function">switchTo</span><span class="token punctuation">(</span>task<span class="token punctuation">)</span></span>
263<span class="line"></span>
264<span class="line">  <span class="token operator">...</span></span>
265<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></div><p>Much simpler. Let&#39;s try it out.</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">kernel: Initializing GDT [success]</span>
266<span class="line">kernel: Initializing IDT [success]</span>
267<span class="line">kernel: Initializing Syscalls [success]</span>
268<span class="line">kernel: Creating user task</span>
269<span class="line">kernel: Switching to user mode</span>
270<span class="line">syscall: num=2</span>
271<span class="line">syscall: print</span>
272<span class="line">user: Hello from user mode!</span>
273<span class="line">syscall: num=1</span>
274<span class="line">syscall: exit: code=0</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></div><p>All good! We&#39;re in a much better place than we were before.</p><p>Ideally, we should now be able to create multiple tasks and switch between them. But, since we&#39;re creating a single address space OS, we need to be able to load tasks at different virtual addresses. So far, we&#39;ve been using a fixed virtual address for the user task; i.e., the task image is not relocatable. This means we have to link every user program at a different virtual address, which is not ideal. Traditional operating systems use a separate address space for each task, so linking the task image at a fixed virtual address is not a problem. In our case, we need to make the task image relocatable, so that we can load it at an arbitrary virtual address. That&#39;s what we&#39;ll do next.</p>`,53)]))}const c=n(t,[["render",l],["__file","19-tasks.html.vue"]]),r=JSON.parse(`{"path":"/osdev/19-tasks.html","title":"Tasks","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Task definition","slug":"task-definition","link":"#task-definition","children":[]},{"level":2,"title":"Address space abstraction","slug":"address-space-abstraction","link":"#address-space-abstraction","children":[]},{"level":2,"title":"Kernel address space","slug":"kernel-address-space","link":"#kernel-address-space","children":[]}
275,{"level":2,"title":"Creating a task","slug":"creating-a-task","link":"#creating-a-task","children":[]},{"level":2,"title":"Switching to a task","slug":"switching-to-a-task","link":"#switching-to-a-task","children":[]},{"level":2,"title":"Trying it out","slug":"trying-it-out","link":"#trying-it-out","children":[]},{"level":2,"title":"Tracking the current task","slug":"tracking-the-current-task","link":"#tracking-the-current-task","children":[]}],"git":{"updatedTime":1744638230000},"filePathRelative":"osdev/19-tasks.md","excerpt":"\\n<p>We're starting to accumulate a number of things about the user program that the kernel\\nneeds to track: the user page table, the user stack, the kernel switch stack, and the user\\n<code>rsp</code> when executing <code>syscall</code>. These are all currently tracked in global variables. Once\\nwe start having more than one user task, it will be hard to keep track of all these\\nthings.</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.