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