Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / arch / x86_64 / kernel / sys_arch_prctl.c
diff --git a/kitten/arch/x86_64/kernel/sys_arch_prctl.c b/kitten/arch/x86_64/kernel/sys_arch_prctl.c
new file mode 100644 (file)
index 0000000..5243162
--- /dev/null
@@ -0,0 +1,84 @@
+#include <lwk/kernel.h>
+#include <lwk/task.h>
+#include <arch/prctl.h>
+#include <arch/uaccess.h>
+
+
+long
+do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
+{
+       int ret = 0; 
+       int doit = task == current;
+
+       switch (code) { 
+       case ARCH_SET_GS:
+               if (addr >= task->arch.addr_limit)
+                       return -EPERM; 
+
+               task->arch.thread.gsindex = 0;
+               task->arch.thread.gs = addr;
+               if (doit) {
+                       /* The kernel's %gs is currently loaded, so this
+                          call is needed to set the user version. */
+                       load_gs_index(0);
+                       ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr);
+               } 
+
+               break;
+       case ARCH_SET_FS:
+               /* Not strictly needed for fs, but do it for symmetry
+                  with gs */
+               if (addr >= task->arch.addr_limit)
+                       return -EPERM; 
+
+               task->arch.thread.fsindex = 0;
+               task->arch.thread.fs = addr;
+               if (doit) {
+                       /* The kernel doesn't use %fs so we can set it
+                          directly.  set the selector to 0 to not confuse
+                          __switch_to */
+                       asm volatile("movl %0,%%fs" :: "r" (0));
+                       ret = checking_wrmsrl(MSR_FS_BASE, addr);
+               }
+
+               break;
+       case ARCH_GET_FS: { 
+               unsigned long base; 
+               if (doit)
+                       rdmsrl(MSR_FS_BASE, base);
+               else
+                       base = task->arch.thread.fs;
+               ret = put_user(base, (unsigned long __user *)addr); 
+               break; 
+       }
+       case ARCH_GET_GS: { 
+               unsigned long base;
+               unsigned gsindex;
+               if (doit) {
+                       asm("movl %%gs,%0" : "=r" (gsindex));
+                       if (gsindex)
+                               rdmsrl(MSR_KERNEL_GS_BASE, base);
+                       else
+                               base = task->arch.thread.gs;
+               }
+               else
+                       base = task->arch.thread.gs;
+               ret = put_user(base, (unsigned long __user *)addr); 
+               break;
+       }
+
+       default:
+               ret = -EINVAL;
+               break;
+       } 
+
+       return ret;     
+}
+
+
+long
+sys_arch_prctl(int code, unsigned long addr)
+{
+       return do_arch_prctl(current, code, addr);
+}
+