Download presentation
Presentation is loading. Please wait.
Published byJulius Poole Modified over 9 years ago
1
Drivers For 64-Bit Windows ® Nar Ganapathy Software Design Engineer Windows NT ® Base Systems Microsoft Corporation
3
Agenda What is 64-bit Windows Programming model Porting guidelines Programming issues
4
64-Bit Windows 2000 Goals Porting from Win32 ® to Win64 should be simple A single source code base for Win32 and Win64 Enable existing applications to scale to enterprise capacities Enable new designs that use huge address space and memory Support existing 32-bit applications 32-bit device drivers not supported
5
What Is 64-Bit Version Of Windows 2000? 64-Bit Windows is an evolution of the Windows programming model and APIs LLP64 model Pointers are expanded to 64 bits Memory allocation sizes are 64 bits Longs and ints are 32 bits
6
Win64 Programming Model Uses the same Win32 DDIs/APIs Adds new explicitly sized types Adds new integral types that match the precision of a pointer Almost all Win32 32-bit data types remain 32-bits E.g., size of ULONG is still 32 bits under Win64 Pointers are 64-bits
7
Win64 Programming Model Items expanded to 64 bits Length for most memory allocations CPU mask Unchanged Length for I/O operations Unicode string lengths
8
Win64 Data Types TYPE NAME What It is LONG32, INT32 32 bit signed LONG64, INT64 64 bit signed ULONG32,UINT32,DWORD32 32 bit unsigned ULONG64,UINT64,DWORD64 64 bit unsigned
9
Win64 Data Types Continued TYPE NAME What it is INT_PTR,LONG_PTR Signed Int, Pointer precision UINT_PTR,ULONG_PTR,DWORD_PTR Unsigned Int, Pointer precision SIZE_T Unsigned count, Pointer precision SSIZE_T Signed count, Pointer precision
10
Win64 Porting Guidelines Use Win64 safe data types Examine all pointer usage, especially pointer arithmetic Two major porting topics Driver specific issues (e.g., IOCTLs, DMA) Programming issues
11
Memory Management (IA64) User addresses range from 0x10000 – 0x000006FBFFFEFFFF One terabyte system cache Sixteen gigabyte HyperSpace 128 gigabyte paged pool 128 gigabyte System address space for kernel threads, etc. 128 gigabyte non-paged pool Physical memory addresses are 64 bits
12
WOW64 Runs Windows NT x86 binaries No support for mixing of x86 and IA-64 code within a process User/kernel transitions are thunked to account for structure differences and transition between instruction sets Only a few dlls are thunked: ntdll.dll user.dll, gdi.dll plus a set of LPC calls The rest of the dlls are stock x86 binaries copied from the release shares
13
Driver Specific Issues Drivers need to support Plug and Play and Power Management I/O request length is limited to 32 bits 32-bit devices will be double buffered for DMA transfers Some drivers will need to support 32- and 64-bit versions of IOCTL command
14
Support 32-Bit IOCTLS IOCTL structures that contain pointer dependent types have different sizes in 64-bit and 32-bit applications Driver has to distinguish between Ioctls issued from 32-bit or 64-bit threads Driver validates the input or output buffer lengths based on the issuer’s bit width
15
Supporting 32-Bit IOCTL Three possible solutions Avoid having pointer types in IOCTL structures Use the API IoIs32bitProcess() Use a new bit in the Function code field of the IOCTL code for 64-bit callers
16
32 And 64-Bit IOCTL Example IOCTL structure in header file typedef struct _IOCTL_PARAMETERS { PVOID Addr; PVOID Addr; SIZE_T Length; SIZE_T Length; HANDLE Handle; HANDLE Handle; } IOCTL_PARAMETERS, *PIOCTL_PARAMETERS;
17
32 And 64-Bit IOCTL Example 32-bit IOCTL structure // // This structure is defined inside the driver source code // typedef struct _IOCTL_PARAMETERS_32 { VOID*POINTER_32 Addr; VOID*POINTER_32 Addr; INT32 Length; INT32 Length; VOID*POINTER_32 Handle; VOID*POINTER_32 Handle; } IOCTL_PARAMETERS_32, *PIOCTL_PARAMETERS_32;
18
32 And 64-Bit IOCTL Example #ifdef _WIN64 case IOCTL_REGISTER: if (IoIs32bitProcess(Irp)) { /* If this is a 32 bit process */ params32 = (PIOCTL_PARAMETERS_32) (Irp->AssociatedIrp.SystemBuffer); if(irpSp->Parameters.DeviceIoControl.InputBufferLength Addr; LocalParam.Handle = params32->Handle; LocalParam.Length = params32->Length; if(irpSp->Parameters.DeviceIoControl.InputBufferLength Addr; LocalParam.Handle = params32->Handle; LocalParam.Length = params32->Length; /* Handle the ioctl here */ /* Handle the ioctl here */ status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(IOCTL_PARAMETERS); }
19
32 And 64-Bit IOCTL Example } else { /* 64bit process IOCTL */ params = (PIOCTL_PARAMETERS) (Irp->AssociatedIrp.SystemBuffer); params = (PIOCTL_PARAMETERS) (Irp->AssociatedIrp.SystemBuffer); if (irpSp->Parameters.DeviceIoControl.InputBufferLength Parameters.DeviceIoControl.InputBufferLength < sizeof(IOCTL_PARAMETERS)) { status = STATUS_INVALID_PARAMETER; } else { RtlCopyMemory(&LocalParam, params, sizeof(IOCTL_PARAMETERS)); /* Handle the ioctl here */ /* Handle the ioctl here */ status = STATUS_SUCCESS; } Irp->IoStatus.Information = sizeof(IOCTL_PARAMETERS); status = STATUS_SUCCESS; } Irp->IoStatus.Information = sizeof(IOCTL_PARAMETERS); } break;
20
Use New IOCTL Code Use bit in function field to indicate 64-bit IOCTL Current IOCTL codes have four fields New IOCTL code has one extra bit for 64 bit Device Type (16) Access (2) Function (12) Method (2) Device Type (16) Access (2) 64 bit (1) Function (11) Method (2)
21
DMA APIs Drivers should use PHYSICAL_ADDRESS typedef to access physical addresses (64 bits long) Driver must treat all 64 bits as a Valid Physical Address, do not ignore top 32 bits Drivers must use the Windows DMA APIs IoAllocateAdapter, IoAllocateAdapterChannel,IoMapTransfer,etc. Use new scatter/gather DMA APIs Devices with 64-bit addressing capability will significantly improve performance
22
Programming Issues Polymorphic Data usage Miscellaneous cleanup Alignment issues
23
Polymorphic Data Usage Don’t cast pointer to int, long, ULONG, DWORD Use UINT_PTR and INT_PTR ImageBase = (PVOID) ((ULONG)ImageBase | 1); ImageBase = (PVOID) ((ULONG_PTR)ImageBase | 1); Should be re-written as
24
…Polymorphic Data Usage… Use PtrToUlong and PtrToLong to truncate pointers Never cast a int or ULONG that stores a truncated pointer back to a pointer Be careful when computing buffer sizes; Sizes may exceed capacity of ULONG
25
…Polymorhpic Data Usage Be careful when calling functions that have pointer OUT parameters void GetBufferAddress(OUT PULONG *ptr); {*ptr=0x1000100010001000;} void foo() { ULONG bufAddress; ULONG bufAddress; // // // this call causes memory corruption // this call causes memory corruption // // GetBufferAddress((PULONG *)&bufAddress); GetBufferAddress((PULONG *)&bufAddress);}
26
Miscellaneous Cleanup -1 != 0xFFFFFFFF 0xFFFFFFFF != invalid handle DWORD is always 32 bits Look for DWORD variables used to store pointers or handles Cast pointers to PCHAR for Pointer arithmetic ptr = (PVOID) ((PCHAR) ptr + pageSize);
27
Miscellaneous Cleanup Use %I to print pointers in debug statements Addresses >= 0x80000000 are not necessarily kernel addresses
28
Alignment Misaligned memory references will raise an exception on Win64 #pragma pack (1) /* also set by /Zp switch */ struct AlignSample { ULONG size; void *ptr; }; void foo(void *p) { struct AlignSample s; s.ptr = p;// will cause alignment fault...}
29
Alignment Use UNALIGNED macro to fix Better solution is to put 64-bit values and pointers at the beginning of the structure void foo(void *p) { struct AlignSample s; *(UNALIGNED void *)&s.ptr = p; *(UNALIGNED void *)&s.ptr = p;}
30
Alignment Be cautious of any structure packing directives Be especially cautious of different PACK levels used in the same header RtlCopyMemory and memcpy will not fault
31
More Programming Issues Carefully examine Explicit and implicit unions with pointers Data structures stored on disk or exchanged with 32-bit processes Security descriptors Code which deals with memory region sizes len = ptr2 – ptr1 len = ptr2 – ptr1 len could be greater than 2^32 len could be greater than 2^32
32
Miscellaneous Programming Issues Executive handles can be truncated to 32 bit Piecemeal size allocations: struct foo { DWORD NumberOfPointers; PVOID Pointers[1]; } xx; Wrong:malloc(sizeof(DWORD)+100*sizeof(PVOID));Correct: malloc(FIELD_OFFSET(struct foo,Pointers) +100*sizeof(PVOID));
33
Miscellaneous Programming Issues Be careful when using hexadecimal constants and unsigned values Following assertion not true on 64 bit systems ~((UINT64)(PAGE_SIZE-1)) == (UINT64)~(PAGE_SIZE-1) PAGE_SIZE = 0x1000UL // Unsigned Long - 32 bits PAGE_SIZE - 1 = 0x00000fff LHS expression: // Unsigned expansion (UINT64)(PAGE_SIZE -1 ) = 0x0000000000000fff ~((UINT64)(PAGE_SIZE -1 ))= 0xfffffffffffff000 RHS expression: ~(PAGE_SIZE-1) = 0xfffff000 (UINT64)(~(PAGE_SIZE - 1)) = 0x00000000fffff000 Hence ~((UINT64)(PAGE_SIZE-1))!= (UINT64)(~(PAGE_SIZE-1))
34
Miscellaneous Programming Issues Be careful when using unsigned numbers as subscripts: DWORD index = 0; CHAR *p; If (p[index – 1] == ‘0’) causes access violation on Win64! On 32-bit machines: p[index-1] == p[0xffffffff] == p[-1] On 64-bit machines: p[index-1] == p[0x00000000ffffffff] != p[-1]
35
Call To Action Develop Windows 2000 ready drivers by supporting Plug and Play and Power Management Start coding using Win64 safe programming practices now! Use the 64-bit compiler to find problem areas Make your devices address 64 bits of physical memory
36
Additional Information Read “Getting Ready for 64-bit Windows” porting guide on Windows 2000 SDK Other information available at http://www.microsoft.com/windows2000 /guide/platform/strategic/64bit.asp http://www.microsoft.com/windows2000 /guide/platform/strategic/64bit.asp http://www.microsoft.com/windows2000 /guide/platform/strategic/64bit.asp
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.