//! TODO: currently assumes this translation map is active /*static*/ status_t ARMPagingMethod32Bit::_EarlyQuery(addr_t virtualAddress, phys_addr_t *_physicalAddress) { ARMPagingMethod32Bit* method = ARMPagingMethod32Bit::Method(); int index = VADDR_TO_PDENT(virtualAddress); if ((method->KernelVirtualPageDirectory()[index] & ARM_PDE_TYPE_MASK) == 0) { // no pagetable here return B_ERROR; } page_table_entry* entry = (page_table_entry*) (method->KernelVirtualPageDirectory()[index] & ARM_PDE_ADDRESS_MASK); entry += VADDR_TO_PTENT(virtualAddress); if ((*entry & ARM_PTE_TYPE_MASK) == 0) { // page mapping not valid return B_ERROR; } *_physicalAddress = (*entry & ARM_PTE_ADDRESS_MASK) | VADDR_TO_PGOFF(virtualAddress); return B_OK; }
/*static*/ void ARMPagingMethod32Bit::_EarlyPreparePageTables(page_table_entry* pageTables, addr_t address, size_t size) { ARMPagingMethod32Bit* method = ARMPagingMethod32Bit::Method(); memset(pageTables, 0, 256 * (size / (B_PAGE_SIZE * 256))); // put the array of pgtables directly into the kernel pagedir // these will be wired and kept mapped into virtual space to be easy to get // to { addr_t virtualTable = (addr_t)pageTables; for (size_t i = 0; i < (size / (B_PAGE_SIZE * 256)); i++, virtualTable += 256*sizeof(page_directory_entry)) { phys_addr_t physicalTable = 0; _EarlyQuery(virtualTable, &physicalTable); page_directory_entry* entry = method->KernelVirtualPageDirectory() + VADDR_TO_PDENT(address) + i; PutPageTableInPageDir(entry, physicalTable, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); } } }
status_t ARMVMTranslationMap32Bit::Init(bool kernel) { TRACE("ARMVMTranslationMap32Bit::Init()\n"); ARMVMTranslationMap::Init(kernel); fPagingStructures = new(std::nothrow) ARMPagingStructures32Bit; if (fPagingStructures == NULL) return B_NO_MEMORY; ARMPagingMethod32Bit* method = ARMPagingMethod32Bit::Method(); if (!kernel) { // user // allocate a physical page mapper status_t error = method->PhysicalPageMapper() ->CreateTranslationMapPhysicalPageMapper(&fPageMapper); if (error != B_OK) return error; // allocate the page directory page_directory_entry* virtualPageDir = (page_directory_entry*)memalign( B_PAGE_SIZE, B_PAGE_SIZE); if (virtualPageDir == NULL) return B_NO_MEMORY; // look up the page directory's physical address phys_addr_t physicalPageDir; vm_get_page_mapping(VMAddressSpace::KernelID(), (addr_t)virtualPageDir, &physicalPageDir); fPagingStructures->Init(virtualPageDir, physicalPageDir, method->KernelVirtualPageDirectory()); } else { // kernel // get the physical page mapper fPageMapper = method->KernelPhysicalPageMapper(); // we already know the kernel pgdir mapping fPagingStructures->Init(method->KernelVirtualPageDirectory(), method->KernelPhysicalPageDirectory(), NULL); } return B_OK; }