Hello Jason, Dmitry,
+-- On Tue, 8 Dec 2015, P J P wrote --+
| |1) VMXNET3_CMD_QUIESCE_DEV
|
| IIUC, it is used to pause the device when the receiver end is unable to
| keee-up with the incoming flow. After a brief period, the operation could be
| resumed again.
|
| |2) VMXNET3_REG_DSAL
|
| Shared memory between a driver and the device appears to be set in two
| steps. Firs low address, followed by the high address(VMXNET3_REG_DSAH). I
| guess 's->device_active' needs to be enabled again while setting the higher
| part of the address.
Please see below another (tested)patch, it fixes the VMXNET3_CMD_QUIESCE_DEV
case above. It's not clear if the device would be initialised and active while
setting shared memory via VMXNET3_REG_DSAL/DSAH.
===
From 81c4ecb67635435f01397dc21210497e6420bdca Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <
address@hidden>
Date: Wed, 9 Dec 2015 20:45:25 +0530
Subject: [PATCH] net: vmxnet3: avoid memory leakage in activate_device
Vmxnet3 device emulator does not check if the device is active
before activating it, resulting in memory leakage on the host.
This memory leakage could also occur, if the device was paused
during flow control and activated thereafter.
Introduced a 'Pause' state for the vmxnet3 device to differentiate
it from the earlier active and inactive states. One need not
'activate' the device to resume operation after pause.
This patch adds a check to verify these device states and avoid
memory leakage during activating the device.
Reported-by: Qinghao Tang <
address@hidden>
Signed-off-by: Prasad J Pandit <
address@hidden>
---
hw/net/vmxnet3.c | 43 +++++++++++++++++++++++++++++++++++--------
hw/net/vmxnet3.h | 6 ++++++
2 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 37373e5..be2c9e2 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -1195,7 +1195,19 @@ static void vmxnet3_reset_mac(VMXNET3State *s)
static void vmxnet3_deactivate_device(VMXNET3State *s)
{
VMW_CBPRN("Deactivating vmxnet3...");
- s->device_active = false;
+ s->device_active = VMXNET3_DEV_DEACTIVE;
+}
+
+static void vmxnet3_pause_device(VMXNET3State *s)
+{
+ VMW_CBPRN("Pausing vmxnet3...");
+ s->device_active = VMXNET3_DEV_PAUSE;
+}
+
+static void vmxnet3_resume_device(VMXNET3State *s)
+{
+ VMW_CBPRN("Resuming vmxnet3...");
+ s->device_active = VMXNET3_DEV_ACTIVE;
}
static void vmxnet3_reset(VMXNET3State *s)
@@ -1431,6 +1443,12 @@ static void vmxnet3_activate_device(VMXNET3State *s)
return;
}
+ /* Verify if device is active */
+ if (s->device_active) {
+ VMW_CFPRN("Vmxnet3 device is active");
+ return;
+ }
+
vmxnet3_adjust_by_guest_type(s);
vmxnet3_update_features(s);
vmxnet3_update_pm_state(s);
@@ -1566,7 +1584,7 @@ static void vmxnet3_activate_device(VMXNET3State *s)
vmxnet3_reset_mac(s);
- s->device_active = true;
+ s->device_active = VMXNET3_DEV_ACTIVE;
}
static void vmxnet3_handle_command(VMXNET3State *s, uint64_t cmd)
@@ -1627,8 +1645,13 @@ static void vmxnet3_handle_command(VMXNET3State *s, uint64_t cmd)
break;
case VMXNET3_CMD_QUIESCE_DEV:
- VMW_CBPRN("Set: VMXNET3_CMD_QUIESCE_DEV - pause the device");
- vmxnet3_deactivate_device(s);
+ if (s->device_active & VMXNET3_DEV_ACTIVE) {
+ VMW_CBPRN("Set: VMXNET3_CMD_QUIESCE_DEV - pause the device");
+ vmxnet3_pause_device(s);
+ } else if (s->device_active & VMXNET3_DEV_PAUSE) {
+ VMW_CBPRN("Set: VMXNET3_CMD_QUIESCE_DEV - resume the device");
+ vmxnet3_resume_device(s);
+ }