123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- #include "mmio.h"
- #include "mmio-buddy.h"
- #include <common/math.h>
- void mmio_init()
- {
- mmio_buddy_init();
- }
- int mmio_create(uint32_t size, vm_flags_t vm_flags, uint64_t *res_vaddr, uint64_t *res_size)
- {
- int retval = 0;
-
- if (unlikely(size > PAGE_1G_SIZE || size == 0))
- return -EPERM;
-
- int size_exp = 31 - __clz(size);
- if (size_exp < PAGE_4K_SHIFT)
- {
- size_exp = PAGE_4K_SHIFT;
- size = PAGE_4K_SIZE;
- }
- else if (size & (~(1 << size_exp)))
- {
- ++size_exp;
- size = 1 << size_exp;
- }
-
- struct __mmio_buddy_addr_region *buddy_region = mmio_buddy_query_addr_region(size_exp);
- if (buddy_region == NULL)
- return -ENOMEM;
- *res_vaddr = buddy_region->vaddr;
- *res_size = size;
-
- __mmio_buddy_release_addr_region(buddy_region);
-
-
- vm_flags |= (VM_IO | VM_DONTCOPY);
- uint64_t len_4k = size % PAGE_2M_SIZE;
- uint64_t len_2m = size - len_4k;
-
- for (uint32_t i = 0; i < len_2m; i += PAGE_2M_SIZE)
- {
- retval = mm_create_vma(&initial_mm, buddy_region->vaddr + i, PAGE_2M_SIZE, vm_flags, NULL, NULL);
- if (unlikely(retval != 0))
- goto failed;
- }
- for (uint32_t i = len_2m; i < size; i += PAGE_4K_SIZE)
- {
- retval = mm_create_vma(&initial_mm, buddy_region->vaddr + i, PAGE_4K_SIZE, vm_flags, NULL, NULL);
- if (unlikely(retval != 0))
- goto failed;
- }
- return 0;
- failed:;
- kerror("failed to create mmio vma. pid=%d", current_pcb->pid);
-
- return retval;
- }
- int mmio_release(uint64_t vaddr, uint64_t length)
- {
- int retval = 0;
-
- mm_unmap(&initial_mm, vaddr, length, false);
-
- for (uint64_t i = 0; i < length;)
- {
- struct vm_area_struct *vma = vma_find(&initial_mm, vaddr + i);
- if (unlikely(vma == NULL))
- {
- kerror("mmio_release failed: vma not found. At address: %#018lx, pid=%ld", vaddr + i, current_pcb->pid);
- return -EINVAL;
- }
- if (unlikely(vma->vm_start != (vaddr + i)))
- {
- kerror("mmio_release failed: addr_start is not equal to current: %#018lx.", vaddr + i);
- return -EINVAL;
- }
-
- retval = __mmio_buddy_give_back(vma->vm_start, 31 - __clz(vma->vm_end - vma->vm_start));
- i += vma->vm_end - vma->vm_start;
-
- vm_area_del(vma);
- vm_area_free(vma);
- if (unlikely(retval != 0))
- goto give_back_failed;
- }
- return 0;
- give_back_failed:;
- kerror("mmio_release give_back failed: ");
- return retval;
- }
|