13 Stimmen

SSE-Registerrückgabe bei deaktivierter SSE

Ich befinde mich in der folgenden Situation:

  • Ich schreibe Code für einen Kernel, der keine SSE-Befehle zulässt
  • Ich muss Gleitkomma-Arithmetik betreiben
  • Ich kompiliere für eine x86_64-Plattform

Hier ist ein Codebeispiel, das das Problem veranschaulicht:

int
main(int argc, char** argv)
{
    double d = 0.0, dbase;
    uint64_t base_value = 300;

    d = (2200.0 - 1000.0)/(1000.0);
    dbase = d * base_value;
    printf("d = %f, dbase = %f\n", d, dbase);
    base_value = dbase;
    printf("base_value = %llu\n", (long long unsigned)base_value);
    return 0;
}

Und hier ist die entsprechende Zeile aus dem Makefile:

CFLAGS +=   -mcmodel=kernel -mno-red-zone -mfpmath=387 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow \
            -msoft-float -fno-asynchronous-unwind-tables -fno-omit-frame-pointer

Wenn ich einen Build ausführe, erhalte ich diesen Fehler:

SSE register return with SSE disabled

(Der Fehler zeigt auf die Zeile, die d und base_value multipliziert)

Haben Sie eine Idee, was ich tun kann, um das Problem zu beheben? Entfernen -mno-sse ist keine Option, aber es scheint, wie der Compiler sollte in der Lage sein, nicht-se Code zu generieren, um die Multiplikation zu tun.

Danke Nathan

1 Stimmen

Es ist möglich, dass gcc mit diesem Fall nicht umgehen kann, weil er davon ausgeht, dass alle x86-64-Prozessoren SSE haben.

1 Stimmen

Bedeutet das, dass niemand jemals etwas innerhalb des FreeBSD-Kernels auf 64-Bit-Builds multipliziert?

0 Stimmen

Jeder Kernel, an dem ich gearbeitet habe, neigt dazu, Fließkommazahlen so weit wie möglich zu vermeiden.

10voto

Stephen Canon Punkte 100340

Es hört sich so an, als ob der Compiler einen Aufruf an eine Bibliotheksroutine ausgibt, um die Fließkommamultiplikation für Sie durchzuführen (vermutlich ohne SSE zu verwenden), aber versucht, eine ABI für den Aufruf zu verwenden, die den Rückgabewert in SSE übergeben hat. Offensichtlich funktioniert das nicht.

Wenn es überhaupt möglich ist, Fließkommazahlen in Ihrem Kernel zu verwenden, sollte es eine spezielle Laufzeitbibliothek für Soft-Float-Operationen geben, die nicht die üblichen (Userland-)Argumentübergabe- und Rückgabekonventionen verwendet. Soweit ich weiß, gibt es im BSD-Kernel jedoch keine Unterstützung für Fließkommazahlen. Das war jedenfalls vor ein paar Jahren der Fall.

Sie sollten wahrscheinlich einfach die BSD-Kernel-Entwickler-E-Mail-Liste fragen, ob es möglich ist, Fließkomma zu verwenden oder nicht; ich vermute, dass Sie dort schneller eine definitive Antwort bekommen als bei SO.

0 Stimmen

Ich beschloss, stattdessen Festkomma-Arithmetik zu verwenden (der fragliche Kernel basiert auf dem FreeBSD-Kernel, ist aber erheblich verändert, so dass ich nicht sicher war, dass eine der offiziellen Mailinglisten eine bessere Antwort als "Tu das nicht" geben würde.

0 Stimmen

Ah. Es tut mir leid, dass es dafür keine glücklichere Antwort gibt.

0voto

Radle Punkte 1

Wie ich weiß, verwendet der Kernel SSE nicht oft, aber Sie können SSE nur für die Modul- oder Anwendungserstellung einschalten, wenn die Architektur dies unterstützt.

Bei mir habe ich die CPU mit überprüft: cat /proc/cpuinfo | grep --color -i sse ob ich irgendwelche sse-bezogenen Flaggen oder Tränke (falls vorhanden) sehen kann. Wenn Sie irgendwelche Ergebnisse zurückbekommen haben, dann ist das gut, jetzt können Sie sehen, welche sse-Versionen wie verfügbar sind: sse sse2 sse3 sse4 .

Nach der Inspektion können Sie die folgenden Flags in das Makefile oder den Builder einfügen:

CFLAGS += -msoft-float -msse -msse2 -msse3 -msse4

oder wie:

EXTRA_CFLAGS := -msoft-float -msse -msse2 -msse3 -msse4

Ich stoße auf dieses Problem, wenn ich einen Intel Atom Prozessor der neueren Generation mit Kervel Version 5.5.7 unter Debian verwende.

1 Stimmen

Sie können nicht sicher dies für Kernel-Code tun, es sei denn, alle Funktionen in dieser Datei werden nur von anderen Funktionen aufgerufen, die kernel_fpu_begin() vor dem Aufruf, und verwendet kernel_fpu_end() Irgendwann danach. Siehe Warum kann ich innerhalb eines Linux-Kernelmoduls Gleitkommaoperationen durchführen? . Normalerweise baut Linux mit -mgeneral-regs-only (auf dem neuen GCC), so dass FP-Mathematik oder SIMD nur möglich ist mit __attribute__((target(...))) oder Inline-Asm.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X