W-M-R commented on code in PR #15616: URL: https://github.com/apache/nuttx/pull/15616#discussion_r1924632306
########## arch/arm/src/armv7-a/arm_dbgmonitor.c: ########## @@ -0,0 +1,767 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_dbgmonitor.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/arch.h> + +#include <stdint.h> +#include <string.h> +#include <assert.h> +#include <debug.h> + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Debug architecture numbers. */ + +#define ARM_DEBUG_ARCH_RESERVED 0 /* In case of ptrace ABI updates. */ +#define ARM_DEBUG_ARCH_V6 1 +#define ARM_DEBUG_ARCH_V6_1 2 +#define ARM_DEBUG_ARCH_V7_ECP14 3 +#define ARM_DEBUG_ARCH_V7_MM 4 +#define ARM_DEBUG_ARCH_V7_1 5 +#define ARM_DEBUG_ARCH_V8 6 +#define ARM_DEBUG_ARCH_V8_1 7 +#define ARM_DEBUG_ARCH_V8_2 8 +#define ARM_DEBUG_ARCH_V8_4 9 + +/* Breakpoint */ + +#define ARM_BREAKPOINT_EXECUTE 0 + +/* Watchpoints */ + +#define ARM_BREAKPOINT_LOAD 1 +#define ARM_BREAKPOINT_STORE 2 +#define ARM_FSR_ACCESS_MASK (1 << 11) + +/* Privilege Levels */ + +#define ARM_BREAKPOINT_PRIV 1 +#define ARM_BREAKPOINT_USER 2 + +/* Lengths */ + +#define ARM_BREAKPOINT_LEN_1 0x1 +#define ARM_BREAKPOINT_LEN_2 0x3 +#define ARM_BREAKPOINT_LEN_4 0xf +#define ARM_BREAKPOINT_LEN_8 0xff + +/* Limits */ + +#define ARM_MAX_BREAKPOINT 16 +#define ARM_MAX_WATCHPOINT 16 + +/* DSCR method of entry bits. */ + +#define ARM_DSCR_MOE(x) ((x >> 2) & 0xf) +#define ARM_ENTRY_BREAKPOINT 0x1 +#define ARM_ENTRY_ASYNC_WATCHPOINT 0x2 +#define ARM_ENTRY_CFI_BREAKPOINT 0x3 +#define ARM_ENTRY_SYNC_WATCHPOINT 0xa + +/* DSCR monitor/halting bits. */ + +#define ARM_DSCR_HDBGEN (1 << 14) +#define ARM_DSCR_MDBGEN (1 << 15) + +/* OSLSR os lock model bits */ + +#define ARM_OSLSR_OSLM0 (1 << 0) + +/* opcode2 numbers for the co-processor instructions. */ + +#define ARM_OP2_BVR 4 +#define ARM_OP2_BCR 5 +#define ARM_OP2_WVR 6 +#define ARM_OP2_WCR 7 + +/* Base register numbers for the debug registers. */ + +#define ARM_BASE_BVR 64 +#define ARM_BASE_BCR 80 +#define ARM_BASE_WVR 96 +#define ARM_BASE_WCR 112 + +/* Accessor macros for the debug registers. */ +#define ARM_DBG_READ(N, M, OP2, VAL) \ + do { \ + asm volatile("mrc p14, 0, %0, " #N "," #M ", " #OP2 : "=r" (VAL)); \ + } while (0) + +#define ARM_DBG_WRITE(N, M, OP2, VAL) \ + do { \ + asm volatile("mcr p14, 0, %0, " #N "," #M ", " #OP2 : : "r" (VAL)); \ + } while (0) + +#define READ_WB_REG_CASE(OP2, M, VAL) \ + case ((OP2 << 4) + M): \ + ARM_DBG_READ(c0, c ## M, OP2, VAL); \ + break + +#define WRITE_WB_REG_CASE(OP2, M, VAL) \ + case ((OP2 << 4) + M): \ + ARM_DBG_WRITE(c0, c ## M, OP2, VAL); \ + break + +#define GEN_READ_WB_REG_CASES(OP2, VAL) \ + READ_WB_REG_CASE(OP2, 0, VAL); \ + READ_WB_REG_CASE(OP2, 1, VAL); \ + READ_WB_REG_CASE(OP2, 2, VAL); \ + READ_WB_REG_CASE(OP2, 3, VAL); \ + READ_WB_REG_CASE(OP2, 4, VAL); \ + READ_WB_REG_CASE(OP2, 5, VAL); \ + READ_WB_REG_CASE(OP2, 6, VAL); \ + READ_WB_REG_CASE(OP2, 7, VAL); \ + READ_WB_REG_CASE(OP2, 8, VAL); \ + READ_WB_REG_CASE(OP2, 9, VAL); \ + READ_WB_REG_CASE(OP2, 10, VAL); \ + READ_WB_REG_CASE(OP2, 11, VAL); \ + READ_WB_REG_CASE(OP2, 12, VAL); \ + READ_WB_REG_CASE(OP2, 13, VAL); \ + READ_WB_REG_CASE(OP2, 14, VAL); \ + READ_WB_REG_CASE(OP2, 15, VAL) + +#define GEN_WRITE_WB_REG_CASES(OP2, VAL) \ + WRITE_WB_REG_CASE(OP2, 0, VAL); \ + WRITE_WB_REG_CASE(OP2, 1, VAL); \ + WRITE_WB_REG_CASE(OP2, 2, VAL); \ + WRITE_WB_REG_CASE(OP2, 3, VAL); \ + WRITE_WB_REG_CASE(OP2, 4, VAL); \ + WRITE_WB_REG_CASE(OP2, 5, VAL); \ + WRITE_WB_REG_CASE(OP2, 6, VAL); \ + WRITE_WB_REG_CASE(OP2, 7, VAL); \ + WRITE_WB_REG_CASE(OP2, 8, VAL); \ + WRITE_WB_REG_CASE(OP2, 9, VAL); \ + WRITE_WB_REG_CASE(OP2, 10, VAL); \ + WRITE_WB_REG_CASE(OP2, 11, VAL); \ + WRITE_WB_REG_CASE(OP2, 12, VAL); \ + WRITE_WB_REG_CASE(OP2, 13, VAL); \ + WRITE_WB_REG_CASE(OP2, 14, VAL); \ + WRITE_WB_REG_CASE(OP2, 15, VAL) + +/**************************************************************************** + * Private Type + ****************************************************************************/ + +struct arch_hw_breakpoint_ctrl +{ + uint32_t __reserved : 9, + mismatch : 1, + : 9, + len : 8, + type : 2, + privilege : 2, + enabled : 1; +}; + +struct arch_hw_breakpoint +{ + uint32_t address; + uint32_t trigger; + struct arch_hw_breakpoint_ctrl step_ctrl; + struct arch_hw_breakpoint_ctrl ctrl; +}; + +struct arch_debug_s +{ + int type; + uint32_t addr; + size_t size; + debug_callback_t callback; + void *arg; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Number of BRP/WRP registers on this CPU. */ + +static int g_breakpoint_num; +static int g_watchpoint_num; + +/* Maximum supported watchpoint length. */ + +static uint8_t g_max_watchpoint_len; + +static struct arch_debug_s g_breakpoints[ARM_MAX_BREAKPOINT]; +static struct arch_debug_s g_watchpoints[ARM_MAX_WATCHPOINT]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static uint32_t read_wb_reg(int n) +{ + uint32_t val = 0; + + switch (n) + { + GEN_READ_WB_REG_CASES(ARM_OP2_BVR, val); + GEN_READ_WB_REG_CASES(ARM_OP2_BCR, val); + GEN_READ_WB_REG_CASES(ARM_OP2_WVR, val); + GEN_READ_WB_REG_CASES(ARM_OP2_WCR, val); + default: + binfo("attempt to read from unknown breakpoint register %d\n", n); + } + + return val; +} + +static void write_wb_reg(int n, uint32_t val) +{ + switch (n) + { + GEN_WRITE_WB_REG_CASES(ARM_OP2_BVR, val); + GEN_WRITE_WB_REG_CASES(ARM_OP2_BCR, val); + GEN_WRITE_WB_REG_CASES(ARM_OP2_WVR, val); + GEN_WRITE_WB_REG_CASES(ARM_OP2_WCR, val); + default: + binfo("attempt to write to unknown breakpoint register %d\n", n); + } +} + +static uint32_t encode_ctrl_reg(struct arch_hw_breakpoint_ctrl *ctrl) +{ + return (ctrl->mismatch << 22) | (ctrl->len << 5) | (ctrl->type << 3) | + (ctrl->privilege << 1) | ctrl->enabled; +} + +/* Determine debug architecture. */ + +static uint8_t get_debug_arch(void) +{ + uint32_t didr; + + /* Do we implement the extended CPUID interface? */ + + if (((up_read_cpuid() >> 16) & 0xf) != 0xf) + { + binfo("CPUID feature registers not supported. " + "Assuming v6 debug is present.\n"); + return ARM_DEBUG_ARCH_V6; + } + + ARM_DBG_READ(c0, c0, 0, didr); + return (didr >> 16) & 0xf; +} + +/* Check if 8-bit byte-address select is available. + * This clobbers WRP 0. + */ + +static uint8_t get_max_wp_len(void) +{ + struct arch_hw_breakpoint_ctrl ctrl; + uint32_t ctrl_reg; + uint8_t size = 4; + + if (get_debug_arch() < ARM_DEBUG_ARCH_V7_ECP14) + { + goto out; + } + + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.len = ARM_BREAKPOINT_LEN_8; + ctrl_reg = encode_ctrl_reg(&ctrl); + + write_wb_reg(ARM_BASE_WVR, 0); + write_wb_reg(ARM_BASE_WCR, ctrl_reg); + if ((read_wb_reg(ARM_BASE_WCR) & ctrl_reg) == ctrl_reg) + { + size = 8; + } + +out: + return size; +} + +/* Determine architecture is supported */ + +static int debug_arch_supported(void) +{ + uint8_t arch = get_debug_arch(); + + /* We don't support the memory-mapped interface. */ + + return (arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14) || Review Comment: So can i consider moving this file to the common folder? Because hwdebug in the Linux kernel is a common implementation, by judging the arch -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org