From: Narcisa Ana Maria Vasile <navasile@linux.microsoft.com>
To: dev@dpdk.org, thomas@monjalon.net, haramakr@linux.microsoft.com,
ocardona@microsoft.com, pallavi.kadam@intel.com,
dmitry.kozliuk@gmail.com
Cc: ranjit.menon@intel.com, dmitrym@microsoft.com,
Harini Ramakrishnan <haramakr@microsoft.com>
Subject: [dpdk-dev] [PATCH 12/22] uio: Fix 64 bit BARs mapping
Date: Thu, 13 Aug 2020 16:21:35 -0700 [thread overview]
Message-ID: <1597360905-74106-13-git-send-email-navasile@linux.microsoft.com> (raw)
In-Reply-To: <1597360905-74106-1-git-send-email-navasile@linux.microsoft.com>
From: Harini Ramakrishnan <haramakr@microsoft.com>
---
kernel/windows/netuio/netuio.inf | 12 +-
kernel/windows/netuio/netuio_dev.c | 181 +++++++++++++++++------
kernel/windows/netuio/netuio_dev.h | 15 +-
kernel/windows/netuio/netuio_drv.c | 43 +++---
kernel/windows/netuio/netuio_drv.h | 1 +
kernel/windows/netuio/netuio_interface.h | 10 +-
kernel/windows/netuio/netuio_queue.c | 176 ++++++++++++++--------
kernel/windows/netuio/netuio_queue.h | 2 +
8 files changed, 297 insertions(+), 143 deletions(-)
diff --git a/kernel/windows/netuio/netuio.inf b/kernel/windows/netuio/netuio.inf
index b1696cc50..4c4d5e047 100644
--- a/kernel/windows/netuio/netuio.inf
+++ b/kernel/windows/netuio/netuio.inf
@@ -38,7 +38,7 @@
Signature="$WINDOWS NT$"
Class=Net
ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318}
-Provider=%ManufacturerName%
+Provider=%Intel%
CatalogFile=netuio.cat
DriverVer=
@@ -47,7 +47,8 @@ DriverVer=
;*****************************************
[Manufacturer]
-%ManufacturerName%=Standard,NT$ARCH$
+%Intel%=Standard,NT$ARCH$
+%Broadcom%=Broadcom,NT$ARCH$
[Standard.NT$ARCH$]
%F1583.netuio.Description%=netuio_Device, PCI\VEN_8086&DEV_1583
@@ -56,6 +57,9 @@ DriverVer=
%F37D0.netuio.Description%=netuio_Device, PCI\VEN_8086&DEV_37D0
%F153B.netuio.Description%=netuio_Device, PCI\VEN_8086&DEV_153B
+[Broadcom.NT$ARCH$]
+%F16D7.netuio.Description%=netuio_Device, PCI\VEN_14E4&DEV_16D7
+
[netuio_Device.NT]
CopyFiles=Drivers_Dir
@@ -113,7 +117,8 @@ KmdfLibraryVersion = $KMDFVERSION$
[Strings]
SPSVCINST_ASSOCSERVICE= 0x00000002
-ManufacturerName="Intel"
+Intel = "Intel"
+Broadcom = "Broadcom Corporation"
ClassName = "Intel(R) DPDK netUIO Driver"
DiskName = "DPDK netUIO Installation Disk"
F1583.netuio.Description = "DPDK netUIO for Intel(R) Ethernet Converged Network Adapter XL710-Q2"
@@ -121,5 +126,6 @@ F158A.netuio.Description = "DPDK netUIO for Intel(R) Ethernet Network Adapter XX
F158B.netuio.Description = "DPDK netUIO for Intel(R) Ethernet Network Adapter XXV710-DA1"
F37D0.netuio.Description = "DPDK netUIO for Intel(R) Ethernet Connection X722"
F153B.netuio.Description = "DPDK netUIO for Intel(R) Ethernet Connection I217-V"
+F16D7.netuio.Description = "DPDK netUIO for Broadcom P225p NetXtreme-E Dual-port 10Gb/25Gb Ethernet PCIe Adapter"
netuio.DeviceDesc = "netuio Device"
netuio.SVCDESC = "netuio Service"
diff --git a/kernel/windows/netuio/netuio_dev.c b/kernel/windows/netuio/netuio_dev.c
index a1fe447f7..3b5c95e84 100644
--- a/kernel/windows/netuio/netuio_dev.c
+++ b/kernel/windows/netuio/netuio_dev.c
@@ -27,16 +27,28 @@ Return Value:
NTSTATUS
netuio_create_device(_Inout_ PWDFDEVICE_INIT DeviceInit)
{
- WDF_OBJECT_ATTRIBUTES deviceAttributes;
- WDFDEVICE device = NULL;
NTSTATUS status;
+ WDFDEVICE device = NULL;
+
+ WDF_OBJECT_ATTRIBUTES deviceAttributes;
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
+ WDF_FILEOBJECT_CONFIG fileConfig;
PAGED_CODE();
- WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, NETUIO_CONTEXT_DATA);
+ // Register PnP power management callbacks
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
+ pnpPowerCallbacks.EvtDevicePrepareHardware = netuio_evt_prepare_hw;
+ pnpPowerCallbacks.EvtDeviceReleaseHardware = netuio_evt_release_hw;
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
+
+ // Register callbacks for when a HANDLE is opened or closed.
+ WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK, netuio_evt_file_cleanup);
+ WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES);
// Set the device context cleanup callback.
// This function will be called when the WDF Device Object associated to the current device is destroyed
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, NETUIO_CONTEXT_DATA);
deviceAttributes.EvtCleanupCallback = netuio_evt_device_context_cleanup;
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
@@ -88,63 +100,112 @@ netuio_map_hw_resources(_In_ WDFDEVICE Device, _In_ WDFCMRESLIST Resources, _In_
{
UNREFERENCED_PARAMETER(Resources);
- NTSTATUS status = STATUS_SUCCESS;
+ NTSTATUS status;
PNETUIO_CONTEXT_DATA netuio_contextdata;
netuio_contextdata = netuio_get_context_data(Device);
- if (!netuio_contextdata)
+ if (!netuio_contextdata) {
return STATUS_UNSUCCESSFUL;
+ }
- PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
- UINT8 bar_index = 0;
+ PCI_COMMON_HEADER pci_config = {0};
+ ULONG bytes_returned;
- // Collect device BAR resources from the ResourcesTranslated object
- for (ULONG idx = 0; idx < WdfCmResourceListGetCount(ResourcesTranslated); idx++) {
- descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, idx);
- if (!descriptor) {
- status = STATUS_DEVICE_CONFIGURATION_ERROR;
- goto end;
+ // Read PCI configuration space
+ bytes_returned = netuio_contextdata->bus_interface.GetBusData(
+ netuio_contextdata->bus_interface.Context,
+ PCI_WHICHSPACE_CONFIG,
+ &pci_config,
+ 0,
+ sizeof(pci_config));
+
+ if (bytes_returned != sizeof(pci_config)) {
+ status = STATUS_NOT_SUPPORTED;
+ goto end;
+ }
+
+ // Device type is implictly enforced by .inf
+ ASSERT(PCI_CONFIGURATION_TYPE(&pci_config) == PCI_DEVICE_TYPE);
+
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
+ ULONG next_descriptor = 0;
+ ULONGLONG bar_addr = 0;
+ ULONG curr_bar = 0;
+ ULONG prev_bar = 0;
+
+ for (INT bar_index = 0; bar_index < PCI_MAX_BAR; bar_index++) {
+ prev_bar = curr_bar;
+ curr_bar = pci_config.u.type0.BaseAddresses[bar_index];
+ if (curr_bar == 0 || (prev_bar & PCI_TYPE_64BIT)) {
+ // Skip this bar
+ netuio_contextdata->bar[bar_index].base_addr.QuadPart = 0;
+ netuio_contextdata->bar[bar_index].size = 0;
+ netuio_contextdata->bar[bar_index].virt_addr = 0;
+
+ netuio_contextdata->dpdk_hw[bar_index].mdl = NULL;
+ netuio_contextdata->dpdk_hw[bar_index].mem.size = 0;
+
+ continue;
}
- switch (descriptor->Type) {
- case CmResourceTypeMemory:
- // Retrieve and map the BARs
- netuio_contextdata->bar[bar_index].base_addr.QuadPart = descriptor->u.Memory.Start.QuadPart;
- netuio_contextdata->bar[bar_index].size = descriptor->u.Memory.Length;
- netuio_contextdata->bar[bar_index].virt_addr =
- MmMapIoSpace(descriptor->u.Memory.Start, descriptor->u.Memory.Length, MmNonCached);
+ // Find next CmResourceTypeMemory
+ do {
+ descriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, next_descriptor);
+ next_descriptor++;
- if (netuio_contextdata->bar[bar_index].virt_addr == NULL) {
- status = STATUS_UNSUCCESSFUL;
+ if (descriptor == NULL) {
+ status = STATUS_DEVICE_CONFIGURATION_ERROR;
goto end;
}
+ } while (descriptor->Type != CmResourceTypeMemory);
- bar_index++;
- break;
+ // Assert that we have the correct descriptor
+ ASSERT((descriptor->Flags & CM_RESOURCE_MEMORY_BAR) != 0);
- // Don't handle any other resource type
- // This could be device-private type added by the PCI bus driver.
- case CmResourceTypeInterrupt:
- default:
- break;
+ if (curr_bar & PCI_TYPE_64BIT) {
+ ASSERT(bar_index != PCI_TYPE0_ADDRESSES - 1);
+ bar_addr = ((ULONGLONG)pci_config.u.type0.BaseAddresses[bar_index + 1] << 32) | (curr_bar & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
+ }
+ else
+ {
+ bar_addr = curr_bar & PCI_ADDRESS_MEMORY_ADDRESS_MASK;
}
- }
- // Allocate an MDL for the device BAR, so that we can map it to the user's process context later...
- if (status == STATUS_SUCCESS) {
- // Bar 0 is typically the HW BAR
- if (netuio_contextdata->bar[0].virt_addr) {
- netuio_contextdata->dpdk_hw.mdl = IoAllocateMdl(netuio_contextdata->bar[0].virt_addr, (ULONG)netuio_contextdata->bar[0].size, FALSE, FALSE, NULL);
- if (!netuio_contextdata->dpdk_hw.mdl) {
- status = STATUS_INSUFFICIENT_RESOURCES;
- goto end;
- }
- netuio_contextdata->dpdk_hw.mem.size = netuio_contextdata->bar[0].size;
+ ASSERT((ULONGLONG)descriptor->u.Memory.Start.QuadPart == bar_addr);
+
+ // Retrieve and map the BARs
+ netuio_contextdata->bar[bar_index].base_addr.QuadPart = descriptor->u.Memory.Start.QuadPart;
+ netuio_contextdata->bar[bar_index].size = descriptor->u.Memory.Length;
+ netuio_contextdata->bar[bar_index].virt_addr = MmMapIoSpace(descriptor->u.Memory.Start,
+ descriptor->u.Memory.Length,
+ MmNonCached);
+ if (netuio_contextdata->bar[bar_index].virt_addr == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto end;
}
- }
+
+ // Allocate an MDL for the device BAR, so we can map it to the user's process context later.
+ netuio_contextdata->dpdk_hw[bar_index].mdl = IoAllocateMdl(netuio_contextdata->bar[bar_index].virt_addr,
+ (ULONG)netuio_contextdata->bar[bar_index].size,
+ FALSE,
+ FALSE,
+ NULL);
+ if (!netuio_contextdata->dpdk_hw[bar_index].mdl) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto end;
+ }
+
+ netuio_contextdata->dpdk_hw[bar_index].mem.size = netuio_contextdata->bar[bar_index].size;
+ } // for bar_index
+
+ status = STATUS_SUCCESS;
end:
+ if (status != STATUS_SUCCESS) {
+ netuio_free_hw_resources(Device);
+ }
+
return status;
}
@@ -155,15 +216,21 @@ netuio_free_hw_resources(_In_ WDFDEVICE Device)
netuio_contextdata = netuio_get_context_data(Device);
if (netuio_contextdata) {
- // Free the allocated MDL
- if (netuio_contextdata->dpdk_hw.mdl)
- IoFreeMdl(netuio_contextdata->dpdk_hw.mdl);
-
- // Unmap all the BAR regions previously mapped
for (UINT8 bar_index = 0; bar_index < PCI_MAX_BAR; bar_index++) {
- if (netuio_contextdata->bar[bar_index].virt_addr)
+
+ // Free the allocated MDLs
+ if (netuio_contextdata->dpdk_hw[bar_index].mdl) {
+ IoFreeMdl(netuio_contextdata->dpdk_hw[bar_index].mdl);
+ }
+
+ // Unmap all the BAR regions previously mapped
+ if (netuio_contextdata->bar[bar_index].virt_addr) {
MmUnmapIoSpace(netuio_contextdata->bar[bar_index].virt_addr, netuio_contextdata->bar[bar_index].size);
+ }
}
+
+ RtlZeroMemory(netuio_contextdata->dpdk_hw, sizeof(netuio_contextdata->dpdk_hw));
+ RtlZeroMemory(netuio_contextdata->bar, sizeof(netuio_contextdata->bar));
}
}
@@ -246,13 +313,16 @@ create_device_specific_symbolic_link(_In_ WDFOBJECT device)
static NTSTATUS
allocate_usermemory_segment(_In_ WDFOBJECT device)
{
- NTSTATUS status = STATUS_SUCCESS;
+ NTSTATUS status;
PNETUIO_CONTEXT_DATA netuio_contextdata;
netuio_contextdata = netuio_get_context_data(device);
if (!netuio_contextdata)
- return STATUS_UNSUCCESSFUL;
+ {
+ status = STATUS_INVALID_DEVICE_STATE;
+ goto end;
+ }
PHYSICAL_ADDRESS lowest_acceptable_address;
PHYSICAL_ADDRESS highest_acceptable_address;
@@ -287,7 +357,14 @@ allocate_usermemory_segment(_In_ WDFOBJECT device)
// Store the region's physical address
netuio_contextdata->dpdk_seg.mem.phys_addr = MmGetPhysicalAddress(netuio_contextdata->dpdk_seg.mem.virt_addr);
+ status = STATUS_SUCCESS;
+
end:
+ if (status != STATUS_SUCCESS)
+ {
+ free_usermemory_segment(device);
+ }
+
return status;
}
@@ -299,9 +376,15 @@ free_usermemory_segment(_In_ WDFOBJECT device)
if (netuio_contextdata) {
if (netuio_contextdata->dpdk_seg.mdl)
+ {
IoFreeMdl(netuio_contextdata->dpdk_seg.mdl);
+ netuio_contextdata->dpdk_seg.mdl = NULL;
+ }
if (netuio_contextdata->dpdk_seg.mem.virt_addr)
+ {
MmFreeContiguousMemory(netuio_contextdata->dpdk_seg.mem.virt_addr);
+ netuio_contextdata->dpdk_seg.mem.virt_addr = NULL;
+ }
}
}
diff --git a/kernel/windows/netuio/netuio_dev.h b/kernel/windows/netuio/netuio_dev.h
index a19a4fb42..59956720e 100644
--- a/kernel/windows/netuio/netuio_dev.h
+++ b/kernel/windows/netuio/netuio_dev.h
@@ -12,7 +12,6 @@ EXTERN_C_START
#include "netuio_interface.h"
// Constants
-#define PCI_MAX_BAR 3
#define USER_MEMORY_SEGMENT_SIZE (256ULL * 1024ULL * 1024ULL) // 256MB
struct pci_bar {
@@ -29,13 +28,13 @@ struct mem_map_region {
// The device context performs the same job as a WDM device extension in the driver frameworks
typedef struct _NETUIO_CONTEXT_DATA
{
- WDFDEVICE wdf_device; // WDF device handle to the FDO
- BUS_INTERFACE_STANDARD bus_interface; // Bus interface for config space access
- struct pci_bar bar[PCI_MAX_BAR]; // device BARs
- struct dev_addr addr; // B:D:F details of device
- USHORT dev_numa_node; // The NUMA node of the device
- struct mem_map_region dpdk_hw; // mapped region for the device's register space
- struct mem_map_region dpdk_seg; // mapped region allocated for DPDK process use
+ WDFDEVICE wdf_device; // WDF device handle to the FDO
+ BUS_INTERFACE_STANDARD bus_interface; // Bus interface for config space access
+ struct pci_bar bar[PCI_MAX_BAR]; // device BARs
+ struct dev_addr addr; // B:D:F details of device
+ USHORT dev_numa_node; // The NUMA node of the device
+ struct mem_map_region dpdk_hw[PCI_MAX_BAR]; // mapped region for the device's register space
+ struct mem_map_region dpdk_seg; // mapped region allocated for DPDK process use
} NETUIO_CONTEXT_DATA, *PNETUIO_CONTEXT_DATA;
diff --git a/kernel/windows/netuio/netuio_drv.c b/kernel/windows/netuio/netuio_drv.c
index d45a9ec4f..554629c98 100644
--- a/kernel/windows/netuio/netuio_drv.c
+++ b/kernel/windows/netuio/netuio_drv.c
@@ -62,25 +62,8 @@ Return Value:
NTSTATUS
netuio_evt_device_add(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
{
- NTSTATUS status;
- WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
-
UNREFERENCED_PARAMETER(Driver);
-
- PAGED_CODE();
-
- // Zero out the PnpPowerCallbacks structure
- WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
-
- // Register Plug-aNd-Play and power management callbacks
- pnpPowerCallbacks.EvtDevicePrepareHardware = netuio_evt_prepare_hw;
- pnpPowerCallbacks.EvtDeviceReleaseHardware = netuio_evt_release_hw;
-
- WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
-
- status = netuio_create_device(DeviceInit);
-
- return status;
+ return netuio_create_device(DeviceInit);
}
/*
@@ -140,3 +123,27 @@ netuio_evt_driver_context_cleanup(_In_ WDFOBJECT DriverObject)
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_NETUIO_INFO_LEVEL, "netUIO Driver unloaded.\n");
PAGED_CODE();
}
+
+/*
+Routine Description :
+ EVT_WDF_FILE_CLEANUP callback, called when user process handle is closed.
+
+ Undoes IOCTL_NETUIO_MAP_HW_INTO_USERMODE.
+
+Return value :
+ None
+-*/
+VOID
+netuio_evt_file_cleanup(_In_ WDFFILEOBJECT FileObject)
+{
+ WDFDEVICE device;
+ PNETUIO_CONTEXT_DATA netuio_contextdata;
+
+ device = WdfFileObjectGetDevice(FileObject);
+ netuio_contextdata = netuio_get_context_data(device);
+
+ if (netuio_contextdata)
+ {
+ netuio_unmap_address_from_user_process(netuio_contextdata);
+ }
+}
diff --git a/kernel/windows/netuio/netuio_drv.h b/kernel/windows/netuio/netuio_drv.h
index 39d7f301e..5dc778625 100644
--- a/kernel/windows/netuio/netuio_drv.h
+++ b/kernel/windows/netuio/netuio_drv.h
@@ -27,6 +27,7 @@ EVT_WDF_DRIVER_DEVICE_ADD netuio_evt_device_add;
EVT_WDF_OBJECT_CONTEXT_CLEANUP netuio_evt_driver_context_cleanup;
EVT_WDF_DEVICE_PREPARE_HARDWARE netuio_evt_prepare_hw;
EVT_WDF_DEVICE_RELEASE_HARDWARE netuio_evt_release_hw;
+EVT_WDF_FILE_CLOSE netuio_evt_file_cleanup;
EXTERN_C_END
diff --git a/kernel/windows/netuio/netuio_interface.h b/kernel/windows/netuio/netuio_interface.h
index f84ee895c..82fb1cb50 100644
--- a/kernel/windows/netuio/netuio_interface.h
+++ b/kernel/windows/netuio/netuio_interface.h
@@ -22,8 +22,8 @@ DEFINE_GUID (GUID_DEVINTERFACE_netUIO, 0x08336f60,0x0679,0x4c6c,0x85,0xd2,0xae,0
#define NETUIO_DRIVER_NAME _T("netuio")
// IOCTL code definitions
-#define IOCTL_NETUIO_GET_HW_DATA CTL_CODE(FILE_DEVICE_NETWORK, 51, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-#define IOCTL_NETUIO_PCI_CONFIG_IO CTL_CODE(FILE_DEVICE_NETWORK, 52, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_NETUIO_MAP_HW_INTO_USERMODE CTL_CODE(FILE_DEVICE_NETWORK, 51, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_NETUIO_PCI_CONFIG_IO CTL_CODE(FILE_DEVICE_NETWORK, 52, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
struct mem_region {
UINT64 size; // memory region size
@@ -43,13 +43,13 @@ enum pci_io {
PCI_IO_WRITE = 1
};
+#define PCI_MAX_BAR 6
+
struct dpdk_private_info
{
- struct mem_region hw;
+ struct mem_region hw[PCI_MAX_BAR];
struct mem_region ms;
struct dev_addr dev_addr;
- struct mem_region bar1;
-// struct mem_region bar2;
UINT16 dev_id;
UINT16 sub_dev_id;
USHORT dev_numa_node;
diff --git a/kernel/windows/netuio/netuio_queue.c b/kernel/windows/netuio/netuio_queue.c
index 760b4a7e5..9c7ff7d06 100644
--- a/kernel/windows/netuio/netuio_queue.c
+++ b/kernel/windows/netuio/netuio_queue.c
@@ -11,54 +11,113 @@
#pragma alloc_text (PAGE, netuio_queue_initialize)
#endif
-VOID netuio_read_PCI_config(PNETUIO_CONTEXT_DATA netuio_contextdata, ULONG offset, UINT32 access_size, _Out_ UINT64 *output)
-{
- *output = 0;
- netuio_contextdata->bus_interface.GetBusData(netuio_contextdata->bus_interface.Context,
- PCI_WHICHSPACE_CONFIG,
- output,
- offset,
- access_size);
-}
-
-VOID netuio_write_PCI_config(PNETUIO_CONTEXT_DATA netuio_contextdata, ULONG offset, UINT32 access_size, union dpdk_pci_config_io_data const *input)
-{
- netuio_contextdata->bus_interface.SetBusData(netuio_contextdata->bus_interface.Context,
- PCI_WHICHSPACE_CONFIG,
- (PVOID)input,
- offset,
- access_size);
-}
-
-static NTSTATUS
+static void
netuio_handle_get_hw_data_request(_In_ WDFREQUEST Request, _In_ PNETUIO_CONTEXT_DATA netuio_contextdata,
_In_ PVOID outputBuf, _In_ size_t outputBufSize)
{
- NTSTATUS status = STATUS_SUCCESS;
-
WDF_REQUEST_PARAMETERS params;
WDF_REQUEST_PARAMETERS_INIT(¶ms);
WdfRequestGetParameters(Request, ¶ms);
- if (!netuio_contextdata || (outputBufSize != sizeof(struct dpdk_private_info))) {
- status = STATUS_INVALID_PARAMETER;
- goto end;
- }
+ ASSERT(outputBufSize == sizeof(struct dpdk_private_info));
struct dpdk_private_info *dpdk_pvt_info = (struct dpdk_private_info *)outputBuf;
RtlZeroMemory(dpdk_pvt_info, outputBufSize);
- dpdk_pvt_info->hw.phys_addr.QuadPart = netuio_contextdata->bar[0].base_addr.QuadPart;
- dpdk_pvt_info->hw.user_mapped_virt_addr = netuio_contextdata->dpdk_hw.mem.user_mapped_virt_addr;
- dpdk_pvt_info->hw.size = netuio_contextdata->bar[0].size;
+ for (ULONG idx = 0; idx < PCI_MAX_BAR; idx++) {
+ dpdk_pvt_info->hw[idx].phys_addr.QuadPart = netuio_contextdata->bar[idx].base_addr.QuadPart;
+ dpdk_pvt_info->hw[idx].user_mapped_virt_addr = netuio_contextdata->dpdk_hw[idx].mem.user_mapped_virt_addr;
+ dpdk_pvt_info->hw[idx].size = netuio_contextdata->bar[idx].size;
+ }
dpdk_pvt_info->ms.phys_addr.QuadPart = netuio_contextdata->dpdk_seg.mem.phys_addr.QuadPart;
dpdk_pvt_info->ms.user_mapped_virt_addr = netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr;
dpdk_pvt_info->ms.size = netuio_contextdata->dpdk_seg.mem.size;
+}
+
+/*
+Routine Description:
+ Maps address ranges into the usermode process's address space. The following
+ ranges are mapped:
+
+ * Any PCI BARs that our device was assigned
+ * The scratch buffer of contiguous pages
+
+Return Value:
+ NTSTATUS
+*/
+static NTSTATUS
+netuio_map_address_into_user_process(_In_ PNETUIO_CONTEXT_DATA netuio_contextdata)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ // Map the scratch memory regions to the user's process context
+ MmBuildMdlForNonPagedPool(netuio_contextdata->dpdk_seg.mdl);
+ netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr =
+ MmMapLockedPagesSpecifyCache(
+ netuio_contextdata->dpdk_seg.mdl, UserMode, MmCached,
+ NULL, FALSE, (NormalPagePriority | MdlMappingNoExecute));
+
+ if (netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto end;
+ }
+
+ // Map any device BAR(s) to the user's process context
+ for (INT idx = 0; idx < PCI_MAX_BAR; idx++) {
+ if (netuio_contextdata->dpdk_hw[idx].mdl == NULL) {
+ continue;
+ }
+
+ MmBuildMdlForNonPagedPool(netuio_contextdata->dpdk_hw[idx].mdl);
+ netuio_contextdata->dpdk_hw[idx].mem.user_mapped_virt_addr =
+ MmMapLockedPagesSpecifyCache(
+ netuio_contextdata->dpdk_hw[idx].mdl, UserMode, MmCached,
+ NULL, FALSE, (NormalPagePriority | MdlMappingNoExecute));
+
+ if (netuio_contextdata->dpdk_hw[idx].mem.user_mapped_virt_addr == NULL) {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto end;
+ }
+ }
+
end:
+ if (status != STATUS_SUCCESS) {
+ netuio_unmap_address_from_user_process(netuio_contextdata);
+ }
+
return status;
}
+/*
+Routine Description:
+ Unmaps all address ranges from the usermode process address space.
+ MUST be called in the context of the same process which created
+ the mapping.
+
+Return Value:
+ None
+ */
+VOID
+netuio_unmap_address_from_user_process(_In_ PNETUIO_CONTEXT_DATA netuio_contextdata)
+{
+ if (netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr != NULL) {
+ MmUnmapLockedPages(
+ netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr,
+ netuio_contextdata->dpdk_seg.mdl);
+ netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr = NULL;
+ }
+
+ for (INT idx = 0; idx < PCI_MAX_BAR; idx++) {
+ if (netuio_contextdata->dpdk_hw[idx].mem.user_mapped_virt_addr != NULL) {
+ MmUnmapLockedPages(
+ netuio_contextdata->dpdk_hw[idx].mem.user_mapped_virt_addr,
+ netuio_contextdata->dpdk_hw[idx].mdl);
+ netuio_contextdata->dpdk_hw[idx].mem.user_mapped_virt_addr = NULL;
+ }
+ }
+}
+
/*
Routine Description:
The I/O dispatch callbacks for the frameworks device object are configured here.
@@ -123,7 +182,7 @@ netuio_evt_IO_device_control(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,
netuio_contextdata = netuio_get_context_data(device);
switch (IoControlCode) {
- case IOCTL_NETUIO_GET_HW_DATA:
+ case IOCTL_NETUIO_MAP_HW_INTO_USERMODE:
// First retrieve the input buffer and see if it matches our device
status = WdfRequestRetrieveInputBuffer(Request, sizeof(struct dpdk_private_info), &input_buf, &input_buf_size);
if (!NT_SUCCESS(status)) {
@@ -140,35 +199,29 @@ netuio_evt_IO_device_control(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,
break;
}
- // Map the previously allocated/defined memory regions to the user's process context
- MmBuildMdlForNonPagedPool(netuio_contextdata->dpdk_hw.mdl);
- netuio_contextdata->dpdk_hw.mem.user_mapped_virt_addr =
- MmMapLockedPagesSpecifyCache(netuio_contextdata->dpdk_hw.mdl, UserMode, MmCached,
- NULL, FALSE, (NormalPagePriority | MdlMappingNoExecute));
-
- MmBuildMdlForNonPagedPool(netuio_contextdata->dpdk_seg.mdl);
- netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr =
- MmMapLockedPagesSpecifyCache(netuio_contextdata->dpdk_seg.mdl, UserMode, MmCached,
- NULL, FALSE, (NormalPagePriority | MdlMappingNoExecute));
-
- if (!netuio_contextdata->dpdk_hw.mem.user_mapped_virt_addr && !netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr) {
- status = STATUS_INSUFFICIENT_RESOURCES;
+ if (netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr != NULL) {
+ status = STATUS_ALREADY_COMMITTED;
break;
}
- // Zero out the physically contiguous block
- RtlZeroMemory(netuio_contextdata->dpdk_seg.mem.virt_addr, netuio_contextdata->dpdk_seg.mem.size);
-
// Return relevant data to the caller
status = WdfRequestRetrieveOutputBuffer(Request, sizeof(struct dpdk_private_info), &output_buf, &output_buf_size);
if (!NT_SUCCESS(status)) {
status = STATUS_INVALID_BUFFER_SIZE;
break;
}
+
+ // Zero out the physically contiguous block
+ RtlZeroMemory(netuio_contextdata->dpdk_seg.mem.virt_addr, netuio_contextdata->dpdk_seg.mem.size);
+
+ status = netuio_map_address_into_user_process(netuio_contextdata);
+ if (status != STATUS_SUCCESS) {
+ break;
+ }
+
ASSERT(output_buf_size == OutputBufferLength);
- status = netuio_handle_get_hw_data_request(Request, netuio_contextdata, output_buf, output_buf_size);
- if (NT_SUCCESS(status))
- bytes_returned = output_buf_size;
+ netuio_handle_get_hw_data_request(Request, netuio_contextdata, output_buf, output_buf_size);
+ bytes_returned = output_buf_size;
break;
@@ -206,19 +259,22 @@ netuio_evt_IO_device_control(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,
ASSERT(output_buf_size == OutputBufferLength);
if (dpdk_pci_io_input->op == PCI_IO_READ) {
- netuio_read_PCI_config(netuio_contextdata,
- dpdk_pci_io_input->offset,
- dpdk_pci_io_input->access_size,
- (UINT64*)output_buf);
-
- bytes_returned = sizeof(UINT64);
+ *(UINT64 *)output_buf = 0;
+ bytes_returned = netuio_contextdata->bus_interface.GetBusData(
+ netuio_contextdata->bus_interface.Context,
+ PCI_WHICHSPACE_CONFIG,
+ output_buf,
+ dpdk_pci_io_input->offset,
+ dpdk_pci_io_input->access_size);
}
else if (dpdk_pci_io_input->op == PCI_IO_WRITE) {
- netuio_write_PCI_config(netuio_contextdata,
- dpdk_pci_io_input->offset,
- dpdk_pci_io_input->access_size,
- &dpdk_pci_io_input->data);
- bytes_returned = 0;
+ // returns bytes written
+ bytes_returned = netuio_contextdata->bus_interface.SetBusData(
+ netuio_contextdata->bus_interface.Context,
+ PCI_WHICHSPACE_CONFIG,
+ (PVOID)&dpdk_pci_io_input->data,
+ dpdk_pci_io_input->offset,
+ dpdk_pci_io_input->access_size);
}
else {
status = STATUS_INVALID_PARAMETER;
diff --git a/kernel/windows/netuio/netuio_queue.h b/kernel/windows/netuio/netuio_queue.h
index 6a0306516..90fdb4008 100644
--- a/kernel/windows/netuio/netuio_queue.h
+++ b/kernel/windows/netuio/netuio_queue.h
@@ -17,6 +17,8 @@ typedef struct _QUEUE_CONTEXT {
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext)
+VOID
+netuio_unmap_address_from_user_process(_In_ PNETUIO_CONTEXT_DATA netuio_contextdata);
NTSTATUS
netuio_queue_initialize(_In_ WDFDEVICE hDevice);
--
2.23.0.vfs.1.1.63.g5a5ad7f
next prev parent reply other threads:[~2020-08-13 23:24 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-13 23:21 [dpdk-dev] [PATCH 00/22] windows/netuio: add netuio driver for Windows Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 01/22] init DPDK repository Narcisa Ana Maria Vasile
2020-08-14 20:02 ` Dmitry Kozlyuk
2020-08-13 23:21 ` [dpdk-dev] [PATCH 02/22] Initial commit of UIO driver for Windows Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 03/22] Added new core libraries " Narcisa Ana Maria Vasile
2020-08-14 20:02 ` Dmitry Kozlyuk
2020-08-13 23:21 ` [dpdk-dev] [PATCH 04/22] Windows DPDK libraries and applications have now been updated to the latest public release v18.08, of the main DPDK source Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 05/22] doc: remove embedded buffer from Windows UIO ioctl Narcisa Ana Maria Vasile
2020-08-14 20:02 ` Dmitry Kozlyuk
2020-08-13 23:21 ` [dpdk-dev] [PATCH 06/22] Windows DPDK libraries and applications have now been updated to the latest public release v18.08, of the main DPDK source Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 07/22] doc: change the Windows UIO driver's default security descriptor to admin only Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 08/22] doc: remove lower bound on mapped address from Windows UIO driver Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 09/22] doc: remove embedded buffer from Windows UIO ioctl Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 10/22] uio: move SDDL string to INF on Windows Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 11/22] Updated Source and Project files to use Clang toolset Narcisa Ana Maria Vasile
2020-08-14 20:02 ` Dmitry Kozlyuk
2020-08-13 23:21 ` Narcisa Ana Maria Vasile [this message]
2020-08-13 23:21 ` [dpdk-dev] [PATCH 13/22] Update .gitignore and create .gitattributes Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 14/22] uio: Use local time when verifying INF DriverVer Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 15/22] uio: Remove co-installers section from inf Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 16/22] uio: Wrap call into try/except block Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 17/22] uio: Use request handler that guarantees execution in correct context Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 18/22] uio: Change the device setup class to a custom one Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 19/22] Enable DMA remapping through INF directive Narcisa Ana Maria Vasile
2020-08-13 23:21 ` [dpdk-dev] [PATCH 20/22] license: update headers with BSD 3-clause license: Narcisa Ana Maria Vasile
2020-08-14 20:02 ` Dmitry Kozlyuk
2020-08-13 23:21 ` [dpdk-dev] [PATCH 21/22] doc: updating REAME for NetUIO driver Narcisa Ana Maria Vasile
2020-08-14 20:11 ` Dmitry Kozlyuk
2020-08-13 23:21 ` [dpdk-dev] [PATCH 22/22] Move all files under windows folder Narcisa Ana Maria Vasile
2020-08-14 14:56 ` [dpdk-dev] [PATCH 00/22] windows/netuio: add netuio driver for Windows Harini Ramakrishnan
2020-08-14 20:01 ` Dmitry Kozlyuk
2020-08-14 20:26 ` Narcisa Ana Maria Vasile
2020-08-14 20:45 ` Omar Cardona
2020-08-14 20:57 ` Dmitry Kozlyuk
2020-08-14 22:51 ` Ranjit Menon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1597360905-74106-13-git-send-email-navasile@linux.microsoft.com \
--to=navasile@linux.microsoft.com \
--cc=dev@dpdk.org \
--cc=dmitry.kozliuk@gmail.com \
--cc=dmitrym@microsoft.com \
--cc=haramakr@linux.microsoft.com \
--cc=haramakr@microsoft.com \
--cc=ocardona@microsoft.com \
--cc=pallavi.kadam@intel.com \
--cc=ranjit.menon@intel.com \
--cc=thomas@monjalon.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).