Implement hardware triggers that match spec.
It's basically working, but the following corner cases are failing: TriggerDmode TriggerLoadAddressInstant TriggerStoreAddressInstant__archive__
parent
526bbc5284
commit
cf1dc0b6cb
|
@ -18,6 +18,7 @@
|
|||
#define MSTATUS_XS 0x00018000
|
||||
#define MSTATUS_MPRV 0x00020000
|
||||
#define MSTATUS_PUM 0x00040000
|
||||
#define MSTATUS_MXR 0x00080000
|
||||
#define MSTATUS_VM 0x1F000000
|
||||
#define MSTATUS32_SD 0x80000000
|
||||
#define MSTATUS64_SD 0x8000000000000000
|
||||
|
@ -36,7 +37,6 @@
|
|||
#define DCSR_XDEBUGVER (3U<<30)
|
||||
#define DCSR_NDRESET (1<<29)
|
||||
#define DCSR_FULLRESET (1<<28)
|
||||
#define DCSR_HWBPCOUNT (0xfff<<16)
|
||||
#define DCSR_EBREAKM (1<<15)
|
||||
#define DCSR_EBREAKH (1<<14)
|
||||
#define DCSR_EBREAKS (1<<13)
|
||||
|
@ -56,6 +56,39 @@
|
|||
#define DCSR_CAUSE_STEP 4
|
||||
#define DCSR_CAUSE_HALT 5
|
||||
|
||||
#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
|
||||
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
|
||||
#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
|
||||
|
||||
#define MCONTROL_SELECT (1<<19)
|
||||
#define MCONTROL_TIMING (1<<18)
|
||||
#define MCONTROL_ACTION (0x3f<<12)
|
||||
#define MCONTROL_CHAIN (1<<11)
|
||||
#define MCONTROL_MATCH (0xf<<7)
|
||||
#define MCONTROL_M (1<<6)
|
||||
#define MCONTROL_H (1<<5)
|
||||
#define MCONTROL_S (1<<4)
|
||||
#define MCONTROL_U (1<<3)
|
||||
#define MCONTROL_EXECUTE (1<<2)
|
||||
#define MCONTROL_STORE (1<<1)
|
||||
#define MCONTROL_LOAD (1<<0)
|
||||
|
||||
#define MCONTROL_TYPE_NONE 0
|
||||
#define MCONTROL_TYPE_MATCH 2
|
||||
|
||||
#define MCONTROL_ACTION_DEBUG_EXCEPTION 0
|
||||
#define MCONTROL_ACTION_DEBUG_MODE 1
|
||||
#define MCONTROL_ACTION_TRACE_START 2
|
||||
#define MCONTROL_ACTION_TRACE_STOP 3
|
||||
#define MCONTROL_ACTION_TRACE_EMIT 4
|
||||
|
||||
#define MCONTROL_MATCH_EQUAL 0
|
||||
#define MCONTROL_MATCH_NAPOT 1
|
||||
#define MCONTROL_MATCH_GE 2
|
||||
#define MCONTROL_MATCH_LT 3
|
||||
#define MCONTROL_MATCH_MASK_LOW 4
|
||||
#define MCONTROL_MATCH_MASK_HIGH 5
|
||||
|
||||
#define MIP_SSIP (1 << IRQ_S_SOFT)
|
||||
#define MIP_HSIP (1 << IRQ_H_SOFT)
|
||||
#define MIP_MSIP (1 << IRQ_M_SOFT)
|
||||
|
@ -102,42 +135,18 @@
|
|||
|
||||
// page table entry (PTE) fields
|
||||
#define PTE_V 0x001 // Valid
|
||||
#define PTE_TYPE 0x01E // Type
|
||||
#define PTE_R 0x020 // Referenced
|
||||
#define PTE_D 0x040 // Dirty
|
||||
#define PTE_SOFT 0x380 // Reserved for Software
|
||||
|
||||
#define PTE_TYPE_TABLE 0x00
|
||||
#define PTE_TYPE_TABLE_GLOBAL 0x02
|
||||
#define PTE_TYPE_URX_SR 0x04
|
||||
#define PTE_TYPE_URWX_SRW 0x06
|
||||
#define PTE_TYPE_UR_SR 0x08
|
||||
#define PTE_TYPE_URW_SRW 0x0A
|
||||
#define PTE_TYPE_URX_SRX 0x0C
|
||||
#define PTE_TYPE_URWX_SRWX 0x0E
|
||||
#define PTE_TYPE_SR 0x10
|
||||
#define PTE_TYPE_SRW 0x12
|
||||
#define PTE_TYPE_SRX 0x14
|
||||
#define PTE_TYPE_SRWX 0x16
|
||||
#define PTE_TYPE_SR_GLOBAL 0x18
|
||||
#define PTE_TYPE_SRW_GLOBAL 0x1A
|
||||
#define PTE_TYPE_SRX_GLOBAL 0x1C
|
||||
#define PTE_TYPE_SRWX_GLOBAL 0x1E
|
||||
#define PTE_R 0x002 // Read
|
||||
#define PTE_W 0x004 // Write
|
||||
#define PTE_X 0x008 // Execute
|
||||
#define PTE_U 0x010 // User
|
||||
#define PTE_G 0x020 // Global
|
||||
#define PTE_A 0x040 // Accessed
|
||||
#define PTE_D 0x080 // Dirty
|
||||
#define PTE_SOFT 0x300 // Reserved for Software
|
||||
|
||||
#define PTE_PPN_SHIFT 10
|
||||
|
||||
#define PTE_TABLE(PTE) ((0x0000000AU >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_UR(PTE) ((0x0000AAA0U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_UW(PTE) ((0x00008880U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_UX(PTE) ((0x0000A0A0U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_SR(PTE) ((0xAAAAAAA0U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_SW(PTE) ((0x88888880U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_SX(PTE) ((0xA0A0A000U >> ((PTE) & 0x1F)) & 1)
|
||||
|
||||
#define PTE_CHECK_PERM(PTE, SUPERVISOR, STORE, FETCH) \
|
||||
((STORE) ? ((SUPERVISOR) ? PTE_SW(PTE) : PTE_UW(PTE)) : \
|
||||
(FETCH) ? ((SUPERVISOR) ? PTE_SX(PTE) : PTE_UX(PTE)) : \
|
||||
((SUPERVISOR) ? PTE_SR(PTE) : PTE_UR(PTE)))
|
||||
#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
|
||||
|
||||
#ifdef __riscv
|
||||
|
||||
|
@ -666,6 +675,35 @@
|
|||
#define CSR_CYCLE 0xc00
|
||||
#define CSR_TIME 0xc01
|
||||
#define CSR_INSTRET 0xc02
|
||||
#define CSR_HPMCOUNTER3 0xc03
|
||||
#define CSR_HPMCOUNTER4 0xc04
|
||||
#define CSR_HPMCOUNTER5 0xc05
|
||||
#define CSR_HPMCOUNTER6 0xc06
|
||||
#define CSR_HPMCOUNTER7 0xc07
|
||||
#define CSR_HPMCOUNTER8 0xc08
|
||||
#define CSR_HPMCOUNTER9 0xc09
|
||||
#define CSR_HPMCOUNTER10 0xc0a
|
||||
#define CSR_HPMCOUNTER11 0xc0b
|
||||
#define CSR_HPMCOUNTER12 0xc0c
|
||||
#define CSR_HPMCOUNTER13 0xc0d
|
||||
#define CSR_HPMCOUNTER14 0xc0e
|
||||
#define CSR_HPMCOUNTER15 0xc0f
|
||||
#define CSR_HPMCOUNTER16 0xc10
|
||||
#define CSR_HPMCOUNTER17 0xc11
|
||||
#define CSR_HPMCOUNTER18 0xc12
|
||||
#define CSR_HPMCOUNTER19 0xc13
|
||||
#define CSR_HPMCOUNTER20 0xc14
|
||||
#define CSR_HPMCOUNTER21 0xc15
|
||||
#define CSR_HPMCOUNTER22 0xc16
|
||||
#define CSR_HPMCOUNTER23 0xc17
|
||||
#define CSR_HPMCOUNTER24 0xc18
|
||||
#define CSR_HPMCOUNTER25 0xc19
|
||||
#define CSR_HPMCOUNTER26 0xc1a
|
||||
#define CSR_HPMCOUNTER27 0xc1b
|
||||
#define CSR_HPMCOUNTER28 0xc1c
|
||||
#define CSR_HPMCOUNTER29 0xc1d
|
||||
#define CSR_HPMCOUNTER30 0xc1e
|
||||
#define CSR_HPMCOUNTER31 0xc1f
|
||||
#define CSR_SSTATUS 0x100
|
||||
#define CSR_SIE 0x104
|
||||
#define CSR_STVEC 0x105
|
||||
|
@ -675,11 +713,8 @@
|
|||
#define CSR_SBADADDR 0x143
|
||||
#define CSR_SIP 0x144
|
||||
#define CSR_SPTBR 0x180
|
||||
#define CSR_SASID 0x181
|
||||
#define CSR_SCYCLE 0xd00
|
||||
#define CSR_STIME 0xd01
|
||||
#define CSR_SINSTRET 0xd02
|
||||
#define CSR_MSTATUS 0x300
|
||||
#define CSR_MISA 0x301
|
||||
#define CSR_MEDELEG 0x302
|
||||
#define CSR_MIDELEG 0x303
|
||||
#define CSR_MIE 0x304
|
||||
|
@ -689,38 +724,142 @@
|
|||
#define CSR_MCAUSE 0x342
|
||||
#define CSR_MBADADDR 0x343
|
||||
#define CSR_MIP 0x344
|
||||
#define CSR_MUCOUNTEREN 0x310
|
||||
#define CSR_MSCOUNTEREN 0x311
|
||||
#define CSR_MUCYCLE_DELTA 0x700
|
||||
#define CSR_MUTIME_DELTA 0x701
|
||||
#define CSR_MUINSTRET_DELTA 0x702
|
||||
#define CSR_MSCYCLE_DELTA 0x704
|
||||
#define CSR_MSTIME_DELTA 0x705
|
||||
#define CSR_MSINSTRET_DELTA 0x706
|
||||
#define CSR_TSELECT 0x7a0
|
||||
#define CSR_TDATA1 0x7a1
|
||||
#define CSR_TDATA2 0x7a2
|
||||
#define CSR_TDATA3 0x7a3
|
||||
#define CSR_DCSR 0x7b0
|
||||
#define CSR_DPC 0x7b1
|
||||
#define CSR_DSCRATCH 0x7b2
|
||||
#define CSR_MCYCLE 0xf00
|
||||
#define CSR_MTIME 0xf01
|
||||
#define CSR_MINSTRET 0xf02
|
||||
#define CSR_MISA 0xf10
|
||||
#define CSR_MCYCLE 0xb00
|
||||
#define CSR_MINSTRET 0xb02
|
||||
#define CSR_MHPMCOUNTER3 0xb03
|
||||
#define CSR_MHPMCOUNTER4 0xb04
|
||||
#define CSR_MHPMCOUNTER5 0xb05
|
||||
#define CSR_MHPMCOUNTER6 0xb06
|
||||
#define CSR_MHPMCOUNTER7 0xb07
|
||||
#define CSR_MHPMCOUNTER8 0xb08
|
||||
#define CSR_MHPMCOUNTER9 0xb09
|
||||
#define CSR_MHPMCOUNTER10 0xb0a
|
||||
#define CSR_MHPMCOUNTER11 0xb0b
|
||||
#define CSR_MHPMCOUNTER12 0xb0c
|
||||
#define CSR_MHPMCOUNTER13 0xb0d
|
||||
#define CSR_MHPMCOUNTER14 0xb0e
|
||||
#define CSR_MHPMCOUNTER15 0xb0f
|
||||
#define CSR_MHPMCOUNTER16 0xb10
|
||||
#define CSR_MHPMCOUNTER17 0xb11
|
||||
#define CSR_MHPMCOUNTER18 0xb12
|
||||
#define CSR_MHPMCOUNTER19 0xb13
|
||||
#define CSR_MHPMCOUNTER20 0xb14
|
||||
#define CSR_MHPMCOUNTER21 0xb15
|
||||
#define CSR_MHPMCOUNTER22 0xb16
|
||||
#define CSR_MHPMCOUNTER23 0xb17
|
||||
#define CSR_MHPMCOUNTER24 0xb18
|
||||
#define CSR_MHPMCOUNTER25 0xb19
|
||||
#define CSR_MHPMCOUNTER26 0xb1a
|
||||
#define CSR_MHPMCOUNTER27 0xb1b
|
||||
#define CSR_MHPMCOUNTER28 0xb1c
|
||||
#define CSR_MHPMCOUNTER29 0xb1d
|
||||
#define CSR_MHPMCOUNTER30 0xb1e
|
||||
#define CSR_MHPMCOUNTER31 0xb1f
|
||||
#define CSR_MUCOUNTEREN 0x320
|
||||
#define CSR_MSCOUNTEREN 0x321
|
||||
#define CSR_MHPMEVENT3 0x323
|
||||
#define CSR_MHPMEVENT4 0x324
|
||||
#define CSR_MHPMEVENT5 0x325
|
||||
#define CSR_MHPMEVENT6 0x326
|
||||
#define CSR_MHPMEVENT7 0x327
|
||||
#define CSR_MHPMEVENT8 0x328
|
||||
#define CSR_MHPMEVENT9 0x329
|
||||
#define CSR_MHPMEVENT10 0x32a
|
||||
#define CSR_MHPMEVENT11 0x32b
|
||||
#define CSR_MHPMEVENT12 0x32c
|
||||
#define CSR_MHPMEVENT13 0x32d
|
||||
#define CSR_MHPMEVENT14 0x32e
|
||||
#define CSR_MHPMEVENT15 0x32f
|
||||
#define CSR_MHPMEVENT16 0x330
|
||||
#define CSR_MHPMEVENT17 0x331
|
||||
#define CSR_MHPMEVENT18 0x332
|
||||
#define CSR_MHPMEVENT19 0x333
|
||||
#define CSR_MHPMEVENT20 0x334
|
||||
#define CSR_MHPMEVENT21 0x335
|
||||
#define CSR_MHPMEVENT22 0x336
|
||||
#define CSR_MHPMEVENT23 0x337
|
||||
#define CSR_MHPMEVENT24 0x338
|
||||
#define CSR_MHPMEVENT25 0x339
|
||||
#define CSR_MHPMEVENT26 0x33a
|
||||
#define CSR_MHPMEVENT27 0x33b
|
||||
#define CSR_MHPMEVENT28 0x33c
|
||||
#define CSR_MHPMEVENT29 0x33d
|
||||
#define CSR_MHPMEVENT30 0x33e
|
||||
#define CSR_MHPMEVENT31 0x33f
|
||||
#define CSR_MVENDORID 0xf11
|
||||
#define CSR_MARCHID 0xf12
|
||||
#define CSR_MIMPID 0xf13
|
||||
#define CSR_MHARTID 0xf14
|
||||
#define CSR_MRESET 0x7c2
|
||||
#define CSR_CYCLEH 0xc80
|
||||
#define CSR_TIMEH 0xc81
|
||||
#define CSR_INSTRETH 0xc82
|
||||
#define CSR_MUCYCLE_DELTAH 0x780
|
||||
#define CSR_MUTIME_DELTAH 0x781
|
||||
#define CSR_MUINSTRET_DELTAH 0x782
|
||||
#define CSR_MSCYCLE_DELTAH 0x784
|
||||
#define CSR_MSTIME_DELTAH 0x785
|
||||
#define CSR_MSINSTRET_DELTAH 0x786
|
||||
#define CSR_MCYCLEH 0xf80
|
||||
#define CSR_MTIMEH 0xf81
|
||||
#define CSR_MINSTRETH 0xf82
|
||||
#define CSR_HPMCOUNTER3H 0xc83
|
||||
#define CSR_HPMCOUNTER4H 0xc84
|
||||
#define CSR_HPMCOUNTER5H 0xc85
|
||||
#define CSR_HPMCOUNTER6H 0xc86
|
||||
#define CSR_HPMCOUNTER7H 0xc87
|
||||
#define CSR_HPMCOUNTER8H 0xc88
|
||||
#define CSR_HPMCOUNTER9H 0xc89
|
||||
#define CSR_HPMCOUNTER10H 0xc8a
|
||||
#define CSR_HPMCOUNTER11H 0xc8b
|
||||
#define CSR_HPMCOUNTER12H 0xc8c
|
||||
#define CSR_HPMCOUNTER13H 0xc8d
|
||||
#define CSR_HPMCOUNTER14H 0xc8e
|
||||
#define CSR_HPMCOUNTER15H 0xc8f
|
||||
#define CSR_HPMCOUNTER16H 0xc90
|
||||
#define CSR_HPMCOUNTER17H 0xc91
|
||||
#define CSR_HPMCOUNTER18H 0xc92
|
||||
#define CSR_HPMCOUNTER19H 0xc93
|
||||
#define CSR_HPMCOUNTER20H 0xc94
|
||||
#define CSR_HPMCOUNTER21H 0xc95
|
||||
#define CSR_HPMCOUNTER22H 0xc96
|
||||
#define CSR_HPMCOUNTER23H 0xc97
|
||||
#define CSR_HPMCOUNTER24H 0xc98
|
||||
#define CSR_HPMCOUNTER25H 0xc99
|
||||
#define CSR_HPMCOUNTER26H 0xc9a
|
||||
#define CSR_HPMCOUNTER27H 0xc9b
|
||||
#define CSR_HPMCOUNTER28H 0xc9c
|
||||
#define CSR_HPMCOUNTER29H 0xc9d
|
||||
#define CSR_HPMCOUNTER30H 0xc9e
|
||||
#define CSR_HPMCOUNTER31H 0xc9f
|
||||
#define CSR_MCYCLEH 0xb80
|
||||
#define CSR_MINSTRETH 0xb82
|
||||
#define CSR_MHPMCOUNTER3H 0xb83
|
||||
#define CSR_MHPMCOUNTER4H 0xb84
|
||||
#define CSR_MHPMCOUNTER5H 0xb85
|
||||
#define CSR_MHPMCOUNTER6H 0xb86
|
||||
#define CSR_MHPMCOUNTER7H 0xb87
|
||||
#define CSR_MHPMCOUNTER8H 0xb88
|
||||
#define CSR_MHPMCOUNTER9H 0xb89
|
||||
#define CSR_MHPMCOUNTER10H 0xb8a
|
||||
#define CSR_MHPMCOUNTER11H 0xb8b
|
||||
#define CSR_MHPMCOUNTER12H 0xb8c
|
||||
#define CSR_MHPMCOUNTER13H 0xb8d
|
||||
#define CSR_MHPMCOUNTER14H 0xb8e
|
||||
#define CSR_MHPMCOUNTER15H 0xb8f
|
||||
#define CSR_MHPMCOUNTER16H 0xb90
|
||||
#define CSR_MHPMCOUNTER17H 0xb91
|
||||
#define CSR_MHPMCOUNTER18H 0xb92
|
||||
#define CSR_MHPMCOUNTER19H 0xb93
|
||||
#define CSR_MHPMCOUNTER20H 0xb94
|
||||
#define CSR_MHPMCOUNTER21H 0xb95
|
||||
#define CSR_MHPMCOUNTER22H 0xb96
|
||||
#define CSR_MHPMCOUNTER23H 0xb97
|
||||
#define CSR_MHPMCOUNTER24H 0xb98
|
||||
#define CSR_MHPMCOUNTER25H 0xb99
|
||||
#define CSR_MHPMCOUNTER26H 0xb9a
|
||||
#define CSR_MHPMCOUNTER27H 0xb9b
|
||||
#define CSR_MHPMCOUNTER28H 0xb9c
|
||||
#define CSR_MHPMCOUNTER29H 0xb9d
|
||||
#define CSR_MHPMCOUNTER30H 0xb9e
|
||||
#define CSR_MHPMCOUNTER31H 0xb9f
|
||||
#define CAUSE_MISALIGNED_FETCH 0x0
|
||||
#define CAUSE_FAULT_FETCH 0x1
|
||||
#define CAUSE_ILLEGAL_INSTRUCTION 0x2
|
||||
|
@ -972,6 +1111,35 @@ DECLARE_CSR(fcsr, CSR_FCSR)
|
|||
DECLARE_CSR(cycle, CSR_CYCLE)
|
||||
DECLARE_CSR(time, CSR_TIME)
|
||||
DECLARE_CSR(instret, CSR_INSTRET)
|
||||
DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3)
|
||||
DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4)
|
||||
DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5)
|
||||
DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6)
|
||||
DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7)
|
||||
DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8)
|
||||
DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9)
|
||||
DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10)
|
||||
DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11)
|
||||
DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12)
|
||||
DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13)
|
||||
DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14)
|
||||
DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15)
|
||||
DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16)
|
||||
DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17)
|
||||
DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18)
|
||||
DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19)
|
||||
DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20)
|
||||
DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21)
|
||||
DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22)
|
||||
DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23)
|
||||
DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24)
|
||||
DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25)
|
||||
DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26)
|
||||
DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27)
|
||||
DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28)
|
||||
DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29)
|
||||
DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30)
|
||||
DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31)
|
||||
DECLARE_CSR(sstatus, CSR_SSTATUS)
|
||||
DECLARE_CSR(sie, CSR_SIE)
|
||||
DECLARE_CSR(stvec, CSR_STVEC)
|
||||
|
@ -981,11 +1149,8 @@ DECLARE_CSR(scause, CSR_SCAUSE)
|
|||
DECLARE_CSR(sbadaddr, CSR_SBADADDR)
|
||||
DECLARE_CSR(sip, CSR_SIP)
|
||||
DECLARE_CSR(sptbr, CSR_SPTBR)
|
||||
DECLARE_CSR(sasid, CSR_SASID)
|
||||
DECLARE_CSR(scycle, CSR_SCYCLE)
|
||||
DECLARE_CSR(stime, CSR_STIME)
|
||||
DECLARE_CSR(sinstret, CSR_SINSTRET)
|
||||
DECLARE_CSR(mstatus, CSR_MSTATUS)
|
||||
DECLARE_CSR(misa, CSR_MISA)
|
||||
DECLARE_CSR(medeleg, CSR_MEDELEG)
|
||||
DECLARE_CSR(mideleg, CSR_MIDELEG)
|
||||
DECLARE_CSR(mie, CSR_MIE)
|
||||
|
@ -995,38 +1160,142 @@ DECLARE_CSR(mepc, CSR_MEPC)
|
|||
DECLARE_CSR(mcause, CSR_MCAUSE)
|
||||
DECLARE_CSR(mbadaddr, CSR_MBADADDR)
|
||||
DECLARE_CSR(mip, CSR_MIP)
|
||||
DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN)
|
||||
DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN)
|
||||
DECLARE_CSR(mucycle_delta, CSR_MUCYCLE_DELTA)
|
||||
DECLARE_CSR(mutime_delta, CSR_MUTIME_DELTA)
|
||||
DECLARE_CSR(muinstret_delta, CSR_MUINSTRET_DELTA)
|
||||
DECLARE_CSR(mscycle_delta, CSR_MSCYCLE_DELTA)
|
||||
DECLARE_CSR(mstime_delta, CSR_MSTIME_DELTA)
|
||||
DECLARE_CSR(msinstret_delta, CSR_MSINSTRET_DELTA)
|
||||
DECLARE_CSR(tselect, CSR_TSELECT)
|
||||
DECLARE_CSR(tdata1, CSR_TDATA1)
|
||||
DECLARE_CSR(tdata2, CSR_TDATA2)
|
||||
DECLARE_CSR(tdata3, CSR_TDATA3)
|
||||
DECLARE_CSR(dcsr, CSR_DCSR)
|
||||
DECLARE_CSR(dpc, CSR_DPC)
|
||||
DECLARE_CSR(dscratch, CSR_DSCRATCH)
|
||||
DECLARE_CSR(mcycle, CSR_MCYCLE)
|
||||
DECLARE_CSR(mtime, CSR_MTIME)
|
||||
DECLARE_CSR(minstret, CSR_MINSTRET)
|
||||
DECLARE_CSR(misa, CSR_MISA)
|
||||
DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3)
|
||||
DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4)
|
||||
DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5)
|
||||
DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6)
|
||||
DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7)
|
||||
DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8)
|
||||
DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9)
|
||||
DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10)
|
||||
DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11)
|
||||
DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12)
|
||||
DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13)
|
||||
DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14)
|
||||
DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15)
|
||||
DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16)
|
||||
DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17)
|
||||
DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18)
|
||||
DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19)
|
||||
DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20)
|
||||
DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21)
|
||||
DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22)
|
||||
DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23)
|
||||
DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24)
|
||||
DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25)
|
||||
DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26)
|
||||
DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27)
|
||||
DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28)
|
||||
DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29)
|
||||
DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30)
|
||||
DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31)
|
||||
DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN)
|
||||
DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN)
|
||||
DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3)
|
||||
DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4)
|
||||
DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5)
|
||||
DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6)
|
||||
DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7)
|
||||
DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8)
|
||||
DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9)
|
||||
DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10)
|
||||
DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11)
|
||||
DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12)
|
||||
DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13)
|
||||
DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14)
|
||||
DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15)
|
||||
DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16)
|
||||
DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17)
|
||||
DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18)
|
||||
DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19)
|
||||
DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20)
|
||||
DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21)
|
||||
DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22)
|
||||
DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23)
|
||||
DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24)
|
||||
DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25)
|
||||
DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26)
|
||||
DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27)
|
||||
DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28)
|
||||
DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29)
|
||||
DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30)
|
||||
DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31)
|
||||
DECLARE_CSR(mvendorid, CSR_MVENDORID)
|
||||
DECLARE_CSR(marchid, CSR_MARCHID)
|
||||
DECLARE_CSR(mimpid, CSR_MIMPID)
|
||||
DECLARE_CSR(mhartid, CSR_MHARTID)
|
||||
DECLARE_CSR(mreset, CSR_MRESET)
|
||||
DECLARE_CSR(cycleh, CSR_CYCLEH)
|
||||
DECLARE_CSR(timeh, CSR_TIMEH)
|
||||
DECLARE_CSR(instreth, CSR_INSTRETH)
|
||||
DECLARE_CSR(mucycle_deltah, CSR_MUCYCLE_DELTAH)
|
||||
DECLARE_CSR(mutime_deltah, CSR_MUTIME_DELTAH)
|
||||
DECLARE_CSR(muinstret_deltah, CSR_MUINSTRET_DELTAH)
|
||||
DECLARE_CSR(mscycle_deltah, CSR_MSCYCLE_DELTAH)
|
||||
DECLARE_CSR(mstime_deltah, CSR_MSTIME_DELTAH)
|
||||
DECLARE_CSR(msinstret_deltah, CSR_MSINSTRET_DELTAH)
|
||||
DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H)
|
||||
DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H)
|
||||
DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H)
|
||||
DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H)
|
||||
DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H)
|
||||
DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H)
|
||||
DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H)
|
||||
DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H)
|
||||
DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H)
|
||||
DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H)
|
||||
DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H)
|
||||
DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H)
|
||||
DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H)
|
||||
DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H)
|
||||
DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H)
|
||||
DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H)
|
||||
DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H)
|
||||
DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H)
|
||||
DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H)
|
||||
DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H)
|
||||
DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H)
|
||||
DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H)
|
||||
DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H)
|
||||
DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H)
|
||||
DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H)
|
||||
DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H)
|
||||
DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H)
|
||||
DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H)
|
||||
DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H)
|
||||
DECLARE_CSR(mcycleh, CSR_MCYCLEH)
|
||||
DECLARE_CSR(mtimeh, CSR_MTIMEH)
|
||||
DECLARE_CSR(minstreth, CSR_MINSTRETH)
|
||||
DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H)
|
||||
DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H)
|
||||
DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H)
|
||||
DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H)
|
||||
DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H)
|
||||
DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H)
|
||||
DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H)
|
||||
DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H)
|
||||
DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H)
|
||||
DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H)
|
||||
DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H)
|
||||
DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H)
|
||||
DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H)
|
||||
DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H)
|
||||
DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H)
|
||||
DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H)
|
||||
DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H)
|
||||
DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H)
|
||||
DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H)
|
||||
DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H)
|
||||
DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H)
|
||||
DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H)
|
||||
DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H)
|
||||
DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H)
|
||||
DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H)
|
||||
DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H)
|
||||
DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H)
|
||||
DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H)
|
||||
DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H)
|
||||
#endif
|
||||
#ifdef DECLARE_CAUSE
|
||||
DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH)
|
||||
|
|
|
@ -26,11 +26,7 @@
|
|||
|
||||
#define DIM(x) (sizeof(x)/sizeof(*x))
|
||||
|
||||
#define CSR_TDRSELECT 0x7a0
|
||||
#define CSR_TDRDATA1 0x7a1
|
||||
#define CSR_TDRDATA2 0x7a2
|
||||
#define CSR_TDRDATA3 0x7a3
|
||||
|
||||
// Constants for legacy SiFive hardware breakpoints.
|
||||
#define CSR_BPCONTROL_X (1<<0)
|
||||
#define CSR_BPCONTROL_W (1<<1)
|
||||
#define CSR_BPCONTROL_R (1<<2)
|
||||
|
@ -131,6 +127,15 @@ enum {
|
|||
#define MAX_HWBPS 16
|
||||
#define DRAM_CACHE_SIZE 16
|
||||
|
||||
struct trigger {
|
||||
uint64_t address;
|
||||
uint32_t length;
|
||||
uint64_t mask;
|
||||
uint64_t value;
|
||||
bool read, write, execute;
|
||||
int unique_id;
|
||||
};
|
||||
|
||||
struct memory_cache_line {
|
||||
uint32_t data;
|
||||
bool valid;
|
||||
|
@ -146,6 +151,9 @@ typedef struct {
|
|||
unsigned int dramsize;
|
||||
uint64_t dcsr;
|
||||
uint64_t dpc;
|
||||
uint64_t misa;
|
||||
uint64_t tselect;
|
||||
bool tselect_dirty;
|
||||
|
||||
struct memory_cache_line dram_cache[DRAM_CACHE_SIZE];
|
||||
|
||||
|
@ -156,9 +164,9 @@ typedef struct {
|
|||
/* Single buffer that contains all register values. */
|
||||
void *reg_values;
|
||||
|
||||
// For each physical hwbp, contains ~0 if the hwbp is available, or the
|
||||
// unique_id of the breakpoint that is using it.
|
||||
uint32_t hwbp_unique_id[MAX_HWBPS];
|
||||
// For each physical trigger, contains -1 if the hwbp is available, or the
|
||||
// unique_id of the breakpoint/watchpoint that is using it.
|
||||
int trigger_unique_id[MAX_HWBPS];
|
||||
|
||||
// This value is incremented every time a dbus access comes back as "busy".
|
||||
// It's used to determine how many run-test/idle cycles to feed the target
|
||||
|
@ -173,6 +181,8 @@ typedef struct {
|
|||
|
||||
// This cache is write-through, and always valid when the target is halted.
|
||||
uint64_t gpr_cache[32];
|
||||
|
||||
bool need_strict_step;
|
||||
} riscv_info_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -183,6 +193,7 @@ typedef struct {
|
|||
/*** Necessary prototypes. ***/
|
||||
|
||||
static int riscv_poll(struct target *target);
|
||||
static int poll_target(struct target *target, bool announce);
|
||||
|
||||
/*** Utility functions. ***/
|
||||
|
||||
|
@ -501,7 +512,7 @@ static int dram_check32(struct target *target, unsigned int index,
|
|||
static void cache_set32(struct target *target, unsigned int index, uint32_t data)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
if (info->dram_cache[index].valid &&
|
||||
if (false && info->dram_cache[index].valid &&
|
||||
info->dram_cache[index].data == data) {
|
||||
// This is already preset on the target.
|
||||
LOG_DEBUG("cache[0x%x] = 0x%x (hit)", index, data);
|
||||
|
@ -817,28 +828,41 @@ static int write_gpr(struct target *target, unsigned int gpr, uint64_t value)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int resume(struct target *target, int current, uint32_t address,
|
||||
int handle_breakpoints, int debug_execution, bool step)
|
||||
static int maybe_read_tselect(struct target *target)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
if (!current) {
|
||||
if (info->xlen > 32) {
|
||||
LOG_WARNING("Asked to resume at 32-bit PC on %d-bit target.",
|
||||
info->xlen);
|
||||
}
|
||||
LOG_ERROR("TODO: current is false");
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (info->tselect_dirty) {
|
||||
int result = read_csr(target, &info->tselect, CSR_TSELECT);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
info->tselect_dirty = false;
|
||||
}
|
||||
|
||||
if (handle_breakpoints) {
|
||||
LOG_ERROR("TODO: handle_breakpoints is true");
|
||||
return ERROR_FAIL;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int maybe_write_tselect(struct target *target)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
if (!info->tselect_dirty) {
|
||||
int result = write_csr(target, CSR_TSELECT, info->tselect);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
info->tselect_dirty = true;
|
||||
}
|
||||
|
||||
if (debug_execution) {
|
||||
LOG_ERROR("TODO: debug_execution is true");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int execute_resume(struct target *target, bool step)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
LOG_DEBUG("resume(step=%d)", step);
|
||||
|
||||
maybe_write_tselect(target);
|
||||
|
||||
// TODO: check if dpc is dirty (which also is true if an exception was hit
|
||||
// at any time)
|
||||
|
@ -883,6 +907,54 @@ static int resume(struct target *target, int current, uint32_t address,
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
// Execute a step, and wait for reentry into Debug Mode.
|
||||
static int full_step(struct target *target, bool announce)
|
||||
{
|
||||
int result = execute_resume(target, true);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
time_t start = time(NULL);
|
||||
while (1) {
|
||||
result = poll_target(target, announce);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
if (target->state != TARGET_DEBUG_RUNNING)
|
||||
break;
|
||||
if (time(NULL) - start > 2) {
|
||||
LOG_ERROR("Timed out waiting for step to complete.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int resume(struct target *target, int current, uint32_t address,
|
||||
int handle_breakpoints, int debug_execution, bool step)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
if (!current) {
|
||||
if (info->xlen > 32) {
|
||||
LOG_WARNING("Asked to resume at 32-bit PC on %d-bit target.",
|
||||
info->xlen);
|
||||
}
|
||||
LOG_ERROR("TODO: current is false");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (handle_breakpoints) {
|
||||
LOG_ERROR("TODO: handle_breakpoints is true");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (debug_execution) {
|
||||
LOG_ERROR("TODO: debug_execution is true");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return execute_resume(target, step);
|
||||
}
|
||||
|
||||
/** Update register sizes based on xlen. */
|
||||
static void update_reg_list(struct target *target)
|
||||
{
|
||||
|
@ -1024,6 +1096,8 @@ static int register_get(struct reg *reg)
|
|||
struct target *target = (struct target *) reg->arch_info;
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
maybe_write_tselect(target);
|
||||
|
||||
if (reg->number <= REG_XPR31) {
|
||||
buf_set_u64(reg->value, 0, info->xlen, info->gpr_cache[reg->number]);
|
||||
LOG_DEBUG("%s=0x%" PRIx64, reg->name, info->gpr_cache[reg->number]);
|
||||
|
@ -1078,6 +1152,8 @@ static int register_write(struct target *target, unsigned int number,
|
|||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
maybe_write_tselect(target);
|
||||
|
||||
if (number == S0) {
|
||||
cache_set_load(target, 0, S0, SLOT0);
|
||||
cache_set32(target, 1, csrw(S0, CSR_DSCRATCH));
|
||||
|
@ -1184,7 +1260,7 @@ static int riscv_init_target(struct command_context *cmd_ctx,
|
|||
}
|
||||
update_reg_list(target);
|
||||
|
||||
memset(info->hwbp_unique_id, 0xff, sizeof(info->hwbp_unique_id));
|
||||
memset(info->trigger_unique_id, 0xff, sizeof(info->trigger_unique_id));
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -1215,11 +1291,299 @@ static int riscv_halt(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int add_trigger(struct target *target, struct trigger *trigger)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
maybe_read_tselect(target);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_HWBPS; i++) {
|
||||
if (info->trigger_unique_id[i] != -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t tselect = i;
|
||||
write_csr(target, CSR_TSELECT, tselect);
|
||||
uint64_t tselect_rb;
|
||||
read_csr(target, &tselect_rb, CSR_TSELECT);
|
||||
if (tselect_rb != tselect) {
|
||||
// We've run out of breakpoints.
|
||||
LOG_ERROR("Couldn't find an available hardware trigger. "
|
||||
"(0x%" PRIx64 " != 0x%" PRIx64 ")", tselect,
|
||||
tselect_rb);
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
uint64_t tdata1;
|
||||
read_csr(target, &tdata1, CSR_TDATA1);
|
||||
int type = get_field(tdata1, MCONTROL_TYPE(info->xlen));
|
||||
|
||||
if (type != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tdata1 & (MCONTROL_EXECUTE | MCONTROL_STORE | MCONTROL_LOAD)) {
|
||||
// Trigger is already in use, presumably by user code.
|
||||
continue;
|
||||
}
|
||||
|
||||
// address/data match trigger
|
||||
tdata1 |= MCONTROL_DMODE(info->xlen);
|
||||
tdata1 = set_field(tdata1, MCONTROL_ACTION,
|
||||
MCONTROL_ACTION_DEBUG_MODE);
|
||||
tdata1 = set_field(tdata1, MCONTROL_MATCH, MCONTROL_MATCH_EQUAL);
|
||||
tdata1 |= MCONTROL_M;
|
||||
if (info->misa & (1 << ('H' - 'A')))
|
||||
tdata1 |= MCONTROL_H;
|
||||
if (info->misa & (1 << ('S' - 'A')))
|
||||
tdata1 |= MCONTROL_S;
|
||||
if (info->misa & (1 << ('U' - 'A')))
|
||||
tdata1 |= MCONTROL_U;
|
||||
|
||||
if (trigger->execute)
|
||||
tdata1 |= MCONTROL_EXECUTE;
|
||||
if (trigger->read)
|
||||
tdata1 |= MCONTROL_LOAD;
|
||||
if (trigger->write)
|
||||
tdata1 |= MCONTROL_STORE;
|
||||
|
||||
write_csr(target, CSR_TDATA1, tdata1);
|
||||
|
||||
uint64_t tdata1_rb;
|
||||
read_csr(target, &tdata1_rb, CSR_TDATA1);
|
||||
LOG_DEBUG("tdata1=0x%" PRIx64, tdata1_rb);
|
||||
|
||||
if (tdata1 != tdata1_rb) {
|
||||
LOG_DEBUG("Trigger %d doesn't support what we need; After writing 0x%"
|
||||
PRIx64 " to tdata1 it contains 0x%" PRIx64,
|
||||
i, tdata1, tdata1_rb);
|
||||
write_csr(target, CSR_TDATA1, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
write_csr(target, CSR_TDATA2, trigger->address);
|
||||
|
||||
LOG_DEBUG("Using resource %d for bp %d", i,
|
||||
trigger->unique_id);
|
||||
info->trigger_unique_id[i] = trigger->unique_id;
|
||||
break;
|
||||
}
|
||||
if (i >= MAX_HWBPS) {
|
||||
LOG_ERROR("Couldn't find an available hardware trigger.");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int remove_trigger(struct target *target, struct trigger *trigger)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
maybe_read_tselect(target);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MAX_HWBPS; i++) {
|
||||
if (info->trigger_unique_id[i] == trigger->unique_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= MAX_HWBPS) {
|
||||
LOG_ERROR("Couldn't find the hardware resources used by hardware "
|
||||
"trigger.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
LOG_DEBUG("Stop using resource %d for bp %d", i, trigger->unique_id);
|
||||
write_csr(target, CSR_TSELECT, i);
|
||||
write_csr(target, CSR_TDATA1, 0);
|
||||
info->trigger_unique_id[i] = -1;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static void trigger_from_breakpoint(struct trigger *trigger,
|
||||
const struct breakpoint *breakpoint)
|
||||
{
|
||||
trigger->address = breakpoint->address;
|
||||
trigger->length = breakpoint->length;
|
||||
trigger->mask = ~0LL;
|
||||
trigger->read = false;
|
||||
trigger->write = false;
|
||||
trigger->execute = true;
|
||||
// unique_id is unique across both breakpoints and watchpoints.
|
||||
trigger->unique_id = breakpoint->unique_id;
|
||||
}
|
||||
|
||||
static void trigger_from_watchpoint(struct trigger *trigger,
|
||||
const struct watchpoint *watchpoint)
|
||||
{
|
||||
trigger->address = watchpoint->address;
|
||||
trigger->length = watchpoint->length;
|
||||
trigger->mask = watchpoint->mask;
|
||||
trigger->value = watchpoint->value;
|
||||
trigger->read = (watchpoint->rw == WPT_READ || watchpoint->rw == WPT_ACCESS);
|
||||
trigger->write = (watchpoint->rw == WPT_WRITE || watchpoint->rw == WPT_ACCESS);
|
||||
trigger->execute = false;
|
||||
// unique_id is unique across both breakpoints and watchpoints.
|
||||
trigger->unique_id = watchpoint->unique_id;
|
||||
}
|
||||
|
||||
static int riscv_add_breakpoint(struct target *target,
|
||||
struct breakpoint *breakpoint)
|
||||
{
|
||||
if (breakpoint->type == BKPT_SOFT) {
|
||||
if (target_read_memory(target, breakpoint->address, breakpoint->length, 1,
|
||||
breakpoint->orig_instr) != ERROR_OK) {
|
||||
LOG_ERROR("Failed to read original instruction at 0x%x",
|
||||
breakpoint->address);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
int retval;
|
||||
if (breakpoint->length == 4) {
|
||||
retval = target_write_u32(target, breakpoint->address, ebreak());
|
||||
} else {
|
||||
retval = target_write_u16(target, breakpoint->address, ebreak_c());
|
||||
}
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("Failed to write %d-byte breakpoint instruction at 0x%x",
|
||||
breakpoint->length, breakpoint->address);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
} else if (breakpoint->type == BKPT_HARD) {
|
||||
struct trigger trigger;
|
||||
trigger_from_breakpoint(&trigger, breakpoint);
|
||||
int result = add_trigger(target, &trigger);
|
||||
if (result != ERROR_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
breakpoint->set = true;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv_remove_breakpoint(struct target *target,
|
||||
struct breakpoint *breakpoint)
|
||||
{
|
||||
if (breakpoint->type == BKPT_SOFT) {
|
||||
if (target_write_memory(target, breakpoint->address, breakpoint->length, 1,
|
||||
breakpoint->orig_instr) != ERROR_OK) {
|
||||
LOG_ERROR("Failed to restore instruction for %d-byte breakpoint at "
|
||||
"0x%x", breakpoint->length, breakpoint->address);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
} else if (breakpoint->type == BKPT_HARD) {
|
||||
struct trigger trigger;
|
||||
trigger_from_breakpoint(&trigger, breakpoint);
|
||||
int result = remove_trigger(target, &trigger);
|
||||
if (result != ERROR_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
breakpoint->set = false;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv_add_watchpoint(struct target *target,
|
||||
struct watchpoint *watchpoint)
|
||||
{
|
||||
struct trigger trigger;
|
||||
trigger_from_watchpoint(&trigger, watchpoint);
|
||||
|
||||
int result = add_trigger(target, &trigger);
|
||||
if (result != ERROR_OK) {
|
||||
return result;
|
||||
}
|
||||
watchpoint->set = true;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv_remove_watchpoint(struct target *target,
|
||||
struct watchpoint *watchpoint)
|
||||
{
|
||||
struct trigger trigger;
|
||||
trigger_from_watchpoint(&trigger, watchpoint);
|
||||
|
||||
int result = remove_trigger(target, &trigger);
|
||||
if (result != ERROR_OK) {
|
||||
return result;
|
||||
}
|
||||
watchpoint->set = false;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int strict_step(struct target *target, bool announce)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
LOG_DEBUG("enter");
|
||||
|
||||
struct breakpoint *breakpoint = target->breakpoints;
|
||||
while (breakpoint) {
|
||||
riscv_remove_breakpoint(target, breakpoint);
|
||||
breakpoint = breakpoint->next;
|
||||
}
|
||||
|
||||
struct watchpoint *watchpoint = target->watchpoints;
|
||||
while (watchpoint) {
|
||||
riscv_remove_watchpoint(target, watchpoint);
|
||||
watchpoint = watchpoint->next;
|
||||
}
|
||||
|
||||
int result = full_step(target, announce);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
breakpoint = target->breakpoints;
|
||||
while (breakpoint) {
|
||||
riscv_add_breakpoint(target, breakpoint);
|
||||
breakpoint = breakpoint->next;
|
||||
}
|
||||
|
||||
watchpoint = target->watchpoints;
|
||||
while (watchpoint) {
|
||||
riscv_add_watchpoint(target, watchpoint);
|
||||
watchpoint = watchpoint->next;
|
||||
}
|
||||
|
||||
info->need_strict_step = false;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv_step(struct target *target, int current, uint32_t address,
|
||||
int handle_breakpoints)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
||||
return resume(target, current, address, handle_breakpoints, 0, true);
|
||||
|
||||
if (info->need_strict_step) {
|
||||
int result = strict_step(target, true);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
} else {
|
||||
return resume(target, current, address, handle_breakpoints, 0, true);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv_examine(struct target *target)
|
||||
|
@ -1322,10 +1686,10 @@ static int riscv_examine(struct target *target)
|
|||
|
||||
target_set_examined(target);
|
||||
|
||||
//write_constants(target);
|
||||
//light_leds(target);
|
||||
//dram_test(target);
|
||||
//test_s1(target);
|
||||
if (read_csr(target, &info->misa, CSR_MISA) != ERROR_OK) {
|
||||
LOG_ERROR("Failed to read misa.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -1386,9 +1750,11 @@ static riscv_error_t handle_halt_routine(struct target *target)
|
|||
// The first scan result is the result from something old we don't care
|
||||
// about.
|
||||
for (unsigned int i = 1; i < scans->next_scan && dbus_busy == 0; i++) {
|
||||
dbus_status_t status = scans_get_u32(scans, i, DBUS_OP_START, DBUS_OP_SIZE);
|
||||
dbus_status_t status = scans_get_u32(scans, i, DBUS_OP_START,
|
||||
DBUS_OP_SIZE);
|
||||
uint64_t data = scans_get_u64(scans, i, DBUS_DATA_START, DBUS_DATA_SIZE);
|
||||
uint32_t address = scans_get_u32(scans, i, DBUS_ADDRESS_START, info->addrbits);
|
||||
uint32_t address = scans_get_u32(scans, i, DBUS_ADDRESS_START,
|
||||
info->addrbits);
|
||||
LOG_DEBUG("read scan=%d result=%d data=%09" PRIx64 " address=%02x",
|
||||
i, status, data, address);
|
||||
switch (status) {
|
||||
|
@ -1483,7 +1849,7 @@ error:
|
|||
return RE_FAIL;
|
||||
}
|
||||
|
||||
static int handle_halt(struct target *target)
|
||||
static int handle_halt(struct target *target, bool announce)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
target->state = TARGET_HALTED;
|
||||
|
@ -1501,9 +1867,14 @@ static int handle_halt(struct target *target)
|
|||
LOG_DEBUG("halt cause is %d; dcsr=0x%" PRIx64, cause, info->dcsr);
|
||||
switch (cause) {
|
||||
case DCSR_CAUSE_SWBP:
|
||||
case DCSR_CAUSE_HWBP:
|
||||
target->debug_reason = DBG_REASON_BREAKPOINT;
|
||||
break;
|
||||
case DCSR_CAUSE_HWBP:
|
||||
target->debug_reason = DBG_REASON_WPTANDBKPT;
|
||||
// If we halted because of a data trigger, gdb doesn't know to do
|
||||
// the disable-breakpoints-step-enable-breakpoints dance.
|
||||
info->need_strict_step = true;
|
||||
break;
|
||||
case DCSR_CAUSE_DEBUGINT:
|
||||
target->debug_reason = DBG_REASON_DBGRQ;
|
||||
break;
|
||||
|
@ -1516,14 +1887,16 @@ static int handle_halt(struct target *target)
|
|||
cause, info->dcsr);
|
||||
}
|
||||
|
||||
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||
if (announce) {
|
||||
target_call_event_callbacks(target, TARGET_EVENT_HALTED);
|
||||
}
|
||||
|
||||
LOG_DEBUG("halted at 0x%" PRIx64, info->dpc);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv_poll(struct target *target)
|
||||
static int poll_target(struct target *target, bool announce)
|
||||
{
|
||||
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
||||
bits_t bits = read_bits(target);
|
||||
|
@ -1533,7 +1906,7 @@ static int riscv_poll(struct target *target)
|
|||
LOG_DEBUG("debug running");
|
||||
} else if (bits.haltnot && !bits.interrupt) {
|
||||
if (target->state != TARGET_HALTED) {
|
||||
return handle_halt(target);
|
||||
return handle_halt(target, announce);
|
||||
}
|
||||
} else if (!bits.haltnot && bits.interrupt) {
|
||||
// Target is halting. There is no state for that, so don't change anything.
|
||||
|
@ -1546,10 +1919,24 @@ static int riscv_poll(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv_poll(struct target *target)
|
||||
{
|
||||
return poll_target(target, true);
|
||||
}
|
||||
|
||||
static int riscv_resume(struct target *target, int current, uint32_t address,
|
||||
int handle_breakpoints, int debug_execution)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
||||
|
||||
if (info->need_strict_step) {
|
||||
int result = strict_step(target, false);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
return resume(target, current, address, handle_breakpoints,
|
||||
debug_execution, false);
|
||||
}
|
||||
|
@ -1953,125 +2340,6 @@ static int riscv_get_gdb_reg_list(struct target *target,
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
if (breakpoint->type == BKPT_SOFT) {
|
||||
if (target_read_memory(target, breakpoint->address, breakpoint->length, 1,
|
||||
breakpoint->orig_instr) != ERROR_OK) {
|
||||
LOG_ERROR("Failed to read original instruction at 0x%x",
|
||||
breakpoint->address);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
int retval;
|
||||
if (breakpoint->length == 4) {
|
||||
retval = target_write_u32(target, breakpoint->address, ebreak());
|
||||
} else {
|
||||
retval = target_write_u16(target, breakpoint->address, ebreak_c());
|
||||
}
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("Failed to write %d-byte breakpoint instruction at 0x%x",
|
||||
breakpoint->length, breakpoint->address);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
} else if (breakpoint->type == BKPT_HARD) {
|
||||
int i;
|
||||
uint64_t tdrdata1;
|
||||
uint64_t tdrselect, tdrselect_rb;
|
||||
for (i = 0; i < MAX_HWBPS; i++) {
|
||||
if (info->hwbp_unique_id[i] == ~0U) {
|
||||
// TODO 0x80000000 is a hack until the core supports proper
|
||||
// debug hwbps.
|
||||
tdrselect = 0x80000000 | i;
|
||||
write_csr(target, CSR_TDRSELECT, tdrselect);
|
||||
read_csr(target, &tdrselect_rb, CSR_TDRSELECT);
|
||||
if (tdrselect_rb != tdrselect) {
|
||||
// We've run out of breakpoints.
|
||||
LOG_ERROR("Couldn't find an available hardware breakpoint. "
|
||||
"(0x%" PRIx64 " != 0x%" PRIx64 ")", tdrselect,
|
||||
tdrselect_rb);
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
read_csr(target, &tdrdata1, CSR_TDRDATA1);
|
||||
if ((tdrdata1 >> (info->xlen - 4)) == 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i >= MAX_HWBPS) {
|
||||
LOG_ERROR("Couldn't find an available hardware breakpoint.");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
LOG_DEBUG("Start using resource %d for bp %d", i, breakpoint->unique_id);
|
||||
|
||||
tdrdata1 |= CSR_BPCONTROL_X;
|
||||
tdrdata1 |= CSR_BPCONTROL_U;
|
||||
tdrdata1 |= CSR_BPCONTROL_S;
|
||||
tdrdata1 |= CSR_BPCONTROL_H;
|
||||
tdrdata1 |= CSR_BPCONTROL_M;
|
||||
write_csr(target, CSR_TDRDATA1, tdrdata1);
|
||||
write_csr(target, CSR_TDRDATA2, breakpoint->address);
|
||||
|
||||
uint64_t tdrdata1_rb;
|
||||
read_csr(target, &tdrdata1_rb, CSR_TDRDATA1);
|
||||
LOG_DEBUG("tdrdata1=0x%" PRIx64, tdrdata1_rb);
|
||||
|
||||
if (!(tdrdata1_rb & CSR_BPCONTROL_X)) {
|
||||
LOG_ERROR("Breakpoint %d doesn't support execute", i);
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
info->hwbp_unique_id[i] = breakpoint->unique_id;
|
||||
} else {
|
||||
LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
breakpoint->set = true;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int riscv_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
|
||||
{
|
||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||
|
||||
if (breakpoint->type == BKPT_SOFT) {
|
||||
if (target_write_memory(target, breakpoint->address, breakpoint->length, 1,
|
||||
breakpoint->orig_instr) != ERROR_OK) {
|
||||
LOG_ERROR("Failed to restore instruction for %d-byte breakpoint at 0x%x",
|
||||
breakpoint->length, breakpoint->address);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
} else if (breakpoint->type == BKPT_HARD) {
|
||||
int i;
|
||||
for (i = 0; i < MAX_HWBPS; i++) {
|
||||
if (info->hwbp_unique_id[i] == breakpoint->unique_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= MAX_HWBPS) {
|
||||
LOG_ERROR("Couldn't find the hardware resources used by hardware breakpoint.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
LOG_DEBUG("Stop using resource %d for bp %d", i, breakpoint->unique_id);
|
||||
write_csr(target, CSR_TDRSELECT, 0x80000000 | i);
|
||||
write_csr(target, CSR_TDRDATA1, 0);
|
||||
info->hwbp_unique_id[i] = ~0U;
|
||||
|
||||
} else {
|
||||
LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
breakpoint->set = false;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int riscv_arch_state(struct target *target)
|
||||
{
|
||||
return ERROR_OK;
|
||||
|
@ -2103,5 +2371,8 @@ struct target_type riscv_target =
|
|||
.add_breakpoint = riscv_add_breakpoint,
|
||||
.remove_breakpoint = riscv_remove_breakpoint,
|
||||
|
||||
.add_watchpoint = riscv_add_watchpoint,
|
||||
.remove_watchpoint = riscv_remove_watchpoint,
|
||||
|
||||
.arch_state = riscv_arch_state,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue