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

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

unix.superglobalmegacorp.com

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