123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- #include "mm.h"
- #include "slab.h"
- #include "internal.h"
- struct vm_area_struct *vm_area_alloc(struct mm_struct *mm)
- {
- struct vm_area_struct *vma = (struct vm_area_struct *)kmalloc(sizeof(struct vm_area_struct), 0);
- if (vma)
- vma_init(vma, mm);
- return vma;
- }
- void vm_area_del(struct vm_area_struct *vma)
- {
- if (vma->vm_mm == NULL)
- return;
- __vma_unlink_list(vma->vm_mm, vma);
- }
- void vm_area_free(struct vm_area_struct *vma)
- {
- if (vma->vm_prev == NULL && vma->vm_next == NULL)
- vma->vm_mm->vmas = NULL;
- kfree(vma);
- }
- void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev)
- {
- struct vm_area_struct *next = NULL;
- vma->vm_prev = prev;
- if (prev)
- {
- next = prev->vm_next;
- prev->vm_next = vma;
- }
- else
- {
- next = mm->vmas;
- mm->vmas = vma;
- }
- vma->vm_next = next;
- if (next != NULL)
- next->vm_prev = vma;
- }
- void __vma_unlink_list(struct mm_struct *mm, struct vm_area_struct *vma)
- {
- struct vm_area_struct *prev, *next;
- next = vma->vm_next;
- prev = vma->vm_prev;
- if (prev)
- prev->vm_next = next;
- else
- mm->vmas = next;
- if (next)
- next->vm_prev = prev;
- }
- struct vm_area_struct *vma_find(struct mm_struct *mm, uint64_t addr)
- {
- struct vm_area_struct *vma = mm->vmas;
- struct vm_area_struct *result = NULL;
- while (vma != NULL)
- {
- if (vma->vm_end > addr)
- {
- result = vma;
- break;
- }
- vma = vma->vm_next;
- }
- return result;
- }
- int vma_insert(struct mm_struct *mm, struct vm_area_struct *vma)
- {
- struct vm_area_struct *prev;
- prev = vma_find(mm, vma->vm_start);
- if (prev && prev->vm_start <= vma->vm_start && prev->vm_end >= vma->vm_end)
- {
-
- return -EEXIST;
- }
- else if (prev && (prev->vm_start == vma->vm_start || prev->vm_end == vma->vm_end))
- {
- kwarn("Not support: expand vma");
- return -ENOTSUP;
- }
- prev = vma_find(mm, vma->vm_end);
- if (prev)
- prev = prev->vm_prev;
- if (prev == NULL)
- {
- struct vm_area_struct *ptr = mm->vmas;
- while (ptr)
- {
- if (ptr->vm_next)
- ptr = ptr->vm_next;
- else
- {
- prev = ptr;
- break;
- }
- }
- }
- __vma_link_list(mm, vma, prev);
- return 0;
- }
- struct anon_vma_t *__anon_vma_create_alloc(struct Page *page, bool lock_page)
- {
- struct anon_vma_t *anon_vma = (struct anon_vma_t *)kmalloc(sizeof(struct anon_vma_t), 0);
- if (unlikely(anon_vma == NULL))
- return NULL;
- memset(anon_vma, 0, sizeof(struct anon_vma_t));
- list_init(&anon_vma->vma_list);
- semaphore_init(&anon_vma->sem, 1);
-
- if (page != NULL)
- {
- if (lock_page == true)
- {
- uint64_t rflags;
- spin_lock(&page->op_lock);
- page->anon_vma = anon_vma;
- spin_unlock(&page->op_lock);
- }
- else
- page->anon_vma = anon_vma;
- anon_vma->page = page;
- }
- return anon_vma;
- }
- int __anon_vma_add(struct anon_vma_t *anon_vma, struct vm_area_struct *vma)
- {
- semaphore_down(&anon_vma->sem);
- list_add(&anon_vma->vma_list, &vma->anon_vma_list);
- vma->anon_vma = anon_vma;
- atomic_inc(&anon_vma->ref_count);
- semaphore_up(&anon_vma->sem);
- return 0;
- }
- int __anon_vma_free(struct anon_vma_t *anon_vma)
- {
- if (anon_vma->page != NULL)
- {
- spin_lock(&anon_vma->page->op_lock);
- anon_vma->page->anon_vma = NULL;
- spin_unlock(&anon_vma->page->op_lock);
- }
- kfree(anon_vma);
- return 0;
- }
- int __anon_vma_del(struct vm_area_struct *vma)
- {
-
- if (vma->anon_vma == NULL)
- return -EINVAL;
- list_del(&vma->anon_vma_list);
- semaphore_down(&vma->anon_vma->sem);
- atomic_dec(&vma->anon_vma->ref_count);
- if (unlikely(atomic_read(&vma->anon_vma->ref_count) == 0))
- {
- __anon_vma_free(vma->anon_vma);
-
- vma->anon_vma = NULL;
- list_init(&vma->anon_vma_list);
- }
- else
- semaphore_up(&vma->anon_vma->sem);
- }
|