1/**
2 * Program that maps its own page-table into
3 * it's virtual address space.
4 **/
5#include <stdio.h>
6#include <inttypes.h>
7#include <assert.h>
8
9#include <barrelfish/barrelfish.h>
10#include <barrelfish/invocations_arch.h>
11#include <barrelfish/except.h>
12
13#define ALL_PRIVILEGES (VREGION_FLAGS_READ | VREGION_FLAGS_WRITE | VREGION_FLAGS_EXECUTE)
14#define NO_PRIVILEGES 0x0
15
16static void print_vnodes(struct vnode* current, int depth);
17static void print_vnode(struct vnode *current, int depth)
18{
19    char pad[depth+1];
20    for (int i=0; i<depth; i++) {
21        pad[i] = ' ';
22    }
23    pad[depth] = '\0';
24
25    char capbuffer[1024];
26
27    printf("%s", pad);
28    printf("vnode:%p { entry: %d is_vnode: %d\n", current, current->v.entry, current->v.is_vnode);
29    if (current->v.is_vnode) {
30        debug_print_cap_at_capref(capbuffer, 1024, current->v.cap);
31        printf("%s", pad);
32        printf("vnode: cap=%s\n", capbuffer);
33#if defined(PMAP_LL)
34        print_vnodes(current->v.u.vnode.children, depth+1);
35#elif defined(PMAP_ARRAY)
36        print_vnodes(current->v.u.vnode.children[0], depth+1);
37#else
38#error Invalid pmap datastructure
39#endif
40    }
41    else {
42        debug_print_cap_at_capref(capbuffer, 1024, current->v.cap);
43        printf("%s", pad);
44        printf("frame: cap=%s offset:%"PRIxGENVADDR" flags:%d",
45                capbuffer, current->v.u.frame.offset, current->v.u.frame.flags);
46    }
47    printf("\n");
48    printf("%s", pad);
49    printf("}\n");
50}
51
52static void print_vnodes(struct vnode* current, int depth) {
53#if defined(PMAP_LL)
54    while(current != NULL) {
55#elif defined(PMAP_ARRAY)
56    if (depth == 0) {
57        print_vnode(current, depth);
58        return;
59    }
60    struct vnode **currentp = &current;
61    for (int i = 0; i < PTABLE_SIZE; i++) {
62        current = currentp[i];
63#else
64#error Invalid pmap datastructure
65#endif
66        print_vnode(current, depth);
67    }
68}
69
70#if defined(PMAP_LL)
71static void find_pagetables(struct vnode* current) {
72    char capbuffer[1024];
73
74    while(current != NULL) {
75        if (current->v.is_vnode) {
76            struct capability ret;
77            errval_t err = debug_cap_identify(current->v.cap, &ret);
78            if (err_is_fail(err)) {
79                USER_PANIC_ERR(err, "debug_cap_identify failed.");
80            }
81
82            if (ret.type == ObjType_VNode_x86_64_ptable) {
83                printf("%s:%s:%d: we have a pagetable\n", __FILE__, __FUNCTION__, __LINE__);
84
85                struct frame_identity id = { .base = 0, .bits = 0 };
86                err = frame_identify(current->v.cap, &id);
87                if (err_is_fail(err)) {
88                    USER_PANIC_ERR(err, "Invoke vnode identify failed.");
89                }
90
91                struct capref ptable_copy;
92                err = slot_alloc(&ptable_copy);
93                if (err_is_fail(err)) {
94                    USER_PANIC_ERR(err, "Failed to allocate slot");
95                }
96
97                err = cap_copy(ptable_copy, current->v.cap);
98                if (err_is_fail(err)) {
99                    DEBUG_ERR(err, "cap_copy failed");
100                }
101
102                genpaddr_t *ptable = NULL;
103                err = vspace_map_one_frame((void**)&ptable, (size_t)1<<id.bits,
104                                           ptable_copy, NULL, NULL);
105                if (err_is_fail(err)) {
106                    USER_PANIC_ERR(err, "Can not map the frame.");
107                }
108
109                debug_print_cap_at_capref(capbuffer, 1024, current->v.cap);
110                printf("vnode: cap=%s\n", capbuffer);
111
112                for(size_t i=0; i < X86_64_PTABLE_SIZE; i++) {
113                    bool is_dirty = (ptable[i] & X86_64_PTABLE_DIRTY) > 0;
114                    if (is_dirty) {
115                        printf("retaddr[%zu] = 0x%"PRIxGENPADDR" is_dirty = %d\n", i, ptable[i], is_dirty);
116                    }
117                }
118
119                size_t how_many = 0;
120                err = invoke_clean_dirty_bits(current->v.cap, &how_many);
121                if (err_is_fail(err)) {
122                    USER_PANIC_ERR(err, "clean dirty bits failed.");
123                }
124            }
125
126            find_pagetables(current->v.u.vnode.children);
127        }
128        else {
129            // Ignore frames
130        }
131        current = current->next;
132    }
133}
134#elif defined(PMAP_ARRAY)
135static void find_pagetables(struct vnode* current) {
136    USER_PANIC("find_pagetables NYI for array-backed pmap.");
137#if 0
138    char capbuffer[1024];
139
140    while(current != NULL) {
141        if (current->v.is_vnode) {
142            struct capability ret;
143            errval_t err = debug_cap_identify(current->v.cap, &ret);
144            if (err_is_fail(err)) {
145                USER_PANIC_ERR(err, "debug_cap_identify failed.");
146            }
147
148            if (ret.type == ObjType_VNode_x86_64_ptable) {
149                printf("%s:%s:%d: we have a pagetable\n", __FILE__, __FUNCTION__, __LINE__);
150
151                struct frame_identity id = { .base = 0, .bits = 0 };
152                err = frame_identify(current->v.cap, &id);
153                if (err_is_fail(err)) {
154                    USER_PANIC_ERR(err, "Invoke vnode identify failed.");
155                }
156
157                struct capref ptable_copy;
158                err = slot_alloc(&ptable_copy);
159                if (err_is_fail(err)) {
160                    USER_PANIC_ERR(err, "Failed to allocate slot");
161                }
162
163                err = cap_copy(ptable_copy, current->v.cap);
164                if (err_is_fail(err)) {
165                    DEBUG_ERR(err, "cap_copy failed");
166                }
167
168                genpaddr_t *ptable = NULL;
169                err = vspace_map_one_frame((void**)&ptable, (size_t)1<<id.bits,
170                        ptable_copy, NULL, NULL);
171                if (err_is_fail(err)) {
172                    USER_PANIC_ERR(err, "Can not map the frame.");
173                }
174
175                debug_print_cap_at_capref(capbuffer, 1024, current->v.cap);
176                printf("vnode: cap=%s\n", capbuffer);
177
178                for(size_t i=0; i < X86_64_PTABLE_SIZE; i++) {
179                    bool is_dirty = (ptable[i] & X86_64_PTABLE_DIRTY) > 0;
180                    if (is_dirty) {
181                        printf("retaddr[%zu] = 0x%"PRIxGENPADDR" is_dirty = %d\n", i, ptable[i], is_dirty);
182                    }
183                }
184
185                size_t how_many = 0;
186                err = invoke_clean_dirty_bits(current->v.cap, &how_many);
187                if (err_is_fail(err)) {
188                    USER_PANIC_ERR(err, "clean dirty bits failed.");
189                }
190            }
191
192            find_pagetables(current->v.u.vnode.children);
193        }
194        else {
195            // Ignore frames
196        }
197        current = current->next;
198    }
199#endif
200}
201#else
202#error Invalid pmap datastructure
203#endif
204
205int main(int argc, char *argv[])
206{
207    printf("%s:%s:%d: Hi, lets map our own ptable!\n",
208           __FILE__, __FUNCTION__, __LINE__);
209
210    struct pmap* pmap = get_current_pmap();
211    assert(pmap != NULL);
212    struct pmap_x86 *x86 = (struct pmap_x86*)pmap;
213
214    printf("%s:%s:%d: About to print the vnode tree\n",
215           __FILE__, __FUNCTION__, __LINE__);
216    struct vnode* current = &x86->root;
217    print_vnodes(current, 0);
218    find_pagetables(current);
219
220    void *sbrk(intptr_t increment);
221    void* base = sbrk(0);
222    void* limit = sbrk(1<<20); // 1mb
223    assert(base != NULL);
224    printf("%s:%s:%d: base = %p limit = %p\n", __FILE__, __FUNCTION__, __LINE__, base, limit);
225    assert(limit > base);
226
227    struct memobj_anon* sbrk_get_memobj(void);
228    struct vregion* sbrk_get_vregion(void);
229
230    struct memobj_anon* m = sbrk_get_memobj();
231    struct vregion* vr = sbrk_get_vregion();
232    assert(m != NULL);
233    assert(vr != NULL);
234
235
236
237    return EXIT_SUCCESS;
238}
239