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 }