ia64/xen-unstable

view xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_core.c @ 75:dd6547801b23

bitkeeper revision 1.7.3.50 (3e0c25b7tjRVPou2bUeilwKeAOW8Ww)

kmalloc bug fix
author lynx@idefix.cl.cam.ac.uk
date Fri Dec 27 10:04:39 2002 +0000 (2002-12-27)
parents cc3048fbafd8
children 7c48a158429c
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 //addr = direct_mmap(mem_data->pfn, mem_data->tot_pages << PAGE_SHIFT, prot, 1,
178 // mem_data->tot_pages);
179 copy_to_user((unsigned long *)buff, &addr, sizeof(addr));
181 printk(KERN_ALERT "bd240 debug: exiting dom_mem_read\n");
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 int ret = -ENOENT;
195 struct proc_dir_entry * pd = xeno_base->subdir;
196 struct proc_dir_entry * file;
197 proc_memdata_t * memdata;
199 while(pd != NULL){
201 if((pd->mode & S_IFDIR) && ((dom_procdata_t *)pd->data)->domain == dom){
203 /* check if there is already an entry for mem and if so
204 * remove it.
205 */
206 remove_proc_entry(DOM_MEM, pd);
208 /* create new entry with parameters describing what to do
209 * when it is mmaped.
210 */
211 file = create_proc_entry(DOM_MEM, 0600, pd);
212 if(file != NULL)
213 {
214 file->owner = THIS_MODULE;
215 file->nlink = 1;
216 file->proc_fops = &dom_mem_ops;
218 memdata = (proc_memdata_t *)kmalloc(sizeof(proc_memdata_t), GFP_KERNEL);
219 memdata->pfn = pfn;
220 memdata->tot_pages = tot_pages;
221 file->data = memdata;
223 printk(KERN_ALERT "bd240 debug: cmd setup dom mem: %lx, %d\n", memdata->pfn, memdata->tot_pages);
225 ret = 0;
226 break;
227 }
228 ret = -EAGAIN;
229 break;
230 }
231 pd = pd->next;
232 }
234 return ret;
235 }
237 /* return dom id stored as data pointer to userspace */
238 static int dom_id_read_proc(char *page, char **start, off_t off,
239 int count, int *eof, void *data)
240 {
241 char arg[16];
242 sprintf(arg, "%d", (int)data);
243 strcpy(page, arg);
244 remove_proc_entry(DOM0_NEWDOM, xeno_base);
245 return sizeof(unsigned int);
246 }
248 static int cmd_write_proc(struct file *file, const char *buffer,
249 u_long count, void *data)
250 {
251 dom0_op_t op;
252 int ret = 0;
253 struct proc_dir_entry * new_dom_id;
255 copy_from_user(&op, buffer, sizeof(dom0_op_t));
257 /* do some sanity checks */
258 if(op.cmd > MAX_CMD){
259 ret = -ENOSYS;
260 goto out;
261 }
263 /* is the request intended for hypervisor? */
264 if(op.cmd != MAP_DOM_MEM){
265 ret = HYPERVISOR_dom0_op(&op);
267 /* if new domain created, create proc entries */
268 if(op.cmd == DOM0_NEWDOMAIN){
269 create_proc_dom_entries(ret);
271 /* now notify user space of the new domain's id */
272 new_dom_id = create_proc_entry(DOM0_NEWDOM, 0600, xeno_base);
273 if ( new_dom_id != NULL )
274 {
275 new_dom_id->owner = THIS_MODULE;
276 new_dom_id->nlink = 1;
277 new_dom_id->read_proc = dom_id_read_proc;
278 new_dom_id->data = (void *)ret;
279 }
281 }
283 } else {
285 ret = dom_map_mem(op.u.reqdommem.domain, op.u.reqdommem.start_pfn,
286 op.u.reqdommem.tot_pages);
287 }
289 out:
290 return ret;
292 }
294 static ssize_t ft_write(struct file * file, const char * buff, size_t size , loff_t * off)
295 {
296 unsigned long addr;
298 copy_from_user(&addr, (unsigned long *)buff, sizeof(addr));
300 if(direct_unmap(addr, frame_table_len) == 0){
301 return sizeof(addr);
302 } else {
303 return -1;
304 }
305 }
307 static ssize_t ft_read(struct file * file, char * buff, size_t size, loff_t * off)
308 {
309 unsigned long addr;
310 pgprot_t prot;
312 prot = PAGE_SHARED;
314 /* remap the range using xen specific routines */
315 addr = direct_mmap(frame_table_pa, frame_table_len, prot, 0, 0);
316 copy_to_user((unsigned long *)buff, &addr, sizeof(addr));
318 return sizeof(addr);
320 }
322 struct file_operations ft_ops = {
323 read: ft_read,
324 write: ft_write,
325 };
327 static int __init init_module(void)
328 {
330 frame_table = (frame_table_t *)start_info.frame_table;
331 frame_table_len = start_info.frame_table_len;
332 frame_table_pa = start_info.frame_table_pa;
334 /* xeno proc root setup */
335 xeno_base = proc_mkdir(XENO_BASE, &proc_root);
337 /* xeno control interface */
338 *readbuf = '\0';
339 dom0_cmd_intf = create_proc_entry (DOM0_CMD_INTF, 0600, xeno_base);
340 if ( dom0_cmd_intf != NULL )
341 {
342 dom0_cmd_intf->owner = THIS_MODULE;
343 dom0_cmd_intf->nlink = 1;
344 dom0_cmd_intf->read_proc = cmd_read_proc;
345 dom0_cmd_intf->write_proc = cmd_write_proc;
346 }
348 /* frame table mapping, to be mmaped */
349 proc_ft = create_proc_entry(DOM0_FT, 0600, xeno_base);
350 if(proc_ft != NULL)
351 {
352 proc_ft->owner = THIS_MODULE;
353 proc_ft->nlink = 1;
354 proc_ft->proc_fops = &ft_ops;
355 }
357 /* set up /proc entries for dom 0 */
358 create_proc_dom_entries(0);
360 return 0;
361 }
364 static void __exit cleanup_module(void)
365 {
366 if ( dom0_cmd_intf == NULL ) return;
367 remove_proc_entry("dom0", &proc_root);
368 dom0_cmd_intf = NULL;
369 }
372 module_init(init_module);
373 module_exit(cleanup_module);