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/devicesegment.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/devicesegment.C')
| -rw-r--r-- | src/kernel/devicesegment.C | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/kernel/devicesegment.C b/src/kernel/devicesegment.C new file mode 100644 index 000000000..446d17298 --- /dev/null +++ b/src/kernel/devicesegment.C @@ -0,0 +1,91 @@ +#include <util/singleton.H> +#include <limits.h> + +#include <kernel/vmmmgr.H> +#include <kernel/ptmgr.H> +#include <kernel/devicesegment.H> +#include <kernel/segmentmgr.H> + +#define SLBE_s 40 + +#include <kernel/console.H> + +void DeviceSegment::init() +{ + Singleton<DeviceSegment>::instance()._init(); +} + +void* DeviceSegment::mmioMap(void* ra, size_t pages) +{ + return Singleton<DeviceSegment>::instance()._mmioMap(ra, pages); +} + +int DeviceSegment::mmioUnmap(void* ea, size_t pages) +{ + return Singleton<DeviceSegment>::instance()._mmioUnmap(ea, pages); +} + +void DeviceSegment::_init() +{ + SegmentManager::addSegment(this, SegmentManager::MMIO_SEGMENT_ID); +} + +bool DeviceSegment::handlePageFault(task_t* i_task, uint64_t i_addr) +{ + // Check address range. + if (i_addr < this->getBaseAddress() || + i_addr >= (this->getBaseAddress() + 0x010000000000ull)) + { + return false; + } + + // Check valid device. + uint64_t segment_ea = i_addr - this->getBaseAddress(); + size_t idx = segment_ea / ((1ull << SLBE_s) / MMIO_MAP_DEVICES); + uint64_t device_offset = segment_ea - + (idx * (1ull << SLBE_s) / MMIO_MAP_DEVICES); + + if (0 == iv_mmioMap[idx]) + { + return false; + } + + PageTableManager::addEntry((i_addr / PAGESIZE) * PAGESIZE, + (iv_mmioMap[idx] + device_offset) / PAGESIZE, + VmmManager::CI_ACCESS); + return true; +} + +void* DeviceSegment::_mmioMap(void* ra, size_t pages) +{ + for (size_t i = 0; i < MMIO_MAP_DEVICES; i++) + { + if (0 == iv_mmioMap[i]) + { + iv_mmioMap[i] = reinterpret_cast<uint64_t>(ra); + return reinterpret_cast<void*>(i * + ((1ull << SLBE_s) / MMIO_MAP_DEVICES) + + this->getBaseAddress()); + } + } + + return NULL; +} + +int DeviceSegment::_mmioUnmap(void* ea, size_t pages) +{ + uint64_t segment_ea = reinterpret_cast<uint64_t>(ea) - + this->getBaseAddress(); + size_t idx = segment_ea / ((1ull << SLBE_s) / MMIO_MAP_DEVICES); + if (0 != iv_mmioMap[idx]) + { + PageTableManager::delRangePN(iv_mmioMap[idx] / PAGESIZE, + iv_mmioMap[idx] / PAGESIZE + + pages); + iv_mmioMap[idx] = 0; + return 0; + } + + return -1; +} + |

