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 <indan@nul.nu>
Signed-off-by: Corey Lewis <corey.lewis@proofcraft.systems>
This commit is contained in:
Indan Zupancic
2024-09-08 20:14:57 +01:00
committed by Gerwin Klein
parent 8f8776a541
commit 1415cac443
5 changed files with 92 additions and 1 deletions

View File

@@ -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*/

View File

@@ -825,6 +825,28 @@
</error>
</method>
<method id="TCBSetFlags" name="SetFlags" manual_name="Set Feature Flags" manual_label="tcb_setflags">
<brief>
Set or clear <texttt text="seL4_TCBFlag"/> feature flags of the target TCB.
</brief>
<description>
A newly created TCB has all flags cleared.
Currently the only flag supported is <texttt text="seL4_TCBFlag_fpuDisabled"/>.
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.
</description>
<return>
The resulting TCB flags value is returned in the first message register.
</return>
<param dir="in" name="clear" type="seL4_Word" description="Bitwise OR'd set of seL4_TCBFlag to clear."/>
<param dir="in" name="set" type="seL4_Word" description="Bitwise OR'd set of seL4_TCBFlag to set."/>
<param dir="out" name="flags" type="seL4_Word" description="Returned value of the TCB flags"/>
<error name="seL4_InvalidCapability">
<description>
The <texttt text="_service"/> is a CPtr to a capability of the wrong type.
</description>
</error>
</method>
</interface>
<interface name="seL4_CNode" manual_name="CNode">

View File

@@ -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

View File

@@ -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}

View File

@@ -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.");