1 /******************************************************************************
2 * Copyright (c) 2013 IBM Corporation
4 * This program and the accompanying materials
5 * are made available under the terms of the BSD License
6 * which accompanies this distribution, and is available at
7 * http://www.opensource.org/licenses/bsd-license.php
10 * IBM Corporation - initial implementation
11 *****************************************************************************/
13 * All functions concerning interface to slof
24 #define dprintf(_x ...) do { printf ("%s: ", __func__); printf(_x); } while (0);
26 #define dprintf(_x ...)
29 #define DEFAULT_BLOCK_SIZE 4096
31 #define BM_WORD_SIZE (sizeof(unsigned long))
32 #define BM_WORD_BITS (BM_WORD_SIZE * 8)
37 unsigned long bm_size;
38 unsigned long block_size;
39 unsigned long free_blocks;
43 #define BIT(x) (1UL << x)
44 #define BM_WORD(bmw, n) (bmw[n/BM_WORD_BITS])
45 #define BM_WORD_MODULO(n) (n % BM_WORD_BITS)
46 #define BM_NUM_BITS(reqsize, bsize) ((reqsize / bsize) + (reqsize % bsize? 1 : 0))
48 void bm_clear_bit(unsigned long *bmw, int n)
50 BM_WORD(bmw, n) &= ~BIT(BM_WORD_MODULO(n));
53 void bm_set_bit(unsigned long *bmw, int n)
55 BM_WORD(bmw, n) |= BIT(BM_WORD_MODULO(n));
58 bool bm_test_bit(unsigned long *bmw, int n)
61 //printf("BMW %x, bitpos %d, value %d\n", &BM_WORD(bmw, n), n, !!(BM_WORD(bmw, n) & BIT(BM_WORD_MODULO(n))));
63 return !!(BM_WORD(bmw, n) & BIT(BM_WORD_MODULO(n)));
66 /* Improvement: can use FFS routines to get faster results */
67 int bm_find_bits(struct bitmap *bm, unsigned int n_bits)
69 unsigned int i, j, total_bits;
71 dprintf("Finding %d bits set\n", n_bits);
72 total_bits = BM_NUM_BITS(bm->size, bm->block_size);
73 for(i = 0; i < total_bits; i++) {
74 if (!bm_test_bit(bm->bmw, i))
76 /* we have hit the boundary now, give up */
77 if (i + n_bits > total_bits)
79 /* Lets find if we have consecutive bits set */
80 for(j = i; j < (i + n_bits); j++) {
81 if (!bm_test_bit(bm->bmw, (j)))
85 if (j == (i + n_bits)) {
93 void SLOF_bm_print(unsigned long handle)
101 bm = (struct bitmap *) handle;
102 printf("BITMAP: start %lx, size %ld, blocksize %ld\n\n",
103 bm->start, bm->size, bm->block_size);
104 printf("0 16 32 48 63\n");
105 for(i = 0; i < BM_NUM_BITS(bm->size, bm->block_size); i++) {
106 if (i > 0 && (i % 64 == 0))
108 else if (i > 0 && (i % 8 == 0))
110 printf("%d", bm_test_bit(bm->bmw, i));
115 unsigned long SLOF_bm_allocator_init(unsigned long start, unsigned long size,
116 unsigned long blocksize)
119 unsigned long alloc_size, bm_size, n_bits;
121 dprintf("enter start %x, size %d, block-size %d\n", start, size, blocksize);
126 blocksize = DEFAULT_BLOCK_SIZE;
128 n_bits = BM_NUM_BITS(size, blocksize);
129 bm_size = (n_bits / BM_WORD_BITS) + ((n_bits % BM_WORD_BITS)? 1 : 0);
130 alloc_size = sizeof(struct bitmap) + bm_size * BM_WORD_SIZE;
131 dprintf("Size %ld, blocksize %ld, bm_size %ld, alloc_size %ld\n",
132 size, blocksize, bm_size, alloc_size);
133 bm = (struct bitmap *) SLOF_alloc_mem(alloc_size);
138 bm->bm_size = bm_size;
139 bm->block_size = blocksize;
140 bm->free_blocks = n_bits;
141 memset(bm->bmw, 0xFF, bm_size*BM_WORD_SIZE);
142 return (unsigned long)bm;
145 unsigned long SLOF_bm_alloc(unsigned long handle, unsigned long size)
148 unsigned long n_bits;
156 bm = (struct bitmap *) handle;
158 n_bits = BM_NUM_BITS(size, bm->block_size);
159 if (n_bits > bm->free_blocks)
162 bitpos = bm_find_bits(bm, n_bits);
166 dprintf("BMW %d, bitpos %d\n", i, bitpos);
167 dprintf("size %d, block_size %d, n_bits %d\n", size, bm->block_size, n_bits);
168 for(i = bitpos; i < (bitpos + n_bits); i++) {
170 if (!bm_test_bit(bm->bmw, i))
171 dprintf("Warning: Bit already in use: %d\n", i);
173 bm_clear_bit(bm->bmw, i);
175 bm->free_blocks -= n_bits;
176 addr = bm->start + bitpos * bm->block_size;
177 dprintf("BMW %d, bitpos %d addr %lx free_blocks %d\n", i, bitpos, addr, bm->free_blocks);
181 void SLOF_bm_free(unsigned long handle, unsigned long ptr, unsigned long size)
184 unsigned long bitpos, n_bits;
191 bm = (struct bitmap *) handle;
192 addr = (unsigned long ) ptr;
193 n_bits = BM_NUM_BITS(size, bm->block_size);
194 if (addr < bm->start || (bm->start + bm->size) < (addr + size)) {
195 printf("Error: Bitmap start %lx, size %ld, requested address %lx, size %ld\n",
196 bm->start, bm->size, addr, size);
199 bitpos = (addr - bm->start) / bm->block_size;
200 bm->free_blocks += n_bits;
203 dprintf("addr %lx, bitpos %d\n", addr, bitpos);
204 dprintf("size %d, block_size %d, n_bits %d, free_blocks %d\n", size, bm->block_size, n_bits, bm->free_blocks);
205 if (addr % bm->block_size) {
206 dprintf("Warning: Address not aligned addr %lx\n", addr);
210 for(i = bitpos; i < (bitpos + n_bits); i++) {
212 if (bm_test_bit(bm->bmw, i))
213 dprintf("Warning: Bit already set: %d\n", i);
215 bm_set_bit(bm->bmw, i);