diff options
Diffstat (limited to 'target-s390x/kvm.c')
-rw-r--r-- | target-s390x/kvm.c | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 90aad61eb0..47008c24f2 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -135,6 +135,41 @@ int kvm_arch_get_registers(CPUS390XState *env) return 0; } +/* + * Legacy layout for s390: + * Older S390 KVM requires the topmost vma of the RAM to be + * smaller than an system defined value, which is at least 256GB. + * Larger systems have larger values. We put the guest between + * the end of data segment (system break) and this value. We + * use 32GB as a base to have enough room for the system break + * to grow. We also have to use MAP parameters that avoid + * read-only mapping of guest pages. + */ +static void *legacy_s390_alloc(ram_addr_t size) +{ + void *mem; + + mem = mmap((void *) 0x800000000ULL, size, + PROT_EXEC|PROT_READ|PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + if (mem == MAP_FAILED) { + fprintf(stderr, "Allocating RAM failed\n"); + abort(); + } + return mem; +} + +void *kvm_arch_vmalloc(ram_addr_t size) +{ + /* Can we use the standard allocation ? */ + if (kvm_check_extension(kvm_state, KVM_CAP_S390_GMAP) && + kvm_check_extension(kvm_state, KVM_CAP_S390_COW)) { + return NULL; + } else { + return legacy_s390_alloc(size); + } +} + int kvm_arch_insert_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp) { static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01}; @@ -292,8 +327,10 @@ static int handle_diag(CPUS390XState *env, struct kvm_run *run, int ipb_code) return r; } -static int s390_cpu_restart(CPUS390XState *env) +static int s390_cpu_restart(S390CPU *cpu) { + CPUS390XState *env = &cpu->env; + kvm_s390_interrupt(env, KVM_S390_RESTART, 0); s390_add_running_cpu(env); qemu_cpu_kick(env); @@ -312,6 +349,7 @@ static int s390_cpu_initial_reset(CPUS390XState *env) { int i; + s390_del_running_cpu(env); if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) { perror("cannot init reset vcpu"); } @@ -333,6 +371,7 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1) uint16_t cpu_addr; uint8_t t; int r = -1; + S390CPU *target_cpu; CPUS390XState *target_env; cpu_synchronize_state(env); @@ -353,14 +392,15 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1) parameter = env->regs[t] & 0x7ffffe00; cpu_addr = env->regs[ipa1 & 0x0f]; - target_env = s390_cpu_addr2state(cpu_addr); - if (!target_env) { + target_cpu = s390_cpu_addr2state(cpu_addr); + if (target_cpu == NULL) { goto out; } + target_env = &target_cpu->env; switch (order_code) { case SIGP_RESTART: - r = s390_cpu_restart(target_env); + r = s390_cpu_restart(target_cpu); break; case SIGP_STORE_STATUS_ADDR: r = s390_store_status(target_env, parameter); |