aarch64: update smp halt and resume to better facilitate CTI
Set up CTI so that halt and resume requests get routed to all PEs in the SMP group. Change-Id: Ie92cfd3fe54632e5fdc049a6bf5b24b99451a8c9 Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com>
This commit is contained in:
parent
c6ed75fb0e
commit
6b392dea66
|
@ -212,19 +212,6 @@ static int aarch64_init_debug_access(struct target *target)
|
||||||
|
|
||||||
LOG_DEBUG(" ");
|
LOG_DEBUG(" ");
|
||||||
|
|
||||||
/* Unlocking the debug registers for modification
|
|
||||||
* The debugport might be uninitialised so try twice */
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
|
||||||
armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55);
|
|
||||||
if (retval != ERROR_OK) {
|
|
||||||
/* try again */
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
|
||||||
armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55);
|
|
||||||
if (retval == ERROR_OK)
|
|
||||||
LOG_USER("Locking debug access failed on first, but succeeded on second try.");
|
|
||||||
}
|
|
||||||
if (retval != ERROR_OK)
|
|
||||||
return retval;
|
|
||||||
/* Clear Sticky Power Down status Bit in PRSR to enable access to
|
/* Clear Sticky Power Down status Bit in PRSR to enable access to
|
||||||
the registers in the Core Power Domain */
|
the registers in the Core Power Domain */
|
||||||
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
||||||
|
@ -232,7 +219,30 @@ static int aarch64_init_debug_access(struct target *target)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* Enabling of instruction execution in debug mode is done in debug_entry code */
|
/*
|
||||||
|
* Static CTI configuration:
|
||||||
|
* Channel 0 -> trigger outputs HALT request to PE
|
||||||
|
* Channel 1 -> trigger outputs Resume request to PE
|
||||||
|
* Gate all channel trigger events from entering the CTM
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Enable CTI */
|
||||||
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
|
armv8->cti_base + CTI_CTR, 1);
|
||||||
|
/* By default, gate all channel triggers to and from the CTM */
|
||||||
|
if (retval == ERROR_OK)
|
||||||
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
|
armv8->cti_base + CTI_GATE, 0);
|
||||||
|
/* output halt requests to PE on channel 0 trigger */
|
||||||
|
if (retval == ERROR_OK)
|
||||||
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
|
armv8->cti_base + CTI_OUTEN0, CTI_CHNL(0));
|
||||||
|
/* output restart requests to PE on channel 1 trigger */
|
||||||
|
if (retval == ERROR_OK)
|
||||||
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
|
armv8->cti_base + CTI_OUTEN1, CTI_CHNL(1));
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
/* Resync breakpoint registers */
|
/* Resync breakpoint registers */
|
||||||
|
|
||||||
|
@ -783,16 +793,27 @@ static int aarch64_halt(struct target *target);
|
||||||
|
|
||||||
static int aarch64_halt_smp(struct target *target)
|
static int aarch64_halt_smp(struct target *target)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = ERROR_OK;
|
||||||
struct target_list *head;
|
struct target_list *head = target->head;
|
||||||
struct target *curr;
|
|
||||||
head = target->head;
|
|
||||||
while (head != (struct target_list *)NULL) {
|
while (head != (struct target_list *)NULL) {
|
||||||
curr = head->target;
|
struct target *curr = head->target;
|
||||||
if ((curr != target) && (curr->state != TARGET_HALTED))
|
struct armv8_common *armv8 = target_to_armv8(curr);
|
||||||
retval += aarch64_halt(curr);
|
|
||||||
|
/* open the gate for channel 0 to let HALT requests pass to the CTM */
|
||||||
|
if (curr->smp)
|
||||||
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
|
armv8->cti_base + CTI_GATE, CTI_CHNL(0));
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
head = head->next;
|
head = head->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* halt the target PE */
|
||||||
|
if (retval == ERROR_OK)
|
||||||
|
retval = aarch64_halt(target);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,51 +904,23 @@ static int aarch64_halt(struct target *target)
|
||||||
uint32_t dscr;
|
uint32_t dscr;
|
||||||
struct armv8_common *armv8 = target_to_armv8(target);
|
struct armv8_common *armv8 = target_to_armv8(target);
|
||||||
|
|
||||||
/* enable CTI*/
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
|
||||||
armv8->cti_base + CTI_CTR, 1);
|
|
||||||
if (retval != ERROR_OK)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
|
||||||
armv8->cti_base + CTI_GATE, 3);
|
|
||||||
if (retval != ERROR_OK)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
|
||||||
armv8->cti_base + CTI_OUTEN0, 1);
|
|
||||||
if (retval != ERROR_OK)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
|
||||||
armv8->cti_base + CTI_OUTEN1, 2);
|
|
||||||
if (retval != ERROR_OK)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add HDE in halting debug mode
|
* add HDE in halting debug mode
|
||||||
*/
|
*/
|
||||||
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
||||||
armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
|
armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
|
||||||
if (retval != ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
return retval;
|
|
||||||
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
armv8->debug_base + CPUV8_DBG_DSCR, dscr | DSCR_HDE);
|
armv8->debug_base + CPUV8_DBG_DSCR, dscr | DSCR_HDE);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
/* trigger an event on channel 0, this outputs a halt request to the PE */
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
armv8->cti_base + CTI_APPPULSE, 1);
|
armv8->cti_base + CTI_APPPULSE, CTI_CHNL(0));
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
|
||||||
armv8->cti_base + CTI_INACK, 1);
|
|
||||||
if (retval != ERROR_OK)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
|
|
||||||
long long then = timeval_ms();
|
long long then = timeval_ms();
|
||||||
for (;; ) {
|
for (;; ) {
|
||||||
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
||||||
|
@ -1023,7 +1016,7 @@ static int aarch64_internal_restore(struct target *target, int current,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aarch64_internal_restart(struct target *target)
|
static int aarch64_internal_restart(struct target *target, bool slave_pe)
|
||||||
{
|
{
|
||||||
struct armv8_common *armv8 = target_to_armv8(target);
|
struct armv8_common *armv8 = target_to_armv8(target);
|
||||||
struct arm *arm = &armv8->arm;
|
struct arm *arm = &armv8->arm;
|
||||||
|
@ -1045,8 +1038,24 @@ static int aarch64_internal_restart(struct target *target)
|
||||||
if ((dscr & DSCR_ITE) == 0)
|
if ((dscr & DSCR_ITE) == 0)
|
||||||
LOG_ERROR("DSCR InstrCompl must be set before leaving debug!");
|
LOG_ERROR("DSCR InstrCompl must be set before leaving debug!");
|
||||||
|
|
||||||
|
/* make sure to acknowledge the halt event before resuming */
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
armv8->cti_base + CTI_APPPULSE, 2);
|
armv8->cti_base + CTI_INACK, CTI_TRIG(HALT));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open the CTI gate for channel 1 so that the restart events
|
||||||
|
* get passed along to all PEs
|
||||||
|
*/
|
||||||
|
if (retval == ERROR_OK)
|
||||||
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
|
armv8->cti_base + CTI_GATE, CTI_CHNL(1));
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
if (!slave_pe) {
|
||||||
|
/* trigger an event on channel 1, generates a restart request to the PE */
|
||||||
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
|
armv8->cti_base + CTI_APPPULSE, CTI_CHNL(1));
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
@ -1063,6 +1072,7 @@ static int aarch64_internal_restart(struct target *target)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
target->debug_reason = DBG_REASON_NOTHALTED;
|
target->debug_reason = DBG_REASON_NOTHALTED;
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
|
@ -1086,7 +1096,7 @@ static int aarch64_restore_smp(struct target *target, int handle_breakpoints)
|
||||||
/* resume current address , not in step mode */
|
/* resume current address , not in step mode */
|
||||||
retval += aarch64_internal_restore(curr, 1, &address,
|
retval += aarch64_internal_restore(curr, 1, &address,
|
||||||
handle_breakpoints, 0);
|
handle_breakpoints, 0);
|
||||||
retval += aarch64_internal_restart(curr);
|
retval += aarch64_internal_restart(curr, true);
|
||||||
}
|
}
|
||||||
head = head->next;
|
head = head->next;
|
||||||
|
|
||||||
|
@ -1117,7 +1127,7 @@ static int aarch64_resume(struct target *target, int current,
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
aarch64_internal_restart(target);
|
aarch64_internal_restart(target, false);
|
||||||
|
|
||||||
if (!debug_execution) {
|
if (!debug_execution) {
|
||||||
target->state = TARGET_RUNNING;
|
target->state = TARGET_RUNNING;
|
||||||
|
@ -2398,12 +2408,6 @@ static int aarch64_examine_first(struct target *target)
|
||||||
} else
|
} else
|
||||||
armv8->cti_base = target->ctibase;
|
armv8->cti_base = target->ctibase;
|
||||||
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
|
||||||
armv8->cti_base + CTI_UNLOCK , 0xC5ACCE55);
|
|
||||||
if (retval != ERROR_OK)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
|
|
||||||
armv8->arm.core_type = ARM_MODE_MON;
|
armv8->arm.core_type = ARM_MODE_MON;
|
||||||
retval = aarch64_dpm_setup(aarch64, debug);
|
retval = aarch64_dpm_setup(aarch64, debug);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
|
|
@ -225,6 +225,11 @@ target_to_armv8(struct target *target)
|
||||||
#define CTI_GATE 0x140
|
#define CTI_GATE 0x140
|
||||||
#define CTI_UNLOCK 0xFB0
|
#define CTI_UNLOCK 0xFB0
|
||||||
|
|
||||||
|
#define CTI_CHNL(x) (1 << x)
|
||||||
|
#define CTI_TRIG_HALT 0
|
||||||
|
#define CTI_TRIG_RESUME 1
|
||||||
|
#define CTI_TRIG(n) (1 << CTI_TRIG_##n)
|
||||||
|
|
||||||
#define PAGE_SIZE_4KB 0x1000
|
#define PAGE_SIZE_4KB 0x1000
|
||||||
#define PAGE_SIZE_4KB_LEVEL0_BITS 39
|
#define PAGE_SIZE_4KB_LEVEL0_BITS 39
|
||||||
#define PAGE_SIZE_4KB_LEVEL1_BITS 30
|
#define PAGE_SIZE_4KB_LEVEL1_BITS 30
|
||||||
|
|
Loading…
Reference in New Issue