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 @@ -241,6 +242,8 @@ struct nvme_command *, struct nvme_completion *); +typedef struct timeval timeval_t; + struct nvme_feature_obj { uint32_t cdw11; nvme_feature_cb set; @@ -300,6 +303,7 @@ __uint128_t write_commands; uint32_t read_dunits_remainder; uint32_t write_dunits_remainder; + timeval_t power_on_time; STAILQ_HEAD(, pci_nvme_aer) aer_list; uint32_t aer_count; @@ -503,6 +507,8 @@ cd->fna = 0x03; cd->power_state[0].mp = 10; + + gettimeofday(&sc->power_on_time, NULL); } /* @@ -596,6 +602,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 +616,8 @@ 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 +1080,8 @@ { uint32_t logsize; uint8_t logpage = command->cdw10 & 0xFF; + timeval_t now; + __uint128_t power_on_hours; DPRINTF("%s log page %u len %u", __func__, logpage, logsize); @@ -1091,6 +1102,9 @@ NVME_COPY_TO_PRP); break; case NVME_LOG_HEALTH_INFORMATION: + gettimeofday(&now, NULL); + power_on_hours = (now.tv_sec - sc->power_on_time.tv_sec) / 3600; + pthread_mutex_lock(&sc->mtx); memcpy(&sc->health_log.data_units_read, &sc->read_data_units, sizeof(sc->health_log.data_units_read)); @@ -1100,6 +1114,8 @@ sizeof(sc->health_log.host_read_commands)); memcpy(&sc->health_log.host_write_commands, &sc->write_commands, sizeof(sc->health_log.host_write_commands)); + memcpy(&sc->health_log.power_on_hours, &power_on_hours, + sizeof(sc->health_log.power_on_hours)); pthread_mutex_unlock(&sc->mtx); nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,