chiark / gitweb /
This patch replaces the existing OsLayer::VirtualToPhysical stub with
authornick.j.sanders <nick.j.sanders@93e54ea4-8218-11de-8aaf-8d8425684b44>
Mon, 7 Jan 2013 22:02:45 +0000 (22:02 +0000)
committernick.j.sanders <nick.j.sanders@93e54ea4-8218-11de-8aaf-8d8425684b44>
Mon, 7 Jan 2013 22:02:45 +0000 (22:02 +0000)
an actual implementation that translates addresses via the Linux
/proc/self/pagemap interface. This causes failing memory locations to
be reported with both virtual and physical address, and facilitates
isolating a defective memory module.

Like many other functions currently implemented in the generic OsLayer
class, this functionality is specific to Linux and would need to be
moved to a respective subclass if proper multi-OS support ever gets
implemented.

Signed-off-by: Julius Werner <jwerner@chromium.org>
src/os.cc
src/os.h

index 8032cfcd183675fdcda884d4fd8d43963c89c028..944ff8851cf872fead5f58db70a6e079a78c9c25 100644 (file)
--- a/src/os.cc
+++ b/src/os.cc
@@ -129,8 +129,24 @@ int OsLayer::AddressMode() {
 
 // Translates user virtual to physical address.
 uint64 OsLayer::VirtualToPhysical(void *vaddr) {
-  // Needs platform specific implementation.
-  return 0;
+  uint64 frame, shift;
+  off64_t off = ((uintptr_t)vaddr) / getpagesize() * 8;
+  int fd = open(kPagemapPath, O_RDONLY);
+  if (fd < 0 || lseek64(fd, off, SEEK_SET) != off || read(fd, &frame, 8) != 8) {
+    int err = errno;
+    string errtxt = ErrorString(err);
+    logprintf(0, "Error: failed to access %s with errno %d (%s)\n",
+              kPagemapPath, err, errtxt.c_str());
+    if (fd >= 0)
+      close(fd);
+    return 0;
+  }
+  close(fd);
+  if (!(frame & (1LL << 63)) || (frame & (1LL << 62)))
+    return 0;
+  shift = (frame >> 55) & 0x3f;
+  frame = (frame & 0x007fffffffffffffLL) << shift;
+  return frame | ((uintptr_t)vaddr & ((1LL << shift) - 1));
 }
 
 // Returns the HD device that contains this file.
index b043b61b7de28d4fa461e40d96c6b61b6153d248..3f3d3e97aca86414377e26ff0a13356070b27707 100644 (file)
--- a/src/os.h
+++ b/src/os.h
@@ -27,6 +27,7 @@
 #include "adler32memcpy.h"  // NOLINT
 #include "sattypes.h"       // NOLINT
 
+const char kPagemapPath[] = "/proc/self/pagemap";
 const char kSysfsPath[] = "/sys/bus/pci/devices";
 
 struct PCIDevice {