zephyr/arch/x86/core/ia32/intstub.S

457 lines
12 KiB
ArmAsm
Raw Permalink Normal View History

/*
* Copyright (c) 2010-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @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.
*/
#define LOAPIC_BASE_ADDRESS DT_REG_ADDR(DT_NODELABEL(intc_loapic))
#include <zephyr/arch/x86/ia32/asm.h>
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
#include <offsets_short.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/drivers/interrupt_controller/sysapic.h>
/* exports (internal APIs) */
GTEXT(_interrupt_enter)
GTEXT(z_SpuriousIntNoErrCodeHandler)
GTEXT(z_SpuriousIntHandler)
GTEXT(_irq_sw_handler)
GTEXT(z_dynamic_stubs_begin)
/* externs */
GTEXT(arch_swap)
unified/x86: add unified kernel support for x86 arch The x86 architecture port is fitted with support for the unified kernel, namely: - the interrupt exit code now calls _Swap() if the current thread is not a coop thread and if the scheduler is not locked - there is no 'task' fields in the _nanokernel anymore: _Swap() now calls _get_next_ready_thread instead - the _nanokernel.fiber field is replaced by a more sophisticated ready_q, based on the microkernel's priority-bitmap-based one - nano_private includes nano_internal.h from the unified directory - the FIBER, TASK and PREEMPTIBLE flags do not exist anymore: the thread priority drives the behaviour - the tcs uses a dlist for queuing in both ready and wait queues instead of a custom singly-linked list - other new fields in the tcs include a schedule-lock count, a back-pointer to init data (when the task is static) and a pointer to swap data, needed when a thread pending on _Swap() must be passed more then just one value (e.g. k_stack_pop() needs an error code and data) - fiberRtnValueSet() is aliased to _set_thread_return_value since it also operates on preempt threads now - _set_thread_return_value_with_data() sets the swap_data field in addition to a return value from _Swap() - convenience aliases are created for shorter names: - _current is defined as _nanokernel.current - _ready_q is defined as _nanokernel.ready_q - _Swap() sets the threads's return code to -EAGAIN before swapping out to prevent timeouts to have to set it (solves hard issues in some kernel objects). - Floating point support. Note that, in _Swap(), the register holding the thread to be swapped in has been changed from %ecx to %eax in both the legacy kernel and the unified kernel to take advantage of the fact that the return value of _get_next_ready_thread() is stored in %eax, and this avoids moving it to %ecx. Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com> Allan Stephens <allan.stephens@windriver.com> Benjamin Walsh <benjamin.walsh@windriver.com> Change-Id: I4ce2bd47bcdc62034c669b5e889fc0f29480c43b Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 22:34:35 +02:00
#ifdef CONFIG_PM
GTEXT(z_pm_save_idle_exit)
#endif
/**
*
* @brief Inform the kernel of an interrupt
*
* This function is called from the interrupt stub created by IRQ_CONNECT()
* to inform the kernel of an interrupt. This routine increments
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
* _kernel.nested (to support interrupt nesting), switches to the
* 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
* utilize floating point (or SSE) instructions.
*
* 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:
*
* void _interrupt_enter(void *isr, void *isr_param);
*/
SECTION_FUNC(PINNED_TEXT, _interrupt_enter)
/*
* 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
*/
/*
* The gen_idt tool creates an interrupt-gate descriptor for
* all connections. The processor will automatically clear the IF
* bit in the EFLAGS register upon execution of the handler, hence
* this need not issue an 'cli' as the first instruction.
*
* Clear the direction flag. It is automatically restored when the
* interrupt exits via the IRET instruction.
*/
cld
#ifdef CONFIG_X86_KPTI
call z_x86_trampoline_to_kernel
#endif
/*
* Swap EAX with isr_param and EDX with isr.
* Push ECX onto the stack
*/
xchgl %eax, 4(%esp)
xchgl %edx, (%esp)
pushl %ecx
/* Now the stack looks like:
*
* EFLAGS
* CS
* EIP
* saved EAX
* saved EDX
* saved ECX
*
* EAX = isr_param, EDX = isr
*/
/* Push EDI as we will use it for scratch space.
* Rest of the callee-saved regs get saved by invocation of C
* functions (isr handler, arch_swap(), etc)
*/
pushl %edi
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
/* load %ecx with &_kernel */
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
movl $_kernel, %ecx
/* switch to the interrupt stack for the non-nested case */
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
incl _kernel_offset_to_nested(%ecx)
/* use interrupt stack if not nested */
cmpl $1, _kernel_offset_to_nested(%ecx)
jne alreadyOnIntStack
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
/*
* switch to base of the interrupt stack: save esp in edi, then load
* irq_stack pointer
*/
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
movl %esp, %edi
movl _kernel_offset_to_irq_stack(%ecx), %esp
/* save thread's stack pointer onto base of interrupt stack */
pushl %edi /* Save stack pointer */
#ifdef CONFIG_PM
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
cmpl $0, _kernel_offset_to_idle(%ecx)
jne handle_idle
/* fast path is !idle, in the pipeline */
#endif /* CONFIG_PM */
/* fall through to nested case */
alreadyOnIntStack:
push %eax /* interrupt handler argument */
#if defined(CONFIG_TRACING_ISR)
/* 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
#ifdef CONFIG_NESTED_INTERRUPTS
sti /* re-enable interrupts */
#endif
/* Now call the interrupt handler */
call *%edx
/* Discard ISR argument */
addl $0x4, %esp
#ifdef CONFIG_NESTED_INTERRUPTS
cli /* disable interrupts again */
#endif
x86: declare internal API for interrupt controllers Originally, x86 just supported APIC. Then later support for the Mint Valley Interrupt Controller was added. This controller is mostly similar to the APIC with some differences, but was integrated in a somewhat hacked-up fashion. Now we define irq_controller.h, which is a layer of abstraction between the core arch code and the interrupt controller implementation. Contents of the API: - Controllers with a fixed irq-to-vector mapping define _IRQ_CONTROLLER_VECTOR_MAPPING(irq) to obtain a compile-time map between the two. - _irq_controller_program() notifies the interrupt controller what vector will be used for a particular IRQ along with triggering flags - _irq_controller_isr_vector_get() reports the vector number of the IRQ currently being serviced - In assembly language domain, _irq_controller_eoi implements EOI handling. - Since triggering options can vary, some common defines for triggering IRQ_TRIGGER_EDGE, IRQ_TRIGGER_LEVEL, IRQ_POLARITY_HIGH, IRQ_POLARITY_LOW introduced. Specific changes made: - New Kconfig X86_FIXED_IRQ_MAPPING for those interrupt controllers that have a fixed relationship between IRQ lines and IDT vectors. - MVIC driver rewritten per the HAS instead of the tortuous methods used to get it to behave like LOAPIC. We are no longer writing values to reserved registers. Additional assertions added. - Some cleanup in the loapic_timer driver to make the MVIC differences clearer. - Unused APIs removed, or folded into calling code when used just once. - MVIC doesn't bother to write a -1 to the intList priority field since it gets ignored anyway Issue: ZEP-48 Change-Id: I071a477ea68c36e00c3d0653ce74b3583454154d Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2016-08-02 21:05:08 +02:00
#if defined(CONFIG_TRACING_ISR)
pushl %eax
call sys_trace_isr_exit
popl %eax
#endif
#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
xorl %eax, %eax
#if defined(CONFIG_X2APIC)
xorl %edx, %edx
movl $(X86_X2APIC_BASE_MSR + (LOAPIC_EOI >> 4)), %ecx
wrmsr
#else /* xAPIC */
#ifdef DEVICE_MMIO_IS_IN_RAM
movl Z_TOPLEVEL_RAM_NAME(LOAPIC_REGS_STR), %edx
movl %eax, LOAPIC_EOI(%edx)
#else
movl %eax, (LOAPIC_BASE_ADDRESS + LOAPIC_EOI)
#endif /* DEVICE_MMIO_IS_IN_RAM */
#endif /* CONFIG_X2APIC */
x86: declare internal API for interrupt controllers Originally, x86 just supported APIC. Then later support for the Mint Valley Interrupt Controller was added. This controller is mostly similar to the APIC with some differences, but was integrated in a somewhat hacked-up fashion. Now we define irq_controller.h, which is a layer of abstraction between the core arch code and the interrupt controller implementation. Contents of the API: - Controllers with a fixed irq-to-vector mapping define _IRQ_CONTROLLER_VECTOR_MAPPING(irq) to obtain a compile-time map between the two. - _irq_controller_program() notifies the interrupt controller what vector will be used for a particular IRQ along with triggering flags - _irq_controller_isr_vector_get() reports the vector number of the IRQ currently being serviced - In assembly language domain, _irq_controller_eoi implements EOI handling. - Since triggering options can vary, some common defines for triggering IRQ_TRIGGER_EDGE, IRQ_TRIGGER_LEVEL, IRQ_POLARITY_HIGH, IRQ_POLARITY_LOW introduced. Specific changes made: - New Kconfig X86_FIXED_IRQ_MAPPING for those interrupt controllers that have a fixed relationship between IRQ lines and IDT vectors. - MVIC driver rewritten per the HAS instead of the tortuous methods used to get it to behave like LOAPIC. We are no longer writing values to reserved registers. Additional assertions added. - Some cleanup in the loapic_timer driver to make the MVIC differences clearer. - Unused APIs removed, or folded into calling code when used just once. - MVIC doesn't bother to write a -1 to the intList priority field since it gets ignored anyway Issue: ZEP-48 Change-Id: I071a477ea68c36e00c3d0653ce74b3583454154d Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
2016-08-02 21:05:08 +02:00
/* determine whether exiting from a nested interrupt */
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
movl $_kernel, %ecx
decl _kernel_offset_to_nested(%ecx) /* dec interrupt nest count */
jne nestedInterrupt /* 'iret' if nested case */
#ifdef CONFIG_PREEMPT_ENABLED
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
movl _kernel_offset_to_current(%ecx), %edx
unified/x86: add unified kernel support for x86 arch The x86 architecture port is fitted with support for the unified kernel, namely: - the interrupt exit code now calls _Swap() if the current thread is not a coop thread and if the scheduler is not locked - there is no 'task' fields in the _nanokernel anymore: _Swap() now calls _get_next_ready_thread instead - the _nanokernel.fiber field is replaced by a more sophisticated ready_q, based on the microkernel's priority-bitmap-based one - nano_private includes nano_internal.h from the unified directory - the FIBER, TASK and PREEMPTIBLE flags do not exist anymore: the thread priority drives the behaviour - the tcs uses a dlist for queuing in both ready and wait queues instead of a custom singly-linked list - other new fields in the tcs include a schedule-lock count, a back-pointer to init data (when the task is static) and a pointer to swap data, needed when a thread pending on _Swap() must be passed more then just one value (e.g. k_stack_pop() needs an error code and data) - fiberRtnValueSet() is aliased to _set_thread_return_value since it also operates on preempt threads now - _set_thread_return_value_with_data() sets the swap_data field in addition to a return value from _Swap() - convenience aliases are created for shorter names: - _current is defined as _nanokernel.current - _ready_q is defined as _nanokernel.ready_q - _Swap() sets the threads's return code to -EAGAIN before swapping out to prevent timeouts to have to set it (solves hard issues in some kernel objects). - Floating point support. Note that, in _Swap(), the register holding the thread to be swapped in has been changed from %ecx to %eax in both the legacy kernel and the unified kernel to take advantage of the fact that the return value of _get_next_ready_thread() is stored in %eax, and this avoids moving it to %ecx. Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com> Allan Stephens <allan.stephens@windriver.com> Benjamin Walsh <benjamin.walsh@windriver.com> Change-Id: I4ce2bd47bcdc62034c669b5e889fc0f29480c43b Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 22:34:35 +02: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 16:37:27 +01:00
cmpl %edx, _kernel_offset_to_ready_q_cache(%ecx)
je noReschedule
/*
* Set X86_THREAD_FLAG_INT bit in k_thread to allow the upcoming call
* to arch_swap() to determine whether non-floating registers need to be
* preserved using the lazy save/restore algorithm, or to indicate to
* debug tools that a preemptive context switch has occurred.
*/
#if defined(CONFIG_LAZY_FPU_SHARING)
orb $X86_THREAD_FLAG_INT, _thread_offset_to_flags(%edx)
#endif
/*
* A context reschedule is required: keep the volatile registers of
* the interrupted thread on the context's stack. Utilize
* the existing arch_swap() primitive to save the remaining
* thread's registers (including floating point) and perform
* a switch to the new thread.
*/
unified/x86: add unified kernel support for x86 arch The x86 architecture port is fitted with support for the unified kernel, namely: - the interrupt exit code now calls _Swap() if the current thread is not a coop thread and if the scheduler is not locked - there is no 'task' fields in the _nanokernel anymore: _Swap() now calls _get_next_ready_thread instead - the _nanokernel.fiber field is replaced by a more sophisticated ready_q, based on the microkernel's priority-bitmap-based one - nano_private includes nano_internal.h from the unified directory - the FIBER, TASK and PREEMPTIBLE flags do not exist anymore: the thread priority drives the behaviour - the tcs uses a dlist for queuing in both ready and wait queues instead of a custom singly-linked list - other new fields in the tcs include a schedule-lock count, a back-pointer to init data (when the task is static) and a pointer to swap data, needed when a thread pending on _Swap() must be passed more then just one value (e.g. k_stack_pop() needs an error code and data) - fiberRtnValueSet() is aliased to _set_thread_return_value since it also operates on preempt threads now - _set_thread_return_value_with_data() sets the swap_data field in addition to a return value from _Swap() - convenience aliases are created for shorter names: - _current is defined as _nanokernel.current - _ready_q is defined as _nanokernel.ready_q - _Swap() sets the threads's return code to -EAGAIN before swapping out to prevent timeouts to have to set it (solves hard issues in some kernel objects). - Floating point support. Note that, in _Swap(), the register holding the thread to be swapped in has been changed from %ecx to %eax in both the legacy kernel and the unified kernel to take advantage of the fact that the return value of _get_next_ready_thread() is stored in %eax, and this avoids moving it to %ecx. Work by: Dmitriy Korovkin <dmitriy.korovkin@windriver.com> Allan Stephens <allan.stephens@windriver.com> Benjamin Walsh <benjamin.walsh@windriver.com> Change-Id: I4ce2bd47bcdc62034c669b5e889fc0f29480c43b Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-09-02 22:34:35 +02:00
popl %esp /* switch back to outgoing thread's stack */
#ifdef CONFIG_STACK_SENTINEL
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-06 04:37:19 +01:00
#endif
pushfl /* push KERNEL_LOCK_KEY argument */
call arch_swap
addl $4, %esp /* pop KERNEL_LOCK_KEY argument */
/*
* The interrupted thread has now been scheduled,
* as the result of a _later_ invocation of arch_swap().
*
* Now need to restore the interrupted thread's environment before
* returning control to it at the point where it was interrupted ...
*/
#if defined(CONFIG_LAZY_FPU_SHARING)
/*
* arch_swap() has restored the floating point registers, if needed.
* Clear X86_THREAD_FLAG_INT in the interrupted thread's state
* since it has served its purpose.
*/
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
movl _kernel + _kernel_offset_to_current, %eax
andb $~X86_THREAD_FLAG_INT, _thread_offset_to_flags(%eax)
#endif /* CONFIG_LAZY_FPU_SHARING */
/* Restore volatile registers and return to the interrupted thread */
popl %edi
popl %ecx
popl %edx
popl %eax
/* Pop of EFLAGS will re-enable interrupts and restore direction flag */
KPTI_IRET
#endif /* CONFIG_PREEMPT_ENABLED */
noReschedule:
/*
* A thread reschedule is not required; switch back to the
* interrupted thread's stack and restore volatile registers
*/
popl %esp /* pop thread stack pointer */
#ifdef CONFIG_STACK_SENTINEL
call z_check_stack_sentinel
#endif
/* 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.
*/
nestedInterrupt:
popl %edi
popl %ecx /* pop volatile registers in reverse order */
popl %edx
popl %eax
/* Pop of EFLAGS will re-enable interrupts and restore direction flag */
KPTI_IRET
#ifdef CONFIG_PM
handle_idle:
pushl %eax
pushl %edx
kernel/arch: consolidate tTCS and TNANO definitions There was a lot of duplication between architectures for the definition of threads and the "nanokernel" guts. These have been consolidated. Now, a common file kernel/unified/include/kernel_structs.h holds the common definitions. Architectures provide two files to complement it: kernel_arch_data.h and kernel_arch_func.h. The first one contains at least the struct _thread_arch and struct _kernel_arch data structures, as well as the struct _callee_saved and struct _caller_saved register layouts. The second file contains anything that needs what is provided by the common stuff in kernel_structs.h. Those two files are only meant to be included in kernel_structs.h in very specific locations. The thread data structure has been separated into three major parts: common struct _thread_base and struct k_thread, and arch-specific struct _thread_arch. The first and third ones are included in the second. The struct s_NANO data structure has been split into two: common struct _kernel and arch-specific struct _kernel_arch. The latter is included in the former. Offsets files have also changed: nano_offsets.h has been renamed kernel_offsets.h and is still included by the arch-specific offsets.c. Also, since the thread and kernel data structures are now made of sub-structures, offsets have to be added to make up the full offset. Some of these additions have been consolidated in shorter symbols, available from kernel/unified/include/offsets_short.h, which includes an arch-specific offsets_arch_short.h. Most of the code include offsets_short.h now instead of offsets.h. Change-Id: I084645cb7e6db8db69aeaaf162963fe157045d5a Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
2016-11-08 16:36:50 +01:00
/* Zero out _kernel.idle */
movl $0, _kernel_offset_to_idle(%ecx)
/*
* Beware that a timer driver's z_pm_save_idle_exit() implementation might
* 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.
*/
call z_pm_save_idle_exit
popl %edx
popl %eax
jmp alreadyOnIntStack
#endif /* CONFIG_PM */
/**
*
* z_SpuriousIntHandler -
* @brief Spurious interrupt handler stubs
*
* Interrupt-gate descriptors are statically created for all slots in the IDT
* that point to z_SpuriousIntHandler() or z_SpuriousIntNoErrCodeHandler(). The
* 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.
*
* 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.
*
* @return Never returns
*
* C function prototype:
*
* void z_SpuriousIntHandler (void);
*
* INTERNAL
* The gen_idt tool creates an interrupt-gate descriptor for all
* connections. The processor will automatically clear the IF bit
* in the EFLAGS register upon execution of the handler,
* thus z_SpuriousIntNoErrCodeHandler()/z_SpuriousIntHandler() shall be
* invoked with interrupts disabled.
*/
SECTION_FUNC(PINNED_TEXT, z_SpuriousIntNoErrCodeHandler)
pushl $0 /* push dummy err code onto stk */
/* fall through to z_SpuriousIntHandler */
SECTION_FUNC(PINNED_TEXT, z_SpuriousIntHandler)
cld /* Clear direction flag */
/* 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 */
pushl %esp /* push cur stack pointer: pEsf arg */
/* re-enable interrupts */
sti
/* call the fatal error handler */
call z_x86_spurious_irq
/* handler doesn't return */
#if CONFIG_IRQ_OFFLOAD
SECTION_FUNC(PINNED_TEXT, _irq_sw_handler)
push $0
push $z_irq_do_offload
jmp _interrupt_enter
#endif
#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
*
* 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
*/
/*
* 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
/*
* 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 */