diff options
author | Missy Connell <missyc@us.ibm.com> | 2011-09-19 15:13:28 -0500 |
---|---|---|
committer | Melissa J. Connell <missyc@us.ibm.com> | 2011-10-06 11:41:57 -0500 |
commit | fdbe0a754e64fb8c4c7cb9aa98184ca87a867e22 (patch) | |
tree | fe4b3b6dc6b84c0e494dd6ab305e1e60635dd7d7 /src/kernel | |
parent | 336f6ac6abc1d5ee4efc1229be06a66baf06643b (diff) | |
download | talos-hostboot-fdbe0a754e64fb8c4c7cb9aa98184ca87a867e22.tar.gz talos-hostboot-fdbe0a754e64fb8c4c7cb9aa98184ca87a867e22.zip |
pge permission functionality..
Add code that applies the permissions requested.
Add merge conflicts
Change-Id: I5911406ba4670714faaf4880399da71692559397
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/353
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 | 46 | ||||
-rw-r--r-- | src/kernel/block.C | 110 | ||||
-rw-r--r-- | src/kernel/vmmmgr.C | 4 |
3 files changed, 156 insertions, 4 deletions
diff --git a/src/kernel/basesegment.C b/src/kernel/basesegment.C index eab00accc..8eb7e5484 100644 --- a/src/kernel/basesegment.C +++ b/src/kernel/basesegment.C @@ -142,11 +142,53 @@ void BaseSegment::updateRefCount( uint64_t i_vaddr, } /** + * STATIC * Sets the Page Permissions for a given page via virtual address */ -int BaseSegment::mmSetPermission(void* i_va, uint64_t i_size,PAGE_PERMISSIONS i_access_type) +int BaseSegment::mmSetPermission(void* i_va, uint64_t i_size, uint64_t i_access_type) { - return 0; + return Singleton<BaseSegment>::instance()._mmSetPermission(i_va,i_size,i_access_type); +} + + +/** + * Sets the Page Permissions for a given page via virtual address + */ +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->iv_nextBlock); + + return l_rc; + } void BaseSegment::castOutPages(uint64_t i_type) diff --git a/src/kernel/block.C b/src/kernel/block.C index 63c1fae92..f72a8f6f7 100644 --- a/src/kernel/block.C +++ b/src/kernel/block.C @@ -33,6 +33,7 @@ #include <kernel/ptmgr.H> #include <kernel/pagemgr.H> #include <kernel/console.H> +#include <util/align.H> Block::~Block() { @@ -171,16 +172,19 @@ void Block::setPhysicalPage(uint64_t i_vAddr, uint64_t i_pAddr, 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; @@ -311,6 +315,7 @@ void Block::updateRefCount( uint64_t i_vaddr, } + bool Block::evictPage(ShadowPTE* i_pte) { ShadowPTE* pte = i_pte; @@ -400,3 +405,108 @@ size_t Block::castOutPages(uint64_t i_type) return cast_out; } + + +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)) + { + return -EINVAL; + } + } + // if writable + else if ( i_access_type & WRITABLE) + { + spte->setReadable(true); + spte->setWritable(true); + spte->setExecutable(false); + + if (i_access_type & EXECUTABLE) + { + // error condition.. not valid to be + // writable and executable + return -EINVAL; + } + } + // 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; + +} diff --git a/src/kernel/vmmmgr.C b/src/kernel/vmmmgr.C index b2026944e..c923d80e0 100644 --- a/src/kernel/vmmmgr.C +++ b/src/kernel/vmmmgr.C @@ -176,13 +176,13 @@ int VmmManager::mmRemovePages(PAGE_REMOVAL_OPS i_op, void* i_vaddr, } -int VmmManager::mmSetPermission(void* i_va, uint64_t i_size, PAGE_PERMISSIONS i_access_type) +int VmmManager::mmSetPermission(void* i_va, uint64_t i_size, uint64_t i_access_type) { return Singleton<VmmManager>::instance()._mmSetPermission(i_va, i_size, i_access_type); } -int VmmManager::_mmSetPermission(void* i_va, uint64_t i_size, PAGE_PERMISSIONS i_access_type) +int VmmManager::_mmSetPermission(void* i_va, uint64_t i_size, uint64_t i_access_type) { int rc = 1; |