Patchwork [14/23] PPC: KVM: Add generic function to read host clockfreq

login
register
mail settings
Submitter Alexander Graf
Date July 21, 2011, 1:27 a.m.
Message ID <1311211654-14326-15-git-send-email-agraf@suse.de>
Download mbox | patch
Permalink /patch/105906/
State New
Headers show

Comments

Alexander Graf - July 21, 2011, 1:27 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>
---
 target-ppc/kvm.c     |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/kvm_ppc.h |    1 +
 2 files changed, 66 insertions(+), 0 deletions(-)
Scott Wood - July 21, 2011, 5:51 p.m.
On Thu, 21 Jul 2011 03:27:25 +0200
Alexander Graf <agraf@suse.de> wrote:

> +/* 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, "%scpus/%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;
> +    }

"Unknown host!" is a little vague for an error message.

> +uint32_t kvmppc_get_clockfreq(void)
> +{
> +    char buf[512];
> +    uint32_t tb;
> +    FILE *f;
> +    int len;
> +
> +    if (kvmppc_find_cpu_dt(buf, sizeof(buf))) {
> +        return 0;
> +    }
> +
> +    snprintf(buf, sizeof(buf), "%s/clock-frequency", buf);
> +
> +    f = fopen(buf, "rb");
> +    if (!f) {
> +        return -1;
> +    }
> +
> +    len = fread(&tb, sizeof(tb), 1, f);
> +    if (len != 1) {
> +        goto err;
> +    }
> +
> +    return tb;
> +err:
> +    fclose(f);
> +    return 0;
> +}

Need to convert endian from big to host.  Also, the frequency can be 64-bit.

-Scott
Alexander Graf - July 21, 2011, 6:59 p.m.
Am 21.07.2011 um 19:51 schrieb Scott Wood <scottwood@freescale.com>:

> On Thu, 21 Jul 2011 03:27:25 +0200
> Alexander Graf <agraf@suse.de> wrote:
> 
>> +/* 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, "%scpus/%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;
>> +    }
> 
> "Unknown host!" is a little vague for an error message.
> 
>> +uint32_t kvmppc_get_clockfreq(void)
>> +{
>> +    char buf[512];
>> +    uint32_t tb;
>> +    FILE *f;
>> +    int len;
>> +
>> +    if (kvmppc_find_cpu_dt(buf, sizeof(buf))) {
>> +        return 0;
>> +    }
>> +
>> +    snprintf(buf, sizeof(buf), "%s/clock-frequency", buf);
>> +
>> +    f = fopen(buf, "rb");
>> +    if (!f) {
>> +        return -1;
>> +    }
>> +
>> +    len = fread(&tb, sizeof(tb), 1, f);
>> +    if (len != 1) {
>> +        goto err;
>> +    }
>> +
>> +    return tb;
>> +err:
>> +    fclose(f);
>> +    return 0;
>> +}
> 
> Need to convert endian from big to host.  

Hm. This is kvm specific code for ppc, so only ever runs on host==big :)

> Also, the frequency can be 64-bit.

Would the parameter just be 2 cells then? Got an example how this works?

Alex

> 
> -Scott
>
Scott Wood - July 21, 2011, 7:06 p.m.
On Thu, 21 Jul 2011 20:59:40 +0200
Alexander Graf <agraf@suse.de> wrote:

> >> +uint32_t kvmppc_get_clockfreq(void)
> >> +{
> >> +    char buf[512];
> >> +    uint32_t tb;
> >> +    FILE *f;
> >> +    int len;
> >> +
> >> +    if (kvmppc_find_cpu_dt(buf, sizeof(buf))) {
> >> +        return 0;
> >> +    }
> >> +
> >> +    snprintf(buf, sizeof(buf), "%s/clock-frequency", buf);
> >> +
> >> +    f = fopen(buf, "rb");
> >> +    if (!f) {
> >> +        return -1;
> >> +    }
> >> +
> >> +    len = fread(&tb, sizeof(tb), 1, f);
> >> +    if (len != 1) {
> >> +        goto err;
> >> +    }
> >> +
> >> +    return tb;
> >> +err:
> >> +    fclose(f);
> >> +    return 0;
> >> +}
> > 
> > Need to convert endian from big to host.  
> 
> Hm. This is kvm specific code for ppc, so only ever runs on host==big :)

Sigh.  I looked at what file it was specifically to check whether it was
in a ppc or generic file, and somehow I still didn't see the "ppc". :-P

> > Also, the frequency can be 64-bit.
> 
> Would the parameter just be 2 cells then? Got an example how this works?

Yes, it would be 2 cells.  Just check the property length.

-Scott

Patch

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 21f35af..13aa9ae 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,68 @@  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, "%scpus/%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;
+}
+
+uint32_t kvmppc_get_clockfreq(void)
+{
+    char buf[512];
+    uint32_t tb;
+    FILE *f;
+    int len;
+
+    if (kvmppc_find_cpu_dt(buf, sizeof(buf))) {
+        return 0;
+    }
+
+    snprintf(buf, sizeof(buf), "%s/clock-frequency", buf);
+
+    f = fopen(buf, "rb");
+    if (!f) {
+        return -1;
+    }
+
+    len = fread(&tb, sizeof(tb), 1, f);
+    if (len != 1) {
+        goto err;
+    }
+
+    return tb;
+err:
+    fclose(f);
+    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..1827a13 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);
+uint32_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);