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(¶ms);
+ WdfRequestGetParameters(Request, ¶ms);
- 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
next prev 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 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).