Skip to content

Commit

Permalink
rtos/zephyr: add coop and preempt registers concept
Browse files Browse the repository at this point in the history
Depending on the architecture, a different set of registers may be saved on a thread's stack in a cooperative vs. a preemptive switch.

Signed-off-by: Bruno Mendes <bd_mendes@outlook.com>
  • Loading branch information
bdmendes committed Aug 3, 2023
1 parent 10e3679 commit d2da61b
Showing 1 changed file with 87 additions and 24 deletions.
111 changes: 87 additions & 24 deletions src/rtos/zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ struct zephyr_params {
uint32_t num_offsets;
uint32_t offsets[OFFSET_MAX];
const struct rtos_register_stacking *callee_saved_stacking;
const struct rtos_register_stacking *cpu_saved_nofp_stacking;
const struct rtos_register_stacking *cpu_saved_nofp_stacking_coop;
const struct rtos_register_stacking *cpu_saved_nofp_stacking_preempt;
const struct rtos_register_stacking *cpu_saved_fp_stacking;
int (*get_cpu_state)(struct rtos *rtos, target_addr_t *addr,
struct zephyr_params *params,
Expand Down Expand Up @@ -139,7 +140,10 @@ static const struct stack_register_offset arm_cpu_saved[] = {
{ ARMV7M_xPSR, 28, 32 },
};

static struct stack_register_offset arc_cpu_saved[] = {
/* in the case of cooperative switches, the kernel will save
* status32 and blink on the stack before the callee-saved registers;
* the compiler is responsible for caller-saved registers */
static struct stack_register_offset arc_cpu_saved_coop[] = {
{ ARC_R0, -1, 32 },
{ ARC_R1, -1, 32 },
{ ARC_R2, -1, 32 },
Expand Down Expand Up @@ -180,6 +184,50 @@ static struct stack_register_offset arc_cpu_saved[] = {
{ ARC_STATUS32, 4, 32 }
};

/* in the case of preemptive switches, the kernel will save
* status32 and blink, and caller-saved registers are pushed
* automatically by hardware (RIRQ) or by the kernel (FIRQ) */
static struct stack_register_offset arc_cpu_saved_preempt[] = {
{ ARC_R0, 8, 32 },
{ ARC_R1, 12, 32 },
{ ARC_R2, 16, 32 },
{ ARC_R3, 20, 32 },
{ ARC_R4, 24, 32 },
{ ARC_R5, 28, 32 },
{ ARC_R6, 32, 32 },
{ ARC_R7, 36, 32 },
{ ARC_R8, 40, 32 },
{ ARC_R9, 44, 32 },
{ ARC_R10, 48, 32 },
{ ARC_R11, 52, 32 },
{ ARC_R12, 56, 32 },
{ ARC_R13, 60, 32 },
{ ARC_R14, -1, 32 },
{ ARC_R15, -1, 32 },
{ ARC_R16, -1, 32 },
{ ARC_R17, -1, 32 },
{ ARC_R18, -1, 32 },
{ ARC_R19, -1, 32 },
{ ARC_R20, -1, 32 },
{ ARC_R21, -1, 32 },
{ ARC_R22, -1, 32 },
{ ARC_R23, -1, 32 },
{ ARC_R24, -1, 32 },
{ ARC_R25, -1, 32 },
{ ARC_GP, -1, 32 },
{ ARC_FP, -1, 32 },
{ ARC_SP, -1, 32 },
{ ARC_ILINK, -1, 32 },
{ ARC_R30, -1, 32 },
{ ARC_BLINK, 0, 32 },
{ ARC_LP_COUNT, -1, 32 },
{ ARC_PCL, -1, 32 },
{ ARC_PC, -1, 32 },
{ ARC_LP_START, -1, 32 },
{ ARC_LP_END, -1, 32 },
{ ARC_STATUS32, 4, 32 }
};


enum zephyr_symbol_values {
ZEPHYR_VAL__KERNEL,
Expand Down Expand Up @@ -213,13 +261,18 @@ static const struct rtos_register_stacking arm_cpu_saved_fp_stacking = {
.register_offsets = arm_cpu_saved,
};

/* stack_registers_size is 8 because besides caller registers
* there are only blink and Status32 registers on stack left */
static struct rtos_register_stacking arc_cpu_saved_stacking = {
.stack_registers_size = 8,
static struct rtos_register_stacking arc_cpu_saved_stacking_coop = {
.stack_registers_size = 2*4,
.stack_growth_direction = -1,
.num_output_registers = ARRAY_SIZE(arc_cpu_saved_coop),
.register_offsets = arc_cpu_saved_coop,
};

static struct rtos_register_stacking arc_cpu_saved_stacking_preempt = {
.stack_registers_size = 2*4 + 14*4,
.stack_growth_direction = -1,
.num_output_registers = ARRAY_SIZE(arc_cpu_saved),
.register_offsets = arc_cpu_saved,
.num_output_registers = ARRAY_SIZE(arc_cpu_saved_preempt),
.register_offsets = arc_cpu_saved_preempt,
};

/* ARCv2 specific implementation */
Expand All @@ -228,7 +281,6 @@ static int zephyr_get_arc_state(struct rtos *rtos, target_addr_t *addr,
struct rtos_reg *callee_saved_reg_list,
struct rtos_reg **reg_list, int *num_regs)
{

uint32_t real_stack_addr;
int retval = 0;
int num_callee_saved_regs;
Expand All @@ -247,15 +299,18 @@ static int zephyr_get_arc_state(struct rtos *rtos, target_addr_t *addr,
if (retval != ERROR_OK)
return retval;

stacking = params->cpu_saved_nofp_stacking;
/* TODO check relinquish state and opt for coop or preempt */
stacking = params->cpu_saved_nofp_stacking_coop;

/* Getting blink and status32 registers */
/* Getting cpu saved registers into reg_list */
retval = rtos_generic_stack_read(rtos->target, stacking,
real_stack_addr + num_callee_saved_regs * 4,
reg_list, num_regs);
if (retval != ERROR_OK)
return retval;

/* Since reg_list does not contain callee saved values,
* copy them from the values read from the thread's stack */
for (int i = 0; i < num_callee_saved_regs; i++)
buf_cpy(callee_saved_reg_list[i].value,
(*reg_list)[callee_saved_reg_list[i].number].value,
Expand All @@ -265,12 +320,12 @@ static int zephyr_get_arc_state(struct rtos *rtos, target_addr_t *addr,
* but the registers number shall not. So the next code searches the
* offsetst of these registers in arc_cpu_saved structure. */
unsigned short blink_offset = 0, pc_offset = 0, sp_offset = 0;
for (size_t i = 0; i < ARRAY_SIZE(arc_cpu_saved); i++) {
if (arc_cpu_saved[i].number == ARC_BLINK)
for (size_t i = 0; i < stacking->num_output_registers; i++) {
if (stacking->register_offsets[i].number == ARC_BLINK)
blink_offset = i;
if (arc_cpu_saved[i].number == ARC_SP)
if (stacking->register_offsets[i].number == ARC_SP)
sp_offset = i;
if (arc_cpu_saved[i].number == ARC_PC)
if (stacking->register_offsets[i].number == ARC_PC)
pc_offset = i;
}

Expand All @@ -285,9 +340,8 @@ static int zephyr_get_arc_state(struct rtos *rtos, target_addr_t *addr,

/* Put address after callee/caller in SP. */
int64_t stack_top;

stack_top = real_stack_addr + num_callee_saved_regs * 4
+ arc_cpu_saved_stacking.stack_registers_size;
+ stacking->stack_registers_size;
buf_cpy(&stack_top, (*reg_list)[sp_offset].value, sizeof(stack_top));

return retval;
Expand All @@ -299,7 +353,6 @@ static int zephyr_get_arm_state(struct rtos *rtos, target_addr_t *addr,
struct rtos_reg *callee_saved_reg_list,
struct rtos_reg **reg_list, int *num_regs)
{

int retval = 0;
int num_callee_saved_regs;
const struct rtos_register_stacking *stacking;
Expand All @@ -315,9 +368,14 @@ static int zephyr_get_arm_state(struct rtos *rtos, target_addr_t *addr,
callee_saved_reg_list[0].value);

if (params->offsets[OFFSET_T_PREEMPT_FLOAT] != UNIMPLEMENTED)
{
stacking = params->cpu_saved_fp_stacking;
}
else
stacking = params->cpu_saved_nofp_stacking;
{
/* TODO check relinquish state and opt for coop or preempt */
stacking = params->cpu_saved_nofp_stacking_coop;
}

retval = rtos_generic_stack_read(rtos->target, stacking, *addr, reg_list,
num_regs);
Expand All @@ -332,27 +390,31 @@ static int zephyr_get_arm_state(struct rtos *rtos, target_addr_t *addr,
}

static struct zephyr_params zephyr_params_list[] = {
/* TODO check if more registers can be read on ARM in case of preemption */
{
.target_name = "cortex_m",
.pointer_width = 4,
.callee_saved_stacking = &arm_callee_saved_stacking,
.cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
.cpu_saved_nofp_stacking_coop = &arm_cpu_saved_nofp_stacking,
.cpu_saved_nofp_stacking_preempt = &arm_cpu_saved_nofp_stacking,
.cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
.get_cpu_state = &zephyr_get_arm_state,
},
{
.target_name = "cortex_r4",
.pointer_width = 4,
.callee_saved_stacking = &arm_callee_saved_stacking,
.cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
.cpu_saved_nofp_stacking_coop = &arm_cpu_saved_nofp_stacking,
.cpu_saved_nofp_stacking_preempt = &arm_cpu_saved_nofp_stacking,
.cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
.get_cpu_state = &zephyr_get_arm_state,
},
{
.target_name = "hla_target",
.pointer_width = 4,
.callee_saved_stacking = &arm_callee_saved_stacking,
.cpu_saved_nofp_stacking = &arm_cpu_saved_nofp_stacking,
.cpu_saved_nofp_stacking_coop = &arm_cpu_saved_nofp_stacking,
.cpu_saved_nofp_stacking_preempt = &arm_cpu_saved_nofp_stacking,
.cpu_saved_fp_stacking = &arm_cpu_saved_fp_stacking,
.get_cpu_state = &zephyr_get_arm_state,

Expand All @@ -361,7 +423,8 @@ static struct zephyr_params zephyr_params_list[] = {
.target_name = "arcv2",
.pointer_width = 4,
.callee_saved_stacking = &arc_callee_saved_stacking,
.cpu_saved_nofp_stacking = &arc_cpu_saved_stacking,
.cpu_saved_nofp_stacking_coop = &arc_cpu_saved_stacking_coop,
.cpu_saved_nofp_stacking_preempt = &arc_cpu_saved_stacking_preempt,
.get_cpu_state = &zephyr_get_arc_state,
},
{
Expand Down Expand Up @@ -773,4 +836,4 @@ struct rtos_type zephyr_rtos = {
.update_threads = zephyr_update_threads,
.get_thread_reg_list = zephyr_get_thread_reg_list,
.get_symbol_list_to_lookup = zephyr_get_symbol_list_to_lookup,
};
};

0 comments on commit d2da61b

Please sign in to comment.