From patchwork Thu Nov 12 16:20:47 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alex_Benn=C3=A9e?= X-Patchwork-Id: 56437 Delivered-To: patch@linaro.org Received: by 10.112.155.196 with SMTP id vy4csp510835lbb; Thu, 12 Nov 2015 08:24:04 -0800 (PST) X-Received: by 10.66.90.165 with SMTP id bx5mr23982466pab.25.1447345443868; Thu, 12 Nov 2015 08:24:03 -0800 (PST) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id pn2si20870148pac.121.2015.11.12.08.24.03 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Nov 2015 08:24:03 -0800 (PST) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) client-ip=2001:1868:205::9; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) smtp.mailfrom=linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org; dkim=neutral (body hash did not verify) header.i=@linaro_org.20150623.gappssmtp.com Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Zwuds-0006Zj-2u; Thu, 12 Nov 2015 16:22:32 +0000 Received: from mail-wm0-x233.google.com ([2a00:1450:400c:c09::233]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Zwucy-0005z0-Kk for linux-arm-kernel@lists.infradead.org; Thu, 12 Nov 2015 16:21:39 +0000 Received: by wmec201 with SMTP id c201so99417168wme.1 for ; Thu, 12 Nov 2015 08:21:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro_org.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=AbKaVfsO/gGU14sITi9GuwPq1U53QSuxH3dv6ib3VBk=; b=zyjTwjenV7D8td6Gla9GxDhQbzGLdbHDluCcCOmJJPmj0TD1qptDSc1M4MIMWMZ0+T ekCOQYIfoLUeOIVoYnHzljWph4dwknmuKhTcwTNzTqpwwPOAu/zoPoz77EXb5umAa4Li 6gJCoOavYfYScMI4pw3C5PdeQT8lPBBLEi6gVWpferty5mznBcwDfdTEW6WdLNqCgkIp m9K/goWbFIgwDtmaHrHXUCf4XpxgJ+oSgDWOjH83sdHXj9TOJMdoAfiTZvKvE2Vb5osn q1CITgGu8DR13HS1ANzVy7yYvpgYDRf3TS7CvPoyPTRBEQ7H7eCLSuY0CMJjy2rQ5S2K Epiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; bh=AbKaVfsO/gGU14sITi9GuwPq1U53QSuxH3dv6ib3VBk=; b=bxNIBrntQTeVRcazXrXuZZWYyT2NN7pL8cOjxVK7TwZ2bcjRY0NBwUAWxO7q51cW1W Py3WR6ntGdKVMVmGhDAwXitIit9Xcs4CU22/e5eomSR5ABDxo7aRefkOMZKCblO24e4W QIOo2yc23cyY6xW61u0NISFAgjfDUyLYmsRXfMOItxmRpEB3yaTU9wDAOVgZI91y/3fm GgMNuUZtsCLQ/jhav8ZfRJKXKqGYbFeLsfAffs28tPfTj9OSVVUdjxcOZrmTEU7kXi41 lmB8dbImhQ2rJXDIY8uMKEn1UzI61aLaqLp/2GieDqK10NSEdMbpkFHao0pfEEWTfLRr ajlw== X-Gm-Message-State: ALoCoQmBRHD46OnXYwP7P/9KDLGfM4NjiYwjgzJLYAhVeLwx9sYkl+t4Ryg2LL1rLHpjrqIGZ7xt X-Received: by 10.28.214.146 with SMTP id n140mr17981023wmg.47.1447345275117; Thu, 12 Nov 2015 08:21:15 -0800 (PST) Received: from zen.linaro.local ([81.128.185.34]) by smtp.gmail.com with ESMTPSA id 77sm15789745wml.20.2015.11.12.08.21.13 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Nov 2015 08:21:13 -0800 (PST) Received: from zen.linaroharston (localhost [127.0.0.1]) by zen.linaro.local (Postfix) with ESMTP id 9F4FF3E050D; Thu, 12 Nov 2015 16:21:12 +0000 (GMT) From: =?UTF-8?q?Alex=20Benn=C3=A9e?= To: qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, christoffer.dall@linaro.org, zhichao.huang@linaro.org Subject: [PATCH v9 2/6] target-arm: kvm - implement software breakpoints Date: Thu, 12 Nov 2015 16:20:47 +0000 Message-Id: <1447345251-22625-3-git-send-email-alex.bennee@linaro.org> X-Mailer: git-send-email 2.6.3 In-Reply-To: <1447345251-22625-1-git-send-email-alex.bennee@linaro.org> References: <1447345251-22625-1-git-send-email-alex.bennee@linaro.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151112_082137_187898_6CAD2E91 X-CRM114-Status: GOOD ( 19.56 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2a00:1450:400c:c09:0:0:0:233 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, marc.zyngier@arm.com, Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org These don't involve messing around with debug registers, just setting the breakpoint instruction in memory. GDB will not use this mechanism if it can't access the memory to write the breakpoint. All the kernel has to do is ensure the hypervisor traps the breakpoint exceptions and returns to userspace. Signed-off-by: Alex Bennée --- v2 - handle debug exit with new hsr exception info - add verbosity to UNIMP message v3 - sync with kvm_cpu_synchronize_state() before checking PC. - use internals.h defines - use env->pc - use proper format types v9 - add include for error_report - define a brk_insn constant --- target-arm/kvm.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 12 deletions(-) diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 79ef4c6..50f70ef 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -17,6 +17,7 @@ #include "qemu-common.h" #include "qemu/timer.h" +#include "qemu/error-report.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "kvm_arm.h" @@ -516,9 +517,60 @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) return MEMTXATTRS_UNSPECIFIED; } +/* See v8 ARM ARM D7.2.27 ESR_ELx, Exception Syndrome Register + * + * To minimise translating between kernel and user-space the kernel + * ABI just provides user-space with the full exception syndrome + * register value to be decoded in QEMU. + */ + +static int kvm_handle_debug(CPUState *cs, struct kvm_run *run) +{ + struct kvm_debug_exit_arch *arch_info = &run->debug.arch; + int hsr_ec = arch_info->hsr >> ARM_EL_EC_SHIFT; + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + /* Ensure PC is synchronised */ + kvm_cpu_synchronize_state(cs); + + switch (hsr_ec) { + case EC_AA64_BKPT: + if (kvm_find_sw_breakpoint(cs, env->pc)) { + return true; + } + break; + default: + error_report("%s: unhandled debug exit (%"PRIx32", %"PRIx64")\n", + __func__, arch_info->hsr, env->pc); + } + + /* If we don't handle this it could be it really is for the + guest to handle */ + qemu_log_mask(LOG_UNIMP, + "%s: re-injecting exception not yet implemented" + " (0x%"PRIx32", %"PRIx64")\n", + __func__, hsr_ec, env->pc); + + return false; +} + int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { - return 0; + int ret = 0; + + switch (run->exit_reason) { + case KVM_EXIT_DEBUG: + if (kvm_handle_debug(cs, run)) { + ret = EXCP_DEBUG; + } /* otherwise return to guest */ + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", + __func__, run->exit_reason); + break; + } + return ret; } bool kvm_arch_stop_on_emulation_error(CPUState *cs) @@ -543,14 +595,34 @@ int kvm_arch_on_sigbus(int code, void *addr) void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) { - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); + if (kvm_sw_breakpoints_active(cs)) { + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; + } } -int kvm_arch_insert_sw_breakpoint(CPUState *cs, - struct kvm_sw_breakpoint *bp) +/* C6.6.29 BRK instruction */ +static const uint32_t brk_insn = 0xd4200000; + +int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) { - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); - return -EINVAL; + + if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) || + cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk_insn, 4, 1)) { + return -EINVAL; + } + return 0; +} + +int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) +{ + static uint32_t brk; + + if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk, 4, 0) || + brk != brk_insn || + cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 1)) { + return -EINVAL; + } + return 0; } int kvm_arch_insert_hw_breakpoint(target_ulong addr, @@ -567,12 +639,6 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr, return -EINVAL; } -int kvm_arch_remove_sw_breakpoint(CPUState *cs, - struct kvm_sw_breakpoint *bp) -{ - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); - return -EINVAL; -} void kvm_arch_remove_all_hw_breakpoints(void) {