一. 内核启动时保留内存
start_kernel
--> setup_arch
-->arm_memblock_init
--> rk30_reserve
在内核启动时会保留一部分内存
在arch/arm/mach-rk3188/board-rk3188-ds1006h.c中
-
static void __init rk30_reserve(void)
-
{
-
//保存在变量 rk30_ion_pdata.heaps[0].base 中
-
rk30_ion_pdata.heaps[0].base = board_mem_reserve_add("ion", ION_RESERVE_SIZE);
-
}
bank.start=0x60000000, size=0x36800000
reserved_base_end就是内存的结束地址: 0x6000000+0x36800000=0x96800000
-
phys_addr_t __init board_mem_reserve_add(char *name, size_t size)
-
{
-
phys_addr_t base = 0;
-
if(reserved_base_end == 0)
-
reserved_base_end = meminfo.bank[0].start + meminfo.bank[0].size;
-
reserved_size += size;
-
base = reserved_base_end - reserved_size;
-
-
return base;
-
}
分配内存之后base=内存结束地址-80M=0x96800000-0x5000000=0x91800000
memory reserve: Memory(base:0x91800000 size:80M) reserved for
二. ION驱动的初始化
2.1 platform_device
在arch/arm/mach-rk3188/board-rk3188-ds1006h.c中
-
static struct ion_platform_data rk30_ion_pdata = {
-
.nr = 1,
-
.heaps = {
-
{
-
.type = ION_HEAP_TYPE_CARVEOUT, //reserve memory:这是在保留内存块中分配内存
-
.id = ION_NOR_HEAP_ID,
-
.name = "norheap",
-
.size = ION_RESERVE_SIZE,
-
}
-
},
-
};
-
-
static struct platform_device device_ion = {
-
.name = "ion-rockchip",
-
.id = 0,
-
.dev = {
-
.platform_data = &rk30_ion_pdata,
-
},
-
};
2.2 platform_driver
cong@ubuntu:/rk/rk3188/kernel/drivers/gpu$ tree
├── ion
│ ├── ion.c
│ ├── ion_carveout_heap.c
│ ├── ion_heap.c
│ ├── ion_priv.h
│ ├── ion_system_heap.c
│ ├── ion_system_mapper.c
│ └── rockchip
│ └── rockchip_ion.c
└── Makefile
module_init(ion_init);
--> ion_init
-
static struct platform_driver ion_driver = {
-
.probe = rockchip_ion_probe,
-
.remove = rockchip_ion_remove,
-
.driver = { .name = "ion-rockchip" }
-
};
-
-
static int __init ion_init(void)
-
{
-
return platform_driver_register(&ion_driver);
-
}
module_init(ion_init);
--> ion_init
--> rockchip_ion_probe
-
static int rockchip_ion_probe(struct platform_device *pdev)
-
{
-
struct ion_device *idev;
-
struct ion_platform_data *pdata = pdev->dev.platform_data;
-
-
num_heaps = pdata->nr; //num_heaps =1
-
heaps = kzalloc(sizeof(struct ion_heap *) * pdata->nr, GFP_KERNEL);
-
-
idev = ion_device_create(rockchip_custom_ioctl);
-
-
for (i = 0; i < num_heaps; i++) {
-
struct ion_platform_heap *heap_data = &pdata->heaps[i];
-
heaps[i] = ion_heap_create(heap_data);
-
ion_device_add_heap(idev, heaps[i]);
-
}
-
platform_set_drvdata(pdev, idev);
-
return 0;
-
}
rockchip_ion_probe
--> ion_device_create
在drivers/gpu/ion/ion.c中
-
struct ion_device *ion_device_create(long (*custom_ioctl)(struct ion_client *client, unsigned int cmd, unsigned long arg))
-
{
-
struct ion_device *idev;
-
idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL);
-
idev->dev.minor = MISC_DYNAMIC_MINOR;
-
idev->dev.name = "ion";
-
idev->dev.fops = &ion_fops;
-
idev->dev.parent = NULL;
-
ret = misc_register(&idev->dev);
-
-
idev->debug_root = debugfs_create_dir("ion", NULL);
-
-
idev->custom_ioctl = custom_ioctl;
-
idev->buffers = RB_ROOT;
-
mutex_init(&idev->lock);
-
idev->heaps = RB_ROOT;
-
idev->user_clients = RB_ROOT;
-
idev->kernel_clients = RB_ROOT;
-
debugfs_create_file("leak", 0664, idev->debug_root, idev, &debug_leak_fops);
-
return idev;
-
}
rockchip_ion_probe
--> ion_heap_create
-
struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
-
{
-
struct ion_heap *heap = NULL;
-
-
switch (heap_data->type) {
-
case ION_HEAP_TYPE_SYSTEM_CONTIG: //通过kmalloc分配内存
-
heap = ion_system_contig_heap_create(heap_data);
-
break;
-
case ION_HEAP_TYPE_SYSTEM: //通过vmalloc分配内存
-
heap = ion_system_heap_create(heap_data);
-
break;
-
case ION_HEAP_TYPE_CARVEOUT: //在保留内存块中(reserve memory)分配内存
-
heap = ion_carveout_heap_create(heap_data);
-
break;
-
default:
-
pr_err("%s: Invalid heap type %d\n", __func__, heap_data->type);
-
return ERR_PTR(-EINVAL);
-
}
-
heap->name = heap_data->name;
-
heap->id = heap_data->id;
-
return heap;
-
}
rockchip_ion_probe
--> ion_heap_create
--> ion_carveout_heap_create
在drivers/gpu/ion/ion_heap.c中
-
struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
-
{
-
struct ion_carveout_heap *carveout_heap;
-
-
carveout_heap = kzalloc(sizeof(struct ion_carveout_heap), GFP_KERNEL);
-
-
carveout_heap->pool = gen_pool_create(12, -1);
-
carveout_heap->base = heap_data->base; //系统保留的物理地址base=0x91800000
-
// 向内存池中加入内存块,起始地址base=0x918000000,size=0x50000000=80M
gen_pool_add(carveout_heap->pool, carveout_heap->base, heap_data->size, -1);
-
carveout_heap->heap.ops = &carveout_heap_ops;
-
carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
-
carveout_heap->heap.allocated_size = 0;
-
carveout_heap->heap.max_allocated = 0;
-
carveout_heap->heap.total_size = heap_data->size; // size=0x5000000=80M
-
//内存的映射位图: 每个bit代表1个PAGE
-
carveout_heap->bit_nr = heap_data->size/(PAGE_SIZE * sizeof(unsigned long) * 8);
-
carveout_heap->bits = (unsigned long *)kzalloc(carveout_heap->bit_nr * sizeof(unsigned long), GFP_KERNEL);
-
-
return &carveout_heap->heap;
-
}
rockchip_ion_probe
--> ion_device_add_heap
-
void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
-
{
-
struct rb_node **p = &dev->heaps.rb_node;
-
struct rb_node *parent = NULL;
-
struct ion_heap *entry;
-
-
heap->dev = dev;
-
mutex_lock(&dev->lock);
-
while (*p) {
-
parent = *p;
-
entry = rb_entry(parent, struct ion_heap, node);
-
-
if (heap->id < entry->id) {
-
p = &(*p)->rb_left;
-
} else if (heap->id > entry->id ) {
-
p = &(*p)->rb_right;
-
} else {
-
pr_err("%s: can not insert multiple heaps with id %d\n", __func__, heap->id);
-
goto end;
-
}
-
}
-
-
rb_link_node(&heap->node, parent, p);
-
rb_insert_color(&heap->node, &dev->heaps);
-
debugfs_create_file(heap->name, 0664, dev->debug_root, heap, &debug_heap_fops);
-
end:
-
mutex_unlock(&dev->lock);
-
}
三. ION分配内存的过程
drivers/gpu/ion/ion.c --> ion_ioctl //cmd=0xc0104900 接收到命令:ION_IOC_ALLOC
--> ion_alloc
--> ion_carveout_heap_allocate
--> drivers/gpu/ion/ion_carveout_heap.c 调用 ion_carveout_allocate[47]:
-
static int ion_carveout_heap_allocate(struct ion_heap *heap,
-
struct ion_buffer *buffer, unsigned long size, unsigned long align, unsigned long flags)
-
{
-
buffer->priv_phys = ion_carveout_allocate(heap, size, align); //buffer->priv_phy=0x91a00000是物理地址
-
return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0;
-
}
ion_carveout_heap_allocate
-->
ion_carveout_allocate
在drivers/gpu/ion/ion_carverout_heap.c中
-
ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size, unsigned long align)
-
{
-
struct ion_carveout_heap *carveout_heap = container_of(heap, struct ion_carveout_heap, heap);
-
unsigned long offset = gen_pool_alloc(carveout_heap->pool, size); //offset=0x91a00000,是物理地址
-
-
heap->allocated_size += size; //统计己分配的大小
-
//防止越界
-
if((offset + size - carveout_heap->base) > heap->max_allocated)
-
heap->max_allocated = offset + size - carveout_heap->base;
-
//填充位图
-
bitmap_set(carveout_heap->bits, (offset - carveout_heap->base)/PAGE_SIZE , size/PAGE_SIZE);
-
return offset;
-
}
原理很简单:
就是在位图中查找适合的大小,然后把位图所代表的地址返回 (怎么有点表达不清楚了??? 反正就这个意思,呵呵)
ion_carveout_heap_allocate
-->
ion_carveout_allocate
-->
gen_pool_alloc
在lib/genalloc.c中
-
unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
-
{
-
struct list_head *_chunk;
-
struct gen_pool_chunk *chunk;
-
unsigned long addr, flags;
-
int order = pool->min_alloc_order;
-
int nbits, start_bit, end_bit;
-
-
if (size == 0)
-
return 0;
-
-
nbits = (size + (1UL << order) - 1) >> order; //由字节转成块,转成位图所代表的大小
-
-
read_lock(&pool->lock);
-
list_for_each(_chunk, &pool->chunks) {
-
chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
-
-
end_bit = (chunk->end_addr - chunk->start_addr) >> order;
-
-
spin_lock_irqsave(&chunk->lock, flags);
-
//在这个内存位图中查找足够大的内存
-
start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0, nbits, 0);
-
if (start_bit >= end_bit) {
-
spin_unlock_irqrestore(&chunk->lock, flags);
-
continue;
-
}
-
//由位图映射到实际的地址
-
addr = chunk->start_addr + ((unsigned long)start_bit << order);
-
//填充位图,说明这块内存地方己分配
-
bitmap_set(chunk->bits, start_bit, nbits);
-
spin_unlock_irqrestore(&chunk->lock, flags);
-
read_unlock(&pool->lock);
-
return addr; //返回地址
-
}
-
read_unlock(&pool->lock);
-
return 0;
-
}
-
EXPORT_SYMBOL(gen_pool_alloc);
阅读(3517) | 评论(0) | 转发(0) |