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; }
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; }
/** * @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; }
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; } }
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; }