XenevaOS
Loading...
Searching...
No Matches
fs.h
Go to the documentation of this file.
1#ifndef __LINUX_FS_H__
2#define __LINUX_FS_H__
3
4/*
5 * Linux VFS ABI pins for the DCL layer.
6 *
7 * Frozen against linux-7.2.6 arm64 defconfig built with clang -- the exact
8 * headers and .config that produced virtio_console.ko. The module reads and
9 * writes these structs with its own compiled-in offsets, so every member the
10 * module touches MUST sit at the offset marked below; everything else is
11 * padding. Offsets verified by offsetof probes compiled inside the same
12 * kernel tree (file 176B, file_operations 272B, inode 560B, cdev 104B,
13 * device 800B, poll_table_struct 16B).
14 */
15
16#include <stdint.h>
17#include <stddef.h>
18
19struct cdev;
20struct inode;
21struct file;
22struct module;
23struct kiocb;
24struct iov_iter;
25struct dir_context;
26struct vm_area_struct;
27struct file_lock;
28struct pipe_inode_info;
29struct seq_file;
30struct io_uring_cmd;
31struct address_space;
32struct io_comp_batch;
33struct vm_area_desc;
34struct inode;
35struct super_block;
36
37#ifndef MKDEV
38#define MKDEV(ma, mi) (((unsigned int)(ma) << 20) | ((unsigned int)(mi)))
39#define MAJOR(dev) ((unsigned int)(dev) >> 20)
40#define MINOR(dev) ((unsigned int)(dev) & 0xFFFFFu)
41#endif
42
43/* The input core's initcall is compiled but never run; these keep its body
44 * linkable without claiming a major from the DCL allocator. */
45int register_chrdev_region(unsigned int from, unsigned int count,
46 const char* name);
47void unregister_chrdev_region(unsigned int from, unsigned int count);
48
49typedef unsigned int fop_flags_t;
50typedef unsigned int __poll_t;
51
53 void (*_qproc)(struct file*, void* wait_queue_head, struct poll_table_struct*);
54 unsigned int _key;
55};
56
57/*
58 * Member order copied verbatim from linux-7.2.6 include/linux/fs.h.
59 * Offsets: owner 0, fop_flags 8, llseek 16, read 24, write 32, read_iter 40,
60 * write_iter 48, iopoll 56, iterate_shared 64, poll 72, unlocked_ioctl 80,
61 * compat_ioctl 88, mmap 96, open 104, flush 112, release 120, fsync 128,
62 * fasync 136, lock 144, get_unmapped_area 152, check_flags 160, flock 168,
63 * splice_write 176, ... mmap_prepare 264, size 272.
64 * DCL only calls read/write/open/release/poll/fasync; the rest are layout
65 * slots so the module's static initializers land correctly.
66 */
68 struct module* owner; /* 0 */
70 unsigned int _pad_flags; /* 12 */
71 void* llseek; /* 16 */
72 long (*read)(struct file*, char*, size_t, long long*); /* 24 */
73 long (*write)(struct file*, const char*, size_t, long long*); /* 32 */
74 void* read_iter; /* 40 */
75 void* write_iter; /* 48 */
76 void* iopoll; /* 56 */
77 void* iterate_shared; /* 64 */
78 __poll_t (*poll)(struct file*, struct poll_table_struct*); /* 72 */
79 void* unlocked_ioctl; /* 80 */
80 void* compat_ioctl; /* 88 */
81 /*
82 * mmap and get_unmapped_area are the third deviation from this
83 * header's pinned rule, and the reason is the same one as i_mapping's
84 * below: the drm core *calls* them, and a call through a void* is
85 * not a call at all -- clang reports "called object type 'void *' is
86 * not a function or function pointer". Two sites, drm_gem.c:1353
87 * (get_unmapped_area) and drm_prime.c:798 (mmap), both through a
88 * `const struct file_operations *` that is this struct.
89 *
90 * Both are given mainline's own signatures and both keep their slot:
91 * a function pointer is 8 bytes, a void* is 8 bytes, so offset 96 and
92 * offset 152 and sizeof(struct file_operations) are all unchanged.
93 * Every existing assignment still fits, since it was already assigning
94 * a function to these fields -- DEFINE_DRM_GEM_FOPS at drm_gem.h:472-473
95 * and DCL/mem.c:641 and :675 all spell the same 5-argument
96 * unsigned-long-returning get_unmapped_area mainline does.
97 */
98 int (*mmap)(struct file*, struct vm_area_struct*); /* 96 */
99 int (*open)(struct inode*, struct file*); /* 104 */
100 void* flush; /* 112 */
101 int (*release)(struct inode*, struct file*); /* 120 */
102 void* fsync; /* 128 */
103 int (*fasync)(int, struct file*, int); /* 136 */
104 void* lock; /* 144 */
105 unsigned long (*get_unmapped_area)(struct file*, unsigned long, unsigned long, unsigned long, unsigned long); /* 152 */
106 void* check_flags; /* 160 */
107 void* flock; /* 168 */
108 void* splice_write; /* 176 */
109 void* splice_read; /* 184 */
110 void* splice_eof; /* 192 */
111 void* setlease; /* 200 */
112 void* fallocate; /* 208 */
113 void* show_fdinfo; /* 216 */
114 void* copy_file_range; /* 224 */
115 void* remap_file_range; /* 232 */
116 void* fadvise; /* 240 */
117 void* uring_cmd; /* 248 */
118 void* uring_cmd_iopoll; /* 256 */
119 void* mmap_prepare; /* 264 */
120};
121
122/*
123 * mmap and get_unmapped_area are the two slots the drm core *calls* through
124 * this struct (drm_prime.c:798, drm_gem.c:1353 -- the note inside the struct
125 * explains why they carry real signatures). The asserts pin the offsets that
126 * comment claims, so a member inserted above them is a compile error here
127 * rather than a call to an 8-byte field that is no longer a function.
128 */
129_Static_assert(__builtin_offsetof(struct file_operations, mmap) == 96,
130 "fs.h: f_op->mmap is pinned at 96 (drm_prime.c:798 calls it)");
131_Static_assert(__builtin_offsetof(struct file_operations, get_unmapped_area) == 152,
132 "fs.h: f_op->get_unmapped_area is pinned at 152 (drm_gem.c:1353 calls it)");
133
134/*
135 * linux-7.2.6 struct file: f_lock 0, f_mode 4, f_op 8, f_mapping 16,
136 * private_data 24, f_inode 32, f_flags 40, f_iocb_flags 44, f_cred 48,
137 * f_owner 56, f_path 64, f_pos_lock 80, f_pos 96, ... size 176.
138 * The module touches private_data (rw) and f_flags (O_NONBLOCK reads);
139 * the bridge passes &f_pos to ->read/->write as the loff_t* position.
140 * tail/field behind pad are layout-only (CONFIG_SECURITY etc. vary).
141 */
142struct file {
143 int f_lock; /* 0 */
144 unsigned int f_mode; /* 4 */
145 const struct file_operations* f_op; /* 8 */
146 void* f_mapping; /* 16 */
147 void* private_data; /* 24 */
148 void* f_inode; /* 32 */
149 unsigned int f_flags; /* 40 */
150 unsigned int f_iocb_flags; /* 44 */
151 void* f_cred; /* 48 */
152 void* f_owner; /* 56 */
153 void* f_path; /* 64 */
154 unsigned char _pos_lock[16]; /* 80 */
155 long long f_pos; /* 96 */
156 unsigned char _tail[176 - 104]; /* 104..175 */
157};
158
159/*
160 * linux-7.2.6 struct inode: i_rdev 76, i_cdev 528, size 560.
161 * The module reads only i_cdev (port_fops_open resolves its port from
162 * inode->i_cdev->dev); i_rdev is kept for the bridge's own bookkeeping.
163 *
164 * i_mapping is the second deviation from the "pinned, do not edit" rule for
165 * this header, and it is the same shape as the first: a member the drm core
166 * cannot work without, taken out of padding rather than added at the end.
167 *
168 * Four sites read it -- drm_file.c:386 and :1074, drm_gem.c:747 and
169 * drm_prime.c:251 -- all of them `...->i_mapping` on a struct inode *, which
170 * is the one form a macro cannot fix: the token is to the right of `->`, and
171 * a member that does not exist cannot be named, aliased or discarded from the
172 * outside. Every consumer is an address-and-store (`filp->f_mapping =
173 * dev->anon_inode->i_mapping`), so the object it points at is never touched
174 * through this header -- an opaque pointer is enough.
175 *
176 * It is placed at offset 80, the first byte of what used to be _mid[448],
177 * and _mid is shortened to 440 to keep every other offset where it was:
178 * i_rdev still at 76, i_cdev still at 528, sizeof still 560. Nothing is
179 * persisted, but the ABI these offsets describe belongs to code this header
180 * does not own, and a blob whose padding moved would be a blob whose one
181 * readable member landed somewhere else.
182 */
183struct inode {
184 unsigned char _head[76]; /* 0..75 */
185 unsigned int i_rdev; /* 76 */
186 struct address_space* i_mapping; /* 80 */
187 unsigned char _mid[440]; /* 88..527 */
188 struct cdev* i_cdev; /* 528 */
189 unsigned char _tail[24]; /* 536..559 */
190};
191
192/*
193 * i_cdev is the member the module actually reads -- cdev_shim's open resolves
194 * a port from inode->i_cdev->dev -- and the size is pinned because the
195 * module's own struct inode is 560 bytes: a blob whose padding moved would be
196 * a blob whose one readable member landed somewhere else. Both numbers are
197 * mainline's, as the comment above the struct records; the asserts are what
198 * keeps them that way.
199 */
200_Static_assert(sizeof(struct inode) == 560,
201 "fs.h: struct inode is pinned to 560B (linux-7.2.6 arm64)");
202_Static_assert(__builtin_offsetof(struct inode, i_cdev) == 528,
203 "fs.h: i_cdev is pinned at 528 (the module resolves its port from it)");
204
205/*
206 * linux-7.2.6 struct cdev: kobj 0 (64B), owner 64, ops 72, list 80,
207 * dev 96, count 100, size 104. The module writes ->ops before cdev_add
208 * and reads ->dev in find_port_by_devt().
209 */
210struct cdev {
211 unsigned char kobj[64]; /* 0 (kobject: name at 0) */
212 void* owner; /* 64 */
213 const struct file_operations* ops; /* 72 */
214 unsigned char list[16]; /* 80 */
215 unsigned int dev; /* 96 */
216 unsigned int count; /* 100 */
217};
218
219/*
220 * linux-7.2.6 struct device: kobj.name 0, devt 708, size 800.
221 * device_create() sets name (dev_name() reads kobj.name) and the module's
222 * device_destroy() reads ->devt. Everything between is padding; PM and
223 * link-state members live there in mainline and are never dereferenced
224 * from the module.
225 */
226/* Owned by <linux/of.h>; declared here only so the of_node member below has a
227 * type to point at without this header having to know what a device tree is. */
228struct device_node;
229struct class;
230struct device_type;
231
232/*
233 * Two DCL-only members are carved out of the padding this struct declares
234 * above, rather than appended after it, and the three things that make this
235 * struct an ABI pin all still hold afterwards: kobj_name at 0, devt at 708,
236 * sizeof 800. Appending would have kept the first two and silently broken
237 * the third -- the module embeds `struct device` inside its own objects and
238 * was compiled with a 800-byte one, so an 816-byte DCL would have DCL's
239 * writes landing past the end of the module's allocation.
240 *
241 * The offsets are mainline's, not chosen: `struct device` opens with `struct
242 * kobject kobj`, which the struct cdev above measures at 64 bytes, so
243 * `parent` is the next member at 64 -- the same slot the module would read
244 * if it ever read one. `of_node` sits at 696, the last 8-byte-aligned hole
245 * before the devt pin, with 704..707 left as `_pad` so devt does not move.
246 * Both are read-only at their two call sites (serial_core.c:3093 and :3236),
247 * and DCL's own devices come out of device_create()'s memset, so they read
248 * zero rather than whatever the module left in those bytes.
249 *
250 * The three _Static_asserts below exist so that none of this has to be
251 * re-argued: if a future edit moves devt or grows the struct, the build says
252 * so at this line instead of at boot, when the failure would be a corrupt
253 * device table and no message to explain it.
254 */
255struct device {
256 union {
257 const char* kobj_name; /* 0 (kobject.name) */
258 unsigned char kobj[64]; /* 0..63, same as struct kobject */
259 };
260 struct device* parent; /* 64 (after kobj, as in mainline) */
261 const struct class* class; /* 72 */
262 const struct device_type* type; /* 80 */
263 void* driver_data; /* 88 */
264 void (*release)(struct device*); /* 96 */
265 const struct attribute_group** groups; /* 104 */
266 unsigned char _mid[584]; /* 112..695 */
267 struct device_node* of_node; /* 696 */
268 unsigned char _pad[4]; /* 700..707 */
269 unsigned int devt; /* 708 */
270 unsigned char _tail[88]; /* 712..799 */
271};
272
273_Static_assert(sizeof(struct device) == 800,
274 "fs.h: struct device is pinned to 800B (linux-7.2.6 arm64)");
275_Static_assert(__builtin_offsetof(struct device, kobj_name) == 0,
276 "fs.h: kobj_name is pinned at 0 (device_create writes it)");
277_Static_assert(__builtin_offsetof(struct device, devt) == 708,
278 "fs.h: devt is pinned at 708 (the module's device_destroy reads it)");
279
280/* IS_ERR/PTR_ERR: same range check the module inlines from linux/err.h. */
281#define DCL_MAX_ERRNO 4095
282static inline int dcl_is_err(const void* ptr) {
283 /* uintptr_t, not unsigned long: this target is LLP64 (aarch64
284 * windows), where unsigned long is 32 bits */
285 return (uintptr_t)ptr >= (uintptr_t)(-(long)DCL_MAX_ERRNO);
286}
287#define ERR_PTR(err) ((void*)(long)(err))
288#define PTR_ERR(ptr) ((long)(ptr))
289#define IS_ERR(ptr) dcl_is_err(ptr)
290
291/*
292 * fops_get() / replace_fops() -- mainline's two <linux/fs.h> helpers for
293 * rebinding a file's operations from ->open(); drm_stub_open() (drm_drv.c
294 * :1203, :1209) is the tree's only caller and includes this header directly.
295 *
296 * Both keep mainline's signature and its effect, not its implementation:
297 * mainline's fops_get() is a macro over try_module_get() and its
298 * replace_fops() a macro pairing fops_put() with a BUG_ON() on the new
299 * pointer. DCL modules are compiled into the image and never unloaded, so
300 * holding a reference is keeping the pointer -- the same trade get_file()
301 * makes next door in <linux/file.h> -- and neither module_put() nor BUG_ON()
302 * is reachable from this header. A NULL fops still answers NULL.
303 */
304static inline const struct file_operations*
305fops_get(const struct file_operations* fops)
306{
307 return fops;
308}
309
310static inline void replace_fops(struct file* filp,
311 const struct file_operations* fops)
312{
313 filp->f_op = fops;
314}
315
316#endif /* __LINUX_FS_H__ */
uint64_t size_t
Definition stdint.h:104
unsigned int uintptr_t
Definition stdint.h:94
struct drm_crtc struct drm_plane struct drm_plane const struct drm_crtc_funcs const char * name
Definition drm_crtc.h:1242
#define DCL_MAX_ERRNO
Definition fs.h:281
unsigned int __poll_t
Definition fs.h:50
void unregister_chrdev_region(unsigned int from, unsigned int count)
int register_chrdev_region(unsigned int from, unsigned int count, const char *name)
unsigned int fop_flags_t
Definition fs.h:49
Definition shmem_fs.h:25
Definition sysfs.h:33
Definition fs.h:210
unsigned int count
Definition fs.h:216
unsigned int dev
Definition fs.h:215
unsigned char list[16]
Definition fs.h:214
const struct file_operations * ops
Definition fs.h:213
unsigned char kobj[64]
Definition fs.h:211
void * owner
Definition fs.h:212
Definition device.h:38
Definition device.h:29
Definition fs.h:255
const struct device_type * type
Definition fs.h:262
struct device * parent
Definition fs.h:260
unsigned int devt
Definition fs.h:269
unsigned char kobj[64]
Definition fs.h:258
const struct attribute_group ** groups
Definition fs.h:265
unsigned char _tail[88]
Definition fs.h:270
void(* release)(struct device *)
Definition fs.h:264
struct device_node * of_node
Definition fs.h:267
unsigned char _pad[4]
Definition fs.h:268
unsigned char _mid[584]
Definition fs.h:266
const char * kobj_name
Definition fs.h:257
void * driver_data
Definition fs.h:263
Definition fs.h:67
void * llseek
Definition fs.h:71
unsigned long(* get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long)
Definition fs.h:105
void * flock
Definition fs.h:107
void * unlocked_ioctl
Definition fs.h:79
void * check_flags
Definition fs.h:106
fop_flags_t fop_flags
Definition fs.h:69
void * mmap_prepare
Definition fs.h:119
void * splice_eof
Definition fs.h:110
void * compat_ioctl
Definition fs.h:80
void * uring_cmd_iopoll
Definition fs.h:118
int(* fasync)(int, struct file *, int)
Definition fs.h:103
void * splice_write
Definition fs.h:108
int(* open)(struct inode *, struct file *)
Definition fs.h:99
struct module * owner
Definition fs.h:68
void * lock
Definition fs.h:104
void * remap_file_range
Definition fs.h:115
void * iopoll
Definition fs.h:76
long(* write)(struct file *, const char *, size_t, long long *)
Definition fs.h:73
void * iterate_shared
Definition fs.h:77
void * fallocate
Definition fs.h:112
void * show_fdinfo
Definition fs.h:113
void * setlease
Definition fs.h:111
void * uring_cmd
Definition fs.h:117
long(* read)(struct file *, char *, size_t, long long *)
Definition fs.h:72
void * write_iter
Definition fs.h:75
int(* mmap)(struct file *, struct vm_area_struct *)
Definition fs.h:98
void * splice_read
Definition fs.h:109
void * read_iter
Definition fs.h:74
void * flush
Definition fs.h:100
unsigned int _pad_flags
Definition fs.h:70
__poll_t(* poll)(struct file *, struct poll_table_struct *)
Definition fs.h:78
void * copy_file_range
Definition fs.h:114
void * fsync
Definition fs.h:102
void * fadvise
Definition fs.h:116
int(* release)(struct inode *, struct file *)
Definition fs.h:101
Definition fs.h:142
void * f_owner
Definition fs.h:152
unsigned int f_iocb_flags
Definition fs.h:150
void * private_data
Definition fs.h:147
unsigned char _pos_lock[16]
Definition fs.h:154
int f_lock
Definition fs.h:143
unsigned char _tail[176 - 104]
Definition fs.h:156
const struct file_operations * f_op
Definition fs.h:145
unsigned int f_mode
Definition fs.h:144
void * f_path
Definition fs.h:153
long long f_pos
Definition fs.h:155
void * f_inode
Definition fs.h:148
unsigned int f_flags
Definition fs.h:149
void * f_cred
Definition fs.h:151
void * f_mapping
Definition fs.h:146
Definition fs.h:183
unsigned int i_rdev
Definition fs.h:185
unsigned char _mid[440]
Definition fs.h:187
unsigned char _head[76]
Definition fs.h:184
unsigned char _tail[24]
Definition fs.h:189
struct address_space * i_mapping
Definition fs.h:186
struct cdev * i_cdev
Definition fs.h:188
Definition uio.h:40
Definition uio.h:21
Definition fs.h:52
unsigned int _key
Definition fs.h:54
void(* _qproc)(struct file *, void *wait_queue_head, struct poll_table_struct *)
Definition fs.h:53
Definition seq_file.h:47
Definition mm.h:353
Definition mm.h:182
Definition wait.h:75