I said it's unclear how, not that it doesn't happen ;)
This change fixes boot on the machine mentioned in
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(a)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);
> +}
> +
>
>