From patchwork Fri Sep 12 13:23:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 37318 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f69.google.com (mail-la0-f69.google.com [209.85.215.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 716B7203EE for ; Fri, 12 Sep 2014 13:34:03 +0000 (UTC) Received: by mail-la0-f69.google.com with SMTP id ty20sf483607lab.4 for ; Fri, 12 Sep 2014 06:34:02 -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: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=fHFPUvB5GCIqc10lAvZ7urLXedJc3o9zSx2inTnlBQE=; b=g5FVN+pnHK0/dVvzEHKRyProqr6YEFa+Ymm/Xj5f4i9Bif321bsJtlmtkyWFYPE13t 96qrOtiyQ7HPIGKJoXsf5+X06pP8WJWpgGAHKL8DXDjOT5XSK0K5nExJ3FfD/DHJNM+g dbUNadDtOoiCg2S9MSJQHuTGBkKIPLbZqmfMWSWaOHwH18HxH2D4diZNMuzMREBzx8YP rt5kvmu9he4XAev6gCqwxhjcCfVHIzp9y0yjCtZuWjJwhjrCvCq+NvN7EVd3C4Q3XuPk I5mWeUTnbM0ZDNkrXmsxKkV86pfbMbL0LDd7QqQ0yA+wHGWZBD5xptYWnfDFAUA9qYe5 1FKg== X-Gm-Message-State: ALoCoQl4PCHKSFXoVUTllpLIYSe79P+nM5qiHU6d6VldOIhDh+cv0/c7itC9FgiFPCnteJhtaQXM X-Received: by 10.112.170.166 with SMTP id an6mr802761lbc.17.1410528842219; Fri, 12 Sep 2014 06:34:02 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.87.44 with SMTP id u12ls157797laz.16.gmail; Fri, 12 Sep 2014 06:34:02 -0700 (PDT) X-Received: by 10.112.161.70 with SMTP id xq6mr8672044lbb.49.1410528842057; Fri, 12 Sep 2014 06:34:02 -0700 (PDT) Received: from mail-lb0-f178.google.com (mail-lb0-f178.google.com [209.85.217.178]) by mx.google.com with ESMTPS id s6si6493118las.121.2014.09.12.06.34.02 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 12 Sep 2014 06:34:02 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.178 as permitted sender) client-ip=209.85.217.178; Received: by mail-lb0-f178.google.com with SMTP id c11so901434lbj.37 for ; Fri, 12 Sep 2014 06:34:01 -0700 (PDT) X-Received: by 10.112.4.33 with SMTP id h1mr8324294lbh.67.1410528841935; Fri, 12 Sep 2014 06:34:01 -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.112.141.42 with SMTP id rl10csp732422lbb; Fri, 12 Sep 2014 06:34:01 -0700 (PDT) X-Received: by 10.140.35.242 with SMTP id n105mr12221382qgn.11.1410528840629; Fri, 12 Sep 2014 06:34:00 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id g69si5591714qgg.113.2014.09.12.06.34.00 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 12 Sep 2014 06:34:00 -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]:45000 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XSQz9-0007pc-MJ for patch@linaro.org; Fri, 12 Sep 2014 09:33:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56962) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XSQpY-0006q0-Q3 for qemu-devel@nongnu.org; Fri, 12 Sep 2014 09:24:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XSQpS-0003zi-JC for qemu-devel@nongnu.org; Fri, 12 Sep 2014 09:24:04 -0400 Received: from mnementh.archaic.org.uk ([81.2.115.146]:46961) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XSQpS-0003xi-Ah for qemu-devel@nongnu.org; Fri, 12 Sep 2014 09:23:58 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1XSQpO-0003XU-Pw for qemu-devel@nongnu.org; Fri, 12 Sep 2014 14:23:54 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Fri, 12 Sep 2014 14:23:38 +0100 Message-Id: <1410528234-13545-8-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1410528234-13545-1-git-send-email-peter.maydell@linaro.org> References: <1410528234-13545-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 Subject: [Qemu-devel] [PULL 07/23] exec.c: Relax restrictions on watchpoint length and alignment 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.217.178 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 The current implementation of watchpoints requires that they have a power of 2 length which is not greater than TARGET_PAGE_SIZE and that their address is a multiple of their length. Watchpoints on ARM don't fit these restrictions, so change the implementation so they can be relaxed. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson --- exec.c | 44 +++++++++++++++++++++++++++++++------------- include/qom/cpu.h | 2 +- linux-user/main.c | 3 +-- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/exec.c b/exec.c index 7dddcc8..f3e7fb6 100644 --- a/exec.c +++ b/exec.c @@ -582,12 +582,10 @@ int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, int flags, CPUWatchpoint **watchpoint) { - vaddr len_mask = ~(len - 1); CPUWatchpoint *wp; - /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */ - if ((len & (len - 1)) || (addr & ~len_mask) || - len == 0 || len > TARGET_PAGE_SIZE) { + /* forbid ranges which are empty or run off the end of the address space */ + if (len == 0 || (addr + len - 1) <= addr) { error_report("tried to set invalid watchpoint at %" VADDR_PRIx ", len=%" VADDR_PRIu, addr, len); return -EINVAL; @@ -595,7 +593,7 @@ int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, wp = g_malloc(sizeof(*wp)); wp->vaddr = addr; - wp->len_mask = len_mask; + wp->len = len; wp->flags = flags; /* keep all GDB-injected watchpoints in front */ @@ -616,11 +614,10 @@ int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, vaddr len, int flags) { - vaddr len_mask = ~(len - 1); CPUWatchpoint *wp; QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { - if (addr == wp->vaddr && len_mask == wp->len_mask + if (addr == wp->vaddr && len == wp->len && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) { cpu_watchpoint_remove_by_ref(cpu, wp); return 0; @@ -650,6 +647,27 @@ void cpu_watchpoint_remove_all(CPUState *cpu, int mask) } } } + +/* Return true if this watchpoint address matches the specified + * access (ie the address range covered by the watchpoint overlaps + * partially or completely with the address range covered by the + * access). + */ +static inline bool cpu_watchpoint_address_matches(CPUWatchpoint *wp, + vaddr addr, + vaddr len) +{ + /* We know the lengths are non-zero, but a little caution is + * required to avoid errors in the case where the range ends + * exactly at the top of the address space and so addr + len + * wraps round to zero. + */ + vaddr wpend = wp->vaddr + wp->len - 1; + vaddr addrend = addr + len - 1; + + return !(addr > wpend || wp->vaddr > addrend); +} + #endif /* Add a breakpoint. */ @@ -861,7 +879,7 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu, /* Make accesses to pages with watchpoints go via the watchpoint trap routines. */ QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { - if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { + if (cpu_watchpoint_address_matches(wp, vaddr, TARGET_PAGE_SIZE)) { /* Avoid trapping reads of pages with a write breakpoint. */ if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) { iotlb = PHYS_SECTION_WATCH + paddr; @@ -1625,7 +1643,7 @@ static const MemoryRegionOps notdirty_mem_ops = { }; /* Generate a debug exception if a watchpoint has been hit. */ -static void check_watchpoint(int offset, int len_mask, int flags) +static void check_watchpoint(int offset, int len, int flags) { CPUState *cpu = current_cpu; CPUArchState *env = cpu->env_ptr; @@ -1643,8 +1661,8 @@ static void check_watchpoint(int offset, int len_mask, int flags) } vaddr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset; QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { - if ((vaddr == (wp->vaddr & len_mask) || - (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) { + if (cpu_watchpoint_address_matches(wp, vaddr, len) + && (wp->flags & flags)) { wp->flags |= BP_WATCHPOINT_HIT; if (!cpu->watchpoint_hit) { cpu->watchpoint_hit = wp; @@ -1670,7 +1688,7 @@ static void check_watchpoint(int offset, int len_mask, int flags) static uint64_t watch_mem_read(void *opaque, hwaddr addr, unsigned size) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_READ); + check_watchpoint(addr & ~TARGET_PAGE_MASK, size, BP_MEM_READ); switch (size) { case 1: return ldub_phys(&address_space_memory, addr); case 2: return lduw_phys(&address_space_memory, addr); @@ -1682,7 +1700,7 @@ static uint64_t watch_mem_read(void *opaque, hwaddr addr, static void watch_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_WRITE); + check_watchpoint(addr & ~TARGET_PAGE_MASK, size, BP_MEM_WRITE); switch (size) { case 1: stb_phys(&address_space_memory, addr, val); diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 1aafbf5..7c06f37 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -169,7 +169,7 @@ typedef struct CPUBreakpoint { typedef struct CPUWatchpoint { vaddr vaddr; - vaddr len_mask; + vaddr len; int flags; /* BP_* */ QTAILQ_ENTRY(CPUWatchpoint) entry; } CPUWatchpoint; diff --git a/linux-user/main.c b/linux-user/main.c index 472a16d..483eb3f 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3458,8 +3458,7 @@ CPUArchState *cpu_copy(CPUArchState *env) cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); } QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { - cpu_watchpoint_insert(new_cpu, wp->vaddr, (~wp->len_mask) + 1, - wp->flags, NULL); + cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL); } #endif