netkvm: Arm Windows support

NdisMAllocateSharedMemory maps memory as non cacheable on Arm Windows,
Given that Windows on Arm does not support unaligned accesses on uncached memory,
this behavior does result in crashes.

As such, use MmAllocateContiguousMemorySpecifyCache for the Arm64 architecture.
This choice is safe.

It's also to be noted that NdisMAllocateSharedMemory
ignores the isCached attribute anyway, and always
maps as cached on amd64.

This also allows us to remove the need for the Rx bounce buffer.

With this fix, networking w/ netkvm for Windows on Arm works fine.
(tested with QEMU emulator version 5.0.50 (v5.0.0-1065-g9f1f264edb))

Signed-off-by: Mohamed Mediouni <[email protected]>
This commit is contained in:
Mohamed Mediouni authored and Yan Vugenfirer committed 2020-07-09 15:19:32 +03:00
1 parent b5089f0602
commit 76ef17bf98
4 files changed
+36 -10

No files matched your search

+2 -6
View File
@@ -767,7 +767,8 @@ NDIS_STATUS ParaNdis_InitializeContext(
DumpVirtIOFeatures(pContext);
// Enable VIRTIO_F_IOMMU_PLATFORM feature on Windows 10 and Windows Server 2016
#if (WINVER == 0x0A00)
// Do not enable it on arm64 yet.
#if (WINVER == 0x0A00) && !defined(_ARM64_)
AckFeature(pContext, VIRTIO_F_IOMMU_PLATFORM);
#endif
AckFeature(pContext, VIRTIO_NET_F_STANDBY);
@@ -785,11 +786,6 @@ NDIS_STATUS ParaNdis_InitializeContext(
InitializeLinkPropertiesConfig(pContext);
#if !defined(_ARM64_)
pContext->bControlQueueSupported = AckFeature(pContext, VIRTIO_NET_F_CTRL_VQ);
#else
DPrintf(0, "[%s] Control queue disabled for ARM64\n", __FUNCTION__);
#endif
pContext->bGuestAnnounceSupported = pContext->bLinkDetectSupported && pContext->bControlQueueSupported && AckFeature(pContext, VIRTIO_NET_F_GUEST_ANNOUNCE);
InitializeMAC(pContext, CurrentMAC);
InitializeMaxMTUConfig(pContext);
+16
View File
@@ -23,7 +23,19 @@ bool CNdisSharedMemory::Allocate(ULONG Size, bool IsCached)
{
m_Size = Size;
m_IsCached = IsCached;
#if defined(_ARM64_)
/*
* On Windows on Arm, do not use NdisMAllocateSharedMemory.
* TODO: Figure out a neater way to allocate memory in those cases.
*/
LARGE_INTEGER bound1, bound2;
bound1.QuadPart = 0;
bound2.QuadPart = MAXUINT64;
m_VA = MmAllocateContiguousMemorySpecifyCache(m_Size, bound1, bound2, bound1, MmCached);
m_PA = MmGetPhysicalAddress(m_VA);
#else
NdisMAllocateSharedMemory(m_DrvHandle, Size, m_IsCached, &m_VA, &m_PA);
#endif
return m_VA != nullptr;
}
@@ -31,7 +43,11 @@ CNdisSharedMemory::~CNdisSharedMemory()
{
if(m_VA != nullptr)
{
#if defined(_ARM64_)
MmFreeContiguousMemorySpecifyCache(m_VA, m_Size, MmCached);
#else
NdisMFreeSharedMemory(m_DrvHandle, m_Size, m_IsCached, m_VA, m_PA);
#endif
m_VA = nullptr;
}
}
-4
View File
@@ -84,10 +84,6 @@ extern "C"
#define _Function_class_(x)
#endif
#if defined(_ARM64_)
#define NETKVM_COPY_RX_DATA
#endif
typedef struct _tagRunTimeNdisVersion
{
UCHAR major;
+18
View File
@@ -110,12 +110,25 @@ BOOLEAN ParaNdis_InitialAllocatePhysicalMemory(
ULONG ulSize,
tCompletePhysicalAddress *pAddresses)
{
#if defined(_ARM64_)
UNREFERENCED_PARAMETER(pContext);
/*
* On Windows on Arm, do not use NdisMAllocateSharedMemory.
* TODO: Figure out a neater way to allocate memory in those cases.
*/
LARGE_INTEGER bound1, bound2;
bound1.QuadPart = 0;
bound2.QuadPart = MAXUINT64;
pAddresses->Virtual = MmAllocateContiguousMemorySpecifyCache(ulSize, bound1, bound2, bound1, MmCached);
pAddresses->Physical = MmGetPhysicalAddress(pAddresses->Virtual);
#else
NdisMAllocateSharedMemory(
pContext->MiniportHandle,
ulSize,
TRUE,
&pAddresses->Virtual,
&pAddresses->Physical);
#endif
if (pAddresses->Virtual != NULL)
{
pAddresses->size = ulSize;
@@ -137,12 +150,17 @@ VOID ParaNdis_FreePhysicalMemory(
PARANDIS_ADAPTER *pContext,
tCompletePhysicalAddress *pAddresses)
{
#if defined(_ARM64_)
UNREFERENCED_PARAMETER(pContext);
MmFreeContiguousMemorySpecifyCache(pAddresses->Virtual, pAddresses->size, MmCached);
#else
NdisMFreeSharedMemory(
pContext->MiniportHandle,
pAddresses->size,
TRUE,
pAddresses->Virtual,
pAddresses->Physical);
#endif
}
#if (NDIS_SUPPORT_NDIS620)