From patchwork Fri Sep 12 12:04:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 37297 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wg0-f71.google.com (mail-wg0-f71.google.com [74.125.82.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id E34AD206A5 for ; Fri, 12 Sep 2014 12:05:43 +0000 (UTC) Received: by mail-wg0-f71.google.com with SMTP id x12sf405747wgg.6 for ; Fri, 12 Sep 2014 05:05:41 -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:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=Shbmjg2NTapp30sXD2GJyr85WhdEX4T4X4xRAe48BfE=; b=gZoIg4J56bFIexTaM9fJPSm4gi2udrd00t2N7d+/qLysrhNZGXjIIHZQxwIyNbbaOn lHh/hj2WdeAX1U3vcjIul8A3YmPVpReVM9TtX4qIzWFBIYmo9/o9lFpce/uZXx/B06FD yXAWyxoM49fkIu2pemRgVV0vFUJKs31Emed8b6yxXSDLAersSh8apy94SFIgTJBH4yDY Z4SFaI47ifx+YdIUIfCtAeCm1RzOwbCcS4jk1ii7GXcbI8FRieAdm7vynMzArf3dFlEO XWg6ZFINh7MqRmfU9c3qXDZH72AYNIXoqReHLRfoQ0dFBZLPxoRjja93qvVtaYZqK35y rRoA== X-Gm-Message-State: ALoCoQmJzPhXMA50vvAoDrsEeCL6vOOlL7/y1z840/KbiclNzuh0ceOijG6aTggMIfxLKcEpXQiY X-Received: by 10.112.182.8 with SMTP id ea8mr2125801lbc.11.1410523541044; Fri, 12 Sep 2014 05:05:41 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.42.132 with SMTP id o4ls161324lal.21.gmail; Fri, 12 Sep 2014 05:05:40 -0700 (PDT) X-Received: by 10.152.10.203 with SMTP id k11mr8649838lab.30.1410523540815; Fri, 12 Sep 2014 05:05:40 -0700 (PDT) Received: from mail-lb0-f175.google.com (mail-lb0-f175.google.com [209.85.217.175]) by mx.google.com with ESMTPS id t2si6142759lbm.102.2014.09.12.05.05.40 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 12 Sep 2014 05:05:40 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.175 as permitted sender) client-ip=209.85.217.175; Received: by mail-lb0-f175.google.com with SMTP id v6so746591lbi.6 for ; Fri, 12 Sep 2014 05:05:40 -0700 (PDT) X-Received: by 10.152.246.6 with SMTP id xs6mr8553015lac.56.1410523539882; Fri, 12 Sep 2014 05:05:39 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.112.141.42 with SMTP id rl10csp717889lbb; Fri, 12 Sep 2014 05:05:39 -0700 (PDT) X-Received: by 10.70.91.208 with SMTP id cg16mr5264138pdb.91.1410523538234; Fri, 12 Sep 2014 05:05:38 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [81.2.115.146]) by mx.google.com with ESMTPS id z1si7509326pas.101.2014.09.12.05.05.35 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 12 Sep 2014 05:05:36 -0700 (PDT) Received-SPF: none (google.com: pm215@archaic.org.uk does not designate permitted sender hosts) client-ip=81.2.115.146; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1XSPaT-0003Ue-Gl; Fri, 12 Sep 2014 13:04:25 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Richard Henderson Subject: [PATCH 1/2] target-arm: Implement setting guest breakpoints Date: Fri, 12 Sep 2014 13:04:24 +0100 Message-Id: <1410523465-13400-2-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1410523465-13400-1-git-send-email-peter.maydell@linaro.org> References: <1410523465-13400-1-git-send-email-peter.maydell@linaro.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.217.175 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , This patch adds support for setting guest breakpoints based on values the guest writes to the DBGBVR and DBGBCR registers. (It doesn't include the code to handle when these breakpoints fire, so has no guest-visible effect.) Signed-off-by: Peter Maydell --- target-arm/cpu.c | 1 + target-arm/cpu.h | 1 + target-arm/helper.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++- target-arm/internals.h | 9 ++++ target-arm/machine.c | 1 + 5 files changed, 136 insertions(+), 2 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 7ea12bd..5b5531a 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -185,6 +185,7 @@ static void arm_cpu_reset(CPUState *s) } #endif + hw_breakpoint_update_all(cpu); hw_watchpoint_update_all(cpu); } diff --git a/target-arm/cpu.h b/target-arm/cpu.h index d1e1ccb..fa6ae0a 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -323,6 +323,7 @@ typedef struct CPUARMState { int eabi; #endif + struct CPUBreakpoint *cpu_breakpoint[16]; struct CPUWatchpoint *cpu_watchpoint[16]; CPU_COMMON diff --git a/target-arm/helper.c b/target-arm/helper.c index ece9673..d246d36 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2492,6 +2492,124 @@ static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, hw_watchpoint_update(cpu, i); } +void hw_breakpoint_update(ARMCPU *cpu, int n) +{ + CPUARMState *env = &cpu->env; + uint64_t bvr = env->cp15.dbgbvr[n]; + uint64_t bcr = env->cp15.dbgbcr[n]; + vaddr addr; + int bt; + int flags = BP_CPU; + + if (env->cpu_breakpoint[n]) { + cpu_breakpoint_remove_by_ref(CPU(cpu), env->cpu_breakpoint[n]); + env->cpu_breakpoint[n] = NULL; + } + + if (!extract64(bcr, 0, 1)) { + /* E bit clear : watchpoint disabled */ + return; + } + + bt = extract64(bcr, 20, 4); + + switch (bt) { + case 4: /* unlinked address mismatch (reserved if AArch64) */ + case 5: /* linked address mismatch (reserved if AArch64) */ + qemu_log_mask(LOG_UNIMP, + "arm: address mismatch breakpoint types not implemented"); + return; + case 0: /* unlinked address match */ + case 1: /* linked address match */ + { + /* Bits [63:49] are hardwired to the value of bit [48]; that is, + * we behave as if the register was sign extended. Bits [1:0] are + * RES0. The BAS field is used to allow setting breakpoints on 16 + * bit wide instructions; it is CONSTRAINED UNPREDICTABLE whether + * a bp will fire if the addresses covered by the bp and the addresses + * covered by the insn overlap but the insn doesn't start at the + * start of the bp address range. We choose to require the insn and + * the bp to have the same address. The constraints on writing to + * BAS enforced in dbgbcr_write mean we have only four cases: + * 0b0000 => no breakpoint + * 0b0011 => breakpoint on addr + * 0b1100 => breakpoint on addr + 2 + * 0b1111 => breakpoint on addr + * See also figure D2-3 in the v8 ARM ARM (DDI0487A.c). + */ + int bas = extract64(bcr, 5, 4); + addr = sextract64(bvr, 0, 49) & ~3ULL; + if (bas == 0) { + return; + } + if (bas == 0xc) { + addr += 2; + } + break; + } + case 2: /* unlinked context ID match */ + case 8: /* unlinked VMID match (reserved if no EL2) */ + case 10: /* unlinked context ID and VMID match (reserved if no EL2) */ + qemu_log_mask(LOG_UNIMP, + "arm: unlinked context breakpoint types not implemented"); + return; + case 9: /* linked VMID match (reserved if no EL2) */ + case 11: /* linked context ID and VMID match (reserved if no EL2) */ + case 3: /* linked context ID match */ + default: + /* We must generate no events for Linked context matches (unless + * they are linked to by some other bp/wp, which is handled in + * updates for the linking bp/wp). We choose to also generate no events + * for reserved values. + */ + return; + } + + cpu_breakpoint_insert(CPU(cpu), addr, flags, &env->cpu_breakpoint[n]); +} + +void hw_breakpoint_update_all(ARMCPU *cpu) +{ + int i; + CPUARMState *env = &cpu->env; + + /* Completely clear out existing QEMU breakpoints and our array, to + * avoid possible stale entries following migration load. + */ + cpu_breakpoint_remove_all(CPU(cpu), BP_CPU); + memset(env->cpu_breakpoint, 0, sizeof(env->cpu_breakpoint)); + + for (i = 0; i < ARRAY_SIZE(cpu->env.cpu_breakpoint); i++) { + hw_breakpoint_update(cpu, i); + } +} + +static void dbgbvr_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_breakpoint_update(cpu, i); +} + +static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu = arm_env_get_cpu(env); + int i = ri->crm; + + /* BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only + * copy of BAS[0]. + */ + value = deposit64(value, 6, 1, extract64(value, 5, 1)); + value = deposit64(value, 8, 1, extract64(value, 7, 1)); + + raw_write(env, ri, value); + hw_breakpoint_update(cpu, i); +} + static void define_debug_regs(ARMCPU *cpu) { /* Define v7 and v8 architectural debug registers. @@ -2533,11 +2651,15 @@ static void define_debug_regs(ARMCPU *cpu) { .name = "DBGBVR", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4, .access = PL1_RW, - .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]) }, + .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]), + .writefn = dbgbvr_write, .raw_writefn = raw_write + }, { .name = "DBGBCR", .state = ARM_CP_STATE_BOTH, .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5, .access = PL1_RW, - .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]) }, + .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]), + .writefn = dbgbcr_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 64751a0..b7e4822 100644 --- a/target-arm/internals.h +++ b/target-arm/internals.h @@ -322,6 +322,15 @@ void hw_watchpoint_update(ARMCPU *cpu, int n); * suitable for use after migration or on reset. */ void hw_watchpoint_update_all(ARMCPU *cpu); +/* Update a QEMU breakpoint based on the information the guest has set in the + * DBGBCR_EL1 and DBGBVR_EL1 registers. + */ +void hw_breakpoint_update(ARMCPU *cpu, int n); +/* Update the QEMU breakpoints for every guest breakpoint. This does a + * complete delete-and-reinstate of the QEMU breakpoint list and so is + * suitable for use after migration or on reset. + */ +void hw_breakpoint_update_all(ARMCPU *cpu); /* Callback function for when a watchpoint or breakpoint triggers. */ void arm_debug_excp_handler(CPUState *cs); diff --git a/target-arm/machine.c b/target-arm/machine.c index 8dfe87c..ddb7d05 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -214,6 +214,7 @@ static int cpu_post_load(void *opaque, int version_id) } } + hw_breakpoint_update_all(cpu); hw_watchpoint_update_all(cpu); return 0;