2015-04-10 16:44:37 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2010-2014 Wind River Systems, Inc.
|
|
|
|
|
*
|
2017-01-18 17:01:01 -08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2015-04-10 16:44:37 -07:00
|
|
|
*/
|
|
|
|
|
|
2015-12-04 10:09:39 -05:00
|
|
|
/**
|
|
|
|
|
* @file
|
|
|
|
|
* @brief Interrupt management support for IA-32 architecture
|
|
|
|
|
*
|
|
|
|
|
* This module implements assembly routines to manage interrupts on
|
|
|
|
|
* the Intel IA-32 architecture. More specifically, the interrupt (asynchronous
|
|
|
|
|
* exception) stubs are implemented in this module. The stubs are invoked when
|
|
|
|
|
* entering and exiting a C interrupt handler.
|
|
|
|
|
*/
|
2023-07-06 22:27:04 +02:00
|
|
|
#define LOAPIC_BASE_ADDRESS DT_REG_ADDR(DT_NODELABEL(intc_loapic))
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2022-05-09 13:56:13 +02:00
|
|
|
#include <zephyr/arch/x86/ia32/asm.h>
|
2016-11-08 10:36:50 -05:00
|
|
|
#include <offsets_short.h>
|
2022-05-09 13:56:13 +02:00
|
|
|
#include <zephyr/arch/cpu.h>
|
|
|
|
|
#include <zephyr/drivers/interrupt_controller/sysapic.h>
|
2025-03-25 16:14:35 -07:00
|
|
|
#include <cet_asm.inc>
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2025-03-25 15:55:31 -07:00
|
|
|
#ifdef CONFIG_X86_CET_SOC_PREPARE_SHADOW_STACK_SWITCH
|
|
|
|
|
#include <soc_cet.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
/* exports (internal APIs) */
|
|
|
|
|
|
2016-09-23 14:01:39 -07:00
|
|
|
GTEXT(_interrupt_enter)
|
2019-03-14 09:20:46 -06:00
|
|
|
GTEXT(z_SpuriousIntNoErrCodeHandler)
|
|
|
|
|
GTEXT(z_SpuriousIntHandler)
|
2015-11-17 14:08:45 -08:00
|
|
|
GTEXT(_irq_sw_handler)
|
2018-10-30 16:55:38 -07:00
|
|
|
GTEXT(z_dynamic_stubs_begin)
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-11-17 13:31:42 -05:00
|
|
|
/* externs */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2019-11-07 12:43:29 -08:00
|
|
|
GTEXT(arch_swap)
|
2016-09-02 16:34:35 -04:00
|
|
|
|
2020-09-01 18:31:40 -04:00
|
|
|
#ifdef CONFIG_PM
|
2024-05-31 14:56:03 -07:00
|
|
|
GTEXT(pm_system_resume)
|
2016-03-18 16:43:40 -07:00
|
|
|
#endif
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-07-01 17:22:39 -04:00
|
|
|
/**
|
|
|
|
|
*
|
2015-07-01 17:51:40 -04:00
|
|
|
* @brief Inform the kernel of an interrupt
|
2015-07-01 17:22:39 -04:00
|
|
|
*
|
2016-01-27 10:07:31 -08:00
|
|
|
* This function is called from the interrupt stub created by IRQ_CONNECT()
|
2015-07-01 17:22:39 -04:00
|
|
|
* to inform the kernel of an interrupt. This routine increments
|
2016-11-08 10:36:50 -05:00
|
|
|
* _kernel.nested (to support interrupt nesting), switches to the
|
2015-07-01 17:22:39 -04:00
|
|
|
* base of the interrupt stack, if not already on the interrupt stack, and then
|
|
|
|
|
* saves the volatile integer registers onto the stack. Finally, control is
|
|
|
|
|
* returned back to the interrupt stub code (which will then invoke the
|
|
|
|
|
* "application" interrupt service routine).
|
|
|
|
|
*
|
|
|
|
|
* Only the volatile integer registers are saved since ISRs are assumed not to
|
2018-03-06 13:42:29 -08:00
|
|
|
* utilize floating point (or SSE) instructions.
|
2015-07-01 17:22:39 -04:00
|
|
|
*
|
|
|
|
|
* WARNINGS
|
|
|
|
|
*
|
|
|
|
|
* Host-based tools and the target-based GDB agent depend on the stack frame
|
|
|
|
|
* created by this routine to determine the locations of volatile registers.
|
|
|
|
|
* These tools must be updated to reflect any changes to the stack frame.
|
|
|
|
|
*
|
|
|
|
|
* C function prototype:
|
|
|
|
|
*
|
2016-09-23 14:01:39 -07:00
|
|
|
* void _interrupt_enter(void *isr, void *isr_param);
|
2015-07-01 17:22:39 -04:00
|
|
|
*/
|
kernel: mmu: remove LINKER_USE_PINNED_SECTION and __pinned_* tagging
CONFIG_LINKER_USE_PINNED_SECTION is the second half of the selective
kernel-pinning model removed in issue #108773. With the kernel image
now always resident at boot (previous commit), the __pinned_*
attribute family is a no-op: every page they would have segregated is
already pinned by z_mem_manage_init()'s whole-image loop, so the
tagging contract neither adds safety nor remains maintainable.
Drop it.
Mechanical removals:
* All ~219 in-tree uses of __pinned_text, __pinned_rodata,
__pinned_data, __pinned_bss, __pinned_noinit, and __pinned_func
across arch/x86, drivers/interrupt_controller, drivers/timer,
arch/common, kernel, lib/libc, subsys/portability/posix, tests, and
the syscall code generator (scripts/build/gen_syscalls.py).
* The assembly aliases PINNED_TEXT/RODATA/DATA/BSS/NOINIT used in
arch/x86/core/ia32/*.S and drivers/interrupt_controller/
intc_loapic_spurious.S become plain TEXT/RODATA/DATA/BSS/NOINIT.
* K_KERNEL_PINNED_STACK_DEFINE, K_KERNEL_PINNED_STACK_ARRAY_DEFINE,
K_KERNEL_PINNED_STACK_ARRAY_DECLARE, K_THREAD_PINNED_STACK_DEFINE,
and K_THREAD_PINNED_STACK_ARRAY_DEFINE are removed. The few
in-tree callers (kernel/init.c, arch/arm/core/cortex_a_r/smp.c,
arch/arm64/core/fatal.c, arch/rx/core/prep_c.c,
arch/x86/core/prep_c.c, kernel/include/kernel_internal.h,
tests/bluetooth/hci_uart_async) move to the corresponding
non-pinned macros.
Machinery removals:
* Kconfig.zephyr drops CONFIG_LINKER_USE_PINNED_SECTION.
qemu_x86_tiny and qemu_x86_atom_virt drop their =y overrides.
* include/zephyr/linker/section_tags.h drops the __pinned_* macro
definitions (both arms). __isr collapses to an empty macro since
its only purpose was to alias __pinned_func.
* include/zephyr/linker/sections.h drops PINNED_TEXT_SECTION_NAME,
PINNED_BSS_SECTION_NAME, etc. and the bare PINNED_TEXT/RODATA/etc.
forwarders, plus the _APP_SMEM_PINNED_SECTION_NAME constant.
* include/zephyr/linker/linker-defs.h drops the lnkr_pinned_*
externs, the _app_smem_pinned_* externs, and the lnkr_is_pinned()
/ lnkr_is_region_pinned() inline helpers.
* include/zephyr/linker/utils.h drops the lnkr_pinned_rodata branch
in linker_is_in_rodata().
* include/zephyr/linker/app_smem_pinned{,_aligned,_unaligned}.ld
are deleted; cmake/linker/ld/target_configure.cmake stops
configuring them.
* boards/qemu/x86/qemu_x86_tiny.ld and
include/zephyr/arch/x86/ia32/linker.ld drop their pinned-section
blocks and the now-redundant #ifndef CONFIG_LINKER_USE_PINNED_SECTION
conditionals throughout the body. The
LIB_KERNEL_IN_SECT / LIB_ARCH_X86_IN_SECT / LIB_ZEPHYR_IN_SECT /
LIB_C_IN_SECT / LIB_DRIVERS_IN_SECT / LIB_SUBSYS_LOGGING_IN_SECT /
LIB_ZEPHYR_OBJECT_FILE_IN_SECT / ZEPHYR_KERNEL_FUNCS_IN_SECT macros
in qemu_x86_tiny.ld are deleted; they existed only to feed the
pinned text/rodata/data/bss/noinit sections.
* kernel/mmu.c drops the mark_linker_section_pinned(lnkr_pinned_start,
...) call. The mark_linker_section_pinned() helper survives but is
now gated only on CONFIG_LINKER_USE_BOOT_SECTION.
* arch/common/init.c and include/zephyr/arch/common/init.h drop
arch_bss_zero_pinned(); arch/x86/core/ia32/crt0.S drops the call
to it.
* arch/x86/core/userspace.c drops the eager k_mem_page_in() of the
thread's privileged stack on user-mode entry. With the kernel
image fully resident the stack is already mapped.
* arch/x86/gen_mmu.py drops map_region("lnkr_pinned") and the
set_region_perms() calls for lnkr_pinned_text / lnkr_pinned_rodata.
* CMakeLists.txt drops the LINKER_USE_PINNED_SECTION block that
generated APP_SMEM_PINNED_* variables and the
pinned_partitions target property feeding gen_app_partitions.py.
cmake/modules/extensions.cmake removes the PINNED_RODATA /
PINNED_RAM_SECTIONS / PINNED_DATA_SECTIONS zephyr_linker_sources()
location keywords and their snippet files.
scripts/build/gen_app_partitions.py drops --pinoutput /
--pinpartitions arguments and the pinned-output branch.
subsys/testsuite/coverage/CMakeLists.txt drops its
CONFIG_DEMAND_PAGING-conditional fork.
* scripts/build/gen_kobject_list.py drops the
app_smem_pinned_start / _end fallback for kobject placement
validation.
* tests/arch/x86/pagetables and tests/kernel/mem_protect/userspace
drop their lnkr_pinned_text / lnkr_pinned_rodata branches.
* include/zephyr/arch/x86/ia32/arch.h folds IRQSTUBS_TEXT_SECTION
to the unconditional ".text.irqstubs" form.
* tests/subsys/llext/src/syscalls_ext.c drops a stale comment about
syscalls landing in .pinned_text.
Targeted retentions:
* arch/x86/core/bootargs.c keeps multiboot_cmdline and efi_bootargs
in .noinit (was __pinned_noinit, which decayed to __noinit when
LINKER_USE_PINNED_SECTION was unset). The multiboot and zefi loader
paths write these buffers before Zephyr's BSS-zero step, so
zeroing them at boot loses the cmdline.
* arch/x86/core/ia32/fatal.c keeps _df_esf and _df_stack in .noinit.
They are scratch space written by the double-fault handler and have
no zero-init requirement; keeping them in .noinit also preserves
the historical post-noinit alignment that gen_mmu.py relies on
(z_mapped_size is computed before CMake-injected iterable sections
are appended to the linker script, so the post-noinit page padding
is what keeps those sections within the mapped region).
* include/zephyr/arch/x86/ia32/syscall.h and
include/zephyr/arch/x86/arch.h wrap the per-arch
arch_syscall_invoke* / arch_is_user_context / arch_k_cycle_get_*
implementations in @cond INTERNAL_HIDDEN. The public Doxygen
contract lives on the prototypes in
include/zephyr/arch/arch_interface.h; the per-arch implementations
are internal. Without this, removing the __pinned_func attribute
exposes the implementations to the doxygen-coverage delta check
as 10 newly-undocumented APIs.
Documentation updates are deferred to a separate commit.
Issue: #108773
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-05-15 16:33:20 -04:00
|
|
|
SECTION_FUNC(TEXT, _interrupt_enter)
|
2019-02-06 15:35:24 -08:00
|
|
|
/*
|
|
|
|
|
* Note that the processor has pushed both the EFLAGS register
|
|
|
|
|
* and the logical return address (cs:eip) onto the stack prior
|
|
|
|
|
* to invoking the handler specified in the IDT. The stack looks
|
|
|
|
|
* like this:
|
|
|
|
|
*
|
|
|
|
|
* 24 SS (only on privilege level change)
|
|
|
|
|
* 20 ESP (only on privilege level change)
|
|
|
|
|
* 16 EFLAGS
|
|
|
|
|
* 12 CS
|
|
|
|
|
* 8 EIP
|
|
|
|
|
* 4 isr_param
|
|
|
|
|
* 0 isr <-- stack pointer
|
|
|
|
|
*/
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
/*
|
2016-08-01 15:59:10 -07:00
|
|
|
* The gen_idt tool creates an interrupt-gate descriptor for
|
2015-04-10 16:44:37 -07:00
|
|
|
* all connections. The processor will automatically clear the IF
|
2016-09-23 14:01:39 -07:00
|
|
|
* bit in the EFLAGS register upon execution of the handler, hence
|
|
|
|
|
* this need not issue an 'cli' as the first instruction.
|
2015-04-10 16:44:37 -07:00
|
|
|
*
|
|
|
|
|
* Clear the direction flag. It is automatically restored when the
|
|
|
|
|
* interrupt exits via the IRET instruction.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
cld
|
|
|
|
|
|
2019-02-06 15:35:24 -08:00
|
|
|
#ifdef CONFIG_X86_KPTI
|
|
|
|
|
call z_x86_trampoline_to_kernel
|
|
|
|
|
#endif
|
2015-04-10 16:44:37 -07:00
|
|
|
/*
|
2016-09-23 14:01:39 -07:00
|
|
|
* Swap EAX with isr_param and EDX with isr.
|
|
|
|
|
* Push ECX onto the stack
|
2015-04-10 16:44:37 -07:00
|
|
|
*/
|
2016-09-23 14:01:39 -07:00
|
|
|
xchgl %eax, 4(%esp)
|
|
|
|
|
xchgl %edx, (%esp)
|
|
|
|
|
pushl %ecx
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2016-09-23 14:01:39 -07:00
|
|
|
/* Now the stack looks like:
|
|
|
|
|
*
|
|
|
|
|
* EFLAGS
|
|
|
|
|
* CS
|
|
|
|
|
* EIP
|
|
|
|
|
* saved EAX
|
|
|
|
|
* saved EDX
|
|
|
|
|
* saved ECX
|
|
|
|
|
*
|
|
|
|
|
* EAX = isr_param, EDX = isr
|
2015-04-10 16:44:37 -07:00
|
|
|
*/
|
|
|
|
|
|
2025-03-25 16:14:35 -07:00
|
|
|
/* Push some registers we will use it for scratch space.
|
|
|
|
|
* Also it helps in stack unwinding
|
2016-09-23 14:01:39 -07:00
|
|
|
* Rest of the callee-saved regs get saved by invocation of C
|
2019-11-07 12:43:29 -08:00
|
|
|
* functions (isr handler, arch_swap(), etc)
|
2016-09-23 14:01:39 -07:00
|
|
|
*/
|
2024-07-04 12:39:28 +03:00
|
|
|
pushl %ebp
|
2025-03-25 16:14:35 -07:00
|
|
|
pushl %edi
|
|
|
|
|
pushl %ebx
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2016-11-08 10:36:50 -05:00
|
|
|
/* load %ecx with &_kernel */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2016-11-08 10:36:50 -05:00
|
|
|
movl $_kernel, %ecx
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
/* switch to the interrupt stack for the non-nested case */
|
|
|
|
|
|
2016-11-08 10:36:50 -05:00
|
|
|
incl _kernel_offset_to_nested(%ecx)
|
|
|
|
|
|
|
|
|
|
/* use interrupt stack if not nested */
|
|
|
|
|
cmpl $1, _kernel_offset_to_nested(%ecx)
|
2015-04-10 16:44:37 -07:00
|
|
|
jne alreadyOnIntStack
|
|
|
|
|
|
2016-11-08 10:36:50 -05:00
|
|
|
/*
|
2024-07-04 12:39:28 +03:00
|
|
|
* switch to base of the interrupt stack: save esp in ebp, then load
|
2016-11-08 10:36:50 -05:00
|
|
|
* irq_stack pointer
|
|
|
|
|
*/
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2024-07-04 12:39:28 +03:00
|
|
|
movl %esp, %ebp
|
2016-11-08 10:36:50 -05:00
|
|
|
movl _kernel_offset_to_irq_stack(%ecx), %esp
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
|
2015-08-20 11:04:01 -04:00
|
|
|
/* save thread's stack pointer onto base of interrupt stack */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2024-07-04 12:39:28 +03:00
|
|
|
pushl %ebp /* Save stack pointer */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2025-05-07 14:02:34 -07:00
|
|
|
#ifdef CONFIG_HW_SHADOW_STACK
|
2025-03-25 16:14:35 -07:00
|
|
|
movl _kernel_offset_to_current(%ecx), %ebp
|
|
|
|
|
cmpl $0, _thread_offset_to_shstk_addr(%ebp)
|
|
|
|
|
jz __sh_stk_verify
|
|
|
|
|
|
2025-03-25 15:55:31 -07:00
|
|
|
/* Create restore SSP token. We can't use saveprevssp as it may
|
|
|
|
|
* conflict with the prepare_shadow_stack_switch from an SoC.
|
|
|
|
|
* Note that first scratch register will contain SSP after this
|
|
|
|
|
* macro runs.
|
2025-03-25 16:14:35 -07:00
|
|
|
*/
|
|
|
|
|
save_ssp_restore_token %ebx, %edi
|
|
|
|
|
movl %ebx, _thread_offset_to_shstk_addr(%ebp)
|
|
|
|
|
|
2025-03-25 15:55:31 -07:00
|
|
|
#ifdef CONFIG_X86_CET_SOC_PREPARE_SHADOW_STACK_SWITCH
|
|
|
|
|
pushl %eax
|
|
|
|
|
pushl %edx
|
|
|
|
|
pushl %ecx
|
|
|
|
|
soc_prepare_irq_shadow_stack_switch
|
|
|
|
|
popl %ecx
|
|
|
|
|
popl %edx
|
|
|
|
|
popl %eax
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-03-25 16:14:35 -07:00
|
|
|
movl _kernel_offset_to_shstk_addr(%ecx), %edi
|
|
|
|
|
rstorssp (%edi)
|
|
|
|
|
discard_previous_ssp_token %edi
|
|
|
|
|
|
|
|
|
|
pushl %ebx /* Save SSP */
|
|
|
|
|
jmp __sh_stk_out
|
|
|
|
|
__sh_stk_verify:
|
|
|
|
|
#ifdef CONFIG_X86_CET_VERIFY_KERNEL_SHADOW_STACK
|
|
|
|
|
pushl %eax
|
|
|
|
|
pushl %edx
|
|
|
|
|
pushl %ecx
|
|
|
|
|
movl $X86_S_CET_MSR, %ecx
|
|
|
|
|
rdmsr
|
|
|
|
|
testl $X86_S_CET_MSR_SHSTK_EN, %eax
|
|
|
|
|
jz __sh_stk_verify_out
|
|
|
|
|
pushl %ebp
|
|
|
|
|
call z_x86_cet_shadow_stack_panic
|
|
|
|
|
|
|
|
|
|
__sh_stk_verify_out:
|
|
|
|
|
popl %ecx
|
|
|
|
|
popl %edx
|
|
|
|
|
popl %eax
|
|
|
|
|
#endif
|
|
|
|
|
__sh_stk_out:
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-09-01 18:31:40 -04:00
|
|
|
#ifdef CONFIG_PM
|
2016-11-08 10:36:50 -05:00
|
|
|
cmpl $0, _kernel_offset_to_idle(%ecx)
|
2016-09-26 13:15:58 -07:00
|
|
|
jne handle_idle
|
2015-04-10 16:44:37 -07:00
|
|
|
/* fast path is !idle, in the pipeline */
|
2020-09-01 18:31:40 -04:00
|
|
|
#endif /* CONFIG_PM */
|
2016-09-26 13:15:58 -07:00
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
/* fall through to nested case */
|
|
|
|
|
|
2016-08-18 09:25:00 -07:00
|
|
|
alreadyOnIntStack:
|
2016-09-23 14:01:39 -07:00
|
|
|
|
2019-08-22 19:46:50 -07:00
|
|
|
push %eax /* interrupt handler argument */
|
|
|
|
|
|
2026-07-12 06:01:07 -04:00
|
|
|
/* CONFIG_SYS_IDLE_HOOKS also needs this hook: x86 halts with interrupts enabled
|
|
|
|
|
* ("sti; hlt"), so this ISR may have interrupted the idle thread and can
|
|
|
|
|
* reschedule away from it before the idle-exit hook runs. Notifying here closes
|
|
|
|
|
* the idle window at the instant idle actually ended.
|
|
|
|
|
*/
|
|
|
|
|
#if defined(CONFIG_TRACING_ISR) || defined(CONFIG_SYS_IDLE_HOOKS)
|
2020-08-20 14:30:28 -04:00
|
|
|
/* Save these as we are using to keep track of isr and isr_param */
|
|
|
|
|
pushl %eax
|
|
|
|
|
pushl %edx
|
|
|
|
|
call sys_trace_isr_enter
|
|
|
|
|
popl %edx
|
|
|
|
|
popl %eax
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-10-19 15:08:43 -04:00
|
|
|
#ifdef CONFIG_NESTED_INTERRUPTS
|
2015-04-10 16:44:37 -07:00
|
|
|
sti /* re-enable interrupts */
|
2015-08-19 18:01:26 -04:00
|
|
|
#endif
|
2016-09-23 14:01:39 -07:00
|
|
|
/* Now call the interrupt handler */
|
2019-12-18 15:11:59 -08:00
|
|
|
call *%edx
|
2016-09-23 14:01:39 -07:00
|
|
|
/* Discard ISR argument */
|
|
|
|
|
addl $0x4, %esp
|
|
|
|
|
#ifdef CONFIG_NESTED_INTERRUPTS
|
|
|
|
|
cli /* disable interrupts again */
|
2016-07-08 13:53:50 -07:00
|
|
|
#endif
|
2016-08-02 12:05:08 -07:00
|
|
|
|
2020-08-20 14:30:28 -04:00
|
|
|
#if defined(CONFIG_TRACING_ISR)
|
|
|
|
|
pushl %eax
|
|
|
|
|
call sys_trace_isr_exit
|
|
|
|
|
popl %eax
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-05-10 13:40:32 +08:00
|
|
|
#if defined(CONFIG_X86_RUNTIME_IRQ_STATS)
|
|
|
|
|
/*
|
|
|
|
|
* The runtime_irq_stats() function should be implemented
|
|
|
|
|
* by platform with this config.
|
|
|
|
|
*/
|
|
|
|
|
pushl %eax
|
|
|
|
|
call runtime_irq_stats
|
|
|
|
|
popl %eax
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-06-28 13:06:37 -07:00
|
|
|
xorl %eax, %eax
|
2019-09-11 14:20:49 -04:00
|
|
|
#if defined(CONFIG_X2APIC)
|
|
|
|
|
xorl %edx, %edx
|
|
|
|
|
movl $(X86_X2APIC_BASE_MSR + (LOAPIC_EOI >> 4)), %ecx
|
|
|
|
|
wrmsr
|
|
|
|
|
#else /* xAPIC */
|
2020-06-26 12:09:01 -07:00
|
|
|
#ifdef DEVICE_MMIO_IS_IN_RAM
|
2023-07-06 22:27:04 +02:00
|
|
|
movl Z_TOPLEVEL_RAM_NAME(LOAPIC_REGS_STR), %edx
|
2020-06-26 12:09:01 -07:00
|
|
|
movl %eax, LOAPIC_EOI(%edx)
|
|
|
|
|
#else
|
2023-07-06 22:27:04 +02:00
|
|
|
movl %eax, (LOAPIC_BASE_ADDRESS + LOAPIC_EOI)
|
2020-06-26 12:09:01 -07:00
|
|
|
#endif /* DEVICE_MMIO_IS_IN_RAM */
|
|
|
|
|
#endif /* CONFIG_X2APIC */
|
2016-08-02 12:05:08 -07:00
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
/* determine whether exiting from a nested interrupt */
|
2016-11-08 10:36:50 -05:00
|
|
|
movl $_kernel, %ecx
|
|
|
|
|
decl _kernel_offset_to_nested(%ecx) /* dec interrupt nest count */
|
2015-04-10 16:44:37 -07:00
|
|
|
jne nestedInterrupt /* 'iret' if nested case */
|
|
|
|
|
|
2016-12-14 14:34:29 -05:00
|
|
|
#ifdef CONFIG_PREEMPT_ENABLED
|
2016-11-08 10:36:50 -05:00
|
|
|
movl _kernel_offset_to_current(%ecx), %edx
|
2016-09-02 16:34:35 -04:00
|
|
|
|
|
|
|
|
/* reschedule only if the scheduler says that we must do so */
|
kernel/arch: enhance the "ready thread" cache
The way the ready thread cache was implemented caused it to not always
be "hot", i.e. there could be some misses, which happened when the
cached thread was taken out of the ready queue. When that happened, it
was not replaced immediately, since doing so could mean that the
replacement might not run because the flow could be interrupted and
another thread could take its place. This was the more conservative
approach that insured that moving a thread to the cache would never be
wasted.
However, this caused two problems:
1. The cache could not be refilled until another thread context-switched
in, since there was no thread in the cache to compare priorities
against.
2. Interrupt exit code would always have to call into C to find what
thread to run when the current thread was not coop and did not have the
scheduler locked. Furthermore, it was possible for this code path to
encounter a cold cache and then it had to find out what thread to run
the long way.
To fix this, filling the cache is now more aggressive, i.e. the next
thread to put in the cache is found even in the case the current cached
thread is context-switched out. This ensures the interrupt exit code is
much faster on the slow path. In addition, since finding the next thread
to run is now always "get it from the cache", which is a simple fetch
from memory (_kernel.ready_q.cache), there is no need to call the more
complex C code.
On the ARM FRDM K64F board, this improvement is seen:
Before:
1- Measure time to switch from ISR back to interrupted task
switching time is 215 tcs = 1791 nsec
2- Measure time from ISR to executing a different task (rescheduled)
switch time is 315 tcs = 2625 nsec
After:
1- Measure time to switch from ISR back to interrupted task
switching time is 130 tcs = 1083 nsec
2- Measure time from ISR to executing a different task (rescheduled)
switch time is 225 tcs = 1875 nsec
These are the most dramatic improvements, but most of the numbers
generated by the latency_measure test are improved.
Fixes ZEP-1401.
Change-Id: I2eaac147048b1ec71a93bd0a285e743a39533973
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-12-02 10:37:27 -05:00
|
|
|
cmpl %edx, _kernel_offset_to_ready_q_cache(%ecx)
|
|
|
|
|
je noReschedule
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
/*
|
2019-09-18 19:30:39 -04:00
|
|
|
* Set X86_THREAD_FLAG_INT bit in k_thread to allow the upcoming call
|
2019-11-07 12:43:29 -08:00
|
|
|
* to arch_swap() to determine whether non-floating registers need to be
|
2015-04-10 16:44:37 -07:00
|
|
|
* preserved using the lazy save/restore algorithm, or to indicate to
|
|
|
|
|
* debug tools that a preemptive context switch has occurred.
|
|
|
|
|
*/
|
2015-08-22 18:41:06 -04:00
|
|
|
|
2020-05-03 18:18:37 +09:00
|
|
|
#if defined(CONFIG_LAZY_FPU_SHARING)
|
2019-09-18 19:30:39 -04:00
|
|
|
orb $X86_THREAD_FLAG_INT, _thread_offset_to_flags(%edx)
|
2015-04-10 16:44:37 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A context reschedule is required: keep the volatile registers of
|
2015-08-20 11:04:01 -04:00
|
|
|
* the interrupted thread on the context's stack. Utilize
|
2019-11-07 12:43:29 -08:00
|
|
|
* the existing arch_swap() primitive to save the remaining
|
2015-04-10 16:44:37 -07:00
|
|
|
* thread's registers (including floating point) and perform
|
2015-08-20 11:04:01 -04:00
|
|
|
* a switch to the new thread.
|
2015-04-10 16:44:37 -07:00
|
|
|
*/
|
|
|
|
|
|
2025-05-07 14:02:34 -07:00
|
|
|
#ifdef CONFIG_HW_SHADOW_STACK
|
2025-03-25 16:14:35 -07:00
|
|
|
movl _kernel_offset_to_current(%ecx), %edi
|
|
|
|
|
cmpl $0, _thread_offset_to_shstk_addr(%edi)
|
|
|
|
|
jz __sh_stk_out_reschedule
|
|
|
|
|
|
|
|
|
|
/* No need to save SSP on _kernel as it should always be at the
|
|
|
|
|
* same location. But we need to have a token there.
|
|
|
|
|
*/
|
|
|
|
|
save_ssp_restore_token %edi, %ebx
|
|
|
|
|
|
2025-03-25 15:55:31 -07:00
|
|
|
#ifdef CONFIG_X86_CET_SOC_PREPARE_SHADOW_STACK_SWITCH
|
|
|
|
|
pushl %edi
|
|
|
|
|
soc_prepare_shadow_stack_switch
|
|
|
|
|
popl %edi
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-03-25 16:14:35 -07:00
|
|
|
popl %ebp /* Get previous SSP token */
|
|
|
|
|
rstorssp (%ebp)
|
|
|
|
|
discard_previous_ssp_token %ebp
|
|
|
|
|
__sh_stk_out_reschedule:
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-09-02 16:34:35 -04:00
|
|
|
popl %esp /* switch back to outgoing thread's stack */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2017-06-07 09:33:16 -07:00
|
|
|
#ifdef CONFIG_STACK_SENTINEL
|
2019-03-08 14:19:05 -07:00
|
|
|
call z_check_stack_sentinel
|
kernel: tickless: Add tickless kernel support
Adds event based scheduling logic to the kernel. Updates
management of timeouts, timers, idling etc. based on
time tracked at events rather than periodic ticks. Provides
interfaces for timers to announce and get next timer expiry
based on kernel scheduling decisions involving time slicing
of threads, timeouts and idling. Uses wall time units instead
of ticks in all scheduling activities.
The implementation involves changes in the following areas
1. Management of time in wall units like ms/us instead of ticks
The existing implementation already had an option to configure
number of ticks in a second. The new implementation builds on
top of that feature and provides option to set the size of the
scheduling granurality to mili seconds or micro seconds. This
allows most of the current implementation to be reused. Due to
this re-use and co-existence with tick based kernel, the names
of variables may contain the word "tick". However, in the
tickless kernel implementation, it represents the currently
configured time unit, which would be be mili seconds or
micro seconds. The APIs that take time as a parameter are not
impacted and they continue to pass time in mili seconds.
2. Timers would not be programmed in periodic mode
generating ticks. Instead they would be programmed in one
shot mode to generate events at the time the kernel scheduler
needs to gain control for its scheduling activities like
timers, timeouts, time slicing, idling etc.
3. The scheduler provides interfaces that the timer drivers
use to announce elapsed time and get the next time the scheduler
needs a timer event. It is possible that the scheduler may not
need another timer event, in which case the system would wait
for a non-timer event to wake it up if it is idling.
4. New APIs are defined to be implemented by timer drivers. Also
they need to handler timer events differently. These changes
have been done in the HPET timer driver. In future other timers
that support tickles kernel should implement these APIs as well.
These APIs are to re-program the timer, update and announce
elapsed time.
5. Philosopher and timer_api applications have been enabled to
test tickless kernel. Separate configuration files are created
which define the necessary CONFIG flags. Run these apps using
following command
make pristine && make BOARD=qemu_x86 CONF_FILE=prj_tickless.conf qemu
Jira: ZEP-339 ZEP-1946 ZEP-948
Change-Id: I7d950c31bf1ff929a9066fad42c2f0559a2e5983
Signed-off-by: Ramesh Thomas <ramesh.thomas@intel.com>
2017-02-05 19:37:19 -08:00
|
|
|
#endif
|
2015-04-10 16:44:37 -07:00
|
|
|
pushfl /* push KERNEL_LOCK_KEY argument */
|
2019-11-07 12:43:29 -08:00
|
|
|
call arch_swap
|
2016-07-08 13:53:50 -07:00
|
|
|
addl $4, %esp /* pop KERNEL_LOCK_KEY argument */
|
2019-08-22 19:46:50 -07:00
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
/*
|
2015-08-20 11:04:01 -04:00
|
|
|
* The interrupted thread has now been scheduled,
|
2019-11-07 12:43:29 -08:00
|
|
|
* as the result of a _later_ invocation of arch_swap().
|
2015-04-10 16:44:37 -07:00
|
|
|
*
|
2015-08-20 11:04:01 -04:00
|
|
|
* Now need to restore the interrupted thread's environment before
|
2015-04-10 16:44:37 -07:00
|
|
|
* returning control to it at the point where it was interrupted ...
|
|
|
|
|
*/
|
2015-08-22 18:41:06 -04:00
|
|
|
|
2020-05-03 18:18:37 +09:00
|
|
|
#if defined(CONFIG_LAZY_FPU_SHARING)
|
2015-04-10 16:44:37 -07:00
|
|
|
/*
|
2019-11-07 12:43:29 -08:00
|
|
|
* arch_swap() has restored the floating point registers, if needed.
|
2019-09-18 19:30:39 -04:00
|
|
|
* Clear X86_THREAD_FLAG_INT in the interrupted thread's state
|
2015-04-10 16:44:37 -07:00
|
|
|
* since it has served its purpose.
|
|
|
|
|
*/
|
2015-08-22 18:41:06 -04:00
|
|
|
|
2016-11-08 10:36:50 -05:00
|
|
|
movl _kernel + _kernel_offset_to_current, %eax
|
2019-09-18 19:30:39 -04:00
|
|
|
andb $~X86_THREAD_FLAG_INT, _thread_offset_to_flags(%eax)
|
2020-05-03 18:18:37 +09:00
|
|
|
#endif /* CONFIG_LAZY_FPU_SHARING */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-08-20 11:04:01 -04:00
|
|
|
/* Restore volatile registers and return to the interrupted thread */
|
2025-03-25 16:14:35 -07:00
|
|
|
popl %ebx
|
|
|
|
|
popl %edi
|
2024-07-04 12:39:28 +03:00
|
|
|
popl %ebp
|
2015-04-10 16:44:37 -07:00
|
|
|
popl %ecx
|
2016-09-23 14:01:39 -07:00
|
|
|
popl %edx
|
2015-08-22 18:41:06 -04:00
|
|
|
popl %eax
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
/* Pop of EFLAGS will re-enable interrupts and restore direction flag */
|
2019-02-06 15:35:24 -08:00
|
|
|
KPTI_IRET
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2016-12-14 14:34:29 -05:00
|
|
|
#endif /* CONFIG_PREEMPT_ENABLED */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2016-08-18 09:25:00 -07:00
|
|
|
noReschedule:
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A thread reschedule is not required; switch back to the
|
|
|
|
|
* interrupted thread's stack and restore volatile registers
|
|
|
|
|
*/
|
|
|
|
|
|
2025-05-07 14:02:34 -07:00
|
|
|
#ifdef CONFIG_HW_SHADOW_STACK
|
2025-03-25 16:14:35 -07:00
|
|
|
movl _kernel_offset_to_current(%ecx), %ebp
|
|
|
|
|
cmpl $0, _thread_offset_to_shstk_addr(%ebp)
|
|
|
|
|
jz __sh_stk_out_no_reschedule
|
|
|
|
|
|
|
|
|
|
/* No need to save SSP on _kernel as it should always be at the
|
|
|
|
|
* same location. But we need to have a token there.
|
|
|
|
|
*/
|
|
|
|
|
save_ssp_restore_token %edi, %ebx
|
|
|
|
|
|
2025-03-25 15:55:31 -07:00
|
|
|
#ifdef CONFIG_X86_CET_SOC_PREPARE_SHADOW_STACK_SWITCH
|
|
|
|
|
pushl %ebp
|
|
|
|
|
soc_prepare_shadow_stack_switch
|
|
|
|
|
popl %ebp
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-03-25 16:14:35 -07:00
|
|
|
popl %ebp /* Get previous SSP token position */
|
|
|
|
|
rstorssp (%ebp)
|
|
|
|
|
discard_previous_ssp_token %ebp
|
|
|
|
|
__sh_stk_out_no_reschedule:
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
popl %esp /* pop thread stack pointer */
|
|
|
|
|
|
2017-05-11 13:29:15 -07:00
|
|
|
#ifdef CONFIG_STACK_SENTINEL
|
2019-03-08 14:19:05 -07:00
|
|
|
call z_check_stack_sentinel
|
2017-05-11 13:29:15 -07:00
|
|
|
#endif
|
2017-06-07 09:33:16 -07:00
|
|
|
|
2015-04-10 16:44:37 -07:00
|
|
|
/* fall through to 'nestedInterrupt' */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* For the nested interrupt case, the interrupt stack must still be
|
|
|
|
|
* utilized, and more importantly, a rescheduling decision must
|
|
|
|
|
* not be performed.
|
|
|
|
|
*/
|
|
|
|
|
|
2016-08-18 09:25:00 -07:00
|
|
|
nestedInterrupt:
|
2025-03-25 16:14:35 -07:00
|
|
|
popl %ebx
|
|
|
|
|
popl %edi
|
2024-07-04 12:39:28 +03:00
|
|
|
popl %ebp
|
2016-09-23 14:01:39 -07:00
|
|
|
popl %ecx /* pop volatile registers in reverse order */
|
|
|
|
|
popl %edx
|
2015-04-10 16:44:37 -07:00
|
|
|
popl %eax
|
|
|
|
|
/* Pop of EFLAGS will re-enable interrupts and restore direction flag */
|
2019-02-06 15:35:24 -08:00
|
|
|
KPTI_IRET
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
|
2020-09-01 18:31:40 -04:00
|
|
|
#ifdef CONFIG_PM
|
2016-09-26 13:15:58 -07:00
|
|
|
handle_idle:
|
|
|
|
|
pushl %eax
|
|
|
|
|
pushl %edx
|
2016-11-08 10:36:50 -05:00
|
|
|
/* Zero out _kernel.idle */
|
|
|
|
|
movl $0, _kernel_offset_to_idle(%ecx)
|
2016-09-26 13:15:58 -07:00
|
|
|
|
|
|
|
|
/*
|
2024-05-31 14:56:03 -07:00
|
|
|
* Beware that a timer driver's pm_system_resume() implementation might
|
2016-09-26 13:15:58 -07:00
|
|
|
* expect that interrupts are disabled when invoked. This ensures that
|
|
|
|
|
* the calculation and programming of the device for the next timer
|
|
|
|
|
* deadline is not interrupted.
|
|
|
|
|
*/
|
|
|
|
|
|
2024-05-31 14:56:03 -07:00
|
|
|
call pm_system_resume
|
2016-09-26 13:15:58 -07:00
|
|
|
popl %edx
|
|
|
|
|
popl %eax
|
|
|
|
|
jmp alreadyOnIntStack
|
2020-09-01 18:31:40 -04:00
|
|
|
#endif /* CONFIG_PM */
|
2016-09-26 13:15:58 -07:00
|
|
|
|
2015-07-01 17:22:39 -04:00
|
|
|
/**
|
|
|
|
|
*
|
2019-03-14 09:20:46 -06:00
|
|
|
* z_SpuriousIntHandler -
|
2015-07-01 17:51:40 -04:00
|
|
|
* @brief Spurious interrupt handler stubs
|
2015-07-01 17:22:39 -04:00
|
|
|
*
|
|
|
|
|
* Interrupt-gate descriptors are statically created for all slots in the IDT
|
2019-03-14 09:20:46 -06:00
|
|
|
* that point to z_SpuriousIntHandler() or z_SpuriousIntNoErrCodeHandler(). The
|
2015-07-01 17:22:39 -04:00
|
|
|
* former stub is connected to exception vectors where the processor pushes an
|
|
|
|
|
* error code onto the stack (or kernel stack) in addition to the EFLAGS/CS/EIP
|
|
|
|
|
* records.
|
|
|
|
|
*
|
2019-07-11 14:18:28 -07:00
|
|
|
* A spurious interrupt is considered a fatal condition; there is no provision
|
|
|
|
|
* to return to the interrupted execution context and thus the volatile
|
|
|
|
|
* registers are not saved.
|
2015-07-01 17:22:39 -04:00
|
|
|
*
|
2015-07-01 17:29:04 -04:00
|
|
|
* @return Never returns
|
2015-07-01 17:22:39 -04:00
|
|
|
*
|
|
|
|
|
* C function prototype:
|
|
|
|
|
*
|
2019-03-14 09:20:46 -06:00
|
|
|
* void z_SpuriousIntHandler (void);
|
2015-07-01 17:22:39 -04:00
|
|
|
*
|
|
|
|
|
* INTERNAL
|
2016-08-01 15:59:10 -07:00
|
|
|
* The gen_idt tool creates an interrupt-gate descriptor for all
|
2015-07-01 17:22:39 -04:00
|
|
|
* connections. The processor will automatically clear the IF bit
|
|
|
|
|
* in the EFLAGS register upon execution of the handler,
|
2019-03-14 09:20:46 -06:00
|
|
|
* thus z_SpuriousIntNoErrCodeHandler()/z_SpuriousIntHandler() shall be
|
2015-07-01 17:22:39 -04:00
|
|
|
* invoked with interrupts disabled.
|
|
|
|
|
*/
|
kernel: mmu: remove LINKER_USE_PINNED_SECTION and __pinned_* tagging
CONFIG_LINKER_USE_PINNED_SECTION is the second half of the selective
kernel-pinning model removed in issue #108773. With the kernel image
now always resident at boot (previous commit), the __pinned_*
attribute family is a no-op: every page they would have segregated is
already pinned by z_mem_manage_init()'s whole-image loop, so the
tagging contract neither adds safety nor remains maintainable.
Drop it.
Mechanical removals:
* All ~219 in-tree uses of __pinned_text, __pinned_rodata,
__pinned_data, __pinned_bss, __pinned_noinit, and __pinned_func
across arch/x86, drivers/interrupt_controller, drivers/timer,
arch/common, kernel, lib/libc, subsys/portability/posix, tests, and
the syscall code generator (scripts/build/gen_syscalls.py).
* The assembly aliases PINNED_TEXT/RODATA/DATA/BSS/NOINIT used in
arch/x86/core/ia32/*.S and drivers/interrupt_controller/
intc_loapic_spurious.S become plain TEXT/RODATA/DATA/BSS/NOINIT.
* K_KERNEL_PINNED_STACK_DEFINE, K_KERNEL_PINNED_STACK_ARRAY_DEFINE,
K_KERNEL_PINNED_STACK_ARRAY_DECLARE, K_THREAD_PINNED_STACK_DEFINE,
and K_THREAD_PINNED_STACK_ARRAY_DEFINE are removed. The few
in-tree callers (kernel/init.c, arch/arm/core/cortex_a_r/smp.c,
arch/arm64/core/fatal.c, arch/rx/core/prep_c.c,
arch/x86/core/prep_c.c, kernel/include/kernel_internal.h,
tests/bluetooth/hci_uart_async) move to the corresponding
non-pinned macros.
Machinery removals:
* Kconfig.zephyr drops CONFIG_LINKER_USE_PINNED_SECTION.
qemu_x86_tiny and qemu_x86_atom_virt drop their =y overrides.
* include/zephyr/linker/section_tags.h drops the __pinned_* macro
definitions (both arms). __isr collapses to an empty macro since
its only purpose was to alias __pinned_func.
* include/zephyr/linker/sections.h drops PINNED_TEXT_SECTION_NAME,
PINNED_BSS_SECTION_NAME, etc. and the bare PINNED_TEXT/RODATA/etc.
forwarders, plus the _APP_SMEM_PINNED_SECTION_NAME constant.
* include/zephyr/linker/linker-defs.h drops the lnkr_pinned_*
externs, the _app_smem_pinned_* externs, and the lnkr_is_pinned()
/ lnkr_is_region_pinned() inline helpers.
* include/zephyr/linker/utils.h drops the lnkr_pinned_rodata branch
in linker_is_in_rodata().
* include/zephyr/linker/app_smem_pinned{,_aligned,_unaligned}.ld
are deleted; cmake/linker/ld/target_configure.cmake stops
configuring them.
* boards/qemu/x86/qemu_x86_tiny.ld and
include/zephyr/arch/x86/ia32/linker.ld drop their pinned-section
blocks and the now-redundant #ifndef CONFIG_LINKER_USE_PINNED_SECTION
conditionals throughout the body. The
LIB_KERNEL_IN_SECT / LIB_ARCH_X86_IN_SECT / LIB_ZEPHYR_IN_SECT /
LIB_C_IN_SECT / LIB_DRIVERS_IN_SECT / LIB_SUBSYS_LOGGING_IN_SECT /
LIB_ZEPHYR_OBJECT_FILE_IN_SECT / ZEPHYR_KERNEL_FUNCS_IN_SECT macros
in qemu_x86_tiny.ld are deleted; they existed only to feed the
pinned text/rodata/data/bss/noinit sections.
* kernel/mmu.c drops the mark_linker_section_pinned(lnkr_pinned_start,
...) call. The mark_linker_section_pinned() helper survives but is
now gated only on CONFIG_LINKER_USE_BOOT_SECTION.
* arch/common/init.c and include/zephyr/arch/common/init.h drop
arch_bss_zero_pinned(); arch/x86/core/ia32/crt0.S drops the call
to it.
* arch/x86/core/userspace.c drops the eager k_mem_page_in() of the
thread's privileged stack on user-mode entry. With the kernel
image fully resident the stack is already mapped.
* arch/x86/gen_mmu.py drops map_region("lnkr_pinned") and the
set_region_perms() calls for lnkr_pinned_text / lnkr_pinned_rodata.
* CMakeLists.txt drops the LINKER_USE_PINNED_SECTION block that
generated APP_SMEM_PINNED_* variables and the
pinned_partitions target property feeding gen_app_partitions.py.
cmake/modules/extensions.cmake removes the PINNED_RODATA /
PINNED_RAM_SECTIONS / PINNED_DATA_SECTIONS zephyr_linker_sources()
location keywords and their snippet files.
scripts/build/gen_app_partitions.py drops --pinoutput /
--pinpartitions arguments and the pinned-output branch.
subsys/testsuite/coverage/CMakeLists.txt drops its
CONFIG_DEMAND_PAGING-conditional fork.
* scripts/build/gen_kobject_list.py drops the
app_smem_pinned_start / _end fallback for kobject placement
validation.
* tests/arch/x86/pagetables and tests/kernel/mem_protect/userspace
drop their lnkr_pinned_text / lnkr_pinned_rodata branches.
* include/zephyr/arch/x86/ia32/arch.h folds IRQSTUBS_TEXT_SECTION
to the unconditional ".text.irqstubs" form.
* tests/subsys/llext/src/syscalls_ext.c drops a stale comment about
syscalls landing in .pinned_text.
Targeted retentions:
* arch/x86/core/bootargs.c keeps multiboot_cmdline and efi_bootargs
in .noinit (was __pinned_noinit, which decayed to __noinit when
LINKER_USE_PINNED_SECTION was unset). The multiboot and zefi loader
paths write these buffers before Zephyr's BSS-zero step, so
zeroing them at boot loses the cmdline.
* arch/x86/core/ia32/fatal.c keeps _df_esf and _df_stack in .noinit.
They are scratch space written by the double-fault handler and have
no zero-init requirement; keeping them in .noinit also preserves
the historical post-noinit alignment that gen_mmu.py relies on
(z_mapped_size is computed before CMake-injected iterable sections
are appended to the linker script, so the post-noinit page padding
is what keeps those sections within the mapped region).
* include/zephyr/arch/x86/ia32/syscall.h and
include/zephyr/arch/x86/arch.h wrap the per-arch
arch_syscall_invoke* / arch_is_user_context / arch_k_cycle_get_*
implementations in @cond INTERNAL_HIDDEN. The public Doxygen
contract lives on the prototypes in
include/zephyr/arch/arch_interface.h; the per-arch implementations
are internal. Without this, removing the __pinned_func attribute
exposes the implementations to the doxygen-coverage delta check
as 10 newly-undocumented APIs.
Documentation updates are deferred to a separate commit.
Issue: #108773
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-05-15 16:33:20 -04:00
|
|
|
SECTION_FUNC(TEXT, z_SpuriousIntNoErrCodeHandler)
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2025-03-25 12:19:43 -07:00
|
|
|
endbr32
|
2015-04-10 16:44:37 -07:00
|
|
|
pushl $0 /* push dummy err code onto stk */
|
|
|
|
|
|
2019-03-14 09:20:46 -06:00
|
|
|
/* fall through to z_SpuriousIntHandler */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
|
kernel: mmu: remove LINKER_USE_PINNED_SECTION and __pinned_* tagging
CONFIG_LINKER_USE_PINNED_SECTION is the second half of the selective
kernel-pinning model removed in issue #108773. With the kernel image
now always resident at boot (previous commit), the __pinned_*
attribute family is a no-op: every page they would have segregated is
already pinned by z_mem_manage_init()'s whole-image loop, so the
tagging contract neither adds safety nor remains maintainable.
Drop it.
Mechanical removals:
* All ~219 in-tree uses of __pinned_text, __pinned_rodata,
__pinned_data, __pinned_bss, __pinned_noinit, and __pinned_func
across arch/x86, drivers/interrupt_controller, drivers/timer,
arch/common, kernel, lib/libc, subsys/portability/posix, tests, and
the syscall code generator (scripts/build/gen_syscalls.py).
* The assembly aliases PINNED_TEXT/RODATA/DATA/BSS/NOINIT used in
arch/x86/core/ia32/*.S and drivers/interrupt_controller/
intc_loapic_spurious.S become plain TEXT/RODATA/DATA/BSS/NOINIT.
* K_KERNEL_PINNED_STACK_DEFINE, K_KERNEL_PINNED_STACK_ARRAY_DEFINE,
K_KERNEL_PINNED_STACK_ARRAY_DECLARE, K_THREAD_PINNED_STACK_DEFINE,
and K_THREAD_PINNED_STACK_ARRAY_DEFINE are removed. The few
in-tree callers (kernel/init.c, arch/arm/core/cortex_a_r/smp.c,
arch/arm64/core/fatal.c, arch/rx/core/prep_c.c,
arch/x86/core/prep_c.c, kernel/include/kernel_internal.h,
tests/bluetooth/hci_uart_async) move to the corresponding
non-pinned macros.
Machinery removals:
* Kconfig.zephyr drops CONFIG_LINKER_USE_PINNED_SECTION.
qemu_x86_tiny and qemu_x86_atom_virt drop their =y overrides.
* include/zephyr/linker/section_tags.h drops the __pinned_* macro
definitions (both arms). __isr collapses to an empty macro since
its only purpose was to alias __pinned_func.
* include/zephyr/linker/sections.h drops PINNED_TEXT_SECTION_NAME,
PINNED_BSS_SECTION_NAME, etc. and the bare PINNED_TEXT/RODATA/etc.
forwarders, plus the _APP_SMEM_PINNED_SECTION_NAME constant.
* include/zephyr/linker/linker-defs.h drops the lnkr_pinned_*
externs, the _app_smem_pinned_* externs, and the lnkr_is_pinned()
/ lnkr_is_region_pinned() inline helpers.
* include/zephyr/linker/utils.h drops the lnkr_pinned_rodata branch
in linker_is_in_rodata().
* include/zephyr/linker/app_smem_pinned{,_aligned,_unaligned}.ld
are deleted; cmake/linker/ld/target_configure.cmake stops
configuring them.
* boards/qemu/x86/qemu_x86_tiny.ld and
include/zephyr/arch/x86/ia32/linker.ld drop their pinned-section
blocks and the now-redundant #ifndef CONFIG_LINKER_USE_PINNED_SECTION
conditionals throughout the body. The
LIB_KERNEL_IN_SECT / LIB_ARCH_X86_IN_SECT / LIB_ZEPHYR_IN_SECT /
LIB_C_IN_SECT / LIB_DRIVERS_IN_SECT / LIB_SUBSYS_LOGGING_IN_SECT /
LIB_ZEPHYR_OBJECT_FILE_IN_SECT / ZEPHYR_KERNEL_FUNCS_IN_SECT macros
in qemu_x86_tiny.ld are deleted; they existed only to feed the
pinned text/rodata/data/bss/noinit sections.
* kernel/mmu.c drops the mark_linker_section_pinned(lnkr_pinned_start,
...) call. The mark_linker_section_pinned() helper survives but is
now gated only on CONFIG_LINKER_USE_BOOT_SECTION.
* arch/common/init.c and include/zephyr/arch/common/init.h drop
arch_bss_zero_pinned(); arch/x86/core/ia32/crt0.S drops the call
to it.
* arch/x86/core/userspace.c drops the eager k_mem_page_in() of the
thread's privileged stack on user-mode entry. With the kernel
image fully resident the stack is already mapped.
* arch/x86/gen_mmu.py drops map_region("lnkr_pinned") and the
set_region_perms() calls for lnkr_pinned_text / lnkr_pinned_rodata.
* CMakeLists.txt drops the LINKER_USE_PINNED_SECTION block that
generated APP_SMEM_PINNED_* variables and the
pinned_partitions target property feeding gen_app_partitions.py.
cmake/modules/extensions.cmake removes the PINNED_RODATA /
PINNED_RAM_SECTIONS / PINNED_DATA_SECTIONS zephyr_linker_sources()
location keywords and their snippet files.
scripts/build/gen_app_partitions.py drops --pinoutput /
--pinpartitions arguments and the pinned-output branch.
subsys/testsuite/coverage/CMakeLists.txt drops its
CONFIG_DEMAND_PAGING-conditional fork.
* scripts/build/gen_kobject_list.py drops the
app_smem_pinned_start / _end fallback for kobject placement
validation.
* tests/arch/x86/pagetables and tests/kernel/mem_protect/userspace
drop their lnkr_pinned_text / lnkr_pinned_rodata branches.
* include/zephyr/arch/x86/ia32/arch.h folds IRQSTUBS_TEXT_SECTION
to the unconditional ".text.irqstubs" form.
* tests/subsys/llext/src/syscalls_ext.c drops a stale comment about
syscalls landing in .pinned_text.
Targeted retentions:
* arch/x86/core/bootargs.c keeps multiboot_cmdline and efi_bootargs
in .noinit (was __pinned_noinit, which decayed to __noinit when
LINKER_USE_PINNED_SECTION was unset). The multiboot and zefi loader
paths write these buffers before Zephyr's BSS-zero step, so
zeroing them at boot loses the cmdline.
* arch/x86/core/ia32/fatal.c keeps _df_esf and _df_stack in .noinit.
They are scratch space written by the double-fault handler and have
no zero-init requirement; keeping them in .noinit also preserves
the historical post-noinit alignment that gen_mmu.py relies on
(z_mapped_size is computed before CMake-injected iterable sections
are appended to the linker script, so the post-noinit page padding
is what keeps those sections within the mapped region).
* include/zephyr/arch/x86/ia32/syscall.h and
include/zephyr/arch/x86/arch.h wrap the per-arch
arch_syscall_invoke* / arch_is_user_context / arch_k_cycle_get_*
implementations in @cond INTERNAL_HIDDEN. The public Doxygen
contract lives on the prototypes in
include/zephyr/arch/arch_interface.h; the per-arch implementations
are internal. Without this, removing the __pinned_func attribute
exposes the implementations to the doxygen-coverage delta check
as 10 newly-undocumented APIs.
Documentation updates are deferred to a separate commit.
Issue: #108773
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-05-15 16:33:20 -04:00
|
|
|
SECTION_FUNC(TEXT, z_SpuriousIntHandler)
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2025-03-25 12:19:43 -07:00
|
|
|
endbr32
|
2015-04-10 16:44:37 -07:00
|
|
|
cld /* Clear direction flag */
|
|
|
|
|
|
2015-10-05 10:48:46 -04:00
|
|
|
/* Create the ESF */
|
|
|
|
|
|
|
|
|
|
pushl %eax
|
|
|
|
|
pushl %ecx
|
|
|
|
|
pushl %edx
|
|
|
|
|
pushl %edi
|
|
|
|
|
pushl %esi
|
|
|
|
|
pushl %ebx
|
|
|
|
|
pushl %ebp
|
|
|
|
|
|
|
|
|
|
leal 44(%esp), %ecx /* Calculate ESP before exception occurred */
|
|
|
|
|
pushl %ecx /* Save calculated ESP */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2019-08-22 19:46:50 -07:00
|
|
|
pushl %esp /* push cur stack pointer: pEsf arg */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
/* re-enable interrupts */
|
2015-08-22 18:41:06 -04:00
|
|
|
sti
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
|
/* call the fatal error handler */
|
2019-07-11 14:18:28 -07:00
|
|
|
call z_x86_spurious_irq
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2016-07-08 13:53:50 -07:00
|
|
|
/* handler doesn't return */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-11-17 14:08:45 -08:00
|
|
|
#if CONFIG_IRQ_OFFLOAD
|
kernel: mmu: remove LINKER_USE_PINNED_SECTION and __pinned_* tagging
CONFIG_LINKER_USE_PINNED_SECTION is the second half of the selective
kernel-pinning model removed in issue #108773. With the kernel image
now always resident at boot (previous commit), the __pinned_*
attribute family is a no-op: every page they would have segregated is
already pinned by z_mem_manage_init()'s whole-image loop, so the
tagging contract neither adds safety nor remains maintainable.
Drop it.
Mechanical removals:
* All ~219 in-tree uses of __pinned_text, __pinned_rodata,
__pinned_data, __pinned_bss, __pinned_noinit, and __pinned_func
across arch/x86, drivers/interrupt_controller, drivers/timer,
arch/common, kernel, lib/libc, subsys/portability/posix, tests, and
the syscall code generator (scripts/build/gen_syscalls.py).
* The assembly aliases PINNED_TEXT/RODATA/DATA/BSS/NOINIT used in
arch/x86/core/ia32/*.S and drivers/interrupt_controller/
intc_loapic_spurious.S become plain TEXT/RODATA/DATA/BSS/NOINIT.
* K_KERNEL_PINNED_STACK_DEFINE, K_KERNEL_PINNED_STACK_ARRAY_DEFINE,
K_KERNEL_PINNED_STACK_ARRAY_DECLARE, K_THREAD_PINNED_STACK_DEFINE,
and K_THREAD_PINNED_STACK_ARRAY_DEFINE are removed. The few
in-tree callers (kernel/init.c, arch/arm/core/cortex_a_r/smp.c,
arch/arm64/core/fatal.c, arch/rx/core/prep_c.c,
arch/x86/core/prep_c.c, kernel/include/kernel_internal.h,
tests/bluetooth/hci_uart_async) move to the corresponding
non-pinned macros.
Machinery removals:
* Kconfig.zephyr drops CONFIG_LINKER_USE_PINNED_SECTION.
qemu_x86_tiny and qemu_x86_atom_virt drop their =y overrides.
* include/zephyr/linker/section_tags.h drops the __pinned_* macro
definitions (both arms). __isr collapses to an empty macro since
its only purpose was to alias __pinned_func.
* include/zephyr/linker/sections.h drops PINNED_TEXT_SECTION_NAME,
PINNED_BSS_SECTION_NAME, etc. and the bare PINNED_TEXT/RODATA/etc.
forwarders, plus the _APP_SMEM_PINNED_SECTION_NAME constant.
* include/zephyr/linker/linker-defs.h drops the lnkr_pinned_*
externs, the _app_smem_pinned_* externs, and the lnkr_is_pinned()
/ lnkr_is_region_pinned() inline helpers.
* include/zephyr/linker/utils.h drops the lnkr_pinned_rodata branch
in linker_is_in_rodata().
* include/zephyr/linker/app_smem_pinned{,_aligned,_unaligned}.ld
are deleted; cmake/linker/ld/target_configure.cmake stops
configuring them.
* boards/qemu/x86/qemu_x86_tiny.ld and
include/zephyr/arch/x86/ia32/linker.ld drop their pinned-section
blocks and the now-redundant #ifndef CONFIG_LINKER_USE_PINNED_SECTION
conditionals throughout the body. The
LIB_KERNEL_IN_SECT / LIB_ARCH_X86_IN_SECT / LIB_ZEPHYR_IN_SECT /
LIB_C_IN_SECT / LIB_DRIVERS_IN_SECT / LIB_SUBSYS_LOGGING_IN_SECT /
LIB_ZEPHYR_OBJECT_FILE_IN_SECT / ZEPHYR_KERNEL_FUNCS_IN_SECT macros
in qemu_x86_tiny.ld are deleted; they existed only to feed the
pinned text/rodata/data/bss/noinit sections.
* kernel/mmu.c drops the mark_linker_section_pinned(lnkr_pinned_start,
...) call. The mark_linker_section_pinned() helper survives but is
now gated only on CONFIG_LINKER_USE_BOOT_SECTION.
* arch/common/init.c and include/zephyr/arch/common/init.h drop
arch_bss_zero_pinned(); arch/x86/core/ia32/crt0.S drops the call
to it.
* arch/x86/core/userspace.c drops the eager k_mem_page_in() of the
thread's privileged stack on user-mode entry. With the kernel
image fully resident the stack is already mapped.
* arch/x86/gen_mmu.py drops map_region("lnkr_pinned") and the
set_region_perms() calls for lnkr_pinned_text / lnkr_pinned_rodata.
* CMakeLists.txt drops the LINKER_USE_PINNED_SECTION block that
generated APP_SMEM_PINNED_* variables and the
pinned_partitions target property feeding gen_app_partitions.py.
cmake/modules/extensions.cmake removes the PINNED_RODATA /
PINNED_RAM_SECTIONS / PINNED_DATA_SECTIONS zephyr_linker_sources()
location keywords and their snippet files.
scripts/build/gen_app_partitions.py drops --pinoutput /
--pinpartitions arguments and the pinned-output branch.
subsys/testsuite/coverage/CMakeLists.txt drops its
CONFIG_DEMAND_PAGING-conditional fork.
* scripts/build/gen_kobject_list.py drops the
app_smem_pinned_start / _end fallback for kobject placement
validation.
* tests/arch/x86/pagetables and tests/kernel/mem_protect/userspace
drop their lnkr_pinned_text / lnkr_pinned_rodata branches.
* include/zephyr/arch/x86/ia32/arch.h folds IRQSTUBS_TEXT_SECTION
to the unconditional ".text.irqstubs" form.
* tests/subsys/llext/src/syscalls_ext.c drops a stale comment about
syscalls landing in .pinned_text.
Targeted retentions:
* arch/x86/core/bootargs.c keeps multiboot_cmdline and efi_bootargs
in .noinit (was __pinned_noinit, which decayed to __noinit when
LINKER_USE_PINNED_SECTION was unset). The multiboot and zefi loader
paths write these buffers before Zephyr's BSS-zero step, so
zeroing them at boot loses the cmdline.
* arch/x86/core/ia32/fatal.c keeps _df_esf and _df_stack in .noinit.
They are scratch space written by the double-fault handler and have
no zero-init requirement; keeping them in .noinit also preserves
the historical post-noinit alignment that gen_mmu.py relies on
(z_mapped_size is computed before CMake-injected iterable sections
are appended to the linker script, so the post-noinit page padding
is what keeps those sections within the mapped region).
* include/zephyr/arch/x86/ia32/syscall.h and
include/zephyr/arch/x86/arch.h wrap the per-arch
arch_syscall_invoke* / arch_is_user_context / arch_k_cycle_get_*
implementations in @cond INTERNAL_HIDDEN. The public Doxygen
contract lives on the prototypes in
include/zephyr/arch/arch_interface.h; the per-arch implementations
are internal. Without this, removing the __pinned_func attribute
exposes the implementations to the doxygen-coverage delta check
as 10 newly-undocumented APIs.
Documentation updates are deferred to a separate commit.
Issue: #108773
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-05-15 16:33:20 -04:00
|
|
|
SECTION_FUNC(TEXT, _irq_sw_handler)
|
2025-03-25 12:19:43 -07:00
|
|
|
endbr32
|
2016-09-23 14:01:39 -07:00
|
|
|
push $0
|
2019-03-14 09:20:46 -06:00
|
|
|
push $z_irq_do_offload
|
2016-09-23 14:01:39 -07:00
|
|
|
jmp _interrupt_enter
|
2015-11-17 14:08:45 -08:00
|
|
|
|
|
|
|
|
#endif
|
2018-10-30 16:55:38 -07:00
|
|
|
|
|
|
|
|
#if CONFIG_X86_DYNAMIC_IRQ_STUBS > 0
|
|
|
|
|
z_dynamic_irq_stub_common:
|
|
|
|
|
/* stub number already pushed */
|
|
|
|
|
push $z_x86_dynamic_irq_handler
|
|
|
|
|
jmp _interrupt_enter
|
|
|
|
|
|
|
|
|
|
/* Create all the dynamic IRQ stubs
|
|
|
|
|
*
|
2019-06-27 15:01:01 -07:00
|
|
|
* NOTE: Please update DYN_STUB_SIZE in include/arch/x86/ia32/arch.h if you
|
|
|
|
|
* change how large the generated stubs are, otherwise _get_dynamic_stub()
|
|
|
|
|
* will be unable to correctly determine the offset
|
2018-10-30 16:55:38 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Create nice labels for all the stubs so we can see where we
|
|
|
|
|
* are in a debugger
|
|
|
|
|
*/
|
|
|
|
|
.altmacro
|
|
|
|
|
.macro __INT_STUB_NUM id
|
|
|
|
|
z_dynamic_irq_stub_\id:
|
|
|
|
|
.endm
|
|
|
|
|
.macro INT_STUB_NUM id
|
|
|
|
|
__INT_STUB_NUM %id
|
|
|
|
|
.endm
|
|
|
|
|
|
|
|
|
|
z_dynamic_stubs_begin:
|
|
|
|
|
stub_num = 0
|
|
|
|
|
.rept ((CONFIG_X86_DYNAMIC_IRQ_STUBS + Z_DYN_STUB_PER_BLOCK - 1) / Z_DYN_STUB_PER_BLOCK)
|
|
|
|
|
block_counter = 0
|
|
|
|
|
.rept Z_DYN_STUB_PER_BLOCK
|
|
|
|
|
.if stub_num < CONFIG_X86_DYNAMIC_IRQ_STUBS
|
|
|
|
|
INT_STUB_NUM stub_num
|
2025-03-25 12:19:43 -07:00
|
|
|
/*
|
|
|
|
|
* 4-byte endbr32
|
|
|
|
|
*/
|
|
|
|
|
endbr32
|
2018-10-30 16:55:38 -07:00
|
|
|
/*
|
|
|
|
|
* 2-byte push imm8.
|
|
|
|
|
*/
|
|
|
|
|
push $stub_num
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check to make sure this isn't the last stub in
|
|
|
|
|
* a block, in which case we just fall through
|
|
|
|
|
*/
|
|
|
|
|
.if (block_counter <> (Z_DYN_STUB_PER_BLOCK - 1) && \
|
|
|
|
|
(stub_num <> CONFIG_X86_DYNAMIC_IRQ_STUBS - 1))
|
|
|
|
|
/* This should always be a 2-byte jmp rel8 */
|
|
|
|
|
jmp 1f
|
|
|
|
|
.endif
|
|
|
|
|
stub_num = stub_num + 1
|
|
|
|
|
block_counter = block_counter + 1
|
|
|
|
|
.endif
|
|
|
|
|
.endr
|
|
|
|
|
/*
|
|
|
|
|
* This must a 5-bvte jump rel32, which is why z_dynamic_irq_stub_common
|
|
|
|
|
* is before the actual stubs
|
|
|
|
|
*/
|
|
|
|
|
1: jmp z_dynamic_irq_stub_common
|
|
|
|
|
.endr
|
|
|
|
|
#endif /* CONFIG_X86_DYNAMIC_IRQ_STUBS > 0 */
|
|
|
|
|
|