xref: /haiku/src/system/kernel/arch/x86/paging/32bit/X86PagingStructures32Bit.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
1 /*
2  * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  *
6  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
7  * Distributed under the terms of the NewOS License.
8  */
9 
10 
11 #include "paging/32bit/X86PagingStructures32Bit.h"
12 
13 #include <stdlib.h>
14 
15 #include <heap.h>
16 #include <util/AutoLock.h>
17 
18 
19 // Accessor class to reuse the SinglyLinkedListLink of DeferredDeletable for
20 // X86PagingStructures32Bit.
21 struct PagingStructuresGetLink {
22 private:
23 	typedef SinglyLinkedListLink<X86PagingStructures32Bit> Link;
24 
25 public:
26 	inline Link* operator()(X86PagingStructures32Bit* element) const
27 	{
28 		return (Link*)element->GetSinglyLinkedListLink();
29 	}
30 
31 	inline const Link* operator()(
32 		const X86PagingStructures32Bit* element) const
33 	{
34 		return (const Link*)element->GetSinglyLinkedListLink();
35 	}
36 };
37 
38 
39 typedef SinglyLinkedList<X86PagingStructures32Bit, PagingStructuresGetLink>
40 	PagingStructuresList;
41 
42 
43 static PagingStructuresList sPagingStructuresList;
44 static spinlock sPagingStructuresListLock;
45 
46 
47 X86PagingStructures32Bit::X86PagingStructures32Bit()
48 	:
49 	pgdir_virt(NULL)
50 {
51 }
52 
53 
54 X86PagingStructures32Bit::~X86PagingStructures32Bit()
55 {
56 	// free the page dir
57 	free(pgdir_virt);
58 }
59 
60 
61 void
62 X86PagingStructures32Bit::Init(page_directory_entry* virtualPageDir,
63 	phys_addr_t physicalPageDir, page_directory_entry* kernelPageDir)
64 {
65 	pgdir_virt = virtualPageDir;
66 	pgdir_phys = physicalPageDir;
67 
68 	// zero out the bottom portion of the new pgdir
69 	memset(pgdir_virt + FIRST_USER_PGDIR_ENT, 0,
70 		NUM_USER_PGDIR_ENTS * sizeof(page_directory_entry));
71 
72 	// insert this new map into the map list
73 	{
74 		int state = disable_interrupts();
75 		acquire_spinlock(&sPagingStructuresListLock);
76 
77 		// copy the top portion of the page dir from the kernel page dir
78 		if (kernelPageDir != NULL) {
79 			memcpy(pgdir_virt + FIRST_KERNEL_PGDIR_ENT,
80 				kernelPageDir + FIRST_KERNEL_PGDIR_ENT,
81 				NUM_KERNEL_PGDIR_ENTS * sizeof(page_directory_entry));
82 		}
83 
84 		sPagingStructuresList.Add(this);
85 
86 		release_spinlock(&sPagingStructuresListLock);
87 		restore_interrupts(state);
88 	}
89 }
90 
91 
92 void
93 X86PagingStructures32Bit::Delete()
94 {
95 	// remove from global list
96 	InterruptsSpinLocker locker(sPagingStructuresListLock);
97 	sPagingStructuresList.Remove(this);
98 	locker.Unlock();
99 
100 #if 0
101 	// this sanity check can be enabled when corruption due to
102 	// overwriting an active page directory is suspected
103 	uint32 activePageDirectory = x86_read_cr3();
104 	if (activePageDirectory == pgdir_phys)
105 		panic("deleting a still active page directory\n");
106 #endif
107 
108 	if (are_interrupts_enabled())
109 		delete this;
110 	else
111 		deferred_delete(this);
112 }
113 
114 
115 /*static*/ void
116 X86PagingStructures32Bit::StaticInit()
117 {
118 	B_INITIALIZE_SPINLOCK(&sPagingStructuresListLock);
119 	new (&sPagingStructuresList) PagingStructuresList;
120 }
121 
122 
123 /*static*/ void
124 X86PagingStructures32Bit::UpdateAllPageDirs(int index,
125 	page_directory_entry entry)
126 {
127 	InterruptsSpinLocker locker(sPagingStructuresListLock);
128 
129 	PagingStructuresList::ConstIterator it = sPagingStructuresList.GetIterator();
130 	while (X86PagingStructures32Bit* info = it.Next())
131 		info->pgdir_virt[index] = entry;
132 }
133