XenevaOS
Loading...
Searching...
No Matches
pagemap.h
Go to the documentation of this file.
1#ifndef __LINUX_PAGEMAP_H__
2#define __LINUX_PAGEMAP_H__
3
4/*
5 * DCL <linux/pagemap.h> -- the eight page primitives virtio_console.c uses.
6 *
7 * mainline's is 50 KB and its first include is <linux/mm.h>, which is the
8 * whole memory-management subsystem (rmap, page tables, compaction, the NUMA
9 * balancing state reached through gfp.h). The driver's entire contact with
10 * the page model is:
11 *
12 * alloc_page(GFP_KERNEL) :875 splice fallback buffer
13 * page_address(page) :888 destination of the copy
14 * kmap_local_page / kunmap :887 source window over pipe_buffer.page
15 * get_page / put_page :868 refcount, and free_buf()'s release loop
16 * lock_page / unlock_page :869 taken around the steal
17 * sg_page / sg_set_page :354 <linux/scatterlist.h>, which is DCL's own
18 * PAGE_SIZE / PAGE_MASK :884 <Mm/vmmngr.h>, Xeneva's native geometry
19 *
20 * so this header defines exactly that and nothing else.
21 *
22 * The page *contents* live inside struct page itself. DCL has no buddy-to-
23 * struct-page array and no virtual-address lookup, and splice is not routed
24 * by the devfs bridge yet (see <linux/splice.h>), so the honest shape for a
25 * page here is one kmalloc'd block that is both the descriptor and the
26 * storage. alloc_page() therefore returns a block whose ->data is what
27 * page_address() hands out, which is an ordinary kernel heap pointer -- the
28 * same kind of pointer that sg_init_one() already feeds to the virtio queue,
29 * so the DMA translation in DCL/virtio_shim.c needs no new case for it.
30 */
31
32#include <linux/gfp.h>
33#include <linux/types.h>
34#include <linux/mm.h> /* DCL's hub header: uaccess (copy_*_user),
35 * register_chrdev, min/ARRAY_SIZE, PAGE_SIZE */
36#include <Mm/vmmngr.h> /* PAGE_SHIFT, PAGE_SIZE, PAGE_MASK */
37
38struct page {
39 unsigned int refcount;
41};
42
43/*
44 * page_address(page) -- the data block of a struct page.
45 *
46 * It used to be spelled `((page)->data)`, which is right for every call that
47 * passes a `struct page *` and wrong the moment anything else does: a member
48 * reference through a `void *` argument is a hard error (one `->` on a void
49 * base), and virtio_console.c:887 passes `buf->page` from <linux/splice.h>,
50 * where the field is `void *` because DCL's pipe_buffer has no page array
51 * behind it. Adding the offset instead of dereferencing answers both forms
52 * with one expression, and it answers them the same way -- __builtin_offsetof
53 * needs no <stddef.h> and gives the exact displacement the `->` did.
54 *
55 * The argument is still read as a struct page pointer, which is what it is:
56 * the alternative (treating it as a raw buffer) would silently shift a real
57 * page by the refcount's four bytes.
58 */
59/*
60 * The parameter is named `p`, not `page`: a macro argument replaces every
61 * token that spells it, including the one in `struct page` two lines down,
62 * and `__builtin_offsetof(struct p, data)` is a diagnostic about an expected
63 * comma at an expression that was never meant to hold one.
64 */
65#define page_address(p) \
66 ((void*)((char*)(void*)(p) + __builtin_offsetof(struct page, data)))
67#define lowmem_page_address(page) page_address(page)
68
69/*
70 * kmap_local_page / kunmap_local -- mainline maps the page into the caller's
71 * address space for the duration of the statement. DCL's kernel is a single
72 * flat higher-half mapping, so a page's address is already its address: the
73 * map is the identity and the unmap is a statement that has to stay, because
74 * the driver writes it and it has to parse.
75 */
76#define kmap_local_page(page) page_address(page)
77#define kunmap_local(addr) ((void)(addr))
78
79void* alloc_page(gfp_t gfp);
80
81/*
82 * Refcounts are real: alloc_page() starts at 1, get_page() adds one,
83 * put_page() drops one and frees at zero, which is the contract free_buf()
84 * relies on at :350-357 (it walks sgpages and releases each page exactly
85 * once).
86 */
87void get_page(struct page* page);
88void put_page(struct page* page);
89
90/*
91 * lock_page / unlock_page -- no-ops, deliberately. The only pair in the
92 * driver is :868-869, inside pipe_to_sg(), which runs only when splice is
93 * actually routed, and the devfs bridge does not route it yet. Making them
94 * real would mean a per-page waitqueue for a path that cannot be entered;
95 * a no-op here is the same class of decision as device_find_child() ->
96 * NULL and pm_runtime_enabled() -> 0. If splice is ever wired up, this is
97 * the one line in this file that has to change.
98 */
99void lock_page(struct page* page);
100void unlock_page(struct page* page);
101
102#endif /* __LINUX_PAGEMAP_H__ */
#define PAGE_SIZE
Definition vmmngr.h:92
unsigned int gfp_t
Definition kernel.h:56
void lock_page(struct page *page)
void get_page(struct page *page)
void * alloc_page(gfp_t gfp)
void unlock_page(struct page *page)
void put_page(struct page *page)
Definition pagemap.h:38
char data[PAGE_SIZE]
Definition pagemap.h:40
unsigned int refcount
Definition pagemap.h:39