xref: /xv6-public/kalloc.c (revision 5f069dcf)
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 
12 struct run {
13   struct run *next;
14 };
15 
16 struct {
17   struct spinlock lock;
18   struct run *freelist;
19 } kmem;
20 
21 extern char end[]; // first address after kernel loaded from ELF file
22 static char *newend;
23 
24 // simple page allocator to get off the ground during entry
25 char *
26 enter_alloc(void)
27 {
28   if (newend == 0)
29     newend = end;
30 
31   if ((uint) newend >= KERNBASE + 0x400000)
32     panic("only first 4Mbyte are mapped during entry");
33   void *p = (void*)PGROUNDUP((uint)newend);
34   memset(p, 0, PGSIZE);
35   newend = newend + PGSIZE;
36   return p;
37 }
38 
39 uint
40 detect_memory(void)
41 {
42   return 0xE000000;
43 }
44 
45 // Initialize free list of physical pages.
46 void
47 kinit(void)
48 {
49   char *p;
50 
51   initlock(&kmem.lock, "kmem");
52   p = (char*)PGROUNDUP((uint)newend);
53   for(; p + PGSIZE <= (char*)p2v(PHYSTOP); p += PGSIZE)
54     kfree(p);
55 }
56 
57 //PAGEBREAK: 21
58 // Free the page of physical memory pointed at by v,
59 // which normally should have been returned by a
60 // call to kalloc().  (The exception is when
61 // initializing the allocator; see kinit above.)
62 void
63 kfree(char *v)
64 {
65   struct run *r;
66 
67   if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP)
68     panic("kfree");
69 
70   // Fill with junk to catch dangling refs.
71   memset(v, 1, PGSIZE);
72 
73   acquire(&kmem.lock);
74   r = (struct run*)v;
75   r->next = kmem.freelist;
76   kmem.freelist = r;
77   release(&kmem.lock);
78 }
79 
80 // Allocate one 4096-byte page of physical memory.
81 // Returns a pointer that the kernel can use.
82 // Returns 0 if the memory cannot be allocated.
83 char*
84 kalloc(void)
85 {
86   struct run *r;
87 
88   acquire(&kmem.lock);
89   r = kmem.freelist;
90   if(r)
91     kmem.freelist = r->next;
92   release(&kmem.lock);
93   return (char*)r;
94 }
95 
96