Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: s137 am 06. November 2014, 12:49

Titel: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 06. November 2014, 12:49
Hallo zusammen,

Bei der Programmierung der physikalischen Speicherverwaltung ( in Form einer Bitmap) für meinen Kernel, bin ich auf folgendes Problem gestoßen:

Wenn ich Speicher für ein Programm freigeben will, suche ich ja nach einem gesetzten Bit ( frei = 1 ) in der Bitmap, und gebe dann die Adresse zurück. Jedoch ist dass dann ja nur ein Speicherblock mit 4kB. Was wenn mein Programm mehr Speicher benötigt? Und wie kann ich herausfinden wieviel Speicher mein Programm überhaupt benötigt?

Schon mal vielen Dank im Vorraus
s137
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Svenska am 06. November 2014, 14:49
Wenn ein Programm sagt "ich will 4 MB Speicher", dann ist normalerweise eine Bibliothek dafür zuständig, diese 4 MB Speicher zu besorgen und sich zusätzlich zu merken, wieviel Speicher das für diesen Block war. Diese Bibliothek besorgt sich also diese 4 MB Speicher (und wahrscheinlich sogar etwas mehr für die Verwaltung) vom Kernel.

Im Kernel sitzt die virtuelle Speicherverwaltung, die dann 4+ MB Speicher finden muss und auch in den Prozess mappen muss, damit der auch Zugriff darauf hat. Dazu benutzt sie wiederum die physikalische Speicherverwaltung, indem sie genug einzelne Pages (die normalerweise nicht zusammenhängen müssen!) anfordert und zu einem großen virtuellen Block zusammenschweißt.

Deine physikalische Speicherverwaltung weiß davon nichts. Die sieht im Zweifelsfall nur über tausend einzelne Anfragen vom Typ "gib mir eine freie Page, egal welche" und kann das nicht mehr zu irgendwelchen Blöcken zuordnen.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 06. November 2014, 15:28
ah ok, ich denke ich habs verstanden, vielen Dank :) d.h. ich brauche auch noch eine Virtuelle Speicherverwaltung die dann über die Physikalische Speicherverwaltung mir den Speicher freigibt. Aber für einen ersten Test mit einem kleinen Programm sollte die Physikalische Speicherverwaltung ja ausreichen.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Svenska am 06. November 2014, 17:54
Du kannst deiner physischen Speicherverwaltung (nicht physikalische, aber ich mach' den Fehler auch immer mal wieder...) auch beibringen, mehrere aufeinanderfolgende Seiten zu besorgen. Auf dem PC ist das für das Diskettenlaufwerk noch halbwegs sinnvoll, sonst braucht man das aber eigentlich nicht mehr. (Außerhalb der Welt von x86 ist das noch anders.)
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 06. November 2014, 21:36
Oh, ich werds mir merken für die Zukunft^^
Naja wenn ich schonmal anfange dann schon gescheit ^^ Also mit virtueller Speicherverwaltung.. aber jetzt muss ich erstmal die physische hinkriegen^^
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 12. November 2014, 19:27
Ich hab jetz noch konkrete Probleme, bei der Funktion die mir Speicher freigibt. Diese gibt ja eine Adresse zurück, allerdings weiß ich zwar bis jetzt wie ich diese Adresse berechne habe allerdings keine Ahnung wie also in welchem konkreten Format ich diese Adresse zurückgebe also welcher Datentyp.
Soll ich die Adresse noch irgendiwe vorher in Hex umwalndeln?

Das ist bis jetzt der Code meiner Funktion (hab jetzt einfach mal unsigned char* als Datentyp gewählt kann das stimmen? eigtl müsste das doch zu klein sein oder?)

unsigned char* pmm_alloc()
{

unsigned char x = 0;
unsigned char flag = 1;
unsigned char* addr;
long i;

for(i=0, i<=32768, i++)
{

  while (x<=31) {

    if (bitmap[i] & flag ) == 1 {

     addr = i*(31*4096) + x*4 // Rueckgabe der Adresse in Bytes

     pmm_mark_used(addr);

     return addr;
     }

     x++;
     flag = (flag << x);

  }

}

return addr;

}

Schonmal Vielen Dank im Vorraus
s137
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 12. November 2014, 20:43
Mal eine Gegenfrage: Mit welcher Programmiersprache bist du denn sonst so unterwegs? Könntest du darin eine Funktion schreiben, die in einem Array bestimmter Größe den Index eines Eintrags zurückliefert, der ungleich Null ist? Und könntest du eine weitere Funktion schreiben, die in einem Integer den Index des niedrigsten gesetzten Bits findet? (Darfst sogar annehmen, dass dieser Integer ungleich 0 ist. Kann man ja später mit der ersten Funktion kombinieren.)

Mein Vorschlag wäre, erstmal diese beiden Funktionen (am besten in der dir vertrauten Sprache) zu schreiben und - ganz wichtig - gründlich zu testen. (Randbedingungen/Grenzfälle überlegen!) Es muss (sollte am besten sogar) nicht in deinem OS sein, sondern einfach in einem ganz normalen kleinen Testprogramm unter Linux/Windows/etc. Dann findest du sicherlich selbst viele Probleme, die in dem geposteten Codeschnipsel bestehen. Das ist zumindest meine Hoffnung.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 12. November 2014, 20:44
Java  :-D sollte machbar sein^^

ich probiers auf jedenfall mal aus.. danke für den Tipp^^
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 12. November 2014, 20:46
Das ist perfekt. Für diese Zwecke ist sie C ähnlich genug.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 12. November 2014, 20:50
ok wie gesagt werds mal versuchen^^
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 17. November 2014, 22:46
Also ich hab des erste jetzt mal versucht in Java zu implementieren:

Ist das so wie du das gemeint hast?:

public class MainClass {

public static void main(String[] args) {

        long[] testarr = {0,0,0,3,4,5,0,3,0};

        int index = indexArrayValNotNull(testarr);

        System.out.println(index);
 
}


// Array Eintrag ungleich null?
public static int indexArrayValNotNull(long[] array) {

int i;

for (i=0; i<= array.length; i++)
{
if (array[i] != 0) { return i; }
}

return -1;
}

}


Bei dem 2. bin ich mir allerdings nicht sicher wie ich das hinkriege dass ich das niedrigste gesetzte Bit in einem Integer finde.

Viele Grüße
s137
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 18. November 2014, 00:06
Ist das so wie du das gemeint hast?
Jep, genau sowas. Einen Bug sehe ich da allerdings noch. Der macht sich zwar nur in einem der Grenzfälle bemerkbar, aber ein Auge für sowas zu entwickeln, ist nie schlecht. Was passiert wenn, du
long[] testarr = {0,0,0,0,0,0,0,0,0}; /* die anzahl nullen ist egal */verwendest? Und wie korrigiert man das? Auf Grund der Uhrzeit1) entschließe ich mich mal, das als Rätsel zu formulieren. Falls du nicht auf die Lösung kommst, geht die Schnitzeljagd hier los: http://pastebin.com/JdPGFGn1 ;)

Die Entdeckung solcher Probleme meinte ich übrigens mit "gründlich Testen". Andere Testfälle, wären beispielsweise noch ein leeres Array, oder ein Array mit 0xfffffffff belegt. Einfach mal gucken, ob die Funktion, da dann auch das tut, was sie soll, auch wenn es ggf. nur eine Fehlermeldung (oder Rückgabewert -1) ist.


Bei dem 2. bin ich mir allerdings nicht sicher wie ich das hinkriege dass ich das niedrigste gesetzte Bit in einem Integer finde.

Das ist schwer zu erklären ohne gleich den Code zu servieren, deswegen hier mal eine einfache Implementierung:

    private static int bitscanforward(int x) {
int i;

for (i = 0; i < 32; i++) {
if ((x & (1 << i)) != 0)
return i;
}

/* ups gar kein bit war gesetzt */
return -1;
}

Ein (32-Bit-)Integer hat 32 Bits. Deswegen habe ich da eine Schleife, die von 0 bis 31 läuft. Der Wert von 1 << i ist mathematisch gesehen 2^i und ist in Binärdarstellung eine Zahl, die genau ein Bit auf 1 gesetzt hat (nämlich das i-te) und alle anderen sind 0. Das heißt wenn wir x & (1 << i) auswerten, hat dieses ein Ergebnis ungleich 0, wenn sowohl x als auch 1 << i an der selben Bitposition ungleich 0 sind. Also genau dann, wenn x an der i-ten Bitposition ungleich 0 ist. Weil wir die Schleife aufsteigend von 0 an durchlaufen, finden wir mit dieser Methode das niedrigste Bit ungleich 0. (Das ist etwas, das man sich im Zweifelsfall mal aufmalen sollte.)

Deine (hoffentlich korrigierte) Funktion und meine Funktion kannst du nun kombinieren, um deine pmm_alloc zu implementieren. Deine Funktion sollte einen Eintrag in der Bitmap ungleich 0 finden, und meine Funktion sollte darin den Index bestimmen. Der Algorithmus ist dann 2)

index = indexArrayValNotNull(bitmap);
bit = bitscanforward(bitmap[index]);
page_nummer = index * 32 + bit; // 32 pages pro eintrag in "bitmap"
adresse = page_nummer * 4096; // jede page ist 4096 bytes groß

Und zu der Frage, ob nun char* oder void* oder unsigned int: Eigentlich absolut nicht egal, aber solange mir keiner widerspricht: unsigned int.

Zur Fehlerbehandlung: Wenn deine Funktion (gerechtfertigt) -1 zurück gibt, dann ist der Speicher übrigens komplett belegt, und dein OS sollte anhalten. Meine Funktion sollte nie -1 zurückgeben, wenn du sie mit Bitmap-Einträgen fütterst, die ungleich 0 sind.

1) :mrgreen:
2) Individualisierung angebracht und erwünscht
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Svenska am 18. November 2014, 01:23
"-1" als Fehlerwert passt nicht zu "unsigned int" als Datentyp.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 18. November 2014, 11:31
Aber zum Glück hat Java ja keine unsigned-Variablen. ;)

In C kann man dann eben (unsigned) -1 nehmen.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 19. November 2014, 12:49
Aber natürlich -> ArrayIndexOutOfBoundsException: 9 -> nur Elemente mit Index 0-8 im Array und "array.length = 9" also darf ich natürlich nur "< array.length" schreiben, danke für das Rätsel aber ich bin noch selber draufgekommen und hab dann geschaut obs richtig war ^^

Und die 2. Funktion hab ich denke ich jetzt soweit auch verstaden, werde dann mal versuchen das so zu implementieren, vielen Dank für die ausführliche Erklrung.

Viele Grüße
s137
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 20. November 2014, 16:16
Also meine pmm_alloc() sollte jetzt eigentlich funktionieren, jedoch brauche ich ja auch noch eine pmm_free() und eine pmm_mark_used() funktion um speicher wieder freizugeben oder als markiert zu kennzeichnen, als argument erhalten die Funktionen einen Zeiger vom Typ void auf die addresse also: z.B. pmm_free(void* addr)

Jetzt weiß ich nur nicht genau wie ich aus der Adresse wieder auf die genaue Bitposition in meinem Bitmap Array komme... wie genau drehe ich den vorgang um. Vermutlich is es ganz einfache Mathematik und ich seh den Wald vor lauter Bäumen nicht..

Vg
s137
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 20. November 2014, 16:26
Versuch mal, in Worten (also auf deutsch, nicht in C) zu beschreiben, was der Arrayindex und die Bitnummer für die Page Nummer x ist. Oder wenn dir das zu abstrakt ist, kannst du auch eine konkrete Zahl einsetzen und schauen, wo Page 42 landen würde. Im Zweifelsfall ruhig auch mal ein Blatt Papier hernehmen und die Bitmap aufmalen.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 20. November 2014, 16:37
Naja ok das find ich jetz ja noch gar nicht so schwierig, also imho ergibt ArrayIndex * 32 + Bitnummer = Pagenummer.

Nur kann ich daraus immer noch nicht genau ableiten was ArrayIndex und Bitnummer für Werte sind. Ich komm zwar durch addresse / 4096 auf die Pagenummer, jedoch weiß ich dann nicht wie ich weiterrechnen soll.Vermutlich ist es einfachste Mathematik und ich komm halt einfach nicht drauf...
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 20. November 2014, 17:53
Wenn du ein Problem nicht verstehst, mach einfach ein paar Beispiele und schau, ob dir etwas auffällt:

Was sind Arrayindex/Bitnummer für Page 0?
Was sind Arrayindex/Bitnummer für Page 1?
...
Was sind Arrayindex/Bitnummer für Page 31?
Was sind Arrayindex/Bitnummer für Page 32?
...
Was sind Arrayindex/Bitnummer für Page 63?
Was sind Arrayindex/Bitnummer für Page 64?
...
Was sind Arrayindex/Bitnummer für Page 1337?
Was sind Arrayindex/Bitnummer für Page n?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 21. November 2014, 18:31
Danke, jetz hab ichs rausgefunden... Gepriesen sei der Modulo Operator... den hatt ich fast vergessen^^

Bitnummer = page_nummer % 32;
Array_Index = (page_nummer - Bitnummer) / 32;

Vg s137
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 21. November 2014, 20:18
Sieht richtig aus.

Weil du mit Integern rechnest und / deswegen eine ganzzahlige Division ist, kannst du auch direkt page_nummer / 32 machen. Der Rest, den du vor der Division abziehst, sind am Ende nur Nachkommastellen, die sowieso abgeschnitten werden.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 21. November 2014, 21:26
Ok, dann passt das, eine kleine Frage hab ich noch bei der Initialisierung der Bitmap habe ich im Tutorial etwa folgenden Code: (nur mal ein kleiner Ausschnitt):


uintptr_t addr = (uintptr_t) &kernel_start;
while (addr < (uintptr_t) &kernel_end) {
    pmm_mark_used((void*) addr);
    addr += 0x1000;
}

Da ich uintptr_t nirgends als Typ definiert habe, dachte ich mir da könnte man doch auch einfach einen Typlosen pointer also (void*) nehmen? Irgendwie funktioniert das aber nicht ganz so wie ich mir das vorgestellt habe... Ich kann ja z.B. uint8_t durch ein einfaches "unsigned char" ersetzen, oder ein uint16_t durch ein unsigned short, durch was muss  ich dann uintptr_t ersetzen, wenn es mit "void*" nicht funktioniert?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 21. November 2014, 22:05
uintptr_t ist ein Integer-Datentyp, der so breit ist wie ein Pointer. Das sind auf i386 32 Bit und auf x86_64 64 Bit, also das, was normalerweise ein unsigned long darstellen kann. So würde ich den Typ dann auch definieren.

Ein Pointer zeigt aber immer auf virtuellen Speicher. Das heißt, uintptr_t (und void*) sind geeignet, um Adressen im virtuellen Adressraum zu referenzieren. Wenn man es genau nimmt, ist der physische Adressraum etwas anderes und du könntest dafür separate Typen benutzen, um die Absicht klar zu machen. tyndur hat zum Beispiel einen paddr_t für physische Adressen (der auch wieder ein unsigned long ist). Aber unabhängig davon, ob du paddr_t oder uintptr_t nimmst: Pointertypen wie void* für physischen Speicher würde ich nie benutzen, denn beim Dereferenzieren käme nichts sinnvolles heraus.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 21. November 2014, 22:08
Bedeutet das quasi ich kann einfach jedes "uintptr_t" durch ein "unsigned long" austauschen?

Entschuldige die Frage aber was bedeutet "Dereferenzieren"? Denn genau da krige ich im Moment ne Fehlermeldung.

Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 21. November 2014, 22:57
Dereferenzieren heißt auf die Speicher zuzugreifen, auf den ein Pointer zeigt. Also *p dereferenziert p.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 21. November 2014, 23:04
Achso ok dann hab ich das verstanden. Danke
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 22. November 2014, 14:22
Nur eine kleine Frage zur Definition von "NULL", NULL ist ja nicht gleich 0 oder?, d.h. ich muss NULL irgendwie definieren, da ich es sonst nicht benutzen kann. Wie genau sollte ich NULL definieren.

wenn ich #define NULL   0 mache, dann kann ich ja auch gleich 0 schreiben.

Oder sehe ich das falsch?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: OsDevNewbie am 22. November 2014, 15:21
Hallo,
ich habe bei NULL folgendermassen definiert:
#define NULL ((void*)0)
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 22. November 2014, 15:28
ok danke :DD
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Svenska am 22. November 2014, 15:52
Die Typen uint32_t, int8_t, uintptr_t usw. haben ihren Sinn. Wenn du eine bestimmte Bitbreite brauchst, dann solltest du diese Typen benutzen, und nicht "unsigned long", auch wenn das zufällig die gleichen Typen sind. Aus dem gleichen Grund solltest du diese Typen auch nicht selbst definieren (gilt auch für NULL).

Dein Compiler stellt dir das alles in den Header-Dateien stdint.h und stddef.h bereit. Nutze sie. Die sind auch für Kernelprogrammierung geeignet und enthalten noch ein paar andere nützliche Dinge.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 22. November 2014, 16:23
oh ok danke dann werd ich mal meine eigenen mit denen des compilers austauschen...
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 22. November 2014, 16:28
blöde frage, aber wenn ich versuche die Datei mit #include <stdint.h> einzubinden, bekomme ich einen Kompilierungsfeher dass die Datei nicht gefundne wurde.

was mache ich falsch?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 22. November 2014, 17:35
außerdem geht mein multitasking versuch irgendwie drunter und drüber... ich hbe 3 Tasks und habe das TSS und die schedule sowie die init_task Funktion wie im Tutorial aufgesetzt. Nur endet mein Kernel immer mit einer Invalid Opcode Exception, und irgendiwe werde ich nicht ganz schlau daraus...
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Svenska am 22. November 2014, 19:33
blöde frage, aber wenn ich versuche die Datei mit #include <stdint.h> einzubinden, bekomme ich einen Kompilierungsfeher dass die Datei nicht gefundne wurde.
Vermutlich kompilierst du mit ungünstigen Compiler-Flags. Wenn da "-nostdinc" drin steht, dann ersetze das mal durch "-ffreestanding".
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 23. November 2014, 09:17
Ja danke, jetz hats geklappt. Allerdings funktioniert mein Hardware Multitasking immer noch nicht... Ich registrieren 3 Tasks von denen immernur der letzte läuft und dann beim ersten Timerinterrupt bekomme ich eine invalid opcode exception...
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 23. November 2014, 14:19
ok jetzt hab ich ein bisschen unbedeutenden code verändert, ein par debugging ausgaben... und jetz kriege ich statt der Invalid Opcode Exception einen General Protection Fault...
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 23. November 2014, 15:13
Also um dir zu helfen, brauchen wir mehr Informationen. Einmal ist der Quellcode interessant, falls du den irgendwo auf github oder einem anderen Repository hochladen könntest, wäre das am einfachsten für uns da reinzuschauen. Außerdem solltest du dich mit den Logging-Funktionen deines Emulators auseinandersetzen. Zum Beispiel hab ich das vor einiger Zeit mal hier an einem konkreten Problem erklärt: http://forum.lowlevel.eu/index.php?topic=3247.msg37696#msg37696
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 23. November 2014, 16:50
Also das mit dem Quellcode ist eher schwierig weils ziemlich viel ist an dem es liegen könnte, aber ich kann den relevanten Teil mal hier hochladen, die Logging Funktion meines Emulators kann ich leider nicht nutzen, weil ich einen echten PC als Emulator verwende und von einem USB-Stick boote (Die quemu installation ist desöfteren gescheitert und ein ordentliches Image hab ich dank fehlendem grub legacy auch nicht hingekriegt).

Aber ich habe es jetz hinreichend getestet, also wenn nur ein Task läuft ist alles in Ordnung, aber sobald ich mehrere tasks laufen habe, eigtl immer genau dann wenn der Taskswitch stattfindet, also beim Timerinterrupt, bekomme ich einen General Protection Fault, der von meinem Interrupt Handler bearbeitet wird und dann hält mein Kernel gewollt an.

Anbei meine task.c:

// Sourcecode File for Headerdatei task.h
#include "console.h"
#include "pmm.h"
#include "task.h"
//#include "stdint.h"
#include <stdint.h>
#include <stddef.h>

struct task {
    struct cpu_state* cpu_state; // Pointer auf obige Struktur
    struct task*      next;
};

static struct task* first_task = NULL; // Nullzeiger
static struct task* current_task = NULL; // Nullzeiger

// Jeder Task: Einsprungpunkt -> entry; Stack -> stack;

struct task* init_task(void* entry)
{

    uint8_t* stack = pmm_alloc(); // unsigned char (uint8_t*) weil void* typlos
    uint8_t* user_stack = pmm_alloc(); // -"-


    // CPU-Zustand fuer den neuen Task festlegen
    struct cpu_state new_state = {
        .eax = 0,
        .ebx = 0,
        .ecx = 0,
        .edx = 0,
        .esi = 0,
        .edi = 0,
        .ebp = 0,
        .esp = (uint32_t) user_stack + 4096, // Ring Wechsel auf Ring 3
        .eip = (uint32_t) entry,

        // Ring-0-Segmentregister : 0x08
        .cs  = 0x1b,
        .ss  = 0x20 | 0x03, // benutzt weil Ringwechsel auf 3

        // IRQs einschalten (IF = 1)
        .eflags = 0x202,
    };


    /*
     * Den angelegten CPU-Zustand auf den Stack des Tasks kopieren, damit es am
     * Ende so aussieht als waere der Task durch einen Interrupt unterbrochen
     * worden. So kann man dem Interrupthandler den neuen Task unterschieben
     * und er stellt einfach den neuen Prozessorzustand "wieder her".
     */
     struct cpu_state* state = (void*) (stack + 4096 - sizeof(new_state));
    *state = new_state;

    /*
     * Neue Taskstruktur anlegen und in die Liste einhaengen
     */

   
    struct task* task = pmm_alloc();
    task->cpu_state = state;
    task->next = first_task;
    first_task = task;
    return task;
}

// Aktueller Zustand wird als Parameteuebergeben und gespeichert.
// Neuer Prozessorzusatand wirdurueck gegeben

struct cpu_state* schedule(struct cpu_state* cpu)
{

// Wenn Task vorhanden, Zusatand sichern. Wenn nicht Prozessorzustand vernachla$
  if (current_task != NULL) {
    current_task->cpu_state = cpu;
  }

  // Naechsten Task auswaehlen -> schleife von vorne wenn durch
  if (current_task == NULL) {
    current_task = first_task;
  }
  else {
    current_task = current_task->next;
    if (current_task == NULL) {
       current_task = first_task;
    }
  }

  // Prozessorzustand des neuen Task zurueckgeben
  cpu = current_task->cpu_state;

  return cpu;

}


Und hier mal mein Interrupt Handler:

struct cpu_state* handle_interrupt(struct cpu_state* cpu)
{

  struct cpu_state* new_cpu = cpu;

  if (cpu->intr <= 0x1f) {
        // kprintf("Exception %d, Kernel angehalten!\n", cpu->intr);
           kputs("Exception: ");
           kputn(cpu->intr, 10);
           kputs("\n Kernel angehalten! \n");
        // Hier den CPU-Zustand ausgeben

        while(1) {
            // Prozessor anhalten
            asm volatile("cli; hlt");
        }
   } else {
        // Hier den Hardwareinterrupt behandeln
        // kputs("Hardwareinterrupt");

        if (cpu->intr >= 0x20 && cpu->intr <= 0x2f) {

           if (cpu->intr == 0x20) {
            kputs("Timerinterrupt vor");
            new_cpu = schedule(cpu); // #debug
            set_tss_entry(1, (unsigned long) (new_cpu + 1)); // #debug
            kputs("Timerinterrupt nach");
           }

           if (cpu->intr == 0x21) {
            kputs("Tastaturinterrupt");
           }

           if (cpu->intr >= 0x28) {
               outb(0xa0, 0x20); // End of Interrupt: Slave PIC
            }

            outb(0x20, 0x20); // End of Interrupt: Master PIC
        }
   }
return new_cpu;
}


Die Funktion set_tss_entry erstellt einen Eintrag im TSS das in einer anderen Datei liegt. Diese Funktion wird über eine Headerdatei bereitgestellt und funktioniert auch.
Die kputs() im Timerinterrupt sind nur zu Debuggingzwecken vorhanden.

Vg s137
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 23. November 2014, 19:00
Also das mit dem Quellcode ist eher schwierig weils ziemlich viel ist an dem es liegen könnte, aber ich kann den relevanten Teil mal hier hochladen
Gerade weil es an so vielem liegen kann, ist der komplette Quelltext hilfreich. An dem geposteten Code kann ich nichts falsches entdecken.

die Logging Funktion meines Emulators kann ich leider nicht nutzen, weil ich einen echten PC als Emulator verwende und von einem USB-Stick boote (Die quemu installation ist desöfteren gescheitert und ein ordentliches Image hab ich dank fehlendem grub legacy auch nicht hingekriegt).
Das ist nicht gut. Gerade am Anfang ist ein Emulator sehr nützlich.

Aber ich habe es jetz hinreichend getestet, also wenn nur ein Task läuft ist alles in Ordnung, aber sobald ich mehrere tasks laufen habe, eigtl immer genau dann wenn der Taskswitch stattfindet, also beim Timerinterrupt, bekomme ich einen General Protection Fault, der von meinem Interrupt Handler bearbeitet wird und dann hält mein Kernel gewollt an.
Wie lautet der Fehlercode?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 23. November 2014, 19:12
Zitat
Wie lautet der Fehlercode?
Der Fehlercode also die Nummer des Interrupts "cpu->intr" ist 13 was meiner Belegung nach einem General Protection Fault entspricht.

Zitat
Das ist nicht gut. Gerade am Anfang ist ein Emulator sehr nützlich.
Das mit dem Emulator könnte auf meinem System schwierig werden, aber ich kanns ja nochmal versuchen...

Zitat
Gerade weil es an so vielem liegen kann, ist der komplette Quelltext hilfreich. An dem geposteten Code kann ich nichts falsches entdecken.
dann werde ich mal schauen ob ich mein projekt irgendwie auf github bekomme...
sollte ja nicht so schwer sein... aber eigtl sollte ja nur der code den ich gepostet habe für mein problem releavant sein... oder? kann es daran liegen dass meine physische Speicherverwaltung nicht richtig funktioniert und die pmm_alloc() Funktion nicht funktioniert?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 23. November 2014, 20:02
Zitat
Wie lautet der Fehlercode?
Der Fehlercode also die Nummer des Interrupts "cpu->intr" ist 13 was meiner Belegung nach einem General Protection Fault entspricht.
Der Fehlercode ist in cpu->error.

Zitat
Gerade weil es an so vielem liegen kann, ist der komplette Quelltext hilfreich. An dem geposteten Code kann ich nichts falsches entdecken.
dann werde ich mal schauen ob ich mein projekt irgendwie auf github bekomme...
sollte ja nicht so schwer sein... aber eigtl sollte ja nur der code den ich gepostet habe für mein problem releavant sein... oder? kann es daran liegen dass meine physische Speicherverwaltung nicht richtig funktioniert und die pmm_alloc() Funktion nicht funktioniert?
Das wäre eine Möglichkeit von mindestens 1596.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 23. November 2014, 20:10
oh ok d.h. es gibt viele Möglichkeiten ^^ ich werde gleich mal den Fehlercode heraussuchen und posten.

Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 23. November 2014, 21:52
ok der Fehlercode ist 258 (dezimal) und die auftretende Exception meines Wissens nach ein General Protection Fault.

Schonmal Danke für Eure Hilfe
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 23. November 2014, 22:33
Bei den Fehlercodes ist die Betrachung in Hexadezimal am sinnvollsten. Der Wert ist also 0x102. Das setzt sich aus zwei Teilen zusammen: Die unteren 3 Bits geben an, wo der Fehler aufgetreten ist (IDT oder GDT), und die restlichen Bits geben den Eintrag an. (Siehe auch Kapitel 6.13 in Volume 3 der Manuals.) Die 2 heißt IDT und 0x100 ist die Adresse des 32. Eintrags (0x100 / 8 = 32), also des Timer IRQs. Das heißt deine IDT wird vermutlich überschrieben, unerreichbar gemacht (Paging) oder verschoben (LIDT), bevor der nächste Timerinterrupt auftritt. Außerdem ist das Aufrufen aus dem Userspace (int 0x20) nicht erlaubt. Glaube das gibt auch diesen Fault.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 24. November 2014, 18:27
oh ok ich hab meinen Fehler entdeckt ich habe versucht aus einer Funktion heraus (Userspace) den Timerinterrupt auszulösen.. hab das jetzt entfernt und statt irgendeiner exception oder irgendwelchen fehlercodes startet er jetzt einfach neu. Das allerdings erst ab dem 2. Task also vermutlich ist auch wieder der Taskswitch oder der Timerinterrupt schuld.

Das bedeutet, solang ich mit init_task() nur einen Task initialisiere, gibt er meine A's unendlich lang auf dem Bildschirm aus und alles funktioniert wie gewollt, aber ab dem 2. Task -> Neustart..

Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 24. November 2014, 20:04
also ich hab jetzt mal in meine task.c in die schedule Funktion, ein


  // Prozessorzustand des neuen Tasks zurueckgeben
  if(current_task != NULL) {
    cpu = current_task->cpu_state;
  }

  return cpu;


eingefügt um zu überprüfen ob der Task == NULL ist also noch uninitialisiert, d.h. die schedule Funktion zu früh aufgerufen wurde...

Das hat zwar den Neustart Fehler beseitigt, allerdings bekomme ich jetzt einen General Protection Fault, mit dem Fehlercode: 1364 (dezimal). Wenn ich das richtig interpretiere liegt mein Fehler also in der GDT, oder? wie genau finde ich den Deskriptor raus an dem es konkret liegt?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 24. November 2014, 20:12
Die Deskriptornummer steht ab Bit 3 im Fehlercode, Bits 0, 1 und 2 sind Flags, die dir sagen, in welcher Tabelle und so. Kapitel 6.13 ("Error Code") in meiner Fassung des Intel-Manuals erklärt das.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 24. November 2014, 20:20
ja ich denke das hab ich verstanden, ich versuche das grad rauszufinden komme aber nicht so recht klar, also mein Fehlercode entspricht in Binärformat: 10101010100

d.h. da Bit 2 gesetzt ist liegt es laut Intel Manual an der GDT.

Doch bei der Berechnung der Nummer des Deskriptors komme ich irgendwie nicht ganz klar: Binär: 10101010 also Hexadezimal: 0xAA also Dezimal: 170

170 / 8 (weil ein Eintrag 8 Bytes) ergibt eine Kommazahl?!
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 24. November 2014, 20:25
Das ist kein Byte-Offset (und auch kein Selektor), sondern direkt die Nummer des Deskriptors.

Dass der GDT-Eintrag 170 nicht existiert, überrascht uns vermutlich beide nicht. Deine nächste Aufgabe wäre herauszufinden, aus welchem Grund dein Code versucht, diesen Deskriptor zu benutzen.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 24. November 2014, 20:32
gute frage, die ich vermutlich auf echter hardware ohne debugging nicht beantworten kann.. aber ich denke mal dass bei dem Aufruf meines TSS irgendwas schiefgeht.. werd das mal überprüfen…
danke schonmal..
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 24. November 2014, 20:44
Hier mal meine gdt.c falls man da irgendwas rauslesen kann..

// Source Code Fileor GDT Header File

#include "gdt.h"
#define GDT_ENTRIES 6

#define GDT_FLAG_DATASEG 0x02
#define GDT_FLAG_CODESEG 0x0a
#define GDT_FLAG_TSS     0x09

#define GDT_FLAG_SEGMENT 0x10
#define GDT_FLAG_RING0   0x00
#define GDT_FLAG_RING3   0x60
#define GDT_FLAG_PRESENT 0x80

#define GDT_FLAG_4K_GRAN 0x800
#define GDT_FLAG_32_BIT  0x400


static unsigned long long gdt[GDT_ENTRIES];
static unsigned long tss[32] = { 0, 0, 0x10 };

void set_tss_entry(int x, unsigned long val)
{
 tss[x] = val;
}

static void set_entry(int i, unsigned int base, unsigned int limit, int flags)
{
    gdt[i] = limit & 0xffffLL;
    gdt[i] |= (base & 0xffffffLL) << 16;
    gdt[i] |= (flags & 0xffLL) << 40;
    gdt[i] |= ((limit >> 16) & 0xfLL) << 48;
    gdt[i] |= ((flags >> 8 )& 0xffLL) << 52;
    gdt[i] |= ((base >> 24) & 0xffLL) << 56;
}


void load_gdt(void)
{

struct {
    unsigned short limit;
    void* pointer;
} __attribute__((packed)) gdtp = {
    .limit = GDT_ENTRIES * 8 - 1,
    .pointer = gdt,
};
asm volatile("lgdt %0" : : "m" (gdtp));


asm volatile(
  "mov $0x10, %ax;"
  "mov %ax, %ds;"
  "mov %ax, %es;"
  "mov %ax, %fs;"
  "mov %ax, %gs;"
  "mov %ax, %ss;"
  "ljmp $0x8, $.1;"
  ".1:;"
);

}

void init_gdt(void)
{
    set_entry(0, 0, 0, 0);
    set_entry(1, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
        GDT_FLAG_CODESEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT);
    set_entry(2, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
        GDT_FLAG_DATASEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT);
    set_entry(3, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
        GDT_FLAG_CODESEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
    set_entry(4, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
        GDT_FLAG_DATASEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
    set_entry(5, (unsigned long) tss, sizeof(tss), GDT_FLAG_TSS | GDT_FLAG_PRESENT | GDT_FLAG_RING3);

    load_gdt();

    // Taskregister neu laden
    asm volatile("ltr %%ax" : : "a" (5 << 3));

}
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 24. November 2014, 20:49
Ich hätte noch zwei, drei Theorien einzuwerfen: Vielleicht schaust du gerade auf den falschen Wert (etwas das gar nicht der Error Code ist), oder deine Ausgabefunktion ist fehlerhaft. Und der Klassiker kaputter Stack ist auch immer dabei.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 24. November 2014, 20:54
also die Ausgabefunktion ist mit kputn genauso wie im Tutorial 1:1 übernommen… d.h. ich gebe direkt mit

kputn(cpu->error, 10); // Basis 10, also decimal

den Error Code aus…
sollte also nicht das Problem sein…

Wie genau erkenne ich einen kaputten Stack? und was kann ich dagegen tun?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 24. November 2014, 21:01
Den könntest du erkennen, indem du schaust, ob die anderen Werte auf dem Stack plausibel sind.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 24. November 2014, 21:03
ok, also soll ich quasi die register auslesen.. nur weiß ich ja nicht welche werte in den registern normalerweise stehen sollten ^^
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 24. November 2014, 21:08
In EIP sollte ein Wert stehen, der auf deinen Code zeigt, in ESP sollte eine Adresse stehen, die auf einen der dir bekannten Stacks liegt. Du legst die ja mit pmm_alloc an, bzw. die sind direkt im Kernel. In den Segmentregistern sollten gültige Werte stehen.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 24. November 2014, 21:21
also gut jetz spielt mein Kernel endgültig verrükct.. bin mit meinem Latein am Ende...

Jetz wollte ich debugging Ausgaben mit kputs und kputn einbauen.. -> Neustart (vermutlich Triple Fault)

Kommentiere ich die Debuggingausgaben aus, also genau die selbe situation wie vorher tritt statt eines GPF nun eine Invalid Opcode Exception mit Fehlercode: 0 auf...
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 24. November 2014, 22:04
In solchen Fällen ist es sinnvoll zu schauen, was überhaupt noch funktioniert.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 24. November 2014, 23:12
Naja solange weniger als 2 Tasks laufen, also kein Taskswitch stattfindet geht alles..GDT einwandfrei, IDT einwandfrei, Testausgaben mit kputs und kputn auch.

Hmm komisch..
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: OsDevNewbie am 25. November 2014, 12:22
Mal ne Frage wieso ist deine TSS in der GDT im Ring 3  eingetragen? Muss die nicht im Ring 0 sein?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 25. November 2014, 13:57
Also laut dieser Seite: http://www.lowlevel.eu/wiki/Global_Descriptor_Table (http://www.lowlevel.eu/wiki/Global_Descriptor_Table)
siehe hier: "Ein Task State Segment für Multitasking (Present, Ring 3, 386-TSS)" sollte es doch in Ring 3 eingetragen werden, oder?

Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: OsDevNewbie am 25. November 2014, 14:38
Also ich habe bei meinem Kernel die TSS als Ring 0 definiert. Kannst ja mal ausprobieren ob es funktioniert.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 25. November 2014, 19:24
Also gut… nach ein paar kleinen Änderungen nun ein anderes Fehlerbild, ich bekomme keine Exceptions mehr und mein Kernel hält auch nicht mehr an.

Aber sobald ich mehr als einen Task initialisiere passiert nichtsmehr außer die Bestätigung eines einzigen Timerinterrupts (dabei ist es egal ob das TSS in Ring0 oder Ring3 ist).

Ein Task läuft einwandfrei. Und wenn ich 2 eintrage und in dem Interrupthandler bei dem Timerinterrupt die schedule und set_tss_entry Funktion auskommentiere:

if (cpu->intr == 0x20) {
 kputs("Timerinterrupt vor");
 //new_cpu = schedule(cpu);
 //set_tss_entry(1, (unsigned long) (new_cpu + 1));
 kputs("Timerinterrupt nach");
}

bekomme ich zwar die Bestätigung von konstant aufeinanderfolgenden Timerinterrupts aber meine Tasks machen gar nichts… eigtl sollte ja zumindest A auf dem Bildschirm vom ersten Task ausgegeben werden auch wenn kein Taskswitch stattfindet...
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 25. November 2014, 21:04
Also gut hab mich mal ein bisschen im Debugging geübt und die Werte ausgelesen, die init_task zurückgibt... also den CPU Status.

Dabei bin ich auf folgendes gestoßen... die Werte die der erste Aufruf von init_task zurückgibt sind ja noch ganz ok, und wie erwartet: (alles hexadezimale Zahlen):

eax: 0
ebx: 0
ecx: 0
edx: 0
esi: 0
edi: 0
ebp: 0
eip: 100d29 (Einsprungpunkt des Tasks)
cs: 1b
eflags: 200
esp: 21000
ss: 23

Aber bei den Rückgabewerten des 2. init_task aufrufs:

eax: eef3ff
ebx: eef3f0
ecx: e2c3f0
edx: eef3f0
esi: eef3f0
edi: ff54f0
ebp: 313df0
eip: e987f0 (Adresse existiert in meinem Kernel nicht...)
cs: eef3f0
eflags: eef3f0
esp: eef3f0
ss: eef3f0

Ich versuch jetz grad mal rauszufinden was es mit dem "eef3f0" auf sich hat...

Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 25. November 2014, 22:13
edit: Ergänzung:

Hab mal in meiner handle_interrupt Funktion beim ersten Timerinterrupt auch debuggt:

Das hier is rausgekommen, theoretisch müssten das die Werte sein die vor dem Aufruf des ersten Timerinterrupts von der CPU gesichert worden sind:

eax: 0
ebx: 10000
ecx: b8000
edx: b8f29
esi: 0
edi: 0
ebp: 126204
eip: 100d3f (Ende der init Funktion: Endlosschleife mit << asm volatile("hlt;"); >>)
cs: 8
eflags: 200246
esp: ffffffff
ss: 0

vielleicht kann man ja da noch was rauslesen...
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: OsDevNewbie am 25. November 2014, 22:56
Verwendest du hardware Multitasking odersoftware Multitasking?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 26. November 2014, 06:27
Also ich habe dieses Tutorial für mein Multitasking benutzt: http://www.lowlevel.eu/wiki/Teil_6_-_Multitasking (http://www.lowlevel.eu/wiki/Teil_6_-_Multitasking) denke mal es ist Hardware Multitasking... Ich weiß es aber nicht genau...
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 26. November 2014, 09:31
Nein, das ist Software-Multitasking. Das mag vielleicht auf den ersten Blick komisch klingen, aber das ist schneller und besser als Hardware-Multitasking (außer manchmal, wenn Software-Multitasking gar nicht geht, aber das würde hier zu weit führen).

Was dein Problem betrifft, sehen ja alle Werte kaputt aus. Ich würde an deiner Stelle mal bei der Initialisierung der Tasks und bei jedem Taskwechsel den Stackpointer (oder cpu_state, der ja auf dem Stack liegt und damit ungefähr dasselbe sein müsste) von altem und neuem Task ausgeben. Da müsstest du dann zumindest mal sehen, ob dein cpu_state-Pointer verrutscht ist und auf was falsches zeigt oder ob du den Inhalt der Struktur aus Versehen überschrieben hast.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 26. November 2014, 15:45
Also hier mal die Ergebnisse des Debuggens: (Instrucion Pointer (eip), Codesegment (cs), Stackpointer (esp)):

Rückgabe von Task 1 Initialisierung:

eip: 100d95 (Einsprungpunkt des ersten Tasks)
cs: 1b (Codesegment Userspace)
esp: 21000


Rückgabe von Task 2 Initialisierung:

eip: e987f0 (Adresse existiert nicht)
cs: eef3f0
esp: eef3f0

erster Timerinterrupt cpu_state vor Taskswitch:

eip: 100d93 (Ende der init Funktion: Endlosschleife mit << asm volatile("hlt;"); >>)
cs: 8
esp: ffffffff

erster Timerinterrupt new cpu_state nach Taskswitch:

eip: e987f0 (Adresse existiert nicht)
cs: eef3f0
esp: eef3f0
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 26. November 2014, 16:06
Rückgabe von Task 1 Initialisierung:
Rückgabe von Task 1 Initialisierung:
Ich weiß ja nicht, wie oft du Task 1 initialisierst, aber unabhängig davon, was du mit dem zweiten Block wirklich meintest, sieht das schon kaputt aus (was dir hoffentlich auch aufgefallen ist).
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 26. November 2014, 17:33
Sry, hab mich verschrieben.. Meinte beim 2. Mal natürlichen Task 2.. Mir is schon aufgefallen, dass beim 2.Task und nach dem Taskswitch kaputte werte rauskommen.. Aber ich weiß halt nicht woher die kommen..

Jetzt allerdings noch eine Verständnisfrage zu oben... Wann springt mein Kernel denn in den Task den ich initialisiere? Normalerweise doch erst wenn der erste Timerinterrupt kommt und meine schedule Funktion aufgerufen wird... Das wirft für mich noch eine Frage auf... Wann kommt der erste Timerinterrupt und von was hängt das ab?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Svenska am 26. November 2014, 19:19
Der erste Timerinterrupt wird ausgelöst, nachdem du Interrupts aktiviert hast (mit STI), allerdings nicht unbedingt sofort, sondern erst nach einer (für dich) zufälligen Zeitspanne.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 26. November 2014, 19:29
Das heißt irgendwann, kurz nachdem ich die Interrupts aktiviert habe, kommt der erste Timerinterrupt, meine schedule Funktion wird aufgerufen und mein Kernel springt in den Task den ich vorher initialisiert habe. Und dann beim zweiten Timerinterrupt, wird meine schedule Funktion erneut aufgerufen und in den nächsten Task gesprungen. Sehe ich das so richtig? '

Dann hätte ich noch eine Frage, wozu brauche ich den Eintrag ins TSS und wieso trage ich dort "new_cpu + 1" als ersten Eintrag immer wieder neu ein?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 26. November 2014, 19:36
Das ist außerdem noch meine init_task() könnte ja sein dass man da nen Fehler entdeckt... der Rückgabewert beim ersten Aufruf ist ganz normal, aber beim 2. Mal chaotisch siehe oben.

struct task* init_task(void* entry)
{

    uint8_t* stack = pmm_alloc(); // unsigned char (uint8_t*) weil void* typlos
    uint8_t* user_stack = pmm_alloc(); // -"-


    // CPU-Zustand fuer den neuen Task festlegen
    struct cpu_state new_state = {
        .eax = 0,
        .ebx = 0,
        .ecx = 0,
        .edx = 0,
        .esi = 0,
        .edi = 0,
        .ebp = 0,
        .esp = (uint32_t) user_stack + 4096, // Ring Wechsel auf Ring 3
        .eip = (uint32_t) entry,

        // Ring-0-Segmentregister : 0x08
        .cs  = 0x1b,
        .ss  = 0x20 | 0x03, // benutzt weil Ringwechsel auf 3

        // IRQs einschalten (IF = 1)
        .eflags = 0x200, // 200 ?!
    };


    /*
     * Den angelegten CPU-Zustand auf den Stack des Tasks kopieren, damit es am
     * Ende so aussieht als waere der Task durch einen Interrupt unterbrochen
     * worden. So kann man dem Interrupthandler den neuen Task unterschieben
     * und er stellt einfach den neuen Prozessorzustand "wieder her".
     */
    struct cpu_state* state = (void*) (stack + 4096 - sizeof(new_state));
    *state = new_state;

    /*
     * Neue Taskstruktur anlegen und in die Liste einhaengen
     */

    struct task* task = pmm_alloc();
    //struct task* task;
    task->cpu_state = state;
    task->next = first_task;
    first_task = task;
    return task;
}


Ich würde halt irgendwie mal drauf tippen dass bei dem "struct task* task = pmm_alloc()" also beim allozieren von Speicher für die Taskstruktur was schiefgeht.. aber dann dürfte es ja beim ersten mal auch schon nicht funktionieren oder?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 26. November 2014, 21:57
Wie sieht denn der Code aus, der init_task() aufruft und die (falschen) Debugmeldungen ausgibt?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 26. November 2014, 22:08
In der init.c:

      struct task* task = init_task(test_task_1);

      struct cpu_state* cpu = task->cpu_state;

      debug(cpu, 0, "Task 1:");

Hier noch den Deklaration der Funktion Test Task:


void test_task_1(void);

Und an anderer Stelle die Funktion selbst:

void test_task_1(void)
{
 while(1) {
 kputs("A");
 }
}

Bei Task 2 ist es dasselbe nur mit "B".

Hier noch der Code von debug.c die über eine Headerdatei in der init.c eingebunden ist:

#include "console.h"
#include "debug.h"
#include "task.h"

void debug(struct cpu_state* cpu, int verbose_level, char text[]) {

           kputs(text);
           kputs("\n");

  if(verbose_level == 0) {

           kputs("\n Register eip: ");
           kputn(cpu->eip, 16);
           kputs("\n Register cs: ");
           kputn(cpu->cs, 16);
           kputs("\n Register esp: ");
           kputn(cpu->esp, 16);

  }

  if(verbose_level == 1) {

           kputs("\n Register eax: ");
           kputn(cpu->eax, 16);
           kputs("\n Register ebx: ");
           kputn(cpu->ebx, 16);
           kputs("\n Register ecx: ");
           kputn(cpu->ecx, 16);
           kputs("\n Register edx: ");
           kputn(cpu->edx, 16);
           kputs("\n Register esi: ");
           kputn(cpu->esi, 16);
           kputs("\n Register edi: ");
           kputn(cpu->edi, 16);
           kputs("\n Register ebp: ");
           kputn(cpu->ebp, 16);
           kputs("\n Register eip: ");
           kputn(cpu->eip, 16);
           kputs("\n Register cs: ");
           kputn(cpu->cs, 16);
           kputs("\n Register eflags: ");
           kputn(cpu->eflags, 16);
           kputs("\n Register esp: ");
           kputn(cpu->esp, 16);
           kputs("\n Register ss: ");
           kputn(cpu->ss, 16);
  }

}
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Svenska am 26. November 2014, 23:03
Das heißt irgendwann, kurz nachdem ich die Interrupts aktiviert habe, kommt der erste Timerinterrupt, meine schedule Funktion wird aufgerufen und mein Kernel springt in den Task den ich vorher initialisiert habe. Und dann beim zweiten Timerinterrupt, wird meine schedule Funktion erneut aufgerufen und in den nächsten Task gesprungen. Sehe ich das so richtig?
Ja.

Dann hätte ich noch eine Frage, wozu brauche ich den Eintrag ins TSS und wieso trage ich dort "new_cpu + 1" als ersten Eintrag immer wieder neu ein?
Du machst Software-Multitasking. Das heißt, du hast genau ein einziges TSS, welches du beim Taskwechsel immer wieder neu befüllst und dann der CPU wieder vor die Nase wirfst. (Bei Hardware-Multitasking hättest du stattdessen ein TSS pro Task, und würdest die CPU immer wieder ein anderes aktivieren lassen, wenn du wechseln möchtest.)
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 27. November 2014, 07:40
Oh ok naja dann geht ja anscheinend schon bei der 2. Taskinitialisierung was schief.. Aber warum erst bei der 2.
Wenns an der Speicherallokation für die Taskstruktur läge, müsste es doch beim 1. Mal auch schon nicht funktionieren oder?

Aber wieso dann "new_cpu +1" was macht dieses Plus eins für das TSS..?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 27. November 2014, 09:59
Wenn deine Initialisierung für Task 2 genauso aussieht wie die für Task 1, dann geht der Inhalt ja ziemlich sofort kaputt nachdem du ihn eingetragen hast. Mit gdb und Singlestep müsstest du die Stelle dann schnell finden können. Du könntest dir allerdings auch noch die Rückgabewerte von pmm_alloc() ausgeben lassen, nicht dass dort etwas schiefgeht und du in einem ROM landest oder ähnliche Späße.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 27. November 2014, 16:23
Was genau muss ich denn mit gdb machen? Denn wenn ich den Kernel mit gdb debugge dann sagst er mir erstmal dass meine multiboot_structure = 0x0 ist.. was ja auch logisch ist, wenns nicht auf echter hardware oder einem emulator ausgeführt wird.
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: kevin am 27. November 2014, 16:36
Ich dachte daran, den gdb-Stub in qemu zu benutzen. Aber du benutzt gar keinen Emulator, oder wie war das?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 27. November 2014, 16:39
nein eigentlich nicht.. ich teste auf echer hardware... naja aber wenns nicht anders geht muss ich halt versuchen des mit qemu irgendwie hinzukiegen..
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 27. November 2014, 16:41
jetzt weiß ich wieder wieso ich qemu nicht benutze ^^ qemu funktioniert bei mir nicht weil ich auf einem Serversystem ohne grafische Oberfläche Programmiere... siehe: "Could not initialize SDL(No available video device) - exiting"
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 27. November 2014, 18:53
Also hier mal die Rückgabewerte der pmm_alloc() für die Taskstruktur (struct task* task = pmm_alloc()), bei Task1: 40000 und bei Task2: fffdf000

Da der 2. Wert sehr kaputt erscheint hier mal meine pmm.c:

// Source File for Headerdatei pmm.h

/*
 * Der Einfachheit halber deklarieren wir die maximal benoetige Bitmapgroesse
 * statisch (Wir brauchen 4 GB / 4 kB = 1M Bits; 1M Bits sind 1M/32 = 32k
 * Eintraege fuer das Array)
 *
 * Willkuerliche Festlegung: 1 = Speicher frei, 0 = Speicher belegt
 */
#include "console.h"
#include <stdint.h>
#include <stddef.h>
//#include "stdint.h"
#include "pmm.h"

#define BITMAP_SIZE 32768

static unsigned long bitmap[BITMAP_SIZE];

extern const void kernel_start;
extern const void kernel_end;

unsigned int indexArrayValNotNull(unsigned long array[]);
unsigned int indexLowestBit(int x);
void pmm_mark_all(void);

void pmm_mark_used(void* addr)
{

uintptr_t page_nummer;
uintptr_t bitnummer;
uintptr_t array_index;

page_nummer = (uintptr_t) addr / 4096;
bitnummer = page_nummer % 32;
array_index = (page_nummer - bitnummer) / 32;

//Bit loeschen weil Speicher belegt: Bit = 0
// x &= FLAG
bitmap[array_index] &= bitnummer;

}

void pmm_free(void* addr)
{

uintptr_t page_nummer;
uintptr_t bitnummer;
uintptr_t array_index;

page_nummer = (uintptr_t) addr / 4096;
bitnummer = page_nummer % 32;
array_index = (page_nummer - bitnummer) / 32;

// Bit setzen weil Speicher frei: Bit = 1
// x |= FLAG
bitmap[array_index] |= bitnummer;

}

void* pmm_alloc(void)
{

// TODO: Exceptions einbauen

unsigned int index;
unsigned int bit;
unsigned int page_nummer;
unsigned int adresse;

index = indexArrayValNotNull(bitmap);
bit = indexLowestBit(bitmap[index]);
page_nummer = index * 32 + bit; // 32 pages pro eintrag in "bitmap"
adresse = page_nummer * 4096; // jede page ist 4096 groß

// Pmm mark used
pmm_mark_used((void*) adresse);

return (void*) adresse;

}
void pmm_init(struct multiboot_info *mb_info)
{

struct multiboot_mmap* mmap = mb_info->mbs_mmap_addr; // Pointer zur Memory Map wird in Pointer mmmap gelegt
struct multiboot_mmap* mmap_end = (void*) ((uintptr_t) mb_info->mbs_mmap_addr + mb_info->mbs_mmap_length);

// Alles als belegt markieren
pmm_mark_all();

while (mmap < mmap_end) {
    if (mmap->type == 1) {
        // Der Speicherbereich ist frei, entsprechend markieren
        uintptr_t addr = mmap->base; // Groesse: 1byte = 8bit = 0x1000 = addre zeigt auf adresse *addr auf inhalt
        uintptr_t  end_addr = addr + mmap->length; // 8bit

        while (addr < end_addr) {
               pmm_free((void*) addr);
            addr += 0x1000;
        }
    }
    mmap++;
}

uintptr_t kernel_addr = (uintptr_t) &kernel_start;
uintptr_t kernel_end_addr = (uintptr_t) &kernel_end;

while (kernel_addr < kernel_end_addr) {
      pmm_mark_used((void*) kernel_addr);
   kernel_addr += 0x1000;
}

}

unsigned int indexArrayValNotNull(unsigned long array[]) {

                int i;

                for (i=0; i < sizeof(array); i++) { // Array Laenge ?!

                        if (array[i] != 0) { return i; }
                }

                /* Fehlercode wenn nur 0en */
                return (unsigned) -1;
        }



        unsigned int indexLowestBit(int x) {

                int i;

                for (i=0; i < 32; i++) {

                        if ((x & (1 << i)) != 0) { return i; }
                }

                /* Fehlercode wenn kein Bit gesetzt */
                return (unsigned) -1;
        }


void pmm_mark_all(void) {

int i;
int x;

for(i=0; i < BITMAP_SIZE; i++) {

    for(x=0; x < 32; x++) {

       //Bit loeschen weil Speicher belegt: Bit = 0
       // x &= FLAG
       bitmap[i] &= x;
    }

}

}

void pmm_check(void* addr) {

uintptr_t page_nummer;
uintptr_t bitnummer;
uintptr_t array_index;

page_nummer = (uintptr_t) addr / 4096;
bitnummer = page_nummer % 32;
array_index = (page_nummer - bitnummer) / 32;

        if(bitmap[array_index] & (1 << bitnummer)) { kputs("-1-"); }
        else { kputs("-0-"); }

}

Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: Jidder am 27. November 2014, 23:13
// Bit setzen weil Speicher frei: Bit = 1
// x |= FLAG
bitmap[array_index] |= bitnummer;

Damit setzt du nicht das Bit, sondern du verknüpfst die beiden Werte.

Hier ein Beispiel: http://ideone.com/viksw9 Beachte die Ausgabe.

Es muss also folgendes sein:
bitmap[array_index] |= 1 << bitnummer;

Bit löschen geht mit:
bitmap[array_index] &= ~(1 << bitnummer);

Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 27. November 2014, 23:22
Ach gott.. Natürlich... Da hätte ich aber auch selber draufkommen können... Danke :DD Eine Frage hätt ich noch.. Bei dem 2. was macht das "~" da genau?
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: OsDevNewbie am 28. November 2014, 00:45
~ ist der not Operator. Er dreht alle Bits um. D.haus 1 wird 0 und ummgekehrt. Z.b ist ~0b1011 = 0b0100.

Bei
~(1 << bitnummer);
sind also dann alle Bits gesetzt ausser das Bit mit an der Stelle bitnummer (dort steht dann eine 0).
Titel: Re: Problem bei Physikalischer Speicherverwaltung (Bitmap)
Beitrag von: s137 am 28. November 2014, 14:10
Also vielen Dank für eure ganze Hilfe, es funktioniert jetzt einwandfrei :DD... Man denkt irgendwie gar nicht dass so ein kleiner Fehler so großes Chaos verursachen kann...

Vg s137