Page MenuHomeFreeBSD

D32903.id98237.diff
No OneTemporary

D32903.id98237.diff

Index: usr.sbin/bhyve/pci_nvme.c
===================================================================
--- usr.sbin/bhyve/pci_nvme.c
+++ usr.sbin/bhyve/pci_nvme.c
@@ -62,6 +62,7 @@
#include <sys/errno.h>
#include <sys/types.h>
#include <net/ieee_oui.h>
+#include <sys/time.h>
#include <assert.h>
#include <pthread.h>
@@ -129,6 +130,9 @@
#define NVME_DOORBELL_OFFSET offsetof(struct nvme_registers, doorbell)
+#define TIMEVAL_DIFF_MILISECONDS(now, from) \
+ ((now.tv_sec - from.tv_sec) * 1000 + (now.tv_usec - from.tv_usec) / 1000)
+
enum nvme_controller_register_offsets {
NVME_CR_CAP_LOW = 0x00,
NVME_CR_CAP_HI = 0x04,
@@ -159,6 +163,8 @@
#define NVME_CQ_INTEN 0x01
#define NVME_CQ_INTCOAL 0x02
+#define NVME_FEAT_TIMESTAMP_TIMESTAMP_ORIGIN_SHIFT (1)
+
struct nvme_completion_queue {
struct nvme_completion *qbase;
pthread_mutex_t mtx;
@@ -242,12 +248,22 @@
struct nvme_completion *);
struct nvme_feature_obj {
- uint32_t cdw11;
+ void *data;
nvme_feature_cb set;
nvme_feature_cb get;
bool namespace_specific;
};
+/* feature timestamp */
+static struct nvme_feature_timestamp_data {
+ uint8_t timestamp_origin;
+ struct timeval timestamp;
+} timestamp_data = {
+ .timestamp_origin = 0,
+ .timestamp.tv_sec = 0,
+ .timestamp.tv_usec = 0,
+};
+
#define NVME_FID_MAX (NVME_FEAT_ENDURANCE_GROUP_EVENT_CONFIGURATION + 1)
struct pci_nvme_aer {
@@ -303,6 +319,8 @@
STAILQ_HEAD(, pci_nvme_aer) aer_list;
uint32_t aer_count;
+
+ struct timeval power_on_time;
};
@@ -359,6 +377,14 @@
struct nvme_feature_obj *,
struct nvme_command *,
struct nvme_completion *);
+static void nvme_feature_timestamp_get(struct pci_nvme_softc *,
+ struct nvme_feature_obj *,
+ struct nvme_command *,
+ struct nvme_completion *);
+static void nvme_feature_timestamp_set(struct pci_nvme_softc *,
+ struct nvme_feature_obj *,
+ struct nvme_command *,
+ struct nvme_completion *);
static __inline void
cpywithpad(char *dst, size_t dst_size, const char *src, char pad)
@@ -487,7 +513,8 @@
(4 << NVME_CTRLR_DATA_CQES_MIN_SHIFT);
cd->nn = 1; /* number of namespaces */
- cd->oncs = 0;
+ cd->oncs = 1 << NVME_CTRLR_DATA_ONCS_TIMESTAMP_SHIFT;
+
switch (sc->dataset_management) {
case NVME_DATASET_MANAGEMENT_AUTO:
if (sc->nvstore.deallocate)
@@ -503,6 +530,8 @@
cd->fna = 0x03;
cd->power_state[0].mp = 10;
+
+ gettimeofday(&sc->power_on_time, NULL);
}
/*
@@ -627,6 +656,11 @@
nvme_feature_invalid_cb;
sc->feat[NVME_FEAT_PREDICTABLE_LATENCY_MODE_WINDOW].get =
nvme_feature_invalid_cb;
+ sc->feat[NVME_FEAT_TIMESTAMP].set =
+ nvme_feature_timestamp_set;
+ sc->feat[NVME_FEAT_TIMESTAMP].get =
+ nvme_feature_timestamp_get;
+ sc->feat[NVME_FEAT_TIMESTAMP].data = &timestamp_data;
}
static void
@@ -1376,6 +1410,57 @@
sc->num_q_is_set = true;
}
+static void
+nvme_feature_timestamp_set(struct pci_nvme_softc *sc,
+ struct nvme_feature_obj *feat,
+ struct nvme_command *command,
+ struct nvme_completion *compl)
+{
+ uint64_t miliseconds;
+ struct nvme_feature_timestamp_data *data = (struct nvme_feature_timestamp_data *)feat->data;
+
+ nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
+ command->prp2, (uint8_t*)&miliseconds,
+ sizeof(miliseconds), NVME_COPY_FROM_PRP);
+
+ DPRINTF("%s: miliseconds: %lu", __func__, miliseconds);
+ miliseconds &= 0xFFFFFFFFFFFF;
+
+ /* Set by Timestamp command */
+ data->timestamp_origin = 1;
+ data->timestamp.tv_sec = miliseconds / 1000;
+ data->timestamp.tv_usec = (miliseconds % 1000) * 1000;
+}
+
+static void
+nvme_feature_timestamp_get(struct pci_nvme_softc *sc,
+ struct nvme_feature_obj *feat,
+ struct nvme_command *command,
+ struct nvme_completion *compl)
+{
+ uint8_t timestamp[8];
+ uint64_t elapsed;
+ struct timeval now;
+ struct nvme_feature_timestamp_data *data = (struct nvme_feature_timestamp_data *)feat->data;
+
+ gettimeofday(&now, NULL);
+ if (data->timestamp_origin == 0)
+ elapsed = TIMEVAL_DIFF_MILISECONDS(now, sc->power_on_time);
+ else
+ elapsed = TIMEVAL_DIFF_MILISECONDS(now, data->timestamp);
+
+ DPRINTF("%s: elapsed: %lu", __func__, elapsed);
+
+ memcpy(timestamp, (uint8_t*)&elapsed, sizeof(elapsed));
+ timestamp[7] = 0;
+ timestamp[6] = data->timestamp_origin <<
+ NVME_FEAT_TIMESTAMP_TIMESTAMP_ORIGIN_SHIFT;
+
+ nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
+ command->prp2, timestamp,
+ sizeof(timestamp), NVME_COPY_TO_PRP);
+}
+
static int
nvme_opc_set_features(struct pci_nvme_softc *sc, struct nvme_command *command,
struct nvme_completion *compl)
@@ -1406,9 +1491,6 @@
if (feat->set)
feat->set(sc, feat, command, compl);
- if (compl->status == NVME_SC_SUCCESS)
- feat->cdw11 = command->cdw11;
-
return (0);
}
@@ -1435,10 +1517,6 @@
feat->get(sc, feat, command, compl);
}
- if (compl->status == NVME_SC_SUCCESS) {
- compl->cdw0 = feat->cdw11;
- }
-
return (0);
}

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 8, 6:40 PM (6 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28485286
Default Alt Text
D32903.id98237.diff (4 KB)

Event Timeline