mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-07 12:29:48 +00:00
DM: add interface to set intr storm monitor params
modify and add interface to set interrupt monitor params; it can be set by acrn-dm input arguments like following: --intr_monitor 10000,10,1,100 the 4 params order is: interrupt storm theshold per second, probe period to get interrupt data, pass-through devices' interrupt injection delay time, delay duration, after it, stop injection & restore to normal Tracked-On: #1724 Signed-off-by: Minggui Cao <minggui.cao@intel.com> Acked-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
parent
1902d725a0
commit
ad1cbb7623
@ -157,7 +157,9 @@ usage(int code)
|
||||
" --part_info: guest partition info file path\n"
|
||||
" --enable_trusty: enable trusty for guest\n"
|
||||
" --ptdev_no_reset: disable reset check for ptdev\n"
|
||||
" --debugexit: enable debug exit function\n",
|
||||
" --debugexit: enable debug exit function\n"
|
||||
" --intr_monitor: enable interrupt storm monitor\n"
|
||||
"............its params: threshold/s,probe-period(s),delay_time(ms),delay_duration(ms)\n",
|
||||
progname, (int)strlen(progname), "", (int)strlen(progname), "",
|
||||
(int)strlen(progname), "");
|
||||
|
||||
@ -701,6 +703,7 @@ enum {
|
||||
CMD_OPT_DEBUGEXIT,
|
||||
CMD_OPT_VMCFG,
|
||||
CMD_OPT_DUMP,
|
||||
CMD_OPT_INTR_MONITOR,
|
||||
};
|
||||
|
||||
static struct option long_options[] = {
|
||||
@ -734,6 +737,7 @@ static struct option long_options[] = {
|
||||
{"ptdev_no_reset", no_argument, 0,
|
||||
CMD_OPT_PTDEV_NO_RESET},
|
||||
{"debugexit", no_argument, 0, CMD_OPT_DEBUGEXIT},
|
||||
{"intr_monitor", required_argument, 0, CMD_OPT_INTR_MONITOR},
|
||||
{0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
@ -859,6 +863,12 @@ dm_run(int argc, char *argv[])
|
||||
case CMD_OPT_DEBUGEXIT:
|
||||
debugexit_enabled = true;
|
||||
break;
|
||||
case CMD_OPT_INTR_MONITOR:
|
||||
if (acrn_parse_intr_monitor(optarg) != 0) {
|
||||
errx(EX_USAGE, "invalid intr-monitor params %s", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
usage(0);
|
||||
default:
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include "dm.h"
|
||||
#include "dm_string.h"
|
||||
#include "monitor.h"
|
||||
#include "acrn_mngr.h"
|
||||
#include "pm.h"
|
||||
@ -30,6 +31,14 @@
|
||||
#define DELAY_DURATION 100000 /* 100ms of total duration for delay intr */
|
||||
#define TIME_TO_CHECK_AGAIN 2 /* 2seconds */
|
||||
|
||||
struct intr_monitor_setting_t {
|
||||
bool enable;
|
||||
uint32_t threshold; /* intr count in probe_period when intr storm happens */
|
||||
uint32_t probe_period; /* seconds: the period to probe intr data */
|
||||
uint32_t delay_time; /* ms: the time to delay each intr injection */
|
||||
uint32_t delay_duration; /* us: the delay duration, after it, intr injection restore to normal */
|
||||
};
|
||||
|
||||
union intr_monitor_t {
|
||||
struct acrn_intr_monitor monitor;
|
||||
char reserved[4096];
|
||||
@ -39,6 +48,10 @@ static union intr_monitor_t intr_data;
|
||||
static uint64_t intr_cnt_buf[MAX_PTDEV_NUM * 2];
|
||||
static pthread_t intr_storm_monitor_pid;
|
||||
|
||||
static struct intr_monitor_setting_t intr_monitor_setting = {
|
||||
.enable = false,
|
||||
};
|
||||
|
||||
/* switch macro, just open in debug */
|
||||
/* #define INTR_MONITOR_DBG */
|
||||
|
||||
@ -59,8 +72,7 @@ static void write_intr_data_to_file(const struct acrn_intr_monitor *hdr)
|
||||
|
||||
for (j = 0; j < hdr->buf_cnt; j += 2) {
|
||||
if (hdr->buffer[j + 1] != 0) {
|
||||
fprintf(dbg_file, "%ld\t\t%ld\n", hdr->buffer[j],
|
||||
hdr->buffer[j + 1]);
|
||||
fprintf(dbg_file, "%ld\t\t%ld\n", hdr->buffer[j], hdr->buffer[j + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +92,7 @@ static void *intr_storm_monitor_thread(void *arg)
|
||||
#ifdef INTR_MONITOR_DBG
|
||||
dbg_file = fopen("/tmp/intr_log", "w+");
|
||||
#endif
|
||||
sleep(INTR_STORM_MONITOR_PERIOD);
|
||||
sleep(intr_monitor_setting.probe_period);
|
||||
|
||||
/* first to get interrupt data */
|
||||
hdr->cmd = INTR_CMD_GET_DATA;
|
||||
@ -98,9 +110,8 @@ static void *intr_storm_monitor_thread(void *arg)
|
||||
#ifdef INTR_MONITOR_DBG
|
||||
write_intr_data_to_file(hdr);
|
||||
#endif
|
||||
memcpy(intr_cnt_buf, hdr->buffer,
|
||||
sizeof(uint64_t) * hdr->buf_cnt);
|
||||
sleep(INTR_STORM_MONITOR_PERIOD);
|
||||
memcpy(intr_cnt_buf, hdr->buffer, sizeof(uint64_t) * hdr->buf_cnt);
|
||||
sleep(intr_monitor_setting.probe_period);
|
||||
|
||||
/* next time to get interrupt data */
|
||||
memset(hdr->buffer, 0, sizeof(uint64_t) * hdr->buf_cnt);
|
||||
@ -126,7 +137,7 @@ static void *intr_storm_monitor_thread(void *arg)
|
||||
continue;
|
||||
|
||||
delta = hdr->buffer[i + 1] - intr_cnt_buf[i + 1];
|
||||
if (delta > INTR_STORM_THRESHOLD) {
|
||||
if (delta > intr_monitor_setting.threshold) {
|
||||
#ifdef INTR_MONITOR_DBG
|
||||
write_intr_data_to_file(hdr);
|
||||
#endif
|
||||
@ -139,17 +150,16 @@ static void *intr_storm_monitor_thread(void *arg)
|
||||
DPRINTF("irq=%ld, delta=%ld\n", intr_cnt_buf[i], delta);
|
||||
|
||||
hdr->cmd = INTR_CMD_DELAY_INT;
|
||||
hdr->buffer[0] = DELAY_INTR_TIME;
|
||||
hdr->buffer[0] = intr_monitor_setting.delay_time;
|
||||
vm_intr_monitor(ctx, hdr);
|
||||
usleep(DELAY_DURATION); /* sleep-delay intr */
|
||||
usleep(intr_monitor_setting.delay_duration); /* sleep-delay intr */
|
||||
hdr->buffer[0] = 0; /* cancel to delay intr */
|
||||
vm_intr_monitor(ctx, hdr);
|
||||
|
||||
sleep(TIME_TO_CHECK_AGAIN); /* time to get data again */
|
||||
hdr->cmd = INTR_CMD_GET_DATA;
|
||||
hdr->buf_cnt = MAX_PTDEV_NUM * 2;
|
||||
memset(hdr->buffer, 0,
|
||||
sizeof(uint64_t) * hdr->buf_cnt);
|
||||
memset(hdr->buffer, 0, sizeof(uint64_t) * hdr->buf_cnt);
|
||||
vm_intr_monitor(ctx, hdr);
|
||||
}
|
||||
}
|
||||
@ -159,14 +169,15 @@ static void *intr_storm_monitor_thread(void *arg)
|
||||
|
||||
static void start_intr_storm_monitor(struct vmctx *ctx)
|
||||
{
|
||||
int ret = pthread_create(&intr_storm_monitor_pid, NULL,
|
||||
intr_storm_monitor_thread, ctx);
|
||||
if (ret) {
|
||||
printf("failed %s %d\n", __func__, __LINE__);
|
||||
intr_storm_monitor_pid = 0;
|
||||
}
|
||||
if (intr_monitor_setting.enable) {
|
||||
int ret = pthread_create(&intr_storm_monitor_pid, NULL, intr_storm_monitor_thread, ctx);
|
||||
if (ret) {
|
||||
printf("failed %s %d\n", __func__, __LINE__);
|
||||
intr_storm_monitor_pid = 0;
|
||||
}
|
||||
|
||||
printf("start monitor interrupt data...\n");
|
||||
printf("start monitor interrupt data...\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void stop_intr_storm_monitor(void)
|
||||
@ -177,6 +188,40 @@ static void stop_intr_storm_monitor(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
.* interrupt monitor setting params, current interrupt mitigation will delay UOS's
|
||||
.* pass-through devices' interrupt injection, the settings input from acrn-dm:
|
||||
.* params:
|
||||
.* threshold: each intr count/second when intr storm happens;
|
||||
.* probe_period: seconds -- the period to probe intr data;
|
||||
.* delay_time: ms -- the time to delay each intr injection;
|
||||
* delay_duration; us -- the delay duration, after it, intr injection restore to normal
|
||||
.*/
|
||||
int acrn_parse_intr_monitor(const char *opt)
|
||||
{
|
||||
uint32_t threshold, period, delay, duration;
|
||||
char *cp;
|
||||
|
||||
if((!dm_strtoui(opt, &cp, 10, &threshold) && *cp == ',') &&
|
||||
(!dm_strtoui(cp + 1, &cp, 10, &period) && *cp == ',') &&
|
||||
(!dm_strtoui(cp + 1, &cp, 10, &delay) && *cp == ',') &&
|
||||
(!dm_strtoui(cp + 1, &cp, 10, &duration))) {
|
||||
printf("interrupt storm monitor params: %d, %d, %d, %d\n", threshold, period, delay, duration);
|
||||
} else {
|
||||
printf("%s: not correct, it should be like: --intr_monitor 10000,10,1,100, please check!\n", opt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
intr_monitor_setting.enable = true;
|
||||
intr_monitor_setting.threshold = threshold * period;
|
||||
intr_monitor_setting.probe_period = period;
|
||||
intr_monitor_setting.delay_time = delay;
|
||||
intr_monitor_setting.delay_duration = duration * 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* helpers */
|
||||
/* Check if @path is a directory, and create if not exist */
|
||||
static int check_dir(const char *path)
|
||||
|
@ -33,4 +33,5 @@ int monitor_register_vm_ops(struct monitor_vm_ops *ops, void *arg,
|
||||
/* helper functions for vm_ops callback developer */
|
||||
unsigned get_wakeup_reason(void);
|
||||
int set_wakeup_timer(time_t t);
|
||||
int acrn_parse_intr_monitor(const char *opt);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user