|
|
1.1 ! root 1: /* ! 2: * PowerPC implementation of KVM hooks ! 3: * ! 4: * Copyright IBM Corp. 2007 ! 5: * ! 6: * Authors: ! 7: * Jerone Young <[email protected]> ! 8: * Christian Ehrhardt <[email protected]> ! 9: * Hollis Blanchard <[email protected]> ! 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: return 0; ! 48: } ! 49: ! 50: int kvm_arch_put_registers(CPUState *env) ! 51: { ! 52: struct kvm_regs regs; ! 53: int ret; ! 54: int i; ! 55: ! 56: ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); ! 57: if (ret < 0) ! 58: return ret; ! 59: ! 60: regs.ctr = env->ctr; ! 61: regs.lr = env->lr; ! 62: regs.xer = env->xer; ! 63: regs.msr = env->msr; ! 64: regs.pc = env->nip; ! 65: ! 66: regs.srr0 = env->spr[SPR_SRR0]; ! 67: regs.srr1 = env->spr[SPR_SRR1]; ! 68: ! 69: regs.sprg0 = env->spr[SPR_SPRG0]; ! 70: regs.sprg1 = env->spr[SPR_SPRG1]; ! 71: regs.sprg2 = env->spr[SPR_SPRG2]; ! 72: regs.sprg3 = env->spr[SPR_SPRG3]; ! 73: regs.sprg4 = env->spr[SPR_SPRG4]; ! 74: regs.sprg5 = env->spr[SPR_SPRG5]; ! 75: regs.sprg6 = env->spr[SPR_SPRG6]; ! 76: regs.sprg7 = env->spr[SPR_SPRG7]; ! 77: ! 78: for (i = 0;i < 32; i++) ! 79: regs.gpr[i] = env->gpr[i]; ! 80: ! 81: ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); ! 82: if (ret < 0) ! 83: return ret; ! 84: ! 85: return ret; ! 86: } ! 87: ! 88: int kvm_arch_get_registers(CPUState *env) ! 89: { ! 90: struct kvm_regs regs; ! 91: uint32_t i, ret; ! 92: ! 93: ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); ! 94: if (ret < 0) ! 95: return ret; ! 96: ! 97: env->ctr = regs.ctr; ! 98: env->lr = regs.lr; ! 99: env->xer = regs.xer; ! 100: env->msr = regs.msr; ! 101: env->nip = regs.pc; ! 102: ! 103: env->spr[SPR_SRR0] = regs.srr0; ! 104: env->spr[SPR_SRR1] = regs.srr1; ! 105: ! 106: env->spr[SPR_SPRG0] = regs.sprg0; ! 107: env->spr[SPR_SPRG1] = regs.sprg1; ! 108: env->spr[SPR_SPRG2] = regs.sprg2; ! 109: env->spr[SPR_SPRG3] = regs.sprg3; ! 110: env->spr[SPR_SPRG4] = regs.sprg4; ! 111: env->spr[SPR_SPRG5] = regs.sprg5; ! 112: env->spr[SPR_SPRG6] = regs.sprg6; ! 113: env->spr[SPR_SPRG7] = regs.sprg7; ! 114: ! 115: for (i = 0;i < 32; i++) ! 116: env->gpr[i] = regs.gpr[i]; ! 117: ! 118: return 0; ! 119: } ! 120: ! 121: int kvm_arch_pre_run(CPUState *env, struct kvm_run *run) ! 122: { ! 123: int r; ! 124: unsigned irq; ! 125: ! 126: /* PowerPC Qemu tracks the various core input pins (interrupt, critical ! 127: * interrupt, reset, etc) in PPC-specific env->irq_input_state. */ ! 128: if (run->ready_for_interrupt_injection && ! 129: (env->interrupt_request & CPU_INTERRUPT_HARD) && ! 130: (env->irq_input_state & (1<<PPC40x_INPUT_INT))) ! 131: { ! 132: /* For now KVM disregards the 'irq' argument. However, in the ! 133: * future KVM could cache it in-kernel to avoid a heavyweight exit ! 134: * when reading the UIC. ! 135: */ ! 136: irq = -1U; ! 137: ! 138: dprintf("injected interrupt %d\n", irq); ! 139: r = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &irq); ! 140: if (r < 0) ! 141: printf("cpu %d fail inject %x\n", env->cpu_index, irq); ! 142: } ! 143: ! 144: /* We don't know if there are more interrupts pending after this. However, ! 145: * the guest will return to userspace in the course of handling this one ! 146: * anyways, so we will get a chance to deliver the rest. */ ! 147: return 0; ! 148: } ! 149: ! 150: int kvm_arch_post_run(CPUState *env, struct kvm_run *run) ! 151: { ! 152: return 0; ! 153: } ! 154: ! 155: static int kvmppc_handle_halt(CPUState *env) ! 156: { ! 157: if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) { ! 158: env->halted = 1; ! 159: env->exception_index = EXCP_HLT; ! 160: } ! 161: ! 162: return 1; ! 163: } ! 164: ! 165: /* map dcr access to existing qemu dcr emulation */ ! 166: static int kvmppc_handle_dcr_read(CPUState *env, uint32_t dcrn, uint32_t *data) ! 167: { ! 168: if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0) ! 169: fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn); ! 170: ! 171: return 1; ! 172: } ! 173: ! 174: static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data) ! 175: { ! 176: if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0) ! 177: fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn); ! 178: ! 179: return 1; ! 180: } ! 181: ! 182: int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run) ! 183: { ! 184: int ret = 0; ! 185: ! 186: switch (run->exit_reason) { ! 187: case KVM_EXIT_DCR: ! 188: if (run->dcr.is_write) { ! 189: dprintf("handle dcr write\n"); ! 190: ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data); ! 191: } else { ! 192: dprintf("handle dcr read\n"); ! 193: ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data); ! 194: } ! 195: break; ! 196: case KVM_EXIT_HLT: ! 197: dprintf("handle halt\n"); ! 198: ret = kvmppc_handle_halt(env); ! 199: break; ! 200: } ! 201: ! 202: return ret; ! 203: } ! 204:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.