summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/kernel/basesegment.H9
-rw-r--r--src/include/kernel/block.H7
-rw-r--r--src/include/kernel/devicesegment.H7
-rw-r--r--src/include/kernel/ptmgr.H29
-rw-r--r--src/include/kernel/segment.H4
-rw-r--r--src/include/kernel/segmentmgr.H6
-rw-r--r--src/include/kernel/stacksegment.H2
-rw-r--r--src/include/kernel/vmmmgr.H5
-rw-r--r--src/kernel/basesegment.C4
-rw-r--r--src/kernel/block.C36
-rw-r--r--src/kernel/devicesegment.C3
-rw-r--r--src/kernel/exception.C21
-rw-r--r--src/kernel/ptmgr.C401
-rw-r--r--src/kernel/segmentmgr.C10
-rw-r--r--src/kernel/stacksegment.C5
-rw-r--r--src/kernel/vmmmgr.C8
16 files changed, 332 insertions, 225 deletions
diff --git a/src/include/kernel/basesegment.H b/src/include/kernel/basesegment.H
index 51e99b0bf..293b24f1c 100644
--- a/src/include/kernel/basesegment.H
+++ b/src/include/kernel/basesegment.H
@@ -64,7 +64,8 @@ class BaseSegment : public Segment
*
* Calls block chain to deal with page fault.
*/
- virtual bool handlePageFault(task_t* i_task, uint64_t i_addr);
+ virtual bool handlePageFault(task_t* i_task, uint64_t i_addr,
+ bool i_store);
/**
* @brief Implementation of the pure-virtual function from Segment.
@@ -108,8 +109,8 @@ class BaseSegment : public Segment
/**
* @brief Sets the page permissions for a given virtual address and size.
- * @param i_va[in] - virtual address of the page(s) to set permissions
- * @param i_size[in] - range of memory that needs permissions updated...
+ * @param i_va[in] - virtual address of the page(s) to set permissions
+ * @param i_size[in] - range of memory that needs permissions updated...
* if i_size equals 0 then we only need to update an
* individual page.
* @param i_access_type[in] - type of permission to set
@@ -148,7 +149,7 @@ class BaseSegment : public Segment
/**
* @brief Sets the page permissions for a given virtual address and size.
* @param i_va[in] - virtual address of the page(s) to set permissions
- * @param i_size[in] - range of memory that needs permissions updated...
+ * @param i_size[in] - range of memory that needs permissions updated...
* if i_size equals 0 then we only need to update an individual
* page.
* @param i_access_type[in] - type of permission to set
diff --git a/src/include/kernel/block.H b/src/include/kernel/block.H
index 48e27b803..5d80ea7c6 100644
--- a/src/include/kernel/block.H
+++ b/src/include/kernel/block.H
@@ -104,6 +104,7 @@ class Block
*
* @param[in] i_task - Task causing the page fault.
* @param[in] i_addr - Effective address accessed to cause fault.
+ * @param[in] i_store - The fault was due to a store.
*
* @return true - Page fault was successfully handled.
*
@@ -114,14 +115,14 @@ class Block
* If the address is not within this block, the block will attempt to
* make calls down the block-chain if it exists.
*/
- bool handlePageFault(task_t* i_task, uint64_t i_addr);
+ bool handlePageFault(task_t* i_task, uint64_t i_addr, bool i_store);
/**
* @brief Locate the physical address of the given virtual address
*
* @param[in] i_vaddr virtual address
*
- * @return the physical address bound to the virtual address,
+ * @return the physical address bound to the virtual address,
* -EFAULT if not found @see errno.h
*/
uint64_t findPhysicalAddress(uint64_t i_vaddr) const;
@@ -202,7 +203,7 @@ class Block
* and a size of memory needing updated permissions
* @param i_va[in] - virtual address of the beginning of the
* pages that need updating.
- * @param i_size[in] - range of memory that needs updating
+ * @param i_size[in] - range of memory that needs updating
* if i_size equals 0 then we only need to update an
* individual page.
* @param i_access_type[in] - type of permission to set using
diff --git a/src/include/kernel/devicesegment.H b/src/include/kernel/devicesegment.H
index dcaf78af8..c300eedde 100644
--- a/src/include/kernel/devicesegment.H
+++ b/src/include/kernel/devicesegment.H
@@ -56,12 +56,13 @@ class DeviceSegment : public Segment
/**
* @brief Handle a page fault for a device address access
- * @param i_task[in] - Task pointer to the task requiring the page
- * @param i_addr[in] - 64-bit address needed to be paged
+ * @param[in] i_task - Task pointer to the task requiring the page
+ * @param[in] i_addr - 64-bit address needed to be paged
+ * @param[in] i_store - Fault was due to a store.
* @return bool - true: Page added to page table
* false: Not a valid address to be paged
*/
- bool handlePageFault(task_t* i_task, uint64_t i_addr);
+ bool handlePageFault(task_t* i_task, uint64_t i_addr, bool i_store);
/**
diff --git a/src/include/kernel/ptmgr.H b/src/include/kernel/ptmgr.H
index 918e4211f..b570e0d14 100644
--- a/src/include/kernel/ptmgr.H
+++ b/src/include/kernel/ptmgr.H
@@ -59,12 +59,12 @@ class PageTableManager
{
PT_SIZE = (1 << 18), /**< Size of Page Table in bytes */
PTE_SIZE = /**< Size of 1 Page Table Entry in bytes */
- 2*sizeof(uint64_t),
+ 2*sizeof(uint64_t),
PTEG_SIZE = 8, /**< Number of PTEs in a single PTE Group */
PTEG_COUNT = /**< Number of PTEGs in the Page Table */
(PT_SIZE / PTE_SIZE) / PTEG_SIZE,
INVALID_PN = /**< Error value for a Page Number return */
- 0xFFFFFFFFFFFFFFFF,
+ 0xFFFFFFFFFFFFFFFF,
};
/**
@@ -72,7 +72,7 @@ class PageTableManager
*/
struct UsageStats_t {
union {
- struct {
+ struct {
uint64_t C:1; /**< Page has been modified */
uint64_t R:1; /**< Page has been referenced */
uint64_t LRU:2; /**< Current value of LRU */
@@ -299,6 +299,11 @@ class PageTableManager
/**
* @brief Write a PTE to memory and update caches appropriately
*
+ * @note This function should only be used to change a PTE from valid to
+ * invalid or from invalid to valid, unless modifying the permissions
+ * on an existing PTE (without changing addresses). Use in two
+ * stages otherwise.
+ *
* @param[in] i_pte Local pointer to PTE data
* @param[in] i_dest Real Address inside page table to write i_pte data into
* @param[in] i_valid true=set Valid bit, false=clear Valid bit
@@ -371,11 +376,21 @@ class PageTableManager
uint64_t getStatus( PageTableEntry* i_pte );
/**
- * @brief Update the LRU statistics for other PTEs in the same PTEG as the target
+ * @brief Update the LRU statistics for other PTEs in the same PTEG as the
+ * target
+ *
+ * @param[in] i_newPTE Real address of PTE that is being added to the
+ * Page Table
+ */
+ void updateLRUGroup( const PageTableEntry* i_newPTE );
+
+ /**
+ * @brief Update the LRU statistics for a specific PTE.
*
- * @param[in] i_newPTE Real address of PTE that is being added to the Page Table
+ * @param[in] i_newPTE Real address of PTE to update.
*/
- void updateLRU( const PageTableEntry* i_newPTE );
+ void updateLRUEntry( PageTableEntry* i_newPTE );
+
/**
* @brief Invalidate TLB for a PTE
@@ -449,7 +464,7 @@ class PageTableManager
*
* @param[out] o_pte PTE to modify
*/
- static void setupDefaultPTE( PageTableEntry* o_pte );
+ static void setupDefaultPTE( PageTableEntry* o_pte ) ALWAYS_INLINE;
/**
* @brief Push C/R/LRU bits to the VMM
diff --git a/src/include/kernel/segment.H b/src/include/kernel/segment.H
index 798539309..63aa13480 100644
--- a/src/include/kernel/segment.H
+++ b/src/include/kernel/segment.H
@@ -53,6 +53,7 @@ class Segment
*
* @param[in] i_task - Task causing the page fault.
* @param[in] i_addr - Effective address accessed to cause fault.
+ * @param[in] i_store - The fault was due to a store.
*
* @return true - Page fault was successfully handled.
*
@@ -60,7 +61,8 @@ class Segment
* that the VMM will perform appropriate action, such as killing the
* task.
*/
- virtual bool handlePageFault(task_t* i_task, uint64_t i_addr) = 0;
+ virtual bool handlePageFault(task_t* i_task, uint64_t i_addr,
+ bool i_store) = 0;
/**
* @brief Get the base address of this segment.
diff --git a/src/include/kernel/segmentmgr.H b/src/include/kernel/segmentmgr.H
index 85ecf3269..ecefbc0dd 100644
--- a/src/include/kernel/segmentmgr.H
+++ b/src/include/kernel/segmentmgr.H
@@ -84,6 +84,7 @@ class SegmentManager
*
* @param[in] i_task - Task causing the page fault.
* @param[in] i_addr - Effective address accessed to cause fault.
+ * @param[in] i_store - The page fault was due to a store.
*
* @return true - Page fault was successfully handled.
*
@@ -91,7 +92,8 @@ class SegmentManager
* that the VMM will perform appropriate action, such as killing the
* task.
*/
- static bool handlePageFault(task_t* i_task, uint64_t i_addr);
+ static bool handlePageFault(task_t* i_task, uint64_t i_addr,
+ bool i_store);
/**
* @brief Adds a segment to the container.
@@ -150,7 +152,7 @@ class SegmentManager
private:
/** See handlePageFault. */
- bool _handlePageFault(task_t* i_task, uint64_t i_addr);
+ bool _handlePageFault(task_t* i_task, uint64_t i_addr, bool i_store);
/** See addSegment. */
void _addSegment(Segment* i_segment, size_t i_segId);
/** See getSegment. */
diff --git a/src/include/kernel/stacksegment.H b/src/include/kernel/stacksegment.H
index 460a61b49..0c80d9fae 100644
--- a/src/include/kernel/stacksegment.H
+++ b/src/include/kernel/stacksegment.H
@@ -85,7 +85,7 @@ class StackSegment : public Segment
*
* Calls block chain to deal with page fault.
*/
- bool handlePageFault(task_t* i_task, uint64_t i_addr);
+ bool handlePageFault(task_t* i_task, uint64_t i_addr, bool i_store);
/**
* @brief Locate the physical address of the given virtual address
diff --git a/src/include/kernel/vmmmgr.H b/src/include/kernel/vmmmgr.H
index 46f283e18..7a1fd6f7b 100644
--- a/src/include/kernel/vmmmgr.H
+++ b/src/include/kernel/vmmmgr.H
@@ -77,13 +77,14 @@ class VmmManager
*
* @param[in] t - Task causing the page fault.
* @param[in] effAddr - Effective address accessed to cause fault.
+ * @param[in] store - The PTE miss was due to a store.
*
* @return true - PTE miss was successfully handled.
*
* If the PTE miss is not successfully handled, the exception
* handler should collect debug information and kill the task.
*/
- static bool pteMiss(task_t* t, uint64_t effAddr);
+ static bool pteMiss(task_t* t, uint64_t effAddr, bool store);
/**
* @brief Map a device into the device segment
@@ -177,7 +178,7 @@ class VmmManager
void initPTEs();
void initSDR1();
- bool _pteMiss(task_t*, uint64_t);
+ bool _pteMiss(task_t*, uint64_t, bool);
/** See findPhysicalAddress */
uint64_t _findPhysicalAddress(uint64_t i_vaddr);
diff --git a/src/kernel/basesegment.C b/src/kernel/basesegment.C
index 780c60792..8430538f8 100644
--- a/src/kernel/basesegment.C
+++ b/src/kernel/basesegment.C
@@ -89,10 +89,10 @@ void BaseSegment::_init()
}
}
-bool BaseSegment::handlePageFault(task_t* i_task, uint64_t i_addr)
+bool BaseSegment::handlePageFault(task_t* i_task, uint64_t i_addr, bool i_store)
{
// Tail recursion to block chain.
- return iv_block->handlePageFault(i_task, i_addr);
+ return iv_block->handlePageFault(i_task, i_addr, i_store);
}
/**
diff --git a/src/kernel/block.C b/src/kernel/block.C
index 221d536e1..8afc39ae7 100644
--- a/src/kernel/block.C
+++ b/src/kernel/block.C
@@ -78,13 +78,15 @@ ShadowPTE* Block::getPTE(uint64_t i_addr) const
return &iv_ptes[(i_addr - iv_baseAddr) / PAGESIZE];
};
-bool Block::handlePageFault(task_t* i_task, uint64_t i_addr)
+
+bool Block::handlePageFault(task_t* i_task, uint64_t i_addr, bool i_store)
{
// Check containment, call down chain if address isn't in this block.
if (!isContained(i_addr))
{
return (iv_nextBlock ?
- iv_nextBlock->handlePageFault(i_task, i_addr) : false);
+ iv_nextBlock->handlePageFault(i_task, i_addr, i_store) :
+ false);
}
// Calculate page aligned virtual address.
@@ -101,6 +103,19 @@ bool Block::handlePageFault(task_t* i_task, uint64_t i_addr)
return false;
}
+ // Mark the page as dirty if this is a store to it.
+ if (i_store)
+ {
+ if (pte->isWritable())
+ {
+ pte->setDirty(true);
+ }
+ else // Store to non-writable page! This is a permission fault, so
+ // return unhandled.
+ {
+ return false;
+ }
+ }
if (!pte->isPresent())
{
@@ -152,7 +167,7 @@ bool Block::handlePageFault(task_t* i_task, uint64_t i_addr)
l_addr_palign,
pte->getPage(),
(pte->isExecutable() ? EXECUTABLE :
- (pte->isWritable() ? WRITABLE :
+ ((pte->isWritable() && pte->isDirty()) ? WRITABLE :
READ_ONLY)));
return true;
@@ -217,8 +232,9 @@ void Block::attachSPTE(void *i_vaddr)
PageTableManager::addEntry((l_vaddr / PAGESIZE) * PAGESIZE,
l_pte->getPage(),
(l_pte->isExecutable() ? EXECUTABLE :
- (l_pte->isWritable() ? WRITABLE :
- READ_ONLY)));
+ ((l_pte->isWritable() && l_pte->isDirty()) ?
+ WRITABLE :
+ READ_ONLY)));
// update permission for the page that corresponds to the physical page
// addr now that we have handled the page fault.
@@ -257,9 +273,6 @@ uint64_t Block::findPhysicalAddress(uint64_t i_vaddr) const
void Block::releaseAllPages()
{
- // Release all pages from page table.
- PageTableManager::delRangeVA(iv_baseAddr, iv_baseAddr + iv_size);
-
// Free all pages back to page manager.
for(uint64_t page = iv_baseAddr;
page < (iv_baseAddr + iv_size);
@@ -268,6 +281,7 @@ void Block::releaseAllPages()
ShadowPTE* pte = getPTE(page);
if (pte->isPresent())
{
+ PageTableManager::delEntry(page);
uint64_t addr = pte->getPageAddr();
if (0 != addr)
{
@@ -308,12 +322,6 @@ void Block::updateRefCount( uint64_t i_vaddr,
{
spte->incLRU();
}
-
- // track the changed/dirty bit
- if (i_stats.C)
- {
- spte->setDirty( i_stats.C );
- }
}
diff --git a/src/kernel/devicesegment.C b/src/kernel/devicesegment.C
index fae4b7032..04e41b7be 100644
--- a/src/kernel/devicesegment.C
+++ b/src/kernel/devicesegment.C
@@ -49,7 +49,8 @@ void DeviceSegment::init(size_t segId)
* @return bool - TRUE: Page added to page table
* FALSE: Not a valid address to be paged
*/
-bool DeviceSegment::handlePageFault(task_t* i_task, uint64_t i_addr)
+bool DeviceSegment::handlePageFault(task_t* i_task, uint64_t i_addr,
+ bool i_store)
{
//Verify input address falls within this segment's address range
if (i_addr < this->getBaseAddress() ||
diff --git a/src/kernel/exception.C b/src/kernel/exception.C
index 78f43d581..2759c71e4 100644
--- a/src/kernel/exception.C
+++ b/src/kernel/exception.C
@@ -58,8 +58,10 @@ void kernel_execute_prog_ex()
}
}
-const uint64_t EXCEPTION_DSISR_MASK = 0x0000000040000000;
+const uint64_t EXCEPTION_DSISR_MASK = 0x0000000048000000;
const uint64_t EXCEPTION_DSISR_PTEMISS = 0x0000000040000000;
+const uint64_t EXCEPTION_DSISR_PERMERR = 0x0000000008000000;
+const uint64_t EXCEPTION_DSISR_STORE = 0x0000000002000000;
extern "C"
void kernel_execute_data_storage()
@@ -71,8 +73,21 @@ void kernel_execute_data_storage()
switch(exception)
{
case EXCEPTION_DSISR_PTEMISS:
- handled = VmmManager::pteMiss(t, getDAR());
+ {
+ uint64_t is_store = getDSISR() & EXCEPTION_DSISR_STORE;
+ handled = VmmManager::pteMiss(t, getDAR(), 0 != is_store);
+ break;
+ }
+
+ case EXCEPTION_DSISR_PERMERR:
+ {
+ uint64_t is_store = getDSISR() & EXCEPTION_DSISR_STORE;
+ if (is_store)
+ {
+ handled = VmmManager::pteMiss(t, getDAR(), true);
+ }
break;
+ }
}
if (!handled)
{
@@ -103,7 +118,7 @@ void kernel_execute_inst_storage()
switch (exception)
{
case EXCEPTION_SRR1_INSTR_PTEMISS:
- handled = VmmManager::pteMiss(t, getSRR0());
+ handled = VmmManager::pteMiss(t, getSRR0(), false);
break;
}
if (!handled)
diff --git a/src/kernel/ptmgr.C b/src/kernel/ptmgr.C
index 9807750ed..3d7f28578 100644
--- a/src/kernel/ptmgr.C
+++ b/src/kernel/ptmgr.C
@@ -38,62 +38,78 @@
/**
* @brief Extract a set of bits and right-justify the result
- * @param i_var64[in] 64-bit word to extract data from
- * @param i_startbit[in] Bit to start extraction from
- * @param i_lastbit[in] Bit to stop extraction on, inclusive
+ * @param[in] i_var64 64-bit word to extract data from
+ * @param[in] i_startbit Bit to start extraction from
+ * @param[in] i_lastbit Bit to stop extraction on, inclusive
* @return uint64_t Right-justified data
*/
-ALWAYS_INLINE uint64_t EXTRACT_RJ( uint64_t i_var64,
- uint64_t i_startbit,
- uint64_t i_lastbit )
+ALWAYS_INLINE static
+uint64_t EXTRACT_RJ( uint64_t i_var64,
+ uint64_t i_startbit,
+ uint64_t i_lastbit )
{
- uint64_t mask = ((0xFFFFFFFFFFFFFFFF >> i_startbit) & (0xFFFFFFFFFFFFFFFF << (63 - i_lastbit)));
+ uint64_t mask = ((0xFFFFFFFFFFFFFFFF >> i_startbit) &
+ (0xFFFFFFFFFFFFFFFF << (63 - i_lastbit)));
uint64_t result = (i_var64 & mask) >> (63 - i_lastbit);
return result;
}
/**
* @brief Extract a set of bits and left-justify the result
- * @param i_var64[in] 64-bit word to extract data from
- * @param i_startbit[in] Bit to start extraction from
- * @param i_lastbit[in] Bit to stop extraction on, inclusive
+ * @param[in] i_var64 64-bit word to extract data from
+ * @param[in] i_startbit Bit to start extraction from
+ * @param[in] i_lastbit Bit to stop extraction on, inclusive
* @return uint64_t Left-justified data
*/
-ALWAYS_INLINE uint64_t EXTRACT_LJ( uint64_t var64,
- uint64_t i_startbit,
- uint64_t i_lastbit )
+/*
+ALWAYS_INLINE static
+uint64_t EXTRACT_LJ( uint64_t var64,
+ uint64_t i_startbit,
+ uint64_t i_lastbit )
{
- uint64_t mask = ((0xFFFFFFFFFFFFFFFF >> i_startbit) & (0xFFFFFFFFFFFFFFFF << (63 - i_lastbit)));
+ uint64_t mask = ((0xFFFFFFFFFFFFFFFF >> i_startbit) &
+ (0xFFFFFFFFFFFFFFFF << (63 - i_lastbit)));
uint64_t result = (var64 & mask) << i_startbit;
return result;
}
+*/
/**
- * @brief Extract a set of bits from the last word of data and right-justify the result
+ * @brief Extract a set of bits from the last word of data and right-justify
+ * the result
*
* Example: Extract bits 25:54 from a 79 bit buffer :
* bb = EXTRACT_RJ_LEN(aa,79,25,54)
*
- * @param i_lastword[in] Right-most 64-bit word of larger data buffer, data[len-64:len]
- * @param i_bitlen[in] Total number of bits in original buffer
- * @param i_startbit[in] Bit to start extraction from, relative to original bit length
- * @param i_lastbit[in] Bit to stop extraction on, inclusive, relative to original bit length
+ * @param[in] i_lastword Right-most 64-bit word of larger data buffer,
+ * data[len-64:len]
+ * @param[in] i_bitlen Total number of bits in original buffer
+ * @param[in] i_startbit Bit to start extraction from, relative to original
+ * bit length
+ * @param[in] i_lastbit Bit to stop extraction on, inclusive, relative to
+ * original bit length
* @return uint64_t Left-justified data
*/
-ALWAYS_INLINE uint64_t EXTRACT_RJ_LEN( uint64_t i_lastword,
- uint64_t i_bitlen,
- uint64_t i_startbit,
- uint64_t i_lastbit )
+ALWAYS_INLINE static
+uint64_t EXTRACT_RJ_LEN( uint64_t i_lastword,
+ uint64_t i_bitlen,
+ uint64_t i_startbit,
+ uint64_t i_lastbit )
{
- Dprintk( "i_lastword=%.16lX, i_bitlen=%ld, i_startbit=%ld, i_lastbit=%ld\n", i_lastword, i_bitlen, i_startbit, i_lastbit );
+ Dprintk( "i_lastword=%.16lX, i_bitlen=%ld, i_startbit=%ld, i_lastbit=%ld\n",
+ i_lastword, i_bitlen, i_startbit, i_lastbit );
if( (i_lastbit - i_startbit) > 64 )
{
- Eprintk("error %d : i_lastword=%.16lX, i_bitlen=%ld, i_startbit=%ld, i_lastbit=%ld\n", __LINE__, i_lastword, i_bitlen, i_startbit, i_lastbit);
+ Eprintk("error %d : i_lastword=%.16lX, i_bitlen=%ld, i_startbit=%ld,"
+ " i_lastbit=%ld\n", __LINE__,
+ i_lastword, i_bitlen, i_startbit, i_lastbit);
kassert(false);
}
else if( i_lastbit >= i_bitlen )
{
- Eprintk("error %d : i_lastword=%.16lX, i_bitlen=%ld, i_startbit=%ld, i_lastbit=%ld\n", __LINE__, i_lastword, i_bitlen, i_startbit, i_lastbit);
+ Eprintk("error %d : i_lastword=%.16lX, i_bitlen=%ld, i_startbit=%ld,"
+ " i_lastbit=%ld\n", __LINE__,
+ i_lastword, i_bitlen, i_startbit, i_lastbit);
kassert(false);
}
else if( i_bitlen <= 64 )
@@ -129,32 +145,46 @@ ALWAYS_INLINE uint64_t EXTRACT_RJ_LEN( uint64_t i_lastword,
}
/**
- * @brief Extract a set of bits from the last word of data and left-justify the result
+ * @brief Extract a set of bits from the last word of data and left-justify
+ * the result
*
- * @param i_lastword[in] Right-most 64-bit word of larger data buffer, data[len-64:len]
- * @param i_bitlen[in] Total number of bits in original buffer
- * @param i_startbit[in] Bit to start extraction from, relative to original bit length
- * @param i_lastbit[in] Bit to stop extraction on, inclusive, relative to original bit length
+ * @param[in] i_lastword Right-most 64-bit word of larger data buffer,
+ * data[len-64:len]
+ * @param[in] i_bitlen Total number of bits in original buffer
+ * @param[in] i_startbit Bit to start extraction from, relative to original
+ * bit length
+ * @param[in] i_lastbit Bit to stop extraction on, inclusive, relative to
+ * original bit length
* @return uint64_t Left-justified data
*/
-ALWAYS_INLINE uint64_t EXTRACT_LJ_LEN( uint64_t i_lastword, uint64_t i_bitlen, uint64_t i_startbit, uint64_t i_lastbit )
+/*
+ALWAYS_INLINE static
+uint64_t EXTRACT_LJ_LEN( uint64_t i_lastword,
+ uint64_t i_bitlen,
+ uint64_t i_startbit,
+ uint64_t i_lastbit )
{
uint64_t diff = i_bitlen - 64;
i_lastword = i_lastword >> diff;
if( i_lastbit < 64 ) {
i_lastbit = i_lastbit - diff;
} else {
- Eprintk("error %d : i_lastword=%lX, i_bitlen=%ld, i_startbit=%ld, i_lastbit=%ld\n", __LINE__, i_lastword, i_bitlen, i_startbit, i_lastbit);
+ Eprintk("error %d : i_lastword=%lX, i_bitlen=%ld, i_startbit=%ld,"
+ " i_lastbit=%ld\n", __LINE__,
+ i_lastword, i_bitlen, i_startbit, i_lastbit);
kassert(false);
}
if( i_startbit < 64 ) {
i_startbit = i_startbit - diff;
} else {
- Eprintk("error %d : i_lastword=%lX, i_bitlen=%ld, i_startbit=%ld, i_lastbit=%ld\n", __LINE__, i_lastword, i_bitlen, i_startbit, i_lastbit);
+ Eprintk("error %d : i_lastword=%lX, i_bitlen=%ld, i_startbit=%ld,"
+ " i_lastbit=%ld\n", __LINE__,
+ i_lastword, i_bitlen, i_startbit, i_lastbit);
kassert(false);
}
return EXTRACT_LJ( i_lastword, i_startbit, i_lastbit );
}
+*/
/********************
Public Methods
@@ -228,7 +258,9 @@ void PageTableManager::printPTE( const char* i_label,
uint64_t i_pteAddr,
bool i_verbose )
{
+#ifdef HOSTBOOT_DEBUG
Singleton<PageTableManager>::instance().printPTE( i_label, (PageTableEntry*)i_pteAddr, i_verbose );
+#endif
}
/**
@@ -238,8 +270,10 @@ void PageTableManager::printPTE( const char* i_label,
void PageTableManager::printPTE( uint64_t i_va,
bool i_verbose )
{
+#ifdef HOSTBOOT_DEBUG
PageTableEntry* pte = Singleton<PageTableManager>::instance().findPTE(i_va);
Singleton<PageTableManager>::instance().printPTE( NULL, pte, i_verbose );
+#endif
}
/**
@@ -248,7 +282,9 @@ void PageTableManager::printPTE( uint64_t i_va,
*/
void PageTableManager::printPT( void )
{
+#ifdef HOSTBOOT_DEBUG
Singleton<PageTableManager>::instance()._printPT();
+#endif
}
void PageTableManager::flush( void )
@@ -273,7 +309,8 @@ PageTableManager::PageTableManager( bool i_userSpace )
}
else
{
- printkd( "Page Table is at 0x%.16lX : 0x%.16lX\n", getAddress(), getAddress() + getSize() );
+ printkd( "Page Table is at 0x%.16lX : 0x%.16lX\n",
+ getAddress(), getAddress() + getSize() );
}
//initialize the table to be invalid
@@ -310,7 +347,8 @@ void PageTableManager::_addEntry( uint64_t i_vAddr,
uint64_t i_page,
uint64_t i_accessType )
{
- Tprintk( ">> PageTableManager::_addEntry( i_vAddr=0x%.16lX, i_page=%ld, i_accessType=%d )\n", i_vAddr, i_page, i_accessType );
+ Tprintk( ">> PageTableManager::_addEntry( i_vAddr=0x%.16lX, i_page=%ld,"
+ " i_accessType=%d )\n", i_vAddr, i_page, i_accessType );
//Note: no need to lock here because that is handled by higher function
@@ -340,7 +378,6 @@ void PageTableManager::_addEntry( uint64_t i_vAddr,
// since the entry isn't in the table right now we should
// start fresh with the usage bits
- pte_data.C = 0b0; //Clear Changed bit
pte_data.R = 0b0; //Clear Referenced bit
pte_data.LRU = 0b00; //Clear LRU bits
}
@@ -350,16 +387,25 @@ void PageTableManager::_addEntry( uint64_t i_vAddr,
{
if( i_page != pte_slot->PN )
{
- Eprintk( "**ERROR** PageTableManager::_addEntry> Duplicate PTE with different page number\n" );
+ Eprintk( "**ERROR** PageTableManager::_addEntry>"
+ " Duplicate PTE with different page number\n" );
kassert(false);
}
}
+ else
+ {
+ // We reused a PTE previously used, but it wasn't marked valid
+ // so clear the R/LRU bits to reset it to a clean state.
+ pte_data.R = 0b0; //Clear Referenced bit
+ pte_data.LRU = 0b00; //Clear LRU bits
+ }
}
// we can't handle any other cases...
if( pte_slot == NULL )
{
- Eprintk( "**ERROR** PageTableManager::_addEntry> Nowhere to put the new PTE\n" );
+ Eprintk( "**ERROR** PageTableManager::_addEntry>"
+ " Nowhere to put the new PTE\n" );
kassert(false);
}
@@ -399,18 +445,21 @@ void PageTableManager::_delEntry( uint64_t i_vAddr )
*/
void PageTableManager::delEntry( PageTableEntry* i_pte )
{
- // clear the entry from the table
- writePTE( i_pte, i_pte, false );
+ if (i_pte->V)
+ {
+ // clear the entry from the table
+ writePTE( i_pte, i_pte, false );
- // need to notify VMM when we remove a PTE
- pushUsageStats( i_pte );
+ // need to notify VMM when we remove a PTE
+ pushUsageStats( i_pte );
+ }
}
/**
* @brief Remove a range of entries from the hardware page table
*/
void PageTableManager::_delRangeVA( uint64_t i_vAddrStart,
- uint64_t i_vAddrFinish )
+ uint64_t i_vAddrFinish )
{
// Note : this could potentially be very slow for large ranges
@@ -482,7 +531,7 @@ uint64_t PageTableManager::getStatus( PageTableEntry* i_pte )
case SegmentManager::CI_ACCESS:
status |= PTE_CACHE_INHIBITED;
break;
-
+
case READ_ONLY:
status |= PTE_READ;
break;
@@ -492,7 +541,7 @@ uint64_t PageTableManager::getStatus( PageTableEntry* i_pte )
status |= PTE_READ;
break;
- case EXECUTABLE:
+ case EXECUTABLE:
status |= PTE_EXECUTE;
status |= PTE_READ;
break;
@@ -501,9 +550,6 @@ uint64_t PageTableManager::getStatus( PageTableEntry* i_pte )
break;
}
- if( i_pte->C == 1 ) {
- status |= PTE_MODIFIED;
- }
if( i_pte->R == 1 ) {
status |= PTE_ACCESSED;
}
@@ -563,7 +609,8 @@ uint64_t PageTableManager::computeHash( uint64_t i_vAddr )
}
/**
- * @brief Find the 60-bit real address of the PTEG that matches the given virtual address
+ * @brief Find the 60-bit real address of the PTEG that matches the given
+ * virtual address
*/
uint64_t PageTableManager::findPTEG( uint64_t i_vAddr )
{
@@ -576,7 +623,8 @@ uint64_t PageTableManager::findPTEG( uint64_t i_vAddr )
// use the hash as the index into the array of PTEGs
uint64_t pteg_addr = getAddress() + hash * PTEG_SIZE_BYTES;
- Dprintk( "PageTableManager::findPTEG(i_vAddr=0x%.16lX) = 0x%.16lX\n", i_vAddr, pteg_addr );
+ Dprintk( "PageTableManager::findPTEG(i_vAddr=0x%.16lX) = 0x%.16lX\n",
+ i_vAddr, pteg_addr );
return pteg_addr;
}
@@ -601,9 +649,12 @@ PageTableManager::PageTableEntry* PageTableManager::findPTE( uint64_t i_vAddr )
* @brief Find the real address of the PTE that matches the given address
*/
PageTableManager::PageTableEntry* PageTableManager::findPTE( uint64_t i_vAddr,
- uint64_t i_ptegAddr )
+ uint64_t i_ptegAddr
+ )
{
- Tprintk( "PageTableManager::findPTE(i_vAddr=0x%.16lX,i_ptegAddr=0x%.16lX)>>\n", i_vAddr, i_ptegAddr );
+ Tprintk( "PageTableManager::findPTE(i_vAddr=0x%.16lX"
+ ",i_ptegAddr=0x%.16lX)>>\n",
+ i_vAddr, i_ptegAddr );
PageTableEntry* pte_found = NULL;
@@ -625,7 +676,8 @@ PageTableManager::PageTableEntry* PageTableManager::findPTE( uint64_t i_vAddr,
pte_cur++;
}
- Dprintk( "<<PageTableManager::findPTE() = %.16lX>>\n", (uint64_t)pte_found );
+ Dprintk( "<<PageTableManager::findPTE() = %.16lX>>\n",
+ (uint64_t)pte_found );
return pte_found;
}
@@ -645,44 +697,49 @@ void PageTableManager::writePTE( PageTableEntry* i_pte,
// this should never happen because we should always go
// through the delEntry() path instead
printPTE( "Stealing", i_dest ); /*no effect*/ // BEAM Fix.
- Eprintk( "**ERROR** PageTableManager::writePTE> Trying to steal a PTE\n" );
+ Eprintk( "**ERROR** PageTableManager::writePTE>"
+ " Trying to steal a PTE\n" );
kassert(false);
}
}
- if(ivTABLE)
+ if(unlikely(ivTABLE != NULL))
{
- Dprintk( ">> PageTableManager::writePTE( i_dest=%p, i_valid=%d ) **FAKE**\n", i_dest, i_valid );
+ Dprintk( ">> PageTableManager::writePTE( i_dest=%p, i_valid=%d )"
+ " **FAKE**\n",
+ i_dest, i_valid );
memcpy( (void*) i_dest, (void*) i_pte, sizeof(PageTableEntry) );
if( i_valid ) {
i_dest->V = 1;
//printPTE( "Writing", i_dest );
} else {
i_dest->V = 0;
- //printk( ">> PageTableManager::writePTE( i_dest=%p, i_valid=%d ) **FAKE**\n", i_dest, i_valid );
+ //printk( ">> PageTableManager::writePTE( i_dest=%p, i_valid=%d )"
+ // " **FAKE**\n",
+ // i_dest, i_valid );
//printPTE( "Removing", i_dest );
}
}
else
{
- Dprintk( ">> PageTableManager::writePTE( i_dest=0x%.lX, i_valid=%d )\n", i_dest, i_valid );
-
- //if( i_valid ) {
- //printPTE( "Writing", i_dest );
- //} else {
- //printPTE( "Removing", i_dest );
- //}
+ Dprintk( ">> PageTableManager::writePTE( i_dest=0x%.lX, i_valid=%d )\n",
+ i_dest, i_valid );
- i_dest->V = 0; /* (other fields don't matter) */
+ // If we are invalidating or modifying permissions, need to invalidate
+ // the PTE.
+ if ((!i_valid) || (i_dest->V == 1) )
+ {
+ i_dest->V = 0; /* (other fields don't matter) */
- /* order update before tlbie and before next Page Table search */
- asm volatile("ptesync" ::: "memory");
+ /* order update before tlbie and before next Page Table search */
+ asm volatile("ptesync" ::: "memory");
- // tlbie, eieio, tlbsync, ptesync
- invalidateTLB(i_dest);
+ // tlbie, eieio, tlbsync, ptesync
+ invalidateTLB(i_dest);
+ }
- // if we're removing an entry we can ignore the other fields
- if( i_valid )
+ // Requested to mark page valid?
+ if (i_valid)
{
//PTE:ARPN,LP,AC,R,C,WIMG,N,PP set to new values
i_dest->dword1 = i_pte->dword1;
@@ -701,7 +758,10 @@ void PageTableManager::writePTE( PageTableEntry* i_pte,
}
// update the other entries' LRU statistics
- updateLRU( i_dest );
+ if (i_valid)
+ {
+ updateLRUGroup( i_dest );
+ }
Dprintk( "<< PageTableManager::writePTE()\n" );
}
@@ -714,6 +774,7 @@ void PageTableManager::printPTE( const char* i_label,
const PageTableEntry* i_pte,
bool i_verbose )
{
+#ifdef HOSTBOOT_DEBUG
if( i_pte == NULL )
{
if( i_label ) { printkd( "%s :: ", i_label ); }
@@ -743,7 +804,7 @@ void PageTableManager::printPTE( const char* i_label,
{
printkd( "[%4ld:%4ld]> @%p : %.16lX %.16lX : VA=%16lX, PN=%ld\n", pte_num/PTEG_SIZE, pte_num%PTEG_SIZE, i_pte, i_pte->dword0, i_pte->dword1, getVirtAddrFromPTE(i_pte), i_pte->PN );
}
-
+#endif
}
@@ -752,6 +813,7 @@ void PageTableManager::printPTE( const char* i_label,
*/
void PageTableManager::_printPT( void )
{
+#ifdef HOSTBOOT_DEBUG
printkd( "- -Page Table --\n" );
uint64_t pt_addr = getAddress();
PageTableEntry* pte = (PageTableEntry*) pt_addr;
@@ -769,6 +831,7 @@ void PageTableManager::_printPT( void )
}
printkd( "-- End Page Table --\n" );
+#endif
}
/**
@@ -776,7 +839,7 @@ void PageTableManager::_printPT( void )
*/
uint64_t PageTableManager::getAddress( void )
{
- if(ivTABLE) {
+ if(unlikely(ivTABLE != NULL)) {
return (uint64_t)ivTABLE;
} else {
return VmmManager::HTABORG;
@@ -861,10 +924,10 @@ uint64_t PageTableManager::getAccessType( const PageTableEntry* i_pte )
else if (i_pte->WIMG == 0b0010)
{
if (i_pte->pp1_2 == 0b00)
- {
+ {
return NO_ACCESS;
}
- // If read and no execute
+ // If read and no execute
else if ((i_pte->pp1_2 == 0b01) && (i_pte->N == 0b1))
{
return READ_ONLY;
@@ -874,35 +937,41 @@ uint64_t PageTableManager::getAccessType( const PageTableEntry* i_pte )
{
return WRITABLE;
}
- // if readably and executable..
+ // if readably and executable..
else if ((i_pte->pp1_2 == 0b01) && (i_pte->N == 0b0))
{
- return EXECUTABLE;
+ return EXECUTABLE;
}
}
}
- Eprintk( "I don't recognize this PTE : WIMG=%ld, pp1_2=%ld\n", i_pte->WIMG, i_pte->pp1_2 );
+ 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
*/
+ALWAYS_INLINE
void PageTableManager::setupDefaultPTE( PageTableEntry* o_pte )
{
o_pte->B = 0b01; //Segment Size (01=1TB)
o_pte->L = 0b0; //Virtual page size (1=>4KB)
o_pte->H = 0b0; //Hash function identifier (0=primary hash)
+ o_pte->C = 0b1; // Mark change bit so HW doesn't have to; we don't use
+ // the change bits anyhow.
}
/**
* @brief Find the real address of a PTE that that is empty or invalid
*/
-PageTableManager::PageTableEntry* PageTableManager::findEmptyPTE( uint64_t i_ptegAddr )
+PageTableManager::PageTableEntry*
+ PageTableManager::findEmptyPTE( uint64_t i_ptegAddr )
{
- Tprintk( "PageTableManager::findEmptyPTE(i_ptegAddr=0x%.16lX)>>\n", i_ptegAddr );
+ Tprintk( "PageTableManager::findEmptyPTE(i_ptegAddr=0x%.16lX)>>\n",
+ i_ptegAddr );
PageTableEntry* pte_slot = NULL;
PageTableEntry* pte_cur = (PageTableEntry*)i_ptegAddr;
@@ -930,7 +999,8 @@ PageTableManager::PageTableEntry* PageTableManager::findEmptyPTE( uint64_t i_pte
* @brief Find the real address of a PTE that can be invalidated
* and replaced
*/
-PageTableManager::PageTableEntry* PageTableManager::findOldPTE( uint64_t i_ptegAddr )
+PageTableManager::PageTableEntry*
+ PageTableManager::findOldPTE( uint64_t i_ptegAddr )
{
// Order of preference for PTE slots to steal:
// 1) PTE with highest use count (LRU==SW[2:3])
@@ -952,15 +1022,16 @@ PageTableManager::PageTableEntry* PageTableManager::findOldPTE( uint64_t i_ptegA
}
/**
- * @brief Update the LRU statistics for other PTEs in the same PTEG as the target
+ * @brief Update the LRU statistics for other PTEs in the same PTEG as
+ * the target
*/
-void PageTableManager::updateLRU( const PageTableEntry* i_newPTE )
+void PageTableManager::updateLRUGroup( const PageTableEntry* i_newPTE )
{
- Tprintk( ">> PageTableManager::updateLRU( i_newPTE=%p )\n", i_newPTE );
+ Tprintk( ">> PageTableManager::updateLRUGroup( i_newPTE=%p )\n", i_newPTE );
- // find the beginning of the PTEG
- uint64_t pteg_addr = (((uint64_t)i_newPTE) - getAddress()) / PTEG_SIZE_BYTES;
- pteg_addr = pteg_addr*PTEG_SIZE_BYTES + getAddress();
+ // find the beginning of the PTEG, by rounding down by PTEG_SIZE_BYTES.
+ uint64_t pteg_addr = (((uint64_t)i_newPTE) / PTEG_SIZE_BYTES) *
+ PTEG_SIZE_BYTES;
// loop through all 8 PTEs in the PTEG
PageTableEntry* pte_cur = (PageTableEntry*)pteg_addr;
@@ -969,62 +1040,60 @@ void PageTableManager::updateLRU( const PageTableEntry* i_newPTE )
// skip the entry we just added
if( pte_cur != i_newPTE )
{
- PageTableEntry new_pte = *pte_cur;
- PageTableEntry old_pte = *pte_cur;
-
- // use this funny loop to avoid races where another thread
- // is causing the C bit to be updated at the same time
- do {
- new_pte = *pte_cur;
- old_pte = *pte_cur;
-
- // if the entry is valid and has been used since last update
- // then reset the LRU to 0 and clear the R bit
- if( (new_pte.V == 1) && (new_pte.R == 1) )
- {
- new_pte.LRU = 0;
- new_pte.R = 0;
- new_pte.R2 = 1; // remember that the R bit was set
- }
- else
- {
- // page hasn't been used, increment the LRU
- if( new_pte.LRU < 0b11 )
- {
- new_pte.LRU++;
- }
- }
-
-
- // if the value currently in the table (pte_cur) is still
- // equal to the value we saved off earlier (old_pte) then
- // we will write our new data (new_pte) into the table
- // else we will try again
- } while( !__sync_bool_compare_and_swap( &(pte_cur->dword1),
- old_pte.dword1,
- new_pte.dword1 ) );
-
- // LRU and R2 are on dword0
- pte_cur->dword0 = new_pte.dword0;
-
- // tlbie, eieio, tlbsync, ptesync
- invalidateTLB(pte_cur);
+ updateLRUEntry(pte_cur);
}
pte_cur++;
}
- Tprintk( "<< PageTableManager::updateLRU(\n" );
+ Tprintk( "<< PageTableManager::updateLRUGroup(\n" );
}
/**
+ * @brief Update the LRU statistics for a specific PTE.
+ */
+void PageTableManager::updateLRUEntry( PageTableEntry* i_PTE )
+{
+ Tprintk( ">> PageTableManager::updateLRUEntry( i_PTE=%p )\n", i_PTE);
+
+ PageTableEntry pte = *i_PTE;
+
+ // Check if referenced.
+ if ((pte.V == 1) && (pte.R == 1))
+ {
+ // Save software bit updates for later.
+ pte.LRU = 0;
+ pte.R2 = 1;
+
+ // Update R bit in PTE.
+ // See Resetting the Reference Bit in ISA.
+ i_PTE->R = 0; // should only be updating 1 byte.
+ invalidateTLB(i_PTE);
+ }
+ else if (pte.LRU < 0b11)
+ {
+ pte.LRU++;
+ }
+
+ // Update the sofware bits of the PTE.
+ // The ISA suggests we need to do a ldarx/stdcx combination
+ // here, but this isn't required because we have a spinlock
+ // around the page table as a whole. No other thread will
+ // be even reading this word here.
+ i_PTE->dword0 = pte.dword0;
+
+ Tprintk( "<< PageTableManager::updateLRUEntry(\n" );
+}
+
+
+/**
* @brief Invalidate TLB for a PTE
*/
void PageTableManager::invalidateTLB( PageTableEntry* i_pte )
{
Tprintk( ">> PageTableManager::invalidateTLB( i_pte=%p )\n", i_pte );
- if( ivTABLE == NULL )
+ if( likely(ivTABLE == NULL) )
{
// TLBIE's AVA is 14:65 of the original VA (!= pte->AVA)
uint64_t tlbie_ava = EXTRACT_RJ_LEN(
@@ -1099,51 +1168,37 @@ uint64_t PageTableManager::getVirtAddrFromPTE( const PageTableEntry* i_pte )
void PageTableManager::pushUsageStats( PageTableEntry* i_pte )
{
// skip this in unit-test mode because addresses aren't really backed
- if( ivTABLE )
+ if( unlikely(ivTABLE != NULL) )
{
return;
}
UsageStats_t stats;
- PageTableEntry new_pte = *i_pte;
- PageTableEntry old_pte = *i_pte;
+ // Read LRU.
+ stats.LRU = i_pte->LRU;
- // use this funny loop to avoid races where another thread
- // is causing the C bit to be updated at the same time
- do {
- new_pte = *i_pte;
- old_pte = *i_pte;
-
- // always update the R,R2,C bits, even for invalid entries
- // it is up to the caller to be sensible about when this
- // function is called
-
- // read and clear the referenced bit
- stats.R = new_pte.R || new_pte.R2;
- new_pte.R = 0;
- new_pte.R2 = 0; //R2 is on dword0
-
- // read and clear the changed bit
- stats.C = new_pte.C;
- new_pte.C = 0;
-
- // just read the LRU and send it up
- stats.LRU = new_pte.LRU;
-
- // if the value currently in the table (i_pte) is still
- // equal to the value we saved off earlier (old_pte) then
- // we will write our new data (new_pte) into the table
- // else we will try again
- } while( !__sync_bool_compare_and_swap( &(i_pte->dword1),
- old_pte.dword1,
- new_pte.dword1 ) );
-
- // R2 is on dword0
- i_pte->dword0 = new_pte.dword0;
+ // Update R-bit.
+ // See Resetting the Reference Bit in ISA.
+ if (i_pte->R)
+ {
+ stats.R = 1;
+ i_pte->R = 0;
+ invalidateTLB(i_pte);
+ }
- // tlbie, eieio, tlbsync, ptesync
- invalidateTLB(i_pte);
+ // Update R2-bit (saved reference from updateLRUEntry).
+ if (i_pte->R2)
+ {
+ stats.R = 1;
+
+ // Update R2 (software field) bit in PTE.
+ // The ISA suggests we need to do a ldarx/stdcx combination
+ // here, but this isn't required because we have a spinlock
+ // around the page table as a whole. No other thread will
+ // be even reading this word here.
+ i_pte->R2 = 0;
+ }
// now we need to send what we learned to the rest of the VMM
uint64_t va = getVirtAddrFromPTE(i_pte);
@@ -1152,7 +1207,7 @@ void PageTableManager::pushUsageStats( PageTableEntry* i_pte )
void PageTableManager::_flush( void )
{
- if( ivTABLE )
+ if( unlikely(ivTABLE != NULL) )
{
return;
}
@@ -1161,8 +1216,10 @@ void PageTableManager::_flush( void )
uint64_t num_ptes = getSize() / sizeof(PageTableEntry);
for (uint64_t i = 0; i < num_ptes; ++i)
{
- updateLRU( pte );
- pushUsageStats ( pte );
+ if (pte->V)
+ {
+ pushUsageStats ( pte );
+ }
++pte;
}
}
diff --git a/src/kernel/segmentmgr.C b/src/kernel/segmentmgr.C
index 6659c634c..998e7af5a 100644
--- a/src/kernel/segmentmgr.C
+++ b/src/kernel/segmentmgr.C
@@ -30,10 +30,11 @@
#include <kernel/segment.H>
#include <kernel/devicesegment.H>
-bool SegmentManager::handlePageFault(task_t* i_task, uint64_t i_addr)
+bool SegmentManager::handlePageFault(task_t* i_task, uint64_t i_addr,
+ bool i_store)
{
return Singleton<SegmentManager>::instance().
- _handlePageFault(i_task, i_addr);
+ _handlePageFault(i_task, i_addr, i_store);
}
void SegmentManager::addSegment(Segment* i_segment, size_t i_segId)
@@ -72,14 +73,15 @@ int SegmentManager::devUnmap(void* ea)
return Singleton<SegmentManager>::instance()._devUnmap(ea);
}
-bool SegmentManager::_handlePageFault(task_t* i_task, uint64_t i_addr)
+bool SegmentManager::_handlePageFault(task_t* i_task, uint64_t i_addr,
+ bool i_store)
{
size_t segId = getSegmentIdFromAddress(i_addr);
// Call contained segment object to handle page fault.
if ((segId < MAX_SEGMENTS) && (NULL != iv_segments[segId]))
{
- return iv_segments[segId]->handlePageFault(i_task, i_addr);
+ return iv_segments[segId]->handlePageFault(i_task, i_addr, i_store);
}
return false;
diff --git a/src/kernel/stacksegment.C b/src/kernel/stacksegment.C
index f7ced0f1f..fdc6c7a8f 100644
--- a/src/kernel/stacksegment.C
+++ b/src/kernel/stacksegment.C
@@ -61,7 +61,8 @@ StackSegment::~StackSegment()
} while (l_node != NULL); /*using deallocated*/ // BEAM invalid error.
}
-bool StackSegment::handlePageFault(task_t* i_task, uint64_t i_addr)
+bool StackSegment::handlePageFault(task_t* i_task, uint64_t i_addr,
+ bool i_store)
{
uint64_t l_addr_8mb = i_addr & ~((8*MEGABYTE) - 1);
@@ -69,7 +70,7 @@ bool StackSegment::handlePageFault(task_t* i_task, uint64_t i_addr)
return (NULL == l_node ?
false :
- l_node->block->handlePageFault(i_task, i_addr));
+ l_node->block->handlePageFault(i_task, i_addr, i_store));
}
uint64_t StackSegment::findPhysicalAddress(uint64_t i_vaddr) const
diff --git a/src/kernel/vmmmgr.C b/src/kernel/vmmmgr.C
index b1f13f1a3..ed88a4879 100644
--- a/src/kernel/vmmmgr.C
+++ b/src/kernel/vmmmgr.C
@@ -66,9 +66,9 @@ void VmmManager::init_slb()
v.initSDR1(); /*no effect*/ // BEAM Fix.
}
-bool VmmManager::pteMiss(task_t* t, uint64_t effAddr)
+bool VmmManager::pteMiss(task_t* t, uint64_t effAddr, bool store)
{
- return Singleton<VmmManager>::instance()._pteMiss(t, effAddr);
+ return Singleton<VmmManager>::instance()._pteMiss(t, effAddr, store);
}
uint64_t VmmManager::findPhysicalAddress(uint64_t i_vaddr)
@@ -112,11 +112,11 @@ void VmmManager::initSDR1()
asm volatile("mtsdr1 %0" :: "r"(sdr1) : "memory");
}
-bool VmmManager::_pteMiss(task_t* t, uint64_t effAddr)
+bool VmmManager::_pteMiss(task_t* t, uint64_t effAddr, bool store)
{
lock.lock();
- bool rc = SegmentManager::handlePageFault(t, effAddr);
+ bool rc = SegmentManager::handlePageFault(t, effAddr, store);
lock.unlock();
OpenPOWER on IntegriCloud