Index: /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 44183)
+++ /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 44184)
@@ -96,5 +96,6 @@
 static int  VBoxDrvLinuxInit(void);
 static void VBoxDrvLinuxUnload(void);
-static int  VBoxDrvLinuxCreate(struct inode *pInode, struct file *pFilp);
+static int  VBoxDrvLinuxCreateSys(struct inode *pInode, struct file *pFilp);
+static int  VBoxDrvLinuxCreateUsr(struct inode *pInode, struct file *pFilp);
 static int  VBoxDrvLinuxClose(struct inode *pInode, struct file *pFilp);
 #ifdef HAVE_UNLOCKED_IOCTL
@@ -103,5 +104,5 @@
 static int  VBoxDrvLinuxIOCtl(struct inode *pInode, struct file *pFilp, unsigned int uCmd, unsigned long ulArg);
 #endif
-static int  VBoxDrvLinuxIOCtlSlow(struct file *pFilp, unsigned int uCmd, unsigned long ulArg);
+static int  VBoxDrvLinuxIOCtlSlow(struct file *pFilp, unsigned int uCmd, unsigned long ulArg, PSUPDRVSESSION pSession);
 static int  VBoxDrvLinuxErr2LinuxErr(int);
 #ifdef VBOX_WITH_SUSPEND_NOTIFICATION
@@ -127,8 +128,12 @@
 
 #ifndef CONFIG_VBOXDRV_AS_MISC
-/** Module major number */
-#define DEVICE_MAJOR        234
-/** Saved major device number */
-static int                  g_iModuleMajor;
+/** Module major number for vboxdrv. */
+#define DEVICE_MAJOR_SYS    234
+/** Saved major device number for vboxdrv. */
+static int                  g_iModuleMajorSys;
+/** Module major number for vboxdrvu. */
+#define DEVICE_MAJOR_USR    235
+/** Saved major device number for vboxdrvu. */
+static int                  g_iModuleMajorUsr;
 #endif /* !CONFIG_VBOXDRV_AS_MISC */
 
@@ -137,6 +142,8 @@
 static int force_async_tsc = 0;
 
-/** The module name. */
-#define DEVICE_NAME         "vboxdrv"
+/** The system device name. */
+#define DEVICE_NAME_SYS     "vboxdrvu"
+/** The user device name. */
+#define DEVICE_NAME_USR     "vboxdrv"
 
 #if defined(RT_ARCH_AMD64) && !defined(CONFIG_DEBUG_SET_MODULE_RONX)
@@ -156,8 +163,8 @@
 
 /** The file_operations structure. */
-static struct file_operations gFileOpsVBoxDrv =
+static struct file_operations gFileOpsVBoxDrvSys =
 {
     owner:      THIS_MODULE,
-    open:       VBoxDrvLinuxCreate,
+    open:       VBoxDrvLinuxCreateSys,
     release:    VBoxDrvLinuxClose,
 #ifdef HAVE_UNLOCKED_IOCTL
@@ -168,13 +175,36 @@
 };
 
+/** The file_operations structure. */
+static struct file_operations gFileOpsVBoxDrvUsr =
+{
+    owner:      THIS_MODULE,
+    open:       VBoxDrvLinuxCreateUsr,
+    release:    VBoxDrvLinuxClose,
+#ifdef HAVE_UNLOCKED_IOCTL
+    unlocked_ioctl: VBoxDrvLinuxIOCtl,
+#else
+    ioctl:      VBoxDrvLinuxIOCtl,
+#endif
+};
+
 #ifdef CONFIG_VBOXDRV_AS_MISC
-/** The miscdevice structure. */
-static struct miscdevice gMiscDevice =
+/** The miscdevice structure for vboxdrv. */
+static struct miscdevice gMiscDeviceSys =
 {
     minor:      MISC_DYNAMIC_MINOR,
-    name:       DEVICE_NAME,
-    fops:       &gFileOpsVBoxDrv,
+    name:       DEVICE_NAME_SYS,
+    fops:       &gFileOpsVBoxDrvSys,
 # if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
-    devfs_name: DEVICE_NAME,
+    devfs_name: DEVICE_NAME_SYS,
+# endif
+};
+/** The miscdevice structure for vboxdrvu. */
+static struct miscdevice gMiscDeviceUsr =
+{
+    minor:      MISC_DYNAMIC_MINOR,
+    name:       DEVICE_NAME_USR,
+    fops:       &gFileOpsVBoxDrvUsr,
+# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
+    devfs_name: DEVICE_NAME_USR,
 # endif
 };
@@ -260,31 +290,50 @@
      * Check for synchronous/asynchronous TSC mode.
      */
-    printk(KERN_DEBUG DEVICE_NAME ": Found %u processor cores.\n", (unsigned)RTMpGetOnlineCount());
+    printk(KERN_DEBUG "vboxdrv: Found %u processor cores.\n", (unsigned)RTMpGetOnlineCount());
 #ifdef CONFIG_VBOXDRV_AS_MISC
-    rc = misc_register(&gMiscDevice);
+    rc = misc_register(&gMiscDeviceSys);
     if (rc)
     {
-        printk(KERN_ERR DEVICE_NAME ": Can't register misc device! rc=%d\n", rc);
+        printk(KERN_ERR "vboxdrv: Can't register system misc device! rc=%d\n", rc);
         return rc;
     }
+    rc = misc_register(&gMiscDeviceUsr);
+    if (rc)
+    {
+        printk(KERN_ERR "vboxdrv: Can't register user misc device! rc=%d\n", rc);
+        misc_deregister(&gMiscDeviceSys);
+        return rc;
+    }
 #else  /* !CONFIG_VBOXDRV_AS_MISC */
     /*
-     * Register character device.
-     */
-    g_iModuleMajor = DEVICE_MAJOR;
-    rc = register_chrdev((dev_t)g_iModuleMajor, DEVICE_NAME, &gFileOpsVBoxDrv);
+     * Register character devices and save the returned major numbers.
+     */
+    /* /dev/vboxdrv */
+    g_iModuleMajorSys = DEVICE_MAJOR_SYS;
+    rc = register_chrdev((dev_t)g_iModuleMajorSys, DEVICE_NAME_SYS, &gFileOpsVBoxDrvSys);
     if (rc < 0)
     {
-        Log(("register_chrdev() failed with rc=%#x!\n", rc));
+        Log(("register_chrdev() failed with rc=%#x for vboxdrv!\n", rc));
         return rc;
     }
-
-    /*
-     * Save returned module major number
-     */
-    if (DEVICE_MAJOR != 0)
-        g_iModuleMajor = DEVICE_MAJOR;
+    if (DEVICE_MAJOR_SYS != 0)
+        g_iModuleMajorSys = DEVICE_MAJOR_SYS;
     else
-        g_iModuleMajor = rc;
+        g_iModuleMajorSys = rc;
+
+    /* /dev/vboxdrvu */
+    /** @todo Use a minor number of this bugger (not sure if this code is used
+     *        though, so not bothering right now.) */
+    g_iModuleMajorUsr = DEVICE_MAJOR_USR;
+    rc = register_chrdev((dev_t)g_iModuleMajorUsr, DEVICE_NAME_USR, &gFileOpsVBoxDrvUsr);
+    if (rc < 0)
+    {
+        Log(("register_chrdev() failed with rc=%#x for vboxdrv!\n", rc));
+        return rc;
+    }
+    if (DEVICE_MAJOR_USR != 0)
+        g_iModuleMajorUsr = DEVICE_MAJOR_USR;
+    else
+        g_iModuleMajorUsr = rc;
     rc = 0;
 
@@ -293,5 +342,6 @@
      * Register a device entry
      */
-    if (devfs_mk_cdev(MKDEV(DEVICE_MAJOR, 0), S_IFCHR | VBOX_DEV_FMASK, DEVICE_NAME) != 0)
+    if (   devfs_mk_cdev(MKDEV(DEVICE_MAJOR_SYS, 0), S_IFCHR | VBOX_DEV_FMASK, DEVICE_NAME_SYS) != 0
+        || devfs_mk_cdev(MKDEV(DEVICE_MAJOR_USR, 0), S_IFCHR | VBOX_DEV_FMASK, DEVICE_NAME_USR) != 0)
     {
         Log(("devfs_register failed!\n"));
@@ -330,8 +380,8 @@
 #endif
                     {
-                        printk(KERN_INFO DEVICE_NAME ": TSC mode is %s, kernel timer mode is 'normal'.\n",
+                        printk(KERN_INFO "vboxdrv: TSC mode is %s, kernel timer mode is 'normal'.\n",
                                g_DevExt.pGip->u32Mode == SUPGIPMODE_SYNC_TSC ? "'synchronous'" : "'asynchronous'");
                         LogFlow(("VBoxDrv::ModuleInit returning %#x\n", rc));
-                        printk(KERN_DEBUG DEVICE_NAME ": Successfully loaded version "
+                        printk(KERN_DEBUG "vboxdrv: Successfully loaded version "
                                 VBOX_VERSION_STRING " (interface " RT_XSTR(SUPDRV_IOC_VERSION) ").\n");
                         return rc;
@@ -354,13 +404,16 @@
          */
 #if defined(CONFIG_DEVFS_FS) && !defined(CONFIG_VBOXDRV_AS_MISC)
-        devfs_remove(DEVICE_NAME);
+        devfs_remove(DEVICE_NAME_SYS);
+        devfs_remove(DEVICE_NAME_USR);
 #endif
     }
 #ifdef CONFIG_VBOXDRV_AS_MISC
-    misc_deregister(&gMiscDevice);
-    Log(("VBoxDrv::ModuleInit returning %#x (minor:%d)\n", rc, gMiscDevice.minor));
+    misc_deregister(&gMiscDeviceSys);
+    misc_deregister(&gMiscDeviceUsr);
+    Log(("VBoxDrv::ModuleInit returning %#x (minor:%d & %d)\n", rc, gMiscDeviceSys.minor, gMiscDeviceUsr.minor));
 #else
-    unregister_chrdev(g_iModuleMajor, DEVICE_NAME);
-    Log(("VBoxDrv::ModuleInit returning %#x (major:%d)\n", rc, g_iModuleMajor));
+    unregister_chrdev(g_iModuleMajorUsr, DEVICE_NAME_USR);
+    unregister_chrdev(g_iModuleMajorSys, DEVICE_NAME_SYS);
+    Log(("VBoxDrv::ModuleInit returning %#x (major:%d & %d)\n", rc, g_iModuleMajorSys, g_iModuleMajorUsr));
 #endif
     return rc;
@@ -387,8 +440,13 @@
      */
 #ifdef CONFIG_VBOXDRV_AS_MISC
-    rc = misc_deregister(&gMiscDevice);
+    rc = misc_deregister(&gMiscDeviceUsr);
     if (rc < 0)
     {
-        Log(("misc_deregister failed with rc=%#x\n", rc));
+        Log(("misc_deregister failed with rc=%#x on vboxdrvu\n", rc));
+    }
+    rc = misc_deregister(&gMiscDeviceSys);
+    if (rc < 0)
+    {
+        Log(("misc_deregister failed with rc=%#x on vboxdrv\n", rc));
     }
 #else  /* !CONFIG_VBOXDRV_AS_MISC */
@@ -397,7 +455,9 @@
      * Unregister a device entry
      */
-    devfs_remove(DEVICE_NAME);
+    devfs_remove(DEVICE_NAME_USR);
+    devfs_remove(DEVICE_NAME_SYS);
 # endif /* devfs */
-    unregister_chrdev(g_iModuleMajor, DEVICE_NAME);
+    unregister_chrdev(g_iModuleMajorUsr, DEVICE_NAME_USR);
+    unregister_chrdev(g_iModuleMajorSys, DEVICE_NAME_SYS);
 #endif /* !CONFIG_VBOXDRV_AS_MISC */
 
@@ -411,10 +471,11 @@
 
 /**
- * Device open. Called on open /dev/vboxdrv
- *
- * @param   pInode      Pointer to inode info structure.
- * @param   pFilp       Associated file pointer.
- */
-static int VBoxDrvLinuxCreate(struct inode *pInode, struct file *pFilp)
+ * Common open code.
+ *
+ * @param   pInode          Pointer to inode info structure.
+ * @param   pFilp           Associated file pointer.
+ * @param   fUnrestricted   Indicates which device node which was opened.
+ */
+static int VBoxDrvLinuxCreateCommon(struct inode *pInode, struct file *pFilp, bool fUnrestricted)
 {
     int                 rc;
@@ -436,5 +497,5 @@
      * Call common code for the rest.
      */
-    rc = supdrvCreateSession(&g_DevExt, true /* fUser */, true /*fUnrestricted*/, &pSession);
+    rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession);
     if (!rc)
     {
@@ -449,4 +510,18 @@
          RTProcSelf(), current->pid, current->comm));
     return VBoxDrvLinuxErr2LinuxErr(rc);
+}
+
+
+/** /dev/vboxdrv.  */
+static int VBoxDrvLinuxCreateSys(struct inode *pInode, struct file *pFilp)
+{
+    return vboxdrvLinuxCreateCommon(pInode, pFilp, true);
+}
+
+
+/** /dev/vboxdrvu.  */
+static int VBoxDrvLinuxCreateUsr(struct inode *pInode, struct file *pFilp)
+{
+    return vboxdrvLinuxCreateCommon(pInode, pFilp, false);
 }
 
@@ -534,4 +609,6 @@
 #endif
 {
+    PSUPDRVSESSION pSession = (PSUPDRVSESSION)pFilp->private_data;
+
     /*
      * Deal with the two high-speed IOCtl that takes it's arguments from
@@ -539,9 +616,10 @@
      */
 #ifdef HAVE_UNLOCKED_IOCTL
-    if (RT_LIKELY(   uCmd == SUP_IOCTL_FAST_DO_RAW_RUN
-                  || uCmd == SUP_IOCTL_FAST_DO_HM_RUN
-                  || uCmd == SUP_IOCTL_FAST_DO_NOP))
-        return supdrvIOCtlFast(uCmd, ulArg, &g_DevExt, (PSUPDRVSESSION)pFilp->private_data);
-    return VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg);
+    if (RT_LIKELY(   (   uCmd == SUP_IOCTL_FAST_DO_RAW_RUN
+                      || uCmd == SUP_IOCTL_FAST_DO_HM_RUN
+                      || uCmd == SUP_IOCTL_FAST_DO_NOP)
+                  && pSession->fUnrestricted == true))
+        return supdrvIOCtlFast(uCmd, ulArg, &g_DevExt, pSession);
+    return VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg, pSession);
 
 #else   /* !HAVE_UNLOCKED_IOCTL */
@@ -549,10 +627,11 @@
     int rc;
     unlock_kernel();
-    if (RT_LIKELY(   uCmd == SUP_IOCTL_FAST_DO_RAW_RUN
-                  || uCmd == SUP_IOCTL_FAST_DO_HM_RUN
-                  || uCmd == SUP_IOCTL_FAST_DO_NOP))
-        rc = supdrvIOCtlFast(uCmd, ulArg, &g_DevExt, (PSUPDRVSESSION)pFilp->private_data);
+    if (RT_LIKELY(   (   uCmd == SUP_IOCTL_FAST_DO_RAW_RUN
+                      || uCmd == SUP_IOCTL_FAST_DO_HM_RUN
+                      || uCmd == SUP_IOCTL_FAST_DO_NOP)
+                  && pSession->fUnrestricted == true))
+        rc = supdrvIOCtlFast(uCmd, ulArg, &g_DevExt, pSession);
     else
-        rc = VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg);
+        rc = VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg, pSession);
     lock_kernel();
     return rc;
@@ -567,6 +646,7 @@
  * @param   uCmd        The function specified to ioctl().
  * @param   ulArg       The argument specified to ioctl().
- */
-static int VBoxDrvLinuxIOCtlSlow(struct file *pFilp, unsigned int uCmd, unsigned long ulArg)
+ * @param   pSession    The session instance.
+ */
+static int VBoxDrvLinuxIOCtlSlow(struct file *pFilp, unsigned int uCmd, unsigned long ulArg, PSUPDRVSESSION pSession)
 {
     int                 rc;
@@ -621,5 +701,5 @@
      * Process the IOCtl.
      */
-    rc = supdrvIOCtl(uCmd, &g_DevExt, (PSUPDRVSESSION)pFilp->private_data, pHdr);
+    rc = supdrvIOCtl(uCmd, &g_DevExt, pSession, pHdr);
 
     /*
