diff options
| author | Patrick Williams <iawillia@us.ibm.com> | 2011-07-08 19:33:40 -0500 |
|---|---|---|
| committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2011-07-20 14:58:43 -0500 |
| commit | 471f09f1a9bcc46fc385fa8aca776cb682075c0b (patch) | |
| tree | e0a4969825799dcc4c28a71975cb68439f507390 /src/kernel/segmentmgr.C | |
| parent | 3ecf7085ccc55eb4f815a62f47ea09f55bb6688e (diff) | |
| download | talos-hostboot-471f09f1a9bcc46fc385fa8aca776cb682075c0b.tar.gz talos-hostboot-471f09f1a9bcc46fc385fa8aca776cb682075c0b.zip | |
VMM Improvements.
- Segment Manager
- Base / Device Segments
- Block for Base image.
Change-Id: Ic0c058e5c5b210ec1c48d30f6ed9f9837d74a3c8
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/193
Tested-by: Jenkins Server
Reviewed-by: MATTHEW S. BARTH <msbarth@us.ibm.com>
Diffstat (limited to 'src/kernel/segmentmgr.C')
| -rw-r--r-- | src/kernel/segmentmgr.C | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/kernel/segmentmgr.C b/src/kernel/segmentmgr.C new file mode 100644 index 000000000..fae9d3479 --- /dev/null +++ b/src/kernel/segmentmgr.C @@ -0,0 +1,76 @@ +#include <assert.h> +#include <arch/ppc.H> +#include <util/singleton.H> + +#include <kernel/segmentmgr.H> +#include <kernel/segment.H> + +bool SegmentManager::handlePageFault(task_t* i_task, uint64_t i_addr) +{ + return Singleton<SegmentManager>::instance(). + _handlePageFault(i_task, i_addr); +} + +void SegmentManager::addSegment(Segment* i_segment, size_t i_segId) +{ + Singleton<SegmentManager>::instance()._addSegment(i_segment, i_segId); +} + +void SegmentManager::initSLB() +{ + Singleton<SegmentManager>::instance()._initSLB(); +} + +bool SegmentManager::_handlePageFault(task_t* i_task, uint64_t i_addr) +{ + // This constant should come from page manager. Segment size. + const size_t SLBE_s = 40; + + // Get segment ID from effective address. + size_t segId = i_addr >> SLBE_s; + + // 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 false; +} + +void SegmentManager::_addSegment(Segment* i_segment, size_t i_segId) +{ + kassert(i_segId < MAX_SEGMENTS); + iv_segments[i_segId] = i_segment; +} + +void SegmentManager::_initSLB() +{ + // Flush SLB. + asm volatile("slbia" ::: "memory"); + isync(); // Ensure slbia completes prior to slbmtes. + + register uint64_t slbRS, slbRB; + + // Default segment descriptors. + // ESID = 0, V = 1, Index = 1. + slbRB = 0x0000000008000001; + // B = 01 (1TB), VSID = 0, Ks = 0, Kp = 1, NLCLP = 0 + slbRS = 0x4000000000000400; + + // Add all segments to SLB. + for (size_t i = 0; i < MAX_SEGMENTS; i++) + { + // Add segment to SLB. + if (NULL != iv_segments[i]) + { + asm volatile("slbmte %0, %1" :: "r"(slbRS), "r"(slbRB) : "memory"); + } + + // Increment ESID, VSID, Index. + slbRB += 0x0000010000000001; + slbRS += 0x0000000001000000; + } + + isync(); // Ensure slbmtes complete prior to continuing on. +} |

