From patchwork Wed Dec 11 19:10:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabiano Rosas X-Patchwork-Id: 11286075 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 46B3314BD for ; Wed, 11 Dec 2019 19:11:26 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 26301206A5 for ; Wed, 11 Dec 2019 19:11:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 26301206A5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:48126 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1if7OP-00014M-3Q for patchwork-qemu-devel@patchwork.kernel.org; Wed, 11 Dec 2019 14:11:25 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46032) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1if7NY-0008Jt-QO for qemu-devel@nongnu.org; Wed, 11 Dec 2019 14:10:33 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1if7NX-000220-LE for qemu-devel@nongnu.org; Wed, 11 Dec 2019 14:10:32 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:20972) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1if7NX-0001z4-D0; Wed, 11 Dec 2019 14:10:31 -0500 Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id xBBJ2Bm3052554; Wed, 11 Dec 2019 14:10:21 -0500 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 2wsu3r8sby-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 14:10:20 -0500 Received: from m0098399.ppops.net (m0098399.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.36/8.16.0.36) with SMTP id xBBJ40cE058368; Wed, 11 Dec 2019 14:10:20 -0500 Received: from ppma05wdc.us.ibm.com (1b.90.2fa9.ip4.static.sl-reverse.com [169.47.144.27]) by mx0a-001b2d01.pphosted.com with ESMTP id 2wsu3r8sb8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 14:10:20 -0500 Received: from pps.filterd (ppma05wdc.us.ibm.com [127.0.0.1]) by ppma05wdc.us.ibm.com (8.16.0.27/8.16.0.27) with SMTP id xBBIwAnT000910; Wed, 11 Dec 2019 19:10:19 GMT Received: from b03cxnp08026.gho.boulder.ibm.com (b03cxnp08026.gho.boulder.ibm.com [9.17.130.18]) by ppma05wdc.us.ibm.com with ESMTP id 2wtdq7akw1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 19:10:19 +0000 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id xBBJAIpn60621108 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 11 Dec 2019 19:10:18 GMT Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 14FD2C605B; Wed, 11 Dec 2019 19:10:18 +0000 (GMT) Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C7689C6069; Wed, 11 Dec 2019 19:10:16 +0000 (GMT) Received: from farosas.linux.ibm.com.br.ibm.com (unknown [9.86.27.131]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP; Wed, 11 Dec 2019 19:10:16 +0000 (GMT) From: Fabiano Rosas To: qemu-devel@nongnu.org Subject: [PATCH v5 1/3] linux-headers: Update kvm.h for ppc single step capability Date: Wed, 11 Dec 2019 16:10:11 -0300 Message-Id: <20191211191013.454125-2-farosas@linux.ibm.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191211191013.454125-1-farosas@linux.ibm.com> References: <20191211191013.454125-1-farosas@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.95,18.0.572 definitions=2019-12-11_05:2019-12-11,2019-12-11 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 clxscore=1015 bulkscore=0 spamscore=0 lowpriorityscore=0 adultscore=0 impostorscore=0 mlxlogscore=999 mlxscore=0 suspectscore=1 malwarescore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-1910280000 definitions=main-1912110156 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.156.1 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Paolo Bonzini , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Fabiano Rosas --- linux-headers/linux/kvm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 3d9b18f7f8..488f3baf01 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -1000,6 +1000,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PMU_EVENT_FILTER 173 #define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174 #define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175 +#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176 #ifdef KVM_CAP_IRQ_ROUTING From patchwork Wed Dec 11 19:10:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabiano Rosas X-Patchwork-Id: 11286113 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2B5A514BD for ; Wed, 11 Dec 2019 19:13:04 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 09D73206A5 for ; Wed, 11 Dec 2019 19:13:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 09D73206A5 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:48148 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1if7Py-00039A-Li for patchwork-qemu-devel@patchwork.kernel.org; Wed, 11 Dec 2019 14:13:02 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46103) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1if7NZ-0008Jv-3O for qemu-devel@nongnu.org; Wed, 11 Dec 2019 14:10:34 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1if7NX-00021b-GO for qemu-devel@nongnu.org; Wed, 11 Dec 2019 14:10:32 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:31582 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1if7NX-0001yp-Aw; Wed, 11 Dec 2019 14:10:31 -0500 Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id xBBJ1lRe059661; Wed, 11 Dec 2019 14:10:22 -0500 Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 2wsqc2mevc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 14:10:22 -0500 Received: from m0098413.ppops.net (m0098413.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.36/8.16.0.36) with SMTP id xBBJ3dsQ064832; Wed, 11 Dec 2019 14:10:21 -0500 Received: from ppma05wdc.us.ibm.com (1b.90.2fa9.ip4.static.sl-reverse.com [169.47.144.27]) by mx0b-001b2d01.pphosted.com with ESMTP id 2wsqc2mev3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 14:10:21 -0500 Received: from pps.filterd (ppma05wdc.us.ibm.com [127.0.0.1]) by ppma05wdc.us.ibm.com (8.16.0.27/8.16.0.27) with SMTP id xBBIwAnZ000910; Wed, 11 Dec 2019 19:10:21 GMT Received: from b03cxnp08027.gho.boulder.ibm.com (b03cxnp08027.gho.boulder.ibm.com [9.17.130.19]) by ppma05wdc.us.ibm.com with ESMTP id 2wtdq7akwc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 19:10:21 +0000 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp08027.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id xBBJAKPq60490076 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 11 Dec 2019 19:10:20 GMT Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CD6ECC605B; Wed, 11 Dec 2019 19:10:19 +0000 (GMT) Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 82172C606E; Wed, 11 Dec 2019 19:10:18 +0000 (GMT) Received: from farosas.linux.ibm.com.br.ibm.com (unknown [9.86.27.131]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP; Wed, 11 Dec 2019 19:10:18 +0000 (GMT) From: Fabiano Rosas To: qemu-devel@nongnu.org Subject: [PATCH v5 2/3] kvm-all: Introduce kvm_set_singlestep Date: Wed, 11 Dec 2019 16:10:12 -0300 Message-Id: <20191211191013.454125-3-farosas@linux.ibm.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191211191013.454125-1-farosas@linux.ibm.com> References: <20191211191013.454125-1-farosas@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.95,18.0.572 definitions=2019-12-11_05:2019-12-11,2019-12-11 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 adultscore=0 malwarescore=0 suspectscore=1 clxscore=1015 mlxscore=0 phishscore=0 priorityscore=1501 mlxlogscore=999 spamscore=0 lowpriorityscore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-1910280000 definitions=main-1912110156 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.158.5 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Paolo Bonzini , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" For single stepping (via KVM) of a guest vcpu to work, KVM needs not only to support the SET_GUEST_DEBUG ioctl but to also recognize the KVM_GUESTDBG_SINGLESTEP bit in the control field of the kvm_guest_debug struct. This patch adds support for querying the single step capability so that QEMU can decide what to do for the platforms that do not have such support. This will allow architecture-specific implementations of a fallback mechanism for single stepping in cases where KVM does not support it. Signed-off-by: Fabiano Rosas --- accel/kvm/kvm-all.c | 14 ++++++++++++++ accel/stubs/kvm-stub.c | 4 ++++ exec.c | 2 +- include/sysemu/kvm.h | 4 ++++ stubs/Makefile.objs | 1 + stubs/kvm-arch-singlestep.c | 14 ++++++++++++++ target/ppc/kvm.c | 14 ++++++++++++++ 7 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 stubs/kvm-arch-singlestep.c diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index ca00daa2f5..a61beb0b53 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2599,6 +2599,11 @@ bool kvm_arm_supports_user_irq(void) } #ifdef KVM_CAP_SET_GUEST_DEBUG +bool kvm_has_guest_debug_singlestep(CPUState *cs) +{ + return kvm_arch_has_guest_debug_singlestep(cs); +} + struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, target_ulong pc) { @@ -2647,6 +2652,15 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) return data.err; } +void kvm_set_singlestep(CPUState *cs, int enabled) +{ + if (kvm_has_guest_debug_singlestep(cs)) { + kvm_update_guest_debug(cs, 0); + } else { + kvm_arch_set_singlestep(cs, enabled); + } +} + int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr, target_ulong len, int type) { diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index 82f118d2df..b4df48b6f1 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -78,6 +78,10 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) return -ENOSYS; } +void kvm_set_singlestep(CPUState *cs, int enabled) +{ +} + int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr, target_ulong len, int type) { diff --git a/exec.c b/exec.c index ffdb518535..ff46ea1846 100644 --- a/exec.c +++ b/exec.c @@ -1202,7 +1202,7 @@ void cpu_single_step(CPUState *cpu, int enabled) if (cpu->singlestep_enabled != enabled) { cpu->singlestep_enabled = enabled; if (kvm_enabled()) { - kvm_update_guest_debug(cpu, 0); + kvm_set_singlestep(cpu, enabled); } else { /* must flush all the translated code to avoid inconsistencies */ /* XXX: only flush what is necessary */ diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 9fe233b9bf..7a42978b11 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -215,6 +215,7 @@ int kvm_has_pit_state2(void); int kvm_has_many_ioeventfds(void); int kvm_has_gsi_routing(void); int kvm_has_intx_set_mask(void); +bool kvm_has_guest_debug_singlestep(CPUState *cs); int kvm_init_vcpu(CPUState *cpu); int kvm_cpu_exec(CPUState *cpu); @@ -247,6 +248,8 @@ bool kvm_memcrypt_enabled(void); */ int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len); +bool kvm_arch_has_guest_debug_singlestep(CPUState *cs); +void kvm_arch_set_singlestep(CPUState *cpu, int enabled); #ifdef NEED_CPU_H #include "cpu.h" @@ -259,6 +262,7 @@ int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr, target_ulong len, int type); void kvm_remove_all_breakpoints(CPUState *cpu); int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap); +void kvm_set_singlestep(CPUState *cs, int enabled); int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr); int kvm_on_sigbus(int code, void *addr); diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 4a50e95ec3..361f4088fa 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -12,6 +12,7 @@ stub-obj-y += get-vm-name.o stub-obj-y += iothread.o stub-obj-y += iothread-lock.o stub-obj-y += is-daemonized.o +stub-obj-y += kvm-arch-singlestep.o stub-obj-$(CONFIG_LINUX_AIO) += linux-aio.o stub-obj-y += machine-init-done.o stub-obj-y += migr-blocker.o diff --git a/stubs/kvm-arch-singlestep.c b/stubs/kvm-arch-singlestep.c new file mode 100644 index 0000000000..18bfba61f6 --- /dev/null +++ b/stubs/kvm-arch-singlestep.c @@ -0,0 +1,14 @@ +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "sysemu/kvm.h" + +bool kvm_arch_has_guest_debug_singlestep(CPUState *cs) +{ + /* for backwards compatibility assume the feature is present */ + return true; +} + +void kvm_arch_set_singlestep(CPUState *cpu, int enabled) +{ + warn_report("KVM does not support single stepping"); +} diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index c77f9848ec..3a2cfe883c 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -85,6 +85,7 @@ static int cap_ppc_safe_indirect_branch; static int cap_ppc_count_cache_flush_assist; static int cap_ppc_nested_kvm_hv; static int cap_large_decr; +static int cap_ppc_singlestep; static uint32_t debug_inst_opcode; @@ -133,6 +134,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) kvmppc_get_cpu_characteristics(s); cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV); cap_large_decr = kvmppc_get_dec_bits(); + cap_ppc_singlestep = kvm_vm_check_extension(s, KVM_CAP_PPC_GUEST_DEBUG_SSTEP); /* * Note: setting it to false because there is not such capability * in KVM at this moment. @@ -1380,6 +1382,18 @@ static int kvmppc_handle_dcr_write(CPUPPCState *env, return 0; } +bool kvm_arch_has_guest_debug_singlestep(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + if (cap_ppc_singlestep) { + return true; + } + + return env->excp_model == POWERPC_EXCP_BOOKE || kvmppc_is_pr(kvm_state); +} + int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) { /* Mixed endian case is not handled */ From patchwork Wed Dec 11 19:10:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabiano Rosas X-Patchwork-Id: 11286119 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0203614BD for ; Wed, 11 Dec 2019 19:13:18 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C5A59206C3 for ; Wed, 11 Dec 2019 19:13:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C5A59206C3 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:48150 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1if7QC-0003UH-Kp for patchwork-qemu-devel@patchwork.kernel.org; Wed, 11 Dec 2019 14:13:16 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:46205) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1if7NZ-0008Jz-O7 for qemu-devel@nongnu.org; Wed, 11 Dec 2019 14:10:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1if7NX-00022E-OJ for qemu-devel@nongnu.org; Wed, 11 Dec 2019 14:10:33 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:19898) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1if7NX-00020e-IQ; Wed, 11 Dec 2019 14:10:31 -0500 Received: from pps.filterd (m0127361.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id xBBJ0Pge104760; Wed, 11 Dec 2019 14:10:28 -0500 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 2wtf6yqfxs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 14:10:26 -0500 Received: from m0127361.ppops.net (m0127361.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.36/8.16.0.36) with SMTP id xBBJ0Ro1104841; Wed, 11 Dec 2019 14:10:24 -0500 Received: from ppma03dal.us.ibm.com (b.bd.3ea9.ip4.static.sl-reverse.com [169.62.189.11]) by mx0a-001b2d01.pphosted.com with ESMTP id 2wtf6yqfwf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 14:10:24 -0500 Received: from pps.filterd (ppma03dal.us.ibm.com [127.0.0.1]) by ppma03dal.us.ibm.com (8.16.0.27/8.16.0.27) with SMTP id xBBJ19HC010412; Wed, 11 Dec 2019 19:10:23 GMT Received: from b03cxnp07029.gho.boulder.ibm.com (b03cxnp07029.gho.boulder.ibm.com [9.17.130.16]) by ppma03dal.us.ibm.com with ESMTP id 2wr3q7s8gr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 11 Dec 2019 19:10:23 +0000 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp07029.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id xBBJALtg32244204 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 11 Dec 2019 19:10:21 GMT Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A22DEC605D; Wed, 11 Dec 2019 19:10:21 +0000 (GMT) Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 42D84C6069; Wed, 11 Dec 2019 19:10:20 +0000 (GMT) Received: from farosas.linux.ibm.com.br.ibm.com (unknown [9.86.27.131]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP; Wed, 11 Dec 2019 19:10:20 +0000 (GMT) From: Fabiano Rosas To: qemu-devel@nongnu.org Subject: [PATCH v5 3/3] target/ppc: support single stepping with KVM HV Date: Wed, 11 Dec 2019 16:10:13 -0300 Message-Id: <20191211191013.454125-4-farosas@linux.ibm.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191211191013.454125-1-farosas@linux.ibm.com> References: <20191211191013.454125-1-farosas@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.95,18.0.572 definitions=2019-12-11_05:2019-12-11,2019-12-11 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 priorityscore=1501 adultscore=0 clxscore=1015 malwarescore=0 suspectscore=1 impostorscore=0 bulkscore=0 phishscore=0 spamscore=0 mlxscore=0 mlxlogscore=557 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-1910280000 definitions=main-1912110156 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.158.5 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Paolo Bonzini , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" The hardware singlestep mechanism in POWER works via a Trace Interrupt (0xd00) that happens after any instruction executes, whenever MSR_SE = 1 (PowerISA Section 6.5.15 - Trace Interrupt). However, with kvm_hv, the Trace Interrupt happens inside the guest and KVM has no visibility of it. Therefore, when the gdbstub uses the KVM_SET_GUEST_DEBUG ioctl to enable singlestep, KVM simply ignores it. This patch takes advantage of the Trace Interrupt to perform the step inside the guest, but uses a breakpoint at the Trace Interrupt handler to return control to KVM. The exit is treated by KVM as a regular breakpoint and it returns to the host (and QEMU eventually). Before signalling GDB, QEMU sets the Next Instruction Pointer to the instruction following the one being stepped and restores the MSR, SRR0, SRR1 values from before the step, effectively skipping the interrupt handler execution and hiding the trace interrupt breakpoint from GDB. This approach works with both of GDB's 'scheduler-locking' options (off, step). Note: - kvm_arch_set_singlestep happens after GDB asks for a single step, while the vcpus are stopped. - kvm_handle_singlestep executes after the step, during the handling of the Emulation Assist Interrupt (breakpoint). Signed-off-by: Fabiano Rosas --- target/ppc/cpu.h | 16 ++++ target/ppc/excp_helper.c | 13 +++ target/ppc/gdbstub.c | 35 +++++++ target/ppc/kvm.c | 195 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 252 insertions(+), 7 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index e3e82327b7..37119cd0b4 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1156,6 +1156,11 @@ struct CPUPPCState { uint32_t tm_vscr; uint64_t tm_dscr; uint64_t tm_tar; + + /* Used for software single step */ + target_ulong sstep_msr; + target_ulong sstep_srr0; + target_ulong sstep_srr1; }; #define SET_FIT_PERIOD(a_, b_, c_, d_) \ @@ -1253,6 +1258,7 @@ struct PPCVirtualHypervisorClass { OBJECT_GET_CLASS(PPCVirtualHypervisorClass, (obj), \ TYPE_PPC_VIRTUAL_HYPERVISOR) +target_ulong ppc_get_trace_int_handler_addr(CPUState *cs); void ppc_cpu_do_interrupt(CPUState *cpu); bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req); void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags); @@ -1266,6 +1272,12 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cpu, uint8_t *buf, int reg); void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu); const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name); #endif +uint32_t ppc_gdb_read_insn(CPUState *cs, target_ulong addr); +uint32_t ppc_gdb_get_op(uint32_t insn); +uint32_t ppc_gdb_get_xop(uint32_t insn); +uint32_t ppc_gdb_get_spr(uint32_t insn); +uint32_t ppc_gdb_get_rt(uint32_t insn); + int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque); int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, @@ -2217,6 +2229,10 @@ enum { PPC2_ISA300) }; +#define XOP_RFID 18 +#define XOP_MFMSR 83 +#define XOP_MTSPR 467 + /*****************************************************************************/ /* * Memory access type : diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 50b004d00d..8ce395004a 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -112,6 +112,8 @@ static uint64_t ppc_excp_vector_offset(CPUState *cs, int ail) uint64_t offset = 0; switch (ail) { + case AIL_NONE: + break; case AIL_0001_8000: offset = 0x18000; break; @@ -782,6 +784,17 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) check_tlb_flush(env, false); } +target_ulong ppc_get_trace_int_handler_addr(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + int ail; + + ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; + return env->excp_vectors[POWERPC_EXCP_TRACE] | + ppc_excp_vector_offset(cs, ail); +} + void ppc_cpu_do_interrupt(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c index 823759c92e..540b767445 100644 --- a/target/ppc/gdbstub.c +++ b/target/ppc/gdbstub.c @@ -383,3 +383,38 @@ const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name) return NULL; } #endif + +uint32_t ppc_gdb_read_insn(CPUState *cs, target_ulong addr) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + uint32_t insn; + + cpu_memory_rw_debug(cs, addr, (uint8_t *)&insn, sizeof(insn), 0); + + if (msr_le) { + return ldl_le_p(&insn); + } else { + return ldl_be_p(&insn); + } +} + +uint32_t ppc_gdb_get_op(uint32_t insn) +{ + return extract32(insn, 26, 6); +} + +uint32_t ppc_gdb_get_xop(uint32_t insn) +{ + return extract32(insn, 1, 10); +} + +uint32_t ppc_gdb_get_spr(uint32_t insn) +{ + return extract32(insn, 11, 5) << 5 | extract32(insn, 16, 5); +} + +uint32_t ppc_gdb_get_rt(uint32_t insn) +{ + return extract32(insn, 21, 5); +} diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index 3a2cfe883c..fedb8e787d 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -1542,6 +1542,86 @@ void kvm_arch_remove_all_hw_breakpoints(void) nb_hw_breakpoint = nb_hw_watchpoint = 0; } +void kvm_arch_set_singlestep(CPUState *cs, int enabled) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + target_ulong trace_handler_addr; + uint32_t insn; + bool rfid; + + if (!enabled) { + return; + } + + cpu_synchronize_state(cs); + insn = ppc_gdb_read_insn(cs, env->nip); + + /* + * rfid needs special handling because it: + * - overwrites NIP with SRR0; + * - overwrites MSR with SRR1; + * - cannot be single stepped. + */ + rfid = ppc_gdb_get_op(insn) == 19 && ppc_gdb_get_xop(insn) == XOP_RFID; + + if (rfid && kvm_find_sw_breakpoint(cs, env->spr[SPR_SRR0])) { + /* + * There is a breakpoint at the next instruction address. It + * will already cause the vm exit we need for the single step, + * so there's nothing to be done. + */ + return; + } + + /* + * Save the registers that will be affected by the single step + * mechanism. These will be restored after the step at + * kvm_handle_singlestep. + */ + env->sstep_msr = env->msr; + env->sstep_srr0 = env->spr[SPR_SRR0]; + env->sstep_srr1 = env->spr[SPR_SRR1]; + + /* + * MSR_SE = 1 will cause a Trace Interrupt in the guest after the + * next instruction executes. If this is a rfid, use SRR1 instead + * of MSR. + */ + if (rfid) { + if ((env->spr[SPR_SRR1] >> MSR_SE) & 1) { + /* + * The guest is doing a single step itself. Make sure we + * restore it later. + */ + env->sstep_msr |= (1ULL << MSR_SE); + } + + env->spr[SPR_SRR1] |= (1ULL << MSR_SE); + } else { + env->msr |= (1ULL << MSR_SE); + } + + /* + * We set a breakpoint at the interrupt handler address so + * that the singlestep will be seen by KVM (this is treated by + * KVM like an ordinary breakpoint) and control is returned to + * QEMU. + */ + trace_handler_addr = ppc_get_trace_int_handler_addr(cs); + + if (env->nip == trace_handler_addr) { + /* + * We are trying to step over the interrupt handler + * address itself; move the breakpoint to the next + * instruction. + */ + trace_handler_addr += 4; + } + + kvm_insert_breakpoint(cs, trace_handler_addr, 4, GDB_BREAKPOINT_SW); +} + void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) { int n; @@ -1581,6 +1661,91 @@ void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) } } +/* Revert any side-effects caused during single step */ +static void restore_singlestep_env(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + uint32_t insn; + int reg; + int spr; + + insn = ppc_gdb_read_insn(cs, env->spr[SPR_SRR0] - 4); + + env->spr[SPR_SRR0] = env->sstep_srr0; + env->spr[SPR_SRR1] = env->sstep_srr1; + + if (ppc_gdb_get_op(insn) != 31) { + return; + } + + reg = ppc_gdb_get_rt(insn); + + switch (ppc_gdb_get_xop(insn)) { + case XOP_MTSPR: + /* + * mtspr: the guest altered the SRR, so do not use the + * pre-step value. + */ + spr = ppc_gdb_get_spr(insn); + if (spr == SPR_SRR0 || spr == SPR_SRR1) { + env->spr[spr] = env->gpr[reg]; + } + break; + case XOP_MFMSR: + /* + * mfmsr: clear MSR_SE bit to avoid the guest knowing + * that it is being single-stepped. + */ + env->gpr[reg] &= ~(1ULL << MSR_SE); + break; + } +} + +static int kvm_handle_singlestep(CPUState *cs, target_ulong address) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + target_ulong trace_handler_addr; + + if (cap_ppc_singlestep) { + return 1; + } + + cpu_synchronize_state(cs); + trace_handler_addr = ppc_get_trace_int_handler_addr(cs); + + if (address == trace_handler_addr) { + kvm_remove_breakpoint(cs, trace_handler_addr, 4, GDB_BREAKPOINT_SW); + + if (env->sstep_msr & (1ULL << MSR_SE)) { + /* + * The guest expects the last instruction to have caused a + * single step, go back into the interrupt handler. + */ + return 1; + } + + env->nip = env->spr[SPR_SRR0]; + /* Bits 33-36, 43-47 are set by the interrupt */ + env->msr = env->spr[SPR_SRR1] & ~(1ULL << MSR_SE | + PPC_BITMASK(33, 36) | + PPC_BITMASK(43, 47)); + restore_singlestep_env(cs); + + } else if (address == trace_handler_addr + 4) { + /* + * A step at trace_handler_addr would interfere with the + * singlestep mechanism itself, so we have previously + * displaced the breakpoint to the next instruction. + */ + kvm_remove_breakpoint(cs, trace_handler_addr + 4, 4, GDB_BREAKPOINT_SW); + restore_singlestep_env(cs); + } + + return 1; +} + static int kvm_handle_hw_breakpoint(CPUState *cs, struct kvm_debug_exit_arch *arch_info) { @@ -1608,13 +1773,29 @@ static int kvm_handle_hw_breakpoint(CPUState *cs, return handle; } -static int kvm_handle_singlestep(void) +static int kvm_handle_sw_breakpoint(CPUState *cs, target_ulong address) { - return 1; -} + target_ulong trace_handler_addr; -static int kvm_handle_sw_breakpoint(void) -{ + if (cap_ppc_singlestep) { + return 1; + } + + cpu_synchronize_state(cs); + trace_handler_addr = ppc_get_trace_int_handler_addr(cs); + + if (address == trace_handler_addr) { + CPU_FOREACH(cs) { + if (cs->singlestep_enabled) { + /* + * We hit this breakpoint while another cpu is doing a + * software single step. Go back into the guest to + * give chance for the single step to finish. + */ + return 0; + } + } + } return 1; } @@ -1625,7 +1806,7 @@ static int kvm_handle_debug(PowerPCCPU *cpu, struct kvm_run *run) struct kvm_debug_exit_arch *arch_info = &run->debug.arch; if (cs->singlestep_enabled) { - return kvm_handle_singlestep(); + return kvm_handle_singlestep(cs, arch_info->address); } if (arch_info->status) { @@ -1633,7 +1814,7 @@ static int kvm_handle_debug(PowerPCCPU *cpu, struct kvm_run *run) } if (kvm_find_sw_breakpoint(cs, arch_info->address)) { - return kvm_handle_sw_breakpoint(); + return kvm_handle_sw_breakpoint(cs, arch_info->address); } /*