Lowlevel
Lowlevel => OS-Design => Thema gestartet von: SHyx0rmZ am 14. February 2010, 13:36
-
Nun, ich hänge mal wieder beim Paging fest, das Problem ist folgendes:
Wenn eine neue Page gemappt werden soll, die dafür nötigen, höheren Level in der Pagingstruktur aber noch nicht vorhanden sind, werden diese zwar erstellt, müssen aber noch gemappt werden. Dies führt unweigerlich zu einer Rekursion und ich weiß einfach nicht, wie ich da raus komme.
void PagingManager::Map(uintptr_t virtual_address, uintptr_t physical_address)
{
this->UpdateIndexes(virtual_address & 0x000FFFFFFFFFF000LL);
PageMapLevel4Entry *pml4e = (PageMapLevel4Entry *)(page_map_level_4[pml4i].GetAddress());
if(pml4e->IsPresent() == false)
{
pml4e->Clear();
pml4e->SetAccess(PageAccess::UserWritable);
pml4e->SetAddress(memory.PAlloc());
pml4e->SetCachability(PageCachability::WriteThroughCachable);
pml4e->SetPresence(true);
}
PageDirectoryPointerEntry *pdpe = (PageDirectoryPointerEntry *)(pml4e[pdpi].GetAddress());
if(pdpe->IsPresent() == false)
{
pdpe->Clear();
pdpe->SetAccess(PageAccess::UserWritable);
pdpe->SetAddress(memory.PAlloc());
pdpe->SetCachability(PageCachability::WriteThroughCachable);
pdpe->SetPresence(true);
}
PageDirectoryEntry *pde = (PageDirectoryEntry *)(pdpe[pdi].GetAddress());
if(pde->IsPresent() == false)
{
pde->Clear();
pde->SetAccess(PageAccess::UserWritable);
pde->SetAddress(memory.PAlloc());
pde->SetCachability(PageCachability::WriteThroughCachable);
pde->SetPresence(true);
}
PageTableEntry *pte = (PageTableEntry *)(pde[pti].GetAddress());
pte->Clear();
pte->SetAccess(PageAccess::UserWritable);
pte->SetAddress(physical_address);
pte->SetCachability(PageCachability::WriteThroughCachable);
pte->SetPresence(true);
}
-
Ich sehe in dem Quellcode keine Rekursion und ich kann mir auch nicht wirklich denken wo genau eine sein soll.
-
Mein Fehler, dies ist noch der Code, der sich einfach verabschiedet (#PF), wenn die Level fehlen. Mit Rekursion wäre es dann:
void PagingManager::Map(uintptr_t virtual_address, uintptr_t physical_address)
{
this->UpdateIndexes(virtual_address & 0x000FFFFFFFFFF000LL);
PageMapLevel4Entry *pml4e = (PageMapLevel4Entry *)(page_map_level_4[pml4i].GetAddress());
if(pml4e->IsPresent() == false)
{
pml4e->Clear();
pml4e->SetAccess(PageAccess::UserWritable);
pml4e->SetAddress(memory.PAlloc());
pml4e->SetCachability(PageCachability::WriteThroughCachable);
pml4e->SetPresence(true);
this->Map(pml4e->GetAddress(), pml4e->GetAddress());
}
PageDirectoryPointerEntry *pdpe = (PageDirectoryPointerEntry *)(pml4e[pdpi].GetAddress());
if(pdpe->IsPresent() == false)
{
pdpe->Clear();
pdpe->SetAccess(PageAccess::UserWritable);
pdpe->SetAddress(memory.PAlloc());
pdpe->SetCachability(PageCachability::WriteThroughCachable);
pdpe->SetPresence(true);
this->Map(pdpe->GetAddress(), pdpe->GetAddress());
}
PageDirectoryEntry *pde = (PageDirectoryEntry *)(pdpe[pdi].GetAddress());
if(pde->IsPresent() == false)
{
pde->Clear();
pde->SetAccess(PageAccess::UserWritable);
pde->SetAddress(memory.PAlloc());
pde->SetCachability(PageCachability::WriteThroughCachable);
pde->SetPresence(true);
this->Map(pde->GetAddress(), pde->GetAddress());
}
PageTableEntry *pte = (PageTableEntry *)(pde[pti].GetAddress());
pte->Clear();
pte->SetAccess(PageAccess::UserWritable);
pte->SetAddress(physical_address);
pte->SetCachability(PageCachability::WriteThroughCachable);
pte->SetPresence(true);
}
-
Wieso machst du nicht von Anfang an ein Identity Mapping des verfügbaren RAMs mit 2MiB Pages?
edit: Ansonsten gibts halt noch den Trick das PML4 als Page Directory irgendwo zu verwenden, dann sind auch alle Tabellen gemappt, zwar nicht identity, aber das brauchts ja eh nicht.
-
Weil ich dann für jeden Task massig Speicher benötige, glaub ich. Ich müsste das trotzdem mal versuchen, sagt mir aber nicht so zu.
-
Dafür brauchst du einmal Speicher, sicherlich nicht für jeden Task.
edit: Ich bin mir jetzt nicht 100% sicher, aber ich glaube es gibt auch 1GiB Pages.
-
Jo, die gibt es, sind aber a) nicht auf jeder CPU verfügbar und b) sehr wenige. Ich versuche jetzt mit dem letzten 4 KiB Block (0xFFFFFFFFFFFFF000) immer das zu bearbeitende Element zu mappen, allerdings scheint es da noch ein wenig Probleme zu geben. Zur Zeit sieht das so aus:
void PagingManager::Map(uintptr_t virtual_address, uintptr_t physical_address)
{
this->UpdateIndexes(virtual_address & 0x000FFFFFFFFFF000LL);
this->dynamic_page->SetAddress(page_map_level_4[pml4i].GetAddress());
PageMapLevel4Entry *pml4e = (PageMapLevel4Entry *)(0xFFFFFFFFFFFFF000LL + pml4i * sizeof(PageMapLevel4Entry));
if(pml4e->IsPresent() == false)
{
pml4e->Clear();
pml4e->SetAccess(PageAccess::UserWritable);
pml4e->SetAddress(memory.PAlloc());
pml4e->SetCachability(PageCachability::WriteThroughCachable);
pml4e->SetPresence(true);
}
this->dynamic_page->SetAddress(pml4e[pdpi].GetAddress());
PageDirectoryPointerEntry *pdpe = (PageDirectoryPointerEntry *)(0xFFFFFFFFFFFFF000LL + pdpi * sizeof(PageMapLevel4Entry));
if(pdpe->IsPresent() == false)
{
pdpe->Clear();
pdpe->SetAccess(PageAccess::UserWritable);
pdpe->SetAddress(memory.PAlloc());
pdpe->SetCachability(PageCachability::WriteThroughCachable);
pdpe->SetPresence(true);
}
this->dynamic_page->SetAddress(pdpe[pdi].GetAddress());
PageDirectoryEntry *pde = (PageDirectoryEntry *)(0xFFFFFFFFFFFFF000LL + pdi * sizeof(PageDirectoryEntry));
pde->Clear();
pde->SetAccess(PageAccess::UserWritable);
pde->SetAddress(physical_address);
pde->SetCachability(PageCachability::WriteThroughCachable);
pde->SetPresence(true);
}
-
Jo, nimm das PML4 als PDPT, wenn das geht. Ist das einfachste, spart dir ständiges temporäres Ummappen und kostet nur virtuellen Speicher, den du sowieso in Massen hast.
-
Du meinst rekursives Mapping wie im PM? Ist im LM nicht möglich, da sich die einzelnen Level in ihren Attributen unterscheiden :(
-
Hm, dann hat bluecode wohl Mist vorgeschlagen. ;)
Sind das kritische Attribute? Im PM unterscheiden sich PDE und PTE ja auch geringfügig, was man aber einfach ignorieren kann.
-
Ja, im LM bestimmt z.B. Bit 7, ob das aktuelle Level das unterste ist (Nötig, da LM sowohl 1 GiB, 2 MiB und 4 KiB unterstützt).
-
Hm, dann hat bluecode wohl Mist vorgeschlagen. ;)
Jop, hat er. :-D
SHyx0rmZ im IRC und ein Blick in die Manuals haben mich dann auch überzeugt, dass das nicht so toll tut.
-
Auch wenn du den gesamten physischen Speicher nur mit 2 MiB Pages einfach irgendwohin mappst, brauchst du nur ein paar KB RAM für die PDPT.