X86VMTranslationMapPAE: Extend kernel tracing
* Beside the physical address also print the PTE flags. * Also trace Protect(), ClearFlags(), ClearAccessedAndModified().
This commit is contained in:
@@ -41,67 +41,68 @@
|
|||||||
namespace TranslationMapTracing {
|
namespace TranslationMapTracing {
|
||||||
|
|
||||||
|
|
||||||
class TraceEntryBase : public AbstractTraceEntry {
|
class TranslationMapTraceEntryBase
|
||||||
|
: public TRACE_ENTRY_SELECTOR(TRANSLATION_MAP_TRACING_STACK_TRACE) {
|
||||||
public:
|
public:
|
||||||
TraceEntryBase()
|
TranslationMapTraceEntryBase()
|
||||||
|
:
|
||||||
|
TraceEntryBase(TRANSLATION_MAP_TRACING_STACK_TRACE, 0, true)
|
||||||
{
|
{
|
||||||
#if TRANSLATION_MAP_TRACING_STACK_TRACE
|
|
||||||
fStackTrace = capture_tracing_stack_trace(
|
|
||||||
TRANSLATION_MAP_TRACING_STACK_TRACE, 0, true);
|
|
||||||
// Don't capture userland stack trace to avoid potential
|
|
||||||
// deadlocks.
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TRANSLATION_MAP_TRACING_STACK_TRACE
|
void PrintPageTableEntry(TraceOutput& out, pae_page_table_entry entry)
|
||||||
virtual void DumpStackTrace(TraceOutput& out)
|
|
||||||
{
|
{
|
||||||
out.PrintStackTrace(fStackTrace);
|
out.Print("%#" B_PRIx64 " %c%c%c%c%c %s %s %c%c",
|
||||||
|
entry & X86_PAE_PTE_ADDRESS_MASK,
|
||||||
|
(entry & X86_PAE_PTE_PRESENT) != 0 ? 'P' : '-',
|
||||||
|
(entry & X86_PAE_PTE_WRITABLE) != 0 ? 'W' : '-',
|
||||||
|
(entry & X86_PAE_PTE_USER) != 0 ? 'U' : '-',
|
||||||
|
(entry & X86_PAE_PTE_NOT_EXECUTABLE) != 0 ? '-' : 'X',
|
||||||
|
(entry & X86_PAE_PTE_GLOBAL) != 0 ? 'G' : '-',
|
||||||
|
(entry & X86_PAE_PTE_WRITE_THROUGH) != 0 ? "WT" : "--",
|
||||||
|
(entry & X86_PAE_PTE_CACHING_DISABLED) != 0 ? "UC" : "--",
|
||||||
|
(entry & X86_PAE_PTE_ACCESSED) != 0 ? 'A' : '-',
|
||||||
|
(entry & X86_PAE_PTE_DIRTY) != 0 ? 'D' : '-');
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
#if TRANSLATION_MAP_TRACING_STACK_TRACE
|
|
||||||
tracing_stack_trace* fStackTrace;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Map : public TraceEntryBase {
|
class Map : public TranslationMapTraceEntryBase {
|
||||||
public:
|
public:
|
||||||
Map(X86VMTranslationMapPAE* map, addr_t virtualAddress,
|
Map(X86VMTranslationMapPAE* map, addr_t virtualAddress,
|
||||||
phys_addr_t physicalAddress)
|
pae_page_table_entry entry)
|
||||||
:
|
:
|
||||||
TraceEntryBase(),
|
TranslationMapTraceEntryBase(),
|
||||||
fMap(map),
|
fMap(map),
|
||||||
fVirtualAddress(virtualAddress),
|
fVirtualAddress(virtualAddress),
|
||||||
fPhysicalAddress(physicalAddress)
|
fEntry(entry)
|
||||||
{
|
{
|
||||||
Initialized();
|
Initialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void AddDump(TraceOutput& out)
|
virtual void AddDump(TraceOutput& out)
|
||||||
{
|
{
|
||||||
out.Print("translation map map: %p: %#" B_PRIxADDR
|
out.Print("translation map map: %p: %#" B_PRIxADDR " -> ", fMap,
|
||||||
" -> %#" B_PRIxPHYSADDR, fMap, fVirtualAddress, fPhysicalAddress);
|
fVirtualAddress);
|
||||||
|
PrintPageTableEntry(out, fEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
X86VMTranslationMapPAE* fMap;
|
X86VMTranslationMapPAE* fMap;
|
||||||
addr_t fVirtualAddress;
|
addr_t fVirtualAddress;
|
||||||
phys_addr_t fPhysicalAddress;
|
pae_page_table_entry fEntry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Unmap : public TraceEntryBase {
|
class Unmap : public TranslationMapTraceEntryBase {
|
||||||
public:
|
public:
|
||||||
Unmap(X86VMTranslationMapPAE* map, addr_t virtualAddress,
|
Unmap(X86VMTranslationMapPAE* map, addr_t virtualAddress,
|
||||||
phys_addr_t physicalAddress)
|
pae_page_table_entry entry)
|
||||||
:
|
:
|
||||||
TraceEntryBase(),
|
TranslationMapTraceEntryBase(),
|
||||||
fMap(map),
|
fMap(map),
|
||||||
fVirtualAddress(virtualAddress),
|
fVirtualAddress(virtualAddress),
|
||||||
fPhysicalAddress(physicalAddress)
|
fEntry(entry)
|
||||||
{
|
{
|
||||||
Initialized();
|
Initialized();
|
||||||
}
|
}
|
||||||
@@ -109,13 +110,108 @@ public:
|
|||||||
virtual void AddDump(TraceOutput& out)
|
virtual void AddDump(TraceOutput& out)
|
||||||
{
|
{
|
||||||
out.Print("translation map unmap: %p: %#" B_PRIxADDR
|
out.Print("translation map unmap: %p: %#" B_PRIxADDR
|
||||||
" -> %#" B_PRIxPHYSADDR, fMap, fVirtualAddress, fPhysicalAddress);
|
" -> ", fMap, fVirtualAddress);
|
||||||
|
PrintPageTableEntry(out, fEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
X86VMTranslationMapPAE* fMap;
|
X86VMTranslationMapPAE* fMap;
|
||||||
addr_t fVirtualAddress;
|
addr_t fVirtualAddress;
|
||||||
phys_addr_t fPhysicalAddress;
|
pae_page_table_entry fEntry;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Protect : public TranslationMapTraceEntryBase {
|
||||||
|
public:
|
||||||
|
Protect(X86VMTranslationMapPAE* map, addr_t virtualAddress,
|
||||||
|
pae_page_table_entry oldEntry, pae_page_table_entry newEntry)
|
||||||
|
:
|
||||||
|
TranslationMapTraceEntryBase(),
|
||||||
|
fMap(map),
|
||||||
|
fVirtualAddress(virtualAddress),
|
||||||
|
fOldEntry(oldEntry),
|
||||||
|
fNewEntry(newEntry)
|
||||||
|
{
|
||||||
|
Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddDump(TraceOutput& out)
|
||||||
|
{
|
||||||
|
out.Print("translation map protect: %p: %#" B_PRIxADDR
|
||||||
|
" -> ", fMap, fVirtualAddress);
|
||||||
|
PrintPageTableEntry(out, fNewEntry);
|
||||||
|
out.Print(" (%c%c%c)",
|
||||||
|
(fOldEntry & X86_PAE_PTE_WRITABLE) != 0 ? 'W' : '-',
|
||||||
|
(fOldEntry & X86_PAE_PTE_USER) != 0 ? 'U' : '-',
|
||||||
|
(fOldEntry & X86_PAE_PTE_NOT_EXECUTABLE) != 0 ? '-' : 'X');
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
X86VMTranslationMapPAE* fMap;
|
||||||
|
addr_t fVirtualAddress;
|
||||||
|
pae_page_table_entry fOldEntry;
|
||||||
|
pae_page_table_entry fNewEntry;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ClearFlags : public TranslationMapTraceEntryBase {
|
||||||
|
public:
|
||||||
|
ClearFlags(X86VMTranslationMapPAE* map, addr_t virtualAddress,
|
||||||
|
pae_page_table_entry oldEntry, pae_page_table_entry flagsCleared)
|
||||||
|
:
|
||||||
|
TranslationMapTraceEntryBase(),
|
||||||
|
fMap(map),
|
||||||
|
fVirtualAddress(virtualAddress),
|
||||||
|
fOldEntry(oldEntry),
|
||||||
|
fFlagsCleared(flagsCleared)
|
||||||
|
{
|
||||||
|
Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddDump(TraceOutput& out)
|
||||||
|
{
|
||||||
|
out.Print("translation map clear flags: %p: %#" B_PRIxADDR
|
||||||
|
" -> ", fMap, fVirtualAddress);
|
||||||
|
PrintPageTableEntry(out, fOldEntry & ~fFlagsCleared);
|
||||||
|
out.Print(", cleared %c%c (%c%c)",
|
||||||
|
(fOldEntry & fFlagsCleared & X86_PAE_PTE_ACCESSED) != 0 ? 'A' : '-',
|
||||||
|
(fOldEntry & fFlagsCleared & X86_PAE_PTE_DIRTY) != 0 ? 'D' : '-',
|
||||||
|
(fFlagsCleared & X86_PAE_PTE_ACCESSED) != 0 ? 'A' : '-',
|
||||||
|
(fFlagsCleared & X86_PAE_PTE_DIRTY) != 0 ? 'D' : '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
X86VMTranslationMapPAE* fMap;
|
||||||
|
addr_t fVirtualAddress;
|
||||||
|
pae_page_table_entry fOldEntry;
|
||||||
|
pae_page_table_entry fFlagsCleared;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ClearFlagsUnmap : public TranslationMapTraceEntryBase {
|
||||||
|
public:
|
||||||
|
ClearFlagsUnmap(X86VMTranslationMapPAE* map, addr_t virtualAddress,
|
||||||
|
pae_page_table_entry entry)
|
||||||
|
:
|
||||||
|
TranslationMapTraceEntryBase(),
|
||||||
|
fMap(map),
|
||||||
|
fVirtualAddress(virtualAddress),
|
||||||
|
fEntry(entry)
|
||||||
|
{
|
||||||
|
Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddDump(TraceOutput& out)
|
||||||
|
{
|
||||||
|
out.Print("translation map clear flags unmap: %p: %#" B_PRIxADDR
|
||||||
|
" -> ", fMap, fVirtualAddress);
|
||||||
|
PrintPageTableEntry(out, fEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
X86VMTranslationMapPAE* fMap;
|
||||||
|
addr_t fVirtualAddress;
|
||||||
|
pae_page_table_entry fEntry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -283,7 +379,6 @@ X86VMTranslationMapPAE::Map(addr_t virtualAddress, phys_addr_t physicalAddress,
|
|||||||
{
|
{
|
||||||
TRACE("X86VMTranslationMapPAE::Map(): %#" B_PRIxADDR " -> %#" B_PRIxPHYSADDR
|
TRACE("X86VMTranslationMapPAE::Map(): %#" B_PRIxADDR " -> %#" B_PRIxPHYSADDR
|
||||||
"\n", virtualAddress, physicalAddress);
|
"\n", virtualAddress, physicalAddress);
|
||||||
T(Map(this, virtualAddress, physicalAddress));
|
|
||||||
|
|
||||||
// check to see if a page table exists for this range
|
// check to see if a page table exists for this range
|
||||||
pae_page_directory_entry* pageDirEntry
|
pae_page_directory_entry* pageDirEntry
|
||||||
@@ -329,6 +424,8 @@ X86VMTranslationMapPAE::Map(addr_t virtualAddress, phys_addr_t physicalAddress,
|
|||||||
X86PagingMethodPAE::PutPageTableEntryInTable(entry, physicalAddress,
|
X86PagingMethodPAE::PutPageTableEntryInTable(entry, physicalAddress,
|
||||||
attributes, memoryType, fIsKernelMap);
|
attributes, memoryType, fIsKernelMap);
|
||||||
|
|
||||||
|
T(Map(this, virtualAddress, *entry));
|
||||||
|
|
||||||
pinner.Unlock();
|
pinner.Unlock();
|
||||||
|
|
||||||
// Note: We don't need to invalidate the TLB for this address, as previously
|
// Note: We don't need to invalidate the TLB for this address, as previously
|
||||||
@@ -383,7 +480,7 @@ X86VMTranslationMapPAE::Unmap(addr_t start, addr_t end)
|
|||||||
= X86PagingMethodPAE::ClearPageTableEntryFlags(
|
= X86PagingMethodPAE::ClearPageTableEntryFlags(
|
||||||
&pageTable[index], X86_PAE_PTE_PRESENT);
|
&pageTable[index], X86_PAE_PTE_PRESENT);
|
||||||
|
|
||||||
T(Unmap(this, start, oldEntry & X86_PAE_PDE_ADDRESS_MASK));
|
T(Unmap(this, start, oldEntry));
|
||||||
|
|
||||||
fMapCount--;
|
fMapCount--;
|
||||||
|
|
||||||
@@ -487,7 +584,7 @@ X86VMTranslationMapPAE::UnmapPage(VMArea* area, addr_t address,
|
|||||||
pae_page_table_entry oldEntry = X86PagingMethodPAE::ClearPageTableEntry(
|
pae_page_table_entry oldEntry = X86PagingMethodPAE::ClearPageTableEntry(
|
||||||
&pageTable[address / B_PAGE_SIZE % kPAEPageTableEntryCount]);
|
&pageTable[address / B_PAGE_SIZE % kPAEPageTableEntryCount]);
|
||||||
|
|
||||||
T(Unmap(this, address, oldEntry & X86_PAE_PDE_ADDRESS_MASK));
|
T(Unmap(this, address, oldEntry));
|
||||||
|
|
||||||
pinner.Unlock();
|
pinner.Unlock();
|
||||||
|
|
||||||
@@ -572,7 +669,7 @@ X86VMTranslationMapPAE::UnmapPages(VMArea* area, addr_t base, size_t size,
|
|||||||
if ((oldEntry & X86_PAE_PTE_PRESENT) == 0)
|
if ((oldEntry & X86_PAE_PTE_PRESENT) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
T(Unmap(this, start, oldEntry & X86_PAE_PDE_ADDRESS_MASK));
|
T(Unmap(this, start, oldEntry));
|
||||||
|
|
||||||
fMapCount--;
|
fMapCount--;
|
||||||
|
|
||||||
@@ -714,7 +811,7 @@ X86VMTranslationMapPAE::UnmapArea(VMArea* area, bool deletingAddressSpace,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
T(Unmap(this, address, oldEntry & X86_PAE_PDE_ADDRESS_MASK));
|
T(Unmap(this, address, oldEntry));
|
||||||
|
|
||||||
// transfer the accessed/dirty flags to the page and invalidate
|
// transfer the accessed/dirty flags to the page and invalidate
|
||||||
// the mapping, if necessary
|
// the mapping, if necessary
|
||||||
@@ -759,10 +856,8 @@ X86VMTranslationMapPAE::UnmapArea(VMArea* area, bool deletingAddressSpace,
|
|||||||
|
|
||||||
pinner.Unlock();
|
pinner.Unlock();
|
||||||
|
|
||||||
if ((oldEntry & X86_PAE_PTE_PRESENT) != 0) {
|
if ((oldEntry & X86_PAE_PTE_PRESENT) != 0)
|
||||||
T(Unmap(this, address,
|
T(Unmap(this, address, oldEntry));
|
||||||
oldEntry & X86_PAE_PDE_ADDRESS_MASK));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -896,18 +991,19 @@ X86VMTranslationMapPAE::Protect(addr_t start, addr_t end, uint32 attributes,
|
|||||||
TRACE("X86VMTranslationMapPAE::Protect(): %#" B_PRIxADDR " - %#" B_PRIxADDR
|
TRACE("X86VMTranslationMapPAE::Protect(): %#" B_PRIxADDR " - %#" B_PRIxADDR
|
||||||
", attributes: %#" B_PRIx32 "\n", start, end, attributes);
|
", attributes: %#" B_PRIx32 "\n", start, end, attributes);
|
||||||
|
|
||||||
// compute protection flags
|
// compute protection/memory type flags
|
||||||
uint64 newProtectionFlags = 0;
|
uint64 newFlags
|
||||||
|
= X86PagingMethodPAE::MemoryTypeToPageTableEntryFlags(memoryType);
|
||||||
if ((attributes & B_USER_PROTECTION) != 0) {
|
if ((attributes & B_USER_PROTECTION) != 0) {
|
||||||
newProtectionFlags = X86_PAE_PTE_USER;
|
newFlags |= X86_PAE_PTE_USER;
|
||||||
if ((attributes & B_WRITE_AREA) != 0)
|
if ((attributes & B_WRITE_AREA) != 0)
|
||||||
newProtectionFlags |= X86_PAE_PTE_WRITABLE;
|
newFlags |= X86_PAE_PTE_WRITABLE;
|
||||||
if ((attributes & B_EXECUTE_AREA) == 0
|
if ((attributes & B_EXECUTE_AREA) == 0
|
||||||
&& x86_check_feature(IA32_FEATURE_AMD_EXT_NX, FEATURE_EXT_AMD)) {
|
&& x86_check_feature(IA32_FEATURE_AMD_EXT_NX, FEATURE_EXT_AMD)) {
|
||||||
newProtectionFlags |= X86_PAE_PTE_NOT_EXECUTABLE;
|
newFlags |= X86_PAE_PTE_NOT_EXECUTABLE;
|
||||||
}
|
}
|
||||||
} else if ((attributes & B_KERNEL_WRITE_AREA) != 0)
|
} else if ((attributes & B_KERNEL_WRITE_AREA) != 0)
|
||||||
newProtectionFlags = X86_PAE_PTE_WRITABLE;
|
newFlags |= X86_PAE_PTE_WRITABLE;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
pae_page_directory_entry* pageDirEntry
|
pae_page_directory_entry* pageDirEntry
|
||||||
@@ -947,15 +1043,18 @@ X86VMTranslationMapPAE::Protect(addr_t start, addr_t end, uint32 attributes,
|
|||||||
&pageTable[index],
|
&pageTable[index],
|
||||||
(entry & ~(X86_PAE_PTE_PROTECTION_MASK
|
(entry & ~(X86_PAE_PTE_PROTECTION_MASK
|
||||||
| X86_PAE_PTE_MEMORY_TYPE_MASK))
|
| X86_PAE_PTE_MEMORY_TYPE_MASK))
|
||||||
| newProtectionFlags
|
| newFlags,
|
||||||
| X86PagingMethodPAE::MemoryTypeToPageTableEntryFlags(
|
|
||||||
memoryType),
|
|
||||||
entry);
|
entry);
|
||||||
if (oldEntry == entry)
|
if (oldEntry == entry)
|
||||||
break;
|
break;
|
||||||
entry = oldEntry;
|
entry = oldEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T(Protect(this, start, entry,
|
||||||
|
(entry & ~(X86_PAE_PTE_PROTECTION_MASK
|
||||||
|
| X86_PAE_PTE_MEMORY_TYPE_MASK))
|
||||||
|
| newFlags));
|
||||||
|
|
||||||
if ((oldEntry & X86_PAE_PTE_ACCESSED) != 0) {
|
if ((oldEntry & X86_PAE_PTE_ACCESSED) != 0) {
|
||||||
// Note, that we only need to invalidate the address, if the
|
// Note, that we only need to invalidate the address, if the
|
||||||
// accessed flag was set, since only then the entry could have been
|
// accessed flag was set, since only then the entry could have been
|
||||||
@@ -997,6 +1096,8 @@ X86VMTranslationMapPAE::ClearFlags(addr_t address, uint32 flags)
|
|||||||
|
|
||||||
pinner.Unlock();
|
pinner.Unlock();
|
||||||
|
|
||||||
|
T(ClearFlags(this, address, oldEntry, flagsToClear));
|
||||||
|
|
||||||
if ((oldEntry & flagsToClear) != 0)
|
if ((oldEntry & flagsToClear) != 0)
|
||||||
InvalidatePage(address);
|
InvalidatePage(address);
|
||||||
|
|
||||||
@@ -1044,12 +1145,15 @@ X86VMTranslationMapPAE::ClearAccessedAndModified(VMArea* area, addr_t address,
|
|||||||
// page was accessed -- just clear the flags
|
// page was accessed -- just clear the flags
|
||||||
oldEntry = X86PagingMethodPAE::ClearPageTableEntryFlags(entry,
|
oldEntry = X86PagingMethodPAE::ClearPageTableEntryFlags(entry,
|
||||||
X86_PAE_PTE_ACCESSED | X86_PAE_PTE_DIRTY);
|
X86_PAE_PTE_ACCESSED | X86_PAE_PTE_DIRTY);
|
||||||
|
T(ClearFlags(this, address, oldEntry,
|
||||||
|
X86_PAE_PTE_ACCESSED | X86_PAE_PTE_DIRTY));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// page hasn't been accessed -- unmap it
|
// page hasn't been accessed -- unmap it
|
||||||
if (X86PagingMethodPAE::TestAndSetPageTableEntry(entry, 0, oldEntry)
|
if (X86PagingMethodPAE::TestAndSetPageTableEntry(entry, 0, oldEntry)
|
||||||
== oldEntry) {
|
== oldEntry) {
|
||||||
|
T(ClearFlagsUnmap(this, address, oldEntry));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1058,6 +1162,8 @@ X86VMTranslationMapPAE::ClearAccessedAndModified(VMArea* area, addr_t address,
|
|||||||
} else {
|
} else {
|
||||||
oldEntry = X86PagingMethodPAE::ClearPageTableEntryFlags(entry,
|
oldEntry = X86PagingMethodPAE::ClearPageTableEntryFlags(entry,
|
||||||
X86_PAE_PTE_ACCESSED | X86_PAE_PTE_DIRTY);
|
X86_PAE_PTE_ACCESSED | X86_PAE_PTE_DIRTY);
|
||||||
|
T(ClearFlags(this, address, oldEntry,
|
||||||
|
X86_PAE_PTE_ACCESSED | X86_PAE_PTE_DIRTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
pinner.Unlock();
|
pinner.Unlock();
|
||||||
|
|||||||
Reference in New Issue
Block a user