summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMissy Connell <missyc@us.ibm.com>2011-10-25 11:12:55 -0500
committerMelissa J. Connell <missyc@us.ibm.com>2011-10-27 15:56:31 -0500
commit9e86b070a4429e7db34a5438611a67098ab92dfb (patch)
tree52e04b08288a7496359c41eff98e8463e73ae5dc
parent71564141e3a6c7f023a9484549baf319f0e1807e (diff)
downloadtalos-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>
-rw-r--r--src/include/kernel/block.H72
-rw-r--r--src/include/kernel/ptmgr.H21
-rw-r--r--src/include/kernel/segmentmgr.H6
-rw-r--r--src/include/kernel/vmmmgr.H9
-rw-r--r--src/kernel/basesegment.C41
-rw-r--r--src/kernel/block.C427
-rw-r--r--src/kernel/blockmsghdlr.C9
-rw-r--r--src/kernel/devicesegment.C2
-rw-r--r--src/kernel/ptmgr.C177
-rw-r--r--src/kernel/stacksegment.C3
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvctasks.H48
-rw-r--r--src/usr/initservice/test/initservicetest.H2
-rw-r--r--src/usr/pnor/pnorrp.C8
-rw-r--r--src/usr/testcore/kernel/ptmgrtest.H4
-rw-r--r--src/usr/testcore/kernel/vmmpagetest.H137
15 files changed, 613 insertions, 353 deletions
diff --git a/src/include/kernel/block.H b/src/include/kernel/block.H
index 60aeadaf0..b5ab709cc 100644
--- a/src/include/kernel/block.H
+++ b/src/include/kernel/block.H
@@ -140,23 +140,6 @@ class Block
void updateRefCount( uint64_t i_vaddr,
PageTableManager::UsageStats_t i_stats );
- /**
- * @brief Cast out older phyiscal memory pages
- * @param[in] i_type - Castout contraint @see VmmManager::castOutPages()
- */
- void castOutPages(uint64_t i_type);
-
- /**
- * @brief Removes a range of pages within a block of virtual memory
- * @param[in] i_op - Page removal operation to perform
- * @param[in] i_vaddr - Virtual address associated to page(s)
- * @param[in] i_size - Size of memory to perform page removal on
- * @param[in] i_task - Task requesting page removal.
- * @return int - 0 for successful page removal, non-zero otherwise
- */
- int removePages(VmmManager::PAGE_REMOVAL_OPS i_op, void* i_vaddr,
- uint64_t i_size, task_t* i_task);
-
friend class Segment;
friend class BaseSegment;
friend class StackSegment;
@@ -194,14 +177,7 @@ class Block
* mode is still set.
*/
void setPhysicalPage(uint64_t i_vAddr, uint64_t i_pAddr,
- VmmManager::ACCESS_TYPES i_access);
-
- /**
- * @brief Set up a virtual address to be "allocate-from-zero".
- *
- * @param[in] i_vAddr - The virtual address of the page.
- */
- void setPageAllocateFromZero(uint64_t i_vAddr);
+ uint64_t i_access);
/**
* @brief Adds up the total size of all blocks within the segment
@@ -231,7 +207,7 @@ class Block
* individual page.
* @param i_access_type[in] - type of permission to set using
* PAGE_PERMISSION enum values OR'd together
- * @return int - 0 for successful block allocation,
+ * @return int - 0 for successful permission update,
* non-zero otherwise
*/
int mmSetPermission(uint64_t i_va, uint64_t i_size, uint64_t i_access_type);
@@ -260,6 +236,50 @@ class Block
*/
void releasePTE(ShadowPTE* i_pte);
+ /**
+ * @brief Cast out older phyiscal memory pages
+ * @param[in] i_type - Castout contraint @see VmmManager::castOutPages()
+ */
+ void castOutPages(uint64_t i_type);
+
+ /**
+ * @brief Evict a memory page
+ * @param[in] i_pte shadow page table entry
+ * @return true of page was evicted
+ */
+ bool evictPage(ShadowPTE* i_pte);
+
+ /**
+ * @brief Sets the page permissions for a given SPTE
+ * @param i_spte[in] - i_pte shadow page table entry
+ * @param i_access_type[in] - type of permission to set using
+ * PAGE_PERMISSION enum values OR'd together
+ * @return int - 0 for successful update
+ * non-zero otherwise
+ */
+ int setPermSPTE( ShadowPTE* i_spte, uint64_t i_access_type);
+
+ /**
+ * @brief Gets the page permissions for a given SPTE
+ * @param i_spte[in] - i_pte shadow page table entry
+ * @return uint64_t - type of permission for that SPTE using
+ * PAGE_PERMISSION enum values OR'd together
+ */
+ uint64_t getPermission( ShadowPTE* i_spte);
+
+ /**
+ * @brief Removes a range of pages within a block of virtual memory
+ * @param[in] i_op - Page removal operation to perform
+ * @param[in] i_vaddr - Virtual address associated to page(s)
+ * @param[in] i_size - Size of memory to perform page removal on
+ * @param[in] i_task - Task requesting page removal.
+ * @return int - 0 for successful page removal, non-zero otherwise
+ */
+ int removePages(VmmManager::PAGE_REMOVAL_OPS i_op, void* i_vaddr,
+ uint64_t i_size, task_t* i_task);
+
+
+
private:
/** Base address of the block */
const uint64_t iv_baseAddr;
diff --git a/src/include/kernel/ptmgr.H b/src/include/kernel/ptmgr.H
index 9ae092857..918e4211f 100644
--- a/src/include/kernel/ptmgr.H
+++ b/src/include/kernel/ptmgr.H
@@ -44,11 +44,12 @@ class PageTableManager
PTE_UNKNOWN = 0x0000000000000000, /**< Entry wasn't found */
PTE_PRESENT = 0x0000000000000001, /**< Entry is present in table */
PTE_VALID = 0x0000000000000002, /**< Entry is valid */
- PTE_READ_ONLY = 0x0000000000000004, /**< Read-Only */
- PTE_EXECUTE = 0x0000000000000008, /**< Execute permission */
- PTE_CACHE_INHIBITED = 0x0000000000000010, /**< Cache-Inhibited Access */
- PTE_MODIFIED = 0x0000000000000020, /**< Page has been modified */
- PTE_ACCESSED = 0x0000000000000040, /**< Page has been accessed */
+ PTE_READ = 0x0000000000000004, /**< Read permission */
+ PTE_WRITABLE = 0x0000000000000008, /**< Write permission */
+ PTE_EXECUTE = 0x0000000000000010, /**< Execute permission */
+ PTE_CACHE_INHIBITED = 0x0000000000000020, /**< Cache-Inhibited Access */
+ PTE_MODIFIED = 0x0000000000000040, /**< Page has been modified */
+ PTE_ACCESSED = 0x0000000000000080, /**< Page has been accessed */
};
/**
@@ -96,7 +97,7 @@ class PageTableManager
*/
static void addEntry( uint64_t i_vAddr,
uint64_t i_page,
- VmmManager::ACCESS_TYPES i_accessType );
+ uint64_t i_accessType );
/**
* @brief Remove an entry from the hardware page table
@@ -315,7 +316,7 @@ class PageTableManager
*/
void _addEntry( uint64_t i_vAddr,
uint64_t i_page,
- VmmManager::ACCESS_TYPES i_accessType );
+ uint64_t i_accessType );
/**
* @brief Remove an entry from the hardware page table
@@ -423,16 +424,16 @@ class PageTableManager
* @param[in] i_accessType Access parameter to apply to PTE
*/
void setAccessBits( PageTableEntry* o_pte,
- VmmManager::ACCESS_TYPES i_accessType );
+ uint64_t i_accessType );
/**
* @brief Convert the bits from a PTE into a ACCESS_TYPES
*
* @param[in] i_pte PTE to examine
*
- * @return ACCESS_TYPES Access parameters of given PTE
+ * @return uint64_t Access parameters of given PTE
*/
- VmmManager::ACCESS_TYPES getAccessType( const PageTableEntry* i_pte );
+ uint64_t getAccessType( const PageTableEntry* i_pte );
/**
* @brief Calculate the original Virtual Address from a PTE
diff --git a/src/include/kernel/segmentmgr.H b/src/include/kernel/segmentmgr.H
index 7232c7d4f..d2e4be2df 100644
--- a/src/include/kernel/segmentmgr.H
+++ b/src/include/kernel/segmentmgr.H
@@ -57,6 +57,12 @@ class SegmentManager
MAX_SEGMENTS = 4
};
+ enum
+ {
+ CI_ACCESS = 0xFFFFFFFF
+ // Set to all F's to identify this type
+ };
+
/**
* Constructor. Initializes instance variables.
*/
diff --git a/src/include/kernel/vmmmgr.H b/src/include/kernel/vmmmgr.H
index 98b202db1..6e41ddb34 100644
--- a/src/include/kernel/vmmmgr.H
+++ b/src/include/kernel/vmmmgr.H
@@ -46,15 +46,6 @@ class VmmManager
HTABORG = (FULL_MEM_SIZE - PTSIZE),
};
- enum ACCESS_TYPES
- {
- NO_USER_ACCESS,
- READ_O_ACCESS,
- NORMAL_ACCESS,
- CI_ACCESS,
- RO_EXE_ACCESS,
- };
-
enum castout_t
{
NORMAL,
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.
diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H
index 761295319..9ac783eb9 100644
--- a/src/usr/initservice/extinitsvc/extinitsvctasks.H
+++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H
@@ -106,30 +106,35 @@ const TaskInfo g_exttaskinfolist[] = {
START_PLAT_ERRL_ID, // module id
}
},
-
+
+// TODO: Added this in order to successfull init.. Need to remove this and put
+// the module load and unload from a the istep dispatcher
/**
- * @brief targeting task,
+ * @brief HWAS,
*/
+
+
{
- "libtargeting.so" , // taskname
+ "libhwas.so" , // taskname
NULL, // no pointer to fn
{
- START_TASK, // task type
+ INIT_TASK, // task type
EXT_IMAGE, // Extended Module
- START_TARGETING_ERRL_ID, // module id
+ EXECUTE_ISTEPS_ERRL_ID, // module id
}
},
+// end TODO
/**
- * @brief IStep Dispatcher task, runs ISteps
+ * @brief FSI Device Driver
*/
{
- "libistepdisp.so" , // taskname
+ "libfsi.so" , // taskname
NULL, // no pointer to fn
{
- START_TASK, // task type
+ INIT_TASK, // task type
EXT_IMAGE, // Extended Module
- EXECUTE_ISTEPS_ERRL_ID, // module id
+ START_FSIDD_ERRL_ID, // module id
}
},
@@ -137,28 +142,41 @@ const TaskInfo g_exttaskinfolist[] = {
* @brief FSI Device Driver
*/
{
- "libfsi.so" , // taskname
+ "libfsiscom.so" , // taskname
NULL, // no pointer to fn
{
INIT_TASK, // task type
EXT_IMAGE, // Extended Module
- START_FSIDD_ERRL_ID, // module id
+ START_FSISCOM_ERRL_ID, // module id
}
},
/**
- * @brief FSI Device Driver
+ * @brief targeting task,
*/
{
- "libfsiscom.so" , // taskname
+ "libtargeting.so" , // taskname
NULL, // no pointer to fn
{
- INIT_TASK, // task type
+ START_TASK, // task type
EXT_IMAGE, // Extended Module
- START_FSISCOM_ERRL_ID, // module id
+ START_TARGETING_ERRL_ID, // module id
}
},
+ /**
+ * @brief IStep Dispatcher task, runs ISteps
+ */
+ {
+ "libistepdisp.so" , // taskname
+ NULL, // no pointer to fn
+ {
+ START_TASK, // task type
+ EXT_IMAGE, // Extended Module
+ EXECUTE_ISTEPS_ERRL_ID, // module id
+ }
+ },
+ // NOTE: libistepdisp.so needs to always be last in this list!!
// ---------------------------------------------------------------
// ----- END OF LIST!!! ---------------------------------------
diff --git a/src/usr/initservice/test/initservicetest.H b/src/usr/initservice/test/initservicetest.H
index 6a32d73fd..1a8951ff3 100644
--- a/src/usr/initservice/test/initservicetest.H
+++ b/src/usr/initservice/test/initservicetest.H
@@ -63,7 +63,7 @@ const INITSERVICE::TaskInfo TASK_TEST2 = {
NULL, // ptr to fn
{
INITSERVICE::START_TASK, // startflag=true, try to start
- INITSERVICE::BASE_IMAGE, // Base Module
+ INITSERVICE::EXT_IMAGE, // Ext Inmage Module
INITSERVICE::INIT_SVC_TEST2_ERRL_ID, // module id for errorlog
},
};
diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C
index 5a479f03e..76bcb89b1 100644
--- a/src/usr/pnor/pnorrp.C
+++ b/src/usr/pnor/pnorrp.C
@@ -193,6 +193,14 @@ void PnorRP::initDaemon()
break;
}
+
+ // Need to set permissions to R/W
+ rc = mm_set_permission((void*) BASE_VADDR,
+ TOTAL_SIZE ,
+ WRITABLE);
+
+
+
// start task to wait on the queue
task_create( wait_for_message, NULL );
diff --git a/src/usr/testcore/kernel/ptmgrtest.H b/src/usr/testcore/kernel/ptmgrtest.H
index 1d87b312e..e97457513 100644
--- a/src/usr/testcore/kernel/ptmgrtest.H
+++ b/src/usr/testcore/kernel/ptmgrtest.H
@@ -144,7 +144,7 @@ class ptmgrtest : public CxxTest::TestSuite
for( uint64_t x = 0; x < (sizeof(TEST_DATA)/sizeof(TEST_DATA[0])); x++ )
{
// 2) Add some PTEs
- ptmgr->_addEntry( TEST_DATA[x].va, TEST_DATA[x].page, VmmManager::NORMAL_ACCESS );
+ ptmgr->_addEntry( TEST_DATA[x].va, TEST_DATA[x].page, WRITABLE );
// 3) Verify the PTE we just added is in the Page Table
status = ptmgr->_getStatus( TEST_DATA[x].va, pn );
@@ -406,7 +406,7 @@ class ptmgrtest : public CxxTest::TestSuite
for( uint64_t x = 0; x < (sizeof(TEST_DATA)/sizeof(TEST_DATA[0])); x++ )
{
// 2) Add some PTEs
- ptmgr->_addEntry( TEST_DATA[x].va, TEST_DATA[x].page, VmmManager::NORMAL_ACCESS );
+ ptmgr->_addEntry( TEST_DATA[x].va, TEST_DATA[x].page, WRITABLE );
}
}
diff --git a/src/usr/testcore/kernel/vmmpagetest.H b/src/usr/testcore/kernel/vmmpagetest.H
index 39090b542..3559fd3cb 100644
--- a/src/usr/testcore/kernel/vmmpagetest.H
+++ b/src/usr/testcore/kernel/vmmpagetest.H
@@ -39,6 +39,7 @@ class vmmpagetest: public CxxTest::TestSuite
public:
static volatile int rc;
+ static volatile int iv_rc;
//Testing page removal variables
static msg_q_t iv_mq;
static uint64_t iv_va;
@@ -63,8 +64,15 @@ class vmmpagetest: public CxxTest::TestSuite
void testReadPageRelease()
{
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va+2*PAGESIZE),0,
+ WRITABLE);
+
//Dependent on block being initialized to READ_ONLY
(*(volatile uint64_t *)(iv_va+2*PAGESIZE)) = 0x11111111; sync();
+
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va+2*PAGESIZE),0,
+ READ_ONLY);
+
rc = mm_remove_pages(RELEASE,
reinterpret_cast<void*>(iv_va),iv_size);
if (rc != 0)
@@ -75,17 +83,19 @@ class vmmpagetest: public CxxTest::TestSuite
void testWriteTrackPageFlush()
{
- (*(volatile uint64_t *)iv_va) = 0x12345678; sync();
- (*(volatile uint64_t *)(iv_va+PAGESIZE)) = 0x87654321; sync();
- (*(volatile uint64_t *)(iv_va+2*PAGESIZE)) = 0x22222222; sync();
- uint64_t updPerm = (uint64_t)(WRITE_TRACKED);
- rc = mm_set_permission(reinterpret_cast<void*>(iv_va),0,updPerm);
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va),3*PAGESIZE,WRITABLE|WRITE_TRACKED);
if (rc != 0)
{
TS_FAIL(
"Failed to set WRITE_TRACKED permissions on first page.\n");
}
- rc = mm_set_permission(reinterpret_cast<void*>((iv_va+PAGESIZE)),0,
+
+ (*(volatile uint64_t *)iv_va) = 0x12345678; sync();
+ (*(volatile uint64_t *)(iv_va+PAGESIZE)) = 0x87654321; sync();
+ (*(volatile uint64_t *)(iv_va+2*PAGESIZE)) = 0x22222222; sync();
+ uint64_t updPerm = (uint64_t)(READ_ONLY);
+
+ rc = mm_set_permission(reinterpret_cast<void*>((iv_va+2*PAGESIZE)),0,
updPerm);
if (rc != 0)
{
@@ -102,8 +112,24 @@ class vmmpagetest: public CxxTest::TestSuite
void testWriteTrackPageRelease()
{
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va+2*PAGESIZE),0 ,WRITABLE);
+ if (rc != 0)
+ {
+ TS_FAIL(
+ "Failed to set WRITE_TRACKED permissions on first page.\n");
+ }
+
(*(volatile uint64_t *)(iv_va+2*PAGESIZE)) = 0x33333333; sync();
(*(volatile uint64_t *)iv_va) = 0x12121212; sync();
+
+ uint64_t updPerm = (uint64_t)(READ_ONLY);
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va+2*PAGESIZE),0,updPerm);
+ if (rc != 0)
+ {
+ TS_FAIL(
+ "Failed to set WRITE_TRACKED permissions on first page.\n");
+ }
+
rc = mm_remove_pages(RELEASE,
reinterpret_cast<void*>(iv_va),iv_size);
if (rc != 0)
@@ -114,48 +140,80 @@ class vmmpagetest: public CxxTest::TestSuite
void testSetPerm()
{
- int rc = 1;
- uint64_t va = 0xC800000000; //800GB
- uint64_t size = 0x0;
- uint64_t access = (uint64_t)(WRITABLE | ALLOCATE_FROM_ZERO); //Access value
- printkd("Update Page Permissions. Writable/Allocate from zero to addr 800Gb and size = 0 \n");
- rc = mm_set_permission(reinterpret_cast<void*>(va), size, access);
+
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va+4*PAGESIZE), 3*PAGESIZE, READ_ONLY);
if (rc != 0)
{
TS_FAIL(" 1 Failed to Update permissions.\n");
}
- rc = 1;
- size = PAGESIZE * 3;
- access = (uint64_t)(WRITE_TRACKED); //Access value
- printkd("Update Page Permissions. write_tracked to addr 800Gb and size = 3 pages\n");
- rc = mm_set_permission(reinterpret_cast<void*>(va), size, access);
+ // try to write to a read_only page
+ iv_rc = 0; sync();
+ printk("\nTest case1: Expect to see uncaught exception! ");
+ task_create(writeAddrWithNoPerm, NULL);
+ while (iv_rc == 0) task_yield();
+ task_yield();
+ if (iv_rc == -1)
+ {
+ TS_FAIL("ERROR! Write to READ_ONLY address not caught.");
+ }
+
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va+4*PAGESIZE), 3*PAGESIZE, EXECUTABLE);
if (rc != 0)
{
TS_FAIL("2 Failed to Update permissions.\n");
}
- rc = 1;
- va = 0xC800000000 + (PAGESIZE * 10);
- size = PAGESIZE * 2;
- access = (uint64_t)(EXECUTABLE); //Access value
- printkd("Update Page Permissions. executable to addr C800A000 and size = 2 pages\n");
- rc = mm_set_permission(reinterpret_cast<void*>(va), size, access);
+
+ // try to write to an executable page
+ iv_rc = 0; sync();
+ printk("\nTest case2: Expect to see uncaught exception! ");
+ task_create(writeAddrWithNoPerm2, NULL);
+ while (iv_rc == 0) task_yield();
+ task_yield();
+ if (iv_rc == -1)
+ {
+ TS_FAIL("ERROR! Write to EXECUTABLE address not caught.");
+ }
+
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va+4*PAGESIZE), 3*PAGESIZE, NO_ACCESS);
if (rc != 0)
{
TS_FAIL("3 Failed to Update permissions.\n");
}
- rc = 0;
- va = 0xC800000000; //800GB
- size = 0x0;
- access = (uint64_t)(WRITABLE | EXECUTABLE); //Access value
- printkd("Update Page Permissions. Writable/executable to addr 800Gb and size = 0 \n");
- rc = mm_set_permission(reinterpret_cast<void*>(va), size, access);
+
+ // try to write to a no access page
+ iv_rc = 0; sync();
+ printk("\nTest case3: Expect to see uncaught exception! ");
+ task_create(writeAddrWithNoPerm, NULL);
+ while (iv_rc == 0) task_yield();
+ task_yield();
+ if (iv_rc == -1)
+ {
+ TS_FAIL("ERROR! write to a NO_ACCESS addr not caught.\n");
+ }
+
+ // test that you cannot set WRITABLE and EXECUTABLE permissions
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va+4*PAGESIZE), 3*PAGESIZE, WRITABLE|EXECUTABLE);
if (rc == 0)
{
printk("Error .. invalid combination that did not get detected\n");
+ TS_FAIL(" ERROR..Failed to detect a bad parm condition.\n");
+ }
+
+ rc = mm_set_permission(reinterpret_cast<void*>(iv_va+4*PAGESIZE), 3*PAGESIZE, WRITABLE);
+ if (rc != 0)
+ {
TS_FAIL(" 4 Failed to detect a bad parm condition.\n");
}
- }
+
+
+ (*(volatile uint64_t *)(iv_va+4*PAGESIZE)) = 0x34343434;
+
+
+ printk("\n%lx\n", (*(volatile uint64_t *)(iv_va+4*PAGESIZE)));
+ //printkd(" Successfully read from a WRITABLE page\n");
+
+ }
private:
@@ -177,8 +235,27 @@ class vmmpagetest: public CxxTest::TestSuite
}
}
+
+ static void writeAddrWithNoPerm(void* unused)
+ {
+ iv_rc = 1; sync();
+ (*(volatile uint64_t *)(iv_va+4*PAGESIZE)) = 0x11111111; sync();
+ iv_rc = -1; sync();
+ task_end();
+ }
+
+ static void writeAddrWithNoPerm2(void* unused)
+ {
+ iv_rc = 1; sync();
+ (*(volatile uint64_t *)(iv_va+4*PAGESIZE+2*PAGESIZE)) = 0x22222222; sync();
+ iv_rc = -1; sync();
+ task_end();
+ }
+
+
};
volatile int vmmpagetest::rc = 0;
+volatile int vmmpagetest::iv_rc = 0;
msg_q_t vmmpagetest::iv_mq = msg_q_create();
uint64_t vmmpagetest::iv_va = VMM_VADDR_RMVPAGE_TEST;
uint64_t vmmpagetest::iv_size = VMM_SIZE_RMVPAGE_TEST;
OpenPOWER on IntegriCloud