arch/x86: Add support for cooperative multitasking on x86_64
This commit extends the cooperative multitasking functionality to support the x86_64 architecture. Previously, cooperative multitasking was only available for x86_32, as indicated by the error directive in thread.c. A new thread_switch_64.S file has been added to implement 64-bit register handling for thread switching, and thread_switch.S has been renamed to thread_switch_32.S accordingly. Change-Id: I14ed625160a62e42d800757d30397c6c85f943b4 Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/88216 Reviewed-by: Shuo Liu <shuo.liu@intel.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
569b7a8861
commit
8b52167a9f
4 changed files with 115 additions and 7 deletions
|
|
@ -159,7 +159,10 @@ romstage-y += postcar_loader.c
|
|||
romstage-$(CONFIG_COLLECT_TIMESTAMPS_TSC) += timestamp.c
|
||||
romstage-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
|
||||
romstage-$(CONFIG_COOP_MULTITASKING) += thread.c
|
||||
romstage-$(CONFIG_COOP_MULTITASKING) += thread_switch.S
|
||||
ifeq ($(CONFIG_COOP_MULTITASKING),y)
|
||||
romstage-$(CONFIG_ARCH_ROMSTAGE_X86_32) += thread_switch_32.S
|
||||
romstage-$(CONFIG_ARCH_ROMSTAGE_X86_64) += thread_switch_64.S
|
||||
endif # CONFIG_COOP_MULTITASKING
|
||||
romstage-y += car.ld
|
||||
|
||||
romstage-srcs += $(wildcard $(src)/mainboard/$(MAINBOARDDIR)/romstage.c)
|
||||
|
|
@ -248,7 +251,10 @@ ramstage-y += rdrand.c
|
|||
ramstage-$(CONFIG_GENERATE_SMBIOS_TABLES) += smbios.c
|
||||
ramstage-y += tables.c
|
||||
ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c
|
||||
ramstage-$(CONFIG_COOP_MULTITASKING) += thread_switch.S
|
||||
ifeq ($(CONFIG_COOP_MULTITASKING),y)
|
||||
ramstage-$(CONFIG_ARCH_RAMSTAGE_X86_32) += thread_switch_32.S
|
||||
ramstage-$(CONFIG_ARCH_RAMSTAGE_X86_64) += thread_switch_64.S
|
||||
endif # CONFIG_COOP_MULTITASKING
|
||||
ramstage-$(CONFIG_COLLECT_TIMESTAMPS_TSC) += timestamp.c
|
||||
ramstage-$(CONFIG_HAVE_ACPI_RESUME) += wakeup.S
|
||||
ramstage-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
|
||||
|
|
|
|||
|
|
@ -3,11 +3,26 @@
|
|||
#include <thread.h>
|
||||
|
||||
#if ENV_X86_64
|
||||
#error COOP_MULTITASKING does not currently support x86_64
|
||||
#endif
|
||||
|
||||
struct saved_regs {
|
||||
uint64_t r15; /* Offset 0x00 */
|
||||
uint64_t r14; /* Offset 0x08 */
|
||||
uint64_t r13; /* Offset 0x10 */
|
||||
uint64_t r12; /* Offset 0x18 */
|
||||
uint64_t r11; /* Offset 0x20 */
|
||||
uint64_t r10; /* Offset 0x28 */
|
||||
uint64_t r9; /* Offset 0x30 */
|
||||
uint64_t r8; /* Offset 0x38 */
|
||||
uint64_t rdi; /* Offset 0x40 */
|
||||
uint64_t rsi; /* Offset 0x48 */
|
||||
uint64_t rbp; /* Offset 0x50 */
|
||||
uint64_t rbx; /* Offset 0x58 */
|
||||
uint64_t rdx; /* Offset 0x60 */
|
||||
uint64_t rcx; /* Offset 0x68 */
|
||||
uint64_t rax; /* Offset 0x70 */
|
||||
};
|
||||
#else
|
||||
/* The stack frame looks like the following after a pushad instruction. */
|
||||
struct pushad_regs {
|
||||
struct saved_regs {
|
||||
uint32_t edi; /* Offset 0x00 */
|
||||
uint32_t esi; /* Offset 0x04 */
|
||||
uint32_t ebp; /* Offset 0x08 */
|
||||
|
|
@ -17,6 +32,7 @@ struct pushad_regs {
|
|||
uint32_t ecx; /* Offset 0x18 */
|
||||
uint32_t eax; /* Offset 0x1c */
|
||||
};
|
||||
#endif /* ENV_X86_64 */
|
||||
|
||||
static inline uintptr_t push_stack(uintptr_t cur_stack, uintptr_t value)
|
||||
{
|
||||
|
|
@ -39,7 +55,7 @@ void arch_prepare_thread(struct thread *t,
|
|||
stack = push_stack(stack, (uintptr_t)0);
|
||||
stack = push_stack(stack, (uintptr_t)thread_entry);
|
||||
/* Make room for the registers. Ignore initial values. */
|
||||
stack -= sizeof(struct pushad_regs);
|
||||
stack -= sizeof(struct saved_regs);
|
||||
|
||||
t->stack_current = stack;
|
||||
}
|
||||
|
|
|
|||
86
src/arch/x86/thread_switch_64.S
Normal file
86
src/arch/x86/thread_switch_64.S
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
/*
|
||||
* Stack layout after pushing all the registers.
|
||||
* +------------+
|
||||
* | ret addr | <-- esp + 0x78
|
||||
* +------------+
|
||||
* | rax | <-- esp + 0x70
|
||||
* +------------+
|
||||
* | rcx | <-- esp + 0x68
|
||||
* +------------+
|
||||
* | rdx | <-- esp + 0x60
|
||||
* +------------+
|
||||
* | rbx | <-- esp + 0x58
|
||||
* +------------+
|
||||
* | rbp | <-- esp + 0x50
|
||||
* +------------+
|
||||
* | rsi | <-- esp + 0x48
|
||||
* +------------+
|
||||
* | rdi | <-- esp + 0x40
|
||||
* +------------+
|
||||
* | r8 | <-- esp + 0x38
|
||||
* +------------+
|
||||
* | r9 | <-- esp + 0x30
|
||||
* +------------+
|
||||
* | r10 | <-- esp + 0x28
|
||||
* +------------+
|
||||
* | r11 | <-- esp + 0x20
|
||||
* +------------+
|
||||
* | r12 | <-- esp + 0x18
|
||||
* +------------+
|
||||
* | r13 | <-- esp + 0x10
|
||||
* +------------+
|
||||
* | r14 | <-- esp + 0x08
|
||||
* +------------+
|
||||
* | r15 | <-- esp + 0x00
|
||||
* +------------+
|
||||
*/
|
||||
.global switch_to_thread
|
||||
switch_to_thread:
|
||||
/* Backup registers. */
|
||||
push %rax
|
||||
push %rcx
|
||||
push %rdx
|
||||
push %rbx
|
||||
|
||||
push %rbp
|
||||
push %rsi
|
||||
push %rdi
|
||||
|
||||
push %r8
|
||||
push %r9
|
||||
push %r10
|
||||
push %r11
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
|
||||
/* Save the current stack */
|
||||
mov %rsp, (%rsi)
|
||||
|
||||
/* Switch to the new stack. */
|
||||
mov %rdi, %rsp
|
||||
|
||||
/* Restore registers. */
|
||||
pop %r15
|
||||
pop %r14
|
||||
pop %r13
|
||||
pop %r12
|
||||
pop %r11
|
||||
pop %r10
|
||||
pop %r9
|
||||
pop %r8
|
||||
|
||||
pop %rdi
|
||||
pop %rsi
|
||||
pop %rbp
|
||||
|
||||
pop %rbx
|
||||
pop %rdx
|
||||
pop %rcx
|
||||
pop %rax
|
||||
|
||||
/* Done. */
|
||||
ret
|
||||
Loading…
Add table
Add a link
Reference in a new issue