diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/HostDrivers/Support/linux | |
parent | Initial commit. (diff) | |
download | virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip |
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/HostDrivers/Support/linux')
-rw-r--r-- | src/VBox/HostDrivers/Support/linux/Makefile | 173 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/linux/Makefile.kup | 0 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c | 1450 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/linux/SUPDrv-linux.mod.c | 87 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp | 309 | ||||
-rw-r--r-- | src/VBox/HostDrivers/Support/linux/SUPR0IdcClient-linux.c | 56 | ||||
-rwxr-xr-x | src/VBox/HostDrivers/Support/linux/files_vboxdrv | 218 |
7 files changed, 2293 insertions, 0 deletions
diff --git a/src/VBox/HostDrivers/Support/linux/Makefile b/src/VBox/HostDrivers/Support/linux/Makefile new file mode 100644 index 00000000..7d5a3e1e --- /dev/null +++ b/src/VBox/HostDrivers/Support/linux/Makefile @@ -0,0 +1,173 @@ +# $Id: Makefile $ +## @file +# Makefile for the VirtualBox Linux Host Driver. +# + +# +# Copyright (C) 2006-2019 Oracle Corporation +# +# This file is part of VirtualBox Open Source Edition (OSE), as +# available from http://www.virtualbox.org. This file is free software; +# you can redistribute it and/or modify it under the terms of the GNU +# General Public License (GPL) as published by the Free Software +# Foundation, in version 2 as it comes in the "COPYING" file of the +# VirtualBox OSE distribution. VirtualBox OSE is distributed in the +# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL) only, as it comes in the "COPYING.CDDL" file of the +# VirtualBox OSE distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# + +# Linux kbuild sets this to our source directory if we are called from +# there +obj ?= $(CURDIR) +include $(obj)/Makefile.include.header + +MOD_NAME = vboxdrv +MOD_OBJS = \ + linux/SUPDrv-linux.o \ + SUPDrv.o \ + SUPDrvGip.o \ + SUPDrvSem.o \ + SUPDrvTracer.o \ + SUPLibAll.o \ + r0drv/alloc-r0drv.o \ + r0drv/initterm-r0drv.o \ + r0drv/memobj-r0drv.o \ + r0drv/mpnotification-r0drv.o \ + r0drv/powernotification-r0drv.o \ + r0drv/linux/assert-r0drv-linux.o \ + r0drv/linux/alloc-r0drv-linux.o \ + r0drv/linux/initterm-r0drv-linux.o \ + r0drv/linux/memobj-r0drv-linux.o \ + r0drv/linux/memuserkernel-r0drv-linux.o \ + r0drv/linux/mp-r0drv-linux.o \ + r0drv/linux/mpnotification-r0drv-linux.o \ + r0drv/linux/process-r0drv-linux.o \ + r0drv/linux/rtStrFormatKernelAddress-r0drv-linux.o \ + r0drv/linux/semevent-r0drv-linux.o \ + r0drv/linux/semeventmulti-r0drv-linux.o \ + r0drv/linux/semfastmutex-r0drv-linux.o \ + r0drv/linux/semmutex-r0drv-linux.o \ + r0drv/linux/spinlock-r0drv-linux.o \ + r0drv/linux/thread-r0drv-linux.o \ + r0drv/linux/thread2-r0drv-linux.o \ + r0drv/linux/threadctxhooks-r0drv-linux.o \ + r0drv/linux/time-r0drv-linux.o \ + r0drv/linux/timer-r0drv-linux.o \ + r0drv/generic/semspinmutex-r0drv-generic.o \ + common/alloc/alloc.o \ + common/checksum/crc32.o \ + common/checksum/ipv4.o \ + common/checksum/ipv6.o \ + common/err/RTErrConvertFromErrno.o \ + common/err/RTErrConvertToErrno.o \ + common/err/errinfo.o \ + common/log/log.o \ + common/log/logellipsis.o \ + common/log/logrel.o \ + common/log/logrelellipsis.o \ + common/log/logcom.o \ + common/log/logformat.o \ + common/misc/RTAssertMsg1Weak.o \ + common/misc/RTAssertMsg2.o \ + common/misc/RTAssertMsg2Add.o \ + common/misc/RTAssertMsg2AddWeak.o \ + common/misc/RTAssertMsg2AddWeakV.o \ + common/misc/RTAssertMsg2Weak.o \ + common/misc/RTAssertMsg2WeakV.o \ + common/misc/assert.o \ + common/misc/handletable.o \ + common/misc/handletablectx.o \ + common/misc/thread.o \ + common/string/RTStrCat.o \ + common/string/RTStrCopy.o \ + common/string/RTStrCopyEx.o \ + common/string/RTStrCopyP.o \ + common/string/RTStrNCmp.o \ + common/string/RTStrNLen.o \ + common/string/stringalloc.o \ + common/string/strformat.o \ + common/string/strformatnum.o \ + common/string/strformatrt.o \ + common/string/strformattype.o \ + common/string/strprintf.o \ + common/string/strtonum.o \ + common/table/avlpv.o \ + common/time/time.o \ + r0drv/linux/RTLogWriteDebugger-r0drv-linux.o \ + generic/RTAssertShouldPanic-generic.o \ + generic/RTLogWriteStdErr-stub-generic.o \ + generic/RTLogWriteStdOut-stub-generic.o \ + generic/RTLogWriteUser-generic.o \ + generic/RTMpGetArraySize-generic.o \ + generic/RTMpGetCoreCount-generic.o \ + generic/RTSemEventWait-2-ex-generic.o \ + generic/RTSemEventWaitNoResume-2-ex-generic.o \ + generic/RTSemEventMultiWait-2-ex-generic.o \ + generic/RTSemEventMultiWaitNoResume-2-ex-generic.o \ + generic/RTTimerCreate-generic.o \ + generic/errvars-generic.o \ + generic/mppresent-generic.o \ + generic/uuid-generic.o \ + VBox/log-vbox.o +ifeq ($(BUILD_TARGET_ARCH),x86) + MOD_OBJS += math/gcc/divdi3.o \ + math/gcc/moddi3.o \ + math/gcc/qdivrem.o \ + math/gcc/udivdi3.o \ + math/gcc/udivmoddi4.o \ + math/gcc/divdi3.o \ + math/gcc/umoddi3.o +endif +ifeq ($(BUILD_TARGET_ARCH),amd64) + MOD_OBJS += common/alloc/heapsimple.o +endif +ifdef VBOX_WITH_NATIVE_DTRACE + MOD_OBJS += SUPDrvDTrace.o +endif + +MOD_INCL = $(addprefix -I$(KBUILD_EXTMOD),/ /include /r0drv/linux) +ifdef VBOX_WITH_NATIVE_DTRACE + MOD_INCL += -I/usr/include/linux -I/usr/include +endif +MOD_DEFS = -DRT_OS_LINUX -DIN_RING0 -DIN_RT_R0 -DIN_SUP_R0 -DVBOX \ + -DRT_WITH_VBOX -DVBOX_WITH_HARDENING -DSUPDRV_WITH_RELEASE_LOGGER \ + -DVBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV -DIPRT_WITH_EFLAGS_AC_PRESERVING \ + -Wno-declaration-after-statement +ifndef CONFIG_VBOXDRV_FIXEDMAJOR + MOD_DEFS += -DCONFIG_VBOXDRV_AS_MISC +endif +ifdef VBOX_WITH_NATIVE_DTRACE + MOD_DEFS += -DVBOX_WITH_NATIVE_DTRACE +endif +ifeq ($(BUILD_TARGET_ARCH),amd64) + MOD_DEFS += -DRT_ARCH_AMD64 +else + MOD_DEFS += -DRT_ARCH_X86 +endif +# must be consistent with Config.kmk! +MOD_DEFS += -DVBOX_WITH_64_BITS_GUESTS +ifdef VBOX_WITH_TEXT_MODMEM_HACK + MOD_DEFS += -DRTMEMALLOC_EXEC_HEAP -DVBOX_WITH_TEXT_MODMEM_HACK +endif + +# build defs +MOD_CFLAGS = -include $(KBUILD_EXTMOD)/include/VBox/SUPDrvMangling.h \ + -fno-omit-frame-pointer -fno-pie + +include $(obj)/Makefile.include.footer + +check: $(MODULE) + @if ! readelf -p __ksymtab_strings vboxdrv.ko | grep -E "\[.*\] *(RT|g_..*RT.*)"; then \ + echo "All exported IPRT symbols are properly renamed!"; \ + else \ + echo "error: Some exported IPRT symbols was not properly renamed! See above." >&2; \ + false; \ + fi diff --git a/src/VBox/HostDrivers/Support/linux/Makefile.kup b/src/VBox/HostDrivers/Support/linux/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/HostDrivers/Support/linux/Makefile.kup diff --git a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c new file mode 100644 index 00000000..43751c85 --- /dev/null +++ b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c @@ -0,0 +1,1450 @@ +/* $Rev: 127855 $ */ +/** @file + * VBoxDrv - The VirtualBox Support Driver - Linux specifics. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_SUP_DRV +#include "../SUPDrvInternal.h" +#include "the-linux-kernel.h" +#include "version-generated.h" +#include "product-generated.h" +#include "revision-generated.h" + +#include <iprt/assert.h> +#include <iprt/spinlock.h> +#include <iprt/semaphore.h> +#include <iprt/initterm.h> +#include <iprt/process.h> +#include <VBox/err.h> +#include <iprt/mem.h> +#include <VBox/log.h> +#include <iprt/mp.h> + +/** @todo figure out the exact version number */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16) +# include <iprt/power.h> +# define VBOX_WITH_SUSPEND_NOTIFICATION +#endif + +#include <linux/sched.h> +#include <linux/miscdevice.h> +#ifdef VBOX_WITH_SUSPEND_NOTIFICATION +# include <linux/platform_device.h> +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) && defined(SUPDRV_WITH_MSR_PROBER) +# define SUPDRV_LINUX_HAS_SAFE_MSR_API +# include <asm/msr.h> +#endif + +#include <asm/desc.h> + +#include <iprt/asm-amd64-x86.h> + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/* check kernel version */ +# ifndef SUPDRV_AGNOSTIC +# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +# error Unsupported kernel version! +# endif +# endif + +#ifdef CONFIG_X86_HIGH_ENTRY +# error "CONFIG_X86_HIGH_ENTRY is not supported by VBoxDrv at this time." +#endif + +/* We cannot include x86.h, so we copy the defines we need here: */ +#define X86_EFL_IF RT_BIT(9) +#define X86_EFL_AC RT_BIT(18) +#define X86_EFL_DF RT_BIT(10) +#define X86_EFL_IOPL (RT_BIT(12) | RT_BIT(13)) + +/* To include the version number of VirtualBox into kernel backtraces: */ +#define VBoxDrvLinuxVersion RT_CONCAT3(RT_CONCAT(VBOX_VERSION_MAJOR, _), \ + RT_CONCAT(VBOX_VERSION_MINOR, _), \ + VBOX_VERSION_BUILD) +#define VBoxDrvLinuxIOCtl RT_CONCAT(VBoxDrvLinuxIOCtl_,VBoxDrvLinuxVersion) + + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ +static int VBoxDrvLinuxInit(void); +static void VBoxDrvLinuxUnload(void); +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 +static long VBoxDrvLinuxIOCtl(struct file *pFilp, unsigned int uCmd, unsigned long ulArg); +#else +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, PSUPDRVSESSION pSession); +static int VBoxDrvLinuxErr2LinuxErr(int); +#ifdef VBOX_WITH_SUSPEND_NOTIFICATION +static int VBoxDrvProbe(struct platform_device *pDev); +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) +static int VBoxDrvSuspend(struct device *pDev); +static int VBoxDrvResume(struct device *pDev); +# else +static int VBoxDrvSuspend(struct platform_device *pDev, pm_message_t State); +static int VBoxDrvResume(struct platform_device *pDev); +# endif +static void VBoxDevRelease(struct device *pDev); +#endif + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** + * Device extention & session data association structure. + */ +static SUPDRVDEVEXT g_DevExt; + +/** Module parameter. + * Not prefixed because the name is used by macros and the end of this file. */ +static int force_async_tsc = 0; + +/** The system device name. */ +#define DEVICE_NAME_SYS "vboxdrv" +/** The user device name. */ +#define DEVICE_NAME_USR "vboxdrvu" + +#if (defined(RT_ARCH_AMD64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)) || defined(VBOX_WITH_TEXT_MODMEM_HACK) +/** + * Memory for the executable memory heap (in IPRT). + */ +# ifdef DEBUG +# define EXEC_MEMORY_SIZE 8388608 /* 8 MB */ +# else +# define EXEC_MEMORY_SIZE 2097152 /* 2 MB */ +# endif +extern uint8_t g_abExecMemory[EXEC_MEMORY_SIZE]; +# ifndef VBOX_WITH_TEXT_MODMEM_HACK +__asm__(".section execmemory, \"awx\", @progbits\n\t" + ".align 32\n\t" + ".globl g_abExecMemory\n" + "g_abExecMemory:\n\t" + ".zero " RT_XSTR(EXEC_MEMORY_SIZE) "\n\t" + ".type g_abExecMemory, @object\n\t" + ".size g_abExecMemory, " RT_XSTR(EXEC_MEMORY_SIZE) "\n\t" + ".text\n\t"); +# else +__asm__(".text\n\t" + ".align 4096\n\t" + ".globl g_abExecMemory\n" + "g_abExecMemory:\n\t" + ".zero " RT_XSTR(EXEC_MEMORY_SIZE) "\n\t" + ".type g_abExecMemory, @object\n\t" + ".size g_abExecMemory, " RT_XSTR(EXEC_MEMORY_SIZE) "\n\t" + ".text\n\t"); +# endif +#endif + +/** The file_operations structure. */ +static struct file_operations gFileOpsVBoxDrvSys = +{ + owner: THIS_MODULE, + open: VBoxDrvLinuxCreateSys, + release: VBoxDrvLinuxClose, +#ifdef HAVE_UNLOCKED_IOCTL + unlocked_ioctl: VBoxDrvLinuxIOCtl, +#else + ioctl: VBoxDrvLinuxIOCtl, +#endif +}; + +/** 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 +}; + +/** The miscdevice structure for vboxdrv. */ +static struct miscdevice gMiscDeviceSys = +{ + minor: MISC_DYNAMIC_MINOR, + name: DEVICE_NAME_SYS, + fops: &gFileOpsVBoxDrvSys, +# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17) + 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 +}; + + +#ifdef VBOX_WITH_SUSPEND_NOTIFICATION +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) +static struct dev_pm_ops gPlatformPMOps = +{ + .suspend = VBoxDrvSuspend, /* before entering deep sleep */ + .resume = VBoxDrvResume, /* after wakeup from deep sleep */ + .freeze = VBoxDrvSuspend, /* before creating hibernation image */ + .restore = VBoxDrvResume, /* after waking up from hibernation */ +}; +# endif + +static struct platform_driver gPlatformDriver = +{ + .probe = VBoxDrvProbe, +# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) + .suspend = VBoxDrvSuspend, + .resume = VBoxDrvResume, +# endif + /** @todo .shutdown? */ + .driver = + { + .name = "vboxdrv", +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) + .pm = &gPlatformPMOps, +# endif + } +}; + +static struct platform_device gPlatformDevice = +{ + .name = "vboxdrv", + .dev = + { + .release = VBoxDevRelease + } +}; +#endif /* VBOX_WITH_SUSPEND_NOTIFICATION */ + + +DECLINLINE(RTUID) vboxdrvLinuxUid(void) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + return from_kuid(current_user_ns(), current->cred->uid); +# else + return current->cred->uid; +# endif +#else + return current->uid; +#endif +} + +DECLINLINE(RTGID) vboxdrvLinuxGid(void) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + return from_kgid(current_user_ns(), current->cred->gid); +# else + return current->cred->gid; +# endif +#else + return current->gid; +#endif +} + +DECLINLINE(RTUID) vboxdrvLinuxEuid(void) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + return from_kuid(current_user_ns(), current->cred->euid); +# else + return current->cred->euid; +# endif +#else + return current->euid; +#endif +} + +/** + * Initialize module. + * + * @returns appropriate status code. + */ +static int __init VBoxDrvLinuxInit(void) +{ + int rc; + + /* + * Check for synchronous/asynchronous TSC mode. + */ + printk(KERN_DEBUG "vboxdrv: Found %u processor cores\n", (unsigned)RTMpGetOnlineCount()); + rc = misc_register(&gMiscDeviceSys); + if (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; + } + if (!rc) + { + /* + * Initialize the runtime. + * On AMD64 we'll have to donate the high rwx memory block to the exec allocator. + */ + rc = RTR0Init(0); + if (RT_SUCCESS(rc)) + { +#if (defined(RT_ARCH_AMD64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)) || defined(VBOX_WITH_TEXT_MODMEM_HACK) +# ifdef VBOX_WITH_TEXT_MODMEM_HACK + set_memory_x(&g_abExecMemory[0], sizeof(g_abExecMemory) / PAGE_SIZE); + set_memory_rw(&g_abExecMemory[0], sizeof(g_abExecMemory) / PAGE_SIZE); +# endif + rc = RTR0MemExecDonate(&g_abExecMemory[0], sizeof(g_abExecMemory)); + printk(KERN_DEBUG "VBoxDrv: dbg - g_abExecMemory=%p\n", (void *)&g_abExecMemory[0]); +#endif + Log(("VBoxDrv::ModuleInit\n")); + + /* + * Initialize the device extension. + */ + if (RT_SUCCESS(rc)) + rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION)); + if (RT_SUCCESS(rc)) + { +#ifdef VBOX_WITH_SUSPEND_NOTIFICATION + rc = platform_driver_register(&gPlatformDriver); + if (rc == 0) + { + rc = platform_device_register(&gPlatformDevice); + if (rc == 0) +#endif + { + printk(KERN_INFO "vboxdrv: TSC mode is %s, tentative frequency %llu Hz\n", + SUPGetGIPModeName(g_DevExt.pGip), g_DevExt.pGip->u64CpuHz); + LogFlow(("VBoxDrv::ModuleInit returning %#x\n", rc)); + printk(KERN_DEBUG "vboxdrv: Successfully loaded version " + VBOX_VERSION_STRING " (interface " RT_XSTR(SUPDRV_IOC_VERSION) ")\n"); + return rc; + } +#ifdef VBOX_WITH_SUSPEND_NOTIFICATION + else + platform_driver_unregister(&gPlatformDriver); + } +#endif + } + + rc = -EINVAL; + RTR0TermForced(); + } + else + rc = -EINVAL; + + /* + * Failed, cleanup and return the error code. + */ + } + misc_deregister(&gMiscDeviceSys); + misc_deregister(&gMiscDeviceUsr); + Log(("VBoxDrv::ModuleInit returning %#x (minor:%d & %d)\n", rc, gMiscDeviceSys.minor, gMiscDeviceUsr.minor)); + return rc; +} + + +/** + * Unload the module. + */ +static void __exit VBoxDrvLinuxUnload(void) +{ + Log(("VBoxDrvLinuxUnload\n")); + +#ifdef VBOX_WITH_SUSPEND_NOTIFICATION + platform_device_unregister(&gPlatformDevice); + platform_driver_unregister(&gPlatformDriver); +#endif + + /* + * I Don't think it's possible to unload a driver which processes have + * opened, at least we'll blindly assume that here. + */ + misc_deregister(&gMiscDeviceUsr); + misc_deregister(&gMiscDeviceSys); + + /* + * Destroy GIP, delete the device extension and terminate IPRT. + */ + supdrvDeleteDevExt(&g_DevExt); + RTR0TermForced(); +} + + +/** + * 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; + PSUPDRVSESSION pSession; + Log(("VBoxDrvLinuxCreate: pFilp=%p pid=%d/%d %s\n", pFilp, RTProcSelf(), current->pid, current->comm)); + +#ifdef VBOX_WITH_HARDENING + /* + * Only root is allowed to access the unrestricted device, enforce it! + */ + if ( fUnrestricted + && vboxdrvLinuxEuid() != 0 /* root */ ) + { + Log(("VBoxDrvLinuxCreate: euid=%d, expected 0 (root)\n", vboxdrvLinuxEuid())); + return -EPERM; + } +#endif /* VBOX_WITH_HARDENING */ + + /* + * Call common code for the rest. + */ + rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession); + if (!rc) + { + pSession->Uid = vboxdrvLinuxUid(); + pSession->Gid = vboxdrvLinuxGid(); + } + + pFilp->private_data = pSession; + + Log(("VBoxDrvLinuxCreate: g_DevExt=%p pSession=%p rc=%d/%d (pid=%d/%d %s)\n", + &g_DevExt, pSession, rc, VBoxDrvLinuxErr2LinuxErr(rc), + 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); +} + + +/** + * Close device. + * + * @param pInode Pointer to inode info structure. + * @param pFilp Associated file pointer. + */ +static int VBoxDrvLinuxClose(struct inode *pInode, struct file *pFilp) +{ + Log(("VBoxDrvLinuxClose: pFilp=%p pSession=%p pid=%d/%d %s\n", + pFilp, pFilp->private_data, RTProcSelf(), current->pid, current->comm)); + supdrvSessionRelease((PSUPDRVSESSION)pFilp->private_data); + pFilp->private_data = NULL; + return 0; +} + + +#ifdef VBOX_WITH_SUSPEND_NOTIFICATION +/** + * Dummy device release function. We have to provide this function, + * otherwise the kernel will complain. + * + * @param pDev Pointer to the platform device. + */ +static void VBoxDevRelease(struct device *pDev) +{ +} + +/** + * Dummy probe function. + * + * @param pDev Pointer to the platform device. + */ +static int VBoxDrvProbe(struct platform_device *pDev) +{ + return 0; +} + +/** + * Suspend callback. + * @param pDev Pointer to the platform device. + * @param State Message type, see Documentation/power/devices.txt. + * Ignored. + */ +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) && !defined(DOXYGEN_RUNNING) +static int VBoxDrvSuspend(struct device *pDev) +# else +static int VBoxDrvSuspend(struct platform_device *pDev, pm_message_t State) +# endif +{ + RTPowerSignalEvent(RTPOWEREVENT_SUSPEND); + return 0; +} + +/** + * Resume callback. + * + * @param pDev Pointer to the platform device. + */ +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) +static int VBoxDrvResume(struct device *pDev) +# else +static int VBoxDrvResume(struct platform_device *pDev) +# endif +{ + RTPowerSignalEvent(RTPOWEREVENT_RESUME); + return 0; +} +#endif /* VBOX_WITH_SUSPEND_NOTIFICATION */ + + +/** + * Device I/O Control entry point. + * + * @param pFilp Associated file pointer. + * @param uCmd The function specified to ioctl(). + * @param ulArg The argument specified to ioctl(). + */ +#if defined(HAVE_UNLOCKED_IOCTL) || defined(DOXYGEN_RUNNING) +static long VBoxDrvLinuxIOCtl(struct file *pFilp, unsigned int uCmd, unsigned long ulArg) +#else +static int VBoxDrvLinuxIOCtl(struct inode *pInode, struct file *pFilp, unsigned int uCmd, unsigned long ulArg) +#endif +{ + PSUPDRVSESSION pSession = (PSUPDRVSESSION)pFilp->private_data; + int rc; +#if defined(VBOX_STRICT) || defined(VBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV) + RTCCUINTREG fSavedEfl; + + /* + * Refuse all I/O control calls if we've ever detected EFLAGS.AC being cleared. + * + * This isn't a problem, as there is absolutely nothing in the kernel context that + * depend on user context triggering cleanups. That would be pretty wild, right? + */ + if (RT_UNLIKELY(g_DevExt.cBadContextCalls > 0)) + { + SUPR0Printf("VBoxDrvLinuxIOCtl: EFLAGS.AC=0 detected %u times, refusing all I/O controls!\n", g_DevExt.cBadContextCalls); + return ESPIPE; + } + + fSavedEfl = ASMAddFlags(X86_EFL_AC); +# else + stac(); +# endif + + /* + * Deal with the two high-speed IOCtl that takes it's arguments from + * the session and iCmd, and only returns a VBox status code. + */ + AssertCompile(_IOC_NRSHIFT == 0 && _IOC_NRBITS == 8); +#ifdef HAVE_UNLOCKED_IOCTL + if (RT_LIKELY( (unsigned int)(uCmd - SUP_IOCTL_FAST_DO_FIRST) < (unsigned int)32 + && pSession->fUnrestricted)) + rc = supdrvIOCtlFast(uCmd - SUP_IOCTL_FAST_DO_FIRST, ulArg, &g_DevExt, pSession); + else + rc = VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg, pSession); +#else /* !HAVE_UNLOCKED_IOCTL */ + unlock_kernel(); + if (RT_LIKELY( (unsigned int)(uCmd - SUP_IOCTL_FAST_DO_FIRST) < (unsigned int)32 + && pSession->fUnrestricted)) + rc = supdrvIOCtlFast(uCmd - SUP_IOCTL_FAST_DO_FIRST, ulArg, &g_DevExt, pSession); + else + rc = VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg, pSession); + lock_kernel(); +#endif /* !HAVE_UNLOCKED_IOCTL */ + +#if defined(VBOX_STRICT) || defined(VBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV) + /* + * Before we restore AC and the rest of EFLAGS, check if the IOCtl handler code + * accidentially modified it or some other important flag. + */ + if (RT_UNLIKELY( (ASMGetFlags() & (X86_EFL_AC | X86_EFL_IF | X86_EFL_DF)) + != ((fSavedEfl & (X86_EFL_AC | X86_EFL_IF | X86_EFL_DF)) | X86_EFL_AC) )) + { + char szTmp[48]; + RTStrPrintf(szTmp, sizeof(szTmp), "uCmd=%#x: %#x->%#x!", _IOC_NR(uCmd), (uint32_t)fSavedEfl, (uint32_t)ASMGetFlags()); + supdrvBadContext(&g_DevExt, "SUPDrv-linux.c", __LINE__, szTmp); + } + ASMSetFlags(fSavedEfl); +#else + clac(); +#endif + return rc; +} + + +/** + * Device I/O Control entry point. + * + * @param pFilp Associated file pointer. + * @param uCmd The function specified to ioctl(). + * @param ulArg The argument specified to ioctl(). + * @param pSession The session instance. + */ +static int VBoxDrvLinuxIOCtlSlow(struct file *pFilp, unsigned int uCmd, unsigned long ulArg, PSUPDRVSESSION pSession) +{ + int rc; + SUPREQHDR Hdr; + PSUPREQHDR pHdr; + uint32_t cbBuf; + + Log6(("VBoxDrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p pid=%d/%d\n", pFilp, uCmd, (void *)ulArg, RTProcSelf(), current->pid)); + + /* + * Read the header. + */ + if (RT_FAILURE(RTR0MemUserCopyFrom(&Hdr, ulArg, sizeof(Hdr)))) + { + Log(("VBoxDrvLinuxIOCtl: copy_from_user(,%#lx,) failed; uCmd=%#x\n", ulArg, uCmd)); + return -EFAULT; + } + if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) + { + Log(("VBoxDrvLinuxIOCtl: bad header magic %#x; uCmd=%#x\n", Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK, uCmd)); + return -EINVAL; + } + + /* + * Buffer the request. + */ + cbBuf = RT_MAX(Hdr.cbIn, Hdr.cbOut); + if (RT_UNLIKELY(cbBuf > _1M*16)) + { + Log(("VBoxDrvLinuxIOCtl: too big cbBuf=%#x; uCmd=%#x\n", cbBuf, uCmd)); + return -E2BIG; + } + if (RT_UNLIKELY(_IOC_SIZE(uCmd) ? cbBuf != _IOC_SIZE(uCmd) : Hdr.cbIn < sizeof(Hdr))) + { + Log(("VBoxDrvLinuxIOCtl: bad ioctl cbBuf=%#x _IOC_SIZE=%#x; uCmd=%#x\n", cbBuf, _IOC_SIZE(uCmd), uCmd)); + return -EINVAL; + } + pHdr = RTMemAlloc(cbBuf); + if (RT_UNLIKELY(!pHdr)) + { + OSDBGPRINT(("VBoxDrvLinuxIOCtl: failed to allocate buffer of %d bytes for uCmd=%#x\n", cbBuf, uCmd)); + return -ENOMEM; + } + if (RT_FAILURE(RTR0MemUserCopyFrom(pHdr, ulArg, Hdr.cbIn))) + { + Log(("VBoxDrvLinuxIOCtl: copy_from_user(,%#lx, %#x) failed; uCmd=%#x\n", ulArg, Hdr.cbIn, uCmd)); + RTMemFree(pHdr); + return -EFAULT; + } + if (Hdr.cbIn < cbBuf) + RT_BZERO((uint8_t *)pHdr + Hdr.cbIn, cbBuf - Hdr.cbIn); + + /* + * Process the IOCtl. + */ + rc = supdrvIOCtl(uCmd, &g_DevExt, pSession, pHdr, cbBuf); + + /* + * Copy ioctl data and output buffer back to user space. + */ + if (RT_LIKELY(!rc)) + { + uint32_t cbOut = pHdr->cbOut; + if (RT_UNLIKELY(cbOut > cbBuf)) + { + OSDBGPRINT(("VBoxDrvLinuxIOCtl: too much output! %#x > %#x; uCmd=%#x!\n", cbOut, cbBuf, uCmd)); + cbOut = cbBuf; + } + if (RT_FAILURE(RTR0MemUserCopyTo(ulArg, pHdr, cbOut))) + { + /* this is really bad! */ + OSDBGPRINT(("VBoxDrvLinuxIOCtl: copy_to_user(%#lx,,%#x); uCmd=%#x!\n", ulArg, cbOut, uCmd)); + rc = -EFAULT; + } + } + else + { + Log(("VBoxDrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p failed, rc=%d\n", pFilp, uCmd, (void *)ulArg, rc)); + rc = -EINVAL; + } + RTMemFree(pHdr); + + Log6(("VBoxDrvLinuxIOCtl: returns %d (pid=%d/%d)\n", rc, RTProcSelf(), current->pid)); + return rc; +} + + +/** + * The SUPDRV IDC entry point. + * + * @returns VBox status code, see supdrvIDC. + * @param uReq The request code. + * @param pReq The request. + */ +int VBOXCALL SUPDrvLinuxIDC(uint32_t uReq, PSUPDRVIDCREQHDR pReq) +{ + PSUPDRVSESSION pSession; + + /* + * Some quick validations. + */ + if (RT_UNLIKELY(!VALID_PTR(pReq))) + return VERR_INVALID_POINTER; + + pSession = pReq->pSession; + if (pSession) + { + if (RT_UNLIKELY(!VALID_PTR(pSession))) + return VERR_INVALID_PARAMETER; + if (RT_UNLIKELY(pSession->pDevExt != &g_DevExt)) + return VERR_INVALID_PARAMETER; + } + else if (RT_UNLIKELY(uReq != SUPDRV_IDC_REQ_CONNECT)) + return VERR_INVALID_PARAMETER; + + /* + * Do the job. + */ + return supdrvIDC(uReq, &g_DevExt, pSession, pReq); +} + +EXPORT_SYMBOL(SUPDrvLinuxIDC); + + +RTCCUINTREG VBOXCALL supdrvOSChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0) + RTCCUINTREG uOld = this_cpu_read(cpu_tlbstate.cr4); + RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask; + if (uNew != uOld) + { + this_cpu_write(cpu_tlbstate.cr4, uNew); + __write_cr4(uNew); + } +#else + RTCCUINTREG uOld = ASMGetCR4(); + RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask; + if (uNew != uOld) + ASMSetCR4(uNew); +#endif + return uOld; +} + + +void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession) +{ + NOREF(pDevExt); + NOREF(pSession); +} + + +void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser) +{ + NOREF(pDevExt); NOREF(pSession); NOREF(pvUser); +} + + +void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser) +{ + NOREF(pDevExt); NOREF(pSession); NOREF(pvUser); +} + + +/** + * Initializes any OS specific object creator fields. + */ +void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession) +{ + NOREF(pObj); + NOREF(pSession); +} + + +/** + * Checks if the session can access the object. + * + * @returns true if a decision has been made. + * @returns false if the default access policy should be applied. + * + * @param pObj The object in question. + * @param pSession The session wanting to access the object. + * @param pszObjName The object name, can be NULL. + * @param prc Where to store the result when returning true. + */ +bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc) +{ + NOREF(pObj); + NOREF(pSession); + NOREF(pszObjName); + NOREF(prc); + return false; +} + + +bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt) +{ + return force_async_tsc != 0; +} + + +bool VBOXCALL supdrvOSAreCpusOfflinedOnSuspend(void) +{ + return true; +} + + +bool VBOXCALL supdrvOSAreTscDeltasInSync(void) +{ + return false; +} + + +int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename) +{ + NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename); + return VERR_NOT_SUPPORTED; +} + + +int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, + const uint8_t *pbImageBits, const char *pszSymbol) +{ + NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits); NOREF(pszSymbol); + return VERR_NOT_SUPPORTED; +} + + +int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq) +{ + NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); NOREF(pReq); + return VERR_NOT_SUPPORTED; +} + + +void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) +{ + NOREF(pDevExt); NOREF(pImage); +} + + +/** @def VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS + * A very crude hack for debugging using perf and dtrace. + * + * DO ABSOLUTELY NOT ENABLE IN PRODUCTION BUILDS! DEVELOPMENT ONLY!! + * DO ABSOLUTELY NOT ENABLE IN PRODUCTION BUILDS! DEVELOPMENT ONLY!! + * DO ABSOLUTELY NOT ENABLE IN PRODUCTION BUILDS! DEVELOPMENT ONLY!! + * + */ +#if 0 || defined(DOXYGEN_RUNNING) +# define VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS +#endif + +#if defined(VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS) && defined(CONFIG_MODULES_TREE_LOOKUP) +/** Whether g_pfnModTreeInsert and g_pfnModTreeRemove have been initialized. + * @remarks can still be NULL after init. */ +static volatile bool g_fLookedForModTreeFunctions = false; +static void (*g_pfnModTreeInsert)(struct mod_tree_node *) = NULL; /**< __mod_tree_insert */ +static void (*g_pfnModTreeRemove)(struct mod_tree_node *) = NULL; /**< __mod_tree_remove */ +#endif + + +void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename) +{ +#ifdef VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS /* Not for production use!! Debugging only! */ + /* + * This trick stops working with 4.2 when CONFIG_MODULES_TREE_LOOKUP is + * defined. The module lookups are done via a tree structure and we + * cannot get at the root of it. :-( + */ +# ifdef CONFIG_KALLSYMS + size_t const cchName = strlen(pImage->szName); +# endif + struct module *pMyMod, *pSelfMod, *pTestMod, *pTestModByName; + IPRT_LINUX_SAVE_EFL_AC(); + + pImage->pLnxModHack = NULL; + +# ifdef CONFIG_MODULES_TREE_LOOKUP + /* + * This is pretty naive, but works for 4.2 on arch linux. I don't think we + * can count on finding __mod_tree_remove in all kernel builds as it's not + * marked noinline like __mod_tree_insert. + */ + if (!g_fLookedForModTreeFunctions) + { + unsigned long ulInsert = kallsyms_lookup_name("__mod_tree_insert"); + unsigned long ulRemove = kallsyms_lookup_name("__mod_tree_remove"); + if (!ulInsert || !ulRemove) + { + g_fLookedForModTreeFunctions = true; + printk(KERN_ERR "vboxdrv: failed to locate __mod_tree_insert and __mod_tree_remove.\n"); + IPRT_LINUX_RESTORE_EFL_AC(); + return; + } + *(unsigned long *)&g_pfnModTreeInsert = ulInsert; + *(unsigned long *)&g_pfnModTreeRemove = ulRemove; + ASMCompilerBarrier(); + g_fLookedForModTreeFunctions = true; + } + else if (!g_pfnModTreeInsert || !g_pfnModTreeRemove) + return; +#endif + + /* + * Make sure we've found our own module, otherwise we cannot access the linked list. + */ + mutex_lock(&module_mutex); + pSelfMod = find_module("vboxdrv"); + mutex_unlock(&module_mutex); + if (!pSelfMod) + { + IPRT_LINUX_RESTORE_EFL_AC(); + return; + } + + /* + * Cook up a module structure for the image. + * We allocate symbol and string tables in the allocation and the module to keep things simple. + */ +# ifdef CONFIG_KALLSYMS + pMyMod = (struct module *)RTMemAllocZ(sizeof(*pMyMod) + + sizeof(Elf_Sym) * 3 + + 1 + cchName * 2 + sizeof("_start") + sizeof("_end") + 4 ); +# else + pMyMod = (struct module *)RTMemAllocZ(sizeof(*pMyMod)); +# endif + if (pMyMod) + { + int rc = VINF_SUCCESS; +# ifdef CONFIG_KALLSYMS + Elf_Sym *paSymbols = (Elf_Sym *)(pMyMod + 1); + char *pchStrTab = (char *)(paSymbols + 3); +# endif + + pMyMod->state = MODULE_STATE_LIVE; + INIT_LIST_HEAD(&pMyMod->list); /* just in case */ + + /* Perf only matches up files with a .ko extension (maybe .ko.gz), + so in order for this crap to work smoothly, we append .ko to the + module name and require the user to create symbolic links in + /lib/modules/`uname -r`: + for i in VMMR0.r0 VBoxDDR0.r0 VBoxDD2R0.r0; do + sudo ln -s /mnt/scratch/vbox/svn/trunk/out/linux.amd64/debug/bin/$i /lib/modules/`uname -r`/$i.ko; + done */ + RTStrPrintf(pMyMod->name, sizeof(pMyMod->name), "%s", pImage->szName); + + /* sysfs bits. */ + INIT_LIST_HEAD(&pMyMod->mkobj.kobj.entry); /* rest of kobj is already zeroed, hopefully never accessed... */ + pMyMod->mkobj.mod = pMyMod; + pMyMod->mkobj.drivers_dir = NULL; + pMyMod->mkobj.mp = NULL; + pMyMod->mkobj.kobj_completion = NULL; + + pMyMod->modinfo_attrs = NULL; /* hopefully not accessed after setup. */ + pMyMod->holders_dir = NULL; /* hopefully not accessed. */ + pMyMod->version = "N/A"; + pMyMod->srcversion = "N/A"; + + /* We export no symbols. */ + pMyMod->num_syms = 0; + pMyMod->syms = NULL; + pMyMod->crcs = NULL; + + pMyMod->num_gpl_syms = 0; + pMyMod->gpl_syms = NULL; + pMyMod->gpl_crcs = NULL; + + pMyMod->num_gpl_future_syms = 0; + pMyMod->gpl_future_syms = NULL; + pMyMod->gpl_future_crcs = NULL; + +# if CONFIG_UNUSED_SYMBOLS + pMyMod->num_unused_syms = 0; + pMyMod->unused_syms = NULL; + pMyMod->unused_crcs = NULL; + + pMyMod->num_unused_gpl_syms = 0; + pMyMod->unused_gpl_syms = NULL; + pMyMod->unused_gpl_crcs = NULL; +# endif + /* No kernel parameters either. */ + pMyMod->kp = NULL; + pMyMod->num_kp = 0; + +# ifdef CONFIG_MODULE_SIG + /* Pretend ok signature. */ + pMyMod->sig_ok = true; +# endif + /* No exception table. */ + pMyMod->num_exentries = 0; + pMyMod->extable = NULL; + + /* No init function */ + pMyMod->init = NULL; + pMyMod->module_init = NULL; + pMyMod->init_size = 0; + pMyMod->init_ro_size = 0; + pMyMod->init_text_size = 0; + + /* The module address and size. It's all text. */ + pMyMod->module_core = pImage->pvImage; + pMyMod->core_size = pImage->cbImageBits; + pMyMod->core_text_size = pImage->cbImageBits; + pMyMod->core_ro_size = pImage->cbImageBits; + +#ifdef CONFIG_MODULES_TREE_LOOKUP + /* Fill in the self pointers for the tree nodes. */ + pMyMod->mtn_core.mod = pMyMod; + pMyMod->mtn_init.mod = pMyMod; +#endif + /* They invented the tained bit for us, didn't they? */ + pMyMod->taints = 1; + +# ifdef CONFIG_GENERIC_BUGS + /* No BUGs in our modules. */ + pMyMod->num_bugs = 0; + INIT_LIST_HEAD(&pMyMod->bug_list); + pMyMod->bug_table = NULL; +# endif + +# ifdef CONFIG_KALLSYMS + /* The core stuff is documented as only used when loading. So just zero them. */ + pMyMod->core_num_syms = 0; + pMyMod->core_symtab = NULL; + pMyMod->core_strtab = NULL; + + /* Construct a symbol table with start and end symbols. + Note! We don't have our own symbol table at this point, image bit + are not uploaded yet! */ + pMyMod->num_symtab = 3; + pMyMod->symtab = paSymbols; + pMyMod->strtab = pchStrTab; + RT_ZERO(paSymbols[0]); + pchStrTab[0] = '\0'; + paSymbols[1].st_name = 1; + paSymbols[2].st_name = 2 + RTStrPrintf(&pchStrTab[paSymbols[1].st_name], cchName + sizeof("_start"), + "%s_start", pImage->szName); + RTStrPrintf(&pchStrTab[paSymbols[2].st_name], cchName + sizeof("_end"), "%s_end", pImage->szName); + paSymbols[1].st_info = 't'; + paSymbols[2].st_info = 'b'; + paSymbols[1].st_other = 0; + paSymbols[2].st_other = 0; + paSymbols[1].st_shndx = 0; + paSymbols[2].st_shndx = 0; + paSymbols[1].st_value = (uintptr_t)pImage->pvImage; + paSymbols[2].st_value = (uintptr_t)pImage->pvImage + pImage->cbImageBits - 1; + paSymbols[1].st_size = pImage->cbImageBits - 1; + paSymbols[2].st_size = 1; +# endif + /* No arguments, but seems its always non-NULL so put empty string there. */ + pMyMod->args = ""; + +# ifdef CONFIG_SMP + /* No per CPU data. */ + pMyMod->percpu = NULL; + pMyMod->percpu_size = 0; +# endif +# ifdef CONFIG_TRACEPOINTS + /* No tracepoints we like to share. */ + pMyMod->num_tracepoints = 0; + pMyMod->tracepoints_ptrs = NULL; +#endif +# ifdef HAVE_JUMP_LABEL + /* No jump lable stuff either. */ + pMyMod->jump_entries = NULL; + pMyMod->num_jump_entries = 0; +# endif +# ifdef CONFIG_TRACING + pMyMod->num_trace_bprintk_fmt = 0; + pMyMod->trace_bprintk_fmt_start = NULL; +# endif +# ifdef CONFIG_EVENT_TRACING + pMyMod->trace_events = NULL; + pMyMod->num_trace_events = 0; +# endif +# ifdef CONFIG_FTRACE_MCOUNT_RECORD + pMyMod->num_ftrace_callsites = 0; + pMyMod->ftrace_callsites = NULL; +# endif +# ifdef CONFIG_MODULE_UNLOAD + /* Dependency lists, not worth sharing */ + INIT_LIST_HEAD(&pMyMod->source_list); + INIT_LIST_HEAD(&pMyMod->target_list); + + /* Nobody waiting and no exit function. */ +# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) + pMyMod->waiter = NULL; +# endif + pMyMod->exit = NULL; + + /* References, very important as we must not allow the module + to be unloaded using rmmod. */ +# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + atomic_set(&pMyMod->refcnt, 42); +# else + pMyMod->refptr = alloc_percpu(struct module_ref); + if (pMyMod->refptr) + { + int iCpu; + for_each_possible_cpu(iCpu) + { + per_cpu_ptr(pMyMod->refptr, iCpu)->decs = 0; + per_cpu_ptr(pMyMod->refptr, iCpu)->incs = 1; + } + } + else + rc = VERR_NO_MEMORY; +# endif +# endif +# ifdef CONFIG_CONSTRUCTORS + /* No constructors. */ + pMyMod->ctors = NULL; + pMyMod->num_ctors = 0; +# endif + if (RT_SUCCESS(rc)) + { + bool fIsModText; + + /* + * Add the module to the list. + */ + mutex_lock(&module_mutex); + list_add_rcu(&pMyMod->list, &pSelfMod->list); + pImage->pLnxModHack = pMyMod; +# ifdef CONFIG_MODULES_TREE_LOOKUP + g_pfnModTreeInsert(&pMyMod->mtn_core); /* __mod_tree_insert */ +# endif + mutex_unlock(&module_mutex); + + /* + * Test it. + */ + mutex_lock(&module_mutex); + pTestModByName = find_module(pMyMod->name); + pTestMod = __module_address((uintptr_t)pImage->pvImage + pImage->cbImageBits / 4); + fIsModText = __module_text_address((uintptr_t)pImage->pvImage + pImage->cbImageBits / 2); + mutex_unlock(&module_mutex); + if ( pTestMod == pMyMod + && pTestModByName == pMyMod + && fIsModText) + printk(KERN_ERR "vboxdrv: fake module works for '%s' (%#lx to %#lx)\n", + pMyMod->name, (unsigned long)paSymbols[1].st_value, (unsigned long)paSymbols[2].st_value); + else + printk(KERN_ERR "vboxdrv: failed to find fake module (pTestMod=%p, pTestModByName=%p, pMyMod=%p, fIsModText=%d)\n", + pTestMod, pTestModByName, pMyMod, fIsModText); + } + else + RTMemFree(pMyMod); + } + + IPRT_LINUX_RESTORE_EFL_AC(); +#else + pImage->pLnxModHack = NULL; +#endif + NOREF(pDevExt); NOREF(pImage); +} + + +void VBOXCALL supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) +{ +#ifdef VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS /* Not for production use!! Debugging only! */ + struct module *pMyMod = pImage->pLnxModHack; + pImage->pLnxModHack = NULL; + if (pMyMod) + { + /* + * Remove the fake module list entry and free it. + */ + IPRT_LINUX_SAVE_EFL_AC(); + mutex_lock(&module_mutex); + list_del_rcu(&pMyMod->list); +# ifdef CONFIG_MODULES_TREE_LOOKUP + g_pfnModTreeRemove(&pMyMod->mtn_core); +# endif + synchronize_sched(); + mutex_unlock(&module_mutex); + +# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) + free_percpu(pMyMod->refptr); +# endif + RTMemFree(pMyMod); + IPRT_LINUX_RESTORE_EFL_AC(); + } + +#else + Assert(pImage->pLnxModHack == NULL); +#endif + NOREF(pDevExt); NOREF(pImage); +} + + +int VBOXCALL supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, + const char *pszSymbol, size_t cchSymbol, void **ppvSymbol) +{ +#ifdef VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS +# error "implement me!" +#endif + RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol); + return VERR_WRONG_ORDER; +} + + +#ifdef SUPDRV_WITH_MSR_PROBER + +int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue) +{ +# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API + uint32_t u32Low, u32High; + int rc; + + IPRT_LINUX_SAVE_EFL_AC(); + if (idCpu == NIL_RTCPUID) + rc = rdmsr_safe(uMsr, &u32Low, &u32High); + else if (RTMpIsCpuOnline(idCpu)) + rc = rdmsr_safe_on_cpu(idCpu, uMsr, &u32Low, &u32High); + else + return VERR_CPU_OFFLINE; + IPRT_LINUX_RESTORE_EFL_AC(); + if (rc == 0) + { + *puValue = RT_MAKE_U64(u32Low, u32High); + return VINF_SUCCESS; + } + return VERR_ACCESS_DENIED; +# else + return VERR_NOT_SUPPORTED; +# endif +} + + +int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue) +{ +# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API + int rc; + + IPRT_LINUX_SAVE_EFL_AC(); + if (idCpu == NIL_RTCPUID) + rc = wrmsr_safe(uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue)); + else if (RTMpIsCpuOnline(idCpu)) + rc = wrmsr_safe_on_cpu(idCpu, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue)); + else + return VERR_CPU_OFFLINE; + IPRT_LINUX_RESTORE_EFL_AC(); + + if (rc == 0) + return VINF_SUCCESS; + return VERR_ACCESS_DENIED; +# else + return VERR_NOT_SUPPORTED; +# endif +} + +# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API +/** + * Worker for supdrvOSMsrProberModify. + */ +static DECLCALLBACK(void) supdrvLnxMsrProberModifyOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2) +{ + PSUPMSRPROBER pReq = (PSUPMSRPROBER)pvUser1; + register uint32_t uMsr = pReq->u.In.uMsr; + bool const fFaster = pReq->u.In.enmOp == SUPMSRPROBEROP_MODIFY_FASTER; + uint64_t uBefore; + uint64_t uWritten; + uint64_t uAfter; + int rcBefore, rcWrite, rcAfter, rcRestore; + RTCCUINTREG fOldFlags; + + /* Initialize result variables. */ + uBefore = uWritten = uAfter = 0; + rcWrite = rcAfter = rcRestore = -EIO; + + /* + * Do the job. + */ + fOldFlags = ASMIntDisableFlags(); + ASMCompilerBarrier(); /* paranoia */ + if (!fFaster) + ASMWriteBackAndInvalidateCaches(); + + rcBefore = rdmsrl_safe(uMsr, &uBefore); + if (rcBefore >= 0) + { + register uint64_t uRestore = uBefore; + uWritten = uRestore; + uWritten &= pReq->u.In.uArgs.Modify.fAndMask; + uWritten |= pReq->u.In.uArgs.Modify.fOrMask; + + rcWrite = wrmsr_safe(uMsr, RT_LODWORD(uWritten), RT_HIDWORD(uWritten)); + rcAfter = rdmsrl_safe(uMsr, &uAfter); + rcRestore = wrmsr_safe(uMsr, RT_LODWORD(uRestore), RT_HIDWORD(uRestore)); + + if (!fFaster) + { + ASMWriteBackAndInvalidateCaches(); + ASMReloadCR3(); + ASMNopPause(); + } + } + + ASMCompilerBarrier(); /* paranoia */ + ASMSetFlags(fOldFlags); + + /* + * Write out the results. + */ + pReq->u.Out.uResults.Modify.uBefore = uBefore; + pReq->u.Out.uResults.Modify.uWritten = uWritten; + pReq->u.Out.uResults.Modify.uAfter = uAfter; + pReq->u.Out.uResults.Modify.fBeforeGp = rcBefore != 0; + pReq->u.Out.uResults.Modify.fModifyGp = rcWrite != 0; + pReq->u.Out.uResults.Modify.fAfterGp = rcAfter != 0; + pReq->u.Out.uResults.Modify.fRestoreGp = rcRestore != 0; + RT_ZERO(pReq->u.Out.uResults.Modify.afReserved); +} +# endif + + +int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq) +{ +# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API + if (idCpu == NIL_RTCPUID) + { + supdrvLnxMsrProberModifyOnCpu(idCpu, pReq, NULL); + return VINF_SUCCESS; + } + return RTMpOnSpecific(idCpu, supdrvLnxMsrProberModifyOnCpu, pReq, NULL); +# else + return VERR_NOT_SUPPORTED; +# endif +} + +#endif /* SUPDRV_WITH_MSR_PROBER */ + + +/** + * Converts a supdrv error code to an linux error code. + * + * @returns corresponding linux error code. + * @param rc IPRT status code. + */ +static int VBoxDrvLinuxErr2LinuxErr(int rc) +{ + switch (rc) + { + case VINF_SUCCESS: return 0; + case VERR_GENERAL_FAILURE: return -EACCES; + case VERR_INVALID_PARAMETER: return -EINVAL; + case VERR_INVALID_MAGIC: return -EILSEQ; + case VERR_INVALID_HANDLE: return -ENXIO; + case VERR_INVALID_POINTER: return -EFAULT; + case VERR_LOCK_FAILED: return -ENOLCK; + case VERR_ALREADY_LOADED: return -EEXIST; + case VERR_PERMISSION_DENIED: return -EPERM; + case VERR_VERSION_MISMATCH: return -ENOSYS; + case VERR_IDT_FAILED: return -1000; + } + + return -EPERM; +} + + +RTDECL(int) SUPR0Printf(const char *pszFormat, ...) +{ + va_list va; + char szMsg[512]; + IPRT_LINUX_SAVE_EFL_AC(); + + va_start(va, pszFormat); + RTStrPrintfV(szMsg, sizeof(szMsg) - 1, pszFormat, va); + va_end(va); + szMsg[sizeof(szMsg) - 1] = '\0'; + + printk("%s", szMsg); + + IPRT_LINUX_RESTORE_EFL_AC(); + return 0; +} + + +SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void) +{ + uint32_t fFlags = 0; +#ifdef CONFIG_PAX_KERNEXEC + fFlags |= SUPKERNELFEATURES_GDT_READ_ONLY; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + fFlags |= SUPKERNELFEATURES_GDT_NEED_WRITABLE; +#endif +#if defined(VBOX_STRICT) || defined(VBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV) + fFlags |= SUPKERNELFEATURES_SMAP; +#elif defined(CONFIG_X86_SMAP) + if (ASMGetCR4() & X86_CR4_SMAP) + fFlags |= SUPKERNELFEATURES_SMAP; +#endif + return fFlags; +} + + +int VBOXCALL supdrvOSGetCurrentGdtRw(RTHCUINTPTR *pGdtRw) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + *pGdtRw = (RTHCUINTPTR)get_current_gdt_rw(); + return VINF_SUCCESS; +#else + return VERR_NOT_IMPLEMENTED; +#endif +} + + +module_init(VBoxDrvLinuxInit); +module_exit(VBoxDrvLinuxUnload); + +MODULE_AUTHOR(VBOX_VENDOR); +MODULE_DESCRIPTION(VBOX_PRODUCT " Support Driver"); +MODULE_LICENSE("GPL"); +#ifdef MODULE_VERSION +MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV) " (" RT_XSTR(SUPDRV_IOC_VERSION) ")"); +#endif + +module_param(force_async_tsc, int, 0444); +MODULE_PARM_DESC(force_async_tsc, "force the asynchronous TSC mode"); + diff --git a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.mod.c b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.mod.c new file mode 100644 index 00000000..284c595d --- /dev/null +++ b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.mod.c @@ -0,0 +1,87 @@ +/* $Id: SUPDrv-linux.mod.c $ */ +/** @file + * VBoxDrv - The VirtualBox Support Driver - Autogenerated Linux code. + * + * This is checked in to assist syntax checking the module. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +#include "SUPDrvInternal.h" /* for KBUILD_STR */ +#include "the-linux-kernel.h" +#include <linux/vermagic.h> + +MODULE_INFO(vermagic, VERMAGIC_STRING); + +#undef unix +struct module __this_module +__attribute__((section(".gnu.linkonce.this_module"))) = { + .name = __stringify(KBUILD_MODNAME), + .init = init_module, +#ifdef CONFIG_MODULE_UNLOAD + .exit = cleanup_module, +#endif +}; + +static const struct modversion_info ____versions[] +__attribute_used__ +__attribute__((section("__versions"))) = { + { 0, "cleanup_module" }, + { 0, "init_module" }, + { 0, "struct_module" }, + { 0, "strpbrk" }, + { 0, "__kmalloc" }, + { 0, "mem_map" }, + { 0, "vmalloc" }, + { 0, "malloc_sizes" }, + { 0, "vfree" }, + { 0, "change_page_attr" }, + { 0, "__might_sleep" }, + { 0, "remap_page_range" }, + { 0, "__alloc_pages" }, + { 0, "printk" }, + { 0, "__PAGE_KERNEL" }, + { 0, "rwsem_wake" }, + { 0, "copy_to_user" }, + { 0, "preempt_schedule" }, + { 0, "contig_page_data" }, + { 0, "do_mmap_pgoff" }, + { 0, "find_vma" }, + { 0, "kmem_cache_alloc" }, + { 0, "__free_pages" }, + { 0, "do_munmap" }, + { 0, "get_user_pages" }, + { 0, "vsnprintf" }, + { 0, "kfree" }, + { 0, "memcpy" }, + { 0, "put_page" }, + { 0, "__up_wakeup" }, + { 0, "__down_failed" }, + { 0, "copy_from_user" }, + { 0, "rwsem_down_read_failed" }, +}; + +static const char __module_depends[] +__attribute_used__ +__attribute__((section(".modinfo"))) = +"depends="; + diff --git a/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp b/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp new file mode 100644 index 00000000..37ee18a9 --- /dev/null +++ b/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp @@ -0,0 +1,309 @@ +/* $Id: SUPLib-linux.cpp $ */ +/** @file + * VirtualBox Support Library - GNU/Linux specific parts. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_SUP +#ifdef IN_SUP_HARDENED_R3 +# undef DEBUG /* Warning: disables RT_STRICT */ +# undef RT_STRICT +# ifndef LOG_DISABLED +# define LOG_DISABLED +# endif +# define RTLOG_REL_DISABLED +# include <iprt/log.h> +#endif + +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <malloc.h> + +#include <VBox/log.h> +#include <VBox/sup.h> +#include <iprt/path.h> +#include <iprt/assert.h> +#include <VBox/types.h> +#include <iprt/string.h> +#include <iprt/system.h> +#include <VBox/err.h> +#include <VBox/param.h> +#include "../SUPLibInternal.h" +#include "../SUPDrvIOC.h" + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/** System device name. */ +#define DEVICE_NAME_SYS "/dev/vboxdrv" +/** User device name. */ +#define DEVICE_NAME_USR "/dev/vboxdrvu" + +/* define MADV_DONTFORK if it's missing from the system headers. */ +#ifndef MADV_DONTFORK +# define MADV_DONTFORK 10 +#endif + + + +int suplibOsInit(PSUPLIBDATA pThis, bool fPreInited, bool fUnrestricted, SUPINITOP *penmWhat, PRTERRINFO pErrInfo) +{ + RT_NOREF2(penmWhat, pErrInfo); + + /* + * Nothing to do if pre-inited. + */ + if (fPreInited) + return VINF_SUCCESS; + Assert(pThis->hDevice == (intptr_t)NIL_RTFILE); + + /* + * Check if madvise works. + */ + void *pv = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (pv == MAP_FAILED) + return VERR_NO_MEMORY; + pThis->fSysMadviseWorks = (0 == madvise(pv, PAGE_SIZE, MADV_DONTFORK)); + munmap(pv, PAGE_SIZE); + + /* + * Try open the device. + */ + const char *pszDeviceNm = fUnrestricted ? DEVICE_NAME_SYS : DEVICE_NAME_USR; + int hDevice = open(pszDeviceNm, O_RDWR, 0); + if (hDevice < 0) + { + /* + * Try load the device. + */ + hDevice = open(pszDeviceNm, O_RDWR, 0); + if (hDevice < 0) + { + int rc; + switch (errno) + { + case ENXIO: /* see man 2 open, ENODEV is actually a kernel bug */ + case ENODEV: rc = VERR_VM_DRIVER_LOAD_ERROR; break; + case EPERM: + case EACCES: rc = VERR_VM_DRIVER_NOT_ACCESSIBLE; break; + case ENOENT: rc = VERR_VM_DRIVER_NOT_INSTALLED; break; + default: rc = VERR_VM_DRIVER_OPEN_ERROR; break; + } + LogRel(("Failed to open \"%s\", errno=%d, rc=%Rrc\n", pszDeviceNm, errno, rc)); + return rc; + } + } + + /* + * Mark the file handle close on exec. + */ + if (fcntl(hDevice, F_SETFD, FD_CLOEXEC) == -1) + { + close(hDevice); +#ifdef IN_SUP_HARDENED_R3 + return VERR_INTERNAL_ERROR; +#else + return RTErrConvertFromErrno(errno); +#endif + } + + /* + * We're done. + */ + pThis->hDevice = hDevice; + pThis->fUnrestricted = fUnrestricted; + return VINF_SUCCESS; +} + + +int suplibOsTerm(PSUPLIBDATA pThis) +{ + /* + * Close the device if it's actually open. + */ + if (pThis->hDevice != (intptr_t)NIL_RTFILE) + { + if (close(pThis->hDevice)) + AssertFailed(); + pThis->hDevice = (intptr_t)NIL_RTFILE; + } + + return 0; +} + + +#ifndef IN_SUP_HARDENED_R3 + +int suplibOsInstall(void) +{ + // nothing to do on Linux + return VERR_NOT_IMPLEMENTED; +} + + +int suplibOsUninstall(void) +{ + // nothing to do on Linux + return VERR_NOT_IMPLEMENTED; +} + + +int suplibOsIOCtl(PSUPLIBDATA pThis, uintptr_t uFunction, void *pvReq, size_t cbReq) +{ + AssertMsg(pThis->hDevice != (intptr_t)NIL_RTFILE, ("SUPLIB not initiated successfully!\n")); + NOREF(cbReq); + + /* + * Issue device iocontrol. + */ + if (RT_LIKELY(ioctl(pThis->hDevice, uFunction, pvReq) >= 0)) + return VINF_SUCCESS; + + /* This is the reverse operation of the one found in SUPDrv-linux.c */ + switch (errno) + { + case EACCES: return VERR_GENERAL_FAILURE; + case EINVAL: return VERR_INVALID_PARAMETER; + case EILSEQ: return VERR_INVALID_MAGIC; + case ENXIO: return VERR_INVALID_HANDLE; + case EFAULT: return VERR_INVALID_POINTER; + case ENOLCK: return VERR_LOCK_FAILED; + case EEXIST: return VERR_ALREADY_LOADED; + case EPERM: return VERR_PERMISSION_DENIED; + case ENOSYS: return VERR_VERSION_MISMATCH; + case 1000: return VERR_IDT_FAILED; + } + + return RTErrConvertFromErrno(errno); +} + + +int suplibOsIOCtlFast(PSUPLIBDATA pThis, uintptr_t uFunction, uintptr_t idCpu) +{ + int rc = ioctl(pThis->hDevice, uFunction, idCpu); + if (rc == -1) + rc = -errno; + return rc; +} + + +int suplibOsPageAlloc(PSUPLIBDATA pThis, size_t cPages, void **ppvPages) +{ + size_t cbMmap = (pThis->fSysMadviseWorks ? cPages : cPages + 2) << PAGE_SHIFT; + char *pvPages = (char *)mmap(NULL, cbMmap, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (pvPages == MAP_FAILED) + return VERR_NO_MEMORY; + + if (pThis->fSysMadviseWorks) + { + /* + * It is not fatal if we fail here but a forked child (e.g. the ALSA sound server) + * could crash. Linux < 2.6.16 does not implement madvise(MADV_DONTFORK) but the + * kernel seems to split bigger VMAs and that is all that we want -- later we set the + * VM_DONTCOPY attribute in supdrvOSLockMemOne(). + */ + if (madvise (pvPages, cbMmap, MADV_DONTFORK)) + LogRel(("SUPLib: madvise %p-%p failed\n", pvPages, cbMmap)); + *ppvPages = pvPages; + } + else + { + /* + * madvise(MADV_DONTFORK) is not available (most probably Linux 2.4). Enclose any + * mmapped region by two unmapped pages to guarantee that there is exactly one VM + * area struct of the very same size as the mmap area. + */ + mprotect(pvPages, PAGE_SIZE, PROT_NONE); + mprotect(pvPages + cbMmap - PAGE_SIZE, PAGE_SIZE, PROT_NONE); + *ppvPages = pvPages + PAGE_SIZE; + } + memset(*ppvPages, 0, cPages << PAGE_SHIFT); + return VINF_SUCCESS; +} + + +int suplibOsPageFree(PSUPLIBDATA pThis, void *pvPages, size_t cPages) +{ + NOREF(pThis); + munmap(pvPages, cPages << PAGE_SHIFT); + return VINF_SUCCESS; +} + + +/** + * Check if the host kernel supports VT-x or not. + * + * Older Linux kernels clear the VMXE bit in the CR4 register (function + * tlb_flush_all()) leading to a host kernel panic. + * + * @returns VBox status code (no info). + * @param ppszWhy Where to return explanatory message. + */ +int suplibOsQueryVTxSupported(const char **ppszWhy) +{ + char szBuf[256]; + int rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szBuf, sizeof(szBuf)); + if (RT_SUCCESS(rc)) + { + char *pszNext; + uint32_t uA, uB, uC; + + rc = RTStrToUInt32Ex(szBuf, &pszNext, 10, &uA); + if ( RT_SUCCESS(rc) + && *pszNext == '.') + { + /* + * new version number scheme starting with Linux 3.0 + */ + if (uA >= 3) + return VINF_SUCCESS; + rc = RTStrToUInt32Ex(pszNext+1, &pszNext, 10, &uB); + if ( RT_SUCCESS(rc) + && *pszNext == '.') + { + rc = RTStrToUInt32Ex(pszNext+1, &pszNext, 10, &uC); + if (RT_SUCCESS(rc)) + { + uint32_t uLinuxVersion = (uA << 16) + (uB << 8) + uC; + if (uLinuxVersion >= (2 << 16) + (6 << 8) + 13) + return VINF_SUCCESS; + } + } + } + } + + *ppszWhy = "Linux 2.6.13 or newer required!"; + return VERR_SUPDRV_KERNEL_TOO_OLD_FOR_VTX; +} + +#endif /* !IN_SUP_HARDENED_R3 */ + diff --git a/src/VBox/HostDrivers/Support/linux/SUPR0IdcClient-linux.c b/src/VBox/HostDrivers/Support/linux/SUPR0IdcClient-linux.c new file mode 100644 index 00000000..9dc8412c --- /dev/null +++ b/src/VBox/HostDrivers/Support/linux/SUPR0IdcClient-linux.c @@ -0,0 +1,56 @@ +/* $Id: SUPR0IdcClient-linux.c $ */ +/** @file + * VirtualBox Support Driver - IDC Client Lib, Linux Specific Code. + */ + +/* + * Copyright (C) 2008-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "../SUPR0IdcClientInternal.h" +#include <iprt/errcore.h> + + +int VBOXCALL supR0IdcNativeOpen(PSUPDRVIDCHANDLE pHandle, PSUPDRVIDCREQCONNECT pReq) +{ + return supR0IdcNativeCall(pHandle, SUPDRV_IDC_REQ_CONNECT, &pReq->Hdr); +} + + +int VBOXCALL supR0IdcNativeClose(PSUPDRVIDCHANDLE pHandle, PSUPDRVIDCREQHDR pReq) +{ + return supR0IdcNativeCall(pHandle, SUPDRV_IDC_REQ_DISCONNECT, pReq); +} + + +int VBOXCALL supR0IdcNativeCall(PSUPDRVIDCHANDLE pHandle, uint32_t iReq, PSUPDRVIDCREQHDR pReq) +{ + int rc = SUPDrvLinuxIDC(iReq, pReq); + if (RT_SUCCESS(rc)) + rc = pReq->rc; + + NOREF(pHandle); + return rc; +} + diff --git a/src/VBox/HostDrivers/Support/linux/files_vboxdrv b/src/VBox/HostDrivers/Support/linux/files_vboxdrv new file mode 100755 index 00000000..9e7f57c9 --- /dev/null +++ b/src/VBox/HostDrivers/Support/linux/files_vboxdrv @@ -0,0 +1,218 @@ +#!/bin/sh +# $Id: files_vboxdrv $ +## @file +# Shared file between Makefile.kmk and export_modules.sh. +# + +# +# Copyright (C) 2007-2019 Oracle Corporation +# +# This file is part of VirtualBox Open Source Edition (OSE), as +# available from http://www.virtualbox.org. This file is free software; +# you can redistribute it and/or modify it under the terms of the GNU +# General Public License (GPL) as published by the Free Software +# Foundation, in version 2 as it comes in the "COPYING" file of the +# VirtualBox OSE distribution. VirtualBox OSE is distributed in the +# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL) only, as it comes in the "COPYING.CDDL" file of the +# VirtualBox OSE distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# + +FILES_VBOXDRV_NOBIN=" \ + ${PATH_ROOT}/include/iprt/alloc.h=>include/iprt/alloc.h \ + ${PATH_ROOT}/include/iprt/asm.h=>include/iprt/asm.h \ + ${PATH_ROOT}/include/iprt/asm-amd64-x86.h=>include/iprt/asm-amd64-x86.h \ + ${PATH_ROOT}/include/iprt/asm-math.h=>include/iprt/asm-math.h \ + ${PATH_ROOT}/include/iprt/assert.h=>include/iprt/assert.h \ + ${PATH_ROOT}/include/iprt/assertcompile.h=>include/iprt/assertcompile.h \ + ${PATH_ROOT}/include/iprt/avl.h=>include/iprt/avl.h \ + ${PATH_ROOT}/include/iprt/cdefs.h=>include/iprt/cdefs.h \ + ${PATH_ROOT}/include/iprt/cpuset.h=>include/iprt/cpuset.h \ + ${PATH_ROOT}/include/iprt/crc.h=>include/iprt/crc.h \ + ${PATH_ROOT}/include/iprt/ctype.h=>include/iprt/ctype.h \ + ${PATH_ROOT}/include/iprt/err.h=>include/iprt/err.h \ + ${PATH_ROOT}/include/iprt/errcore.h=>include/iprt/errcore.h \ + ${PATH_ROOT}/include/iprt/errno.h=>include/iprt/errno.h \ + ${PATH_ROOT}/include/iprt/heap.h=>include/iprt/heap.h \ + ${PATH_ROOT}/include/iprt/handletable.h=>include/iprt/handletable.h \ + ${PATH_ROOT}/include/iprt/initterm.h=>include/iprt/initterm.h \ + ${PATH_ROOT}/include/iprt/latin1.h=>include/iprt/latin1.h \ + ${PATH_ROOT}/include/iprt/list.h=>include/iprt/list.h \ + ${PATH_ROOT}/include/iprt/lockvalidator.h=>include/iprt/lockvalidator.h \ + ${PATH_ROOT}/include/iprt/log.h=>include/iprt/log.h \ + ${PATH_ROOT}/include/iprt/mangling.h=>include/iprt/mangling.h \ + ${PATH_ROOT}/include/iprt/mem.h=>include/iprt/mem.h \ + ${PATH_ROOT}/include/iprt/memobj.h=>include/iprt/memobj.h \ + ${PATH_ROOT}/include/iprt/mp.h=>include/iprt/mp.h \ + ${PATH_ROOT}/include/iprt/net.h=>include/iprt/net.h \ + ${PATH_ROOT}/include/iprt/param.h=>include/iprt/param.h \ + ${PATH_ROOT}/include/iprt/path.h=>include/iprt/path.h \ + ${PATH_ROOT}/include/iprt/power.h=>include/iprt/power.h \ + ${PATH_ROOT}/include/iprt/process.h=>include/iprt/process.h \ + ${PATH_ROOT}/include/iprt/rand.h=>include/iprt/rand.h \ + ${PATH_ROOT}/include/iprt/semaphore.h=>include/iprt/semaphore.h \ + ${PATH_ROOT}/include/iprt/spinlock.h=>include/iprt/spinlock.h \ + ${PATH_ROOT}/include/iprt/stdarg.h=>include/iprt/stdarg.h \ + ${PATH_ROOT}/include/iprt/stdint.h=>include/iprt/stdint.h \ + ${PATH_ROOT}/include/iprt/string.h=>include/iprt/string.h \ + ${PATH_ROOT}/include/iprt/thread.h=>include/iprt/thread.h \ + ${PATH_ROOT}/include/iprt/time.h=>include/iprt/time.h \ + ${PATH_ROOT}/include/iprt/timer.h=>include/iprt/timer.h \ + ${PATH_ROOT}/include/iprt/types.h=>include/iprt/types.h \ + ${PATH_ROOT}/include/iprt/uint128.h=>include/iprt/uint128.h \ + ${PATH_ROOT}/include/iprt/uint64.h=>include/iprt/uint64.h \ + ${PATH_ROOT}/include/iprt/uni.h=>include/iprt/uni.h \ + ${PATH_ROOT}/include/iprt/utf16.h=>include/iprt/utf16.h \ + ${PATH_ROOT}/include/iprt/uuid.h=>include/iprt/uuid.h \ + ${PATH_ROOT}/include/iprt/x86.h=>include/iprt/x86.h \ + ${PATH_ROOT}/include/iprt/nocrt/limits.h=>include/iprt/nocrt/limits.h \ + ${PATH_ROOT}/include/VBox/cdefs.h=>include/VBox/cdefs.h \ + ${PATH_ROOT}/include/VBox/err.h=>include/VBox/err.h \ + ${PATH_ROOT}/include/VBox/log.h=>include/VBox/log.h \ + ${PATH_ROOT}/include/VBox/param.h=>include/VBox/param.h \ + ${PATH_ROOT}/include/VBox/sup.h=>include/VBox/sup.h \ + ${PATH_ROOT}/include/VBox/types.h=>include/VBox/types.h \ + ${PATH_ROOT}/include/VBox/SUPDrvMangling.h=>include/VBox/SUPDrvMangling.h \ + ${PATH_ROOT}/include/VBox/VBoxTpG.h=>include/VBox/VBoxTpG.h \ + ${PATH_ROOT}/include/VBox/vmm/hm_vmx.h=>include/VBox/vmm/hm_vmx.h \ + ${PATH_ROOT}/include/VBox/vmm/hm_svm.h=>include/VBox/vmm/hm_svm.h \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c=>linux/SUPDrv-linux.c \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrv.cpp=>SUPDrv.c \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvGip.cpp=>SUPDrvGip.c \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvSem.cpp=>SUPDrvSem.c \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp=>SUPDrvTracer.c \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrv-dtrace.cpp=>SUPDrvDTrace.c \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvIDC.h=>SUPDrvIDC.h \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvIOC.h=>SUPDrvIOC.h \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPDrvInternal.h=>SUPDrvInternal.h \ + ${PATH_ROOT}/src/VBox/HostDrivers/Support/SUPLibAll.cpp=>SUPLibAll.c \ + ${PATH_ROOT}/src/VBox/Installer/linux/Makefile.include.footer=>Makefile.include.footer \ + ${PATH_ROOT}/src/VBox/Installer/linux/Makefile.include.header=>Makefile.include.header \ + ${PATH_ROOT}/src/VBox/Runtime/common/alloc/alloc.cpp=>common/alloc/alloc.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/alloc/heapsimple.cpp=>common/alloc/heapsimple.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/checksum/crc32.cpp=>common/checksum/crc32.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/checksum/ipv4.cpp=>common/checksum/ipv4.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/checksum/ipv6.cpp=>common/checksum/ipv6.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/err/RTErrConvertFromErrno.cpp=>common/err/RTErrConvertFromErrno.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/err/RTErrConvertToErrno.cpp=>common/err/RTErrConvertToErrno.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/err/errinfo.cpp=>common/err/errinfo.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/log/log.cpp=>common/log/log.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/log/logellipsis.cpp=>common/log/logellipsis.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/log/logrel.cpp=>common/log/logrel.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/log/logrelellipsis.cpp=>common/log/logrelellipsis.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/log/logcom.cpp=>common/log/logcom.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/log/logformat.cpp=>common/log/logformat.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/divdi3.c=>math/gcc/divdi3.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/moddi3.c=>math/gcc/moddi3.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/qdivrem.c=>math/gcc/qdivrem.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/quad.h=>math/gcc/quad.h \ + ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivdi3.c=>math/gcc/udivdi3.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/udivmoddi4.c=>math/gcc/udivmoddi4.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/math/gcc/umoddi3.c=>math/gcc/umoddi3.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg1Weak.cpp=>common/misc/RTAssertMsg1Weak.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg2.cpp=>common/misc/RTAssertMsg2.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg2Add.cpp=>common/misc/RTAssertMsg2Add.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg2AddWeak.cpp=>common/misc/RTAssertMsg2AddWeak.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg2AddWeakV.cpp=>common/misc/RTAssertMsg2AddWeakV.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg2Weak.cpp=>common/misc/RTAssertMsg2Weak.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/RTAssertMsg2WeakV.cpp=>common/misc/RTAssertMsg2WeakV.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/assert.cpp=>common/misc/assert.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/handletable.cpp=>common/misc/handletable.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/handletable.h=>common/misc/handletable.h \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/handletablectx.cpp=>common/misc/handletablectx.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/misc/thread.cpp=>common/misc/thread.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCat.cpp=>common/string/RTStrCat.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopy.cpp=>common/string/RTStrCopy.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopyEx.cpp=>common/string/RTStrCopyEx.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrCopyP.cpp=>common/string/RTStrCopyP.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrNCmp.cpp=>common/string/RTStrNCmp.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/RTStrNLen.cpp=>common/string/RTStrNLen.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/stringalloc.cpp=>common/string/stringalloc.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/strformat.cpp=>common/string/strformat.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/strformatnum.cpp=>common/string/strformatnum.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/strformatrt.cpp=>common/string/strformatrt.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/strformattype.cpp=>common/string/strformattype.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/strprintf.cpp=>common/string/strprintf.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/string/strtonum.cpp=>common/string/strtonum.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/table/avlpv.cpp=>common/table/avlpv.c \ + ${PATH_ROOT}/src/VBox/Runtime/common/table/avl_Base.cpp.h=>common/table/avl_Base.cpp.h \ + ${PATH_ROOT}/src/VBox/Runtime/common/table/avl_Get.cpp.h=>common/table/avl_Get.cpp.h \ + ${PATH_ROOT}/src/VBox/Runtime/common/table/avl_GetBestFit.cpp.h=>common/table/avl_GetBestFit.cpp.h \ + ${PATH_ROOT}/src/VBox/Runtime/common/table/avl_RemoveBestFit.cpp.h=>common/table/avl_RemoveBestFit.cpp.h \ + ${PATH_ROOT}/src/VBox/Runtime/common/table/avl_DoWithAll.cpp.h=>common/table/avl_DoWithAll.cpp.h \ + ${PATH_ROOT}/src/VBox/Runtime/common/table/avl_Destroy.cpp.h=>common/table/avl_Destroy.cpp.h \ + ${PATH_ROOT}/src/VBox/Runtime/common/time/time.cpp=>common/time/time.c \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/assert.h=>include/internal/assert.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/initterm.h=>include/internal/initterm.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/iprt.h=>include/internal/iprt.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/lockvalidator.h=>include/internal/lockvalidator.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/magics.h=>include/internal/magics.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/mem.h=>include/internal/mem.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/memobj.h=>include/internal/memobj.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/string.h=>include/internal/string.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/sched.h=>include/internal/sched.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/process.h=>include/internal/process.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/thread.h=>include/internal/thread.h \ + ${PATH_ROOT}/src/VBox/Runtime/include/internal/time.h=>include/internal/time.h \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTAssertShouldPanic-generic.cpp=>generic/RTAssertShouldPanic-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTLogWriteStdErr-stub-generic.cpp=>generic/RTLogWriteStdErr-stub-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTLogWriteStdOut-stub-generic.cpp=>generic/RTLogWriteStdOut-stub-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTLogWriteUser-generic.cpp=>generic/RTLogWriteUser-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpGetArraySize-generic.cpp=>generic/RTMpGetArraySize-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTMpGetCoreCount-generic.cpp=>generic/RTMpGetCoreCount-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventWait-2-ex-generic.cpp=>generic/RTSemEventWait-2-ex-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventWaitNoResume-2-ex-generic.cpp=>generic/RTSemEventWaitNoResume-2-ex-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventMultiWait-2-ex-generic.cpp=>generic/RTSemEventMultiWait-2-ex-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp=>generic/RTSemEventMultiWaitNoResume-2-ex-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/RTTimerCreate-generic.cpp=>generic/RTTimerCreate-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/errvars-generic.cpp=>generic/errvars-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/mppresent-generic.cpp=>generic/mppresent-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/generic/uuid-generic.cpp=>generic/uuid-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.cpp=>r0drv/alloc-r0drv.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/alloc-r0drv.h=>r0drv/alloc-r0drv.h \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/initterm-r0drv.cpp=>r0drv/initterm-r0drv.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/mp-r0drv.h=>r0drv/mp-r0drv.h \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/mpnotification-r0drv.c=>r0drv/mpnotification-r0drv.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/power-r0drv.h=>r0drv/power-r0drv.h \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/powernotification-r0drv.c=>r0drv/powernotification-r0drv.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/rtStrFormatKernelAddress-r0drv-linux.c=>r0drv/linux/rtStrFormatKernelAddress-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c=>r0drv/linux/RTLogWriteDebugger-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/assert-r0drv-linux.c=>r0drv/linux/assert-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c=>r0drv/linux/alloc-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/initterm-r0drv-linux.c=>r0drv/linux/initterm-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c=>r0drv/linux/memobj-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/memuserkernel-r0drv-linux.c=>r0drv/linux/memuserkernel-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c=>r0drv/linux/mp-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/mpnotification-r0drv-linux.c=>r0drv/linux/mpnotification-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/process-r0drv-linux.c=>r0drv/linux/process-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c=>r0drv/linux/semevent-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c=>r0drv/linux/semeventmulti-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/semfastmutex-r0drv-linux.c=>r0drv/linux/semfastmutex-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/semmutex-r0drv-linux.c=>r0drv/linux/semmutex-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/spinlock-r0drv-linux.c=>r0drv/linux/spinlock-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/string.h=>r0drv/linux/string.h \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h=>r0drv/linux/the-linux-kernel.h \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/thread-r0drv-linux.c=>r0drv/linux/thread-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c=>r0drv/linux/thread2-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c=>r0drv/linux/threadctxhooks-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c=>r0drv/linux/time-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c=>r0drv/linux/timer-r0drv-linux.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h=>r0drv/linux/waitqueue-r0drv-linux.h \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/semspinmutex-r0drv-generic.c=>r0drv/generic/semspinmutex-r0drv-generic.c \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp=>r0drv/generic/threadctxhooks-r0drv-generic.cpp \ + ${PATH_ROOT}/src/VBox/Runtime/r0drv/memobj-r0drv.cpp=>r0drv/memobj-r0drv.c \ + ${PATH_ROOT}/src/VBox/Runtime/VBox/log-vbox.cpp=>VBox/log-vbox.c \ + ${PATH_OUT}/version-generated.h=>version-generated.h \ + ${PATH_OUT}/revision-generated.h=>revision-generated.h \ + ${PATH_OUT}/product-generated.h=>product-generated.h \ +" + +FILES_VBOXDRV_BIN=" \ +" |