diff --git a/hyptop/dg_debugfs_lpar.c b/hyptop/dg_debugfs_lpar.c index 48880855..56e2a113 100644 --- a/hyptop/dg_debugfs_lpar.c +++ b/hyptop/dg_debugfs_lpar.c @@ -116,6 +116,7 @@ static void l_sd_cpu_fill(struct sd_cpu *cpu, struct l_x_cpu_info *cpu_info, int threads) { sd_cpu_cpu_time_us_set(cpu, cpu_info->lp_time); + sd_cpu_threads_per_core_set(cpu, threads); if (threads > 1) sd_cpu_thread_time_us_set(cpu, cpu_info->lp_time * threads - cpu_info->mt_idle_time); @@ -297,6 +298,7 @@ static struct sd_sys_item *l_sys_item_vec[] = { &sd_sys_item_thread_cnt, &sd_sys_item_core_diff, &sd_sys_item_thread_diff, + &sd_sys_item_smt_diff, &sd_sys_item_mgm_diff, &sd_sys_item_core, &sd_sys_item_thread, @@ -326,6 +328,7 @@ static struct sd_cpu_item *l_cpu_item_vec[] = { &sd_cpu_item_type, &sd_cpu_item_core_diff, &sd_cpu_item_thread_diff, + &sd_cpu_item_smt_diff, &sd_cpu_item_mgm_diff, &sd_cpu_item_core, &sd_cpu_item_thread, diff --git a/hyptop/helper.c b/hyptop/helper.c index 7fb70ffe..85b06682 100644 --- a/hyptop/helper.c +++ b/hyptop/helper.c @@ -391,3 +391,24 @@ void hyptop_helper_init(void) if (l_iconv_ebcdic_ascii == (iconv_t) -1) ERR_EXIT("Could not initialize iconv\n"); } + +/* + * Calculate real SMT utilization + * @core_us: core utilization in us + * @thr_us: thread utilization in us + * @mgm_us: management utilization in us + * @thread_per_core: SMT thread count per core + */ +s64 ht_calculate_smt_util(u64 core_us, u64 thr_us, u64 mgm_us, int thread_per_core) +{ + s64 component1, component2, smt_us; + double smt_factor = SMT_FACTOR_DEFAULT; + + component1 = G0(thread_per_core * core_us - thr_us); + if (thread_per_core > 1) + component1 /= smt_factor; + component2 = G0(thr_us - core_us); + smt_us = component1 + component2 + mgm_us; + + return smt_us; +} diff --git a/hyptop/helper.h b/hyptop/helper.h index 205b48f2..5ed92519 100644 --- a/hyptop/helper.h +++ b/hyptop/helper.h @@ -21,6 +21,7 @@ #include "lib/zt_common.h" #define G0(x) MAX(0, (s64) (x)) +#define SMT_FACTOR_DEFAULT 1.3 /* * Helper Prototypes @@ -34,6 +35,7 @@ extern void ht_ebcdic_to_ascii(char *in, char *out, size_t len); extern char *ht_mount_point_get(const char *fs_type); extern u64 ht_ext_tod_2_us(void *tod_ext); extern void ht_print_time(void); +extern s64 ht_calculate_smt_util(u64 core_us, u64 thr_us, u64 mgm_us, int thread_per_core); /* * Memory alloc functions diff --git a/hyptop/hyptop.8 b/hyptop/hyptop.8 index b98fc959..739835cc 100644 --- a/hyptop/hyptop.8 +++ b/hyptop/hyptop.8 @@ -119,6 +119,7 @@ The following fields are available under LPAR: In "sys_list" and "sys" window: 'c' - Core dispatch time per second 'e' - Thread time per second + 'S' - Real CPU SMT utilization 'm' - Management time per second 'C' - Total core dispatch time 'E' - Total thread time diff --git a/hyptop/sd.h b/hyptop/sd.h index 1aed7074..ee84799b 100644 --- a/hyptop/sd.h +++ b/hyptop/sd.h @@ -200,6 +200,7 @@ struct sd_cpu { struct sd_cpu_info *d_cur; struct sd_cpu_info *d_prev; u16 cnt; + int threads_per_core; enum sd_cpu_state state; }; @@ -232,6 +233,11 @@ static inline void sd_cpu_cpu_time_us_set(struct sd_cpu *cpu, u64 value) cpu->d_cur->cpu_time_us = value; } +static inline void sd_cpu_threads_per_core_set(struct sd_cpu *cpu, int value) +{ + cpu->threads_per_core = value; +} + static inline void sd_cpu_thread_time_us_set(struct sd_cpu *cpu, u64 value) { cpu->d_cur->thread_time_us = value; @@ -335,6 +341,7 @@ extern struct sd_cpu_item sd_cpu_item_state; extern struct sd_cpu_item sd_cpu_item_cpu_diff; extern struct sd_cpu_item sd_cpu_item_core_diff; extern struct sd_cpu_item sd_cpu_item_thread_diff; +extern struct sd_cpu_item sd_cpu_item_smt_diff; extern struct sd_cpu_item sd_cpu_item_mgm_diff; extern struct sd_cpu_item sd_cpu_item_wait_diff; extern struct sd_cpu_item sd_cpu_item_steal_diff; @@ -398,6 +405,7 @@ static inline char *sd_sys_item_str(struct sd_sys *sys, extern struct sd_sys_item sd_sys_item_cpu_cnt; extern struct sd_sys_item sd_sys_item_core_cnt; extern struct sd_sys_item sd_sys_item_thread_cnt; +extern struct sd_sys_item sd_sys_item_smt_diff; extern struct sd_sys_item sd_sys_item_cpu_oper_cnt; extern struct sd_sys_item sd_sys_item_cpu_deconf_cnt; extern struct sd_sys_item sd_sys_item_cpu_stop_cnt; diff --git a/hyptop/sd_cpu_items.c b/hyptop/sd_cpu_items.c index 1f4c2ca5..380c296d 100644 --- a/hyptop/sd_cpu_items.c +++ b/hyptop/sd_cpu_items.c @@ -98,6 +98,18 @@ static u64 l_cpu_item_64(struct sd_cpu_item *item, struct sd_cpu *cpu) return l_cpu_info_u64(cpu->d_cur, item->offset) / cpu->cnt; } +static u64 l_cpu_smt_util(struct sd_cpu_item *item, struct sd_cpu *cpu) +{ + u64 core_us, thr_us, mgm_us; + (void)item; + + core_us = sd_cpu_item_u64(&sd_cpu_item_core_diff, cpu); + thr_us = sd_cpu_item_u64(&sd_cpu_item_thread_diff, cpu); + mgm_us = sd_cpu_item_u64(&sd_cpu_item_mgm_diff, cpu); + + return ht_calculate_smt_util(core_us, thr_us, mgm_us, cpu->threads_per_core); +} + /* * CPU item definitions */ @@ -139,6 +151,13 @@ struct sd_cpu_item sd_cpu_item_thread_diff = { .fn_u64 = l_cpu_diff_u64, }; +struct sd_cpu_item sd_cpu_item_smt_diff = { + .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'S', "smt"), + .type = SD_TYPE_U64, + .desc = "Real CPU SMT utilization", + .fn_u64 = l_cpu_smt_util, +}; + struct sd_cpu_item sd_cpu_item_mgm_diff = { .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"), .type = SD_TYPE_U64, diff --git a/hyptop/sd_sys_items.c b/hyptop/sd_sys_items.c index f86ab51c..6102d6b3 100644 --- a/hyptop/sd_sys_items.c +++ b/hyptop/sd_sys_items.c @@ -208,6 +208,18 @@ static s64 l_sys_cpu_info_diff_s64(struct sd_sys_item *item, struct sd_sys *sys) return rc; } +static u64 l_sys_smt_util(struct sd_sys_item *item, struct sd_sys *sys) +{ + u64 core_us, thr_us, mgm_us; + (void)item; + + core_us = sd_sys_item_u64(sys, &sd_sys_item_core_diff); + thr_us = sd_sys_item_u64(sys, &sd_sys_item_thread_diff); + mgm_us = sd_sys_item_u64(sys, &sd_sys_item_mgm_diff); + + return ht_calculate_smt_util(core_us, thr_us, mgm_us, sys->threads_per_core); +} + /* * System item definitions */ @@ -277,6 +289,13 @@ struct sd_sys_item sd_sys_item_thread_diff = { .fn_u64 = l_sys_cpu_info_diff_u64, }; +struct sd_sys_item sd_sys_item_smt_diff = { + .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'S', "smt"), + .type = SD_TYPE_U64, + .desc = "Real CPU SMT utilization", + .fn_u64 = l_sys_smt_util, +}; + struct sd_sys_item sd_sys_item_mgm_diff = { .table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"), .offset = SD_CPU_INFO_OFFSET(mgm_time_us),