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