mm.c (3492B)
1 #include <kernel.h> 2 #include <mmu.h> 3 4 #define ALIGN32(x) (((x) + 31) & ~31) 5 6 extern void *_ram_start; 7 extern void *_ram_end; 8 extern void *_kernel_bin_start; 9 extern void *_kernel_bin_end; 10 extern void *_kernel_heap_start; 11 extern void *_kernel_heap_end; 12 13 static u32 *bitmap; 14 static uint_t bitmapsz; 15 static uint_t kbound_s; 16 static uint_t kbound_e; 17 static uint_t kheapbound_s; 18 static uint_t kheapbound_e; 19 20 /* set range of bits */ 21 static int 22 set_bitmap_bits(uint_t start_bit, uint_t n, int flag) 23 { 24 uint_t bound_s, bound_e, i; 25 u32 bits; 26 27 if (n == 0) 28 return -EINVAL; 29 30 bound_s = start_bit; 31 bound_e = start_bit + n; 32 33 if (bound_e > bitmapsz * 32) 34 return -EINVAL; 35 36 if (bound_s / 32 != bound_e / 32) { 37 bits = ~((1 << (bound_s % 32)) - 1); 38 if (flag) 39 bitmap[bound_s/32] |= bits; 40 else 41 bitmap[bound_s/32] &= ~bits; 42 43 bits = (1 << (bound_e % 32)) - 1; 44 if (flag) 45 bitmap[bound_e/32] |= bits; 46 else 47 bitmap[bound_e/32] &= ~bits; 48 } else { 49 bits = ~((1 << (bound_s % 32)) - 1); 50 bits &= (1 << (bound_e % 32)) - 1; 51 if (flag) 52 bitmap[bound_s/32] |= bits; 53 else 54 bitmap[bound_s/32] &= ~bits; 55 } 56 57 for (i = (bound_s / 32) + 1; i < bound_e / 32; i++) { 58 if (flag) 59 bitmap[i] = ~0U; 60 else 61 bitmap[i] = 0; 62 } 63 64 return 0; 65 } 66 67 void 68 mm_init() 69 { 70 uint_t i; 71 size_t ramsz; 72 73 kbound_s = PAGE_ALIGN(PTR_DIFF(&_kernel_bin_start, &_ram_start)) >> PAGE_SHIFT; 74 kbound_e = PAGE_ALIGN(PTR_DIFF(&_kernel_bin_end, &_ram_start)) >> PAGE_SHIFT; 75 kheapbound_s = PAGE_ALIGN(PTR_DIFF(&_kernel_heap_start, &_ram_start)) >> PAGE_SHIFT; 76 kheapbound_e = PAGE_ALIGN(PTR_DIFF(&_kernel_heap_end, &_ram_start)) >> PAGE_SHIFT; 77 78 ramsz = PTR_DIFF(&_ram_end, &_ram_start) + 1; 79 bitmapsz = ALIGN32(ramsz >> PAGE_SHIFT) / 32; 80 bitmap = (u32*)&_kernel_bin_end; 81 kbound_e += PAGE_ALIGN(bitmapsz * 4) >> PAGE_SHIFT; 82 83 for (i = 0; i < bitmapsz; i++) 84 bitmap[i] = 0; 85 86 set_bitmap_bits(kbound_s, kheapbound_s - kbound_s, 1); 87 set_bitmap_bits(kheapbound_e, kbound_e - kheapbound_e, 1); 88 89 mmu_init(); 90 91 /* map on-chip memory */ 92 mmu_map_page((void*)0x40000000, (void*)0x40000000, 93 0x40000, MMU_AP_RW_NONE); 94 /* map kernel memory */ 95 mmu_map_page(&_kernel_bin_start, &_kernel_bin_start, 96 kheapbound_s - kbound_s, MMU_AP_RW_NONE); 97 mmu_map_page(&_kernel_heap_end, &_kernel_heap_end, 98 kbound_e - kheapbound_e, MMU_AP_RW_NONE); 99 100 mmu_enable(); 101 } 102 103 void * 104 palloc(uint_t npages) 105 { 106 uint_t i, j, n; 107 uint_t sbit; 108 int ret; 109 110 if (npages == 0) 111 return ERR_PTR(-EINVAL); 112 113 n = 0; 114 for (i = 0; i < bitmapsz; i++) { 115 /* if bitmap[i] has unallocated page */ 116 if (bitmap[i] != ~0U) { 117 for (j = 0; j < 32; j++) { 118 if (n > 0 && (bitmap[i] & (1 << j))) 119 n = 0; 120 else if (!(bitmap[i] & (1 << j))) 121 n++; 122 if (n == npages) { 123 sbit = i * 32 + j - n + 1; 124 goto out; 125 } 126 } 127 } else 128 n = 0; 129 } 130 131 return ERR_PTR(-EINVAL); 132 133 out: 134 ret = set_bitmap_bits(sbit, npages, 1); 135 if (ret < 0) 136 return ERR_PTR(ret); 137 return (void*)((uintptr_t)sbit * PAGE_SIZE + (uintptr_t)&_ram_start); 138 } 139 140 int 141 pfree(void *paddr, uint_t npages) 142 { 143 uintptr_t paddr_a = (uintptr_t)paddr; 144 uint_t sbit; 145 146 if (npages == 0 || paddr_a & (PAGE_SIZE - 1) || 147 paddr_a < (uintptr_t)&_ram_start || 148 paddr_a >= (uintptr_t)&_ram_end) 149 return -EINVAL; 150 151 sbit = (paddr_a - (uintptr_t)&_ram_start) >> PAGE_SHIFT; 152 153 /* we cannot free the memory of ourself */ 154 if ((sbit >= kbound_s && sbit < kheapbound_s) || 155 (sbit >= kheapbound_e && sbit < kbound_e)) 156 return -EINVAL; 157 158 return set_bitmap_bits(sbit, npages, 0); 159 }