VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c@ 55435

Last change on this file since 55435 was 55435, checked in by vboxsync, 10 years ago

Bad commit, reverted with following changeset

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.9 KB
Line 
1/* $Rev: 55435 $ */
2/** @file
3 * VBoxDrv - The VirtualBox Support Driver - Linux specifics.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#define LOG_GROUP LOG_GROUP_SUP_DRV
31#include "../SUPDrvInternal.h"
32#include "the-linux-kernel.h"
33#include "version-generated.h"
34#include "product-generated.h"
35
36#include <iprt/assert.h>
37#include <iprt/spinlock.h>
38#include <iprt/semaphore.h>
39#include <iprt/initterm.h>
40#include <iprt/process.h>
41#include <VBox/err.h>
42#include <iprt/mem.h>
43#include <VBox/log.h>
44#include <iprt/mp.h>
45
46/** @todo figure out the exact version number */
47#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
48# include <iprt/power.h>
49# define VBOX_WITH_SUSPEND_NOTIFICATION
50# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
51# define VBOX_WITH_PRE_SUSPEND_NOTIFICATION
52# endif
53#endif
54
55#include <linux/sched.h>
56#ifdef CONFIG_DEVFS_FS
57# include <linux/devfs_fs_kernel.h>
58#endif
59#ifdef CONFIG_VBOXDRV_AS_MISC
60# include <linux/miscdevice.h>
61#endif
62#ifdef VBOX_WITH_SUSPEND_NOTIFICATION
63# include <linux/platform_device.h>
64#endif
65#ifdef VBOX_WITH_PRE_SUSPEND_NOTIFICATION
66# include <linux/suspend.h>
67# include <linux/notifier.h>
68#endif
69#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) && defined(SUPDRV_WITH_MSR_PROBER)
70# define SUPDRV_LINUX_HAS_SAFE_MSR_API
71# include <asm/msr.h>
72#endif
73#include <iprt/asm-amd64-x86.h>
74
75
76
77/*******************************************************************************
78* Defined Constants And Macros *
79*******************************************************************************/
80/* check kernel version */
81# ifndef SUPDRV_AGNOSTIC
82# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
83# error Unsupported kernel version!
84# endif
85# endif
86
87/* devfs defines */
88#if defined(CONFIG_DEVFS_FS) && !defined(CONFIG_VBOXDRV_AS_MISC)
89# ifdef VBOX_WITH_HARDENING
90# define VBOX_DEV_FMASK (S_IWUSR | S_IRUSR)
91# else
92# define VBOX_DEV_FMASK (S_IRUGO | S_IWUGO)
93# endif
94#endif /* CONFIG_DEV_FS && !CONFIG_VBOXDEV_AS_MISC */
95
96#ifdef CONFIG_X86_HIGH_ENTRY
97# error "CONFIG_X86_HIGH_ENTRY is not supported by VBoxDrv at this time."
98#endif
99
100/* to include the version number of VirtualBox into kernel backtraces */
101#define VBoxDrvLinuxVersion RT_CONCAT3(RT_CONCAT(VBOX_VERSION_MAJOR, _), \
102 RT_CONCAT(VBOX_VERSION_MINOR, _), \
103 VBOX_VERSION_BUILD)
104#define VBoxDrvLinuxIOCtl RT_CONCAT(VBoxDrvLinuxIOCtl_,VBoxDrvLinuxVersion)
105
106/*******************************************************************************
107* Internal Functions *
108*******************************************************************************/
109static int VBoxDrvLinuxInit(void);
110static void VBoxDrvLinuxUnload(void);
111static int VBoxDrvLinuxCreateSys(struct inode *pInode, struct file *pFilp);
112static int VBoxDrvLinuxCreateUsr(struct inode *pInode, struct file *pFilp);
113static int VBoxDrvLinuxClose(struct inode *pInode, struct file *pFilp);
114#ifdef HAVE_UNLOCKED_IOCTL
115static long VBoxDrvLinuxIOCtl(struct file *pFilp, unsigned int uCmd, unsigned long ulArg);
116#else
117static int VBoxDrvLinuxIOCtl(struct inode *pInode, struct file *pFilp, unsigned int uCmd, unsigned long ulArg);
118#endif
119static int VBoxDrvLinuxIOCtlSlow(struct file *pFilp, unsigned int uCmd, unsigned long ulArg, PSUPDRVSESSION pSession);
120static int VBoxDrvLinuxErr2LinuxErr(int);
121#ifdef VBOX_WITH_SUSPEND_NOTIFICATION
122static int VBoxDrvProbe(struct platform_device *pDev);
123# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
124static int VBoxDrvSuspend(struct device *pDev);
125static int VBoxDrvResume(struct device *pDev);
126# else
127static int VBoxDrvSuspend(struct platform_device *pDev, pm_message_t State);
128static int VBoxDrvResume(struct platform_device *pDev);
129# endif
130static void VBoxDevRelease(struct device *pDev);
131# ifdef VBOX_WITH_PRE_SUSPEND_NOTIFICATION
132static int VBoxDrvPowerNotificationCallback(struct notifier_block *, unsigned long, void *);
133# endif
134#endif
135
136
137/*******************************************************************************
138* Global Variables *
139*******************************************************************************/
140/**
141 * Device extention & session data association structure.
142 */
143static SUPDRVDEVEXT g_DevExt;
144
145#ifndef CONFIG_VBOXDRV_AS_MISC
146/** Module major number for vboxdrv. */
147#define DEVICE_MAJOR_SYS 234
148/** Saved major device number for vboxdrv. */
149static int g_iModuleMajorSys;
150/** Module major number for vboxdrvu. */
151#define DEVICE_MAJOR_USR 235
152/** Saved major device number for vboxdrvu. */
153static int g_iModuleMajorUsr;
154#endif /* !CONFIG_VBOXDRV_AS_MISC */
155
156/** Module parameter.
157 * Not prefixed because the name is used by macros and the end of this file. */
158static int force_async_tsc = 0;
159
160/** The system device name. */
161#define DEVICE_NAME_SYS "vboxdrv"
162/** The user device name. */
163#define DEVICE_NAME_USR "vboxdrvu"
164
165#if (defined(RT_ARCH_AMD64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)) || defined(VBOX_WITH_TEXT_MODMEM_HACK)
166/**
167 * Memory for the executable memory heap (in IPRT).
168 */
169# ifdef DEBUG
170# define EXEC_MEMORY_SIZE 6291456 /* 6 MB */
171# else
172# define EXEC_MEMORY_SIZE 1572864 /* 1.5 MB */
173# endif
174extern uint8_t g_abExecMemory[EXEC_MEMORY_SIZE];
175# ifndef VBOX_WITH_TEXT_MODMEM_HACK
176__asm__(".section execmemory, \"awx\", @progbits\n\t"
177 ".align 32\n\t"
178 ".globl g_abExecMemory\n"
179 "g_abExecMemory:\n\t"
180 ".zero " RT_XSTR(EXEC_MEMORY_SIZE) "\n\t"
181 ".type g_abExecMemory, @object\n\t"
182 ".size g_abExecMemory, " RT_XSTR(EXEC_MEMORY_SIZE) "\n\t"
183 ".text\n\t");
184# else
185__asm__(".text\n\t"
186 ".align 4096\n\t"
187 ".globl g_abExecMemory\n"
188 "g_abExecMemory:\n\t"
189 ".zero " RT_XSTR(EXEC_MEMORY_SIZE) "\n\t"
190 ".type g_abExecMemory, @object\n\t"
191 ".size g_abExecMemory, " RT_XSTR(EXEC_MEMORY_SIZE) "\n\t"
192 ".text\n\t");
193# endif
194#endif
195
196/** The file_operations structure. */
197static struct file_operations gFileOpsVBoxDrvSys =
198{
199 owner: THIS_MODULE,
200 open: VBoxDrvLinuxCreateSys,
201 release: VBoxDrvLinuxClose,
202#ifdef HAVE_UNLOCKED_IOCTL
203 unlocked_ioctl: VBoxDrvLinuxIOCtl,
204#else
205 ioctl: VBoxDrvLinuxIOCtl,
206#endif
207};
208
209/** The file_operations structure. */
210static struct file_operations gFileOpsVBoxDrvUsr =
211{
212 owner: THIS_MODULE,
213 open: VBoxDrvLinuxCreateUsr,
214 release: VBoxDrvLinuxClose,
215#ifdef HAVE_UNLOCKED_IOCTL
216 unlocked_ioctl: VBoxDrvLinuxIOCtl,
217#else
218 ioctl: VBoxDrvLinuxIOCtl,
219#endif
220};
221
222#ifdef CONFIG_VBOXDRV_AS_MISC
223/** The miscdevice structure for vboxdrv. */
224static struct miscdevice gMiscDeviceSys =
225{
226 minor: MISC_DYNAMIC_MINOR,
227 name: DEVICE_NAME_SYS,
228 fops: &gFileOpsVBoxDrvSys,
229# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
230 devfs_name: DEVICE_NAME_SYS,
231# endif
232};
233/** The miscdevice structure for vboxdrvu. */
234static struct miscdevice gMiscDeviceUsr =
235{
236 minor: MISC_DYNAMIC_MINOR,
237 name: DEVICE_NAME_USR,
238 fops: &gFileOpsVBoxDrvUsr,
239# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
240 devfs_name: DEVICE_NAME_USR,
241# endif
242};
243#endif
244
245
246#ifdef VBOX_WITH_SUSPEND_NOTIFICATION
247# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
248static struct dev_pm_ops gPlatformPMOps =
249{
250 .suspend = VBoxDrvSuspend, /* before entering deep sleep */
251 .resume = VBoxDrvResume, /* after wakeup from deep sleep */
252 .freeze = VBoxDrvSuspend, /* before creating hibernation image */
253 .restore = VBoxDrvResume, /* after waking up from hibernation */
254};
255# endif
256
257static struct platform_driver gPlatformDriver =
258{
259 .probe = VBoxDrvProbe,
260# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
261 .suspend = VBoxDrvSuspend,
262 .resume = VBoxDrvResume,
263# endif
264 /** @todo .shutdown? */
265 .driver =
266 {
267 .name = "vboxdrv",
268# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
269 .pm = &gPlatformPMOps,
270# endif
271 }
272};
273
274static struct platform_device gPlatformDevice =
275{
276 .name = "vboxdrv",
277 .dev =
278 {
279 .release = VBoxDevRelease
280 }
281};
282
283# ifdef VBOX_WITH_PRE_SUSPEND_NOTIFICATION
284static struct notifier_block *g_pNotifier;
285# endif /* VBOX_WITH_PRE_SUSPEND_NOTIFICATION */
286#endif /* VBOX_WITH_SUSPEND_NOTIFICATION */
287
288
289DECLINLINE(RTUID) vboxdrvLinuxUid(void)
290{
291#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
292# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
293 return from_kuid(current_user_ns(), current->cred->uid);
294# else
295 return current->cred->uid;
296# endif
297#else
298 return current->uid;
299#endif
300}
301
302DECLINLINE(RTGID) vboxdrvLinuxGid(void)
303{
304#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
305# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
306 return from_kgid(current_user_ns(), current->cred->gid);
307# else
308 return current->cred->gid;
309# endif
310#else
311 return current->gid;
312#endif
313}
314
315DECLINLINE(RTUID) vboxdrvLinuxEuid(void)
316{
317#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
318# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
319 return from_kuid(current_user_ns(), current->cred->euid);
320# else
321 return current->cred->euid;
322# endif
323#else
324 return current->euid;
325#endif
326}
327
328/**
329 * Initialize module.
330 *
331 * @returns appropriate status code.
332 */
333static int __init VBoxDrvLinuxInit(void)
334{
335 int rc;
336
337 /*
338 * Check for synchronous/asynchronous TSC mode.
339 */
340 printk(KERN_DEBUG "vboxdrv: Found %u processor cores\n", (unsigned)RTMpGetOnlineCount());
341#ifdef CONFIG_VBOXDRV_AS_MISC
342 rc = misc_register(&gMiscDeviceSys);
343 if (rc)
344 {
345 printk(KERN_ERR "vboxdrv: Can't register system misc device! rc=%d\n", rc);
346 return rc;
347 }
348 rc = misc_register(&gMiscDeviceUsr);
349 if (rc)
350 {
351 printk(KERN_ERR "vboxdrv: Can't register user misc device! rc=%d\n", rc);
352 misc_deregister(&gMiscDeviceSys);
353 return rc;
354 }
355#else /* !CONFIG_VBOXDRV_AS_MISC */
356 /*
357 * Register character devices and save the returned major numbers.
358 */
359 /* /dev/vboxdrv */
360 g_iModuleMajorSys = DEVICE_MAJOR_SYS;
361 rc = register_chrdev((dev_t)g_iModuleMajorSys, DEVICE_NAME_SYS, &gFileOpsVBoxDrvSys);
362 if (rc < 0)
363 {
364 Log(("register_chrdev() failed with rc=%#x for vboxdrv!\n", rc));
365 return rc;
366 }
367 if (DEVICE_MAJOR_SYS != 0)
368 g_iModuleMajorSys = DEVICE_MAJOR_SYS;
369 else
370 g_iModuleMajorSys = rc;
371
372 /* /dev/vboxdrvu */
373 /** @todo Use a minor number of this bugger (not sure if this code is used
374 * though, so not bothering right now.) */
375 g_iModuleMajorUsr = DEVICE_MAJOR_USR;
376 rc = register_chrdev((dev_t)g_iModuleMajorUsr, DEVICE_NAME_USR, &gFileOpsVBoxDrvUsr);
377 if (rc < 0)
378 {
379 Log(("register_chrdev() failed with rc=%#x for vboxdrv!\n", rc));
380 return rc;
381 }
382 if (DEVICE_MAJOR_USR != 0)
383 g_iModuleMajorUsr = DEVICE_MAJOR_USR;
384 else
385 g_iModuleMajorUsr = rc;
386 rc = 0;
387
388# ifdef CONFIG_DEVFS_FS
389 /*
390 * Register a device entry
391 */
392 if ( devfs_mk_cdev(MKDEV(DEVICE_MAJOR_SYS, 0), S_IFCHR | VBOX_DEV_FMASK, DEVICE_NAME_SYS) != 0
393 || devfs_mk_cdev(MKDEV(DEVICE_MAJOR_USR, 0), S_IFCHR | VBOX_DEV_FMASK, DEVICE_NAME_USR) != 0)
394 {
395 Log(("devfs_register failed!\n"));
396 rc = -EINVAL;
397 }
398# endif
399#endif /* !CONFIG_VBOXDRV_AS_MISC */
400 if (!rc)
401 {
402 /*
403 * Initialize the runtime.
404 * On AMD64 we'll have to donate the high rwx memory block to the exec allocator.
405 */
406 rc = RTR0Init(0);
407 if (RT_SUCCESS(rc))
408 {
409#if (defined(RT_ARCH_AMD64) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)) || defined(VBOX_WITH_TEXT_MODMEM_HACK)
410# ifdef VBOX_WITH_TEXT_MODMEM_HACK
411 set_memory_x(&g_abExecMemory[0], sizeof(g_abExecMemory) / PAGE_SIZE);
412 set_memory_rw(&g_abExecMemory[0], sizeof(g_abExecMemory) / PAGE_SIZE);
413# endif
414 rc = RTR0MemExecDonate(&g_abExecMemory[0], sizeof(g_abExecMemory));
415 printk(KERN_DEBUG "VBoxDrv: dbg - g_abExecMemory=%p\n", (void *)&g_abExecMemory[0]);
416#endif
417 Log(("VBoxDrv::ModuleInit\n"));
418
419 /*
420 * Initialize the device extension.
421 */
422 if (RT_SUCCESS(rc))
423 rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION));
424 if (RT_SUCCESS(rc))
425 {
426#ifdef VBOX_WITH_SUSPEND_NOTIFICATION
427 rc = platform_driver_register(&gPlatformDriver);
428 if (rc == 0)
429 {
430 rc = platform_device_register(&gPlatformDevice);
431 if (rc == 0)
432#endif
433 {
434# ifdef VBOX_WITH_PRE_SUSPEND_NOTIFICATION
435 size_t const cbNotifier = sizeof(*g_pNotifier);
436 g_pNotifier = RTMemAllocZ(cbNotifier);
437 if (g_pNotifier)
438 {
439 g_pNotifier->notifier_call = VBoxDrvPowerNotificationCallback;
440 g_pNotifier->priority = 0;
441 rc = register_pm_notifier(g_pNotifier);
442 if (!rc)
443 printk(KERN_INFO "vboxdrv: Successfully registered power notifier\n");
444 else
445 {
446 printk(KERN_INFO "vboxdrv: Failed to register power notifier! rc=%d\n", rc);
447 rc = 0;
448 }
449 }
450 else
451 printk(KERN_INFO "vboxdrv: Failed to alloc %lu bytes for power notifier\n", cbNotifier);
452# endif
453
454 printk(KERN_INFO "vboxdrv: TSC mode is %s, tentative frequency %llu Hz\n",
455 SUPGetGIPModeName(g_DevExt.pGip), g_DevExt.pGip->u64CpuHz);
456 LogFlow(("VBoxDrv::ModuleInit returning %#x\n", rc));
457 printk(KERN_DEBUG "vboxdrv: Successfully loaded version "
458 VBOX_VERSION_STRING " (interface " RT_XSTR(SUPDRV_IOC_VERSION) ")\n");
459 return rc;
460 }
461#ifdef VBOX_WITH_SUSPEND_NOTIFICATION
462 else
463 platform_driver_unregister(&gPlatformDriver);
464 }
465#endif
466 }
467
468 rc = -EINVAL;
469 RTR0TermForced();
470 }
471 else
472 rc = -EINVAL;
473
474 /*
475 * Failed, cleanup and return the error code.
476 */
477#if defined(CONFIG_DEVFS_FS) && !defined(CONFIG_VBOXDRV_AS_MISC)
478 devfs_remove(DEVICE_NAME_SYS);
479 devfs_remove(DEVICE_NAME_USR);
480#endif
481 }
482#ifdef CONFIG_VBOXDRV_AS_MISC
483 misc_deregister(&gMiscDeviceSys);
484 misc_deregister(&gMiscDeviceUsr);
485 Log(("VBoxDrv::ModuleInit returning %#x (minor:%d & %d)\n", rc, gMiscDeviceSys.minor, gMiscDeviceUsr.minor));
486#else
487 unregister_chrdev(g_iModuleMajorUsr, DEVICE_NAME_USR);
488 unregister_chrdev(g_iModuleMajorSys, DEVICE_NAME_SYS);
489 Log(("VBoxDrv::ModuleInit returning %#x (major:%d & %d)\n", rc, g_iModuleMajorSys, g_iModuleMajorUsr));
490#endif
491 return rc;
492}
493
494
495/**
496 * Unload the module.
497 */
498static void __exit VBoxDrvLinuxUnload(void)
499{
500 int rc;
501 Log(("VBoxDrvLinuxUnload\n"));
502 NOREF(rc);
503
504#ifdef VBOX_WITH_SUSPEND_NOTIFICATION
505 platform_device_unregister(&gPlatformDevice);
506 platform_driver_unregister(&gPlatformDriver);
507# ifdef VBOX_WITH_PRE_SUSPEND_NOTIFICATION
508 if (g_pNotifier)
509 {
510 unregister_pm_notifier(g_pNotifier);
511 g_pNotifier = NULL;
512 }
513# endif
514#endif
515
516 /*
517 * I Don't think it's possible to unload a driver which processes have
518 * opened, at least we'll blindly assume that here.
519 */
520#ifdef CONFIG_VBOXDRV_AS_MISC
521 rc = misc_deregister(&gMiscDeviceUsr);
522 if (rc < 0)
523 {
524 Log(("misc_deregister failed with rc=%#x on vboxdrvu\n", rc));
525 }
526 rc = misc_deregister(&gMiscDeviceSys);
527 if (rc < 0)
528 {
529 Log(("misc_deregister failed with rc=%#x on vboxdrv\n", rc));
530 }
531#else /* !CONFIG_VBOXDRV_AS_MISC */
532# ifdef CONFIG_DEVFS_FS
533 /*
534 * Unregister a device entry
535 */
536 devfs_remove(DEVICE_NAME_USR);
537 devfs_remove(DEVICE_NAME_SYS);
538# endif /* devfs */
539 unregister_chrdev(g_iModuleMajorUsr, DEVICE_NAME_USR);
540 unregister_chrdev(g_iModuleMajorSys, DEVICE_NAME_SYS);
541#endif /* !CONFIG_VBOXDRV_AS_MISC */
542
543 /*
544 * Destroy GIP, delete the device extension and terminate IPRT.
545 */
546 supdrvDeleteDevExt(&g_DevExt);
547 RTR0TermForced();
548}
549
550
551/**
552 * Common open code.
553 *
554 * @param pInode Pointer to inode info structure.
555 * @param pFilp Associated file pointer.
556 * @param fUnrestricted Indicates which device node which was opened.
557 */
558static int vboxdrvLinuxCreateCommon(struct inode *pInode, struct file *pFilp, bool fUnrestricted)
559{
560 int rc;
561 PSUPDRVSESSION pSession;
562 Log(("VBoxDrvLinuxCreate: pFilp=%p pid=%d/%d %s\n", pFilp, RTProcSelf(), current->pid, current->comm));
563
564#ifdef VBOX_WITH_HARDENING
565 /*
566 * Only root is allowed to access the unrestricted device, enforce it!
567 */
568 if ( fUnrestricted
569 && vboxdrvLinuxEuid() != 0 /* root */ )
570 {
571 Log(("VBoxDrvLinuxCreate: euid=%d, expected 0 (root)\n", vboxdrvLinuxEuid()));
572 return -EPERM;
573 }
574#endif /* VBOX_WITH_HARDENING */
575
576 /*
577 * Call common code for the rest.
578 */
579 rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession);
580 if (!rc)
581 {
582 pSession->Uid = vboxdrvLinuxUid();
583 pSession->Gid = vboxdrvLinuxGid();
584 }
585
586 pFilp->private_data = pSession;
587
588 Log(("VBoxDrvLinuxCreate: g_DevExt=%p pSession=%p rc=%d/%d (pid=%d/%d %s)\n",
589 &g_DevExt, pSession, rc, VBoxDrvLinuxErr2LinuxErr(rc),
590 RTProcSelf(), current->pid, current->comm));
591 return VBoxDrvLinuxErr2LinuxErr(rc);
592}
593
594
595/** /dev/vboxdrv. */
596static int VBoxDrvLinuxCreateSys(struct inode *pInode, struct file *pFilp)
597{
598 return vboxdrvLinuxCreateCommon(pInode, pFilp, true);
599}
600
601
602/** /dev/vboxdrvu. */
603static int VBoxDrvLinuxCreateUsr(struct inode *pInode, struct file *pFilp)
604{
605 return vboxdrvLinuxCreateCommon(pInode, pFilp, false);
606}
607
608
609/**
610 * Close device.
611 *
612 * @param pInode Pointer to inode info structure.
613 * @param pFilp Associated file pointer.
614 */
615static int VBoxDrvLinuxClose(struct inode *pInode, struct file *pFilp)
616{
617 Log(("VBoxDrvLinuxClose: pFilp=%p pSession=%p pid=%d/%d %s\n",
618 pFilp, pFilp->private_data, RTProcSelf(), current->pid, current->comm));
619 supdrvSessionRelease((PSUPDRVSESSION)pFilp->private_data);
620 pFilp->private_data = NULL;
621 return 0;
622}
623
624
625#ifdef VBOX_WITH_SUSPEND_NOTIFICATION
626/**
627 * Dummy device release function. We have to provide this function,
628 * otherwise the kernel will complain.
629 *
630 * @param pDev Pointer to the platform device.
631 */
632static void VBoxDevRelease(struct device *pDev)
633{
634}
635
636/**
637 * Dummy probe function.
638 *
639 * @param pDev Pointer to the platform device.
640 */
641static int VBoxDrvProbe(struct platform_device *pDev)
642{
643 return 0;
644}
645
646/**
647 * Suspend callback.
648 * @param pDev Pointer to the platform device.
649 * @param State message type, see Documentation/power/devices.txt.
650 */
651# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
652static int VBoxDrvSuspend(struct device *pDev)
653# else
654static int VBoxDrvSuspend(struct platform_device *pDev, pm_message_t State)
655# endif
656{
657 RTPowerSignalEvent(RTPOWEREVENT_SUSPEND);
658 return 0;
659}
660
661/**
662 * Resume callback.
663 *
664 * @param pDev Pointer to the platform device.
665 */
666# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
667static int VBoxDrvResume(struct device *pDev)
668# else
669static int VBoxDrvResume(struct platform_device *pDev)
670# endif
671{
672 RTPowerSignalEvent(RTPOWEREVENT_RESUME);
673 return 0;
674}
675#endif /* VBOX_WITH_SUSPEND_NOTIFICATION */
676
677
678#ifdef VBOX_WITH_PRE_SUSPEND_NOTIFICATION
679static int VBoxDrvPowerNotificationCallback(struct notifier_block *pNotifier, unsigned long uEvent, void *pvUnused)
680{
681 NOREF(pvUnused);
682 if (uEvent == PM_SUSPEND_PREPARE)
683 RTPowerSignalEvent(RTPOWEREVENT_PRE_SUSPEND);
684 /* The remaining events are taken care by VBoxDrvSuspend() and VboxDrvResume() hooks. */
685 return NOTIFY_DONE;
686}
687#endif
688
689/**
690 * Device I/O Control entry point.
691 *
692 * @param pFilp Associated file pointer.
693 * @param uCmd The function specified to ioctl().
694 * @param ulArg The argument specified to ioctl().
695 */
696#ifdef HAVE_UNLOCKED_IOCTL
697static long VBoxDrvLinuxIOCtl(struct file *pFilp, unsigned int uCmd, unsigned long ulArg)
698#else
699static int VBoxDrvLinuxIOCtl(struct inode *pInode, struct file *pFilp, unsigned int uCmd, unsigned long ulArg)
700#endif
701{
702 PSUPDRVSESSION pSession = (PSUPDRVSESSION)pFilp->private_data;
703 int rc;
704
705 /*
706 * Deal with the two high-speed IOCtl that takes it's arguments from
707 * the session and iCmd, and only returns a VBox status code.
708 */
709#ifdef HAVE_UNLOCKED_IOCTL
710 if (RT_LIKELY( ( uCmd == SUP_IOCTL_FAST_DO_RAW_RUN
711 || uCmd == SUP_IOCTL_FAST_DO_HM_RUN
712 || uCmd == SUP_IOCTL_FAST_DO_NOP)
713 && pSession->fUnrestricted == true))
714 {
715 stac();
716 rc = supdrvIOCtlFast(uCmd, ulArg, &g_DevExt, pSession);
717 clac();
718 return rc;
719 }
720 return VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg, pSession);
721
722#else /* !HAVE_UNLOCKED_IOCTL */
723 unlock_kernel();
724 if (RT_LIKELY( ( uCmd == SUP_IOCTL_FAST_DO_RAW_RUN
725 || uCmd == SUP_IOCTL_FAST_DO_HM_RUN
726 || uCmd == SUP_IOCTL_FAST_DO_NOP)
727 && pSession->fUnrestricted == true))
728 rc = supdrvIOCtlFast(uCmd, ulArg, &g_DevExt, pSession);
729 else
730 rc = VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg, pSession);
731 lock_kernel();
732 return rc;
733#endif /* !HAVE_UNLOCKED_IOCTL */
734}
735
736
737/**
738 * Device I/O Control entry point.
739 *
740 * @param pFilp Associated file pointer.
741 * @param uCmd The function specified to ioctl().
742 * @param ulArg The argument specified to ioctl().
743 * @param pSession The session instance.
744 */
745static int VBoxDrvLinuxIOCtlSlow(struct file *pFilp, unsigned int uCmd, unsigned long ulArg, PSUPDRVSESSION pSession)
746{
747 int rc;
748 SUPREQHDR Hdr;
749 PSUPREQHDR pHdr;
750 uint32_t cbBuf;
751
752 Log6(("VBoxDrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p pid=%d/%d\n", pFilp, uCmd, (void *)ulArg, RTProcSelf(), current->pid));
753
754 /*
755 * Read the header.
756 */
757 if (RT_UNLIKELY(copy_from_user(&Hdr, (void *)ulArg, sizeof(Hdr))))
758 {
759 Log(("VBoxDrvLinuxIOCtl: copy_from_user(,%#lx,) failed; uCmd=%#x\n", ulArg, uCmd));
760 return -EFAULT;
761 }
762 if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC))
763 {
764 Log(("VBoxDrvLinuxIOCtl: bad header magic %#x; uCmd=%#x\n", Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK, uCmd));
765 return -EINVAL;
766 }
767
768 /*
769 * Buffer the request.
770 */
771 cbBuf = RT_MAX(Hdr.cbIn, Hdr.cbOut);
772 if (RT_UNLIKELY(cbBuf > _1M*16))
773 {
774 Log(("VBoxDrvLinuxIOCtl: too big cbBuf=%#x; uCmd=%#x\n", cbBuf, uCmd));
775 return -E2BIG;
776 }
777 if (RT_UNLIKELY(_IOC_SIZE(uCmd) ? cbBuf != _IOC_SIZE(uCmd) : Hdr.cbIn < sizeof(Hdr)))
778 {
779 Log(("VBoxDrvLinuxIOCtl: bad ioctl cbBuf=%#x _IOC_SIZE=%#x; uCmd=%#x\n", cbBuf, _IOC_SIZE(uCmd), uCmd));
780 return -EINVAL;
781 }
782 pHdr = RTMemAlloc(cbBuf);
783 if (RT_UNLIKELY(!pHdr))
784 {
785 OSDBGPRINT(("VBoxDrvLinuxIOCtl: failed to allocate buffer of %d bytes for uCmd=%#x\n", cbBuf, uCmd));
786 return -ENOMEM;
787 }
788 if (RT_UNLIKELY(copy_from_user(pHdr, (void *)ulArg, Hdr.cbIn)))
789 {
790 Log(("VBoxDrvLinuxIOCtl: copy_from_user(,%#lx, %#x) failed; uCmd=%#x\n", ulArg, Hdr.cbIn, uCmd));
791 RTMemFree(pHdr);
792 return -EFAULT;
793 }
794 if (Hdr.cbIn < cbBuf)
795 RT_BZERO((uint8_t *)pHdr + Hdr.cbIn, cbBuf - Hdr.cbIn);
796
797 /*
798 * Process the IOCtl.
799 */
800 stac();
801 rc = supdrvIOCtl(uCmd, &g_DevExt, pSession, pHdr, cbBuf);
802 clac();
803
804 /*
805 * Copy ioctl data and output buffer back to user space.
806 */
807 if (RT_LIKELY(!rc))
808 {
809 uint32_t cbOut = pHdr->cbOut;
810 if (RT_UNLIKELY(cbOut > cbBuf))
811 {
812 OSDBGPRINT(("VBoxDrvLinuxIOCtl: too much output! %#x > %#x; uCmd=%#x!\n", cbOut, cbBuf, uCmd));
813 cbOut = cbBuf;
814 }
815 if (RT_UNLIKELY(copy_to_user((void *)ulArg, pHdr, cbOut)))
816 {
817 /* this is really bad! */
818 OSDBGPRINT(("VBoxDrvLinuxIOCtl: copy_to_user(%#lx,,%#x); uCmd=%#x!\n", ulArg, cbOut, uCmd));
819 rc = -EFAULT;
820 }
821 }
822 else
823 {
824 Log(("VBoxDrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p failed, rc=%d\n", pFilp, uCmd, (void *)ulArg, rc));
825 rc = -EINVAL;
826 }
827 RTMemFree(pHdr);
828
829 Log6(("VBoxDrvLinuxIOCtl: returns %d (pid=%d/%d)\n", rc, RTProcSelf(), current->pid));
830 return rc;
831}
832
833
834/**
835 * The SUPDRV IDC entry point.
836 *
837 * @returns VBox status code, see supdrvIDC.
838 * @param iReq The request code.
839 * @param pReq The request.
840 */
841int VBOXCALL SUPDrvLinuxIDC(uint32_t uReq, PSUPDRVIDCREQHDR pReq)
842{
843 PSUPDRVSESSION pSession;
844
845 /*
846 * Some quick validations.
847 */
848 if (RT_UNLIKELY(!VALID_PTR(pReq)))
849 return VERR_INVALID_POINTER;
850
851 pSession = pReq->pSession;
852 if (pSession)
853 {
854 if (RT_UNLIKELY(!VALID_PTR(pSession)))
855 return VERR_INVALID_PARAMETER;
856 if (RT_UNLIKELY(pSession->pDevExt != &g_DevExt))
857 return VERR_INVALID_PARAMETER;
858 }
859 else if (RT_UNLIKELY(uReq != SUPDRV_IDC_REQ_CONNECT))
860 return VERR_INVALID_PARAMETER;
861
862 /*
863 * Do the job.
864 */
865 return supdrvIDC(uReq, &g_DevExt, pSession, pReq);
866}
867
868EXPORT_SYMBOL(SUPDrvLinuxIDC);
869
870
871RTCCUINTREG VBOXCALL supdrvOSChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask)
872{
873#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
874 RTCCUINTREG uOld = this_cpu_read(cpu_tlbstate.cr4);
875 RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
876 if (uNew != uOld)
877 {
878 this_cpu_write(cpu_tlbstate.cr4, uNew);
879 __write_cr4(uNew);
880 }
881#else
882 RTCCUINTREG uOld = ASMGetCR4();
883 RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
884 if (uNew != uOld)
885 ASMSetCR4(uNew);
886#endif
887 return uOld;
888}
889
890
891void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
892{
893 NOREF(pDevExt);
894 NOREF(pSession);
895}
896
897
898void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
899{
900 NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
901}
902
903
904void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
905{
906 NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
907}
908
909
910/**
911 * Initializes any OS specific object creator fields.
912 */
913void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
914{
915 NOREF(pObj);
916 NOREF(pSession);
917}
918
919
920/**
921 * Checks if the session can access the object.
922 *
923 * @returns true if a decision has been made.
924 * @returns false if the default access policy should be applied.
925 *
926 * @param pObj The object in question.
927 * @param pSession The session wanting to access the object.
928 * @param pszObjName The object name, can be NULL.
929 * @param prc Where to store the result when returning true.
930 */
931bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
932{
933 NOREF(pObj);
934 NOREF(pSession);
935 NOREF(pszObjName);
936 NOREF(prc);
937 return false;
938}
939
940
941bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt)
942{
943 return force_async_tsc != 0;
944}
945
946
947bool VBOXCALL supdrvOSAreCpusOfflinedOnSuspend(void)
948{
949 return true;
950}
951
952
953bool VBOXCALL supdrvOSAreTscDeltasInSync(void)
954{
955 return false;
956}
957
958
959int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
960{
961 NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
962 return VERR_NOT_SUPPORTED;
963}
964
965
966void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
967{
968 NOREF(pDevExt); NOREF(pImage);
969}
970
971
972int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
973{
974 NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits);
975 return VERR_NOT_SUPPORTED;
976}
977
978
979int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
980{
981 NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); NOREF(pReq);
982 return VERR_NOT_SUPPORTED;
983}
984
985
986void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
987{
988 NOREF(pDevExt); NOREF(pImage);
989}
990
991
992#ifdef SUPDRV_WITH_MSR_PROBER
993
994int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
995{
996# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
997 uint32_t u32Low, u32High;
998 int rc;
999
1000 if (idCpu == NIL_RTCPUID)
1001 rc = rdmsr_safe(uMsr, &u32Low, &u32High);
1002 else if (RTMpIsCpuOnline(idCpu))
1003 rc = rdmsr_safe_on_cpu(idCpu, uMsr, &u32Low, &u32High);
1004 else
1005 return VERR_CPU_OFFLINE;
1006 if (rc == 0)
1007 {
1008 *puValue = RT_MAKE_U64(u32Low, u32High);
1009 return VINF_SUCCESS;
1010 }
1011 return VERR_ACCESS_DENIED;
1012# else
1013 return VERR_NOT_SUPPORTED;
1014# endif
1015}
1016
1017
1018int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
1019{
1020# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
1021 int rc;
1022
1023 if (idCpu == NIL_RTCPUID)
1024 rc = wrmsr_safe(uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue));
1025 else if (RTMpIsCpuOnline(idCpu))
1026 rc = wrmsr_safe_on_cpu(idCpu, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue));
1027 else
1028 return VERR_CPU_OFFLINE;
1029 if (rc == 0)
1030 return VINF_SUCCESS;
1031 return VERR_ACCESS_DENIED;
1032# else
1033 return VERR_NOT_SUPPORTED;
1034# endif
1035}
1036
1037# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
1038/**
1039 * Worker for supdrvOSMsrProberModify.
1040 */
1041static DECLCALLBACK(void) supdrvLnxMsrProberModifyOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
1042{
1043 PSUPMSRPROBER pReq = (PSUPMSRPROBER)pvUser1;
1044 register uint32_t uMsr = pReq->u.In.uMsr;
1045 bool const fFaster = pReq->u.In.enmOp == SUPMSRPROBEROP_MODIFY_FASTER;
1046 uint64_t uBefore;
1047 uint64_t uWritten;
1048 uint64_t uAfter;
1049 int rcBefore, rcWrite, rcAfter, rcRestore;
1050 RTCCUINTREG fOldFlags;
1051
1052 /* Initialize result variables. */
1053 uBefore = uWritten = uAfter = 0;
1054 rcWrite = rcAfter = rcRestore = -EIO;
1055
1056 /*
1057 * Do the job.
1058 */
1059 fOldFlags = ASMIntDisableFlags();
1060 ASMCompilerBarrier(); /* paranoia */
1061 if (!fFaster)
1062 ASMWriteBackAndInvalidateCaches();
1063
1064 rcBefore = rdmsrl_safe(uMsr, &uBefore);
1065 if (rcBefore >= 0)
1066 {
1067 register uint64_t uRestore = uBefore;
1068 uWritten = uRestore;
1069 uWritten &= pReq->u.In.uArgs.Modify.fAndMask;
1070 uWritten |= pReq->u.In.uArgs.Modify.fOrMask;
1071
1072 rcWrite = wrmsr_safe(uMsr, RT_LODWORD(uWritten), RT_HIDWORD(uWritten));
1073 rcAfter = rdmsrl_safe(uMsr, &uAfter);
1074 rcRestore = wrmsr_safe(uMsr, RT_LODWORD(uRestore), RT_HIDWORD(uRestore));
1075
1076 if (!fFaster)
1077 {
1078 ASMWriteBackAndInvalidateCaches();
1079 ASMReloadCR3();
1080 ASMNopPause();
1081 }
1082 }
1083
1084 ASMCompilerBarrier(); /* paranoia */
1085 ASMSetFlags(fOldFlags);
1086
1087 /*
1088 * Write out the results.
1089 */
1090 pReq->u.Out.uResults.Modify.uBefore = uBefore;
1091 pReq->u.Out.uResults.Modify.uWritten = uWritten;
1092 pReq->u.Out.uResults.Modify.uAfter = uAfter;
1093 pReq->u.Out.uResults.Modify.fBeforeGp = rcBefore != 0;
1094 pReq->u.Out.uResults.Modify.fModifyGp = rcWrite != 0;
1095 pReq->u.Out.uResults.Modify.fAfterGp = rcAfter != 0;
1096 pReq->u.Out.uResults.Modify.fRestoreGp = rcRestore != 0;
1097 RT_ZERO(pReq->u.Out.uResults.Modify.afReserved);
1098}
1099# endif
1100
1101
1102int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
1103{
1104# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
1105 if (idCpu == NIL_RTCPUID)
1106 {
1107 supdrvLnxMsrProberModifyOnCpu(idCpu, pReq, NULL);
1108 return VINF_SUCCESS;
1109 }
1110 return RTMpOnSpecific(idCpu, supdrvLnxMsrProberModifyOnCpu, pReq, NULL);
1111# else
1112 return VERR_NOT_SUPPORTED;
1113# endif
1114}
1115
1116#endif /* SUPDRV_WITH_MSR_PROBER */
1117
1118
1119/**
1120 * Converts a supdrv error code to an linux error code.
1121 *
1122 * @returns corresponding linux error code.
1123 * @param rc IPRT status code.
1124 */
1125static int VBoxDrvLinuxErr2LinuxErr(int rc)
1126{
1127 switch (rc)
1128 {
1129 case VINF_SUCCESS: return 0;
1130 case VERR_GENERAL_FAILURE: return -EACCES;
1131 case VERR_INVALID_PARAMETER: return -EINVAL;
1132 case VERR_INVALID_MAGIC: return -EILSEQ;
1133 case VERR_INVALID_HANDLE: return -ENXIO;
1134 case VERR_INVALID_POINTER: return -EFAULT;
1135 case VERR_LOCK_FAILED: return -ENOLCK;
1136 case VERR_ALREADY_LOADED: return -EEXIST;
1137 case VERR_PERMISSION_DENIED: return -EPERM;
1138 case VERR_VERSION_MISMATCH: return -ENOSYS;
1139 case VERR_IDT_FAILED: return -1000;
1140 }
1141
1142 return -EPERM;
1143}
1144
1145
1146RTDECL(int) SUPR0Printf(const char *pszFormat, ...)
1147{
1148 va_list va;
1149 char szMsg[512];
1150
1151 va_start(va, pszFormat);
1152 RTStrPrintfV(szMsg, sizeof(szMsg) - 1, pszFormat, va);
1153 va_end(va);
1154 szMsg[sizeof(szMsg) - 1] = '\0';
1155
1156 printk("%s", szMsg);
1157 return 0;
1158}
1159
1160
1161/**
1162 * Returns configuration flags of the host kernel.
1163 */
1164SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void)
1165{
1166 uint32_t fFlags = 0;
1167#ifdef CONFIG_PAX_KERNEXEC
1168 fFlags |= SUPKERNELFEATURES_GDT_READ_ONLY;
1169#endif
1170 return fFlags;
1171}
1172
1173
1174module_init(VBoxDrvLinuxInit);
1175module_exit(VBoxDrvLinuxUnload);
1176
1177MODULE_AUTHOR(VBOX_VENDOR);
1178MODULE_DESCRIPTION(VBOX_PRODUCT " Support Driver");
1179MODULE_LICENSE("GPL");
1180#ifdef MODULE_VERSION
1181MODULE_VERSION(VBOX_VERSION_STRING " (" RT_XSTR(SUPDRV_IOC_VERSION) ")");
1182#endif
1183
1184module_param(force_async_tsc, int, 0444);
1185MODULE_PARM_DESC(force_async_tsc, "force the asynchronous TSC mode");
1186
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette