xref: /haiku/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.h (revision 7a74a5df454197933bc6e80a542102362ee98703)
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 									phys_addr_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 	static	void				_EarlyPreparePageTables(
81 									page_table_entry* pageTables,
82 									addr_t address, size_t size);
83 	static	status_t			_EarlyQuery(addr_t virtualAddress,
84 									phys_addr_t *_physicalAddress);
85 
86 private:
87 			uint32				fKernelPhysicalPageDirectory;
88 			page_directory_entry* fKernelVirtualPageDirectory;
89 
90 			ARMPhysicalPageMapper* fPhysicalPageMapper;
91 			TranslationMapPhysicalPageMapper* fKernelPhysicalPageMapper;
92 };
93 
94 
95 /*static*/ inline ARMPagingMethod32Bit*
96 ARMPagingMethod32Bit::Method()
97 {
98 	return static_cast<ARMPagingMethod32Bit*>(gARMPagingMethod);
99 }
100 
101 
102 /*static*/ inline page_table_entry
103 ARMPagingMethod32Bit::SetPageTableEntry(page_table_entry* entry,
104 	page_table_entry newEntry)
105 {
106 	return atomic_set((int32*)entry, newEntry);
107 }
108 
109 
110 /*static*/ inline page_table_entry
111 ARMPagingMethod32Bit::SetPageTableEntryFlags(page_table_entry* entry,
112 	uint32 flags)
113 {
114 	return atomic_or((int32*)entry, flags);
115 }
116 
117 
118 /*static*/ inline page_table_entry
119 ARMPagingMethod32Bit::TestAndSetPageTableEntry(page_table_entry* entry,
120 	page_table_entry newEntry, page_table_entry oldEntry)
121 {
122 	return atomic_test_and_set((int32*)entry, newEntry, oldEntry);
123 }
124 
125 
126 /*static*/ inline page_table_entry
127 ARMPagingMethod32Bit::ClearPageTableEntry(page_table_entry* entry)
128 {
129 	return SetPageTableEntry(entry, 0);
130 }
131 
132 
133 /*static*/ inline page_table_entry
134 ARMPagingMethod32Bit::ClearPageTableEntryFlags(page_table_entry* entry, uint32 flags)
135 {
136 	return atomic_and((int32*)entry, ~flags);
137 }
138 
139 
140 /*static*/ inline uint32
141 ARMPagingMethod32Bit::MemoryTypeToPageTableEntryFlags(uint32 memoryType)
142 {
143 #if 0 //IRA
144 	// ATM we only handle the uncacheable and write-through type explicitly. For
145 	// all other types we rely on the MTRRs to be set up correctly. Since we set
146 	// the default memory type to write-back and since the uncacheable type in
147 	// the PTE overrides any MTRR attribute (though, as per the specs, that is
148 	// not recommended for performance reasons), this reduces the work we
149 	// actually *have* to do with the MTRRs to setting the remaining types
150 	// (usually only write-combining for the frame buffer).
151 	switch (memoryType) {
152 		case B_MTR_UC:
153 			return ARM_PTE_CACHING_DISABLED | ARM_PTE_WRITE_THROUGH;
154 
155 		case B_MTR_WC:
156 			// ARM_PTE_WRITE_THROUGH would be closer, but the combination with
157 			// MTRR WC is "implementation defined" for Pentium Pro/II.
158 			return 0;
159 
160 		case B_MTR_WT:
161 			return ARM_PTE_WRITE_THROUGH;
162 
163 		case B_MTR_WP:
164 		case B_MTR_WB:
165 		default:
166 			return 0;
167 	}
168 #else
169 	return 0;
170 #endif
171 }
172 
173 
174 #endif	// KERNEL_ARCH_ARM_PAGING_32_BIT_ARM_PAGING_METHOD_32_BIT_H
175