From patchwork Fri Jul 21 14:45:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 9857083 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7D342601C0 for ; Fri, 21 Jul 2017 14:47:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6474E287EB for ; Fri, 21 Jul 2017 14:47:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 597F3287ED; Fri, 21 Jul 2017 14:47:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9069E287EB for ; Fri, 21 Jul 2017 14:47:35 +0000 (UTC) Received: from localhost ([::1]:43557 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dYZDK-0005p2-QW for patchwork-qemu-devel@patchwork.kernel.org; Fri, 21 Jul 2017 10:47:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40222) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dYZC1-0005me-KE for qemu-devel@nongnu.org; Fri, 21 Jul 2017 10:46:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dYZC0-0002J2-3f for qemu-devel@nongnu.org; Fri, 21 Jul 2017 10:46:13 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36914) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dYZBz-0002IR-QB for qemu-devel@nongnu.org; Fri, 21 Jul 2017 10:46:12 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B0306A9627; Fri, 21 Jul 2017 14:46:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com B0306A9627 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=thuth@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com B0306A9627 Received: from thh440s.redhat.com (ovpn-117-121.ams2.redhat.com [10.36.117.121]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9F7C974AAF; Fri, 21 Jul 2017 14:46:07 +0000 (UTC) From: Thomas Huth To: qemu-devel@nongnu.org, Richard Henderson Date: Fri, 21 Jul 2017 16:45:56 +0200 Message-Id: <1500648359-25931-3-git-send-email-thuth@redhat.com> In-Reply-To: <1500648359-25931-1-git-send-email-thuth@redhat.com> References: <1500648359-25931-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 21 Jul 2017 14:46:10 +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 v2 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 += translate.o helper.o cpu.o interrupt.o obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-y += gdbstub.o cpu_models.o cpu_features.o -obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o +obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o diag.o obj-$(CONFIG_KVM) += kvm.o # 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 = 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 = 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 = env->regs[r1]; + uint64_t timeout = env->regs[r1 + 1]; + uint64_t action = env->regs[r3]; + Object *obj; + DIAG288State *diag288; + DIAG288Class *diag288_class; + + if (r1 % 2 || action != 0) { + return -1; + } + + /* Timeout must be more than 15 seconds except for timer deletion */ + if (func != WDT_DIAG288_CANCEL && timeout < 15) { + return -1; + } + + obj = object_resolve_path_type("", TYPE_WDT_DIAG288, NULL); + if (!obj) { + return -1; + } + + diag288 = DIAG288(obj); + diag288_class = 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 = env->regs[r1]; + uint64_t subcode = 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 = g_malloc0(sizeof(IplParameterBlock)); + cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); + if (!iplb_valid_len(iplb)) { + env->regs[r1 + 1] = 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] = DIAG_308_RC_INVALID; + goto out; + } + + s390_ipl_update_diag308(iplb); + env->regs[r1 + 1] = 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 = s390_ipl_get_iplb(); + if (iplb) { + cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); + env->regs[r1 + 1] = DIAG_308_RC_OK; + } else { + env->regs[r1 + 1] = 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" #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 /* #define DEBUG_HELPER */ @@ -116,166 +109,6 @@ uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2) return r; } -#ifndef CONFIG_USER_ONLY -static int modified_clear_reset(S390CPU *cpu) -{ - S390CPUClass *scc = 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 = 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 = env->regs[r1]; - uint64_t timeout = env->regs[r1 + 1]; - uint64_t action = env->regs[r3]; - Object *obj; - DIAG288State *diag288; - DIAG288Class *diag288_class; - - if (r1 % 2 || action != 0) { - return -1; - } - - /* Timeout must be more than 15 seconds except for timer deletion */ - if (func != WDT_DIAG288_CANCEL && timeout < 15) { - return -1; - } - - obj = object_resolve_path_type("", TYPE_WDT_DIAG288, NULL); - if (!obj) { - return -1; - } - - diag288 = DIAG288(obj); - diag288_class = 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 = env->regs[r1]; - uint64_t subcode = 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 = g_malloc0(sizeof(IplParameterBlock)); - cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); - if (!iplb_valid_len(iplb)) { - env->regs[r1 + 1] = 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] = DIAG_308_RC_INVALID; - goto out; - } - - s390_ipl_update_diag308(iplb); - env->regs[r1 + 1] = 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 = s390_ipl_get_iplb(); - if (iplb) { - cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); - env->regs[r1 + 1] = DIAG_308_RC_OK; - } else { - env->regs[r1 + 1] = 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 num) { uint64_t r;