Initial revision
[linux-2.6.git] / arch / xen / x86_64 / kernel / ioport.c
1 /*
2  *      linux/arch/x86_64/kernel/ioport.c
3  *
4  * This contains the io-permission bitmap code - written by obz, with changes
5  * by Linus.
6  */
7
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/types.h>
12 #include <linux/ioport.h>
13 #include <linux/mm.h>
14 #include <linux/smp.h>
15 #include <linux/smp_lock.h>
16 #include <linux/stddef.h>
17 #include <linux/slab.h>
18 #include <linux/thread_info.h>
19 #include <asm-xen/xen-public/physdev.h>
20
21 /*
22  * sys_iopl has to be used when you want to access the IO ports
23  * beyond the 0x3ff range: to get the full 65536 ports bitmapped
24  * you'd need 8kB of bitmaps/process, which is a bit excessive.
25  *
26  */
27
28 // asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
29 asmlinkage long sys_iopl(unsigned int new_io_pl)
30 {
31         unsigned int old_io_pl = current->thread.io_pl;
32         physdev_op_t op;
33
34
35         if (new_io_pl > 3)
36                 return -EINVAL;
37
38         /* Need "raw I/O" privileges for direct port access. */
39         if ((new_io_pl > old_io_pl) && !capable(CAP_SYS_RAWIO))
40                 return -EPERM;
41
42         /* Maintain OS privileges even if user attempts to relinquish them. */
43         if (new_io_pl == 0)
44                 new_io_pl = 1;
45
46         /* Change our version of the privilege levels. */
47         current->thread.io_pl = new_io_pl;
48
49         /* Force the change at ring 0. */
50         op.cmd             = PHYSDEVOP_SET_IOPL;
51         op.u.set_iopl.iopl = new_io_pl;
52         HYPERVISOR_physdev_op(&op);
53
54         return 0;
55 }
56
57 /*
58  * this changes the io permissions bitmap in the current task.
59  */
60 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
61 {
62   return turn_on ? sys_iopl(3) : 0;
63 }