[NTOS:KD] Move handling of Dmesg buffer from screen provider to KDBG provider. (#5143)

CORE-10749

The dmesg command is now available even if screen output is disabled.

Co-authored-by: Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
This commit is contained in:
Hervé Poussineau 2022-07-10 15:01:01 +02:00 committed by Hermès Bélusca-Maïto
parent 86e2f9e635
commit bf734e5373
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
3 changed files with 85 additions and 79 deletions

View file

@ -53,6 +53,17 @@ VOID
/* INIT ROUTINES *************************************************************/
KIRQL
NTAPI
KdbpAcquireLock(
_In_ PKSPIN_LOCK SpinLock);
VOID
NTAPI
KdbpReleaseLock(
_In_ PKSPIN_LOCK SpinLock,
_In_ KIRQL OldIrql);
VOID
KdpScreenAcquire(VOID);

View file

@ -37,14 +37,6 @@ CPPORT SerialPortInfo = {0, DEFAULT_DEBUG_BAUD_RATE, 0};
static CHAR KdpScreenLineBuffer[KdpScreenLineLengthDefault + 1] = "";
static ULONG KdpScreenLineBufferPos = 0, KdpScreenLineLength = 0;
const ULONG KdpDmesgBufferSize = 128 * 1024; // 512*1024;
PCHAR KdpDmesgBuffer = NULL;
volatile ULONG KdpDmesgCurrentPosition = 0;
volatile ULONG KdpDmesgFreeBytes = 0;
volatile ULONG KdbDmesgTotalWritten = 0;
volatile BOOLEAN KdbpIsInDmesgMode = FALSE;
static KSPIN_LOCK KdpDmesgLogSpinLock;
KDP_DEBUG_MODE KdpDebugMode;
LIST_ENTRY KdProviders = {&KdProviders, &KdProviders};
KD_DISPATCH_TABLE DispatchTable[KdMax];
@ -440,20 +432,12 @@ KdpScreenRelease(VOID)
}
}
/*
* Screen debug logger function KdpScreenPrint() writes text strings into
* KdpDmesgBuffer, using it as a circular buffer. KdpDmesgBuffer contents could
* be later (re)viewed using dmesg command of kdbg. KdpScreenPrint() protects
* KdpDmesgBuffer from simultaneous writes by use of KdpDmesgLogSpinLock.
*/
static VOID
NTAPI
KdpScreenPrint(PCHAR String,
ULONG Length)
{
PCHAR pch = String;
KIRQL OldIrql;
ULONG beg, end, num;
while (pch < String + Length && *pch)
{
@ -497,45 +481,6 @@ KdpScreenPrint(PCHAR String,
HalDisplayString(KdpScreenLineBuffer + KdpScreenLineBufferPos);
KdpScreenLineBufferPos = KdpScreenLineLength;
}
/* Dmesg: store the string in the buffer to show it later */
if (KdbpIsInDmesgMode)
return;
if (KdpDmesgBuffer == NULL)
return;
/* Acquire the printing spinlock without waiting at raised IRQL */
OldIrql = KdbpAcquireLock(&KdpDmesgLogSpinLock);
beg = KdpDmesgCurrentPosition;
/* Invariant: always_true(KdpDmesgFreeBytes == KdpDmesgBufferSize); */
num = min(Length, KdpDmesgFreeBytes);
if (num != 0)
{
end = (beg + num) % KdpDmesgBufferSize;
if (end > beg)
{
RtlCopyMemory(KdpDmesgBuffer + beg, String, Length);
}
else
{
RtlCopyMemory(KdpDmesgBuffer + beg, String, KdpDmesgBufferSize - beg);
RtlCopyMemory(KdpDmesgBuffer, String + (KdpDmesgBufferSize - beg), end);
}
KdpDmesgCurrentPosition = end;
/* Counting the total bytes written */
KdbDmesgTotalWritten += num;
}
/* Release the spinlock */
KdbpReleaseLock(&KdpDmesgLogSpinLock, OldIrql);
/* Optional step(?): find out a way to notify about buffer exhaustion,
* and possibly fall into kbd to use dmesg command: user will read
* debug strings before they will be wiped over by next writes.
*/
}
VOID
@ -557,22 +502,9 @@ KdpScreenInit(
}
else if (BootPhase == 1)
{
/* Allocate a buffer for dmesg log buffer. +1 for terminating null,
* see kdbp_cli.c:KdbpCmdDmesg()/2
*/
KdpDmesgBuffer = ExAllocatePoolZero(NonPagedPool,
KdpDmesgBufferSize + 1,
TAG_KDBG);
/* Ignore failure if KdpDmesgBuffer is NULL */
KdpDmesgFreeBytes = KdpDmesgBufferSize;
KdbDmesgTotalWritten = 0;
/* Take control of the display */
KdpScreenAcquire();
/* Initialize spinlock */
KeInitializeSpinLock(&KdpDmesgLogSpinLock);
HalDisplayString("\r\n Screen debugging enabled\r\n\r\n");
}
}

View file

@ -155,14 +155,14 @@ static LONG KdbNumberOfColsTerminal = -1;
PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during initialization */
BOOLEAN KdbpBugCheckRequested = FALSE;
/* Vars for dmesg */
/* defined in ../kd/kdio.c, declare here: */
extern volatile BOOLEAN KdbpIsInDmesgMode;
extern const ULONG KdpDmesgBufferSize;
extern PCHAR KdpDmesgBuffer;
extern volatile ULONG KdpDmesgCurrentPosition;
extern volatile ULONG KdpDmesgFreeBytes;
extern volatile ULONG KdbDmesgTotalWritten;
/* Variables for Dmesg */
static const ULONG KdpDmesgBufferSize = 128 * 1024; // 512*1024;
static PCHAR KdpDmesgBuffer = NULL;
static volatile ULONG KdpDmesgCurrentPosition = 0;
static volatile ULONG KdpDmesgFreeBytes = 0;
static volatile ULONG KdbDmesgTotalWritten = 0;
static volatile BOOLEAN KdbpIsInDmesgMode = FALSE;
static KSPIN_LOCK KdpDmesgLogSpinLock;
STRING KdbPromptString = RTL_CONSTANT_STRING("kdb:> ");
@ -3882,13 +3882,60 @@ KdbpCliInit(VOID)
}
/**
* @brief Debug logger function.
*
* This function writes text strings into KdpDmesgBuffer, using it as
* a circular buffer. KdpDmesgBuffer contents can be later (re)viewed
* using the dmesg command. KdbDebugPrint() protects KdpDmesgBuffer
* from simultaneous writes by use of KdpDmesgLogSpinLock.
**/
static VOID
NTAPI
KdbDebugPrint(
PCH Message,
ULONG Length)
_In_ PCHAR String,
_In_ ULONG Length)
{
/* Nothing here */
KIRQL OldIrql;
ULONG beg, end, num;
/* Avoid recursive calling if we already are in Dmesg mode */
if (KdbpIsInDmesgMode)
return;
if (KdpDmesgBuffer == NULL)
return;
/* Acquire the printing spinlock without waiting at raised IRQL */
OldIrql = KdbpAcquireLock(&KdpDmesgLogSpinLock);
beg = KdpDmesgCurrentPosition;
/* Invariant: always_true(KdpDmesgFreeBytes == KdpDmesgBufferSize); */
num = min(Length, KdpDmesgFreeBytes);
if (num != 0)
{
end = (beg + num) % KdpDmesgBufferSize;
if (end > beg)
{
RtlCopyMemory(KdpDmesgBuffer + beg, String, Length);
}
else
{
RtlCopyMemory(KdpDmesgBuffer + beg, String, KdpDmesgBufferSize - beg);
RtlCopyMemory(KdpDmesgBuffer, String + (KdpDmesgBufferSize - beg), end);
}
KdpDmesgCurrentPosition = end;
/* Counting the total bytes written */
KdbDmesgTotalWritten += num;
}
/* Release the spinlock */
KdbpReleaseLock(&KdpDmesgLogSpinLock, OldIrql);
/* Optional step(?): find out a way to notify about buffer exhaustion,
* and possibly fall into kbd to use dmesg command: user will read
* debug strings before they will be wiped over by next writes. */
}
/**
@ -3918,6 +3965,22 @@ KdbInitialize(
/* Register as a Provider */
InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
}
else if (BootPhase == 1)
{
/* Initialize Dmesg support */
/* Allocate a buffer for Dmesg log buffer. +1 for terminating null,
* see kdbp_cli.c:KdbpCmdDmesg()/2 */
KdpDmesgBuffer = ExAllocatePoolZero(NonPagedPool,
KdpDmesgBufferSize + 1,
TAG_KDBG);
/* Ignore failure if KdpDmesgBuffer is NULL */
KdpDmesgFreeBytes = KdpDmesgBufferSize;
KdbDmesgTotalWritten = 0;
/* Initialize spinlock */
KeInitializeSpinLock(&KdpDmesgLogSpinLock);
}
if (BootPhase <= 1)
{