Replaced the non-kernel code of WinRing0 with a managed implementation. The new implementation should fix Issue 32 and simplify further work on Issue 46.
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 The contents of this file are subject to the Mozilla Public License Version
6 1.1 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
9 http://www.mozilla.org/MPL/
11 Software distributed under the License is distributed on an "AS IS" basis,
12 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 for the specific language governing rights and limitations under the License.
15 The Original Code is the Open Hardware Monitor code.
17 The Initial Developer of the Original Code is
18 Michael Möller <m.moeller@gmx.ch>.
19 Portions created by the Initial Developer are Copyright (C) 2010
20 the Initial Developer. All Rights Reserved.
24 Alternatively, the contents of this file may be used under the terms of
25 either the GNU General Public License Version 2 or later (the "GPL"), or
26 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 in which case the provisions of the GPL or the LGPL are applicable instead
28 of those above. If you wish to allow use of your version of this file only
29 under the terms of either the GPL or the LGPL, and not to allow others to
30 use your version of this file under the terms of the MPL, indicate your
31 decision by deleting the provisions above and replace them with the notice
32 and other provisions required by the GPL or the LGPL. If you do not delete
33 the provisions above, a recipient may use your version of this file under
34 the terms of any one of the MPL, the GPL or the LGPL.
39 using System.Runtime.InteropServices;
41 namespace OpenHardwareMonitor.Hardware {
42 internal static class Opcode {
43 private static IntPtr codeBuffer;
45 public static void Open() {
46 // No implementation for Unix systems
47 int p = (int)Environment.OSVersion.Platform;
48 if ((p == 4) || (p == 128))
53 if (IntPtr.Size == 4) {
61 codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero,
62 (UIntPtr)(rdtscCode.Length + cpuidCode.Length),
63 AllocationType.COMMIT | AllocationType.RESERVE,
64 MemoryProtection.EXECUTE_READWRITE);
66 Marshal.Copy(rdtscCode, 0, codeBuffer, rdtscCode.Length);
68 Rdtsc = Marshal.GetDelegateForFunctionPointer(
69 codeBuffer, typeof(RdtscDelegate)) as RdtscDelegate;
71 IntPtr cpuidAddress = (IntPtr)((long)codeBuffer + rdtscCode.Length);
72 Marshal.Copy(cpuidCode, 0, cpuidAddress, cpuidCode.Length);
74 Cpuid = Marshal.GetDelegateForFunctionPointer(
75 cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;
78 public static void Close() {
82 NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero,
86 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
87 public delegate ulong RdtscDelegate();
89 public static RdtscDelegate Rdtsc;
91 // unsigned __int64 __stdcall rdtsc() {
95 private static readonly byte[] RDTSC_32 = new byte[] {
100 private static readonly byte[] RDTSC_64 = new byte[] {
102 0x48, 0xC1, 0xE2, 0x20, // shl rdx,20h
103 0x48, 0x0B, 0xC2, // or rax,rdx
107 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
108 public delegate bool CpuidDelegate(uint index, uint ecxValue,
109 out uint eax, out uint ebx, out uint ecx, out uint edx);
111 public static CpuidDelegate Cpuid;
114 // void __stdcall cpuidex(unsigned int index, unsigned int ecxValue,
115 // unsigned int* eax, unsigned int* ebx, unsigned int* ecx,
116 // unsigned int* edx)
119 // __cpuidex(info, index, ecxValue);
126 private static readonly byte[] CPUID_32 = new byte[] {
128 0x8B, 0xEC, // mov ebp,esp
129 0x83, 0xEC, 0x10, // sub esp,10h
130 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp+8]
131 0x8B, 0x4D, 0x0C, // mov ecx,dword ptr [ebp+0Ch]
135 0x8D, 0x75, 0xF0, // lea esi,[info]
136 0x89, 0x06, // mov dword ptr [esi],eax
137 0x8B, 0x45, 0x10, // mov eax,dword ptr [eax]
138 0x89, 0x5E, 0x04, // mov dword ptr [esi+4],ebx
139 0x89, 0x4E, 0x08, // mov dword ptr [esi+8],ecx
140 0x89, 0x56, 0x0C, // mov dword ptr [esi+0Ch],edx
141 0x8B, 0x4D, 0xF0, // mov ecx,dword ptr [info]
142 0x89, 0x08, // mov dword ptr [eax],ecx
143 0x8B, 0x45, 0x14, // mov eax,dword ptr [ebx]
144 0x8B, 0x4D, 0xF4, // mov ecx,dword ptr [ebp-0Ch]
145 0x89, 0x08, // mov dword ptr [eax],ecx
146 0x8B, 0x45, 0x18, // mov eax,dword ptr [ecx]
147 0x8B, 0x4D, 0xF8, // mov ecx,dword ptr [ebp-8]
148 0x89, 0x08, // mov dword ptr [eax],ecx
149 0x8B, 0x45, 0x1C, // mov eax,dword ptr [edx]
150 0x8B, 0x4D, 0xFC, // mov ecx,dword ptr [ebp-4]
152 0x89, 0x08, // mov dword ptr [eax],ecx
155 0xC2, 0x18, 0x00 // ret 18h
158 private static readonly byte[] CPUID_64 = new byte[] {
159 0x48, 0x89, 0x5C, 0x24, 0x08, // mov qword ptr [rsp+8],rbx
160 0x8B, 0xC1, // mov eax,ecx
161 0x8B, 0xCA, // mov ecx,edx
163 0x41, 0x89, 0x00, // mov dword ptr [r8],eax
164 0x48, 0x8B, 0x44, 0x24, 0x28, // mov rax,qword ptr [ecx]
165 0x41, 0x89, 0x19, // mov dword ptr [r9],ebx
166 0x48, 0x8B, 0x5C, 0x24, 0x08, // mov rbx,qword ptr [rsp+8]
167 0x89, 0x08, // mov dword ptr [rax],ecx
168 0x48, 0x8B, 0x44, 0x24, 0x30, // mov rax,qword ptr [rsp+30h]
169 0x89, 0x10, // mov dword ptr [rax],edx
173 public static bool CpuidTx(uint index, uint ecxValue,
174 out uint eax, out uint ebx, out uint ecx, out uint edx,
175 UIntPtr threadAffinityMask) {
177 IntPtr thread = NativeMethods.GetCurrentThread();
178 UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread,
181 if (mask == UIntPtr.Zero) {
182 eax = ebx = ecx = edx = 0;
186 Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx);
188 NativeMethods.SetThreadAffinityMask(thread, mask);
194 public enum AllocationType : uint {
198 LARGE_PAGES = 0x20000000,
201 WRITE_WATCH = 0x200000
205 public enum MemoryProtection : uint {
208 EXECUTE_READWRITE = 0x40,
209 EXECUTE_WRITECOPY = 0x80,
225 private static class NativeMethods {
226 private const string KERNEL = "kernel32.dll";
228 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
229 public static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize,
230 AllocationType flAllocationType, MemoryProtection flProtect);
232 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
233 public static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize,
234 FreeType dwFreeType);
236 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
237 public static extern UIntPtr
238 SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
240 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
241 public static extern IntPtr GetCurrentThread();