Kernel: PageTable now supports reserved pages
You can now map pages as reserved, so that they will not be given from get_free_page() or get_free_contiguous_pages().
This commit is contained in:
		
							parent
							
								
									dddfa308d7
								
							
						
					
					
						commit
						64ad752e73
					
				|  | @ -48,7 +48,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	static inline PageTable::flags_t parse_flags(uint64_t entry) | 	static inline PageTable::flags_t parse_flags(uint64_t entry) | ||||||
| 	{ | 	{ | ||||||
| 		return (s_has_nxe && !(entry & (1ull << 63)) ? PageTable::Flags::Execute : 0) | (entry & 0b111); | 		return (s_has_nxe && !(entry & (1ull << 63)) ? PageTable::Flags::Execute : 0) | (entry & 0b100000111); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void PageTable::initialize() | 	void PageTable::initialize() | ||||||
|  | @ -251,7 +251,7 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 		ASSERT(paddr % PAGE_SIZE == 0); | 		ASSERT(paddr % PAGE_SIZE == 0); | ||||||
| 		ASSERT(vaddr % PAGE_SIZE == 0); | 		ASSERT(vaddr % PAGE_SIZE == 0); | ||||||
| 		ASSERT(flags & Flags::Present); | 		ASSERT(flags & Flags::Used); | ||||||
| 
 | 
 | ||||||
| 		uint64_t pml4e = (vaddr >> 39) & 0x1FF; | 		uint64_t pml4e = (vaddr >> 39) & 0x1FF; | ||||||
| 		uint64_t pdpte = (vaddr >> 30) & 0x1FF; | 		uint64_t pdpte = (vaddr >> 30) & 0x1FF; | ||||||
|  | @ -263,6 +263,8 @@ namespace Kernel | ||||||
| 			extra_flags |= 1ull << 63; | 			extra_flags |= 1ull << 63; | ||||||
| 		if (s_has_pge && pml4e == 511) | 		if (s_has_pge && pml4e == 511) | ||||||
| 			extra_flags |= 1ull << 8; | 			extra_flags |= 1ull << 8; | ||||||
|  | 		if (flags & Flags::Reserved) | ||||||
|  | 			extra_flags |= Flags::Reserved; | ||||||
| 		flags_t uwr_flags = flags & 0b111; | 		flags_t uwr_flags = flags & 0b111; | ||||||
| 
 | 
 | ||||||
| 		uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct); | 		uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct); | ||||||
|  | @ -355,7 +357,7 @@ namespace Kernel | ||||||
| 		return (page_data & PAGE_ADDR_MASK) & ~(1ull << 63); | 		return (page_data & PAGE_ADDR_MASK) & ~(1ull << 63); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	vaddr_t PageTable::get_free_page(vaddr_t first_address) const | 	vaddr_t PageTable::get_free_page(vaddr_t first_address) | ||||||
| 	{ | 	{ | ||||||
| 		LockGuard _(m_lock); | 		LockGuard _(m_lock); | ||||||
| 
 | 
 | ||||||
|  | @ -390,13 +392,14 @@ namespace Kernel | ||||||
| 					uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK); | 					uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK); | ||||||
| 					for (; pte < 512; pte++) | 					for (; pte < 512; pte++) | ||||||
| 					{ | 					{ | ||||||
| 						if (!(pt[pte] & Flags::Present)) | 						if (!(pt[pte] & Flags::Used)) | ||||||
| 						{ | 						{ | ||||||
| 							vaddr_t vaddr = 0; | 							vaddr_t vaddr = 0; | ||||||
| 							vaddr |= pml4e << 39; | 							vaddr |= pml4e << 39; | ||||||
| 							vaddr |= pdpte << 30; | 							vaddr |= pdpte << 30; | ||||||
| 							vaddr |= pde   << 21; | 							vaddr |= pde   << 21; | ||||||
| 							vaddr |= pte   << 12; | 							vaddr |= pte   << 12; | ||||||
|  | 							pt[pte] |= Flags::Reserved; | ||||||
| 							return canonicalize(vaddr); | 							return canonicalize(vaddr); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  | @ -404,12 +407,15 @@ namespace Kernel | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Find any free page page (except for page 0)
 | 		// Find any free page page
 | ||||||
| 		vaddr = first_address; | 		vaddr = first_address; | ||||||
| 		while (is_canonical(vaddr)) | 		while (is_canonical(vaddr)) | ||||||
| 		{ | 		{ | ||||||
| 			if (is_page_free(vaddr)) | 			if (is_page_free(vaddr)) | ||||||
|  | 			{ | ||||||
|  | 				map_page_at(0, vaddr, Flags::Reserved); | ||||||
| 				return vaddr; | 				return vaddr; | ||||||
|  | 			} | ||||||
| 			if (vaddr > vaddr + PAGE_SIZE) | 			if (vaddr > vaddr + PAGE_SIZE) | ||||||
| 				break; | 				break; | ||||||
| 			vaddr += PAGE_SIZE; | 			vaddr += PAGE_SIZE; | ||||||
|  | @ -418,7 +424,7 @@ namespace Kernel | ||||||
| 		ASSERT_NOT_REACHED(); | 		ASSERT_NOT_REACHED(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	vaddr_t PageTable::get_free_contiguous_pages(size_t page_count, vaddr_t first_address) const | 	vaddr_t PageTable::get_free_contiguous_pages(size_t page_count, vaddr_t first_address) | ||||||
| 	{ | 	{ | ||||||
| 		if (first_address % PAGE_SIZE) | 		if (first_address % PAGE_SIZE) | ||||||
| 			first_address = (first_address + PAGE_SIZE - 1) & PAGE_ADDR_MASK; | 			first_address = (first_address + PAGE_SIZE - 1) & PAGE_ADDR_MASK; | ||||||
|  | @ -430,7 +436,7 @@ namespace Kernel | ||||||
| 			bool valid { true }; | 			bool valid { true }; | ||||||
| 			for (size_t page = 0; page < page_count; page++) | 			for (size_t page = 0; page < page_count; page++) | ||||||
| 			{ | 			{ | ||||||
| 				if (get_page_flags(vaddr + page * PAGE_SIZE) & Flags::Present) | 				if (get_page_flags(vaddr + page * PAGE_SIZE) & Flags::Used) | ||||||
| 				{ | 				{ | ||||||
| 					vaddr += page * PAGE_SIZE; | 					vaddr += page * PAGE_SIZE; | ||||||
| 					valid = false; | 					valid = false; | ||||||
|  | @ -438,7 +444,11 @@ namespace Kernel | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			if (valid) | 			if (valid) | ||||||
|  | 			{ | ||||||
|  | 				for (size_t page = 0; page < page_count; page++) | ||||||
|  | 					map_page_at(0, vaddr + page * PAGE_SIZE, Flags::Reserved); | ||||||
| 				return vaddr; | 				return vaddr; | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ASSERT_NOT_REACHED(); | 		ASSERT_NOT_REACHED(); | ||||||
|  | @ -447,7 +457,7 @@ namespace Kernel | ||||||
| 	bool PageTable::is_page_free(vaddr_t page) const | 	bool PageTable::is_page_free(vaddr_t page) const | ||||||
| 	{ | 	{ | ||||||
| 		ASSERT(page % PAGE_SIZE == 0); | 		ASSERT(page % PAGE_SIZE == 0); | ||||||
| 		return !(get_page_flags(page) & Flags::Present); | 		return !(get_page_flags(page) & Flags::Used); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bool PageTable::is_range_free(vaddr_t start, size_t size) const | 	bool PageTable::is_range_free(vaddr_t start, size_t size) const | ||||||
|  | @ -519,7 +529,7 @@ namespace Kernel | ||||||
| 							start = 0; | 							start = 0; | ||||||
| 						} | 						} | ||||||
| 
 | 
 | ||||||
| 						if (!(pt[pte] & Flags::Present)) | 						if (!(pt[pte] & Flags::Used)) | ||||||
| 							continue; | 							continue; | ||||||
| 						 | 						 | ||||||
| 						if (start == 0) | 						if (start == 0) | ||||||
|  |  | ||||||
|  | @ -10,13 +10,16 @@ namespace Kernel | ||||||
| 	class PageTable | 	class PageTable | ||||||
| 	{ | 	{ | ||||||
| 	public: | 	public: | ||||||
| 		using flags_t = uint8_t; | 		using flags_t = uint16_t; | ||||||
| 		enum Flags : flags_t  | 		enum Flags : flags_t  | ||||||
| 		{ | 		{ | ||||||
| 			Present = 1, | 			Present = 1, | ||||||
| 			ReadWrite = 2, | 			ReadWrite = 2, | ||||||
| 			UserSupervisor = 4, | 			UserSupervisor = 4, | ||||||
| 			Execute = 8, | 			Execute = 8, | ||||||
|  | 			Reserved = 256, | ||||||
|  | 
 | ||||||
|  | 			Used = Present | Reserved, | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 	public: | 	public: | ||||||
|  | @ -40,8 +43,8 @@ namespace Kernel | ||||||
| 		bool is_page_free(vaddr_t) const; | 		bool is_page_free(vaddr_t) const; | ||||||
| 		bool is_range_free(vaddr_t, size_t bytes) const; | 		bool is_range_free(vaddr_t, size_t bytes) const; | ||||||
| 
 | 
 | ||||||
| 		vaddr_t get_free_page(vaddr_t first_address = PAGE_SIZE) const; | 		vaddr_t get_free_page(vaddr_t first_address = PAGE_SIZE); | ||||||
| 		vaddr_t get_free_contiguous_pages(size_t page_count, vaddr_t first_address = PAGE_SIZE) const; | 		vaddr_t get_free_contiguous_pages(size_t page_count, vaddr_t first_address = PAGE_SIZE); | ||||||
| 
 | 
 | ||||||
| 		void load(); | 		void load(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue