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

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

unix.superglobalmegacorp.com

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