Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - rizor

Seiten: [1] 2 3 ... 27
1
Lowlevel-Coding / Re: x86-Startup
« am: 23. December 2015, 17:15 »
Danke fuer den Tipp. Hatte bisher nur mit QEmu getestet.
Jetzt klappt es und die anderen CPUs booten
2
Lowlevel-Coding / x86-Startup
« am: 15. December 2015, 23:34 »
Hallo zusammen,

habe mir mal ein wenig Code zusammen gebastelt, um die AP-Prozessoren zu starten.
Leider bekomme ich bei den IPIs immer Fehlercodes zurück.

Hier ist meine LAPIC-Initialisierung des BSP:
static __inline int __MaskLVT(ApicRegister i_register) {
    UInt32 value;

    int retval = CPU_ApicRead(i_register, &value);
    if (ESuccess != retval)
        return retval;

    return CPU_ApicWrite(i_register, value | (1 << 16));
}

static __inline int __CleanLApic() {
    UInt32 maxLvt;

    int retval = CPU_ApicRead(LocalApicVersion, &maxLvt);
    if (ESuccess != retval)
        return retval;
    maxLvt = (maxLvt >> 16) & 0xff;

    if (3 <= maxLvt) {
        retval = CPU_ApicWrite(LvtError, 0xfe | (1 << 16));
        if (ESuccess != retval)
            return retval;
    }

    retval = __MaskLVT(LvtTimer);
    if (ESuccess != retval)
        return retval;
    retval = __MaskLVT(LvtLInt0);
    if (ESuccess != retval)
        return retval;
    retval = __MaskLVT(LvtLInt1);
    if (ESuccess != retval)
        return retval;
    if (4 <= maxLvt) {
        retval = __MaskLVT(LvtPerformanceMonitoringCounters);
        if (ESuccess != retval)
            return retval;
    }

    retval = CPU_ApicWrite(LvtTimer, 1 << 16);
    if (ESuccess != retval)
        return retval;
    retval = CPU_ApicWrite(LvtLInt0, 1 << 16);
    if (ESuccess != retval)
        return retval;
    retval = CPU_ApicWrite(LvtLInt1, 1 << 16);
    if (ESuccess != retval)
        return retval;
    if (3 <= maxLvt) {
        retval = CPU_ApicWrite(LvtError, 1 << 16);
        if (ESuccess != retval)
            return retval;
    }
    if (4 <= maxLvt) {
        retval = CPU_ApicWrite(LvtPerformanceMonitoringCounters, 1 << 16);
        if (ESuccess != retval)
            return retval;
    }

    return ESuccess;
}

static __inline int __InitializeLogicDestination() {
    UInt32 value;
    int retval = CPU_ApicWrite(DestinationFormat, 0xffffffff);
    if (ESuccess != retval)
        return retval;
    retval = CPU_ApicRead(LogicalDestination, &value);
    if (ESuccess != retval)
        return retval;
    value &= ~(0xff << 24);

    UInt32 cpuId;
    retval = CPU_GetProcessorId(&cpuId);
    if (ESuccess != retval)
        return retval;
    value |= ((1 << cpuId) << 24);

    return CPU_ApicWrite(LogicalDestination, value);
}

int CPU_ApicInitialize() {
    UInt32 value;

    /* disable the PIC */
    CPU_IOPortWriteByte(0xa1, 0xff);
    CPU_IOPortWriteByte(0x21, 0xff);

    int retval = __CleanLApic();
    if (ESuccess != retval)
        return retval;

    retval = __InitializeLogicDestination();
    if (ESuccess != retval)
        return retval;

    /* set the task priority */
    retval = CPU_ApicRead(TaskPriority, &value);
    if (ESuccess != retval)
        return retval;
    value &= ~0xff;
    retval = CPU_ApicWrite(TaskPriority, value);
    if (ESuccess != retval)
        return retval;

    /* all done - activate the lapic */
    retval = CPU_ApicRead(SpuriousInterruptVector, &value);
    if (ESuccess != retval)
        return retval;
    value &= ~0xff;
    value |= (1 << 8) | 0xff;
    retval = CPU_ApicWrite(SpuriousInterruptVector, value);
    if (ESuccess != retval)
        return retval;

    return ESuccess;
}

Wenn ich über das MSR prüfe, ob die LAPIC aktiv ist, bekomme ich auch eine positive Rückmeldung.

Hier mein SMP-Init-Code (dabei verwende ich INIT-INIT-STARTUP):
static __inline int __BootApplicationProcessor(UInt16 i_cpuCount, UInt32 i_stacks[]) {
    UIntPtr size = (UIntPtr)__trampoline_smp_end - (UIntPtr)__trampoline_smp_start;
    UInt32* stackPtr = (UInt32*)(0x7000 + size - 8);
    UInt8 acpis[i_cpuCount];
    UInt32 status;

    int retval = ACPI_GetProcessorInformation(acpis);
    if (ESuccess != retval) {
        KLog(Error, "Unable to get processor information: %d\n", retval);
        return retval;
    }

    UInt32 ownId;
    retval = CPU_GetProcessorId(&ownId);
    if (ESuccess != retval) {
        KLog(Error, "Unable to get the own CPU-ID: %d\n", retval);
        return retval;
    }

    UInt32 low, high;
    CPU_ReadMsr(0x1B, &low, &high);
    if (0 == (0x800 & low)) {
        KLog(Error, "LAPIC is not disabled\n");
        return -ENoPermission;
    }

    UInt32 value;
    retval = CPU_ApicRead(ErrorStatus, &value);

    for (UInt16 i = 0, c = 0; i < i_cpuCount; i++) {
        if (ownId == acpis[i])
            continue;

        *stackPtr = i_stacks[c++];
        KLog(Info, "Bringing up CPU #%u...", acpis[i]);
        currentBootId = acpis[i];

        KLog(Debug, "Sending INIT-IPI-1...");
        retval = __SendIPI(0xc500, &status);
        if (ESuccess != retval)
            return retval;
        KLog(Debug, "%#x\n", status);

        __UDelay(10000);

        KLog(Debug, "Sending INIT-IPI-2...");
        retval = __SendIPI(0x8500, &status);
        if (ESuccess != retval)
            return retval;
        KLog(Debug, "%#x\n", status);

        retval = CPU_ApicRead(ErrorStatus, &value);
        if (ESuccess != retval)
            return retval;

        KLog(Debug, "Sending STARTUP-IPI...");
        retval = __SendIPI(0x600 | (0x7000 >> 12), &status);
        if (ESuccess != retval)
            return retval;
        KLog(Debug, "%#x\n", status);

        __UDelay(300);
        __WaitForApic(&status);
        __UDelay(200);

        retval = CPU_ApicRead(ErrorStatus, &value);
        UInt32 accept = value & 0xef;

        if (0 == accept && 0 == status) {
            while ((UInt32)~0x0 != currentBootId) ;
            continue;
        }

        if (0 != accept)
            KLog(Error, "APIC-delivery: %#x\n", accept);
        if (0 != status)
            KLog(Error, "APIC not delivered: %#x\n", status);

        return -EBusy;
    }

    return ESuccess;
}

status innerhalb der __SendIPI-Aufrufe gibt immer 0x1000 zurück.
Ich sorge durch io_delay auch dafür, dass ich die erforderliche Zeit warte, damit die APs genug Zeit bekommen.

Getestet ist der Code unter QEmu.

Sieht einer von euch den Fehler?
Die APIC-IDs hole ich mir über die ACPI-MADT-Tabelle.

Viele Grüße
rizor
3
Lowlevel-Coding / Re: ELF-Relocatables
« am: 24. December 2014, 21:20 »
Das klingt plausibel.
Alle Werte in diesen Bereichen zeigen auch in verschiedene Sektionen der ELF-Datei.
Halt immer an unterschiedliche. Von daher steht der Addend also schon an der Adresse.
4
Lowlevel-Coding / Re: ELF-Relocatables
« am: 24. December 2014, 14:28 »
So sieht objdump -R aus:

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
00002190 R_386_RELATIVE    *ABS*
00002194 R_386_RELATIVE    *ABS*
00002198 R_386_RELATIVE    *ABS*
0000219c R_386_RELATIVE    *ABS*
000021a0 R_386_RELATIVE    *ABS*
000021a4 R_386_RELATIVE    *ABS*
000021a8 R_386_RELATIVE    *ABS*
00002184 R_386_JUMP_SLOT   HALMemCopy
00002188 R_386_JUMP_SLOT   HALMemSet
0000218c R_386_JUMP_SLOT   HALStrEqual

Habe eben gesehen, dass viele ELF-Loader in diesem Fall ein Addend von 0 annehmen.
Ist vermutlich zur Minimierung da, da die R_386_RELATIVE in den meisten Faellen ja fuer Zugriff auf Data, etc. ausgehen.
5
Lowlevel-Coding / Re: ELF-Relocatables
« am: 24. December 2014, 12:09 »
Ah, okay. Jetzt habe ich es verstanden.
Allerdings wundert mich eines.
Ich habe eine REL-Sektion und dort sind R_386_RELATIVE enthalten, die angeblich aus dem Addend bestehen, allerdings enthaelt die REL-Sektion doch keine RELA-Eintraege, oder?
Ist dann Addend automatisch 0?
6
Lowlevel-Coding / Re: ELF-Relocatables
« am: 23. December 2014, 23:26 »
Danke, das hilft schon mal richtig weiter.
Du machst aber ein 1:1-Mapping, oder?

Erlaubt es ELF eigentlich, dass zwei Program-Header, die geladen werden koennen, nicht den selben Offset zwischeneinander haben wie in der Datei definiert?

Also z.B.:
Program-Header 1: Offset 0x1000
Program-Header 2: Offset 0x2000
Und jetzt lade ich Header 1 an 0x1000
und Header 2 an 0x3000.

Geht das oder muss ich mich bei ELF an die Offsets halten und darf nur die globale Base-Addresse veraendern?
7
Lowlevel-Coding / ELF-Relocatables
« am: 23. December 2014, 13:09 »
Hallo zusammen,

ich sitze gerade daran einen modularen Kernel zu bauen und versuche ELF zu verstehen.
Für Executables ist es ja recht einfach, aber Relocatables verwirren mich etwas.
Hier mal meine Interpretation, wie ich den ganzen Spaß zu interpretieren und zu laden habe:

Wenn ich Abhängigkeiten zu anderen Modulen habe, wird eine .plt-Sektion angelegt, die eigentlich nichts anderes als ein großes Array ist,
in das ich die entsprechenden absulten Adressen der Funktionen eintragen muss, oder?
Dann habe ich noch eine .got.plt.
Die ist dafür da, dass ich die Relocation meines Moduls anpassen kann und die richtigen Stellen in der .plt angesprungen werden, oder?

Dann habe ich noch .rel.dyn. Was mache ich damit? Anhand des Namens sehe ich, dass es dabei um die Relocation geht, aber so ganz kapiere ich den Teil noch nich.

Allerdings verstehe ich nicht wozu .dynsym und .dynstr da sind.
Was soll ich mit denen anfangen?
.dynsym sehe ich momentan als eine Art Offset-Tabelle an, die mir angibt welche Funktionen zu welcher Sektion und zu welchen Offset gehören.
Ist das richtig?
Aber dafür hätte ich doch auch .symtab. Die sagen doch genau das Gleiche aus, oder?

Grüße
rizor
8
Lowlevel-Coding / Re: Werte übergeben
« am: 30. May 2014, 14:31 »
Hier mal ein rudimentärer String:

struct String {
    char *m_charArr;
    int m_length;
};

So könnten Strings verwaltet werden.
Dann würde deine Funktion so aussehen:
void myfunc(struct String* i_string, const char[] text);

Das Problem an der ganzen Geschichte ist, dass du nichts gewinnst. Weder Lesbarkeit, noch einfacheren Code.
Denn du musst die gesamte String-Funktionalität wieder auf char-Arrays rechnen. Macht C++ auch nicht anders.
Somit musst du im Prinzip alle Funktionen der string.h-Datei auf "struct String" implementieren. Das tut nicht weh,
aber ist unnötig. Der einzige offensichtliche Vorteil ist die Möglichkeit die Länge des Char-Arrays/String implizit zu bestimmen
und somit auf strlen verzichten zu könne.
9
Lowlevel-Coding / Re: Werte übergeben
« am: 30. May 2014, 11:20 »
Das extern funktioniert auch bei Funktionen, allerdings bin ich mir nicht sicher, ob er die Funktion in diesem Fall nimmt,
da das extern ihm sagt, dass sie woanders liegt und er gleichzeitig eine Definition findet.
10
Offtopic / Re: Wohin kann man mit Werten?
« am: 21. May 2014, 21:15 »
Das ist komplizierter. Dafür kannst du Festplatten, USB-Sticks und Disketten verwenden. Allerdings brauchst du dafür entsprechende Treiber.
Entweder einen Treiber für die Festplatten, bzw. den USB-Hub oder einen Floppy-Treiber (der noch der Einfachste sein dürfte).
Dann brauchst du noch einen Dateisystemtreiber (z.B. FAT, NTFS oder ext2/ext3/ext4). Und dann kannst du dir überlegen wie die Datei aussehen muss.
Würde dir empfehlen die Idee erst einmal zu verwerfen. Dazu brauchst du eine funktionierende Speicherverwaltung, etc.
11
Offtopic / Re: Wohin kann man mit Werten?
« am: 21. May 2014, 21:04 »
Ich glaube mal, dass es ein grundlegendes Verständnisproblem ist.

Du bekommst den Speicher (die Adressen) auf zwei Arten, zumindest wenn wir mal von C/C++ ausgehen.
Entweder deine Werte (Variablen) liegen auf dem Stack, der ist auch im RAM zu finden.
Wenn man mal von der OS-Entwicklung weg geht, dann bekommt dein Programm vom OS einen Speicher auf dem RAM zugewiesen, der als Stack
verwendet wird. Dann kannst du innerhalb von Funktionen Variablen definieren, die dann vom Compiler auf den Stack gelegt werden.
Allerdings sind diese Werte verschwunden, wenn die Funktion abgearbeitet wurde.

Eine andere Möglichkeit ist der Heap. Die Variablen auf dem Heap bleiben auch gültig, wenn die Funktion beendet ist.
Dazu gibt es beim OS eine sogenannte Speicherverwaltung. Die garantiert dir, dass dein Speicher nicht doppelt belegt wird.
Dazu gibt es bei C die Funktionen malloc und free. Malloc holt dir Speicher, den du verwenden kannst und free gibt ihn wieder zurück.
Nach dem free ist der Wert natürlich ungültig, da du damit dem OS sagst, dass du diesen Speicher nicht mehr benötigst.
Bei C++ heißen die Funktionen new und delete. Machen eigentlich genau das gleiche. Allerdings werden hier noch Konstruktoren der Klassen aufgerufen, weshalb es andere Funktionen als malloc und free sind. Das führt aber hier zu weit.

Für dich ist es nur wichtig zu wissen welchen Speicher es gibt. Also auf dem Stack und auf dem Heap.

Falls es wirklich um die OS-Entwicklung geht, dann sag nochmal bescheid. Dann muss man das etwas anders erklären.
12
Offtopic / Re: Wohin kann man mit Werten?
« am: 21. May 2014, 19:00 »
Solange du das System nicht wieder startest, nimmst du den RAM.
Es liegt dann an dir, dass du dir die RAM-Adresse merkst an der du deinen Wert gespeichert hast, zzgl. der Größe des Wertes.
Dann kannst du immer wieder darauf zugreifen.
13
Offtopic / Re: Wohin kann man mit Werten?
« am: 21. May 2014, 17:23 »
Was meinst du mit Lager?
Im RAM kannst du jede Form von Datenstruktur (Zahlen (Ganzzahlen und rationale Zahlen), Zeichenketten, Strukturen, etc.) speichern.
Ist alles eine Frage der Interpretation.
14
OS-Design / Re: Code-Dispatcher
« am: 31. January 2013, 17:54 »
Danke für die Links.
Sowas habe ich gesucht.
Macht es mir zumindest mal einfacher.
15
OS-Design / Code-Dispatcher
« am: 31. January 2013, 15:52 »
Hi zusammen,

ich versuche gerade die Module meines Kernels so umzubauen, dass sie abhängig von der Architektur optimalen Code ausführen.
z.B. Es soll eine generische memset funktion geben und dann noch eine optimierte, damit die Hardware optimal ausgenutzt wird.
Das wollte ich so machen, dass mein Module-Loader die Funktionen entsprechend wählt, bzw. dass das Modul anhand der Architektur sagt, welche Funktionen genutzt werden sollen.

Habt ihr Ideen, wie man das am Effektivsten umsetzen kann?

Grüße,
rizor
16
Lowlevel-Coding / Re: Treiber gleich Prozess?
« am: 18. January 2013, 11:43 »
Und wenn du sie als Module (Libraries) baust, hast du einen modularen Kernel.
17
Offtopic / Re: Beichte
« am: 25. November 2012, 12:52 »
Ich habe es mir auch installiert.
An sich ist die Idee nicht schlecht, die sie mit Metro hatten, allerdings mal wieder nicht bis zum Ende gedacht.
Viele Komponenten wirken noch recht unfertig und einfach nur mal schnell dahin gehackt.

Ansonsten habe ich einen reproduzierbaren Bluescreen entdeckt, der u.U. bald mal gefixt wird.
Einfach mal bei Hyper-V die aktive Netzwerkkarte als Extern an den Guest weiterreichen und in Win8 dann eine Webseite aufrufen.
Und schon fliegt es einem um die Ohren :D

Man kann sich aber an den Wechsel zwischen Metro und Desktop gewöhnen.
Außerdem ist die Akkulaufzeit meines Notebooks um ca. 10% gestiegen, was auch sehr schön ist und sogar Connected Standby funktioniert sehr gut.

Ein Manko ist, dass MS groß angegeben hat, dass man nach Updates das System sehr selten neu starten muss.
Es gab für mich jetzt zwei große 400 MB Patches und ich musste beide Male das System neu starten... MS hat eine komische Definition von "sehr selten" ;)

So, hier etwas Hassfutter :D
18
Lowlevel-Coding / Re: Relocatable ELF
« am: 17. September 2012, 14:44 »
So, habe doch noch ein Problem.

Bin bei folgendem Stand:
Kann eine ELF komplett gegen eine bestimmte Adresse linken.
Wenn ich nun die Program Header durchgehen möchte und den Code in den RAM laden will,
stelle ich fest, dass meine Program-Header 0 sind.

Muss ich bei einer Relocatable-ELF durch die Section-Tables laufen und alles so laden?
19
Lowlevel-Coding / Re: Kernel mit GCJ
« am: 14. September 2012, 12:46 »
Falls du dir nicht sicher bist, ob die Funktionen referenziert werden, lass gjc und ld mal Testweise mit -flto laufen.
Wenn du in der Binary das Dingen dann noch immer findest, übersiehst du nur die Referenz ;)
20
Lowlevel-Coding / Re: Relocatable ELF
« am: 14. September 2012, 08:27 »
Hat sich erledigt.
Code hat den falschen Index ermittelt...
Seiten: [1] 2 3 ... 27

Einloggen