Autor Thema: Schnellste Möglichkeit des Syscalls  (Gelesen 15368 mal)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #20 am: 11. July 2011, 22:33 »
Naja, TSS-Descriptor benötigt man eh in der GDT aber die Gates kann man IMHO schon in die LDT packen, könnte also eine Erleichterung sein. Genau beschäftigt hab ich mich damit aber auch noch nicht, diese ganze Angelegenheit mit den Gates ist recht komplex und in meiner CPU will ich darauf konsequent verzichten (hab ja eh keine HW-Unterstützung für Tasks vorgesehen aber dafür einen richtig schnellen syscall-Befehl).
Reality is that which, when you stop believing in it, doesn't go away.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #21 am: 12. July 2011, 12:42 »
Das blöde ist halt, das sysenter/syscall nicht das selbe ist, oder lässt sich da irgend eine Uniformierung einbauen.
Für ein Protected-Mode-OS nimmst du einfach immer sysenter und für ein Long-Mode-OS immer syscall.
SYSENTER können Intel-CPUs erst ab dem Pentium II, seit wann SYSCALL existiert, weiß ich nicht. Außerdem gibt es dann ja noch so Dinge wie CPUs von VIA oder Transmeta... bei denen wäre ich mir nicht sicher, ob die das auch können.

Ah danke jetzt kapier ich das. Was mich verwirrt ist, das man in Linux Assemblerprogrammen Syscalls über Interrupts handelt. Besitzt das System dann zwei Syscallmethoden?
Ja. Wenn das Betriebssystem eine spezielle Page mit Syscall-Code hat, dann enthält der Code dort auf alten/unüblichen Prozessoren auch nur einen Interruptaufruf. Den Interrupt-Handler kann man aber auch aktiv lassen, wenn dort anderer Code ist. :-) Der offizielle Weg ist ein FAR CALL an eine bestimmte Speicheradresse (nämlich die reservierte Page).

Gruß,
Svenska

Sannaj

  • Beiträge: 103
    • Profil anzeigen
Gespeichert
« Antwort #22 am: 12. July 2011, 15:10 »
Ok dann frag ich mal was anderes. Ist sysenter immer noch schnelle, wenn man dazu eine Funktion von der Syscall-Page aufrufen muss, als wenn man über eine Call-Gate arbeitet (dann ohne syscall-Page)

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #23 am: 12. July 2011, 15:56 »
Die Funktion auf der Syscall-Page ist ja nicht groß, sollte also keinen wesentlichen Unterschied zum Szenario ohne Indirektion machen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #24 am: 12. July 2011, 17:00 »
Hallo,

um den Code in der Syscall-Page auszuführen, brauchst du einen far jump oder far call. Der ist verglichen mit dem Sysenter selbst extrem schnell. Ein Call Gate ist wesentlich langsamer (wäre es schnell, gäbe es weder Sysenter noch Syscall, weil die dann unnötig wären).

Die ganzen Verrenkungen sind schon nicht ohne Grund so, wie sie sind. ;-)

Gruß,
Svenska

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #25 am: 12. July 2011, 17:02 »
Sicher, dass du nicht einen near call (absolute indirect) meinst?
Dieser Text wird unter jedem Beitrag angezeigt.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #26 am: 12. July 2011, 17:10 »
Hallo,


Anspringen sollte man diese Page IMHO mit einem NEAR CALL, da das User-Programm ja trotzdem nur 2 Segmente in der GDT belegt gibt es auch kein alternatives Code-Segment auf das sich ein FAR CALL beziehen könnte. Wahrscheinlich muss der CALL beim Laden des Executables reloziert werden ansonsten muss spätestens der Linker statisch wissen wo im virtuellen Adressraum diese Page liegt und genau diese Freiheit würde ich dem Kernel überlassen.

Diese spezielle Page dürfte fast keine Performance kosten. Zum einen sollte sie im Bereich des Kernel-Space liegen (nur eben auch mit Ring 3 Lesbar/Ausführbar) und als global gekennzeichnet werden damit sie bei einem TLB-Flush nicht aus dem TLB fliegt (CPUs die sysenter/syscall können können auch das). Zum anderen sollte der kurze Code (sind ja nur 2 Assemblerbefehle) direkt am Anfang stehen damit er auch immer gut ausgerichtet in eine Cacheline passt. Dieser kurze Code belegt auch nur eine einzige Cacheline und bei der häufigen Verwendung dieses Codes sollte diese Cacheline auch mindestens im L2-Cache permanent drin bleiben (da der L2-Cache üblicherweise mit physischen Adressen getaggt und indiziert ist ist diese Cachline auch für alle Prozesse nutzbar).

Den durchschnittlichen Performanceverlust durch diese Indirektion würde ich auf etwa 1 bis 4 Takte pro Benutzung schätzen.
Da die Hersteller von x86-CPUs die Segmentierung schon vor sehr vielen Jahren beerdigt haben und daher Mechanismen wie Call-Gates schon sehr lange nicht mehr optimiert wurden schätze ich den Zeitbedarf eines Call-Gates (mit allen seinen Sicherheitschecks) auf mindestens 20 Takte ein.
(alle Angaben wie immer ohne Gewähr ;) )


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #27 am: 12. July 2011, 17:27 »
Au weia. Fasse mich kurz. Telegramm teuer. Da der call indirect ist, reicht es die Adresse zur Laufzeit (Initialisierung) zu wissen.
« Letzte Änderung: 12. July 2011, 17:29 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #28 am: 12. July 2011, 17:36 »
Hallo,


Da der call indirect ist
Du meinst einen Call der die Zieladresse aus einer extra Variable holt? Davon würde ich abraten da das eine weitere Indirektion ist die das ganze zusätzlich verteuert. Ein absoluter Call ist IMHO die beste Lösung und da der Executable-Loade eh Relozieren können muss (zumindest wenn man mehr als nur simpelste Executables haben will) macht das auch nichts aus.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #29 am: 12. July 2011, 22:46 »
Sicher, dass du nicht einen near call (absolute indirect) meinst?
Meinetwegen auch einen near jump, aber die Adresse ist bekannt und konstant.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #30 am: 13. July 2011, 13:00 »
Hallo,


aber die Adresse ist bekannt und konstant.
Ja, zur Laufzeit auf jeden Fall.
Die Frage ist nur ab wann, also schon zur Compilezeit (dann könnte diese Adresse bereits vom Linker fest im Call-Befehl eingebaut werden) oder erst zur Ladezeit (dann muss der Executable-Loader passend Relozieren). Ich persönlich würde mich für die zweite Variante entscheiden (um dem Kernel etwas mehr Flexibilität zu geben) aber für die Performance macht das absolut keinen Unterschied.

Ein Call oder Jump dessen Zieladresse bereits der Decoder ermitteln kann (das trifft auch auf relative Sprünge zu da der Decoder ja die Adresse das Sprungs selber kennt und demzufolge auch das relative Ziel errechnen kann) kostet fast gar nichts, im Optimum kostet der wirklich 0 Takte. Call-Befehle die ihre Zieladresse erst während der Ausführung ermitteln müssen sind dagegen auf jeden Fall ziemlich teuer. Intel und AMD geben sich da zwar viel Mühe um das zu bessern, diese Calls werden auch für virtuelle Methoden benötigt, aber ganz kostenlos sind diese indirekten Sprünge auf jeden Fall nicht.

Das besondere an der hier diskutierten Situation ist natürlich das der angesprungene Code in einer speziellen extra Page liegt so das eben doch ab und an mal ein TLB-Miss oder auch ein normaler Code-Cache-Miss auftreten kann aber das dürfte wohl ziemlich selten sein.


Grüße
Erik
« Letzte Änderung: 13. July 2011, 13:02 von erik.vikinger »
Reality is that which, when you stop believing in it, doesn't go away.

 

Einloggen