Autor Thema: GP-Fault beim schreiben von CR0  (Gelesen 5056 mal)

streetrunner

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« am: 17. March 2014, 20:17 »
Guten Abend,

ich bin gerade dabei einen Startup-Code zu schreiben um in den Long-Mode zu kommen. Dabei bin ich auf einen Fehler gestoßen zu dem mir überhaubt nicht einfällt wie dieser zu stande kommen könnte. Es geht sich um folgendes: So bald ich diesen Code
asm volatile("movl %cr0, %eax");
asm volatile("or $0x80000000, %eax");
asm volatile("movl %eax, %cr0");
ausführe bricht mir qemu mit einem GP-Fault ab. Hier mal die interessanten Zeilen des Logs:
0: v=0d e=0010 i=0 cpl=0 IP=0008:0000000000100ba2 pc=0000000000100ba2 SP=0010:00000000433385e6 env->regs[R_EAX]=000000002bb00fe3
EAX=2bb00fe3 EBX=00009500 ECX=c000007b EDX=a30c3147
ESI=93416461 EDI=00129000 EBP=00104fc0 ESP=433385e6
EIP=00100ba2 EFL=00000003 [------C] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00104fa8 00000017
IDT=     00000000 000003ff
CR0=80000011 CR2=00000000 CR3=08000000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000001 CCD=2bb00fe3 CCO=INCL   
EFER=0000000000000000
So bald ich aber "asm volatile("movl %eax, %cr0")" auskommentiere läuft alles wie geschmiert (außer dass das Paging natürlich nicht aktiviert wird). Ein objdump hat mir bis jetzt auch nicht weitergeholfen, denn die Speicheraddresse in EIP liegt nicht mehr in meinem Code, sondern irgendwo dahinter (aber immer noch im .text Segment).
Hat irgendjemand eine Ahnung woran dass liegen könnte?

Gruß,

Streetrunner

PS: Der Fehler ist natürlich reproduzierbar

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 17. March 2014, 21:05 »
Nach dem Ende des asm-Blocks garantiert dir kein Mensch, welchen Inhalt die Register haben. Du hast dem Compiler außerdem nicht mitgeteilt, dass du eax benutzt, d.h. er könnte darin eigentlich noch andere Daten gespeichert haben. Mach einen einzigen asm-Block draus (als einen einzigen langen C-String mit Zeilenumbrüchen drin) und benutz die Clobber-Liste:
asm volatile(
    "movl %cr0, %eax\n"
    "or $0x80000000, %eax\n"
    "movl %eax, %cr0"
: : : "eax");
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

streetrunner

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 17. March 2014, 22:02 »
Danke für deine Hilfe,

leider ergibt sich damit der gleiche Fehler. Nach objdump gibt es keinen Unterschied zwischen den beiden Versionen.

Gruß,

Streetrunner

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 17. March 2014, 23:32 »
Ist es gewollt, dass sich das Page Directory an Adresse 0x08000000 (CR3) befindet? Das ist nämlich 128 MB und soviel hat QEMU per default nicht. Wenn es nicht gewollt ist, liegt die Schuld vermutlich an der physischen Speicherverwaltung.
« Letzte Änderung: 17. March 2014, 23:35 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

streetrunner

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 18. March 2014, 00:03 »
Ja ist es. An dieser Stelle liegt die PML4T. Ich starte qemu mit "-m 2048", das sollte reichen. Außerdem teste ich ob der Speicher auch wirklich frei ist. Wo ich mir auch keinen Reim drauf machen kann ist, warum ESP so verdammt hoch ist. Bei der aktuellen Version ist ESP = 0xa680895f, also über 2GB. Vllt. hilft die Gegenüberstellung von Log und objdump weiter:
0: v=0d e=0010 i=0 cpl=0 IP=0008:0000000000100ba2 pc=0000000000100ba2 SP=0010:00000000a680895f env->regs[R_EAX]=000000006d3b16ab
EAX=6d3b16ab EBX=00009500 ECX=bffffffd EDX=193cb72b
ESI=9bbf37e6 EDI=0012b000 EBP=00106fc0 ESP=a680895f
EIP=00100ba2 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00127000 00000017
IDT=     00000000 000003ff
CR0=80000011 CR2=00000000 CR3=08000000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=6d3b16ab CCO=INCL   
EFER=0000000000000000
00100691 <StartImage>:
  100691: 55                    push   %ebp
  100692: 89 e5                mov    %esp,%ebp
  100694: 83 ec 28              sub    $0x28,%esp
  100697: b8 10 00 00 00        mov    $0x10,%eax
  10069c: 8e d8                mov    %eax,%ds
  10069e: 8e c0                mov    %eax,%es
  1006a0: 8e e0                mov    %eax,%fs
  1006a2: 8e e8                mov    %eax,%gs
  1006a4: 0f 20 e0              mov    %cr4,%eax
  1006a7: 83 c8 20              or     $0x20,%eax
  1006aa: 0f 22 e0              mov    %eax,%cr4
  1006ad: b9 80 00 00 c0        mov    $0xc0000080,%ecx
  1006b2: 0f 32                rdmsr 
  1006b4: 0d 00 00 00 80        or     $0x80000000,%eax
  1006b9: 0f 30                wrmsr 
  1006bb: b8 00 00 00 08        mov    $0x8000000,%eax
  1006c0: 0f 22 d8              mov    %eax,%cr3
  1006c3: 0f 20 c0              mov    %cr0,%eax
  1006c6: 0d 00 00 00 80        or     $0x80000000,%eax
  1006cb: 0f 22 c0              mov    %eax,%cr0
  1006ce: a1 18 70 12 00        mov    0x127018,%eax
  1006d3: 89 45 f0              mov    %eax,-0x10(%ebp)
  1006d6: c7 45 f4 08 00 00 00 movl   $0x8,-0xc(%ebp)
  1006dd: f4                    hlt   
  1006de: c7 04 24 8f 21 10 00 movl   $0x10218f,(%esp)
  1006e5: e8 a3 00 00 00        call   10078d <print>
  1006ea: 90                    nop
  1006eb: c9                    leave 
  1006ec: c3                    ret   
  1006ed: 66 90                xchg   %ax,%ax
  1006ef: 90                    nop
Wie man aus den Daten entnehmen kann, ist CR3 = 0x8000000. Der Code läuft also mindestens bis Zeile 0x1006c0. Gleichzeitig bis maximal 0x1006dd, denn da sollte Schluss sein. Das letzte mal wird EBP in Zeile 0x100692 geändert, da war ESP also noch normal. Also muss irgendwo dazwischen ESP um einen sehr großen Wert geändert worden sein, nur wo?

Gruß,
Streetrunner

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 18. March 2014, 01:54 »
Also zwei Sachen fallen mir noch auf: Der Errorcode 0010 besagt, dass was mit dem GDT-Deskriptor 0x10 nicht stimmt. Möglicherweise ist was in der GDT nicht korrekt. Allerdings erklärt das nicht das übrige Verhalten (Wert in ESP).

Ich habe deswegen mal in meinen 64-Bit-Code geschaut, und mir ist aufgefallen, dass du in dem MSR Bit 31 (0x80000000) setzt. Korrekt wäre glaube ich Bit 8 (0x100). Möglicherweise erklärt das das komische Verhalten.

Wenn das funktioniert, landest du mit deinem Code übrigens im Compatibility Mode. (Falls dir das nicht bewusst ist.)
Dieser Text wird unter jedem Beitrag angezeigt.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 18. March 2014, 09:58 »
Korrekt wäre glaube ich Bit 8 (0x100). Möglicherweise erklärt das das komische Verhalten.
Da hat Jidder recht. Und mit nicht eingeschaltetem LM-Bit wird natürlich eine ganz andere Paging Tabelle erwartet. Womit man dann keiner Adresse mehr trauen kann.

Nach dem "movl eax, cr0" wird also vermutlich nichts mehr von dem ausgeführt was da in deinem Listing steht, sondern irgend ein teil deiner Pagingtabelle als Code interpretiert.
Was dann auch erklärt warum er nicht bei 0x1006dd anhält sondern bis 0x100ba2 weiter läuft.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

streetrunner

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 18. March 2014, 10:52 »
Zitat
Wenn das funktioniert, landest du mit deinem Code übrigens im Compatibility Mode.
Ja, ich weiß. Von da aus geht es dann weiter in den Long Mode. Der Code dafür ist aber auskommentiert, da er nur unnötig verwirrung stiften würde und auch erst nach der Zeile mit dem Fehler ausgeführt werden würde.

Die Idee mit dem falschen Wert im MSR trifft genau ins Schwarze, das behebt den Fehler komplett. Danke an dieser Stelle. Ich weiß nicht was mich da geritten hat (vllt. Verwechslung von 8tes Bit und 0x80000000??). Werde auch gleich mal auf die Suche gehen was ich denn da fälschlicherweise aktiviert habe.

Gruß,
Streetrunner

 

Einloggen