Lowlevel

Lowlevel => OS-Design => Thema gestartet von: SHyx0rmZ am 14. February 2010, 13:36

Titel: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag 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);
}
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: bluecode am 14. February 2010, 14:25
Ich sehe in dem Quellcode keine Rekursion und ich kann mir auch nicht wirklich denken wo genau eine sein soll.
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: SHyx0rmZ am 14. February 2010, 14:31
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);
}
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: bluecode am 14. February 2010, 14:33
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.
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: SHyx0rmZ am 14. February 2010, 14:36
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.
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: bluecode am 14. February 2010, 14:41
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.
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: SHyx0rmZ am 14. February 2010, 19:00
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);
}
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: kevin am 14. February 2010, 21:16
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.
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: SHyx0rmZ am 14. February 2010, 21:21
Du meinst rekursives Mapping wie im PM? Ist im LM nicht möglich, da sich die einzelnen Level in ihren Attributen unterscheiden :(
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: kevin am 14. February 2010, 21:24
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.
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: SHyx0rmZ am 14. February 2010, 22:06
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).
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: bluecode am 15. February 2010, 06:53
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.
Titel: Re: Paging und das ewige Problem mit der Rekursion (x86-64)
Beitrag von: Jidder am 16. February 2010, 19:50
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.