From patchwork Fri Aug 29 11:21:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 36281 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 C2BE4202DD for ; Fri, 29 Aug 2014 11:28:51 +0000 (UTC) Received: by mail-ob0-f198.google.com with SMTP id wp18sf14305227obc.1 for ; Fri, 29 Aug 2014 04:28:51 -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=hGesLG2Qo5i6XVTLMAZeM9TqjVP1CGssaLLS1734Wpc=; b=MnkVtgATdO3cSnfpLTZzmw6hOT+KUvZTadLj6yLdx/JHu5N0aLGkOKjLERRAQkCnwK poHVtYsh0oy5IBi1CkwlRnJNKPQ01AFCUMiRfzGQrAlaOJf2W+m9Z4ZAjJ841n+r7XNy sxkdkHP45PB/+J1Jf6XAI1JhEzrn71p7lC/dgsYxqLBySDRO288MhY+AJ92YpMBUZHTm Y6IeaYsMC/aQ48VcQ9g8f22EvBtyQGY0e5TbAZZqM25puhqBwGSUGD1dNK5GUSnpfOd0 G3PnNUsoX5EAlDX3SfXcHH63lG4bAyc+BCOqaUKvxZ4l4y2evJLF4vpswgrureHibK0y 1Hng== X-Gm-Message-State: ALoCoQkOaxL6xgHkewyluR2MXzDVXSe53KvBXO2Ihpt+y7FjSz7kRkAa6IoAowN0ziilH9xbrKb4 X-Received: by 10.182.68.17 with SMTP id r17mr5307917obt.26.1409311731338; Fri, 29 Aug 2014 04:28:51 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.109.246 with SMTP id l109ls102966qgf.1.gmail; Fri, 29 Aug 2014 04:28:51 -0700 (PDT) X-Received: by 10.220.95.132 with SMTP id d4mr7425011vcn.33.1409311731231; Fri, 29 Aug 2014 04:28:51 -0700 (PDT) Received: from mail-vc0-f173.google.com (mail-vc0-f173.google.com [209.85.220.173]) by mx.google.com with ESMTPS id dm3si6043373vcb.91.2014.08.29.04.28.51 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 29 Aug 2014 04:28:51 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.173 as permitted sender) client-ip=209.85.220.173; Received: by mail-vc0-f173.google.com with SMTP id im17so2266444vcb.32 for ; Fri, 29 Aug 2014 04:28:51 -0700 (PDT) X-Received: by 10.52.6.138 with SMTP id b10mr153075vda.84.1409311731140; Fri, 29 Aug 2014 04:28:51 -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.221.45.67 with SMTP id uj3csp893vcb; Fri, 29 Aug 2014 04:28:50 -0700 (PDT) X-Received: by 10.180.99.131 with SMTP id eq3mr3241581wib.5.1409311730206; Fri, 29 Aug 2014 04:28:50 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [81.2.115.146]) by mx.google.com with ESMTPS id yr7si11723522wjc.158.2014.08.29.04.28.49 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 29 Aug 2014 04:28:50 -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 1XNKFI-0004uj-6S; Fri, 29 Aug 2014 12:21:32 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, =?UTF-8?q?Andreas=20F=C3=A4rber?= , Paolo Bonzini , Richard Henderson Subject: [PATCH 01/10] exec.c: Relax restrictions on watchpoint length and alignment Date: Fri, 29 Aug 2014 12:21:23 +0100 Message-Id: <1409311292-18860-2-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-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.173 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: , 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 --- 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 5f9857c..1f3f4a5 100644 --- a/exec.c +++ b/exec.c @@ -547,12 +547,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; @@ -560,7 +558,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 */ @@ -581,11 +579,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; @@ -615,6 +612,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. */ @@ -826,7 +844,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; @@ -1590,7 +1608,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; @@ -1608,8 +1626,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; @@ -1635,7 +1653,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); @@ -1647,7 +1665,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