Support memory types in page mappings to the degree that is possible without

PAT support (i.e. uncacheable, write-through, and write-back). Has pretty
much no effect ATM, as the MTRRs restrict the types to what is actually
requested.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36583 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2010-05-02 15:30:52 +00:00
parent ed620d575c
commit f23be5bbed
2 changed files with 41 additions and 8 deletions

View File

@ -151,12 +151,44 @@ early_query(addr_t va, addr_t *_physicalAddress)
}
static inline uint32
memory_type_to_pte_flags(uint32 memoryType)
{
// ATM we only handle the uncacheable and write-through type explicitly. For
// all other types we rely on the MTRRs to be set up correctly. Since we set
// the default memory type to write-back and since the uncacheable type in
// the PTE overrides any MTRR attribute (though, as per the specs, that is
// not recommended for performance reasons), this reduces the work we
// actually *have* to do with the MTRRs to setting the remaining types
// (usually only write-combining for the frame buffer).
switch (memoryType) {
case B_MTR_UC:
return X86_PTE_CACHING_DISABLED;
case B_MTR_WC:
// X86_PTE_WRITE_THROUGH would be closer, but the combination with
// MTRR WC is "implementation defined" for Pentium [Pro].
return 0;
case B_MTR_WT:
return X86_PTE_WRITE_THROUGH;
case B_MTR_WP:
case B_MTR_WB:
default:
return 0;
}
}
static void
put_page_table_entry_in_pgtable(page_table_entry* entry,
addr_t physicalAddress, uint32 attributes, bool globalPage)
addr_t physicalAddress, uint32 attributes, uint32 memoryType,
bool globalPage)
{
page_table_entry page = (physicalAddress & X86_PTE_ADDRESS_MASK)
| X86_PTE_PRESENT | (globalPage ? X86_PTE_GLOBAL : 0);
| X86_PTE_PRESENT | (globalPage ? X86_PTE_GLOBAL : 0)
| memory_type_to_pte_flags(memoryType);
// if the page is user accessible, it's automatically
// accessible in kernel space, too (but with the same
@ -404,7 +436,6 @@ status_t
X86VMTranslationMap::Map(addr_t va, addr_t pa, uint32 attributes,
uint32 memoryType, vm_page_reservation* reservation)
{
// TODO: Support memory types!
TRACE("map_tmap: entry pa 0x%lx va 0x%lx\n", pa, va);
/*
@ -458,7 +489,7 @@ X86VMTranslationMap::Map(addr_t va, addr_t pa, uint32 attributes,
"virtual address: %#" B_PRIxADDR ", existing pte: %#" B_PRIx32, va,
pt[index]);
put_page_table_entry_in_pgtable(&pt[index], pa, attributes,
put_page_table_entry_in_pgtable(&pt[index], pa, attributes, memoryType,
IS_KERNEL_MAP(map));
pinner.Unlock();
@ -975,7 +1006,6 @@ status_t
X86VMTranslationMap::Protect(addr_t start, addr_t end, uint32 attributes,
uint32 memoryType)
{
// TODO: Support memory types!
page_directory_entry *pd = fArchData->pgdir_virt;
start = ROUNDDOWN(start, B_PAGE_SIZE);
@ -1026,8 +1056,8 @@ restart:
page_table_entry oldEntry;
while (true) {
oldEntry = test_and_set_page_table_entry(&pt[index],
(entry & ~(X86_PTE_WRITABLE | X86_PTE_USER))
| newProtectionFlags,
(entry & ~(X86_PTE_PROTECTION_MASK | X86_PTE_MEMORY_TYPE_MASK))
| newProtectionFlags | memory_type_to_pte_flags(memoryType),
entry);
if (oldEntry == entry)
break;
@ -1449,7 +1479,7 @@ arch_vm_translation_map_early_map(kernel_args *args, addr_t va, addr_t pa,
// now, fill in the pentry
put_page_table_entry_in_pgtable(sPageHole + va / B_PAGE_SIZE, pa,
attributes, IS_KERNEL_ADDRESS(va));
attributes, 0, IS_KERNEL_ADDRESS(va));
return B_OK;
}

View File

@ -54,6 +54,9 @@ class TranslationMapPhysicalPageMapper;
#define X86_PTE_IGNORED2 0x00000400
#define X86_PTE_IGNORED3 0x00000800
#define X86_PTE_ADDRESS_MASK 0xfffff000
#define X86_PTE_PROTECTION_MASK (X86_PTE_WRITABLE | X86_PTE_USER)
#define X86_PTE_MEMORY_TYPE_MASK (X86_PTE_WRITE_THROUGH \
| X86_PTE_CACHING_DISABLED)
typedef uint32 page_table_entry;