arm64: Support hardware debug
Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
This commit is contained in:
parent
3c2b203286
commit
1df6aa92f9
7 changed files with 601 additions and 0 deletions
|
|
@ -343,6 +343,7 @@ config ARCH_CPU_UNKNOWN
|
|||
default n
|
||||
select ARCH_ARMV8A
|
||||
select ARCH_HAVE_TRUSTZONE
|
||||
select ARCH_HAVE_DEBUG
|
||||
select ARCH_DCACHE
|
||||
select ARCH_ICACHE
|
||||
select ARCH_HAVE_MMU
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ if(CONFIG_ARM64_GIC_VERSION EQUAL 2)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARCH_HAVE_DEBUG)
|
||||
list(APPEND SRCS arm64_hwdebug.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARCH_HAVE_EL3)
|
||||
list(APPEND SRCS arm64_smccc.S)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -67,6 +67,10 @@ CMN_CSRCS += arm64_gicv2m.c
|
|||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_ARCH_HAVE_DEBUG),)
|
||||
CMN_CSRCS += arm64_hwdebug.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_HAVE_EL3),y)
|
||||
CMN_ASRCS += arm64_smccc.S
|
||||
endif
|
||||
|
|
|
|||
460
arch/arm64/src/common/arm64_hwdebug.c
Normal file
460
arch/arm64/src/common/arm64_hwdebug.c
Normal file
|
|
@ -0,0 +1,460 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_hwdebug.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 <nuttx/mm/kasan.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "arm64_fatal.h"
|
||||
#include "arm64_hwdebug.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define ARM64_DBGBWCR_VAL(type, len) \
|
||||
(arm64_convert_type(type) | arm64_convert_size(len) | \
|
||||
ARM64_DBGBCR_PAC_ALL | ARM64_DBGBWCR_E)
|
||||
|
||||
#define ARM64_MASK_ADDR(addr) \
|
||||
((uint64_t)kasan_clear_tag((void *)addr) & ~0x3)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type
|
||||
****************************************************************************/
|
||||
|
||||
struct arm64_debugpoint_s
|
||||
{
|
||||
int type;
|
||||
void *addr;
|
||||
size_t size;
|
||||
debug_callback_t callback;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct arm64_debug_s
|
||||
{
|
||||
/* Breakpoint currently in use for each BRP, WRP */
|
||||
|
||||
struct arm64_debugpoint_s brps[ID_AA64DFR0_MAX_BRPS];
|
||||
struct arm64_debugpoint_s wrps[ID_AA64DFR0_MAX_WRPS];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct arm64_debug_s g_arm64_debug[CONFIG_SMP_NCPUS];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t arm64_convert_type(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DEBUGPOINT_WATCHPOINT_RO:
|
||||
return ARM64_DBGBWCR_LSC_LOAD << ARM64_DBGBWCR_LSC_OFFSET;
|
||||
|
||||
case DEBUGPOINT_WATCHPOINT_WO:
|
||||
return ARM64_DBGBWCR_LSC_STORE << ARM64_DBGBWCR_LSC_OFFSET;
|
||||
|
||||
case DEBUGPOINT_WATCHPOINT_RW:
|
||||
return (ARM64_DBGBWCR_LSC_LOAD | ARM64_DBGBWCR_LSC_STORE)
|
||||
<< ARM64_DBGBWCR_LSC_OFFSET;
|
||||
|
||||
case DEBUGPOINT_BREAKPOINT:
|
||||
case DEBUGPOINT_STEPPOINT:
|
||||
default:
|
||||
return ARM64_DBGBWCR_LSC_EXECUTE << ARM64_DBGBWCR_LSC_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t arm64_convert_size(size_t len)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 1:
|
||||
return ARM64_DBGBWCR_BAS_LEN_1 << ARM64_DBGBWCR_BAS_OFFSET;
|
||||
case 2:
|
||||
return ARM64_DBGBWCR_BAS_LEN_2 << ARM64_DBGBWCR_BAS_OFFSET;
|
||||
case 3:
|
||||
return ARM64_DBGBWCR_BAS_LEN_3 << ARM64_DBGBWCR_BAS_OFFSET;
|
||||
case 4:
|
||||
return ARM64_DBGBWCR_BAS_LEN_4 << ARM64_DBGBWCR_BAS_OFFSET;
|
||||
case 5:
|
||||
return ARM64_DBGBWCR_BAS_LEN_5 << ARM64_DBGBWCR_BAS_OFFSET;
|
||||
case 6:
|
||||
return ARM64_DBGBWCR_BAS_LEN_6 << ARM64_DBGBWCR_BAS_OFFSET;
|
||||
case 7:
|
||||
return ARM64_DBGBWCR_BAS_LEN_7 << ARM64_DBGBWCR_BAS_OFFSET;
|
||||
case 8:
|
||||
default:
|
||||
return ARM64_DBGBWCR_BAS_LEN_8 << ARM64_DBGBWCR_BAS_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine number of usable WRPs available. */
|
||||
|
||||
static int arm64_get_num_wrps(void)
|
||||
{
|
||||
return (read_sysreg(id_aa64dfr0_el1) >> ID_AA64DFR0_EL1_WRPS_OFFSET)
|
||||
& ID_AA64DFR0_EL1_WRPS_MASK;
|
||||
}
|
||||
|
||||
/* Determine number of usable BRPs available. */
|
||||
|
||||
static int arm64_get_num_brps(void)
|
||||
{
|
||||
return (read_sysreg(id_aa64dfr0_el1) >> ID_AA64DFR0_EL1_BRPS_OFFSET)
|
||||
& ID_AA64DFR0_EL1_BRPS_MASK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm64_watchpoint_add
|
||||
*
|
||||
* Description:
|
||||
* Add a watchpoint on the address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* type - The type of the watchpoint
|
||||
* addr - The address to be watched
|
||||
* size - The size of the address to be watched
|
||||
*
|
||||
* Returned Value:
|
||||
* Index in wprs array on success; a negated errno value on failure
|
||||
*
|
||||
* Notes:
|
||||
* The size of the watchpoint is determined by the hardware.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int arm64_watchpoint_add(int type, uint64_t addr, size_t size)
|
||||
{
|
||||
int num = arm64_get_num_wrps();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (!(ARM64_DBG_GETN(wcr, i) & ARM64_DBGBWCR_E))
|
||||
{
|
||||
ARM64_DBG_SETN(wvr, i, ARM64_MASK_ADDR(addr));
|
||||
ARM64_DBG_SETN(wcr, i, ARM64_DBGBWCR_VAL(type, size));
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm64_watchpoint_remove
|
||||
*
|
||||
* Description:
|
||||
* Remove a watchpoint on the address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addr - The address to be watched.
|
||||
*
|
||||
* Returned Value:
|
||||
* Index in wprs array on success; a negated errno value on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int arm64_watchpoint_remove(uint64_t addr)
|
||||
{
|
||||
int num = arm64_get_num_wrps();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (ARM64_DBG_GETN(wvr, i) == ARM64_MASK_ADDR(addr))
|
||||
{
|
||||
ARM64_DBG_SETN(wcr, i, 0);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm64_breakpoint_add
|
||||
*
|
||||
* Description:
|
||||
* Add a breakpoint on addr.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addr - The address to break.
|
||||
*
|
||||
* Returned Value:
|
||||
* Index in bprs array on success; a negated errno value on failure
|
||||
*
|
||||
* Notes:
|
||||
* 1. If breakpoint is already set, it will do nothing.
|
||||
* 2. If all comparators are in use, it will return -1.
|
||||
* 3. When the breakpoint trigger, if enable monitor exception already ,
|
||||
* will cause a debug monitor exception, oaddr=0x4020392ctherwise will
|
||||
* cause a hard fault.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int arm64_breakpoint_add(uintptr_t addr)
|
||||
{
|
||||
int num = arm64_get_num_brps();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (!(ARM64_DBG_GETN(bcr, i) & ARM64_DBGBWCR_E))
|
||||
{
|
||||
ARM64_DBG_SETN(bvr, i, ARM64_MASK_ADDR(addr));
|
||||
ARM64_DBG_SETN(bcr, i,
|
||||
ARM64_DBGBWCR_VAL(DEBUGPOINT_BREAKPOINT, 8));
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm64_breakpoint_remove
|
||||
*
|
||||
* Description:
|
||||
* Remove a breakpoint on addr.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addr - The address to remove.
|
||||
*
|
||||
* Returned Value:
|
||||
* Index in bprs array on success; a negated errno value on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int arm64_breakpoint_remove(uintptr_t addr)
|
||||
{
|
||||
int num = arm64_get_num_brps();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (ARM64_DBG_GETN(bvr, i) == ARM64_MASK_ADDR(addr))
|
||||
{
|
||||
ARM64_DBG_SETN(bcr, i, 0);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int arm64_watchpoint_match(uint64_t *regs, uint64_t far, uint64_t esr)
|
||||
{
|
||||
struct arm64_debugpoint_s *dp = g_arm64_debug[this_cpu()].wrps;
|
||||
int num = arm64_get_num_wrps();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (ARM64_MASK_ADDR(dp[i].addr) == ARM64_MASK_ADDR(far))
|
||||
{
|
||||
dp[i].callback(dp[i].type, dp[i].addr,
|
||||
dp[i].size, dp[i].arg);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
static int arm64_breakpoint_match(uint64_t *regs, uint64_t far, uint64_t esr)
|
||||
{
|
||||
struct arm64_debugpoint_s *dp = g_arm64_debug[this_cpu()].brps;
|
||||
int num = arm64_get_num_brps();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (ARM64_MASK_ADDR(dp[i].addr) == ARM64_MASK_ADDR(up_getusrpc(regs)))
|
||||
{
|
||||
dp[i].callback(dp[i].type, dp[i].addr,
|
||||
dp[i].size, dp[i].arg);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm64_enable_dbgmonitor
|
||||
*
|
||||
* Description:
|
||||
* This function enables the debug monitor exception.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arm64_enable_dbgmonitor(void)
|
||||
{
|
||||
uint32_t mdscr;
|
||||
|
||||
/* Determine how many BRPs/WRPs are available.
|
||||
* And work out the maximum supported watchpoint length.
|
||||
*/
|
||||
|
||||
binfo("found %d breakpoint and %d watchpoint registers.\n",
|
||||
arm64_get_num_brps(), arm64_get_num_wrps());
|
||||
|
||||
mdscr = read_sysreg(mdscr_el1);
|
||||
mdscr |= ARM64_MDSCR_EL1_MDE | ARM64_MDSCR_EL1_KDE;
|
||||
write_sysreg(mdscr, mdscr_el1);
|
||||
|
||||
arm64_register_debug_hook(DBG_ESR_EVT_HWBP, arm64_breakpoint_match);
|
||||
arm64_register_debug_hook(DBG_ESR_EVT_HWWP, arm64_watchpoint_match);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_debugpoint_add
|
||||
*
|
||||
* Description:
|
||||
* Add a debugpoint.
|
||||
*
|
||||
* Input Parameters:
|
||||
* type - The debugpoint type. optional value:
|
||||
* DEBUGPOINT_WATCHPOINT_RO - Read only watchpoint.
|
||||
* DEBUGPOINT_WATCHPOINT_WO - Write only watchpoint.
|
||||
* DEBUGPOINT_WATCHPOINT_RW - Read and write watchpoint.
|
||||
* DEBUGPOINT_BREAKPOINT - Breakpoint.
|
||||
* DEBUGPOINT_STEPPOINT - Single step.
|
||||
* addr - The address to be debugged.
|
||||
* size - The watchpoint size. only for watchpoint.
|
||||
* callback - The callback function when debugpoint triggered.
|
||||
* if NULL, the debugpoint will be removed.
|
||||
* arg - The argument of callback function.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_debugpoint_add(int type, void *addr, size_t size,
|
||||
debug_callback_t callback, void *arg)
|
||||
{
|
||||
struct arm64_debugpoint_s *dp;
|
||||
int cpu = this_cpu();
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (type == DEBUGPOINT_BREAKPOINT)
|
||||
{
|
||||
ret = arm64_breakpoint_add((uintptr_t)addr);
|
||||
dp = g_arm64_debug[cpu].brps;
|
||||
}
|
||||
else if (type == DEBUGPOINT_WATCHPOINT_RO ||
|
||||
type == DEBUGPOINT_WATCHPOINT_WO ||
|
||||
type == DEBUGPOINT_WATCHPOINT_RW)
|
||||
{
|
||||
ret = arm64_watchpoint_add(type, (uintptr_t)addr, size);
|
||||
dp = g_arm64_debug[cpu].wrps;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
dp[ret].type = type;
|
||||
dp[ret].addr = addr;
|
||||
dp[ret].size = size;
|
||||
dp[ret].callback = callback;
|
||||
dp[ret].arg = arg;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_debugpoint_remove
|
||||
*
|
||||
* Description:
|
||||
* Remove a debugpoint.
|
||||
*
|
||||
* Input Parameters:
|
||||
* type - The debugpoint type. optional value:
|
||||
* DEBUGPOINT_WATCHPOINT_RO - Read only watchpoint.
|
||||
* DEBUGPOINT_WATCHPOINT_WO - Write only watchpoint.
|
||||
* DEBUGPOINT_WATCHPOINT_RW - Read and write watchpoint.
|
||||
* DEBUGPOINT_BREAKPOINT - Breakpoint.
|
||||
* DEBUGPOINT_STEPPOINT - Single step.
|
||||
* addr - The address to be debugged.
|
||||
* size - The watchpoint size. only for watchpoint.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int up_debugpoint_remove(int type, void *addr, size_t size)
|
||||
{
|
||||
struct arm64_debugpoint_s *dp;
|
||||
int cpu = this_cpu();
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (type == DEBUGPOINT_BREAKPOINT)
|
||||
{
|
||||
ret = arm64_breakpoint_remove((uintptr_t)addr);
|
||||
dp = g_arm64_debug[cpu].brps;
|
||||
}
|
||||
else if (type == DEBUGPOINT_WATCHPOINT_RO ||
|
||||
type == DEBUGPOINT_WATCHPOINT_WO ||
|
||||
type == DEBUGPOINT_WATCHPOINT_RW)
|
||||
{
|
||||
ret = arm64_watchpoint_remove((uintptr_t)addr);
|
||||
dp = g_arm64_debug[cpu].wrps;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
dp[ret].type = 0;
|
||||
dp[ret].addr = 0;
|
||||
dp[ret].size = 0;
|
||||
dp[ret].callback = NULL;
|
||||
dp[ret].arg = NULL;
|
||||
|
||||
return OK;
|
||||
}
|
||||
124
arch/arm64/src/common/arm64_hwdebug.h
Normal file
124
arch/arm64/src/common/arm64_hwdebug.h
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_hwdebug.h
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_COMMON_ARM64_HWDEBUG_H
|
||||
#define __ARCH_ARM64_SRC_COMMON_ARM64_HWDEBUG_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/bits.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define ARM64_DBGBWCR_E BIT(0)
|
||||
|
||||
#define ARM64_DBGBWCR_LSC_OFFSET 3
|
||||
#define ARM64_DBGBWCR_LSC_EXECUTE 0
|
||||
#define ARM64_DBGBWCR_LSC_LOAD 1
|
||||
#define ARM64_DBGBWCR_LSC_STORE 2
|
||||
|
||||
#define ARM64_DBGBWCR_BAS_OFFSET 5
|
||||
#define ARM64_DBGBWCR_BAS_LEN_1 0x1
|
||||
#define ARM64_DBGBWCR_BAS_LEN_2 0x3
|
||||
#define ARM64_DBGBWCR_BAS_LEN_3 0x7
|
||||
#define ARM64_DBGBWCR_BAS_LEN_4 0xf
|
||||
#define ARM64_DBGBWCR_BAS_LEN_5 0x1f
|
||||
#define ARM64_DBGBWCR_BAS_LEN_6 0x3f
|
||||
#define ARM64_DBGBWCR_BAS_LEN_7 0x7f
|
||||
#define ARM64_DBGBWCR_BAS_LEN_8 0xff
|
||||
|
||||
#define ARM64_DBGBCR_PAC_PRIV BIT(1)
|
||||
#define ARM64_DBGBCR_PAC_USER BIT(2)
|
||||
#define ARM64_DBGBCR_PAC_ALL (ARM64_DBGBCR_PAC_PRIV | ARM64_DBGBCR_PAC_USER)
|
||||
|
||||
#define ARM64_MDSCR_EL1_KDE BIT(13)
|
||||
#define ARM64_MDSCR_EL1_MDE BIT(15)
|
||||
|
||||
#define ID_AA64DFR0_EL1_BRPS_MASK 0xf
|
||||
#define ID_AA64DFR0_EL1_BRPS_OFFSET 12
|
||||
|
||||
#define ID_AA64DFR0_EL1_WRPS_MASK 0xf
|
||||
#define ID_AA64DFR0_EL1_WRPS_OFFSET 20
|
||||
|
||||
#define ID_AA64DFR0_MAX_BRPS 16
|
||||
#define ID_AA64DFR0_MAX_WRPS 16
|
||||
|
||||
#define ARM64_DBG_SET_CASE(reg, n, val) \
|
||||
case n: \
|
||||
write_sysreg(val, dbg##reg##n##_el1); \
|
||||
break;
|
||||
|
||||
#define ARM64_DBG_GET_CASE(reg, n, val) \
|
||||
case n: \
|
||||
val = read_sysreg(dbg##reg##n##_el1); \
|
||||
break;
|
||||
|
||||
#define ARM64_DBG_SETN(reg, n, val) \
|
||||
switch (n) \
|
||||
{ \
|
||||
ARM64_DBG_SET_CASE(reg, 0, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 1, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 2, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 3, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 4, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 5, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 6, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 7, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 8, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 9, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 10, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 11, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 12, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 13, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 14, val) \
|
||||
ARM64_DBG_SET_CASE(reg, 15, val) \
|
||||
}
|
||||
|
||||
#define ARM64_DBG_GETN(reg, n) \
|
||||
({ \
|
||||
uint64_t _val = 0; \
|
||||
switch (n) \
|
||||
{ \
|
||||
ARM64_DBG_GET_CASE(reg, 0, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 1, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 2, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 3, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 4, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 5, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 6, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 7, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 8, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 9, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 10, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 11, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 12, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 13, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 14, _val) \
|
||||
ARM64_DBG_GET_CASE(reg, 15, _val) \
|
||||
} \
|
||||
_val; \
|
||||
})
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_COMMON_ARM64_HWDEBUG_H */
|
||||
|
|
@ -217,5 +217,9 @@ void up_initialize(void)
|
|||
arm64_fpu_procfs_register();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_HAVE_DEBUG
|
||||
arm64_enable_dbgmonitor();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -393,6 +393,10 @@ size_t arm64_stack_check(void *stackbase, size_t nbytes);
|
|||
void arm64_stack_color(void *stackbase, size_t nbytes);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_HAVE_DEBUG
|
||||
void arm64_enable_dbgmonitor(void);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue