[ros-dev] [ros-diffs] [tfaber] 74305: [NTOS:KE] - Gracefully handle page faults during V86 code execution. This is a bit of a hack because with our limited use of V86 code it is unclear how a page fault can even occur. ...
Thomas Faber
thomas.faber at reactos.org
Fri Apr 14 21:36:26 UTC 2017
I said it's unclear how, not that it doesn't happen ;)
This change fixes boot on the machine mentioned in
https://jira.reactos.org/browse/CORE-12993
What happens is there's a bug in the BIOS that causes a ret to an
broken address, then we execute garbage and fault on a stack address.
The stack didn't overflow so I'm not sure what caused the page to
become invalid; but the machine doesn't have a serial port and I'm at
the end of what I'm able (well, willing) to do with printf debugging.
Hence the hack. I'm always open to better suggestions :)
On 2017-04-14 18:51, Alex Ionescu wrote:
> So why implement this code path if we have nothing that hits it?
>
> Best regards,
> Alex Ionescu
>
> On Fri, Apr 14, 2017 at 4:18 AM, <tfaber at svn.reactos.org> wrote:
>
>> Author: tfaber
>> Date: Fri Apr 14 11:18:22 2017
>> New Revision: 74305
>>
>> URL: http://svn.reactos.org/svn/reactos?rev=74305&view=rev
>> Log:
>> [NTOS:KE]
>> - Gracefully handle page faults during V86 code execution. This is a bit
>> of a hack because with our limited use of V86 code it is unclear how a page
>> fault can even occur.
>> CORE-12993 #resolve
>>
>> Modified:
>> trunk/reactos/ntoskrnl/include/internal/i386/ke.h
>> trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
>> trunk/reactos/ntoskrnl/vdm/vdmexec.c
>>
>> Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
>> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/
>> ntoskrnl/include/internal/i386/ke.h?rev=74305&r1=74304&r2=74305&view=diff
>> ============================================================
>> ==================
>> --- trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1]
>> (original)
>> +++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] Fri
>> Apr 14 11:18:22 2017
>> @@ -478,6 +478,12 @@
>> NTAPI
>> VdmDispatchBop(
>> IN PKTRAP_FRAME TrapFrame
>> +);
>> +
>> +BOOLEAN
>> +NTAPI
>> +VdmDispatchPageFault(
>> + _In_ PKTRAP_FRAME TrapFrame
>> );
>>
>> BOOLEAN
>>
>> Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
>> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/
>> ntoskrnl/ke/i386/traphdlr.c?rev=74305&r1=74304&r2=74305&view=diff
>> ============================================================
>> ==================
>> --- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
>> +++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Fri Apr 14
>> 11:18:22 2017
>> @@ -1304,8 +1304,20 @@
>> UNIMPLEMENTED_FATAL();
>> }
>> #endif
>> +
>> /* Check for VDM trap */
>> - ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
>> + if (KiVdmTrap(TrapFrame))
>> + {
>> + DPRINT1("VDM PAGE FAULT at %lx:%lx for address %lx\n",
>> + TrapFrame->SegCs, TrapFrame->Eip, Cr2);
>> + if (VdmDispatchPageFault(TrapFrame))
>> + {
>> + /* Return and end VDM execution */
>> + DPRINT1("VDM page fault with status 0x%lx resolved\n",
>> Status);
>> + KiEoiHelper(TrapFrame);
>> + }
>> + DPRINT1("VDM page fault with status 0x%lx NOT resolved\n",
>> Status);
>> + }
>>
>> /* Either kernel or user trap (non VDM) so dispatch exception */
>> if (Status == STATUS_ACCESS_VIOLATION)
>>
>> Modified: trunk/reactos/ntoskrnl/vdm/vdmexec.c
>> URL: http://svn.reactos.org/svn/reactos/trunk/reactos/
>> ntoskrnl/vdm/vdmexec.c?rev=74305&r1=74304&r2=74305&view=diff
>> ============================================================
>> ==================
>> --- trunk/reactos/ntoskrnl/vdm/vdmexec.c [iso-8859-1] (original)
>> +++ trunk/reactos/ntoskrnl/vdm/vdmexec.c [iso-8859-1] Fri Apr 14
>> 11:18:22 2017
>> @@ -239,7 +239,7 @@
>> KeLowerIrql(OldIrql);
>> return STATUS_INVALID_SYSTEM_SERVICE;
>> }
>> -
>> +
>> /* Now do the VDM Swap */
>> VdmSwapContext(VdmFrame, &VdmTib->MonitorContext, &VdmContext);
>>
>> @@ -269,7 +269,7 @@
>>
>> /* Make a copy of the monitor context */
>> Context = VdmTib->MonitorContext;
>> -
>> +
>> /* Check if V86 mode was enabled or the trap was edited */
>> if ((Context.EFlags & EFLAGS_V86_MASK) || (Context.SegCs &
>> FRAME_EDITED))
>> {
>> @@ -291,7 +291,7 @@
>> /* Remove real IF flag */
>> VdmTib->VdmContext.EFlags &= ~EFLAGS_INTERRUPT_MASK;
>> }
>> -
>> +
>> /* Turn off VIP and VIF */
>> TrapFrame->EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
>> VdmTib->VdmContext.EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
>> @@ -362,4 +362,45 @@
>> return TRUE;
>> }
>>
>> -
>> +BOOLEAN
>> +NTAPI
>> +VdmDispatchPageFault(
>> + _In_ PKTRAP_FRAME TrapFrame)
>> +{
>> + NTSTATUS Status;
>> + PVDM_TIB VdmTib;
>> +
>> + PAGED_CODE();
>> +
>> + /* Get the VDM TIB so we can terminate V86 execution */
>> + Status = VdmpGetVdmTib(&VdmTib);
>> + if (!NT_SUCCESS(Status))
>> + {
>> + /* Not a proper VDM fault, keep looking */
>> + DPRINT1("VdmDispatchPageFault: no VDM TIB, Vdm=%p\n",
>> NtCurrentTeb()->Vdm);
>> + return FALSE;
>> + }
>> +
>> + /* Must be coming from V86 code */
>> + ASSERT(TrapFrame->EFlags & EFLAGS_V86_MASK);
>> +
>> + _SEH2_TRY
>> + {
>> + /* Fill out a VDM Event */
>> + VdmTib->EventInfo.Event = VdmMemAccess;
>> + VdmTib->EventInfo.InstructionSize = 0;
>> +
>> + /* End VDM Execution */
>> + VdmEndExecution(TrapFrame, VdmTib);
>> + }
>> + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
>> + {
>> + Status = _SEH2_GetExceptionCode();
>> + }
>> + _SEH2_END;
>> +
>> + /* Consider the exception handled if we succeeded */
>> + DPRINT1("VdmDispatchPageFault EFlags %lx exit with 0x%lx\n",
>> TrapFrame->EFlags, Status);
>> + return NT_SUCCESS(Status);
>> +}
>> +
>>
>>
More information about the Ros-dev
mailing list