Esempio n. 1
0
int Block::mmSetPermission(uint64_t i_va, uint64_t i_size,
                           uint64_t i_access_type)
{
    int l_rc = 0;

    // Need to align the page address and the size on a page boundary.
    uint64_t l_aligned_va = ALIGN_PAGE_DOWN(i_va);
    uint64_t l_aligned_size = ALIGN_PAGE(i_size);


    if(!isContained(l_aligned_va))
    {
        return (iv_nextBlock ?
                iv_nextBlock->mmSetPermission(i_va,i_size,i_access_type) :
                -EINVAL);
    }

    //printk("\n             aligned VA = 0x%.lX aligned size = %ld access_type = 0x%.lX\n", l_aligned_va,	l_aligned_size, i_access_type);

    // if i_size is zero we are only updating 1 page; increment the size to
    // one page.
    if (i_size == 0)
    {
        l_aligned_size+=PAGESIZE;
    }

    // loop through all the pages asked for based on passed aligned
    // Virtual address and passed in aligned size.
    for(uint64_t cur_page_addr = l_aligned_va;
        cur_page_addr < (l_aligned_va + l_aligned_size);
        cur_page_addr += PAGESIZE)
    {

        ShadowPTE* spte = getPTE(cur_page_addr);

        // if the page present need to delete the hardware
        // page table entry before we set permissions.
        if (spte->isPresent())
        {
            // delete the hardware page table entry
            PageTableManager::delEntry(cur_page_addr);
        }

        if (setPermSPTE(spte, i_access_type))
        {
            printkd("               SET PERMISSIONS.. FAILED \n");
            return -EINVAL;
        }
    }

    return l_rc;
}
Esempio n. 2
0
int Block::removePages(VmmManager::PAGE_REMOVAL_OPS i_op, void* i_vaddr,
                                 uint64_t i_size, task_t* i_task)
{
    uint64_t l_vaddr = reinterpret_cast<uint64_t>(i_vaddr);
    //Align virtual address & size to page boundary
    /*The given virtual address will be 'rounded' down to the nearest page
      boundary, along with the given size will be 'rounded' up to the
      nearest divisible page size.*/
    uint64_t l_aligned_va = ALIGN_PAGE_DOWN(l_vaddr);
    uint64_t l_aligned_size = ALIGN_PAGE(i_size);
    //Find block containing virtual address
    if(!this->isContained(l_aligned_va))
    {
        return (iv_nextBlock ?
                iv_nextBlock->removePages(i_op,i_vaddr,i_size,i_task):-EINVAL);
    }
    else if ((l_aligned_va+l_aligned_size) > (this->iv_baseAddr+this->iv_size))
    {
        return -EINVAL;
    }

    //Perform requested page removal operation
    for (l_vaddr = l_aligned_va;l_vaddr < (l_aligned_va+l_aligned_size);
         l_vaddr+= PAGESIZE)
    {
        ShadowPTE* pte = getPTE(l_vaddr);
        uint64_t pageAddr = pte->getPageAddr();
        if (pte->isPresent() && (0 != pageAddr))
        {
            //Delete from HW page table immediately
            PageTableManager::delEntry(l_vaddr);
            if (pte->isDirty() && pte->isWriteTracked() &&
                this->iv_writeMsgHdlr != NULL)
            {
                releaseSPTE(pte);
                //Send write msg with the page address
                if (i_task != NULL)
                {
                    this->iv_writeMsgHdlr->incMsgCount(i_task);
                }

                this->iv_writeMsgHdlr->addVirtAddr(
                        reinterpret_cast<void*>(l_vaddr),pageAddr);
                this->iv_writeMsgHdlr->sendMessage(MSG_MM_RP_WRITE,
                        reinterpret_cast<void*>(l_vaddr),
                        reinterpret_cast<void*>(pageAddr),i_task);
            }
            else if (pte->isDirty() && !pte->isWriteTracked() &&
                     i_op == VmmManager::EVICT)
            {
                //Skip page
            }
            else if (i_op != VmmManager::FLUSH)
            {
                //'Release' page entry
                releaseSPTE(pte);
                PageManager::freePage(reinterpret_cast<void*>(pageAddr));

	    }
        }
    }
    return 0;
}
Esempio n. 3
0
/**
 * @brief Read the TOC and store section information
 */
errlHndl_t PnorRP::readTOC()
{
    TRACUCOMP(g_trac_pnor, "PnorRP::readTOC>" );
    errlHndl_t l_errhdl = NULL;
    uint8_t* tocBuffer = NULL;
    uint64_t fatal_error = 0;
    bool TOC_0_failed = false;

    do{
        iv_TOC_used = 0;

        for (uint32_t cur_TOC = 0; cur_TOC < NUM_TOCS; ++cur_TOC)
        {
            TRACFCOMP(g_trac_pnor, "PnorRP::readTOC verifying TOC: %d",cur_TOC);
            uint64_t nextVAddr = BASE_VADDR;

            // Zero out my table
            for( size_t id = PNOR::FIRST_SECTION;
                 id <= PNOR::NUM_SECTIONS; //include extra entry for error paths
                 ++id )
            {
                iv_TOC[id].id = (PNOR::SectionId)id;
                //everything else should default to zero
            }

            // Read TOC information from TOC 0 and then TOC 1
            tocBuffer = new uint8_t[PAGESIZE];
            if (cur_TOC == 0)
            {
                l_errhdl = readFromDevice( TOC_0_OFFSET, 0, false,
                                           tocBuffer, fatal_error );
            }
            else if (cur_TOC == 1)
            {
                l_errhdl = readFromDevice( TOC_1_OFFSET, 0, false,
                                           tocBuffer, fatal_error );
            }

            if( l_errhdl )
            {
                TRACFCOMP(g_trac_pnor, "PnorRP::readTOC readFromDevice Failed.");
                break;
            }

            ffs_hdr* l_ffs_hdr = (ffs_hdr*) tocBuffer;

            // ffs entry check, 0 if checksums match
            if( PNOR::pnor_ffs_checksum(l_ffs_hdr, FFS_HDR_SIZE) != 0)
            {
                //@TODO - RTC:90780 - May need to handle this differently in SP-less config
                TRACFCOMP(g_trac_pnor, "PnorRP::readTOC pnor_ffs_checksum header checksums do not match.");
                if (cur_TOC == 0)
                {
                    TRACFCOMP(g_trac_pnor, "PnorRP::readTOC TOC 0 failed header checksum");
                    TOC_0_failed = true;
                    iv_TOC_used = 1;
                    continue;
                }
                else if (cur_TOC == 1 && TOC_0_failed)
                {
                    // Both TOC's failed
                    TRACFCOMP(g_trac_pnor, "PnorRP::readTOC both TOC's are corrupted");
                    INITSERVICE::doShutdown( PNOR::RC_PARTITION_TABLE_INVALID);
                }
                else
                {
                    // TOC 1 failed
                    TRACFCOMP(g_trac_pnor, "PnorRP::readTOC TOC 1 failed header checksum");
                    break;
                }
            }

            // Only check header if on first TOC or the first TOC failed
            if (cur_TOC == 0 || TOC_0_failed)
            {
                TRACFCOMP(g_trac_pnor, "PnorRP::readTOC:  FFS Block size = 0x%.8X, Partition Table Size = 0x%.8x, entry_count=%d",
                          l_ffs_hdr->block_size, l_ffs_hdr->size, l_ffs_hdr->entry_count);

                uint64_t spaceUsed = (sizeof(ffs_entry))*l_ffs_hdr->entry_count;

                /* Checking FFS Header to make sure it looks valid */
                bool header_good = true;
                if(l_ffs_hdr->magic != FFS_MAGIC)
                {
                    TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC:  Invalid magic number in FFS header: 0x%.4X",
                              l_ffs_hdr->magic);
                    header_good = false;
                }
                else if(l_ffs_hdr->version != SUPPORTED_FFS_VERSION)
                {
                    TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC:  Unsupported FFS Header version: 0x%.4X",
                              l_ffs_hdr->version);
                    header_good = false;
                }
                else if(l_ffs_hdr->entry_size != sizeof(ffs_entry))
                {
                    TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC:  Unexpected entry_size(0x%.8x) in FFS header: 0x%.4X", l_ffs_hdr->entry_size);
                    header_good = false;
                }
                else if(l_ffs_hdr->entries == NULL)
                {
                    TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC:  FFS Header pointer to entries is NULL.");
                    header_good = false;
                }
                else if(l_ffs_hdr->block_size != PAGESIZE)
                {
                    TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC:  Unsupported Block Size(0x%.4X). PNOR Blocks must be 4k",
                              l_ffs_hdr->block_size);
                    header_good = false;
                }
                else if(l_ffs_hdr->block_count == 0)
                {
                    TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC:  Unsupported BLock COunt(0x%.4X). Device cannot be zero blocks in length.",
                              l_ffs_hdr->block_count);
                    header_good = false;
                }
                //Make sure all the entries fit in specified partition table size.
                else if(spaceUsed >
                        ((l_ffs_hdr->block_size * l_ffs_hdr->size) - sizeof(ffs_hdr)))
                {
                    TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC:  FFS Entries (0x%.16X) go past end of FFS Table.",
                              spaceUsed);
                    header_good = false;
                }

                if(!header_good)
                {
                    //Shutdown if we detected a partition table issue for any reason
                    if (TOC_0_failed)
                    {
                        INITSERVICE::doShutdown( PNOR::RC_PARTITION_TABLE_INVALID);
                    }
                    else
                    {
                        TOC_0_failed = true;
                    }
                    //Try TOC1
                    continue;
                }
            }

            ffs_hb_user_t* ffsUserData = NULL;

            //Walk through all the entries in the table and parse the data.
            for(uint32_t i=0; i<l_ffs_hdr->entry_count; i++)
            {
                ffs_entry* cur_entry = (&l_ffs_hdr->entries[i]);

                TRACUCOMP(g_trac_pnor, "PnorRP::readTOC:  Entry %d, name=%s, pointer=0x%X", i, cur_entry->name, (uint64_t)cur_entry);

                uint32_t secId = PNOR::INVALID_SECTION;

                // ffs entry check, 0 if checksums match
                if( PNOR::pnor_ffs_checksum(cur_entry, FFS_ENTRY_SIZE) != 0)
                {
                    //@TODO - RTC:90780 - May need to handle this differently in SP-less config
                    TRACFCOMP(g_trac_pnor, "PnorRP::readTOC pnor_ffs_checksum entry checksums do not match.");
                    if (cur_TOC == 0)
                    {
                        TRACFCOMP(g_trac_pnor, "PnorRP::readTOC TOC 0 entry checksum failed");
                        TOC_0_failed = true;
                        iv_TOC_used = 1;
                        break;
                    }
                    else if (cur_TOC == 1 && TOC_0_failed)
                    {
                        // Both TOC's failed
                        TRACFCOMP(g_trac_pnor, "PnorRP::readTOC both TOC's are corrupted");
                        INITSERVICE::doShutdown( PNOR::RC_PARTITION_TABLE_INVALID);
                    }
                    else
                    {
                        // TOC 1 failed
                        TRACFCOMP(g_trac_pnor, "PnorRP::readTOC TOC 1 entry checksum failed");
                        break;
                    }
                }

                // Only set data if on first TOC or the first TOC failed
                if (cur_TOC == 0 || TOC_0_failed)
                {
                    //Figure out section enum
                    for(uint32_t eyeIndex=PNOR::TOC; eyeIndex < PNOR::NUM_SECTIONS; eyeIndex++)
                    {
                        if(strcmp(cv_EYECATCHER[eyeIndex], cur_entry->name) == 0)
                        {
                            secId = eyeIndex;
                            TRACUCOMP(g_trac_pnor, "PnorRP::readTOC: sectionId=%d", secId);
                            break;
                        }
                    }

                    if(secId == PNOR::INVALID_SECTION)
                    {
                        TRACFCOMP(g_trac_pnor, "PnorRP::readTOC:  Unrecognized Section name(%s), skipping", cur_entry->name);
                        continue;
                    }

                    ffsUserData = (ffs_hb_user_t*)&(cur_entry->user);

                    //size
                    iv_TOC[secId].size = ((uint64_t)cur_entry->size)*PAGESIZE;

                    //virtAddr
                    iv_TOC[secId].virtAddr = nextVAddr;
                    nextVAddr += iv_TOC[secId].size;

                    //flashAddr
                    iv_TOC[secId].flashAddr = ((uint64_t)cur_entry->base)*PAGESIZE;

                    //chipSelect
                    iv_TOC[secId].chip = ffsUserData->chip;

                    //user data
                    iv_TOC[secId].integrity = ffsUserData->dataInteg;
                    iv_TOC[secId].version = ffsUserData->verCheck;
                    iv_TOC[secId].misc = ffsUserData->miscFlags;

                    TRACFCOMP(g_trac_pnor, "PnorRp::readTOC: User Data %s", cur_entry->name);

                    if (iv_TOC[secId].integrity == FFS_INTEG_ECC_PROTECT)
                    {
                        TRACFCOMP(g_trac_pnor, "PnorRP::readTOC: ECC enabled for %s", cur_entry->name);
                        iv_TOC[secId].size = ALIGN_PAGE_DOWN((iv_TOC[secId].size * 8 ) / 9);
                    }

                    // TODO RTC:96009 handle version header w/secureboot
                    if (iv_TOC[secId].version == FFS_VERS_SHA512)
                    {
                        TRACFCOMP(g_trac_pnor, "PnorRP::readTOC: Incrementing Flash Address for SHA Header");
                        if (iv_TOC[secId].integrity == FFS_INTEG_ECC_PROTECT)
                        {
                            iv_TOC[secId].flashAddr += PAGESIZE_PLUS_ECC;
                        }
                        else
                        {
                            iv_TOC[secId].flashAddr += PAGESIZE;
                        }
                    }

                    if((iv_TOC[secId].flashAddr + iv_TOC[secId].size) > (l_ffs_hdr->block_count*PAGESIZE))
                    {
                        TRACFCOMP(g_trac_pnor, "E>PnorRP::readTOC:  Partition(%s) at base address (0x%.8x) extends past end of flash device",
                                  cur_entry->name, iv_TOC[secId].flashAddr);
                        INITSERVICE::doShutdown( PNOR::RC_PARTITION_TABLE_INVALID);
                    }
                }
            }

            //keep these traces here until PNOR is rock-solid
            for(PNOR::SectionId tmpId = PNOR::FIRST_SECTION;
                tmpId < PNOR::NUM_SECTIONS;
                tmpId = (PNOR::SectionId) (tmpId + 1) )
            {
                TRACFCOMP(g_trac_pnor, "%s:    size=0x%.8X  flash=0x%.8X  virt=0x%.16X", cv_EYECATCHER[tmpId], iv_TOC[tmpId].size, iv_TOC[tmpId].flashAddr, iv_TOC[tmpId].virtAddr );
            }
        }
    }while(0);

    if(tocBuffer != NULL)
    {
        TRACUCOMP(g_trac_pnor, "Deleting tocBuffer");
        delete[] tocBuffer;
    }

    TRACUCOMP(g_trac_pnor, "< PnorRP::readTOC" );
    return l_errhdl;
}
Esempio n. 4
0
    void Daemon::pruneTraceEntries(bool i_all)
    {
        ComponentList::List::iterator component;

        size_t pruned = 0;

        // Iterate through the components...
        bool more = iv_service->iv_compList->first(component);
        while(more)
        {
            Entry* entry = component->iv_last;
            Entry* orig_entry = entry;

            // Invalidate entries until the component is small enough.
            while((entry) &&
                    ((component->iv_curSize > component->iv_maxSize) ||
                     i_all)
                 )
            {
                if (!reinterpret_cast<BufferPage*>(
                        ALIGN_PAGE_DOWN(
                            reinterpret_cast<uint64_t>(entry)))->commonPage)
                {
                    break;
                }

                entry->comp = NULL; // Invalidate entry.

                __sync_sub_and_fetch(&component->iv_curSize, entry->size);
                pruned += entry->size;

                entry = entry->prev;
            }

            if (entry != orig_entry)
            {
                printkd("%s,", component->iv_compName);

                // Break chain of linked list.
                if (entry != NULL)
                {
                    entry->next = NULL;
                }

                // Update component pointers.
                Buffer* b =
                    iv_service->iv_buffers[component->iv_bufferType];

                // consumerOp pseudo-code:
                //    if (entry == NULL) component->first = NULL;
                //    component->last = entry;
                b->consumerOp(&entry, NULL,
                              &component->iv_first, NULL,
                              &component->iv_last, entry);
            }

            // Get next component.
            more = iv_service->iv_compList->next(component);
        }

        // Record size of pruned entries in a global.
        if (pruned)
        {
            printkd(": pruned %ld\n", pruned);
            iv_totalPruned += pruned;
        }
    }
Esempio n. 5
0
HdatSpiraS::HdatSpiraS(const hdatMsAddr_t &i_msAddr)
: iv_spirasSize(0), iv_spiras(NULL)
{
    HDAT_ENTER();


    iv_spirasSize = sizeof(hdatSpiraS_t);


    uint64_t l_base_addr = ((uint64_t) i_msAddr.hi << 32) | i_msAddr.lo;

    HDAT_DBG("l_base_addr at SPIRA-S=0x%016llX",l_base_addr);


    //calculate the hrmor and add to base address
    TARGETING::Target * sys = NULL;
    TARGETING::targetService().getTopLevelTarget( sys );

    assert(sys != NULL);

    uint64_t l_hrmor =
                   sys->getAttr<TARGETING::ATTR_PAYLOAD_BASE>()*MEGABYTE;

    HDAT_DBG("HRMOR=0x%08x",l_hrmor);

    l_base_addr = l_hrmor + l_base_addr;

    HDAT_DBG("base address after adding HRMOR=0x%08x",l_base_addr);

    uint64_t l_base_addr_down = ALIGN_PAGE_DOWN(l_base_addr);
    HDAT_DBG("l_base_addr_down=0x%016llX",l_base_addr_down);

    HDAT_DBG("reqd space=0x%x, will do a block map of size 0x%x",
             iv_spirasSize, ALIGN_PAGE(iv_spirasSize));


    void *l_virt_addr = mm_block_map( reinterpret_cast<void*>(l_base_addr_down),
                        ALIGN_PAGE(iv_spirasSize) + PAGESIZE);

    HDAT_DBG("l_virt_addr=0x%016llX after block map",l_virt_addr);

    uint64_t l_vaddr = reinterpret_cast<uint64_t>(l_virt_addr);

    HDAT_DBG("will add offset %x to starting virtual address",
             (l_base_addr-l_base_addr_down));

    l_vaddr += l_base_addr-l_base_addr_down;

    HDAT_DBG("l_vaddr after adding=0x%016llX",l_vaddr);

    l_virt_addr = reinterpret_cast<void *>(l_vaddr);
    HDAT_DBG("l_virt_addr=0x%016llX",l_virt_addr);



    iv_spiras = reinterpret_cast<hdatSpiraS_t *>(l_virt_addr);

    HDAT_DBG("constructor iv_spiras addr 0x%016llX virtual addr 0x%016llX,space"
             " allocated=0x%x",(uint64_t) this->iv_spiras,
             (uint64_t)l_virt_addr,iv_spirasSize);

    HDAT_DBG("creating SPIRA-S header");
    setSpiraSHdrs();

    HDAT_DBG("done setting the SPIRA-S header");


    iv_spiras->hdatHDIF.hdatSize   = sizeof(hdatSpira_t);

    HDAT_EXIT();

    return;
}