1/*
2 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef KERNEL_ARCH_PPC_PAGING_460_PPC_PAGING_METHOD_460_H
6#define KERNEL_ARCH_PPC_PAGING_460_PPC_PAGING_METHOD_460_H
7
8
9#include <arch_mmu.h>
10//#include "paging/460/paging.h"
11#include "paging/PPCPagingMethod.h"
12#include "paging/PPCPagingStructures.h"
13#include "GenericVMPhysicalPageMapper.h"
14
15
16class TranslationMapPhysicalPageMapper;
17
18
19class PPCPagingMethod460 : public PPCPagingMethod {
20public:
21								PPCPagingMethod460();
22	virtual						~PPCPagingMethod460();
23
24	virtual	status_t			Init(kernel_args* args,
25									VMPhysicalPageMapper** _physicalPageMapper);
26	virtual	status_t			InitPostArea(kernel_args* args);
27
28	virtual	status_t			CreateTranslationMap(bool kernel,
29									VMTranslationMap** _map);
30
31	virtual	status_t			MapEarly(kernel_args* args,
32									addr_t virtualAddress,
33									phys_addr_t physicalAddress,
34									uint8 attributes,
35									page_num_t (*get_free_page)(kernel_args*));
36
37	virtual	bool				IsKernelPageAccessible(addr_t virtualAddress,
38									uint32 protection);
39#if 0//X86
40	inline	page_table_entry*	PageHole() const
41									{ return fPageHole; }
42	inline	page_directory_entry* PageHolePageDir() const
43									{ return fPageHolePageDir; }
44	inline	uint32				KernelPhysicalPageDirectory() const
45									{ return fKernelPhysicalPageDirectory; }
46	inline	page_directory_entry* KernelVirtualPageDirectory() const
47									{ return fKernelVirtualPageDirectory; }
48	inline	PPCPhysicalPageMapper* PhysicalPageMapper() const
49									{ return fPhysicalPageMapper; }
50	inline	TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const
51									{ return fKernelPhysicalPageMapper; }
52#endif
53
54	inline	page_table_entry_group* PageTable() const
55									{ return fPageTable; }
56	inline	size_t				PageTableSize() const
57									{ return fPageTableSize; }
58	inline	uint32				PageTableHashMask() const
59									{ return fPageTableHashMask; }
60
61	static	PPCPagingMethod460* Method();
62
63	void						FillPageTableEntry(page_table_entry *entry,
64									uint32 virtualSegmentID,
65									addr_t virtualAddress,
66									phys_addr_t physicalAddress,
67									uint8 protection, uint32 memoryType,
68									bool secondaryHash);
69
70
71#if 0//X86
72	static	void				PutPageTableInPageDir(
73									page_directory_entry* entry,
74									phys_addr_t pgtablePhysical,
75									uint32 attributes);
76	static	void				PutPageTableEntryInTable(
77									page_table_entry* entry,
78									phys_addr_t physicalAddress,
79									uint32 attributes, uint32 memoryType,
80									bool globalPage);
81	static	page_table_entry	SetPageTableEntry(page_table_entry* entry,
82									page_table_entry newEntry);
83	static	page_table_entry	SetPageTableEntryFlags(page_table_entry* entry,
84									uint32 flags);
85	static	page_table_entry	TestAndSetPageTableEntry(
86									page_table_entry* entry,
87									page_table_entry newEntry,
88									page_table_entry oldEntry);
89	static	page_table_entry	ClearPageTableEntry(page_table_entry* entry);
90	static	page_table_entry	ClearPageTableEntryFlags(
91									page_table_entry* entry, uint32 flags);
92
93	static	uint32				MemoryTypeToPageTableEntryFlags(
94									uint32 memoryType);
95#endif
96
97private:
98			//XXX:x86
99			struct PhysicalPageSlotPool;
100			friend struct PhysicalPageSlotPool;
101
102private:
103#if 0//X86
104	static	void				_EarlyPreparePageTables(
105									page_table_entry* pageTables,
106									addr_t address, size_t size);
107	static	status_t			_EarlyQuery(addr_t virtualAddress,
108									phys_addr_t *_physicalAddress);
109#endif
110
111private:
112			struct page_table_entry_group *fPageTable;
113			size_t				fPageTableSize;
114			uint32				fPageTableHashMask;
115			area_id				fPageTableArea;
116
117			GenericVMPhysicalPageMapper	fPhysicalPageMapper;
118
119
120#if 0			//XXX:x86
121			page_table_entry*	fPageHole;
122			page_directory_entry* fPageHolePageDir;
123			uint32				fKernelPhysicalPageDirectory;
124			page_directory_entry* fKernelVirtualPageDirectory;
125			PPCPhysicalPageMapper* fPhysicalPageMapper;
126			TranslationMapPhysicalPageMapper* fKernelPhysicalPageMapper;
127#endif
128};
129
130
131/*static*/ inline PPCPagingMethod460*
132PPCPagingMethod460::Method()
133{
134	return static_cast<PPCPagingMethod460*>(gPPCPagingMethod);
135}
136
137
138#if 0//X86
139/*static*/ inline page_table_entry
140PPCPagingMethod460::SetPageTableEntry(page_table_entry* entry,
141	page_table_entry newEntry)
142{
143	return atomic_set((int32*)entry, newEntry);
144}
145
146
147/*static*/ inline page_table_entry
148PPCPagingMethod460::SetPageTableEntryFlags(page_table_entry* entry,
149	uint32 flags)
150{
151	return atomic_or((int32*)entry, flags);
152}
153
154
155/*static*/ inline page_table_entry
156PPCPagingMethod460::TestAndSetPageTableEntry(page_table_entry* entry,
157	page_table_entry newEntry, page_table_entry oldEntry)
158{
159	return atomic_test_and_set((int32*)entry, newEntry, oldEntry);
160}
161
162
163/*static*/ inline page_table_entry
164PPCPagingMethod460::ClearPageTableEntry(page_table_entry* entry)
165{
166	return SetPageTableEntry(entry, 0);
167}
168
169
170/*static*/ inline page_table_entry
171PPCPagingMethod460::ClearPageTableEntryFlags(page_table_entry* entry, uint32 flags)
172{
173	return atomic_and((int32*)entry, ~flags);
174}
175
176
177/*static*/ inline uint32
178PPCPagingMethod460::MemoryTypeToPageTableEntryFlags(uint32 memoryType)
179{
180	// ATM we only handle the uncacheable and write-through type explicitly. For
181	// all other types we rely on the MTRRs to be set up correctly. Since we set
182	// the default memory type to write-back and since the uncacheable type in
183	// the PTE overrides any MTRR attribute (though, as per the specs, that is
184	// not recommended for performance reasons), this reduces the work we
185	// actually *have* to do with the MTRRs to setting the remaining types
186	// (usually only write-combining for the frame buffer).
187	switch (memoryType) {
188		case B_MTR_UC:
189			return PPC_PTE_CACHING_DISABLED | PPC_PTE_WRITE_THROUGH;
190
191		case B_MTR_WC:
192			// PPC_PTE_WRITE_THROUGH would be closer, but the combination with
193			// MTRR WC is "implementation defined" for Pentium Pro/II.
194			return 0;
195
196		case B_MTR_WT:
197			return PPC_PTE_WRITE_THROUGH;
198
199		case B_MTR_WP:
200		case B_MTR_WB:
201		default:
202			return 0;
203	}
204}
205#endif//X86
206
207
208#endif	// KERNEL_ARCH_PPC_PAGING_460_PPC_PAGING_METHOD_460_H
209