From nobody Sat May 18 09:22:53 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1500886494569879.918337001972; Mon, 24 Jul 2017 01:54:54 -0700 (PDT) Received: from localhost ([::1]:53588 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZ8f-0003f2-23 for importer@patchew.org; Mon, 24 Jul 2017 04:54:53 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59015) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZ6o-0002M3-9f for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:52:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dZZ6m-0008IS-4g for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:52:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43468) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dZZ6l-0008II-Rl for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:52:56 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8106C80E6A; Mon, 24 Jul 2017 08:52:54 +0000 (UTC) Received: from thh440s.str.redhat.com (reserved-198-123.str.redhat.com [10.33.198.123]) by smtp.corp.redhat.com (Postfix) with ESMTP id 52AB761F2F; Mon, 24 Jul 2017 08:52:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 8106C80E6A Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=thuth@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 8106C80E6A From: Thomas Huth To: qemu-devel@nongnu.org, Richard Henderson Date: Mon, 24 Jul 2017 10:52:46 +0200 Message-Id: <1500886370-14572-2-git-send-email-thuth@redhat.com> In-Reply-To: <1500886370-14572-1-git-send-email-thuth@redhat.com> References: <1500886370-14572-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 24 Jul 2017 08:52:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v3 1/5] target/s390x: Move s390_cpu_dump_state() to helper.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Christian Borntraeger , Cornelia Huck , Alexander Graf Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" translate.c can not be compiled with --disable-tcg, but we need the s390_cpu_dump_state() in KVM-only builds, too. So let's move that function to helper.c instead, which will also be compiled when --disable-tcg has been specified. Reviewed-by: Richard Henderson Signed-off-by: Thomas Huth --- target/s390x/helper.c | 60 ++++++++++++++++++++++++++++++++++++++++++++= ++++ target/s390x/translate.c | 60 --------------------------------------------= ---- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/target/s390x/helper.c b/target/s390x/helper.c index aef09e1..30ac2a7 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -766,3 +766,63 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr= addr, program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); } #endif /* CONFIG_USER_ONLY */ + +void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprin= tf, + int flags) +{ + S390CPU *cpu =3D S390_CPU(cs); + CPUS390XState *env =3D &cpu->env; + int i; + + if (env->cc_op > 3) { + cpu_fprintf(f, "PSW=3Dmask %016" PRIx64 " addr %016" PRIx64 " cc %= 15s\n", + env->psw.mask, env->psw.addr, cc_name(env->cc_op)); + } else { + cpu_fprintf(f, "PSW=3Dmask %016" PRIx64 " addr %016" PRIx64 " cc %= 02x\n", + env->psw.mask, env->psw.addr, env->cc_op); + } + + for (i =3D 0; i < 16; i++) { + cpu_fprintf(f, "R%02d=3D%016" PRIx64, i, env->regs[i]); + if ((i % 4) =3D=3D 3) { + cpu_fprintf(f, "\n"); + } else { + cpu_fprintf(f, " "); + } + } + + for (i =3D 0; i < 16; i++) { + cpu_fprintf(f, "F%02d=3D%016" PRIx64, i, get_freg(env, i)->ll); + if ((i % 4) =3D=3D 3) { + cpu_fprintf(f, "\n"); + } else { + cpu_fprintf(f, " "); + } + } + + for (i =3D 0; i < 32; i++) { + cpu_fprintf(f, "V%02d=3D%016" PRIx64 "%016" PRIx64, i, + env->vregs[i][0].ll, env->vregs[i][1].ll); + cpu_fprintf(f, (i % 2) ? "\n" : " "); + } + +#ifndef CONFIG_USER_ONLY + for (i =3D 0; i < 16; i++) { + cpu_fprintf(f, "C%02d=3D%016" PRIx64, i, env->cregs[i]); + if ((i % 4) =3D=3D 3) { + cpu_fprintf(f, "\n"); + } else { + cpu_fprintf(f, " "); + } + } +#endif + +#ifdef DEBUG_INLINE_BRANCHES + for (i =3D 0; i < CC_OP_MAX; i++) { + cpu_fprintf(f, " %15s =3D %10ld\t%10ld\n", cc_name(i), + inline_branch_miss[i], inline_branch_hit[i]); + } +#endif + + cpu_fprintf(f, "\n"); +} diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 48b71f9..cd96a8d 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -93,66 +93,6 @@ static uint64_t pc_to_link_info(DisasContext *s, uint64_= t pc) return pc; } =20 -void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprin= tf, - int flags) -{ - S390CPU *cpu =3D S390_CPU(cs); - CPUS390XState *env =3D &cpu->env; - int i; - - if (env->cc_op > 3) { - cpu_fprintf(f, "PSW=3Dmask %016" PRIx64 " addr %016" PRIx64 " cc %= 15s\n", - env->psw.mask, env->psw.addr, cc_name(env->cc_op)); - } else { - cpu_fprintf(f, "PSW=3Dmask %016" PRIx64 " addr %016" PRIx64 " cc %= 02x\n", - env->psw.mask, env->psw.addr, env->cc_op); - } - - for (i =3D 0; i < 16; i++) { - cpu_fprintf(f, "R%02d=3D%016" PRIx64, i, env->regs[i]); - if ((i % 4) =3D=3D 3) { - cpu_fprintf(f, "\n"); - } else { - cpu_fprintf(f, " "); - } - } - - for (i =3D 0; i < 16; i++) { - cpu_fprintf(f, "F%02d=3D%016" PRIx64, i, get_freg(env, i)->ll); - if ((i % 4) =3D=3D 3) { - cpu_fprintf(f, "\n"); - } else { - cpu_fprintf(f, " "); - } - } - - for (i =3D 0; i < 32; i++) { - cpu_fprintf(f, "V%02d=3D%016" PRIx64 "%016" PRIx64, i, - env->vregs[i][0].ll, env->vregs[i][1].ll); - cpu_fprintf(f, (i % 2) ? "\n" : " "); - } - -#ifndef CONFIG_USER_ONLY - for (i =3D 0; i < 16; i++) { - cpu_fprintf(f, "C%02d=3D%016" PRIx64, i, env->cregs[i]); - if ((i % 4) =3D=3D 3) { - cpu_fprintf(f, "\n"); - } else { - cpu_fprintf(f, " "); - } - } -#endif - -#ifdef DEBUG_INLINE_BRANCHES - for (i =3D 0; i < CC_OP_MAX; i++) { - cpu_fprintf(f, " %15s =3D %10ld\t%10ld\n", cc_name(i), - inline_branch_miss[i], inline_branch_hit[i]); - } -#endif - - cpu_fprintf(f, "\n"); -} - static TCGv_i64 psw_addr; static TCGv_i64 psw_mask; static TCGv_i64 gbea; --=20 1.8.3.1 From nobody Sat May 18 09:22:53 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1500886501381906.026307856867; Mon, 24 Jul 2017 01:55:01 -0700 (PDT) Received: from localhost ([::1]:53589 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZ8m-0003hg-0b for importer@patchew.org; Mon, 24 Jul 2017 04:55:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59038) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZ6p-0002MG-Ud for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dZZ6n-0008J2-Rz for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50594) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dZZ6n-0008Ii-IX for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:52:57 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 64E70C058EA3; Mon, 24 Jul 2017 08:52:56 +0000 (UTC) Received: from thh440s.str.redhat.com (reserved-198-123.str.redhat.com [10.33.198.123]) by smtp.corp.redhat.com (Postfix) with ESMTP id DCF3461F2F; Mon, 24 Jul 2017 08:52:54 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 64E70C058EA3 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=thuth@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 64E70C058EA3 From: Thomas Huth To: qemu-devel@nongnu.org, Richard Henderson Date: Mon, 24 Jul 2017 10:52:47 +0200 Message-Id: <1500886370-14572-3-git-send-email-thuth@redhat.com> In-Reply-To: <1500886370-14572-1-git-send-email-thuth@redhat.com> References: <1500886370-14572-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 24 Jul 2017 08:52:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v3 2/5] target/s390x: Move diag helpers to a separate file X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Christian Borntraeger , Cornelia Huck , Alexander Graf Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" misc_helper.c won't be compiled with --disable-tcg anymore, but we still need the diag helpers in KVM builds, too, so move the helper functions to a separate file. Reviewed-by: Richard Henderson Signed-off-by: Thomas Huth --- target/s390x/Makefile.objs | 2 +- target/s390x/diag.c | 179 +++++++++++++++++++++++++++++++++++++++++= ++++ target/s390x/misc_helper.c | 167 ------------------------------------------ 3 files changed, 180 insertions(+), 168 deletions(-) create mode 100644 target/s390x/diag.c diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs index 46f6a8c..8002852 100644 --- a/target/s390x/Makefile.objs +++ b/target/s390x/Makefile.objs @@ -1,7 +1,7 @@ obj-y +=3D translate.o helper.o cpu.o interrupt.o obj-y +=3D int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-y +=3D gdbstub.o cpu_models.o cpu_features.o -obj-$(CONFIG_SOFTMMU) +=3D machine.o ioinst.o arch_dump.o mmu_helper.o +obj-$(CONFIG_SOFTMMU) +=3D machine.o ioinst.o arch_dump.o mmu_helper.o dia= g.o obj-$(CONFIG_KVM) +=3D kvm.o =20 # build and run feature list generator diff --git a/target/s390x/diag.c b/target/s390x/diag.c new file mode 100644 index 0000000..10ac845 --- /dev/null +++ b/target/s390x/diag.c @@ -0,0 +1,179 @@ +/* + * S390x DIAG instruction helper functions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/address-spaces.h" +#include "exec/exec-all.h" +#include "hw/watchdog/wdt_diag288.h" +#include "sysemu/cpus.h" +#include "hw/s390x/ipl.h" + +static int modified_clear_reset(S390CPU *cpu) +{ + S390CPUClass *scc =3D S390_CPU_GET_CLASS(cpu); + CPUState *t; + + pause_all_vcpus(); + cpu_synchronize_all_states(); + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); + } + s390_cmma_reset(); + subsystem_reset(); + s390_crypto_reset(); + scc->load_normal(CPU(cpu)); + cpu_synchronize_all_post_reset(); + resume_all_vcpus(); + return 0; +} + +static int load_normal_reset(S390CPU *cpu) +{ + S390CPUClass *scc =3D S390_CPU_GET_CLASS(cpu); + CPUState *t; + + pause_all_vcpus(); + cpu_synchronize_all_states(); + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); + } + s390_cmma_reset(); + subsystem_reset(); + scc->initial_cpu_reset(CPU(cpu)); + scc->load_normal(CPU(cpu)); + cpu_synchronize_all_post_reset(); + resume_all_vcpus(); + return 0; +} + +int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) +{ + uint64_t func =3D env->regs[r1]; + uint64_t timeout =3D env->regs[r1 + 1]; + uint64_t action =3D env->regs[r3]; + Object *obj; + DIAG288State *diag288; + DIAG288Class *diag288_class; + + if (r1 % 2 || action !=3D 0) { + return -1; + } + + /* Timeout must be more than 15 seconds except for timer deletion */ + if (func !=3D WDT_DIAG288_CANCEL && timeout < 15) { + return -1; + } + + obj =3D object_resolve_path_type("", TYPE_WDT_DIAG288, NULL); + if (!obj) { + return -1; + } + + diag288 =3D DIAG288(obj); + diag288_class =3D DIAG288_GET_CLASS(diag288); + return diag288_class->handle_timer(diag288, func, timeout); +} + +#define DIAG_308_RC_OK 0x0001 +#define DIAG_308_RC_NO_CONF 0x0102 +#define DIAG_308_RC_INVALID 0x0402 + +void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) +{ + uint64_t addr =3D env->regs[r1]; + uint64_t subcode =3D env->regs[r3]; + IplParameterBlock *iplb; + + if (env->psw.mask & PSW_MASK_PSTATE) { + program_interrupt(env, PGM_PRIVILEGED, ILEN_AUTO); + return; + } + + if ((subcode & ~0x0ffffULL) || (subcode > 6)) { + program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); + return; + } + + switch (subcode) { + case 0: + modified_clear_reset(s390_env_get_cpu(env)); + if (tcg_enabled()) { + cpu_loop_exit(CPU(s390_env_get_cpu(env))); + } + break; + case 1: + load_normal_reset(s390_env_get_cpu(env)); + if (tcg_enabled()) { + cpu_loop_exit(CPU(s390_env_get_cpu(env))); + } + break; + case 3: + s390_reipl_request(); + if (tcg_enabled()) { + cpu_loop_exit(CPU(s390_env_get_cpu(env))); + } + break; + case 5: + if ((r1 & 1) || (addr & 0x0fffULL)) { + program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); + return; + } + if (!address_space_access_valid(&address_space_memory, addr, + sizeof(IplParameterBlock), false))= { + program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO); + return; + } + iplb =3D g_malloc0(sizeof(IplParameterBlock)); + cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); + if (!iplb_valid_len(iplb)) { + env->regs[r1 + 1] =3D DIAG_308_RC_INVALID; + goto out; + } + + cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); + + if (!iplb_valid_ccw(iplb) && !iplb_valid_fcp(iplb)) { + env->regs[r1 + 1] =3D DIAG_308_RC_INVALID; + goto out; + } + + s390_ipl_update_diag308(iplb); + env->regs[r1 + 1] =3D DIAG_308_RC_OK; +out: + g_free(iplb); + return; + case 6: + if ((r1 & 1) || (addr & 0x0fffULL)) { + program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); + return; + } + if (!address_space_access_valid(&address_space_memory, addr, + sizeof(IplParameterBlock), true)) { + program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO); + return; + } + iplb =3D s390_ipl_get_iplb(); + if (iplb) { + cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); + env->regs[r1 + 1] =3D DIAG_308_RC_OK; + } else { + env->regs[r1 + 1] =3D DIAG_308_RC_NO_CONF; + } + return; + default: + hw_error("Unhandled diag308 subcode %" PRIx64, subcode); + break; + } +} diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index b508101..6a90ad5 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -24,22 +24,15 @@ #include "exec/memory.h" #include "qemu/host-utils.h" #include "exec/helper-proto.h" -#include "sysemu/kvm.h" #include "qemu/timer.h" -#include "qemu/main-loop.h" #include "exec/address-spaces.h" -#ifdef CONFIG_KVM -#include -#endif #include "exec/exec-all.h" #include "exec/cpu_ldst.h" =20 #if !defined(CONFIG_USER_ONLY) -#include "hw/watchdog/wdt_diag288.h" #include "sysemu/cpus.h" #include "sysemu/sysemu.h" #include "hw/s390x/ebcdic.h" -#include "hw/s390x/ipl.h" #endif =20 /* #define DEBUG_HELPER */ @@ -116,166 +109,6 @@ uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r= 1, uint64_t r2) return r; } =20 -#ifndef CONFIG_USER_ONLY -static int modified_clear_reset(S390CPU *cpu) -{ - S390CPUClass *scc =3D S390_CPU_GET_CLASS(cpu); - CPUState *t; - - pause_all_vcpus(); - cpu_synchronize_all_states(); - CPU_FOREACH(t) { - run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); - } - s390_cmma_reset(); - subsystem_reset(); - s390_crypto_reset(); - scc->load_normal(CPU(cpu)); - cpu_synchronize_all_post_reset(); - resume_all_vcpus(); - return 0; -} - -static int load_normal_reset(S390CPU *cpu) -{ - S390CPUClass *scc =3D S390_CPU_GET_CLASS(cpu); - CPUState *t; - - pause_all_vcpus(); - cpu_synchronize_all_states(); - CPU_FOREACH(t) { - run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); - } - s390_cmma_reset(); - subsystem_reset(); - scc->initial_cpu_reset(CPU(cpu)); - scc->load_normal(CPU(cpu)); - cpu_synchronize_all_post_reset(); - resume_all_vcpus(); - return 0; -} - -int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) -{ - uint64_t func =3D env->regs[r1]; - uint64_t timeout =3D env->regs[r1 + 1]; - uint64_t action =3D env->regs[r3]; - Object *obj; - DIAG288State *diag288; - DIAG288Class *diag288_class; - - if (r1 % 2 || action !=3D 0) { - return -1; - } - - /* Timeout must be more than 15 seconds except for timer deletion */ - if (func !=3D WDT_DIAG288_CANCEL && timeout < 15) { - return -1; - } - - obj =3D object_resolve_path_type("", TYPE_WDT_DIAG288, NULL); - if (!obj) { - return -1; - } - - diag288 =3D DIAG288(obj); - diag288_class =3D DIAG288_GET_CLASS(diag288); - return diag288_class->handle_timer(diag288, func, timeout); -} - -#define DIAG_308_RC_OK 0x0001 -#define DIAG_308_RC_NO_CONF 0x0102 -#define DIAG_308_RC_INVALID 0x0402 - -void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) -{ - uint64_t addr =3D env->regs[r1]; - uint64_t subcode =3D env->regs[r3]; - IplParameterBlock *iplb; - - if (env->psw.mask & PSW_MASK_PSTATE) { - program_interrupt(env, PGM_PRIVILEGED, ILEN_AUTO); - return; - } - - if ((subcode & ~0x0ffffULL) || (subcode > 6)) { - program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); - return; - } - - switch (subcode) { - case 0: - modified_clear_reset(s390_env_get_cpu(env)); - if (tcg_enabled()) { - cpu_loop_exit(CPU(s390_env_get_cpu(env))); - } - break; - case 1: - load_normal_reset(s390_env_get_cpu(env)); - if (tcg_enabled()) { - cpu_loop_exit(CPU(s390_env_get_cpu(env))); - } - break; - case 3: - s390_reipl_request(); - if (tcg_enabled()) { - cpu_loop_exit(CPU(s390_env_get_cpu(env))); - } - break; - case 5: - if ((r1 & 1) || (addr & 0x0fffULL)) { - program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); - return; - } - if (!address_space_access_valid(&address_space_memory, addr, - sizeof(IplParameterBlock), false))= { - program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO); - return; - } - iplb =3D g_malloc0(sizeof(IplParameterBlock)); - cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); - if (!iplb_valid_len(iplb)) { - env->regs[r1 + 1] =3D DIAG_308_RC_INVALID; - goto out; - } - - cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); - - if (!iplb_valid_ccw(iplb) && !iplb_valid_fcp(iplb)) { - env->regs[r1 + 1] =3D DIAG_308_RC_INVALID; - goto out; - } - - s390_ipl_update_diag308(iplb); - env->regs[r1 + 1] =3D DIAG_308_RC_OK; -out: - g_free(iplb); - return; - case 6: - if ((r1 & 1) || (addr & 0x0fffULL)) { - program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); - return; - } - if (!address_space_access_valid(&address_space_memory, addr, - sizeof(IplParameterBlock), true)) { - program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO); - return; - } - iplb =3D s390_ipl_get_iplb(); - if (iplb) { - cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); - env->regs[r1 + 1] =3D DIAG_308_RC_OK; - } else { - env->regs[r1 + 1] =3D DIAG_308_RC_NO_CONF; - } - return; - default: - hw_error("Unhandled diag308 subcode %" PRIx64, subcode); - break; - } -} -#endif - void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t n= um) { uint64_t r; --=20 1.8.3.1 From nobody Sat May 18 09:22:53 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1500886501436541.4755696767867; Mon, 24 Jul 2017 01:55:01 -0700 (PDT) Received: from localhost ([::1]:53590 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZ8l-0003iE-TG for importer@patchew.org; Mon, 24 Jul 2017 04:55:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59044) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZ6q-0002Mf-Lp for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dZZ6p-0008Kt-BT for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51520) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dZZ6p-0008JW-2r for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:52:59 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E940B3680E; Mon, 24 Jul 2017 08:52:57 +0000 (UTC) Received: from thh440s.str.redhat.com (reserved-198-123.str.redhat.com [10.33.198.123]) by smtp.corp.redhat.com (Postfix) with ESMTP id C01E661F2F; Mon, 24 Jul 2017 08:52:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com E940B3680E Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=thuth@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com E940B3680E From: Thomas Huth To: qemu-devel@nongnu.org, Richard Henderson Date: Mon, 24 Jul 2017 10:52:48 +0200 Message-Id: <1500886370-14572-4-git-send-email-thuth@redhat.com> In-Reply-To: <1500886370-14572-1-git-send-email-thuth@redhat.com> References: <1500886370-14572-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 24 Jul 2017 08:52:58 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v3 3/5] target/s390x: Rework program_interrupt() and related functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Christian Borntraeger , Cornelia Huck , Alexander Graf Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" misc_helper.c won't be compiled with --disable-tcg anymore, but we still need the program_interrupt() function in that case. Move it to interrupt.c instead, and refactor it to re-use the code from trigger_pgm_exception() (for TCG) and enter_pgmcheck() (for KVM, which now got renamed to kvm_s390_program_interrupt() for clarity). Signed-off-by: Thomas Huth Reviewed-by: Richard Henderson --- target/s390x/cpu.h | 9 +++++---- target/s390x/helper.c | 10 ---------- target/s390x/interrupt.c | 39 +++++++++++++++++++++++++++++++++++++++ target/s390x/kvm.c | 16 ++++++++-------- target/s390x/misc_helper.c | 26 -------------------------- 5 files changed, 52 insertions(+), 48 deletions(-) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 7732d01..4041bfc 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -474,10 +474,6 @@ static inline bool get_per_in_range(CPUS390XState *env= , uint64_t addr) } } =20 -#ifndef CONFIG_USER_ONLY -void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ile= n); -#endif - S390CPU *cpu_s390x_init(const char *cpu_model); S390CPU *s390x_new_cpu(const char *cpu_model, int64_t id, Error **errp); S390CPU *cpu_s390x_create(const char *cpu_model, Error **errp); @@ -1146,10 +1142,12 @@ void handle_diag_308(CPUS390XState *env, uint64_t r= 1, uint64_t r3); /* automatically detect the instruction length */ #define ILEN_AUTO 0xff void program_interrupt(CPUS390XState *env, uint32_t code, int ilen); +void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ile= n); void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, uintptr_t retaddr); =20 #ifdef CONFIG_KVM +void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code); void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_parm, uint32_t io_int_word); @@ -1170,6 +1168,9 @@ int kvm_s390_get_ri(void); int kvm_s390_get_gs(void); void kvm_s390_crypto_reset(void); #else +static inline void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code) +{ +} static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_parm, diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 30ac2a7..e2040d6 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -165,16 +165,6 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr addr= ess, =20 #else /* !CONFIG_USER_ONLY */ =20 -/* Ensure to exit the TB after this call! */ -void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ile= n) -{ - CPUState *cs =3D CPU(s390_env_get_cpu(env)); - - cs->exception_index =3D EXCP_PGM; - env->int_pgm_code =3D code; - env->int_pgm_ilen =3D ilen; -} - int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, int rw, int mmu_idx) { diff --git a/target/s390x/interrupt.c b/target/s390x/interrupt.c index 9edef96..fde3da7 100644 --- a/target/s390x/interrupt.c +++ b/target/s390x/interrupt.c @@ -8,10 +8,49 @@ */ =20 #include "qemu/osdep.h" +#include "qemu/log.h" #include "cpu.h" +#include "exec/exec-all.h" #include "sysemu/kvm.h" #include "hw/s390x/ioinst.h" =20 +/* Ensure to exit the TB after this call! */ +void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ile= n) +{ + CPUState *cs =3D CPU(s390_env_get_cpu(env)); + + cs->exception_index =3D EXCP_PGM; + env->int_pgm_code =3D code; + env->int_pgm_ilen =3D ilen; +} + +static void tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code, + int ilen) +{ +#ifdef CONFIG_TCG + trigger_pgm_exception(env, code, ilen); + cpu_loop_exit(CPU(s390_env_get_cpu(env))); +#else + g_assert_not_reached(); +#endif +} + +void program_interrupt(CPUS390XState *env, uint32_t code, int ilen) +{ + S390CPU *cpu =3D s390_env_get_cpu(env); + + qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n", + env->psw.addr); + + if (kvm_enabled()) { + kvm_s390_program_interrupt(cpu, code); + } else if (tcg_enabled()) { + tcg_s390_program_interrupt(env, code, ilen); + } else { + g_assert_not_reached(); + } +} + #if !defined(CONFIG_USER_ONLY) void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param, uint64_t param64) diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 831492f..4dd85e4 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -1032,7 +1032,7 @@ void kvm_s390_service_interrupt(uint32_t parm) kvm_s390_floating_interrupt(&irq); } =20 -static void enter_pgmcheck(S390CPU *cpu, uint16_t code) +void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code) { struct kvm_s390_irq irq =3D { .type =3D KVM_S390_PROGRAM_INT, @@ -1068,7 +1068,7 @@ static int kvm_sclp_service_call(S390CPU *cpu, struct= kvm_run *run, =20 r =3D sclp_service_call(env, sccb, code); if (r < 0) { - enter_pgmcheck(cpu, -r); + kvm_s390_program_interrupt(cpu, -r); } else { setcc(cpu, r); } @@ -1236,7 +1236,7 @@ static int kvm_sic_service_call(S390CPU *cpu, struct = kvm_run *run) isc =3D (env->regs[r3] >> 27) & 0x7; r =3D css_do_sic(env, isc, mode); if (r) { - enter_pgmcheck(cpu, -r); + kvm_s390_program_interrupt(cpu, -r); } =20 return 0; @@ -1357,7 +1357,7 @@ static int handle_hypercall(S390CPU *cpu, struct kvm_= run *run) cpu_synchronize_state(CPU(cpu)); ret =3D s390_virtio_hypercall(env); if (ret =3D=3D -EINVAL) { - enter_pgmcheck(cpu, PGM_SPECIFICATION); + kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION); return 0; } =20 @@ -1374,7 +1374,7 @@ static void kvm_handle_diag_288(S390CPU *cpu, struct = kvm_run *run) r3 =3D run->s390_sieic.ipa & 0x000f; rc =3D handle_diag_288(&cpu->env, r1, r3); if (rc) { - enter_pgmcheck(cpu, PGM_SPECIFICATION); + kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION); } } =20 @@ -1431,7 +1431,7 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *= run, uint32_t ipb) break; default: DPRINTF("KVM: unknown DIAG: 0x%x\n", func_code); - enter_pgmcheck(cpu, PGM_SPECIFICATION); + kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION); break; } =20 @@ -1899,7 +1899,7 @@ static int handle_instruction(S390CPU *cpu, struct kv= m_run *run) =20 if (r < 0) { r =3D 0; - enter_pgmcheck(cpu, 0x0001); + kvm_s390_program_interrupt(cpu, PGM_OPERATION); } =20 return r; @@ -2009,7 +2009,7 @@ static int handle_intercept(S390CPU *cpu) /* Then check for potential pgm check loops */ r =3D handle_oper_loop(cpu, run); if (r =3D=3D 0) { - enter_pgmcheck(cpu, PGM_OPERATION); + kvm_s390_program_interrupt(cpu, PGM_OPERATION); } } break; diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index 6a90ad5..44c5c40 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -68,32 +68,6 @@ void HELPER(exception)(CPUS390XState *env, uint32_t excp) cpu_loop_exit(cs); } =20 -void program_interrupt(CPUS390XState *env, uint32_t code, int ilen) -{ - S390CPU *cpu =3D s390_env_get_cpu(env); - - qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n", - env->psw.addr); - - if (kvm_enabled()) { -#ifdef CONFIG_KVM - struct kvm_s390_irq irq =3D { - .type =3D KVM_S390_PROGRAM_INT, - .u.pgm.code =3D code, - }; - - kvm_s390_vcpu_interrupt(cpu, &irq); -#endif - } else { - CPUState *cs =3D CPU(cpu); - - env->int_pgm_code =3D code; - env->int_pgm_ilen =3D ilen; - cs->exception_index =3D EXCP_PGM; - cpu_loop_exit(cs); - } -} - #ifndef CONFIG_USER_ONLY =20 /* SCLP service call */ --=20 1.8.3.1 From nobody Sat May 18 09:22:53 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1500886639993793.2850676290005; Mon, 24 Jul 2017 01:57:19 -0700 (PDT) Received: from localhost ([::1]:53602 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZB0-0005Vz-CZ for importer@patchew.org; Mon, 24 Jul 2017 04:57:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59091) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZ6u-0002Qe-S1 for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dZZ6r-0008Ld-4r for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:04 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44990) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dZZ6q-0008LH-P3 for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:01 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A0F8380462; Mon, 24 Jul 2017 08:52:59 +0000 (UTC) Received: from thh440s.str.redhat.com (reserved-198-123.str.redhat.com [10.33.198.123]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4A45D61F2F; Mon, 24 Jul 2017 08:52:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com A0F8380462 Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=thuth@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com A0F8380462 From: Thomas Huth To: qemu-devel@nongnu.org, Richard Henderson Date: Mon, 24 Jul 2017 10:52:49 +0200 Message-Id: <1500886370-14572-5-git-send-email-thuth@redhat.com> In-Reply-To: <1500886370-14572-1-git-send-email-thuth@redhat.com> References: <1500886370-14572-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 24 Jul 2017 08:52:59 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v3 4/5] target/s390x: Move exception-related functions to a new excp_helper.c file X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Christian Borntraeger , Cornelia Huck , Alexander Graf Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These functions can not be compiled with --disable-tcg. But since we need the other functions from helper.c in the non-tcg build, we can also not simply remove helper.c from the non-tcg builds. Thus the problematic functions have to be moved into a separate new file instead that we can later omit in the non-tcg builds. Reviewed-by: Richard Henderson Signed-off-by: Thomas Huth --- target/s390x/Makefile.objs | 2 +- target/s390x/cpu.h | 8 + target/s390x/excp_helper.c | 515 +++++++++++++++++++++++++++++++++++++++++= ++++ target/s390x/helper.c | 472 +---------------------------------------- 4 files changed, 528 insertions(+), 469 deletions(-) create mode 100644 target/s390x/excp_helper.c diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs index 8002852..cc2b4c9 100644 --- a/target/s390x/Makefile.objs +++ b/target/s390x/Makefile.objs @@ -1,6 +1,6 @@ obj-y +=3D translate.o helper.o cpu.o interrupt.o obj-y +=3D int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o -obj-y +=3D gdbstub.o cpu_models.o cpu_features.o +obj-y +=3D gdbstub.o cpu_models.o cpu_features.o excp_helper.o obj-$(CONFIG_SOFTMMU) +=3D machine.o ioinst.o arch_dump.o mmu_helper.o dia= g.o obj-$(CONFIG_KVM) +=3D kvm.o =20 diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 4041bfc..29fdd5d 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -801,6 +801,8 @@ static inline void setcc(S390CPU *cpu, uint64_t cc) env->cc_op =3D cc; } =20 +#ifndef CONFIG_USER_ONLY + typedef struct LowCore { /* prefix area: defined by architecture */ @@ -918,6 +920,11 @@ typedef struct LowCore uint8_t pad18[0x2000-0x1400]; /* 0x1400 */ } QEMU_PACKED LowCore; =20 +LowCore *cpu_map_lowcore(CPUS390XState *env); +void cpu_unmap_lowcore(LowCore *lowcore); + +#endif + /* STSI */ #define STSI_LEVEL_MASK 0x00000000f0000000ULL #define STSI_LEVEL_CURRENT 0x0000000000000000ULL @@ -1094,6 +1101,7 @@ struct sysib_322 { #define SIGP_ORDER_MASK 0x000000ff =20 void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr); +uint64_t get_psw_mask(CPUS390XState *env); target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr); int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t= asc, target_ulong *raddr, int *flags, bool exc); diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c new file mode 100644 index 0000000..d183377 --- /dev/null +++ b/target/s390x/excp_helper.c @@ -0,0 +1,515 @@ +/* + * s390x exception / interrupt helpers + * + * Copyright (c) 2009 Ulrich Hecht + * Copyright (c) 2011 Alexander Graf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "cpu.h" +#include "qemu/timer.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "hw/s390x/ioinst.h" +#ifndef CONFIG_USER_ONLY +#include "sysemu/sysemu.h" +#endif + +/* #define DEBUG_S390 */ +/* #define DEBUG_S390_STDOUT */ + +#ifdef DEBUG_S390 +#ifdef DEBUG_S390_STDOUT +#define DPRINTF(fmt, ...) \ + do { fprintf(stderr, fmt, ## __VA_ARGS__); \ + if (qemu_log_separate()) { qemu_log(fmt, ##__VA_ARGS__); } } whil= e (0) +#else +#define DPRINTF(fmt, ...) \ + do { qemu_log(fmt, ## __VA_ARGS__); } while (0) +#endif +#else +#define DPRINTF(fmt, ...) \ + do { } while (0) +#endif + +#if defined(CONFIG_USER_ONLY) + +void s390_cpu_do_interrupt(CPUState *cs) +{ + cs->exception_index =3D -1; +} + +int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, + int rw, int mmu_idx) +{ + S390CPU *cpu =3D S390_CPU(cs); + + cs->exception_index =3D EXCP_PGM; + cpu->env.int_pgm_code =3D PGM_ADDRESSING; + /* On real machines this value is dropped into LowMem. Since this + is userland, simply put this someplace that cpu_loop can find it. = */ + cpu->env.__excp_addr =3D address; + return 1; +} + +#else /* !CONFIG_USER_ONLY */ + +int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, + int rw, int mmu_idx) +{ + S390CPU *cpu =3D S390_CPU(cs); + CPUS390XState *env =3D &cpu->env; + uint64_t asc =3D cpu_mmu_idx_to_asc(mmu_idx); + target_ulong vaddr, raddr; + int prot; + + DPRINTF("%s: address 0x%" VADDR_PRIx " rw %d mmu_idx %d\n", + __func__, orig_vaddr, rw, mmu_idx); + + orig_vaddr &=3D TARGET_PAGE_MASK; + vaddr =3D orig_vaddr; + + /* 31-Bit mode */ + if (!(env->psw.mask & PSW_MASK_64)) { + vaddr &=3D 0x7fffffff; + } + + if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) { + /* Translation ended in exception */ + return 1; + } + + /* check out of RAM access */ + if (raddr > ram_size) { + DPRINTF("%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__, + (uint64_t)raddr, (uint64_t)ram_size); + trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO); + return 1; + } + + qemu_log_mask(CPU_LOG_MMU, "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x= )\n", + __func__, (uint64_t)vaddr, (uint64_t)raddr, prot); + + tlb_set_page(cs, orig_vaddr, raddr, prot, + mmu_idx, TARGET_PAGE_SIZE); + + return 0; +} + +static void do_program_interrupt(CPUS390XState *env) +{ + uint64_t mask, addr; + LowCore *lowcore; + int ilen =3D env->int_pgm_ilen; + + if (ilen =3D=3D ILEN_AUTO) { + ilen =3D get_ilen(cpu_ldub_code(env, env->psw.addr)); + } + assert(ilen =3D=3D 2 || ilen =3D=3D 4 || ilen =3D=3D 6); + + switch (env->int_pgm_code) { + case PGM_PER: + if (env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION) { + break; + } + /* FALL THROUGH */ + case PGM_OPERATION: + case PGM_PRIVILEGED: + case PGM_EXECUTE: + case PGM_PROTECTION: + case PGM_ADDRESSING: + case PGM_SPECIFICATION: + case PGM_DATA: + case PGM_FIXPT_OVERFLOW: + case PGM_FIXPT_DIVIDE: + case PGM_DEC_OVERFLOW: + case PGM_DEC_DIVIDE: + case PGM_HFP_EXP_OVERFLOW: + case PGM_HFP_EXP_UNDERFLOW: + case PGM_HFP_SIGNIFICANCE: + case PGM_HFP_DIVIDE: + case PGM_TRANS_SPEC: + case PGM_SPECIAL_OP: + case PGM_OPERAND: + case PGM_HFP_SQRT: + case PGM_PC_TRANS_SPEC: + case PGM_ALET_SPEC: + case PGM_MONITOR: + /* advance the PSW if our exception is not nullifying */ + env->psw.addr +=3D ilen; + break; + } + + qemu_log_mask(CPU_LOG_INT, "%s: code=3D0x%x ilen=3D%d\n", + __func__, env->int_pgm_code, ilen); + + lowcore =3D cpu_map_lowcore(env); + + /* Signal PER events with the exception. */ + if (env->per_perc_atmid) { + env->int_pgm_code |=3D PGM_PER; + lowcore->per_address =3D cpu_to_be64(env->per_address); + lowcore->per_perc_atmid =3D cpu_to_be16(env->per_perc_atmid); + env->per_perc_atmid =3D 0; + } + + lowcore->pgm_ilen =3D cpu_to_be16(ilen); + lowcore->pgm_code =3D cpu_to_be16(env->int_pgm_code); + lowcore->program_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); + lowcore->program_old_psw.addr =3D cpu_to_be64(env->psw.addr); + mask =3D be64_to_cpu(lowcore->program_new_psw.mask); + addr =3D be64_to_cpu(lowcore->program_new_psw.addr); + lowcore->per_breaking_event_addr =3D cpu_to_be64(env->gbea); + + cpu_unmap_lowcore(lowcore); + + DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__, + env->int_pgm_code, ilen, env->psw.mask, + env->psw.addr); + + load_psw(env, mask, addr); +} + +static void do_svc_interrupt(CPUS390XState *env) +{ + uint64_t mask, addr; + LowCore *lowcore; + + lowcore =3D cpu_map_lowcore(env); + + lowcore->svc_code =3D cpu_to_be16(env->int_svc_code); + lowcore->svc_ilen =3D cpu_to_be16(env->int_svc_ilen); + lowcore->svc_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); + lowcore->svc_old_psw.addr =3D cpu_to_be64(env->psw.addr + env->int_svc= _ilen); + mask =3D be64_to_cpu(lowcore->svc_new_psw.mask); + addr =3D be64_to_cpu(lowcore->svc_new_psw.addr); + + cpu_unmap_lowcore(lowcore); + + load_psw(env, mask, addr); + + /* When a PER event is pending, the PER exception has to happen + immediately after the SERVICE CALL one. */ + if (env->per_perc_atmid) { + env->int_pgm_code =3D PGM_PER; + env->int_pgm_ilen =3D env->int_svc_ilen; + do_program_interrupt(env); + } +} + +#define VIRTIO_SUBCODE_64 0x0D00 + +static void do_ext_interrupt(CPUS390XState *env) +{ + S390CPU *cpu =3D s390_env_get_cpu(env); + uint64_t mask, addr; + LowCore *lowcore; + ExtQueue *q; + + if (!(env->psw.mask & PSW_MASK_EXT)) { + cpu_abort(CPU(cpu), "Ext int w/o ext mask\n"); + } + + if (env->ext_index < 0 || env->ext_index >=3D MAX_EXT_QUEUE) { + cpu_abort(CPU(cpu), "Ext queue overrun: %d\n", env->ext_index); + } + + q =3D &env->ext_queue[env->ext_index]; + lowcore =3D cpu_map_lowcore(env); + + lowcore->ext_int_code =3D cpu_to_be16(q->code); + lowcore->ext_params =3D cpu_to_be32(q->param); + lowcore->ext_params2 =3D cpu_to_be64(q->param64); + lowcore->external_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); + lowcore->external_old_psw.addr =3D cpu_to_be64(env->psw.addr); + lowcore->cpu_addr =3D cpu_to_be16(env->cpu_num | VIRTIO_SUBCODE_64); + mask =3D be64_to_cpu(lowcore->external_new_psw.mask); + addr =3D be64_to_cpu(lowcore->external_new_psw.addr); + + cpu_unmap_lowcore(lowcore); + + env->ext_index--; + if (env->ext_index =3D=3D -1) { + env->pending_int &=3D ~INTERRUPT_EXT; + } + + DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, + env->psw.mask, env->psw.addr); + + load_psw(env, mask, addr); +} + +static void do_io_interrupt(CPUS390XState *env) +{ + S390CPU *cpu =3D s390_env_get_cpu(env); + LowCore *lowcore; + IOIntQueue *q; + uint8_t isc; + int disable =3D 1; + int found =3D 0; + + if (!(env->psw.mask & PSW_MASK_IO)) { + cpu_abort(CPU(cpu), "I/O int w/o I/O mask\n"); + } + + for (isc =3D 0; isc < ARRAY_SIZE(env->io_index); isc++) { + uint64_t isc_bits; + + if (env->io_index[isc] < 0) { + continue; + } + if (env->io_index[isc] >=3D MAX_IO_QUEUE) { + cpu_abort(CPU(cpu), "I/O queue overrun for isc %d: %d\n", + isc, env->io_index[isc]); + } + + q =3D &env->io_queue[env->io_index[isc]][isc]; + isc_bits =3D ISC_TO_ISC_BITS(IO_INT_WORD_ISC(q->word)); + if (!(env->cregs[6] & isc_bits)) { + disable =3D 0; + continue; + } + if (!found) { + uint64_t mask, addr; + + found =3D 1; + lowcore =3D cpu_map_lowcore(env); + + lowcore->subchannel_id =3D cpu_to_be16(q->id); + lowcore->subchannel_nr =3D cpu_to_be16(q->nr); + lowcore->io_int_parm =3D cpu_to_be32(q->parm); + lowcore->io_int_word =3D cpu_to_be32(q->word); + lowcore->io_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); + lowcore->io_old_psw.addr =3D cpu_to_be64(env->psw.addr); + mask =3D be64_to_cpu(lowcore->io_new_psw.mask); + addr =3D be64_to_cpu(lowcore->io_new_psw.addr); + + cpu_unmap_lowcore(lowcore); + + env->io_index[isc]--; + + DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, + env->psw.mask, env->psw.addr); + load_psw(env, mask, addr); + } + if (env->io_index[isc] >=3D 0) { + disable =3D 0; + } + continue; + } + + if (disable) { + env->pending_int &=3D ~INTERRUPT_IO; + } + +} + +static void do_mchk_interrupt(CPUS390XState *env) +{ + S390CPU *cpu =3D s390_env_get_cpu(env); + uint64_t mask, addr; + LowCore *lowcore; + MchkQueue *q; + int i; + + if (!(env->psw.mask & PSW_MASK_MCHECK)) { + cpu_abort(CPU(cpu), "Machine check w/o mchk mask\n"); + } + + if (env->mchk_index < 0 || env->mchk_index >=3D MAX_MCHK_QUEUE) { + cpu_abort(CPU(cpu), "Mchk queue overrun: %d\n", env->mchk_index); + } + + q =3D &env->mchk_queue[env->mchk_index]; + + if (q->type !=3D 1) { + /* Don't know how to handle this... */ + cpu_abort(CPU(cpu), "Unknown machine check type %d\n", q->type); + } + if (!(env->cregs[14] & (1 << 28))) { + /* CRW machine checks disabled */ + return; + } + + lowcore =3D cpu_map_lowcore(env); + + for (i =3D 0; i < 16; i++) { + lowcore->floating_pt_save_area[i] =3D cpu_to_be64(get_freg(env, i)= ->ll); + lowcore->gpregs_save_area[i] =3D cpu_to_be64(env->regs[i]); + lowcore->access_regs_save_area[i] =3D cpu_to_be32(env->aregs[i]); + lowcore->cregs_save_area[i] =3D cpu_to_be64(env->cregs[i]); + } + lowcore->prefixreg_save_area =3D cpu_to_be32(env->psa); + lowcore->fpt_creg_save_area =3D cpu_to_be32(env->fpc); + lowcore->tod_progreg_save_area =3D cpu_to_be32(env->todpr); + lowcore->cpu_timer_save_area[0] =3D cpu_to_be32(env->cputm >> 32); + lowcore->cpu_timer_save_area[1] =3D cpu_to_be32((uint32_t)env->cputm); + lowcore->clock_comp_save_area[0] =3D cpu_to_be32(env->ckc >> 32); + lowcore->clock_comp_save_area[1] =3D cpu_to_be32((uint32_t)env->ckc); + + lowcore->mcck_interruption_code[0] =3D cpu_to_be32(0x00400f1d); + lowcore->mcck_interruption_code[1] =3D cpu_to_be32(0x40330000); + lowcore->mcck_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); + lowcore->mcck_old_psw.addr =3D cpu_to_be64(env->psw.addr); + mask =3D be64_to_cpu(lowcore->mcck_new_psw.mask); + addr =3D be64_to_cpu(lowcore->mcck_new_psw.addr); + + cpu_unmap_lowcore(lowcore); + + env->mchk_index--; + if (env->mchk_index =3D=3D -1) { + env->pending_int &=3D ~INTERRUPT_MCHK; + } + + DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, + env->psw.mask, env->psw.addr); + + load_psw(env, mask, addr); +} + +void s390_cpu_do_interrupt(CPUState *cs) +{ + S390CPU *cpu =3D S390_CPU(cs); + CPUS390XState *env =3D &cpu->env; + + qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=3D%" PRIx64 "\n", + __func__, cs->exception_index, env->psw.addr); + + s390_cpu_set_state(CPU_STATE_OPERATING, cpu); + /* handle machine checks */ + if ((env->psw.mask & PSW_MASK_MCHECK) && + (cs->exception_index =3D=3D -1)) { + if (env->pending_int & INTERRUPT_MCHK) { + cs->exception_index =3D EXCP_MCHK; + } + } + /* handle external interrupts */ + if ((env->psw.mask & PSW_MASK_EXT) && + cs->exception_index =3D=3D -1) { + if (env->pending_int & INTERRUPT_EXT) { + /* code is already in env */ + cs->exception_index =3D EXCP_EXT; + } else if (env->pending_int & INTERRUPT_TOD) { + cpu_inject_ext(cpu, 0x1004, 0, 0); + cs->exception_index =3D EXCP_EXT; + env->pending_int &=3D ~INTERRUPT_EXT; + env->pending_int &=3D ~INTERRUPT_TOD; + } else if (env->pending_int & INTERRUPT_CPUTIMER) { + cpu_inject_ext(cpu, 0x1005, 0, 0); + cs->exception_index =3D EXCP_EXT; + env->pending_int &=3D ~INTERRUPT_EXT; + env->pending_int &=3D ~INTERRUPT_TOD; + } + } + /* handle I/O interrupts */ + if ((env->psw.mask & PSW_MASK_IO) && + (cs->exception_index =3D=3D -1)) { + if (env->pending_int & INTERRUPT_IO) { + cs->exception_index =3D EXCP_IO; + } + } + + switch (cs->exception_index) { + case EXCP_PGM: + do_program_interrupt(env); + break; + case EXCP_SVC: + do_svc_interrupt(env); + break; + case EXCP_EXT: + do_ext_interrupt(env); + break; + case EXCP_IO: + do_io_interrupt(env); + break; + case EXCP_MCHK: + do_mchk_interrupt(env); + break; + } + cs->exception_index =3D -1; + + if (!env->pending_int) { + cs->interrupt_request &=3D ~CPU_INTERRUPT_HARD; + } +} + +bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + if (interrupt_request & CPU_INTERRUPT_HARD) { + S390CPU *cpu =3D S390_CPU(cs); + CPUS390XState *env =3D &cpu->env; + + if (env->ex_value) { + /* Execution of the target insn is indivisible from + the parent EXECUTE insn. */ + return false; + } + if (env->psw.mask & PSW_MASK_EXT) { + s390_cpu_do_interrupt(cs); + return true; + } + } + return false; +} + +void s390x_cpu_debug_excp_handler(CPUState *cs) +{ + S390CPU *cpu =3D S390_CPU(cs); + CPUS390XState *env =3D &cpu->env; + CPUWatchpoint *wp_hit =3D cs->watchpoint_hit; + + if (wp_hit && wp_hit->flags & BP_CPU) { + /* FIXME: When the storage-alteration-space control bit is set, + the exception should only be triggered if the memory access + is done using an address space with the storage-alteration-event + bit set. We have no way to detect that with the current + watchpoint code. */ + cs->watchpoint_hit =3D NULL; + + env->per_address =3D env->psw.addr; + env->per_perc_atmid |=3D PER_CODE_EVENT_STORE | get_per_atmid(env); + /* FIXME: We currently no way to detect the address space used + to trigger the watchpoint. For now just consider it is the + current default ASC. This turn to be true except when MVCP + and MVCS instrutions are not used. */ + env->per_perc_atmid |=3D env->psw.mask & (PSW_MASK_ASC) >> 46; + + /* Remove all watchpoints to re-execute the code. A PER exception + will be triggered, it will call load_psw which will recompute + the watchpoints. */ + cpu_watchpoint_remove_all(cs, BP_CPU); + cpu_loop_exit_noexc(cs); + } +} + +/* Unaligned accesses are only diagnosed with MO_ALIGN. At the moment, + this is only for the atomic operations, for which we want to raise a + specification exception. */ +void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr) +{ + S390CPU *cpu =3D S390_CPU(cs); + CPUS390XState *env =3D &cpu->env; + + if (retaddr) { + cpu_restore_state(cs, retaddr); + } + program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); +} + +#endif /* CONFIG_USER_ONLY */ diff --git a/target/s390x/helper.c b/target/s390x/helper.c index e2040d6..0c989b1 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -24,7 +24,6 @@ #include "exec/gdbstub.h" #include "qemu/timer.h" #include "exec/exec-all.h" -#include "exec/cpu_ldst.h" #include "hw/s390x/ioinst.h" #ifndef CONFIG_USER_ONLY #include "sysemu/sysemu.h" @@ -143,69 +142,7 @@ S390CPU *cpu_s390x_init(const char *cpu_model) return cpu; } =20 -#if defined(CONFIG_USER_ONLY) - -void s390_cpu_do_interrupt(CPUState *cs) -{ - cs->exception_index =3D -1; -} - -int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address, - int rw, int mmu_idx) -{ - S390CPU *cpu =3D S390_CPU(cs); - - cs->exception_index =3D EXCP_PGM; - cpu->env.int_pgm_code =3D PGM_ADDRESSING; - /* On real machines this value is dropped into LowMem. Since this - is userland, simply put this someplace that cpu_loop can find it. = */ - cpu->env.__excp_addr =3D address; - return 1; -} - -#else /* !CONFIG_USER_ONLY */ - -int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, - int rw, int mmu_idx) -{ - S390CPU *cpu =3D S390_CPU(cs); - CPUS390XState *env =3D &cpu->env; - uint64_t asc =3D cpu_mmu_idx_to_asc(mmu_idx); - target_ulong vaddr, raddr; - int prot; - - DPRINTF("%s: address 0x%" VADDR_PRIx " rw %d mmu_idx %d\n", - __func__, orig_vaddr, rw, mmu_idx); - - orig_vaddr &=3D TARGET_PAGE_MASK; - vaddr =3D orig_vaddr; - - /* 31-Bit mode */ - if (!(env->psw.mask & PSW_MASK_64)) { - vaddr &=3D 0x7fffffff; - } - - if (mmu_translate(env, vaddr, rw, asc, &raddr, &prot, true)) { - /* Translation ended in exception */ - return 1; - } - - /* check out of RAM access */ - if (raddr > ram_size) { - DPRINTF("%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__, - (uint64_t)raddr, (uint64_t)ram_size); - trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO); - return 1; - } - - qemu_log_mask(CPU_LOG_MMU, "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x= )\n", - __func__, (uint64_t)vaddr, (uint64_t)raddr, prot); - - tlb_set_page(cs, orig_vaddr, raddr, prot, - mmu_idx, TARGET_PAGE_SIZE); - - return 0; -} +#ifndef CONFIG_USER_ONLY =20 hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr) { @@ -262,7 +199,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64= _t addr) } } =20 -static uint64_t get_psw_mask(CPUS390XState *env) +uint64_t get_psw_mask(CPUS390XState *env) { uint64_t r =3D env->psw.mask; =20 @@ -278,7 +215,7 @@ static uint64_t get_psw_mask(CPUS390XState *env) return r; } =20 -static LowCore *cpu_map_lowcore(CPUS390XState *env) +LowCore *cpu_map_lowcore(CPUS390XState *env) { S390CPU *cpu =3D s390_env_get_cpu(env); LowCore *lowcore; @@ -293,7 +230,7 @@ static LowCore *cpu_map_lowcore(CPUS390XState *env) return lowcore; } =20 -static void cpu_unmap_lowcore(LowCore *lowcore) +void cpu_unmap_lowcore(LowCore *lowcore) { cpu_physical_memory_unmap(lowcore, sizeof(LowCore), 1, sizeof(LowCore)= ); } @@ -315,362 +252,6 @@ void do_restart_interrupt(CPUS390XState *env) load_psw(env, mask, addr); } =20 -static void do_program_interrupt(CPUS390XState *env) -{ - uint64_t mask, addr; - LowCore *lowcore; - int ilen =3D env->int_pgm_ilen; - - if (ilen =3D=3D ILEN_AUTO) { - ilen =3D get_ilen(cpu_ldub_code(env, env->psw.addr)); - } - assert(ilen =3D=3D 2 || ilen =3D=3D 4 || ilen =3D=3D 6); - - switch (env->int_pgm_code) { - case PGM_PER: - if (env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION) { - break; - } - /* FALL THROUGH */ - case PGM_OPERATION: - case PGM_PRIVILEGED: - case PGM_EXECUTE: - case PGM_PROTECTION: - case PGM_ADDRESSING: - case PGM_SPECIFICATION: - case PGM_DATA: - case PGM_FIXPT_OVERFLOW: - case PGM_FIXPT_DIVIDE: - case PGM_DEC_OVERFLOW: - case PGM_DEC_DIVIDE: - case PGM_HFP_EXP_OVERFLOW: - case PGM_HFP_EXP_UNDERFLOW: - case PGM_HFP_SIGNIFICANCE: - case PGM_HFP_DIVIDE: - case PGM_TRANS_SPEC: - case PGM_SPECIAL_OP: - case PGM_OPERAND: - case PGM_HFP_SQRT: - case PGM_PC_TRANS_SPEC: - case PGM_ALET_SPEC: - case PGM_MONITOR: - /* advance the PSW if our exception is not nullifying */ - env->psw.addr +=3D ilen; - break; - } - - qemu_log_mask(CPU_LOG_INT, "%s: code=3D0x%x ilen=3D%d\n", - __func__, env->int_pgm_code, ilen); - - lowcore =3D cpu_map_lowcore(env); - - /* Signal PER events with the exception. */ - if (env->per_perc_atmid) { - env->int_pgm_code |=3D PGM_PER; - lowcore->per_address =3D cpu_to_be64(env->per_address); - lowcore->per_perc_atmid =3D cpu_to_be16(env->per_perc_atmid); - env->per_perc_atmid =3D 0; - } - - lowcore->pgm_ilen =3D cpu_to_be16(ilen); - lowcore->pgm_code =3D cpu_to_be16(env->int_pgm_code); - lowcore->program_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); - lowcore->program_old_psw.addr =3D cpu_to_be64(env->psw.addr); - mask =3D be64_to_cpu(lowcore->program_new_psw.mask); - addr =3D be64_to_cpu(lowcore->program_new_psw.addr); - lowcore->per_breaking_event_addr =3D cpu_to_be64(env->gbea); - - cpu_unmap_lowcore(lowcore); - - DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__, - env->int_pgm_code, ilen, env->psw.mask, - env->psw.addr); - - load_psw(env, mask, addr); -} - -static void do_svc_interrupt(CPUS390XState *env) -{ - uint64_t mask, addr; - LowCore *lowcore; - - lowcore =3D cpu_map_lowcore(env); - - lowcore->svc_code =3D cpu_to_be16(env->int_svc_code); - lowcore->svc_ilen =3D cpu_to_be16(env->int_svc_ilen); - lowcore->svc_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); - lowcore->svc_old_psw.addr =3D cpu_to_be64(env->psw.addr + env->int_svc= _ilen); - mask =3D be64_to_cpu(lowcore->svc_new_psw.mask); - addr =3D be64_to_cpu(lowcore->svc_new_psw.addr); - - cpu_unmap_lowcore(lowcore); - - load_psw(env, mask, addr); - - /* When a PER event is pending, the PER exception has to happen - immediately after the SERVICE CALL one. */ - if (env->per_perc_atmid) { - env->int_pgm_code =3D PGM_PER; - env->int_pgm_ilen =3D env->int_svc_ilen; - do_program_interrupt(env); - } -} - -#define VIRTIO_SUBCODE_64 0x0D00 - -static void do_ext_interrupt(CPUS390XState *env) -{ - S390CPU *cpu =3D s390_env_get_cpu(env); - uint64_t mask, addr; - LowCore *lowcore; - ExtQueue *q; - - if (!(env->psw.mask & PSW_MASK_EXT)) { - cpu_abort(CPU(cpu), "Ext int w/o ext mask\n"); - } - - if (env->ext_index < 0 || env->ext_index >=3D MAX_EXT_QUEUE) { - cpu_abort(CPU(cpu), "Ext queue overrun: %d\n", env->ext_index); - } - - q =3D &env->ext_queue[env->ext_index]; - lowcore =3D cpu_map_lowcore(env); - - lowcore->ext_int_code =3D cpu_to_be16(q->code); - lowcore->ext_params =3D cpu_to_be32(q->param); - lowcore->ext_params2 =3D cpu_to_be64(q->param64); - lowcore->external_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); - lowcore->external_old_psw.addr =3D cpu_to_be64(env->psw.addr); - lowcore->cpu_addr =3D cpu_to_be16(env->cpu_num | VIRTIO_SUBCODE_64); - mask =3D be64_to_cpu(lowcore->external_new_psw.mask); - addr =3D be64_to_cpu(lowcore->external_new_psw.addr); - - cpu_unmap_lowcore(lowcore); - - env->ext_index--; - if (env->ext_index =3D=3D -1) { - env->pending_int &=3D ~INTERRUPT_EXT; - } - - DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, - env->psw.mask, env->psw.addr); - - load_psw(env, mask, addr); -} - -static void do_io_interrupt(CPUS390XState *env) -{ - S390CPU *cpu =3D s390_env_get_cpu(env); - LowCore *lowcore; - IOIntQueue *q; - uint8_t isc; - int disable =3D 1; - int found =3D 0; - - if (!(env->psw.mask & PSW_MASK_IO)) { - cpu_abort(CPU(cpu), "I/O int w/o I/O mask\n"); - } - - for (isc =3D 0; isc < ARRAY_SIZE(env->io_index); isc++) { - uint64_t isc_bits; - - if (env->io_index[isc] < 0) { - continue; - } - if (env->io_index[isc] >=3D MAX_IO_QUEUE) { - cpu_abort(CPU(cpu), "I/O queue overrun for isc %d: %d\n", - isc, env->io_index[isc]); - } - - q =3D &env->io_queue[env->io_index[isc]][isc]; - isc_bits =3D ISC_TO_ISC_BITS(IO_INT_WORD_ISC(q->word)); - if (!(env->cregs[6] & isc_bits)) { - disable =3D 0; - continue; - } - if (!found) { - uint64_t mask, addr; - - found =3D 1; - lowcore =3D cpu_map_lowcore(env); - - lowcore->subchannel_id =3D cpu_to_be16(q->id); - lowcore->subchannel_nr =3D cpu_to_be16(q->nr); - lowcore->io_int_parm =3D cpu_to_be32(q->parm); - lowcore->io_int_word =3D cpu_to_be32(q->word); - lowcore->io_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); - lowcore->io_old_psw.addr =3D cpu_to_be64(env->psw.addr); - mask =3D be64_to_cpu(lowcore->io_new_psw.mask); - addr =3D be64_to_cpu(lowcore->io_new_psw.addr); - - cpu_unmap_lowcore(lowcore); - - env->io_index[isc]--; - - DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, - env->psw.mask, env->psw.addr); - load_psw(env, mask, addr); - } - if (env->io_index[isc] >=3D 0) { - disable =3D 0; - } - continue; - } - - if (disable) { - env->pending_int &=3D ~INTERRUPT_IO; - } - -} - -static void do_mchk_interrupt(CPUS390XState *env) -{ - S390CPU *cpu =3D s390_env_get_cpu(env); - uint64_t mask, addr; - LowCore *lowcore; - MchkQueue *q; - int i; - - if (!(env->psw.mask & PSW_MASK_MCHECK)) { - cpu_abort(CPU(cpu), "Machine check w/o mchk mask\n"); - } - - if (env->mchk_index < 0 || env->mchk_index >=3D MAX_MCHK_QUEUE) { - cpu_abort(CPU(cpu), "Mchk queue overrun: %d\n", env->mchk_index); - } - - q =3D &env->mchk_queue[env->mchk_index]; - - if (q->type !=3D 1) { - /* Don't know how to handle this... */ - cpu_abort(CPU(cpu), "Unknown machine check type %d\n", q->type); - } - if (!(env->cregs[14] & (1 << 28))) { - /* CRW machine checks disabled */ - return; - } - - lowcore =3D cpu_map_lowcore(env); - - for (i =3D 0; i < 16; i++) { - lowcore->floating_pt_save_area[i] =3D cpu_to_be64(get_freg(env, i)= ->ll); - lowcore->gpregs_save_area[i] =3D cpu_to_be64(env->regs[i]); - lowcore->access_regs_save_area[i] =3D cpu_to_be32(env->aregs[i]); - lowcore->cregs_save_area[i] =3D cpu_to_be64(env->cregs[i]); - } - lowcore->prefixreg_save_area =3D cpu_to_be32(env->psa); - lowcore->fpt_creg_save_area =3D cpu_to_be32(env->fpc); - lowcore->tod_progreg_save_area =3D cpu_to_be32(env->todpr); - lowcore->cpu_timer_save_area[0] =3D cpu_to_be32(env->cputm >> 32); - lowcore->cpu_timer_save_area[1] =3D cpu_to_be32((uint32_t)env->cputm); - lowcore->clock_comp_save_area[0] =3D cpu_to_be32(env->ckc >> 32); - lowcore->clock_comp_save_area[1] =3D cpu_to_be32((uint32_t)env->ckc); - - lowcore->mcck_interruption_code[0] =3D cpu_to_be32(0x00400f1d); - lowcore->mcck_interruption_code[1] =3D cpu_to_be32(0x40330000); - lowcore->mcck_old_psw.mask =3D cpu_to_be64(get_psw_mask(env)); - lowcore->mcck_old_psw.addr =3D cpu_to_be64(env->psw.addr); - mask =3D be64_to_cpu(lowcore->mcck_new_psw.mask); - addr =3D be64_to_cpu(lowcore->mcck_new_psw.addr); - - cpu_unmap_lowcore(lowcore); - - env->mchk_index--; - if (env->mchk_index =3D=3D -1) { - env->pending_int &=3D ~INTERRUPT_MCHK; - } - - DPRINTF("%s: %" PRIx64 " %" PRIx64 "\n", __func__, - env->psw.mask, env->psw.addr); - - load_psw(env, mask, addr); -} - -void s390_cpu_do_interrupt(CPUState *cs) -{ - S390CPU *cpu =3D S390_CPU(cs); - CPUS390XState *env =3D &cpu->env; - - qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=3D%" PRIx64 "\n", - __func__, cs->exception_index, env->psw.addr); - - s390_cpu_set_state(CPU_STATE_OPERATING, cpu); - /* handle machine checks */ - if ((env->psw.mask & PSW_MASK_MCHECK) && - (cs->exception_index =3D=3D -1)) { - if (env->pending_int & INTERRUPT_MCHK) { - cs->exception_index =3D EXCP_MCHK; - } - } - /* handle external interrupts */ - if ((env->psw.mask & PSW_MASK_EXT) && - cs->exception_index =3D=3D -1) { - if (env->pending_int & INTERRUPT_EXT) { - /* code is already in env */ - cs->exception_index =3D EXCP_EXT; - } else if (env->pending_int & INTERRUPT_TOD) { - cpu_inject_ext(cpu, 0x1004, 0, 0); - cs->exception_index =3D EXCP_EXT; - env->pending_int &=3D ~INTERRUPT_EXT; - env->pending_int &=3D ~INTERRUPT_TOD; - } else if (env->pending_int & INTERRUPT_CPUTIMER) { - cpu_inject_ext(cpu, 0x1005, 0, 0); - cs->exception_index =3D EXCP_EXT; - env->pending_int &=3D ~INTERRUPT_EXT; - env->pending_int &=3D ~INTERRUPT_TOD; - } - } - /* handle I/O interrupts */ - if ((env->psw.mask & PSW_MASK_IO) && - (cs->exception_index =3D=3D -1)) { - if (env->pending_int & INTERRUPT_IO) { - cs->exception_index =3D EXCP_IO; - } - } - - switch (cs->exception_index) { - case EXCP_PGM: - do_program_interrupt(env); - break; - case EXCP_SVC: - do_svc_interrupt(env); - break; - case EXCP_EXT: - do_ext_interrupt(env); - break; - case EXCP_IO: - do_io_interrupt(env); - break; - case EXCP_MCHK: - do_mchk_interrupt(env); - break; - } - cs->exception_index =3D -1; - - if (!env->pending_int) { - cs->interrupt_request &=3D ~CPU_INTERRUPT_HARD; - } -} - -bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request) -{ - if (interrupt_request & CPU_INTERRUPT_HARD) { - S390CPU *cpu =3D S390_CPU(cs); - CPUS390XState *env =3D &cpu->env; - - if (env->ex_value) { - /* Execution of the target insn is indivisible from - the parent EXECUTE insn. */ - return false; - } - if (env->psw.mask & PSW_MASK_EXT) { - s390_cpu_do_interrupt(cs); - return true; - } - } - return false; -} - void s390_cpu_recompute_watchpoints(CPUState *cs) { const int wp_flags =3D BP_CPU | BP_MEM_WRITE | BP_STOP_BEFORE_ACCESS; @@ -710,51 +291,6 @@ void s390_cpu_recompute_watchpoints(CPUState *cs) } } =20 -void s390x_cpu_debug_excp_handler(CPUState *cs) -{ - S390CPU *cpu =3D S390_CPU(cs); - CPUS390XState *env =3D &cpu->env; - CPUWatchpoint *wp_hit =3D cs->watchpoint_hit; - - if (wp_hit && wp_hit->flags & BP_CPU) { - /* FIXME: When the storage-alteration-space control bit is set, - the exception should only be triggered if the memory access - is done using an address space with the storage-alteration-event - bit set. We have no way to detect that with the current - watchpoint code. */ - cs->watchpoint_hit =3D NULL; - - env->per_address =3D env->psw.addr; - env->per_perc_atmid |=3D PER_CODE_EVENT_STORE | get_per_atmid(env); - /* FIXME: We currently no way to detect the address space used - to trigger the watchpoint. For now just consider it is the - current default ASC. This turn to be true except when MVCP - and MVCS instrutions are not used. */ - env->per_perc_atmid |=3D env->psw.mask & (PSW_MASK_ASC) >> 46; - - /* Remove all watchpoints to re-execute the code. A PER exception - will be triggered, it will call load_psw which will recompute - the watchpoints. */ - cpu_watchpoint_remove_all(cs, BP_CPU); - cpu_loop_exit_noexc(cs); - } -} - -/* Unaligned accesses are only diagnosed with MO_ALIGN. At the moment, - this is only for the atomic operations, for which we want to raise a - specification exception. */ -void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr, - MMUAccessType access_type, - int mmu_idx, uintptr_t retaddr) -{ - S390CPU *cpu =3D S390_CPU(cs); - CPUS390XState *env =3D &cpu->env; - - if (retaddr) { - cpu_restore_state(cs, retaddr); - } - program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); -} #endif /* CONFIG_USER_ONLY */ =20 void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprin= tf, --=20 1.8.3.1 From nobody Sat May 18 09:22:53 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1500886639629854.901247624532; Mon, 24 Jul 2017 01:57:19 -0700 (PDT) Received: from localhost ([::1]:53603 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZB0-0005Xm-6P for importer@patchew.org; Mon, 24 Jul 2017 04:57:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59063) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dZZ6t-0002P9-FT for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dZZ6s-0008M3-H9 for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42208) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dZZ6s-0008Lq-B1 for qemu-devel@nongnu.org; Mon, 24 Jul 2017 04:53:02 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 34FA2C04B328; Mon, 24 Jul 2017 08:53:01 +0000 (UTC) Received: from thh440s.str.redhat.com (reserved-198-123.str.redhat.com [10.33.198.123]) by smtp.corp.redhat.com (Postfix) with ESMTP id E759861F2F; Mon, 24 Jul 2017 08:52:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 34FA2C04B328 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=thuth@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 34FA2C04B328 From: Thomas Huth To: qemu-devel@nongnu.org, Richard Henderson Date: Mon, 24 Jul 2017 10:52:50 +0200 Message-Id: <1500886370-14572-6-git-send-email-thuth@redhat.com> In-Reply-To: <1500886370-14572-1-git-send-email-thuth@redhat.com> References: <1500886370-14572-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 24 Jul 2017 08:53:01 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v3 5/5] target/s390x: Add remaining switches to compile with --disable-tcg X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Christian Borntraeger , Cornelia Huck , Alexander Graf Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Adding some CONFIG_TCG tests to be finally able to compile QEMU on s390x also without TCG. Reviewed-by: Richard Henderson Signed-off-by: Thomas Huth --- target/s390x/Makefile.objs | 6 +++--- target/s390x/cpu.c | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs index cc2b4c9..f42cd1f 100644 --- a/target/s390x/Makefile.objs +++ b/target/s390x/Makefile.objs @@ -1,6 +1,6 @@ -obj-y +=3D translate.o helper.o cpu.o interrupt.o -obj-y +=3D int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o -obj-y +=3D gdbstub.o cpu_models.o cpu_features.o excp_helper.o +obj-y +=3D cpu.o cpu_models.o cpu_features.o gdbstub.o interrupt.o helper.o +obj-$(CONFIG_TCG) +=3D translate.o cc_helper.o excp_helper.o fpu_helper.o +obj-$(CONFIG_TCG) +=3D int_helper.o mem_helper.o misc_helper.o obj-$(CONFIG_SOFTMMU) +=3D machine.o ioinst.o arch_dump.o mmu_helper.o dia= g.o obj-$(CONFIG_KVM) +=3D kvm.o =20 diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index accef03..489bc25 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -417,7 +417,9 @@ static void s390_cpu_class_init(ObjectClass *oc, void *= data) cc->reset =3D s390_cpu_full_reset; cc->class_by_name =3D s390_cpu_class_by_name, cc->has_work =3D s390_cpu_has_work; +#ifdef CONFIG_TCG cc->do_interrupt =3D s390_cpu_do_interrupt; +#endif cc->dump_state =3D s390_cpu_dump_state; cc->set_pc =3D s390_cpu_set_pc; cc->gdb_read_register =3D s390_cpu_gdb_read_register; @@ -428,10 +430,12 @@ static void s390_cpu_class_init(ObjectClass *oc, void= *data) cc->get_phys_page_debug =3D s390_cpu_get_phys_page_debug; cc->vmsd =3D &vmstate_s390_cpu; cc->write_elf64_note =3D s390_cpu_write_elf64_note; +#ifdef CONFIG_TCG cc->cpu_exec_interrupt =3D s390_cpu_exec_interrupt; cc->debug_excp_handler =3D s390x_cpu_debug_excp_handler; cc->do_unaligned_access =3D s390x_cpu_do_unaligned_access; #endif +#endif cc->disas_set_info =3D s390_cpu_disas_set_info; =20 cc->gdb_num_core_regs =3D S390_NUM_CORE_REGS; --=20 1.8.3.1