Autor Thema: Problem mit Multitasking im Ring3  (Gelesen 4918 mal)

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« am: 03. July 2010, 12:32 »
Hallo,

nachdem ich mein OS nochmal von vorne angefangen habe, hänge ich nun wiedermal beim Multitasking am Wechsel in den Userspace.
Das komische ist, das mein Bluescreen nichtmal aufgerufen wird, obwohl er ansonsten funktioniert. Stattdessen stürzt QEMU ab.

Hier die Ausgaben von QEMU:
qemu: fatal trying to execute code outside RAM or ROM at 0x2e532074

EAX=00000000 EBX=32303032 ECX=00000000 EDX=00000000
ESI=6e614d20 EDI=6b617264 EBP666f5365 ESP=ffffff18
EIP=2e532074 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300
CS =0008 00000000 ffffffff 00cf9a00
SS =0010 00000000 ffffffff 00cf9300
DS =0010 00000000 ffffffff 00cf9300
FS =0000 00000000 00000000 00000000
GS =0000 00000000 00000000 00000000
LDT=0000 00000000 0000ffff 00008200
TR =0028 00103020 00000080 0000e910
GDT=     00104000 00000037
IDT=     001080c0 000007ff
CR0=60000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=0000007c CCD=00000000 CCO=LOGICL
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0-7 (alle gleich) = 0000000000000000 0000
XMM00-07 (alle gleich) = 00000000000000000000000000000000

meine GDT:
struct {uint16_t limit;
void* pointer;
} __attribute__((packed)) gdtp = {
.limit = GDT_ENTRIES * 8 - 1,
.pointer = gdt,
};

// GDT-Eintraege aufbauen
gdt_set_entry(0, 0, 0, 0);
gdt_set_entry(1, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
GDT_FLAG_CODESEG | GDT_FLAG_4K | GDT_FLAG_PRESENT);
gdt_set_entry(2, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
GDT_FLAG_DATASEG | GDT_FLAG_4K | GDT_FLAG_PRESENT);
gdt_set_entry(3, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
GDT_FLAG_CODESEG | GDT_FLAG_4K | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
gdt_set_entry(4, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT |
GDT_FLAG_DATASEG | GDT_FLAG_4K | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
gdt_set_entry(5, (uint32_t) tss, sizeof(tss),
GDT_FLAG_TSS | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
// GDT neu laden
asm volatile("lgdt %0" : : "m" (gdtp));

// Segmentregister neu laden, damit die neuen GDT-Eintraege auch wirklich
// benutzt werden
asm volatile("mov $0x10, %ax;"
"mov %ax, %ds;"
"mov %ax, %es;"
"mov %ax, %ss;"
"ljmp $0x8, $.1;"
".1:");
// Taskregister neu laden
asm volatile("ltr %%ax" : : "a" (5 << 3));

init_multitasking():
task_states[0] = init_task(stack_a, user_stack_a, task_a);
task_states[1] = init_task(stack_b, user_stack_b, task_b);

irq_common_stub:
; CPU-Zustand sichern
    push ebp
    push edi
    push esi
    push edx
    push ecx
    push ebx
    push eax
 
; Kernel-Datensegmente laden
    mov ax, 0x10
    mov ds, ax
    mov es, ax
 
    ; Handler aufrufen
    push esp
    call interrupt_handler
    mov esp, eax

; User-Datensegmente laden
    mov ax, 0x23
    mov ds, ax
    mov es, ax
 
    ; CPU-Zustand wiederherstellen
    pop eax
    pop ebx
    pop ecx
    pop edx
    pop esi
    pop edi
    pop ebp
 
    ; Fehlercode und Interruptnummer vom Stack nehmen
    add esp, 8
 
    ; Ruecksprung zum unterbrochenen Code
    iret

Wenn ihr nochwas braucht, bitte bescheid sagen.
Bevor die Frage kommt, in meinem alten Kernel hatte ich nur Ring0 Multitasking

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 03. July 2010, 15:02 »
Ist dein Stack in Ordnung? Das sieht aus als würde das iret an irgendeine nicht beabsichtigte Adresse springen.

Edit: Hm, nein eigentlich sind deine Datenregister noch auf den Kernelwerten. Der kaputte Sprung muss schon irgendwo vorher passieren.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #2 am: 03. July 2010, 19:55 »
Die tasks laufen los, stürzen nur sehr schnell wieder ab.
Es kommen auch beide an die Reihe, also kann es doch nur im Handler schiefgehen, oder?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 03. July 2010, 20:04 »
Wenn du gar nicht drauf kommst, woran es liegt, kannst du qemu mittracen lassen, was er so ausführt. (-d in_asm -singlestep oder sowas war das). Der Code läuft dann natürlich etwas langsamer.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #4 am: 03. July 2010, 20:59 »
das letzte was er macht ist scheinbar ein iret zu sein

wenn ich nur -d in_asm angebe, fährt er gar nicht hoch
hab dann jetzt noch op angegeben

eigentlich ist es der code aus dem tutorial, deswegen versteh ich nicht, warum das nicht geht :?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 03. July 2010, 21:21 »
Dann würde ich mal einen Breakpoint auf dieses iret setzen und mir anschauen, wie der Stack vor dem iret aussieht.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #6 am: 03. July 2010, 21:50 »
das werde ich gleich mal ausprobieren.
vorher ist mir noch was anderes aufgefallen, im beispielkernel wird ja pushl verwendet um fehler- und irqnummern auf den stack zu legen. Ich habe aber push byte ...
kann es vielleicht daran liegen, weil mein add esp, 8 dann nicht stimmt?

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #7 am: 04. July 2010, 10:33 »
Ja. :-) (siehe taljeth)
« Letzte Änderung: 04. July 2010, 11:12 von bluecode »
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 04. July 2010, 11:05 »
Hatten wir uns nicht gestern im IRC geeinigt, dass trotzdem 32 Bit auf dem Stack landen? ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 04. July 2010, 11:52 »
Hallo,


ich bin mir ziemlich sicher das es im x86-32Bit-PM möglich ist einen 8 Bit-Wert oder auch einen 32 Bit-Wert zu pushen.
Wo ich mal so eine Liste mit den 256 Individuellen Interrupt-Einsprungspunkten erstellt habe hat der Assembler für die Werte 0...127 einen 8 Bit-Push-Befehl (OpCode 0x6A) erzeugt und für den Rest einen 32 Bit-Push (OpCode 0x68), ich habs dann so umformuliert das immer ein 32 Bit-Wert gepusht wurde. Wenn man einen 16 Bit-Wert pushen möchte (was IMHO auch geht) dann wird dieses 0x66-Präfix (für OpCode 0x68) benötigt.
Oder meint Ihr das beim 8Bit Befehl es nur darum geht das der Immed-Wert (als Bestandteil des Befehls-OpCodes) nur 8 Bit groß ist und dieser dann immer zum pushen vorzeichengerecht auf 32Bit erweitert wird? Dann wäre es ja gar nicht möglich einzelne Bytes (ohne Registerbenutzung) auf den Stack zu legen, es würde mir schwer fallen an eine derartige Einschränkung zu glauben.


@littlefox:
Nimm einfach die 32Bit-Variante, ausgerichtete Speicherzugriffe gefallen der CPU deutlich besser.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 04. July 2010, 12:19 »
Es geht hier um ein Immediate-Push, und die werden alle auf 32 Bit sign-extended (im PM). Wenn man über ein Register oder Speicher geht, kann man auch 16 oder 64 Bit pushen, aber byteweise geht nicht.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #11 am: 04. July 2010, 12:20 »
das Problem hat sich gerade von sich aus erledigt :? :?
Hab gerade mal den CPU Zustand beim Taskwechsel ausgeben lassen und damit gerechnet, dass QEMU nur einmal zu diesem Punkt kommt.
QEMU lief weiter!
Jetzt funktionierts, obwohl ich eigenlich nix geändert hab :?

Wenn sich alle Probleme so lösen würden ... :lol:
« Letzte Änderung: 04. July 2010, 16:16 von littlefox »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 04. July 2010, 12:35 »
Ein Problem, das auf diese Weise "gelöst" ist, kommt garantiert wieder. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #13 am: 04. July 2010, 13:11 »
solange es nicht sofort wieder kommt :D

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #14 am: 04. July 2010, 13:24 »
Die Probleme die erst nach Ewigkeiten wieder auftauchen sind erfahrungsgemäß die schlimmsten, da die Codebase um einiges größer ist und die Auswahl wo das Problem liegt auch. Abgesehen davon sucht man nach dem Fehler erfahrungsgemäß erstmal in dem neuesten Sourcecode, wird aber da leider nicht fündig werden.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #15 am: 04. July 2010, 13:27 »
was soll ich denn jetzt machen?
Ich kann doch keinen Fehler beseitigen, der nicht mehr da ist ...
 :|

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #16 am: 04. July 2010, 14:41 »
Die Debugausgaben wieder rausnehmen und rausfinden warum es dann nicht funktioniert, oder so...
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #17 am: 04. July 2010, 14:45 »
die sind schon wieder raus und es geht trotzdem

EDIT: juhuu Jr. Member :D

 

Einloggen