Annotation of qemu/target-ppc/kvm.c, revision 1.1.1.4

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: 
1.1.1.4 ! root       40: const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
        !            41:     KVM_CAP_LAST_INFO
        !            42: };
        !            43: 
        !            44: static int cap_interrupt_unset = false;
        !            45: static int cap_interrupt_level = false;
        !            46: 
1.1.1.3   root       47: /* XXX We have a race condition where we actually have a level triggered
                     48:  *     interrupt, but the infrastructure can't expose that yet, so the guest
                     49:  *     takes but ignores it, goes to sleep and never gets notified that there's
                     50:  *     still an interrupt pending.
                     51:  *
                     52:  *     As a quick workaround, let's just wake up again 20 ms after we injected
                     53:  *     an interrupt. That way we can assure that we're always reinjecting
                     54:  *     interrupts in case the guest swallowed them.
                     55:  */
                     56: static QEMUTimer *idle_timer;
                     57: 
                     58: static void kvm_kick_env(void *env)
                     59: {
                     60:     qemu_cpu_kick(env);
                     61: }
                     62: 
1.1.1.4 ! root       63: int kvm_arch_init(KVMState *s)
1.1       root       64: {
1.1.1.4 ! root       65: #ifdef KVM_CAP_PPC_UNSET_IRQ
        !            66:     cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ);
        !            67: #endif
        !            68: #ifdef KVM_CAP_PPC_IRQ_LEVEL
        !            69:     cap_interrupt_level = kvm_check_extension(s, KVM_CAP_PPC_IRQ_LEVEL);
        !            70: #endif
        !            71: 
        !            72:     if (!cap_interrupt_level) {
        !            73:         fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
        !            74:                         "VM to stall at times!\n");
        !            75:     }
        !            76: 
1.1       root       77:     return 0;
                     78: }
                     79: 
                     80: int kvm_arch_init_vcpu(CPUState *cenv)
                     81: {
1.1.1.2   root       82:     int ret = 0;
                     83:     struct kvm_sregs sregs;
                     84: 
                     85:     sregs.pvr = cenv->spr[SPR_PVR];
                     86:     ret = kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
                     87: 
1.1.1.3   root       88:     idle_timer = qemu_new_timer(vm_clock, kvm_kick_env, cenv);
                     89: 
1.1.1.2   root       90:     return ret;
                     91: }
                     92: 
                     93: void kvm_arch_reset_vcpu(CPUState *env)
                     94: {
1.1       root       95: }
                     96: 
1.1.1.3   root       97: int kvm_arch_put_registers(CPUState *env, int level)
1.1       root       98: {
                     99:     struct kvm_regs regs;
                    100:     int ret;
                    101:     int i;
                    102: 
                    103:     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
                    104:     if (ret < 0)
                    105:         return ret;
                    106: 
                    107:     regs.ctr = env->ctr;
                    108:     regs.lr  = env->lr;
                    109:     regs.xer = env->xer;
                    110:     regs.msr = env->msr;
                    111:     regs.pc = env->nip;
                    112: 
                    113:     regs.srr0 = env->spr[SPR_SRR0];
                    114:     regs.srr1 = env->spr[SPR_SRR1];
                    115: 
                    116:     regs.sprg0 = env->spr[SPR_SPRG0];
                    117:     regs.sprg1 = env->spr[SPR_SPRG1];
                    118:     regs.sprg2 = env->spr[SPR_SPRG2];
                    119:     regs.sprg3 = env->spr[SPR_SPRG3];
                    120:     regs.sprg4 = env->spr[SPR_SPRG4];
                    121:     regs.sprg5 = env->spr[SPR_SPRG5];
                    122:     regs.sprg6 = env->spr[SPR_SPRG6];
                    123:     regs.sprg7 = env->spr[SPR_SPRG7];
                    124: 
                    125:     for (i = 0;i < 32; i++)
                    126:         regs.gpr[i] = env->gpr[i];
                    127: 
                    128:     ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs);
                    129:     if (ret < 0)
                    130:         return ret;
                    131: 
                    132:     return ret;
                    133: }
                    134: 
                    135: int kvm_arch_get_registers(CPUState *env)
                    136: {
                    137:     struct kvm_regs regs;
1.1.1.2   root      138:     struct kvm_sregs sregs;
1.1.1.4 ! root      139:     int i, ret;
1.1       root      140: 
                    141:     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
                    142:     if (ret < 0)
                    143:         return ret;
                    144: 
1.1.1.2   root      145:     ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
                    146:     if (ret < 0)
                    147:         return ret;
                    148: 
1.1       root      149:     env->ctr = regs.ctr;
                    150:     env->lr = regs.lr;
                    151:     env->xer = regs.xer;
                    152:     env->msr = regs.msr;
                    153:     env->nip = regs.pc;
                    154: 
                    155:     env->spr[SPR_SRR0] = regs.srr0;
                    156:     env->spr[SPR_SRR1] = regs.srr1;
                    157: 
                    158:     env->spr[SPR_SPRG0] = regs.sprg0;
                    159:     env->spr[SPR_SPRG1] = regs.sprg1;
                    160:     env->spr[SPR_SPRG2] = regs.sprg2;
                    161:     env->spr[SPR_SPRG3] = regs.sprg3;
                    162:     env->spr[SPR_SPRG4] = regs.sprg4;
                    163:     env->spr[SPR_SPRG5] = regs.sprg5;
                    164:     env->spr[SPR_SPRG6] = regs.sprg6;
                    165:     env->spr[SPR_SPRG7] = regs.sprg7;
                    166: 
                    167:     for (i = 0;i < 32; i++)
                    168:         env->gpr[i] = regs.gpr[i];
                    169: 
1.1.1.2   root      170: #ifdef KVM_CAP_PPC_SEGSTATE
                    171:     if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_SEGSTATE)) {
                    172:         env->sdr1 = sregs.u.s.sdr1;
                    173: 
                    174:         /* Sync SLB */
                    175: #ifdef TARGET_PPC64
                    176:         for (i = 0; i < 64; i++) {
                    177:             ppc_store_slb(env, sregs.u.s.ppc64.slb[i].slbe,
                    178:                                sregs.u.s.ppc64.slb[i].slbv);
                    179:         }
                    180: #endif
                    181: 
                    182:         /* Sync SRs */
                    183:         for (i = 0; i < 16; i++) {
                    184:             env->sr[i] = sregs.u.s.ppc32.sr[i];
                    185:         }
                    186: 
                    187:         /* Sync BATs */
                    188:         for (i = 0; i < 8; i++) {
                    189:             env->DBAT[0][i] = sregs.u.s.ppc32.dbat[i] & 0xffffffff;
                    190:             env->DBAT[1][i] = sregs.u.s.ppc32.dbat[i] >> 32;
                    191:             env->IBAT[0][i] = sregs.u.s.ppc32.ibat[i] & 0xffffffff;
                    192:             env->IBAT[1][i] = sregs.u.s.ppc32.ibat[i] >> 32;
                    193:         }
                    194:     }
                    195: #endif
                    196: 
1.1       root      197:     return 0;
                    198: }
                    199: 
1.1.1.4 ! root      200: int kvmppc_set_interrupt(CPUState *env, int irq, int level)
        !           201: {
        !           202:     unsigned virq = level ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET;
        !           203: 
        !           204:     if (irq != PPC_INTERRUPT_EXT) {
        !           205:         return 0;
        !           206:     }
        !           207: 
        !           208:     if (!kvm_enabled() || !cap_interrupt_unset || !cap_interrupt_level) {
        !           209:         return 0;
        !           210:     }
        !           211: 
        !           212:     kvm_vcpu_ioctl(env, KVM_INTERRUPT, &virq);
        !           213: 
        !           214:     return 0;
        !           215: }
        !           216: 
1.1.1.2   root      217: #if defined(TARGET_PPCEMB)
                    218: #define PPC_INPUT_INT PPC40x_INPUT_INT
                    219: #elif defined(TARGET_PPC64)
                    220: #define PPC_INPUT_INT PPC970_INPUT_INT
                    221: #else
                    222: #define PPC_INPUT_INT PPC6xx_INPUT_INT
                    223: #endif
                    224: 
1.1       root      225: int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
                    226: {
                    227:     int r;
                    228:     unsigned irq;
                    229: 
                    230:     /* PowerPC Qemu tracks the various core input pins (interrupt, critical
                    231:      * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
1.1.1.4 ! root      232:     if (!cap_interrupt_level &&
        !           233:         run->ready_for_interrupt_injection &&
1.1       root      234:         (env->interrupt_request & CPU_INTERRUPT_HARD) &&
1.1.1.2   root      235:         (env->irq_input_state & (1<<PPC_INPUT_INT)))
1.1       root      236:     {
                    237:         /* For now KVM disregards the 'irq' argument. However, in the
                    238:          * future KVM could cache it in-kernel to avoid a heavyweight exit
                    239:          * when reading the UIC.
                    240:          */
1.1.1.4 ! root      241:         irq = KVM_INTERRUPT_SET;
1.1       root      242: 
                    243:         dprintf("injected interrupt %d\n", irq);
                    244:         r = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &irq);
                    245:         if (r < 0)
                    246:             printf("cpu %d fail inject %x\n", env->cpu_index, irq);
1.1.1.3   root      247: 
                    248:         /* Always wake up soon in case the interrupt was level based */
                    249:         qemu_mod_timer(idle_timer, qemu_get_clock(vm_clock) +
                    250:                        (get_ticks_per_sec() / 50));
1.1       root      251:     }
                    252: 
                    253:     /* We don't know if there are more interrupts pending after this. However,
                    254:      * the guest will return to userspace in the course of handling this one
                    255:      * anyways, so we will get a chance to deliver the rest. */
                    256:     return 0;
                    257: }
                    258: 
                    259: int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
                    260: {
                    261:     return 0;
                    262: }
                    263: 
1.1.1.3   root      264: int kvm_arch_process_irqchip_events(CPUState *env)
                    265: {
                    266:     return 0;
                    267: }
                    268: 
1.1       root      269: static int kvmppc_handle_halt(CPUState *env)
                    270: {
                    271:     if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
                    272:         env->halted = 1;
                    273:         env->exception_index = EXCP_HLT;
                    274:     }
                    275: 
                    276:     return 1;
                    277: }
                    278: 
                    279: /* map dcr access to existing qemu dcr emulation */
                    280: static int kvmppc_handle_dcr_read(CPUState *env, uint32_t dcrn, uint32_t *data)
                    281: {
                    282:     if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0)
                    283:         fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn);
                    284: 
                    285:     return 1;
                    286: }
                    287: 
                    288: static int kvmppc_handle_dcr_write(CPUState *env, uint32_t dcrn, uint32_t data)
                    289: {
                    290:     if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0)
                    291:         fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn);
                    292: 
                    293:     return 1;
                    294: }
                    295: 
                    296: int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
                    297: {
                    298:     int ret = 0;
                    299: 
                    300:     switch (run->exit_reason) {
                    301:     case KVM_EXIT_DCR:
                    302:         if (run->dcr.is_write) {
                    303:             dprintf("handle dcr write\n");
                    304:             ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data);
                    305:         } else {
                    306:             dprintf("handle dcr read\n");
                    307:             ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data);
                    308:         }
                    309:         break;
                    310:     case KVM_EXIT_HLT:
                    311:         dprintf("handle halt\n");
                    312:         ret = kvmppc_handle_halt(env);
                    313:         break;
1.1.1.4 ! root      314:     default:
        !           315:         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
        !           316:         ret = -1;
        !           317:         break;
1.1       root      318:     }
                    319: 
                    320:     return ret;
                    321: }
                    322: 
1.1.1.3   root      323: static int read_cpuinfo(const char *field, char *value, int len)
                    324: {
                    325:     FILE *f;
                    326:     int ret = -1;
                    327:     int field_len = strlen(field);
                    328:     char line[512];
                    329: 
                    330:     f = fopen("/proc/cpuinfo", "r");
                    331:     if (!f) {
                    332:         return -1;
                    333:     }
                    334: 
                    335:     do {
                    336:         if(!fgets(line, sizeof(line), f)) {
                    337:             break;
                    338:         }
                    339:         if (!strncmp(line, field, field_len)) {
                    340:             strncpy(value, line, len);
                    341:             ret = 0;
                    342:             break;
                    343:         }
                    344:     } while(*line);
                    345: 
                    346:     fclose(f);
                    347: 
                    348:     return ret;
                    349: }
                    350: 
                    351: uint32_t kvmppc_get_tbfreq(void)
                    352: {
                    353:     char line[512];
                    354:     char *ns;
                    355:     uint32_t retval = get_ticks_per_sec();
                    356: 
                    357:     if (read_cpuinfo("timebase", line, sizeof(line))) {
                    358:         return retval;
                    359:     }
                    360: 
                    361:     if (!(ns = strchr(line, ':'))) {
                    362:         return retval;
                    363:     }
                    364: 
                    365:     ns++;
                    366: 
                    367:     retval = atoi(ns);
                    368:     return retval;
                    369: }
                    370: 
1.1.1.4 ! root      371: int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
        !           372: {
        !           373:     uint32_t *hc = (uint32_t*)buf;
        !           374: 
        !           375: #ifdef KVM_CAP_PPC_GET_PVINFO
        !           376:     struct kvm_ppc_pvinfo pvinfo;
        !           377: 
        !           378:     if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
        !           379:         !kvm_vm_ioctl(env->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) {
        !           380:         memcpy(buf, pvinfo.hcall, buf_len);
        !           381: 
        !           382:         return 0;
        !           383:     }
        !           384: #endif
        !           385: 
        !           386:     /*
        !           387:      * Fallback to always fail hypercalls:
        !           388:      *
        !           389:      *     li r3, -1
        !           390:      *     nop
        !           391:      *     nop
        !           392:      *     nop
        !           393:      */
        !           394: 
        !           395:     hc[0] = 0x3860ffff;
        !           396:     hc[1] = 0x60000000;
        !           397:     hc[2] = 0x60000000;
        !           398:     hc[3] = 0x60000000;
        !           399: 
        !           400:     return 0;
        !           401: }
        !           402: 
1.1.1.3   root      403: bool kvm_arch_stop_on_emulation_error(CPUState *env)
                    404: {
                    405:     return true;
                    406: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.