[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdelibs/solid
From:       Bernhard Loos <nhuh.put () web ! de>
Date:       2007-08-16 22:14:09
Message-ID: 1187302449.624387.5449.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 700972 by bloos:

This adds a method to Solid::Processor to query the instruction sets supported by the \
CPU. The hal back end doesn't use hal but the cpuid instruction. Hal has no support \
for the instruction sets afaik.

Many thanks to jpwhiting and mwoehlke for many tests and review.

 M  +10 -0     solid/CMakeLists.txt  
 M  +1 -0      solid/backends/fakehw/fakecomputer.xml  
 M  +38 -0     solid/backends/fakehw/fakeprocessor.cpp  
 M  +1 -0      solid/backends/fakehw/fakeprocessor.h  
 M  +155 -0    solid/backends/hal/halprocessor.cpp  
 M  +1 -0      solid/backends/hal/halprocessor.h  
 A             solid/config-processor.h.cmake  
 M  +9 -0      solid/ifaces/processor.h  
 M  +6 -0      solid/processor.cpp  
 M  +33 -1     solid/processor.h  
 M  +5 -0      tests/fakehardwaretest.cpp  


--- trunk/KDE/kdelibs/solid/solid/CMakeLists.txt #700971:700972
@@ -8,6 +8,16 @@
 
 configure_file(solid_export.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/solid_export.h)
 
+include (CheckCXXSourceCompiles)
+
+CHECK_CXX_SOURCE_COMPILES(" int main() { __asm__(\"pxor %mm0, %mm0\") ; }" \
HAVE_X86_MMX) +CHECK_CXX_SOURCE_COMPILES(" int main() { __asm__(\"xorps %xmm0, \
%xmm0\"); }" HAVE_X86_SSE) +CHECK_CXX_SOURCE_COMPILES(" int main() { __asm__(\"xorpd \
%xmm0, %xmm0\"); }" HAVE_X86_SSE2) +CHECK_CXX_SOURCE_COMPILES(" int main() { \
__asm__(\"femms\"); }" HAVE_X86_3DNOW) +CHECK_CXX_SOURCE_COMPILES(" int main() { \
__asm__(\"mtspr 256, %0; vand %%v0, %%v0, %%v0\" : : \"r\"(-1) ); }" \
HAVE_PPC_ALTIVEC) +
+configure_file(config-processor.h.cmake \
${CMAKE_CURRENT_BINARY_DIR}/config-processor.h ) +
 ########### next target ###############
 
 set(solid_LIB_SRCS 
--- trunk/KDE/kdelibs/solid/solid/backends/fakehw/fakecomputer.xml #700971:700972
@@ -79,6 +79,7 @@
             <property key="number">0</property>
             <property key="maxSpeed">3200</property>
             <property key="canChangeFrequency">true</property>
+            <property key="extensions">mmx,sse</property>
         </device>
         <device udi="/org/kde/solid/fakehw/acpi_CPU1">
             <property key="name">Solid Processor #1</property>
--- trunk/KDE/kdelibs/solid/solid/backends/fakehw/fakeprocessor.cpp #700971:700972
@@ -19,6 +19,8 @@
 
 #include "fakeprocessor.h"
 
+#include <QtCore/QStringList>
+
 FakeProcessor::FakeProcessor(FakeDevice *device)
  : FakeDeviceInterface(device)
 {
@@ -43,4 +45,40 @@
     return fakeDevice()->property("canChangeFrequency").toBool();
 }
 
+Solid::Processor::Extensions FakeProcessor::extensions() const
+{
+    Solid::Processor::Extensions result;
+
+    QString str = fakeDevice()->property("extensions").toString();
+
+    QStringList extension_list = str.split(",");
+
+    foreach (const QString &extension_str, extension_list) {
+        if (extension_str == "mmx") {
+            result |= Solid::Processor::IntelMMX;
+        }
+        else if (extension_str == "sse") {
+            result |= Solid::Processor::IntelSSE;
+        }
+        else if (extension_str == "sse2") {
+            result |= Solid::Processor::IntelSSE2;
+        }
+        else if (extension_str == "sse3") {
+            result |= Solid::Processor::IntelSSE3;
+        }
+        else if (extension_str == "sse4") {
+            result |= Solid::Processor::IntelSSE4;
+        }
+        else if (extension_str == "3dnow") {
+            result |= Solid::Processor::AMD3DNOW;
+        }
+        else if (extension_str == "altivec") {
+            result |= Solid::Processor::AltiVec;
+        }
+     }
+
+    return result;
+
+}
+
 #include "backends/fakehw/fakeprocessor.moc"
--- trunk/KDE/kdelibs/solid/solid/backends/fakehw/fakeprocessor.h #700971:700972
@@ -35,6 +35,7 @@
     virtual int number() const;
     virtual int maxSpeed() const;
     virtual bool canChangeFrequency() const;
+    virtual Solid::Processor::Extensions extensions() const;
 };
 
 #endif
--- trunk/KDE/kdelibs/solid/solid/backends/hal/halprocessor.cpp #700971:700972
@@ -21,6 +21,11 @@
 
 #include "haldevice.h"
 
+//for cpuFeatures
+#include <csignal>
+#include <csetjmp>
+#include <config-processor.h>
+
 Processor::Processor(HalDevice *device)
     : DeviceInterface(device)
 {
@@ -49,4 +54,154 @@
     return false;
 }
 
+static Solid::Processor::Extensions cpuFeatures();
+
+Solid::Processor::Extensions Processor::extensions() const
+{
+    static Solid::Processor::Extensions cpuextensions = cpuFeatures();
+
+    return cpuextensions;
+}
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+#  define HAVE_GNU_INLINE_ASM
+#endif
+
+typedef void (*kde_sighandler_t) (int);
+
+#ifdef __i386__
+static jmp_buf env;
+
+#ifdef HAVE_X86_SSE
+// Sighandler for the SSE OS support check
+static void sighandler( int )
+{
+    std::longjmp( env, 1 );
+}
+#endif
+#endif
+
+#ifdef __PPC__
+static sigjmp_buf KDE_NO_EXPORT jmpbuf;
+static sig_atomic_t KDE_NO_EXPORT canjump = 0;
+
+static void KDE_NO_EXPORT sigill_handler( int sig )
+{
+    if ( !canjump ) {
+        signal( sig, SIG_DFL );
+        raise( sig );
+    }
+    canjump = 0;
+    siglongjmp( jmpbuf, 1 );
+}
+#endif
+
+static Solid::Processor::Extensions cpuFeatures()
+{
+    volatile unsigned int features = 0;
+
+#if defined( HAVE_GNU_INLINE_ASM )
+#if defined( __i386__ )
+    bool haveCPUID = false;
+    unsigned int result = 0;
+
+    // First check if the CPU supports the CPUID instruction
+    __asm__ __volatile__(
+    // Try to toggle the CPUID bit in the EFLAGS register
+    "pushf                      \n\t"   // Push the EFLAGS register onto the stack
+    "popl   %%ecx               \n\t"   // Pop the value into ECX
+    "movl   %%ecx, %%edx        \n\t"   // Copy ECX to EDX
+    "xorl   $0x00200000, %%ecx  \n\t"   // Toggle bit 21 (CPUID) in ECX
+    "pushl  %%ecx               \n\t"   // Push the modified value onto the stack
+    "popf                       \n\t"   // Pop it back into EFLAGS
+
+    // Check if the CPUID bit was successfully toggled
+    "pushf                      \n\t"   // Push EFLAGS back onto the stack
+    "popl   %%ecx               \n\t"   // Pop the value into ECX
+    "xorl   %%eax, %%eax        \n\t"   // Zero out the EAX register
+    "cmpl   %%ecx, %%edx        \n\t"   // Compare ECX with EDX
+    "je    .Lno_cpuid_support%= \n\t"   // Jump if they're identical
+    "movl      $1, %%eax        \n\t"   // Set EAX to true
+    ".Lno_cpuid_support%=:      \n\t"
+    : "=a"(haveCPUID) : : "%ecx", "%edx" );
+
+    // If we don't have CPUID we won't have the other extensions either
+    if (haveCPUID) {
+        // Execute CPUID with the feature request bit set
+        __asm__ __volatile__(
+            "pushl  %%ebx               \n\t"   // Save EBX
+            "movl      $1, %%eax        \n\t"   // Set EAX to 1 (features request)
+            "cpuid                      \n\t"   // Call CPUID
+            "popl   %%ebx               \n\t"   // Restore EBX
+            : "=d"(result) : : "%eax", "%ecx" );
+
+        features = result & 0x00E00000; //copy the mmx and sse bits to features
+
+        __asm__ __volatile__ (
+             "pushl %%ebx             \n\t"
+             "movl $0x80000000, %%eax \n\t"
+             "cpuid                   \n\t"
+             "cmpl $0x80000000, %%eax \n\t"
+             "jbe .Lno_extended%=     \n\t"
+             "movl $0x80000001, %%eax \n\t"
+             "cpuid                   \n\t"
+             ".Lno_extended%=:        \n\t"
+             "popl   %%ebx            \n\t"   // Restore EBX
+             : "=d"(result) : : "%eax", "%ecx");
+
+        if (result & 0x80000000)
+            features |= 0x80000000;
+
+#ifdef HAVE_X86_SSE
+        // Test bit 25 (SSE support)
+        if (features & 0x00600000) {
+            // OS support test for SSE.
+            // Install our own sighandler for SIGILL.
+            kde_sighandler_t oldhandler = std::signal(SIGILL, sighandler);
+
+            // Try executing an SSE insn to see if we get a SIGILL
+            if (setjmp(env))
+                features &= ~0x00600000; // The OS support test failed
+            else
+                __asm__ __volatile__("xorps %xmm0, %xmm0");
+
+            // Restore the default sighandler
+            std::signal( SIGILL, oldhandler );
+
+            // Note: The OS requirements for SSE2 are the same as for SSE
+            //       so we don't have to do any additional tests for that.
+        }
+#endif // HAVE_X86_SSE
+    }
+#elif defined __PPC__ && defined HAVE_PPC_ALTIVEC
+    signal( SIGILL, sigill_handler );
+    if ( sigsetjmp( jmpbuf, 1 ) ) {
+        signal( SIGILL, SIG_DFL );
+    } else {
+        canjump = 1;
+        __asm__ __volatile__( "mtspr 256, %0\n\t"
+                              "vand %%v0, %%v0, %%v0"
+                              : /* none */
+                              : "r" (-1) );
+        signal( SIGILL, SIG_DFL );
+        features = 0x1;
+    }
+#endif // __i386__
+#endif //HAVE_GNU_INLINE_ASM
+    Solid::Processor::Extensions featureflags;
+
+    if (features & 0x80000000)
+        featureflags |= Solid::Processor::AMD3DNOW;
+    if (features & 0x00800000)
+        featureflags |= Solid::Processor::IntelMMX;
+    if (features & 0x00200000)
+        featureflags |= Solid::Processor::IntelSSE;
+    if (features & 0x00400000)
+        featureflags |= Solid::Processor::IntelSSE2;
+    if (features & 0x1)
+        featureflags |= Solid::Processor::AltiVec;
+
+   return featureflags;
+}
+
 #include "backends/hal/halprocessor.moc"
--- trunk/KDE/kdelibs/solid/solid/backends/hal/halprocessor.h #700971:700972
@@ -37,6 +37,7 @@
     virtual int number() const;
     virtual int maxSpeed() const;
     virtual bool canChangeFrequency() const;
+    virtual Solid::Processor::Extensions extensions() const;
 };
 
 #endif
--- trunk/KDE/kdelibs/solid/solid/ifaces/processor.h #700971:700972
@@ -21,6 +21,7 @@
 #define SOLID_IFACES_PROCESSOR_H
 
 #include <solid/ifaces/deviceinterface.h>
+#include <solid/processor.h>
 
 namespace Solid
 {
@@ -60,6 +61,14 @@
          * @return true if the processor can change CPU frequency, false otherwise
          */
         virtual bool canChangeFrequency() const = 0;
+
+        /**
+         * Queries the instructions set extensions of the CPU.
+         *
+         * @return the extensions supported by the CPU
+         */
+        virtual Solid::Processor::Extensions extensions() const = 0;
+
     };
 }
 }
--- trunk/KDE/kdelibs/solid/solid/processor.cpp #700971:700972
@@ -52,4 +52,10 @@
     return_SOLID_CALL(Ifaces::Processor *, d->backendObject(), false, \
canChangeFrequency());  }
 
+Solid::Processor::Extensions Solid::Processor::extensions() const
+{
+    Q_D(const Processor);
+    return_SOLID_CALL(Ifaces::Processor *, d->backendObject(), Extensions(), \
extensions()); +}
+
 #include "processor.moc"
--- trunk/KDE/kdelibs/solid/solid/processor.h #700971:700972
@@ -35,9 +35,12 @@
     class SOLID_EXPORT Processor : public DeviceInterface
     {
         Q_OBJECT
+        Q_ENUMS(Extension)
+        Q_FLAGS(Extensions)
         Q_PROPERTY(int number READ number)
         Q_PROPERTY(qulonglong maxSpeed READ maxSpeed)
         Q_PROPERTY(bool canChangeFrequency READ canChangeFrequency)
+        Q_PROPERTY(Extensions extensions READ extensions)
         Q_DECLARE_PRIVATE(Processor)
         friend class Device;
 
@@ -54,11 +57,31 @@
 
     public:
         /**
+         * This enum contains the list of architecture extensions you
+         * can query.
+         */
+        enum Extension {
+            NoExtensions = 0x0,
+            IntelMMX = 0x1,
+            IntelSSE = 0x2,
+            IntelSSE2 = 0x4,
+            IntelSSE3 = 0x8,
+            IntelSSE4 = 0x10,
+            AMD3DNOW = 0x20,
+            AltiVec = 0x40
+        };
+
+        /*
+         * The flags for the Extension enum.
+         */
+        Q_DECLARE_FLAGS(Extensions, Extension)
+
+
+        /**
          * Destroys a Processor object.
          */
         virtual ~Processor();
 
-
         /**
          * Get the Solid::DeviceInterface::Type of the Processor device interface.
          *
@@ -90,7 +113,16 @@
          * @return true if the processor can change CPU frequency, false otherwise
          */
         bool canChangeFrequency() const;
+
+        /**
+         * Queries the instructions set extensions of the CPU.
+         *
+         * @return the extensions supported by the CPU
+         */
+        Extensions extensions() const;
     };
 }
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(Solid::Processor::Extensions);
+
 #endif
--- trunk/KDE/kdelibs/solid/tests/fakehardwaretest.cpp #700971:700972
@@ -60,6 +60,11 @@
     QCOMPARE(processor->number(), 0);
     QCOMPARE(processor->canChangeFrequency(), true);
     QCOMPARE((int)processor->maxSpeed(), 3200);
+
+    Solid::Processor::Extensions extensions;
+    extensions |= Solid::Processor::IntelMMX;
+    extensions |= Solid::Processor::IntelSSE;
+    QCOMPARE(processor->extensions(), extensions);
 }
 
 #include "fakehardwaretest.moc"


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic