XenevaOS
Loading...
Searching...
No Matches
mm.h
Go to the documentation of this file.
1#ifndef __LINUX_MM_H__
2#define __LINUX_MM_H__
3
4/*
5 * DCL <linux/mm.h> -- the hub header for ports that live under drivers/char.
6 *
7 * A mainline drivers/char/*.c includes mm.h and then leans on its own
8 * transitive chain for printk, VFS helpers, scheduler hooks, errno values
9 * and the mmap descriptor type. Xeneva's DCL headers do not have that chain,
10 * so mm.h collects it here rather than editing the vendored source. Items
11 * mainline actually declares in include/linux/fs.h or include/linux/major.h
12 * are marked as such.
13 */
14
15#include <linux/autoconf.h>
16#include <linux/kernel.h> /* types, errno, GFP_KERNEL, __user */
17#include <linux/compiler.h> /* likely/unlikely */
18#include <linux/fs.h> /* file/inode/cdev/device ABI pins */
19#include <linux/mount.h> /* the VFS helpers mainline has in fs.h -- * * file_inode, iminor, inode_lock/unlock,
20 * noop_llseek -- which DCL's pinned fs.h
21 * cannot carry. See the note there. */
22#include <linux/mm_types.h> /* struct folio + page_folio() helpers --
23 * drm_gem.c/drm_gem_shmem_helper.c batch
24 * folios and mainline mm.h provides these */
25#include <linux/printk.h> /* printk() -- mem.c never includes this directly */
26#include <linux/init.h>
27#include <linux/uaccess.h>
28#include <Mm/vmmngr.h>\t\t/* PAGE_SIZE/PAGE_SHIFT: Xeneva's native page geometry */
29
30/*
31 * vma_flags_t / mk_vma_flags() / VMA_NORESERVE_BIT -- the packed VMA flag
32 * word v7.2 hands to shmem_file_setup(). One caller in this tree:
33 * drm_gem_object_init() (drm_gem.c:189) builds the word and passes it on.
34 * Xeneva has no VMAs to carry flags, and the shmem shims take the word but
35 * do not read it, so the type exists for that expression's sake and the bit
36 * is a position rather than a policy.
37 */
38typedef unsigned long vma_flags_t;
39
40#define VMA_NORESERVE_BIT 0
41
42static inline vma_flags_t mk_vma_flags(unsigned int bit)
43{
44 return (vma_flags_t)1 << bit;
45}
46
47/* ── general helpers (mainline: include/linux/{kernel,overflow}.h) ─────── */
48
49#ifndef min
50#define min(a, b) (((a) < (b)) ? (a) : (b))
51#endif
52#ifndef min_t
53#define min_t(type, a, b) ((type)(a) < (type)(b) ? (type)(a) : (type)(b))
54#endif
55#ifndef ARRAY_SIZE
56#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
57#endif
58#ifndef fallthrough
59#define fallthrough __attribute__((fallthrough))
60#endif
61
62/* errno values kernel.h does not carry yet */
63#ifndef EFAULT
64#define EFAULT 14
65#endif
66#ifndef EFBIG
67#define EFBIG 27
68#endif
69#ifndef ENXIO
70#define ENXIO 6
71#endif
72#ifndef ERESTARTSYS
73#define ERESTARTSYS 512
74#endif
75
76/* ── scheduler surface (mainline: linux/sched/{signal.h}) ────────────────
77 * Xeneva's DCL ports are polled and run to completion inside the syscall;
78 * no preemption point and no signal delivery to unwind out of a copy. */
79
80#ifndef need_resched
81#define need_resched() 0
82#endif
83#ifndef cond_resched
84#define cond_resched() ((void)0)
85#endif
86#ifndef signal_pending
87#define signal_pending(p) 0
88#endif
89#ifndef current
90#define current ((void*)0)
91#endif
92
93/*
94 * The VFS helpers that used to open this section -- file_inode(), iminor(),
95 * inode_lock()/inode_unlock() and noop_llseek() -- have moved to
96 * <linux/mount.h>, included at the top of this file so ports reaching them
97 * through mm.h keep working. mainline keeps all five in its fs.h, DCL's fs.h
98 * is pinned and cannot carry them, and mount.h has taken that fs.h surface
99 * over (it already had simple_pin_fs() and unmap_mapping_range() for the same
100 * reason). The drm set reaches them from mount.h directly, which is what let
101 * them leave here; nothing in mm.h's own body uses them.
102 */
103
104/* mainline include/linux/major.h */
105#define MEM_MAJOR 1
106
107/* lseek origins (mainline: uapi asm-generic/fcntl.h) */
108#define SEEK_SET 0
109#define SEEK_CUR 1
110#define SEEK_END 2
111
112/*
113 * mainline include/linux/fs.h: register_chrdev() is a static inline that
114 * forwards to __register_chrdev(), which the cdev bridge implements.
115 */
116extern int __register_chrdev(unsigned int major, unsigned int baseminor,
117 unsigned int count, const char* name,
118 const void* fops);
119extern void __unregister_chrdev(unsigned int major, unsigned int baseminor,
120 unsigned int count, const char* name);
121
122static inline int register_chrdev(unsigned int major, const char* name,
123 const struct file_operations* fops) {
124 return __register_chrdev(major, 0, 256, name, (const void*)fops);
125}
126
127static inline void unregister_chrdev(unsigned int major, const char* name) {
128 __unregister_chrdev(major, 0, 256, name);
129}
130
131/* used by open_port(); DCL keeps no iomem mapping object */
132static inline void* iomem_get_mapping(void) { return (void*)0; }
133
134/* mainline include/linux/fs.h; fmode/fop flag bits mem.c ORs into struct file */
135#define FMODE_NOWAIT 0x00080000
136#define FOP_UNSIGNED_OFFSET 0x0001
137
138/* ── mmap descriptor surface (mainline: linux/mm.h + vma.h) ──────────────
139 * Xeneva's devfs bridge has no ->mmap routing yet, so these types exist so
140 * the mainline mmap arms compile; the shims below report "unsupported"
141 * instead of pretending a pfn remap happened. */
142
144
146 void* access; /* generic_access_phys only under CONFIG_HAVE_IOREMAP_PROT */
147 void* close;
148 /*
149 * DCL delta: mainline's open() callback, added with the virtio-gpu
150 * port -- virtgpu_vram.c:30 names .open = drm_gem_vm_open. No VMA is
151 * ever constructed on this port, so nothing calls it; the field exists
152 * so the vendored initialiser compiles, the same reason the two above
153 * are void pointers rather than typed function pointers.
154 */
155 void* open;
156};
157
158/* ── struct vm_area_struct ───────────────────────────────────────────────
159 *
160 * mainline keeps this in <linux/mm_types.h>. DCL's cannot: the struct's
161 * vm_page_prot member is a pgprot_t, pgprot_t is defined at the top of this
162 * file, and mm_types.h is included *by* it -- the definition would have to
163 * run the other way. So it lives here, next to the type it needs.
164 *
165 * It is the whole struct and not just the members drm reads, because a
166 * partial struct is indistinguishable from a complete one until someone adds
167 * a member: the compiler would accept a write to a field that is not there
168 * and place it at whatever offset it had computed, which is the failure mode
169 * an ABI pin exists to prevent.
170 *
171 * The members are mainline's names and mainline's order for the ones
172 * drm_gem.c touches -- vm_start, vm_end, vm_flags, vm_page_prot, vm_pgoff,
173 * vm_private_data, vm_ops -- plus vm_file, which mainline carries in the same
174 * place and which nothing here reads yet. This is a layout nothing persists
175 * and nothing outside this kernel sees: Xeneva's devfs bridge has no ->mmap
176 * routing (see the note opening this section), so no vma is ever constructed.
177 * The struct exists so that drm_gem.c's mmap half compiles, and drm_gem.c
178 * only ever reads these members back.
179 */
181
192
193/*
194 * The four VM_* bits drm names, at drm_gem.c:1247 and :1254.
195 *
196 * They are mainline's long-standing numbers, and they are spelled as numbers
197 * rather than as mainline v7.2 spells them -- v7.2 moved the entire VM_* set
198 * onto a VMA_*_BIT enum whose numbering is generated by a DECLARE_VMA_BIT()
199 * list in that header, and reproducing the generated order here would be a
200 * claim about a bit layout that nothing in this kernel can read back. What
201 * matters is that the four are distinct, that they do not collide with the
202 * VMA_NORESERVE_BIT and VMA_SHARED_BIT already named above, and that the
203 * flag word they are OR'd into is the same word vm_flags_set() writes and
204 * vm_get_page_prot() reads -- all three of which are here.
205 */
206#define VM_PFNMAP 0x00000400 /* the whole range is one page table */
207/*
208 * DCL delta: mainline's flag, added with the virtio-gpu port --
209 * virtgpu_vram.c:58 sets it on a host-visible blob mapping. Same value as
210 * linux-7.2's include/linux/mm.h; nothing in DCL reads it, and no VMA is
211 * built on this port (see the note above struct vm_operations_struct).
212 */
213#define VM_MIXEDMAP 0x00000100
214#define VM_IO 0x00004000 /* mapped I/O or similar */
215#define VM_DONTEXPAND 0x00080000 /* mremap may not grow this */
216#define VM_DONTDUMP 0x02000000 /* leave out of the core dump */
217
218/*
219 * vm_flags_set() -- OR flags into a vma. mainline's also asserts the mmap
220 * lock is held and goes through a private atomic copy of the flag word;
221 * neither has a referent here, and the assertion would fire on every call
222 * since nothing takes a lock that nothing releases.
223 */
224static inline void vm_flags_set(struct vm_area_struct *vma, vm_flags_t flags)
225{
226 vma->vm_flags |= flags;
227}
228
229/*
230 * vma_pages() -- the length of a mapping in pages, from its bounds.
231 * drm_gem.c:1380 passes the result of this to drm_gem_object_lookup_at_offset()
232 * as the extent to search. Undefined, it was an implicit int-returning
233 * function, which is a warning -- the reason it is defined rather than left
234 * implicit is that the argument it feeds is a u64 offset limit, and a 32-bit
235 * return would silently truncate a mapping larger than 4 GB of pages.
236 */
237static inline unsigned long vma_pages(const struct vm_area_struct *vma)
238{
239 return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
240}
241
242/*
243 * PAGE_ALIGNED(addr) -- mainline's "is this address page-aligned" (v7.2
244 * mm.h), added with the virtio-gpu port: the command path warns on the
245 * answer before walking a buffer page by page, and with the macro
246 * undeclared that line compiled as an implicit call. uintptr_t, not
247 * unsigned long: addresses here hold the top of the 64-bit space and long
248 * is 32 bits on this LLP64 target -- the same width note the allocation
249 * casts carry.
250 */
251#define PAGE_ALIGNED(addr) (((uintptr_t)(addr) & (PAGE_SIZE - 1)) == 0)
252
253/*
254 * is_vmalloc_addr() / vmalloc_to_page() -- mainline declares both in this
255 * header (v7.2 mm.h:1849 and :1859), and that is how the virtio-gpu port's
256 * command path reaches them: the translation unit's include list carries no
257 * <linux/vmalloc.h>, only the DRM headers that land here. There is no
258 * vmalloc address range in this tree (see <linux/vmalloc.h>), so no pointer
259 * can be inside of one and there is no page to translate; both answers are
260 * exactly the ones mainline gives for a kmalloc'd argument, which is what
261 * every caller here passes. Added with the virtio-gpu port, whose vbuf
262 * assembly tests a buffer before walking it page by page and translates it
263 * when the test says vmalloc.
264 */
265struct page;
266
267static inline bool is_vmalloc_addr(const void* addr)
268{
269 (void)addr;
270 return false;
271}
272
273static inline struct page* vmalloc_to_page(const void* addr)
274{
275 (void)addr;
276 return NULL;
277}
278
279/*
280 * vm_get_page_prot() -- turn VMA flags into a page-table protection.
281 *
282 * There are no page tables to translate into, and the answer is never
283 * observed: drm_gem.c:1255-1256 pipes it through pgprot_writecombine() and
284 * pgprot_decrypted(), both of which below return their argument unchanged,
285 * into vma->vm_page_prot -- a field nothing reads. Returning 0 is "no
286 * attributes", which is what these flags mean before an arch adds one.
287 *
288 * A static inline rather than the exported function mainline has in
289 * mm/pgprot.c, so no link symbol is added for a body that is one line.
290 */
291static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
292{
293 (void)vm_flags;
294 return 0;
295}
296
297/*
298 * pgprot_writecombine() / pgprot_decrypted() -- the two transformations
299 * drm_gem.c:1255-1256 applies in turn. mainline's are arch hooks: arm64's
300 * writecombine clears the cacheability bits to a write-combining encoding,
301 * and the decrypted pair is AMD SEV. Xeneva has neither a cache attribute
302 * encoding to clear nor an encrypted memory to decrypt, so both are the
303 * identity -- which is why vm_get_page_prot()'s answer can be 0 with nothing
304 * lost.
305 *
306 * mainline's home for pgprot_writecombine() is <linux/pgtable.h> and
307 * arm64's asm/pgtable.h; there is no such header here, and pgprot_t lives in
308 * this file, so this is where they go.
309 */
310static inline pgprot_t pgprot_writecombine(pgprot_t prot)
311{
312 return prot;
313}
314
315static inline pgprot_t pgprot_decrypted(pgprot_t prot)
316{
317 return prot;
318}
319
320/*
321 * pgprot_noncached() -- arm64's "map uncached" attribute, the sibling of
322 * pgprot_writecombine() above and the same identity for the same reason.
323 * Added with the virtio-gpu port: the vram mmap path selects it for blobs
324 * whose host mapping is uncached, and that path is only reachable on a
325 * device with a host-visible region -- none of the ones this tree scans.
326 */
327static inline pgprot_t pgprot_noncached(pgprot_t prot)
328{
329 return prot;
330}
331
332/*
333 * io_remap_pfn_range() -- mainline's remap of a pfn range into a VMA
334 * (arm64 declares it; the generic form is a #define to remap_pfn_range).
335 * One caller, the same unreachable vram mmap path as pgprot_noncached()
336 * above. There is no pfn remap on this port -- the devfs bridge builds no
337 * VMAs for drivers (see the vma section note) -- so the honest answer is
338 * mainline's "cannot remap" failure, which the one caller already has a
339 * branch for.
340 */
341static inline int io_remap_pfn_range(struct vm_area_struct *vma,
342 unsigned long addr, unsigned long pfn,
343 unsigned long size, pgprot_t prot)
344{
345 (void)vma;
346 (void)addr;
347 (void)pfn;
348 (void)size;
349 (void)prot;
350 return -ENOSYS;
351}
352
354 struct file* file;
355 unsigned long vm_flags;
356 unsigned long pgoff;
357 unsigned long len;
360 struct {
363};
364
365#define VMA_SHARED_BIT 3
366
367static inline size_t vma_desc_size(const struct vm_area_desc* desc) {
368 return (size_t)desc->len;
369}
370static inline int vma_desc_test(const struct vm_area_desc* desc, int bit) {
371 (void)desc;
372 (void)bit;
373 return 0;
374}
375static inline void vma_desc_set_anonymous(struct vm_area_desc* desc) {
376 (void)desc;
377}
378static inline void mmap_action_remap_full(struct vm_area_desc* desc, unsigned long pgoff) {
379 (void)desc;
380 (void)pgoff;
381}
382
383int valid_phys_addr_range(phys_addr_t addr, size_t count);
384int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
385int range_is_allowed(unsigned long pgoff, unsigned long size);
386int phys_mem_access_prot_allowed(struct file* file, unsigned long pfn,
387 unsigned long size, pgprot_t* vma_prot);
388unsigned long mm_get_unmapped_area(struct file* file, unsigned long addr,
389 unsigned long len, unsigned long pgoff,
390 unsigned long flags);
391
392/* /dev/kmsg -- mainline declares kmsg_fops in include/linux/printk.h */
393extern const struct file_operations kmsg_fops;
394
395#endif /* __LINUX_MM_H__ */
#define PAGE_SHIFT
Definition vmmngr.h:80
uint8_t flags
Definition virtio.h:0
COMPILER_DEPENDENT_UINT64 uint64_t
Definition acefiex.h:165
#define NULL
Definition actypes.h:561
size_t size
Definition drm_bridge.h:1299
struct drm_crtc struct drm_plane struct drm_plane const struct drm_crtc_funcs const char * name
Definition drm_crtc.h:1242
size_t len
Definition initial.c:23
uintptr_t phys_addr_t
Definition kernel.h:40
#define ENOSYS
Definition kernel.h:310
int __register_chrdev(unsigned int major, unsigned int baseminor, unsigned int count, const char *name, const void *fops)
t t typedef unsigned long vma_flags_t
Definition mm.h:38
vma_flags_t vm_flags_t
Definition mm.h:180
int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, unsigned long size, pgprot_t *vma_prot)
uint64_t pgprot_t
Definition mm.h:143
int range_is_allowed(unsigned long pgoff, unsigned long size)
const struct file_operations kmsg_fops
unsigned long mm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
void __unregister_chrdev(unsigned int major, unsigned int baseminor, unsigned int count, const char *name)
int valid_phys_addr_range(phys_addr_t addr, size_t count)
Definition fs.h:67
Definition fs.h:142
Definition pagemap.h:38
Definition mm.h:353
pgprot_t page_prot
Definition mm.h:358
int error_override
Definition mm.h:361
unsigned long len
Definition mm.h:357
unsigned long vm_flags
Definition mm.h:355
struct vm_area_desc::@81 action
struct file * file
Definition mm.h:354
const struct vm_operations_struct * vm_ops
Definition mm.h:359
unsigned long pgoff
Definition mm.h:356
Definition mm.h:182
vm_flags_t vm_flags
Definition mm.h:185
unsigned long vm_start
Definition mm.h:183
const struct vm_operations_struct * vm_ops
Definition mm.h:190
struct file * vm_file
Definition mm.h:189
unsigned long vm_end
Definition mm.h:184
pgprot_t vm_page_prot
Definition mm.h:186
unsigned long vm_pgoff
Definition mm.h:187
void * vm_private_data
Definition mm.h:188
Definition mm.h:145
void * open
Definition mm.h:155
void * close
Definition mm.h:147
void * access
Definition mm.h:146