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 char *newend; 23 24 // simple page allocator to get off the ground during boot 25 char * 26 pgalloc(void) 27 { 28 if (newend == 0) 29 newend = end; 30 31 void *p = (void*)PGROUNDUP((uint)newend); 32 memset(p, 0, PGSIZE); 33 newend = newend + PGSIZE; 34 return p; 35 } 36 37 // Initialize free list of physical pages. 38 void 39 kinit(void) 40 { 41 char *p; 42 43 initlock(&kmem.lock, "kmem"); 44 p = (char*)PGROUNDUP((uint)newend); 45 for(; p + PGSIZE <= (char*)p2v(PHYSTOP); p += PGSIZE) 46 kfree(p); 47 } 48 49 //PAGEBREAK: 21 50 // Free the page of physical memory pointed at by v, 51 // which normally should have been returned by a 52 // call to kalloc(). (The exception is when 53 // initializing the allocator; see kinit above.) 54 void 55 kfree(char *v) 56 { 57 struct run *r; 58 59 if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP) 60 panic("kfree"); 61 62 // Fill with junk to catch dangling refs. 63 memset(v, 1, PGSIZE); 64 65 acquire(&kmem.lock); 66 r = (struct run*)v; 67 r->next = kmem.freelist; 68 kmem.freelist = r; 69 release(&kmem.lock); 70 } 71 72 // Allocate one 4096-byte page of physical memory. 73 // Returns a pointer that the kernel can use. 74 // Returns 0 if the memory cannot be allocated. 75 char* 76 kalloc(void) 77 { 78 struct run *r; 79 80 acquire(&kmem.lock); 81 r = kmem.freelist; 82 if(r) 83 kmem.freelist = r->next; 84 release(&kmem.lock); 85 cprintf("kalloc: 0x%x\n", r); 86 return (char*)r; 87 } 88 89