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.


added host_pci passthrough PCI support
[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 = kmalloc(sizeof(struct global_ctrl), GFP_KERNEL);
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         kfree(ctrl);
59         return -1;
60     }
61     
62     rb_insert_color(&(ctrl->tree_node), &(global_ctrls));
63
64     return 0;
65 }
66
67
68 struct global_ctrl * get_global_ctrl(unsigned int cmd) {
69     struct rb_node * n = global_ctrls.rb_node;
70     struct global_ctrl * ctrl = NULL;
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 ctrl;
81         }
82     }
83
84     return NULL;
85 }
86
87
88
89
90
91 /*             */
92 /* VM Controls */
93 /*             */
94
95 struct vm_ext {
96     struct linux_ext * impl;
97     void * vm_data;
98     struct list_head node;
99 };
100
101
102 void * get_vm_ext_data(struct v3_guest * guest, char * ext_name) {
103     struct vm_ext * ext = NULL;
104
105     list_for_each_entry(ext, &(guest->exts), node) {
106         if (strncmp(ext->impl->name, ext_name, strlen(ext->impl->name)) == 0) {
107             return ext->vm_data;
108         }
109     }
110
111     return NULL;
112 }
113
114
115 int init_vm_extensions(struct v3_guest * guest) {
116     extern struct linux_ext * __start__lnx_exts[];
117     extern struct linux_ext * __stop__lnx_exts[];
118     struct linux_ext * ext_impl = __start__lnx_exts[0];
119     int i = 0;
120
121     while (ext_impl != __stop__lnx_exts[0]) {
122         struct vm_ext * ext = NULL;
123
124         if (ext_impl->guest_init == NULL) {
125             // We can have global extensions without per guest state
126             ext_impl = __start__lnx_exts[++i];
127             continue;
128         }
129         
130         INFO("Registering Linux Extension (%s)\n", ext_impl->name);
131
132         ext = palacios_alloc(sizeof(struct vm_ext));
133         
134         if (!ext) {
135             WARNING("Error allocating VM extension (%s)\n", ext_impl->name);
136             return -1;
137         }
138
139         ext->impl = ext_impl;
140
141         ext_impl->guest_init(guest, &(ext->vm_data));
142
143         list_add(&(ext->node), &(guest->exts));
144
145         ext_impl = __start__lnx_exts[++i];
146     }
147     
148     return 0;
149 }
150
151
152
153 int deinit_vm_extensions(struct v3_guest * guest) {
154     struct vm_ext * ext = NULL;
155     struct vm_ext * tmp = NULL;
156
157     list_for_each_entry_safe(ext, tmp, &(guest->exts), node) {
158         if (ext->impl->guest_deinit) {
159             ext->impl->guest_deinit(guest, ext->vm_data);
160         } else {
161             WARNING("WARNING: Extension %s, does not have a guest deinit function\n", ext->impl->name);
162         }
163
164         list_del(&(ext->node));
165         palacios_free(ext);
166     }
167
168     return 0;
169 }
170
171
172 int init_lnx_extensions( void ) {
173     extern struct linux_ext * __start__lnx_exts[];
174     extern struct linux_ext * __stop__lnx_exts[];
175     struct linux_ext * tmp_ext = __start__lnx_exts[0];
176     int i = 0;
177
178     while (tmp_ext != __stop__lnx_exts[0]) {
179
180         DEBUG("tmp_ext=%p\n", tmp_ext);
181
182         if (tmp_ext->init != NULL) {
183             INFO("Registering Linux Extension (%s)\n", tmp_ext->name);
184             tmp_ext->init();
185         }
186
187         tmp_ext = __start__lnx_exts[++i];
188     }
189     
190     return 0;
191 }
192
193
194 int deinit_lnx_extensions( void ) {
195     extern struct linux_ext * __start__lnx_exts[];
196     extern struct linux_ext * __stop__lnx_exts[];
197     struct linux_ext * tmp_ext = __start__lnx_exts[0];
198     int i = 0;
199
200     while (tmp_ext != __stop__lnx_exts[0]) {
201         INFO("Cleaning up Linux Extension (%s)\n", tmp_ext->name);
202
203         if (tmp_ext->deinit != NULL) {
204             tmp_ext->deinit();
205         } else {
206             WARNING("WARNING: Extension %s does not have a global deinit function\n", tmp_ext->name);
207         }
208
209         tmp_ext = __start__lnx_exts[++i];
210     }
211     
212     return 0;
213 }
214