2010-10-18 6 views
5

Ich verwende den folgenden Code, um das cr0-Bit so einzustellen, dass der Cache deaktiviert wird. Wenn ich kompilieren diesesWie setze ich die Register 0 (cr0) des Steuerregisters 0 in x86-64 unter Verwendung von gcc assembly unter linux

#include <stdio.h> 

int main() 
{ 
     __asm__("pushl %eax\n\t" 
       "mov %cr0,%eax;\n\t" 
       "orl $(1 << 30),%eax;\n\t" 
       "mov %eax,%cr0;\n\t" 
       "wbinvd\n\t" 
       "popl %eax" 
); 

     return 0; 
} 

Ich erhalte Fehlermeldung, dass die Operanden für mov ungültig sind.

Kann mir bitte jemand eine gute gcc x86-64 Anleitung für diese Art von Dingen zeigen? Auch was genau ist falsch mit dem obigen Code?

+0

Funktioniert es, wenn Sie es außerhalb der eingebetteten Baugruppe zusammenbauen (machen Sie eine Montagedatei und montieren Sie sie mit 'gas' oder' nasm')? – Jonathan

+0

Nützliche SO Frage: http://stackoverflow.com/questions/1108485/disable-l2-l1-caches –

+0

Warum möchten Sie dies tun? Was versuchst du zu erreichen? – Hasturkun

Antwort

5

Ok, also habe ich endlich folgendes Kernelmodul geschrieben. Ich bin mir nicht sicher, ob es richtig ist, da ich nicht die drastische Verlangsamung beobachte, die mit der Deaktivierung des Cache einhergehen sollte. Aber das kompiliert und fügt richtig ein.

Alle Hinweise sind hilfreich.

Danke!

#include <linux/init.h> 
#include <linux/module.h> 
MODULE_LICENSE("Dual BSD/GPL"); 
static int hello_init(void) 
{ 
     printk(KERN_ALERT "Hello, world\n"); 
     __asm__("push %rax\n\t" 
       "mov %cr0,%rax;\n\t" 
       "or  $(1 << 30),%rax;\n\t" 
       "mov %rax,%cr0;\n\t" 
       "wbinvd\n\t" 
       "pop %rax" 
); 
     return 0; 
} 
static void hello_exit(void) 
{ 
     printk(KERN_ALERT "Goodbye, cruel world\n"); 
     __asm__("push %rax\n\t" 
       "mov %cr0,%rax;\n\t" 
       "and  $~(1 << 30),%rax;\n\t" 
       "mov %rax,%cr0;\n\t" 
       "wbinvd\n\t" 
       "pop %rax" 
); 
} 
module_init(hello_init); 
module_exit(hello_exit); 
+0

Ok. Ich habe gerade bestätigt, dass das funktioniert. Sie müssen auch die MTRR-Register durch $ echo "disable = 00"> | deaktivieren/proc/mtrr – sanatana

1

Try this: "mov %% cr0, %% EAX \ n"

Ein einfaches% als Benutzer Argument interpretiert wird (glaube ich).

sollten Sie lesen this

+0

__asm__ ("mov \t %% cr0, %% rax; "); Das sagt Error: schlechter Registername '%% cr0 ' – sanatana

+0

von der Verbindung: Dem Registernamen sind zwei Prozent vorangestellt. Dies hilft GCC bei der Unterscheidung zwischen Operanden und Registern. Operanden haben einen einzelnen% als Präfix. – sanatana

+0

Sind Sie sicher, dass es immer noch cr0 der Name des Registers in 64bit ist? Der Code, den ich eingefügt habe, stammt von einem Miniknoten, den ich geschrieben habe. – Thomas

0

Der Code für mich auf 32-Bit-x86-Bit nicht auf x86-64 OK kompiliert - das ist mit gcc 4.2.1 auf Mac OS X:

$ gcc -Wall -m32 cr0.c -o cr0 
$ 

Nein Fehler oder Warnungen.

$ gcc -Wall -m64 cr0.c -o cr0 
/var/folders/.../cce0FYAB.s:9:suffix or operands invalid for `push' 
/var/folders/.../cce0FYAB.s:10:suffix or operands invalid for `mov' 
/var/folders/.../cce0FYAB.s:12:suffix or operands invalid for `mov' 
/var/folders/.../cce0FYAB.s:14:suffix or operands invalid for `pop' 
$ 

Also ich denke, es gibt tiefere Probleme als nur die mov %eax,%cr0 Anweisung hier mit asm auf x86-64.

am x86-64 Blick ISA es scheint, dass Sie wahrscheinlich für x86-64 so etwas wie dies benötigen:

#include <stdio.h> 

int main() 
{ 
     __asm__("pushq %rax\n\t" 
       "movq %cr0,%rax\n\t" 
       "orl $(1 << 30),%eax\n\t" 
       "movq %rax,%cr0\n\t" 
       "wbinvd\n\t" 
       "popq %rax" 
); 

     return 0; 
} 

Ich weiß nicht, ob dies funktioniert, aber es zumindest kompiliert/OK assembliert:

$ gcc -Wall -m64 cr0.c -o cr0 
$ 
+0

Ja, das Problem liegt beim Kompilieren auf x86-64. Ich habe% rax anstelle von% eax verwendet. Es kompiliert feine aber seg Fehler, wenn ich es ausführe. – sanatana

2

Sie können solche Operationen nicht aus Benutzercode ausführen und sogar als root ausführen ist Benutzercode.

Sie müssen dies zu einem Treibermodul machen und es mit insmod laden.

+0

Ok, ich werde es versuchen, indem ich es als Modul schreibe! Danke Zan. – sanatana

3

Ich glaube, Sie nicht die „drastische Verlangsamung“ sehen, weil Sie mehrere Kerne haben, nicht wahr? Ich habe einige Experimente gemacht und es scheint mir, dass die Einstellung der CD in% cr0 nur den Prozessor betrifft, auf dem das Modul läuft.

Stellen Sie sicher, dass Sie den Code in allen Cores ausführen, für die Sie das Caching deaktivieren möchten. Sie könnten zum Beispiel eine/proc/cachedisable-Datei erstellen, in der ein Lesevorgang Ihren Code auslöst. Verwenden Sie dann

taskset -c cpu_number cat /proc/cachedisable 

, um die Caches auf CPU cpu_number zu deaktivieren. Mach dasselbe mit/proc/cacheenable und du hast alles was du brauchst. Dies funktioniert für mich und es besteht keine Notwendigkeit, die MTRRs zu ändern, was ziemlich kompliziert ist.Wenn Sie mehrere Prozessoren haben, können Sie das Caching für nur eine davon deaktivieren und Ihre Experimente mit dieser CPU durchführen. Dann bleibt der Rest des Systems nutzbar.