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

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

unix.superglobalmegacorp.com

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