void chal_pgtbl_copy_range_nocheck(paddr_t pt_to, paddr_t pt_from, unsigned long lower_addr, unsigned long size) { pgd_t *tpgd = ((pgd_t *)chal_pa2va((void*)pt_to)) + pgd_index(lower_addr); pgd_t *fpgd = ((pgd_t *)chal_pa2va((void*)pt_from)) + pgd_index(lower_addr); unsigned int span = hpage_index(size); /* sizeof(pgd entry) is intended */ memcpy(tpgd, fpgd, span*sizeof(pgd_t)); }
int chal_pgtbl_rem_middledir(paddr_t pt, unsigned long vaddr) { pgd_t *pgd = ((pgd_t *)chal_pa2va((void*)pt)) + pgd_index(vaddr); unsigned long *page; page = (unsigned long *)chal_pa2va((void*)(pgd->pgd & PTE_PFN_MASK)); pgd->pgd = 0; chal_free_page(page); return 0; }
void chal_pgtbl_copy_range(paddr_t pt_to, paddr_t pt_from, unsigned long lower_addr, unsigned long size) { pgd_t *tpgd = ((pgd_t *)chal_pa2va((void*)pt_to)) + pgd_index(lower_addr); pgd_t *fpgd = ((pgd_t *)chal_pa2va((void*)pt_from)) + pgd_index(lower_addr); unsigned int span = hpage_index(size); if (!(pgd_val(*fpgd)) & _PAGE_PRESENT) { printk("cos: BUG: nothing to copy from pgd @ %x.\n", (unsigned int)lower_addr); } /* sizeof(pgd entry) is intended */ memcpy(tpgd, fpgd, span*sizeof(pgd_t)); }
/* * Verify that the given address in the page table is present. Return * 0 if present, 1 if not. *This will check the pgd, not for the pte.* */ int chal_pgtbl_entry_absent(paddr_t pt, unsigned long addr) { pgd_t *pgd = ((pgd_t *)chal_pa2va((void*)pt)) + pgd_index(addr); return !((pgd_val(*pgd)) & _PAGE_PRESENT); }
/* Copy pages non-empty in from, and empty in to */ void copy_pgtbl_range_nonzero(paddr_t pt_to, paddr_t pt_from, unsigned long lower_addr, unsigned long size) { pgd_t *tpgd = ((pgd_t *)chal_pa2va((void*)pt_to)) + pgd_index(lower_addr); pgd_t *fpgd = ((pgd_t *)chal_pa2va((void*)pt_from)) + pgd_index(lower_addr); unsigned int span = hpage_index(size); int i; printk("Copying from %p:%d to %p.\n", fpgd, span, tpgd); /* sizeof(pgd entry) is intended */ for (i = 0 ; i < span ; i++) { if (!(pgd_val(tpgd[i]) & _PAGE_PRESENT)) { if (pgd_val(fpgd[i]) & _PAGE_PRESENT) printk("\tcopying vaddr %lx.\n", lower_addr + i * HPAGE_SHIFT); memcpy(&tpgd[i], &fpgd[i], sizeof(pgd_t)); } } }
void pgtbl_print_path(paddr_t pgtbl, unsigned long addr) { pgd_t *pt = ((pgd_t *)chal_pa2va((void*)pgtbl)) + pgd_index(addr); pte_t *pe = pgtbl_lookup_address(pgtbl, addr); printk("cos: addr %x, pgd entry - %x, pte entry - %x\n", (unsigned int)addr, (unsigned int)pgd_val(*pt), (unsigned int)pte_val(*pe)); return; }
/* allocate and link in a page middle directory */ int chal_pgtbl_add_middledir(paddr_t pt, unsigned long vaddr) { pgd_t *pgd = ((pgd_t *)chal_pa2va((void*)pt)) + pgd_index(vaddr); unsigned long *page; page = chal_alloc_page(); /* zeroed */ if (!page) return -1; pgd->pgd = (unsigned long)chal_va2pa(page) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED; return 0; }
static pte_t * pgtbl_lookup_address(paddr_t pgtbl, unsigned long addr) { pgd_t *pgd = ((pgd_t *)chal_pa2va((void*)pgtbl)) + pgd_index(addr); pud_t *pud; pmd_t *pmd; if (pgd_none(*pgd)) { return NULL; } pud = pud_offset(pgd, addr); if (pud_none(*pud)) { return NULL; } pmd = pmd_offset(pud, addr); if (pmd_none(*pmd)) { return NULL; } if (pmd_large(*pmd)) return (pte_t *)pmd; return pte_offset_kernel(pmd, addr); }
void kern_boot_comp(void) { struct pt_regs regs; struct captbl *ct, *ct0; pgtbl_t pt, pt0 = 0; unsigned int i; struct thread *thd = (struct thread *)thdinit; /* llbooter's captbl */ ct = captbl_create(boot_comp_captbl); assert(ct); pt = pgtbl_create(boot_comp_pgd, boot_comp_pgd); assert(pt); pgtbl_init_pte(boot_comp_pte_vm); pgtbl_init_pte(boot_comp_pte_pm); assert(!captbl_activate_boot(ct, BOOT_CAPTBL_SELF_CT)); assert(!sret_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SRET)); assert(!pgtbl_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_PT, pt, 0)); assert(!pgtbl_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_BOOTVM_PTE, (pgtbl_t)boot_comp_pte_vm, 1)); assert(!pgtbl_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_PHYSM_PTE, (pgtbl_t)boot_comp_pte_pm, 1)); assert(!comp_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_COMP, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_PT, 0, 0x37337, NULL)); /* construct the page tables */ assert(!cap_cons(ct, BOOT_CAPTBL_SELF_PT, BOOT_CAPTBL_BOOTVM_PTE, BOOT_MEM_VM_BASE)); assert(!cap_cons(ct, BOOT_CAPTBL_SELF_PT, BOOT_CAPTBL_PHYSM_PTE, BOOT_MEM_PM_BASE)); /* add the component's virtual memory at 4MB (1<<22) using "physical memory" starting at 0xADEAD000 */ for (i = 0 ; i < sys_llbooter_sz ; i++) { u32_t addr = 0xADEAD000 + i*PAGE_SIZE; u32_t flags; assert(!cap_memactivate(ct, BOOT_CAPTBL_SELF_PT, BOOT_MEM_VM_BASE + i*PAGE_SIZE, addr, PGTBL_USER_DEF)); assert(chal_pa2va((void *)addr) == pgtbl_lkup(pt, BOOT_MEM_VM_BASE+i*PAGE_SIZE, &flags)); } /* add the system's physical memory at address 1GB */ for (i = 0 ; i < sys_maxmem ; i++) { u32_t addr = i*PAGE_SIZE; u32_t flags; assert(!cap_memactivate(ct, BOOT_CAPTBL_SELF_PT, BOOT_MEM_PM_BASE + i*PAGE_SIZE, addr, PGTBL_COSFRAME)); assert(chal_pa2va((void *)addr) == pgtbl_lkup(pt, BOOT_MEM_PM_BASE+i*PAGE_SIZE, &flags)); } /* comp0's data, culminated in a static invocation capability to the llbooter */ ct0 = captbl_create(c0_comp_captbl); assert(ct0); assert(!captbl_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_COMP0_CT, ct0, 0)); /* pt0 should be replaced with page tables from the Linux cos_loader */ assert(!pgtbl_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_COMP0_PT, pt0, 0)); assert(!comp_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_COMP0_COMP, BOOT_CAPTBL_COMP0_CT, BOOT_CAPTBL_COMP0_PT, 0, 0x37337, NULL)); /* * Only capability for the comp0 is 0: the synchronous * invocation capability. * * Replace 0xADD44343 with the actual entry-point in the * llbooter! */ assert(!sinv_activate(ct, BOOT_CAPTBL_COMP0_CT, 0, BOOT_CAPTBL_SELF_COMP, 0xADD44343)); /* * Create a thread in comp0. */ assert(!thd_activate(ct, BOOT_CAPTBL_SELF_CT, BOOT_CAPTBL_SELF_INITTHD_BASE, thd, BOOT_CAPTBL_COMP0_COMP, 0)); thd_current_update(thd, NULL); /* * Synchronous invocation! */ u32_t cap_no = 1; u32_t ret_cap = 0; u32_t orig_cr3 = __cr3_contents; regs.ax = (cap_no + 1) << COS_CAPABILITY_OFFSET; /* sinv */ syscall_handler(®s); assert(cos_cpu_local_info()->invstk_top > 0); /* we cache invstk_top on kernel stk */ assert(__cr3_contents != orig_cr3); regs.ax = (ret_cap + 1) << COS_CAPABILITY_OFFSET; /* sret */ syscall_handler(®s); assert(cos_cpu_local_info()->invstk_top == 0); assert(__cr3_contents == orig_cr3); printf("Test passed!\n"); }