Autor Thema: Ring0 -> Ring3  (Gelesen 9695 mal)

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« am: 11. January 2006, 16:41 »
Hallo

Ich habe Softwaremultitasking in einem flachen Speichermodell. Nun will ich auch Ring3 Tasks implementieren. Das funktioniert aber nicht. Nach dem iret zum Ring3 Task meldet Bochs: "ss.rpl != cs.dpl". Dann zeigt Bochs die Werte aller Register zum Zeitpunkt des Fehlers. Da steht das RPL von SS = 3 ist. Und der Index von CS = 4. In der GDT im 4. (bzw. 5.) Deskriptor ist das DPL "11b" für Ring3 eingetragen. Wiso funzt das nicht??

Hier mein Deskriptor:
dw 0xFFFF                    ;Limit
dw 0                            ;Keine Startadresse
db 0
db 11111010b
db 0xCF
db 0


Vielen Dank
Nooooooooooos

Legend

  • Beiträge: 635
    • Profil anzeigen
    • http://os.joachimnock.de
Gespeichert
« Antwort #1 am: 11. January 2006, 16:56 »
Index 4? Also  4*0xF = 0x20?

Lädst du dann auch brav CS = 0x23? ;)
*post*

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #2 am: 11. January 2006, 18:32 »
Zitat von: Legend
Index 4? Also  4*0xF = 0x20?

fast  :lol:

Wie sehen den die Register laut Bochs nach dem Taskswitch aus (copy&paste doch mal plz)? Was du erzählst hört sich nämlich richtig an...
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

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 11. January 2006, 20:08 »
Ja ich schreib 23h. Die Register von Bochs:
00000900038p[CPU0 ] >>PANIC<< interrupt(): SS.rpl != CS.dpl
00000900038i[SYS  ] Last time is 1137006314
# In bx_win32_gui_c::exit(void)!
00000900038i[CPU0 ] protected mode
00000900038i[CPU0 ] CS.d_b = 32 bit
00000900038i[CPU0 ] SS.d_b = 32 bit
00000900038i[CPU0 ] | EAX=00000000  EBX=00000000  ECX=00000000  EDX=00000000
00000900038i[CPU0 ] | ESP=00070000  EBP=00000000  ESI=00000000  EDI=00000000
00000900038i[CPU0 ] | IOPL=0 NV UP EI PL NZ NA PO NC
00000900038i[CPU0 ] | SEG selector     base    limit G D
00000900038i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00000900038i[CPU0 ] |  CS:0023( 0004| 0|  3) 00000000 000fffff 1 1
00000900038i[CPU0 ] |  DS:002b( 0005| 0|  3) 00000000 000fffff 1 1
00000900038i[CPU0 ] |  SS:002b( 0005| 0|  3) 00000000 000fffff 1 1
00000900038i[CPU0 ] |  ES:002b( 0005| 0|  3) 00000000 000fffff 1 1
00000900038i[CPU0 ] |  FS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00000900038i[CPU0 ] |  GS:0000( 0000| 0|  0) 00000000 0000ffff 0 0
00000900038i[CPU0 ] | EIP=00008122 (00008122)
00000900038i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00000900038i[CPU0 ] | CR3=0x00000000 CR4=0x00000000


Gruss Nooooooooos

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 11. January 2006, 20:22 »
Könnte es vieleicht daran liegen, dass ich im TSS noch sonstige Register usw. speichern muss. Muss man da mehr also nur der esp0 reinschreiben. Ist das das einzige oder muss da noch mehr rein????


Gruss
Noooooooos

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #5 am: 11. January 2006, 20:32 »
du musst beim software-multitasking nur esp0, ss0 und cr3 im TSS ausfüllen. Kann es sein, dass der Fehler erst beim zurückspringen vom Task zum Kernel passiert, d.h. esp0/ss0 im TSS nicht richtig ausgefüllt sind :?:
Interrupts deaktiviert :?:

[edit: cr3 nur bei aktivem Paging]
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

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 11. January 2006, 20:40 »
Den ss0 hab ich eingetragen, doch es funzt immer noch nicht.
Es ist möglich, dass der Fehler erst beim Wechsel vom Ring3 zum Ring0 geschieht.

Gruss Noooooooos

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 11. January 2006, 20:55 »
Ich hab den Bug. Ich hatte von früher mal ne Zeile die ss0 im TSS mit dem Ring3 Selektor belädt.

@bluecode: Vielen Dank für die schnelle Hilfe. Ohne dich hätte es noch lange gedauert, bis ich den Bug gefunden hätte!!!!

Gruss
Nooooooooos

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 11. January 2006, 21:28 »
cr3 muss man nicht in das TSS eintragen.
Bei einem Interrupt wird cr3 nicht getauscht.

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #9 am: 11. January 2006, 22:43 »
Zitat von: SSJ7Gohan
cr3 muss man nicht in das TSS eintragen.
Bei einem Interrupt wird cr3 nicht getauscht.


ups, stimmt :oops:
muss man beim software-taskswitching vor dem Taskswitch laden...
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

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 23. January 2006, 17:46 »
Die Ring3 Tasks funktionieren nun schon eine ganze Weile, aber jetzt habe ich ein neues Problem, dass gerade auch noch in diesen Theard passt:  (benutze immer noch Software-MT)

Kann man für einen Interrupt ein anderes CR3 als für den Task speichern, denn wenn ich aus (dem vom Scheduler neu geladenen)Stack den neuen Wert fürs CR3 poppen will, geht das doch nicht, weil ja immer noch die Adresse des PG des alten Tasks im CR3 ist, und somit die Stack-Adresse des neuen Tasks falsch ist.

Wie löse ich das Problem??? Könnte das über das CR3-Feld im TSS gehen????


Gruss
Noooooooooooos

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #11 am: 23. January 2006, 19:01 »
Zitat von: nooooooooos
Kann man für einen Interrupt ein anderes CR3 als für den Task speichern, denn wenn ich aus (dem vom Scheduler neu geladenen)Stack den neuen Wert fürs CR3 poppen will, geht das doch nicht, weil ja immer noch die Adresse des PG des alten Tasks im CR3 ist, und somit die Stack-Adresse des neuen Tasks falsch ist.


Vielleicht hab ich verstanden welches Problem du hast :lol:
Ich versuchs mal mit ner "Grafik":
Task1 / ThreadStack1 / Cr3-1 -> [Interrupt] -> InterruptHandler / KernelThreadStack1 -> Stackswitch zum KernelStack -> Aufruf des Schedulers -> Aussuchen eines neien Tasks -> Laden von Cr3-2 -> Stackswitch zu KernelThreadStack2 -> [Iret] -> Task2 / ThreadStack2 /Cr3-2

Hab des jetzt mir mal aus den Fingern gesogen, also keine Garantie.
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

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 23. January 2006, 19:07 »
Also muss ich das CR3 und den Theardstack abspeichern, wobei, das CR3 unveränderlich ist????????

Aber wozu muss man denn im TSS das CR3 eintragen????

Gruss Nooooooooos

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 23. January 2006, 19:38 »
Im TSS muss man CR3 nicht eintragen (siehe die letzten Posts).

CR3 wird bei einem Interrupt nie geändert - egal ob Software oder Hardwaretasking.

Du mappst einfach den Kernelstack jedes Threads in jeden Prozess. (Der Kernel ist ja normalerweise eh in alle Prozesse gemappt). Dann kannst du ganz einfach das CR3 ändern indem du "mov eax, [deine_thread_struktur + offset des cr3 registers]" und "mov cr3, eax" machst. Du kannst natürlich auch CR3 immer auf den Taskstack pushen und dann popen, ich mache das aber nicht, weil bei mir nicht alle Tasks unterschiedliche CR3s haben (ein CR3 Switch kostet einige Hundert P4 Taskzyklen)

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 23. January 2006, 19:54 »
Also, muss ich sowohl das CR3 also auch den KernelStack des Tasks irgendwo abspeichern???????????


Du sagst aber, dass man das CR3 auch auf dem KernelStack speichern kann. Wie soll denn das funktionieren??? Wenn ich jetzt den neuen Stack vom Scheduler erhalte, wie poppe ich da das CR3, denn mit dem alten CR3 werden die Adressen ja noch anders gemappt. Wie kann ich also etwas vom Stack poppen, ohne das dazugehörige CR3 zu kennen.

SSJ7Gohan

  • Beiträge: 398
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 23. January 2006, 20:19 »
Die Kernelstacks müssen in alle Prozesse gemappt sein.
Du kannst es dann so pushen / popen

; cr3 pushen
mov eax, cr3
push eax

; [...]
; scheduler aufrufen, stacks ändern usw.

pop eax
mov cr3, eax

Osbios

  • Beiträge: 247
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 24. January 2006, 14:44 »
Ich habe mir mal irgendwann ein "inline" Schaubild für die Adressierung gemacht:
;paging and addressspace:
;KERNEL   TASK0    TASK1    TASK2 ...
;         (CR3)    (CR3)    (CR3)
;
;          ||       ||       ||
;          \/       \/       \/
;
;          DT 4GB   DT 4GB   DT 4GB
; //------<--------<--------<
; ||       ||       ||       ||
; \/       \/       \/       \/
;
; PT 1GB   PT 3GB   PT 3GB   PT 3GB
;
; ||       ||       ||       ||
; \/       \/       \/       \/
; _____________________________
;/             RAM             \


Der Kernel hat selber keine Descriptortable (DT), bzw. er benutzt den letzten GiB Adressbereich jedes Tasks. Du muss nur bedenken dass bei Änderungen im 3-4 GiB Bereich alle Descriptortables mit einbezogen werden.
db 0x55AA

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 24. January 2006, 19:56 »
So, jetzt funktionierts wuderbar!!

@SSJ7Gohan: Danke für den Hinweis, dass alle KernelStacks überall gemappt sein müssen.

Gruss
Noooooooos

Osbios

  • Beiträge: 247
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 24. January 2006, 22:20 »
Ich habe eine schreckliche Entdeckung gemacht, doch seht selbst:

Zitat von: nooooooooos
Gruss
Noooooooos


Wir wurden unterwandert?!

CMP! :
nooooooooos
<>
Noooooooos


!!!

Hier stimmt was nicht!!!

PS: Nacht!
db 0x55AA

 

Einloggen