Now fetching some of our Sound Graph DLL function pointers.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2010 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Runtime.InteropServices;
13 using System.Reflection;
15 namespace OpenHardwareMonitor.Hardware {
16 internal static class Opcode {
18 private static IntPtr codeBuffer;
19 private static ulong size;
21 public static void Open() {
22 int p = (int)Environment.OSVersion.Platform;
26 if (IntPtr.Size == 4) {
32 if ((p == 4) || (p == 128)) { // Unix
33 cpuidCode = CPUID_64_LINUX;
35 cpuidCode = CPUID_64_WINDOWS;
39 size = (ulong)(rdtscCode.Length + cpuidCode.Length);
41 if ((p == 4) || (p == 128)) { // Unix
43 Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " +
44 "PublicKeyToken=0738eb9f132ed756");
46 Type syscall = assembly.GetType("Mono.Unix.Native.Syscall");
47 MethodInfo mmap = syscall.GetMethod("mmap");
49 Type mmapProts = assembly.GetType("Mono.Unix.Native.MmapProts");
50 object mmapProtsParam = Enum.ToObject(mmapProts,
51 (int)mmapProts.GetField("PROT_READ").GetValue(null) |
52 (int)mmapProts.GetField("PROT_WRITE").GetValue(null) |
53 (int)mmapProts.GetField("PROT_EXEC").GetValue(null));
55 Type mmapFlags = assembly.GetType("Mono.Unix.Native.MmapFlags");
56 object mmapFlagsParam = Enum.ToObject(mmapFlags,
57 (int)mmapFlags.GetField("MAP_ANONYMOUS").GetValue(null) |
58 (int)mmapFlags.GetField("MAP_PRIVATE").GetValue(null));
60 codeBuffer = (IntPtr)mmap.Invoke(null, new object[] { IntPtr.Zero,
61 size, mmapProtsParam, mmapFlagsParam, -1, 0 });
63 codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero,
64 (UIntPtr)size, AllocationType.COMMIT | AllocationType.RESERVE,
65 MemoryProtection.EXECUTE_READWRITE);
68 Marshal.Copy(rdtscCode, 0, codeBuffer, rdtscCode.Length);
70 Rdtsc = Marshal.GetDelegateForFunctionPointer(
71 codeBuffer, typeof(RdtscDelegate)) as RdtscDelegate;
73 IntPtr cpuidAddress = (IntPtr)((long)codeBuffer + rdtscCode.Length);
74 Marshal.Copy(cpuidCode, 0, cpuidAddress, cpuidCode.Length);
76 Cpuid = Marshal.GetDelegateForFunctionPointer(
77 cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;
80 public static void Close() {
84 int p = (int)Environment.OSVersion.Platform;
85 if ((p == 4) || (p == 128)) { // Unix
87 Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " +
88 "PublicKeyToken=0738eb9f132ed756");
90 Type syscall = assembly.GetType("Mono.Unix.Native.Syscall");
91 MethodInfo munmap = syscall.GetMethod("munmap");
92 munmap.Invoke(null, new object[] { codeBuffer, size });
95 NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero,
100 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
101 public delegate ulong RdtscDelegate();
103 public static RdtscDelegate Rdtsc;
105 // unsigned __int64 __stdcall rdtsc() {
109 private static readonly byte[] RDTSC_32 = new byte[] {
114 private static readonly byte[] RDTSC_64 = new byte[] {
116 0x48, 0xC1, 0xE2, 0x20, // shl rdx, 20h
117 0x48, 0x0B, 0xC2, // or rax, rdx
121 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
122 public delegate bool CpuidDelegate(uint index, uint ecxValue,
123 out uint eax, out uint ebx, out uint ecx, out uint edx);
125 public static CpuidDelegate Cpuid;
128 // void __stdcall cpuidex(unsigned int index, unsigned int ecxValue,
129 // unsigned int* eax, unsigned int* ebx, unsigned int* ecx,
130 // unsigned int* edx)
133 // __cpuidex(info, index, ecxValue);
140 private static readonly byte[] CPUID_32 = new byte[] {
142 0x8B, 0xEC, // mov ebp, esp
143 0x83, 0xEC, 0x10, // sub esp, 10h
144 0x8B, 0x45, 0x08, // mov eax, dword ptr [ebp+8]
145 0x8B, 0x4D, 0x0C, // mov ecx, dword ptr [ebp+0Ch]
149 0x8D, 0x75, 0xF0, // lea esi, [info]
150 0x89, 0x06, // mov dword ptr [esi],eax
151 0x8B, 0x45, 0x10, // mov eax, dword ptr [eax]
152 0x89, 0x5E, 0x04, // mov dword ptr [esi+4], ebx
153 0x89, 0x4E, 0x08, // mov dword ptr [esi+8], ecx
154 0x89, 0x56, 0x0C, // mov dword ptr [esi+0Ch], edx
155 0x8B, 0x4D, 0xF0, // mov ecx, dword ptr [info]
156 0x89, 0x08, // mov dword ptr [eax], ecx
157 0x8B, 0x45, 0x14, // mov eax, dword ptr [ebx]
158 0x8B, 0x4D, 0xF4, // mov ecx, dword ptr [ebp-0Ch]
159 0x89, 0x08, // mov dword ptr [eax], ecx
160 0x8B, 0x45, 0x18, // mov eax, dword ptr [ecx]
161 0x8B, 0x4D, 0xF8, // mov ecx, dword ptr [ebp-8]
162 0x89, 0x08, // mov dword ptr [eax], ecx
163 0x8B, 0x45, 0x1C, // mov eax, dword ptr [edx]
164 0x8B, 0x4D, 0xFC, // mov ecx, dword ptr [ebp-4]
166 0x89, 0x08, // mov dword ptr [eax], ecx
169 0xC2, 0x18, 0x00 // ret 18h
172 private static readonly byte[] CPUID_64_WINDOWS = new byte[] {
173 0x48, 0x89, 0x5C, 0x24, 0x08, // mov qword ptr [rsp+8], rbx
174 0x8B, 0xC1, // mov eax, ecx
175 0x8B, 0xCA, // mov ecx, edx
177 0x41, 0x89, 0x00, // mov dword ptr [r8], eax
178 0x48, 0x8B, 0x44, 0x24, 0x28, // mov rax, qword ptr [rsp+28h]
179 0x41, 0x89, 0x19, // mov dword ptr [r9], ebx
180 0x48, 0x8B, 0x5C, 0x24, 0x08, // mov rbx, qword ptr [rsp+8]
181 0x89, 0x08, // mov dword ptr [rax], ecx
182 0x48, 0x8B, 0x44, 0x24, 0x30, // mov rax, qword ptr [rsp+30h]
183 0x89, 0x10, // mov dword ptr [rax], edx
187 private static readonly byte[] CPUID_64_LINUX = new byte[] {
188 0x49, 0x89, 0xD2, // mov r10, rdx
189 0x49, 0x89, 0xCB, // mov r11, rcx
191 0x89, 0xF8, // mov eax, edi
192 0x89, 0xF1, // mov ecx, esi
194 0x41, 0x89, 0x02, // mov dword ptr [r10], eax
195 0x41, 0x89, 0x1B, // mov dword ptr [r11], ebx
196 0x41, 0x89, 0x08, // mov dword ptr [r8], ecx
197 0x41, 0x89, 0x11, // mov dword ptr [r9], edx
202 public static bool CpuidTx(uint index, uint ecxValue,
203 out uint eax, out uint ebx, out uint ecx, out uint edx,
204 ulong threadAffinityMask) {
206 ulong mask = ThreadAffinity.Set(threadAffinityMask);
209 eax = ebx = ecx = edx = 0;
213 Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx);
215 ThreadAffinity.Set(mask);
220 public enum AllocationType : uint {
224 LARGE_PAGES = 0x20000000,
227 WRITE_WATCH = 0x200000
231 public enum MemoryProtection : uint {
234 EXECUTE_READWRITE = 0x40,
235 EXECUTE_WRITECOPY = 0x80,
246 public enum FreeType {
251 private static class NativeMethods {
252 private const string KERNEL = "kernel32.dll";
254 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
255 public static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize,
256 AllocationType flAllocationType, MemoryProtection flProtect);
258 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
259 public static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize,
260 FreeType dwFreeType);