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 = ¤t; 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