bugfixes+cleanup
aken: clean up debug strings mahaf: use checked/free version of aken depending on config. refactor to eliminate goto. hpet: avoid undefined unmap if HPET not found whrt/*: make sure all counter class data is initialized whrt: prefer QPC over PMT (it's much faster?!) winit: add some instrumentation wutil: win_exe_dir and win_sys_dir shouldn't end in slash. fixed. This was SVN commit r5116.
This commit is contained in:
parent
fba692c8b5
commit
cba876b246
@ -3,8 +3,6 @@ extern "C" { // must come before ntddk.h
|
||||
#include <ntddk.h>
|
||||
#include "aken.h"
|
||||
|
||||
#define KDPRINT KdPrint(("AKEN: ")); KdPrint
|
||||
|
||||
#define WIN32_NAME L"\\DosDevices\\Aken"
|
||||
#define DEVICE_NAME L"\\Device\\Aken"
|
||||
|
||||
@ -36,7 +34,7 @@ static NTSTATUS AkenMapPhysicalMemory(const DWORD64 physicalAddress64, const DWO
|
||||
ntStatus = ZwOpenSection(&hMemory, SECTION_ALL_ACCESS, &objectAttributes);
|
||||
if(!NT_SUCCESS(ntStatus))
|
||||
{
|
||||
KDPRINT(("ZwOpenSection failed\n"));
|
||||
KdPrint(("AkenMapPhysicalMemory: ZwOpenSection failed\n"));
|
||||
return ntStatus;
|
||||
}
|
||||
}
|
||||
@ -48,7 +46,7 @@ static NTSTATUS AkenMapPhysicalMemory(const DWORD64 physicalAddress64, const DWO
|
||||
ntStatus = ObReferenceObjectByHandle(hMemory, SECTION_ALL_ACCESS, objectType, KernelMode, &physicalMemorySection, 0);
|
||||
if(!NT_SUCCESS(ntStatus))
|
||||
{
|
||||
KDPRINT(("ObReferenceObjectByHandle failed\n"));
|
||||
KdPrint(("AkenMapPhysicalMemory: ObReferenceObjectByHandle failed\n"));
|
||||
goto close_handle;
|
||||
}
|
||||
}
|
||||
@ -67,7 +65,7 @@ static NTSTATUS AkenMapPhysicalMemory(const DWORD64 physicalAddress64, const DWO
|
||||
ntStatus = ZwMapViewOfSection(hMemory, hProcess, &virtualBaseAddress, zeroBits, mappedSize, &physicalBaseAddress, &mappedSize, inheritDisposition, allocationType, protect);
|
||||
if(!NT_SUCCESS(ntStatus))
|
||||
{
|
||||
KDPRINT(("ZwMapViewOfSection failed\n"));
|
||||
KdPrint(("AkenMapPhysicalMemory: ZwMapViewOfSection failed\n"));
|
||||
goto close_handle;
|
||||
}
|
||||
|
||||
@ -97,7 +95,7 @@ static NTSTATUS AkenUnmapPhysicalMemory(const DWORD64 virtualAddress)
|
||||
NTSTATUS ntStatus = ZwUnmapViewOfSection(hProcess, baseAddress);
|
||||
if(!NT_SUCCESS(ntStatus))
|
||||
{
|
||||
KDPRINT(("ZwUnmapViewOfSection failed\n"));
|
||||
KdPrint(("AkenUnmapPhysicalMemory: ZwUnmapViewOfSection failed\n"));
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
@ -111,8 +109,6 @@ static NTSTATUS AkenUnmapPhysicalMemory(const DWORD64 virtualAddress)
|
||||
|
||||
static NTSTATUS AkenIoctlReadPort(PVOID buf, const ULONG inSize, ULONG& outSize)
|
||||
{
|
||||
KDPRINT(("IOCTL_AKEN_READ_PORT\n"));
|
||||
|
||||
if(inSize != sizeof(AkenReadPortIn) || outSize != sizeof(AkenReadPortOut))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
@ -134,7 +130,7 @@ static NTSTATUS AkenIoctlReadPort(PVOID buf, const ULONG inSize, ULONG& outSize)
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
KDPRINT((" port %x = %x\n", port, value));
|
||||
KdPrint(("AkenIoctlReadPort: port %x = %x\n", port, value));
|
||||
|
||||
AkenReadPortOut* out = (AkenReadPortOut*)buf;
|
||||
out->value = value;
|
||||
@ -143,8 +139,6 @@ static NTSTATUS AkenIoctlReadPort(PVOID buf, const ULONG inSize, ULONG& outSize)
|
||||
|
||||
static NTSTATUS AkenIoctlWritePort(PVOID buf, const ULONG inSize, ULONG& outSize)
|
||||
{
|
||||
KDPRINT(("IOCTL_AKEN_WRITE_PORT\n"));
|
||||
|
||||
if(inSize != sizeof(AkenWritePortIn) || outSize != 0)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
@ -166,15 +160,13 @@ static NTSTATUS AkenIoctlWritePort(PVOID buf, const ULONG inSize, ULONG& outSize
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
KDPRINT((" port %x := %x\n", port, value));
|
||||
KdPrint(("AkenIoctlWritePort: port %x := %x\n", port, value));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS AkenIoctlMap(PVOID buf, const ULONG inSize, ULONG& outSize)
|
||||
{
|
||||
KDPRINT(("IOCTL_AKEN_MAP\n"));
|
||||
|
||||
if(inSize != sizeof(AkenMapIn) || outSize != sizeof(AkenMapOut))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
@ -191,8 +183,6 @@ static NTSTATUS AkenIoctlMap(PVOID buf, const ULONG inSize, ULONG& outSize)
|
||||
|
||||
static NTSTATUS AkenIoctlUnmap(PVOID buf, const ULONG inSize, ULONG& outSize)
|
||||
{
|
||||
KDPRINT(("IOCTL_AKEN_UNMAP\n"));
|
||||
|
||||
if(inSize != sizeof(AkenUnmapIn) || outSize != 0)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
@ -205,7 +195,7 @@ static NTSTATUS AkenIoctlUnmap(PVOID buf, const ULONG inSize, ULONG& outSize)
|
||||
|
||||
static NTSTATUS AkenIoctlUnknown(PVOID buf, const ULONG inSize, ULONG& outSize)
|
||||
{
|
||||
KDPRINT(("Unknown IOCTL\n"));
|
||||
KdPrint(("AkenIoctlUnknown\n"));
|
||||
outSize = 0;
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
@ -239,8 +229,7 @@ static inline AkenIoctl AkenIoctlFromCode(ULONG ioctlCode)
|
||||
// entry points
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// used as Create and Close entry point since this driver is stateless.
|
||||
static NTSTATUS MarkRequestComplete(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
|
||||
static NTSTATUS AkenCreate(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
|
||||
{
|
||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
irp->IoStatus.Information = 0;
|
||||
@ -249,7 +238,17 @@ static NTSTATUS MarkRequestComplete(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS DeviceControl(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
|
||||
static NTSTATUS AkenClose(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
|
||||
{
|
||||
// same as AkenCreate ATM
|
||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS AkenDeviceControl(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
|
||||
{
|
||||
// get buffer from IRP. all our IOCTLs are METHOD_BUFFERED, so buf is
|
||||
// allocated by the I/O manager and used for both input and output.
|
||||
@ -269,9 +268,9 @@ static NTSTATUS DeviceControl(IN PDEVICE_OBJECT deviceObject, IN PIRP irp)
|
||||
}
|
||||
|
||||
|
||||
static VOID Unload(IN PDRIVER_OBJECT driverObject)
|
||||
static VOID AkenUnload(IN PDRIVER_OBJECT driverObject)
|
||||
{
|
||||
KDPRINT(("Unload\n"));
|
||||
KdPrint(("AkenUnload\n"));
|
||||
|
||||
UNICODE_STRING win32Name = RTL_CONSTANT_STRING(WIN32_NAME);
|
||||
IoDeleteSymbolicLink(&win32Name);
|
||||
@ -283,8 +282,6 @@ static VOID Unload(IN PDRIVER_OBJECT driverObject)
|
||||
|
||||
NTSTATUS DriverEntry(IN OUT PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath)
|
||||
{
|
||||
KDPRINT(("DriverEntry\n"));
|
||||
|
||||
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
|
||||
|
||||
// create device object
|
||||
@ -296,16 +293,16 @@ NTSTATUS DriverEntry(IN OUT PDRIVER_OBJECT driverObject, IN PUNICODE_STRING regi
|
||||
NTSTATUS ntStatus = IoCreateDevice(driverObject, deviceExtensionSize, &deviceName, FILE_DEVICE_AKEN, deviceCharacteristics, exlusive, &deviceObject);
|
||||
if(!NT_SUCCESS(ntStatus))
|
||||
{
|
||||
KDPRINT(("IoCreateDevice failed\n"));
|
||||
KdPrint(("DriverEntry: IoCreateDevice failed\n"));
|
||||
return ntStatus;
|
||||
}
|
||||
}
|
||||
|
||||
// set entry points
|
||||
driverObject->MajorFunction[IRP_MJ_CREATE] = MarkRequestComplete;
|
||||
driverObject->MajorFunction[IRP_MJ_CLOSE] = MarkRequestComplete;
|
||||
driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
|
||||
driverObject->DriverUnload = Unload;
|
||||
driverObject->MajorFunction[IRP_MJ_CREATE] = AkenCreate;
|
||||
driverObject->MajorFunction[IRP_MJ_CLOSE] = AkenClose;
|
||||
driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AkenDeviceControl;
|
||||
driverObject->DriverUnload = AkenUnload;
|
||||
|
||||
// symlink NT device name to Win32 namespace
|
||||
{
|
||||
@ -313,7 +310,7 @@ NTSTATUS DriverEntry(IN OUT PDRIVER_OBJECT driverObject, IN PUNICODE_STRING regi
|
||||
NTSTATUS ntStatus = IoCreateSymbolicLink(&win32Name, &deviceName);
|
||||
if(!NT_SUCCESS(ntStatus))
|
||||
{
|
||||
KDPRINT(("IoCreateSymbolicLink failed\n"));
|
||||
KdPrint(("DriverEntry: IoCreateSymbolicLink failed\n"));
|
||||
IoDeleteDevice(deviceObject);
|
||||
return ntStatus;
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <winioctl.h>
|
||||
#include "aken/aken.h"
|
||||
#include "wutil.h"
|
||||
#include "lib/path_util.h"
|
||||
#include "lib/module_init.h"
|
||||
|
||||
|
||||
@ -76,8 +75,7 @@ static void WritePort(u16 port, u32 value, u8 numBytes)
|
||||
DWORD bytesReturned; // unused but must be passed to DeviceIoControl
|
||||
LPOVERLAPPED ovl = 0; // synchronous
|
||||
BOOL ok = DeviceIoControl(hAken, (DWORD)IOCTL_AKEN_WRITE_PORT, &in, sizeof(in), 0, 0u, &bytesReturned, ovl);
|
||||
if(!ok)
|
||||
WARN_WIN32_ERR;
|
||||
WARN_IF_FALSE(ok);
|
||||
}
|
||||
|
||||
void mahaf_WritePort8(u16 port, u8 value)
|
||||
@ -126,8 +124,7 @@ void mahaf_UnmapPhysicalMemory(void* virtualAddress)
|
||||
DWORD bytesReturned; // unused but must be passed to DeviceIoControl
|
||||
LPOVERLAPPED ovl = 0; // synchronous
|
||||
BOOL ok = DeviceIoControl(hAken, (DWORD)IOCTL_AKEN_UNMAP, &in, sizeof(in), 0, 0u, &bytesReturned, ovl);
|
||||
if(!ok)
|
||||
WARN_WIN32_ERR;
|
||||
WARN_IF_FALSE(ok);
|
||||
}
|
||||
|
||||
|
||||
@ -135,16 +132,6 @@ void mahaf_UnmapPhysicalMemory(void* virtualAddress)
|
||||
// driver installation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool Is64BitOs()
|
||||
{
|
||||
#if OS_WIN64
|
||||
return true;
|
||||
#else
|
||||
return wutil_IsWow64();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static SC_HANDLE OpenServiceControlManager()
|
||||
{
|
||||
LPCSTR machineName = 0; // local
|
||||
@ -206,33 +193,26 @@ static void StartDriver(const char* driverPathname)
|
||||
if(!hSCM)
|
||||
return;
|
||||
|
||||
SC_HANDLE hService = OpenService(hSCM, AKEN_NAME, SERVICE_ALL_ACCESS);
|
||||
|
||||
#if 0
|
||||
// during development, we want to unload and re-create the
|
||||
// service every time to ensure the newest build is used.
|
||||
BOOL ok = CloseServiceHandle(hService);
|
||||
WARN_IF_FALSE(ok);
|
||||
hService = 0;
|
||||
UninstallDriver();
|
||||
#endif
|
||||
|
||||
// create service (note: this just enters the service into SCM's DB;
|
||||
// no error is raised if the driver binary doesn't exist etc.)
|
||||
SC_HANDLE hService;
|
||||
if(!hService)
|
||||
{
|
||||
create:
|
||||
LPCSTR startName = 0; // LocalSystem
|
||||
hService = CreateService(hSCM, AKEN_NAME, AKEN_NAME,
|
||||
SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
|
||||
driverPathname, 0, 0, 0, startName, 0);
|
||||
if(!hService)
|
||||
{
|
||||
// was already created
|
||||
if(GetLastError() == ERROR_SERVICE_EXISTS)
|
||||
{
|
||||
#if 1
|
||||
// during development, we want to unload and re-create the
|
||||
// service every time to ensure the newest build is used.
|
||||
UninstallDriver();
|
||||
goto create;
|
||||
#else
|
||||
// in final builds, just use the existing service.
|
||||
hService = OpenService(hSCM, AKEN_NAME, SERVICE_ALL_ACCESS);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
debug_assert(0); // creating actually failed
|
||||
}
|
||||
debug_assert(hService != 0);
|
||||
}
|
||||
|
||||
// start service
|
||||
@ -252,6 +232,27 @@ create:
|
||||
}
|
||||
|
||||
|
||||
static bool Is64BitOs()
|
||||
{
|
||||
#if OS_WIN64
|
||||
return true;
|
||||
#else
|
||||
return wutil_IsWow64();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void GetDriverPathname(char* driverPathname, size_t maxChars)
|
||||
{
|
||||
const char* const bits = Is64BitOs()? "64" : "";
|
||||
#ifdef NDEBUG
|
||||
const char* const debug = "";
|
||||
#else
|
||||
const char* const debug = "d";
|
||||
#endif
|
||||
sprintf_s(driverPathname, maxChars, "%s\\aken%s%s.sys", win_exe_dir, bits, debug);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static ModuleInitState initState;
|
||||
@ -262,8 +263,7 @@ bool mahaf_Init()
|
||||
return true;
|
||||
|
||||
char driverPathname[PATH_MAX];
|
||||
const char* const driverName = Is64BitOs()? "aken64.sys" : "aken.sys";
|
||||
(void)path_append(driverPathname, win_exe_dir, driverName);
|
||||
GetDriverPathname(driverPathname, ARRAY_SIZE(driverPathname));
|
||||
|
||||
StartDriver(driverPathname);
|
||||
|
||||
|
@ -75,7 +75,8 @@ LibError CounterHPET::Activate()
|
||||
|
||||
void CounterHPET::Shutdown()
|
||||
{
|
||||
mahaf_UnmapPhysicalMemory((void*)m_hpetRegisters);
|
||||
if(m_hpetRegisters)
|
||||
mahaf_UnmapPhysicalMemory((void*)m_hpetRegisters);
|
||||
|
||||
acpi_Shutdown();
|
||||
mahaf_Shutdown();
|
||||
|
@ -17,6 +17,11 @@
|
||||
class CounterHPET : public ICounter
|
||||
{
|
||||
public:
|
||||
CounterHPET()
|
||||
: m_hpetRegisters(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char* Name() const
|
||||
{
|
||||
return "HPET";
|
||||
|
@ -18,6 +18,11 @@ static const i64 PMT_FREQ = 3579545; // (= master oscillator frequency/4)
|
||||
class CounterPMT : public ICounter
|
||||
{
|
||||
public:
|
||||
CounterPMT()
|
||||
: m_portAddress(0xFFFF)
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char* Name() const
|
||||
{
|
||||
return "PMT";
|
||||
|
@ -16,6 +16,11 @@
|
||||
class CounterQPC : public ICounter
|
||||
{
|
||||
public:
|
||||
CounterQPC()
|
||||
: m_frequency(-1)
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char* Name() const
|
||||
{
|
||||
return "QPC";
|
||||
|
@ -39,8 +39,6 @@ public:
|
||||
* (e.g. when using TSC: cpu_ClockFrequency isn't exact).
|
||||
**/
|
||||
virtual double NominalFrequency() const;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // #ifndef INCLUDED_TSC
|
||||
|
@ -64,6 +64,7 @@ static ICounter* ConstructCounterAt(uint id, void* address, size_t& size)
|
||||
// counters are chosen according to the following order. rationale:
|
||||
// - TSC must come before QPC and PMT to make sure a bug in the latter on
|
||||
// Pentium systems doesn't come up.
|
||||
// - PMT works, but is inexplicably slower than QPC on a PIII Mobile.
|
||||
// - TGT really isn't as safe as the others, so it should be last.
|
||||
// - low-overhead and high-resolution counters are preferred.
|
||||
switch(id)
|
||||
@ -73,9 +74,9 @@ static ICounter* ConstructCounterAt(uint id, void* address, size_t& size)
|
||||
case 1:
|
||||
CREATE(HPET)
|
||||
case 2:
|
||||
CREATE(PMT)
|
||||
case 3:
|
||||
CREATE(QPC)
|
||||
case 3:
|
||||
CREATE(PMT)
|
||||
case 4:
|
||||
CREATE(TGT)
|
||||
default:
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "precompiled.h"
|
||||
#include "winit.h"
|
||||
|
||||
#include "win.h" // GetTickCount
|
||||
|
||||
|
||||
typedef LibError (*PfnLibErrorVoid)(void);
|
||||
|
||||
@ -44,11 +46,16 @@ PfnLibErrorVoid shutdownEnd = 0;
|
||||
**/
|
||||
static void CallFunctionPointers(PfnLibErrorVoid* begin, PfnLibErrorVoid* end)
|
||||
{
|
||||
const DWORD t0 = GetTickCount();
|
||||
|
||||
for(PfnLibErrorVoid* ppfunc = begin; ppfunc < end; ppfunc++)
|
||||
{
|
||||
if(*ppfunc)
|
||||
(*ppfunc)();
|
||||
}
|
||||
|
||||
const DWORD t1 = GetTickCount();
|
||||
debug_printf("WINIT/ total elapsed time in callbacks %d ms (+-10)\n", t1-t0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,8 +161,14 @@ static void GetDirectories()
|
||||
{
|
||||
GetSystemDirectory(win_sys_dir, sizeof(win_sys_dir));
|
||||
|
||||
if(GetModuleFileName(GetModuleHandle(0), win_exe_dir, MAX_PATH) != 0)
|
||||
path_strip_fn(win_exe_dir);
|
||||
const DWORD len = GetModuleFileName(GetModuleHandle(0), win_exe_dir, MAX_PATH);
|
||||
debug_assert(len != 0);
|
||||
// strip EXE filename and trailing slash
|
||||
char* slash = strrchr(win_exe_dir, '\\');
|
||||
if(slash)
|
||||
*slash = '\0';
|
||||
else
|
||||
debug_assert(0); // directory name invalid?!
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,6 +89,7 @@ extern LibError LibError_from_win32(DWORD ret, bool warn_if_failed = true);
|
||||
// directories
|
||||
//
|
||||
|
||||
// neither of these end in a slash.
|
||||
extern char win_sys_dir[MAX_PATH+1];
|
||||
extern char win_exe_dir[MAX_PATH+1];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user