X86VMTranslationMapPAE: Extend kernel tracing

* Beside the physical address also print the PTE flags.
* Also trace Protect(), ClearFlags(), ClearAccessedAndModified().
This commit is contained in:
Ingo Weinhold
2013-12-07 15:44:22 +01:00
parent 3c70914f66
commit 0a4cbd786c
@@ -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();