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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.