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