direct-io.hg

view xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_core.c @ 38:78d4e45b3ef6

bitkeeper revision 1.7.3.17 (3dfde058LJQEiBfP5-ipTGIAQXF3RQ)

bug fix :)
author lynx@idefix.cl.cam.ac.uk
date Mon Dec 16 14:16:56 2002 +0000 (2002-12-16)
parents ca058ea744a3
children 707952793128
line source
2 /******************************************************************************
3 * dom0_core.c
4 *
5 * Interface to privileged domain-0 commands.
6 *
7 * Copyright (c) 2002, K A Fraser, B Dragovic
8 */
10 #include <linux/config.h>
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/slab.h>
15 #include <linux/string.h>
16 #include <linux/errno.h>
17 #include <linux/proc_fs.h>
19 #include <linux/mm.h>
20 #include <linux/mman.h>
21 #include <linux/swap.h>
22 #include <linux/smp_lock.h>
23 #include <linux/swapctl.h>
24 #include <linux/iobuf.h>
25 #include <linux/highmem.h>
26 #include <linux/pagemap.h>
28 #include <asm/pgalloc.h>
29 #include <asm/pgtable.h>
30 #include <asm/uaccess.h>
31 #include <asm/tlb.h>
33 #include "dom0_ops.h"
34 #include "hypervisor_defs.h"
36 #define XENO_BASE "xeno" // proc file name defs should be in separate .h
37 #define DOM0_CMD_INTF "dom0_cmd"
38 #define DOM0_FT "frame_table"
39 #define DOM0_NEWDOM "new_dom_id"
41 #define MAX_LEN 16
42 #define DOM_DIR "dom"
43 #define DOM_TS "task_data"
44 #define DOM_MEM "mem"
46 static struct proc_dir_entry *xeno_base;
47 static struct proc_dir_entry *dom0_cmd_intf;
48 static struct proc_dir_entry *proc_ft;
50 unsigned long direct_mmap(unsigned long, unsigned long, pgprot_t, int, int);
51 int direct_unmap(unsigned long, unsigned long);
52 int direct_disc_unmap(unsigned long, unsigned long, int);
54 /* frame_table mapped from dom0 */
55 frame_table_t * frame_table;
56 unsigned long frame_table_len;
57 unsigned long frame_table_pa;
59 static unsigned char readbuf[1204];
61 static int cmd_read_proc(char *page, char **start, off_t off,
62 int count, int *eof, void *data)
63 {
64 strcpy(page, readbuf);
65 *readbuf = '\0';
66 *eof = 1;
67 *start = page;
68 return strlen(page);
69 }
71 static ssize_t ts_read(struct file * file, char * buff, size_t size, loff_t * off)
72 {
73 dom0_op_t op;
74 unsigned long addr;
75 pgprot_t prot;
76 int ret = 0;
78 /* retrieve domain specific data from proc_dir_entry */
79 dom_procdata_t * dom_data = (dom_procdata_t *)((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
81 /*
82 * get the phys addr of the task struct for the requested
83 * domain
84 */
85 op.cmd = DOM0_MAPTASK;
86 op.u.mapdomts.domain = dom_data->domain;
87 op.u.mapdomts.ts_phy_addr = -1;
89 ret = HYPERVISOR_dom0_op(&op);
90 if(ret != 0)
91 return -EAGAIN;
93 prot = PAGE_SHARED;
95 /* remap the range using xen specific routines */
96 addr = direct_mmap(op.u.mapdomts.ts_phy_addr, PAGE_SIZE, prot, 0, 0);
97 copy_to_user((unsigned long *)buff, &addr, sizeof(addr));
98 dom_data->map_size = PAGE_SIZE;
100 return sizeof(addr);
102 }
104 static ssize_t ts_write(struct file * file, const char * buff, size_t size , loff_t * off)
105 {
106 unsigned long addr;
107 dom_procdata_t * dom_data = (dom_procdata_t *)((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
109 copy_from_user(&addr, (unsigned long *)buff, sizeof(addr));
111 if(direct_unmap(addr, dom_data->map_size) == 0){
112 return sizeof(addr);
113 } else {
114 return -1;
115 }
116 }
118 struct file_operations ts_ops = {
119 read: ts_read,
120 write: ts_write,
121 };
123 static void create_proc_dom_entries(int dom)
124 {
125 struct proc_dir_entry * dir;
126 struct proc_dir_entry * file;
127 dom_procdata_t * dom_data;
128 char dir_name[MAX_LEN];
130 snprintf(dir_name, MAX_LEN, "%s%d", DOM_DIR, dom);
132 dom_data = (dom_procdata_t *)kmalloc(GFP_KERNEL, 128);
133 dom_data->domain = dom;
135 dir = proc_mkdir(dir_name, xeno_base);
136 dir->data = dom_data;
138 file = create_proc_entry(DOM_TS, 0600, dir);
139 if(file != NULL)
140 {
141 file->owner = THIS_MODULE;
142 file->nlink = 1;
143 file->proc_fops = &ts_ops;
145 file->data = dom_data;
146 }
147 }
149 static ssize_t dom_mem_write(struct file * file, const char * buff,
150 size_t size , loff_t * off)
151 {
152 unsigned long addr;
153 proc_memdata_t * mem_data = (proc_memdata_t *)((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
155 copy_from_user(&addr, (unsigned long *)buff, sizeof(addr));
157 if(direct_disc_unmap(addr, mem_data->pfn, mem_data->tot_pages) == 0){
158 return sizeof(addr);
159 } else {
160 return -1;
161 }
162 }
164 static ssize_t dom_mem_read(struct file * file, char * buff, size_t size, loff_t * off)
165 {
166 unsigned long addr;
167 pgprot_t prot;
169 printk(KERN_ALERT "bd240 debug: dom_mem_read invoked!\n");
171 proc_memdata_t * mem_data = (proc_memdata_t *)((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
173 prot = PAGE_SHARED;
175 /* remap the range using xen specific routines */
176 printk(KERN_ALERT "bd240 debug: mem_read: mem_data %lx\n", mem_data);
178 addr = direct_mmap(mem_data->pfn << PAGE_SHIFT, mem_data->tot_pages << PAGE_SHIFT, prot, 0, 0);
179 //addr = direct_mmap(mem_data->pfn, mem_data->tot_pages << PAGE_SHIFT, prot, 1,
180 // mem_data->tot_pages);
181 copy_to_user((unsigned long *)buff, &addr, sizeof(addr));
183 return sizeof(addr);
185 }
187 struct file_operations dom_mem_ops = {
188 read: dom_mem_read,
189 write: dom_mem_write,
190 };
192 static int dom_map_mem(unsigned int dom, unsigned long pfn, int tot_pages)
193 {
194 printk(KERN_ALERT "bd240 debug: dom_map_mem: invoked\n");
196 int ret = -ENOENT;
197 struct proc_dir_entry * pd = xeno_base->subdir;
198 struct proc_dir_entry * file;
199 proc_memdata_t * memdata;
201 printk(KERN_ALERT "bd240 debug: dom_map_mem invoked, xeno_base %lx, subdir %lx\n", xeno_base, xeno_base->subdir);
203 printk(KERN_ALERT "bd240 debug: dom_map_mem, pd %lx\n", pd);
204 printk(KERN_ALERT "bd240 debug: dom_map_mem, pd data %lx\n", pd->data);
205 printk(KERN_ALERT "bd240 debug: dom_map_mem, pd name %s\n", pd->name);
206 printk(KERN_ALERT "bd240 debug: dom_map_mem, pd %lx\n", ((dom_procdata_t *)pd->data)->domain);
208 while(pd != NULL){
210 printk(KERN_ALERT "bd240 debug: dom_map: proc %d\n", ((dom_procdata_t *)pd->data)->domain);
212 if((pd->mode & S_IFDIR) && ((dom_procdata_t *)pd->data)->domain == dom){
214 /* check if there is already an entry for mem and if so
215 * remove it.
216 */
217 remove_proc_entry(DOM_MEM, pd);
219 /* create new entry with parameters describing what to do
220 * when it is mmaped.
221 */
222 file = create_proc_entry(DOM_MEM, 0600, pd);
223 if(file != NULL)
224 {
225 file->owner = THIS_MODULE;
226 file->nlink = 1;
227 file->proc_fops = &dom_mem_ops;
229 memdata = (proc_memdata_t *)kmalloc(GFP_KERNEL, sizeof(proc_memdata_t));
230 memdata->pfn = pfn;
231 memdata->tot_pages = tot_pages;
232 file->data = memdata;
234 printk(KERN_ALERT "bd240 debug: associated memdata with proc, memdata %lx, pfn %lx, tot_pages %lx\n", file->data, memdata->pfn, memdata->tot_pages);
236 ret = 0;
237 break;
238 }
239 ret = -EAGAIN;
240 break;
241 }
242 pd = pd->next;
243 }
245 return ret;
246 }
248 /* return dom id stored as data pointer to userspace */
249 static int dom_id_read_proc(char *page, char **start, off_t off,
250 int count, int *eof, void *data)
251 {
252 char arg[16];
253 sprintf(arg, "%d", (int)data);
254 strcpy(page, arg);
255 remove_proc_entry(DOM0_NEWDOM, xeno_base);
256 return sizeof(unsigned int);
257 }
259 static int cmd_write_proc(struct file *file, const char *buffer,
260 u_long count, void *data)
261 {
262 dom0_op_t op;
263 int ret = 0;
264 struct proc_dir_entry * new_dom_id;
266 copy_from_user(&op, buffer, sizeof(dom0_op_t));
268 /* do some sanity checks */
269 if(op.cmd > MAX_CMD){
270 ret = -ENOSYS;
271 goto out;
272 }
274 /* is the request intended for hypervisor? */
275 if(op.cmd != MAP_DOM_MEM){
276 ret = HYPERVISOR_dom0_op(&op);
278 /* if new domain created, create proc entries */
279 if(op.cmd == DOM0_NEWDOMAIN){
280 create_proc_dom_entries(ret);
282 /* now notify user space of the new domain's id */
283 new_dom_id = create_proc_entry(DOM0_NEWDOM, 0600, xeno_base);
284 if ( new_dom_id != NULL )
285 {
286 new_dom_id->owner = THIS_MODULE;
287 new_dom_id->nlink = 1;
288 new_dom_id->read_proc = dom_id_read_proc;
289 new_dom_id->data = (void *)ret;
290 }
292 }
294 } else {
296 printk(KERN_ALERT "bd240 debug: mapping dom %d, %lx, %lx\n", op.u.reqdommem.domain, op.u.reqdommem.start_pfn, op.u.reqdommem.tot_pages);
298 ret = dom_map_mem(op.u.reqdommem.domain, op.u.reqdommem.start_pfn,
299 op.u.reqdommem.tot_pages);
300 }
302 out:
303 return ret;
305 }
307 static ssize_t ft_write(struct file * file, const char * buff, size_t size , loff_t * off)
308 {
309 unsigned long addr;
311 copy_from_user(&addr, (unsigned long *)buff, sizeof(addr));
313 if(direct_unmap(addr, frame_table_len) == 0){
314 return sizeof(addr);
315 } else {
316 return -1;
317 }
318 }
320 static ssize_t ft_read(struct file * file, char * buff, size_t size, loff_t * off)
321 {
322 unsigned long addr;
323 pgprot_t prot;
325 prot = PAGE_SHARED;
327 /* remap the range using xen specific routines */
328 addr = direct_mmap(frame_table_pa, frame_table_len, prot, 0, 0);
329 copy_to_user((unsigned long *)buff, &addr, sizeof(addr));
331 return sizeof(addr);
333 }
335 struct file_operations ft_ops = {
336 read: ft_read,
337 write: ft_write,
338 };
340 static int __init init_module(void)
341 {
343 frame_table = (frame_table_t *)start_info.frame_table;
344 frame_table_len = start_info.frame_table_len;
345 frame_table_pa = start_info.frame_table_pa;
347 /* xeno proc root setup */
348 xeno_base = proc_mkdir(XENO_BASE, &proc_root);
350 /* xeno control interface */
351 *readbuf = '\0';
352 dom0_cmd_intf = create_proc_entry (DOM0_CMD_INTF, 0600, xeno_base);
353 if ( dom0_cmd_intf != NULL )
354 {
355 dom0_cmd_intf->owner = THIS_MODULE;
356 dom0_cmd_intf->nlink = 1;
357 dom0_cmd_intf->read_proc = cmd_read_proc;
358 dom0_cmd_intf->write_proc = cmd_write_proc;
359 }
361 /* frame table mapping, to be mmaped */
362 proc_ft = create_proc_entry(DOM0_FT, 0600, xeno_base);
363 if(proc_ft != NULL)
364 {
365 proc_ft->owner = THIS_MODULE;
366 proc_ft->nlink = 1;
367 proc_ft->proc_fops = &ft_ops;
368 }
370 /* set up /proc entries for dom 0 */
371 create_proc_dom_entries(0);
373 return 0;
374 }
377 static void __exit cleanup_module(void)
378 {
379 if ( dom0_cmd_intf == NULL ) return;
380 remove_proc_entry("dom0", &proc_root);
381 dom0_cmd_intf = NULL;
382 }
385 module_init(init_module);
386 module_exit(cleanup_module);