diff options
author | Missy Connell <missyc@us.ibm.com> | 2011-10-25 11:12:55 -0500 |
---|---|---|
committer | Melissa J. Connell <missyc@us.ibm.com> | 2011-10-27 15:56:31 -0500 |
commit | 9e86b070a4429e7db34a5438611a67098ab92dfb (patch) | |
tree | 52e04b08288a7496359c41eff98e8463e73ae5dc /src/kernel | |
parent | 71564141e3a6c7f023a9484549baf319f0e1807e (diff) | |
download | talos-hostboot-9e86b070a4429e7db34a5438611a67098ab92dfb.tar.gz talos-hostboot-9e86b070a4429e7db34a5438611a67098ab92dfb.zip |
Full permissions with no_access as default
MERGED changes.. only need Patrick and Mark to review extintsvctasks.H
Change-Id: Iba5814e1b5913c6181a2be96df9682555fa2ab58
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/458
Tested-by: Jenkins Server
Reviewed-by: Melissa J. Connell <missyc@us.ibm.com>
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/basesegment.C | 41 | ||||
-rw-r--r-- | src/kernel/block.C | 427 | ||||
-rw-r--r-- | src/kernel/blockmsghdlr.C | 9 | ||||
-rw-r--r-- | src/kernel/devicesegment.C | 2 | ||||
-rw-r--r-- | src/kernel/ptmgr.C | 177 | ||||
-rw-r--r-- | src/kernel/stacksegment.C | 3 |
6 files changed, 399 insertions, 260 deletions
diff --git a/src/kernel/basesegment.C b/src/kernel/basesegment.C index e55c3b735..7b33eed7a 100644 --- a/src/kernel/basesegment.C +++ b/src/kernel/basesegment.C @@ -80,14 +80,14 @@ void BaseSegment::_init() // Set pages in kernel text section to be read-only / executable. if (((uint64_t)&data_load_address) > i) { - iv_block->setPhysicalPage(i, i, VmmManager::RO_EXE_ACCESS); + // Set the Text section to Excutable (implies read) + iv_block->setPhysicalPage(i, i, EXECUTABLE); } // Set all other pages to initially be read/write. VFS will set // permissions on pages outside kernel. - // (@TODO: Future Sprint, for now keep NORMAL_ACCESS as RWX, not RW.) else { - iv_block->setPhysicalPage(i, i, VmmManager::NORMAL_ACCESS); + iv_block->setPhysicalPage(i, i, WRITABLE); } } } @@ -164,39 +164,10 @@ int BaseSegment::mmSetPermission(void* i_va, uint64_t i_size, uint64_t i_access_ */ int BaseSegment::_mmSetPermission(void* i_va, uint64_t i_size, uint64_t i_access_type) { - int l_rc = 0; - Block *l_block = iv_block; - uint64_t l_va = reinterpret_cast<uint64_t>(i_va); - - - do - { - // If the va is not part of this block - if (!(l_block->isContained(l_va))) - { - // Check to see if there is a next block - if (l_block->iv_nextBlock) - { - // set local block to the next block - l_block = l_block->iv_nextBlock; - } - else - { - // address passed in does not fall into a block - return -EINVAL; - } - } - // The virtual address falls within this block - else - { - // Set the permission on the the current block. - return(l_block->mmSetPermission(l_va, i_size, i_access_type)); - - } - } while (l_block); - - return l_rc; + Block *l_block = iv_block; + uint64_t l_va = reinterpret_cast<uint64_t>(i_va); + return (l_block->mmSetPermission(l_va, i_size, i_access_type)); } void BaseSegment::castOutPages(uint64_t i_type) diff --git a/src/kernel/block.C b/src/kernel/block.C index bdec164de..40706ba48 100644 --- a/src/kernel/block.C +++ b/src/kernel/block.C @@ -36,6 +36,7 @@ #include <kernel/pagemgr.H> #include <kernel/console.H> #include <util/align.H> +#include <kernel/basesegment.H> Block::~Block() { @@ -86,6 +87,20 @@ bool Block::handlePageFault(task_t* i_task, uint64_t i_addr) ShadowPTE* pte = getPTE(l_addr_palign); + // TODO... have this commented out at this point because + // checking this here causes the vmmbasetest.H testcases + // to fail... Need to determine how you want the + // NULL condition and the printk testcases handled in the + // testcase or change their default values. + + // If the page table entry has default permission settings +/* if (getPermission(pte) == NO_ACCESS) + { + printk("NO_ACCESS permission for addr 0x%.lX\n", i_addr); + return -EINVAL; + } */ + + if (!pte->isPresent()) { if (this->iv_readMsgHdlr != NULL) @@ -97,11 +112,9 @@ bool Block::handlePageFault(task_t* i_task, uint64_t i_addr) l_page = PageManager::allocatePage(); //Add to ShadowPTE pte->setPageAddr(reinterpret_cast<uint64_t>(l_page)); - //TODO - Update to correct permissions requested - pte->setExecutable(false); - pte->setWritable(true); } - //Send message to handler to read page + + this->iv_readMsgHdlr->sendMessage(MSG_MM_RP_READ, reinterpret_cast<void*>(l_addr_palign),l_page,i_task); //Done(waiting for response) @@ -114,6 +127,12 @@ bool Block::handlePageFault(task_t* i_task, uint64_t i_addr) pte->setPageAddr(reinterpret_cast<uint64_t>(l_page)); pte->setPresent(true); + + // TODO.. add this and test it.. + /* if (BaseSegment::mmSetPermission(reinterpret_cast<void*>(l_page), 0, NO_ACCESS)) + { + printk(" Got an error trying to set permissions in handle page fault\n"); + } */ } else { @@ -125,16 +144,16 @@ bool Block::handlePageFault(task_t* i_task, uint64_t i_addr) PageTableManager::addEntry( l_addr_palign, pte->getPage(), - (pte->isExecutable() ? VmmManager::RO_EXE_ACCESS : - (pte->isWritable() ? VmmManager::NORMAL_ACCESS : - VmmManager::READ_O_ACCESS))); + (pte->isExecutable() ? EXECUTABLE : + (pte->isWritable() ? WRITABLE : + READ_ONLY))); return true; } void Block::setPhysicalPage(uint64_t i_vAddr, uint64_t i_pAddr, - VmmManager::ACCESS_TYPES i_access) + uint64_t i_access) { // Check containment, call down chain if address isn't in this block. if (!isContained(i_vAddr)) @@ -168,32 +187,17 @@ void Block::setPhysicalPage(uint64_t i_vAddr, uint64_t i_pAddr, PageTableManager::delEntry(i_vAddr); } - switch(i_access) - { - case VmmManager::READ_O_ACCESS: - pte->setReadable(true); - pte->setExecutable(false); - pte->setWritable(false); - break; - - case VmmManager::NORMAL_ACCESS: - pte->setReadable(true); - pte->setExecutable(false); - pte->setWritable(true); - break; - - case VmmManager::RO_EXE_ACCESS: - pte->setReadable(true); - pte->setExecutable(true); - pte->setWritable(false); - break; - default: - kassert(false); - break; + // make a call that sets the permssions on a + // shadow page table entry + if (setPermSPTE(pte, i_access)) + { + kassert(false); } + } + void Block::setIsPresent(void* i_vaddr) { uint64_t l_vaddr = reinterpret_cast<uint64_t>(i_vaddr); @@ -208,10 +212,10 @@ void Block::addPTE(void* i_vaddr) ShadowPTE* l_pte = getPTE(l_vaddr); //Add page table entry PageTableManager::addEntry((l_vaddr / PAGESIZE) * PAGESIZE, - l_pte->getPage(), - (l_pte->isExecutable() ? VmmManager::RO_EXE_ACCESS : - (l_pte->isWritable() ? VmmManager::NORMAL_ACCESS : - VmmManager::READ_O_ACCESS))); + l_pte->getPage(), + (l_pte->isExecutable() ? EXECUTABLE : + (l_pte->isWritable() ? WRITABLE : + READ_ONLY))); } uint64_t Block::findPhysicalAddress(uint64_t i_vaddr) const @@ -235,28 +239,6 @@ uint64_t Block::findPhysicalAddress(uint64_t i_vaddr) const return paddr; } -void Block::setPageAllocateFromZero(uint64_t i_vAddr) -{ - // Check containment, call down chain if address isn't in this block. - if (!isContained(i_vAddr)) - { - if (iv_nextBlock) - { - iv_nextBlock->setPageAllocateFromZero(i_vAddr); - } - else - { - // No block owns this address. Code bug. - printk("setPageAllocateFromZero> i_vaddr=0x%.lX\n", i_vAddr ); - kassert(iv_nextBlock); - } - return; - } - - // Set page to allocate-from-zero. - ShadowPTE* pte = getPTE(i_vAddr); - pte->setAllocateFromZero(true); -} void Block::releaseAllPages() { @@ -272,6 +254,14 @@ void Block::releaseAllPages() if (pte->isPresent() && (0 != pte->getPageAddr())) { PageManager::freePage(reinterpret_cast<void*>(pte->getPageAddr())); + +/* TODO.. add this into code and test. + if (BaseSegment::mmSetPermission(reinterpret_cast<void*>(pte->getPageAddr()), + 0, WRITABLE)) + { + printk("Got an error trying to set permissions in release all pages\n"); + } +*/ pte->setPresent(false); pte->setPageAddr(NULL); } @@ -316,6 +306,40 @@ void Block::updateRefCount( uint64_t i_vaddr, } } +bool Block::evictPage(ShadowPTE* i_pte) +{ + ShadowPTE* pte = i_pte; + bool do_cast_out = false; + + if(!pte->isWritable()) // ro, executable + { + do_cast_out = true; + } + else // is writable... + { + // if pte->isWriteTracked() flush then cast out + } + + if(do_cast_out) + { + PageTableManager::delEntry(pte->getPageAddr()); + PageManager::freePage(reinterpret_cast<void*>(pte->getPageAddr())); + +/* TODO.. Add this back in and test + // Need to set the permissions of the heap back to R/W + if (BaseSegment::mmSetPermission(reinterpret_cast<void*>(pte->getPageAddr()), + 0, WRITABLE)) + { + printk(" EVICT Got an error trying to set permissions in evict page\n"); + } +*/ + pte->setPresent(false); + pte->setPageAddr(NULL); + } + + return do_cast_out; +} + void Block::castOutPages(uint64_t i_type) { void* l_vaddr = NULL; @@ -378,107 +402,196 @@ void Block::castOutPages(uint64_t i_type) 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. before I get the page. - uint64_t l_aligned_va = ALIGN_PAGE_DOWN(i_va); - uint64_t l_aligned_size = ALIGN_PAGE(i_size); -//printk("aligned VA = 0x%.lX aligned size = %ld\n", l_aligned_va, l_aligned_size); - - // if size is zero..we are only updating 1 page.. so need to increment the size to 1 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) - { -//printk("aligned VA = 0x%.lX aligned size = %ld\n", l_aligned_va, l_aligned_size); - 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 read_only - if ( i_access_type & READ_ONLY) - { - spte->setReadable(true); - spte->setExecutable(false); - spte->setWritable(false); - - // If the writable or executable access bits - // are set.. invalid combination.. return error - if ((i_access_type & WRITABLE) || (i_access_type & EXECUTABLE)) - { + 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..inncrement the size to 1 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::setPermSPTE( ShadowPTE* i_spte, uint64_t i_access_type) +{ + + // If read_only + if ( i_access_type & READ_ONLY) + { + // If the writable, executable, write_tracked + // or allocate from zero access bits are set + // we have an invalid combination.. return error + if ((i_access_type & WRITABLE) || + (i_access_type & EXECUTABLE) || + (i_access_type & WRITE_TRACKED) || + (i_access_type & ALLOCATE_FROM_ZERO)) + { return -EINVAL; - } - } - // if writable - else if ( i_access_type & WRITABLE) - { - spte->setReadable(true); - spte->setWritable(true); - spte->setExecutable(false); - - if (i_access_type & EXECUTABLE) + } + + // Set the bits after we have verified + // the valid combinations so if we are setting + // permissions on a range only the first page would + // get set to READ_ONLY before we fail. + i_spte->setReadable(true); + i_spte->setExecutable(false); + i_spte->setWritable(false); + } + // if writable + else if ( i_access_type & WRITABLE) + { + if (i_access_type & EXECUTABLE) + { + return -EINVAL; + } + + i_spte->setReadable(true); + i_spte->setWritable(true); + i_spte->setExecutable(false); + + } + // if executable + else if ( i_access_type & EXECUTABLE) + { + i_spte->setReadable(true); + i_spte->setExecutable(true); + i_spte->setWritable(false); + } + + // if write_tracked + if ( i_access_type & WRITE_TRACKED) + { + // TODO.. fail if no message handler when trying to + // set a page to write tracked. + + // If the page is already READ_ONLY + // you cannot set to WRITE_TRACKED + if (getPermission(i_spte) == READ_ONLY) + { + return -EINVAL; + } + i_spte->setWriteTracked(true); + } + else + { + i_spte->setWriteTracked(false); + } + + // if Allocate from zero + if ( i_access_type & ALLOCATE_FROM_ZERO) + { + // If the page is already READ_ONLY + // you cannot set to ALLOCATE_FROM_ZERO + if (getPermission(i_spte) == READ_ONLY) + { + return -EINVAL; + } + + i_spte->setAllocateFromZero(true); + } + // not allocated from zero + else + { + i_spte->setAllocateFromZero(false); + } + + // if no access + if ( i_access_type & NO_ACCESS) + { + i_spte->setReadable(false); + i_spte->setExecutable(false); + i_spte->setWritable(false); + i_spte->setAllocateFromZero(false); + i_spte->setWriteTracked(false); + } + + return 0; +} + +uint64_t Block::getPermission( ShadowPTE* i_spte) +{ + + uint64_t l_accessType = 0; + + if ((!i_spte->isReadable())&& + (!i_spte->isExecutable())&& + (!i_spte->isWritable())&& + (!i_spte->isAllocateFromZero())&& + (!i_spte->isWriteTracked())) + { + return NO_ACCESS; + } + + if (i_spte->isReadable()&& + (!i_spte->isExecutable())&& + (!i_spte->isWritable())) + { + return READ_ONLY; + } + + if (i_spte->isWritable()) + { + l_accessType |= WRITABLE; + } + + if (i_spte->isExecutable()) { - // error condition.. not valid to be - // writable and executable - return -EINVAL; + l_accessType |= EXECUTABLE; } - } - // if executable - else if ( i_access_type & EXECUTABLE) - { - spte->setReadable(true); - spte->setExecutable(true); - spte->setWritable(false); - } - - // if write_tracked - if ( i_access_type & WRITE_TRACKED) - { - spte->setWriteTracked(true); - } - else - { - spte->setWriteTracked(false); - } - - // if Allocate from zero - if ( i_access_type & ALLOCATE_FROM_ZERO) - { - spte->setAllocateFromZero(true); - } - // not allocated from zero - else - { - spte->setAllocateFromZero(false); - } - - // if no access - if ( i_access_type & NO_ACCESS) - { - spte->setReadable(false); - spte->setExecutable(false); - spte->setWritable(false); - spte->setAllocateFromZero(false); - spte->setWriteTracked(false); - } - - } - return l_rc; + + if (i_spte->isWriteTracked()) + { + l_accessType |= WRITE_TRACKED; + } + + if (i_spte->isAllocateFromZero()) + { + l_accessType |= ALLOCATE_FROM_ZERO; + } + + return l_accessType; } + + int Block::removePages(VmmManager::PAGE_REMOVAL_OPS i_op, void* i_vaddr, uint64_t i_size, task_t* i_task) { @@ -519,6 +632,9 @@ int Block::removePages(VmmManager::PAGE_REMOVAL_OPS i_op, void* i_vaddr, { this->iv_writeMsgHdlr->incMsgCount(i_task); } + +// TODO.. Need to map the physical page here before sending the message because +// the RP uses the physical page off the message queue.. (comment from patrick) this->iv_writeMsgHdlr->addVirtAddr( reinterpret_cast<void*>(l_vaddr),pageAddr); this->iv_writeMsgHdlr->sendMessage(MSG_MM_RP_WRITE, @@ -535,6 +651,13 @@ int Block::removePages(VmmManager::PAGE_REMOVAL_OPS i_op, void* i_vaddr, //'Release' page entry releasePTE(pte); PageManager::freePage(reinterpret_cast<void*>(pageAddr)); + +/* TODO.. Add this back in and test. +printk(" \nInside flush.. setting all permissions back to writable on the heap\n"); +// Need to set the permissions of the heap back to R/W + BaseSegment::mmSetPermission(reinterpret_cast<void*>(pte->getPageAddr()), + 0, WRITABLE); +*/ } } } diff --git a/src/kernel/blockmsghdlr.C b/src/kernel/blockmsghdlr.C index fc49ae89d..6a69f3b31 100644 --- a/src/kernel/blockmsghdlr.C +++ b/src/kernel/blockmsghdlr.C @@ -23,7 +23,7 @@ #include <kernel/blockmsghdlr.H> #include <kernel/block.H> #include <kernel/pagemgr.H> - +#include <kernel/basesegment.H> MessageHandler::HandleResult BlockReadMsgHdlr::handleResponse( msg_sys_types_t i_type, void* i_key, task_t* i_task, int i_rc) { @@ -37,6 +37,13 @@ MessageHandler::HandleResult BlockReadMsgHdlr::handleResponse( { //Set the present bit for the address associated with this block iv_block->setIsPresent(i_key); + + // TODO.. Add this call here and test + // update permission for the page that corresponds + // to the physical page addr. + // BaseSegment::mmSetPermission(i_key, 0, NO_ACCESS); + + //Add the address into the page table associated with this block iv_block->addPTE(i_key); return SUCCESS; diff --git a/src/kernel/devicesegment.C b/src/kernel/devicesegment.C index bdf1eab0f..7fb4803dd 100644 --- a/src/kernel/devicesegment.C +++ b/src/kernel/devicesegment.C @@ -111,7 +111,7 @@ bool DeviceSegment::handlePageFault(task_t* i_task, uint64_t i_addr) PageTableManager::addEntry((i_addr / PAGESIZE) * PAGESIZE, (iv_mmioMap[idx].addr + device_offset) / PAGESIZE, - VmmManager::CI_ACCESS); + SegmentManager::CI_ACCESS); return true; } diff --git a/src/kernel/ptmgr.C b/src/kernel/ptmgr.C index 9d0055e83..9807750ed 100644 --- a/src/kernel/ptmgr.C +++ b/src/kernel/ptmgr.C @@ -175,7 +175,7 @@ void PageTableManager::init() */ void PageTableManager::addEntry( uint64_t i_vAddr, uint64_t i_page, - VmmManager::ACCESS_TYPES i_accessType ) + uint64_t i_accessType ) { return Singleton<PageTableManager>::instance()._addEntry( i_vAddr, i_page, i_accessType ); } @@ -308,7 +308,7 @@ PageTableManager::~PageTableManager() */ void PageTableManager::_addEntry( uint64_t i_vAddr, uint64_t i_page, - VmmManager::ACCESS_TYPES i_accessType ) + uint64_t i_accessType ) { Tprintk( ">> PageTableManager::_addEntry( i_vAddr=0x%.16lX, i_page=%ld, i_accessType=%d )\n", i_vAddr, i_page, i_accessType ); @@ -381,7 +381,7 @@ void PageTableManager::_addEntry( uint64_t i_vAddr, Dprintk( "<< PageTableManager::_addEntry()\n" ); } -/** +/**. * @brief Remove an entry from the hardware page table */ void PageTableManager::_delEntry( uint64_t i_vAddr ) @@ -475,24 +475,31 @@ uint64_t PageTableManager::getStatus( PageTableEntry* i_pte ) status |= PTE_VALID; } - VmmManager::ACCESS_TYPES access = getAccessType(i_pte); - switch( access ) { - case( VmmManager::CI_ACCESS ): - status |= PTE_CACHE_INHIBITED; - break; - case( VmmManager::READ_O_ACCESS ): - status |= PTE_READ_ONLY; - break; - case( VmmManager::NORMAL_ACCESS ): - status |= PTE_EXECUTE; //@fixme? - break; - case( VmmManager::RO_EXE_ACCESS ): - status |= PTE_READ_ONLY; - status |= PTE_EXECUTE; - break; - default: - break; - }; + uint64_t access = getAccessType(i_pte); + + switch (access) + { + case SegmentManager::CI_ACCESS: + status |= PTE_CACHE_INHIBITED; + break; + + case READ_ONLY: + status |= PTE_READ; + break; + + case WRITABLE: + status |= PTE_WRITABLE; + status |= PTE_READ; + break; + + case EXECUTABLE: + status |= PTE_EXECUTE; + status |= PTE_READ; + break; + + default: + break; + } if( i_pte->C == 1 ) { status |= PTE_MODIFIED; @@ -788,66 +795,98 @@ inline uint64_t PageTableManager::getSize( void ) * @brief Set bits in PTE for the given ACCESS_TYPES */ void PageTableManager::setAccessBits( PageTableEntry* o_pte, - VmmManager::ACCESS_TYPES i_accessType ) + uint64_t i_accessType ) { o_pte->dword1 &= ~PTE_ACCESS_BITS; - if( VmmManager::NO_USER_ACCESS == i_accessType ) { - o_pte->WIMG = 0b0010; // Memory Coherency Required - o_pte->N = 0b1; // No Execute - } else if( VmmManager::READ_O_ACCESS == i_accessType ) { - o_pte->WIMG = 0b0010; // Memory Coherency Required - o_pte->pp1_2 = 0b01; // PP=001 - o_pte->N = 0b1; // No Execute - } else if( VmmManager::NORMAL_ACCESS == i_accessType ) { - o_pte->WIMG = 0b0010; // Memory Coherency Required - o_pte->pp1_2 = 0b10; // PP=010 - o_pte->N = 0b0; // @TODO Change to 'No Execute' when VFS supports. - } else if( VmmManager::CI_ACCESS == i_accessType ) { - o_pte->WIMG = 0b0101; // Cache Inhibited, Guarded - o_pte->pp1_2 = 0b10; // PP=010 - o_pte->N = 0b1; // No Execute - } else if( VmmManager::RO_EXE_ACCESS == i_accessType ) { - o_pte->WIMG = 0b0010; // Memory Coherency Required - o_pte->pp1_2 = 0b01; // PP=001 - o_pte->N = 0b0; // Execute - } else { - //@fixme - add RO_EXE_ACCESS - Eprintk( "** unrecognized access=%d\n", i_accessType ); + +/* Description of the WIMG bits. + W1,3 0 - not Write Through Required + 1 - Write Through Required + I3 0 - not Caching Inhibited + 1 - Caching Inhibited + M2 0 - not Memory Coherence Required + 1 - Memory Coherence Required + G 0 - not Guarded + 1 - Guarded +*/ + if( SegmentManager::CI_ACCESS == i_accessType ) + { + o_pte->WIMG = 0b0101; // Cache Inhibited, Guarded + o_pte->pp1_2 = 0b10; // PP=010 + o_pte->N = 0b1; // No Execute + } + else + { + // Only setting that changes WIMG is CI_ACCESSS + // All others are set to 0b0010 + o_pte->WIMG = 0b0010; // Memory Coherency Required + + if (i_accessType & READ_ONLY) + { + o_pte->pp1_2 = 0b01; // PP=001 + o_pte->N = 0b1; // No Execute + } + // if writable (implied readable) + else if (i_accessType & WRITABLE) + { + o_pte->pp1_2 = 0b10; // PP=010 + o_pte->N = 0b1; // No Execute + } + // if executable (implied readable) + else if (i_accessType & EXECUTABLE) + { + o_pte->pp1_2 = 0b01; // PP=001 + o_pte->N = 0b0; // Execute + } + else { + //@fixme - add RO_EXE_ACCESS + Eprintk( "** unrecognized access=%ld\n", i_accessType ); + } } } /** * @brief Convert the bits from a PTE into a ACCESS_TYPES */ -VmmManager::ACCESS_TYPES PageTableManager::getAccessType( const PageTableEntry* i_pte ) +uint64_t PageTableManager::getAccessType( const PageTableEntry* i_pte ) { - if( i_pte->pp0 == 0b0 ) + + if( i_pte->pp0 == 0b0 ) + { + // If set to Cache Inhibited. + if( (i_pte->WIMG == 0b0101) && (i_pte->pp1_2 == 0b10) ) { - if( (i_pte->WIMG == 0b0101) && (i_pte->pp1_2 == 0b10) ) - { - return VmmManager::CI_ACCESS; - } - else if( (i_pte->WIMG == 0b0010) && (i_pte->pp1_2 == 0b00) ) - { - return VmmManager::NO_USER_ACCESS; - } - else if( (i_pte->WIMG == 0b0010) && (i_pte->pp1_2 == 0b01) ) - { - return VmmManager::READ_O_ACCESS; - } - else if( (i_pte->WIMG == 0b0010) && (i_pte->pp1_2 == 0b10) ) - { - return VmmManager::NORMAL_ACCESS; - } - //@fixme - add RO_EXE_ACCESS + return SegmentManager::CI_ACCESS; } - - Eprintk( "I don't recognize this PTE : WIMG=%ld, pp1_2=%ld\n", i_pte->WIMG, i_pte->pp1_2 ); - printPTE( "getAccessType", i_pte); /*no effect*/ // BEAM Fix. - kassert(false); - return VmmManager::NO_USER_ACCESS; + else if (i_pte->WIMG == 0b0010) + { + if (i_pte->pp1_2 == 0b00) + { + return NO_ACCESS; + } + // If read and no execute + else if ((i_pte->pp1_2 == 0b01) && (i_pte->N == 0b1)) + { + return READ_ONLY; + } + // if writeable and no executable + else if ((i_pte->pp1_2 == 0b10) && (i_pte->N == 0b1)) + { + return WRITABLE; + } + // if readably and executable.. + else if ((i_pte->pp1_2 == 0b01) && (i_pte->N == 0b0)) + { + return EXECUTABLE; + } + } + } + Eprintk( "I don't recognize this PTE : WIMG=%ld, pp1_2=%ld\n", i_pte->WIMG, i_pte->pp1_2 ); + printPTE( "getAccessType", i_pte); + kassert(false); + return NO_ACCESS; + } - /** * @brief Fill in default values for the PTE */ diff --git a/src/kernel/stacksegment.C b/src/kernel/stacksegment.C index 0c04a2444..0ea3e24a8 100644 --- a/src/kernel/stacksegment.C +++ b/src/kernel/stacksegment.C @@ -134,8 +134,7 @@ void* StackSegment::_createStack(tid_t i_task) // Set pages to be allocate-from-zero. for(uint64_t i = l_addr_bottom; i <= l_addr_top; i += PAGE_SIZE) { - l_block->setPhysicalPage(i, 0, VmmManager::NORMAL_ACCESS); - l_block->setPageAllocateFromZero(i); + l_block->setPhysicalPage(i, 0, WRITABLE | ALLOCATE_FROM_ZERO); } // Insert block to list. |