|
|
1.1 ! root 1: /* ! 2: * PowerPC KVM support ! 3: * ! 4: * Copyright IBM Corp. 2008 ! 5: * ! 6: * Authors: ! 7: * Hollis Blanchard <[email protected]> ! 8: * ! 9: * This work is licensed under the terms of the GNU GPL, version 2 or later. ! 10: * See the COPYING file in the top-level directory. ! 11: * ! 12: */ ! 13: ! 14: #include "qemu-common.h" ! 15: #include "qemu-timer.h" ! 16: #include "kvm_ppc.h" ! 17: #include "device_tree.h" ! 18: ! 19: #define PROC_DEVTREE_PATH "/proc/device-tree" ! 20: ! 21: static QEMUTimer *kvmppc_timer; ! 22: static unsigned int kvmppc_timer_rate; ! 23: ! 24: #ifdef HAVE_FDT ! 25: int kvmppc_read_host_property(const char *node_path, const char *prop, ! 26: void *val, size_t len) ! 27: { ! 28: char *path; ! 29: FILE *f; ! 30: int ret = 0; ! 31: int pathlen; ! 32: ! 33: pathlen = snprintf(NULL, 0, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop) ! 34: + 1; ! 35: path = qemu_malloc(pathlen); ! 36: ! 37: snprintf(path, pathlen, "%s/%s/%s", PROC_DEVTREE_PATH, node_path, prop); ! 38: ! 39: f = fopen(path, "rb"); ! 40: if (f == NULL) { ! 41: ret = errno; ! 42: goto free; ! 43: } ! 44: ! 45: len = fread(val, len, 1, f); ! 46: if (len != 1) { ! 47: ret = ferror(f); ! 48: goto close; ! 49: } ! 50: ! 51: close: ! 52: fclose(f); ! 53: free: ! 54: free(path); ! 55: out: ! 56: return ret; ! 57: } ! 58: ! 59: static int kvmppc_copy_host_cell(void *fdt, const char *node, const char *prop) ! 60: { ! 61: uint32_t cell; ! 62: int ret; ! 63: ! 64: ret = kvmppc_read_host_property(node, prop, &cell, sizeof(cell)); ! 65: if (ret < 0) { ! 66: fprintf(stderr, "couldn't read host %s/%s\n", node, prop); ! 67: goto out; ! 68: } ! 69: ! 70: ret = qemu_devtree_setprop_cell(fdt, node, prop, cell); ! 71: if (ret < 0) { ! 72: fprintf(stderr, "couldn't set guest %s/%s\n", node, prop); ! 73: goto out; ! 74: } ! 75: ! 76: out: ! 77: return ret; ! 78: } ! 79: ! 80: void kvmppc_fdt_update(void *fdt) ! 81: { ! 82: /* Copy data from the host device tree into the guest. Since the guest can ! 83: * directly access the timebase without host involvement, we must expose ! 84: * the correct frequencies. */ ! 85: kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "clock-frequency"); ! 86: kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "timebase-frequency"); ! 87: } ! 88: #endif ! 89: ! 90: static void kvmppc_timer_hack(void *opaque) ! 91: { ! 92: qemu_service_io(); ! 93: qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate); ! 94: } ! 95: ! 96: void kvmppc_init(void) ! 97: { ! 98: /* XXX The only reason KVM yields control back to qemu is device IO. Since ! 99: * an idle guest does no IO, qemu's device model will never get a chance to ! 100: * run. So, until Qemu gains IO threads, we create this timer to ensure ! 101: * that the device model gets a chance to run. */ ! 102: kvmppc_timer_rate = ticks_per_sec / 10; ! 103: kvmppc_timer = qemu_new_timer(vm_clock, &kvmppc_timer_hack, NULL); ! 104: qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate); ! 105: } ! 106:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.