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