Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Avoid strict-aliasing related issues when compiling with optimization
[palacios.git] / linux_module / linux-exts.c
1 #include "linux-exts.h"
2
3 /* 
4  * This is a place holder to ensure that the _lnx_exts section gets created by gcc
5  */
6
7 static struct {} null_ext  __attribute__((__used__))                    \
8     __attribute__((unused, __section__ ("_lnx_exts"),                   \
9                    aligned(sizeof(void *))));
10
11
12
13 /*                 */
14 /* Global controls */
15 /*                 */
16
17 struct rb_root global_ctrls;
18
19 static inline struct global_ctrl * __insert_global_ctrl(struct global_ctrl * ctrl) {
20     struct rb_node ** p = &(global_ctrls.rb_node);
21     struct rb_node * parent = NULL;
22     struct global_ctrl * tmp_ctrl = NULL;
23
24     while (*p) {
25         parent = *p;
26         tmp_ctrl = rb_entry(parent, struct global_ctrl, tree_node);
27
28         if (ctrl->cmd < tmp_ctrl->cmd) {
29             p = &(*p)->rb_left;
30         } else if (ctrl->cmd > tmp_ctrl->cmd) {
31             p = &(*p)->rb_right;
32         } else {
33             return tmp_ctrl;
34         }
35     }
36
37     rb_link_node(&(ctrl->tree_node), parent, p);
38
39     return NULL;
40 }
41
42
43
44 int add_global_ctrl(unsigned int cmd, 
45                    int (*handler)(unsigned int cmd, unsigned long arg)) {
46     struct global_ctrl * ctrl = palacios_alloc_extended(sizeof(struct global_ctrl), GFP_KERNEL,-1);
47
48     if (ctrl == NULL) {
49         printk("Error: Could not allocate global ctrl %d\n", cmd);
50         return -1;
51     }
52
53     ctrl->cmd = cmd;
54     ctrl->handler = handler;
55
56     if (__insert_global_ctrl(ctrl) != NULL) { 
57         printk("Could not insert guest ctrl %d\n", cmd);
58         palacios_free(ctrl);
59         return -1;
60     }
61     
62     rb_insert_color(&(ctrl->tree_node), &(global_ctrls));
63
64     return 0;
65 }
66
67
68 static struct rb_node * find_match(unsigned int cmd) {
69     struct rb_node * n = global_ctrls.rb_node;
70     struct global_ctrl *ctrl;
71
72     while (n) {
73         ctrl = rb_entry(n, struct global_ctrl, tree_node);
74
75         if (cmd < ctrl->cmd) {
76             n = n->rb_left;
77         } else if (cmd > ctrl->cmd) {
78             n = n->rb_right;
79         } else {
80             return n;
81         }
82     }
83
84     return NULL;
85 }
86
87
88 struct global_ctrl * get_global_ctrl(unsigned int cmd) {
89     struct rb_node *n = find_match(cmd);
90
91     if (n) {
92         return rb_entry(n, struct global_ctrl, tree_node);
93     } else {
94         return NULL;
95     }
96 }
97       
98
99 int remove_global_ctrl(unsigned int cmd)
100 {
101     struct rb_node *n = find_match(cmd);
102     struct global_ctrl *c;
103
104     if (!n) { 
105         return -1;
106     }
107
108     c = rb_entry(n, struct global_ctrl, tree_node);
109
110     rb_erase(n,&global_ctrls);
111     
112     if (c) { 
113         palacios_free(c);
114     }
115     
116     return 0;
117 }
118
119
120
121
122
123 /*             */
124 /* VM Controls */
125 /*             */
126
127 struct vm_ext {
128     struct linux_ext * impl;
129     void * vm_data;
130     struct list_head node;
131 };
132
133
134 void * get_vm_ext_data(struct v3_guest * guest, char * ext_name) {
135     struct vm_ext * ext = NULL;
136
137     list_for_each_entry(ext, &(guest->exts), node) {
138         if (strncmp(ext->impl->name, ext_name, strlen(ext->impl->name)) == 0) {
139             return ext->vm_data;
140         }
141     }
142
143     return NULL;
144 }
145
146
147 int init_vm_extensions(struct v3_guest * guest) {
148     extern struct linux_ext * __start__lnx_exts[];
149     extern struct linux_ext * __stop__lnx_exts[];
150     struct linux_ext * ext_impl = __start__lnx_exts[0];
151     int i = 0;
152
153     while (ext_impl != __stop__lnx_exts[0]) {
154         struct vm_ext * ext = NULL;
155
156         if (ext_impl->guest_init == NULL) {
157             // We can have global extensions without per guest state
158             ext_impl = __start__lnx_exts[++i];
159             continue;
160         }
161         
162         INFO("Registering Linux Extension (%s)\n", ext_impl->name);
163
164         ext = palacios_alloc(sizeof(struct vm_ext));
165         
166         if (!ext) {
167             WARNING("Error allocating VM extension (%s)\n", ext_impl->name);
168             return -1;
169         }
170
171         ext->impl = ext_impl;
172
173         ext_impl->guest_init(guest, &(ext->vm_data));
174
175         list_add(&(ext->node), &(guest->exts));
176
177         ext_impl = __start__lnx_exts[++i];
178     }
179     
180     return 0;
181 }
182
183
184
185 int deinit_vm_extensions(struct v3_guest * guest) {
186     struct vm_ext * ext = NULL;
187     struct vm_ext * tmp = NULL;
188
189     list_for_each_entry_safe(ext, tmp, &(guest->exts), node) {
190         if (ext->impl->guest_deinit) {
191             ext->impl->guest_deinit(guest, ext->vm_data);
192         } else {
193             WARNING("WARNING: Extension %s, does not have a guest deinit function\n", ext->impl->name);
194         }
195
196         list_del(&(ext->node));
197         palacios_free(ext);
198     }
199
200     return 0;
201 }
202
203
204 int init_lnx_extensions( void ) {
205     extern struct linux_ext * __start__lnx_exts[];
206     extern struct linux_ext * __stop__lnx_exts[];
207     struct linux_ext * tmp_ext = __start__lnx_exts[0];
208     int i = 0;
209
210     while (tmp_ext != __stop__lnx_exts[0]) {
211
212         DEBUG("tmp_ext=%p\n", tmp_ext);
213
214         if (tmp_ext->init != NULL) {
215             INFO("Registering Linux Extension (%s)\n", tmp_ext->name);
216             tmp_ext->init();
217         }
218
219         tmp_ext = __start__lnx_exts[++i];
220     }
221     
222     return 0;
223 }
224
225
226 int deinit_lnx_extensions( void ) {
227     extern struct linux_ext * __start__lnx_exts[];
228     extern struct linux_ext * __stop__lnx_exts[];
229     struct linux_ext * tmp_ext = __start__lnx_exts[0];
230     int i = 0;
231
232     while (tmp_ext != __stop__lnx_exts[0]) {
233         INFO("Cleaning up Linux Extension (%s)\n", tmp_ext->name);
234
235         if (tmp_ext->deinit != NULL) {
236             tmp_ext->deinit();
237         } else {
238             WARNING("WARNING: Extension %s does not have a global deinit function\n", tmp_ext->name);
239         }
240
241         tmp_ext = __start__lnx_exts[++i];
242     }
243     
244     return 0;
245 }
246