-
Notifications
You must be signed in to change notification settings - Fork 196
/
libos_vma.h
142 lines (118 loc) · 5.57 KB
/
libos_vma.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2014 Stony Brook University
* Copyright (C) 2020 Invisible Things Lab
*/
/*
* Definitions of types and functions for VMA bookkeeping.
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "api.h"
#include "libos_defs.h"
#include "libos_handle.h"
#include "libos_types.h"
#include "linux_abi/memory.h"
#include "pal.h"
#define VMA_COMMENT_LEN 16
/* Public version of libos_vma, used when we want to copy out the VMA and use it without holding
* the VMA list lock. */
struct libos_vma_info {
void* addr;
size_t length;
int prot; // memory protection flags: PROT_*
int flags; // MAP_* and VMA_*
struct libos_handle* file;
uint64_t file_offset;
char comment[VMA_COMMENT_LEN];
};
/* vma is kept for bookkeeping, but the memory is not actually allocated */
#define VMA_UNMAPPED 0x10000000
/* vma is used internally */
#define VMA_INTERNAL 0x20000000
/* vma is backed by a file and has been protected as writable, so it has to be checkpointed during
* migration */
#define VMA_TAINTED 0x40000000
int init_vma(void);
/*
* Bookkeeping a removal of mapped memory. On success returns a temporary VMA pointer in
* `tmp_vma_ptr`, which must be subsequently freed by calling `bkeep_remove_tmp_vma` - but this
* should be done only *AFTER* the memory deallocation itself. For example:
*
* void* tmp_vma = NULL;
* if (bkeep_munmap(ptr, len, is_internal, &tmp_vma) < 0) {
* handle_errors();
* }
* if (PalVirtualMemoryFree(ptr, len) < 0) {
* handle_errors();
* }
* bkeep_remove_tmp_vma(tmp_vma);
*
* Such a way of freeing is needed, so that no other thread will map the same memory in the window
* between `bkeep_munmap` and `PalVirtualMemoryFree`.
* `bkeep_convert_tmp_vma_to_user` can be called instead of `bkeep_remove_tmp_vma` to convert
* the VMA to unmapped user VMA, instead of removing it. See `MMAP_FIXED` implementation for example
* usage.
*/
int bkeep_munmap(void* addr, size_t length, bool is_internal, void** tmp_vma_ptr);
void bkeep_remove_tmp_vma(void* vma);
void bkeep_convert_tmp_vma_to_user(void* vma);
/* Bookkeeping a change to memory protections. */
int bkeep_mprotect(void* addr, size_t length, int prot, bool is_internal);
/*
* Bookkeeping an allocation of memory at a fixed address. `flags` must contain either MAP_FIXED or
* MAP_FIXED_NOREPLACE - the former forces bookkeeping and removes any overlapping VMAs, the latter
* atomically checks for overlaps and fails if one is found.
*/
int bkeep_mmap_fixed(void* addr, size_t length, int prot, int flags, struct libos_handle* file,
uint64_t offset, const char* comment);
/*
* Bookkeeping an allocation of memory at any address in the range [`bottom_addr`, `top_addr`).
* The search is top-down, starting from `top_addr` - `length` and returning the first unoccupied
* area capable of fitting the requested size.
* Start of bookkept range is returned in `*ret_val_ptr`.
*/
int bkeep_mmap_any_in_range(void* bottom_addr, void* top_addr, size_t length, int prot, int flags,
struct libos_handle* file, uint64_t offset, const char* comment,
void** ret_val_ptr);
/* Shorthand for `bkeep_mmap_any_in_range` with the range
* [`g_pal_public_state->memory_address_start`, `g_pal_public_state->memory_address_end`). */
int bkeep_mmap_any(size_t length, int prot, int flags, struct libos_handle* file, uint64_t offset,
const char* comment, void** ret_val_ptr);
/* First tries to bookkeep in [`g_pal_public_state->memory_address_start`, `aslr_addr_top`) range
* and if it fails calls `bkeep_mmap_any`. `aslr_addr_top` is a value randomized on each program
* run. */
int bkeep_mmap_any_aslr(size_t length, int prot, int flags, struct libos_handle* file,
uint64_t offset, const char* comment, void** ret_val_ptr);
/* Looking up VMA that contains `addr`. If one is found, returns its description in `vma_info`.
* This function increases ref-count of `vma_info->file` by one (if it is not NULL). */
int lookup_vma(void* addr, struct libos_vma_info* vma_info);
/* Returns true if the whole range [`addr`, `addr` + `length`) is mapped as user memory and allows
* for `prot` type of access. */
bool is_in_adjacent_user_vmas(const void* addr, size_t length, int prot);
/*
* Dumps all non-internal and mapped VMAs.
* On success returns 0 and puts the pointer to result array into `*vma_infos` and its length into
* `*count`. On error returns negated error code.
* The returned array can be subsequently freed by `free_vma_info_array`.
*/
int dump_all_vmas(bool include_unmapped, struct libos_vma_info** out_infos, size_t* out_count);
/*
* Same as `dump_all_vmas`, but dumps only in `[begin; end)` range.
*/
int dump_vmas_in_range(uintptr_t begin, uintptr_t end, bool include_unmapped,
struct libos_vma_info** out_infos, size_t* out_count);
void free_vma_info_array(struct libos_vma_info* vma_infos, size_t count);
/* Implementation of madvise(MADV_DONTNEED) syscall */
int madvise_dontneed_range(uintptr_t begin, uintptr_t end);
/* Call `msync` for file mappings in given range (should be page-aligned) */
int msync_range(uintptr_t begin, uintptr_t end);
/* Call `msync` for file mappings of `hdl` */
int msync_handle(struct libos_handle* hdl);
/* Call `reload` for file mappings of `hdl` */
int reload_mmaped_from_file_handle(struct libos_handle* hdl);
void debug_print_all_vmas(void);
/* Returns the peak amount of memory usage */
size_t get_peak_memory_usage(void);
/* Returns total memory usage */
size_t get_total_memory_usage(void);