1f5527388Srsc // Physical memory allocator, intended to allocate 27d7dc933SRobert Morris // memory for user processes, kernel stacks, page table pages, 37d7dc933SRobert Morris // and pipe buffers. Allocates 4096-byte pages. 455e95b16Srtm 555e95b16Srtm #include "types.h" 655e95b16Srtm #include "defs.h" 78148b6eeSrtm #include "param.h" 840889627SFrans Kaashoek #include "mmu.h" 94e8f237bSrtm #include "spinlock.h" 104e8f237bSrtm 1155e95b16Srtm struct run { 1255e95b16Srtm struct run *next; 1355e95b16Srtm }; 1434295f46Srsc 1534295f46Srsc struct { 1634295f46Srsc struct spinlock lock; 1755e95b16Srtm struct run *freelist; 1834295f46Srsc } kmem; 1955e95b16Srtm 204587b358SRobert Morris extern char end[]; // first address after kernel loaded from ELF file 214587b358SRobert Morris 22f5527388Srsc // Initialize free list of physical pages. 2355e95b16Srtm void 248d774afbSRobert Morris kinit(void) 2555e95b16Srtm { 26*1a81e38bSRuss Cox char *p; 27*1a81e38bSRuss Cox 2834295f46Srsc initlock(&kmem.lock, "kmem"); 29*1a81e38bSRuss Cox p = (char*)PGROUNDUP((uint)end); 303597d5dcSRobert Morris for(; p + PGSIZE - 1 < (char*)PHYSTOP; p += PGSIZE) 313597d5dcSRobert Morris kfree(p); 3255e95b16Srtm } 3355e95b16Srtm 345048762cSAustin Clements //PAGEBREAK: 21 357d7dc933SRobert Morris // Free the page of physical memory pointed at by v, 3631085bb4Srsc // which normally should have been returned by a 377d7dc933SRobert Morris // call to kalloc(). (The exception is when 3831085bb4Srsc // initializing the allocator; see kinit above.) 3955e95b16Srtm void 407d7dc933SRobert Morris kfree(char *v) 4155e95b16Srtm { 427d7dc933SRobert Morris struct run *r; 4355e95b16Srtm 44*1a81e38bSRuss Cox if((uint)v % PGSIZE || v < end || (uint)v >= PHYSTOP) 4555e95b16Srtm panic("kfree"); 4655e95b16Srtm 47d4c64e5dSrsc // Fill with junk to catch dangling refs. 487d7dc933SRobert Morris memset(v, 1, PGSIZE); 498b4e2a08Srtm 5034295f46Srsc acquire(&kmem.lock); 517d7dc933SRobert Morris r = (struct run*)v; 527d7dc933SRobert Morris r->next = kmem.freelist; 537d7dc933SRobert Morris kmem.freelist = r; 5434295f46Srsc release(&kmem.lock); 5555e95b16Srtm } 5655e95b16Srtm 577d7dc933SRobert Morris // Allocate one 4096-byte page of physical memory. 587d7dc933SRobert Morris // Returns a pointer that the kernel can use. 59f5527388Srsc // Returns 0 if the memory cannot be allocated. 6055e95b16Srtm char* 61*1a81e38bSRuss Cox kalloc(void) 6255e95b16Srtm { 637d7dc933SRobert Morris struct run *r; 6455e95b16Srtm 6534295f46Srsc acquire(&kmem.lock); 667d7dc933SRobert Morris r = kmem.freelist; 677d7dc933SRobert Morris if(r) 687d7dc933SRobert Morris kmem.freelist = r->next; 6934295f46Srsc release(&kmem.lock); 707d7dc933SRobert Morris return (char*)r; 7155e95b16Srtm } 7240889627SFrans Kaashoek 73