debuggers.hg

view xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c @ 631:74a0503a5f5a

bitkeeper revision 1.329.1.2 (3f0d406al_xEBmfvKg96FZ0PQ1E94w)

Make some comments slightly more comprehensible.
author sos22@labyrinth.cl.cam.ac.uk
date Thu Jul 10 10:31:06 2003 +0000 (2003-07-10)
parents 3539152a9fab
children 681598b3259f
line source
1 /******************************************************************************
2 * dom0_core.c
3 *
4 * Interface to privileged domain-0 commands.
5 *
6 * Copyright (c) 2002, K A Fraser, B Dragovic
7 */
9 #include <linux/config.h>
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/slab.h>
14 #include <linux/string.h>
15 #include <linux/errno.h>
16 #include <linux/proc_fs.h>
18 #include <linux/mm.h>
19 #include <linux/mman.h>
20 #include <linux/swap.h>
21 #include <linux/smp_lock.h>
22 #include <linux/swapctl.h>
23 #include <linux/iobuf.h>
24 #include <linux/highmem.h>
25 #include <linux/pagemap.h>
26 #include <linux/seq_file.h>
28 #include <asm/pgalloc.h>
29 #include <asm/pgtable.h>
30 #include <asm/uaccess.h>
31 #include <asm/tlb.h>
32 #include <asm/dom0.h>
34 #include "dom0_ops.h"
36 #define MAP_DISCONT 1
38 /* Private proc-file data structures. */
39 typedef struct proc_data {
40 unsigned int domain;
41 unsigned long map_size;
42 } dom_procdata_t;
44 /* XXX this certainly shouldn't be here. */
45 extern struct file_operations dom0_phd_fops;
47 struct proc_dir_entry *xeno_base;
48 static struct proc_dir_entry *dom0_cmd_intf;
49 static struct proc_dir_entry *dom_list_intf;
51 int direct_unmap(struct mm_struct *, unsigned long, unsigned long);
52 unsigned long direct_mmap(unsigned long phys_addr, unsigned long size,
53 pgprot_t prot, int flag, int tot_pages);
54 struct list_head * find_direct(struct list_head *, unsigned long);
56 static ssize_t dom_usage_read(struct file * file, char * buff, size_t size, loff_t * off)
57 {
58 char str[256];
59 int vifs[32];
60 dom0_op_t op;
61 network_op_t netop;
62 int i, end;
63 unsigned int domain;
64 static int finished = 0;
66 if ( finished )
67 {
68 finished = 0;
69 return 0;
70 }
72 domain = (unsigned int)
73 ((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
74 op.cmd = DOM0_GETDOMAININFO;
76 op.u.getdominfo.domain = domain;
78 (void) HYPERVISOR_dom0_op(&op);
80 end = snprintf(str, 256, "cpu: %lld\n", op.u.getdominfo.cpu_time);
82 netop.cmd = NETWORK_OP_VIFQUERY;
83 netop.u.vif_query.domain = domain;
84 netop.u.vif_query.buf = vifs;
86 (void) HYPERVISOR_network_op(&netop);
88 for(i = 1; i <= vifs[0]; i++) {
89 netop.cmd = NETWORK_OP_VIFGETINFO;
90 netop.u.vif_getinfo.domain = domain;
91 netop.u.vif_getinfo.vif = vifs[i];
93 (void) HYPERVISOR_network_op(&netop);
95 end += snprintf(str + end, 255 - end,
96 "vif%d: sent %lld bytes (%lld packets) "
97 "received %lld bytes (%lld packets)\n",
98 vifs[i],
99 netop.u.vif_getinfo.total_bytes_sent,
100 netop.u.vif_getinfo.total_packets_sent,
101 netop.u.vif_getinfo.total_bytes_received,
102 netop.u.vif_getinfo.total_packets_received);
103 }
105 if (*off >= end + 1) return 0;
107 copy_to_user(buff, str, end);
109 finished = 1;
111 return end + 1;
112 }
114 static struct file_operations dom_usage_ops = {
115 read: dom_usage_read
116 };
119 static void create_proc_dom_entries(int dom)
120 {
121 struct proc_dir_entry * dir;
122 dom_procdata_t * dom_data;
123 char dir_name[16];
124 struct proc_dir_entry * file;
126 sprintf(dir_name, "dom%d", dom);
128 dom_data = (dom_procdata_t *)kmalloc(sizeof(dom_procdata_t), GFP_KERNEL);
129 dom_data->domain = dom;
131 dir = proc_mkdir(dir_name, xeno_base);
132 dir->data = dom_data;
134 file = create_proc_entry("usage", 0600, dir);
135 if (file != NULL)
136 {
137 file->owner = THIS_MODULE;
138 file->nlink = 1;
139 file->proc_fops = &dom_usage_ops;
140 file->data = (void *) dom;
141 }
143 file = create_proc_entry("phd", 0600, dir);
144 if (file != NULL)
145 {
146 file->owner = THIS_MODULE;
147 file->nlink = 1;
148 file->proc_fops = &dom0_phd_fops;
149 file->data = (void *) dom;
150 }
151 }
153 /***********************************************************************
154 *
155 * Implementation of /proc/xeno/domains
156 */
158 static dom0_op_t proc_domains_op;
159 static int proc_domains_finished;
160 static DECLARE_MUTEX(proc_xeno_domains_lock);
162 static void *xeno_domains_next(struct seq_file *s, void *v, loff_t *pos)
163 {
164 int ret;
166 if ( pos != NULL )
167 ++(*pos);
169 if ( !proc_domains_finished )
170 {
171 proc_domains_op.u.getdominfo.domain++;
172 ret = HYPERVISOR_dom0_op(&proc_domains_op);
173 if ( ret < 0 )
174 proc_domains_finished = 1;
175 }
177 return (proc_domains_finished) ? NULL : &proc_domains_op;
178 }
180 static void *xeno_domains_start(struct seq_file *s, loff_t *ppos)
181 {
182 loff_t pos = *ppos;
184 down (&proc_xeno_domains_lock);
185 proc_domains_op.cmd = DOM0_GETDOMAININFO;
186 proc_domains_op.u.getdominfo.domain = 0;
187 (void)HYPERVISOR_dom0_op(&proc_domains_op);
188 proc_domains_finished = 0;
190 while (pos > 0) {
191 pos --;
192 xeno_domains_next (s, NULL, NULL);
193 }
195 return (proc_domains_finished) ? NULL : &proc_domains_op;
196 }
198 static void xeno_domains_stop(struct seq_file *s, void *v)
199 {
200 up(&proc_xeno_domains_lock);
201 }
203 static int xeno_domains_show(struct seq_file *s, void *v)
204 {
205 dom0_op_t *di = v;
207 /*
208 * Output one domain's details to dom0.
209 *
210 * If you update this format string then change xi_list to match.
211 */
213 seq_printf (s,
214 "%8d %2d %1d %2d %8d %8ld %p %8d %s\n",
215 di -> u.getdominfo.domain,
216 di -> u.getdominfo.processor,
217 di -> u.getdominfo.has_cpu,
218 di -> u.getdominfo.state,
219 di -> u.getdominfo.hyp_events,
220 di -> u.getdominfo.mcu_advance,
221 (void *)di -> u.getdominfo.pg_head,
222 di -> u.getdominfo.tot_pages,
223 di -> u.getdominfo.name);
225 return 0;
226 }
228 static struct seq_operations xeno_domains_op = {
229 .start = xeno_domains_start,
230 .next = xeno_domains_next,
231 .stop = xeno_domains_stop,
232 .show = xeno_domains_show,
233 };
235 static int xeno_domains_open(struct inode *inode, struct file *file)
236 {
237 return seq_open(file, &xeno_domains_op);
238 }
240 static struct file_operations proc_xeno_domains_operations = {
241 open: xeno_domains_open,
242 read: seq_read,
243 llseek: seq_lseek,
244 release: seq_release,
245 };
247 /***********************************************************************
248 *
249 * Implementation of /proc/xeno/dom0_cmd
250 */
252 static int dom0_cmd_write(struct file *file, const char *buffer, size_t size,
253 loff_t *off)
254 {
255 dom0_op_t op;
257 copy_from_user(&op, buffer, sizeof(dom0_op_t));
259 return HYPERVISOR_dom0_op(&op);
260 }
262 static int handle_dom0_cmd_createdomain(unsigned long data)
263 {
264 struct dom0_createdomain_args argbuf;
265 int namelen;
266 dom0_op_t op;
267 int ret;
269 if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
270 return -EFAULT;
272 op.cmd = DOM0_CREATEDOMAIN;
273 op.u.newdomain.domain = -666;
274 op.u.newdomain.memory_kb = argbuf.kb_mem;
275 op.u.newdomain.num_vifs = 0; /* Not used anymore -- it's done in
276 BUILDDOMAIN. */
277 namelen = strnlen_user(argbuf.name, MAX_DOMAIN_NAME);
278 if (copy_from_user(op.u.newdomain.name, argbuf.name, namelen + 1))
279 return -EFAULT;
281 /* Error checking? The old code deosn't appear to do any, and I
282 can't see where the return values are documented... */
283 ret = HYPERVISOR_dom0_op(&op);
285 if (op.u.newdomain.domain == -666) {
286 /* HACK: We use this to detect whether the create actually
287 succeeded, because Xen doesn't appear to want to tell us... */
289 /* The only time I've actually got this to happen was when trying
290 to create a domain with more memory than is actually in the
291 machine, so we guess the error code is ENOMEM. */
292 return -ENOMEM;
293 }
295 /* Create proc entries */
296 ret = op.u.newdomain.domain;
297 create_proc_dom_entries(ret);
299 return ret;
300 }
302 static unsigned long handle_dom0_cmd_mapdommem(unsigned long data)
303 {
304 struct dom0_mapdommem_args argbuf;
306 if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
307 return -EFAULT;
309 return direct_mmap(argbuf.start_pfn << PAGE_SHIFT,
310 argbuf.tot_pages << PAGE_SHIFT,
311 PAGE_SHARED,
312 MAP_DISCONT,
313 argbuf.tot_pages);
314 }
316 static int handle_dom0_cmd_unmapdommem(unsigned long data)
317 {
318 struct dom0_unmapdommem_args argbuf;
320 if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
321 return -EFAULT;
323 return direct_unmap(current->mm, argbuf.vaddr,
324 argbuf.tot_pages << PAGE_SHIFT);
325 }
327 static int handle_dom0_cmd_dopgupdates(unsigned long data)
328 {
329 struct dom0_dopgupdates_args argbuf;
330 struct list_head *entry;
331 direct_mmap_node_t *node;
333 if (copy_from_user(&argbuf, (void *)data, sizeof(argbuf)))
334 return -EFAULT;
336 /* argbuf.pgt_update_arr had better be direct mapped... */
337 /* Actually, we only *really* need to make sure that all of it's
338 pages are in memory and aren't going to get swapped out in the
339 mean time, but this is slightly easier than checking all of
340 that and is sufficient for the current userspace tools. */
341 entry = find_direct(&current->mm->context.direct_list,
342 argbuf.pgt_update_arr);
343 if (entry == &current->mm->context.direct_list)
344 return -EINVAL;
345 node = list_entry(entry, direct_mmap_node_t, list);
346 if (node->vm_start > argbuf.pgt_update_arr ||
347 node->vm_end <= argbuf.pgt_update_arr * sizeof(page_update_request_t))
348 return -EINVAL;
350 return HYPERVISOR_pt_update((void *)argbuf.pgt_update_arr,
351 argbuf.num_pgt_updates);
352 }
354 static int dom0_cmd_ioctl(struct inode *inode, struct file *file,
355 unsigned int cmd, unsigned long data)
356 {
357 switch (cmd) {
358 case IOCTL_DOM0_CREATEDOMAIN:
359 return handle_dom0_cmd_createdomain(data);
360 case IOCTL_DOM0_MAPDOMMEM:
361 return handle_dom0_cmd_mapdommem(data);
362 case IOCTL_DOM0_UNMAPDOMMEM:
363 return handle_dom0_cmd_unmapdommem(data);
364 case IOCTL_DOM0_DOPGUPDATES:
365 return handle_dom0_cmd_dopgupdates(data);
366 default:
367 return -ENOTTY; /* It isn't obvious why this is the correct error
368 code when an ioctl isn't recognised, but it
369 does appear to be what's used in the rest of
370 the kernel. */
371 }
372 }
374 /***********************************************************************/
377 static struct file_operations dom0_cmd_file_ops = {
378 write : dom0_cmd_write,
379 ioctl : dom0_cmd_ioctl
380 };
382 static int __init init_module(void)
383 {
384 /* xeno proc root setup */
385 xeno_base = proc_mkdir("xeno", &proc_root);
387 /* xeno control interface */
388 dom0_cmd_intf = create_proc_entry("dom0_cmd", 0600, xeno_base);
390 if ( dom0_cmd_intf != NULL )
391 {
392 dom0_cmd_intf->owner = THIS_MODULE;
393 dom0_cmd_intf->nlink = 1;
394 dom0_cmd_intf->proc_fops = &dom0_cmd_file_ops;
395 }
397 /* domain list interface */
398 dom_list_intf = create_proc_entry("domains", 0400, xeno_base);
399 if ( dom_list_intf != NULL )
400 {
401 dom_list_intf->owner = THIS_MODULE;
402 dom_list_intf->nlink = 1;
403 dom_list_intf->proc_fops = &proc_xeno_domains_operations;
404 }
406 /* set up /proc entries for dom 0 */
407 create_proc_dom_entries(0);
409 return 0;
410 }
413 static void __exit cleanup_module(void)
414 {
415 if ( dom0_cmd_intf == NULL ) return;
416 remove_proc_entry("dom0", &proc_root);
417 dom0_cmd_intf = NULL;
418 }
421 module_init(init_module);
422 module_exit(cleanup_module);