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. 21struct PagingStructuresGetLink { 22private: 23 typedef SinglyLinkedListLink<ARMPagingStructures32Bit> Link; 24 25public: 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 39typedef SinglyLinkedList<ARMPagingStructures32Bit, PagingStructuresGetLink> 40 PagingStructuresList; 41 42 43static PagingStructuresList sPagingStructuresList; 44static spinlock sPagingStructuresListLock; 45 46 47ARMPagingStructures32Bit::ARMPagingStructures32Bit() 48 : 49 pgdir_virt(NULL) 50{ 51} 52 53 54ARMPagingStructures32Bit::~ARMPagingStructures32Bit() 55{ 56 // free the page dir 57 free(pgdir_virt); 58} 59 60 61void 62ARMPagingStructures32Bit::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 92void 93ARMPagingStructures32Bit::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 116ARMPagingStructures32Bit::StaticInit() 117{ 118 B_INITIALIZE_SPINLOCK(&sPagingStructuresListLock); 119 new (&sPagingStructuresList) PagingStructuresList; 120} 121 122 123/*static*/ void 124ARMPagingStructures32Bit::UpdateAllPageDirs(int index, 125 page_directory_entry entry) 126{ 127 InterruptsSpinLocker locker(sPagingStructuresListLock); 128 129 PagingStructuresList::Iterator it = sPagingStructuresList.GetIterator(); 130 while (ARMPagingStructures32Bit* info = it.Next()) 131 info->pgdir_virt[index] = entry; 132} 133