arm,riscv: eliminate idle_thread function prologue
Similar to #510 but for all other platforms. The idle_thread runs without a stack and so cannot handle the stack prologue. This should hopefully make the kernel rely less on FORCE_INLINE for this as well. We create idle.S assembly files for each platform, as GCC does not support `__attribute__((naked))` on AArch64 (GCC 13.2.0) and bails out. Signed-off-by: julia <git.ts@trainwit.ch>
This commit is contained in:
parent
dfaef4b712
commit
5de930983b
15 changed files with 63 additions and 66 deletions
|
|
@ -8,12 +8,6 @@
|
|||
|
||||
#include <util.h>
|
||||
|
||||
/* See idle_thread for an explanation as to why FORCE_INLINE is required here. */
|
||||
static inline void FORCE_INLINE wfi(void)
|
||||
{
|
||||
asm volatile("wfi" ::: "memory");
|
||||
}
|
||||
|
||||
static inline void dsb(void)
|
||||
{
|
||||
asm volatile("dsb" ::: "memory");
|
||||
|
|
|
|||
|
|
@ -6,11 +6,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
static inline void wfi(void)
|
||||
{
|
||||
asm volatile("wfi" ::: "memory");
|
||||
}
|
||||
|
||||
static inline void dsb(void)
|
||||
{
|
||||
asm volatile("dsb sy" ::: "memory");
|
||||
|
|
@ -42,4 +37,3 @@ static inline void isb(void)
|
|||
#define SYSTEM_READ_WORD(reg, v) MRS(reg, v)
|
||||
#define SYSTEM_WRITE_64(reg, v) MSR(reg, v)
|
||||
#define SYSTEM_READ_64(reg, v) MRS(reg, v)
|
||||
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ void Arch_switchToIdleThread(void);
|
|||
void Arch_configureIdleThread(tcb_t *tcb);
|
||||
void Arch_activateIdleThread(tcb_t *tcb);
|
||||
|
||||
void idle_thread(void);
|
||||
void NORETURN idle_thread(void);
|
||||
|
||||
void configureIdleThread(tcb_t *tcb);
|
||||
void activateThread(void);
|
||||
|
|
@ -316,4 +316,3 @@ static inline void setThreadStateBlockedOnReply(tcb_t *tptr, reply_t *reply)
|
|||
scheduleTCB(tptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@ add_sources(
|
|||
idle.c
|
||||
kernel/thread.c
|
||||
kernel/vspace.c
|
||||
ASMFILES head.S traps.S hyp_traps.S
|
||||
ASMFILES head.S traps.S hyp_traps.S idle.S
|
||||
)
|
||||
|
|
|
|||
15
src/arch/arm/32/idle.S
Normal file
15
src/arch/arm/32/idle.S
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright 2025, UNSW
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*/
|
||||
|
||||
#include <machine/assembler.h>
|
||||
|
||||
.code 32
|
||||
.section .text, "ax"
|
||||
|
||||
BEGIN_FUNC(idle_thread)
|
||||
1: wfi
|
||||
b 1b
|
||||
END_FUNC(idle_thread)
|
||||
|
|
@ -8,23 +8,6 @@
|
|||
#include <mode/machine.h>
|
||||
#include <api/debug.h>
|
||||
|
||||
/*
|
||||
* The idle thread currently does not receive a stack pointer and so we rely on
|
||||
* optimisations for correctness here. More specifically, we assume:
|
||||
* - Ordinary prologue/epilogue stack operations are optimised out
|
||||
* - All nested function calls are inlined
|
||||
* Note that GCC does not correctly implement optimisation annotations on nested
|
||||
* functions, so FORCE_INLINE is required on the wfi declaration in this case.
|
||||
* Note that Clang doesn't obey FORCE_O2 and relies on the kernel being compiled
|
||||
* with optimisations enabled.
|
||||
*/
|
||||
void FORCE_O2 idle_thread(void)
|
||||
{
|
||||
while (1) {
|
||||
wfi();
|
||||
}
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
void NORETURN NO_INLINE VISIBLE halt(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@ add_sources(
|
|||
idle.c
|
||||
kernel/thread.c
|
||||
kernel/vspace.c
|
||||
ASMFILES head.S traps.S
|
||||
ASMFILES head.S traps.S idle.S
|
||||
)
|
||||
|
|
|
|||
14
src/arch/arm/64/idle.S
Normal file
14
src/arch/arm/64/idle.S
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright 2025, UNSW
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*/
|
||||
|
||||
#include <machine/assembler.h>
|
||||
|
||||
.section .text, "ax"
|
||||
|
||||
BEGIN_FUNC(idle_thread)
|
||||
1: wfi
|
||||
b 1b
|
||||
END_FUNC(idle_thread)
|
||||
|
|
@ -8,13 +8,6 @@
|
|||
#include <mode/machine.h>
|
||||
#include <api/debug.h>
|
||||
|
||||
void idle_thread(void)
|
||||
{
|
||||
while (1) {
|
||||
wfi();
|
||||
}
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
void NORETURN NO_INLINE VISIBLE halt(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ add_sources(
|
|||
object/objecttype.c
|
||||
object/tcb.c
|
||||
smp/ipi.c
|
||||
ASMFILES head.S traps.S
|
||||
ASMFILES head.S traps.S idle.S
|
||||
)
|
||||
|
||||
add_bf_source_old("KernelArchRiscV" "structures.bf" "include/arch/riscv" "arch/object")
|
||||
|
|
|
|||
14
src/arch/riscv/idle.S
Normal file
14
src/arch/riscv/idle.S
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright 2025, UNSW
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*/
|
||||
|
||||
#include <machine/assembler.h>
|
||||
|
||||
.section .text, "ax"
|
||||
|
||||
BEGIN_FUNC(idle_thread)
|
||||
1: wfi
|
||||
j 1b
|
||||
END_FUNC(idle_thread)
|
||||
|
|
@ -8,13 +8,6 @@
|
|||
#include <config.h>
|
||||
#include <arch/sbi.h>
|
||||
|
||||
void idle_thread(void)
|
||||
{
|
||||
while (1) {
|
||||
asm volatile("wfi");
|
||||
}
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
void VISIBLE NO_INLINE halt(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@ add_sources(
|
|||
machine/registerset.c
|
||||
benchmark/benchmark.c
|
||||
smp/ipi.c
|
||||
ASMFILES multiboot.S
|
||||
ASMFILES multiboot.S idle.S
|
||||
)
|
||||
|
||||
add_bf_source_old("KernelArchX86" "structures.bf" "include/arch/x86" "arch/object")
|
||||
|
|
|
|||
15
src/arch/x86/idle.S
Normal file
15
src/arch/x86/idle.S
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright 2025, UNSW
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*/
|
||||
|
||||
#include <machine/assembler.h>
|
||||
|
||||
.section .text, "ax"
|
||||
.code32
|
||||
|
||||
BEGIN_FUNC(idle_thread)
|
||||
1: hlt
|
||||
jmp 1b
|
||||
END_FUNC(idle_thread)
|
||||
|
|
@ -7,23 +7,6 @@
|
|||
#include <config.h>
|
||||
#include <api/debug.h>
|
||||
|
||||
/*
|
||||
* The idle thread does not have a dedicated stack and runs in
|
||||
* the context of the idle thread TCB. Make sure that the compiler
|
||||
* always eliminates the function prologue by declaring the
|
||||
* idle_thread with the naked attribute.
|
||||
*/
|
||||
__attribute__((naked)) NORETURN void idle_thread(void)
|
||||
{
|
||||
/* We cannot use for-loop or while-loop here because they may
|
||||
* involve stack manipulations (the compiler will not allow
|
||||
* them in a naked function anyway). */
|
||||
asm volatile(
|
||||
"1: hlt\n"
|
||||
"jmp 1b"
|
||||
);
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
void VISIBLE halt(void)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue