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