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