xref: /haiku/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 /*
2  * Copyright 2010, Ithamar R. Adema, ithamar.adema@team-embedded.nl
3  * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
4  * Distributed under the terms of the MIT License.
5  */
6 #ifndef KERNEL_ARCH_ARM_PAGING_32_BIT_ARM_PAGING_METHOD_32_BIT_H
7 #define KERNEL_ARCH_ARM_PAGING_32_BIT_ARM_PAGING_METHOD_32_BIT_H
8 
9 
10 #include "paging/32bit/paging.h"
11 #include "paging/ARMPagingMethod.h"
12 #include "paging/ARMPagingStructures.h"
13 
14 
15 class TranslationMapPhysicalPageMapper;
16 class ARMPhysicalPageMapper;
17 
18 
19 class ARMPagingMethod32Bit : public ARMPagingMethod {
20 public:
21 								ARMPagingMethod32Bit();
22 	virtual						~ARMPagingMethod32Bit();
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 
40 	inline	uint32				KernelPhysicalPageDirectory() const
41 									{ return fKernelPhysicalPageDirectory; }
42 	inline	page_directory_entry* KernelVirtualPageDirectory() const
43 									{ return fKernelVirtualPageDirectory; }
44 	inline	ARMPhysicalPageMapper* PhysicalPageMapper() const
45 									{ return fPhysicalPageMapper; }
46 	inline	TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const
47 									{ return fKernelPhysicalPageMapper; }
48 
49 	static	ARMPagingMethod32Bit* Method();
50 
51 	static	void				PutPageTableInPageDir(
52 									page_directory_entry* entry,
53 									phys_addr_t pgtablePhysical,
54 									uint32 attributes);
55 	static	void				PutPageTableEntryInTable(
56 									page_table_entry* entry,
57 									phys_addr_t physicalAddress,
58 									uint32 attributes, uint32 memoryType,
59 									bool globalPage);
60 	static	page_table_entry	SetPageTableEntry(page_table_entry* entry,
61 									page_table_entry newEntry);
62 	static	page_table_entry	SetPageTableEntryFlags(page_table_entry* entry,
63 									uint32 flags);
64 	static	page_table_entry	TestAndSetPageTableEntry(
65 									page_table_entry* entry,
66 									page_table_entry newEntry,
67 									page_table_entry oldEntry);
68 	static	page_table_entry	ClearPageTableEntry(page_table_entry* entry);
69 	static	page_table_entry	ClearPageTableEntryFlags(
70 									page_table_entry* entry, uint32 flags);
71 
72 	static	uint32				MemoryTypeToPageTableEntryFlags(
73 									uint32 memoryType);
74 
75 private:
76 			struct PhysicalPageSlotPool;
77 			friend struct PhysicalPageSlotPool;
78 
79 private:
80 	inline	int32				_GetInitialPoolCount();
81 
82 	static	void				_EarlyPreparePageTables(
83 									page_table_entry* pageTables,
84 									addr_t address, size_t size);
85 	static	status_t			_EarlyQuery(addr_t virtualAddress,
86 									phys_addr_t *_physicalAddress);
87 
88 private:
89 			uint32				fKernelPhysicalPageDirectory;
90 			page_directory_entry* fKernelVirtualPageDirectory;
91 
92 			ARMPhysicalPageMapper* fPhysicalPageMapper;
93 			TranslationMapPhysicalPageMapper* fKernelPhysicalPageMapper;
94 };
95 
96 
97 /*static*/ inline ARMPagingMethod32Bit*
98 ARMPagingMethod32Bit::Method()
99 {
100 	return static_cast<ARMPagingMethod32Bit*>(gARMPagingMethod);
101 }
102 
103 
104 /*static*/ inline page_table_entry
105 ARMPagingMethod32Bit::SetPageTableEntry(page_table_entry* entry,
106 	page_table_entry newEntry)
107 {
108 	return atomic_get_and_set((int32*)entry, newEntry);
109 }
110 
111 
112 /*static*/ inline page_table_entry
113 ARMPagingMethod32Bit::SetPageTableEntryFlags(page_table_entry* entry,
114 	uint32 flags)
115 {
116 	return atomic_or((int32*)entry, flags);
117 }
118 
119 
120 /*static*/ inline page_table_entry
121 ARMPagingMethod32Bit::TestAndSetPageTableEntry(page_table_entry* entry,
122 	page_table_entry newEntry, page_table_entry oldEntry)
123 {
124 	return atomic_test_and_set((int32*)entry, newEntry, oldEntry);
125 }
126 
127 
128 /*static*/ inline page_table_entry
129 ARMPagingMethod32Bit::ClearPageTableEntry(page_table_entry* entry)
130 {
131 	return SetPageTableEntry(entry, 0);
132 }
133 
134 
135 /*static*/ inline page_table_entry
136 ARMPagingMethod32Bit::ClearPageTableEntryFlags(page_table_entry* entry, uint32 flags)
137 {
138 	return atomic_and((int32*)entry, ~flags);
139 }
140 
141 
142 /*static*/ inline uint32
143 ARMPagingMethod32Bit::MemoryTypeToPageTableEntryFlags(uint32 memoryType)
144 {
145 #if 0 //IRA
146 	// ATM we only handle the uncacheable and write-through type explicitly. For
147 	// all other types we rely on the MTRRs to be set up correctly. Since we set
148 	// the default memory type to write-back and since the uncacheable type in
149 	// the PTE overrides any MTRR attribute (though, as per the specs, that is
150 	// not recommended for performance reasons), this reduces the work we
151 	// actually *have* to do with the MTRRs to setting the remaining types
152 	// (usually only write-combining for the frame buffer).
153 	switch (memoryType) {
154 		case B_MTR_UC:
155 			return X86_PTE_CACHING_DISABLED | X86_PTE_WRITE_THROUGH;
156 
157 		case B_MTR_WC:
158 			// ARM_PTE_WRITE_THROUGH would be closer, but the combination with
159 			// MTRR WC is "implementation defined" for Pentium Pro/II.
160 			return 0;
161 
162 		case B_MTR_WT:
163 			return X86_PTE_WRITE_THROUGH;
164 
165 		case B_MTR_WP:
166 		case B_MTR_WB:
167 		default:
168 			return 0;
169 	}
170 #else
171 	return 0;
172 #endif
173 }
174 
175 
176 #endif	// KERNEL_ARCH_ARM_PAGING_32_BIT_ARM_PAGING_METHOD_32_BIT_H
177