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

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 ICPT_INSTRUCTION                0x04
                     53: #define ICPT_WAITPSW                    0x1c
                     54: #define ICPT_SOFT_INTERCEPT             0x24
                     55: #define ICPT_CPU_STOP                   0x28
                     56: #define ICPT_IO                         0x40
                     57: 
                     58: #define SIGP_RESTART                    0x06
                     59: #define SIGP_INITIAL_CPU_RESET          0x0b
                     60: #define SIGP_STORE_STATUS_ADDR          0x0e
                     61: #define SIGP_SET_ARCH                   0x12
                     62: 
                     63: #define SCLP_CMDW_READ_SCP_INFO         0x00020001
                     64: #define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
                     65: 
1.1.1.3   root       66: const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
                     67:     KVM_CAP_LAST_INFO
                     68: };
                     69: 
                     70: int kvm_arch_init(KVMState *s)
1.1       root       71: {
                     72:     return 0;
                     73: }
                     74: 
                     75: int kvm_arch_init_vcpu(CPUState *env)
                     76: {
                     77:     int ret = 0;
                     78: 
                     79:     if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) {
                     80:         perror("cannot init reset vcpu");
                     81:     }
                     82: 
                     83:     return ret;
                     84: }
                     85: 
                     86: void kvm_arch_reset_vcpu(CPUState *env)
                     87: {
                     88:     /* FIXME: add code to reset vcpu. */
                     89: }
                     90: 
1.1.1.2   root       91: int kvm_arch_put_registers(CPUState *env, int level)
1.1       root       92: {
                     93:     struct kvm_regs regs;
                     94:     int ret;
                     95:     int i;
                     96: 
                     97:     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
                     98:     if (ret < 0) {
                     99:         return ret;
                    100:     }
                    101: 
                    102:     for (i = 0; i < 16; i++) {
                    103:         regs.gprs[i] = env->regs[i];
                    104:     }
                    105: 
                    106:     ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs);
                    107:     if (ret < 0) {
                    108:         return ret;
                    109:     }
                    110: 
                    111:     env->kvm_run->psw_addr = env->psw.addr;
                    112:     env->kvm_run->psw_mask = env->psw.mask;
                    113: 
                    114:     return ret;
                    115: }
                    116: 
                    117: int kvm_arch_get_registers(CPUState *env)
                    118: {
1.1.1.3   root      119:     int ret;
1.1       root      120:     struct kvm_regs regs;
                    121:     int i;
                    122: 
                    123:     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
                    124:     if (ret < 0) {
                    125:         return ret;
                    126:     }
                    127: 
                    128:     for (i = 0; i < 16; i++) {
                    129:         env->regs[i] = regs.gprs[i];
                    130:     }
                    131: 
                    132:     env->psw.addr = env->kvm_run->psw_addr;
                    133:     env->psw.mask = env->kvm_run->psw_mask;
                    134: 
                    135:     return 0;
                    136: }
                    137: 
                    138: int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
                    139: {
                    140:     static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
                    141: 
                    142:     if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
                    143:         cpu_memory_rw_debug(env, bp->pc, (uint8_t *)diag_501, 4, 1)) {
                    144:         return -EINVAL;
                    145:     }
                    146:     return 0;
                    147: }
                    148: 
                    149: int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
                    150: {
                    151:     uint8_t t[4];
                    152:     static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
                    153: 
                    154:     if (cpu_memory_rw_debug(env, bp->pc, t, 4, 0)) {
                    155:         return -EINVAL;
                    156:     } else if (memcmp(t, diag_501, 4)) {
                    157:         return -EINVAL;
                    158:     } else if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
                    159:         return -EINVAL;
                    160:     }
                    161: 
                    162:     return 0;
                    163: }
                    164: 
1.1.1.4 ! root      165: void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
1.1       root      166: {
                    167: }
                    168: 
1.1.1.4 ! root      169: void kvm_arch_post_run(CPUState *env, struct kvm_run *run)
1.1       root      170: {
                    171: }
                    172: 
1.1.1.4 ! root      173: int kvm_arch_process_async_events(CPUState *env)
1.1.1.2   root      174: {
1.1.1.4 ! root      175:     return env->halted;
1.1.1.2   root      176: }
                    177: 
1.1.1.4 ! root      178: void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
        !           179:                                  uint64_t parm64, int vm)
1.1       root      180: {
                    181:     struct kvm_s390_interrupt kvmint;
                    182:     int r;
                    183: 
                    184:     if (!env->kvm_state) {
                    185:         return;
                    186:     }
                    187: 
                    188:     env->halted = 0;
1.1.1.2   root      189:     env->exception_index = -1;
1.1.1.4 ! root      190:     qemu_cpu_kick(env);
1.1       root      191: 
                    192:     kvmint.type = type;
                    193:     kvmint.parm = parm;
                    194:     kvmint.parm64 = parm64;
                    195: 
                    196:     if (vm) {
                    197:         r = kvm_vm_ioctl(env->kvm_state, KVM_S390_INTERRUPT, &kvmint);
                    198:     } else {
                    199:         r = kvm_vcpu_ioctl(env, KVM_S390_INTERRUPT, &kvmint);
                    200:     }
                    201: 
                    202:     if (r < 0) {
                    203:         fprintf(stderr, "KVM failed to inject interrupt\n");
                    204:         exit(1);
                    205:     }
                    206: }
                    207: 
                    208: void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token)
                    209: {
                    210:     kvm_s390_interrupt_internal(env, KVM_S390_INT_VIRTIO, config_change,
                    211:                                 token, 1);
                    212: }
                    213: 
1.1.1.4 ! root      214: void kvm_s390_interrupt(CPUState *env, int type, uint32_t code)
1.1       root      215: {
                    216:     kvm_s390_interrupt_internal(env, type, code, 0, 0);
                    217: }
                    218: 
                    219: static void enter_pgmcheck(CPUState *env, uint16_t code)
                    220: {
                    221:     kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
                    222: }
                    223: 
1.1.1.4 ! root      224: static inline void setcc(CPUState *env, uint64_t cc)
1.1       root      225: {
1.1.1.4 ! root      226:     env->kvm_run->psw_mask &= ~(3ull << 44);
1.1       root      227:     env->kvm_run->psw_mask |= (cc & 3) << 44;
                    228: 
                    229:     env->psw.mask &= ~(3ul << 44);
                    230:     env->psw.mask |= (cc & 3) << 44;
                    231: }
                    232: 
1.1.1.4 ! root      233: static int kvm_sclp_service_call(CPUState *env, struct kvm_run *run,
        !           234:                                  uint16_t ipbh0)
1.1       root      235: {
                    236:     uint32_t sccb;
                    237:     uint64_t code;
                    238:     int r = 0;
                    239: 
                    240:     cpu_synchronize_state(env);
                    241:     sccb = env->regs[ipbh0 & 0xf];
                    242:     code = env->regs[(ipbh0 & 0xf0) >> 4];
                    243: 
1.1.1.4 ! root      244:     r = sclp_service_call(env, sccb, code);
        !           245:     if (r) {
1.1       root      246:         setcc(env, 3);
                    247:     }
1.1.1.4 ! root      248: 
1.1       root      249:     return 0;
                    250: }
                    251: 
                    252: static int handle_priv(CPUState *env, struct kvm_run *run, uint8_t ipa1)
                    253: {
                    254:     int r = 0;
                    255:     uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16;
                    256: 
                    257:     dprintf("KVM: PRIV: %d\n", ipa1);
                    258:     switch (ipa1) {
                    259:         case PRIV_SCLP_CALL:
1.1.1.4 ! root      260:             r = kvm_sclp_service_call(env, run, ipbh0);
1.1       root      261:             break;
                    262:         default:
                    263:             dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
                    264:             r = -1;
                    265:             break;
                    266:     }
                    267: 
                    268:     return r;
                    269: }
                    270: 
                    271: static int handle_hypercall(CPUState *env, struct kvm_run *run)
                    272: {
                    273:     cpu_synchronize_state(env);
1.1.1.4 ! root      274:     env->regs[2] = s390_virtio_hypercall(env, env->regs[2], env->regs[1]);
1.1       root      275: 
1.1.1.4 ! root      276:     return 0;
1.1       root      277: }
                    278: 
                    279: static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code)
                    280: {
                    281:     int r = 0;
                    282: 
                    283:     switch (ipb_code) {
                    284:         case DIAG_KVM_HYPERCALL:
                    285:             r = handle_hypercall(env, run);
                    286:             break;
                    287:         case DIAG_KVM_BREAKPOINT:
                    288:             sleep(10);
                    289:             break;
                    290:         default:
                    291:             dprintf("KVM: unknown DIAG: 0x%x\n", ipb_code);
                    292:             r = -1;
                    293:             break;
                    294:     }
                    295: 
                    296:     return r;
                    297: }
                    298: 
                    299: static int s390_cpu_restart(CPUState *env)
                    300: {
                    301:     kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
                    302:     env->halted = 0;
1.1.1.2   root      303:     env->exception_index = -1;
1.1       root      304:     qemu_cpu_kick(env);
                    305:     dprintf("DONE: SIGP cpu restart: %p\n", env);
                    306:     return 0;
                    307: }
                    308: 
                    309: static int s390_store_status(CPUState *env, uint32_t parameter)
                    310: {
                    311:     /* XXX */
                    312:     fprintf(stderr, "XXX SIGP store status\n");
                    313:     return -1;
                    314: }
                    315: 
                    316: static int s390_cpu_initial_reset(CPUState *env)
                    317: {
1.1.1.2   root      318:     int i;
                    319: 
                    320:     if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) {
                    321:         perror("cannot init reset vcpu");
                    322:     }
                    323: 
                    324:     /* Manually zero out all registers */
                    325:     cpu_synchronize_state(env);
                    326:     for (i = 0; i < 16; i++) {
                    327:         env->regs[i] = 0;
                    328:     }
                    329: 
                    330:     dprintf("DONE: SIGP initial reset: %p\n", env);
                    331:     return 0;
1.1       root      332: }
                    333: 
                    334: static int handle_sigp(CPUState *env, struct kvm_run *run, uint8_t ipa1)
                    335: {
                    336:     uint8_t order_code;
                    337:     uint32_t parameter;
                    338:     uint16_t cpu_addr;
                    339:     uint8_t t;
                    340:     int r = -1;
                    341:     CPUState *target_env;
                    342: 
                    343:     cpu_synchronize_state(env);
                    344: 
                    345:     /* get order code */
                    346:     order_code = run->s390_sieic.ipb >> 28;
                    347:     if (order_code > 0) {
                    348:         order_code = env->regs[order_code];
                    349:     }
                    350:     order_code += (run->s390_sieic.ipb & 0x0fff0000) >> 16;
                    351: 
                    352:     /* get parameters */
                    353:     t = (ipa1 & 0xf0) >> 4;
                    354:     if (!(t % 2)) {
                    355:         t++;
                    356:     }
                    357: 
                    358:     parameter = env->regs[t] & 0x7ffffe00;
                    359:     cpu_addr = env->regs[ipa1 & 0x0f];
                    360: 
                    361:     target_env = s390_cpu_addr2state(cpu_addr);
                    362:     if (!target_env) {
                    363:         goto out;
                    364:     }
                    365: 
                    366:     switch (order_code) {
                    367:         case SIGP_RESTART:
                    368:             r = s390_cpu_restart(target_env);
                    369:             break;
                    370:         case SIGP_STORE_STATUS_ADDR:
                    371:             r = s390_store_status(target_env, parameter);
                    372:             break;
                    373:         case SIGP_SET_ARCH:
                    374:             /* make the caller panic */
                    375:             return -1;
                    376:         case SIGP_INITIAL_CPU_RESET:
                    377:             r = s390_cpu_initial_reset(target_env);
                    378:             break;
                    379:         default:
1.1.1.4 ! root      380:             fprintf(stderr, "KVM: unknown SIGP: 0x%x\n", order_code);
1.1       root      381:             break;
                    382:     }
                    383: 
                    384: out:
                    385:     setcc(env, r ? 3 : 0);
                    386:     return 0;
                    387: }
                    388: 
                    389: static int handle_instruction(CPUState *env, struct kvm_run *run)
                    390: {
                    391:     unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
                    392:     uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
                    393:     int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16;
                    394:     int r = -1;
                    395: 
                    396:     dprintf("handle_instruction 0x%x 0x%x\n", run->s390_sieic.ipa, run->s390_sieic.ipb);
                    397:     switch (ipa0) {
                    398:         case IPA0_PRIV:
                    399:             r = handle_priv(env, run, ipa1);
                    400:             break;
                    401:         case IPA0_DIAG:
                    402:             r = handle_diag(env, run, ipb_code);
                    403:             break;
                    404:         case IPA0_SIGP:
                    405:             r = handle_sigp(env, run, ipa1);
                    406:             break;
                    407:     }
                    408: 
                    409:     if (r < 0) {
                    410:         enter_pgmcheck(env, 0x0001);
                    411:     }
1.1.1.4 ! root      412:     return 0;
1.1       root      413: }
                    414: 
                    415: static int handle_intercept(CPUState *env)
                    416: {
                    417:     struct kvm_run *run = env->kvm_run;
                    418:     int icpt_code = run->s390_sieic.icptcode;
                    419:     int r = 0;
                    420: 
1.1.1.4 ! root      421:     dprintf("intercept: 0x%x (at 0x%lx)\n", icpt_code,
        !           422:             (long)env->kvm_run->psw_addr);
1.1       root      423:     switch (icpt_code) {
                    424:         case ICPT_INSTRUCTION:
                    425:             r = handle_instruction(env, run);
                    426:             break;
                    427:         case ICPT_WAITPSW:
                    428:             /* XXX What to do on system shutdown? */
                    429:             env->halted = 1;
                    430:             env->exception_index = EXCP_HLT;
                    431:             break;
                    432:         case ICPT_SOFT_INTERCEPT:
                    433:             fprintf(stderr, "KVM unimplemented icpt SOFT\n");
                    434:             exit(1);
                    435:             break;
                    436:         case ICPT_CPU_STOP:
                    437:             qemu_system_shutdown_request();
                    438:             break;
                    439:         case ICPT_IO:
                    440:             fprintf(stderr, "KVM unimplemented icpt IO\n");
                    441:             exit(1);
                    442:             break;
                    443:         default:
                    444:             fprintf(stderr, "Unknown intercept code: %d\n", icpt_code);
                    445:             exit(1);
                    446:             break;
                    447:     }
                    448: 
                    449:     return r;
                    450: }
                    451: 
                    452: int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
                    453: {
                    454:     int ret = 0;
                    455: 
                    456:     switch (run->exit_reason) {
                    457:         case KVM_EXIT_S390_SIEIC:
                    458:             ret = handle_intercept(env);
                    459:             break;
                    460:         case KVM_EXIT_S390_RESET:
                    461:             fprintf(stderr, "RESET not implemented\n");
                    462:             exit(1);
                    463:             break;
                    464:         default:
                    465:             fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
                    466:             break;
                    467:     }
                    468: 
1.1.1.4 ! root      469:     if (ret == 0) {
        !           470:         ret = EXCP_INTERRUPT;
        !           471:     } else if (ret > 0) {
        !           472:         ret = 0;
        !           473:     }
1.1       root      474:     return ret;
                    475: }
1.1.1.2   root      476: 
                    477: bool kvm_arch_stop_on_emulation_error(CPUState *env)
                    478: {
                    479:     return true;
                    480: }
1.1.1.4 ! root      481: 
        !           482: int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
        !           483: {
        !           484:     return 1;
        !           485: }
        !           486: 
        !           487: int kvm_arch_on_sigbus(int code, void *addr)
        !           488: {
        !           489:     return 1;
        !           490: }

unix.superglobalmegacorp.com

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