* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2002-2007, Axel DΓΆrfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include "paging/32bit/X86PagingStructures32Bit.h"
#include <stdlib.h>
#include <heap.h>
#include <util/AutoLock.h>
struct PagingStructuresGetLink {
private:
typedef SinglyLinkedListLink<X86PagingStructures32Bit> Link;
public:
inline Link* operator()(X86PagingStructures32Bit* element) const
{
return (Link*)element->GetSinglyLinkedListLink();
}
inline const Link* operator()(
const X86PagingStructures32Bit* element) const
{
return (const Link*)element->GetSinglyLinkedListLink();
}
};
typedef SinglyLinkedList<X86PagingStructures32Bit, PagingStructuresGetLink>
PagingStructuresList;
static PagingStructuresList sPagingStructuresList;
static spinlock sPagingStructuresListLock;
X86PagingStructures32Bit::X86PagingStructures32Bit()
:
pgdir_virt(NULL)
{
}
X86PagingStructures32Bit::~X86PagingStructures32Bit()
{
free(pgdir_virt);
}
void
X86PagingStructures32Bit::Init(page_directory_entry* virtualPageDir,
phys_addr_t physicalPageDir, page_directory_entry* kernelPageDir)
{
pgdir_virt = virtualPageDir;
pgdir_phys = physicalPageDir;
memset(pgdir_virt + FIRST_USER_PGDIR_ENT, 0,
NUM_USER_PGDIR_ENTS * sizeof(page_directory_entry));
{
int state = disable_interrupts();
acquire_spinlock(&sPagingStructuresListLock);
if (kernelPageDir != NULL) {
memcpy(pgdir_virt + FIRST_KERNEL_PGDIR_ENT,
kernelPageDir + FIRST_KERNEL_PGDIR_ENT,
NUM_KERNEL_PGDIR_ENTS * sizeof(page_directory_entry));
}
sPagingStructuresList.Add(this);
release_spinlock(&sPagingStructuresListLock);
restore_interrupts(state);
}
}
void
X86PagingStructures32Bit::Delete()
{
InterruptsSpinLocker locker(sPagingStructuresListLock);
sPagingStructuresList.Remove(this);
locker.Unlock();
#if 0
uint32 activePageDirectory = x86_read_cr3();
if (activePageDirectory == pgdir_phys)
panic("deleting a still active page directory\n");
#endif
if (are_interrupts_enabled())
delete this;
else
deferred_delete(this);
}
void
X86PagingStructures32Bit::StaticInit()
{
B_INITIALIZE_SPINLOCK(&sPagingStructuresListLock);
new (&sPagingStructuresList) PagingStructuresList;
}
void
X86PagingStructures32Bit::UpdateAllPageDirs(int index,
page_directory_entry entry)
{
InterruptsSpinLocker locker(sPagingStructuresListLock);
PagingStructuresList::ConstIterator it = sPagingStructuresList.GetIterator();
while (X86PagingStructures32Bit* info = it.Next())
info->pgdir_virt[index] = entry;
}