Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: nooooooooos 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
-
Index 4? Also 4*0xF = 0x20?
Lädst du dann auch brav CS = 0x23? ;)
-
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...
-
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
-
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
-
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]
-
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
-
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
-
cr3 muss man nicht in das TSS eintragen.
Bei einem Interrupt wird cr3 nicht getauscht.
-
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...
-
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
-
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.
-
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
-
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)
-
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.
-
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
-
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.
-
So, jetzt funktionierts wuderbar!!
@SSJ7Gohan: Danke für den Hinweis, dass alle KernelStacks überall gemappt sein müssen.
Gruss
Noooooooos
-
Ich habe eine schreckliche Entdeckung gemacht, doch seht selbst:
Gruss
Noooooooos
Wir wurden unterwandert?!
CMP! :
nooooooooos
<>
Noooooooos
!!!
Hier stimmt was nicht!!!
PS: Nacht!