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

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: 
1.1.1.2 ! root       94: int kvm_arch_put_registers(CPUState *env, int level)
1.1       root       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: 
1.1.1.2 ! root      178: int kvm_arch_process_irqchip_events(CPUState *env)
        !           179: {
        !           180:     return 0;
        !           181: }
        !           182: 
1.1       root      183: static void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
                    184:                                         uint64_t parm64, int vm)
                    185: {
                    186:     struct kvm_s390_interrupt kvmint;
                    187:     int r;
                    188: 
                    189:     if (!env->kvm_state) {
                    190:         return;
                    191:     }
                    192: 
                    193:     env->halted = 0;
1.1.1.2 ! root      194:     env->exception_index = -1;
1.1       root      195: 
                    196:     kvmint.type = type;
                    197:     kvmint.parm = parm;
                    198:     kvmint.parm64 = parm64;
                    199: 
                    200:     if (vm) {
                    201:         r = kvm_vm_ioctl(env->kvm_state, KVM_S390_INTERRUPT, &kvmint);
                    202:     } else {
                    203:         r = kvm_vcpu_ioctl(env, KVM_S390_INTERRUPT, &kvmint);
                    204:     }
                    205: 
                    206:     if (r < 0) {
                    207:         fprintf(stderr, "KVM failed to inject interrupt\n");
                    208:         exit(1);
                    209:     }
                    210: }
                    211: 
                    212: void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token)
                    213: {
                    214:     kvm_s390_interrupt_internal(env, KVM_S390_INT_VIRTIO, config_change,
                    215:                                 token, 1);
                    216: }
                    217: 
                    218: static void kvm_s390_interrupt(CPUState *env, int type, uint32_t code)
                    219: {
                    220:     kvm_s390_interrupt_internal(env, type, code, 0, 0);
                    221: }
                    222: 
                    223: static void enter_pgmcheck(CPUState *env, uint16_t code)
                    224: {
                    225:     kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
                    226: }
                    227: 
                    228: static void setcc(CPUState *env, uint64_t cc)
                    229: {
                    230:     env->kvm_run->psw_mask &= ~(3ul << 44);
                    231:     env->kvm_run->psw_mask |= (cc & 3) << 44;
                    232: 
                    233:     env->psw.mask &= ~(3ul << 44);
                    234:     env->psw.mask |= (cc & 3) << 44;
                    235: }
                    236: 
                    237: static int sclp_service_call(CPUState *env, struct kvm_run *run, uint16_t ipbh0)
                    238: {
                    239:     uint32_t sccb;
                    240:     uint64_t code;
                    241:     int r = 0;
                    242: 
                    243:     cpu_synchronize_state(env);
                    244:     sccb = env->regs[ipbh0 & 0xf];
                    245:     code = env->regs[(ipbh0 & 0xf0) >> 4];
                    246: 
                    247:     dprintf("sclp(0x%x, 0x%lx)\n", sccb, code);
                    248: 
                    249:     if (sccb & ~0x7ffffff8ul) {
                    250:         fprintf(stderr, "KVM: invalid sccb address 0x%x\n", sccb);
                    251:         r = -1;
                    252:         goto out;
                    253:     }
                    254: 
                    255:     switch(code) {
                    256:         case SCLP_CMDW_READ_SCP_INFO:
                    257:         case SCLP_CMDW_READ_SCP_INFO_FORCED:
                    258:             stw_phys(sccb + SCP_MEM_CODE, ram_size >> 20);
                    259:             stb_phys(sccb + SCP_INCREMENT, 1);
                    260:             stw_phys(sccb + SCP_RESPONSE_CODE, 0x10);
                    261:             setcc(env, 0);
                    262: 
                    263:             kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE,
                    264:                                         sccb & ~3, 0, 1);
                    265:             break;
                    266:         default:
                    267:             dprintf("KVM: invalid sclp call 0x%x / 0x%lx\n", sccb, code);
                    268:             r = -1;
                    269:             break;
                    270:     }
                    271: 
                    272: out:
                    273:     if (r < 0) {
                    274:         setcc(env, 3);
                    275:     }
                    276:     return 0;
                    277: }
                    278: 
                    279: static int handle_priv(CPUState *env, struct kvm_run *run, uint8_t ipa1)
                    280: {
                    281:     int r = 0;
                    282:     uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16;
                    283: 
                    284:     dprintf("KVM: PRIV: %d\n", ipa1);
                    285:     switch (ipa1) {
                    286:         case PRIV_SCLP_CALL:
                    287:             r = sclp_service_call(env, run, ipbh0);
                    288:             break;
                    289:         default:
                    290:             dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
                    291:             r = -1;
                    292:             break;
                    293:     }
                    294: 
                    295:     return r;
                    296: }
                    297: 
                    298: static int handle_hypercall(CPUState *env, struct kvm_run *run)
                    299: {
                    300:     int r;
                    301: 
                    302:     cpu_synchronize_state(env);
                    303:     r = s390_virtio_hypercall(env);
                    304: 
                    305:     return r;
                    306: }
                    307: 
                    308: static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code)
                    309: {
                    310:     int r = 0;
                    311: 
                    312:     switch (ipb_code) {
                    313:         case DIAG_KVM_HYPERCALL:
                    314:             r = handle_hypercall(env, run);
                    315:             break;
                    316:         case DIAG_KVM_BREAKPOINT:
                    317:             sleep(10);
                    318:             break;
                    319:         default:
                    320:             dprintf("KVM: unknown DIAG: 0x%x\n", ipb_code);
                    321:             r = -1;
                    322:             break;
                    323:     }
                    324: 
                    325:     return r;
                    326: }
                    327: 
                    328: static int s390_cpu_restart(CPUState *env)
                    329: {
                    330:     kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
                    331:     env->halted = 0;
1.1.1.2 ! root      332:     env->exception_index = -1;
1.1       root      333:     qemu_cpu_kick(env);
                    334:     dprintf("DONE: SIGP cpu restart: %p\n", env);
                    335:     return 0;
                    336: }
                    337: 
                    338: static int s390_store_status(CPUState *env, uint32_t parameter)
                    339: {
                    340:     /* XXX */
                    341:     fprintf(stderr, "XXX SIGP store status\n");
                    342:     return -1;
                    343: }
                    344: 
                    345: static int s390_cpu_initial_reset(CPUState *env)
                    346: {
1.1.1.2 ! root      347:     int i;
        !           348: 
        !           349:     if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) {
        !           350:         perror("cannot init reset vcpu");
        !           351:     }
        !           352: 
        !           353:     /* Manually zero out all registers */
        !           354:     cpu_synchronize_state(env);
        !           355:     for (i = 0; i < 16; i++) {
        !           356:         env->regs[i] = 0;
        !           357:     }
        !           358: 
        !           359:     dprintf("DONE: SIGP initial reset: %p\n", env);
        !           360:     return 0;
1.1       root      361: }
                    362: 
                    363: static int handle_sigp(CPUState *env, struct kvm_run *run, uint8_t ipa1)
                    364: {
                    365:     uint8_t order_code;
                    366:     uint32_t parameter;
                    367:     uint16_t cpu_addr;
                    368:     uint8_t t;
                    369:     int r = -1;
                    370:     CPUState *target_env;
                    371: 
                    372:     cpu_synchronize_state(env);
                    373: 
                    374:     /* get order code */
                    375:     order_code = run->s390_sieic.ipb >> 28;
                    376:     if (order_code > 0) {
                    377:         order_code = env->regs[order_code];
                    378:     }
                    379:     order_code += (run->s390_sieic.ipb & 0x0fff0000) >> 16;
                    380: 
                    381:     /* get parameters */
                    382:     t = (ipa1 & 0xf0) >> 4;
                    383:     if (!(t % 2)) {
                    384:         t++;
                    385:     }
                    386: 
                    387:     parameter = env->regs[t] & 0x7ffffe00;
                    388:     cpu_addr = env->regs[ipa1 & 0x0f];
                    389: 
                    390:     target_env = s390_cpu_addr2state(cpu_addr);
                    391:     if (!target_env) {
                    392:         goto out;
                    393:     }
                    394: 
                    395:     switch (order_code) {
                    396:         case SIGP_RESTART:
                    397:             r = s390_cpu_restart(target_env);
                    398:             break;
                    399:         case SIGP_STORE_STATUS_ADDR:
                    400:             r = s390_store_status(target_env, parameter);
                    401:             break;
                    402:         case SIGP_SET_ARCH:
                    403:             /* make the caller panic */
                    404:             return -1;
                    405:         case SIGP_INITIAL_CPU_RESET:
                    406:             r = s390_cpu_initial_reset(target_env);
                    407:             break;
                    408:         default:
                    409:             fprintf(stderr, "KVM: unknown SIGP: 0x%x\n", ipa1);
                    410:             break;
                    411:     }
                    412: 
                    413: out:
                    414:     setcc(env, r ? 3 : 0);
                    415:     return 0;
                    416: }
                    417: 
                    418: static int handle_instruction(CPUState *env, struct kvm_run *run)
                    419: {
                    420:     unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
                    421:     uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
                    422:     int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16;
                    423:     int r = -1;
                    424: 
                    425:     dprintf("handle_instruction 0x%x 0x%x\n", run->s390_sieic.ipa, run->s390_sieic.ipb);
                    426:     switch (ipa0) {
                    427:         case IPA0_PRIV:
                    428:             r = handle_priv(env, run, ipa1);
                    429:             break;
                    430:         case IPA0_DIAG:
                    431:             r = handle_diag(env, run, ipb_code);
                    432:             break;
                    433:         case IPA0_SIGP:
                    434:             r = handle_sigp(env, run, ipa1);
                    435:             break;
                    436:     }
                    437: 
                    438:     if (r < 0) {
                    439:         enter_pgmcheck(env, 0x0001);
                    440:     }
                    441:     return r;
                    442: }
                    443: 
                    444: static int handle_intercept(CPUState *env)
                    445: {
                    446:     struct kvm_run *run = env->kvm_run;
                    447:     int icpt_code = run->s390_sieic.icptcode;
                    448:     int r = 0;
                    449: 
                    450:     dprintf("intercept: 0x%x (at 0x%lx)\n", icpt_code, env->kvm_run->psw_addr);
                    451:     switch (icpt_code) {
                    452:         case ICPT_INSTRUCTION:
                    453:             r = handle_instruction(env, run);
                    454:             break;
                    455:         case ICPT_WAITPSW:
                    456:             /* XXX What to do on system shutdown? */
                    457:             env->halted = 1;
                    458:             env->exception_index = EXCP_HLT;
                    459:             break;
                    460:         case ICPT_SOFT_INTERCEPT:
                    461:             fprintf(stderr, "KVM unimplemented icpt SOFT\n");
                    462:             exit(1);
                    463:             break;
                    464:         case ICPT_CPU_STOP:
                    465:             qemu_system_shutdown_request();
                    466:             break;
                    467:         case ICPT_IO:
                    468:             fprintf(stderr, "KVM unimplemented icpt IO\n");
                    469:             exit(1);
                    470:             break;
                    471:         default:
                    472:             fprintf(stderr, "Unknown intercept code: %d\n", icpt_code);
                    473:             exit(1);
                    474:             break;
                    475:     }
                    476: 
                    477:     return r;
                    478: }
                    479: 
                    480: int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
                    481: {
                    482:     int ret = 0;
                    483: 
                    484:     switch (run->exit_reason) {
                    485:         case KVM_EXIT_S390_SIEIC:
                    486:             ret = handle_intercept(env);
                    487:             break;
                    488:         case KVM_EXIT_S390_RESET:
                    489:             fprintf(stderr, "RESET not implemented\n");
                    490:             exit(1);
                    491:             break;
                    492:         default:
                    493:             fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
                    494:             break;
                    495:     }
                    496: 
                    497:     return ret;
                    498: }
1.1.1.2 ! root      499: 
        !           500: bool kvm_arch_stop_on_emulation_error(CPUState *env)
        !           501: {
        !           502:     return true;
        !           503: }

unix.superglobalmegacorp.com

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