Skip to main content

air_sys_types/
mem.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Types de la famille `mem` — mappings, protection, memfd, etc.
6//!
7//! Cf. `docs/specs/layer-0/family-mem.md`.
8
9use core::ptr::NonNull;
10
11use bitflags::bitflags;
12
13bitflags! {
14    /// Protections d'accès pour les mappings mémoire (`mmap`, `mprotect`).
15    ///
16    /// Correspond aux constantes `PROT_*` de `<sys/mman.h>`.
17    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
18    pub struct ProtectionFlags: i32 {
19        /// Aucun accès autorisé.
20        const NONE  = 0;
21        /// Lecture autorisée.
22        const READ  = 1;
23        /// Écriture autorisée.
24        const WRITE = 2;
25        /// Exécution autorisée.
26        const EXEC  = 4;
27    }
28}
29
30bitflags! {
31    /// Drapeaux de type de mapping pour `mmap(2)`.
32    ///
33    /// Les drapeaux [`MapFlags::SHARED`] et [`MapFlags::PRIVATE`] sont
34    /// mutuellement exclusifs et obligatoires. Le wrapper valide ce
35    /// point avant l'appel syscall.
36    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
37    pub struct MapFlags: i32 {
38        /// Modifications visibles aux autres processus partageant le même
39        /// fichier/objet. Nécessaire pour memfd partagé entre processus.
40        const SHARED          = 0x0000_0001;
41        /// Copie-on-write : les modifications ne sont pas répercutées vers
42        /// le fichier sous-jacent ni visibles par les autres processus.
43        const PRIVATE         = 0x0000_0002;
44        /// Mappe exactement à l'adresse spécifiée. Écrase tout mapping
45        /// existant à cette adresse. Voir aussi `FIXED_NOREPLACE`.
46        const FIXED           = 0x0000_0010;
47        /// Mapping anonyme sans fichier sous-jacent. Toujours positionné
48        /// par `mmap_anonymous`.
49        const ANONYMOUS       = 0x0000_0020;
50        /// La pile grandit vers le bas (pile thread).
51        const GROWSDOWN       = 0x0000_0100;
52        /// Empêche le fichier d'être ouvert en écriture (obsolète).
53        const DENYWRITE       = 0x0000_0800;
54        /// Mapping exécutable (obsolète ; utilisez `ProtectionFlags::EXEC`).
55        const EXECUTABLE      = 0x0000_1000;
56        /// Pages verrouillées en mémoire (comme `mlock`).
57        const LOCKED          = 0x0000_2000;
58        /// Pas de réservation de swap pour ce mapping.
59        const NORESERVE       = 0x0000_4000;
60        /// Pré-alloue les pages physiques (fault in) lors du mmap.
61        const POPULATE        = 0x0000_8000;
62        /// Ne bloque pas lors de la pré-allocation des pages.
63        const NONBLOCK        = 0x0001_0000;
64        /// Mapping de pile (hint kernel).
65        const STACK           = 0x0002_0000;
66        /// Huge pages transparentes.
67        const HUGETLB         = 0x0004_0000;
68        /// Synchronisation avec le fichier sur les accès directs.
69        const SYNC            = 0x0008_0000;
70        /// Comme `FIXED` mais retourne `EEXIST` si l'adresse est déjà
71        /// occupée. Linux 4.17+. Préféré à `FIXED` dans les cas normaux.
72        const FIXED_NOREPLACE = 0x0010_0000;
73    }
74}
75
76bitflags! {
77    /// Drapeaux pour `mremap(2)`.
78    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
79    pub struct MremapFlags: i32 {
80        /// Autorise le déplacement du mapping si le redimensionnement
81        /// sur place est impossible.
82        const MAYMOVE   = 1;
83        /// Déplace vers une adresse fixe (combiné avec `MAYMOVE`).
84        const FIXED     = 2;
85        /// Garde le mapping source intact après déplacement.
86        /// Linux 5.7+.
87        const DONTUNMAP = 4;
88    }
89}
90
91/// Conseil kernel sur le pattern d'accès mémoire pour `madvise(2)`.
92///
93/// Ces conseils sont de simples hints : le kernel peut les ignorer.
94/// Les valeurs numériques correspondent aux constantes `MADV_*` de Linux.
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
96#[repr(i32)]
97pub enum MadviseAdvice {
98    /// Comportement normal (supprime les conseils précédents).
99    Normal = 0,
100    /// Accès aléatoires : désactive le préfetch.
101    Random = 1,
102    /// Accès séquentiels : active un préfetch agressif.
103    Sequential = 2,
104    /// Les pages seront bientôt accédées (préfetch immédiat).
105    WillNeed = 3,
106    /// Les pages ne sont plus nécessaires ; libère la mémoire physique
107    /// sans désallouer le mapping (les pages sont remises à zéro au
108    /// prochain accès).
109    DontNeed = 4,
110    /// Libère les pages propres sans désallouer (Linux 4.5+).
111    Free = 8,
112    /// Supprime les pages et l'espace de backing (seulement pour
113    /// `MAP_SHARED` sur des fichiers supportant `FALLOC_FL_PUNCH_HOLE`).
114    Remove = 9,
115    /// Les pages ne doivent pas être héritées par les processus fils.
116    DontFork = 10,
117    /// Annule `DONTFORK`.
118    DoFork = 11,
119    /// Active le KSM (Kernel Samepage Merging) pour ces pages.
120    Mergeable = 12,
121    /// Désactive le KSM pour ces pages.
122    Unmergeable = 13,
123    /// Active les huge pages transparentes.
124    HugePage = 14,
125    /// Désactive les huge pages transparentes.
126    NoHugePage = 15,
127    /// Exclut ces pages des core dumps.
128    DontDump = 16,
129    /// Réintègre ces pages dans les core dumps.
130    DoDump = 17,
131    /// Efface les pages lors d'un fork (Linux 4.14+).
132    WipeOnFork = 18,
133    /// Conserve les pages lors d'un fork (Linux 4.14+).
134    KeepOnFork = 19,
135    /// Indique que les pages sont "froides" (Linux 5.4+).
136    Cold = 20,
137    /// Pousse les pages vers le swap (Linux 5.4+).
138    PageOut = 21,
139    /// Pré-fault les pages en lecture (Linux 5.14+).
140    PopulateRead = 22,
141    /// Pré-fault les pages en écriture (Linux 5.14+).
142    PopulateWrite = 23,
143    /// Libère les pages verrouillées (Linux 5.18+).
144    DontNeedLocked = 24,
145    /// Compacte les huge pages transparentes (Linux 6.1+).
146    Collapse = 25,
147}
148
149bitflags! {
150    /// Drapeaux pour `mlock2(2)` (cf. `linux/mman.h`).
151    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
152    pub struct MlockFlags: u32 {
153        /// Verrouille les pages au fur et à mesure des fautes mémoire,
154        /// plutôt qu'immédiatement (Linux 4.4+).
155        const ONFAULT = 1;
156    }
157}
158
159bitflags! {
160    /// Drapeaux pour `mlockall(2)` (cf. `linux/mman.h`).
161    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
162    pub struct MlockallFlags: i32 {
163        /// Verrouille les pages du mapping actuel.
164        const CURRENT = 1;
165        /// Verrouille automatiquement les futures allocations.
166        const FUTURE  = 2;
167        /// Verrouille au fur et à mesure des fautes (combiné avec
168        /// `CURRENT` ou `FUTURE`, Linux 4.4+).
169        const ONFAULT = 4;
170    }
171}
172
173bitflags! {
174    /// Drapeaux pour `memfd_create(2)` (cf. `linux/memfd.h`).
175    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
176    pub struct MemfdFlags: u32 {
177        /// Ferme le FD à l'`exec`.
178        const CLOEXEC      = 0x0001;
179        /// Autorise le scellement du FD via `fcntl(F_ADD_SEALS)`.
180        /// Nécessaire pour partager en lecture seule via SCM_RIGHTS.
181        const ALLOW_SEALING = 0x0002;
182        /// Alloue des huge pages pour le backing store.
183        const HUGETLB      = 0x0004;
184        /// Scelle automatiquement l'exécution à la création (Linux 6.3+).
185        const NOEXEC_SEAL  = 0x0008;
186        /// Autorise l'exécution des pages (doit être combiné avec
187        /// un mapping `PROT_EXEC`, Linux 6.3+).
188        const EXEC         = 0x0010;
189    }
190}
191
192bitflags! {
193    /// Drapeaux pour `msync(2)` (cf. `linux/mman.h`).
194    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
195    pub struct MsyncFlags: i32 {
196        /// Demande la synchronisation asynchrone (retourne immédiatement).
197        const ASYNC      = 1;
198        /// Invalide les pages pour forcer un rechargement depuis le fichier.
199        const INVALIDATE = 2;
200        /// Attend que la synchronisation soit complète avant de retourner.
201        const SYNC       = 4;
202    }
203}
204
205/// Segment mémoire distant pour `process_vm_readv`/`process_vm_writev`.
206///
207/// Décrit une plage de mémoire dans l'espace d'adressage d'un autre
208/// processus (adresse et longueur en octets). Correspond à `struct iovec`
209/// du côté remote dans le kernel (iova).
210///
211/// `#[repr(C)]` garantit la compatibilité de layout avec `struct iovec`
212/// du kernel Linux sur les architectures LP64 (x86_64, aarch64) :
213/// `{ iov_base: u64, iov_len: usize }`.
214#[repr(C)]
215#[derive(Debug, Clone, Copy)]
216pub struct RemoteIoSlice {
217    /// Adresse dans l'espace d'adressage du processus cible.
218    pub addr: u64,
219    /// Longueur en octets.
220    pub len: usize,
221}
222
223/// Pointeur brut vers un mapping mémoire sans ownership RAII.
224///
225/// Contrairement au type `Mapping` de `air-sys-syscall::mem`, ce type ne
226/// libère **pas** automatiquement la mémoire à la destruction. Il est
227/// utilisé pour les cas avancés (`mmap_fixed`) où l'appelant gère
228/// explicitement la durée de vie du mapping.
229///
230/// # Safety
231///
232/// L'appelant est responsable d'appeler `munmap` avec l'adresse et la
233/// longueur correctes avant que ce type soit abandonné, ou d'utiliser
234/// `mmap_fixed` pour remplacer le mapping.
235#[derive(Debug)]
236pub struct MappingPointer {
237    /// Adresse de base du mapping.
238    pub address: NonNull<u8>,
239    /// Longueur du mapping en octets.
240    pub length: usize,
241}
242
243// SAFETY: Un mapping mémoire est intrinsèquement un pointeur vers de la
244// mémoire partagée — Send + Sync sont corrects si l'accès concurrent est
245// géré par l'appelant (mutex, atomic, etc.). Le wrapper ne garantit pas
246// la synchronisation ; c'est la responsabilité de l'utilisateur.
247unsafe impl Send for MappingPointer {}
248unsafe impl Sync for MappingPointer {}