[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