Skip to content

Hck rss bsod work in progress #1333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8f385f5
netkvm: move all NBLs drop to separate procedure
ybendito Mar 21, 2025
37aed71
netkvm: drop all the NBLs on carrier loss
ybendito Mar 21, 2025
8fa55ef
netkvm: simplify TX code for case of single queue
ybendito Mar 22, 2025
f8aa83d
netkvm: add debug printout in send path
ybendito Mar 22, 2025
42722f7
netkvm: fix broken compilation with history log
ybendito Mar 30, 2025
c850c5c
netkvm: track last tx completion time per queue
ybendito Mar 23, 2025
2dbfe47
netkvm: add public method for getting ref count
ybendito Mar 26, 2025
87c7d3d
netkvm: maintain NBL chain information
ybendito Mar 22, 2025
c21810c
netkvm: remove unneeded procedure
ybendito Apr 7, 2025
8498ea9
netkvm: preserve per-connection chains
ybendito Mar 22, 2025
4f54424
netkvm: add history logs for NBL-related operations
ybendito Mar 30, 2025
1a0a550
netkvm-dumpparser: fix build and update
ybendito Mar 26, 2025
0cb024d
netkvm-dumpparser: parse history data only
ybendito Mar 29, 2025
f378d0f
not for delivery: use performance counter for timestamps
ybendito Mar 23, 2025
a1f5542
netkvm: optionally keep the NBL history in the CNBL
ybendito Mar 28, 2025
f7f42c9
wip Die
ybendito Mar 26, 2025
6dd6d41
netkvm: add CNBL getter for m_NBL
ybendito Apr 5, 2025
8a28663
netkvm: emit debug history with queue index
ybendito Apr 5, 2025
69af2e6
netkvm: emit debug history for chained NBLs with queue index
ybendito Apr 5, 2025
27de6a4
netkvm: remember serial number in chain inside CNBL
ybendito Apr 5, 2025
653784e
netkvm: take care of mapping failure case
ybendito Apr 5, 2025
3805b40
netkvm: do not invert order of NBLs on completion
ybendito Apr 5, 2025
febd004
netkvm: do not change the order of CNBLs after sending
ybendito Apr 7, 2025
0dc95e7
netkvm: recreate the NBL chain on CNBL completion
ybendito Apr 7, 2025
e1e0236
wip fire dpc
ybendito Apr 7, 2025
c2d4571
not sure - additional poll request
ybendito Apr 7, 2025
3529450
fix dump parser
ybendito Apr 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion NetKVM/Common/DebugData.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ typedef enum class _etagHistoryLogOperation
hopTxProcess,
hopPacketReceived, // implementation, when the packet prepared for indication (nbl, length, prio tag, type)
hopOidRequest, // implementation, none, OID, on entry(type, 1), on exit (status, 0), on complete (status, 2)
hopPnpEvent // common, none, event, 0, 0
hopPnpEvent, // common, none, event, 0, 0
hopNBLDestructor,
hopSendCompleteChain,
hopSendDone,
} eHistoryLogOperation;

// {E51FCE18-B3E7-441e-B18C-D9E9B71616F3}
Expand Down
144 changes: 138 additions & 6 deletions NetKVM/Common/ParaNdis-TX.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
#include "ParaNdis-AbstractPath.h"
#include "ParaNdis_GuestAnnounce.h"
#include "ParaNdis_LockFreeQueue.h"
#include "ParaNdis_DebugHistory.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please submit this as a separate PR. It can already be merged and make future review easier.

Thanks!


/* Must be a power of 2 */
#define PARANDIS_TX_LOCK_FREE_QUEUE_DEFAULT_SIZE 2048
#define NBL_MAINTAIN_HISTORY 0
#define NBL_CHAINS 1
#define SPAWN_TX_PROCESS_FROM_SEND_PATH 1
#define REPAIR_CHAIN (NBL_CHAINS && 1)

/* the maximum number of pages that a single network packet can span.
refer linux kernel code #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 1), */
Expand Down Expand Up @@ -105,6 +110,33 @@ class CNB : public CNdisAllocatableViaHelper<CNB>
DECLARE_CNDISLIST_ENTRY(CNB);
};

typedef struct _tChainOfNbls
{
CNdisRefCounter m_NumChained;
CNdisRefCounter m_NumCompleted;
CNBL *m_FirstInChain;
} CChainOfNbls;

class NBLHistory : public CNdisAllocatable<NBLHistory, 'NBLH'>
{
DECLARE_CNDISLIST_ENTRY(NBLHistory);

public:
Copy link
Contributor

@Jedoku Jedoku Mar 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case there should be extra line before access specifiers

NBLHistory(LPCSTR Func, LPCSTR Title, LPCSTR ParameterMeaning, PVOID Parameter, LPCSTR ValueMeaning, ULONG Value);

protected:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jedoku is this behavior configurable? I ask because this does not make too much sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's configured in .clang-format
EmptyLineBeforeAccessModifier: LogicalBlock
If we change it it will affect whole project

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jedoku If there is an option "don't mind" this will not request any change, correct? Is it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave option should work

ULONGLONG m_Timestamp;
LPCSTR m_Function;
LPCSTR m_Title;
LPCSTR m_ParameterMeaning;
PVOID m_Parameter;
LPCSTR m_ValueMeaning;
ULONG m_Value;
ULONG m_CurrentCPU;
};

typedef CNdisList<NBLHistory, CLockedAccess, CNonCountingObject> CHistoryList;

class CNBL : public CNdisAllocatableViaHelper<CNBL>, public CRefCountingObject, public CAllocationHelper<CNB>
{
public:
Expand All @@ -129,6 +161,90 @@ class CNBL : public CNdisAllocatableViaHelper<CNBL>, public CRefCountingObject,
{
return (ParsePriority() && ParseBuffers() && ParseOffloads());
}
#if NBL_CHAINS
void Die()
{
// RtlFailFast(FAST_FAIL_RANGE_CHECK_FAILURE);
DbgBreakPoint();
}
void SetInChain(PNET_BUFFER_LIST FirstInChain)
{
if (FirstInChain != m_NBL)
{
m_Chain.m_FirstInChain = (CNBL *)FirstInChain->Scratch;
LONG serial = m_Chain.m_FirstInChain->m_Chain.m_NumChained.AddRef();
m_Chain.m_FirstInChain->AddRef();
// set the serial number in chain for information
m_Chain.m_NumChained.AddRef(serial);
}
}
void UnsetInChain()
{
// the NBL was failed mapping, if does not go
// to transmit path
ParaNdis_DebugHistory(this,
eHistoryLogOperation::hopSendComplete,
m_NBL,
!m_Chain.m_FirstInChain,
m_NBL->Status,
GetCurrentRefCounterUnsafe());
if (m_Chain.m_FirstInChain)
{
m_Chain.m_FirstInChain->m_Chain.m_NumChained.Release();
// the head of chain will be released in the destructor
}
}
void CompleteInChain()
{
auto head = m_Chain.m_FirstInChain;
if (head)
{
if (m_NBL)
{
// Detach NBL from chained CNBL and chain it the end
// of the chain started from m_NBL of the first CNBL
// The NBL is fully completed, so STATUS_SUCCESS
SetStatus(NDIS_STATUS_SUCCESS);
auto rawNbl = DetachInternalObject();
// save the serial number in chain
rawNbl->Scratch = (PVOID)(LONG)m_Chain.m_NumChained;
PNET_BUFFER_LIST *next = &NET_BUFFER_LIST_NEXT_NBL(head->m_NBL);

// Attach to the tail of NBLs atomically
while (InterlockedCompareExchangePointer((PVOID *)next, rawNbl, nullptr))
{
next = &NET_BUFFER_LIST_NEXT_NBL(*next);
}
}
LONG completed = head->m_Chain.m_NumCompleted.AddRef();
ParaNdis_DebugHistory(this,
eHistoryLogOperation::hopSendCompleteChain,
head,
completed,
m_Chain.m_NumChained,
head->GetCurrentRefCounterUnsafe());
AddHistory(__FUNCTION__, "", "Head", head, "Completed", completed);
if (head->m_Chain.m_NumChained < completed)
{
// this is a fatal problem, probably caused by
// double completion, may cause to list corruption
// TODO: assertion??
Die();
}
}
}
#else
void SetInChain(PNET_BUFFER_LIST FirstInChain)
{
UNREFERENCED_PARAMETER(FirstInChain);
}
void UnsetInChain()
{
}
void CompleteInChain()
{
}
#endif
void StartMapping();
void RegisterMappedNB(CNB *NB);
bool MappingSucceeded()
Expand All @@ -150,11 +266,6 @@ class CNBL : public CNdisAllocatableViaHelper<CNBL>, public CRefCountingObject,
return !m_Buffers.IsEmpty();
}

bool HaveDetachedBuffers()
{
return m_MappedBuffersDetached != 0;
}

PNET_BUFFER_LIST DetachInternalObject();
// TODO: Needs review
void NBComplete();
Expand Down Expand Up @@ -230,6 +341,10 @@ class CNBL : public CNdisAllocatableViaHelper<CNBL>, public CRefCountingObject,
m_TransferSize += ChunkSize;
}
}
bool HasNBL() const
{
return m_NBL != nullptr;
}
ULONG NumberOfBuffers() const
{
return m_BuffersNumber;
Expand All @@ -238,7 +353,18 @@ class CNBL : public CNdisAllocatableViaHelper<CNBL>, public CRefCountingObject,
{
return m_ParentTXPath;
}

#if NBL_MAINTAIN_HISTORY
void AddHistory(LPCSTR Func,
LPCSTR Title,
LPCSTR ParameterMeaning = NULL,
PVOID Parameter = NULL,
LPCSTR ValueMeaning = NULL,
ULONG Value = NULL);
#else
void AddHistory(...)
{
}
#endif
private:
virtual void OnLastReferenceGone() override;

Expand Down Expand Up @@ -276,6 +402,7 @@ class CNBL : public CNdisAllocatableViaHelper<CNBL>, public CRefCountingObject,
// align storage for CNB on pointer size boundary and provide enough room for it
ULONG_PTR m_CNB_Storage[(sizeof(CNB) + sizeof(ULONG_PTR) - 1) / sizeof(ULONG_PTR)];
bool m_HaveFailedMappings = false;
bool m_AllNBCompleted = false;

CNdisList<CNB, CRawAccess, CNonCountingObject> m_Buffers;

Expand All @@ -297,6 +424,9 @@ class CNBL : public CNdisAllocatableViaHelper<CNBL>, public CRefCountingObject,
#endif
CAllocationHelper<CNB> *m_NBAllocator;

CChainOfNbls m_Chain = {};
CHistoryList m_History;

CNBL(const CNBL &) = delete;
CNBL &operator=(const CNBL &) = delete;

Expand Down Expand Up @@ -363,6 +493,8 @@ class CParaNdisTX : public CParaNdisTemplatePath<CTXVirtQueue>, public CNdisAllo

bool SendMapped(bool IsInterrupt, CRawCNBLList &toWaitingList);

void DropAllNBls(CRawCNBLList &Completed, NDIS_STATUS Status);

bool FillQueue();

void PostProcessPendingTask(CRawCNBList &toFree, CRawCNBLList &completed);
Expand Down
10 changes: 8 additions & 2 deletions NetKVM/Common/ParaNdis-Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,13 @@ class CRefCountingObject
}
}

// this is provided only for tracking / reference
// and can't be used for any decision
ULONG GetCurrentRefCounterUnsafe()
{
return (LONG)m_RefCounter;
}

protected:
virtual void OnLastReferenceGone() = 0;

Expand Down Expand Up @@ -945,8 +952,7 @@ static inline void ParaNdis_CompleteNBLChainWithStatus(NDIS_HANDLE MiniportHandl

static FORCEINLINE void UpdateTimestamp(ULONGLONG &Variable)
{
LARGE_INTEGER li;
NdisGetCurrentSystemTime(&li);
LARGE_INTEGER li = KeQueryPerformanceCounter(NULL);
Variable = li.QuadPart;
}

Expand Down
1 change: 1 addition & 0 deletions NetKVM/Common/ParaNdis-VirtQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ class CTXVirtQueue : public CVirtQueue

CNdisList<CTXDescriptor, CRawAccess, CCountingObject> m_Descriptors;
CNdisList<CTXDescriptor, CRawAccess, CNonCountingObject> m_DescriptorsInUse;
ULONGLONG m_LastTxCompletionTimestamp = 0;
ULONG m_TotalDescriptors = 0;
ULONG m_FreeHWBuffers = 0;
// TODO: Temporary
Expand Down
10 changes: 5 additions & 5 deletions NetKVM/Common/ParaNdis_Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,27 +355,27 @@ VOID ParaNdis_OnBugCheck(IN KBUGCHECK_CALLBACK_REASON Reason,
#endif

#if defined(ENABLE_HISTORY_LOG)
void ParaNdis_DebugHistory(PARANDIS_ADAPTER *pContext,
static LONG CurrentHistoryIndex = 0;

void ParaNdis_DebugHistory(PVOID pContext,
eHistoryLogOperation op,
PVOID pParam1,
ULONG lParam2,
ULONG lParam3,
ULONG lParam4)
{
tBugCheckHistoryDataEntry *phe;
ULONG index = InterlockedIncrement(&BugCheckData.StaticData.Data.CurrentHistoryIndex);
ULONG index = InterlockedIncrement(&CurrentHistoryIndex);
index = (index - 1) % MAX_HISTORY;
phe = &BugCheckData.StaticData.History[index];
phe->Context = (UINT_PTR)pContext;
phe->operation = op;
phe->operation = (ULONG)op;
phe->pParam1 = (UINT_PTR)pParam1;
phe->lParam2 = lParam2;
phe->lParam3 = lParam3;
phe->lParam4 = lParam4;
#if (PARANDIS_DEBUG_HISTORY_DATA_VERSION == 1)
phe->uIRQL = KeGetCurrentIrql();
phe->uProcessor = KeGetCurrentProcessorNumber();
#endif
NdisGetCurrentSystemTime(&phe->TimeStamp);
}

Expand Down
6 changes: 3 additions & 3 deletions NetKVM/Common/ParaNdis_DebugHistory.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

// #define ENABLE_HISTORY_LOG
#define ENABLE_HISTORY_LOG
// #define KEEP_PENDING_NBL

#if !defined(KEEP_PENDING_NBL)
Expand All @@ -26,7 +26,7 @@ void ParaNdis_DebugNBLOut(ULONG index, PNET_BUFFER_LIST nbl);

#if !defined(ENABLE_HISTORY_LOG)

void FORCEINLINE ParaNdis_DebugHistory(PARANDIS_ADAPTER *pContext,
void FORCEINLINE ParaNdis_DebugHistory(PVOID pContext,
eHistoryLogOperation op,
PVOID pParam1,
ULONG lParam2,
Expand All @@ -43,7 +43,7 @@ void FORCEINLINE ParaNdis_DebugHistory(PARANDIS_ADAPTER *pContext,

#else

void ParaNdis_DebugHistory(PARANDIS_ADAPTER *pContext,
void ParaNdis_DebugHistory(PVOID pContext,
eHistoryLogOperation op,
PVOID pParam1,
ULONG lParam2,
Expand Down
Loading