From 1415cac443a09360d1f629f36bb32e55475e7c31 Mon Sep 17 00:00:00 2001 From: Indan Zupancic Date: Sun, 8 Sep 2024 20:14:57 +0100 Subject: [PATCH] Add seL4_TCB_SetFlags Syscall Add flags to tcb_t and the seL4_TCBFlag_fpuDisabled flag. Enums are signed, make TCB flags word_t to make it unsigned. Signed-off-by: Indan Zupancic Signed-off-by: Corey Lewis --- include/object/structures.h | 4 +- libsel4/include/interfaces/object-api.xml | 22 +++++++++++ libsel4/include/sel4/constants.h | 13 +++++++ manual/parts/threads.tex | 8 ++++ src/object/tcb.c | 46 +++++++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) diff --git a/include/object/structures.h b/include/object/structures.h index a46f1727e..1b5371898 100644 --- a/include/object/structures.h +++ b/include/object/structures.h @@ -242,7 +242,6 @@ typedef struct sched_context sched_context_t; typedef struct reply reply_t; #endif -/* TCB: size >= 18 words + sizeof(arch_tcb_t) + 1 word on MCS (aligned to nearest power of 2) */ struct tcb { /* arch specific tcb state (including context)*/ arch_tcb_t tcbArch; @@ -250,6 +249,9 @@ struct tcb { /* Thread state, 3 words */ thread_state_t tcbState; + /* Currently only used for seL4_TCBFlag_fpuDisabled */ + word_t tcbFlags; /* seL4_TCBFlag */ + /* Notification that this TCB is bound to. If this is set, when this TCB waits on * any sync endpoint, it may receive a signal from a Notification object. * 1 word*/ diff --git a/libsel4/include/interfaces/object-api.xml b/libsel4/include/interfaces/object-api.xml index 07e5623e5..767a08763 100644 --- a/libsel4/include/interfaces/object-api.xml +++ b/libsel4/include/interfaces/object-api.xml @@ -825,6 +825,28 @@ + + + Set or clear feature flags of the target TCB. + + + A newly created TCB has all flags cleared. + Currently the only flag supported is . + The flags are cleared and set in the given order, i.e. when a flag is both cleared and set, it will be set. + Unknown flags are ignored. Use zero for both clear and set to retrieve the current flags value. + + + The resulting TCB flags value is returned in the first message register. + + + + + + + The is a CPtr to a capability of the wrong type. + + + diff --git a/libsel4/include/sel4/constants.h b/libsel4/include/sel4/constants.h index c5ec69789..921eff675 100644 --- a/libsel4/include/sel4/constants.h +++ b/libsel4/include/sel4/constants.h @@ -68,6 +68,19 @@ typedef enum { seL4_GuardMismatch, SEL4_FORCE_LONG_ENUM(seL4_LookupFailureType), } seL4_LookupFailureType; + +/* Flags to be used with seL4_TCB_Set_Flags */ +typedef enum { + seL4_TCBFlag_NoFlag = 0x0, + seL4_TCBFlag_fpuDisabled = 0x1, + + SEL4_FORCE_LONG_ENUM(seL4_TCBFlag), + seL4_TCBFlag_MASK = seL4_TCBFlag_NoFlag +#ifdef CONFIG_HAVE_FPU + | seL4_TCBFlag_fpuDisabled +#endif +} seL4_TCBFlag; + #endif /* !__ASSEMBLER__ */ #ifdef CONFIG_KERNEL_MCS diff --git a/manual/parts/threads.tex b/manual/parts/threads.tex index f5d680b2d..84415fe5f 100644 --- a/manual/parts/threads.tex +++ b/manual/parts/threads.tex @@ -74,6 +74,14 @@ automatically suspended when the last capability to their \obj{TCB} is deleted. % an example of which is demonstrated in \nameref{ex:second_thread}. +\subsection{Thread Feature Flags} +\label{sec:thread_flags} +Specific features can be enabled or disabled on a per TCB basis with +\apifunc{seL4\_TCB\_SetFlags}{tcb_setflags}. + +If access to the Floating Point Unit is not needed, it can be disabled +for individual threads to maximise context switching speed. + \subsection{Affinity} \label{sec:thread_affinity} diff --git a/src/object/tcb.c b/src/object/tcb.c index b457c1d0d..e41bb390e 100644 --- a/src/object/tcb.c +++ b/src/object/tcb.c @@ -792,6 +792,49 @@ static exception_t decodeSetTLSBase(cap_t cap, word_t length, word_t *buffer) return invokeSetTLSBase(TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), tls_base); } +static void invokeSetFlags(tcb_t *thread, word_t clear, word_t set, bool_t call) +{ + tcb_t *cur_thread = NODE_STATE(ksCurThread); + word_t flags = thread->tcbFlags; + + flags &= ~clear; + flags |= set & seL4_TCBFlag_MASK; + thread->tcbFlags = flags; + +#ifdef CONFIG_HAVE_FPU + /* Save current FPU state before disabling FPU: */ + if (flags & seL4_TCBFlag_fpuDisabled) { + fpuThreadDelete(thread); + } +#endif + if (call) { + word_t *ipcBuffer = lookupIPCBuffer(true, cur_thread); + setRegister(cur_thread, badgeRegister, 0); + unsigned int length = setMR(cur_thread, ipcBuffer, 0, flags); + setRegister(cur_thread, msgInfoRegister, wordFromMessageInfo( + seL4_MessageInfo_new(0, 0, 0, length))); + } + setThreadState(cur_thread, ThreadState_Running); +} + +static exception_t decodeSetFlags(cap_t cap, word_t length, bool_t call, word_t *buffer) +{ + tcb_t *thread = TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)); + + if (length < 2) { + userError("TCB SetFlags: Truncated message."); + current_syscall_error.type = seL4_TruncatedMessage; + return EXCEPTION_SYSCALL_ERROR; + } + + word_t clear = getSyscallArg(0, buffer); + word_t set = getSyscallArg(1, buffer); + + setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart); + invokeSetFlags(thread, clear, set, call); + return EXCEPTION_NONE; +} + /* The following functions sit in the syscall error monad, but include the * exception cases for the preemptible bottom end, as they call the invoke * functions directly. This is a significant deviation from the Haskell @@ -885,6 +928,9 @@ exception_t decodeTCBInvocation(word_t invLabel, word_t length, cap_t cap, case TCBSetTLSBase: return decodeSetTLSBase(cap, length, buffer); + case TCBSetFlags: + return decodeSetFlags(cap, length, call, buffer); + default: /* Haskell: "throw IllegalOperation" */ userError("TCB: Illegal operation.");