2019-09-30 10:53:30 -04:00
|
|
|
From fd447c6f129769fcb685d8a2e22c75a922efe342 Mon Sep 17 00:00:00 2001
|
|
|
|
|
From: Zengruan Ye <yezengruan@huawei.com>
|
|
|
|
|
Date: Mon, 15 Jul 2019 21:35:29 +0800
|
|
|
|
|
Subject: [PATCH 3/6] feature: irqbalance: auto banned pci-assigned irq
|
|
|
|
|
|
|
|
|
|
checkout VM pci-assigned pci device irq, and banned it
|
|
|
|
|
|
|
|
|
|
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
|
|
|
|
|
---
|
|
|
|
|
activate.c | 38 ++++++++++++++++++++++++++++++++++++-
|
|
|
|
|
classify.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++-------
|
|
|
|
|
irqbalance.c | 11 +++++++++++
|
|
|
|
|
irqbalance.h | 2 ++
|
|
|
|
|
procinterrupts.c | 23 ++++++++++++++++++++++
|
|
|
|
|
types.h | 1 +
|
|
|
|
|
6 files changed, 125 insertions(+), 8 deletions(-)
|
|
|
|
|
|
|
|
|
|
diff --git a/activate.c b/activate.c
|
|
|
|
|
index 1c4b867..ad60fde 100644
|
|
|
|
|
--- a/activate.c
|
|
|
|
|
+++ b/activate.c
|
|
|
|
|
@@ -29,9 +29,12 @@
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
+#include <dirent.h>
|
|
|
|
|
|
|
|
|
|
#include "irqbalance.h"
|
|
|
|
|
|
|
|
|
|
+extern int ban_pci_assigned_irq;
|
|
|
|
|
+
|
|
|
|
|
static int check_affinity(struct irq_info *info, cpumask_t applied_mask)
|
|
|
|
|
{
|
|
|
|
|
cpumask_t current_mask;
|
|
|
|
|
@@ -56,6 +59,30 @@ static int check_affinity(struct irq_info *info, cpumask_t applied_mask)
|
|
|
|
|
return cpus_equal(applied_mask, current_mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int is_still_pci_assigned_irq(int irq)
|
|
|
|
|
+{
|
|
|
|
|
+ DIR *dir = NULL;
|
|
|
|
|
+ struct dirent *ptr = NULL;
|
|
|
|
|
+ char irq_path[PATH_MAX] = { 0 };
|
|
|
|
|
+
|
|
|
|
|
+ snprintf(irq_path, PATH_MAX - 1, "/proc/irq/%i/", irq);
|
|
|
|
|
+ if ((dir = opendir(irq_path)) == NULL) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ while ((ptr = readdir(dir)) != NULL) {
|
|
|
|
|
+ if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ } else if (is_pci_assigned_irq(ptr->d_name)) {
|
|
|
|
|
+ closedir(dir);
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ closedir(dir);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
static void activate_mapping(struct irq_info *info, void *data __attribute__((unused)))
|
|
|
|
|
{
|
|
|
|
|
char buf[PATH_MAX];
|
|
|
|
|
@@ -89,7 +116,16 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un
|
|
|
|
|
return;
|
|
|
|
|
|
2020-03-24 11:44:22 +08:00
|
|
|
cpumask_scnprintf(buf, PATH_MAX, info->assigned_obj->mask);
|
|
|
|
|
- ret = fprintf(file, "%s", buf);
|
2019-09-30 10:53:30 -04:00
|
|
|
+ if (ban_pci_assigned_irq) {
|
|
|
|
|
+ if (!is_still_pci_assigned_irq(info->irq)) {
|
2020-03-24 11:44:22 +08:00
|
|
|
+ ret = fprintf(file, "%s", buf);
|
2019-09-30 10:53:30 -04:00
|
|
|
+ } else {
|
|
|
|
|
+ log(TO_CONSOLE, LOG_INFO, "IRQ %d is turned into a PCI-assigned irq number.\n", info->irq);
|
|
|
|
|
+ need_rescan = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
2020-03-24 11:44:22 +08:00
|
|
|
+ ret = fprintf(file, "%s", buf);
|
2019-09-30 10:53:30 -04:00
|
|
|
+ }
|
2020-03-24 11:44:22 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
|
log(TO_ALL, LOG_WARNING, "cannot change irq %i's affinity, add it to banned list", info->irq);
|
|
|
|
|
add_banned_irq(info->irq);
|
2019-09-30 10:53:30 -04:00
|
|
|
diff --git a/classify.c b/classify.c
|
|
|
|
|
index 37bfb29..52fd74a 100644
|
|
|
|
|
--- a/classify.c
|
|
|
|
|
+++ b/classify.c
|
|
|
|
|
@@ -37,6 +37,7 @@ static GList *interrupts_db = NULL;
|
|
|
|
|
static GList *banned_irqs = NULL;
|
|
|
|
|
GList *cl_banned_irqs = NULL;
|
|
|
|
|
static GList *cl_banned_modules = NULL;
|
|
|
|
|
+static GList *vm_banned_irqs = NULL;
|
2020-03-24 11:44:22 +08:00
|
|
|
extern int need_add_single;
|
2019-09-30 10:53:30 -04:00
|
|
|
|
|
|
|
|
#define SYSFS_DIR "/sys"
|
|
|
|
|
@@ -264,7 +265,7 @@ static gint compare_ints(gconstpointer a, gconstpointer b)
|
|
|
|
|
return ai->irq - bi->irq;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-24 11:44:22 +08:00
|
|
|
-static void __add_banned_irq(int irq, GList **list)
|
|
|
|
|
+static void __add_banned_irq(int irq, GList **list, int extra_flag)
|
2019-09-30 10:53:30 -04:00
|
|
|
{
|
|
|
|
|
struct irq_info find, *new;
|
|
|
|
|
GList *entry;
|
|
|
|
|
@@ -282,6 +283,7 @@ static void add_banned_irq(int irq, GList **list)
|
|
|
|
|
|
|
|
|
|
new->irq = irq;
|
|
|
|
|
new->flags |= IRQ_FLAG_BANNED;
|
|
|
|
|
+ new->flags |= extra_flag;
|
|
|
|
|
|
|
|
|
|
*list = g_list_append(*list, new);
|
|
|
|
|
log(TO_CONSOLE, LOG_INFO, "IRQ %d was BANNED.\n", irq);
|
2020-03-24 11:44:22 +08:00
|
|
|
@@ -291,12 +293,17 @@ static void __add_banned_irq(int irq, GList **list)
|
|
|
|
|
|
|
|
|
|
void add_banned_irq(int irq)
|
2019-09-30 10:53:30 -04:00
|
|
|
{
|
2020-03-24 11:44:22 +08:00
|
|
|
- __add_banned_irq(irq, &banned_irqs);
|
|
|
|
|
+ __add_banned_irq(irq, &banned_irqs, 0);
|
2019-09-30 10:53:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void add_cl_banned_irq(int irq)
|
|
|
|
|
{
|
2020-03-24 11:44:22 +08:00
|
|
|
- __add_banned_irq(irq, &cl_banned_irqs);
|
|
|
|
|
+ __add_banned_irq(irq, &cl_banned_irqs, 0);
|
2019-09-30 10:53:30 -04:00
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void add_vm_banned_irq(int irq)
|
|
|
|
|
+{
|
2020-03-24 11:44:22 +08:00
|
|
|
+ __add_banned_irq(irq, &vm_banned_irqs, IRQ_FLAG_VM_BANNED);
|
2019-09-30 10:53:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int is_banned_irq(int irq)
|
|
|
|
|
@@ -307,7 +314,10 @@ static int is_banned_irq(int irq)
|
|
|
|
|
|
|
|
|
|
find.irq = irq;
|
|
|
|
|
|
|
|
|
|
- entry = g_list_find_custom(banned_irqs, &find, compare_ints);
|
|
|
|
|
+ entry = g_list_find_custom(vm_banned_irqs, &find, compare_ints);
|
|
|
|
|
+ if (!entry)
|
|
|
|
|
+ entry = g_list_find_custom(banned_irqs, &find, compare_ints);
|
|
|
|
|
+
|
|
|
|
|
return entry ? 1:0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -660,7 +670,7 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
|
|
|
|
|
continue;
|
|
|
|
|
get_irq_user_policy(devpath, irqnum, &pol);
|
|
|
|
|
if ((pol.ban == 1) || (check_for_irq_ban(devpath, irqnum, tmp_list))) {
|
2020-03-24 11:44:22 +08:00
|
|
|
- __add_banned_irq(irqnum, &banned_irqs);
|
|
|
|
|
+ __add_banned_irq(irqnum, &banned_irqs, 0);
|
2019-09-30 10:53:30 -04:00
|
|
|
continue;
|
|
|
|
|
}
|
2020-03-24 11:44:22 +08:00
|
|
|
if (!is_proc_irq_info_exist(irqnum, tmp_list)) {
|
2019-09-30 10:53:30 -04:00
|
|
|
@@ -695,7 +705,7 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
|
|
|
|
|
goto done;
|
|
|
|
|
get_irq_user_policy(devpath, irqnum, &pol);
|
2020-03-24 11:44:22 +08:00
|
|
|
if ((pol.ban == 1) || (check_for_irq_ban(devpath, irqnum, tmp_list))) {
|
|
|
|
|
- __add_banned_irq(irqnum, &banned_irqs);
|
|
|
|
|
+ __add_banned_irq(irqnum, &banned_irqs, 0);
|
2019-09-30 10:53:30 -04:00
|
|
|
goto done;
|
|
|
|
|
}
|
2020-03-24 11:44:22 +08:00
|
|
|
if (!is_proc_irq_info_exist(irqnum, tmp_list)) {
|
2019-09-30 10:53:30 -04:00
|
|
|
@@ -811,6 +821,9 @@ void free_irq_db(void)
|
|
|
|
|
banned_irqs = NULL;
|
|
|
|
|
g_list_free(rebalance_irq_list);
|
|
|
|
|
rebalance_irq_list = NULL;
|
|
|
|
|
+ for_each_irq(vm_banned_irqs, free_irq, NULL);
|
|
|
|
|
+ g_list_free(vm_banned_irqs);
|
|
|
|
|
+ vm_banned_irqs = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void free_cl_opts(void)
|
|
|
|
|
@@ -832,7 +845,7 @@ struct irq_info *add_new_irq(int irq, struct irq_info *hint, GList *proc_interru
|
|
|
|
|
/* Set NULL devpath for the irq has no sysfs entries */
|
|
|
|
|
get_irq_user_policy(NULL, irq, &pol);
|
|
|
|
|
if ((pol.ban == 1) || check_for_irq_ban(NULL, irq, proc_interrupts)) { /*FIXME*/
|
2020-03-24 11:44:22 +08:00
|
|
|
- __add_banned_irq(irq, &banned_irqs);
|
|
|
|
|
+ __add_banned_irq(irq, &banned_irqs, 0);
|
2019-09-30 10:53:30 -04:00
|
|
|
new = get_irq_info(irq);
|
|
|
|
|
} else
|
|
|
|
|
new = add_one_irq_to_db(NULL, hint, &pol);
|
|
|
|
|
@@ -906,6 +919,9 @@ struct irq_info *get_irq_info(int irq)
|
|
|
|
|
entry = g_list_find_custom(interrupts_db, &find, compare_ints);
|
|
|
|
|
|
|
|
|
|
if (!entry)
|
|
|
|
|
+ entry = g_list_find_custom(vm_banned_irqs, &find, compare_ints);
|
|
|
|
|
+
|
|
|
|
|
+ if (!entry)
|
|
|
|
|
entry = g_list_find_custom(banned_irqs, &find, compare_ints);
|
|
|
|
|
|
|
|
|
|
return entry ? entry->data : NULL;
|
|
|
|
|
@@ -954,3 +970,31 @@ void sort_irq_list(GList **list)
|
|
|
|
|
{
|
|
|
|
|
*list = g_list_sort(*list, sort_irqs);
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * assigned pci device's irq in /proc/interrupts
|
|
|
|
|
+ * has keyword "vfio" or "kvm"
|
|
|
|
|
+ * and BDF notation "xxxx:xx:xx.x"
|
|
|
|
|
+ */
|
|
|
|
|
+int is_pci_assigned_irq(const char *line)
|
|
|
|
|
+{
|
|
|
|
|
+ const char *pos = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ pos = strstr(line, "vfio");
|
|
|
|
|
+ if (!pos) {
|
|
|
|
|
+ pos = strstr(line, "kvm");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!pos)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ while (*pos) {
|
|
|
|
|
+ if (*pos >= '0' && *pos <= '9') {
|
|
|
|
|
+ if (*(pos + 4) == ':' && *(pos + 7) == ':' && *(pos + 10) == '.')
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ pos++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
diff --git a/irqbalance.c b/irqbalance.c
|
|
|
|
|
index 4787cb2..40ec65c 100644
|
|
|
|
|
--- a/irqbalance.c
|
|
|
|
|
+++ b/irqbalance.c
|
|
|
|
|
@@ -44,6 +44,7 @@
|
|
|
|
|
#include "irqbalance.h"
|
|
|
|
|
|
|
|
|
|
volatile int keep_going = 1;
|
|
|
|
|
+volatile int ban_pci_assigned_irq = 1;
|
|
|
|
|
int socket_fd;
|
|
|
|
|
char socket_name[64];
|
|
|
|
|
int one_shot_mode;
|
|
|
|
|
@@ -375,6 +376,12 @@ gboolean scan()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void parse_ban_pci_assigned_irq(char *status)
|
|
|
|
|
+{
|
|
|
|
|
+ if (status && (0 == strcmp(status,"disabled")))
|
|
|
|
|
+ ban_pci_assigned_irq = 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
void get_irq_data(struct irq_info *irq, void *data)
|
|
|
|
|
{
|
|
|
|
|
char **irqdata = (char **)data;
|
|
|
|
|
@@ -619,6 +626,10 @@ int main(int argc, char** argv)
|
|
|
|
|
foreground_mode=1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (getenv("IRQBALANCE_AUTO_BAN_PCI_ASSIGNED_IRQS")) {
|
|
|
|
|
+ parse_ban_pci_assigned_irq(getenv("IRQBALANCE_AUTO_BAN_PCI_ASSIGNED_IRQS"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
/*
|
|
|
|
|
* If we are't in debug mode, don't dump anything to the console
|
|
|
|
|
* note that everything goes to the console before we check this
|
|
|
|
|
diff --git a/irqbalance.h b/irqbalance.h
|
|
|
|
|
index 5016cc8..339e2a3 100644
|
|
|
|
|
--- a/irqbalance.h
|
|
|
|
|
+++ b/irqbalance.h
|
2020-03-24 11:44:22 +08:00
|
|
|
@@ -103,6 +103,8 @@ extern void free_cl_opts(void);
|
|
|
|
|
extern void add_cl_banned_module(char *modname);
|
|
|
|
|
extern void add_banned_irq(int irq);
|
|
|
|
|
extern void remove_one_irq_from_db(int irq);
|
2019-09-30 10:53:30 -04:00
|
|
|
+extern void add_vm_banned_irq(int irq);
|
|
|
|
|
+extern int is_pci_assigned_irq(const char *line);
|
2020-03-24 11:44:22 +08:00
|
|
|
#define irq_numa_node(irq) ((irq)->numa_node)
|
|
|
|
|
|
|
|
|
|
extern struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list);
|
2019-09-30 10:53:30 -04:00
|
|
|
diff --git a/procinterrupts.c b/procinterrupts.c
|
|
|
|
|
index 6cfa661..522b9a1 100644
|
|
|
|
|
--- a/procinterrupts.c
|
|
|
|
|
+++ b/procinterrupts.c
|
|
|
|
|
@@ -42,6 +42,7 @@
|
|
|
|
|
static int proc_int_has_msi = 0;
|
|
|
|
|
static int msi_found_in_sysfs = 0;
|
2020-03-24 11:44:22 +08:00
|
|
|
int need_add_single = 0;
|
2019-09-30 10:53:30 -04:00
|
|
|
+extern int ban_pci_assigned_irq;
|
|
|
|
|
|
|
|
|
|
#ifdef AARCH64
|
|
|
|
|
struct irq_match {
|
2020-03-24 11:44:22 +08:00
|
|
|
@@ -269,6 +270,13 @@ GList* collect_full_irq_list()
|
2019-09-30 10:53:30 -04:00
|
|
|
c++;
|
|
|
|
|
number = strtoul(line, NULL, 10);
|
|
|
|
|
|
|
|
|
|
+ if (ban_pci_assigned_irq && is_pci_assigned_irq(c)) {
|
|
|
|
|
+ log(TO_ALL, LOG_INFO, "Banned PCI-assigned irq %d.\n", number);
|
|
|
|
|
+ add_vm_banned_irq(number);
|
2020-03-24 11:44:22 +08:00
|
|
|
+ free(savedline);
|
2019-09-30 10:53:30 -04:00
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
2020-03-24 11:44:22 +08:00
|
|
|
info = calloc(sizeof(struct irq_info), 1);
|
|
|
|
|
if (info) {
|
|
|
|
|
init_irq_class_and_type(savedline, info, number);
|
2019-09-30 10:53:30 -04:00
|
|
|
@@ -333,6 +340,7 @@ void parse_proc_interrupts(void)
|
|
|
|
|
FILE *file;
|
|
|
|
|
char *line = NULL;
|
|
|
|
|
size_t size = 0;
|
|
|
|
|
+ int vfio_flag = 0;
|
|
|
|
|
|
|
|
|
|
file = fopen("/proc/interrupts", "r");
|
|
|
|
|
if (!file)
|
|
|
|
|
@@ -400,6 +408,21 @@ void parse_proc_interrupts(void)
|
2020-03-24 11:44:22 +08:00
|
|
|
free(savedline);
|
2019-09-30 10:53:30 -04:00
|
|
|
info->existing = 1;
|
|
|
|
|
|
|
|
|
|
+ if (ban_pci_assigned_irq) {
|
|
|
|
|
+ vfio_flag = is_pci_assigned_irq(c);
|
|
|
|
|
+ if (vfio_flag && (info->flags & IRQ_FLAG_VM_BANNED) == 0) {
|
|
|
|
|
+ log(TO_ALL, LOG_INFO, "IRQ %d has been reused as a pci assigned interrupt number", number);
|
|
|
|
|
+ need_rescan = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!vfio_flag && (info->flags & IRQ_FLAG_VM_BANNED) != 0) {
|
|
|
|
|
+ log(TO_ALL, LOG_INFO, "IRQ %d has been reused as a general interrupt number", number);
|
|
|
|
|
+ need_rescan = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
count = 0;
|
|
|
|
|
cpunr = 0;
|
|
|
|
|
|
|
|
|
|
diff --git a/types.h b/types.h
|
|
|
|
|
index 62cc2bb..c0950ee 100644
|
|
|
|
|
--- a/types.h
|
|
|
|
|
+++ b/types.h
|
|
|
|
|
@@ -35,6 +35,7 @@
|
|
|
|
|
* IRQ Internal tracking flags
|
|
|
|
|
*/
|
|
|
|
|
#define IRQ_FLAG_BANNED 1
|
2020-03-24 11:44:22 +08:00
|
|
|
+#define IRQ_FLAG_VM_BANNED 2
|
2019-09-30 10:53:30 -04:00
|
|
|
|
|
|
|
|
enum obj_type_e {
|
|
|
|
|
OBJ_TYPE_CPU,
|
|
|
|
|
--
|
|
|
|
|
1.8.3.1
|
|
|
|
|
|