ia64/xen-unstable

view linux-2.6.11-xen-sparse/drivers/xen/privcmd/privcmd.c @ 4116:c0c50017de07

bitkeeper revision 1.1236.25.12 (42336167xwcAAiaO1PSL9AACpWN72g)

Fix fallout from Update to Linux 2.6.11.
Signed-off-by: Christian Limpach <chris@xensource.com>
author cl349@firebug.cl.cam.ac.uk
date Sat Mar 12 21:38:47 2005 +0000 (2005-03-12)
parents 1d420c415398
children f234096eb41e
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/kernel.h>
11 #include <linux/sched.h>
12 #include <linux/slab.h>
13 #include <linux/string.h>
14 #include <linux/errno.h>
15 #include <linux/mm.h>
16 #include <linux/mman.h>
17 #include <linux/swap.h>
18 #include <linux/smp_lock.h>
19 #include <linux/highmem.h>
20 #include <linux/pagemap.h>
21 #include <linux/seq_file.h>
23 #include <asm/pgalloc.h>
24 #include <asm/pgtable.h>
25 #include <asm/uaccess.h>
26 #include <asm/tlb.h>
27 #include <asm-xen/linux-public/privcmd.h>
28 #include <asm-xen/xen-public/dom0_ops.h>
29 #include <asm-xen/xen_proc.h>
31 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
32 #define pud_t pgd_t
33 #define pud_offset(d, va) d
34 #endif
36 static struct proc_dir_entry *privcmd_intf;
38 static int privcmd_ioctl(struct inode *inode, struct file *file,
39 unsigned int cmd, unsigned long data)
40 {
41 int ret = -ENOSYS;
43 switch ( cmd )
44 {
45 case IOCTL_PRIVCMD_HYPERCALL:
46 {
47 privcmd_hypercall_t hypercall;
49 if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
50 return -EFAULT;
52 __asm__ __volatile__ (
53 "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
54 "movl 4(%%eax),%%ebx ;"
55 "movl 8(%%eax),%%ecx ;"
56 "movl 12(%%eax),%%edx ;"
57 "movl 16(%%eax),%%esi ;"
58 "movl 20(%%eax),%%edi ;"
59 "movl (%%eax),%%eax ;"
60 TRAP_INSTR "; "
61 "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
62 : "=a" (ret) : "0" (&hypercall) : "memory" );
64 }
65 break;
67 case IOCTL_PRIVCMD_INITDOMAIN_EVTCHN:
68 {
69 extern int initdom_ctrlif_domcontroller_port;
70 ret = initdom_ctrlif_domcontroller_port;
71 }
72 break;
74 #if defined(CONFIG_XEN_PRIVILEGED_GUEST)
75 case IOCTL_PRIVCMD_MMAP:
76 {
77 #define PRIVCMD_MMAP_SZ 32
78 privcmd_mmap_t mmapcmd;
79 privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
80 int i, rc;
82 if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) )
83 return -EFAULT;
85 p = mmapcmd.entry;
87 for (i=0; i<mmapcmd.num; i+=PRIVCMD_MMAP_SZ, p+=PRIVCMD_MMAP_SZ)
88 {
89 int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)?
90 PRIVCMD_MMAP_SZ:(mmapcmd.num-i);
91 if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) )
92 return -EFAULT;
94 for ( j = 0; j < n; j++ )
95 {
96 struct vm_area_struct *vma =
97 find_vma( current->mm, msg[j].va );
99 if ( !vma )
100 return -EINVAL;
102 if ( msg[j].va > PAGE_OFFSET )
103 return -EINVAL;
105 if ( (msg[j].va + (msg[j].npages<<PAGE_SHIFT)) > vma->vm_end )
106 return -EINVAL;
108 if ( (rc = direct_remap_area_pages(vma->vm_mm,
109 msg[j].va&PAGE_MASK,
110 msg[j].mfn<<PAGE_SHIFT,
111 msg[j].npages<<PAGE_SHIFT,
112 vma->vm_page_prot,
113 mmapcmd.dom)) < 0 )
114 return rc;
115 }
116 }
117 ret = 0;
118 }
119 break;
121 case IOCTL_PRIVCMD_MMAPBATCH:
122 {
123 #define MAX_DIRECTMAP_MMU_QUEUE 130
124 mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *w, *v;
125 privcmd_mmapbatch_t m;
126 struct vm_area_struct *vma = NULL;
127 unsigned long *p, addr;
128 unsigned long mfn;
129 int i;
131 if ( copy_from_user(&m, (void *)data, sizeof(m)) )
132 { ret = -EFAULT; goto batch_err; }
134 vma = find_vma( current->mm, m.addr );
136 if ( !vma )
137 { ret = -EINVAL; goto batch_err; }
139 if ( m.addr > PAGE_OFFSET )
140 { ret = -EFAULT; goto batch_err; }
142 if ( (m.addr + (m.num<<PAGE_SHIFT)) > vma->vm_end )
143 { ret = -EFAULT; goto batch_err; }
145 u[0].ptr = MMU_EXTENDED_COMMAND;
146 u[0].val = MMUEXT_SET_FOREIGNDOM;
147 u[0].val |= (unsigned long)m.dom << 16;
148 v = w = &u[1];
150 p = m.arr;
151 addr = m.addr;
152 for ( i = 0; i < m.num; i++, addr += PAGE_SIZE, p++ )
153 {
154 if ( get_user(mfn, p) )
155 return -EFAULT;
157 v->val = (mfn << PAGE_SHIFT) | pgprot_val(vma->vm_page_prot);
159 __direct_remap_area_pages(vma->vm_mm,
160 addr,
161 PAGE_SIZE,
162 v);
164 if ( unlikely(HYPERVISOR_mmu_update(u, v - u + 1, NULL) < 0) )
165 put_user( 0xF0000000 | mfn, p );
167 v = w;
168 }
169 ret = 0;
170 break;
172 batch_err:
173 printk("batch_err ret=%d vma=%p addr=%lx num=%d arr=%p %lx-%lx\n",
174 ret, vma, m.addr, m.num, m.arr, vma->vm_start, vma->vm_end);
175 break;
176 }
177 break;
178 #endif
180 case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN:
181 {
182 unsigned long m2pv = (unsigned long)machine_to_phys_mapping;
183 pgd_t *pgd = pgd_offset_k(m2pv);
184 pud_t *pud = pud_offset(pgd, m2pv);
185 pmd_t *pmd = pmd_offset(pud, m2pv);
186 unsigned long m2p_start_mfn = pfn_to_mfn(pmd_val(*pmd) >> PAGE_SHIFT);
187 ret = put_user(m2p_start_mfn, (unsigned long *)data) ? -EFAULT: 0;
188 }
189 break;
191 default:
192 ret = -EINVAL;
193 break;
194 }
195 return ret;
196 }
198 static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
199 {
200 /* DONTCOPY is essential for Xen as copy_page_range is broken. */
201 vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
203 return 0;
204 }
206 static struct file_operations privcmd_file_ops = {
207 ioctl : privcmd_ioctl,
208 mmap: privcmd_mmap
209 };
212 static int __init privcmd_init(void)
213 {
214 if ( !(xen_start_info.flags & SIF_PRIVILEGED) )
215 return 0;
217 privcmd_intf = create_xen_proc_entry("privcmd", 0400);
218 if ( privcmd_intf != NULL )
219 privcmd_intf->proc_fops = &privcmd_file_ops;
221 return 0;
222 }
224 __initcall(privcmd_init);