1*d6618274SFrançois Revol /* 2*d6618274SFrançois Revol * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3*d6618274SFrançois Revol * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 4*d6618274SFrançois Revol * Distributed under the terms of the MIT License. 5*d6618274SFrançois Revol * 6*d6618274SFrançois Revol * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 7*d6618274SFrançois Revol * Distributed under the terms of the NewOS License. 8*d6618274SFrançois Revol */ 9*d6618274SFrançois Revol 10*d6618274SFrançois Revol 11*d6618274SFrançois Revol #include "paging/460/PPCPagingMethod460.h" 12*d6618274SFrançois Revol 13*d6618274SFrançois Revol #include <stdlib.h> 14*d6618274SFrançois Revol #include <string.h> 15*d6618274SFrançois Revol 16*d6618274SFrançois Revol #include <AutoDeleter.h> 17*d6618274SFrançois Revol 18*d6618274SFrançois Revol #include <arch/cpu.h> 19*d6618274SFrançois Revol #include <arch_mmu.h> 20*d6618274SFrançois Revol #include <arch_system_info.h> 21*d6618274SFrançois Revol #include <boot/kernel_args.h> 22*d6618274SFrançois Revol #include <int.h> 23*d6618274SFrançois Revol #include <thread.h> 24*d6618274SFrançois Revol #include <vm/vm.h> 25*d6618274SFrançois Revol #include <vm/VMAddressSpace.h> 26*d6618274SFrançois Revol 27*d6618274SFrançois Revol #include "paging/460/PPCPagingStructures460.h" 28*d6618274SFrançois Revol #include "paging/460/PPCVMTranslationMap460.h" 29*d6618274SFrançois Revol #include "generic_vm_physical_page_mapper.h" 30*d6618274SFrançois Revol #include "generic_vm_physical_page_ops.h" 31*d6618274SFrançois Revol #include "GenericVMPhysicalPageMapper.h" 32*d6618274SFrançois Revol 33*d6618274SFrançois Revol 34*d6618274SFrançois Revol //#define TRACE_PPC_PAGING_METHOD_460 35*d6618274SFrançois Revol #ifdef TRACE_PPC_PAGING_METHOD_460 36*d6618274SFrançois Revol # define TRACE(x...) dprintf(x) 37*d6618274SFrançois Revol #else 38*d6618274SFrançois Revol # define TRACE(x...) ; 39*d6618274SFrançois Revol #endif 40*d6618274SFrançois Revol 41*d6618274SFrançois Revol // 64 MB of iospace 42*d6618274SFrançois Revol #define IOSPACE_SIZE (64*1024*1024) 43*d6618274SFrançois Revol // We only have small (4 KB) pages. The only reason for choosing greater chunk 44*d6618274SFrançois Revol // size is to keep the waste of memory limited, since the generic page mapper 45*d6618274SFrançois Revol // allocates structures per physical/virtual chunk. 46*d6618274SFrançois Revol // TODO: Implement a page mapper more suitable for small pages! 47*d6618274SFrançois Revol #define IOSPACE_CHUNK_SIZE (16 * B_PAGE_SIZE) 48*d6618274SFrançois Revol 49*d6618274SFrançois Revol static addr_t sIOSpaceBase; 50*d6618274SFrançois Revol 51*d6618274SFrançois Revol 52*d6618274SFrançois Revol static status_t 53*d6618274SFrançois Revol map_iospace_chunk(addr_t va, phys_addr_t pa, uint32 flags) 54*d6618274SFrançois Revol { 55*d6618274SFrançois Revol pa &= ~(B_PAGE_SIZE - 1); // make sure it's page aligned 56*d6618274SFrançois Revol va &= ~(B_PAGE_SIZE - 1); // make sure it's page aligned 57*d6618274SFrançois Revol if (va < sIOSpaceBase || va >= (sIOSpaceBase + IOSPACE_SIZE)) 58*d6618274SFrançois Revol panic("map_iospace_chunk: passed invalid va 0x%lx\n", va); 59*d6618274SFrançois Revol 60*d6618274SFrançois Revol // map the pages 61*d6618274SFrançois Revol return ppc_map_address_range(va, pa, IOSPACE_CHUNK_SIZE); 62*d6618274SFrançois Revol } 63*d6618274SFrançois Revol 64*d6618274SFrançois Revol 65*d6618274SFrançois Revol // #pragma mark - PPCPagingMethod460 66*d6618274SFrançois Revol 67*d6618274SFrançois Revol 68*d6618274SFrançois Revol PPCPagingMethod460::PPCPagingMethod460() 69*d6618274SFrançois Revol /* 70*d6618274SFrançois Revol : 71*d6618274SFrançois Revol fPageHole(NULL), 72*d6618274SFrançois Revol fPageHolePageDir(NULL), 73*d6618274SFrançois Revol fKernelPhysicalPageDirectory(0), 74*d6618274SFrançois Revol fKernelVirtualPageDirectory(NULL), 75*d6618274SFrançois Revol fPhysicalPageMapper(NULL), 76*d6618274SFrançois Revol fKernelPhysicalPageMapper(NULL) 77*d6618274SFrançois Revol */ 78*d6618274SFrançois Revol { 79*d6618274SFrançois Revol } 80*d6618274SFrançois Revol 81*d6618274SFrançois Revol 82*d6618274SFrançois Revol PPCPagingMethod460::~PPCPagingMethod460() 83*d6618274SFrançois Revol { 84*d6618274SFrançois Revol } 85*d6618274SFrançois Revol 86*d6618274SFrançois Revol 87*d6618274SFrançois Revol status_t 88*d6618274SFrançois Revol PPCPagingMethod460::Init(kernel_args* args, 89*d6618274SFrançois Revol VMPhysicalPageMapper** _physicalPageMapper) 90*d6618274SFrançois Revol { 91*d6618274SFrançois Revol TRACE("PPCPagingMethod460::Init(): entry\n"); 92*d6618274SFrançois Revol 93*d6618274SFrançois Revol fPageTable = (page_table_entry_group *)args->arch_args.page_table.start; 94*d6618274SFrançois Revol fPageTableSize = args->arch_args.page_table.size; 95*d6618274SFrançois Revol fPageTableHashMask = fPageTableSize / sizeof(page_table_entry_group) - 1; 96*d6618274SFrançois Revol 97*d6618274SFrançois Revol // init physical page mapper 98*d6618274SFrançois Revol status_t error = generic_vm_physical_page_mapper_init(args, 99*d6618274SFrançois Revol map_iospace_chunk, &sIOSpaceBase, IOSPACE_SIZE, IOSPACE_CHUNK_SIZE); 100*d6618274SFrançois Revol if (error != B_OK) 101*d6618274SFrançois Revol return error; 102*d6618274SFrançois Revol 103*d6618274SFrançois Revol new(&fPhysicalPageMapper) GenericVMPhysicalPageMapper; 104*d6618274SFrançois Revol 105*d6618274SFrançois Revol *_physicalPageMapper = &fPhysicalPageMapper; 106*d6618274SFrançois Revol return B_OK; 107*d6618274SFrançois Revol 108*d6618274SFrançois Revol #if 0//X86 109*d6618274SFrançois Revol fKernelPhysicalPageDirectory = args->arch_args.phys_pgdir; 110*d6618274SFrançois Revol fKernelVirtualPageDirectory = (page_directory_entry*)(addr_t) 111*d6618274SFrançois Revol args->arch_args.vir_pgdir; 112*d6618274SFrançois Revol 113*d6618274SFrançois Revol #ifdef TRACE_PPC_PAGING_METHOD_460 114*d6618274SFrançois Revol TRACE("page hole: %p, page dir: %p\n", fPageHole, fPageHolePageDir); 115*d6618274SFrançois Revol TRACE("page dir: %p (physical: %#" B_PRIx32 ")\n", 116*d6618274SFrançois Revol fKernelVirtualPageDirectory, fKernelPhysicalPageDirectory); 117*d6618274SFrançois Revol #endif 118*d6618274SFrançois Revol 119*d6618274SFrançois Revol PPCPagingStructures460::StaticInit(); 120*d6618274SFrançois Revol 121*d6618274SFrançois Revol // create the initial pool for the physical page mapper 122*d6618274SFrançois Revol PhysicalPageSlotPool* pool 123*d6618274SFrançois Revol = new(&PhysicalPageSlotPool::sInitialPhysicalPagePool) 124*d6618274SFrançois Revol PhysicalPageSlotPool; 125*d6618274SFrançois Revol status_t error = pool->InitInitial(args); 126*d6618274SFrançois Revol if (error != B_OK) { 127*d6618274SFrançois Revol panic("PPCPagingMethod460::Init(): Failed to create initial pool " 128*d6618274SFrançois Revol "for physical page mapper!"); 129*d6618274SFrançois Revol return error; 130*d6618274SFrançois Revol } 131*d6618274SFrançois Revol 132*d6618274SFrançois Revol // create physical page mapper 133*d6618274SFrançois Revol large_memory_physical_page_ops_init(args, pool, fPhysicalPageMapper, 134*d6618274SFrançois Revol fKernelPhysicalPageMapper); 135*d6618274SFrançois Revol // TODO: Select the best page mapper! 136*d6618274SFrançois Revol 137*d6618274SFrançois Revol // enable global page feature if available 138*d6618274SFrançois Revol if (x86_check_feature(IA32_FEATURE_PGE, FEATURE_COMMON)) { 139*d6618274SFrançois Revol // this prevents kernel pages from being flushed from TLB on 140*d6618274SFrançois Revol // context-switch 141*d6618274SFrançois Revol x86_write_cr4(x86_read_cr4() | IA32_CR4_GLOBAL_PAGES); 142*d6618274SFrançois Revol } 143*d6618274SFrançois Revol 144*d6618274SFrançois Revol TRACE("PPCPagingMethod460::Init(): done\n"); 145*d6618274SFrançois Revol 146*d6618274SFrançois Revol *_physicalPageMapper = fPhysicalPageMapper; 147*d6618274SFrançois Revol return B_OK; 148*d6618274SFrançois Revol #endif 149*d6618274SFrançois Revol } 150*d6618274SFrançois Revol 151*d6618274SFrançois Revol 152*d6618274SFrançois Revol status_t 153*d6618274SFrançois Revol PPCPagingMethod460::InitPostArea(kernel_args* args) 154*d6618274SFrançois Revol { 155*d6618274SFrançois Revol 156*d6618274SFrançois Revol // If the page table doesn't lie within the kernel address space, we 157*d6618274SFrançois Revol // remap it. 158*d6618274SFrançois Revol if (!IS_KERNEL_ADDRESS(fPageTable)) { 159*d6618274SFrançois Revol addr_t newAddress = (addr_t)fPageTable; 160*d6618274SFrançois Revol status_t error = ppc_remap_address_range(&newAddress, fPageTableSize, 161*d6618274SFrançois Revol false); 162*d6618274SFrançois Revol if (error != B_OK) { 163*d6618274SFrançois Revol panic("arch_vm_translation_map_init_post_area(): Failed to remap " 164*d6618274SFrançois Revol "the page table!"); 165*d6618274SFrançois Revol return error; 166*d6618274SFrançois Revol } 167*d6618274SFrançois Revol 168*d6618274SFrançois Revol // set the new page table address 169*d6618274SFrançois Revol addr_t oldVirtualBase = (addr_t)(fPageTable); 170*d6618274SFrançois Revol fPageTable = (page_table_entry_group*)newAddress; 171*d6618274SFrançois Revol 172*d6618274SFrançois Revol // unmap the old pages 173*d6618274SFrançois Revol ppc_unmap_address_range(oldVirtualBase, fPageTableSize); 174*d6618274SFrançois Revol 175*d6618274SFrançois Revol // TODO: We should probably map the page table via BAT. It is relatively large, 176*d6618274SFrançois Revol // and due to being a hash table the access patterns might look sporadic, which 177*d6618274SFrançois Revol // certainly isn't to the liking of the TLB. 178*d6618274SFrançois Revol } 179*d6618274SFrançois Revol 180*d6618274SFrançois Revol // create an area to cover the page table 181*d6618274SFrançois Revol fPageTableArea = create_area("page_table", (void **)&fPageTable, B_EXACT_ADDRESS, 182*d6618274SFrançois Revol fPageTableSize, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 183*d6618274SFrançois Revol 184*d6618274SFrançois Revol // init physical page mapper 185*d6618274SFrançois Revol status_t error = generic_vm_physical_page_mapper_init_post_area(args); 186*d6618274SFrançois Revol if (error != B_OK) 187*d6618274SFrançois Revol return error; 188*d6618274SFrançois Revol 189*d6618274SFrançois Revol return B_OK; 190*d6618274SFrançois Revol 191*d6618274SFrançois Revol #if 0//X86 192*d6618274SFrançois Revol // now that the vm is initialized, create an area that represents 193*d6618274SFrançois Revol // the page hole 194*d6618274SFrançois Revol void *temp; 195*d6618274SFrançois Revol status_t error; 196*d6618274SFrançois Revol area_id area; 197*d6618274SFrançois Revol 198*d6618274SFrançois Revol // unmap the page hole hack we were using before 199*d6618274SFrançois Revol fKernelVirtualPageDirectory[1023] = 0; 200*d6618274SFrançois Revol fPageHolePageDir = NULL; 201*d6618274SFrançois Revol fPageHole = NULL; 202*d6618274SFrançois Revol 203*d6618274SFrançois Revol temp = (void*)fKernelVirtualPageDirectory; 204*d6618274SFrançois Revol area = create_area("kernel_pgdir", &temp, B_EXACT_ADDRESS, B_PAGE_SIZE, 205*d6618274SFrançois Revol B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 206*d6618274SFrançois Revol if (area < B_OK) 207*d6618274SFrançois Revol return area; 208*d6618274SFrançois Revol 209*d6618274SFrançois Revol error = PhysicalPageSlotPool::sInitialPhysicalPagePool 210*d6618274SFrançois Revol .InitInitialPostArea(args); 211*d6618274SFrançois Revol if (error != B_OK) 212*d6618274SFrançois Revol return error; 213*d6618274SFrançois Revol 214*d6618274SFrançois Revol return B_OK; 215*d6618274SFrançois Revol #endif//X86 216*d6618274SFrançois Revol } 217*d6618274SFrançois Revol 218*d6618274SFrançois Revol 219*d6618274SFrançois Revol status_t 220*d6618274SFrançois Revol PPCPagingMethod460::CreateTranslationMap(bool kernel, VMTranslationMap** _map) 221*d6618274SFrançois Revol { 222*d6618274SFrançois Revol PPCVMTranslationMap460* map = new(std::nothrow) PPCVMTranslationMap460; 223*d6618274SFrançois Revol if (map == NULL) 224*d6618274SFrançois Revol return B_NO_MEMORY; 225*d6618274SFrançois Revol 226*d6618274SFrançois Revol status_t error = map->Init(kernel); 227*d6618274SFrançois Revol if (error != B_OK) { 228*d6618274SFrançois Revol delete map; 229*d6618274SFrançois Revol return error; 230*d6618274SFrançois Revol } 231*d6618274SFrançois Revol 232*d6618274SFrançois Revol *_map = map; 233*d6618274SFrançois Revol return B_OK; 234*d6618274SFrançois Revol } 235*d6618274SFrançois Revol 236*d6618274SFrançois Revol 237*d6618274SFrançois Revol status_t 238*d6618274SFrançois Revol PPCPagingMethod460::MapEarly(kernel_args* args, addr_t virtualAddress, 239*d6618274SFrançois Revol phys_addr_t physicalAddress, uint8 attributes, 240*d6618274SFrançois Revol page_num_t (*get_free_page)(kernel_args*)) 241*d6618274SFrançois Revol { 242*d6618274SFrançois Revol uint32 virtualSegmentID = get_sr((void *)virtualAddress) & 0xffffff; 243*d6618274SFrançois Revol 244*d6618274SFrançois Revol uint32 hash = page_table_entry::PrimaryHash(virtualSegmentID, (uint32)virtualAddress); 245*d6618274SFrançois Revol page_table_entry_group *group = &fPageTable[hash & fPageTableHashMask]; 246*d6618274SFrançois Revol 247*d6618274SFrançois Revol for (int32 i = 0; i < 8; i++) { 248*d6618274SFrançois Revol // 8 entries in a group 249*d6618274SFrançois Revol if (group->entry[i].valid) 250*d6618274SFrançois Revol continue; 251*d6618274SFrançois Revol 252*d6618274SFrançois Revol FillPageTableEntry(&group->entry[i], virtualSegmentID, 253*d6618274SFrançois Revol virtualAddress, physicalAddress, PTE_READ_WRITE, 0, false); 254*d6618274SFrançois Revol return B_OK; 255*d6618274SFrançois Revol } 256*d6618274SFrançois Revol 257*d6618274SFrançois Revol hash = page_table_entry::SecondaryHash(hash); 258*d6618274SFrançois Revol group = &fPageTable[hash & fPageTableHashMask]; 259*d6618274SFrançois Revol 260*d6618274SFrançois Revol for (int32 i = 0; i < 8; i++) { 261*d6618274SFrançois Revol if (group->entry[i].valid) 262*d6618274SFrançois Revol continue; 263*d6618274SFrançois Revol 264*d6618274SFrançois Revol FillPageTableEntry(&group->entry[i], virtualSegmentID, 265*d6618274SFrançois Revol virtualAddress, physicalAddress, PTE_READ_WRITE, 0, true); 266*d6618274SFrançois Revol return B_OK; 267*d6618274SFrançois Revol } 268*d6618274SFrançois Revol 269*d6618274SFrançois Revol return B_ERROR; 270*d6618274SFrançois Revol } 271*d6618274SFrançois Revol 272*d6618274SFrançois Revol 273*d6618274SFrançois Revol bool 274*d6618274SFrançois Revol PPCPagingMethod460::IsKernelPageAccessible(addr_t virtualAddress, 275*d6618274SFrançois Revol uint32 protection) 276*d6618274SFrançois Revol { 277*d6618274SFrançois Revol // TODO:factor out to baseclass 278*d6618274SFrançois Revol VMAddressSpace *addressSpace = VMAddressSpace::Kernel(); 279*d6618274SFrançois Revol 280*d6618274SFrançois Revol //XXX: 281*d6618274SFrançois Revol // PPCVMTranslationMap* map = static_cast<PPCVMTranslationMap*>( 282*d6618274SFrançois Revol // addressSpace->TranslationMap()); 283*d6618274SFrançois Revol // VMTranslationMap* map = addressSpace->TranslationMap(); 284*d6618274SFrançois Revol PPCVMTranslationMap460* map = static_cast<PPCVMTranslationMap460*>( 285*d6618274SFrançois Revol addressSpace->TranslationMap()); 286*d6618274SFrançois Revol 287*d6618274SFrançois Revol phys_addr_t physicalAddress; 288*d6618274SFrançois Revol uint32 flags; 289*d6618274SFrançois Revol if (map->Query(virtualAddress, &physicalAddress, &flags) != B_OK) 290*d6618274SFrançois Revol return false; 291*d6618274SFrançois Revol 292*d6618274SFrançois Revol if ((flags & PAGE_PRESENT) == 0) 293*d6618274SFrançois Revol return false; 294*d6618274SFrançois Revol 295*d6618274SFrançois Revol // present means kernel-readable, so check for writable 296*d6618274SFrançois Revol return (protection & B_KERNEL_WRITE_AREA) == 0 297*d6618274SFrançois Revol || (flags & B_KERNEL_WRITE_AREA) != 0; 298*d6618274SFrançois Revol } 299*d6618274SFrançois Revol 300*d6618274SFrançois Revol 301*d6618274SFrançois Revol void 302*d6618274SFrançois Revol PPCPagingMethod460::FillPageTableEntry(page_table_entry *entry, 303*d6618274SFrançois Revol uint32 virtualSegmentID, addr_t virtualAddress, phys_addr_t physicalAddress, 304*d6618274SFrançois Revol uint8 protection, uint32 memoryType, bool secondaryHash) 305*d6618274SFrançois Revol { 306*d6618274SFrançois Revol // lower 32 bit - set at once 307*d6618274SFrançois Revol entry->physical_page_number = physicalAddress / B_PAGE_SIZE; 308*d6618274SFrançois Revol entry->_reserved0 = 0; 309*d6618274SFrançois Revol entry->referenced = false; 310*d6618274SFrançois Revol entry->changed = false; 311*d6618274SFrançois Revol entry->write_through = (memoryType == B_MTR_UC) || (memoryType == B_MTR_WT); 312*d6618274SFrançois Revol entry->caching_inhibited = (memoryType == B_MTR_UC); 313*d6618274SFrançois Revol entry->memory_coherent = false; 314*d6618274SFrançois Revol entry->guarded = false; 315*d6618274SFrançois Revol entry->_reserved1 = 0; 316*d6618274SFrançois Revol entry->page_protection = protection & 0x3; 317*d6618274SFrançois Revol eieio(); 318*d6618274SFrançois Revol // we need to make sure that the lower 32 bit were 319*d6618274SFrançois Revol // already written when the entry becomes valid 320*d6618274SFrançois Revol 321*d6618274SFrançois Revol // upper 32 bit 322*d6618274SFrançois Revol entry->virtual_segment_id = virtualSegmentID; 323*d6618274SFrançois Revol entry->secondary_hash = secondaryHash; 324*d6618274SFrançois Revol entry->abbr_page_index = (virtualAddress >> 22) & 0x3f; 325*d6618274SFrançois Revol entry->valid = true; 326*d6618274SFrançois Revol 327*d6618274SFrançois Revol ppc_sync(); 328*d6618274SFrançois Revol } 329*d6618274SFrançois Revol 330*d6618274SFrançois Revol 331*d6618274SFrançois Revol #if 0//X86 332*d6618274SFrançois Revol /*static*/ void 333*d6618274SFrançois Revol PPCPagingMethod460::PutPageTableInPageDir(page_directory_entry* entry, 334*d6618274SFrançois Revol phys_addr_t pgtablePhysical, uint32 attributes) 335*d6618274SFrançois Revol { 336*d6618274SFrançois Revol *entry = (pgtablePhysical & PPC_PDE_ADDRESS_MASK) 337*d6618274SFrançois Revol | PPC_PDE_PRESENT 338*d6618274SFrançois Revol | PPC_PDE_WRITABLE 339*d6618274SFrançois Revol | PPC_PDE_USER; 340*d6618274SFrançois Revol // TODO: we ignore the attributes of the page table - for compatibility 341*d6618274SFrançois Revol // with BeOS we allow having user accessible areas in the kernel address 342*d6618274SFrançois Revol // space. This is currently being used by some drivers, mainly for the 343*d6618274SFrançois Revol // frame buffer. Our current real time data implementation makes use of 344*d6618274SFrançois Revol // this fact, too. 345*d6618274SFrançois Revol // We might want to get rid of this possibility one day, especially if 346*d6618274SFrançois Revol // we intend to port it to a platform that does not support this. 347*d6618274SFrançois Revol } 348*d6618274SFrançois Revol 349*d6618274SFrançois Revol 350*d6618274SFrançois Revol /*static*/ void 351*d6618274SFrançois Revol PPCPagingMethod460::PutPageTableEntryInTable(page_table_entry* entry, 352*d6618274SFrançois Revol phys_addr_t physicalAddress, uint32 attributes, uint32 memoryType, 353*d6618274SFrançois Revol bool globalPage) 354*d6618274SFrançois Revol { 355*d6618274SFrançois Revol page_table_entry page = (physicalAddress & PPC_PTE_ADDRESS_MASK) 356*d6618274SFrançois Revol | PPC_PTE_PRESENT | (globalPage ? PPC_PTE_GLOBAL : 0) 357*d6618274SFrançois Revol | MemoryTypeToPageTableEntryFlags(memoryType); 358*d6618274SFrançois Revol 359*d6618274SFrançois Revol // if the page is user accessible, it's automatically 360*d6618274SFrançois Revol // accessible in kernel space, too (but with the same 361*d6618274SFrançois Revol // protection) 362*d6618274SFrançois Revol if ((attributes & B_USER_PROTECTION) != 0) { 363*d6618274SFrançois Revol page |= PPC_PTE_USER; 364*d6618274SFrançois Revol if ((attributes & B_WRITE_AREA) != 0) 365*d6618274SFrançois Revol page |= PPC_PTE_WRITABLE; 366*d6618274SFrançois Revol } else if ((attributes & B_KERNEL_WRITE_AREA) != 0) 367*d6618274SFrançois Revol page |= PPC_PTE_WRITABLE; 368*d6618274SFrançois Revol 369*d6618274SFrançois Revol // put it in the page table 370*d6618274SFrançois Revol *(volatile page_table_entry*)entry = page; 371*d6618274SFrançois Revol } 372*d6618274SFrançois Revol 373*d6618274SFrançois Revol 374*d6618274SFrançois Revol /*static*/ void 375*d6618274SFrançois Revol PPCPagingMethod460::_EarlyPreparePageTables(page_table_entry* pageTables, 376*d6618274SFrançois Revol addr_t address, size_t size) 377*d6618274SFrançois Revol { 378*d6618274SFrançois Revol memset(pageTables, 0, B_PAGE_SIZE * (size / (B_PAGE_SIZE * 1024))); 379*d6618274SFrançois Revol 380*d6618274SFrançois Revol // put the array of pgtables directly into the kernel pagedir 381*d6618274SFrançois Revol // these will be wired and kept mapped into virtual space to be easy to get 382*d6618274SFrançois Revol // to 383*d6618274SFrançois Revol { 384*d6618274SFrançois Revol addr_t virtualTable = (addr_t)pageTables; 385*d6618274SFrançois Revol 386*d6618274SFrançois Revol page_directory_entry* pageHolePageDir 387*d6618274SFrançois Revol = PPCPagingMethod460::Method()->PageHolePageDir(); 388*d6618274SFrançois Revol 389*d6618274SFrançois Revol for (size_t i = 0; i < (size / (B_PAGE_SIZE * 1024)); 390*d6618274SFrançois Revol i++, virtualTable += B_PAGE_SIZE) { 391*d6618274SFrançois Revol phys_addr_t physicalTable = 0; 392*d6618274SFrançois Revol _EarlyQuery(virtualTable, &physicalTable); 393*d6618274SFrançois Revol page_directory_entry* entry = &pageHolePageDir[ 394*d6618274SFrançois Revol (address / (B_PAGE_SIZE * 1024)) + i]; 395*d6618274SFrançois Revol PutPageTableInPageDir(entry, physicalTable, 396*d6618274SFrançois Revol B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 397*d6618274SFrançois Revol } 398*d6618274SFrançois Revol } 399*d6618274SFrançois Revol } 400*d6618274SFrançois Revol 401*d6618274SFrançois Revol 402*d6618274SFrançois Revol //! TODO: currently assumes this translation map is active 403*d6618274SFrançois Revol /*static*/ status_t 404*d6618274SFrançois Revol PPCPagingMethod460::_EarlyQuery(addr_t virtualAddress, 405*d6618274SFrançois Revol phys_addr_t *_physicalAddress) 406*d6618274SFrançois Revol { 407*d6618274SFrançois Revol PPCPagingMethod460* method = PPCPagingMethod460::Method(); 408*d6618274SFrançois Revol int index = VADDR_TO_PDENT(virtualAddress); 409*d6618274SFrançois Revol if ((method->PageHolePageDir()[index] & PPC_PDE_PRESENT) == 0) { 410*d6618274SFrançois Revol // no pagetable here 411*d6618274SFrançois Revol return B_ERROR; 412*d6618274SFrançois Revol } 413*d6618274SFrançois Revol 414*d6618274SFrançois Revol page_table_entry* entry = method->PageHole() + virtualAddress / B_PAGE_SIZE; 415*d6618274SFrançois Revol if ((*entry & PPC_PTE_PRESENT) == 0) { 416*d6618274SFrançois Revol // page mapping not valid 417*d6618274SFrançois Revol return B_ERROR; 418*d6618274SFrançois Revol } 419*d6618274SFrançois Revol 420*d6618274SFrançois Revol *_physicalAddress = *entry & PPC_PTE_ADDRESS_MASK; 421*d6618274SFrançois Revol return B_OK; 422*d6618274SFrançois Revol } 423*d6618274SFrançois Revol #endif 424