aboutsummaryrefslogtreecommitdiff
path: root/src/os.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/os.cc')
-rw-r--r--src/os.cc29
1 files changed, 22 insertions, 7 deletions
diff --git a/src/os.cc b/src/os.cc
index 7c4e3d1..089b92d 100644
--- a/src/os.cc
+++ b/src/os.cc
@@ -63,6 +63,7 @@ OsLayer::OsLayer() {
dynamic_mapped_shmem_ = false;
mmapped_allocation_ = false;
shmid_ = 0;
+ channels_ = NULL;
time_initialized_ = 0;
@@ -140,10 +141,17 @@ int OsLayer::AddressMode() {
// Translates user virtual to physical address.
uint64 OsLayer::VirtualToPhysical(void *vaddr) {
- uint64 frame, shift;
- off64_t off = ((uintptr_t)vaddr) / sysconf(_SC_PAGESIZE) * 8;
+ uint64 frame, paddr, pfnmask, pagemask;
+ int pagesize = sysconf(_SC_PAGESIZE);
+ off64_t off = ((uintptr_t)vaddr) / pagesize * 8;
int fd = open(kPagemapPath, O_RDONLY);
- // /proc/self/pagemap is available in kernel >= 2.6.25
+
+ /*
+ * https://www.kernel.org/doc/Documentation/vm/pagemap.txt
+ * API change (July 2015)
+ * https://patchwork.kernel.org/patch/6787991/
+ */
+
if (fd < 0)
return 0;
@@ -157,11 +165,18 @@ uint64 OsLayer::VirtualToPhysical(void *vaddr) {
return 0;
}
close(fd);
- if (!(frame & (1LL << 63)) || (frame & (1LL << 62)))
+
+ /* Check if page is present and not swapped. */
+ if (!(frame & (1ULL << 63)) || (frame & (1ULL << 62)))
return 0;
- shift = (frame >> 55) & 0x3f;
- frame = (frame & 0x007fffffffffffffLL) << shift;
- return frame | ((uintptr_t)vaddr & ((1LL << shift) - 1));
+
+ /* pfn is bits 0-54. */
+ pfnmask = ((1ULL << 55) - 1);
+ /* Pagesize had better be a power of 2. */
+ pagemask = pagesize - 1;
+
+ paddr = ((frame & pfnmask) * pagesize) | ((uintptr_t)vaddr & pagemask);
+ return paddr;
}
// Returns the HD device that contains this file.