From patchwork Mon Mar 10 00:15:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Andreas_F=C3=A4rber?= X-Patchwork-Id: 3800891 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 0A7E5BF540 for ; Mon, 10 Mar 2014 00:16:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B479A201EF for ; Mon, 10 Mar 2014 00:16:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 34D772022A for ; Mon, 10 Mar 2014 00:16:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752564AbaCJAQU (ORCPT ); Sun, 9 Mar 2014 20:16:20 -0400 Received: from cantor2.suse.de ([195.135.220.15]:51401 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751833AbaCJAQP (ORCPT ); Sun, 9 Mar 2014 20:16:15 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 77B897501D; Mon, 10 Mar 2014 00:16:14 +0000 (UTC) From: =?UTF-8?q?Andreas=20F=C3=A4rber?= To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, =?UTF-8?q?Andreas=20F=C3=A4rber?= , Riku Voipio , Gleb Natapov , Marcelo Tosatti , Michael Walle , Max Filippov , kvm@vger.kernel.org (open list:X86) Subject: [PATCH qom-cpu v2 18/40] cpu: Move watchpoint fields from CPU_COMMON to CPUState Date: Mon, 10 Mar 2014 01:15:27 +0100 Message-Id: <1394410549-13751-19-git-send-email-afaerber@suse.de> X-Mailer: git-send-email 1.8.4.5 In-Reply-To: <1394410549-13751-1-git-send-email-afaerber@suse.de> References: <1394410549-13751-1-git-send-email-afaerber@suse.de> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Andreas Färber --- cpu-exec.c | 5 +++-- exec.c | 33 ++++++++++++++++++++------------- gdbstub.c | 8 ++++---- include/exec/cpu-defs.h | 10 ---------- include/qom/cpu.h | 10 ++++++++++ linux-user/main.c | 5 +++-- target-i386/cpu.h | 2 +- target-i386/helper.c | 7 ++++--- target-i386/kvm.c | 8 ++++---- target-lm32/cpu.h | 2 +- target-lm32/helper.c | 7 ++++--- target-xtensa/cpu.h | 2 +- target-xtensa/helper.c | 8 +++++--- 13 files changed, 60 insertions(+), 47 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 798dc08..d7c21d3 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -200,10 +200,11 @@ void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler) static void cpu_handle_debug_exception(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); CPUWatchpoint *wp; - if (!env->watchpoint_hit) { - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + if (!cpu->watchpoint_hit) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { wp->flags &= ~BP_WATCHPOINT_HIT; } } diff --git a/exec.c b/exec.c index 9b02c6a..cf4a0ef 100644 --- a/exec.c +++ b/exec.c @@ -485,7 +485,7 @@ void cpu_exec_init(CPUArchState *env) cpu->cpu_index = cpu_index; cpu->numa_node = 0; QTAILQ_INIT(&env->breakpoints); - QTAILQ_INIT(&env->watchpoints); + QTAILQ_INIT(&cpu->watchpoints); #ifndef CONFIG_USER_ONLY cpu->as = &address_space_memory; cpu->thread_id = qemu_get_thread_id(); @@ -542,6 +542,7 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len, int flags, CPUWatchpoint **watchpoint) { + CPUState *cpu = ENV_GET_CPU(env); target_ulong len_mask = ~(len - 1); CPUWatchpoint *wp; @@ -559,10 +560,11 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len wp->flags = flags; /* keep all GDB-injected watchpoints in front */ - if (flags & BP_GDB) - QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry); - else - QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry); + if (flags & BP_GDB) { + QTAILQ_INSERT_HEAD(&cpu->watchpoints, wp, entry); + } else { + QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry); + } tlb_flush_page(env, addr); @@ -575,10 +577,11 @@ int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len, int flags) { + CPUState *cpu = ENV_GET_CPU(env); target_ulong len_mask = ~(len - 1); CPUWatchpoint *wp; - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { if (addr == wp->vaddr && len_mask == wp->len_mask && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) { cpu_watchpoint_remove_by_ref(env, wp); @@ -591,7 +594,9 @@ int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len /* Remove a specific watchpoint by reference. */ void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint) { - QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry); + CPUState *cpu = ENV_GET_CPU(env); + + QTAILQ_REMOVE(&cpu->watchpoints, watchpoint, entry); tlb_flush_page(env, watchpoint->vaddr); @@ -601,9 +606,10 @@ void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint) /* Remove all matching watchpoints. */ void cpu_watchpoint_remove_all(CPUArchState *env, int mask) { + CPUState *cpu = ENV_GET_CPU(env); CPUWatchpoint *wp, *next; - QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) { + QTAILQ_FOREACH_SAFE(wp, &cpu->watchpoints, entry, next) { if (wp->flags & mask) cpu_watchpoint_remove_by_ref(env, wp); } @@ -799,6 +805,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, int prot, target_ulong *address) { + CPUState *cpu = ENV_GET_CPU(env); hwaddr iotlb; CPUWatchpoint *wp; @@ -818,7 +825,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, /* Make accesses to pages with watchpoints go via the watchpoint trap routines. */ - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { /* Avoid trapping reads of pages with a write breakpoint. */ if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) { @@ -1573,7 +1580,7 @@ static void check_watchpoint(int offset, int len_mask, int flags) CPUWatchpoint *wp; int cpu_flags; - if (env->watchpoint_hit) { + if (cpu->watchpoint_hit) { /* We re-entered the check after replacing the TB. Now raise * the debug interrupt so that is will trigger after the * current instruction. */ @@ -1581,12 +1588,12 @@ static void check_watchpoint(int offset, int len_mask, int flags) return; } vaddr = (cpu->mem_io_vaddr & TARGET_PAGE_MASK) + offset; - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { if ((vaddr == (wp->vaddr & len_mask) || (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) { wp->flags |= BP_WATCHPOINT_HIT; - if (!env->watchpoint_hit) { - env->watchpoint_hit = wp; + if (!cpu->watchpoint_hit) { + cpu->watchpoint_hit = wp; tb_check_watchpoint(env); if (wp->flags & BP_STOP_BEFORE_ACCESS) { cpu->exception_index = EXCP_DEBUG; diff --git a/gdbstub.c b/gdbstub.c index c5ab73f..0176b3f 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1204,8 +1204,8 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) } switch (state) { case RUN_STATE_DEBUG: - if (env->watchpoint_hit) { - switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) { + if (cpu->watchpoint_hit) { + switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) { case BP_MEM_READ: type = "r"; break; @@ -1219,8 +1219,8 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) snprintf(buf, sizeof(buf), "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";", GDB_SIGNAL_TRAP, cpu_index(cpu), type, - env->watchpoint_hit->vaddr); - env->watchpoint_hit = NULL; + (target_ulong)cpu->watchpoint_hit->vaddr); + cpu->watchpoint_hit = NULL; goto send_packet; } tb_flush(env); diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index be9569c..338b8cb 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -119,13 +119,6 @@ typedef struct CPUBreakpoint { QTAILQ_ENTRY(CPUBreakpoint) entry; } CPUBreakpoint; -typedef struct CPUWatchpoint { - target_ulong vaddr; - target_ulong len_mask; - int flags; /* BP_* */ - QTAILQ_ENTRY(CPUWatchpoint) entry; -} CPUWatchpoint; - #define CPU_TEMP_BUF_NLONGS 128 #define CPU_COMMON \ /* soft mmu support */ \ @@ -134,8 +127,5 @@ typedef struct CPUWatchpoint { /* from this point: preserved by CPU reset */ \ /* ice debug support */ \ QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \ - \ - QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; \ - CPUWatchpoint *watchpoint_hit; \ #endif diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 4d1ea35..c7420e0 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -151,6 +151,13 @@ typedef struct icount_decr_u16 { } icount_decr_u16; #endif +typedef struct CPUWatchpoint { + vaddr vaddr; + vaddr len_mask; + int flags; /* BP_* */ + QTAILQ_ENTRY(CPUWatchpoint) entry; +} CPUWatchpoint; + struct KVMState; struct kvm_run; @@ -231,6 +238,9 @@ struct CPUState { int gdb_num_g_regs; QTAILQ_ENTRY(CPUState) node; + QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; + CPUWatchpoint *watchpoint_hit; + void *opaque; /* In order to avoid passing too many arguments to the MMIO helpers, diff --git a/linux-user/main.c b/linux-user/main.c index 99220b3..3345a8f 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3431,6 +3431,7 @@ void init_task_state(TaskState *ts) CPUArchState *cpu_copy(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); CPUArchState *new_env = cpu_init(cpu_model); #if defined(TARGET_HAS_ICE) CPUBreakpoint *bp; @@ -3446,12 +3447,12 @@ CPUArchState *cpu_copy(CPUArchState *env) Note: Once we support ptrace with hw-debug register access, make sure BP_CPU break/watchpoints are handled correctly on clone. */ QTAILQ_INIT(&env->breakpoints); - QTAILQ_INIT(&env->watchpoints); + QTAILQ_INIT(&cpu->watchpoints); #if defined(TARGET_HAS_ICE) QTAILQ_FOREACH(bp, &env->breakpoints, entry) { cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL); } - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1, wp->flags, NULL); } diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 62641af..9060187 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -876,7 +876,7 @@ typedef struct CPUX86State { target_ulong dr[8]; /* debug registers */ union { CPUBreakpoint *cpu_breakpoint[4]; - CPUWatchpoint *cpu_watchpoint[4]; + struct CPUWatchpoint *cpu_watchpoint[4]; }; /* break/watchpoints for dr[0..3] */ uint32_t smbase; int old_exception; /* exception in flight */ diff --git a/target-i386/helper.c b/target-i386/helper.c index 6d9bd71..bd8da20 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1088,11 +1088,12 @@ bool check_hw_breakpoints(CPUX86State *env, bool force_dr6_update) void breakpoint_handler(CPUX86State *env) { + CPUState *cs = CPU(x86_env_get_cpu(env)); CPUBreakpoint *bp; - if (env->watchpoint_hit) { - if (env->watchpoint_hit->flags & BP_CPU) { - env->watchpoint_hit = NULL; + if (cs->watchpoint_hit) { + if (cs->watchpoint_hit->flags & BP_CPU) { + cs->watchpoint_hit = NULL; if (check_hw_breakpoints(env, false)) { raise_exception(env, EXCP01_DB); } else { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index e555040..7a295f6 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2277,13 +2277,13 @@ static int kvm_handle_debug(X86CPU *cpu, break; case 0x1: ret = EXCP_DEBUG; - env->watchpoint_hit = &hw_watchpoint; + cs->watchpoint_hit = &hw_watchpoint; hw_watchpoint.vaddr = hw_breakpoint[n].addr; hw_watchpoint.flags = BP_MEM_WRITE; break; case 0x3: ret = EXCP_DEBUG; - env->watchpoint_hit = &hw_watchpoint; + cs->watchpoint_hit = &hw_watchpoint; hw_watchpoint.vaddr = hw_breakpoint[n].addr; hw_watchpoint.flags = BP_MEM_ACCESS; break; @@ -2291,11 +2291,11 @@ static int kvm_handle_debug(X86CPU *cpu, } } } - } else if (kvm_find_sw_breakpoint(CPU(cpu), arch_info->pc)) { + } else if (kvm_find_sw_breakpoint(cs, arch_info->pc)) { ret = EXCP_DEBUG; } if (ret == 0) { - cpu_synchronize_state(CPU(cpu)); + cpu_synchronize_state(cs); assert(env->exception_injected == -1); /* pass to guest */ diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h index b94d9b0..d50726b 100644 --- a/target-lm32/cpu.h +++ b/target-lm32/cpu.h @@ -167,7 +167,7 @@ struct CPULM32State { uint32_t wp[4]; /* watchpoints */ CPUBreakpoint * cpu_breakpoint[4]; - CPUWatchpoint * cpu_watchpoint[4]; + struct CPUWatchpoint *cpu_watchpoint[4]; CPU_COMMON diff --git a/target-lm32/helper.c b/target-lm32/helper.c index e5536c0..67ba278 100644 --- a/target-lm32/helper.c +++ b/target-lm32/helper.c @@ -118,11 +118,12 @@ static bool check_watchpoints(CPULM32State *env) void lm32_debug_excp_handler(CPULM32State *env) { + CPUState *cs = CPU(lm32_env_get_cpu(env)); CPUBreakpoint *bp; - if (env->watchpoint_hit) { - if (env->watchpoint_hit->flags & BP_CPU) { - env->watchpoint_hit = NULL; + if (cs->watchpoint_hit) { + if (cs->watchpoint_hit->flags & BP_CPU) { + cs->watchpoint_hit = NULL; if (check_watchpoints(env)) { raise_exception(env, EXCP_WATCHPOINT); } else { diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 4bae693..e210bac 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -359,7 +359,7 @@ typedef struct CPUXtensaState { int exception_taken; /* Watchpoints for DBREAK registers */ - CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK]; + struct CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK]; CPU_COMMON } CPUXtensaState; diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c index 2598788..8a9cb0a 100644 --- a/target-xtensa/helper.c +++ b/target-xtensa/helper.c @@ -81,11 +81,13 @@ static uint32_t check_hw_breakpoints(CPUXtensaState *env) void xtensa_breakpoint_handler(CPUXtensaState *env) { - if (env->watchpoint_hit) { - if (env->watchpoint_hit->flags & BP_CPU) { + CPUState *cs = CPU(xtensa_env_get_cpu(env)); + + if (cs->watchpoint_hit) { + if (cs->watchpoint_hit->flags & BP_CPU) { uint32_t cause; - env->watchpoint_hit = NULL; + cs->watchpoint_hit = NULL; cause = check_hw_breakpoints(env); if (cause) { debug_exception_env(env, cause);