Commit 37f44193 authored by Stephanos Ioannidis's avatar Stephanos Ioannidis Committed by Carles Cufi
Browse files

arch: arm: aarch32: Split exc_exit.S for Cortex-M and the rest



The amount of shared code in exc_exit.S between the ARM Cortex-M and
the rest (i.e. Cortex-A and Cortex-R) is minimal and there is little
benefit in having the two implementations in the same file.

This commit splits the interrupt/exception exit code for the
Cortex-A/-R and Cortex-M into separate files to improve readability as
well as maintainability.

Signed-off-by: default avatarStephanos Ioannidis <root@stephanos.io>
parent adf3c236
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@ if (CONFIG_COVERAGE)
endif ()

zephyr_library_sources(
  exc_exit.S
  swap.c
  swap_helper.S
  irq_manage.c
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ zephyr_library()
zephyr_library_sources(
  vector_table.S
  reset.S
  exc_exit.S
  fault.c
  irq_init.c
  reboot.c
+111 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2020 Stephanos Ioannidis <root@stephanos.io>
 * Copyright (c) 2016 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief ARM Cortex-A and Cortex-R exception/interrupt exit API
 *
 * Provides functions for performing kernel handling when exiting exceptions,
 * or interrupts that are installed directly in the vector table (i.e. that are
 * not wrapped around by _isr_wrapper()).
 */

#include <toolchain.h>
#include <linker/sections.h>
#include <offsets_short.h>
#include <arch/cpu.h>

_ASM_FILE_PROLOGUE

GTEXT(z_arm_exc_exit)
GTEXT(z_arm_int_exit)
GTEXT(z_arm_pendsv)
GDATA(_kernel)

/**
 * @brief Kernel housekeeping when exiting interrupt handler installed directly
 *        in the vector table
 *
 * Kernel allows installing interrupt handlers (ISRs) directly into the vector
 * table to get the lowest interrupt latency possible. This allows the ISR to
 * be invoked directly without going through a software interrupt table.
 * However, upon exiting the ISR, some kernel work must still be performed,
 * namely possible context switching. While ISRs connected in the software
 * interrupt table do this automatically via a wrapper, ISRs connected directly
 * in the vector table must invoke z_arm_int_exit() as the *very last* action
 * before returning.
 *
 * e.g.
 *
 * void myISR(void)
 * {
 * 	printk("in %s\n", __FUNCTION__);
 * 	doStuff();
 * 	z_arm_int_exit();
 * }
 */

SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_int_exit)

/* z_arm_int_exit falls through to z_arm_exc_exit (they are aliases of each
 * other)
 */

/**
 *
 * @brief Kernel housekeeping when exiting exception handler installed
 * 		directly in vector table
 *
 * See z_arm_int_exit().
 *
 * @return N/A
 */

SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_exc_exit)

#ifdef CONFIG_PREEMPT_ENABLED
	/* Do not context switch if exiting a nested interrupt */
	ldr r3, =_kernel
	ldr r0, [r3, #_kernel_offset_to_nested]
	cmp r0, #1
	bhi _EXIT_EXC

	ldr r1, [r3, #_kernel_offset_to_current]
	ldr r0, [r3, #_kernel_offset_to_ready_q_cache]
	cmp r0, r1
	blne z_arm_pendsv
_EXIT_EXC:
#endif /* CONFIG_PREEMPT_ENABLED */

#ifdef CONFIG_STACK_SENTINEL
	bl z_check_stack_sentinel
#endif /* CONFIG_STACK_SENTINEL */

	/* Disable nested interrupts while exiting */
	cpsid i

	/* Decrement interrupt nesting count */
	ldr r2, =_kernel
	ldr r0, [r2, #_kernel_offset_to_nested]
	sub r0, r0, #1
	str r0, [r2, #_kernel_offset_to_nested]

	/* Restore previous stack pointer */
	pop {r2, r3}
	add sp, sp, r3

	/*
	 * Restore r0-r3, r12 and lr_irq stored into the process stack by the
	 * mode entry function. These registers are saved by _isr_wrapper for
	 * IRQ mode and z_arm_svc for SVC mode.
	 *
	 * r0-r3 are either the values from the thread before it was switched
	 * out or they are the args to _new_thread for a new thread.
	 */
	cps #MODE_SYS
	pop {r0-r3, r12, lr}
	rfeia sp!
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ zephyr_library_sources(
  vector_table.S
  reset.S
  fault.c
  exc_exit.S
  scb.c
  irq_init.c
  thread_abort.c
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2014 Wind River Systems, Inc.
 * Copyright (c) 2020 Stephanos Ioannidis <root@stephanos.io>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief ARM Cortex-M and Cortex-R exception/interrupt exit API
 *
 * @brief ARM Cortex-M exception/interrupt exit API
 *
 * Provides functions for performing kernel handling when exiting exceptions or
 * interrupts that are installed directly in the vector table (i.e. that are not
@@ -25,9 +23,6 @@ _ASM_FILE_PROLOGUE
GTEXT(z_arm_exc_exit)
GTEXT(z_arm_int_exit)
GDATA(_kernel)
#if defined(CONFIG_CPU_CORTEX_R)
GTEXT(z_arm_pendsv)
#endif

/**
 *
@@ -76,26 +71,15 @@ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_exc_exit)
#ifdef CONFIG_PREEMPT_ENABLED
	ldr r3, =_kernel

#ifndef CONFIG_CPU_CORTEX_M
    /* Do not context switch if exiting a nested interrupt */
    ldr r0, [r3, #_kernel_offset_to_nested]
    cmp r0, #1
    bhi _EXIT_EXC
#endif /* !CONFIG_CPU_CORTEX_M */

	ldr r1, [r3, #_kernel_offset_to_current]
	ldr r0, [r3, #_kernel_offset_to_ready_q_cache]
	cmp r0, r1
	beq _EXIT_EXC

#if defined(CONFIG_CPU_CORTEX_M)
	/* context switch required, pend the PendSV exception */
	ldr r1, =_SCS_ICSR
	ldr r2, =_SCS_ICSR_PENDSV
	str r2, [r1]
#elif defined(CONFIG_CPU_CORTEX_R)
    bl z_arm_pendsv
#endif

_ExcExitWithGdbStub:

@@ -103,7 +87,6 @@ _EXIT_EXC:
#endif /* CONFIG_PREEMPT_ENABLED */

#ifdef CONFIG_STACK_SENTINEL
#if defined(CONFIG_CPU_CORTEX_M)
	push {r0, lr}
	bl z_check_stack_sentinel
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
@@ -112,36 +95,6 @@ _EXIT_EXC:
#else
	pop {r0, lr}
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
#else
    bl z_check_stack_sentinel
#endif /* CONFIG_CPU_CORTEX_M */
#endif /* CONFIG_STACK_SENTINEL */

#if defined(CONFIG_CPU_CORTEX_M)
	bx lr
#elif defined(CONFIG_CPU_CORTEX_R)
    /* Disable nested interrupts while exiting */
    cpsid i

    /* Decrement interrupt nesting count */
    ldr r2, =_kernel
    ldr r0, [r2, #_kernel_offset_to_nested]
    sub r0, r0, #1
    str r0, [r2, #_kernel_offset_to_nested]

    /* Restore previous stack pointer */
    pop {r2, r3}
    add sp, sp, r3

    /*
     * Restore r0-r3, r12 and lr_irq stored into the process stack by the mode
     * entry function. These registers are saved by _isr_wrapper for IRQ mode
     * and z_arm_svc for SVC mode.
     *
     * r0-r3 are either the values from the thread before it was switched out
     * or they are the args to _new_thread for a new thread.
     */
    cps #MODE_SYS
    pop {r0-r3, r12, lr}
    rfeia sp!
#endif
Loading