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