direct-io.hg

view linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c @ 2821:724449a888fe

bitkeeper revision 1.1159.1.332 (41874e954CLIDA2J3phVFD2RnzVTpA)

Clean up public XenLinux header files. Now accessible from userspace as
#include <xen/linux...>
Got rid of the linux-xen-sparse symlink as it's no longer needed.
author kaf24@freefall.cl.cam.ac.uk
date Tue Nov 02 09:08:37 2004 +0000 (2004-11-02)
parents d60426da6f4c
children a193790c4961 fdd2c0ba9164 5c16d6acb085 fd0d4d8e6193
line source
1 /******************************************************************************
2 * privcmd.c
3 *
4 * Interface to privileged domain-0 commands.
5 *
6 * Copyright (c) 2002-2004, 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/mm.h>
17 #include <linux/mman.h>
18 #include <linux/swap.h>
19 #include <linux/smp_lock.h>
20 #include <linux/highmem.h>
21 #include <linux/pagemap.h>
22 #include <linux/seq_file.h>
24 #include <asm/pgalloc.h>
25 #include <asm/pgtable.h>
26 #include <asm/uaccess.h>
27 #include <asm/tlb.h>
28 #include <asm-xen/linux-public/privcmd.h>
29 #include <asm-xen/xen-public/dom0_ops.h>
30 #include <asm-xen/xen_proc.h>
32 static struct proc_dir_entry *privcmd_intf;
34 static int privcmd_ioctl(struct inode *inode, struct file *file,
35 unsigned int cmd, unsigned long data)
36 {
37 int ret = -ENOSYS;
39 switch ( cmd )
40 {
41 case IOCTL_PRIVCMD_HYPERCALL:
42 {
43 privcmd_hypercall_t hypercall;
45 if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
46 return -EFAULT;
48 __asm__ __volatile__ (
49 "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
50 "movl 4(%%eax),%%ebx ;"
51 "movl 8(%%eax),%%ecx ;"
52 "movl 12(%%eax),%%edx ;"
53 "movl 16(%%eax),%%esi ;"
54 "movl 20(%%eax),%%edi ;"
55 "movl (%%eax),%%eax ;"
56 TRAP_INSTR "; "
57 "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
58 : "=a" (ret) : "0" (&hypercall) : "memory" );
60 }
61 break;
63 case IOCTL_PRIVCMD_INITDOMAIN_EVTCHN:
64 {
65 extern int initdom_ctrlif_domcontroller_port;
66 ret = initdom_ctrlif_domcontroller_port;
67 }
68 break;
70 #if defined(CONFIG_XEN_PRIVILEGED_GUEST)
71 case IOCTL_PRIVCMD_MMAP:
72 {
73 #define PRIVCMD_MMAP_SZ 32
74 privcmd_mmap_t mmapcmd;
75 privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
76 int i, rc;
78 if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) )
79 return -EFAULT;
81 p = mmapcmd.entry;
83 for (i=0; i<mmapcmd.num; i+=PRIVCMD_MMAP_SZ, p+=PRIVCMD_MMAP_SZ)
84 {
85 int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)?
86 PRIVCMD_MMAP_SZ:(mmapcmd.num-i);
87 if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) )
88 return -EFAULT;
90 for ( j = 0; j < n; j++ )
91 {
92 struct vm_area_struct *vma =
93 find_vma( current->mm, msg[j].va );
95 if ( !vma )
96 return -EINVAL;
98 if ( msg[j].va > PAGE_OFFSET )
99 return -EINVAL;
101 if ( (msg[j].va + (msg[j].npages<<PAGE_SHIFT)) > vma->vm_end )
102 return -EINVAL;
104 if ( (rc = direct_remap_area_pages(vma->vm_mm,
105 msg[j].va&PAGE_MASK,
106 msg[j].mfn<<PAGE_SHIFT,
107 msg[j].npages<<PAGE_SHIFT,
108 vma->vm_page_prot,
109 mmapcmd.dom)) < 0 )
110 return rc;
111 }
112 }
113 ret = 0;
114 }
115 break;
117 case IOCTL_PRIVCMD_MMAPBATCH:
118 {
119 #define MAX_DIRECTMAP_MMU_QUEUE 130
120 mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *w, *v;
121 privcmd_mmapbatch_t m;
122 struct vm_area_struct *vma = NULL;
123 unsigned long *p, addr;
124 unsigned long mfn;
125 int i;
127 if ( copy_from_user(&m, (void *)data, sizeof(m)) )
128 { ret = -EFAULT; goto batch_err; }
130 vma = find_vma( current->mm, m.addr );
132 if ( !vma )
133 { ret = -EINVAL; goto batch_err; }
135 if ( m.addr > PAGE_OFFSET )
136 { ret = -EFAULT; goto batch_err; }
138 if ( (m.addr + (m.num<<PAGE_SHIFT)) > vma->vm_end )
139 { ret = -EFAULT; goto batch_err; }
141 u[0].ptr = MMU_EXTENDED_COMMAND;
142 u[0].val = MMUEXT_SET_FOREIGNDOM;
143 u[0].val |= (unsigned long)m.dom << 16;
144 v = w = &u[1];
146 p = m.arr;
147 addr = m.addr;
148 for ( i = 0; i < m.num; i++, addr += PAGE_SIZE, p++ )
149 {
150 if ( get_user(mfn, p) )
151 return -EFAULT;
153 v->val = (mfn << PAGE_SHIFT) | pgprot_val(vma->vm_page_prot);
155 __direct_remap_area_pages(vma->vm_mm,
156 addr,
157 PAGE_SIZE,
158 v);
160 if ( unlikely(HYPERVISOR_mmu_update(u, v - u + 1, NULL) < 0) )
161 put_user( 0xF0000000 | mfn, p );
163 v = w;
164 }
165 ret = 0;
166 break;
168 batch_err:
169 printk("batch_err ret=%d vma=%p addr=%lx num=%d arr=%p %lx-%lx\n",
170 ret, vma, m.addr, m.num, m.arr, vma->vm_start, vma->vm_end);
171 break;
172 }
173 break;
174 #endif
176 case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN:
177 {
178 unsigned long m2p_start_mfn =
179 HYPERVISOR_shared_info->arch.mfn_to_pfn_start;
181 if( put_user( m2p_start_mfn, (unsigned long *) data ) )
182 ret = -EFAULT;
183 else
184 ret = 0;
185 }
186 break;
188 default:
189 ret = -EINVAL;
190 break;
191 }
192 return ret;
193 }
195 static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
196 {
197 /* DONTCOPY is essential for Xen as copy_page_range is broken. */
198 vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
200 return 0;
201 }
203 static struct file_operations privcmd_file_ops = {
204 ioctl : privcmd_ioctl,
205 mmap: privcmd_mmap
206 };
209 static int __init privcmd_init(void)
210 {
211 if ( !(xen_start_info.flags & SIF_PRIVILEGED) )
212 return 0;
214 privcmd_intf = create_xen_proc_entry("privcmd", 0400);
215 if ( privcmd_intf != NULL )
216 {
217 privcmd_intf->owner = THIS_MODULE;
218 privcmd_intf->nlink = 1;
219 privcmd_intf->proc_fops = &privcmd_file_ops;
220 }
222 return 0;
223 }
226 static void __exit privcmd_cleanup(void)
227 {
228 if ( privcmd_intf == NULL ) return;
229 remove_xen_proc_entry("privcmd");
230 privcmd_intf = NULL;
231 }
234 module_init(privcmd_init);
235 module_exit(privcmd_cleanup);