From 76ef17bf9890f0777cbf01acda2c8652850892f4 Mon Sep 17 00:00:00 2001 From: Mohamed Mediouni Date: Tue, 7 Jul 2020 17:15:52 +0200 Subject: [PATCH] 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 --- NetKVM/Common/ParaNdis_Common.cpp | 8 ++------ NetKVM/Common/ParaNdis_Util.cpp | 16 ++++++++++++++++ NetKVM/Common/ndis56common.h | 4 ---- NetKVM/wlh/ParaNdis6_Impl.cpp | 18 ++++++++++++++++++ 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/NetKVM/Common/ParaNdis_Common.cpp b/NetKVM/Common/ParaNdis_Common.cpp index a1e9a52d..fa7ad7e2 100755 --- a/NetKVM/Common/ParaNdis_Common.cpp +++ b/NetKVM/Common/ParaNdis_Common.cpp @@ -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); diff --git a/NetKVM/Common/ParaNdis_Util.cpp b/NetKVM/Common/ParaNdis_Util.cpp index 90f9312a..6edbc13d 100644 --- a/NetKVM/Common/ParaNdis_Util.cpp +++ b/NetKVM/Common/ParaNdis_Util.cpp @@ -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; } } diff --git a/NetKVM/Common/ndis56common.h b/NetKVM/Common/ndis56common.h index faeac1b1..b8349987 100755 --- a/NetKVM/Common/ndis56common.h +++ b/NetKVM/Common/ndis56common.h @@ -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; diff --git a/NetKVM/wlh/ParaNdis6_Impl.cpp b/NetKVM/wlh/ParaNdis6_Impl.cpp index cedfdebd..e24edfea 100755 --- a/NetKVM/wlh/ParaNdis6_Impl.cpp +++ b/NetKVM/wlh/ParaNdis6_Impl.cpp @@ -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)