void* ioremap(paddr_t phys_addr, size_t size) {
size = PAGE_UP(size);
- vm_struct_t* vm_area = alloc_vm_area(size, VM_IOREMAP);
- if (!vm_area) {
+ vmap_region_t* vmap_region = alloc_vmap_region(size, VMAP_IOREMAP);
+ if (!vmap_region) {
return NULL;
}
// 映射物理地址到虚拟地址
- vm_area->vm_paddr = phys_addr;
- vm_area->vm_flags |= VM_IOREMAP;
+ vmap_region->vm_paddr = phys_addr;
+ vmap_region->vm_flags |= VMAP_IOREMAP;
- printk("ioremap: 0x%08x -> 0x%08x size %u\n", phys_addr, vm_area->vm_vaddr, vm_area->vm_size);
+ printk("ioremap: 0x%08x -> 0x%08x size %u\n", phys_addr, vmap_region->vm_vaddr, vmap_region->vm_size);
- ioremap_page_range(vm_area->vm_vaddr, vm_area->vm_paddr, vm_area->vm_size);
+ ioremap_page_range(vmap_region->vm_vaddr, vmap_region->vm_paddr, vmap_region->vm_size);
- return (void*)vm_area->vm_vaddr;
+ return (void*)vmap_region->vm_vaddr;
}
void iounmap(vaddr_t vaddr) {
- vm_struct_t* vm_area = find_vm_area(vaddr);
- assert(vm_area != NULL);
- assert(vm_area->vm_flags & VM_IOREMAP);
+ vmap_region_t* vmap_region = find_vmap_region(vaddr);
+ assert(vmap_region != NULL);
+ assert(vmap_region->vm_flags & VMAP_IOREMAP);
- printk("iounmap: 0x%08x size %u\n", vm_area->vm_vaddr, vm_area->vm_size);
+ printk("iounmap: 0x%08x size %u\n", vmap_region->vm_vaddr, vmap_region->vm_size);
- free_vm_area(vm_area);
+ free_vmap_region(vmap_region);
- ioremap_page_range_clear(vm_area->vm_vaddr, vm_area->vm_size);
+ ioremap_page_range_clear(vmap_region->vm_vaddr, vmap_region->vm_size);
}
#include <string.h>
#include <mm.h>
-static vm_struct_t* vm_area_list = NULL;
+static vmap_region_t* vmap_region_list = NULL;
-vaddr_t vm_vaddr_base = VMALLOC_VADDR_BASE + (8 * 1024 * 1024);
-vaddr_t vm_vaddr_end = VMALLOC_VADDR_END;
+static const int vmap_guard_size = 4 * 1024 * 1024; // 4MB
-vm_struct_t* alloc_vm_area(size_t size, uint32_t flags) {
+static const vaddr_t vmap_vaddr_base = VMALLOC_VADDR_BASE + vmap_guard_size;
+static const vaddr_t vmap_vaddr_end = VMALLOC_VADDR_END - vmap_guard_size;
+
+vmap_region_t* alloc_vmap_region(size_t size, uint32_t flags) {
// assert size是页对齐
assert(PAGE_DOWN(size) == size);
- assert(vm_vaddr_base < vm_vaddr_end);
+ assert(vmap_vaddr_base < vmap_vaddr_end);
size += PAGE_SIZE; // 尾部添加一个空页
- vaddr_t vm_area_gap_bgn = 0;
- vaddr_t vm_area_gap_end = 0;
+ vaddr_t vmap_region_gap_bgn = 0;
+ vaddr_t vmap_region_gap_end = 0;
uint32_t eflags;
irq_save(eflags);
- vm_struct_t* prev = NULL;
- vm_struct_t* curt = vm_area_list;
+ vmap_region_t* prev = NULL;
+ vmap_region_t* curt = vmap_region_list;
while (curt != NULL) {
- assert(curt->vm_vaddr >= vm_vaddr_base);
- assert(curt->vm_vaddr + curt->vm_size <= vm_vaddr_end);
+ assert(curt->vm_vaddr >= vmap_vaddr_base);
+ assert(curt->vm_vaddr + curt->vm_size <= vmap_vaddr_end);
//
- vm_area_gap_bgn = prev == NULL ? vm_vaddr_base : prev->vm_vaddr + prev->vm_size;
- vm_area_gap_end = curt->vm_vaddr;
+ vmap_region_gap_bgn = prev == NULL ? vmap_vaddr_base : prev->vm_vaddr + prev->vm_size;
+ vmap_region_gap_end = curt->vm_vaddr;
- assert(vm_area_gap_bgn <= vm_area_gap_end);
+ assert(vmap_region_gap_bgn <= vmap_region_gap_end);
// 找到了
- if (vm_area_gap_end - vm_area_gap_bgn >= size) {
+ if (vmap_region_gap_end - vmap_region_gap_bgn >= size) {
break;
}
// 如果找到最后了也还没找到
if (curt == NULL) {
- vm_area_gap_bgn = prev == NULL ? vm_vaddr_base : prev->vm_vaddr + prev->vm_size;
- vm_area_gap_end = vm_vaddr_end;
+ vmap_region_gap_bgn = prev == NULL ? vmap_vaddr_base : prev->vm_vaddr + prev->vm_size;
+ vmap_region_gap_end = vmap_vaddr_end;
- assert(vm_area_gap_bgn <= vm_area_gap_end);
+ assert(vmap_region_gap_bgn <= vmap_region_gap_end);
- if (vm_area_gap_end - vm_area_gap_bgn < size) {
+ if (vmap_region_gap_end - vmap_region_gap_bgn < size) {
irq_restore(eflags);
return NULL;
}
}
- // å\88\9b建ä¸\80人vm_struct
- vm_struct_t* vm_area = kmalloc(sizeof(vm_struct_t), 0);
- if (vm_area == NULL) {
+ // å\88\9b建ä¸\80个vmap_region
+ vmap_region_t* vmap_region = kmalloc(sizeof(vmap_region_t), 0);
+ if (vmap_region == NULL) {
irq_restore(eflags);
return NULL;
}
- vm_area->vm_vaddr = vm_area_gap_bgn;
- vm_area->vm_size = size;
- vm_area->vm_flags = flags;
+ vmap_region->vm_vaddr = vmap_region_gap_bgn;
+ vmap_region->vm_size = size;
+ vmap_region->vm_flags = flags;
// add to list
- vm_area->vm_next = curt;
+ vmap_region->vm_next = curt;
if (prev == NULL) {
- vm_area_list = vm_area;
+ vmap_region_list = vmap_region;
} else {
- prev->vm_next = vm_area;
+ prev->vm_next = vmap_region;
}
irq_restore(eflags);
- return vm_area;
+ return vmap_region;
}
-vm_struct_t* find_vm_area(vaddr_t vaddr) {
+vmap_region_t* find_vmap_region(vaddr_t vaddr) {
assert(PAGE_DOWN(vaddr) == vaddr);
- assert(vaddr >= vm_vaddr_base);
- assert(vaddr < vm_vaddr_end);
- assert(vm_area_list != NULL);
+ assert(vaddr >= vmap_vaddr_base);
+ assert(vaddr < vmap_vaddr_end);
+ assert(vmap_region_list != NULL);
uint32_t eflags;
irq_save(eflags);
- vm_struct_t* curt = vm_area_list;
+ vmap_region_t* curt = vmap_region_list;
while (curt != NULL) {
assert(curt->vm_size != 0);
- assert(curt->vm_vaddr >= vm_vaddr_base);
- assert(curt->vm_vaddr + curt->vm_size <= vm_vaddr_end);
+ assert(curt->vm_vaddr >= vmap_vaddr_base);
+ assert(curt->vm_vaddr + curt->vm_size <= vmap_vaddr_end);
if (vaddr == curt->vm_vaddr) {
irq_restore(eflags);
return NULL;
}
-void free_vm_area(vm_struct_t* vm_area) {
- assert(vm_area != NULL);
- assert(vm_area->vm_size != 0);
- assert(vm_area->vm_size % PAGE_SIZE == 0);
- assert(vm_area->vm_size >= (2 * PAGE_SIZE));
- assert(vm_area->vm_vaddr >= vm_vaddr_base);
- assert(vm_area->vm_vaddr + vm_area->vm_size <= vm_vaddr_end);
- assert(vm_area_list != NULL);
+void free_vmap_region(vmap_region_t* region) {
+ assert(region != NULL);
+ assert(region->vm_size != 0);
+ assert(region->vm_size % PAGE_SIZE == 0);
+ assert(region->vm_size >= (2 * PAGE_SIZE));
+ assert(region->vm_vaddr >= vmap_vaddr_base);
+ assert(region->vm_vaddr + region->vm_size <= vmap_vaddr_end);
+ assert(vmap_region_list != NULL);
// TODO
uint32_t eflags;
irq_save(eflags);
- vm_struct_t* prev = NULL;
- vm_struct_t* curt = vm_area_list;
+ vmap_region_t* prev = NULL;
+ vmap_region_t* curt = vmap_region_list;
while (curt != NULL) {
- if (curt == vm_area) {
+ if (curt == region) {
if (prev == NULL) {
// 只有链表上仅有一个节点,且这个节点就是要删除的节点的情况下prev才可能为NULL
- assert(vm_area_list == vm_area);
- assert(vm_area->vm_next == NULL);
+ assert(vmap_region_list == region);
+ assert(region->vm_next == NULL);
//
- vm_area_list = curt->vm_next;
+ vmap_region_list = curt->vm_next;
} else {
prev->vm_next = curt->vm_next;
}
- // 释放前先清空vm_struct避免连续二次释放
- memset(curt, 0, sizeof(vm_struct_t));
+ // 释放前先清空vmap_region避免连续二次释放
+ memset(curt, 0, sizeof(vmap_region_t));
kfree(curt);
}
// 不应该出现这种情况
- assert(0 && "vm_area not found");
+ assert(0 && "vmap_region not found");
irq_restore(eflags);
}
printk("memory init finished...\n");
boot_delay(DEFAULT_BOOT_DELAY_TICKS);
- g_vma_kmem_cache = kmem_cache_create("vma", sizeof(vm_area_t), 4);
+ g_vma_kmem_cache = kmem_cache_create("vma", sizeof(vma_t), 4);
assert(g_vma_kmem_cache != NULL);
}
-vm_area_t* vma_alloc() {
- vm_area_t* vma = kmem_cache_alloc(g_vma_kmem_cache, 0);
+vma_t* vma_alloc() {
+ vma_t* vma = kmem_cache_alloc(g_vma_kmem_cache, 0);
vma->vm_bgn = 0;
vma->vm_end = 0;
vma->vm_flags = 0;
return vma;
}
-void vma_insert(task_t* tsk, vm_area_t* vma_new) {
+void vma_insert(task_t* tsk, vma_t* vma_new) {
//
- vm_area_t** p = &tsk->vma_list;
+ vma_t** p = &tsk->vma_list;
while (*p != NULL) {
- vm_area_t* v = *p;
+ vma_t* v = *p;
assert(v->vm_bgn < v->vm_end);
assert(vma_new->vm_bgn < vma_new->vm_end);
*p = vma_new;
}
-vm_area_t* vma_find(task_t* tsk, vm_area_t* vma, uint32_t addr) {
- vm_area_t** p = &tsk->vma_list;
+vma_t* vma_find(task_t* tsk, vma_t* vma, uint32_t addr) {
+ vma_t** p = &tsk->vma_list;
while (*p != NULL) {
- vm_area_t* v = *p;
+ vma_t* v = *p;
if (addr <= v->vm_end) {
break;