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