윈도우 커널모드 드라이버 64 비트 포팅

58
윈윈윈 윈윈윈윈 윈윈윈윈 64 윈윈 윈윈 월월 월월월월월월월월월 2005.9 월월월 2006.1.21

Upload: darice

Post on 12-Feb-2016

110 views

Category:

Documents


0 download

DESCRIPTION

윈도우 커널모드 드라이버 64 비트 포팅. 월간 마이크로소프트웨어 2005.9 김성현 2006.1.21. 목차. 64 비트 세상 제품 포팅 계획 64 비트 CPU 64 비트 드라이버 빌드 DDK 예제 포팅 포팅 문제 해결. 64 비트 세상. INTEL P4 프레스캇 630 – 3GHz System Bus : 800MHz L1 Cache : 16KB L2 Cache : 2MB 64Bit 지원 ( EM64T ) 하이퍼스레딩 기술 지원. 64 비트 드라이버 포팅 ! Why?. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 윈도우 커널모드 드라이버  64 비트 포팅

윈도우 커널모드 드라이버 64 비트 포팅

월간 마이크로소프트웨어 2005.9

김성현2006.1.21

Page 2: 윈도우 커널모드 드라이버  64 비트 포팅

목차 64 비트 세상 제품 포팅 계획 64 비트 CPU 64 비트 드라이버 빌드 DDK 예제 포팅 포팅 문제 해결

Page 3: 윈도우 커널모드 드라이버  64 비트 포팅

64 비트 세상 INTEL P4 프레스캇 630 – 3GHz

System Bus : 800MHz L1 Cache : 16KB L2 Cache : 2MB 64Bit 지원 ( EM64T ) 하이퍼스레딩 기술 지원

Page 4: 윈도우 커널모드 드라이버  64 비트 포팅

64 비트 드라이버 포팅 ! Why? 64 비트 윈도우 정책

32 비트 APP 지원 , 32 비트 Driver 지원안함 WOW64

32 비트 APP 에뮬레이션 레이어 32 비트 APP 바이너리 그대로 수행 32 비트 Driver 동작 못함

64 비트 드라이버 바이너리 필요 !!! 32 비트 , 64 비트 One Source, Two Binary

Page 5: 윈도우 커널모드 드라이버  64 비트 포팅

64-bit ntdll.dll64-bit ntdll.dll

WoW64.dllWoW64.dll WoW64win.dllWoW64win.dll

WoW64cpu.dllWoW64cpu.dll

Win32k.sysWin32k.sys

NT ExecutiveNT Executive

Kernel ModeKernel Mode

User ModeUser Mode

32-bit ntdll.dll32-bit ntdll.dll

32-bit modules32-bit modules

Reserved Address SpaceReserved Address Space0x00000000`7FFEFFFF or 0x00000000`7FFEFFFF or 0x00000000`FFFEFFFF0x00000000`FFFEFFFF

Page 6: 윈도우 커널모드 드라이버  64 비트 포팅

제품 포팅 계획

32 비트 APP

64 비트 Driver

64 비트 APP

64 비트 Driver

방법 1( 제약사항있

음 )

방법 2

유저모드커널모드

Page 7: 윈도우 커널모드 드라이버  64 비트 포팅

FileSystem Redirection 32 비트 프로세스로 제품설치시 주의 32 비트 APP 접근시 WOW64 에서 처리

C:\Program Files => C:\Program Files(x86) C:\windows\system32 => C:\windows\sys

wow64 Wow64DisableWow64FsRedirection() AP

I 로 제어가능

Page 8: 윈도우 커널모드 드라이버  64 비트 포팅

Registry Redirection 32 비트 APP 접근시 WOW64 에서 처리

HKLM\Software => HKLM\Software\Wow6432Node

HKCR => HKCR\Wow6432Node RegOpenKeyEx(), RegCreateKeyEx()

KEY_WOW64_64KEY: 64bit Registry 접근 KEY_WOW64_32KEY: 32bit Registry 접근

Page 9: 윈도우 커널모드 드라이버  64 비트 포팅

64 비트 CPU 종류 AMD64 ( AMD )

32 비트 호환 Athlon64, Opteron

IA64 ( INTEL ) 진보적인 아키텍쳐 (RISC 기반 , 32 비트 호환 ?) Itanium, Itanium2

EM64T ( INTEL ) AMD64 Clone? 개발시 AMD64 로 취급 ZEON EM64T, Pentium4 with EM64T

Q) Dual P4 Hiper Threading EM64T

Page 10: 윈도우 커널모드 드라이버  64 비트 포팅

CPU 별 바이너리 종류 지원대상 CPU 생성할바이너리종류

AMD Opteron AMD64 바이너리AMD Athlon64 AMD64 바이너리Intel Xeon EM64T AMD64 바이너리Intel Pentium 4 with EM64T AMD64 바이너리Intel Itanium processors

(including the Itanium2) IA64 바이너리

Page 11: 윈도우 커널모드 드라이버  64 비트 포팅

64 비트 드라이버 빌드 DDK 64 비트 빌드환경을 제공하는 DDK Windows Server 2003 SP1 DDK

http://www.microsoft.com/whdc/devtools/ddk/default.mspx CD 신청

http://www.microsoft.com/whdc/driver/wdf/KMDF_pkg.mspx Download 가능

Thanks OSR!!!

Page 12: 윈도우 커널모드 드라이버  64 비트 포팅

64 비트 드라이버 빌드 32 비트 드라이버

NT4 빌드 ? 2K 빌드 ? XP 빌드 ? 64 비트 드라이버

2K3 빌드 ! ( XP x64 Edition 커널 )

Page 13: 윈도우 커널모드 드라이버  64 비트 포팅

64 비트 드라이버 빌드

DDK 빌드 종류 용도Windows Server 2003 Checked

IA-64 Bit Build EnvironmentIA64 용

디버그버전 빌드Windows Server 2003 Free IA-

64 Bit Build EnvironmentIA64 용

릴리즈버전 빌드Windows Server 2003 Checked

x64 Build EnvironmentAMD64, EM64T

디버그버전 빌드Windows Server 2003 Free x64

Build EnvironmentAMD64, EM64T

릴리즈버전 빌드

IA64 define : _M_IA64, __IA64__ ; x64 define : _M_AMD64, __AMD64__

Page 14: 윈도우 커널모드 드라이버  64 비트 포팅

64 비트 Windows Windows XP x64 Edition Windows XP 64bit Edition Windows Server 2003 x64 Edition Windows Server 2003 for Itanium

based system

Page 15: 윈도우 커널모드 드라이버  64 비트 포팅

인라인 어셈블리 OH NO!!! X86 instruction AMD64 instruction IA64 instruction 64 비트 컴파일러는 인라인 어셈블리

미지원 원칙 : 1 C-Source Code, 3 Binary

Page 16: 윈도우 커널모드 드라이버  64 비트 포팅

AMD64 Instruction mov [rbp-0x80],rcx mov rdi,[rdi+0x18] movzx ecx,byte ptr [rax+rdi] sub rsp,rcx and rsp,0xfffffffffffffff0 mov rdi,rsp mov rsi,[rbp+0x100] add rsi,0x28 test byte ptr [rbp+0xf0],0x1

Page 17: 윈도우 커널모드 드라이버  64 비트 포팅

IA64 Instruction addl r2=ffffffff`ffe020b8, gp ;; ld8 r2=[r2] nop.i 0 ;;

ld8 r3=[r2], 8 ;; ld8 gp=[r2] mov b6=r3, +0

nop.m 0 nop.i 0 br.cond.sptk.few b6

Page 18: 윈도우 커널모드 드라이버  64 비트 포팅

64 비트 포팅 가이드라인 _WIN64 define ( _WIN32 ) __AMD64__, __IA64__ 포인터 사용 체크

sizeof(PULONG) != sizeof(ULONG) 포인터 연산 체크

32 비트 + 32 비트 = 64 비트 0xFFFFFFFF != -1

Page 19: 윈도우 커널모드 드라이버  64 비트 포팅

64 비트 포팅 가이드라인 ~((UINT64)(PAGE_SIZE-1)) == (UINT64)~(PAGE_SIZE-1)

PAGE_SIZE = 0x1000UL // Unsigned Long - 32 bitsPAGE_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

~((UINT64)(PAGE_SIZE-1)) != (UINT64)(~(PAGE_SIZE-1))

Page 20: 윈도우 커널모드 드라이버  64 비트 포팅

드라이버 포팅 예제 NT4 DDK 샘플

DDK\src\general\portio 64 비트 빌드환경

Windows Server 2003 Checked IA-64( 또는 x64) 실행

일반샘플처럼 빌드 생성된 Buildchk_wnet_IA64( 또는 AMD

64).err 확인

Page 21: 윈도우 커널모드 드라이버  64 비트 포팅

드라이버 포팅 예제

Page 22: 윈도우 커널모드 드라이버  64 비트 포팅

오류내용 1>sys\genport.c(223) : error C4312: 'type cast' : conversion

from 'ULONG' to 'PVOID' of greater size 1>sys\genport.c(513) : error C4311: 'type cast' : pointer

truncation from 'PVOID' to 'ULONG' 1>sys\genport.c(526) : error C4311: 'type cast' : pointer

truncation from 'PVOID' to 'ULONG' 1>sys\genport.c(526) : error C4312: 'type cast' : conversion

from 'unsigned long' to 'PUCHAR' of greater size 1>sys\genport.c(530) : error C4311: 'type cast' : pointer

truncation from 'PVOID' to 'ULONG' 1>sys\genport.c(530) : error C4312: 'type cast' : conversion

from 'unsigned long' to 'PUSHORT' of greater size 1>sys\genport.c(534) : error C4311: 'type cast' : pointer

truncation from 'PVOID' to 'ULONG'

Page 23: 윈도우 커널모드 드라이버  64 비트 포팅

포인터의 타입캐스팅 데이터 타입의 크기에 대한 문제

32 비트 환경 포인터 크기 : 32 비트 32 비트 환경 ULONG 크기 : 32 비트 64 비트 환경 포인터 크기 : 64 비트 64 비트 환경 ULONG 크기 : 32 비트

포인터와 ULONG 을 구분하지 않고 작성된 코드에 대한 문제

Page 24: 윈도우 커널모드 드라이버  64 비트 포팅

포인터의 타입캐스팅 1>sys\genport.c(513) : error C4311: 'type cast' : pointer t

runcation from 'PVOID' to 'ULONG‘

511 : if (nPort >= pLDI->PortCount || 512 : (nPort + DataBufferSize) > pLDI->PortCount || 513 : (((ULONG)pLDI->PortBase + nPort) & (DataBufferSize - 1)) != 0)

pLDI->PortBase 는 PVOID, nPort 는 ULONG 타입캐스팅이 에러 ?

Page 25: 윈도우 커널모드 드라이버  64 비트 포팅

포인터의 타입캐스팅 해결방법 1

513 : (((ULONG_PTR)pLDI->PortBase + nPort) & (DataBufferSize - 1)) != 0)

ULONG_PTR ULONG 형 포인터 ? X 32 비트 빌드시 : 32 비트 크기의 정수형 64 비트 빌드시 : 64 비트 크기의 정수형

Page 26: 윈도우 커널모드 드라이버  64 비트 포팅

포인터의 타입캐스팅 해결방법 2

513 : ((PtrToUlong(pLDI->PortBase) + nPort) & (DataBufferSize - 1)) != 0)

PtrToUlong() 매크로 #define PtrToUlong( p ) ((ULONG)

(ULONG_PTR) (p) )

주의 ) pLDI->PortBase 가 32 비트로 잘림

Page 27: 윈도우 커널모드 드라이버  64 비트 포팅

포인터의 타입캐스팅 1>sys\genport.c(526) : error C4311: 'type cast' : pointer truncation fro

m 'PVOID' to 'ULONG' 1>sys\genport.c(526) : error C4312: 'type cast' : conversion from 'unsi

gned long' to 'PUCHAR' of greater size

524 : case IOCTL_GPD_READ_PORT_UCHAR: 525: *(PUCHAR)pIOBuffer = READ_PORT_UCHAR( 526: (PUCHAR)((ULONG)pLDI->PortBase + nPort) ); 527: break;

한줄에 2 가지 오류

Page 28: 윈도우 커널모드 드라이버  64 비트 포팅

포인터의 타입캐스팅 방법 1

(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort)); 방법 2

(PUCHAR)PtrToUlong(pLDI->PortBase) + nPort); 방법 2+

(PUCHAR)UlongToPtr(PtrToUlong(pLDI->PortBase) + nPort));

신중히 결정할 것 주의 ) 반복되는 오류처리

Page 29: 윈도우 커널모드 드라이버  64 비트 포팅

타입캐스팅을 넘어서 1>sys\genport.c(223) : error C4312: 'type cast' : conve

rsion from 'ULONG' to 'PVOID' of greater size

223 : pLocalInfo->PortBase = (PVOID)MappedAddress.LowPart;

MappedAddress.LowPart 는 ULONG 타입캐스팅으로 해결 ? 아니면 ?

Page 30: 윈도우 커널모드 드라이버  64 비트 포팅

타입캐스팅을 넘어서 해결방법 1

223 : pLocalInfo->PortBase = UlongToPtr( MappedAddress.LowPart );

해결방법 2 223 : pLocalInfo->PortBase = (PVOID)(ULONG_PT

R)MappedAddress.LowPart;

Page 31: 윈도우 커널모드 드라이버  64 비트 포팅

타입캐스팅을 넘어서 해결방법 3

데이터구조를 생각하자 LowPart? HighPart?

MappedAddress 의 타입 PHYSICAL_ADDRESS MappedAddress; typedef LARGE_INTEGER PHYSICAL_ADDRE

SS, *PPHYSICAL_ADDRESS;

Page 32: 윈도우 커널모드 드라이버  64 비트 포팅

타입캐스팅을 넘어서 typedef union _LARGE_INTEGER { struct { ULONG LowPart; LONG HighPart; }; struct { ULONG LowPart; LONG HighPart; } u; LONGLONG QuadPart; // 64 비트 !!! } LARGE_INTEGER;

Page 33: 윈도우 커널모드 드라이버  64 비트 포팅

타입캐스팅을 넘어서 해결방법 3

223 : pLocalInfo->PortBase = (PVOID)MappedAddress.QuadPart;

198: HalTranslateBusAddress( Isa, 199: 0, 200: PortAddress, 201: &MemType, 202: &MappedAddress );

Page 34: 윈도우 커널모드 드라이버  64 비트 포팅

응용 프로그램과 드라이버가 공유하는 구조체 기존 32 비트 응용프로그램이 사용하던 구조체를 새로 작성되는 64 비트 드라이버에 전달해야 할 때 32 비트 환경과 64 비트 환경에서 데이터 크기가 달라지는 타입에 대한 문제

Page 35: 윈도우 커널모드 드라이버  64 비트 포팅

응용 프로그램과 드라이버가 공유하는 구조체 응용 프로그램 코드 예제

GENPORT_WRITE_INPUT InputBuffer sscanf(argv[2],"%x",&InputBuffer.PortNumber); InputBuffer.LongData = (ULONG)DataValue;

드라이버 코드 예제 GENPORT_WRITE_INPUT *pInputBuffer nPortNum = pInputBuffer->PortNumber; nLongData = pInputBuffer->LongData;

Page 36: 윈도우 커널모드 드라이버  64 비트 포팅

응용 프로그램과 드라이버가 공유하는 구조체 Gpioctl.h

typedef struct _GENPORT_WRITE_INPUT { ULONG PortNumber; // Port # to write to union { // Data to be output to port ULONG LongData; USHORT ShortData; UCHAR CharData; }; } GENPORT_WRITE_INPUT;

Page 37: 윈도우 커널모드 드라이버  64 비트 포팅

응용 프로그램과 드라이버가 공유하는 구조체 32 비트 APP + 64 비트 DRV

64 비트 genport.sys

32 비트 gpdwrite.exe

GENPORT_WRITE_INPUT

(ULONG 4 바이트 , union 4 바이트 )

GENPORT_WRITE_INPUT

(ULONG 4 바이트 , union 4 바이트 )

Page 38: 윈도우 커널모드 드라이버  64 비트 포팅

공유 구조체 문제 32 비트 , 64 비트에서 크기가 다른 데이터가

존재하는 경우

typedef struct _GENPORT_WRITE_INPUT { PVOID PortNumber; union { ULONG LongData; USHORT ShortData; UCHAR CharData; }; } GENPORT_WRITE_INPUT;

Page 39: 윈도우 커널모드 드라이버  64 비트 포팅

공유 구조체 문제 32 비트 APP + 64 비트 DRV

64 비트 genport.sys

32 비트 gpdwrite.exe

GENPORT_WRITE_INPUT

(PVOID 4 바이트 , union 4 바이트 )

GENPORT_WRITE_INPUT

(PVOID 8 바이트 , union 4 바이트 )

Page 40: 윈도우 커널모드 드라이버  64 비트 포팅

공유 구조체 문제 해결 64 비트 드라이버가 사용하는 32 비트용

구조체 정의

typedef struct _GENPORT_WRITE_INPUT_32 { ULONG PortNumber; union { ULONG LongData; USHORT ShortData; UCHAR CharData; }; } GENPORT_WRITE_INPUT;

Page 41: 윈도우 커널모드 드라이버  64 비트 포팅

공유 구조체 문제 해결 32 비트 APP + 64 비트 DRV

64 비트 genport.sys

32 비트 gpdwrite.exe

GENPORT_WRITE_INPUT

(PVOID 4 바이트 , union 4 바이트 )

GENPORT_WRITE_INPUT_32

(ULONG 4 바이트 , union 4 바이트 )

Page 42: 윈도우 커널모드 드라이버  64 비트 포팅

IoIs32bitProcess() 시나리오

32 비트 기존 응용프로그램 사용 64 비트 드라이버 출시 후… 64 비트 응용프로그램 포팅 완료

64 비트 드라이버의 운명은 ? 32 APP, 64 APP 모두 지원 32 APP, 64 APP 구분 필요

Page 43: 윈도우 커널모드 드라이버  64 비트 포팅

IoIs32bitProcess() 64 비트 APP + 64 비트 DRV

64 비트 genport.sys

64 비트 gpdwrite.exe

GENPORT_WRITE_INPUT

(PVOID 8 바이트 , union 4 바이트 )

GENPORT_WRITE_INPUT

(PVOID 8 바이트 , union 4 바이트 )

Page 44: 윈도우 커널모드 드라이버  64 비트 포팅

IoIs32bitProcess() GENPORT_WRITE_INPUT *pInputBuffer GENPORT_WRITE_INPUT_32 *pInputBuffer32

If (IoIs32bitProcess( Irp ) == TRUE) pInputBuffer32 = (GENPORT_WRITE_INPUT_32*) pIrp->AssociatedIrp.SystemBuffer; else pInputBuffer = (GENPORT_WRITE_INPUT*) pIrp->AssociatedIrp.SystemBuffer;

switch (IoctlCode) { case IOCTL_GPD_WRITE_PORT_ULONG: If (IoIs32bitProcess( Irp ) == TRUE) { nPortNum = pInputBuffer32->PortNumber; nLongData = pInputBuffer32->LongData; } Else // 64 bit { nPortNum = pInputBuffer->PortNumber; nLongData = pInputBuffer->LongData; }

Page 45: 윈도우 커널모드 드라이버  64 비트 포팅

IoIs32bitProcess() IOCTL Code 사용하는 방법

현재

64 비트Device Type (16)

Access (2)

Custom(1)

Function (11)

Method (2)

Device Type (16)

Access (2)

Custom(1)

64-Bit (1)

Function (10)

Method (2)

Page 46: 윈도우 커널모드 드라이버  64 비트 포팅

Quiz #pragma pack(1) typedef struct _PACK1_DATA { ULONG ul1; UCHAR uc1; } PACK1_DATA; #pragma pack()

#pragma pack(8) typedef struct _PACK8_DATA { UCHAR uc8; PACK1_DATA p1d; ULONG ul8; } PACK8_DATA; #pragma pack()

Page 47: 윈도우 커널모드 드라이버  64 비트 포팅

Quiz 32 비트 환경에서 메모리 구성은 ? 1

2

3

uc8 padding ul1

uc1 ul8

uc8 padding ul8

padding

ul1

uc1

uc8 padding ul1

uc1 ul8

Page 48: 윈도우 커널모드 드라이버  64 비트 포팅

Data Misalignment 문제 IA64 에서 발생하는 문제 메모리 주소 경계에 맞지 않는 주소를 액세스할 경우 APP => 비정상종료 DRV => 블루스크린

Bug Check 0x1E: KMODE_EXCEPTION_NOT_HANDLED

Parameter 1: 0x80000002 STATUS_DATATYPE_MISALIGNMENT

Page 49: 윈도우 커널모드 드라이버  64 비트 포팅

Data Misalignment 문제 #pragma pack(1) typedef struct _GENPORT_WRITE_INPUT { BOOLEAN bTest; PVOID PortNumber; // Port # to write to union { // Data to be output to port ULONG LongData; USHORT ShortData; UCHAR CharData; }; } GENPORT_WRITE_INPUT; #pragma pack()

Page 50: 윈도우 커널모드 드라이버  64 비트 포팅

Data Misalignment 문제 1 바이트 정렬된 구조체의 메모리구조

bTest

GENPORT_WRITE_INPUT

0 1 2 3 4 5 6 7 8 9 10 11 12

PortNumber LongData

Page 51: 윈도우 커널모드 드라이버  64 비트 포팅

Data Misalignment 문제 해결 1. 예외 핸들링 2. 구조체를 정렬된 형태로 수정 3. 컴파일러에게 도움 요청

Page 52: 윈도우 커널모드 드라이버  64 비트 포팅

Data Misalignment 문제 해결 구조체 선언시 #pragma pack(1) 제거 8 바이트 정렬된 구조체의 메모리구조

bTest

GENPORT_WRITE_INPUT

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

PortNumber LongDataPadding

Page 53: 윈도우 커널모드 드라이버  64 비트 포팅

Data Misalignment 문제 해결 메모리 공간 절약 배치

typedef struct _GENPORT_WRITE_INPUT { PVOID PortNumber; // Port # to write to union { // Data to be output to port ULONG LongData; USHORT ShortData; UCHAR CharData; }; BOOLEAN bTest; } GENPORT_WRITE_INPUT;

Page 54: 윈도우 커널모드 드라이버  64 비트 포팅

Data Misalignment 문제 해결 8 바이트 정렬하고 bTest 를 맨뒤로…

bTest

GENPORT_WRITE_INPUT

0 1 2 3 4 5 6 7 8 9 10 11 12

PortNumber LongData

Page 55: 윈도우 커널모드 드라이버  64 비트 포팅

Data Misalignment 문제 해결 컴파일러에게 도움 요청

죽어도 #pragma pack(1) 을 써야할 경우 32 비트 응용 프로그램의 구조체를

수정하지 못할 경우 UNALIGNED 매크로

문제가 있는 코드임을 컴파일러에게 알림 1 바이트씩 읽어서 조합해 주는 코드 생성 주의 ) 성능 저하의 우려가 있음

Page 56: 윈도우 커널모드 드라이버  64 비트 포팅

Data Misalignment 문제 해결 데이터 미정렬 예외 (data misalignment

exception) 가 발생하는 코드 pInputBuffer->PortNumber = p;

데이터 미정렬 예외 (data misalignment exception) 가 발생하지 않는 코드 *(UNALIGNED PVOID) &pInputBuffer->PortNumber = p;

Page 57: 윈도우 커널모드 드라이버  64 비트 포팅

참고자료 DDK Help: 64-Bit Issues

드라이버 포팅 기본 가이드 MS 사이트 64-bit Platform

http://www.microsoft.com/whdc/system/platform/64bit/default.mspx

64 비트 개발관련 수많은 문서

Page 58: 윈도우 커널모드 드라이버  64 비트 포팅

Q & A