File:  [Qemu by Fabrice Bellard] / qemu / target-ppc / kvm_ppc.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:40:47 2018 UTC (3 years, 8 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, qemu0130, qemu0125, qemu0124, qemu0123, qemu0122, qemu0121, qemu0120, HEAD
qemu 0.12.0

    1: /*
    2:  * PowerPC KVM support
    3:  *
    4:  * Copyright IBM Corp. 2008
    5:  *
    6:  * Authors:
    7:  *  Hollis Blanchard <hollisb@us.ibm.com>
    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 CONFIG_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:     return ret;
   56: }
   57: 
   58: static int kvmppc_copy_host_cell(void *fdt, const char *node, const char *prop)
   59: {
   60:     uint32_t cell;
   61:     int ret;
   62: 
   63:     ret = kvmppc_read_host_property(node, prop, &cell, sizeof(cell));
   64:     if (ret < 0) {
   65:         fprintf(stderr, "couldn't read host %s/%s\n", node, prop);
   66:         goto out;
   67:     }
   68: 
   69:     ret = qemu_devtree_setprop_cell(fdt, node, prop, cell);
   70:     if (ret < 0) {
   71:         fprintf(stderr, "couldn't set guest %s/%s\n", node, prop);
   72:         goto out;
   73:     }
   74: 
   75: out:
   76:     return ret;
   77: }
   78: 
   79: void kvmppc_fdt_update(void *fdt)
   80: {
   81:     /* Copy data from the host device tree into the guest. Since the guest can
   82:      * directly access the timebase without host involvement, we must expose
   83:      * the correct frequencies. */
   84:     kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "clock-frequency");
   85:     kvmppc_copy_host_cell(fdt, "/cpus/cpu@0", "timebase-frequency");
   86: }
   87: #endif
   88: 
   89: static void kvmppc_timer_hack(void *opaque)
   90: {
   91:     qemu_service_io();
   92:     qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate);
   93: }
   94: 
   95: void kvmppc_init(void)
   96: {
   97:     /* XXX The only reason KVM yields control back to qemu is device IO. Since
   98:      * an idle guest does no IO, qemu's device model will never get a chance to
   99:      * run. So, until Qemu gains IO threads, we create this timer to ensure
  100:      * that the device model gets a chance to run. */
  101:     kvmppc_timer_rate = get_ticks_per_sec() / 10;
  102:     kvmppc_timer = qemu_new_timer(vm_clock, &kvmppc_timer_hack, NULL);
  103:     qemu_mod_timer(kvmppc_timer, qemu_get_clock(vm_clock) + kvmppc_timer_rate);
  104: }
  105: 

unix.superglobalmegacorp.com