summaryrefslogtreecommitdiff
path: root/target-ppc/kvm_ppc.c
blob: 26ecc9d25f245b24e58f98db40f1a8e824a50746 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*
 * PowerPC KVM support
 *
 * Copyright IBM Corp. 2008
 *
 * Authors:
 *  Hollis Blanchard <hollisb@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 */

#include "qemu-common.h"
#include "qemu-timer.h"
#include "kvm_ppc.h"
#include "device_tree.h"

#define PROC_DEVTREE_PATH "/proc/device-tree"

static QEMUTimer *kvmppc_timer;
static unsigned int kvmppc_timer_rate;

#ifdef CONFIG_FDT
int kvmppc_read_host_property(const char *node_path, const char *prop,
                                     void *val, size_t len)
{
    char *path;
    FILE *f;
    int ret = 0;
    int pathlen;

    pathlen = snprintf(NULL, 0, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop)
              + 1;
    path = g_malloc(pathlen);

    snprintf(path, pathlen, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop);

    f = fopen(path, "rb");
    if (f == NULL) {
        ret = errno;
        goto free;
    }

    len = fread(val, len, 1, f);
    if (len != 1) {
        ret = ferror(f);
        goto close;
    }

close:
    fclose(f);
free:
    free(path);
    return ret;
}
#endif

static void kvmppc_timer_hack(void *opaque)
{
    qemu_notify_event();
    qemu_mod_timer(kvmppc_timer, qemu_get_clock_ns(vm_clock) + kvmppc_timer_rate);
}

void kvmppc_init(void)
{
    /* XXX The only reason KVM yields control back to qemu is device IO. Since
     * an idle guest does no IO, qemu's device model will never get a chance to
     * run. So, until Qemu gains IO threads, we create this timer to ensure
     * that the device model gets a chance to run. */
    kvmppc_timer_rate = get_ticks_per_sec() / 10;
    kvmppc_timer = qemu_new_timer_ns(vm_clock, &kvmppc_timer_hack, NULL);
    qemu_mod_timer(kvmppc_timer, qemu_get_clock_ns(vm_clock) + kvmppc_timer_rate);
}