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

    1: /*
    2:  * PowerPC implementation of KVM hooks
    3:  *
    4:  * Copyright IBM Corp. 2007
    5:  *
    6:  * Authors:
    7:  *  Jerone Young <jyoung5@us.ibm.com>
    8:  *  Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
    9:  *  Hollis Blanchard <hollisb@us.ibm.com>
   10:  *
   11:  * This work is licensed under the terms of the GNU GPL, version 2 or later.
   12:  * See the COPYING file in the top-level directory.
   13:  *
   14:  */
   15: 
   16: #include <sys/types.h>
   17: #include <sys/ioctl.h>
   18: #include <sys/mman.h>
   19: 
   20: #include <linux/kvm.h>
   21: 
   22: #include "qemu-common.h"
   23: #include "qemu-timer.h"
   24: #include "sysemu.h"
   25: #include "kvm.h"
   26: #include "kvm_ppc.h"
   27: #include "cpu.h"
   28: #include "device_tree.h"
   29: 
   30: //#define DEBUG_KVM
   31: 
   32: #ifdef DEBUG_KVM
   33: #define dprintf(fmt, ...) \
   34:     do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
   35: #else
   36: #define dprintf(fmt, ...) \
   37:     do { } while (0)
   38: #endif
   39: 
   40: int kvm_arch_init(KVMState *s, int smp_cpus)
   41: {
   42:     return 0;
   43: }
   44: 
   45: int kvm_arch_init_vcpu(CPUState *cenv)
   46: {
   47:     int ret = 0;
   48:     struct kvm_sregs sregs;
   49: 
   50:     sregs.pvr = cenv->spr[SPR_PVR];
   51:     ret = kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
   52: 
   53:     return ret;
   54: }
   55: 
   56: void kvm_arch_reset_vcpu(CPUState *env)
   57: {
   58: }
   59: 
   60: int kvm_arch_put_registers(CPUState *env)
   61: {
   62:     struct kvm_regs regs;
   63:     int ret;
   64:     int i;
   65: 
   66:     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
   67:     if (ret < 0)
   68:         return ret;
   69: 
   70:     regs.ctr = env->ctr;
   71:     regs.lr  = env->lr;
   72:     regs.xer = env->xer;
   73:     regs.msr = env->msr;
   74:     regs.pc = env->nip;
   75: 
   76:     regs.srr0 = env->spr[SPR_SRR0];
   77:     regs.srr1 = env->spr[SPR_SRR1];
   78: 
   79:     regs.sprg0 = env->spr[SPR_SPRG0];
   80:     regs.sprg1 = env->spr[SPR_SPRG1];
   81:     regs.sprg2 = env->spr[SPR_SPRG2];
   82:     regs.sprg3 = env->spr[SPR_SPRG3];
   83:     regs.sprg4 = env->spr[SPR_SPRG4];
   84:     regs.sprg5 = env->spr[SPR_SPRG5];
   85:     regs.sprg6 = env->spr[SPR_SPRG6];
   86:     regs.sprg7 = env->spr[SPR_SPRG7];
   87: 
   88:     for (i = 0;i < 32; i++)
   89:         regs.gpr[i] = env->gpr[i];
   90: 
   91:     ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs);
   92:     if (ret < 0)
   93:         return ret;
   94: 
   95:     return ret;
   96: }
   97: 
   98: int kvm_arch_get_registers(CPUState *env)
   99: {
  100:     struct kvm_regs regs;
  101:     struct kvm_sregs sregs;
  102:     uint32_t i, ret;
  103: 
  104:     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
  105:     if (ret < 0)
  106:         return ret;
  107: 
  108:     ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
  109:     if (ret < 0)
  110:         return ret;
  111: 
  112:     env->ctr = regs.ctr;
  113:     env->lr = regs.lr;
  114:     env->xer = regs.xer;
  115:     env->msr = regs.msr;
  116:     env->nip = regs.pc;
  117: 
  118:     env->spr[SPR_SRR0] = regs.srr0;
  119:     env->spr[SPR_SRR1] = regs.srr1;
  120: 
  121:     env->spr[SPR_SPRG0] = regs.sprg0;
  122:     env->spr[SPR_SPRG1] = regs.sprg1;
  123:     env->spr[SPR_SPRG2] = regs.sprg2;
  124:     env->spr[SPR_SPRG3] = regs.sprg3;
  125:     env->spr[SPR_SPRG4] = regs.sprg4;
  126:     env->spr[SPR_SPRG5] = regs.sprg5;
  127:     env->spr[SPR_SPRG6] = regs.sprg6;
  128:     env->spr[SPR_SPRG7] = regs.sprg7;
  129: 
  130:     for (i = 0;i < 32; i++)
  131:         env->gpr[i] = regs.gpr[i];
  132: 
  133: #ifdef KVM_CAP_PPC_SEGSTATE
  134:     if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
  135:         env->sdr1 = sregs.u.s.sdr1;
  136: 
  137:         /* Sync SLB */
  138: #ifdef TARGET_PPC64
  139:         for (i = 0; i < 64; i++) {
  140:             ppc_store_slb(env, sregs.u.s.ppc64.slb[i].slbe,
  141:                                sregs.u.s.ppc64.slb[i].slbv);
  142:         }
  143: #endif
  144: 
  145:         /* Sync SRs */
  146:         for (i = 0; i < 16; i++) {
  147:             env->sr[i] = sregs.u.s.ppc32.sr[i];
  148:         }
  149: 
  150:         /* Sync BATs */
  151:         for (i = 0; i < 8; i++) {
  152:             env->DBAT[0][i] = sregs.u.s.ppc32.dbat[i] & 0xffffffff;
  153:             env->DBAT[1][i] = sregs.u.s.ppc32.dbat[i] >> 32;
  154:             env->IBAT[0][i] = sregs.u.s.ppc32.ibat[i] & 0xffffffff;
  155:             env->IBAT[1][i] = sregs.u.s.ppc32.ibat[i] >> 32;
  156:         }
  157:     }
  158: #endif
  159: 
  160:     return 0;
  161: }
  162: 
  163: #if defined(TARGET_PPCEMB)
  164: #define PPC_INPUT_INT PPC40x_INPUT_INT
  165: #elif defined(TARGET_PPC64)
  166: #define PPC_INPUT_INT PPC970_INPUT_INT
  167: #else
  168: #define PPC_INPUT_INT PPC6xx_INPUT_INT
  169: #endif
  170: 
  171: int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
  172: {
  173:     int r;
  174:     unsigned irq;
  175: 
  176:     /* PowerPC Qemu tracks the various core input pins (interrupt, critical
  177:      * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
  178:     if (run->ready_for_interrupt_injection &&
  179:         (env->interrupt_request & CPU_INTERRUPT_HARD) &&
  180:         (env->irq_input_state & (1<<PPC_INPUT_INT)))
  181:     {
  182:         /* For now KVM disregards the 'irq' argument. However, in the
  183:          * future KVM could cache it in-kernel to avoid a heavyweight exit
  184:          * when reading the UIC.
  185:          */
  186:         irq = -1U;
  187: 
  188:         dprintf("injected interrupt %d\n", irq);
  189:         r = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &irq);
  190:         if (r < 0)
  191:             printf("cpu %d fail inject %x\n", env->cpu_index, irq);
  192:     }
  193: 
  194:     /* We don't know if there are more interrupts pending after this. However,
  195:      * the guest will return to userspace in the course of handling this one
  196:      * anyways, so we will get a chance to deliver the rest. */
  197:     return 0;
  198: }
  199: 
  200: int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
  201: {
  202:     return 0;
  203: }
  204: 
  205: static int kvmppc_handle_halt(CPUState *env)
  206: {
  207:     if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
  208:         env->halted = 1;
  209:         env->exception_index = EXCP_HLT;
  210:     }
  211: 
  212:     return 1;
  213: }
  214: 
  215: /* map dcr access to existing qemu dcr emulation */
  216: static int kvmppc_handle_dcr_read(CPUState *env, uint32_t dcrn, uint32_t *data)
  217: {
  218:     if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0)
  219:         fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn);
  220: 
  221:     return 1;
  222: }
  223: 
  224: static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data)
  225: {
  226:     if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0)
  227:         fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn);
  228: 
  229:     return 1;
  230: }
  231: 
  232: int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
  233: {
  234:     int ret = 0;
  235: 
  236:     switch (run->exit_reason) {
  237:     case KVM_EXIT_DCR:
  238:         if (run->dcr.is_write) {
  239:             dprintf("handle dcr write\n");
  240:             ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data);
  241:         } else {
  242:             dprintf("handle dcr read\n");
  243:             ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data);
  244:         }
  245:         break;
  246:     case KVM_EXIT_HLT:
  247:         dprintf("handle halt\n");
  248:         ret = kvmppc_handle_halt(env);
  249:         break;
  250:     }
  251: 
  252:     return ret;
  253: }
  254: 

unix.superglobalmegacorp.com