From patchwork Fri Aug 29 11:21:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 36279 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f198.google.com (mail-ob0-f198.google.com [209.85.214.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 6A604202DD for ; Fri, 29 Aug 2014 11:25:40 +0000 (UTC) Received: by mail-ob0-f198.google.com with SMTP id wp18sf14293480obc.1 for ; Fri, 29 Aug 2014 04:25:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:in-reply-to:references:cc:subject:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:list-subscribe :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=jwQKQJpMZlCuOu6nT2HJe+6FpJIoLtR4Mrm7yPs8wvw=; b=VVyZg4b4Nh2/Xq3wgn/LSaw9Be6ukn5N8mxSS0GtXKqBrmxnMYEhrC/o07FXU1kFC/ MaTKOHLRjUBbYCamEaqBpmcQE60c8R6XjLvhFdJadZGzkwN1+eVy+drsTG32qie2RGz4 gbhQzba7JC1pRSYqa0ri5NX/PLatZsmY1g2mr+NPRkyllYf2/X/6E4rY3abVQG2Wf16e c2cacABxT1AcjFhx2l4/095Jb031YonSrQS2tr1X3ljUTjdI9HnL+O+gXtDbotjgz23B zpuXqO1OSiX1K6xRNQjZjn6X59U9t1EwjOvXYrmJjdkklC2HKkmrOV6dQQwgm92cHT5i VRlg== X-Gm-Message-State: ALoCoQnNQNSOpWFm0TtMIWUbZJ3SyY9MD7o4i2MI86o5EJy6H+6aTtiNgeFU9QQsr328zjLoqBeL X-Received: by 10.182.232.164 with SMTP id tp4mr5721396obc.29.1409311540049; Fri, 29 Aug 2014 04:25:40 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.19.203 with SMTP id 69ls965529qgh.27.gmail; Fri, 29 Aug 2014 04:25:39 -0700 (PDT) X-Received: by 10.220.46.5 with SMTP id h5mr422385vcf.55.1409311539889; Fri, 29 Aug 2014 04:25:39 -0700 (PDT) Received: from mail-vc0-f177.google.com (mail-vc0-f177.google.com [209.85.220.177]) by mx.google.com with ESMTPS id yq20si6070449vdb.38.2014.08.29.04.25.39 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 29 Aug 2014 04:25:39 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.177 as permitted sender) client-ip=209.85.220.177; Received: by mail-vc0-f177.google.com with SMTP id hq11so2246419vcb.22 for ; Fri, 29 Aug 2014 04:25:39 -0700 (PDT) X-Received: by 10.220.105.201 with SMTP id u9mr9648603vco.11.1409311539798; Fri, 29 Aug 2014 04:25:39 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp393vcb; Fri, 29 Aug 2014 04:25:39 -0700 (PDT) X-Received: by 10.140.98.7 with SMTP id n7mr15558216qge.83.1409311539347; Fri, 29 Aug 2014 04:25:39 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id n7si9859370qas.26.2014.08.29.04.25.39 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 29 Aug 2014 04:25:39 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:41406 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XNKJG-0003j9-K0 for patch@linaro.org; Fri, 29 Aug 2014 07:25:38 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38044) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XNKGb-0007eD-Al for qemu-devel@nongnu.org; Fri, 29 Aug 2014 07:22:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XNKGU-000730-Mm for qemu-devel@nongnu.org; Fri, 29 Aug 2014 07:22:53 -0400 Received: from mnementh.archaic.org.uk ([81.2.115.146]:46718) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XNKGU-00070y-E6 for qemu-devel@nongnu.org; Fri, 29 Aug 2014 07:22:46 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1XNKFI-0004uz-CZ; Fri, 29 Aug 2014 12:21:32 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Fri, 29 Aug 2014 12:21:27 +0100 Message-Id: <1409311292-18860-6-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1409311292-18860-1-git-send-email-peter.maydell@linaro.org> References: <1409311292-18860-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 81.2.115.146 Cc: Paolo Bonzini , Richard Henderson , =?UTF-8?q?Andreas=20F=C3=A4rber?= , patches@linaro.org Subject: [Qemu-devel] [PATCH 05/10] target-arm: Implement setting of watchpoints X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.177 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Implement support for setting QEMU watchpoints based on the values the guest writes to the ARM architected watchpoint registers. (We do not yet report the firing of the watchpoints to the guest, so they will just be ignored.) Signed-off-by: Peter Maydell --- target-arm/cpu.c | 2 + target-arm/cpu.h | 2 + target-arm/helper.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++-- target-arm/internals.h | 10 ++++ target-arm/machine.c | 3 ++ 5 files changed, 149 insertions(+), 3 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 8199f32..3d12656 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -172,6 +172,8 @@ static void arm_cpu_reset(CPUState *s) kvm_arm_reset_vcpu(cpu); } #endif + + hw_watchpoint_update_all(cpu); } #ifndef CONFIG_USER_ONLY diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 8098b8d..2218127 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -322,6 +322,8 @@ typedef struct CPUARMState { int eabi; #endif + struct CPUWatchpoint *cpu_watchpoint[16]; + CPU_COMMON /* These fields after the common ones so they are preserved on reset. */ diff --git a/target-arm/helper.c b/target-arm/helper.c index 2a77c97..406b9bc 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2223,6 +2223,131 @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = { REGINFO_SENTINEL }; +void hw_watchpoint_update(ARMCPU *cpu, int n) +{ + CPUARMState *env = &cpu->env; + vaddr len = 0; + vaddr wvr = env->cp15.dbgwvr[n]; + uint64_t wcr = env->cp15.dbgwcr[n]; + int mask; + int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; + + if (env->cpu_watchpoint[n]) { + cpu_watchpoint_remove_by_ref(CPU(cpu), env->cpu_watchpoint[n]); + env->cpu_watchpoint[n] = NULL; + } + + if (!extract64(wcr, 0, 1)) { + /* E bit clear : watchpoint disabled */ + return; + } + + switch (extract64(wcr, 3, 2)) { + case 0: + /* LSC 00 is reserved and must behave as if the wp is disabled */ + return; + case 1: + flags |= BP_MEM_READ; + break; + case 2: + flags |= BP_MEM_WRITE; + break; + case 3: + flags |= BP_MEM_ACCESS; + break; + } + + /* Attempts to use both MASK and BAS fields simultaneously are + * CONSTRAINED UNPREDICTABLE; we opt to ignore BAS in this case, + * thus generating a watchpoint for every byte in the masked region. + */ + mask = extract64(wcr, 24, 4); + if (mask == 1 || mask == 2) { + /* Reserved values of MASK; we must act as if the mask value was + * some non-reserved value, or as if the watchpoint were disabled. + * We choose the latter. + */ + return; + } else if (mask) { + /* Watchpoint covers an aligned area up to 2GB in size */ + len = 1ULL << mask; + /* If masked bits in WVR are not zero it's CONSTRAINED UNPREDICTABLE + * whether the watchpoint fires when the unmasked bits match; we opt + * to generate the exceptions. + */ + wvr &= (len - 1); + } else { + /* Watchpoint covers bytes defined by the byte address select bits */ + int bas = extract64(wcr, 5, 8); + int basstart; + + if (bas == 0) { + /* This must act as if the watchpoint is disabled */ + return; + } + + if (extract64(wvr, 2, 1)) { + /* Deprecated case of an only 4-aligned address. BAS[7:4] are + * ignored, and BAS[3:0] define which bytes to watch. + */ + bas &= 0xf; + } + /* The BAS bits are supposed to be programmed to indicate a contiguous + * range of bytes. Otherwise it is CONSTRAINED UNPREDICTABLE whether + * we fire for each byte in the word/doubleword addressed by the WVR. + * We choose to ignore any non-zero bits after the first range of 1s. + */ + basstart = ctz32(bas); + len = cto32(bas >> basstart); + wvr += basstart; + } + + cpu_watchpoint_insert(CPU(cpu), wvr, len, flags, + &env->cpu_watchpoint[n]); +} + +void hw_watchpoint_update_all(ARMCPU *cpu) +{ + int i; + CPUARMState *env = &cpu->env; + + /* Completely clear out existing QEMU watchpoints and our array, to + * avoid possible stale entries following migration load. + */ + cpu_watchpoint_remove_all(CPU(cpu), BP_CPU); + memset(env->cpu_watchpoint, 0, sizeof(env->cpu_watchpoint)); + + for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_watchpoint); i++) { + hw_watchpoint_update(cpu, i); + } +} + +static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + int i = ri->crm; + + /* Bits [63:49] are hardwired to the value of bit [48]; that is, the + * register reads and behaves as if values written are sign extended. + * Bits [1:0] are RES0. + */ + value = sextract64(value, 0, 49) & ~3ULL; + + raw_write(env, ri, value); + hw_watchpoint_update(cpu, i); +} + +static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + int i = ri->crm; + + raw_write(env, ri, value); + hw_watchpoint_update(cpu, i); +} + static void define_debug_regs(ARMCPU *cpu) { /* Define v7 and v8 architectural debug registers. @@ -2274,12 +2399,16 @@ static void define_debug_regs(ARMCPU *cpu) { .name = "DBGWVR", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6, .access = PL1_RW, - .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]) }, + .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]), + .writefn = dbgwvr_write, .raw_writefn = raw_write + }, { .name = "DBGWCR", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7, .access = PL1_RW, - .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]) }, - REGINFO_SENTINEL + .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]), + .writefn = dbgwcr_write, .raw_writefn = raw_write + }, + REGINFO_SENTINEL }; define_arm_cp_regs(cpu, dbgregs); } diff --git a/target-arm/internals.h b/target-arm/internals.h index 53c2e3c..22f382c 100644 --- a/target-arm/internals.h +++ b/target-arm/internals.h @@ -296,4 +296,14 @@ static inline uint32_t syn_swstep(int same_el, int isv, int ex) | (isv << 24) | (ex << 6) | 0x22; } +/* Update a QEMU watchpoint based on the information the guest has set in the + * DBGWCR_EL1 and DBGWVR_EL1 registers. + */ +void hw_watchpoint_update(ARMCPU *cpu, int n); +/* Update the QEMU watchpoints for every guest watchpoint. This does a + * complete delete-and-reinstate of the QEMU watchpoint list and so is + * suitable for use after migration or on reset. + */ +void hw_watchpoint_update_all(ARMCPU *cpu); + #endif diff --git a/target-arm/machine.c b/target-arm/machine.c index 3bcc7cc..8dfe87c 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -2,6 +2,7 @@ #include "hw/boards.h" #include "sysemu/kvm.h" #include "kvm_arm.h" +#include "internals.h" static bool vfp_needed(void *opaque) { @@ -213,6 +214,8 @@ static int cpu_post_load(void *opaque, int version_id) } } + hw_watchpoint_update_all(cpu); + return 0; }