Unmap(),Protect(): Removed goto programming by a do {} while loop. Also fixed
problem with potential integer overflow at the end of the address space. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37190 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -211,57 +211,53 @@ X86VMTranslationMap32Bit::Map(addr_t va, phys_addr_t pa, uint32 attributes,
|
|||||||
status_t
|
status_t
|
||||||
X86VMTranslationMap32Bit::Unmap(addr_t start, addr_t end)
|
X86VMTranslationMap32Bit::Unmap(addr_t start, addr_t end)
|
||||||
{
|
{
|
||||||
page_directory_entry *pd = fPagingStructures->pgdir_virt;
|
|
||||||
|
|
||||||
start = ROUNDDOWN(start, B_PAGE_SIZE);
|
start = ROUNDDOWN(start, B_PAGE_SIZE);
|
||||||
end = ROUNDUP(end, B_PAGE_SIZE);
|
|
||||||
|
|
||||||
TRACE("unmap_tmap: asked to free pages 0x%lx to 0x%lx\n", start, end);
|
|
||||||
|
|
||||||
restart:
|
|
||||||
if (start >= end)
|
if (start >= end)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
int index = VADDR_TO_PDENT(start);
|
TRACE("unmap_tmap: asked to free pages 0x%lx to 0x%lx\n", start, end);
|
||||||
if ((pd[index] & X86_PDE_PRESENT) == 0) {
|
|
||||||
// no pagetable here, move the start up to access the next page table
|
|
||||||
start = ROUNDUP(start + 1, B_PAGE_SIZE * 1024);
|
|
||||||
if (start == 0)
|
|
||||||
return B_OK;
|
|
||||||
goto restart;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct thread* thread = thread_get_current_thread();
|
page_directory_entry *pd = fPagingStructures->pgdir_virt;
|
||||||
ThreadCPUPinner pinner(thread);
|
|
||||||
|
|
||||||
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
do {
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
int index = VADDR_TO_PDENT(start);
|
||||||
|
if ((pd[index] & X86_PDE_PRESENT) == 0) {
|
||||||
for (index = VADDR_TO_PTENT(start); (index < 1024) && (start < end);
|
// no page table here, move the start up to access the next page
|
||||||
index++, start += B_PAGE_SIZE) {
|
// table
|
||||||
if ((pt[index] & X86_PTE_PRESENT) == 0) {
|
start = ROUNDUP(start + 1, kPageTableAlignment);
|
||||||
// page mapping not valid
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("unmap_tmap: removing page 0x%lx\n", start);
|
struct thread* thread = thread_get_current_thread();
|
||||||
|
ThreadCPUPinner pinner(thread);
|
||||||
|
|
||||||
page_table_entry oldEntry
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
= X86PagingMethod32Bit::ClearPageTableEntryFlags(&pt[index],
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
X86_PTE_PRESENT);
|
|
||||||
fMapCount--;
|
|
||||||
|
|
||||||
if ((oldEntry & X86_PTE_ACCESSED) != 0) {
|
for (index = VADDR_TO_PTENT(start); (index < 1024) && (start < end);
|
||||||
// Note, that we only need to invalidate the address, if the
|
index++, start += B_PAGE_SIZE) {
|
||||||
// accessed flags was set, since only then the entry could have been
|
if ((pt[index] & X86_PTE_PRESENT) == 0) {
|
||||||
// in any TLB.
|
// page mapping not valid
|
||||||
InvalidatePage(start);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("unmap_tmap: removing page 0x%lx\n", start);
|
||||||
|
|
||||||
|
page_table_entry oldEntry
|
||||||
|
= X86PagingMethod32Bit::ClearPageTableEntryFlags(&pt[index],
|
||||||
|
X86_PTE_PRESENT);
|
||||||
|
fMapCount--;
|
||||||
|
|
||||||
|
if ((oldEntry & X86_PTE_ACCESSED) != 0) {
|
||||||
|
// Note, that we only need to invalidate the address, if the
|
||||||
|
// accessed flags was set, since only then the entry could have
|
||||||
|
// been in any TLB.
|
||||||
|
InvalidatePage(start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} while (start != 0 && start < end);
|
||||||
|
|
||||||
pinner.Unlock();
|
return B_OK;
|
||||||
|
|
||||||
goto restart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -641,9 +637,9 @@ status_t
|
|||||||
X86VMTranslationMap32Bit::Protect(addr_t start, addr_t end, uint32 attributes,
|
X86VMTranslationMap32Bit::Protect(addr_t start, addr_t end, uint32 attributes,
|
||||||
uint32 memoryType)
|
uint32 memoryType)
|
||||||
{
|
{
|
||||||
page_directory_entry *pd = fPagingStructures->pgdir_virt;
|
|
||||||
|
|
||||||
start = ROUNDDOWN(start, B_PAGE_SIZE);
|
start = ROUNDDOWN(start, B_PAGE_SIZE);
|
||||||
|
if (start >= end)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
TRACE("protect_tmap: pages 0x%lx to 0x%lx, attributes %lx\n", start, end,
|
TRACE("protect_tmap: pages 0x%lx to 0x%lx, attributes %lx\n", start, end,
|
||||||
attributes);
|
attributes);
|
||||||
@@ -657,62 +653,60 @@ X86VMTranslationMap32Bit::Protect(addr_t start, addr_t end, uint32 attributes,
|
|||||||
} else if ((attributes & B_KERNEL_WRITE_AREA) != 0)
|
} else if ((attributes & B_KERNEL_WRITE_AREA) != 0)
|
||||||
newProtectionFlags = X86_PTE_WRITABLE;
|
newProtectionFlags = X86_PTE_WRITABLE;
|
||||||
|
|
||||||
restart:
|
page_directory_entry *pd = fPagingStructures->pgdir_virt;
|
||||||
if (start >= end)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
int index = VADDR_TO_PDENT(start);
|
do {
|
||||||
if ((pd[index] & X86_PDE_PRESENT) == 0) {
|
int index = VADDR_TO_PDENT(start);
|
||||||
// no pagetable here, move the start up to access the next page table
|
if ((pd[index] & X86_PDE_PRESENT) == 0) {
|
||||||
start = ROUNDUP(start + 1, B_PAGE_SIZE * 1024);
|
// no page table here, move the start up to access the next page
|
||||||
if (start == 0)
|
// table
|
||||||
return B_OK;
|
start = ROUNDUP(start + 1, kPageTableAlignment);
|
||||||
goto restart;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct thread* thread = thread_get_current_thread();
|
|
||||||
ThreadCPUPinner pinner(thread);
|
|
||||||
|
|
||||||
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
|
||||||
pd[index] & X86_PDE_ADDRESS_MASK);
|
|
||||||
|
|
||||||
for (index = VADDR_TO_PTENT(start); index < 1024 && start < end;
|
|
||||||
index++, start += B_PAGE_SIZE) {
|
|
||||||
page_table_entry entry = pt[index];
|
|
||||||
if ((entry & X86_PTE_PRESENT) == 0) {
|
|
||||||
// page mapping not valid
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("protect_tmap: protect page 0x%lx\n", start);
|
struct thread* thread = thread_get_current_thread();
|
||||||
|
ThreadCPUPinner pinner(thread);
|
||||||
|
|
||||||
// set the new protection flags -- we want to do that atomically,
|
page_table_entry* pt = (page_table_entry*)fPageMapper->GetPageTableAt(
|
||||||
// without changing the accessed or dirty flag
|
pd[index] & X86_PDE_ADDRESS_MASK);
|
||||||
page_table_entry oldEntry;
|
|
||||||
while (true) {
|
for (index = VADDR_TO_PTENT(start); index < 1024 && start < end;
|
||||||
oldEntry = X86PagingMethod32Bit::TestAndSetPageTableEntry(
|
index++, start += B_PAGE_SIZE) {
|
||||||
&pt[index],
|
page_table_entry entry = pt[index];
|
||||||
(entry & ~(X86_PTE_PROTECTION_MASK | X86_PTE_MEMORY_TYPE_MASK))
|
if ((entry & X86_PTE_PRESENT) == 0) {
|
||||||
| newProtectionFlags
|
// page mapping not valid
|
||||||
| X86PagingMethod32Bit::MemoryTypeToPageTableEntryFlags(
|
continue;
|
||||||
memoryType),
|
}
|
||||||
entry);
|
|
||||||
if (oldEntry == entry)
|
TRACE("protect_tmap: protect page 0x%lx\n", start);
|
||||||
break;
|
|
||||||
entry = oldEntry;
|
// set the new protection flags -- we want to do that atomically,
|
||||||
|
// without changing the accessed or dirty flag
|
||||||
|
page_table_entry oldEntry;
|
||||||
|
while (true) {
|
||||||
|
oldEntry = X86PagingMethod32Bit::TestAndSetPageTableEntry(
|
||||||
|
&pt[index],
|
||||||
|
(entry & ~(X86_PTE_PROTECTION_MASK
|
||||||
|
| X86_PTE_MEMORY_TYPE_MASK))
|
||||||
|
| newProtectionFlags
|
||||||
|
| X86PagingMethod32Bit::MemoryTypeToPageTableEntryFlags(
|
||||||
|
memoryType),
|
||||||
|
entry);
|
||||||
|
if (oldEntry == entry)
|
||||||
|
break;
|
||||||
|
entry = oldEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((oldEntry & X86_PTE_ACCESSED) != 0) {
|
||||||
|
// Note, that we only need to invalidate the address, if the
|
||||||
|
// accessed flag was set, since only then the entry could have
|
||||||
|
// been in any TLB.
|
||||||
|
InvalidatePage(start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} while (start != 0 && start < end);
|
||||||
|
|
||||||
if ((oldEntry & X86_PTE_ACCESSED) != 0) {
|
return B_OK;
|
||||||
// Note, that we only need to invalidate the address, if the
|
|
||||||
// accessed flag was set, since only then the entry could have been
|
|
||||||
// in any TLB.
|
|
||||||
InvalidatePage(start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pinner.Unlock();
|
|
||||||
|
|
||||||
goto restart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user