Memory virtualization


In the beginning …

Early systems
Multiprogramming and time sharing

Multiprogramming and time sharing

Recall: Running one process at a time with full memory access
System event Size Latency
CPU   <1ns
L1 cache 32KB 1ns
L2 cache 256KB 4ns
L3 cache >8MB 40ns
DDR RAM 4GB-1TB 80ns
What we want to do

Address space

- __Address high to low__
- __Address low to high__
*Image taken from [Geeksforgeeks](https://www.geeksforgeeks.org/memory-layout-of-c-program/)*

Hands on: Where the stack grows?

stacktest.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// user/stacktest.c
#include "kernel/types.h"
#include "user/user.h"

void f2() {
int a = 5, b = 6;
printf("In f2: &a = 0x%lx, &b = 0x%lx\n", (uint64)&a, (uint64)&b);
}

void f1() {
int x = 3, y = 4;
int arr[5];
printf("In f1: &x = 0x%lx, &y = 0x%lx\n", (uint64)&x, (uint64)&y);
printf("Address of arr       = 0x%lx\n", (uint64)arr);
printf("Address of arr[0]    = 0x%lx\n", (uint64)&arr[0]);
printf("Address of arr[1]    = 0x%lx\n", (uint64)&arr[1]);  f2();
}

int main() {
int m = 1, n = 2;
printf("In main: &m = 0x%lx, &n = 0x%lx\n", (uint64)&m, (uint64)&n);
f1();
exit(0);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
stacktest

<details class="details details--default" data-variant="default"><summary>Observe and discuss output</summary>
<figure>
  <picture>
    <!-- Auto scaling with imagemagick -->
    <!--
      See https://www.debugbear.com/blog/responsive-images#w-descriptors-and-the-sizes-attribute and
      https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images for info on defining 'sizes' for responsive images
    -->
    
      
        <source class="responsive-img-srcset" srcset="/assets/img/courses/csc331/memory-virtualization/05-480.webp 480w,/assets/img/courses/csc331/memory-virtualization/05-800.webp 800w,/assets/img/courses/csc331/memory-virtualization/05-1400.webp 1400w," type="image/webp" sizes="95vw" />
      
    
    <img src="/assets/img/courses/csc331/memory-virtualization/05.png" width="50%" height="auto" data-zoomable="" loading="lazy" onerror="this.onerror=null; $('.responsive-img-srcset').remove();" />
  </picture>

  
</figure>

</details>
---

## Hands on: where the heap grows?


- Create `arraytest.c` inside the `user` directory, rebuild xv6.  

<details class="details details--default" data-variant="default"><summary>arraytest.c</summary>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre><span class="c1">// user/arraytest.c</span>
<span class="cp">#include</span> <span class="cpf">"kernel/types.h"</span><span class="cp">
#include</span> <span class="cpf">"user/user.h"</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">arr</span><span class="p">[</span><span class="mi">10</span><span class="p">];</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[Stack]  &amp;arr[0]     = 0x%lx</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="n">uint64</span><span class="p">)</span><span class="o">&amp;</span><span class="n">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>

<span class="kt">int</span> <span class="o">*</span><span class="n">h1</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">sbrk</span><span class="p">(</span><span class="mi">10</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">h2</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">sbrk</span><span class="p">(</span><span class="mi">10</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">h3</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span><span class="n">sbrk</span><span class="p">(</span><span class="mi">10</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">));</span>

<span class="n">printf</span><span class="p">(</span><span class="s">"[Heap]   h1          = 0x%016lx</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="n">uint64</span><span class="p">)</span><span class="n">h1</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[Heap]   h2          = 0x%016lx</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="n">uint64</span><span class="p">)</span><span class="n">h2</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[Heap]   h3          = 0x%016lx</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="n">uint64</span><span class="p">)</span><span class="n">h3</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>

</details>
- Run `arraytest`. 

~~~bash
arraytest
Observe and discuss output
How the heap grows
Acknowledgement

This section is developed based on Ellis Weaverkreider’s question in Fall 2025

uvmalloc
1
uint64 uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm)
Stack: exec.c/kexec()
Heap: sysproc.c/sys_sbrk()
Linux comparison
1
2
3
/* Do this so that we can load the interpreter, if need be.  We will
change some of these later */
retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), executable_stack);

What is address space, really?


Goals of memory virtualization