diff --git a/src/rtos/zephyr.c b/src/rtos/zephyr.c index 4de7aaa0d..3d5c880f7 100644 --- a/src/rtos/zephyr.c +++ b/src/rtos/zephyr.c @@ -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, @@ -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 }, @@ -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, @@ -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 */ @@ -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; @@ -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, @@ -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; } @@ -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; @@ -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; @@ -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); @@ -332,11 +390,13 @@ 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, }, @@ -344,7 +404,8 @@ static struct zephyr_params zephyr_params_list[] = { .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, }, @@ -352,7 +413,8 @@ static struct zephyr_params zephyr_params_list[] = { .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, @@ -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, }, { @@ -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, -}; +}; \ No newline at end of file