diff options
author | Alexander Graf <agraf@suse.de> | 2011-07-21 02:29:15 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2011-10-06 09:43:34 +0200 |
commit | eadaada1ceb74f152dc9fe196bdda1b79c86275c (patch) | |
tree | e58017de01b4d01138871a28b8d37e78bc1645e5 /target-ppc | |
parent | a489f7f7111fb2e8aaf6a152731a5f1fe7e0c4b3 (diff) |
PPC: KVM: Add generic function to read host clockfreq
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
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/kvm.c | 67 | ||||
-rw-r--r-- | target-ppc/kvm_ppc.h | 1 |
2 files changed, 68 insertions, 0 deletions
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 21f35af762..77b98c4d73 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 2f32249e6d..7c08c0f4eb 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); |