All of lore.kernel.org
 help / color / mirror / Atom feed
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,
	Narcisa Vasile <navasile@microsoft.com>
Subject: [dpdk-dev] [PATCH 17/22] uio: Use request handler that guarantees execution in correct context
Date: Thu, 13 Aug 2020 16:21:40 -0700	[thread overview]
Message-ID: <1597360905-74106-18-git-send-email-navasile@linux.microsoft.com> (raw)
In-Reply-To: <1597360905-74106-1-git-send-email-navasile@linux.microsoft.com>

From: Narcisa Vasile <navasile@microsoft.com>

Use EvtIoInCallerContext to assure the requests are handled in the
right user thread context. If the request does not need to be handled in
a specific context, send it back to framework.

Signed-off-by: Narcisa Vasile <navasile@microsoft.com>
Reported-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
---
 kernel/windows/netuio/netuio_dev.c   |   1 +
 kernel/windows/netuio/netuio_dev.h   |   1 -
 kernel/windows/netuio/netuio_queue.c | 242 ++++++++++++++++-----------
 kernel/windows/netuio/netuio_queue.h |   2 +
 4 files changed, 145 insertions(+), 101 deletions(-)

diff --git a/kernel/windows/netuio/netuio_dev.c b/kernel/windows/netuio/netuio_dev.c
index 3b5c95e84..e4e4570bc 100644
--- a/kernel/windows/netuio/netuio_dev.c
+++ b/kernel/windows/netuio/netuio_dev.c
@@ -50,6 +50,7 @@ netuio_create_device(_Inout_ PWDFDEVICE_INIT DeviceInit)
     // 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;
+    WdfDeviceInitSetIoInCallerContextCallback(DeviceInit, netuio_evt_IO_in_caller_context);
 
     status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
 
diff --git a/kernel/windows/netuio/netuio_dev.h b/kernel/windows/netuio/netuio_dev.h
index 59956720e..6a9b1ff82 100644
--- a/kernel/windows/netuio/netuio_dev.h
+++ b/kernel/windows/netuio/netuio_dev.h
@@ -58,7 +58,6 @@ static NTSTATUS create_device_specific_symbolic_link(_In_ WDFOBJECT device);
 static NTSTATUS allocate_usermemory_segment(_In_ WDFOBJECT device);
 static VOID free_usermemory_segment(_In_ WDFOBJECT device);
 
-
 EXTERN_C_END
 
 #endif // NETUIO_DEV_H
diff --git a/kernel/windows/netuio/netuio_queue.c b/kernel/windows/netuio/netuio_queue.c
index c2bc998dc..7714a4d3a 100644
--- a/kernel/windows/netuio/netuio_queue.c
+++ b/kernel/windows/netuio/netuio_queue.c
@@ -168,135 +168,177 @@ netuio_queue_initialize(_In_ WDFDEVICE Device)
 
 /*
 Routine Description:
-    This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request.
+    This routine is invoked to preprocess an I/O request before being placed into a queue.
+    It is guaranteed that it executes in the context of the process that generated the request.
 
 Return Value:
     None
  */
+_Use_decl_annotations_
 VOID
-netuio_evt_IO_device_control(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,
-                              _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength,
-                              _In_ ULONG IoControlCode)
+netuio_evt_IO_in_caller_context(
+    IN WDFDEVICE  Device,
+    IN WDFREQUEST Request
+)
 {
-    UNREFERENCED_PARAMETER(OutputBufferLength);
-    UNREFERENCED_PARAMETER(InputBufferLength);
-
+    WDF_REQUEST_PARAMETERS params = { 0 };
     NTSTATUS status = STATUS_SUCCESS;
     PVOID    input_buf = NULL, output_buf = NULL;
     size_t   input_buf_size, output_buf_size;
     size_t  bytes_returned = 0;
+    PNETUIO_CONTEXT_DATA  netuio_contextdata = NULL;
 
-    WDFDEVICE device = WdfIoQueueGetDevice(Queue);
+    netuio_contextdata = netuio_get_context_data(Device);
 
-    PNETUIO_CONTEXT_DATA  netuio_contextdata;
-    netuio_contextdata = netuio_get_context_data(device);
+    WDF_REQUEST_PARAMETERS_INIT(&params);
+    WdfRequestGetParameters(Request, &params);
 
-    switch (IoControlCode) {
-    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)) {
-            status = STATUS_INVALID_BUFFER_SIZE;
-            break;
-        }
+    // We only need to be in the context of the process that initiated the request
+    //when we need to map memory to userspace. Otherwise, send the request back to framework.
+    if (!((params.Type == WdfRequestTypeDeviceControl) &&
+        (params.Parameters.DeviceIoControl.IoControlCode == IOCTL_NETUIO_MAP_HW_INTO_USERMODE)))
+    {
+        status = WdfDeviceEnqueueRequest(Device, Request);
 
-        struct dpdk_private_info *dpdk_pvt_info = (struct dpdk_private_info *)input_buf;
-        // Ensure that the B:D:F match - otherwise, fail the IOCTL
-        if ((netuio_contextdata->addr.bus_num != dpdk_pvt_info->dev_addr.bus_num) ||
-            (netuio_contextdata->addr.dev_num != dpdk_pvt_info->dev_addr.dev_num) ||
-            (netuio_contextdata->addr.func_num != dpdk_pvt_info->dev_addr.func_num)) {
-            status = STATUS_NOT_SAME_DEVICE;
-            break;
+        if (!NT_SUCCESS(status))
+        {
+            WdfRequestCompleteWithInformation(Request, status, bytes_returned);
         }
+        return;
+    }
 
-        if (netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr != NULL) {
-            status = STATUS_ALREADY_COMMITTED;
-            break;
-        }
+    // 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)) {
+        status = STATUS_INVALID_BUFFER_SIZE;
+        goto end;
+    }
 
-        // 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;
-        }
+    struct dpdk_private_info* dpdk_pvt_info = (struct dpdk_private_info*)input_buf;
+    // Ensure that the B:D:F match - otherwise, fail the IOCTL
+    if ((netuio_contextdata->addr.bus_num != dpdk_pvt_info->dev_addr.bus_num) ||
+        (netuio_contextdata->addr.dev_num != dpdk_pvt_info->dev_addr.dev_num) ||
+        (netuio_contextdata->addr.func_num != dpdk_pvt_info->dev_addr.func_num)) {
+        status = STATUS_NOT_SAME_DEVICE;
+        goto end;
+    }
 
-        // Zero out the physically contiguous block
-        RtlZeroMemory(netuio_contextdata->dpdk_seg.mem.virt_addr, netuio_contextdata->dpdk_seg.mem.size);
+    if (netuio_contextdata->dpdk_seg.mem.user_mapped_virt_addr != NULL) {
+        status = STATUS_ALREADY_COMMITTED;
+        goto end;
+    }
 
-        status = netuio_map_address_into_user_process(netuio_contextdata);
-        if (status != STATUS_SUCCESS) {
-            break;
-        }
+    // 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;
+        goto end;
+    }
 
-        ASSERT(output_buf_size == OutputBufferLength);
-        netuio_handle_get_hw_data_request(Request, netuio_contextdata, output_buf, output_buf_size);
-        bytes_returned = output_buf_size;
+    // Zero out the physically contiguous block
+    RtlZeroMemory(netuio_contextdata->dpdk_seg.mem.virt_addr, netuio_contextdata->dpdk_seg.mem.size);
 
-        break;
+    status = netuio_map_address_into_user_process(netuio_contextdata);
+    if (status != STATUS_SUCCESS) {
+        goto end;
+    }
 
-    case IOCTL_NETUIO_PCI_CONFIG_IO:
-        // First retrieve the input buffer and see if it matches our device
-        status = WdfRequestRetrieveInputBuffer(Request, sizeof(struct dpdk_pci_config_io), &input_buf, &input_buf_size);
-        if (!NT_SUCCESS(status)) {
-            status = STATUS_INVALID_BUFFER_SIZE;
-            break;
-        }
+    netuio_handle_get_hw_data_request(Request, netuio_contextdata, output_buf, output_buf_size);
+    bytes_returned = output_buf_size;
 
-        struct dpdk_pci_config_io *dpdk_pci_io_input = (struct dpdk_pci_config_io *)input_buf;
+end:
+    WdfRequestCompleteWithInformation(Request, status, bytes_returned);
 
-        if (dpdk_pci_io_input->access_size != 1 &&
-            dpdk_pci_io_input->access_size != 2 &&
-            dpdk_pci_io_input->access_size != 4 &&
-            dpdk_pci_io_input->access_size != 8) {
-            status = STATUS_INVALID_PARAMETER;
-            break;
-        }
+    return;
+}
 
-        // Ensure that the B:D:F match - otherwise, fail the IOCTL
-        if ((netuio_contextdata->addr.bus_num != dpdk_pci_io_input->dev_addr.bus_num) ||
-            (netuio_contextdata->addr.dev_num != dpdk_pci_io_input->dev_addr.dev_num) ||
-            (netuio_contextdata->addr.func_num != dpdk_pci_io_input->dev_addr.func_num)) {
-            status = STATUS_NOT_SAME_DEVICE;
-            break;
-        }
-        // Retrieve output buffer
-        status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT64), &output_buf, &output_buf_size);
-        if (!NT_SUCCESS(status)) {
-            status = STATUS_INVALID_BUFFER_SIZE;
-            break;
-        }
-        ASSERT(output_buf_size == OutputBufferLength);
-
-        if (dpdk_pci_io_input->op == PCI_IO_READ) {
-            *(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) {
-            // 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;
-            break;
-        }
+/*
+Routine Description:
+    This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request.
+
+Return Value:
+    None
+ */
+VOID
+netuio_evt_IO_device_control(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,
+                              _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength,
+                              _In_ ULONG IoControlCode)
+{
+    UNREFERENCED_PARAMETER(OutputBufferLength);
+    UNREFERENCED_PARAMETER(InputBufferLength);
+
+    NTSTATUS status = STATUS_SUCCESS;
+    PVOID    input_buf = NULL, output_buf = NULL;
+    size_t   input_buf_size, output_buf_size;
+    size_t  bytes_returned = 0;
+
+    WDFDEVICE device = WdfIoQueueGetDevice(Queue);
 
-        break;
+    PNETUIO_CONTEXT_DATA  netuio_contextdata;
+    netuio_contextdata = netuio_get_context_data(device);
+
+    if (IoControlCode != IOCTL_NETUIO_PCI_CONFIG_IO)
+    {
+        status = STATUS_INVALID_DEVICE_REQUEST;
+        goto end;
+    }
+
+    // First retrieve the input buffer and see if it matches our device
+    status = WdfRequestRetrieveInputBuffer(Request, sizeof(struct dpdk_pci_config_io), &input_buf, &input_buf_size);
+    if (!NT_SUCCESS(status)) {
+        status = STATUS_INVALID_BUFFER_SIZE;
+        goto end;
+    }
+
+    struct dpdk_pci_config_io *dpdk_pci_io_input = (struct dpdk_pci_config_io *)input_buf;
+
+    if (dpdk_pci_io_input->access_size != 1 &&
+        dpdk_pci_io_input->access_size != 2 &&
+        dpdk_pci_io_input->access_size != 4 &&
+        dpdk_pci_io_input->access_size != 8) {
+        status = STATUS_INVALID_PARAMETER;
+        goto end;
+    }
 
-    default:
-        break;
+    // Ensure that the B:D:F match - otherwise, fail the IOCTL
+    if ((netuio_contextdata->addr.bus_num != dpdk_pci_io_input->dev_addr.bus_num) ||
+        (netuio_contextdata->addr.dev_num != dpdk_pci_io_input->dev_addr.dev_num) ||
+        (netuio_contextdata->addr.func_num != dpdk_pci_io_input->dev_addr.func_num)) {
+        status = STATUS_NOT_SAME_DEVICE;
+        goto end;
+    }
+    // Retrieve output buffer
+    status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT64), &output_buf, &output_buf_size);
+    if (!NT_SUCCESS(status)) {
+        status = STATUS_INVALID_BUFFER_SIZE;
+        goto end;
+    }
+    ASSERT(output_buf_size == OutputBufferLength);
+
+    if (dpdk_pci_io_input->op == PCI_IO_READ) {
+        *(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) {
+        // 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;
+        goto end;
     }
 
+end:
     WdfRequestCompleteWithInformation(Request, status, bytes_returned);
 
     return;
diff --git a/kernel/windows/netuio/netuio_queue.h b/kernel/windows/netuio/netuio_queue.h
index 90fdb4008..68fdaa296 100644
--- a/kernel/windows/netuio/netuio_queue.h
+++ b/kernel/windows/netuio/netuio_queue.h
@@ -27,6 +27,8 @@ netuio_queue_initialize(_In_ WDFDEVICE hDevice);
 EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL netuio_evt_IO_device_control;
 EVT_WDF_IO_QUEUE_IO_STOP netuio_evt_IO_stop;
 
+EVT_WDF_IO_IN_CALLER_CONTEXT netuio_evt_IO_in_caller_context;
+
 EXTERN_C_END
 
 #endif // NETUIO_QUEUE_H
-- 
2.23.0.vfs.1.1.63.g5a5ad7f


  parent reply	other threads:[~2020-08-13 23:25 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 ` [dpdk-dev] [PATCH 12/22] uio: Fix 64 bit BARs mapping Narcisa Ana Maria Vasile
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 ` Narcisa Ana Maria Vasile [this message]
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-18-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=navasile@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.