Annotation of qemu/target-s390x/kvm.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU S390x KVM implementation
                      3:  *
                      4:  * Copyright (c) 2009 Alexander Graf <[email protected]>
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
                     18:  */
                     19: 
                     20: #include <sys/types.h>
                     21: #include <sys/ioctl.h>
                     22: #include <sys/mman.h>
                     23: 
                     24: #include <linux/kvm.h>
                     25: #include <asm/ptrace.h>
                     26: 
                     27: #include "qemu-common.h"
                     28: #include "qemu-timer.h"
                     29: #include "sysemu.h"
                     30: #include "kvm.h"
                     31: #include "cpu.h"
                     32: #include "device_tree.h"
                     33: 
                     34: /* #define DEBUG_KVM */
                     35: 
                     36: #ifdef DEBUG_KVM
                     37: #define dprintf(fmt, ...) \
                     38:     do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
                     39: #else
                     40: #define dprintf(fmt, ...) \
                     41:     do { } while (0)
                     42: #endif
                     43: 
                     44: #define IPA0_DIAG                       0x8300
                     45: #define IPA0_SIGP                       0xae00
                     46: #define IPA0_PRIV                       0xb200
                     47: 
                     48: #define PRIV_SCLP_CALL                  0x20
                     49: #define DIAG_KVM_HYPERCALL              0x500
                     50: #define DIAG_KVM_BREAKPOINT             0x501
                     51: 
                     52: #define SCP_LENGTH                      0x00
                     53: #define SCP_FUNCTION_CODE               0x02
                     54: #define SCP_CONTROL_MASK                0x03
                     55: #define SCP_RESPONSE_CODE               0x06
                     56: #define SCP_MEM_CODE                    0x08
                     57: #define SCP_INCREMENT                   0x0a
                     58: 
                     59: #define ICPT_INSTRUCTION                0x04
                     60: #define ICPT_WAITPSW                    0x1c
                     61: #define ICPT_SOFT_INTERCEPT             0x24
                     62: #define ICPT_CPU_STOP                   0x28
                     63: #define ICPT_IO                         0x40
                     64: 
                     65: #define SIGP_RESTART                    0x06
                     66: #define SIGP_INITIAL_CPU_RESET          0x0b
                     67: #define SIGP_STORE_STATUS_ADDR          0x0e
                     68: #define SIGP_SET_ARCH                   0x12
                     69: 
                     70: #define SCLP_CMDW_READ_SCP_INFO         0x00020001
                     71: #define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
                     72: 
                     73: int kvm_arch_init(KVMState *s, int smp_cpus)
                     74: {
                     75:     return 0;
                     76: }
                     77: 
                     78: int kvm_arch_init_vcpu(CPUState *env)
                     79: {
                     80:     int ret = 0;
                     81: 
                     82:     if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) {
                     83:         perror("cannot init reset vcpu");
                     84:     }
                     85: 
                     86:     return ret;
                     87: }
                     88: 
                     89: void kvm_arch_reset_vcpu(CPUState *env)
                     90: {
                     91:     /* FIXME: add code to reset vcpu. */
                     92: }
                     93: 
                     94: int kvm_arch_put_registers(CPUState *env)
                     95: {
                     96:     struct kvm_regs regs;
                     97:     int ret;
                     98:     int i;
                     99: 
                    100:     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
                    101:     if (ret < 0) {
                    102:         return ret;
                    103:     }
                    104: 
                    105:     for (i = 0; i < 16; i++) {
                    106:         regs.gprs[i] = env->regs[i];
                    107:     }
                    108: 
                    109:     ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs);
                    110:     if (ret < 0) {
                    111:         return ret;
                    112:     }
                    113: 
                    114:     env->kvm_run->psw_addr = env->psw.addr;
                    115:     env->kvm_run->psw_mask = env->psw.mask;
                    116: 
                    117:     return ret;
                    118: }
                    119: 
                    120: int kvm_arch_get_registers(CPUState *env)
                    121: {
                    122:     uint32_t ret;
                    123:     struct kvm_regs regs;
                    124:     int i;
                    125: 
                    126:     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
                    127:     if (ret < 0) {
                    128:         return ret;
                    129:     }
                    130: 
                    131:     for (i = 0; i < 16; i++) {
                    132:         env->regs[i] = regs.gprs[i];
                    133:     }
                    134: 
                    135:     env->psw.addr = env->kvm_run->psw_addr;
                    136:     env->psw.mask = env->kvm_run->psw_mask;
                    137: 
                    138:     return 0;
                    139: }
                    140: 
                    141: int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
                    142: {
                    143:     static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
                    144: 
                    145:     if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
                    146:         cpu_memory_rw_debug(env, bp->pc, (uint8_t *)diag_501, 4, 1)) {
                    147:         return -EINVAL;
                    148:     }
                    149:     return 0;
                    150: }
                    151: 
                    152: int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
                    153: {
                    154:     uint8_t t[4];
                    155:     static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
                    156: 
                    157:     if (cpu_memory_rw_debug(env, bp->pc, t, 4, 0)) {
                    158:         return -EINVAL;
                    159:     } else if (memcmp(t, diag_501, 4)) {
                    160:         return -EINVAL;
                    161:     } else if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
                    162:         return -EINVAL;
                    163:     }
                    164: 
                    165:     return 0;
                    166: }
                    167: 
                    168: int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
                    169: {
                    170:     return 0;
                    171: }
                    172: 
                    173: int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
                    174: {
                    175:     return 0;
                    176: }
                    177: 
                    178: static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
                    179:                                         uint64_t parm64, int vm)
                    180: {
                    181:     struct kvm_s390_interrupt kvmint;
                    182:     int r;
                    183: 
                    184:     if (!env->kvm_state) {
                    185:         return;
                    186:     }
                    187: 
                    188:     env->halted = 0;
                    189:     env->exception_index = 0;
                    190: 
                    191:     kvmint.type = type;
                    192:     kvmint.parm = parm;
                    193:     kvmint.parm64 = parm64;
                    194: 
                    195:     if (vm) {
                    196:         r = kvm_vm_ioctl(env->kvm_state, KVM_S390_INTERRUPT, &kvmint);
                    197:     } else {
                    198:         r = kvm_vcpu_ioctl(env, KVM_S390_INTERRUPT, &kvmint);
                    199:     }
                    200: 
                    201:     if (r < 0) {
                    202:         fprintf(stderr, "KVM failed to inject interrupt\n");
                    203:         exit(1);
                    204:     }
                    205: }
                    206: 
                    207: void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token)
                    208: {
                    209:     kvm_s390_interrupt_internal(env, KVM_S390_INT_VIRTIO, config_change,
                    210:                                 token, 1);
                    211: }
                    212: 
                    213: static void kvm_s390_interrupt(CPUState *env, int type, uint32_t code)
                    214: {
                    215:     kvm_s390_interrupt_internal(env, type, code, 0, 0);
                    216: }
                    217: 
                    218: static void enter_pgmcheck(CPUState *env, uint16_t code)
                    219: {
                    220:     kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
                    221: }
                    222: 
                    223: static void setcc(CPUState *env, uint64_t cc)
                    224: {
                    225:     env->kvm_run->psw_mask &= ~(3ul << 44);
                    226:     env->kvm_run->psw_mask |= (cc & 3) << 44;
                    227: 
                    228:     env->psw.mask &= ~(3ul << 44);
                    229:     env->psw.mask |= (cc & 3) << 44;
                    230: }
                    231: 
                    232: static int sclp_service_call(CPUState *env, struct kvm_run *run, uint16_t ipbh0)
                    233: {
                    234:     uint32_t sccb;
                    235:     uint64_t code;
                    236:     int r = 0;
                    237: 
                    238:     cpu_synchronize_state(env);
                    239:     sccb = env->regs[ipbh0 & 0xf];
                    240:     code = env->regs[(ipbh0 & 0xf0) >> 4];
                    241: 
                    242:     dprintf("sclp(0x%x, 0x%lx)\n", sccb, code);
                    243: 
                    244:     if (sccb & ~0x7ffffff8ul) {
                    245:         fprintf(stderr, "KVM: invalid sccb address 0x%x\n", sccb);
                    246:         r = -1;
                    247:         goto out;
                    248:     }
                    249: 
                    250:     switch(code) {
                    251:         case SCLP_CMDW_READ_SCP_INFO:
                    252:         case SCLP_CMDW_READ_SCP_INFO_FORCED:
                    253:             stw_phys(sccb + SCP_MEM_CODE, ram_size >> 20);
                    254:             stb_phys(sccb + SCP_INCREMENT, 1);
                    255:             stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
                    256:             setcc(env, 0);
                    257: 
                    258:             kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE,
                    259:                                         sccb & ~3, 0, 1);
                    260:             break;
                    261:         default:
                    262:             dprintf("KVM: invalid sclp call 0x%x / 0x%lx\n", sccb, code);
                    263:             r = -1;
                    264:             break;
                    265:     }
                    266: 
                    267: out:
                    268:     if (r < 0) {
                    269:         setcc(env, 3);
                    270:     }
                    271:     return 0;
                    272: }
                    273: 
                    274: static int handle_priv(CPUState *env, struct kvm_run *run, uint8_t ipa1)
                    275: {
                    276:     int r = 0;
                    277:     uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16;
                    278: 
                    279:     dprintf("KVM: PRIV: %d\n", ipa1);
                    280:     switch (ipa1) {
                    281:         case PRIV_SCLP_CALL:
                    282:             r = sclp_service_call(env, run, ipbh0);
                    283:             break;
                    284:         default:
                    285:             dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
                    286:             r = -1;
                    287:             break;
                    288:     }
                    289: 
                    290:     return r;
                    291: }
                    292: 
                    293: static int handle_hypercall(CPUState *env, struct kvm_run *run)
                    294: {
                    295:     int r;
                    296: 
                    297:     cpu_synchronize_state(env);
                    298:     r = s390_virtio_hypercall(env);
                    299:     kvm_arch_put_registers(env);
                    300: 
                    301:     return r;
                    302: }
                    303: 
                    304: static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code)
                    305: {
                    306:     int r = 0;
                    307: 
                    308:     switch (ipb_code) {
                    309:         case DIAG_KVM_HYPERCALL:
                    310:             r = handle_hypercall(env, run);
                    311:             break;
                    312:         case DIAG_KVM_BREAKPOINT:
                    313:             sleep(10);
                    314:             break;
                    315:         default:
                    316:             dprintf("KVM: unknown DIAG: 0x%x\n", ipb_code);
                    317:             r = -1;
                    318:             break;
                    319:     }
                    320: 
                    321:     return r;
                    322: }
                    323: 
                    324: static int s390_cpu_restart(CPUState *env)
                    325: {
                    326:     kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
                    327:     env->halted = 0;
                    328:     env->exception_index = 0;
                    329:     qemu_cpu_kick(env);
                    330:     dprintf("DONE: SIGP cpu restart: %p\n", env);
                    331:     return 0;
                    332: }
                    333: 
                    334: static int s390_store_status(CPUState *env, uint32_t parameter)
                    335: {
                    336:     /* XXX */
                    337:     fprintf(stderr, "XXX SIGP store status\n");
                    338:     return -1;
                    339: }
                    340: 
                    341: static int s390_cpu_initial_reset(CPUState *env)
                    342: {
                    343:     /* XXX */
                    344:     fprintf(stderr, "XXX SIGP init\n");
                    345:     return -1;
                    346: }
                    347: 
                    348: static int handle_sigp(CPUState *env, struct kvm_run *run, uint8_t ipa1)
                    349: {
                    350:     uint8_t order_code;
                    351:     uint32_t parameter;
                    352:     uint16_t cpu_addr;
                    353:     uint8_t t;
                    354:     int r = -1;
                    355:     CPUState *target_env;
                    356: 
                    357:     cpu_synchronize_state(env);
                    358: 
                    359:     /* get order code */
                    360:     order_code = run->s390_sieic.ipb >> 28;
                    361:     if (order_code > 0) {
                    362:         order_code = env->regs[order_code];
                    363:     }
                    364:     order_code += (run->s390_sieic.ipb & 0x0fff0000) >> 16;
                    365: 
                    366:     /* get parameters */
                    367:     t = (ipa1 & 0xf0) >> 4;
                    368:     if (!(t % 2)) {
                    369:         t++;
                    370:     }
                    371: 
                    372:     parameter = env->regs[t] & 0x7ffffe00;
                    373:     cpu_addr = env->regs[ipa1 & 0x0f];
                    374: 
                    375:     target_env = s390_cpu_addr2state(cpu_addr);
                    376:     if (!target_env) {
                    377:         goto out;
                    378:     }
                    379: 
                    380:     switch (order_code) {
                    381:         case SIGP_RESTART:
                    382:             r = s390_cpu_restart(target_env);
                    383:             break;
                    384:         case SIGP_STORE_STATUS_ADDR:
                    385:             r = s390_store_status(target_env, parameter);
                    386:             break;
                    387:         case SIGP_SET_ARCH:
                    388:             /* make the caller panic */
                    389:             return -1;
                    390:         case SIGP_INITIAL_CPU_RESET:
                    391:             r = s390_cpu_initial_reset(target_env);
                    392:             break;
                    393:         default:
                    394:             fprintf(stderr, "KVM: unknown SIGP: 0x%x\n", ipa1);
                    395:             break;
                    396:     }
                    397: 
                    398: out:
                    399:     setcc(env, r ? 3 : 0);
                    400:     return 0;
                    401: }
                    402: 
                    403: static int handle_instruction(CPUState *env, struct kvm_run *run)
                    404: {
                    405:     unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
                    406:     uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
                    407:     int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16;
                    408:     int r = -1;
                    409: 
                    410:     dprintf("handle_instruction 0x%x 0x%x\n", run->s390_sieic.ipa, run->s390_sieic.ipb);
                    411:     switch (ipa0) {
                    412:         case IPA0_PRIV:
                    413:             r = handle_priv(env, run, ipa1);
                    414:             break;
                    415:         case IPA0_DIAG:
                    416:             r = handle_diag(env, run, ipb_code);
                    417:             break;
                    418:         case IPA0_SIGP:
                    419:             r = handle_sigp(env, run, ipa1);
                    420:             break;
                    421:     }
                    422: 
                    423:     if (r < 0) {
                    424:         enter_pgmcheck(env, 0x0001);
                    425:     }
                    426:     return r;
                    427: }
                    428: 
                    429: static int handle_intercept(CPUState *env)
                    430: {
                    431:     struct kvm_run *run = env->kvm_run;
                    432:     int icpt_code = run->s390_sieic.icptcode;
                    433:     int r = 0;
                    434: 
                    435:     dprintf("intercept: 0x%x (at 0x%lx)\n", icpt_code, env->kvm_run->psw_addr);
                    436:     switch (icpt_code) {
                    437:         case ICPT_INSTRUCTION:
                    438:             r = handle_instruction(env, run);
                    439:             break;
                    440:         case ICPT_WAITPSW:
                    441:             /* XXX What to do on system shutdown? */
                    442:             env->halted = 1;
                    443:             env->exception_index = EXCP_HLT;
                    444:             break;
                    445:         case ICPT_SOFT_INTERCEPT:
                    446:             fprintf(stderr, "KVM unimplemented icpt SOFT\n");
                    447:             exit(1);
                    448:             break;
                    449:         case ICPT_CPU_STOP:
                    450:             qemu_system_shutdown_request();
                    451:             break;
                    452:         case ICPT_IO:
                    453:             fprintf(stderr, "KVM unimplemented icpt IO\n");
                    454:             exit(1);
                    455:             break;
                    456:         default:
                    457:             fprintf(stderr, "Unknown intercept code: %d\n", icpt_code);
                    458:             exit(1);
                    459:             break;
                    460:     }
                    461: 
                    462:     return r;
                    463: }
                    464: 
                    465: int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
                    466: {
                    467:     int ret = 0;
                    468: 
                    469:     switch (run->exit_reason) {
                    470:         case KVM_EXIT_S390_SIEIC:
                    471:             ret = handle_intercept(env);
                    472:             break;
                    473:         case KVM_EXIT_S390_RESET:
                    474:             fprintf(stderr, "RESET not implemented\n");
                    475:             exit(1);
                    476:             break;
                    477:         default:
                    478:             fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
                    479:             break;
                    480:     }
                    481: 
                    482:     return ret;
                    483: }

unix.superglobalmegacorp.com

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