VirtualBox

Changeset 39920 in vbox for trunk


Ignore:
Timestamp:
Jan 31, 2012 2:55:13 PM (13 years ago)
Author:
vboxsync
Message:

GMM/PageFusion: Some cleanups (elimiated gotos) and more detailed assertions.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/gmm.h

    r39917 r39920  
    617617{
    618618    /** Region base address. */
    619     RTGCPTR64           GCRegionAddr;
     619    RTGCPTR64                   GCRegionAddr;
    620620    /** Region size. */
    621     uint32_t            cbRegion;
     621    uint32_t                    cbRegion;
    622622    /** Alignment. */
    623     uint32_t            u32Alignment;
    624     /** Pointer to physical page id array. */
    625     uint32_t           *paHCPhysPageID;
     623    uint32_t                    u32Alignment;
     624    /** Pointer to physical GMM page ID array. */
     625    uint32_t                   *paidPages;
    626626} GMMSHAREDREGIONDESC;
    627627/** Pointer to a GMMSHAREDREGIONDESC. */
     
    664664    RTGCPHYS                    GCPhys;
    665665    /** GMM page id. (in/out) */
    666     uint32_t                    uHCPhysPageId;
     666    uint32_t                    idPage;
    667667    /** Align at 8 byte boundary. */
    668668    uint32_t                    uAlignment;
     
    671671typedef GMMSHAREDPAGEDESC *PGMMSHAREDPAGEDESC;
    672672
    673 GMMR0DECL(int) GMMR0SharedModuleCheckPage(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned idxPage, PGMMSHAREDPAGEDESC pPageDesc);
     673GMMR0DECL(int) GMMR0SharedModuleCheckPage(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned idxPage,
     674                                          PGMMSHAREDPAGEDESC pPageDesc);
    674675
    675676/**
  • trunk/src/VBox/VMM/VMMR0/GMMR0.cpp

    r39917 r39920  
    42174217            for (unsigned i = 0; i < cRegions; i++)
    42184218            {
    4219                 pRecVM->aRegions[i].GCRegionAddr      = pRegions[i].GCRegionAddr;
    4220                 pRecVM->aRegions[i].cbRegion          = RT_ALIGN_T(pRegions[i].cbRegion, PAGE_SIZE, uint32_t);
    4221                 pRecVM->aRegions[i].u32Alignment      = 0;
    4222                 pRecVM->aRegions[i].paHCPhysPageID    = NULL; /* unused */
     4219                pRecVM->aRegions[i].GCRegionAddr    = pRegions[i].GCRegionAddr;
     4220                pRecVM->aRegions[i].cbRegion        = RT_ALIGN_T(pRegions[i].cbRegion, PAGE_SIZE, uint32_t);
     4221                pRecVM->aRegions[i].u32Alignment    = 0;
     4222                pRecVM->aRegions[i].paidPages       = NULL; /* unused */
    42234223            }
    42244224
     
    42834283            {
    42844284                Log(("New region %d base=%RGv size %x\n", i, pRegions[i].GCRegionAddr, pRegions[i].cbRegion));
    4285                 pGlobalModule->aRegions[i].GCRegionAddr      = pRegions[i].GCRegionAddr;
    4286                 pGlobalModule->aRegions[i].cbRegion          = RT_ALIGN_T(pRegions[i].cbRegion, PAGE_SIZE, uint32_t);
    4287                 pGlobalModule->aRegions[i].u32Alignment      = 0;
    4288                 pGlobalModule->aRegions[i].paHCPhysPageID    = NULL; /* uninitialized. */
     4285                pGlobalModule->aRegions[i].GCRegionAddr = pRegions[i].GCRegionAddr;
     4286                pGlobalModule->aRegions[i].cbRegion     = RT_ALIGN_T(pRegions[i].cbRegion, PAGE_SIZE, uint32_t);
     4287                pGlobalModule->aRegions[i].u32Alignment = 0;
     4288                pGlobalModule->aRegions[i].paidPages    = NULL; /* uninitialized. */
    42894289            }
    42904290
     
    44184418                    if (pRec->cUsers == 0)
    44194419                    {
    4420                         /* Free the ranges, but leave the pages intact as there might still be references; they will be cleared by the COW mechanism. */
    4421                         for (unsigned i = 0; i < pRec->cRegions; i++)
    4422                             if (pRec->aRegions[i].paHCPhysPageID)
    4423                                 RTMemFree(pRec->aRegions[i].paHCPhysPageID);
     4420                        /* Free the ranges, but leave the pages intact as there
     4421                           might still be references; they will be cleared by
     4422                           the COW mechanism. */
     4423                        for (uint32_t i = 0; i < pRec->cRegions; i++)
     4424                        {
     4425                            RTMemFree(pRec->aRegions[i].paidPages);
     4426                            pRec->aRegions[i].paidPages = NULL;
     4427                        }
    44244428
    44254429                        Assert(pRec->Core.Key == GCBaseAddr || pRec->enmGuestOS == VBOXOSFAMILY_Windows64);
    44264430                        Assert(pRec->cRegions == pRecVM->cRegions);
    44274431#ifdef VBOX_STRICT
    4428                         for (unsigned i = 0; i < pRecVM->cRegions; i++)
     4432                        for (uint32_t i = 0; i < pRecVM->cRegions; i++)
    44294433                        {
    44304434                            Assert(pRecVM->aRegions[i].GCRegionAddr == pRec->aRegions[i].GCRegionAddr);
     
    45404544
    45414545
     4546static int gmmR0SharedModuleCheckPageFirstTime(PGMM pGMM, PGVM pGVM, PGMMSHAREDMODULE pModule,
     4547                                               unsigned idxRegion, unsigned idxPage,
     4548                                               PGMMSHAREDPAGEDESC pPageDesc, PGMMSHAREDREGIONDESC pGlobalRegion)
     4549{
     4550    /* Easy case: just change the internal page type. */
     4551    PGMMPAGE pPage = gmmR0GetPage(pGMM, pPageDesc->idPage);
     4552    AssertMsgReturn(pPage, ("idPage=%#x (GCPhys=%RGp HCPhys=%RHp idxRegion=%#x idxPage=%#x) #1\n",
     4553                            pPageDesc->idPage, pPageDesc->GCPhys, pPageDesc->HCPhys, idxRegion, idxPage),
     4554                    VERR_PGM_PHYS_INVALID_PAGE_ID);
     4555
     4556    AssertMsg(pPageDesc->GCPhys == (pPage->Private.pfn << 12), ("desc %RGp gmm %RGp\n", pPageDesc->HCPhys, (pPage->Private.pfn << 12)));
     4557
     4558    gmmR0ConvertToSharedPage(pGMM, pGVM, pPageDesc->HCPhys, pPageDesc->idPage, pPage);
     4559
     4560    /* Keep track of these references. */
     4561    pGlobalRegion->paidPages[idxPage] = pPageDesc->idPage;
     4562
     4563    return VINF_SUCCESS;
     4564}
     4565
    45424566/**
    45434567 * Checks specified shared module range for changes
     
    45634587                                          PGMMSHAREDPAGEDESC pPageDesc)
    45644588{
    4565     int rc = VINF_SUCCESS;
     4589    int rc;
    45664590    PGMM pGMM;
    45674591    GMM_GET_VALID_INSTANCE(pGMM, VERR_GMM_INSTANCE);
    4568     unsigned cPages = pModule->aRegions[idxRegion].cbRegion >> PAGE_SHIFT;
    4569 
    4570     AssertReturn(idxRegion < pModule->cRegions, VERR_INVALID_PARAMETER);
    4571     AssertReturn(idxPage < cPages, VERR_INVALID_PARAMETER);
     4592
     4593    AssertMsgReturn(idxRegion < pModule->cRegions,
     4594                    ("idxRegion=%#x cRegions=%#x %s %s\n", idxRegion, pModule->cRegions, pModule->szName, pModule->szVersion),
     4595                    VERR_INVALID_PARAMETER);
     4596
     4597    unsigned const cPages = pModule->aRegions[idxRegion].cbRegion >> PAGE_SHIFT;
     4598    AssertMsgReturn(idxPage < cPages,
     4599                    ("idxRegion=%#x cRegions=%#x %s %s\n", idxRegion, pModule->cRegions, pModule->szName, pModule->szVersion),
     4600                    VERR_INVALID_PARAMETER);
    45724601
    45734602    LogFlow(("GMMR0SharedModuleCheckRange %s base %RGv region %d idxPage %d\n", pModule->szName, pModule->Core.Key, idxRegion, idxPage));
    45744603
     4604    /*
     4605     * First time; create a page descriptor array.
     4606     */
    45754607    PGMMSHAREDREGIONDESC pGlobalRegion = &pModule->aRegions[idxRegion];
    4576     if (!pGlobalRegion->paHCPhysPageID)
    4577     {
    4578         /* First time; create a page descriptor array. */
     4608    if (!pGlobalRegion->paidPages)
     4609    {
    45794610        Log(("Allocate page descriptor array for %d pages\n", cPages));
    4580         pGlobalRegion->paHCPhysPageID = (uint32_t *)RTMemAlloc(cPages * sizeof(*pGlobalRegion->paHCPhysPageID));
    4581         if (!pGlobalRegion->paHCPhysPageID)
    4582         {
    4583             AssertFailed();
    4584             rc = VERR_NO_MEMORY;
    4585             goto end;
    4586         }
     4611        pGlobalRegion->paidPages = (uint32_t *)RTMemAlloc(cPages * sizeof(pGlobalRegion->paidPages[0]));
     4612        AssertReturn(pGlobalRegion->paidPages, VERR_NO_MEMORY);
     4613
    45874614        /* Invalidate all descriptors. */
    45884615        for (unsigned i = 0; i < cPages; i++)
    4589             pGlobalRegion->paHCPhysPageID[i] = NIL_GMM_PAGEID;
    4590     }
    4591 
    4592     /* We've seen this shared page for the first time? */
    4593     if (pGlobalRegion->paHCPhysPageID[idxPage] == NIL_GMM_PAGEID)
    4594     {
    4595 new_shared_page:
     4616            pGlobalRegion->paidPages[i] = NIL_GMM_PAGEID;
     4617    }
     4618
     4619    /*
     4620     * We've seen this shared page for the first time?
     4621     */
     4622    if (pGlobalRegion->paidPages[idxPage] == NIL_GMM_PAGEID)
     4623    {
    45964624        Log(("New shared page guest %RGp host %RHp\n", pPageDesc->GCPhys, pPageDesc->HCPhys));
    4597 
    4598         /* Easy case: just change the internal page type. */
    4599         PGMMPAGE pPage = gmmR0GetPage(pGMM, pPageDesc->uHCPhysPageId);
    4600         if (!pPage)
    4601         {
    4602             Log(("GMMR0SharedModuleCheckPage: Invalid idPage=%#x #1 (GCPhys=%RGp HCPhys=%RHp idxRegion=%#x idxPage=%#x)\n",
    4603                  pPageDesc->uHCPhysPageId, pPageDesc->GCPhys, pPageDesc->HCPhys, idxRegion, idxPage));
    4604             AssertFailed();
    4605             rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    4606             goto end;
    4607         }
    4608 
    4609         AssertMsg(pPageDesc->GCPhys == (pPage->Private.pfn << 12), ("desc %RGp gmm %RGp\n", pPageDesc->HCPhys, (pPage->Private.pfn << 12)));
    4610 
    4611         gmmR0ConvertToSharedPage(pGMM, pGVM, pPageDesc->HCPhys, pPageDesc->uHCPhysPageId, pPage);
    4612 
    4613         /* Keep track of these references. */
    4614         pGlobalRegion->paHCPhysPageID[idxPage] = pPageDesc->uHCPhysPageId;
    4615     }
    4616     else
    4617     {
    4618         uint8_t  *pbLocalPage, *pbSharedPage;
    4619         uint8_t  *pbChunk;
    4620         PGMMCHUNK pChunk;
    4621 
    4622         Assert(pPageDesc->uHCPhysPageId != pGlobalRegion->paHCPhysPageID[idxPage]);
    4623 
    4624         Log(("Replace existing page guest %RGp host %RHp id %x -> id %x\n", pPageDesc->GCPhys, pPageDesc->HCPhys, pPageDesc->uHCPhysPageId, pGlobalRegion->paHCPhysPageID[idxPage]));
    4625 
    4626         /* Get the shared page source. */
    4627         PGMMPAGE pPage = gmmR0GetPage(pGMM, pGlobalRegion->paHCPhysPageID[idxPage]);
    4628         if (!pPage)
    4629         {
    4630             Log(("GMMR0SharedModuleCheckPage: Invalid idPage=%#x #2 (idxRegion=%#x idxPage=%#x)\n",
    4631                  pPageDesc->uHCPhysPageId, idxRegion, idxPage));
    4632             AssertFailed();
    4633             rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    4634             goto end;
    4635         }
    4636         if (pPage->Common.u2State != GMM_PAGE_STATE_SHARED)
    4637         {
    4638             /* Page was freed at some point; invalidate this entry. */
    4639             /** @todo this isn't really bullet proof. */
    4640             Log(("Old shared page was freed -> create a new one\n"));
    4641             pGlobalRegion->paHCPhysPageID[idxPage] = NIL_GMM_PAGEID;
    4642             goto new_shared_page; /* ugly goto */
    4643         }
    4644 
    4645         Log(("Replace existing page guest host %RHp -> %RHp\n", pPageDesc->HCPhys, ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT));
    4646 
    4647         /* Calculate the virtual address of the local page. */
    4648         pChunk = gmmR0GetChunk(pGMM, pPageDesc->uHCPhysPageId >> GMM_CHUNKID_SHIFT);
    4649         if (pChunk)
    4650         {
    4651             if (!gmmR0IsChunkMapped(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk))
    4652             {
    4653                 Log(("GMMR0SharedModuleCheckPage: Invalid idPage=%#x #3\n", pPageDesc->uHCPhysPageId));
    4654                 AssertFailed();
    4655                 rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    4656                 goto end;
    4657             }
    4658             pbLocalPage = pbChunk + ((pPageDesc->uHCPhysPageId & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
    4659         }
    4660         else
    4661         {
    4662             Log(("GMMR0SharedModuleCheckPage: Invalid idPage=%#x #4\n", pPageDesc->uHCPhysPageId));
    4663             AssertFailed();
    4664             rc = VERR_PGM_PHYS_INVALID_PAGE_ID;
    4665             goto end;
    4666         }
    4667 
    4668         /* Calculate the virtual address of the shared page. */
    4669         pChunk = gmmR0GetChunk(pGMM, pGlobalRegion->paHCPhysPageID[idxPage] >> GMM_CHUNKID_SHIFT);
    4670         Assert(pChunk); /* can't fail as gmmR0GetPage succeeded. */
    4671 
    4672         /* Get the virtual address of the physical page; map the chunk into the VM process if not already done. */
    4673         if (!gmmR0IsChunkMapped(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk))
    4674         {
    4675             Log(("Map chunk into process!\n"));
    4676             rc = gmmR0MapChunk(pGMM, pGVM, pChunk, false /*fRelaxedSem*/, (PRTR3PTR)&pbChunk);
    4677             if (rc != VINF_SUCCESS)
    4678             {
    4679                 AssertRC(rc);
    4680                 goto end;
    4681             }
    4682         }
    4683         pbSharedPage = pbChunk + ((pGlobalRegion->paHCPhysPageID[idxPage] & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
    4684 
    4685         /** @todo write ASMMemComparePage. */
    4686         if (memcmp(pbSharedPage, pbLocalPage, PAGE_SIZE))
    4687         {
    4688             Log(("Unexpected differences found between local and shared page; skip\n"));
    4689             /* Signal to the caller that this one hasn't changed. */
    4690             pPageDesc->uHCPhysPageId = NIL_GMM_PAGEID;
    4691             goto end;
    4692         }
    4693 
    4694         /* Free the old local page. */
    4695         GMMFREEPAGEDESC PageDesc;
    4696 
    4697         PageDesc.idPage = pPageDesc->uHCPhysPageId;
    4698         rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE);
     4625        return gmmR0SharedModuleCheckPageFirstTime(pGMM, pGVM, pModule, idxRegion, idxPage, pPageDesc, pGlobalRegion);
     4626    }
     4627
     4628    /*
     4629     * We've seen it before...
     4630     */
     4631    Log(("Replace existing page guest %RGp host %RHp id %#x -> id %#x\n",
     4632         pPageDesc->GCPhys, pPageDesc->HCPhys, pPageDesc->idPage, pGlobalRegion->paidPages[idxPage]));
     4633    Assert(pPageDesc->idPage != pGlobalRegion->paidPages[idxPage]);
     4634
     4635    /*
     4636     * Get the shared page source.
     4637     */
     4638    PGMMPAGE pPage = gmmR0GetPage(pGMM, pGlobalRegion->paidPages[idxPage]);
     4639    AssertMsgReturn(pPage, ("idPage=%#x (idxRegion=%#x idxPage=%#x) #2\n", pPageDesc->idPage, idxRegion, idxPage),
     4640                    VERR_PGM_PHYS_INVALID_PAGE_ID);
     4641
     4642    if (pPage->Common.u2State != GMM_PAGE_STATE_SHARED)
     4643    {
     4644        /*
     4645         * Page was freed at some point; invalidate this entry.
     4646         */
     4647        /** @todo this isn't really bullet proof. */
     4648        Log(("Old shared page was freed -> create a new one\n"));
     4649        pGlobalRegion->paidPages[idxPage] = NIL_GMM_PAGEID;
     4650        return gmmR0SharedModuleCheckPageFirstTime(pGMM, pGVM, pModule, idxRegion, idxPage, pPageDesc, pGlobalRegion);
     4651    }
     4652
     4653    Log(("Replace existing page guest host %RHp -> %RHp\n", pPageDesc->HCPhys, ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT));
     4654
     4655    /*
     4656     * Calculate the virtual address of the local page.
     4657     */
     4658    PGMMCHUNK pChunk = gmmR0GetChunk(pGMM, pPageDesc->idPage >> GMM_CHUNKID_SHIFT);
     4659    AssertMsgReturn(pChunk, ("idPage=%#x (idxRegion=%#x idxPage=%#x) #4\n", pPageDesc->idPage, idxRegion, idxPage),
     4660                    VERR_PGM_PHYS_INVALID_PAGE_ID);
     4661
     4662    uint8_t *pbChunk;
     4663    AssertMsgReturn(gmmR0IsChunkMapped(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk),
     4664                    ("idPage=%#x (idxRegion=%#x idxPage=%#x) #3\n", pPageDesc->idPage, idxRegion, idxPage),
     4665                    VERR_PGM_PHYS_INVALID_PAGE_ID);
     4666    uint8_t  *pbLocalPage = pbChunk + ((pPageDesc->idPage & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
     4667
     4668    /*
     4669     * Calculate the virtual address of the shared page.
     4670     */
     4671    pChunk = gmmR0GetChunk(pGMM, pGlobalRegion->paidPages[idxPage] >> GMM_CHUNKID_SHIFT);
     4672    Assert(pChunk); /* can't fail as gmmR0GetPage succeeded. */
     4673
     4674    /*
     4675     * Get the virtual address of the physical page; map the chunk into the VM
     4676     * process if not already done.
     4677     */
     4678    if (!gmmR0IsChunkMapped(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk))
     4679    {
     4680        Log(("Map chunk into process!\n"));
     4681        rc = gmmR0MapChunk(pGMM, pGVM, pChunk, false /*fRelaxedSem*/, (PRTR3PTR)&pbChunk);
    46994682        AssertRCReturn(rc, rc);
    4700 
    4701         gmmR0UseSharedPage(pGMM, pGVM, pPage);
    4702 
    4703         /* Pass along the new physical address & page id. */
    4704         pPageDesc->HCPhys        = ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT;
    4705         pPageDesc->uHCPhysPageId = pGlobalRegion->paHCPhysPageID[idxPage];
    4706     }
    4707 end:
    4708     return rc;
     4683    }
     4684    uint8_t *pbSharedPage = pbChunk + ((pGlobalRegion->paidPages[idxPage] & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT);
     4685
     4686    /** @todo write ASMMemComparePage. */
     4687    if (memcmp(pbSharedPage, pbLocalPage, PAGE_SIZE))
     4688    {
     4689        Log(("Unexpected differences found between local and shared page; skip\n"));
     4690        /* Signal to the caller that this one hasn't changed. */
     4691        pPageDesc->idPage = NIL_GMM_PAGEID;
     4692        return VINF_SUCCESS;
     4693    }
     4694
     4695    /*
     4696     * Free the old local page.
     4697     */
     4698    GMMFREEPAGEDESC PageDesc;
     4699    PageDesc.idPage = pPageDesc->idPage;
     4700    rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE);
     4701    AssertRCReturn(rc, rc);
     4702
     4703    gmmR0UseSharedPage(pGMM, pGVM, pPage);
     4704
     4705    /*
     4706     * Pass along the new physical address & page id.
     4707     */
     4708    pPageDesc->HCPhys = ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT;
     4709    pPageDesc->idPage = pGlobalRegion->paidPages[idxPage];
     4710
     4711    return VINF_SUCCESS;
    47094712}
    47104713
     
    47344737        {
    47354738            for (uint32_t i = 0; i < pRec->cRegions; i++)
    4736                 if (pRec->aRegions[i].paHCPhysPageID)
    4737                     RTMemFree(pRec->aRegions[i].paHCPhysPageID);
     4739            {
     4740                RTMemFree(pRec->aRegions[i].paidPages);
     4741                pRec->aRegions[i].paidPages = NULL;
     4742            }
    47384743
    47394744            /* Remove from the tree and free memory. */
  • trunk/src/VBox/VMM/VMMR0/PGMR0SharedPage.cpp

    r39909 r39920  
    8181                    &&  PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED)
    8282                {
    83                     PageDesc.uHCPhysPageId = PGM_PAGE_GET_PAGEID(pPage);
    84                     PageDesc.HCPhys        = PGM_PAGE_GET_HCPHYS(pPage);
    85                     PageDesc.GCPhys        = GCPhys;
     83                    PageDesc.idPage = PGM_PAGE_GET_PAGEID(pPage);
     84                    PageDesc.HCPhys = PGM_PAGE_GET_HCPHYS(pPage);
     85                    PageDesc.GCPhys = GCPhys;
    8686
    8787                    rc = GMMR0SharedModuleCheckPage(pGVM, pModule, idxRegion, idxPage, &PageDesc);
     
    8989                    {
    9090                        /* Any change for this page? */
    91                         if (PageDesc.uHCPhysPageId != NIL_GMM_PAGEID)
     91                        if (PageDesc.idPage != NIL_GMM_PAGEID)
    9292                        {
    9393                            Assert(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED);
     
    106106                                /* Update the physical address and page id now. */
    107107                                PGM_PAGE_SET_HCPHYS(pVM, pPage, PageDesc.HCPhys);
    108                                 PGM_PAGE_SET_PAGEID(pVM, pPage, PageDesc.uHCPhysPageId);
     108                                PGM_PAGE_SET_PAGEID(pVM, pPage, PageDesc.idPage);
    109109
    110110                                /* Invalidate page map TLB entry for this page too. */
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