voron

experimental ARM OS
git clone git://git.2f30.org/voron
Log | Files | Refs | README | LICENSE

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 }