/* test module for layered bitmaps */ #include #include #include #include #include #include #define VIRT_SIZE SZ_2G #define L1_BM_SEG_SIZE 0x8000000 /* 128MB */ #define L1_BM_NUM_SEGS (VIRT_SIZE / L1_BM_SEG_SIZE) #define L1_BM_BITS L1_BM_NUM_SEGS /* 16 bits */ #define L2_BM_BITS (L1_BM_SEG_SIZE >> PAGE_SHIFT) #define L2_BM_SIZE L1_BM_SEG_SIZE #define L2_BM_LONGS ((L2_BM_BITS + BITS_PER_LONG - 1) / BITS_PER_LONG) static unsigned long bm_l1 = 0x0000; static unsigned long *bm_l2; static unsigned long next_off = 0x0; #define start_addr 0x80000000 static unsigned long test_find_free_region(unsigned long size) { int l1_off, l2_off; unsigned long addr = 0x0; unsigned int order; unsigned long *tmp_bm; if (size > L1_BM_SEG_SIZE) { printk(KERN_ERR "size greater than 128MB is not allowed\n"); return -EINVAL; } order = get_order(size); next_block: l1_off = find_next_zero_bit(&bm_l1, L1_BM_BITS, next_off); if (l1_off >= L1_BM_BITS) { printk(KERN_ERR "layer1 bitmap is full\n"); return -EINVAL; } tmp_bm = bm_l2 + (l1_off * L2_BM_LONGS); l2_off = bitmap_find_free_region(tmp_bm, 32768 /* L2_BM_SIZE */, order); printk(KERN_INFO "l1_off %d l2_off %d\n", l1_off, l2_off); if (l2_off < 0) { next_off = (l1_off >= L1_BM_BITS) ? 0 : (next_off + 1); if (bitmap_full(tmp_bm, L2_BM_SIZE /*L2_BM_BITS*/)) { set_bit(l1_off, &bm_l1); } printk(KERN_INFO "go to next_block %ld\n", next_off); goto next_block; } if (bitmap_full(tmp_bm, L2_BM_SIZE /*L2_BM_BITS*/)) { set_bit(l1_off, &bm_l1); } addr = (l1_off * L1_BM_SEG_SIZE) + (l2_off << PAGE_SHIFT); return (addr + start_addr); } static int __init test_alloc_init(void) { /*required ulongs for storage of nr_bits */ unsigned int size = (L2_BM_BITS + (BITS_PER_LONG - 1)) / BITS_PER_LONG; unsigned long addr; /* sixteen 128MB layer 2 bitmaps */ bm_l2 = kzalloc(size * L1_BM_NUM_SEGS, GFP_KERNEL); if (!bm_l2) { printk(KERN_INFO "No memory...\n"); return -EINVAL; } addr = test_find_free_region(SZ_64M); printk(KERN_INFO "addr is 0x%lx\n", addr); addr = test_find_free_region(SZ_64M + SZ_32M); printk(KERN_INFO "addr is 0x%lx\n", addr); addr = test_find_free_region(SZ_128M); printk(KERN_INFO "addr is 0x%lx\n", addr); return 0; } static void __exit test_alloc_exit(void) { /* TODO: care to free allocations :) */ } module_init(test_alloc_init); module_exit(test_alloc_exit); MODULE_LICENSE("GPL");