1/* @title: Virtual Memory Area */
2#pragma once
3#include <mem/page.h>
4#include <structures/list.h>
5#include <structures/rbit.h>
6#include <types/types.h>
7
8enum vma_range_protection {
9 VMA_PROT_READ = 1,
10 VMA_PROT_WRITE = 1 << 1,
11 VMA_PROT_EX = 1 << 2,
12};
13
14struct vma_range {
15 struct rbit_node mm_node;
16
17 /* min_low = lowest start in the subtree */
18 vaddr_t min_low;
19
20 /* max_gap = largest free gap between consecutive VMAs in the subtree */
21 size_t max_gap;
22 pgoff_t pgoff; /* object-space offset of `start` */
23 enum vma_range_protection prot; /* r/w/x, etc. */
24 struct anon_vma *anon_vma;
25 struct mm *mm; /* whose page tables */
26 struct list_head anon_vma_chain; /* AVCs: own object + every ancestor */
27};
28
29static inline vaddr_t vma_range_start(const struct vma_range *vma_range) {
30 return vma_range->mm_node.interval.low;
31}
32static inline vaddr_t vma_range_end(const struct vma_range *vma_range) {
33 return vma_range->mm_node.interval.high + 1;
34}
35
36struct vma_range *vma_range_alloc(struct mm *mm, vaddr_t start, vaddr_t end,
37 enum vma_range_protection prot);
38void vma_range_free(struct vma_range *vma_range);
39
40void vma_range_init(struct vma_range *vma_range, struct mm *mm, vaddr_t start,
41 vaddr_t end, enum vma_range_protection prot);
42
43struct vma_range *vma_range_find(struct mm *mm, vaddr_t addr);
44struct vma_range *vma_range_find_intersection(struct mm *mm, vaddr_t s,
45 vaddr_t e);
46struct vma_range *vma_range_next(struct vma_range *vma_range);
47struct vma_range *vma_range_prev(struct vma_range *vma_range);
48
49/* fault path helper: write fault on an anon VMA, allocate anon_vma
50 * and AVC, link, stash on vma_range->anon_vma */
51enum errno vma_range_anon_prepare(struct vma_range *vma_range);
52
53enum errno vma_range_expand(struct vma_range *vma_range, vaddr_t new_start,
54 vaddr_t new_end);
55struct vma_range *vma_range_merge(struct mm *mm, struct vma_range *prev,
56 struct vma_range *vma_range);
57enum errno vma_range_set_prot(struct vma_range *vma_range,
58 enum vma_range_protection prot);
59
60void vma_range_unmap_range(struct vma_range *vma_range, vaddr_t s, vaddr_t e);
61void vma_range_teardown(struct vma_range *vma_range);
62
63static inline bool vma_range_is_anonymous(const struct vma_range *vma_range) {
64 return vma_range->anon_vma != NULL;
65}
66static inline size_t vma_range_pages(const struct vma_range *vma_range) {
67 return (vma_range_end(vma_range) - vma_range_start(vma_range)) >>
68 PAGE_4K_SHIFT;
69}
70
71/* split one VMA into two at `addr`, recompute pgoff + tree intervals */
72struct vma_range *vma_range_split(struct vma_range *vma_range, vaddr_t addr);
73
74/* fresh VMA in dst_mm with src's attributes but no linkages */
75struct vma_range *vma_range_dup(struct mm *dst_mm, const struct vma_range *src);
76
77/* The index to VA translation. THE VMA's job, not the anon_vma's. */
78static inline vaddr_t vma_range_address(const struct vma_range *vma_range,
79 pgoff_t index) {
80 return vma_range_start(vma_range) +
81 ((index - vma_range->pgoff) << PAGE_4K_SHIFT);
82}
83