xref: /haiku/src/system/kernel/arch/arm/paging/32bit/ARMPagingStructures32Bit.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
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/ARMPagingStructures32Bit.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 // ARMPagingStructures32Bit.
21 struct PagingStructuresGetLink {
22 private:
23 	typedef SinglyLinkedListLink<ARMPagingStructures32Bit> Link;
24 
25 public:
26 	inline Link* operator()(ARMPagingStructures32Bit* element) const
27 	{
28 		return (Link*)element->GetSinglyLinkedListLink();
29 	}
30 
31 	inline const Link* operator()(
32 		const ARMPagingStructures32Bit* element) const
33 	{
34 		return (const Link*)element->GetSinglyLinkedListLink();
35 	}
36 };
37 
38 
39 typedef SinglyLinkedList<ARMPagingStructures32Bit, PagingStructuresGetLink>
40 	PagingStructuresList;
41 
42 
43 static PagingStructuresList sPagingStructuresList;
44 static spinlock sPagingStructuresListLock;
45 
46 
47 ARMPagingStructures32Bit::ARMPagingStructures32Bit()
48 	:
49 	pgdir_virt(NULL)
50 {
51 }
52 
53 
54 ARMPagingStructures32Bit::~ARMPagingStructures32Bit()
55 {
56 	// free the page dir
57 	free(pgdir_virt);
58 }
59 
60 
61 void
62 ARMPagingStructures32Bit::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 #if 0 // IRA: handle UART better; identity map of DEVICE_BASE from loader gets wiped here
69 	// zero out the bottom portion of the new pgdir
70 	memset(pgdir_virt + FIRST_USER_PGDIR_ENT, 0,
71 		NUM_USER_PGDIR_ENTS * sizeof(page_directory_entry));
72 #endif
73 	// insert this new map into the map list
74 	{
75 		int state = disable_interrupts();
76 		acquire_spinlock(&sPagingStructuresListLock);
77 
78 		// copy the top portion of the page dir from the kernel page dir
79 		if (kernelPageDir != NULL) {
80 			memcpy(pgdir_virt + FIRST_KERNEL_PGDIR_ENT,
81 				kernelPageDir + FIRST_KERNEL_PGDIR_ENT,
82 				NUM_KERNEL_PGDIR_ENTS * sizeof(page_directory_entry));
83 		}
84 
85 		sPagingStructuresList.Add(this);
86 
87 		release_spinlock(&sPagingStructuresListLock);
88 		restore_interrupts(state);
89 	}
90 }
91 
92 
93 void
94 ARMPagingStructures32Bit::Delete()
95 {
96 	// remove from global list
97 	InterruptsSpinLocker locker(sPagingStructuresListLock);
98 	sPagingStructuresList.Remove(this);
99 	locker.Unlock();
100 
101 #if 0
102 	// this sanity check can be enabled when corruption due to
103 	// overwriting an active page directory is suspected
104 	uint32 activePageDirectory;
105 	read_cr3(activePageDirectory);
106 	if (activePageDirectory == pgdir_phys)
107 		panic("deleting a still active page directory\n");
108 #endif
109 
110 	if (are_interrupts_enabled())
111 		delete this;
112 	else
113 		deferred_delete(this);
114 }
115 
116 
117 /*static*/ void
118 ARMPagingStructures32Bit::StaticInit()
119 {
120 	B_INITIALIZE_SPINLOCK(&sPagingStructuresListLock);
121 	new (&sPagingStructuresList) PagingStructuresList;
122 }
123 
124 
125 /*static*/ void
126 ARMPagingStructures32Bit::UpdateAllPageDirs(int index,
127 	page_directory_entry entry)
128 {
129 	InterruptsSpinLocker locker(sPagingStructuresListLock);
130 
131 	PagingStructuresList::Iterator it = sPagingStructuresList.GetIterator();
132 	while (ARMPagingStructures32Bit* info = it.Next())
133 		info->pgdir_virt[index] = entry;
134 }
135