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