Index: usr.sbin/bhyve/pci_nvme.c =================================================================== --- usr.sbin/bhyve/pci_nvme.c +++ usr.sbin/bhyve/pci_nvme.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -115,6 +116,9 @@ #define NVME_NO_STATUS 0xffff #define NVME_COMPLETION_VALID(c) ((c).status != NVME_NO_STATUS) +#define POWER_ON_HOURS(start, now) \ + ((now.tv_sec - start.tv_sec) / 3600) + /* helpers */ /* Convert a zero-based value into a one-based value */ @@ -300,6 +304,7 @@ __uint128_t write_commands; uint32_t read_dunits_remainder; uint32_t write_dunits_remainder; + struct timeval power_on_time; STAILQ_HEAD(, pci_nvme_aer) aer_list; uint32_t aer_count; @@ -503,6 +508,8 @@ cd->fna = 0x03; cd->power_state[0].mp = 10; + + gettimeofday(&sc->power_on_time, NULL); } /* @@ -596,6 +603,7 @@ static void pci_nvme_init_logpages(struct pci_nvme_softc *sc) { + __uint128_t power_cycles = 1; memset(&sc->err_log, 0, sizeof(sc->err_log)); memset(&sc->health_log, 0, sizeof(sc->health_log)); @@ -609,6 +617,9 @@ sc->health_log.temperature = 310; sc->health_log.available_spare = 100; sc->health_log.available_spare_threshold = 10; + + memcpy(&sc->health_log.power_cycles, &power_cycles, + sizeof(sc->health_log.power_cycles)); } static void @@ -1071,6 +1082,8 @@ { uint32_t logsize; uint8_t logpage = command->cdw10 & 0xFF; + struct timeval now; + __uint128_t power_on_hours; DPRINTF("%s log page %u len %u", __func__, logpage, logsize); @@ -1091,6 +1104,11 @@ NVME_COPY_TO_PRP); break; case NVME_LOG_HEALTH_INFORMATION: + gettimeofday(&now, NULL); + power_on_hours = POWER_ON_HOURS(sc->power_on_time, now); + memcpy(&sc->health_log.power_on_hours, &power_on_hours, + sizeof(sc->health_log.power_on_hours)); + pthread_mutex_lock(&sc->mtx); memcpy(&sc->health_log.data_units_read, &sc->read_data_units, sizeof(sc->health_log.data_units_read));