0
|
1 // Physical memory allocator, intended to allocate
|
|
2 // memory for user processes, kernel stacks, page table pages,
|
|
3 // and pipe buffers. Allocates 4096-byte pages.
|
|
4
|
|
5 #include "types.h"
|
|
6 #include "defs.h"
|
|
7 #include "param.h"
|
|
8 #include "memlayout.h"
|
|
9 #include "mmu.h"
|
|
10 #include "spinlock.h"
|
|
11 #include "arm.h"
|
|
12
|
|
13 void freerange(void *vstart, void *vend);
|
|
14 extern char end[]; // first address after kernel loaded from ELF file
|
|
15
|
|
16 struct run {
|
|
17 struct run *next;
|
|
18 };
|
|
19
|
|
20 static struct {
|
|
21 struct spinlock lock;
|
|
22 int use_lock;
|
|
23 struct run *freelist;
|
|
24 } kmem;
|
|
25
|
|
26 void kmem_init (void)
|
|
27 {
|
|
28 initlock(&kmem.lock, "kmem");
|
|
29 kmem.use_lock = 0;
|
|
30 }
|
|
31
|
|
32 // Initialization happens in two phases.
|
|
33 // 1. main() calls kinit1() while still using entrypgdir to place just
|
|
34 // the pages mapped by entrypgdir on free list.
|
|
35 // 2. main() calls kinit2() with the rest of the physical pages
|
|
36 // after installing a full page table that maps them on all cores.
|
|
37 void kinit1(void *vstart, void *vend)
|
|
38 {
|
|
39 freerange(vstart, vend);
|
|
40 }
|
|
41
|
|
42 void kinit2(void *vstart, void *vend)
|
|
43 {
|
|
44 freerange(vstart, vend);
|
|
45 kmem.use_lock = 1;
|
|
46 }
|
|
47
|
|
48 void freerange(void *vstart, void *vend)
|
|
49 {
|
|
50 char *p;
|
|
51
|
|
52 p = (char*)align_up (vstart, PTE_SZ);
|
|
53
|
|
54 for(; p + PTE_SZ <= (char*)vend; p += PTE_SZ) {
|
|
55 kfree(p);
|
|
56 }
|
|
57 }
|
|
58
|
|
59 //PAGEBREAK: 21
|
|
60 // Free the page of physical memory pointed at by v,
|
|
61 // which normally should have been returned by a
|
|
62 // call to kalloc(). (The exception is when
|
|
63 // initializing the allocator; see kinit above.)
|
|
64 void kfree(char *v)
|
|
65 {
|
|
66 struct run *r;
|
|
67
|
|
68 if((uint)v % PTE_SZ || v < end || v2p(v) >= PHYSTOP) {
|
|
69 cprintf("kfree(0x%x)\n", v);
|
|
70 panic("kfree");
|
|
71 }
|
|
72
|
|
73 // Fill with junk to catch dangling refs.
|
|
74 //memset(v, 0x00, PG_SIZE);
|
|
75
|
|
76 if(kmem.use_lock) {
|
|
77 acquire(&kmem.lock);
|
|
78 }
|
|
79
|
|
80 r = (struct run*)v;
|
|
81 r->next = kmem.freelist;
|
|
82 kmem.freelist = r;
|
|
83
|
|
84 if(kmem.use_lock) {
|
|
85 release(&kmem.lock);
|
|
86 }
|
|
87 }
|
|
88
|
|
89 // Allocate one 4096-byte page of physical memory.
|
|
90 // Returns a pointer that the kernel can use.
|
|
91 // Returns 0 if the memory cannot be allocated.
|
|
92 char* kalloc(void)
|
|
93 {
|
|
94 struct run *r;
|
|
95
|
|
96 if(kmem.use_lock) {
|
|
97 acquire(&kmem.lock);
|
|
98 }
|
|
99
|
|
100 r = kmem.freelist;
|
|
101
|
|
102 if(r) {
|
|
103 kmem.freelist = r->next;
|
|
104 }
|
|
105
|
|
106 if(kmem.use_lock) {
|
|
107 release(&kmem.lock);
|
|
108 }
|
|
109
|
|
110 return (char*)r;
|
|
111 }
|