Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: Cheebi am 31. July 2007, 15:56
-
ohjee... warum bekomm' ich denn eine General-Protection-Fault-Exception, wenn ich folgenden Code ausführe?
__asm__ volatile ("ltrw %%ax"::"a"(0x18));
cli();
for(;;);
Descriptor 3 der GDT ist der TSSDescriptor und hat folgende Werte:
Word1: 0x00000068
Word2: 0x05808900
Das heißt also:
Größe = 104 Byte
Base = 0x5000000
Busy = false
DPL = 0
Present = true
Granular = true
Vom TSS selbst sind nur die beiden Einträge ss0 und esp0 mit Werten besetzt. Alle anderen Einträge tragen den Wert 0.
Warum komme ich also nie zu den Befehlen nach ltrw?
Gruß Cheebi
-
Meine ASM-Referenz sagt mir das es für diesen GP-Error folgende glünde geben kann:
- CPL ist größer 0
- Selector zeigt auf eine stelle außerhalb der GDT
- Selector zeigt nicht auf ein TSS
- Selector zeigt auf activen task
Wenn ich das richtig verstanden habe löst das Ding nen TastSwitch aus, oder?
Dann soltest du auch die Selectoren und EIP im TSS überprüfen.
[edit]
:oops: man solte schon zu ende lesen :oops:
wenn CS null ist gibt das natürlich auch nen GP
-
Mein TSS Deskriptor sieht folgendermaßen aus:
dw 0x0068
dw 0x0000
db 0x00
db 0x89
db 0x40
db 0x00
Auf jeden Fall solltest du Granularity auf 0/false setzen.
-
@MNemo: Nein, das Ding löst keinen Taskswitch aus. Es lädt nur einen Selektor in das Taskstateregister.
-
@bluecode:
ich hatte folgende Quelle:
http://en.skelix.org/skelixos/tutorial06.php
nach der ist das Granular-Bit zu setzen... Aber auch ohne es zu setzen, tritt bei mir ne GP auf.
dw 0x0068
dw 0x0000
db 0x00
db 0x89
db 0x40
db 0x00
Warum hast du ein reservierte Bit true gesetzt? (Das 7. Bit des 7. Bytes hast du true gesetzt [db 0x40])
gruß Cheebi
-
@MNemo: Nein, das Ding löst keinen Taskswitch aus. Es lädt nur einen Selektor in das Taskstateregister.
So stand das ach in der ASM - Referenz, konnt mir nur bis eben nix drunter vorstellen.
Dann sollte der Inhalt des TSS ach nicht von Bedeutung sein. Aber das Granularity bit soltest du wirklich aus machen(ich denke nicht das dein tss 104 * 4kb groß ist) und das D-Bit solte dafür vielecht an du hast ja auch im TSS-Type den 368 ausgewählt.
[edit]
bluecode hat das D-Bit auf eins gesetzt nicht ein reservirtes bit.
-
Hm stimmt. Laut den Intel Manuals (6.6.2 TSS Descriptor) ist das Bit reserviert/0... und bei mir funktionierts auch wenn das Bit gelöscht ist. Laut Intel manual können bei ltr folgende Sachen einen GPF auslösen:
#GP(0) If the current privilege level is not 0.
If a memory operand effective address is outside the CS, DS,
ES, FS, or GS segment limit.
If the source operand contains a NULL segment selector.
If the DS, ES, FS, or GS register is used to access memory and it
contains a NULL segment selector.
#GP(selector) If the source selector points to a segment that is not a TSS or to
one for a task that is already busy.
If the selector points to LDT or is beyond the GDT limit.
-
Hm stimmt. Laut den Intel Manuals (6.6.2 TSS Descriptor) ist das Bit reserviert/0...
Ok. fh-zwickau.de (http://www.fh-zwickau.de/doc/prmo/pmtutor/text/p_spez2.htm) ist dann wohl nicht ganz so zuverlässig. (Ist ja auch nicht der einzigste Fehler)
-
Ahso, daher hab ich also den Mist. :-D :mrgreen:
-
sooo... Problem gelöst:
Ich habe vergessen, die GDT neu zu laden, nachdem ich einen neuen Descriptor (TSSDesc) angelegt habe. (also das Feld GDT.size musste mit Hilfe von lgdt [GDT] aktualisiert werden).
Ich habe aber immer noch eine Frage:
Ist es sinnvoll, die GDT von Anfang an mit Nulldescriptoren zu füllen und dementsprechend das Feld GDT.size gleich so zu setzen:
GDT.base = 0x0;
GDT.size = (sizeof(SDESCRIPTOR) * MAX_DESCS) - 1;
load_GDT(GDT);
Oder sollte man bei jedem neu angelegten Descriptor die GDT mit neuen Werten laden?
Gruß Cheebi
-
Ich seh eigentlich keinen Grund warum man die GDT überhaupt zur Laufzeit erweitern muss (wenn man mal SMP außen vor lässt). Aber ansonsten würd ich die Bereiche einfach 0 setzen und das GDTR nicht aktualisieren. Kann ja im Prinzip nichts passieren, da das present-bit auf 0 gesetzt ist.