t_status architecture_environment_kernel(i_as id) { struct { at_pdei start; at_pdei end; at_pdei index; } pde; struct { at_ptei start; at_ptei end; at_ptei index; } pte; i_region useless; at_cr3 pdbr; o_as* as; at_pd pd; at_pt pt; o_region* r; t_uint32 i; /* * 1) */ if (as_get(id, &as) != STATUS_OK) MACHINE_ESCAPE("unable to retrieve the address space object"); /* * 2) */ as->machine.pd = _init->machine.pd; /* * 3) */ if (architecture_paging_pdbr(as->machine.pd, ARCHITECTURE_REGISTER_CR3_PCE | ARCHITECTURE_REGISTER_CR3_PWB, &pdbr) != STATUS_OK) MACHINE_ESCAPE("unable to build the CR3 register's content"); /* * 4) */ pd = (at_pd)as->machine.pd; /* * 5) */ if (architecture_paging_import(pd, pdbr) != STATUS_OK) MACHINE_ESCAPE("unable to import the kernel page directory"); /* * 6) */ if (architecture_pd_insert(pd, ARCHITECTURE_PD_MIRROR, as->machine.pd, ARCHITECTURE_PDE_PRESENT | ARCHITECTURE_PDE_RW | ARCHITECTURE_PDE_SUPERVISOR | ARCHITECTURE_PDE_PWB | ARCHITECTURE_PDE_PCE) != STATUS_OK) MACHINE_ESCAPE("unable to insert the mirroring directory entry"); /* * 7) */ if ((r = malloc(sizeof (o_region))) == NULL) MACHINE_ESCAPE("unable to allocate memory for the region object"); r->address = ARCHITECTURE_PAGING_ADDRESS(ARCHITECTURE_PD_MIRROR, 0); r->segment = ID_UNUSED; r->offset = 0x0; r->size = ARCHITECTURE_PT_SIZE * ___kaneton$pagesz; r->options = REGION_OPTION_NONE; if (region_inject(as->id, r, &useless) != STATUS_OK) MACHINE_ESCAPE("unable to inject the mirroring region"); /* * 8) */ pde.start = 0; pte.start = 0; for (i = 0; i < (_init->nregions + 1); i++) { /* * a) */ if (i != _init->nregions) { pde.end = ARCHITECTURE_PD_INDEX(_init->regions[i].address); pte.end = ARCHITECTURE_PT_INDEX(_init->regions[i].address); } else { pde.end = ARCHITECTURE_PD_SIZE - 1; pte.end = ARCHITECTURE_PT_SIZE; } /* * b) */ for (pde.index = pde.start; pde.index <= pde.end; pde.index++) { /* * i) */ if ((pde.index != ARCHITECTURE_PD_MIRROR) && (pd[pde.index] & ARCHITECTURE_PDE_PRESENT)) { /* * #1) */ pt = (at_pt)ARCHITECTURE_PDE_ADDRESS(pd[pde.index]); /* * #2) */ for (pte.index = (pde.index == pde.start ? pte.start : 0); pte.index < (pde.index == pde.end ? pte.end : ARCHITECTURE_PT_SIZE); pte.index++) { /* * #a) */ if (pt[pte.index] & ARCHITECTURE_PTE_PRESENT) { if (architecture_pt_delete(pt, pte.index) != STATUS_OK) MACHINE_ESCAPE("unable to delete the page " "table entry"); } } } } /* * c) */ if (i != _init->nregions) { pde.start = ARCHITECTURE_PD_INDEX(_init->regions[i].address + _init->regions[i].size); pte.start = ARCHITECTURE_PT_INDEX(_init->regions[i].address + _init->regions[i].size); } } /* * 9) */ if (architecture_tlb_flush() != STATUS_OK) MACHINE_ESCAPE("unable to flush the TLB"); /* * 10) */ _architecture.kernel.pdbr = pdbr; MACHINE_LEAVE(); }
// FIXME: lot of code has been removed here t_error map_page(t_paddr paddr, t_vaddr *vaddr) { o_as* kas; t_ia32_pde pde; t_ia32_pde pte; t_ia32_directory dir; t_ia32_table table; t_ia32_page page; o_region* oreg; i_segment segid; o_segment* segment; int clear = 0; REGION_ENTER(region); if (as_get(kasid, &kas) != ERROR_NONE) REGION_LEAVE(region, ERROR_UNKNOWN); if (region_space(kas, PAGESZ, vaddr) != ERROR_NONE) REGION_LEAVE(region, ERROR_UNKNOWN); if ((oreg = malloc(sizeof(o_region))) == NULL) REGION_LEAVE(region, ERROR_UNKNOWN); oreg->address = *vaddr; oreg->regid = (i_region)oreg->address; oreg->opts = REGION_OPT_PRIVILEGED; oreg->size = PAGESZ; oreg->offset = 0; oreg->segid = (i_segment) paddr; if (region_inject(kasid, oreg) != ERROR_NONE) REGION_LEAVE(region, ERROR_UNKNOWN); // Page Dir dir = kas->machdep.pd; pde = PDE_ENTRY(*vaddr); if (pd_get_table(&dir, pde, &table) == ERROR_UNKNOWN) { segment_reserve(kasid, PAGESZ, PERM_READ | PERM_WRITE, &segid); if (segment_get(segid, &segment) != ERROR_NONE) REGION_LEAVE(region, ERROR_UNKNOWN); table.rw = PT_WRITABLE; pt_build(segment->address, &table, 0); pd_add_table(&dir, pde, table); clear = 1; } table.entries = ENTRY_ADDR(PD_MIRROR, pde); //fixme if (clear) memset((void *)ENTRY_ADDR(PD_MIRROR, pde), '\0', PAGESZ); // Page Table pte = PTE_ENTRY(*vaddr); page.present = 1; page.addr = paddr; page.rw = PG_WRITABLE; pt_add_page(&table, pte, page); tlb_invalidate(*vaddr); REGION_LEAVE(region, ERROR_NONE); }