Patchwork [16/58] PPC: KVM: Add generic function to read host clockfreq

login
register
mail settings
Submitter Alexander Graf
Date Sept. 14, 2011, 8:42 a.m.
Message ID <1315989802-18753-17-git-send-email-agraf@suse.de>
Download mbox | patch
Permalink /patch/114652/
State New
Headers show

Comments

Alexander Graf - Sept. 14, 2011, 8:42 a.m.
We need to find out the host's clock-frequency when running on KVM, so
let's export a respective function.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

v1 -> v2:

  - enable 64bit values
---
 target-ppc/kvm.c     |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/kvm_ppc.h |    1 +
 2 files changed, 68 insertions(+), 0 deletions(-)
David Gibson - Sept. 15, 2011, 3:16 a.m.
On Wed, Sep 14, 2011 at 10:42:40AM +0200, Alexander Graf wrote:
> We need to find out the host's clock-frequency when running on KVM, so
> let's export a respective function.

Oh, handy.  I had been meaning to get around to writing the necessary
readdir() shuffle to do this.

Patch

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 21f35af..77b98c4 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -14,6 +14,7 @@ 
  *
  */
 
+#include <dirent.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
@@ -38,6 +39,8 @@ 
     do { } while (0)
 #endif
 
+#define PROC_DEVTREE_CPU      "/proc/device-tree/cpus/"
+
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
 };
@@ -509,6 +512,70 @@  uint32_t kvmppc_get_tbfreq(void)
     return retval;
 }
 
+/* Try to find a device tree node for a CPU with clock-frequency property */
+static int kvmppc_find_cpu_dt(char *buf, int buf_len)
+{
+    struct dirent *dirp;
+    DIR *dp;
+
+    if ((dp = opendir(PROC_DEVTREE_CPU)) == NULL) {
+        printf("Can't open directory " PROC_DEVTREE_CPU "\n");
+        return -1;
+    }
+
+    buf[0] = '\0';
+    while ((dirp = readdir(dp)) != NULL) {
+        FILE *f;
+        snprintf(buf, buf_len, "%s%s/clock-frequency", PROC_DEVTREE_CPU,
+                 dirp->d_name);
+        f = fopen(buf, "r");
+        if (f) {
+            snprintf(buf, buf_len, "%s%s", PROC_DEVTREE_CPU, dirp->d_name);
+            fclose(f);
+            break;
+        }
+        buf[0] = '\0';
+    }
+    closedir(dp);
+    if (buf[0] == '\0') {
+        printf("Unknown host!\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+uint64_t kvmppc_get_clockfreq(void)
+{
+    char buf[512];
+    uint32_t tb[2];
+    FILE *f;
+    int len;
+
+    if (kvmppc_find_cpu_dt(buf, sizeof(buf))) {
+        return 0;
+    }
+
+    strncat(buf, "/clock-frequency", sizeof(buf) - strlen(buf));
+
+    f = fopen(buf, "rb");
+    if (!f) {
+        return -1;
+    }
+
+    len = fread(tb, sizeof(tb[0]), 2, f);
+    fclose(f);
+    switch (len) {
+    case 1:
+        /* freq is only a single cell */
+        return tb[0];
+    case 2:
+        return *(uint64_t*)tb;
+    }
+
+    return 0;
+}
+
 int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
 {
     uint32_t *hc = (uint32_t*)buf;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 2f32249..7c08c0f 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -23,6 +23,7 @@  int kvmppc_read_host_property(const char *node_path, const char *prop,
 #endif
 
 uint32_t kvmppc_get_tbfreq(void);
+uint64_t kvmppc_get_clockfreq(void);
 int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len);
 int kvmppc_set_interrupt(CPUState *env, int irq, int level);