예제 #1
0
파일: bugcheck.c 프로젝트: conioh/os-design
VOID
KiBugCheckDebugBreak (
    IN ULONG    BreakStatus
    )
{
    do {
        try {

            //
            // Issue a breakpoint
            //

            DbgBreakPointWithStatus (BreakStatus);

        } except(EXCEPTION_EXECUTE_HANDLER) {

            //
            // Failure to issue breakpoint, halt the system
            //

            try {

                HalHaltSystem();

            } except(EXCEPTION_EXECUTE_HANDLER) {

                for (;;) {
                }
            }

            for (;;) {
            }
        }
    } while (BreakStatus != DBG_STATUS_BUGCHECK_FIRST);
}
예제 #2
0
/*++
Routine Description:

    Clock interrupt handler for processor 0.

Arguments:

    Interrupt

    ServiceContext

    TrapFrame

Return Value:

    TRUE

--*/
BOOLEAN
HalpHandleDecrementerInterrupt(
    IN PKINTERRUPT Interrupt,
    IN PVOID ServiceContext,
    IN PVOID TrapFrame
    )
{
	KIRQL OldIrql;
    static int recurse = FALSE;
	ULONG CpuId;
	
	HASSERT(!MSR(EE));

	CpuId = GetCpuId();

	//
	// Raise irql via updating the PCR
	//
	OldIrql = PCR->CurrentIrql;
	PCR->CurrentIrql = CLOCK2_LEVEL;
	RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]);
	WaitForRInterruptMask(CpuId);
	
	//
	// Reset DECREMENTER, accounting for interrupt latency.
	//
	HalpUpdateDecrementer(HalpClockCount);
	
	//
	// Call the kernel to update system time
	//
	KeUpdateSystemTime(TrapFrame,HalpCurrentTimeIncrement);
	HalpCurrentTimeIncrement = HalpNewTimeIncrement;
	
    if (!recurse) {
        //
        // In some circumstances the KdPollBreakIn can
        // take longer than a decrementer interrupt
        // to complete.  This is do to a conflict
        // between DMA and PIO.  For now, just avoid
        // recursing into the debugger check.
        //
        recurse = TRUE;
        if (KdDebuggerEnabled && KdPollBreakIn()) {
            HalpEnableInterrupts();
            DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
            HalpDisableInterrupts();
        }
        recurse = FALSE;
    }

	//
	// Lower Irql to original value and enable interrupts
	//
	PCR->CurrentIrql = OldIrql;
	RInterruptMask(CpuId) = (Irql2Mask[OldIrql] & registeredInts[CpuId]);
	WaitForRInterruptMask(CpuId);
	return (TRUE);
}
예제 #3
0
/*++

Routine Description:

    Clock interrupt handler for processors other than 0.

Arguments:

    Interrupt

    ServiceContext

    TrapFrame

Return Value:

    TRUE

--*/
BOOLEAN
HalpHandleDecrementerInterrupt1(
    IN PKINTERRUPT Interrupt,
    IN PVOID ServiceContext,
    IN PVOID TrapFrame
    )
{
	KIRQL OldIrql;
	ULONG CpuId;
	
	HASSERT(!MSR(EE));

	CpuId = GetCpuId();
	
	//
	// Raise irql via updating the PCR
	//
	OldIrql = PCR->CurrentIrql;
	PCR->CurrentIrql = CLOCK2_LEVEL;
	RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]);
	WaitForRInterruptMask(CpuId);
	
	//
	// Reset DECREMENTER (no account for latency)
	//
	HalpUpdateDecrementer(HalpFullTickClockCount);
	
	//
	// Call the kernel to update run time for this thread and process.
	//
	KeUpdateRunTime(TrapFrame);

	HDBG(DBG_PROC1DBG,
		{
			//
			// Check for the debugger BreakIn only every minute or so.
			// (decrementer is interms of ms so we multiple by 10,000
			// on the order of a minute).
			//
			static Count = 0;
			if (++Count > 10000) {
				Count = 0;
				if (KdDebuggerEnabled && KdPollBreakIn()) {
					HalpEnableInterrupts();
					DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
					HalpDisableInterrupts();
				}
			}
		}
	);
예제 #4
0
파일: bug.c 프로젝트: RPG-7/reactos
VOID
NTAPI
KiBugCheckDebugBreak(IN ULONG StatusCode)
{
    /*
     * Wrap this in SEH so we don't crash if
     * there is no debugger or if it disconnected
     */
DoBreak:
    _SEH2_TRY
    {
        /* Breakpoint */
        DbgBreakPointWithStatus(StatusCode);
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
        /* No debugger, halt the CPU */
        HalHaltSystem();
    }
    _SEH2_END;

    /* Break again if this wasn't first try */
    if (StatusCode != DBG_STATUS_BUGCHECK_FIRST) goto DoBreak;
}
예제 #5
0
파일: time.c 프로젝트: GYGit/reactos
VOID
FASTCALL
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
                   IN ULONG Increment,
                   IN KIRQL Irql)
{
    PKPRCB Prcb = KeGetCurrentPrcb();
    ULARGE_INTEGER CurrentTime, InterruptTime;
    LONG OldTickOffset;

    /* Check if this tick is being skipped */
    if (Prcb->SkipTick)
    {
        /* Handle it next time */
        Prcb->SkipTick = FALSE;

        /* Increase interrupt count and end the interrupt */
        Prcb->InterruptCount++;
        KiEndInterrupt(Irql, TrapFrame);

        /* Note: non-x86 return back to the caller! */
        return;
    }

    /* Add the increment time to the shared data */
    InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime;
    InterruptTime.QuadPart += Increment;
    KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime);

    /* Check for timer expiration */
    KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);

    /* Update the tick offset */
    OldTickOffset = InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment);

    /* If the debugger is enabled, check for break-in request */
    if (KdDebuggerEnabled && KdPollBreakIn())
    {
        /* Break-in requested! */
        DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
    }

    /* Check for full tick */
    if (OldTickOffset <= (LONG)Increment)
    {
        /* Update the system time */
        CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime;
        CurrentTime.QuadPart += KeTimeAdjustment;
        KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime);

        /* Update the tick count */
        CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1;
        KiWriteSystemTime(&KeTickCount, CurrentTime);

        /* Update it in the shared user data */
        KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime);

        /* Check for expiration with the new tick count as well */
        KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);

        /* Reset the tick offset */
        KiTickOffset += KeMaximumIncrement;

        /* Update processor/thread runtime */
        KeUpdateRunTime(TrapFrame, Irql);
    }
    else
    {
        /* Increase interrupt count only */
        Prcb->InterruptCount++;
    }

    /* Disable interrupts and end the interrupt */
    KiEndInterrupt(Irql, TrapFrame);
}
예제 #6
0
파일: keyboard.c 프로젝트: reactos/reactos
BOOLEAN NTAPI
i8042KbdInterruptService(
	IN PKINTERRUPT Interrupt,
	PVOID Context)
{
	PI8042_KEYBOARD_EXTENSION DeviceExtension;
	PPORT_DEVICE_EXTENSION PortDeviceExtension;
	PKEYBOARD_INPUT_DATA InputData;
	ULONG Counter;
	UCHAR PortStatus = 0, Output = 0;
	BOOLEAN ToReturn = FALSE;
	NTSTATUS Status;

	UNREFERENCED_PARAMETER(Interrupt);

	__analysis_assume(Context != NULL);
	DeviceExtension = Context;
	PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension;
	InputData = DeviceExtension->KeyboardBuffer + DeviceExtension->KeysInBuffer;
	Counter = PortDeviceExtension->Settings.PollStatusIterations;

	while (Counter)
	{
		Status = i8042ReadStatus(PortDeviceExtension, &PortStatus);
		if (!NT_SUCCESS(Status))
		{
			WARN_(I8042PRT, "i8042ReadStatus() failed with status 0x%08lx\n", Status);
			return FALSE;
		}
		Status = i8042ReadKeyboardData(PortDeviceExtension, &Output);
		if (NT_SUCCESS(Status))
			break;
		KeStallExecutionProcessor(1);
		Counter--;
	}
	if (Counter == 0)
	{
		WARN_(I8042PRT, "Spurious i8042 keyboard interrupt\n");
		return FALSE;
	}

	INFO_(I8042PRT, "Got: 0x%02x\n", Output);

	if (PortDeviceExtension->Settings.CrashOnCtrlScroll)
	{
		/* Test for CTRL + SCROLL LOCK twice */
		static const UCHAR ScanCodes[] = { 0x1d, 0x46, 0xc6, 0x46, 0 };

		if (Output == ScanCodes[DeviceExtension->ComboPosition])
		{
			DeviceExtension->ComboPosition++;
			if (ScanCodes[DeviceExtension->ComboPosition] == 0)
				KeBugCheck(MANUALLY_INITIATED_CRASH);
		}
		else if (Output == 0xfa)
		{
		    /* Ignore ACK */
		}
		else if (Output == ScanCodes[0])
			DeviceExtension->ComboPosition = 1;
		else
			DeviceExtension->ComboPosition = 0;

		/* Test for TAB + key combination */
		if (InputData->MakeCode == 0x0F)
			DeviceExtension->TabPressed = !(InputData->Flags & KEY_BREAK);
		else if (DeviceExtension->TabPressed)
		{
			DeviceExtension->TabPressed = FALSE;

            /* Check which action to do */
            if (InputData->MakeCode == 0x25)
            {
                /* k - Breakpoint */
                DbgBreakPointWithStatus(DBG_STATUS_SYSRQ);
            }
            else if (InputData->MakeCode == 0x30)
            {
                /* b - Bugcheck */
                KeBugCheck(MANUALLY_INITIATED_CRASH);
            }
#if defined(KDBG)
            else
            {
			    /* Send request to the kernel debugger.
			     * Unknown requests will be ignored. */
			    KdSystemDebugControl(' soR',
			                         (PVOID)(ULONG_PTR)InputData->MakeCode,
			                         0,
			                         NULL,
			                         0,
			                         NULL,
			                         KernelMode);
            }
#endif
		}
	}

	if (i8042KbdCallIsrHook(DeviceExtension, PortStatus, Output, &ToReturn))
		return ToReturn;

	if (i8042PacketIsr(PortDeviceExtension, Output))
	{
		if (PortDeviceExtension->PacketComplete)
		{
			TRACE_(I8042PRT, "Packet complete\n");
			KeInsertQueueDpc(&DeviceExtension->DpcKeyboard, NULL, NULL);
		}
		TRACE_(I8042PRT, "Irq eaten by packet\n");
		return TRUE;
	}

	TRACE_(I8042PRT, "Irq is keyboard input\n");

	if (DeviceExtension->KeyboardScanState == Normal)
	{
		switch (Output)
		{
			case 0xe0:
				DeviceExtension->KeyboardScanState = GotE0;
				return TRUE;
			case 0xe1:
				DeviceExtension->KeyboardScanState = GotE1;
				return TRUE;
			default:
				break;
		}
	}

	/* Update InputData */
	InputData->Flags = 0;
	switch (DeviceExtension->KeyboardScanState)
	{
		case GotE0:
			InputData->Flags |= KEY_E0;
			break;
		case GotE1:
			InputData->Flags |= KEY_E1;
			break;
		default:
			break;
	}
	DeviceExtension->KeyboardScanState = Normal;
	if (Output & 0x80)
		InputData->Flags |= KEY_BREAK;
	else
		InputData->Flags |= KEY_MAKE;
	InputData->MakeCode = Output & 0x7f;
	InputData->Reserved = 0;

	DeviceExtension->KeyboardHook.QueueKeyboardPacket(DeviceExtension->KeyboardHook.CallContext);

	return TRUE;
}
예제 #7
0
파일: worker.c 프로젝트: BaoYu0721/WRK-1.2
VOID
ExpDebuggerWorker(
    IN PVOID Context
    )
/*++

Routine Description:

    This is a worker thread for the kernel debugger that can be used to
    perform certain tasks on the target machine asynchronously.
    This is necessary when the machine needs to run at Dispatch level to
    perform certain operations, such as paging in data.

Arguments:

    Context - not used as this point.

Return Value:

    None.

--*/

{
    NTSTATUS Status;
    KAPC_STATE  ApcState;
    volatile UCHAR Data;
    PRKPROCESS  KillProcess = (PRKPROCESS) ExpDebuggerProcessKill;
    PRKPROCESS  AttachProcess = (PRKPROCESS) ExpDebuggerProcessAttach;
    PUCHAR PageIn = (PUCHAR) ExpDebuggerPageIn;
    PEPROCESS Process;

    ExpDebuggerProcessKill = 0;
    ExpDebuggerProcessAttach = 0;
    ExpDebuggerPageIn = 0;

    UNREFERENCED_PARAMETER (Context);

#if DBG
    if (ExpDebuggerWork != 2)
    {
        DbgPrint("ExpDebuggerWorker being entered with state != 2\n");
    }
#endif

    ExpDebuggerWork = 0;


    Process = NULL;
    if (AttachProcess || KillProcess) {
        for (Process =  PsGetNextProcess (NULL);
             Process != NULL;
             Process =  PsGetNextProcess (Process)) {
            if (&Process->Pcb ==  AttachProcess) {
                KeStackAttachProcess (AttachProcess, &ApcState);
                break;
            }
            if (&Process->Pcb ==  KillProcess) {
                PsTerminateProcess(Process, DBG_TERMINATE_PROCESS);
                PsQuitNextProcess (Process);
                return;
            }
        }
    }

    if (PageIn) {
        try {
            Data = ProbeAndReadUchar (PageIn);
        } except (EXCEPTION_EXECUTE_HANDLER) {
            Status = GetExceptionCode();
        }
    }

    DbgBreakPointWithStatus(DBG_STATUS_WORKER);

    if (Process != NULL) {
        KeUnstackDetachProcess (&ApcState);
        PsQuitNextProcess (Process);
    }

    return;
}
예제 #8
0
파일: kiinit.c 프로젝트: GYGit/reactos
VOID
NTAPI
KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
    CCHAR Cpu;
    PKTHREAD InitialThread;
    ULONG64 InitialStack;
    PKIPCR Pcr;

    /* HACK */
    FrLdrDbgPrint = LoaderBlock->u.I386.CommonDataArea;
    //FrLdrDbgPrint("Hello from KiSystemStartup!!!\n");

    /* Save the loader block */
    KeLoaderBlock = LoaderBlock;

    /* Get the current CPU number */
    Cpu = KeNumberProcessors++; // FIXME

    /* LoaderBlock initialization for Cpu 0 */
    if (Cpu == 0)
    {
        /* Set the initial stack, idle thread and process */
        LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack;
        LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread;
        LoaderBlock->Process = (ULONG_PTR)&KiInitialProcess.Pcb;
        LoaderBlock->Prcb = (ULONG_PTR)&KiInitialPcr.Prcb;
    }

    /* Get Pcr from loader block */
    Pcr = CONTAINING_RECORD(LoaderBlock->Prcb, KIPCR, Prcb);

    /* Set the PRCB for this Processor */
    KiProcessorBlock[Cpu] = &Pcr->Prcb;

    /* Align stack to 16 bytes */
    LoaderBlock->KernelStack &= ~(16 - 1);

    /* Save the initial thread and stack */
    InitialStack = LoaderBlock->KernelStack; // Checkme
    InitialThread = (PKTHREAD)LoaderBlock->Thread;

    /* Set us as the current process */
    InitialThread->ApcState.Process = (PVOID)LoaderBlock->Process;

    /* Initialize the PCR */
    KiInitializePcr(Pcr, Cpu, InitialThread, (PVOID)KiDoubleFaultStack);

    /* Initialize the CPU features */
    KiInitializeCpu(Pcr);

    /* Initial setup for the boot CPU */
    if (Cpu == 0)
    {
        /* Initialize the module list (ntos, hal, kdcom) */
        KiInitModuleList(LoaderBlock);

        /* Setup the TSS descriptors and entries */
        KiInitializeTss(Pcr->TssBase, InitialStack);

        /* Setup the IDT */
        KeInitExceptions();

         /* Initialize debugging system */
        KdInitSystem(0, KeLoaderBlock);

        /* Check for break-in */
        if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
    }

    DPRINT1("Pcr = %p, Gdt = %p, Idt = %p, Tss = %p\n",
           Pcr, Pcr->GdtBase, Pcr->IdtBase, Pcr->TssBase);

    /* Acquire lock */
    while (InterlockedBitTestAndSet64((PLONG64)&KiFreezeExecutionLock, 0))
    {
        /* Loop until lock is free */
        while ((*(volatile KSPIN_LOCK*)&KiFreezeExecutionLock) & 1);
    }

    /* Initialize the Processor with HAL */
    HalInitializeProcessor(Cpu, KeLoaderBlock);

    /* Set processor as active */
    KeActiveProcessors |= 1ULL << Cpu;

    /* Release lock */
    InterlockedAnd64((PLONG64)&KiFreezeExecutionLock, 0);

    /* Raise to HIGH_LEVEL */
    KfRaiseIrql(HIGH_LEVEL);

    /* Machine specific kernel initialization */
    if (Cpu == 0) KiInitializeKernelMachineDependent(&Pcr->Prcb, LoaderBlock);

    /* Switch to new kernel stack and start kernel bootstrapping */
    KiSwitchToBootStack(InitialStack & ~3);
}
예제 #9
0
파일: Log.c 프로젝트: the-alien/evhdparser
NTSTATUS Log_Print(LOG_LEVEL Level, LPCSTR pszFormat, ...)
{
	NTSTATUS Status = STATUS_SUCCESS;
	LARGE_INTEGER SystemTime, LocalTime;
	TIME_FIELDS TimeFields;
	PLOG_COUNTED_STRING Line = NULL;
	va_list args;
	KIRQL Irql = KeGetCurrentIrql();
	LPCSTR StrLevel = "       :";

	if (!LogFile)
		return STATUS_INVALID_DEVICE_STATE;

	if (Irql > DISPATCH_LEVEL)
		return STATUS_INVALID_LEVEL;

	KeQuerySystemTime(&SystemTime);
	ExSystemTimeToLocalTime(&SystemTime, &LocalTime);
	RtlTimeToTimeFields(&LocalTime, &TimeFields);

	Line = ExAllocatePoolWithTag(NonPagedPool, MAX_LOG_STRING_SIZE + FIELD_OFFSET(LOG_COUNTED_STRING, Data), LogAllocationTag);
	if (!Line)
		return STATUS_INSUFFICIENT_RESOURCES;

	switch (Level)
	{
	case LL_FATAL:
#if DBG
		DbgBreakPointWithStatus(DBG_STATUS_FATAL);
#endif
		StrLevel = "FATAL  :";
		break;
	case LL_ERROR:
		StrLevel = "ERROR  :";
		break;
	case LL_WARNING:
		StrLevel = "WARNING:";
		break;
	case LL_INFO:
		StrLevel = "INFO   :";
		break;
	case LL_VERBOSE:
		StrLevel = "VERBOSE:";
		break;
	case LL_DEBUG:
		StrLevel = "DEBUG  :";
		break;
	}

	Status = StringCbPrintfA(Line->Data, MAX_LOG_STRING_SIZE, "%04u.%02u.%02u %02u:%02u:%02u.%03u PR:0x%04X TH:0x%04X IL:%d %s ",
		TimeFields.Year,
		TimeFields.Month,
		TimeFields.Day,
		TimeFields.Hour,
		TimeFields.Minute,
		TimeFields.Second,
		TimeFields.Milliseconds,
		(ULONG)PsGetCurrentProcessId() & 0xFFFF,
		(ULONG)PsGetCurrentThreadId() & 0xFFFF,
		(ULONG)Irql,
		StrLevel);

	if (SUCCEEDED(Status))
	{
		va_start(args, pszFormat);
		Line->DataLength = (USHORT)strlen(Line->Data);
		Status = StringCbVPrintfA(Line->Data + Line->DataLength, MAX_LOG_STRING_SIZE - Line->DataLength, pszFormat, args);
		if (SUCCEEDED(Status))
		{
			Line->DataLength = (USHORT)strlen(Line->Data);
			if (Irql != PASSIVE_LEVEL) {
				PIO_WORKITEM pWorkItem = IoAllocateWorkItem(LogDeviceObject);
				InterlockedIncrement(&LogScheduledPrints);
				IoQueueWorkItemEx(pWorkItem, Log_WriteWorker, DelayedWorkQueue, Line);
				Status = STATUS_PENDING;
			}
			else
			{
				Status = Log_WriteLine(Line);
			}
		}

		va_end(args);
	}

	if (Status != STATUS_PENDING)
		ExFreePoolWithTag(Line, LogAllocationTag);

	return Status;
}
예제 #10
0
VOID
NTAPI
INIT_FUNCTION
KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
    ULONG Cpu;
    PKTHREAD InitialThread;
    ULONG InitialStack;
    PKGDTENTRY Gdt;
    PKIDTENTRY Idt;
    KIDTENTRY NmiEntry, DoubleFaultEntry;
    PKTSS Tss;
    PKIPCR Pcr;

    /* Boot cycles timestamp */
    BootCycles = __rdtsc();

    /* Save the loader block and get the current CPU */
    KeLoaderBlock = LoaderBlock;
    Cpu = KeNumberProcessors;
    if (!Cpu)
    {
        /* If this is the boot CPU, set FS and the CPU Number*/
        Ke386SetFs(KGDT_R0_PCR);
        __writefsdword(KPCR_PROCESSOR_NUMBER, Cpu);

        /* Set the initial stack and idle thread as well */
        LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack;
        LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread;
    }

    /* Save the initial thread and stack */
    InitialStack = LoaderBlock->KernelStack;
    InitialThread = (PKTHREAD)LoaderBlock->Thread;

    /* Clean the APC List Head */
    InitializeListHead(&InitialThread->ApcState.ApcListHead[KernelMode]);

    /* Initialize the machine type */
    KiInitializeMachineType();

    /* Skip initial setup if this isn't the Boot CPU */
    if (Cpu) goto AppCpuInit;

    /* Get GDT, IDT, PCR and TSS pointers */
    KiGetMachineBootPointers(&Gdt, &Idt, &Pcr, &Tss);

    /* Setup the TSS descriptors and entries */
    Ki386InitializeTss(Tss, Idt, Gdt);

    /* Initialize the PCR */
    RtlZeroMemory(Pcr, PAGE_SIZE);
    KiInitializePcr(Cpu,
                    Pcr,
                    Idt,
                    Gdt,
                    Tss,
                    InitialThread,
                    (PVOID)KiDoubleFaultStack);

    /* Set us as the current process */
    InitialThread->ApcState.Process = &KiInitialProcess.Pcb;

    /* Clear DR6/7 to cleanup bootloader debugging */
    __writefsdword(KPCR_TEB, 0);
    __writefsdword(KPCR_DR6, 0);
    __writefsdword(KPCR_DR7, 0);

    /* Setup the IDT */
    KeInitExceptions();

    /* Load Ring 3 selectors for DS/ES */
    Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
    Ke386SetEs(KGDT_R3_DATA | RPL_MASK);

    /* Save NMI and double fault traps */
    RtlCopyMemory(&NmiEntry, &Idt[2], sizeof(KIDTENTRY));
    RtlCopyMemory(&DoubleFaultEntry, &Idt[8], sizeof(KIDTENTRY));

    /* Copy kernel's trap handlers */
    RtlCopyMemory(Idt,
                  (PVOID)KiIdtDescriptor.Base,
                  KiIdtDescriptor.Limit + 1);

    /* Restore NMI and double fault */
    RtlCopyMemory(&Idt[2], &NmiEntry, sizeof(KIDTENTRY));
    RtlCopyMemory(&Idt[8], &DoubleFaultEntry, sizeof(KIDTENTRY));

AppCpuInit:
    /* Loop until we can release the freeze lock */
    do
    {
        /* Loop until execution can continue */
        while (*(volatile PKSPIN_LOCK*)&KiFreezeExecutionLock == (PVOID)1);
    } while(InterlockedBitTestAndSet((PLONG)&KiFreezeExecutionLock, 0));

    /* Setup CPU-related fields */
    __writefsdword(KPCR_NUMBER, Cpu);
    __writefsdword(KPCR_SET_MEMBER, 1 << Cpu);
    __writefsdword(KPCR_SET_MEMBER_COPY, 1 << Cpu);
    __writefsdword(KPCR_PRCB_SET_MEMBER, 1 << Cpu);

    /* Initialize the Processor with HAL */
    HalInitializeProcessor(Cpu, KeLoaderBlock);

    /* Set active processors */
    KeActiveProcessors |= __readfsdword(KPCR_SET_MEMBER);
    KeNumberProcessors++;

    /* Check if this is the boot CPU */
    if (!Cpu)
    {
        /* Initialize debugging system */
        KdInitSystem(0, KeLoaderBlock);

        /* Check for break-in */
        if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
    }

    /* Raise to HIGH_LEVEL */
    KfRaiseIrql(HIGH_LEVEL);

    /* Switch to new kernel stack and start kernel bootstrapping */
    KiSwitchToBootStack(InitialStack & ~3);
}
예제 #11
0
파일: dbgctrl.c 프로젝트: chunhualiu/OpenNT
NTSTATUS
NtSystemDebugControl (
    IN SYSDBG_COMMAND Command,
    IN PVOID InputBuffer,
    IN ULONG InputBufferLength,
    OUT PVOID OutputBuffer,
    IN ULONG OutputBufferLength,
    OUT PULONG ReturnLength OPTIONAL
    )

/*++

Routine Description:

    This function controls the system debugger.

Arguments:

    Command - The command to be executed.  One of the following:

        SysDbgQueryTraceInformation
        SysDbgSetTracepoint
        SysDbgSetSpecialCall
        SysDbgClearSpecialCalls
        SysDbgQuerySpecialCalls

    InputBuffer - A pointer to a buffer describing the input data for
        the request, if any.  The structure of this buffer varies
        depending upon Command.

    InputBufferLength - The length in bytes of InputBuffer.

    OutputBuffer - A pointer to a buffer that is to receive the output
        data for the request, if any.  The structure of this buffer
        varies depending upon Command.

    OutputBufferLength - The length in bytes of OutputBuffer.

    ReturnLength - A optional pointer to a ULONG that is to receive the
        output data length for the request.

Return Value:

    Returns one of the following status codes:

        STATUS_SUCCESS - normal, successful completion.

        STATUS_INVALID_INFO_CLASS - The Command parameter did not
            specify a valid value.

        STATUS_INFO_LENGTH_MISMATCH - The value of the Length field in the
            Parameters buffer was not correct.

        STATUS_ACCESS_VIOLATION - Either the Parameters buffer pointer
            or a pointer within the Parameters buffer specified an
            invalid address.

        STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
            for this request to complete.

--*/

{
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN releaseModuleResoure = FALSE;
    ULONG length = 0;
    KPROCESSOR_MODE PreviousMode;

    PreviousMode = KeGetPreviousMode();

    if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode)) {
        return STATUS_ACCESS_DENIED;
    }

    //
    // Operate within a try block in order to catch errors.
    //

    try {

        //
        // Probe input and output buffers, if previous mode is not
        // kernel.
        //

        if ( PreviousMode != KernelMode ) {

            if ( InputBufferLength != 0 ) {
                ProbeForRead( InputBuffer, InputBufferLength, sizeof(ULONG) );
            }

            if ( OutputBufferLength != 0 ) {
                ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(ULONG) );
            }

            if ( ARGUMENT_PRESENT(ReturnLength) ) {
                ProbeForWriteUlong( ReturnLength );
            }
        }

        //
        // Switch on the command code.
        //

        switch ( Command ) {

#ifdef _X86_

        case SysDbgQueryTraceInformation:

            status = KdGetTraceInformation(
                        OutputBuffer,
                        OutputBufferLength,
                        &length
                        );

            break;

        case SysDbgSetTracepoint:

            if ( InputBufferLength != sizeof(DBGKD_MANIPULATE_STATE64) ) {
                return STATUS_INFO_LENGTH_MISMATCH;
            }

            KdSetInternalBreakpoint( InputBuffer );

            break;

        case SysDbgSetSpecialCall:

            if ( InputBufferLength != sizeof(PVOID) ) {
                return STATUS_INFO_LENGTH_MISMATCH;
            }

            KdSetSpecialCall( InputBuffer, NULL );

            break;

        case SysDbgClearSpecialCalls:

            KdClearSpecialCalls( );

            break;

        case SysDbgQuerySpecialCalls:

            status = KdQuerySpecialCalls(
                        OutputBuffer,
                        OutputBufferLength,
                        &length
                        );

            break;

#endif

        case SysDbgBreakPoint:
            if (KdDebuggerEnabled) {
                DbgBreakPointWithStatus(DBG_STATUS_DEBUG_CONTROL);
            } else {
                status = STATUS_UNSUCCESSFUL;
            }
            break;

        default:

            //
            // Invalid Command.
            //

            status = STATUS_INVALID_INFO_CLASS;
        }

        if ( ARGUMENT_PRESENT(ReturnLength) ) {
            *ReturnLength = length;
        }
    }

    except ( EXCEPTION_EXECUTE_HANDLER ) {

        if ( releaseModuleResoure ) {
            ExReleaseResource( &PsLoadedModuleResource );
            KeLeaveCriticalRegion();
        }

        status = GetExceptionCode();

    }

    return status;

} // NtSystemDebugControl