ia64/xen-unstable

view xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_core.c @ 83:7c48a158429c

bitkeeper revision 1.7.3.58 (3e14aa78jPxKgtkJQt93U8n0Lfr_Og)

debug
author lynx@idefix.cl.cam.ac.uk
date Thu Jan 02 21:09:12 2003 +0000 (2003-01-02)
parents dd6547801b23
children 336647fd8f40
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>
27 #include <asm/pgalloc.h>
28 #include <asm/pgtable.h>
29 #include <asm/uaccess.h>
30 #include <asm/tlb.h>
32 #include "dom0_ops.h"
33 #include "hypervisor_defs.h"
35 #define XENO_BASE "xeno" // proc file name defs should be in separate .h
36 #define DOM0_CMD_INTF "dom0_cmd"
37 #define DOM0_FT "frame_table"
38 #define DOM0_NEWDOM "new_dom_id"
40 #define MAX_LEN 16
41 #define DOM_DIR "dom"
42 #define DOM_TS "task_data"
43 #define DOM_MEM "mem"
45 static struct proc_dir_entry *xeno_base;
46 static struct proc_dir_entry *dom0_cmd_intf;
47 static struct proc_dir_entry *proc_ft;
49 unsigned long direct_mmap(unsigned long, unsigned long, pgprot_t, int, int);
50 int direct_unmap(unsigned long, unsigned long);
51 int direct_disc_unmap(unsigned long, unsigned long, int);
53 /* frame_table mapped from dom0 */
54 frame_table_t * frame_table;
55 unsigned long frame_table_len;
56 unsigned long frame_table_pa;
58 static unsigned char readbuf[1204];
60 static int cmd_read_proc(char *page, char **start, off_t off,
61 int count, int *eof, void *data)
62 {
63 strcpy(page, readbuf);
64 *readbuf = '\0';
65 *eof = 1;
66 *start = page;
67 return strlen(page);
68 }
70 static ssize_t ts_read(struct file * file, char * buff, size_t size, loff_t * off)
71 {
72 dom0_op_t op;
73 unsigned long addr;
74 pgprot_t prot;
75 int ret = 0;
77 /* retrieve domain specific data from proc_dir_entry */
78 dom_procdata_t * dom_data = (dom_procdata_t *)((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
80 /*
81 * get the phys addr of the task struct for the requested
82 * domain
83 */
84 op.cmd = DOM0_MAPTASK;
85 op.u.mapdomts.domain = dom_data->domain;
86 op.u.mapdomts.ts_phy_addr = -1;
88 ret = HYPERVISOR_dom0_op(&op);
89 if(ret != 0)
90 return -EAGAIN;
92 prot = PAGE_SHARED;
94 /* remap the range using xen specific routines */
95 addr = direct_mmap(op.u.mapdomts.ts_phy_addr, PAGE_SIZE, prot, 0, 0);
96 copy_to_user((unsigned long *)buff, &addr, sizeof(addr));
97 dom_data->map_size = PAGE_SIZE;
99 return sizeof(addr);
101 }
103 static ssize_t ts_write(struct file * file, const char * buff, size_t size , loff_t * off)
104 {
105 unsigned long addr;
106 dom_procdata_t * dom_data = (dom_procdata_t *)((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
108 copy_from_user(&addr, (unsigned long *)buff, sizeof(addr));
110 if(direct_unmap(addr, dom_data->map_size) == 0){
111 return sizeof(addr);
112 } else {
113 return -1;
114 }
115 }
117 struct file_operations ts_ops = {
118 read: ts_read,
119 write: ts_write,
120 };
122 static void create_proc_dom_entries(int dom)
123 {
124 struct proc_dir_entry * dir;
125 struct proc_dir_entry * file;
126 dom_procdata_t * dom_data;
127 char dir_name[MAX_LEN];
129 snprintf(dir_name, MAX_LEN, "%s%d", DOM_DIR, dom);
131 dom_data = (dom_procdata_t *)kmalloc(sizeof(dom_procdata_t), GFP_KERNEL);
132 dom_data->domain = dom;
134 dir = proc_mkdir(dir_name, xeno_base);
135 dir->data = dom_data;
137 file = create_proc_entry(DOM_TS, 0600, dir);
138 if(file != NULL)
139 {
140 file->owner = THIS_MODULE;
141 file->nlink = 1;
142 file->proc_fops = &ts_ops;
144 file->data = dom_data;
145 }
146 }
148 static ssize_t dom_mem_write(struct file * file, const char * buff,
149 size_t size , loff_t * off)
150 {
151 unsigned long addr;
152 proc_memdata_t * mem_data = (proc_memdata_t *)((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
154 copy_from_user(&addr, (unsigned long *)buff, sizeof(addr));
156 if(direct_disc_unmap(addr, mem_data->pfn, mem_data->tot_pages) == 0){
157 return sizeof(addr);
158 } else {
159 return -1;
160 }
161 }
163 static ssize_t dom_mem_read(struct file * file, char * buff, size_t size, loff_t * off)
164 {
165 unsigned long addr;
166 pgprot_t prot;
168 proc_memdata_t * mem_data = (proc_memdata_t *)((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
170 prot = PAGE_SHARED;
172 /* remap the range using xen specific routines */
174 addr = direct_mmap(mem_data->pfn << PAGE_SHIFT, mem_data->tot_pages << PAGE_SHIFT, prot, 0, 0);
175 printk(KERN_ALERT "bd240 debug: dom_mem_read: %lx, %lx @ %lx\n", mem_data->pfn << PAGE_SHIFT, mem_data->tot_pages << PAGE_SHIFT, addr);
177 copy_to_user((unsigned long *)buff, &addr, sizeof(addr));
179 printk(KERN_ALERT "bd240 debug: exiting dom_mem_read\n");
181 return sizeof(addr);
183 }
185 struct file_operations dom_mem_ops = {
186 read: dom_mem_read,
187 write: dom_mem_write,
188 };
190 static int dom_map_mem(unsigned int dom, unsigned long pfn, int tot_pages)
191 {
192 int ret = -ENOENT;
193 struct proc_dir_entry * pd = xeno_base->subdir;
194 struct proc_dir_entry * file;
195 proc_memdata_t * memdata;
197 while(pd != NULL){
199 if((pd->mode & S_IFDIR) && ((dom_procdata_t *)pd->data)->domain == dom){
201 /* check if there is already an entry for mem and if so
202 * remove it.
203 */
204 remove_proc_entry(DOM_MEM, pd);
206 /* create new entry with parameters describing what to do
207 * when it is mmaped.
208 */
209 file = create_proc_entry(DOM_MEM, 0600, pd);
210 if(file != NULL)
211 {
212 file->owner = THIS_MODULE;
213 file->nlink = 1;
214 file->proc_fops = &dom_mem_ops;
216 memdata = (proc_memdata_t *)kmalloc(sizeof(proc_memdata_t), GFP_KERNEL);
217 memdata->pfn = pfn;
218 memdata->tot_pages = tot_pages;
219 file->data = memdata;
221 printk(KERN_ALERT "bd240 debug: cmd setup dom mem: %lx, %d\n", memdata->pfn, memdata->tot_pages);
223 ret = 0;
224 break;
225 }
226 ret = -EAGAIN;
227 break;
228 }
229 pd = pd->next;
230 }
232 return ret;
233 }
235 /* return dom id stored as data pointer to userspace */
236 static int dom_id_read_proc(char *page, char **start, off_t off,
237 int count, int *eof, void *data)
238 {
239 char arg[16];
240 sprintf(arg, "%d", (int)data);
241 strcpy(page, arg);
242 remove_proc_entry(DOM0_NEWDOM, xeno_base);
243 return sizeof(unsigned int);
244 }
246 static int cmd_write_proc(struct file *file, const char *buffer,
247 u_long count, void *data)
248 {
249 dom0_op_t op;
250 int ret = 0;
251 struct proc_dir_entry * new_dom_id;
253 copy_from_user(&op, buffer, sizeof(dom0_op_t));
255 /* do some sanity checks */
256 if(op.cmd > MAX_CMD){
257 ret = -ENOSYS;
258 goto out;
259 }
261 /* is the request intended for hypervisor? */
262 if(op.cmd != MAP_DOM_MEM){
263 ret = HYPERVISOR_dom0_op(&op);
265 /* if new domain created, create proc entries */
266 if(op.cmd == DOM0_NEWDOMAIN){
267 create_proc_dom_entries(ret);
269 /* now notify user space of the new domain's id */
270 new_dom_id = create_proc_entry(DOM0_NEWDOM, 0600, xeno_base);
271 if ( new_dom_id != NULL )
272 {
273 new_dom_id->owner = THIS_MODULE;
274 new_dom_id->nlink = 1;
275 new_dom_id->read_proc = dom_id_read_proc;
276 new_dom_id->data = (void *)ret;
277 }
279 }
281 } else {
283 ret = dom_map_mem(op.u.reqdommem.domain, op.u.reqdommem.start_pfn,
284 op.u.reqdommem.tot_pages);
285 }
287 out:
288 return ret;
290 }
292 static ssize_t ft_write(struct file * file, const char * buff, size_t size , loff_t * off)
293 {
294 unsigned long addr;
296 copy_from_user(&addr, (unsigned long *)buff, sizeof(addr));
298 if(direct_unmap(addr, frame_table_len) == 0){
299 return sizeof(addr);
300 } else {
301 return -1;
302 }
303 }
305 static ssize_t ft_read(struct file * file, char * buff, size_t size, loff_t * off)
306 {
307 unsigned long addr;
308 pgprot_t prot;
310 prot = PAGE_SHARED;
312 /* remap the range using xen specific routines */
313 addr = direct_mmap(frame_table_pa, frame_table_len, prot, 0, 0);
314 copy_to_user((unsigned long *)buff, &addr, sizeof(addr));
316 return sizeof(addr);
318 }
320 struct file_operations ft_ops = {
321 read: ft_read,
322 write: ft_write,
323 };
325 static int __init init_module(void)
326 {
328 frame_table = (frame_table_t *)start_info.frame_table;
329 frame_table_len = start_info.frame_table_len;
330 frame_table_pa = start_info.frame_table_pa;
332 /* xeno proc root setup */
333 xeno_base = proc_mkdir(XENO_BASE, &proc_root);
335 /* xeno control interface */
336 *readbuf = '\0';
337 dom0_cmd_intf = create_proc_entry (DOM0_CMD_INTF, 0600, xeno_base);
338 if ( dom0_cmd_intf != NULL )
339 {
340 dom0_cmd_intf->owner = THIS_MODULE;
341 dom0_cmd_intf->nlink = 1;
342 dom0_cmd_intf->read_proc = cmd_read_proc;
343 dom0_cmd_intf->write_proc = cmd_write_proc;
344 }
346 /* frame table mapping, to be mmaped */
347 proc_ft = create_proc_entry(DOM0_FT, 0600, xeno_base);
348 if(proc_ft != NULL)
349 {
350 proc_ft->owner = THIS_MODULE;
351 proc_ft->nlink = 1;
352 proc_ft->proc_fops = &ft_ops;
353 }
355 /* set up /proc entries for dom 0 */
356 create_proc_dom_entries(0);
358 return 0;
359 }
362 static void __exit cleanup_module(void)
363 {
364 if ( dom0_cmd_intf == NULL ) return;
365 remove_proc_entry("dom0", &proc_root);
366 dom0_cmd_intf = NULL;
367 }
370 module_init(init_module);
371 module_exit(cleanup_module);