Lowlevel

Lowlevel => OS-Design => Thema gestartet von: ChristianF am 30. May 2008, 21:45

Titel: Speicherverwaltung
Beitrag von: ChristianF am 30. May 2008, 21:45
Hi Community,
da ich gerade mal wieder am neuschreiben meines Memory Managers bin, habe ich ein paar Fragen an euch. :roll:
 
Nun ist es ja so, dass, wenn ich DMA verwenden will, der Speicher im Bereich unter 16 MB liegen muss, ansonsten sollte das oberhalb sein (>16MB).
Daraus resultierend habe ich mir für meine physikalische Speicherverwaltung folgende Funktionen ausgedacht (Prototypen):
 
extern void physical_page_free(unsigned int page);
extern void physical_page_range_free(unsigned int page, int num);

extern unsigned int physical_alloc_dma_page(void);
extern unsigned int physical_alloc_dma_page_range(unsigned int num);

extern unsigned int physical_alloc_page(void);
extern unsigned int physical_alloc_page_range(unsigned int num);

Was haltet Ihr davon?
Ist das so vollständig, oder fehlt da eventuell noch etwas, das ich übersehen habe?
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: FreakyPenguin am 30. May 2008, 22:00
Du solltest wohl die Funktion nicht auf >16Mb beschränken, denn sonst hast du ein Problem, wenn ein Rechner nur 8 Mb hat. Es macht aber sicherlich Sinn, erst den Speicher über 16Mb zu vergeben.

Vielleicht wären Funktionen um zu Prüfen ob eine bestimmte Page besetzt ist, respektive um eine bestimmte Page zu reservieren nicht verkehrt, falls mal ein Treiber eine bestimmte Adresse will. Später, wenn du mal ein free oder sowas in deiner Shell haben willst, um zu wissen, wieviel Speicher noch frei ist, wäre vielleicht eine Funktion nützlich die dir die Anzahl der freien/besetzen Pages zurückgibt.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 30. May 2008, 23:35
Hi
Vielleicht wären Funktionen um zu Prüfen ob eine bestimmte Page besetzt ist, respektive um eine bestimmte Page zu reservieren nicht verkehrt, falls mal ein Treiber eine bestimmte Adresse will. Später, wenn du mal ein free oder sowas in deiner Shell haben willst, um zu wissen, wieviel Speicher noch frei ist, wäre vielleicht eine Funktion nützlich die dir die Anzahl der freien/besetzen Pages zurückgibt.
Nun das was du meinst, kommt nach der physikalischen Speicherverwaltung, da das Paging ja zur Virtuellen Speicherverwaltung zählt.
Da habe ich mir bis jetzt auch noch nicht so viele Gedanken gemacht, da das Programm, dass Speicherplatz (z.B. ein Treiber) anfordert nur eine virtuelle Addresse bekommt.
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 30. May 2008, 23:42
Wenn dieses Programm aber ein Treiber ist und die Hardware mit virtuellen Adressen füttert, dürfte viel rauskommen, nur nichts sinnvolles. Es gibt schon Software, die einen Grund dazu hat, bestimmte physische Adressen zu wollen.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 31. May 2008, 09:24
Mmmhhh.....
Das einzigste Problem wäre dann aber, dass die Adressen nicht 1:1 gemappt werden.
Mein Kernel wird an die Adresse 0xC0000000 gemappt (Physikalisch 0-2 MB).
Das würde dann heißen, ich bräuchte bei meinen Paging funktionen noch eine Funktion, die 1:1 Mappt, z.B.:

bool map_page_to_address_1to1(...);

(Wenn ich das richtig verstanden habe.)

Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: FreakyPenguin am 31. May 2008, 09:39
Die Adressen müssen ja nicht umbedingt 1:1 gemappt werden. Es reicht, wenn der Treiber einen physischen Speicherbereich anfordern kann, und dann die virtuelle Adresse erhält, an die der Bereich gemappt wurde.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 01. June 2008, 15:53
Und genau so habe ich mir das eigentlich gedacht.

Jetzt mal unabhängig davon, welches Programm/welcher Treiber braucht denn unbedingt eine physikalische Addresse?

Wie sieht es denn aus mit DMA?
Es heißt, dass der Speicher unterhalb der 16 MB grenze liegen muss. Kann ich die Page dann virtuell z.B. an die Stelle 0xABC00000 mappen, oder muss das dann 1:1 sein?
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: Korona am 01. June 2008, 16:45
Den Speicher für DMA kannst du dahin mappen wo du möchtest.
Alle Memory-Mapped Devices brauchen Zugriff auf bestimmte physische Pages. Dazu gehören viele PCI Devices, APICs und andere Geräte. (HPET z.B.)
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 01. June 2008, 18:04
Ok
Jetzt hab ich das verstanden (denke ich mal  :roll: ).

Ein Treiber fordert die Pages im Adressraum 0x60000000 - 0x70000000 an.
Der Kernel mappt die dann in die entsprechende Page des Prozesses und dieser kann dann damit arbeiten.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 01. June 2008, 21:00
Ja, wobei man nur in einem Design mit Microkernel speziellen Prozessen (auch Server genannt) erlaubt physische Speicherbereiche zu allozieren. Bei einem monolithischen Kerneldesign wird nur der Kernel (bzw. die Kernelmodule oder Treiber) diese physischen Speicherbereiche allozieren können und diese werden dann in den Kerneladressraum (also in jeden Prozess, aber mit "supervisor" Rechten als Pageattribut) gemappt.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 02. June 2008, 09:44
Okay.

Hier ist sind die bis jetzt geplanten Funktionen:
extern void physical_page_free(unsigned int page);
extern void physical_page_range_free(unsigned int page, int num);

extern unsigned int physical_alloc_dma_page(void);
extern unsigned int physical_alloc_dma_page_range(unsigned int num);

extern unsigned int physical_alloc_page(void);
extern unsigned int physical_alloc_page_range(unsigned int num);
extern unsigned int physical_alloc_page_limit(unsigned int lower_limit, unsigned int num);

Ich werde dann demnächst mit der Re-Implementierung der Speicherverwaltung beginnen.
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 04. June 2008, 11:24
MMhhh....
Die Physikalische Speicherverwaltung ist nicht sonderlich schwer, da ich das ja nur umbaue.
 
Auf was muss ich denn beim Paging alles achten?
Danach möchte ich mit dem einbauen von Multitasking beginnen, weshalb ich schonmal für alle Paging sachen, wie Page, Pagetable und Page Directory eine Struktur angelegt habe.  :-)
 
Auf was muss ich hinsichtlich des Multitaskings später achten?

Dann ist da nochwas, da ich ja auch einen Heap Manager einbauen muss.
Ist es sinnvoll in einem Microkernel den Heap Manager für den Kernel (Ring 0) und User-Programme/Treiber (Ring 3) in den Kernel einzubauen, oder sollte ich den Part für die User-Programme/Treiber auslagern?
 
Gruß Christian


*EDIT*
Du solltest wohl die Funktion nicht auf >16Mb beschränken, denn sonst hast du ein Problem, wenn ein Rechner nur 8 Mb hat. Es macht aber sicherlich Sinn, erst den Speicher über 16Mb zu vergeben.
Ich habe vor den DMA Speicherbereich dynamisch festzulegen,
z.B.: Wenn 32 MB gesamt da ist, dann nim 16 MB. Wenn nur 16 MB da sind, dann nimm 8 MB.

*EDIT 2*
Laut diesem Tutorial: Multitasking Tutorial (http://www.jamesmolloy.co.uk/tutorial_html/9.-Multitasking.html) muss für das Kopieren der Daten eines Frames/einer Page (physikalisch) das Paging deaktiviert werden, was mir doch recht langsam erscheint.
Geht das nur so, oder ist da noch ein anderer Weg?
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 04. June 2008, 14:03
Auf was muss ich hinsichtlich des Multitaskings später achten?
Alles sinnvoll im Virtuellen Adressraum anordnen, so dass später genug Platz für den userspace ist und nicht ein totales Kuddelmuddel entsteht.

Zitat
Ist es sinnvoll in einem Microkernel den Heap Manager für den Kernel (Ring 0) und User-Programme/Treiber (Ring 3) in den Kernel einzubauen, oder sollte ich den Part für die User-Programme/Treiber auslagern?
Also alles was mit dem Kernelheap zu tun hat, würde ich auf jeden Fall im Kernel haben. Was den Userspaceheap angeht würde ich das nur auf Pageebene im Kernel verwalten, ein malloc kann dann die userspace libc selbst bereitsstellen.

Zitat
Laut diesem Tutorial: Multitasking Tutorial (http://www.jamesmolloy.co.uk/tutorial_html/9.-Multitasking.html) muss für das Kopieren der Daten eines Frames/einer Page (physikalisch) das Paging deaktiviert werden, was mir doch recht langsam erscheint. Geht das nur so, oder ist da noch ein anderer Weg?
Das ist eine Möglichkeit (wenn auch imho eine sehr bescheidene), aber das muss man natürlich nicht so machen. Wenn man das Page-Directory als eine der Page-Tables angibt, dann kann man auf die gesamten page tables zugreifen. Wenn man dann zusätzlich noch das Pagedir mappt, so kann man über den virtuellen Adressraum auf sein Pagedir & seine Pagetables zugreifen und zumindest diese verändern. Wenn man jetzt ein neues PDir erstellen will, dann muss man sich halt in den momentanen Adressraum irgendwo ne physische Page einbinden und diese dann zu nem PageDir bauen und halt wieder unmappen, wenn man damit fertig ist.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 04. June 2008, 15:20
Nun den Speicher habe ich bis jetzt wie folgt aufgeteilt (Virtuell):
0x00000000 - 0xBFFFFFFF     => User Programme
0xC0000000 - 0xCFFFFFFF     => Kernel
0xD0000000 - 0xDFFFFFFF     => Kernel Heap
0xE0000000 - 0xFFFFFFFF     => "Noch nicht vergeben"

Ist das so sinnvoll, oder wäre es besser, da noch was zu ändern, mal abgesehen von dem letzten Eintrag (0xE0000000-0xFFFFFFFF)?
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 04. June 2008, 15:31
Bei uns gibts zwar noch ein paar mehr Sachen im virtuellen Adressraum (siehe hier (http://code.google.com/p/pedigree/wiki/MemoryManagement), das Layout für x64 ist iirc momentan unvollständig und von mips hab ich selbst keine Ahnung *g*), aber ansonsten passt das schon.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 05. June 2008, 08:35
Mal eine technische Frage:
ich habe eine Funktion
unsigned int find_free_page(unsigned int lower_limit);
Wenn ich nun eine page zu DMA-Zwecken reservieren möchte sieht mein Funktionsaufruf wie folgt aus:
unsigned int page = find_free_page(0);
Wenn ich irgendeine andere Page reservieren möchte, dann muss ich ein Limit angeben, das die Grenze zum DMA-Bereich angibt, z.B.:
(Vorrausgesetzt werden für dieses Beispiel 32MB RAM)
unsigned int page = find_free_page(16*1024*1024);
Nun ist es ja so, dass die Addresse, wenn Sie größer 0 ist, in einen Eintrag umgewandelt werden muss. Nun muss ich aber die Startposition für die bitmap berechnen.
Das habe ich mir wie folgt gedacht:
unsigned int loop;
loop = (loop>0)?(lower_limit / 0x1000 /*PAGE_SIZE*/ / 32):0;

Darauf gekommen bin ich durch die Reservierung der Page. Hier wird ja auch erst mit 32 multipliziert und dann später noch mit der Größe der Page.
return(((i*32)+j) * 0x1000 /*PAGE_SIZE*/

Ist das so richtig, oder habe ich da was übersehen?
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: Korona am 05. June 2008, 10:07
Die Bedingung dass die Address größer 0 sein muss ist unnötig.
Außerdem wird die Variable loop in deinem Beispiel nicht initialisiert, die Abfrage if(loop > 0) ist also Schwachsinn. Gemeint war hier wohl eher if(lower_limit > 0).
Ansonsten scheint deine Berechnung in Ordnung zu sein. (Ich gehe davon aus dass du loop als Index in ein Array von 32 Bit Zahlen benutzt; bei einem Bytearray ist die Division durch 32 natürlich falsch)
Ich würde mir aber überlegen, ob die Angabe eines Limits nach oben nicht sinnvoll ist. Schließlich möchtest du nicht, dass ISA DMA Pages in einem Bereich über 16 MiB allokiert werden. Die Behandlung aller Spezialfälle die auftreten könnten fällt warscheinlich mit der Angabe einer oberen Grenze leichter.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 05. June 2008, 10:25
Nun ja...
Meine Code zum finden einer freien page sieht in der Grund-Version so aus
(wird allerdings nochmals überarbeitet, da lower_limit nicht berücksichtigt wird):
// Wird später initialisiert, mit (max_mem / num_pages)
unsigned int *physical_bitmap = NULL;

unsigned int find_free_page(unsigned int lower_limit)
{
   unsigned int i, j;
   for (i = 0; i < physical_bitmap_size; i++)
   {
       if (physical_bitmap[i] != 0xFFFFFFFF)
       {
           // at least one bit is free here.
           for (j = 0; j < 32; j++)
           {
               if ( !(physical_bitmap[i]&(0x1<<j)) )
                   return(((i*32)+j) * 0x1000);
           }
       }
   }
   return(-1);
}

Ansonsten scheint deine Berechnung in Ordnung zu sein. (Ich gehe davon aus dass du loop als Index in ein Array von 32 Bit Zahlen benutzt; bei einem Bytearray ist die Division durch 32 natürlich falsch)
Ist ja auch verständlich, da das Bytearray ein char Array ist, und so 8 Pages pro Eintrag verwalten kann.
Ich habe mich für die 32-Bit Bitmap entschieden, da Sie mir etwas schneller vorkam, oder täusche ich mich da?  :roll:
 
Die Bedingung dass die Address größer 0 sein muss ist unnötig.
Außerdem wird die Variable loop in deinem Beispiel nicht initialisiert, die Abfrage if(loop > 0) ist also Schwachsinn. Gemeint war hier wohl eher if(lower_limit > 0).
Genau das meinte ich.

Ich würde mir aber überlegen, ob die Angabe eines Limits nach oben nicht sinnvoll ist. Schließlich möchtest du nicht, dass ISA DMA Pages in einem Bereich über 16 MiB allokiert werden. Die Behandlung aller Spezialfälle die auftreten könnten fällt warscheinlich mit der Angabe einer oberen Grenze leichter.
Nun ja dafür hatte ich eine globale Variable vorgesehen, mit dem DMA-Limit. Mit einem Übergabeparameter ist das allerdings etwas sauberer, z.B.:
unsigned int find_free_page(unsigned int lower_limit, unsigned int upper_limit);
Oder sollte ich das doch global speichern?  :wink:

Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 09. June 2008, 20:02
Hi
ich habe mit einem richtig komischen Problem zu kämpfen.
 
Folgender Code initialisiert die Physikalische Speicherverwaltung:
void initialise_physical_memory_manager(multiboot_info_t *mbt)
{
unsigned int num_pages = 0, max = 0, i;

if(CHECK_FLAG(mbt->flags, 0))
    {
        max = (mbt->mem_lower + mbt->mem_upper);
max_mem = max * 1024;
        num_pages = max_mem / PAGE_SIZE; /* PAGE_SIZE = 0x1000 */
/* Set DMA-Upper Limit. It should be calculated with max_mem, but max. is 16 MB (16 * 1024 * 1024) */
upper_dma_limit = ((max_mem / 2) > (16 * 1024))?(16*1024*1024):((max_mem / 2) * 1024 * 1024);
    }
    else if(CHECK_FLAG(mbt->flags, 6))
    {
/*
* ToDo: + Look at the Memory Map from GRUB
* + Calculate the whole Memory
* + set the Reserved Areas as used
*
* max = ???
* max_mem = ???
* num_pages = max_mem / PAGE_SIZE;
* upper_dma_limit = ((max_mem / 2) > (16 * 1024))?(16*1024*1024):((max_mem / 2) * 1024 * 1024);
*/
    }
    else
panic("Direct Memory Probing isn't yet implemented!");

/* Calculate the size of the bitmap */
physical_bitmap_size = (num_pages / 32) * 4;
/* Allocate Bitmap and Translate the address to a physical one */
physical_bitmap = (unsigned int *)VIRT2PHYS(kmalloc(physical_bitmap_size));
    /* Set all to 0 from the reserved space */
    memset(physical_bitmap, 0, physical_bitmap_size);
}

Nun hatte ich allerdings das Problem, dass mein Kernel die ganze Zeit hängen geblieben ist (endlosschleife).
Einige Debugausgaben haben folgendes ergeben:
physical_bitmap_size = 131068
physical_bitmap = 0x1069ff

Nun sollte ja eigentlich mit memset der komplette Inhalt auf 0 gesetzt werden, was allerdings nicht passiert, denn alle 131068 Einträge enthalten 0xFFFFFFFF. Auch das manuelle umsetzen ohne Funktionsaufruf hat nichts gebracht.
 
Woran kann das liegen?
 
Gruß Christian

*EDIT*
Genauer gesagt, es kommt ein Out of Memory, da alles mit 0xFFFFFFFF belegt ist.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 09. June 2008, 20:12
Wo bleibt der Kernel den überhaupt hängen und va. ist es wirklich eine Schleife oder geht er baden (im Sinne von Exception nach Exception nach Exception...)?
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 09. June 2008, 20:16
Es gibt einen panic.
Out of Memory!
System is halting now.
Als ich mir von der Funktion, die die bitmap durchläuft, den Inhalt des jeweils aktuellen Eintrags hab ausgeben lassen, war der Wert immer 0xFFFFFFFF.
Ich verstehe nicht, warum das ausftritt, da ich ja die gesamte bitmap auf 0 gesetzt habe.

printf("\n\nphysical_bitmap_size = %d\nphysical_bitmap[1] = 0x%x\nphysical_bitmap = 0x%x\n", physical_bitmap_size, physical_bitmap[1], physical_bitmap);
    unsigned int i, j;
    for(i = 0; i < physical_bitmap_size; i++)
    {
        printf("physical_bitmap[%d] = 0x%x\n", i, physical_bitmap[i]);
        if(physical_bitmap[i] != 0xFFFFFFFF)
{
    printf("Something Free!\n");
    for(j = 0; j < 32; j++)
{
if(physical_bitmap[i] & BIT(j))
return( ((i * 32) + j) * PAGE_SIZE );
}
}
    }
Gesucht habe ich auf die Art und der hat halt durchnummeriert bis 131068 und hat als inhalt immer 0xFFFFFFFF ausgegeben.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 09. June 2008, 20:20
Ist das ein Fehler in kmalloc? Ich mein 128kb ist schon einiges zum allozieren. Auf was greift den kmalloc zurück? Auf diese Bitmap? Das wäre nämlich schlecht, wenn sie noch nicht initialisiert ist.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 09. June 2008, 20:22
Nun mein kmalloc sieht so aus:
unsigned int kmalloc_int(size_t size, unsigned int align, unsigned int *phys)
{
    if (align == 1 && (placement_address & 0xFFFFF000)) // If the address is not already page-aligned
    {
        // Align it.
        placement_address &= 0xFFFFF000;
        placement_address += 0x1000;
    }
    if (phys)
        *phys = placement_address;

    unsigned int tmp = placement_address;
    placement_address += size;
    return tmp;
}

Anmerkung: placement_address startet bei ab 0xC0000000.
Aus diesem Grund wird die Addresse mittels des Makros VIRT2PHYS umgewandelt (+0x40000000).

Einfach eine Variable, die immer ein bissel weiter geschubst wird  :wink:
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 09. June 2008, 20:29
Ich versteh immernoch nicht woher der Panic kommt. Wird der von deinem OS angezeigt, wenn ja wo oder von qemu/bochs oder ...?

edit: Ist denn bei 0xC0000000 irgendwas sinnvolles gemappt?
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 09. June 2008, 21:13
das sollte ja eigentlich gemacht werden.
Der reserviert eine Physische Page, um diese dann nach 0xC0000000 zu mappen.
Allerdings kommt er nicht bis dahin.

Der Reservierte Speicher, der auch durchsucht wird, hat nach dem memset den Wert 0xFFFFFFFF, überall.
 
Die Funktion (testweise find_free_frame) durchläuft das komplette Array und gibt, falls vorhanden, eine Addresse auf eine physische freie Speicheradresse zurück. Nun steht aber in allen einträgen der Bitmap 0xFFFFFFFF.
Dies wertet die funktion physical_alloc_page() so, dass der komplette RAM voll ist, und macht einen Aufruf der Funktion panic, mir dem Text "Out of Memory!".
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 09. June 2008, 21:26
das sollte ja eigentlich gemacht werden.
Der reserviert eine Physische Page, um diese dann nach 0xC0000000 zu mappen.
in kmalloc hier:
physical_bitmap = (unsigned int*)VIRT2PHYS(kmalloc(physical_bitmap_size));
oder wo? Woher kommen den die physischen Pages für dieses kmalloc?

Zitat
Allerdings kommt er nicht bis dahin.
Bis wohin kommt er denn überhaupt...

Könntest du mal sagen, was ausgeführt wird, was nicht, wer den Panic anzeigt, etc...? Ich komm nämlich momentan überhaupt nicht mit... :-P
Titel: Re: Speicherverwaltung
Beitrag von: MNemo am 09. June 2008, 21:40
das löst zwar nicht dein problem aber
if (align == 1 && (placement_address & 0xFFFFF000)) // If the address is not already page-alignedsoll wohl eher
if (align == 1 && (placement_address & 0xFFF)) // If the address is not already page-alignedheißen
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 09. June 2008, 21:52
mmhhh....
was ist denn falsch an der Zeile:
physical_bitmap = (unsigned int *)kmalloc(physical_bitmap_size);
Ich verstehe das nicht so ganz.
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 09. June 2008, 21:56
Fangen wir mal ganz von vorne an: Wie weit wird denn initialise_physical_memory_manager(...) ausgeführt bzw. was wird nicht mehr ausgeführt bzw. wo hängt er in einer Endlosschleife?
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 09. June 2008, 22:08
was ist denn falsch an der Zeile:
physical_bitmap = (unsigned int *)kmalloc(physical_bitmap_size);
Henne-Ei und so. Ein vernueftiges kmalloc braucht selbstverstaendlich eine initialisierte physische Speicherverwaltung. Ansonsten kann ja der reservierte Speicher nicht als belegt markiert werden.

Edit: Aber mit deiner Fakeimplementierung ist das natuerlich nicht dein aktuelles Problem. Nur ein zukuenftiges.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 09. June 2008, 22:13
Meine Vermutung wäre schon oben gewesen, dass du in kmalloc auf die page bitmap zugreifst, die du durch das kmalloc erst allozieren (und danach erst initialisieren) willst.

edit: Der von dir angegebene Code ist übrigens nicht kmalloc sondern kmalloc_int... Das erscheint mir irgendwie was anderes zu sein...

edit2: taljeth bemerkte in #lost noch, dass deine Adresse für physical_bitmap sehr komisch ist und nicht wirklich zu den von dir prophezeiten 0xC0000000 + X passt. Zumindest sagtest du, dass kmalloc, sowas allozieren sollte...

edit3: Wenn du Lust hast kannst du mir auch mal ein (Floppy/CD-)Image + Sourcecode schicken, dann schau ich mir das an... Am liebsten natürlich mit (funktionierenden) Makefiles, damit ich auch ein bisschen was frickeln. kann.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 09. June 2008, 22:40
Also folgendes kmalloc ist nur eine zusatz Funktion. in dieser Funktion wird kmalloc_int so aufgerufen:
return(kmalloc_int(size, 0, 0));
Des Weiteren habe ich kmalloc jetzt so umgestellt, dass physikalische Adressen zurückgegeben werden.
unsigned int placement_address = (unsigned int)&end+0x40000000;
initialise_physical_memory_manager(...) wird komplett ausgeführt.
Er endet dann in einer endlos schleife, wenn nach einer freien physischen Page gesucht wird.
Wie zuvor auch schon gesagt, komischer weise ist die bitmap gefüllt mit dem Wert 0xFFFFFFFF anstatt 0.
 
Ich habe das OS in ein Archiv gelegt und auf meinem Server abgelegt. Wäre schön, wenn du irgendwann die Zeit findest, dir das mal anzuschaun.
http://87.230.87.9/ftp/christian/DeutschOS.tar.gz
 
Gruß Christian

 
PS: Wenn du dir den Code anschaust, dann kannst du den ganzen inhalt der Datei mm/paging.c ignorieren, bis auf die Funktion initialise_paging(...).
Hier soll eine freie Page gefunden und reserviert werden, mittels physical_alloc_page(), was dann aber in einem Out of Memory endet.

*EDIT*
Die Funktionen sind teilweise angelehnt an die von LOST, allerdings selbstgeschrieben.
Des Weiteren muss ich den Paging kram nochmals überarbeiten, wenn die physikalische Speicherverwaltung funktioniert.
Titel: Re: Speicherverwaltung
Beitrag von: FreakyPenguin am 10. June 2008, 08:02
Hm also bei mir tut der Code einfach so nicht. Mit dem ganzem Segment-Gefummel verrutscht da die Adresse der Multiboot-Struktur. Die müsste dann halt auch irgendwo angepasst werden.

Aber das mit der ganzen Segmentierung finde ich ziemlich mühsam und Fehleranfällig, da du da während der ganzen Initialisierung immer die richtigen Adressen umbiegen musst. (Ich hab das auch erst nach einem Hinweis von bluecode gesehen, warum das überhaupt funktioniert) Ich würde dir empfehlen in der start.s ein einfaches PD zu erstellen, das den Kernel sowohl 1:1 als auch auf den 3. GB mappt. So musst du dann nur noch dort am Anfang kurz auf die Adressen achten.

Ah und nochwas, ich glaube im Kernel wäre ein -Werror keine schlechte Idee, denn die Warnungen sind oft nicht nur Dekoration. ;-)

Mir fehlt leider grad die Zeit um noch weiter zu suchem, aber wenn das Problem heute Abend noch nicht gelöst ist, kann ichs mir nochmal anschauen.

Edit:
Abgesehen natürlich von der Zeile "if(physical_bitmap & BIT(j))" in find_free_page, die meiner Meinung nach eher "if(!(physical_bitmap & BIT(j)))" sein sollte.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 10. June 2008, 08:20
Dieser Post wurde unter enormen Zwang auf mich von FreakyPenguin erstellt. Er fordert, dass ich auf den Edit seines letzten Posts explizit hinweise.
Bitte helft mir, er wird, falls ich seine Forderungen nicht erfülle bei meinem OS-Projekt mithelfen. :-o
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 10. June 2008, 09:14
Da habe ich das wohl vergessen.  :cry:
In meinem alten Code war das so drinne, habe allerdings den Unterschied gestern nicht gesehen  :roll:
 
Gruß Christian

*EDIT*
Hm also bei mir tut der Code einfach so nicht. Mit dem ganzem Segment-Gefummel verrutscht da die Adresse der Multiboot-Struktur.
Bei mir hat das Funktioniert, wollte das aber eh schon seit längerer Zeit ändern  :-D
Bin grad dabei eine neue start.s zu erstellen ...
 
*EDIT2*
Mmmhhh....
wie setze ich nur Paging mit nasm auf...  :roll:
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 10. June 2008, 10:13
Mir ist gerade eben noch ein weiterer Fehler aufgefallen.
Und zwar hier:
physical_bitmap_size = (num_pages / 32) * 4;
Das stimmt allerdings so nicht, oder gibt es 128 Bit Variablen (16 Byte) ???
Ich kenne nur 8 Byte große Variablen, also 64 Bit (long long int, C99 Standard).
physical_bitmap_size = num_pages / 32;
Ich weiß nur nicht warum ich das dahin geschrieben habe...
wahrscheinlich, weil ich vorher folgendes da stehen hatte:
physical_bitmap_size = num_pages / ( 8 * 4 );
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 10. June 2008, 13:06
physical_bitmap_size = (num_pages / 32) * 4;Das stimmt allerdings so nicht, oder gibt es 128 Bit Variablen (16 Byte) ???
Das stimmt so schon, du willst doch 32bit integer allozieren, deswegen teilst du durch 32 (für eine page ein bit) und multiplizierst anschließend mit 4 (also der Größe deines Datentyps). Es wird zwar damit nach unten gerundet (was nicht unbedingt richtig ist), aber was solls.

Zitat
Ich kenne nur 8 Byte große Variablen, also 64 Bit (long long int, C99 Standard).
Der C Standard gibt keine feste Größe für die Datentypen an, sondern nur eine Mindestgröße. Gcc stellt iirc als Erweiterung sogar einen 128bit Integerdatentyp zur Verfügung, wie der heißt weiß ich nicht auswendig, wenns dich interessiert muss halt ins Manual schauen.
Was allerdings dein 128bit Datentyp mit dem Code oben zu tun haben soll versteh ich nicht. :wink:
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 10. June 2008, 13:08
wie setze ich nur Paging mit nasm auf...  :roll:
Gibt doch genug Beispielcode dazu :roll: (zB. meinen beiden OS, siehe Signatur, beides higher half und beidesmal wird das in assemblercode initialisiert)
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 10. June 2008, 17:25
Mmmmhhh....
Ich habe den Fehler gefunden  :lol:

Ich habe mal das Makro VIRT2PHYS entfernt und siehe da, es geht!
*freu*
 
Jetzt kommt auch das was ich erwartet habe, und zwar ein neustart beim initialisieren des Pagings.
 
Kampfesgrüße Christian

*EDIT*
auch folgendes habe ich geändert:
unsigned int placement_address = (unsigned int)&end+0x40000000;zu folgendem:
unsigned int placement_address = (unsigned int)&end;
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 10. June 2008, 19:24
Mal ne kurze Frage:
Mein Linker Script sah vorher so aus:
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
SECTIONS
{
. = 0x100000;

.setup :
{
*(.setup)
}

. += 0xC0000000;

.text : AT(ADDR(.text) - 0xC0000000)
{
*(.text)
}

.data ALIGN (4096) : AT(ADDR(.data) - 0xC0000000)
{
*(.data)
*(.rodata*)
}

.bss ALIGN (4096) : AT(ADDR(.bss) - 0xC0000000)
{
*(COMMON*)
*(.bss*)
}
}

Nun wollte ich fragen, ob das auch so geht:
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x00100000;
virt = 0xC0100000;
SECTIONS
{
    . = virt;
    .text virt : AT(phys)
    {
        code = .;
        *(.text)
        *(.rodata)
        . = ALIGN(4096);
    }
    .data : AT(phys + (data - code))
    {
        data = .;
        *(.data)
        . = ALIGN(4096);
    }
    .bss : AT(phys + (bss - code))
    {
        bss = .;
        *(.bss)
        . = ALIGN(4096);
    }
    end = .; _end = .; __end = .;
}

Ich habe mir halt gedacht, wenn ich jetzt schon die start.s überarbeite, kann ich auch mein linker script überarbeiten.
Die untere Version ist eine abgeänderte von Brans Kernel Development Tutorial. Die wurde ersetzt, als ich daraus einen HigherHalf kernel gemacht habe.  :evil:


*EDIT*
wie setze ich nur Paging mit nasm auf...  :roll:
Gibt doch genug Beispielcode dazu :roll: (zB. meinen beiden OS, siehe Signatur, beides higher half und beidesmal wird das in assemblercode initialisiert)
Nun ja, das Problem ist, dass die AT & T Syntax, oder wie auch immer mich immer verwirrt, weshalb dein Code mit nichts bringt.

Ich habe in mein Linkerscript jetzt noch die Einträge __kernel_start__ und __kernel_end__ eingefügt.
Alles was ich jetzt machen muss ist doch von Adresse 0, bzw. __kernel_start__ bis __kernel_end__ in einer loop durchzulaufen und die Adresse in die Page Table (0xC0000000 >> 22) schreiben, falls der Kernel kleiner als 4 MB ist, oder?
Wenn ich doch nur etwas besser Assembler könnte ...
Wie mach ich das jetzt?  :-D
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 10. June 2008, 20:38
wie setze ich nur Paging mit nasm auf...  :roll:
Gibt doch genug Beispielcode dazu :roll: (zB. meinen beiden OS, siehe Signatur, beides higher half und beidesmal wird das in assemblercode initialisiert)
Nun ja, das Problem ist, dass die AT & T Syntax, oder wie auch immer mich immer verwirrt, weshalb dein Code mit nichts bringt.
Zitat
Stimmt doch garnicht, der pedigree Code ist nasm, siehe hier (http://code.google.com/p/pedigree/source/browse/trunk/src/system/kernel/core/processor/x86/asm/boot-standalone.s).

Zitat
Wie mach ich das jetzt?  :-D
siehe Link oben...
pedigree kernel @ 0xFF400000 (siehe auch hier (http://code.google.com/p/pedigree/wiki/MemoryManagement))
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 11. June 2008, 07:54
Nun das ist ja doch nicht so einfach, wie ich mir das gedacht habe.
bekomme ein Page not present von Bochs....
00008393105i[CPU0 ] (instruction unavailable) page not present
00008393105e[CPU0 ] exception(): 3rd (14) exception with no resolution, shutdown status is 00h, resetting

Folgenden Code habe ich mit Händen und Füßen geschrieben  :roll:
[BITS 32]

EXTERN __kernel_start__
EXTERN __kernel_end__
EXTERN main
EXTERN code, bss, end

global start
start:
; Points the Stack to the new stack area
mov esp, _sys_stack
jmp stublet

ALIGN 4
mboot:
; Multiboot macros make a few lines more readable
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_AOUT_KLUDGE equ 1<<16
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
KERNEL_VIRTUAL_BASE equ 0xC0000000
KERNEL_VIRTUAL_DIR_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22)

dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM

dd mboot
dd code
dd bss
dd end
dd start

boot_page_directory:
dd 0x00000083
times (KERNEL_VIRTUAL_DIR_NUMBER - 1) dd 0
dd 0x00000083
times (1024 - KERNEL_VIRTUAL_DIR_NUMBER - 1) dd 0

stublet:
mov ecx, (boot_page_directory - KERNEL_VIRTUAL_BASE)
mov cr3, ecx

mov ecx, cr4
or ecx, 0x00000010
mov cr4, ecx

mov ecx, cr0
or ecx, 0x80000000
mov cr0, ecx

lea ecx, [start_higher_half_kernel]
jmp ecx

start_higher_half_kernel:
;mov dword [boot_page_directory], 0
;invlpg[0]

; Parse the Magic number
push eax
; Parse the multiboot Structure
push ebx
; call main
;call _main

jmp $

SECTION .bss
resb 8192
_sys_stack:

Hier ist noch mein Linker-Script, dass ich nach meinen Bedürfnissen abgeändert habe:
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x00100000;
virt = 0xC0100000;
SECTIONS
{
. = virt;

.text virt : AT(phys)
{
__kernel_start__ = .;
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
__kernel_end__ = .;
}

Wo liegt mein Fehler?
Ich finde ihn nicht und meine nasm Kenntnisse, oder Generell Assemblerkenntnisse sind nicht so umwerfend gut.
Dann habe ich ausserdem noch eine Frage:
Kann ich anstatt der 4MB-Pages auch normale 4KB-Pages benutzen?
Oder hat das irgend einen Grund, dass in allen Code Stückern, die ich bis jetzt gesehen habe, die Page 4MB-Groß ist?
 
 
Gruß Christian
 
*EDIT*
Bei dem Code habe ich mich an dem Beispiel in der OSDev.org Wiki orientiert, allerdings nur das Paging.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 11. June 2008, 13:13
Ich würde erstmal vorschlagen, dass du die absoluten Calls/Jumps aus dem Assemblercode, der vor dem aktivieren des Pagings stattfindet, rausnimmst, da Labels an eine Adresse im Higher-Half zeigen und wenn du dahin springst kommt halt nur Mist raus.

Nun das ist ja doch nicht so einfach, wie ich mir das gedacht habe.
bekomme ein Page not present von Bochs....
Bei welcher Instruktion taucht denn das auf? Wäre wichtig zu wissen :wink:

Zitat
Kann ich anstatt der 4MB-Pages auch normale 4KB-Pages benutzen?
Natürlich kannst du das, aber da du (bzw. ich) sowieso später die 0-4MB nicht mehr gemappt haben möchtest, da der Kernel ja bei 0xC0000000 (bzw. halt irgendwo am oberen Ende) ist. Insofern sparst du dir den Aufwand eine page-table zu erstellen und am Ende sowieso wieder freizugeben. Das kommt natürlich nicht für lau, 4MB Pages sind erst ab dem Pentium 1 unterstützt und man muss bevor man sie verwendet Cr4.PSE (PSE = Page Size Extension, Bit 4) setzten.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 11. June 2008, 13:28
Moin
Ich habe das Higherhalf BareBones Tutorial von der OS-Dev Wiki gelesen,
und auch wenn meine Assemblerkenntnisse mehr schlecht als Recht sind, verstehe ich den Code soweit.
Link zum Tutorial (http://www.osdev.org/wiki/Higher_Half_bare_bones)
 
Ich werde den Code allerdings noch umschreiben, damit 4KB-Pages verwendet werden, damit der Code
auch auf einem älteren Prozessor läuft, vllt. auch i386  :roll: .

Dazu werde ich noch etwas Code einbauen müssen, der prüft, ob 4 MB RAM eingebaut sind. Wie ich das in ASM
realisiere, und wie ich Text mit Assembler im Protected Mode ausgebe, wenn keine 4 MB RAM installiert sind,
da werde ich schon noch dahinter kommen.
 
Kampfesgrüße Christian
Titel: Re: Speicherverwaltung
Beitrag von: nooooooooos am 11. June 2008, 13:57
Hmm also i386 ist mal sicher nicht möglich... Paging funzt erst richtig ab einem i486...

Text in Asm kannst du ausgeben, wenn du ein Byte (Buchstabe) an jedes gerade Byte ab 0xb8000 ausgibst.

Also: mov [0xb8000],'a'
mov [0xb8002],'b'

Mit den ungeraden Bytes könntest du noch die Farben der Anzeige verändern....


Speicher auslesen geht am besten mit Grub, weil ders schon macht:D...Wenn dus selbst machen willst, musst du den int 0x15 mit ax=0xE820 nehmen, um ein brauchbares Resultat (d.h. mit Angaben die stimmen, wo du nichts essenzielles im Speicher kaputt machen könntest und wo auch Speicherbereiche angegeben sind, die du nicht brauchen darfst, weil von Hardware verwendet)...


Gruss
Noooooooooooos
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 11. June 2008, 14:06
Ich hatte auch vor, das ganze mit GRUB zu machen.
Wie ich das mache, muss ich noch herausfinden. Ich kann mir ja mal die Beispiele anschaun.
 
Allerdings habe ich da noch eine Frage: Kann ich zum prüfen des RAMs einfach mem_upper, sowie mem_lower addieren?
Ich müsste dann nämlich prüfen, ob das Ergebnis größer oder gleich 4 MB ist.
Wenn es kleiner ist, wird eine Fehlermeldung ausgegeben, ansonsten geht es ganz normal weiter.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 11. June 2008, 14:13
Hmm also i386 ist mal sicher nicht möglich... Paging funzt erst richtig ab einem i486...
Huh? Wie kommst du darauf?

Zitat
Allerdings habe ich da noch eine Frage: Kann ich zum prüfen des RAMs einfach mem_upper, sowie mem_lower addieren?
Ja, mem_lower und mem_upper sind grobe Werte wieviel Speicher vorhanden ist, aber die genauen Bereiche musst du dann in der (GRUB/BIOS) memory-map nachschauen. Die genauen Bereiche brauchst du dann halt zum initialisieren deiner Speicherverwaltung.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 11. June 2008, 14:27
Das heißt, ich muss in folgende Schritten machen:


Habe ich was vergessen?
Titel: Re: Speicherverwaltung
Beitrag von: nooooooooos am 11. June 2008, 14:30
Hmm also i386 ist mal sicher nicht möglich... Paging funzt erst richtig ab einem i486...
Huh? Wie kommst du darauf?
Hatt ich mal irgendwie im Hinterkopf...aber anscheinend falsch...



EDIT: Das steht zum Beispiel in Homix' Paging Tutorial...(Ausgabe 8)

Gruss
Nooooooooooooos
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 11. June 2008, 14:49
Habe mittlerweile folgenden Code:

; Check installed RAM
push ebx
push eax
cmp ebx, (1 << 0)
je error_no_mem_ul
xor eax, eax
add [ebx], 4
mov eax, ebx
add [ebx], 4
add eax, ebx
pop eax
pop ebx

Ich muss nun nur noch prüfen, ob der wert in eax größer ist als 4096, bzw. 0x1000.
Wie mache ich das, bzw. geht das mit Compair (cmp)?
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 11. June 2008, 14:54
EDIT: Das steht zum Beispiel in Homix' Paging Tutorial...(Ausgabe 8)
Ist meines Erachtens nach trotzdem Unfug.

Zitat
Wie mache ich das, bzw. geht das mit Compair (cmp)?
Lern die Intel Manuals zu lesen oder lern zu googlen.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 11. June 2008, 15:49
Gut habs nun raus.

Eine Frage habe ich allerdings noch.
Und zwar muss ich prüfen, ob der Kernel von einem Multiboot Kompatiblen Bootloader geladen wurde.
Da ich GRUB benutze und das oberhalb als "define" stehen habe (0x1BADB002), habe ich mir gedacht, vergleiche ich das mit eax.
Wenn der vergleich schief läuft mache ich ein "Jump not equal" (jne) zur Fehlermeldung.
Das Funktioniert soweit auch, nur lasse ich meinen Kernel von GRUB laden, und es wird aber jedes mal ausgegeben, dass der Kernel nicht multiboot kompatibel ist.

hier noch ein bissel code:
MAGIC equ 0x1BADB002
....
....
cmp eax, MAGIC
jne error_not_multiboot

Wieso passiert das, wo der Kernel doch von Grub geladen wird ???

*EDIT*
Hat sich erledigt.
So was dummes...
ich hab das mit der Magic Number vom Multiboot Header verwechselt...
 
Richtig ist folgendes:
cmp eax, 0x2BADB002
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 11. June 2008, 17:01
Ich glaube, ich habe schonmal erwaehnt, dass du diese a.out-Kludge nicht brauchst, wenn du eh ELF nimmst. Magic, Flags und Pruefsumme sind absolut genug fuer einen Multiboot-ELF-Kernel. Mach die Sache nicht komplizierter als noetig.

Ach, und dass der 386 kein Paging kann, halte ich auch fuer ein Geruecht. Wahr ist aber (wenn ich mich nicht taeusche), dass erst der 486 ein invlpg kennt, beim 386 muss man den TLB immer komplett flushen.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 11. June 2008, 18:03
Dieser ist entfernt worden.

Ach, und dass der 386 kein Paging kann, halte ich auch fuer ein Geruecht. Wahr ist aber (wenn ich mich nicht taeusche), dass erst der 486 ein invlpg kennt, beim 386 muss man den TLB immer komplett flushen.
Paging gibt es seit dem 386er.
Laut dieser Website: Link (http://home.comcast.net/~fbui/intel_i.html) gibt es den Befehl invlpg erst ab dem 486er.
Wie ich den flush komplett von hand machen kann, dass der kernel auch theoretisch auf einem 386er läuft, finde ich wahrscheinlich über die Intel Docs raus, muss die mir mal intensiv zu gemüte führen.
 
Der Kernel wird geladen, ohne Reboot, mit 4 KB-Pages. Warum die physikalische Speicherverwaltung allerdings immer noch nicht funktioniert, ist mir ein Rätsel, das von mir gelöst werden will  :-D
 
Und, beinahe hätte ich es vergessen...  :-o
Vielen Dank für eure Geduld und Hilfe bei meinen "Problemchen"  :lol:

Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 11. June 2008, 18:29
Wie ich den flush komplett von hand machen kann, dass der kernel auch theoretisch auf einem 386er läuft, finde ich wahrscheinlich über die Intel Docs raus, muss die mir mal intensiv zu gemüte führen.
cr3 neu laden. Das solltest du allerdings wirklich nur auf einem 386 machen, es kostet im Vergleich zu invlpg sehr viel Performance, weil halt der gesamte TLB draufgeht.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 11. June 2008, 18:57
Nun ja...
Das wird ja auch nur einmal kurz vor der Initialisierung des Kernels aufgerufen, sobald die multiboot_info_t Struktur kopiert wurde.
 
Mal so nebenbei, ist sonst noch etwas wichtiges in den ersten 4 MB, das unbedingt gesichert werden sollte?
 

Gruß Christian

*EDIT*
Ich habe mir das boot Page Directory als Pointer an die main-Funktion übergeben lassen.
Was geschieht jetzt genau, wenn ich den Eintrag 0 auf 0 setze.
Kommt das einem invlpg[0] gleich oder würde das theoretisch auch auf einem 386er laufen?
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 11. June 2008, 20:33
Mal so nebenbei, ist sonst noch etwas wichtiges in den ersten 4 MB, das unbedingt gesichert werden sollte?
hm, das wirst du dann feststellen, wenn es knallt :-D btw. in der Multibootinfo Struktur sind auch Pointer, das musst du natürlich auch alles kopieren, wenn du es richtig machen willst. Oder das ganze eben solange gemappt lassen bis du fertig bist damit.
Ansonsten sind schon noch ein paar interessante Sachen in dem Bereich: BIOS Data Area und Extended BIOS Data Area, SMBIOS/SMP/ACPI floating pointer (und evtl. auch Teile der Tabellen). Aber die meisten Sachen kann man sich dann mappen, wenn man es denn benötigt.
hm... irgendwie hab ich grad ein Deja-vu... mir kommt es so vor als ob ich genau die gleiche Frage vor nicht allzu langer Zeit bereits beantwortet hätte, aber kA ob das in diesem Thread war oder überhaupt von dir gestellt wurde...

Zitat
Was geschieht jetzt genau, wenn ich den Eintrag 0 auf 0 setze.
Kommt das einem invlpg[0] gleich oder würde das theoretisch auch auf einem 386er laufen?
Ich denke das haben wir jetzt bereits in #lost geklärt oder?
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 12. June 2008, 08:36
Ich habe das jetzt so geregelt, dass die erste Page Table überhaupt nicht gelöscht wird. Ich muss ja später das Boot Page Directory mit dem "richtigen" Page Directory ersetzen und solange kann ich dann darauf noch zugreifen.
Aus diesem Grund brauche ich auch vorerst kein invlpg und wenn, dann kann man das ja auch anders machen. :evil:
function:
    push eax
    mov eax, cr3
    mov cr3, eax
    pop eax

hm... irgendwie hab ich grad ein Deja-vu... mir kommt es so vor als ob ich genau die gleiche Frage vor nicht allzu langer Zeit bereits beantwortet hätte, aber kA ob das in diesem Thread war oder überhaupt von dir gestellt wurde...
Nein ich kann mich nicht entsinnen, diese Frage schonmal gestellt zu haben.  :-)
 
Gruß Christian

*EDIT*
Wie hoch ist die Wahrscheinlichkeit, dass mein Kernel mehr als 4 MB, bzw 3MB (der Kernel wird nach 0x00100000 geladen) platz braucht (Microkernel)?
Wenn das nämlich hoch sein sollte, müsste ich besser bis zu load_end_addr Speicher mappen.
Vielleicht mache ich das auch gleich so....  :roll:
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 12. June 2008, 14:54
Wenn du einen Microkernel willst, dann nahe 0. Wenn du einen monolitischen Kernel mit dem meisten in extra ladbaren Modulen willst, dann auch eher gering. Wenn du alles in die Kernel-executable packen willst, vllt noch Debuginformationen, dann kann es schon passieren.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 17. June 2008, 10:58
Gut dann lass ich das so.
Allerdings habe ich gerade ein ganz komisches Problem:
 
Ich vergleiche in start.s mem_upper mit 0xC00 (3072).
Nun ist es so, dass in VMWare immer 1 MB fehlt.
Wenn ich 4 MB auswähle, hat mem_upper 2 MB anstatt 3 (umgerechnet). Benutze ich qemu oder Bochs, dann funktioniert alles so wie es soll.
 
Ist das normal?
Oder sollte ich statt jna(jump if not above) jb(jump if below) verwenden?
Hier der aktuelle code:
mov ecx, [ebx+8]
cmp ecx, 0xC00
jna error_to_less_mem


Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 17. June 2008, 12:34
Ist das normal?
Ja, da "fehlt" auch nichts.

Zitat
Oder sollte ich statt jna(jump if not above) jb(jump if below) verwenden?
Das wird in dem Fall auch nicht ändern, denn sowohl 2MB <= 3MB (not above) als auch 2MB < 3MB (below).
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 18. June 2008, 07:24
nun mir ist nur gerade aufgefallen, dass deswegen auch bei exakt 4 MB abgebrochen wird, weshalb ich das so abgeändert habe.
jna => jb

Ist das normal?
Ja, da "fehlt" auch nichts.
Das verstehe ich nicht, muss ich aber auch nicht...
 
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 18. June 2008, 12:44
Ist das normal?
Ja, da "fehlt" auch nichts.
Das verstehe ich nicht, muss ich aber auch nicht...
Es steht nirgends geschrieben, was genau das high_mem sein soll (ist halt mehr oder weniger ein Maß für die Speichergröße über 1MB, aber wie genau das zustandekommt ist eben nicht definiert), es steht aber geschrieben, dass man es eben nicht für die Speicherverwaltung hernehmen soll. Solange also die memory map in Ordnung ist, "fehlt" auch nirgends etwas.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 18. June 2008, 13:09
ich habe jetzt verstanden warum da 1 MB "Fehlt".
The maximum possible value for lower memory is 640 kilobytes. The value returned for upper memory is maximally the address of the first upper memory hole minus 1 megabyte.
Da steht ja, dass 1 MB abgezogen wird. Aber warum ist der Wert dann bei Bochs 3MB, wenn es bei VMWare 2MB ist und laut spezifikation ja der Speicher ab 1 MB - 1 MB sein soll?
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 18. June 2008, 13:12
Wir haben 4MB RAM, d.h. nach 4MB kommt das erste Speicherloch. Dann steht in deiner Erklärung, dass (4MB - 1MB) = 3MB der maximale Wert von mem_high ist. Alle Werte in den Emulatoren verletzen die zitierte Ausage nicht.

edit: Nur um das nochmal hervorzuheben, da steht "address of the first upper memory hole" :wink:
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 18. June 2008, 14:19
Ok
Ich hab das jetzt verstanden.  :-D
 
*EDIT 1*
Nun habe ich allerdings noch eine Frage:
Ab dem Pentium Pro ist es ja möglich mit 36-Bit zu Addressieren PAE-36. Nun stellt sich mir die Frage, wie bewerkstellige ich das, dass die 36 Bit in die 20 Bit für den Page-Frame passen?
Ich könnte das ganze shiften, aber woher weiß die MMU dann, welche Adresse jetzt gemeint ist, weil durch das shiften fallen ja 16-Bit weg?  :-o

Sorry hat sich erledigt. Es gibt ja die Intel Manuals  :roll:
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 26. June 2008, 15:23
SoSo...
Ich arbeite immer noch an der Speicherverwaltung  :-o
Diesmal aber zum größten Teil Konzeption, denn ich habe mir gedacht, wenn ich 512 MB mit einer Bitmap verwalten muss, kann das ja ziemlich lange dauern und eine ziemlich große Bitmap ergeben (ist ja logisch)  :lol:

Nun habe ich einige Beispiele gehört, von wegen den DMA-Space mit einer Bitmap zu verwalten, was heißt max. 16 MB und den Rest mit einem Stack, aus Geschwindigkeitsgründen.

Da ich noch am Durchdenken des Ganzen bin, wollte ich einfach mal fragen, wie ihr das in euren Projekten macht.
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: RedEagle am 26. June 2008, 15:54
Eine Liste, in der die Reservierten pages stehen,
eine Liste in der die Freien Pages stehen,
eine Liste, in der der Byteweise reservierte Speicher steht,
und eine Liste, in der der freie Byteweise reservierbare Speicher steht.
=> 4 voneinander abhängige Listen, und ne menge fast unüberschaubarer code  :evil:

Ist bestimmt nicht die Optimallösung, aber es Funktioniert  :-) ;
und es ist eine Eigenkreation, Ich habe also keine großartigen Theorien zu dem Thema gelesen, sondern einfach selber drauflos entwickelt  8-)

---
zum Thema 4MB-Pages:
Ganz zu beginn (also vor dem aktivieren des pagings) bekommt mein kernel 3 4MB-Pages (die 1. 12 Byte im Speicher, physikalische adresse == virtuelle adresse).
Ansonsten arbeite ich nur mit 4KB-Pages.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 26. June 2008, 19:57
Interface (http://code.google.com/p/pedigree/source/browse/trunk/src/system/include/processor/PhysicalMemoryManager.h)
Implementation für x86/x64: hier (http://code.google.com/p/pedigree/source/browse/trunk/src/system/kernel/core/processor/x86_common/PhysicalMemoryManager.cc) und hier (http://code.google.com/p/pedigree/source/browse/trunk/src/system/kernel/core/processor/x86_common/PhysicalMemoryManager.h).

3 Stacks mit freien Pages (4 bzw. 8byte mit der Adresse der Page, Struktur eines Stacks):
1. freie Pages über 16MB und unter 4GB
2. freie Pages über 4GB und unter 64GB
3. freie Pages über 64GB

2 Listen mit Speicherbereichen (also nur Beginn + Größe gespeichert):
* freie Bereiche unter 1MB
* freie Bereiche unter 16MB und über 1MB
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 27. June 2008, 08:42
Ich habe mir die Beispiele mal kurz angesehen

Das ganze verwirrt mich grad ein wenig...
Sollte man das so machen:
Bsp:
* Bitmap 0 bis <1MB
* Bitmap 1MB bis <16MB
* Stack für den Rest (Bis 64 GB  :evil:)
Ist jetzt von dir abgeschaut bluecode. Wenn man das so machen sollte, warum?
Ich hatte bisher immer nur die beiden letzten Punkte, also "DMA" und "Nicht-DMA".
 
Gruß Christian
 
PS: Momentan ist bei mir alles auf 32-Bit Basis  :mrgreen:
Das ganze 64-Bit Geraffel habe ich mal nach hinten verschoben, bis ich mit Version 0.0.1 fertig bin  :lol:
 
 
*EDIT*
Eine Liste, in der die Reservierten pages stehen,
eine Liste in der die Freien Pages stehen,
eine Liste, in der der Byteweise reservierte Speicher steht,
und eine Liste, in der der freie Byteweise reservierbare Speicher steht.
=> 4 voneinander abhängige Listen, und ne menge fast unüberschaubarer code  :evil:

Ist bestimmt nicht die Optimallösung, aber es Funktioniert  :-) ;
und es ist eine Eigenkreation, Ich habe also keine großartigen Theorien zu dem Thema gelesen, sondern einfach selber drauflos entwickelt  8-)
Also die Idee mit den 4 voneinander abhängigen Listen ist sicherlich nicht schlecht, allerdings leider immer sehr unüberschaubar, da ich Listen ja schon vorher immer wieder Programmiert habe :roll:

zum Thema 4MB-Pages:
Ganz zu beginn (also vor dem aktivieren des pagings) bekommt mein kernel 3 4MB-Pages (die 1. 12 Byte im Speicher, physikalische adresse == virtuelle adresse).
Ansonsten arbeite ich nur mit 4KB-Pages.
Ich hatte vorher auch 4 MB-Pages. Da der Kernel allerdings theoretisch kompatibel zu einem 386er sein soll, habe ich das ganze umgeändert und verwende 4KB-Pages.
Da ich einen HigherHalf Kernel habe, werden kurz vor dem Aufruf der main-Funktion 4 MB speicher gemappt. Das Page Directory muss ich dann später noch ersetzen.
Ich verwende auch 1 zu 1 Mapping, mappe allerdings die ersten 4 MB auch noch nach 0xC0000000, was ich ja muss  :roll:.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 27. June 2008, 15:02
Ist jetzt von dir abgeschaut bluecode. Wenn man das so machen sollte, warum?
Sollen/Müssen tut man garnichts. Es gibt natürlich noch andere (mögliche und vllt sogar andere sinnvolle :-D ) Möglichkeiten. Meine Kriterien waren folgende:
* möglichst wenig Speicherverbrauch für die Datenstrukturen zur Verwaltung
* möglichst effizienter Algorithmus zur Allokation/Deallokation von Speicherbereichen
Deshalb die verschiedenen Stacks für alles >16MB, da ein Stack eine konstante Zeit zur Allokation/Deallokation [einer Page] (aka O(1) in Landau-Notation (http://de.wikipedia.org/wiki/Landau-Symbole)) und geringen Speicherverbraucht (bzw. kein Speicherverbrauch, da man den Stack selbst langsam deallozieren kann, er besteht ja selbst aus Pages), außerdem ist m.E. ein Stack am einfachsten zu Erstellen, da man einfach die freien Pages die man draufpusht dazu verwendet den Speicherplatz für den Stack herzubekommen.
Eine Bitmap ist meiner Erfahrung nach ein ziemliches Gefrickel, da man da meistens statischen einen relativ großen Teil des physischen RAM für selbige verwendet (Mag sein, dass es da bessere Implementationen gibt, das will ich an dieser Stelle nicht ausschließen, aber ich habe glaub ich noch keine gesehen). Mit einer Bitmap bekommt man auch nur lineare Zeit zur Allokation [einer Page] hin (also O(n) in Landau-Notation) [trotzdem aber konstante Zeit zur Deallokation, nur um das auch zu erwähnen]. Außerdem ist dann der Speicherverbrauch größer als bei einem Stack, da man die Bitmap nicht mit der Zeit deallozieren kann.
So, warum nun 3 verschiedene Stacks. Das hat folgenden Grund: Teilweise braucht man Speicherseiten, die eben bestimmten Bedingungen an die Größe der Adresse genügen müssen. Beispielsweise braucht man einem 32bit PCI Gerät keine 36 oder gar 64bit Adressen andrehen. Auch kann man bei PAE für Page Directories keine 36bit Adressen verwenden, da Cr3 trotz allem nur 32bit hat. Deshalb sind m.E. drei Stacks dafür sinnvoll. Bei jeder Allokation wird dann angegeben welchen Bedingungen die Speicherseite genügen muss.
Die drei Stacks decken nun Allokationen ab, welche nicht physisch kontinuierliche Pages brauchen, da dies mit einem Stack nicht effizient implementierbar ist.

Deshalb nun die zwei (ich nenn es mal) "Range-Lists" (also Liste mit Startadresse und Größe eines Speicherbereichs), welche die Speicherbereiche <1MB bzw zwischen 1MB und 16MB verwalten und physisch zusammenhängende Speicherallokationen ermöglichen. Warum solche Rangelists? Weil die solche Allokationen selten sind und damit die Fragmentierung (und damit die Größe der Rangelist) gering ist und außerdem ist die Allokation linear (also O(n), aber mit kleinem n, da es wenig Einträge in der Liste hat). Bei der Komplexität der Deallokation bin ich mir grad nicht ganz sicher, aber ich glaube die ist bei mir auch linear (da Speicherbereiche welche zusammenhängen in einen EIntrage in der Liste gemergt werden). Bei einer Bitmap hingegen hat man eine langsamere Allokation (zwar auch O(n) afaik, aber eben größeres n, da n die Anzahl der verwalteten Pages ist) und die benötigt für meinen bzw. den Verwendungszweck auch mehr Speicher als die Rangelist (gefühlt/geschätzt!).
Warum 2 Rangelist? Teilweise braucht man Speicher <1MB, zB. wenn man über VBE (VESA BIOS Extensions) eine Modiliste bekommen möchte. Außerdem möchte man dann natürlich nicht, dass andere Geräte denen <16MB ausreichen würde <1MB bekommen, sonst geht einem evtl. im entscheidenden Moment der Speicher aus.

Ob sich das alles am Ende bewährt ist eine andere Frage, die ich noch nicht beantworten kann, da das für sich genommen natürlich alles toll klingt, aber fraglich ist zB. was passiert wenn einem zB die >16MB Speicherseiten ausgehen, obwohl noch einige in den Rangelists wären. Da muss man sich dann natürlich zu gegebener Zeit nochmal Gedanken machen.

Zitat
Also die Idee mit den 4 voneinander abhängigen Listen ist sicherlich nicht schlecht, allerdings leider immer sehr unüberschaubar, da ich Listen ja schon vorher immer wieder Programmiert habe :roll:
Wenn du deine Funktionen zur Listenmanipulation sehr allgemein fasst (wie zB die Listenimplementation von LOST für CDI [= Common Driver Interface] bzw. meine C++ Template Implementation für pedigree), dann brauchst du nicht mehrmals das gleiche wieder programmieren.
Und generell gesehen ist die Liste mit dem dynamischen Array aka Vector eine der einfachsten Datenstrukturen überhaupt. Ich denke, dass man das schon hinkriegen sollte ;-)

Ich hoffe das war ein bisschen holfreich :-)
btw. das sind die Gründe warum ich das so mache wie ich es eben mache. Ich erhebe da natürlich keinen Anspruch auf Vollständigkeit & Fehler-/Problemfreiheit.
Titel: Re: Speicherverwaltung
Beitrag von: RedEagle am 27. June 2008, 19:57
[...]
Zitat
Also die Idee mit den 4 voneinander abhängigen Listen ist sicherlich nicht schlecht, allerdings leider immer sehr unüberschaubar, da ich Listen ja schon vorher immer wieder Programmiert habe :roll:
Wenn du deine Funktionen zur Listenmanipulation sehr allgemein fasst (wie zB die Listenimplementation von LOST für CDI [= Common Driver Interface] bzw. meine C++ Template Implementation für pedigree), dann brauchst du nicht mehrmals das gleiche wieder programmieren.
Und generell gesehen ist die Liste mit dem dynamischen Array aka Vector eine der einfachsten Datenstrukturen überhaupt. Ich denke, dass man das schon hinkriegen sollte ;-) [...]

Klar kriegt man das hin, und auch unter 1000 Zeilen code :)
Die "Schwierigkeit" liegt darin, dass man andauernd prüfen muss, ob
a) Eine Liste über eine Page-grenze geht, (also um pages für eine der listen zu reservieren/frei zugeben)
b) Sich 2 elemente einer Liste zusammenfassen lassen.

Es muss also einiges an rechnleistung investiert werden, nur um die Listen zu pflegen.

---
ps.: Man sollte evtl erwähnen, das ich Elektrotechnik studiere und nicht Informatik  :mrgreen:
Ich habe also nie sowas wie softwaredesign gelernt. Ich male im prinzip ein paar bildchen, verfasse sie in Code. Und bis ich den Code soweit lauffähig hatte, vergingen einige Monate  8-)
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 27. June 2008, 21:51
RedEagle: Ich hab nicht dich gequotet und das hatte schon seinen Grund, ich wollte eigentlich eher sagen, dass Listen einfach sind :wink:

Zitat
Klar kriegt man das hin, und auch unter 1000 Zeilen code :)
200 Zeilen mit Kommentaren und in C++ Awesomeness verpackt, siehe hier (http://code.google.com/p/pedigree/source/browse/trunk/src/system/include/utilities/RangeList.h) (nur der Wrapper um die eigentliche Liste). Die eigentliche Liste hat mehr Code (siehe auch hier (http://code.google.com/p/pedigree/source/browse/trunk/src/system/include/utilities/List.h?r=475)) aber bietet halt auch einges was ein C++ STL gewöhnter Mensch so erwarten würde. Die Liste enthält auch einiges an Template-Tricksereien, um Codebloat zu vermeiden (und ist deswegen teilweise mehr Code als wirklich notwendig) und verwendet eine nette Iterator Klasse, die ziemlich viel Code spart (da sie auch von anderen Datenstrukturen verwendet werden kann).
Aber jo, in C kann man das definitiv unter 1000 Zeilen Code machen und jo, ich bin ein C++ Fanatiker. :-D

Zitat
Die "Schwierigkeit" liegt darin, dass man andauernd prüfen muss, ob
a) Eine Liste über eine Page-grenze geht, (also um pages für eine der listen zu reservieren/frei zugeben)
Versteh ich nicht wirklich, ich erlaube da nur Allokationen eines Vielfachen einer Page.

Zitat
b) Sich 2 elemente einer Liste zusammenfassen lassen.
Genau ein mal, beim Freigeben eines Speicherbereiches, siehe auch meine Implementation.

Zitat
Es muss also einiges an rechnleistung investiert werden, nur um die Listen zu pflegen.
Wie gesagt, beim Allozieren brauchst du lineare Zeit (bezogen auf die Anzahl der Einträge in der Liste), d.h. du gehst ein mal die Einträge durch und suchst dir einen passenden raus. Da es sehr wenige Einträge sind in der Liste wird es auch nicht viel Rechenaufwand sein.
Das Freigeben ist auch linear (bezogen auf die Anzahl der Einträge in der Liste), wobei ich diesmal zweimal durch die Einträge durchgehe, um einmal zu schauen ob darunter und das andere Mal, ob darüber ein Speicherbereich liegt. Auch hier gilt, da es wenige Einträge sind fällt das linear so gut wie nicht ins Gewicht.

Vorsicht: Die Ausführung bezieht sich natürlich auf mein konkretes Szenario. Es ist in keinem Fall immer so, dass linear kaum ins Gewicht fällt.

Zitat
ps.: Man sollte evtl erwähnen, das ich Elektrotechnik studiere und nicht Informatik  :mrgreen:
Ich habe also nie sowas wie softwaredesign gelernt.
Ich denke nicht, dass das viel ausmacht.
Ich studiere zwar Informatik, aber mein momentanen Wissen hat sich eher außerhalb des Studiums angesammelt. Ich bin auch erst im zweiten Semester, da sind noch nicht soviele weltbewegende theoretische Dinge in Informatik gesagt worden. Vielleicht abgesehen von der Vorlesung "Einführung in die theoretische Informatik", aber die hat bis jetzt nichts mit dem hier angeschnittenen Thema zu tun.
Titel: Re: Speicherverwaltung
Beitrag von: Korona am 27. June 2008, 22:37
Um einen freien Speicherbereich beliebiger Größe zu finden kannst du ja einen B-Tree mit Knotengröße = Pagesize implementieren, wobei du für jedes Element jeweils die Größe des Blocks (als Schlüssel) und die Addresse speicherst. Damit hast du O(log n) statt O(n) Laufzeit. Falls man zu jedem Knoten noch die Addresse des nächsten Blocks und des vorherigen Blocks speichert + ein Flag das anzeigt ob diese frei oder belegt sind, kann man Speicherblöcke auch in O(1) spalten (oder in O(log n), wenn man den abgespaltenen Speicherblock wieder in den Tree einfügt) oder wieder zusammenführen. So werde ich warscheinlich meinen virtuellen Speichermanager implementieren, wenn ich irgentwann mal Zeit habe den zu überarbeiten (im Moment ist mir das noch zuviel Overkill und mir sind andere Features wichtiger :D). Bis jetzt habe ich ihn nur als binären Suchbaum implementiert, was eine worst-cast Laufzeit von O(n) hat.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 01. July 2008, 13:16
Ahoi,
also ich habe mich nun für folgendes Modell entschieden:
Wie ich das dann mache, wenn aufeinanderfolgender Speicher überhalb des DMA-Bereichs reserviert werden soll, werde ich zu gegebener Zeit nachschauen, was so wie ich das gelesen habe recht schwer ist mit einem Stack :roll:.
 
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 01. July 2008, 15:09
Wie ich das dann mache, wenn aufeinanderfolgender Speicher überhalb des DMA-Bereichs reserviert werden soll, werde ich zu gegebener Zeit nachschauen, was so wie ich das gelesen habe recht schwer ist mit einem Stack :roll:.
Ich würde es als nicht praktikabel bezeichnen. Wie gesagt, wenn jemand zusammenhängenden RAM braucht, dann kriegt er den bei mir (pedigree) aus dem <16MB Allokator. Das kommt m.E. nicht häufig vor und es werden auch nicht große Stücke sein, insofern halte ich es für vertratbar.
Titel: Re: Speicherverwaltung
Beitrag von: jgraef am 03. July 2008, 15:06
Wie ich das dann mache, wenn aufeinanderfolgender Speicher überhalb des DMA-Bereichs reserviert werden soll, werde ich zu gegebener Zeit nachschauen, was so wie ich das gelesen habe recht schwer ist mit einem Stack

Wenn ein Programm "normalen" zusammenhängenden Speicher haben will, ist es doch egal ob dieser physisch zusammenhängt. Er muss nur virtuell zusammenhängen.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 03. July 2008, 16:34
Wie ich das dann mache, wenn aufeinanderfolgender Speicher überhalb des DMA-Bereichs reserviert werden soll, werde ich zu gegebener Zeit nachschauen, was so wie ich das gelesen habe recht schwer ist mit einem Stack

Wenn ein Programm "normalen" zusammenhängenden Speicher haben will, ist es doch egal ob dieser physisch zusammenhängt. Er muss nur virtuell zusammenhängen.
Wo steht da irgendwas von Programm? :wink: Es geht hier eher um speziellere Allokationen innerhalb des Kernels.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 04. August 2008, 14:36
Es funktioniert...
*freu*
 
Nach einer Pause und dem Neuschreiben der Speicherverwaltung funktioniert diese nun, zumindest der Part mit der Bitmap.
Auch einen Stack habe ich drinne, da muss ich bei der Initialisierung allerdings noch die Adressen speichern. (Dafür habe ich schon so eine Idee)
 
Momentan muss ich aber erst einmal schauen, wie ich mit der Memory Map von GRUB den RAM zählen kann, denn mem_end_page (Variable mit der Adresse der letzten Speicherseite) wird bei der Bitmap, sowohl auch bei dem Stack verwendet.
Mit der GNU GRUB Dokumentation und den Beispielen habe ich folgendes Stück Quellcode erstellt:
/* Eine globale Variable, vielleicht auch später lokal :D */
unsigned int mem_end_page = 0;
...
if(CHECK_FLAG(mbt->flags, 6))
{
memory_map_t *mmap;

for(mmap = (memory_map_t *)mbt->mmap_address;
(unsigned long)mmap < mbt->mmap_address + mbt->mmap_length;
mmap = (memory_map_t *)((unsigned long)mmap + mmap->size + sizeof(mmap->size)))
{
mem_end_page += (unsigned int)(mmap->length_low + mmap->length_high);
}
}
Was haltet ihr davon, bzw. wie erfasst ihr die Größe des Arbeitsspeichers?
 
Gruß Christian
 
*EDIT*
So eben habe ich das Stück Quellcode eingebaut und es hat auf anhieb funktioniert  :-D
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 04. August 2008, 18:48
Was haltet ihr davon, bzw. wie erfasst ihr die Größe des Arbeitsspeichers?
Die Größe interessiert mich meistens gar nicht so sehr. ;)

Als brauchbare Näherung kann man mem_upper + 1 MB aus der Multiboot-Info nehmen.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 04. August 2008, 21:42
Nun ja...
mem_upper + 1024 verwende ich vor dem Aufruf der main-Funktion, da mind. 4MB RAM benötigt werden  :-D
 
Die Memory Map so wie in dem Stück Quellcode oben wird bei der Initialisierung der Physikalischen Speicherverwaltung benutzt.
 
 
Jetzt habe ich aber noch eine Frage:
Und zwar habe ich für den nicht DMA-Bereich einen Page Stack, wo ich beliebig Adressen runter nehmen und wieder drauf legen kann.
unsigned int *phys_mem_stack;
unsigned int phys_mem_stack_top;

/* Returns the address of a single page (allocated) */
unsigned int phys_mem_stack_pop(void)
{
/* No free physical Memory. panic should be replaced with a swap function later */
if(!phys_mem_stack_top)
panic("Out of Memory. Try Using DMA-Allocator");

return(phys_mem_stack[--phys_mem_stack_top])
}

/* push a address back to the stack (free it) */
void phys_mem_stack_push(unsigned int physical_address)
{
phys_mem_stack[phys_mem_stack_top++] = physical_address;
}
Wenn ich nun eine solche Adresse reserviere, wird die ja dann später in dem Page-Frame gespeichert.
Daraus schließe ich, dass ich nur den Stack mit den freien Pages brauche  :roll:
 
Wenn das so richtig ist, wie ich mir das denke, dann bin ich zumindest mit der hälfte fertig. Bei der anderen Hälfte sind noch ein paar ToDo's offen...  :mrgreen:
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 05. August 2008, 13:30
Ja, es reicht immer, den freien Speicher zu verwalten. Den besetzten verwaltet schon der Benutzer.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 08. August 2008, 08:33
Das ist sehr gut, dann bin ich schon mal mindestens zur Hälfte fertig.
 
Ich stehe momentan aber irgendwie auf dem Schlauch...
Ich versuche eine Funktion zu schreiben, die eine Anzahl von Speicherseiten sucht und die erste zurück gibt.
Ich habe mir auch die in LOST verwendete Lösung angesehen, aber diese gefällt mir nicht. Die Reservierung ist klar, allerdings ist die Suchfunktion etwas komisch. Da wird gesucht und wenn es heißt, ja found ist größer als num... ...geben wir mal die erste Adresse zurück.

Gibt es da noch eine andere Möglichkeit?
Diese Funktion brauche ich ja nur bei der bitmap, bei dem Stack würde sich das als recht Schwiereig erweisen, und da habe ich auch keine Lust, sowas zu machen...  :roll:
unsigned int physical_dma_find_page_range(unsigned int num);

Gruß Christian
 
PS: Ich möchte hier keine Lösungen von euch, sondern lediglich Anregungen, wie man das machen könnte.
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 08. August 2008, 14:08
Ich versuche eine Funktion zu schreiben, die eine Anzahl von Speicherseiten sucht und die erste zurück gibt.
Ich habe mir auch die in LOST verwendete Lösung angesehen, aber diese gefällt mir nicht. Die Reservierung ist klar, allerdings ist die Suchfunktion etwas komisch. Da wird gesucht und wenn es heißt, ja found ist größer als num... ...geben wir mal die erste Adresse zurück.
Wie willst du es sonst machen? Du fängst an zu schauen, ob ausgehend von der ersten Seite genug freie Seiten am Stück vorhanden sind, und wenn ja, kannst du die nehmen. Wenn nein, muß man eben mit der nächsten freien Seite als erster Seite des Bereichs weiterprobieren.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 13. August 2008, 08:22
Mmmhhh...
Mir kommt da gerade so eine Idee...
 
Ich denke man könnte das auch in folgenden Schritten lösen:

Dies oben ist eine Idee, die mir eben gekommen ist und ist noch nicht programmiert worden.
Bei einer leeren Bitmap dürfte es kein Problem sein, dies zu implementieren. Wie das allerdings bei einer stark benutzten bitmap ist, muss ich prüfen...
Was denkt ihr dazu?
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 13. August 2008, 10:26
Damit machst du eigentlich das gleiche, nur daß du Bereiche übersiehst, die sich über zwei Bitmapeinträge erstrecken. Außerdem hast du dir damit eine maximal allozierbare Größe von 32 Seiten (wenn deine Bitmap aus 32-Bit-Integern besteht) eingehandelt.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 13. August 2008, 10:38
Damit machst du eigentlich das gleiche, nur daß du Bereiche übersiehst, die sich über zwei Bitmapeinträge erstrecken. Außerdem hast du dir damit eine maximal allozierbare Größe von 32 Seiten (wenn deine Bitmap aus 32-Bit-Integern besteht) eingehandelt.
Das habe ich noch nicht bedacht.
Aber das Konzept muss nicht unbedingt auf max 32 Speicherseiten beschränkt sein. Allerdings müsste ich mir dafür jetzt dazu noch etwas einfallen lassen.
 
Allerdings würde dies im Endeffekt dann auf das gleiche hinauslaufen, wie in dem Code von LOST, wenn ich das richtig überlege...  :roll:
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 13. August 2008, 13:22
Richtig. Deswegen auch mein "Wie willst du es sonst machen?".
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 13. August 2008, 14:23
Vielleicht eröffnet sich mir ja noch eine Möglichkeit  :evil:
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 02. September 2008, 10:12
So!
Die physikalische Speicherverwaltung das Paging sind eingebaut.
 
Allerdings stellt sich mir hier noch eine Frage!
Ich muss ja den Kernel mappen, was soweit auch geschieht. Nun wird aber, wenn der Speicher z.B. 4 MB beträgt aufgeteilt in 2MB DMA verwaltet von der Bitmap und 2 MB normal verwaltet von einem Stack.
 
Ich lasse meinen Kernel Physikalische Speicherseiten reservieren vom DMA Part, was wie mir gerade auffällt nicht korrekt funktioniert, da einige physikalische Bereiche ja bereits als benutzt in der bitmap abgelegt werden.
Das würde heißen, beim Mappen des physikalischen Speichers müsste ich das ja eigentlich wie folgt machen:
unsigned int address, virt;
for(address = 0, virt = 0xC0000000; address < (load_end_address+(load_end_address%0x1000)); address += 0x1000, virt += 0x1000)
{
  set_bitmap_entry(address);
 
  map_address(address, address, 1, 1);
  map_address(address, virt, 1, 1);
}

Nun bin ich mir allerdings nicht mehr ganz sicher, was den Speicher betrifft.
Der Kernel wird an die Stelle 0x00100000 also ans erste MB geladen.
Die GRUB-Multiboot Struktur befindet sich irgendwo in den ersten 4 MB, was heißt, dass ich herausfinden muss, ob dies hinter load_end_address ist oder nicht und das dann je nach dem load_end_address ändern muss.
Was auch noch berücksichtigt werden muss, sind die Module, damit diese nicht überschrieben werden.
 
Ist sonst noch etwas wichtiges, worauf unbedingt geachtet werden muss?
 
Grüße Christian
 
*EDIT*
Und noch etwas. Ist es sinnvoller die physikalischen Speicherseiten für den Kernel Heap vom Stack zu nehmen? Oder sollte doch besser der DMA-Part dafür hinhalten.
Titel: Re: Speicherverwaltung
Beitrag von: Termite am 02. September 2008, 10:35
Moin

korrigiert mich wenn ich da falsch leige. es geht doch gerade darum, phisikalische speicherseiten mittels paging in einen logischen speicher einzubinden?

Wenn dem so ist, ist es doch nicht zwingend notwendig, das n seiten genau am stück im physikalischen speicher liegen, es müssen nur n seiten in der logischen speicherverwaltung angehängt werden, und das natürlich vortlaufend. Wo die sich jetzt physikalisch befinden ist doch egal. Das ist doch gerade der vorteil des Pagings. Und wenn ich seiten im speicher nicht brauche, oder ich mehr speicher brauche als gerade frei ist, kann ich die sogar auslagern wenn ich lustig bin.

gruss
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 03. September 2008, 12:33
Das habe ich mir auch gerade gedacht...
 
Und jetzt habe ich da noch eine generelle Frage:
Welche Möglichkeiten gibt es denn, einen Heap Manager einzubauen? (Für den Kernel)
 
Folgende Möglichkeiten sind mir eingefallen oder habe ich irgendwo mal gesehen:

Was verwendet ihr?
Was ist eurer Meinung nach am sinnvollsten?
 
Ich würde zur verketteten Liste greifen.
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 03. September 2008, 12:59
Ein Array ist wohl eher nicht sinnvoll, aber wahrscheinlich meinst du eine Bitmap... die ist im Zusammenhang mit Buddy Allocation sinnvoll.
Ich würde sowenig wie möglich beim Allozieren auf ein allgemeines "malloc" ausweichen, sondern eher mit spezielleren Allokatoren arbeiten (also zB einen für fixed-size messages, etc...), da man da weiß wie groß die Objekte sind und das alles die gleichen Objekte sind. Die Allokatoren klauen sich dann Pages direkt vom physischen Speichermanagement. Damit kann man mit Sicherheit Fragmentation vermeiden und es ist bestimmt schneller bei so kritischen Sachen wie Messages. Sind aber wie immer nur meine 0,02€.

Paar Links mit Infos:
http://wiki.osdev.org/Memory_Allocation#Tips_to_go_further
http://wiki.osdev.org/Page_Frame_Allocation#Tree-based_approach.

Zwei Implementationen:
http://g.oswego.edu/dl/html/malloc.html
http://www.hoard.org/

edit: Es ist übrigens imho "kinderleicht" dlmalloc (bei hoard hab ich es noch nicht probiert) zu portieren (sowohl kernel- als auch userspace).
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 03. September 2008, 13:24
Nun ja ich hatte das ja so in der Art geplant, wie das bei dem ersten Link steht.
Mehrere Pools und zwar für Multitasking Strukturen (tss-, task- und vm86-Struktur), IPC, der ganze rest, wie z.B. Verkette Listen. :D
 
Mal schauen, wie ich das mache. Wahrscheinlich werde ich den Baum nehmen, da dies mich am ehsten anspricht. :)
 
*EDIT*
Was ich ja eigentlich auch machen könnte, wäre einen Heap Manager mit einem normalen malloc() allerdings festen Größen.
Bsp.:
// Größe einer Nachricht in Bytes
#define IPC_MESSAGE 2048
void alloc_message(task_t *task)
{
     /*.....*/
     unsigned char *message = (unsigned char *)malloc(ipc_heap, sizeof(message)*IPC_MESSAGE);
     /*.....*/
}
Die größen und die Funktion sind fiktiv und (noch) nicht vorhanden.
 
Somit hätte ich verschiedene Speicherpools, aber nur eine Funktion zum reservieren des Speichers.
 
Was meint ihr dazu?
 
*EDIT 2*
Mein erstes Ziel ist erst einmal einen Heap Manager einzubauen, der für den ganzen sonstigen Kram zuständig ist, wie z.B. eine Verkettete Liste für irgendwas im Kernel. Das Beispiel ist nicht sehr schön.
Danach werde ich das ganze so ändern, dass man mit der malloc()-Funktion von verschiedenen Heaps speicher reservieren kann.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 13. October 2008, 11:33
Nun denn...
ich bin ein wenig weiter. Ein wenig deswegen, weil ich nicht so viel Zeit hatte. :roll:
Ich habe mich für einen AVL-Baum entschieden und nun eine kleine Frage:
In jedem Knoten wird ein balance-Wert gespeichert. dieser ist je nachdem < -1, -1, 0, 1 oder > 1. Ist der Wert kleiner -1 oder größer 1, muss der Knoten neu ausbalanciert werden, was ich hinbekommen habe.
 
Nun muss ich allerdings nach jedem einfügen oder löschen eines Knotens jeden einzelnen balance-Wert neubestimmen. Laut wikipedia muss dies rekursiv gelöst werden, das könnte ich mir auch nicht anders vorstellen.
 
Allerdings bräuchte ich ein paar anreize, wie man das lösen könnte.
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 13. October 2008, 11:49
Ich habe gerade gestern einen entsprechenden Patch für LOST rausgeschickt: http://list.tyndur.org/pipermail/lost/2008-October/000923.html

Das Ergebnis sieht nicht offensichtlich falsch aus, allerdings würde es mich nicht wundern, wenn doch noch der eine oder andere Fehler drinsteckt. Der Code um diesen Balance-Wert aktuell zu halten, macht definitiv keinen Spaß. Das nachvollziehen zu wollen sorgt in erster Linie für Knoten im Hirn. :|
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 19. October 2008, 17:04
Also der balance-Wert eines neu eingefügten Knotens ist 0, das ist ja offensichtlich, da die beiden Kinder NULL beinhalten.
Nun muss ich allerdings nach dem Einfügen eines Elements alle balance Werte darüber prüfen und gegebenenfalls ändern. Danach muss ich dann eine Funktion drüberlaufen lassen, die die balance-Werte aller Knoten prüft und eventuelle Rotationen vornimmt. Im schlechtesten Fall wäre dies der komplette Baum.  :roll:
 
Das ist, was ich mir dabei gedacht habe. Habe ich vielleicht etwas vergessen, das ich bei der Implementation unbedingt berücksichtigen muss?
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 20. October 2008, 00:03
Ausgehend vom neu eingefügten Knoten von unten nach oben durchgehen reicht, im Rest vom Baum kann sich die Balance nicht ändern.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 20. October 2008, 08:48
Allerdings muss ich dann, nachdem ich alles geprüft und falls nötig geändert habe, die Höhe der beiden Teilbäume vom Wurzelknoten aus prüfen und gegebenenfalls rotieren, da durch das einfügen ein rechter oder linker überhang entstehen kann.
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 20. October 2008, 11:29
Das kannst du alles in einem Zug machen. Nach dem Knoten einfügen von unten nach oben durchgehen und überall die Balance anpassen. Wenn die Balance irgendwo unterwegs 2 oder -2 wird, erstmal rotieren bevor man zum Vaterknoten weitergeht.

Und das ist das auch so ziemlich die einzige wirklich nicht offensichtliche Stelle: Wie ändert sich die Balance der Knoten nach einer Rotation? Du willst ja nicht immer den ganzen Baum durchgehen, sonst kannst du gleich eine verkettete Liste nehmen und bist noch performanter.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 20. October 2008, 13:41
Gut soviel ist mittlerweile klar.
Nun sitze ich vor der Funktion zum berechnen der Höhe eines Teilknotens. Der balance-Wert berechnet sich ja, in dem man die höhe des Linken Teilbaums von der Höhe des rechten Teilbaumes subtrahiert.
 
Wikipedia sagt, dies wird rekursiv gelöst, das habe ich auch gemacht. Die Funktionen sehen wie folgt aus:
unsigned int internal_calculate_avl_tree_balance_factor(avl_node_t *node)
{
    unsigned int retval = 1;

    /* if left and right node are NULL the lowest part has been reached */
    if((node->left == NULL) && (node->right == NULL))
        return(0);
    else
    {
        if(node->right != NULL)
            retval += internal_calculate_avl_tree_balance_factor(node->right);
        if(node->left != NULL)
            retval += internal_calculate_avl_tree_balance_factor(node->left);
    }

    return(retval);
}


/* Function calculates the new balance factor */
unsigned int calculate_avl_tree_balance_factor( avl_tree_t *tree, avl_node_t *node)
{
    unsigned int retval1 = 0;
    unsigned int retval2 = 0;
    avl_node_t *left, *right, *local_node;
/* Check if node is NULL. This should never happen */
if(node == NULL)
panic("AVL Error: node contains NULL!\nNULL is not a valid address!");

if(tree->root_node == NULL)
{
    return(0);
}
else
{
    retval1 = internal_calculate_avl_tree_balance_factor(node->right);
    retval2 = internal_calculate_avl_tree_balance_factor(node->left);

    return( retval2 - retval1 );
}
}
Meine Logik sagt mir, das sollte so funktionieren...
Mein Gefühl sagt mir allerdings, dass da noch etwas fehlt, aber ich komme nicht drauf.
Könnt Ihr mir sagen, ob der Code so richtig ist? Ich habe momentan keine Möglichkeit das ganze zu testen, weswegen ich hier poste.
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: bluecode am 20. October 2008, 16:22
hm, ich kenn mich mit Bäumen zwar nicht so sehr aus, aber m.E. berechnest du in internal_calculate_avl_tree_balance_factor die Anzahl der Knoten (ohne Blätter) des Baumes. Du müsstest m.E. nach nur den größeren Wert von internal_calculate_avl_tree_balance_factor(node->right) und internal_calculate_avl_tree_balance_factor(node->left) hinzufügen. Ich mein die Höhe unterhalb (inklusive) dieses Knotens ergibt sich ja aus 1 + max{rechts, links}.

edit: Wobei mir gerade auffällt, dass du doch eigentlich in der Funktion die Balance berechnen wolltest... :|
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 20. October 2008, 18:18
unsigned int internal_calculate_avl_tree_balance_factor(avl_node_t *node)
{
    unsigned int retval = 1;

    /* if left and right node are NULL the lowest part has been reached */
    if((node->left == NULL) && (node->right == NULL))
        return(0);
    else
    {
        if(node->right != NULL)
            retval += internal_calculate_avl_tree_balance_factor(node->right);
        if(node->left != NULL)
            retval += internal_calculate_avl_tree_balance_factor(node->left);
Sollte das nicht ein -= sein?

Davon abgesehen ist diese Berechnung genau das, was du willst, weil du dazu den ganzen Baum anschauen mußt. Bei nur einem Knoten ist die Balance trivialerweise 0 und beim Einfügen oder Löschen ändert sich nur lokal was. Wenn du diese lokale Änderung richtig hinkriegst, mußt du nie die Balance auf diese Weise ausrechnen, sondern nur an den passenden Stellen was addieren oder subtrahieren.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 20. October 2008, 19:02
Nun, ich füge einen Knoten ein.
Dessen balance-Wert ist 0, das ist mir schon klar. Allerdings muss ich dann den balance-Wert des Elternknotens neuberechnen. Dies bewerkstellige ich, in dem ich die Höhe des linken Teilbaums von der höhe des rechten Teilbaums abziehe.
So gesehen muss ich nach dem Einfügen, bzw. Löschen eines Knotens den Baum von der Stelle aus nach oben gehen und den balance-Wert neu berechnen. Ändert sich dieser jetzt nach 2 oder -2 muss ich rotieren.
 
Aber wie soll ich denn den balance-Wert deiner Meinung nach berechnen? Ich muss von dem Knoten aus die höhen des rechten und linken unterbaumes berechnen. Das heißt, ich muss irgendwie zum tiefsten Knoten kommen den es gibt.
 
Mmmmhhh...
Mir wird schon noch ein Einfall kommen wie ich das bewerkstellige, doch momentan ist das ein kleines Hindernis, an dem ich nicht vorbeikomme, weil ich irgendwo auf dem Schlauch stehe.
 
EDIT:
So wie ich das sehe ist das wie folgt.
Durch das Einfügen eines neuen Knotens wird der balance-Wert des Elternknoten des Elternknotens um eins verringert, bzw. erhöht oder liege ich da falsch?
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 20. October 2008, 21:32
So wie ich das sehe ist das wie folgt.
Durch das Einfügen eines neuen Knotens wird der balance-Wert des Elternknoten des Elternknotens um eins verringert, bzw. erhöht oder liege ich da falsch?
Genau.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 21. October 2008, 09:35
Warum habe ich das nicht gleich so gemacht...  :roll:
 
Ich habe mir ein kleines Programm gebastelt, das einen AVL-Baum zusammen baut. Bis auf die Funktionen zum Löschen eines Knotens und zum Darstellen/Ausgeben des Baums, scheint alles soweit zu funktionieren.
Hier ist der geschriebene Quellcode: http://rafb.net/p/1zNXWH89.html
 
Gruß Christian
 
PS: Vielleicht habe ich auch einen Fehler drinne, denn ob das wirklich Fehlerfrei ist, kann ich nicht sagen. Gut ich habe den Baum getestet und er hat auch immer dann balanciert, wenn er musste, trotzdem bleibt eine kleine Unsicherheit.  :-)
 
EDIT
Anscheinend ist die Berechnung der balance nach dem rotieren doch nicht richtig  :|
 
EDIT 2
Ich habe den Fehler anscheinend gefunden. Nachdem ich in der funktion zum rotieren nach rechts aus dem Aufruf MAX ein MIN gemacht habe, hat es funktioniert.
Hier der Link: http://rafb.net/p/lPLs5012.html
Nur einen etwas kuriose Eigenart habe ich noch. Und zwar wird in der funktion zum balancieren geschaut, ob der balance-Wert kleiner -1 oder größer 1 ist.
Gebe ich den balance-Wert aus, so ist dieser 0. Allerdings wird jedes mal die If-Bedingung ausgeführt, ob der balance-Wert jetzt 2, bzw. -2 ist oder nicht. Irgendwas habe ich da übersehen....
 
EDIT 3
Eine kleine Frage habe ich noch. Ich muss ja den Elternknoten des Elternknotens erhöhen, bzw. verringern. Wenn ich aber beim Elternknoten den balance-Wert um 1 erhöht habe, muss ich dann beim Elternknoten des Elternknotens den balance-Wert um 2 erhöhen oder?
Damit dieser wenn ein überhang entsteht entsprechend rotiert. Also anstatt dem ++ im Quellcode ein +=2!
 
EDIT 4
Nachdem ich nun den kompletten bisherigen Code verworfen und neugeschrieben habe funktioniert nun alles. Was jetzt noch fehlt ist die Funktion zum entfernen eines Knotens, aber das werde ich wahrscheinlich auch noch hinbekommen. Wenn interesse besteht, werde ich den Code hochladen und hierher verlinken.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 02. November 2008, 21:17
Immer ist irgendetwas, mit dem ich mich ärgere weil es nicht funktioniert.
Ich wollte eben meine physikalische Speicherverwaltung testen. Der Stack funktioniert tadellos, die Bitmap allerdings mal wieder nicht...
Ich finde den Fehler nicht! In einer Funktion, die in einer Endlosschleife läuft wird in jedem durchlauf eine Seite gesucht und diese dann reserviert mittels setzen in der Bitmap. Nur funktioniert das setzen wie schon einmal nur bei 0. Sobald der Rückgabewert 1 ist, wird die Page nicht mehr gesetzt.
Hier mal der Quellcode:
bitmap.h
#ifndef __BITMAP_H__
#define __BITMAP_H__

#include <multiboot.h>
#include <system.h>


#define INDEX_FROM_BIT(a) (a/(8*4))
#define OFFSET_FROM_BIT(a) (a%(8*4))
#define BIT(a) (0x1<<a)


extern unsigned int *physical_bitmap;
extern unsigned int nphysical_bitmap;
extern unsigned int num_dma_pages;
extern unsigned int placement_address;


extern unsigned int phys_mem_dma_find_free_page(void);
extern unsigned int phys_mem_dma_find_free_page_range(unsigned int num);
extern unsigned int phys_mem_dma_find_free_page_range_index(unsigned int lower_index, unsigned int num);

extern void phys_mem_dma_set_page(unsigned int physical_address);
extern void phys_mem_dma_reset_page(unsigned int physical_address);
extern unsigned int phys_mem_dma_test_page(unsigned int physical_address);

extern unsigned int phys_mem_dma_available(void);

extern void initialise_phys_dma_mem_manager(multiboot_info_t *mbt);

#endif
bitmap.c
#include <mm/physical/bitmap.h>
#include <mm/kheap.h>
#include <mm/paging.h>

unsigned int *physical_bitmap;
unsigned int nphysical_bitmap;
unsigned int num_dma_pages;

void phys_mem_dma_set_page(unsigned int physical_address)
{
    if(physical_address == -1)
        PANIC("INVALID ADDRESS");

unsigned int frame = physical_address / PAGE_SIZE;
unsigned int index = INDEX_FROM_BIT(frame);
unsigned int offset = OFFSET_FROM_BIT(frame);

physical_bitmap[index] |= BIT(offset);
}

void phys_mem_dma_reset_page(unsigned int physical_address)
{
    if(physical_address == -1)
        PANIC("INVALID ADDRESS");

unsigned int frame = physical_address / PAGE_SIZE;
unsigned int index = INDEX_FROM_BIT(frame);
unsigned int offset = OFFSET_FROM_BIT(frame);

physical_bitmap[index] &= ~(BIT(offset));
}

unsigned int phys_mem_dma_test_page(unsigned int physical_address)
{
    if(physical_address == -1)
        PANIC("INVALID ADDRESS");

unsigned int frame = physical_address / PAGE_SIZE;
unsigned int index = INDEX_FROM_BIT(frame);
unsigned int offset = OFFSET_FROM_BIT(frame);

return( (physical_bitmap[index] & BIT(offset)) );
}

unsigned int phys_mem_dma_find_free_page(void)
{
unsigned int i, j;

for(i = 0; i < INDEX_FROM_BIT(nphysical_bitmap); i++)
{
if(physical_bitmap[i] != 0xFFFFFFFF)
{
for(j = 0; j < 32; j++)
{
if( !(physical_bitmap[i] & BIT(j)) )
return( i*4*8+j );
}
}
}

return(-1);
}

unsigned int phys_mem_dma_available(void)
{
unsigned int i, j, retval = 0;
for(i = 0; i < INDEX_FROM_BIT(nphysical_bitmap); i++)
{
if(physical_bitmap[i] == 0xFFFFFFFF)
retval += 32;
else
{
for(j = 0; j < 32; j++)
{
if( !(physical_bitmap[i] & BIT(j)) )
retval++;
}
}
}
return(retval);
}

void test_manager(void)
{
    unsigned int page = 0;
    for(;;)
    {
        page = phys_mem_dma_find_free_page();
        printf("%i\t", page);
        printf("%i\t", phys_mem_dma_available());
        phys_mem_dma_set_page(page);
    }
}

 
 
An der Funktion zum Reservieren von Speicher (kmalloc) kann es nicht liegen, denn dann würde der Stack Manager auch nicht funktionieren. Des Weiteren habe ich herausgefunden, dass das setzen der Bitmap auf 0xFFFFFFFF funktioniert, denn wenn alles auf 0xFFFFFFFF gesetzt ist, springt die Funktion zum belegen einer physikalischen Seite in die IF-Abfrage rein:
int i;

for(i = 0; i < INDEX_FROM_BIT(nphysical_bitmap); i++)
        physical_bitmap[i] = 0xFFFFFFFF;

    for(i = 0; i < INDEX_FROM_BIT(nphysical_bitmap); i++)
        printf("0x%x\t", physical_bitmap[i]);
Folglich muss der Fehler beim suchen nach einer freien Seite oder beim Setzen eines Eintrags sein, doch kann ich keinen Fehler erkennen. Ich weiß auch nicht, warum der Code auf einmal nicht mehr funktioniert, da er ja zuvor gelaufen ist.  :roll:
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 03. November 2008, 10:20
 :oops:
Ich habe so einige dumme Anfänger-Fehler gemacht, wie mir gerade auffällt. Einer davon ist z.B. bei einem Rückgabetyp unsigned int -1 zurückzugeben, das kann ja nicht funktionieren!  :roll:
 
Ich sehe schon, da muss ich wohl nochmal ran. Ich werde das ganze so abändern, dass die Adressen alle als void pointer übergeben, bzw. zurückgegeben werden. Dieser wird dann je nach dem entsprechend konvertiert.
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 19. December 2008, 14:51
Soso...
ich habe da nochmal eine Frage:
Und zwar braucht man für das Paging ja physikalische Adressen. So weit ist das kein Problem, denn die physikalische Speicherverwaltung funktioniert.
 
Wenn ich also eine neue Page Table brauche, reserviere ich Speicher mit dem physikalischen Speichermanager. Das funktioniert, nur der Zugriff nicht, da die Adresse logischerweise nicht gemappt wurde.
Lange rede kurzer Sinn, es tritt ein Page Fault auf, da wie bereits geschrieben, die Adresse nicht gemappt ist.
 
Ein möglicher Weg wäre, den Speicher an virtuelle Stelle zu mappen und dann zu bearbeiten. Dies würde allerdings nur funktionieren, solange ich kein neues Page Table benötige. Wie kann man das obengenannte Problem noch lösen oder gibt es da keine anderen Möglichkeiten?
 
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: MNemo am 19. December 2008, 17:55
ich löse das so, dass ich eine Page Table im Kernelspace dauerhaft gemapped habe. In dieser PageTable sind ein paar Einträge nur darfür resserviert Pages temporär zu mappen, so dass ich an einer fixen Addresse auf ihren Inhalt zugreifen kann.
Damit habe ich das problem nicht, dass ich evtl. eine neue PageTable benötige.

Eine andere Möglichkeit auf physikalische Addressen zu zugreifen, als sie zu mappen, gibt es AFAIK nicht.
Titel: Re: Speicherverwaltung
Beitrag von: kevin am 19. December 2008, 20:01
Wenn du einen Eintrag im PD auf das PD selbst zeigen läßt, hast du an der Stelle 4 MB im virtuellen Adreßraum reserviert, in denen alle Pagetables hintereinander gemappt sind. Ist auf den ersten Blick verwirrend, aber auf den zweiten recht praktisch. ;)
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 20. December 2008, 14:30
mmhhh...
Also würde das dann so aussehen:
Beim Initialisieren des Paging mappe ich das Page Directory in einen freie Page Table Eintrag.
Brauche ich nun eine neue Page Table, z.B. für die Adresse 0xD0000000, so muss ich den entsprechenden Eintrag setzen und dann über den Eintrag mit dem Page Directory diesen Eintrag z.B. mit erst mit "0|0x2" und dann mit der Adresse befüllen.
 
Allerdings müsste ich dies ja dann überall machen...
mal schauen, wie ich das dann löse.
 
Danke für die Antworten.
Gruß Christian
Titel: Re: Speicherverwaltung
Beitrag von: ChristianF am 22. December 2008, 18:15
So...
ich habe das Page Directory einfach mal in dem Index 1 abgelegt.
Nun gehe ich beim anlegen eines neuen Page Table Eintrags wie folgt vor:
Bis zum letzten Punkt ist mir alles klar.
Nun ist der eigentliche Index im Page Directory an den das Table gemappt wird, jedoch 832. Gibt es dafür einen bestimmten Grund?
Des Weiteren ist die "richtige" Nummer ja 2048+831, da ich mich ja im 3. Page Directory befinde.
 
Allerdings bekomme ich beim Zugriff auf diese Adresse einen Page Fault, wo der Handler mir mitteilt, dass die Adresse nur lesbar ist.
Der Page Table Eintrag wird so gemappt:
unsigned int pdir_flags = (PTE_PRESENT|PTE_WRITEABLE|PTE_USERMODE);
printf("\n\npdir_flags = 0x%x\n", pdir_flags);
page_dir[table_idx] = (unsigned int)table;
page_dir[table_idx] |= pdir_flags;
Allerdings sollte der Fehler ja nicht hier liegen oder doch?
 
Hier ist der Zugriff auf die errechnete Adresse, die den Page Fault auslöst:
unsigned int *test = GET_PAGE_ADDRESS((table_idx)+(2048));
printf("test = 0x%x\n", test);
memset(test, 0|0x2, PAGE_SIZE);

Habe ich da irgendetwas nicht berücksichtigt?