[PATCH 10/10] arm64: stacktrace: unwind exception boundaries

Miroslav Benes mbenes at suse.cz
Fri Oct 11 08:16:23 PDT 2024


Hi,

> +static __always_inline int
> +kunwind_next_frame_record(struct kunwind_state *state)
> +{
> +	unsigned long fp = state->common.fp;
> +	struct frame_record *record;
> +	struct stack_info *info;
> +	unsigned long new_fp, new_pc;
> +
> +	if (fp & 0x7)
> +		return -EINVAL;
> +
> +	info = unwind_find_stack(&state->common, fp, sizeof(*record));
> +	if (!info)
> +		return -EINVAL;
> +
> +	record = (struct frame_record *)fp;
> +	new_fp = READ_ONCE(record->fp);
> +	new_pc = READ_ONCE(record->lr);
> +
> +	if (!new_fp && !new_pc)
> +		return kunwind_next_frame_record_meta(state);
> +
> +	unwind_consume_stack(&state->common, info, fp, sizeof(*record));
> +
> +	state->common.fp = new_fp;
> +	state->common.pc = new_pc;
> +	state->source = KUNWIND_SOURCE_FRAME;
> +
> +	return 0;
> +}
> +
>  /*
>   * Unwind from one frame record (A) to the next frame record (B).
>   *
> @@ -165,30 +266,27 @@ kunwind_recover_return_address(struct kunwind_state *state)
>  static __always_inline int
>  kunwind_next(struct kunwind_state *state)
>  {
> -	struct task_struct *tsk = state->task;
> -	unsigned long fp = state->common.fp;
>  	int err;
>  
>  	state->flags.all = 0;
>  
> -	/* Final frame; nothing to unwind */
> -	if (fp == (unsigned long)&task_pt_regs(tsk)->stackframe)
> -		return -ENOENT;
> -
>  	switch (state->source) {
>  	case KUNWIND_SOURCE_FRAME:
>  	case KUNWIND_SOURCE_CALLER:
>  	case KUNWIND_SOURCE_TASK:
> +	case KUNWIND_SOURCE_REGS_LR:
> +		err = kunwind_next_frame_record(state);
> +		break;
>  	case KUNWIND_SOURCE_REGS_PC:
> -		err = unwind_next_frame_record(&state->common);
> -		if (err)
> -			return err;
> -		state->source = KUNWIND_SOURCE_FRAME;
> +		err = kunwind_next_regs_lr(state);

the remaining users of unwind_next_frame_record() after this change are in 
KVM. How does it work there? What is the difference?

Miroslav



More information about the linux-arm-kernel mailing list