VirtualBox

Changeset 64435 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Oct 27, 2016 12:39:50 PM (8 years ago)
Author:
vboxsync
Message:

bugref:8639 Additions/VBoxGuest: Fix preemptible mouse notification callback being executed under a spinlock (Solaris guests).

Location:
trunk/src/VBox/Additions/common/VBoxGuest
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c

    r62521 r64435  
    7979static int vgdrvSolarisAddIRQ(dev_info_t *pDip);
    8080static void vgdrvSolarisRemoveIRQ(dev_info_t *pDip);
     81static uint_t vgdrvSolarisHighLevelISR(caddr_t Arg);
    8182static uint_t vgdrvSolarisISR(caddr_t Arg);
    8283
     
    178179/** Size of the MMIO region. */
    179180static off_t                g_cbMMIO;
    180 /** Pointer to the interrupt handle vector */
    181 static ddi_intr_handle_t   *g_pIntr;
    182 /** Number of actually allocated interrupt handles */
    183 static size_t               g_cIntrAllocated;
     181/** Pointer to an array of interrupt handles. */
     182static ddi_intr_handle_t   *g_pahIntrs;
     183/** Handle to the soft interrupt. */
     184static ddi_softint_handle_t g_hSoftIntr;
    184185/** The pollhead structure */
    185186static pollhead_t           g_PollHead;
    186187/** The IRQ Mutex */
    187188static kmutex_t             g_IrqMtx;
     189/** The IRQ high-level Mutex. */
     190static kmutex_t             g_HighLevelIrqMtx;
    188191/** Layered device handle for kernel keep-attached opens */
    189192static ldi_handle_t         g_LdiHandle = NULL;
     
    192195/** The Mutex protecting the LDI handle in IDC opens */
    193196static kmutex_t             g_LdiMtx;
     197/** Whether soft-ints are setup. */
     198static bool                 g_fSoftIntRegistered = false;
    194199
    195200/**
     
    353358                                else
    354359                                    LogRel((DEVICE_NAME "::Attach: VGDrvCommonInitDevExt failed.\n"));
     360
    355361                                vgdrvSolarisRemoveIRQ(pDip);
    356362                            }
     
    433439static int vgdrvSolarisQuiesce(dev_info_t *pDip)
    434440{
    435     for (int i = 0; i < g_cIntrAllocated; i++)
    436     {
    437         int rc = ddi_intr_disable(g_pIntr[i]);
    438         if (rc != DDI_SUCCESS)
    439             return DDI_FAILURE;
    440     }
     441    int rc = ddi_intr_disable(g_pahIntrs[0]);
     442    if (rc != DDI_SUCCESS)
     443        return DDI_FAILURE;
    441444
    442445    /** @todo What about HGCM/HGSMI touching guest-memory? */
     
    600603# define IOCPARM_LEN(Code)                      (((Code) >> 16) & IOCPARM_MASK)
    601604#endif
     605
     606
     607/**
     608 * Converts a VBox status code to a Solaris error code.
     609 *
     610 * @returns corresponding Solaris errno.
     611 * @param   rcVBox        VirtualBox error code to convert.
     612 */
     613static int vgdrvSolarisConvertToErrno(int rcVBox)
     614{
     615    /* RTErrConvertToErrno() below will ring-0 debug assert if we don't do such stuff. */
     616    if (rcVBox == VERR_PERMISSION_DENIED)
     617        rcVBox = VERR_ACCESS_DENIED;
     618
     619    if (   rcVBox > -1000
     620        && rcVBox < 1000)
     621        return RTErrConvertToErrno(rcVBox);
     622
     623    switch (rcVBox)
     624    {
     625        case VERR_HGCM_SERVICE_NOT_FOUND:      return ESRCH;
     626        case VINF_HGCM_CLIENT_REJECTED:        return 0;
     627        case VERR_HGCM_INVALID_CMD_ADDRESS:    return EFAULT;
     628        case VINF_HGCM_ASYNC_EXECUTE:          return 0;
     629        case VERR_HGCM_INTERNAL:               return EPROTO;
     630        case VERR_HGCM_INVALID_CLIENT_ID:      return EINVAL;
     631        case VINF_HGCM_SAVE_STATE:             return 0;
     632        /* No reason to return this to a guest. */
     633        /* case VERR_HGCM_SERVICE_EXISTS:      return EEXIST; */
     634
     635        default:
     636        {
     637            AssertMsgFailed(("Unhandled error code %Rrc\n", rcVBox));
     638            return EINVAL;
     639        }
     640    }
     641}
    602642
    603643
     
    724764         */
    725765        Log(("vgdrvSolarisIOCtl: VGDrvCommonIoCtl failed. Cmd=%#x rc=%d\n", Cmd, rc));
    726         if (rc == VERR_PERMISSION_DENIED)   /* RTErrConvertToErrno() below will ring-0 debug assert if we don't do this. */
    727             rc = VERR_ACCESS_DENIED;
    728         rc = RTErrConvertToErrno(rc);
     766        rc = vgdrvSolarisConvertToErrno(rc);
    729767    }
    730768    *pVal = rc;
     
    776814    LogFlow(("vgdrvSolarisAddIRQ: pDip=%p\n", pDip));
    777815
    778     int IntrType = 0;
    779     int rc = ddi_intr_get_supported_types(pDip, &IntrType);
     816    /* Get the types of interrupt supported for this hardware. */
     817    int fIntrType = 0;
     818    int rc = ddi_intr_get_supported_types(pDip, &fIntrType);
    780819    if (rc == DDI_SUCCESS)
    781820    {
    782         /* We won't need to bother about MSIs. */
    783         if (IntrType & DDI_INTR_TYPE_FIXED)
    784         {
    785             int IntrCount = 0;
    786             rc = ddi_intr_get_nintrs(pDip, IntrType, &IntrCount);
     821        /* We only support fixed interrupts at this point, not MSIs. */
     822        if (fIntrType & DDI_INTR_TYPE_FIXED)
     823        {
     824            /* Verify the number of interrupts supported by this device. There can only be one fixed interrupt. */
     825            int cIntrCount = 0;
     826            rc = ddi_intr_get_nintrs(pDip, fIntrType, &cIntrCount);
    787827            if (   rc == DDI_SUCCESS
    788                 && IntrCount > 0)
     828                && cIntrCount == 1)
    789829            {
    790                 int IntrAvail = 0;
    791                 rc = ddi_intr_get_navail(pDip, IntrType, &IntrAvail);
    792                 if (   rc == DDI_SUCCESS
    793                     && IntrAvail > 0)
     830                /* Allocated kernel memory for the interrupt handle. The allocation size is stored internally. */
     831                g_pahIntrs = RTMemAllocZ(cIntrCount * sizeof(ddi_intr_handle_t));
     832                if (g_pahIntrs)
    794833                {
    795                     /* Allocated kernel memory for the interrupt handles. The allocation size is stored internally. */
    796                     g_pIntr = RTMemAlloc(IntrCount * sizeof(ddi_intr_handle_t));
    797                     if (g_pIntr)
     834                    /* Allocate the interrupt for this device and verify the allocation. */
     835                    int cIntrAllocated;
     836                    rc = ddi_intr_alloc(pDip, g_pahIntrs, fIntrType, 0 /* interrupt number */, cIntrCount, &cIntrAllocated,
     837                                        DDI_INTR_ALLOC_NORMAL);
     838                    if (   rc == DDI_SUCCESS
     839                        && cIntrAllocated == 1)
    798840                    {
    799                         int IntrAllocated;
    800                         rc = ddi_intr_alloc(pDip, g_pIntr, IntrType, 0, IntrCount, &IntrAllocated, DDI_INTR_ALLOC_NORMAL);
    801                         if (   rc == DDI_SUCCESS
    802                             && IntrAllocated > 0)
     841                        /* Get the interrupt priority assigned by the system. */
     842                        uint_t uIntrPriority;
     843                        rc = ddi_intr_get_pri(g_pahIntrs[0], &uIntrPriority);
     844                        if (rc == DDI_SUCCESS)
    803845                        {
    804                             g_cIntrAllocated = IntrAllocated;
    805                             uint_t uIntrPriority;
    806                             rc = ddi_intr_get_pri(g_pIntr[0], &uIntrPriority);
    807                             if (rc == DDI_SUCCESS)
     846                            /* Check if the interrupt priority is scheduler level or above, if so we need to use a high-level
     847                               and low-level interrupt handlers with corresponding mutexes. */
     848                            cmn_err(CE_NOTE,  "vboxguest: uIntrPriority=%d hilevel_pri=%d\n", uIntrPriority, ddi_intr_get_hilevel_pri());
     849                            if (uIntrPriority >= ddi_intr_get_hilevel_pri())
    808850                            {
    809                                 /* Initialize the mutex. */
    810                                 mutex_init(&g_IrqMtx, NULL /* pszDesc */, MUTEX_DRIVER, DDI_INTR_PRI(uIntrPriority));
    811 
    812                                 /* Assign interrupt handler functions and enable interrupts. */
    813                                 for (int i = 0; i < IntrAllocated; i++)
     851                                /* Initialize the high-level mutex. */
     852                                mutex_init(&g_HighLevelIrqMtx, NULL /* pszDesc */, MUTEX_DRIVER, DDI_INTR_PRI(uIntrPriority));
     853
     854                                /* Assign interrupt handler function to the interrupt handle. */
     855                                rc = ddi_intr_add_handler(g_pahIntrs[0], (ddi_intr_handler_t *)&vgdrvSolarisHighLevelISR,
     856                                                          NULL /* pvArg1 */, NULL /* pvArg2 */);
     857
     858                                if (rc == DDI_SUCCESS)
    814859                                {
    815                                     rc = ddi_intr_add_handler(g_pIntr[i], (ddi_intr_handler_t *)vgdrvSolarisISR,
    816                                                               NULL /* pvArg1 */, NULL /* pvArg2 */);
     860                                    /* Add the low-level interrupt handler. */
     861                                    rc = ddi_intr_add_softint(pDip, &g_hSoftIntr, DDI_INTR_SOFTPRI_MAX,
     862                                                              (ddi_intr_handler_t *)&vgdrvSolarisISR, NULL /* pvArg1 */);
    817863                                    if (rc == DDI_SUCCESS)
    818                                         rc = ddi_intr_enable(g_pIntr[i]);
    819                                     if (rc != DDI_SUCCESS)
    820864                                    {
    821                                         /* Changing local IntrAllocated to hold so-far allocated handles for freeing. */
    822                                         IntrAllocated = i;
    823                                         break;
     865                                        /* Initialize the low-level mutex at the corresponding level. */
     866                                        mutex_init(&g_IrqMtx, NULL /* pszDesc */,  MUTEX_DRIVER,
     867                                                   DDI_INTR_PRI(DDI_INTR_SOFTPRI_MAX));
     868
     869                                        g_fSoftIntRegistered = true;
     870                                        /* Enable the high-level interrupt. */
     871                                        rc = ddi_intr_enable(g_pahIntrs[0]);
     872                                        if (rc == DDI_SUCCESS)
     873                                            return rc;
     874
     875                                        LogRel((DEVICE_NAME "::AddIRQ: failed to enable interrupt. rc=%d\n", rc));
     876                                        mutex_destroy(&g_IrqMtx);
    824877                                    }
     878                                    else
     879                                        LogRel((DEVICE_NAME "::AddIRQ: failed to add soft interrupt handler. rc=%d\n", rc));
     880
     881                                    ddi_intr_remove_handler(g_pahIntrs[0]);
    825882                                }
    826                                 if (rc == DDI_SUCCESS)
    827                                     return rc;
    828 
    829                                 /* Remove any assigned handlers */
    830                                 LogRel((DEVICE_NAME ":failed to assign IRQs allocated=%d\n", IntrAllocated));
    831                                 for (int x = 0; x < IntrAllocated; x++)
    832                                     ddi_intr_remove_handler(g_pIntr[x]);
     883                                else
     884                                    LogRel((DEVICE_NAME "::AddIRQ: failed to add high-level interrupt handler. rc=%d\n", rc));
     885
     886                                mutex_destroy(&g_HighLevelIrqMtx);
    833887                            }
    834888                            else
    835                                 LogRel((DEVICE_NAME "::AddIRQ: failed to get priority of interrupt. rc=%d\n", rc));
    836 
    837                             /* Remove allocated IRQs, too bad we can free only one handle at a time. */
    838                             for (int k = 0; k < g_cIntrAllocated; k++)
    839                                 ddi_intr_free(g_pIntr[k]);
    840                             g_cIntrAllocated = 0;
     889                            {
     890                                /* Interrupt handler runs at reschedulable level, initialize the mutex at the given priority. */
     891                                mutex_init(&g_IrqMtx, NULL /* pszDesc */, MUTEX_DRIVER, DDI_INTR_PRI(uIntrPriority));
     892
     893                                /* Assign interrupt handler function to the interrupt handle. */
     894                                rc = ddi_intr_add_handler(g_pahIntrs[0], (ddi_intr_handler_t *)vgdrvSolarisISR,
     895                                                          NULL /* pvArg1 */, NULL /* pvArg2 */);
     896                                if (rc == DDI_SUCCESS)
     897                                {
     898                                    /* Enable the interrupt. */
     899                                    rc = ddi_intr_enable(g_pahIntrs[0]);
     900                                    if (rc == DDI_SUCCESS)
     901                                        return rc;
     902
     903                                    LogRel((DEVICE_NAME "::AddIRQ: failed to enable interrupt. rc=%d\n", rc));
     904                                    mutex_destroy(&g_IrqMtx);
     905                                }
     906                            }
    841907                        }
    842908                        else
    843                             LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", IntrCount));
    844                         RTMemFree(g_pIntr);
     909                            LogRel((DEVICE_NAME "::AddIRQ: failed to get priority of interrupt. rc=%d\n", rc));
     910
     911                        Assert(cIntrAllocated == 1);
     912                        ddi_intr_free(g_pahIntrs[0]);
    845913                    }
    846914                    else
    847                         LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", IntrCount));
     915                        LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", cIntrCount));
     916                    RTMemFree(g_pahIntrs);
    848917                }
    849918                else
    850                     LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient available IRQs. rc=%d IntrAvail=%d\n", rc, IntrAvail));
     919                    LogRel((DEVICE_NAME "::AddIRQ: failed to allocated IRQs. count=%d\n", cIntrCount));
    851920            }
    852921            else
    853                 LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient number of IRQs. rc=%d IntrCount=%d\n", rc, IntrCount));
     922                LogRel((DEVICE_NAME "::AddIRQ: failed to get or insufficient number of IRQs. rc=%d cIntrCount=%d\n", rc, cIntrCount));
    854923        }
    855924        else
    856             LogRel((DEVICE_NAME "::AddIRQ: invalid irq type. IntrType=%#x\n", IntrType));
     925            LogRel((DEVICE_NAME "::AddIRQ: fixed-type interrupts not supported. IntrType=%#x\n", fIntrType));
    857926    }
    858927    else
    859         LogRel((DEVICE_NAME "::AddIRQ: failed to get supported interrupt types\n"));
     928        LogRel((DEVICE_NAME "::AddIRQ: failed to get supported interrupt types. rc=%d\n", rc));
    860929    return rc;
    861930}
     
    871940    LogFlow(("vgdrvSolarisRemoveIRQ:\n"));
    872941
    873     for (int i = 0; i < g_cIntrAllocated; i++)
    874     {
    875         int rc = ddi_intr_disable(g_pIntr[i]);
     942    int rc = ddi_intr_disable(g_pahIntrs[0]);
     943    if (rc == DDI_SUCCESS)
     944    {
     945        rc = ddi_intr_remove_handler(g_pahIntrs[0]);
    876946        if (rc == DDI_SUCCESS)
    877         {
    878             rc = ddi_intr_remove_handler(g_pIntr[i]);
    879             if (rc == DDI_SUCCESS)
    880                 ddi_intr_free(g_pIntr[i]);
    881         }
    882     }
    883     g_cIntrAllocated = 0;
    884     RTMemFree(g_pIntr);
     947            ddi_intr_free(g_pahIntrs[0]);
     948    }
     949
     950    if (g_fSoftIntRegistered)
     951    {
     952        ddi_intr_remove_softint(g_hSoftIntr);
     953        mutex_destroy(&g_HighLevelIrqMtx);
     954        g_fSoftIntRegistered = false;
     955    }
     956
    885957    mutex_destroy(&g_IrqMtx);
    886 }
    887 
    888 
    889 /**
    890  * Interrupt Service Routine for VMMDev.
     958    RTMemFree(g_pahIntrs);
     959}
     960
     961
     962/**
     963 * High-level Interrupt Service Routine for VMMDev.
     964 *
     965 * This routine simply dispatches a soft-interrupt at an acceptable IPL as
     966 * VGDrvCommonISR() cannot be called at a high IPL (scheduler level or higher)
     967 * due to pollwakeup() in VGDrvNativeISRMousePollEvent().
    891968 *
    892969 * @param   Arg     Private data (unused, will be NULL).
    893970 * @returns DDI_INTR_CLAIMED if it's our interrupt, DDI_INTR_UNCLAIMED if it isn't.
    894971 */
     972static uint_t vgdrvSolarisHighLevelISR(caddr_t Arg)
     973{
     974    bool const fOurIrq = VGDrvCommonIsOurISR(&g_DevExt);
     975    if (fOurIrq)
     976    {
     977        ddi_intr_trigger_softint(g_hSoftIntr, NULL /* Arg */);
     978        return DDI_INTR_CLAIMED;
     979    }
     980    return DDI_INTR_UNCLAIMED;
     981}
     982
     983
     984/**
     985 * Interrupt Service Routine for VMMDev.
     986 *
     987 * @param   Arg     Private data (unused, will be NULL).
     988 * @returns DDI_INTR_CLAIMED if it's our interrupt, DDI_INTR_UNCLAIMED if it isn't.
     989 */
    895990static uint_t vgdrvSolarisISR(caddr_t Arg)
    896991{
    897992    LogFlow(("vgdrvSolarisISR:\n"));
    898993
     994    /* The mutex is required to protect against parallel executions (if possible?) and also the
     995       mouse notify registeration race between VGDrvNativeSetMouseNotifyCallback() and VGDrvCommonISR(). */
    899996    mutex_enter(&g_IrqMtx);
    900997    bool fOurIRQ = VGDrvCommonISR(&g_DevExt);
     
    9051002
    9061003
     1004/**
     1005 * Poll notifier for mouse poll events.
     1006 *
     1007 * @param   pDevExt   Pointer to the device extension.
     1008 *
     1009 * @remarks This must be called without holding any spinlocks.
     1010 */
    9071011void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
    9081012{
     
    9161020
    9171021
     1022/**
     1023 * Sets the mouse notification callback.
     1024 *
     1025 * @returns VBox status code.
     1026 * @param   pDevExt   Pointer to the device extension.
     1027 * @param   pNotify   Pointer to the mouse notify struct.
     1028 */
     1029int VGDrvNativeSetMouseNotifyCallback(PVBOXGUESTDEVEXT pDevExt, VBoxGuestMouseSetNotifyCallback *pNotify)
     1030{
     1031    /* Take the mutex here so as to not race with VGDrvCommonISR() which invokes the mouse notify callback. */
     1032    mutex_enter(&g_IrqMtx);
     1033    pDevExt->MouseNotifyCallback = *pNotify;
     1034    mutex_exit(&g_IrqMtx);
     1035    return VINF_SUCCESS;
     1036}
     1037
     1038
    9181039/* Common code that depend on g_DevExt. */
    9191040#include "VBoxGuestIDC-unix.c.h"
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r63948 r64435  
    15601560    LogFlow(("VBOXGUEST_IOCTL_SET_MOUSE_NOTIFY_CALLBACK: pfnNotify=%p pvUser=%p\n", pNotify->pfnNotify, pNotify->pvUser));
    15611561
     1562#ifdef VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT
     1563    VGDrvNativeSetMouseNotifyCallback(pDevExt, pNotify);
     1564#else
    15621565    RTSpinlockAcquire(pDevExt->EventSpinlock);
    15631566    pDevExt->MouseNotifyCallback = *pNotify;
    15641567    RTSpinlockRelease(pDevExt->EventSpinlock);
     1568#endif
    15651569    return VINF_SUCCESS;
    15661570}
     
    36403644
    36413645/**
     3646 * Simply checks whether the IRQ is ours or not, does not do any interrupt
     3647 * procesing.
     3648 *
     3649 * @returns true if it was our interrupt, false if it wasn't.
     3650 * @param   pDevExt     The VBoxGuest device extension.
     3651 */
     3652bool VGDrvCommonIsOurISR(PVBOXGUESTDEVEXT pDevExt)
     3653{
     3654    RTSpinlockAcquire(pDevExt->EventSpinlock);
     3655    bool const fOurIrq = pDevExt->pVMMDevMemory->V.V1_04.fHaveEvents;
     3656    RTSpinlockRelease(pDevExt->EventSpinlock);
     3657
     3658    return fOurIrq;
     3659}
     3660
     3661
     3662/**
    36423663 * Common interrupt service routine.
    36433664 *
     
    36893710                fMousePositionChanged = true;
    36903711                fEvents &= ~VMMDEV_EVENT_MOUSE_POSITION_CHANGED;
    3691 #ifndef RT_OS_WINDOWS
     3712#if !defined(RT_OS_WINDOWS) && !defined(VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT)
    36923713                if (pDevExt->MouseNotifyCallback.pfnNotify)
    36933714                    pDevExt->MouseNotifyCallback.pfnNotify(pDevExt->MouseNotifyCallback.pvUser);
     
    37353756    RTSpinlockRelease(pDevExt->EventSpinlock);
    37363757
     3758    /*
     3759     * Execute the mouse notification callback here if it cannot be executed while
     3760     * holding the interrupt safe spinlock, see @bugref{8639}.
     3761     */
     3762#if defined(VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT)
     3763    if (   fMousePositionChanged
     3764        && pDevExt->MouseNotifyCallback.pfnNotify)
     3765        pDevExt->MouseNotifyCallback.pfnNotify(pDevExt->MouseNotifyCallback.pvUser);
     3766#endif
     3767
    37373768#if defined(VBOXGUEST_USE_DEFERRED_WAKE_UP) && !defined(RT_OS_DARWIN) && !defined(RT_OS_WINDOWS)
    37383769    /*
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h

    r62521 r64435  
    4343#endif
    4444
     45/** @def VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT
     46 * The mouse notification callback can cause preemption and must not be invoked
     47 * while holding a high-level spinlock.
     48 */
     49#if defined(RT_OS_SOLARIS)
     50# define VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT
     51#endif
    4552
    4653/** Pointer to the VBoxGuest per session data. */
     
    316323int  VGDrvCommonInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, void *pvMMIOBase, uint32_t cbMMIO,
    317324                           VBOXOSTYPE enmOSType, uint32_t fEvents);
     325bool VGDrvCommonIsOurISR(PVBOXGUESTDEVEXT pDevExt);
    318326bool VGDrvCommonISR(PVBOXGUESTDEVEXT pDevExt);
    319327void VGDrvCommonDeleteDevExt(PVBOXGUESTDEVEXT pDevExt);
     
    346354#endif
    347355
     356#ifdef VBOXGUEST_MOUSE_NOTIFY_CAN_PREEMPT
     357int VGDrvNativeSetMouseNotifyCallback(PVBOXGUESTDEVEXT pDevExt, VBoxGuestMouseSetNotifyCallback *pNotify);
     358#endif
     359
    348360RT_C_DECLS_END
    349361
Note: See TracChangeset for help on using the changeset viewer.

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