From f5cb09e9a43746a7e71b15608e5a499d851eceb3 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Mon, 10 Nov 2014 22:01:27 +0100 Subject: [PATCH] ntoskrnl-Emulator: Add additional patch to emulate access to KI_USER_SHARED_DATA kernel page on x86_64. --- README.md | 3 +- debian/changelog | 1 + patches/Makefile | 9 +- ...-mov-Eb-Gb-instruction-on-x86-proces.patch | 25 +- ...-memory-access-to-KI_USER_SHARED_DAT.patch | 319 ++++++++++++++++++ ...CEs-for-instruction-emulator-on-x86_.patch | 46 +++ patches/ntoskrnl-Emulator/definition | 5 + 7 files changed, 394 insertions(+), 14 deletions(-) create mode 100644 patches/ntoskrnl-Emulator/0002-ntoskrnl-Emulate-memory-access-to-KI_USER_SHARED_DAT.patch create mode 100644 patches/ntoskrnl-Emulator/0003-ntoskrnl-Add-TRACEs-for-instruction-emulator-on-x86_.patch diff --git a/README.md b/README.md index df1c21b4..454e8d90 100644 --- a/README.md +++ b/README.md @@ -39,13 +39,14 @@ Wine. All those differences are also documented on the Included bug fixes and improvements =================================== -**Bugfixes and features included in the next upcoming release [14]:** +**Bugfixes and features included in the next upcoming release [15]:** * Add stub for NtSetLdtEntries/ZwSetLdtEntries ([Wine Bug #26268](https://bugs.winehq.org/show_bug.cgi?id=26268)) * Add stubs for vectored continue handler ([Wine Bug #30572](https://bugs.winehq.org/show_bug.cgi?id=30572)) * Allow NULL pointer for optional arguments of D3DXIntersectTri ([Wine Bug #35133](https://bugs.winehq.org/show_bug.cgi?id=35133)) * Allow selection of audio device for PulseAudio backend * CoWaitForMultipleHandles shouldn't process window events when APC calls are queued ([Wine Bug #32568](https://bugs.winehq.org/show_bug.cgi?id=32568)) +* Emulate access to KI_USER_SHARED_DATA kernel page on x86_64 ([Wine Bug #33849](https://bugs.winehq.org/show_bug.cgi?id=33849)) * Exception during start of fr-043 caused by missing DXTn support ([Wine Bug #37391](https://bugs.winehq.org/show_bug.cgi?id=37391)) * FairplayKD.sys needs KeSetSystemAffinityThread ([Wine Bug #36822](https://bugs.winehq.org/show_bug.cgi?id=36822)) * Fix crash of Trine Demo on start ([Wine Bug #19231](https://bugs.winehq.org/show_bug.cgi?id=19231)) diff --git a/debian/changelog b/debian/changelog index a319d9db..f60ccea4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,7 @@ wine-compholio (1.7.31) UNRELEASED; urgency=low * Added patch to allow NULL pointer for optional arguments of D3DXIntersectTri. * Added patch to fix crash of winedevice when relocation entry crosses page boundary. * Added patch to emulate 'mov Eb, Gb' instruction on x86 processor architecture. + * Added patch to emulate access to KI_USER_SHARED_DATA kernel page on x86_64. * Removed patch for iphlpapi stub functions (accepted upstream). * Removed patches for FindFirstFileExW (accepted upstream). * Removed patches for TLB dependencies lookup in resources (accepted upstream). diff --git a/patches/Makefile b/patches/Makefile index 0996e1bc..2ffaca4d 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -1121,15 +1121,22 @@ ntdll-WRITECOPY.ok: # | # | Included patches: # | * Emulate 'mov Eb, Gb' instruction on x86 processor architecture. [by Sebastian Lackner] +# | * Emulate access to KI_USER_SHARED_DATA kernel page on x86_64. [by Sebastian Lackner] +# | +# | This patchset fixes the following Wine bugs: +# | * [#33849] Emulate access to KI_USER_SHARED_DATA kernel page on x86_64 # | # | Modified files: -# | * dlls/ntoskrnl.exe/instr.c +# | * dlls/ntoskrnl.exe/instr.c, dlls/ntoskrnl.exe/ntoskrnl.c # | .INTERMEDIATE: ntoskrnl-Emulator.ok ntoskrnl-Emulator.ok: $(call APPLY_FILE,ntoskrnl-Emulator/0001-ntoskrnl-Emulate-mov-Eb-Gb-instruction-on-x86-proces.patch) + $(call APPLY_FILE,ntoskrnl-Emulator/0002-ntoskrnl-Emulate-memory-access-to-KI_USER_SHARED_DAT.patch) + $(call APPLY_FILE,ntoskrnl-Emulator/0003-ntoskrnl-Add-TRACEs-for-instruction-emulator-on-x86_.patch) @( \ echo '+ { "ntoskrnl-Emulator", "Sebastian Lackner", "Emulate '\''mov Eb, Gb'\'' instruction on x86 processor architecture." },'; \ + echo '+ { "ntoskrnl-Emulator", "Sebastian Lackner", "Emulate access to KI_USER_SHARED_DATA kernel page on x86_64." },'; \ ) > ntoskrnl-Emulator.ok # Patchset ntoskrnl-IoCsqInitialize diff --git a/patches/ntoskrnl-Emulator/0001-ntoskrnl-Emulate-mov-Eb-Gb-instruction-on-x86-proces.patch b/patches/ntoskrnl-Emulator/0001-ntoskrnl-Emulate-mov-Eb-Gb-instruction-on-x86-proces.patch index 00e308d4..0671bb08 100644 --- a/patches/ntoskrnl-Emulator/0001-ntoskrnl-Emulate-mov-Eb-Gb-instruction-on-x86-proces.patch +++ b/patches/ntoskrnl-Emulator/0001-ntoskrnl-Emulate-mov-Eb-Gb-instruction-on-x86-proces.patch @@ -1,15 +1,15 @@ -From 4fa4d95330e47ca48ea7bfc0297c782374d55a4e Mon Sep 17 00:00:00 2001 +From 332dcc33d8be2ab7cddeba6320bde968b5872246 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Mon, 10 Nov 2014 07:14:48 +0100 Subject: ntoskrnl: Emulate 'mov Eb, Gb' instruction on x86 processor architecture. --- - dlls/ntoskrnl.exe/instr.c | 30 +++++++++++++++++++++++++++--- - 1 file changed, 27 insertions(+), 3 deletions(-) + dlls/ntoskrnl.exe/instr.c | 33 ++++++++++++++++++++++++++++----- + 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c -index fe35686..38492f0 100644 +index fe35686..05cd238 100644 --- a/dlls/ntoskrnl.exe/instr.c +++ b/dlls/ntoskrnl.exe/instr.c @@ -59,7 +59,7 @@ static inline struct idtr get_idtr(void) @@ -44,21 +44,23 @@ index fe35686..38492f0 100644 /*********************************************************************** * INSTR_GetOperandAddr * -@@ -399,19 +415,27 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) +@@ -399,19 +415,26 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) } break; /* Unable to emulate it */ + case 0x8a: /* mov Eb, Gb */ case 0x8b: /* mov Ev, Gv */ { - BYTE *addr = INSTR_GetOperandAddr(context, instr + 1, long_addr, +- BYTE *addr = INSTR_GetOperandAddr(context, instr + 1, long_addr, ++ BYTE *data = INSTR_GetOperandAddr(context, instr + 1, long_addr, segprefix, &len); ++ unsigned int data_size = (*instr == 0x8b) ? (long_op ? 4 : 2) : 1; struct idtr idtr = get_idtr(); - unsigned int offset = addr - idtr.base; -+ unsigned int size = (*instr == 0x8b) ? (long_op ? 4 : 2) : 1; +- unsigned int offset = addr - idtr.base; ++ unsigned int offset = data - idtr.base; - if (offset <= idtr.limit + 1 - (long_op ? 4 : 2)) -+ if (offset <= idtr.limit + 1 - size) ++ if (offset <= idtr.limit + 1 - data_size) { idt[1].LimitLow = 0x100; /* FIXME */ idt[2].LimitLow = 0x11E; /* FIXME */ @@ -67,10 +69,9 @@ index fe35686..38492f0 100644 + + switch (*instr) + { -+ case 0x8a: store_reg_byte( context, instr[1], (BYTE *)idt + offset ); break; -+ case 0x8b: store_reg_word( context, instr[1], (BYTE *)idt + offset, long_op ); break; ++ case 0x8a: store_reg_byte( context, instr[1], (BYTE *)idt + offset ); break; ++ case 0x8b: store_reg_word( context, instr[1], (BYTE *)idt + offset, long_op ); break; + } -+ context->Eip += prefixlen + len + 1; return ExceptionContinueExecution; } diff --git a/patches/ntoskrnl-Emulator/0002-ntoskrnl-Emulate-memory-access-to-KI_USER_SHARED_DAT.patch b/patches/ntoskrnl-Emulator/0002-ntoskrnl-Emulate-memory-access-to-KI_USER_SHARED_DAT.patch new file mode 100644 index 00000000..b3b9f818 --- /dev/null +++ b/patches/ntoskrnl-Emulator/0002-ntoskrnl-Emulate-memory-access-to-KI_USER_SHARED_DAT.patch @@ -0,0 +1,319 @@ +From 9cdc9686cbdd77bfbed039f4811570c955ac26b3 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 10 Nov 2014 21:27:39 +0100 +Subject: ntoskrnl: Emulate memory access to KI_USER_SHARED_DATA on x86_64. + +--- + dlls/ntoskrnl.exe/instr.c | 277 ++++++++++++++++++++++++++++++++++++++++++- + dlls/ntoskrnl.exe/ntoskrnl.c | 2 +- + 2 files changed, 277 insertions(+), 2 deletions(-) + +diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c +index 05cd238..51b7bec 100644 +--- a/dlls/ntoskrnl.exe/instr.c ++++ b/dlls/ntoskrnl.exe/instr.c +@@ -4,6 +4,7 @@ + * Copyright 1995 Alexandre Julliard + * Copyright 2005 Ivan Leo Puoti + * Copyright 2005 Laurent Pinchart ++ * Copyright 2014 Sebastian Lackner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -470,4 +471,278 @@ LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs ) + return EXCEPTION_CONTINUE_SEARCH; + } + +-#endif /* __i386__ */ ++#elif defined(__x86_64__) /* __i386__ */ ++ ++#include ++ ++#include "windef.h" ++#include "winbase.h" ++#include "winternl.h" ++#include "excpt.h" ++#include "wine/debug.h" ++#include "wine/exception.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(int); ++ ++#define REX_B 1 ++#define REX_X 2 ++#define REX_R 4 ++#define REX_W 8 ++ ++#define REGMODRM_MOD(regmodrm, rex) ((regmodrm) >> 6) ++#define REGMODRM_REG(regmodrm, rex) (((regmodrm) >> 3) & 7) | (((rex) & REX_R) ? 8 : 0) ++#define REGMODRM_RM(regmodrm, rex) (((regmodrm) & 7) | (((rex) & REX_B) ? 8 : 0)) ++ ++#define SIB_SS(sib, rex) ((sib) >> 6) ++#define SIB_INDEX(sib, rex) (((sib) >> 3) & 7) | (((rex) & REX_R) ? 8 : 0) ++#define SIB_BASE(sib, rex) (((sib) & 7) | (((rex) & REX_B) ? 8 : 0)) ++ ++#define KI_USER_SHARED_DATA 0xfffff78000000000 ++static BYTE user_shared_data[0x1000]; ++ ++static inline DWORD64 *get_int_reg( CONTEXT *context, int index ) ++{ ++ return &context->Rax + index; /* index should be in range 0 .. 15 */ ++} ++ ++static inline int get_op_size( int long_op, int rex ) ++{ ++ if (rex & REX_W) ++ return sizeof(DWORD64); ++ else if (long_op) ++ return sizeof(DWORD); ++ else ++ return sizeof(WORD); ++} ++ ++/* store an operand into a register */ ++static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op, int rex ) ++{ ++ int index = REGMODRM_REG(regmodrm, rex); ++ BYTE *reg = (BYTE *)get_int_reg( context, index ); ++ memcpy( reg, addr, get_op_size( long_op, rex ) ); ++} ++ ++/* store an operand into a byte register */ ++static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int rex ) ++{ ++ int index = REGMODRM_REG(regmodrm, rex); ++ BYTE *reg = (BYTE *)get_int_reg( context, index ); ++ if (!rex && index >= 4 && index < 8) reg -= (4 * sizeof(DWORD64) - 1); /* special case: ah, ch, dh, bh */ ++ *reg = *addr; ++} ++ ++/*********************************************************************** ++ * INSTR_GetOperandAddr ++ * ++ * Return the address of an instruction operand (from the mod/rm byte). ++ */ ++static BYTE *INSTR_GetOperandAddr( CONTEXT *context, BYTE *instr, ++ int long_addr, int rex, int segprefix, int *len ) ++{ ++ int mod, rm, ss = 0, off, have_sib = 0; ++ DWORD64 base = 0, index = 0; ++ ++#define GET_VAL(val,type) \ ++ { *val = *(type *)instr; instr += sizeof(type); *len += sizeof(type); } ++ ++ *len = 0; ++ GET_VAL( &mod, BYTE ); ++ rm = REGMODRM_RM(mod, rex); ++ mod = REGMODRM_MOD(mod, rex); ++ ++ if (mod == 3) ++ return (BYTE *)get_int_reg( context, rm ); ++ ++ if ((rm & 7) == 4) ++ { ++ BYTE sib; ++ int id; ++ ++ GET_VAL( &sib, BYTE ); ++ rm = SIB_BASE(sib, rex); ++ id = SIB_INDEX(sib, rex); ++ ss = SIB_SS(sib, rex); ++ ++ index = (id != 4) ? *get_int_reg( context, id ) : 0; ++ if (!long_addr) index &= 0xffffffff; ++ have_sib = 1; ++ } ++ ++ base = *get_int_reg( context, rm ); ++ if (!long_addr) base &= 0xffffffff; ++ ++ switch (mod) ++ { ++ case 0: ++ if (rm == 5) /* special case */ ++ { ++ base = have_sib ? 0 : context->Rip; ++ if (!long_addr) base &= 0xffffffff; ++ GET_VAL( &off, DWORD ); ++ base += (signed long)off; ++ } ++ break; ++ ++ case 1: /* 8-bit disp */ ++ GET_VAL( &off, BYTE ); ++ base += (signed char)off; ++ break; ++ ++ case 2: /* 32-bit disp */ ++ GET_VAL( &off, DWORD ); ++ base += (signed long)off; ++ break; ++ } ++ ++ /* FIXME: we assume that all segments have a base of 0 */ ++ return (BYTE *)(base + (index << ss)); ++#undef GET_VAL ++} ++ ++/* update the content of the user shared data page */ ++static void update_user_shared_data(void) ++{ ++ FIXME("TODO: update user shared data\n"); ++} ++ ++ ++/*********************************************************************** ++ * emulate_instruction ++ * ++ * Emulate a privileged instruction. ++ * Returns exception continuation status. ++ */ ++static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) ++{ ++ int prefix, segprefix, prefixlen, len, long_op, long_addr, rex; ++ BYTE *instr; ++ ++ long_op = long_addr = 1; ++ instr = (BYTE *)context->Rip; ++ if (!instr) return ExceptionContinueSearch; ++ ++ /* First handle any possible prefix */ ++ ++ segprefix = -1; /* no seg prefix */ ++ rex = 0; /* no rex prefix */ ++ prefix = 1; ++ prefixlen = 0; ++ while(prefix) ++ { ++ switch(*instr) ++ { ++ case 0x2e: ++ segprefix = context->SegCs; ++ break; ++ case 0x36: ++ segprefix = context->SegSs; ++ break; ++ case 0x3e: ++ segprefix = context->SegDs; ++ break; ++ case 0x26: ++ segprefix = context->SegEs; ++ break; ++ case 0x64: ++ segprefix = context->SegFs; ++ break; ++ case 0x65: ++ segprefix = context->SegGs; ++ break; ++ case 0x66: ++ long_op = !long_op; /* opcode size prefix */ ++ break; ++ case 0x67: ++ long_addr = !long_addr; /* addr size prefix */ ++ break; ++ case 0xf0: /* lock */ ++ break; ++ case 0xf2: /* repne */ ++ break; ++ case 0xf3: /* repe */ ++ break; ++ default: ++ prefix = 0; /* no more prefixes */ ++ break; ++ } ++ if (*instr >= 0x40 && *instr < 0x50) /* rex */ ++ { ++ rex = *instr; ++ prefix = TRUE; ++ } ++ if (prefix) ++ { ++ instr++; ++ prefixlen++; ++ } ++ } ++ ++ /* Now look at the actual instruction */ ++ ++ switch(*instr) ++ { ++ case 0x8a: /* mov Eb, Gb */ ++ case 0x8b: /* mov Ev, Gv */ ++ { ++ BYTE *data = INSTR_GetOperandAddr( context, instr + 1, long_addr, ++ rex, segprefix, &len ); ++ unsigned int data_size = (*instr == 0x8b) ? get_op_size( long_op, rex ) : 1; ++ unsigned int offset = data - (BYTE *)KI_USER_SHARED_DATA; ++ ++ if (offset <= sizeof(user_shared_data) - data_size) ++ { ++ update_user_shared_data(); ++ switch (*instr) ++ { ++ case 0x8a: store_reg_byte( context, instr[1], user_shared_data + offset, rex ); break; ++ case 0x8b: store_reg_word( context, instr[1], user_shared_data + offset, long_op, rex ); break; ++ } ++ context->Rip += prefixlen + len + 1; ++ return ExceptionContinueExecution; ++ } ++ break; /* Unable to emulate it */ ++ } ++ ++ case 0xa0: /* mov Ob, AL */ ++ case 0xa1: /* mov Ovqp, rAX */ ++ { ++ BYTE *data = (BYTE *)(long_addr ? *(DWORD64 *)(instr + 1) : *(DWORD *)(instr + 1)); ++ unsigned int data_size = (*instr == 0xa1) ? get_op_size( long_op, rex ) : 1; ++ unsigned int offset = data - (BYTE *)KI_USER_SHARED_DATA; ++ len = long_addr ? sizeof(DWORD64) : sizeof(DWORD); ++ ++ if (offset <= sizeof(user_shared_data) - data_size) ++ { ++ update_user_shared_data(); ++ memcpy( &context->Rax, user_shared_data + offset, data_size ); ++ context->Rip += prefixlen + len + 1; ++ return ExceptionContinueExecution; ++ } ++ break; /* Unable to emulate it */ ++ } ++ } ++ return ExceptionContinueSearch; /* Unable to emulate it */ ++} ++ ++ ++/*********************************************************************** ++ * vectored_handler ++ * ++ * Vectored exception handler used to emulate protected instructions ++ * from 64-bit code. ++ */ ++LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs ) ++{ ++ EXCEPTION_RECORD *record = ptrs->ExceptionRecord; ++ CONTEXT *context = ptrs->ContextRecord; ++ ++ if (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) ++ { ++ if (emulate_instruction( record, context ) == ExceptionContinueExecution) ++ return EXCEPTION_CONTINUE_EXECUTION; ++ } ++ return EXCEPTION_CONTINUE_SEARCH; ++} ++ ++#endif /* __x86_64__ */ +\ No newline at end of file +diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c +index a31b186..1d87110 100644 +--- a/dlls/ntoskrnl.exe/ntoskrnl.c ++++ b/dlls/ntoskrnl.exe/ntoskrnl.c +@@ -1880,7 +1880,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls( inst ); +-#ifdef __i386__ ++#if defined(__i386__) || defined(__x86_64__) + handler = RtlAddVectoredExceptionHandler( TRUE, vectored_handler ); + #endif + KeQueryTickCount( &count ); /* initialize the global KeTickCount */ +-- +2.1.3 + diff --git a/patches/ntoskrnl-Emulator/0003-ntoskrnl-Add-TRACEs-for-instruction-emulator-on-x86_.patch b/patches/ntoskrnl-Emulator/0003-ntoskrnl-Add-TRACEs-for-instruction-emulator-on-x86_.patch new file mode 100644 index 00000000..ffc4fc77 --- /dev/null +++ b/patches/ntoskrnl-Emulator/0003-ntoskrnl-Add-TRACEs-for-instruction-emulator-on-x86_.patch @@ -0,0 +1,46 @@ +From c5d80d20b8e3ba1eb46d18cef337a1d6d1b0ed10 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 10 Nov 2014 21:42:53 +0100 +Subject: ntoskrnl: Add TRACEs for instruction emulator on x86_64 to simplify + debugging. + +--- + dlls/ntoskrnl.exe/instr.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c +index 51b7bec..16d7afd 100644 +--- a/dlls/ntoskrnl.exe/instr.c ++++ b/dlls/ntoskrnl.exe/instr.c +@@ -739,8 +739,28 @@ LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs ) + + if (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) + { ++ DWORD64 rip = context->Rip; + if (emulate_instruction( record, context ) == ExceptionContinueExecution) ++ { ++ ++ if (context->Rip - rip <= 32) ++ { ++ TRACE("emulated opcodes:"); ++ for (; rip < context->Rip; rip++) TRACE(" %02x", *(BYTE *)rip); ++ TRACE("\n"); ++ } ++ TRACE( "next instruction rip=%lx\n", context->Rip ); ++ TRACE( " rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n", ++ context->Rax, context->Rbx, context->Rcx, context->Rdx ); ++ TRACE( " rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n", ++ context->Rsi, context->Rdi, context->Rbp, context->Rsp ); ++ TRACE( " r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n", ++ context->R8, context->R9, context->R10, context->R11 ); ++ TRACE( " r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", ++ context->R12, context->R13, context->R14, context->R15 ); ++ + return EXCEPTION_CONTINUE_EXECUTION; ++ } + } + return EXCEPTION_CONTINUE_SEARCH; + } +-- +2.1.3 + diff --git a/patches/ntoskrnl-Emulator/definition b/patches/ntoskrnl-Emulator/definition index 0b62c028..358f7303 100644 --- a/patches/ntoskrnl-Emulator/definition +++ b/patches/ntoskrnl-Emulator/definition @@ -1,3 +1,8 @@ Author: Sebastian Lackner Subject: Emulate 'mov Eb, Gb' instruction on x86 processor architecture. Revision: 1 + +Author: Sebastian Lackner +Subject: Emulate access to KI_USER_SHARED_DATA kernel page on x86_64. +Revision: 1 +Fixes: [33849] Emulate access to KI_USER_SHARED_DATA kernel page on x86_64