root/trunk/blade/Performance/MSRDriver.d

Revision 177, 9.3 kB (checked in by Don Clugston, 4 years ago)

Added performance test using MSR registers; the device driver comes from Agner Fog. Only works on my system (path is hard-coded, only works on Windows, Pentium M and Pentium Core (not core2)).

  • Property svn:mime-type set to text/x-dsrc
  • Property svn:eol-style set to native
Line 
1 /**
2  * Device driver for access to Model-specific registers and control registers
3  * in Windows 2000 and later (32 and 64 bit x86 platform).
4  * Author: Agner Fog. Translation to D by Don Clugston.
5  * License: GNU General Public License (GPL)
6  * Copyright: (c) 2007-06-09 Agner Fog.
7  * (c) 2005-2007 GNU General Public License www.gnu.org/copyleft/gpl.html
8  */
9 module Blade.Performance.MSRDriver;
10 import win32.core; //std.c.windows.windows;
11 import win32.winnt;
12 import win32.winsvc;
13 import win32.windef;
14 import std.string;
15 /*
16 alias HANDLE SC_HANDLE;
17 struct SERVICE_STATUS {
18     DWORD dwServiceType;
19     DWORD dwCurrentState;
20     DWORD dwControlsAccepted;
21     DWORD dwWin32ExitCode;
22     DWORD dwServiceSpecificExitCode;
23     DWORD dwCheckPoint;
24     DWORD dwWaitHint;
25 }
26
27 extern(Windows) {
28 SC_HANDLE OpenServiceA(SC_HANDLE, LPCWSTR, DWORD);
29 BOOL DeleteService(SC_HANDLE);
30
31 }
32 alias OpenServiceA OpenService;
33 */
34
35 // commands for MSR driver
36 enum EMSR_COMMAND {
37    MSR_IGNORE = 0,                // do nothing
38    MSR_STOP   = 1,                // skip rest of list
39    MSR_READ   = 2,                // read model specific register
40    MSR_WRITE  = 3,                // write model specific register
41    CR_READ    = 4,                // read control register
42    CR_WRITE   = 5,                // write control register
43    UNUSED1    = 0x7fffffff        // make sure this enum takes 32 bits
44 };
45
46
47 // input/output data structure for MSR driver
48 struct SMSRInOut {   
49    EMSR_COMMAND msr_command;      // command for read or write register
50    uint register_number;  // register number
51    union {
52       long value;              // 64 bit value to read or write
53       uint val[2];        // lower and upper 32 bits
54    };
55 };
56
57
58 // functions defined in MSRDriver2.asm
59 // replaced by intrinsics in MSRDriver.cpp
60 //extern "C"  __int64 ReadMSR (int r);  // read model specific register
61 //extern "C"  void WriteMSR (int r, __int64 value); // write model specific register
62 //extern (C) size_t ReadCR(int r);                 // read control register
63 //extern (C) void WriteCR(int r, size_t value);    // write control register
64
65
66 void lockToSingleCPU()
67 {
68    // We must lock the process to a single CPU core in case the system has
69    // multiple CPUs or a CPU with multiple cores. Otherwise, we can get
70    // errors if the MSRDriver happens to set up the counters on one core
71    // and the test code runs on another core.
72    uint ProcessAffMask = 0, SystemAffMask = 0;
73
74    // Get mask of possible CPU cores
75    GetProcessAffinityMask(GetCurrentProcess(), &ProcessAffMask, &SystemAffMask);
76    //printf("\nProcess mask %X, system mask %X\n\n", ProcessAffMask, SystemAffMask);
77    if (ProcessAffMask > 1) {
78       // more than one CPU core available. Fix to only one:
79       if (ProcessAffMask & 2) {
80          ProcessAffMask = 2;
81       } else {
82          ProcessAffMask = 1;
83       }
84       // Lock process to a single CPU core
85       SetProcessAffinityMask(GetCurrentProcess(), ProcessAffMask);
86    }
87 }
88
89
90 // class CMSRDriver encapsulates the interface to the driver MSRDriver32.sys
91 // which is needed for privileged access to set up the MSRs. This class
92 // loads, unloads and sends commands to MSRDriver
93 class CMSRDriver {
94 public:
95 const char[]   DriverFileName = "MSRDriver32";
96 const char[]   DriverSymbolicName = "\\\\.\\slMSRDriver";
97
98     this() {
99 /*       
100        // Define Driver filename
101        if (Need64BitDriver()) {
102           DriverFileName = "MSRDriver64";
103        }
104        else {
105           DriverFileName = "MSRDriver32";
106        }
107       
108        // Define driver symbolic link name
109        DriverSymbolicName = "\\\\.\\slMSRDriver";
110     */
111         // Initialize
112        scm = null;                       
113        service = null;
114        hDriver = null;
115     }
116     ~this() {
117        // Unload driver if not already unloaded
118         if (scm) UnloadDriver();
119     }
120     int AccessRegisters(SMSRInOut [] data)
121     {
122         if (data.length==0) return 0;
123        
124        const int DeviceType = 0x22;        // FILE_DEVICE_UNKNOWN;
125        const int Function = 0x800;
126        const int Method = 0;               // METHOD_BUFFERED;
127        const int Access = 1 | 2;           // FILE_READ_ACCESS | FILE_WRITE_ACCESS;
128        const int IOCTL_MSR_DRIVER = DeviceType << 16 | Access << 14 | Function << 2 | Method;
129    
130        DWORD len = 0;
131        
132        // This call results in a call to the driver rutine DispatchControl()
133        int res = DeviceIoControl(hDriver, IOCTL_MSR_DRIVER, &data[0], data.length*SMSRInOut.sizeof,
134           &data[0], data.length*SMSRInOut.sizeof, &len, null);
135        if (!res) return GetLastError();
136        return 0;
137     }
138    // send commands to driver to read or write MSR registers
139     int AccessRegisters(void * pnIn, int nInLen, void * pnOut, int nOutLen)
140     {
141         if (nInLen <= 0) return 0;
142        
143            const int DeviceType = 0x22; // FILE_DEVICE_UNKNOWN;
144            const int Function = 0x800;
145            const int Method = 0;        // METHOD_BUFFERED;
146            const int Access = 1 | 2;    // FILE_READ_ACCESS | FILE_WRITE_ACCESS;
147            const int IOCTL_MSR_DRIVER = DeviceType << 16 | Access << 14 | Function << 2 | Method;
148        
149            DWORD len = 0;
150            
151            // This call results in a call to the driver rutine DispatchControl()
152            int res = DeviceIoControl(hDriver, IOCTL_MSR_DRIVER, pnIn, nInLen,
153               pnOut, nOutLen, &len, null);
154            if (!res) {
155               // Error
156               return GetLastError();}
157            return 0;
158    }
159 /+   
160 // Read a control register cr0 or cr4
161 size_t CRRead(int r) {
162    if (r != 0 && r != 4) return -11;
163    SMSRInOut a;
164    a.msr_command = CR_READ;
165    a.register_number = r;
166    a.value = 0;
167    AccessRegisters(&a,sizeof(a),&a,sizeof(a));
168    return size_t(a.value);
169 }
170    // send command to driver to write one control register
171 int CRWrite(int r, size_t val) {
172    if (r != 0 && r != 4) return -12;
173    SMSRInOut a;
174    a.msr_command = CR_WRITE;
175    a.register_number = r;
176    a.value = val;
177    return AccessRegisters(&a,sizeof(a),&a,sizeof(a));
178 }
179 +/
180 int LoadDriver() {
181    
182 //           char[MAX_PATH] DriverFileNameE, DriverFilePath;
183 //           char *p;
184
185    // Open connection to Windows Service Control Manager (SCM)
186    scm = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
187    if(scm != null) {
188       /*
189       // Get the full path of the driver file name
190       strcpy(DriverFileNameE, DriverFileName);
191       strcat(DriverFileNameE, ".sys");           // append .sys to DriverName
192       GetFullPathName(DriverFileNameE, MAX_PATH, DriverFilePath, &p);
193       */
194       char* DriverFilePath = toStringz("C:\\Sandbox\\blade\\performance\\MSRDriver32.sys");
195       char*   DriverFileNameE = toStringz("MSRDriver32.sys");
196  //     char [MAX_PATH] DriverFilePathBuff;
197  //     char *p;
198 //      GetFullPathName(DriverFileNameE, MAX_PATH, &DriverFilePathBuff[0], &p);
199 //      char * DriverFilePath = toString(DriverFilePathBuff);
200
201       // Load the driver into memory and call its entry rutine
202       service = CreateService(scm, DriverFileNameE, toStringz("MSR driver"),
203          SERVICE_START + SERVICE_STOP + DELETE, SERVICE_KERNEL_DRIVER,
204          SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, DriverFilePath,
205          null, null, null, null, null);
206      
207       if(service == null) {
208          // Cannot load driver.
209          // Unload it in case it was not unloaded last time
210          service = OpenService(scm, DriverFileNameE, SERVICE_ALL_ACCESS);
211          SERVICE_STATUS ss;
212          ControlService(service, SERVICE_CONTROL_STOP, &ss);         
213          DeleteService(service);
214          CloseServiceHandle(service);
215
216          // Try again to load driver
217          service = CreateService(scm, DriverFileNameE, toStringz("MSR driver"),
218             SERVICE_START + SERVICE_STOP + DELETE, SERVICE_KERNEL_DRIVER,
219             SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, DriverFilePath,
220             null, null, null, null, null);
221
222          if(service is null) {
223             // Still cannot load driver
224             CloseServiceHandle(scm); scm = null;
225             return -3;
226          }
227       }
228      
229       // Start the service
230       if(!StartService(service, 0, null)) {
231          // Error
232          int ErrNo = GetLastError();
233          // Stop service and cleanup
234          service = OpenService(scm, toStringz(DriverFileName), SERVICE_ALL_ACCESS);
235          SERVICE_STATUS ss;
236          ControlService(service, SERVICE_CONTROL_STOP, &ss);         
237          DeleteService(service);
238          CloseServiceHandle(service);         
239          CloseServiceHandle(scm); scm = null;
240          return ErrNo;
241       }
242      
243       if(service) {
244          // Get handle to driver
245          hDriver = CreateFile(toStringz(DriverSymbolicName), GENERIC_READ + GENERIC_WRITE,
246             0, null, OPEN_EXISTING, 0, null);
247          
248          if(hDriver == null || hDriver == INVALID_HANDLE_VALUE) return -5;
249       }
250       else return -2;
251    }
252    else return GetLastError();
253    
254    return 0;
255 }
256
257     int UnloadDriver() {
258    if(scm == null || service == null || hDriver == null) {
259       return -6;}
260    
261    CloseHandle(hDriver); hDriver = null;
262    
263    SERVICE_STATUS ss;
264    ControlService(service, SERVICE_CONTROL_STOP, &ss);
265    
266    DeleteService(service);
267    CloseServiceHandle(service); service = null;   
268    CloseServiceHandle(scm); scm = null;
269    
270    return 0;
271 }
272 protected:
273    bool Need64BitDriver() { return 0; }    // tell whether we need 32 bit or 64 bit driver
274     SC_HANDLE scm;
275     SC_HANDLE service;
276     HANDLE hDriver;
277 //   LPCTSTR DriverFileName;
278 //   LPCTSTR DriverSymbolicName;
279 };
Note: See TracBrowser for help on using the browser.