Hardware/Opcode.cs
changeset 238 bddc6e01840a
parent 236 763675f19ff4
child 239 91800d0f54de
     1.1 --- a/Hardware/Opcode.cs	Mon Nov 01 20:44:21 2010 +0000
     1.2 +++ b/Hardware/Opcode.cs	Wed Nov 03 22:07:46 2010 +0000
     1.3 @@ -37,17 +37,17 @@
     1.4  
     1.5  using System;
     1.6  using System.Runtime.InteropServices;
     1.7 +using Mono.Unix.Native;
     1.8  
     1.9  namespace OpenHardwareMonitor.Hardware {
    1.10    internal static class Opcode {
    1.11 +    
    1.12      private static IntPtr codeBuffer;
    1.13 +    private static ulong size;
    1.14  
    1.15 -    public static void Open() {
    1.16 -      // No implementation for Unix systems
    1.17 +    public static void Open() {  
    1.18        int p = (int)Environment.OSVersion.Platform;
    1.19 -      if ((p == 4) || (p == 128))
    1.20 -        return;  
    1.21 -
    1.22 +            
    1.23        byte[] rdtscCode;
    1.24        byte[] cpuidCode;
    1.25        if (IntPtr.Size == 4) {
    1.26 @@ -55,13 +55,25 @@
    1.27          cpuidCode = CPUID_32;
    1.28        } else {
    1.29          rdtscCode = RDTSC_64;
    1.30 -        cpuidCode = CPUID_64;
    1.31 +        
    1.32 +        if ((p == 4) || (p == 128)) { // Unix
    1.33 +          cpuidCode = CPUID_64_LINUX;
    1.34 +        } else { // Windows
    1.35 +          cpuidCode = CPUID_64_WINDOWS;
    1.36 +        }
    1.37        }
    1.38 -
    1.39 -      codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero,
    1.40 -        (UIntPtr)(rdtscCode.Length + cpuidCode.Length),
    1.41 -      AllocationType.COMMIT | AllocationType.RESERVE, 
    1.42 -      MemoryProtection.EXECUTE_READWRITE);
    1.43 +      
    1.44 +      size = (ulong)(rdtscCode.Length + cpuidCode.Length);
    1.45 +      
    1.46 +      if ((p == 4) || (p == 128)) { // Unix
    1.47 +        codeBuffer = Syscall.mmap(IntPtr.Zero, size, 
    1.48 +          MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC, 
    1.49 +          MmapFlags.MAP_ANONYMOUS | MmapFlags.MAP_PRIVATE, -1, 0);
    1.50 +      } else { // Windows
    1.51 +        codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero,
    1.52 +          (UIntPtr)size, AllocationType.COMMIT | AllocationType.RESERVE, 
    1.53 +          MemoryProtection.EXECUTE_READWRITE);
    1.54 +      }
    1.55  
    1.56        Marshal.Copy(rdtscCode, 0, codeBuffer, rdtscCode.Length);
    1.57  
    1.58 @@ -72,15 +84,20 @@
    1.59        Marshal.Copy(cpuidCode, 0, cpuidAddress, cpuidCode.Length);
    1.60  
    1.61        Cpuid = Marshal.GetDelegateForFunctionPointer(
    1.62 -        cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;
    1.63 +        cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;         
    1.64      }
    1.65  
    1.66      public static void Close() {
    1.67        Rdtsc = null;
    1.68        Cpuid = null;
    1.69 -
    1.70 -      NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero, 
    1.71 -        FreeType.RELEASE);
    1.72 +      
    1.73 +      int p = (int)Environment.OSVersion.Platform;
    1.74 +      if ((p == 4) || (p == 128)) { // Unix
    1.75 +        Syscall.munmap(codeBuffer, size);
    1.76 +      } else { // Windows
    1.77 +        NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero, 
    1.78 +          FreeType.RELEASE);        
    1.79 +      }
    1.80      }
    1.81  
    1.82      [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    1.83 @@ -99,8 +116,8 @@
    1.84  
    1.85      private static readonly byte[] RDTSC_64 = new byte[] {
    1.86        0x0F, 0x31,                     // rdtsc  
    1.87 -      0x48, 0xC1, 0xE2, 0x20,         // shl rdx,20h  
    1.88 -      0x48, 0x0B, 0xC2,               // or rax,rdx  
    1.89 +      0x48, 0xC1, 0xE2, 0x20,         // shl rdx, 20h  
    1.90 +      0x48, 0x0B, 0xC2,               // or rax, rdx  
    1.91        0xC3                            // ret  
    1.92      };
    1.93      
    1.94 @@ -125,71 +142,83 @@
    1.95  
    1.96      private static readonly byte[] CPUID_32 = new byte[] {
    1.97        0x55,                           // push ebp  
    1.98 -      0x8B, 0xEC,                      // mov ebp,esp  
    1.99 -      0x83, 0xEC, 0x10,               // sub esp,10h  
   1.100 -      0x8B, 0x45, 0x08,               // mov eax,dword ptr [ebp+8]  
   1.101 -      0x8B, 0x4D, 0x0C,               // mov ecx,dword ptr [ebp+0Ch]  
   1.102 +      0x8B, 0xEC,                     // mov ebp, esp  
   1.103 +      0x83, 0xEC, 0x10,               // sub esp, 10h  
   1.104 +      0x8B, 0x45, 0x08,               // mov eax, dword ptr [ebp+8]  
   1.105 +      0x8B, 0x4D, 0x0C,               // mov ecx, dword ptr [ebp+0Ch]  
   1.106        0x53,                           // push ebx  
   1.107        0x0F, 0xA2,                     // cpuid  
   1.108        0x56,                           // push esi  
   1.109 -      0x8D, 0x75, 0xF0,               // lea esi,[info]  
   1.110 -      0x89, 0x06,                      // mov dword ptr [esi],eax  
   1.111 -      0x8B, 0x45, 0x10,               // mov eax,dword ptr [eax]  
   1.112 -      0x89, 0x5E, 0x04,               // mov dword ptr [esi+4],ebx  
   1.113 -      0x89, 0x4E, 0x08,               // mov dword ptr [esi+8],ecx  
   1.114 -      0x89, 0x56, 0x0C,               // mov dword ptr [esi+0Ch],edx  
   1.115 -      0x8B, 0x4D, 0xF0,               // mov ecx,dword ptr [info]  
   1.116 -      0x89, 0x08,                      // mov dword ptr [eax],ecx  
   1.117 -      0x8B, 0x45, 0x14,               // mov eax,dword ptr [ebx]  
   1.118 -      0x8B, 0x4D, 0xF4,               // mov ecx,dword ptr [ebp-0Ch]  
   1.119 -      0x89, 0x08,                      // mov dword ptr [eax],ecx  
   1.120 -      0x8B, 0x45, 0x18,               // mov eax,dword ptr [ecx]  
   1.121 -      0x8B, 0x4D, 0xF8,               // mov ecx,dword ptr [ebp-8]  
   1.122 -      0x89, 0x08,                      // mov dword ptr [eax],ecx  
   1.123 -      0x8B, 0x45, 0x1C,               // mov eax,dword ptr [edx]  
   1.124 -      0x8B, 0x4D, 0xFC,               // mov ecx,dword ptr [ebp-4]  
   1.125 +      0x8D, 0x75, 0xF0,               // lea esi, [info]  
   1.126 +      0x89, 0x06,                     // mov dword ptr [esi],eax  
   1.127 +      0x8B, 0x45, 0x10,               // mov eax, dword ptr [eax]  
   1.128 +      0x89, 0x5E, 0x04,               // mov dword ptr [esi+4], ebx  
   1.129 +      0x89, 0x4E, 0x08,               // mov dword ptr [esi+8], ecx  
   1.130 +      0x89, 0x56, 0x0C,               // mov dword ptr [esi+0Ch], edx  
   1.131 +      0x8B, 0x4D, 0xF0,               // mov ecx, dword ptr [info]  
   1.132 +      0x89, 0x08,                     // mov dword ptr [eax], ecx  
   1.133 +      0x8B, 0x45, 0x14,               // mov eax, dword ptr [ebx]  
   1.134 +      0x8B, 0x4D, 0xF4,               // mov ecx, dword ptr [ebp-0Ch]  
   1.135 +      0x89, 0x08,                     // mov dword ptr [eax], ecx  
   1.136 +      0x8B, 0x45, 0x18,               // mov eax, dword ptr [ecx]  
   1.137 +      0x8B, 0x4D, 0xF8,               // mov ecx, dword ptr [ebp-8]  
   1.138 +      0x89, 0x08,                     // mov dword ptr [eax], ecx  
   1.139 +      0x8B, 0x45, 0x1C,               // mov eax, dword ptr [edx]  
   1.140 +      0x8B, 0x4D, 0xFC,               // mov ecx, dword ptr [ebp-4]  
   1.141        0x5E,                           // pop esi  
   1.142 -      0x89, 0x08,                     // mov dword ptr [eax],ecx  
   1.143 +      0x89, 0x08,                     // mov dword ptr [eax], ecx  
   1.144        0x5B,                           // pop ebx  
   1.145        0xC9,                           // leave  
   1.146        0xC2, 0x18, 0x00                // ret 18h  
   1.147      };
   1.148               
   1.149 -    private static readonly byte[] CPUID_64 = new byte[] {
   1.150 -      0x48, 0x89, 0x5C, 0x24, 0x08,   // mov qword ptr [rsp+8],rbx  
   1.151 -      0x8B, 0xC1,                     // mov eax,ecx  
   1.152 -      0x8B, 0xCA,                     // mov ecx,edx  
   1.153 -      0x0F, 0xA2,                     // cpuid  
   1.154 -      0x41, 0x89, 0x00,               // mov dword ptr [r8],eax  
   1.155 -      0x48, 0x8B, 0x44, 0x24, 0x28,   // mov rax,qword ptr [ecx]  
   1.156 -      0x41, 0x89, 0x19,               // mov dword ptr [r9],ebx  
   1.157 -      0x48, 0x8B, 0x5C, 0x24, 0x08,   // mov rbx,qword ptr [rsp+8]  
   1.158 -      0x89, 0x08,                     // mov dword ptr [rax],ecx  
   1.159 -      0x48, 0x8B, 0x44, 0x24, 0x30,   // mov rax,qword ptr [rsp+30h]  
   1.160 -      0x89, 0x10,                     // mov dword ptr [rax],edx  
   1.161 +    private static readonly byte[] CPUID_64_WINDOWS = new byte[] {
   1.162 +      0x48, 0x89, 0x5C, 0x24, 0x08,   // mov qword ptr [rsp+8], rbx  
   1.163 +      0x8B, 0xC1,                     // mov eax, ecx  
   1.164 +      0x8B, 0xCA,                     // mov ecx, edx        
   1.165 +      0x0F, 0xA2,                     // cpuid        
   1.166 +      0x41, 0x89, 0x00,               // mov dword ptr [r8], eax        
   1.167 +      0x48, 0x8B, 0x44, 0x24, 0x28,   // mov rax, qword ptr [rsp+28h]       
   1.168 +      0x41, 0x89, 0x19,               // mov dword ptr [r9], ebx        
   1.169 +      0x48, 0x8B, 0x5C, 0x24, 0x08,   // mov rbx, qword ptr [rsp+8]      
   1.170 +      0x89, 0x08,                     // mov dword ptr [rax], ecx        
   1.171 +      0x48, 0x8B, 0x44, 0x24, 0x30,   // mov rax, qword ptr [rsp+30h]  
   1.172 +      0x89, 0x10,                     // mov dword ptr [rax], edx  
   1.173        0xC3                            // ret  
   1.174      };
   1.175 +    
   1.176 +    private static readonly byte[] CPUID_64_LINUX = new byte[] {
   1.177 +      0x49, 0x89, 0xD2,               // mov r10, rdx
   1.178 +      0x49, 0x89, 0xCB,               // mov r11, rcx
   1.179 +      0x53,                           // push rbx
   1.180 +      0x89, 0xF8,                     // mov eax, edi
   1.181 +      0x89, 0xF1,                     // mov ecx, esi
   1.182 +      0x0F, 0xA2,                     // cpuid
   1.183 +      0x41, 0x89, 0x02,               // mov dword ptr [r10], eax
   1.184 +      0x41, 0x89, 0x1B,               // mov dword ptr [r11], ebx
   1.185 +      0x41, 0x89, 0x08,               // mov dword ptr [r8], ecx
   1.186 +      0x41, 0x89, 0x11,               // mov dword ptr [r9], edx
   1.187 +      0x5B,                           // pop rbx
   1.188 +      0xC3,                           // ret
   1.189 +    };
   1.190  
   1.191      public static bool CpuidTx(uint index, uint ecxValue, 
   1.192        out uint eax, out uint ebx, out uint ecx, out uint edx, 
   1.193 -      UIntPtr threadAffinityMask) {
   1.194 +      ulong threadAffinityMask) {
   1.195 +      
   1.196 +      ulong mask = ThreadAffinity.Set(threadAffinityMask);
   1.197  
   1.198 -      IntPtr thread = NativeMethods.GetCurrentThread();
   1.199 -      UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread, 
   1.200 -        threadAffinityMask);
   1.201 -
   1.202 -      if (mask == UIntPtr.Zero) {
   1.203 +      if (mask == 0) {
   1.204          eax = ebx = ecx = edx = 0;
   1.205          return false;
   1.206 -      }
   1.207 +      } 
   1.208  
   1.209        Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx);
   1.210  
   1.211 -      NativeMethods.SetThreadAffinityMask(thread, mask);
   1.212 -      
   1.213 +      ThreadAffinity.Set(mask);      
   1.214        return true;
   1.215      }
   1.216 -
   1.217 +    
   1.218      [Flags()]
   1.219      public enum AllocationType : uint {
   1.220        COMMIT = 0x1000,
   1.221 @@ -222,7 +251,7 @@
   1.222        RELEASE = 0x8000
   1.223      }
   1.224  
   1.225 -    private static class NativeMethods {
   1.226 +    private static class NativeMethods {      
   1.227        private const string KERNEL = "kernel32.dll";
   1.228  
   1.229        [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   1.230 @@ -231,14 +260,7 @@
   1.231  
   1.232        [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   1.233        public static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize,
   1.234 -        FreeType dwFreeType);
   1.235 -
   1.236 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   1.237 -      public static extern UIntPtr
   1.238 -        SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
   1.239 -
   1.240 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   1.241 -      public static extern IntPtr GetCurrentThread();
   1.242 +        FreeType dwFreeType);                 
   1.243      }
   1.244    }
   1.245  }