FDIF functioning as a user level driver.
[barrelfish] / kernel / arch / omap44xx / paging.c
1 /*
2  * Copyright (c) 2009 - 2012 ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 #include <kernel.h>
11 #include <dispatch.h>
12 #include <cp15.h>
13 #include <paging_kernel_arch.h>
14 #include <string.h>
15 #include <exceptions.h>
16 #include <arm_hal.h>
17 #include <cap_predicates.h>
18 #include <dispatch.h>
19
20 /**
21  * Kernel L1 page table
22  */
23 //XXX: We reserve double the space needed to be able to align the pagetable
24 //     to 16K after relocation
25 static union arm_l1_entry kernel_l1_table[2*ARM_L1_MAX_ENTRIES]
26 __attribute__((aligned(ARM_L1_ALIGN)));
27 static union arm_l1_entry *aligned_kernel_l1_table;
28
29 #if 0
30 /**
31  * Kernel L2 page table for first MB
32  */
33 //XXX: We reserve double the space needed to be able to align the pagetable
34 //     to 1K after relocation
35 static union arm_l2_entry low_l2_table[2*ARM_L2_MAX_ENTRIES]
36 __attribute__((aligned(ARM_L2_ALIGN)));
37 static union arm_l2_entry *aligned_low_l2_table;
38 #endif // 0
39
40 // ------------------------------------------------------------------------
41 // Utility declarations
42
43 inline static uintptr_t paging_round_down(uintptr_t address, uintptr_t size)
44 {
45     return address & ~(size - 1);
46 }
47
48 inline static uintptr_t paging_round_up(uintptr_t address, uintptr_t size)
49 {
50     return (address + size - 1) & ~(size - 1);
51 }
52
53 inline static int aligned(uintptr_t address, uintptr_t bytes)
54 {
55     return (address & (bytes - 1)) == 0;
56 }
57
58 static inline struct cte *cte_for_cap(struct capability *cap)
59 {
60     return (struct cte *) (cap - offsetof(struct cte, cap));
61 }
62
63
64 static void
65 paging_write_l1_entry(uintptr_t ttbase, lvaddr_t va, union arm_l1_entry l1)
66 {
67     union arm_l1_entry *l1_table;
68     if (ttbase == 0) {
69         if(va < MEMORY_OFFSET)
70             ttbase = cp15_read_ttbr0() + MEMORY_OFFSET;
71         else
72             ttbase = cp15_read_ttbr1() + MEMORY_OFFSET;
73     }
74     l1_table = (union arm_l1_entry *) ttbase;
75     l1_table[ARM_L1_OFFSET(va)] = l1;
76 }
77 // ------------------------------------------------------------------------
78 // Exported functions
79
80
81 void paging_map_kernel_section(uintptr_t ttbase, lvaddr_t va, lpaddr_t pa)
82 {
83
84     union arm_l1_entry l1;
85
86     l1.raw = 0;
87     l1.section.type = L1_TYPE_SECTION_ENTRY;
88     l1.section.bufferable   = 1;
89     l1.section.cacheable    = 1;
90     l1.section.ap10         = 1;    // RW/NA
91     l1.section.ap2          = 0;
92     l1.section.base_address = pa >> 20u;
93
94     paging_write_l1_entry(ttbase, va, l1);
95 }
96
97 void paging_map_memory(uintptr_t ttbase, lpaddr_t paddr, size_t bytes)
98 {
99     lpaddr_t pend  = paging_round_down(paddr + bytes, BYTES_PER_SECTION);
100     while (paddr < pend) {
101         paging_map_kernel_section(ttbase, paddr, paddr);
102         paddr += BYTES_PER_SECTION;
103     }
104 }
105
106 void
107 paging_map_device_section(uintptr_t ttbase, lvaddr_t va, lpaddr_t pa);
108
109 void
110 paging_map_device_section(uintptr_t ttbase, lvaddr_t va, lpaddr_t pa)
111 {
112     union arm_l1_entry l1;
113
114     l1.raw = 0;
115     l1.section.type = L1_TYPE_SECTION_ENTRY;
116     l1.section.bufferable   = 0;
117     l1.section.cacheable    = 0;
118     l1.section.ap10         = 3; // prev value: 3 // RW/NA RW/RW
119     l1.section.ap2        = 0;
120     l1.section.base_address = pa >> 20u;
121
122     paging_write_l1_entry(ttbase, va, l1);
123 }
124
125 lvaddr_t paging_map_device(lpaddr_t device_base, size_t device_bytes)
126 {
127     // HACK to put device in high memory.
128     // Should likely track these allocations.
129     static lvaddr_t dev_alloc = DEVICE_OFFSET;
130     assert(device_bytes <= BYTES_PER_SECTION);
131     dev_alloc -= BYTES_PER_SECTION;
132
133     printf("paging_map_device_section: 0x%"PRIxLVADDR", 0x%"PRIxLVADDR", "
134             "0x%"PRIxLPADDR".\n",
135             (uintptr_t)aligned_kernel_l1_table, dev_alloc, device_base);
136
137     paging_map_device_section((uintptr_t)aligned_kernel_l1_table, dev_alloc,
138             device_base);
139
140     cp15_write_ttbr1(mem_to_local_phys((uintptr_t)aligned_kernel_l1_table));
141     cp15_invalidate_i_and_d_caches_fast();
142     cp15_invalidate_tlb();
143
144     return dev_alloc;
145 }
146
147 /**
148  * \brief Reset kernel paging.
149  *
150  * This function resets the page maps for kernel and memory-space. It clears out
151  * all other mappings. Use this only at system bootup!
152  */
153 void paging_arm_reset(lpaddr_t paddr, size_t bytes)
154 {
155     // make sure kernel pagetable is aligned to 16K after relocation
156     aligned_kernel_l1_table = (union arm_l1_entry *)ROUND_UP(
157             (uintptr_t)kernel_l1_table, ARM_L1_ALIGN);
158
159     // Re-map physical memory
160     //
161     paging_map_memory((uintptr_t)aligned_kernel_l1_table , paddr, bytes);
162
163     //map high-mem relocated exception vector to kernel section
164     paging_map_kernel_section((uintptr_t)aligned_kernel_l1_table, ETABLE_ADDR,
165                               PHYS_MEMORY_START);
166
167     cp15_write_ttbr1(mem_to_local_phys((uintptr_t)aligned_kernel_l1_table));
168     cp15_invalidate_tlb();
169 }
170
171 #if 0
172 /**
173  * \brief Reset kernel paging.
174  *
175  * This function resets the page maps for kernel and memory-space. It clears out
176  * all other mappings. Use this only at system bootup!
177  */
178 void paging_arm_reset(lpaddr_t paddr, size_t bytes)
179 {
180     // make sure kernel pagetable is aligned to 16K after relocation
181     aligned_kernel_l1_table = (union arm_l1_entry *)ROUND_UP(
182             (uintptr_t)aligned_kernel_l1_table, ARM_L1_ALIGN);
183
184     // make sure low l2 pagetable is aligned to 1K after relocation
185     aligned_low_l2_table = (union arm_l2_entry *)ROUND_UP(
186             (uintptr_t)low_l2_table, ARM_L2_ALIGN);
187
188     // Re-map physical memory
189     paging_map_memory((uintptr_t)aligned_kernel_l1_table, paddr, bytes);
190
191     // map first MB at granularity of 4K pages
192     uint32_t l2_flags = ARM_L2_SMALL_USR_NONE | ARM_L2_SMALL_CACHEABLE |
193         ARM_L2_SMALL_BUFFERABLE;
194     paging_map_user_pages_l1((uintptr_t)aligned_kernel_l1_table,
195             MEMORY_OFFSET, mem_to_local_phys((uintptr_t)aligned_low_l2_table));
196     for(lpaddr_t pa=0; pa < ARM_L1_SECTION_BYTES; pa += BYTES_PER_PAGE)
197     {
198         lvaddr_t va = pa + MEMORY_OFFSET;
199         paging_set_l2_entry((uintptr_t *)&aligned_low_l2_table[ARM_L2_OFFSET(va)], pa, l2_flags);
200     }
201
202     // map high-mem relocated exception vector to corresponding page in low MB
203     // core 0: 0xffff0000 -> 0x80000
204     // core 1: 0xffff0000 -> 0x81000
205     // ...
206     paging_map_user_pages_l1((uintptr_t)aligned_kernel_l1_table, ETABLE_ADDR,
207             mem_to_local_phys((uintptr_t)aligned_low_l2_table));
208     int core_id = hal_get_cpu_id();
209     lpaddr_t addr = ETABLE_PHYS_BASE + core_id * BASE_PAGE_SIZE;
210     paging_set_l2_entry((uintptr_t *)&aligned_low_l2_table[ARM_L2_OFFSET(ETABLE_ADDR)], addr, l2_flags);
211
212
213     //map section containing sysflag registers 1:1
214     paging_map_device_section((uintptr_t)aligned_kernel_l1_table, sysflagset_base, sysflagset_base);
215
216     cp15_write_ttbr1(mem_to_local_phys((uintptr_t)aligned_kernel_l1_table));
217
218     cp15_invalidate_tlb();
219 }
220 #endif // 0
221
222 /*
223  * Describe me
224  */
225 void paging_make_good(lvaddr_t new_table_base, size_t new_table_bytes)
226 {
227     assert(new_table_base >= MEMORY_OFFSET);
228     assert(new_table_bytes == ARM_L1_ALIGN);
229     assert(aligned(new_table_base, ARM_L1_ALIGN));
230
231     lvaddr_t ttbr = local_phys_to_mem(cp15_read_ttbr0());
232     size_t st = (MEMORY_OFFSET / ARM_L1_SECTION_BYTES) * ARM_L1_BYTES_PER_ENTRY;
233
234     // Copy kernel pages (everything from MEMORY_OFFSET upwards)
235     memcpy((void*)new_table_base + st, (void*)ttbr + st,
236            ARM_L1_MAX_ENTRIES * ARM_L1_BYTES_PER_ENTRY - st);
237 }
238
239 void paging_map_user_pages_l1(lvaddr_t table_base, lvaddr_t va, lpaddr_t pa)
240 {
241     assert(aligned(table_base, ARM_L1_ALIGN));
242     assert(aligned(pa, BYTES_PER_SMALL_PAGE));
243
244     union arm_l1_entry e;
245
246     e.raw                 = 0;
247     e.page_table.type         = L1_TYPE_PAGE_TABLE_ENTRY;
248     e.page_table.domain       = 0;
249     e.page_table.base_address = (pa >> 10);
250
251     paging_write_l1_entry(table_base, va, e);
252 }
253
254 void paging_set_l2_entry(uintptr_t* l2e, lpaddr_t addr, uintptr_t flags)
255 {
256     assert(0 == (flags & 0xfffff000));
257     assert(0 == (flags & 0x3));
258     assert(0 == (addr & 0xfff));
259
260     union arm_l2_entry e;
261     e.raw = flags;
262
263     e.small_page.type = L2_TYPE_SMALL_PAGE;
264     e.small_page.base_address = (addr >> 12);
265
266     *l2e = e.raw;
267 }
268
269 void paging_context_switch(lpaddr_t ttbr)
270 {
271 //    printf("paging context switch to %"PRIxLPADDR"\n", ttbr);
272     lpaddr_t old_ttbr = cp15_read_ttbr0();
273     if (ttbr != old_ttbr) {
274         cp15_write_ttbr0(ttbr);
275         cp15_invalidate_tlb();
276         cp15_invalidate_i_and_d_caches();
277     }
278 }
279
280 static void
281 paging_set_flags(union arm_l2_entry *entry, uintptr_t kpi_paging_flags)
282 {
283         entry->small_page.bufferable = 1;
284         entry->small_page.cacheable =
285             (kpi_paging_flags & KPI_PAGING_FLAGS_NOCACHE) ? 0 : 1;
286         entry->small_page.ap10  =
287             (kpi_paging_flags & KPI_PAGING_FLAGS_READ)  ? 2 : 0;
288         entry->small_page.ap10 |=
289             (kpi_paging_flags & KPI_PAGING_FLAGS_WRITE) ? 3 : 0;
290         entry->small_page.ap2 = 0;
291 }
292
293 static errval_t
294 caps_map_l1(struct capability* dest,
295             cslot_t            slot,
296             struct capability* src,
297             uintptr_t          kpi_paging_flags,
298             uintptr_t          offset,
299             uintptr_t          pte_count)
300 {
301     //
302     // Note:
303     //
304     // We have chicken-and-egg problem in initializing resources so
305     // instead of treating an L2 table it's actual 1K size, we treat
306     // it as being 4K. As a result when we map an "L2" table we actually
307     // map a page of memory as if it is 4 consecutive L2 tables.
308     //
309     // See lib/barrelfish/arch/arm/pmap_arch.c for more discussion.
310     //
311     const int ARM_L1_SCALE = 4;
312
313     if (slot >= 1024) {
314         printf("slot = %"PRIuCSLOT"\n",slot);
315         panic("oops: slot id >= 1024");
316         return SYS_ERR_VNODE_SLOT_INVALID;
317     }
318
319     if (pte_count != 1) {
320         printf("pte_count = %zu\n",(size_t)pte_count);
321         panic("oops: pte_count");
322         return SYS_ERR_VM_MAP_SIZE;
323     }
324
325     if (src->type != ObjType_VNode_ARM_l2) {
326         panic("oops: wrong src type");
327         return SYS_ERR_WRONG_MAPPING;
328     }
329
330     if (slot >= ARM_L1_OFFSET(MEMORY_OFFSET) / ARM_L1_SCALE) {
331         printf("slot = %"PRIuCSLOT"\n",slot);
332         panic("oops: slot id");
333         return SYS_ERR_VNODE_SLOT_RESERVED;
334     }
335
336     // Destination
337     lpaddr_t dest_lpaddr = gen_phys_to_local_phys(get_address(dest));
338     lvaddr_t dest_lvaddr = local_phys_to_mem(dest_lpaddr);
339
340     union arm_l1_entry* entry = (union arm_l1_entry*)dest_lvaddr + (slot * ARM_L1_SCALE);
341
342     // Source
343     genpaddr_t src_gpaddr = get_address(src);
344     lpaddr_t   src_lpaddr = gen_phys_to_local_phys(src_gpaddr);
345
346     assert(offset == 0);
347     assert(aligned(src_lpaddr, 1u << 10));
348     assert((src_lpaddr < dest_lpaddr) || (src_lpaddr >= dest_lpaddr + 16384));
349
350     struct cte *src_cte = cte_for_cap(src);
351     src_cte->mapping_info.pte_count = pte_count;
352     src_cte->mapping_info.pte = dest_lpaddr + (slot * ARM_L1_SCALE);
353     src_cte->mapping_info.offset = 0;
354
355     for (int i = 0; i < 4; i++, entry++)
356     {
357         entry->raw = 0;
358         entry->page_table.type   = L1_TYPE_PAGE_TABLE_ENTRY;
359         entry->page_table.domain = 0;
360         entry->page_table.base_address =
361             (src_lpaddr + i * BASE_PAGE_SIZE / ARM_L1_SCALE) >> 10;
362         debug(SUBSYS_PAGING, "L1 mapping %"PRIuCSLOT". @%p = %08"PRIx32"\n",
363               slot * ARM_L1_SCALE + i, entry, entry->raw);
364     }
365
366     cp15_invalidate_tlb();
367
368     return SYS_ERR_OK;
369 }
370
371 static errval_t
372 caps_map_l2(struct capability* dest,
373             cslot_t            slot,
374             struct capability* src,
375             uintptr_t          kpi_paging_flags,
376             uintptr_t          offset,
377             uintptr_t          pte_count)
378 {
379     assert(0 == (kpi_paging_flags & ~KPI_PAGING_FLAGS_MASK));
380
381     // ARM L2 has 256 entries, but we treat a 4K page as a consecutive
382     // region of L2 with a single index. 4K == 4 * 1K
383     if (slot >= (256 * 4)) {
384         panic("oops: slot >= (256 * 4)");
385         return SYS_ERR_VNODE_SLOT_INVALID;
386     }
387
388     if (src->type != ObjType_Frame && src->type != ObjType_DevFrame) {
389         panic("oops: src->type != ObjType_Frame && src->type != ObjType_DevFrame");
390         return SYS_ERR_WRONG_MAPPING;
391     }
392
393     // check offset within frame
394     if ((offset + BYTES_PER_PAGE > get_size(src)) ||
395         ((offset % BYTES_PER_PAGE) != 0)) {
396         panic("oops: frame offset invalid");
397         return SYS_ERR_FRAME_OFFSET_INVALID;
398     }
399
400     // check mapping does not overlap leaf page table
401     if (slot + pte_count > (256 * 4)) {
402         return SYS_ERR_VM_MAP_SIZE;
403     }
404
405     // Destination
406     lpaddr_t dest_lpaddr = gen_phys_to_local_phys(get_address(dest));
407     lvaddr_t dest_lvaddr = local_phys_to_mem(dest_lpaddr);
408
409     union arm_l2_entry* entry = (union arm_l2_entry*)dest_lvaddr + slot;
410     if (entry->small_page.type != L2_TYPE_INVALID_PAGE) {
411         panic("Remapping valid page.");
412     }
413
414     lpaddr_t src_lpaddr = gen_phys_to_local_phys(get_address(src) + offset);
415     if ((src_lpaddr & (BASE_PAGE_SIZE - 1))) {
416         panic("Invalid target");
417     }
418
419     struct cte *src_cte = cte_for_cap(src);
420     src_cte->mapping_info.pte_count = pte_count;
421     src_cte->mapping_info.pte = dest_lpaddr;
422     src_cte->mapping_info.offset = offset;
423
424     for (int i = 0; i < pte_count; i++) {
425         entry->raw = 0;
426
427         entry->small_page.type = L2_TYPE_SMALL_PAGE;
428         paging_set_flags(entry, kpi_paging_flags);
429         entry->small_page.base_address = (src_lpaddr + i * BYTES_PER_PAGE) >> 12;
430
431         entry++;
432
433         debug(SUBSYS_PAGING, "L2 mapping %08"PRIxLVADDR"[%"PRIuCSLOT"] @%p = %08"PRIx32"\n",
434                dest_lvaddr, slot, entry, entry->raw);
435     }
436
437     // Flush TLB if remapping.
438     cp15_invalidate_tlb();
439
440     return SYS_ERR_OK;
441 }
442
443 /// Create page mappings
444 errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot,
445                             struct cte *src_cte, uintptr_t flags,
446                             uintptr_t offset, uintptr_t pte_count)
447 {
448     struct capability *src_cap  = &src_cte->cap;
449     struct capability *dest_cap = &dest_vnode_cte->cap;
450
451     if (ObjType_VNode_ARM_l1 == dest_cap->type) {
452         //printf("caps_map_l1: %zu\n", (size_t)pte_count);
453         return caps_map_l1(dest_cap, dest_slot, src_cap,
454                            flags,
455                            offset,
456                            pte_count
457                           );
458     }
459     else if (ObjType_VNode_ARM_l2 == dest_cap->type) {
460         //printf("caps_map_l2: %zu\n", (size_t)pte_count);
461         return caps_map_l2(dest_cap, dest_slot, src_cap,
462                            flags,
463                            offset,
464                            pte_count
465                           );
466     }
467     else {
468         panic("ObjType not VNode");
469     }
470 }
471
472 size_t do_unmap(lvaddr_t pt, cslot_t slot, size_t num_pages)
473 {
474     size_t unmapped_pages = 0;
475     union arm_l2_entry *ptentry = (union arm_l2_entry *)pt + slot;
476     for (int i = 0; i < num_pages; i++) {
477         ptentry++->raw = 0;
478         unmapped_pages++;
479     }
480     return unmapped_pages;
481 }
482
483 static inline void read_pt_entry(struct capability *pgtable, size_t slot, genpaddr_t *paddr)
484 {
485     assert(type_is_vnode(pgtable->type));
486     assert(paddr);
487
488     genpaddr_t gp = get_address(pgtable);
489     lpaddr_t lp = gen_phys_to_local_phys(gp);
490     lvaddr_t lv = local_phys_to_mem(lp);
491
492     switch (pgtable->type) {
493         case ObjType_VNode_ARM_l1:
494         {
495             union arm_l1_entry *e = (union arm_l1_entry*)lv;
496             *paddr = (genpaddr_t)(e->page_table.base_address) << 10;
497             return;
498         }
499         case ObjType_VNode_ARM_l2:
500         {
501             union arm_l2_entry *e = (union arm_l2_entry*)lv;
502             *paddr = (genpaddr_t)(e->small_page.base_address) << 12;
503             return;
504         }
505         default:
506             assert(!"Should not get here");
507     }
508 }
509
510 errval_t page_mappings_unmap(struct capability *pgtable, struct cte *mapping, size_t slot, size_t num_pages)
511 {
512     assert(type_is_vnode(pgtable->type));
513     //printf("page_mappings_unmap(%zd pages, slot = %zd)\n", num_pages, slot);
514
515     // get page table entry data
516     genpaddr_t paddr;
517     //lpaddr_t pte;
518     read_pt_entry(pgtable, slot, &paddr);
519     lvaddr_t pt = local_phys_to_mem(gen_phys_to_local_phys(get_address(pgtable)));
520
521     // get virtual address of first page
522     // TODO: error checking
523     genvaddr_t vaddr;
524     struct cte *leaf_pt = cte_for_cap(pgtable);
525     compile_vaddr(leaf_pt, slot, &vaddr);
526     //genvaddr_t vend = vaddr + num_pages * BASE_PAGE_SIZE;
527     // printf("vaddr = 0x%"PRIxGENVADDR"\n", vaddr);
528     // printf("num_pages = %zu\n", num_pages);
529
530     // get cap for mapping
531     /*
532     struct cte *mem;
533     errval_t err = lookup_cap_for_mapping(paddr, pte, &mem);
534     if (err_is_fail(err)) {
535         printf("page_mappings_unmap: %ld\n", err);
536         return err;
537     }
538     */
539     //printf("state before unmap: mapped_pages = %zd\n", mem->mapping_info.mapped_pages);
540     //printf("state before unmap: num_pages    = %zd\n", num_pages);
541
542     if (num_pages != mapping->mapping_info.pte_count) {
543         printf("num_pages = %zu, mapping = %zu\n", num_pages, mapping->mapping_info.pte_count);
544         // want to unmap a different amount of pages than was mapped
545         return SYS_ERR_VM_MAP_SIZE;
546     }
547
548     do_unmap(pt, slot, num_pages);
549
550     // flush TLB for unmapped pages
551     // TODO: selective TLB flush
552     cp15_invalidate_tlb();
553
554     // update mapping info
555     memset(&mapping->mapping_info, 0, sizeof(struct mapping_info));
556
557     return SYS_ERR_OK;
558 }
559
560 errval_t paging_modify_flags(struct capability *frame, uintptr_t offset,
561                              uintptr_t pages, uintptr_t kpi_paging_flags)
562 {
563     // check flags
564     assert(0 == (kpi_paging_flags & ~KPI_PAGING_FLAGS_MASK));
565
566     struct cte *mapping = cte_for_cap(frame);
567     struct mapping_info *info = &mapping->mapping_info;
568
569     /* Calculate location of page table entries we need to modify */
570     lvaddr_t base = info->pte + offset;
571
572     for (int i = 0; i < pages; i++) {
573         union arm_l2_entry *entry =
574             (union arm_l2_entry *)base + i;
575         paging_set_flags(entry, kpi_paging_flags);
576     }
577
578     return SYS_ERR_OK;
579 }
580
581 void paging_dump_tables(struct dcb *dispatcher)
582 {
583     printf("dump_hw_page_tables\n");
584     lvaddr_t l1 = local_phys_to_mem(dispatcher->vspace);
585
586     for (int l1_index = 0; l1_index < ARM_L1_MAX_ENTRIES; l1_index++) {
587         // get level2 table
588         union arm_l1_entry *l1_e = (union arm_l1_entry *)l1 + l1_index;
589         if (!l1_e->raw) { continue; }
590         genpaddr_t ptable_gp = (genpaddr_t)(l1_e->page_table.base_address) << 10;
591         lvaddr_t ptable_lv = local_phys_to_mem(gen_phys_to_local_phys(ptable_gp));
592
593         for (int entry = 0; entry < ARM_L2_MAX_ENTRIES; entry++) {
594             union arm_l2_entry *e =
595                 (union arm_l2_entry *)ptable_lv + entry;
596             genpaddr_t paddr = (genpaddr_t)(e->small_page.base_address) << BASE_PAGE_BITS;
597             if (!paddr) {
598                 continue;
599             }
600             printf("%d.%d: 0x%"PRIxGENPADDR"\n", l1_index, entry, paddr);
601         }
602     }
603 }