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/040/M68KPagingStructures040.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// M68KPagingStructures040.
21struct PagingStructuresGetLink {
22private:
23	typedef SinglyLinkedListLink<M68KPagingStructures040> Link;
24
25public:
26	inline Link* operator()(M68KPagingStructures040* element) const
27	{
28		return (Link*)element->GetSinglyLinkedListLink();
29	}
30
31	inline const Link* operator()(
32		const M68KPagingStructures040* element) const
33	{
34		return (const Link*)element->GetSinglyLinkedListLink();
35	}
36};
37
38
39typedef SinglyLinkedList<M68KPagingStructures040, PagingStructuresGetLink>
40	PagingStructuresList;
41
42
43static PagingStructuresList sPagingStructuresList;
44static spinlock sPagingStructuresListLock;
45
46
47M68KPagingStructures040::M68KPagingStructures040()
48	:
49	pgroot_virt(NULL)
50{
51}
52
53
54M68KPagingStructures040::~M68KPagingStructures040()
55{
56	// free the page dir
57	free(pgroot_virt);
58}
59
60
61void
62M68KPagingStructures040::Init(page_root_entry* virtualPageRoot,
63	phys_addr_t physicalPageRoot, page_root_entry* kernelPageRoot)
64{
65	pgroot_virt = virtualPageRoot;
66	pgroot_phys = physicalPageRoot;
67
68	// zero out the bottom portion of the new pgroot
69	memset(pgroot_virt + FIRST_USER_PGROOT_ENT, 0,
70		NUM_USER_PGROOT_ENTS * sizeof(page_root_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 (kernelPageRoot != NULL) {
79			memcpy(pgroot_virt + FIRST_KERNEL_PGROOT_ENT,
80				kernelPageRoot + FIRST_KERNEL_PGROOT_ENT,
81				NUM_KERNEL_PGROOT_ENTS * sizeof(page_root_entry));
82		}
83
84		sPagingStructuresList.Add(this);
85
86		release_spinlock(&sPagingStructuresListLock);
87		restore_interrupts(state);
88	}
89}
90
91
92void
93M68KPagingStructures040::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;
104	read_cr3(activePageDirectory);
105	if (activePageDirectory == pgdir_phys)
106		panic("deleting a still active page directory\n");
107#endif
108
109	if (are_interrupts_enabled())
110		delete this;
111	else
112		deferred_delete(this);
113}
114
115
116/*static*/ void
117M68KPagingStructures040::StaticInit()
118{
119	B_INITIALIZE_SPINLOCK(&sPagingStructuresListLock);
120	new (&sPagingStructuresList) PagingStructuresList;
121}
122
123
124/*static*/ void
125M68KPagingStructures040::UpdateAllPageDirs(int index,
126	page_root_entry entry)
127{
128#warning M68K: TODO: allocate all kernel pgdirs at boot and remove this (also dont remove them anymore from unmap)
129#warning M68K:FIXME
130	InterruptsSpinLocker locker(sPagingStructuresListLock);
131
132	PagingStructuresList::Iterator it = sPagingStructuresList.GetIterator();
133	while (M68KPagingStructures040* info = it.Next())
134		info->pgroot_virt[index] = entry;
135}
136