1 #include "kvm/guest_compat.h"
2
3 #include "kvm/mutex.h"
4
5 #include <linux/kernel.h>
6 #include <linux/list.h>
7
8 struct compat_message {
9 int id;
10 char *title;
11 char *desc;
12
13 struct list_head list;
14 };
15
16 static int id;
17 static DEFINE_MUTEX(compat_mtx);
18 static LIST_HEAD(messages);
19
compat__free(struct compat_message * msg)20 static void compat__free(struct compat_message *msg)
21 {
22 free(msg->title);
23 free(msg->desc);
24 free(msg);
25 }
26
compat__add_message(const char * title,const char * desc)27 int compat__add_message(const char *title, const char *desc)
28 {
29 struct compat_message *msg;
30 int msg_id;
31
32 msg = malloc(sizeof(*msg));
33 if (msg == NULL)
34 goto cleanup;
35
36 msg->title = strdup(title);
37 msg->desc = strdup(desc);
38
39 if (msg->title == NULL || msg->desc == NULL)
40 goto cleanup;
41
42 mutex_lock(&compat_mtx);
43
44 msg->id = msg_id = id++;
45 list_add_tail(&msg->list, &messages);
46
47 mutex_unlock(&compat_mtx);
48
49 return msg_id;
50
51 cleanup:
52 if (msg)
53 compat__free(msg);
54
55 return -ENOMEM;
56 }
57
compat__remove_message(int id)58 int compat__remove_message(int id)
59 {
60 struct compat_message *pos, *n;
61
62 mutex_lock(&compat_mtx);
63
64 list_for_each_entry_safe(pos, n, &messages, list) {
65 if (pos->id == id) {
66 list_del(&pos->list);
67 compat__free(pos);
68
69 mutex_unlock(&compat_mtx);
70
71 return 0;
72 }
73 }
74
75 mutex_unlock(&compat_mtx);
76
77 return -ENOENT;
78 }
79
compat__print_all_messages(void)80 int compat__print_all_messages(void)
81 {
82 mutex_lock(&compat_mtx);
83
84 while (!list_empty(&messages)) {
85 struct compat_message *msg;
86
87 msg = list_first_entry(&messages, struct compat_message, list);
88
89 pr_warning("KVM compatibility warning.\n\t%s\n\t%s",
90 msg->title, msg->desc);
91
92 list_del(&msg->list);
93 compat__free(msg);
94 }
95
96 mutex_unlock(&compat_mtx);
97
98 return 0;
99 }
100